blitz-pdf 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -3
- package/THIRD_PARTY_NOTICES.md +2 -0
- package/dist/api.d.ts +9 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +25 -27
- package/dist/api.js.map +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +13 -1
- package/dist/browser.js.map +1 -1
- package/dist/node-worker.d.ts +2 -0
- package/dist/node-worker.d.ts.map +1 -0
- package/dist/node-worker.js +10 -0
- package/dist/node-worker.js.map +1 -0
- package/dist/node.d.ts +1 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +18 -6
- package/dist/node.js.map +1 -1
- package/dist/render.d.ts +8 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +28 -0
- package/dist/render.js.map +1 -0
- package/dist/wasm.d.ts +3 -0
- package/dist/wasm.d.ts.map +1 -0
- package/dist/wasm.js +18 -0
- package/dist/wasm.js.map +1 -0
- package/dist/worker-host.d.ts +16 -0
- package/dist/worker-host.d.ts.map +1 -0
- package/dist/worker-host.js +31 -0
- package/dist/worker-host.js.map +1 -0
- package/dist/worker-protocol.d.ts +22 -0
- package/dist/worker-protocol.d.ts.map +1 -0
- package/dist/worker-protocol.js +2 -0
- package/dist/worker-protocol.js.map +1 -0
- package/dist/worker-runtime.d.ts +8 -0
- package/dist/worker-runtime.d.ts.map +1 -0
- package/dist/worker-runtime.js +34 -0
- package/dist/worker-runtime.js.map +1 -0
- package/dist/worker.d.ts +2 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +7 -0
- package/dist/worker.js.map +1 -0
- package/package.json +5 -2
- package/src/api.ts +33 -22
- package/src/browser.ts +13 -3
- package/src/node-worker.ts +9 -0
- package/src/node.ts +13 -4
- package/src/render.ts +28 -0
- package/src/wasm.ts +17 -0
- package/src/worker-host.ts +45 -0
- package/src/worker-protocol.ts +10 -0
- package/src/worker-runtime.ts +35 -0
- package/src/worker.ts +12 -0
- package/vendor/README.md +24 -0
- package/vendor/blitz-paint/Cargo.toml +50 -0
- package/vendor/blitz-paint/LICENSE-APACHE +176 -0
- package/vendor/blitz-paint/LICENSE-MIT +23 -0
- package/vendor/blitz-paint/src/color.rs +66 -0
- package/vendor/blitz-paint/src/debug_overlay.rs +168 -0
- package/vendor/blitz-paint/src/filters.rs +40 -0
- package/vendor/blitz-paint/src/gradient.rs +536 -0
- package/vendor/blitz-paint/src/kurbo_css/css_box.rs +847 -0
- package/vendor/blitz-paint/src/kurbo_css/mod.rs +77 -0
- package/vendor/blitz-paint/src/kurbo_css/non_uniform_radii.rs +60 -0
- package/vendor/blitz-paint/src/layers.rs +95 -0
- package/vendor/blitz-paint/src/lib.rs +190 -0
- package/vendor/blitz-paint/src/render/background.rs +968 -0
- package/vendor/blitz-paint/src/render/border.rs +631 -0
- package/vendor/blitz-paint/src/render/box_shadow.rs +157 -0
- package/vendor/blitz-paint/src/render/clip_path.rs +492 -0
- package/vendor/blitz-paint/src/render/form_controls.rs +103 -0
- package/vendor/blitz-paint/src/render/mask.rs +144 -0
- package/vendor/blitz-paint/src/render.rs +1351 -0
- package/vendor/blitz-paint/src/sizing.rs +63 -0
- package/vendor/blitz-paint/src/text.rs +747 -0
- package/wasm/blitz_pdf_bg.wasm +0 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
use anyrender::PaintScene;
|
|
2
|
+
use blitz_dom::{BaseDocument, NodeId};
|
|
3
|
+
use kurbo::{Affine, Rect, Vec2};
|
|
4
|
+
|
|
5
|
+
use crate::color::Color;
|
|
6
|
+
|
|
7
|
+
/// Renders a layout debugging overlay which visualises the content size, padding and border
|
|
8
|
+
/// of the node with a transparent overlay.
|
|
9
|
+
pub(crate) fn render_debug_overlay(
|
|
10
|
+
scene: &mut impl PaintScene,
|
|
11
|
+
dom: &BaseDocument,
|
|
12
|
+
node_id: NodeId,
|
|
13
|
+
scale: f64,
|
|
14
|
+
initial_x: f64,
|
|
15
|
+
initial_y: f64,
|
|
16
|
+
) {
|
|
17
|
+
// Non-atomic inline elements have no layout box of their own: they are laid
|
|
18
|
+
// out as style spans within an inline root's text layout and may fragment
|
|
19
|
+
// across multiple line boxes. Highlight each fragment's content box.
|
|
20
|
+
if let Some(rects) = dom.as_ref().inline_fragment_rects(node_id) {
|
|
21
|
+
let fill_color = Color::from_rgba8(66, 144, 245, 128); // blue
|
|
22
|
+
for r in rects {
|
|
23
|
+
let rect = Rect::new(0.0, 0.0, r.width * scale, r.height * scale);
|
|
24
|
+
let translation = Vec2::new(r.x * scale + initial_x, r.y * scale + initial_y);
|
|
25
|
+
scene.fill(
|
|
26
|
+
peniko::Fill::NonZero,
|
|
27
|
+
Affine::translate(translation),
|
|
28
|
+
fill_color,
|
|
29
|
+
None,
|
|
30
|
+
&rect,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let viewport_scroll = dom.as_ref().viewport_scroll();
|
|
37
|
+
let mut node = &dom.as_ref().tree()[node_id];
|
|
38
|
+
|
|
39
|
+
let taffy::Layout {
|
|
40
|
+
size,
|
|
41
|
+
border,
|
|
42
|
+
padding,
|
|
43
|
+
margin,
|
|
44
|
+
..
|
|
45
|
+
} = *node.final_layout();
|
|
46
|
+
let taffy::Size { width, height } = size;
|
|
47
|
+
|
|
48
|
+
let padding_border = padding + border;
|
|
49
|
+
let scaled_pb = padding_border.map(|v| f64::from(v) * scale);
|
|
50
|
+
let scaled_padding = padding.map(|v| f64::from(v) * scale);
|
|
51
|
+
let scaled_border = border.map(|v| f64::from(v) * scale);
|
|
52
|
+
let scaled_margin = margin.map(|v| f64::from(v) * scale);
|
|
53
|
+
|
|
54
|
+
let content_width = width - padding_border.left - padding_border.right;
|
|
55
|
+
let content_height = height - padding_border.top - padding_border.bottom;
|
|
56
|
+
|
|
57
|
+
let taffy::Point { x, y } = node.final_layout().location;
|
|
58
|
+
|
|
59
|
+
let mut abs_x = x;
|
|
60
|
+
let mut abs_y = y;
|
|
61
|
+
// A fixed box whose containing block is the root element does not scroll
|
|
62
|
+
// with it (nor with the viewport).
|
|
63
|
+
let mut fixed_to_viewport = false;
|
|
64
|
+
while let Some(parent_id) = node.containing_block() {
|
|
65
|
+
let child_is_fixed = node.taffy_position() == taffy::Position::Fixed;
|
|
66
|
+
node = &dom.as_ref().tree()[parent_id];
|
|
67
|
+
fixed_to_viewport = child_is_fixed && node.containing_block().is_none();
|
|
68
|
+
let taffy::Point { x, y } = node.final_layout().location;
|
|
69
|
+
abs_x += x;
|
|
70
|
+
abs_y += y;
|
|
71
|
+
if !fixed_to_viewport {
|
|
72
|
+
abs_x -= node.scroll_offset().x as f32;
|
|
73
|
+
abs_y -= node.scroll_offset().y as f32;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if !fixed_to_viewport {
|
|
78
|
+
abs_x -= viewport_scroll.x as f32;
|
|
79
|
+
abs_y -= viewport_scroll.y as f32;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Note: initial_x/initial_y are already in physical (scaled) pixels so they must be added after scaling
|
|
83
|
+
// the other values
|
|
84
|
+
let abs_x = f64::from(abs_x) * scale + initial_x;
|
|
85
|
+
let abs_y = f64::from(abs_y) * scale + initial_y;
|
|
86
|
+
let width = f64::from(width) * scale;
|
|
87
|
+
let height = f64::from(height) * scale;
|
|
88
|
+
let content_width = f64::from(content_width) * scale;
|
|
89
|
+
let content_height = f64::from(content_height) * scale;
|
|
90
|
+
|
|
91
|
+
// Fill content box blue
|
|
92
|
+
let base_translation = Vec2::new(abs_x, abs_y);
|
|
93
|
+
let transform = Affine::translate(base_translation + Vec2::new(scaled_pb.left, scaled_pb.top));
|
|
94
|
+
let rect = Rect::new(0.0, 0.0, content_width, content_height);
|
|
95
|
+
let fill_color = Color::from_rgba8(66, 144, 245, 128); // blue
|
|
96
|
+
scene.fill(peniko::Fill::NonZero, transform, fill_color, None, &rect);
|
|
97
|
+
|
|
98
|
+
let padding_color = Color::from_rgba8(81, 144, 66, 128); // green
|
|
99
|
+
draw_cutout_rect(
|
|
100
|
+
scene,
|
|
101
|
+
base_translation + Vec2::new(scaled_border.left, scaled_border.top),
|
|
102
|
+
Vec2::new(
|
|
103
|
+
content_width + scaled_padding.left + scaled_padding.right,
|
|
104
|
+
content_height + scaled_padding.top + scaled_padding.bottom,
|
|
105
|
+
),
|
|
106
|
+
scaled_padding.map(f64::from),
|
|
107
|
+
padding_color,
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
let border_color = Color::from_rgba8(245, 66, 66, 128); // red
|
|
111
|
+
draw_cutout_rect(
|
|
112
|
+
scene,
|
|
113
|
+
base_translation,
|
|
114
|
+
Vec2::new(width, height),
|
|
115
|
+
scaled_border.map(f64::from),
|
|
116
|
+
border_color,
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
let margin_color = Color::from_rgba8(249, 204, 157, 128); // orange
|
|
120
|
+
draw_cutout_rect(
|
|
121
|
+
scene,
|
|
122
|
+
base_translation - Vec2::new(scaled_margin.left, scaled_margin.top),
|
|
123
|
+
Vec2::new(
|
|
124
|
+
width + scaled_margin.left + scaled_margin.right,
|
|
125
|
+
height + scaled_margin.top + scaled_margin.bottom,
|
|
126
|
+
),
|
|
127
|
+
scaled_margin.map(f64::from),
|
|
128
|
+
margin_color,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
fn draw_cutout_rect(
|
|
133
|
+
scene: &mut impl PaintScene,
|
|
134
|
+
base_translation: Vec2,
|
|
135
|
+
size: Vec2,
|
|
136
|
+
edge_widths: taffy::Rect<f64>,
|
|
137
|
+
color: Color,
|
|
138
|
+
) {
|
|
139
|
+
let mut fill = |pos: Vec2, width: f64, height: f64| {
|
|
140
|
+
scene.fill(
|
|
141
|
+
peniko::Fill::NonZero,
|
|
142
|
+
Affine::translate(pos),
|
|
143
|
+
color,
|
|
144
|
+
None,
|
|
145
|
+
&Rect::new(0.0, 0.0, width, height),
|
|
146
|
+
);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
let right = size.x - edge_widths.right;
|
|
150
|
+
let bottom = size.y - edge_widths.bottom;
|
|
151
|
+
let inner_h = size.y - edge_widths.top - edge_widths.bottom;
|
|
152
|
+
let inner_w = size.x - edge_widths.left - edge_widths.right;
|
|
153
|
+
|
|
154
|
+
let bt = base_translation;
|
|
155
|
+
let ew = edge_widths;
|
|
156
|
+
|
|
157
|
+
// Corners
|
|
158
|
+
fill(bt, ew.left, ew.top); // top-left
|
|
159
|
+
fill(bt + Vec2::new(0.0, bottom), ew.left, ew.bottom); // bottom-left
|
|
160
|
+
fill(bt + Vec2::new(right, 0.0), ew.right, ew.top); // top-right
|
|
161
|
+
fill(bt + Vec2::new(right, bottom), ew.right, ew.bottom); // bottom-right
|
|
162
|
+
|
|
163
|
+
// Sides
|
|
164
|
+
fill(bt + Vec2::new(0.0, ew.top), ew.left, inner_h); // left
|
|
165
|
+
fill(bt + Vec2::new(right, ew.top), ew.right, inner_h); // right
|
|
166
|
+
fill(bt + Vec2::new(ew.left, 0.0), inner_w, ew.top); // top
|
|
167
|
+
fill(bt + Vec2::new(ew.left, bottom), inner_w, ew.bottom); // bottom
|
|
168
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
use blitz_dom::util::ToColorColor as _;
|
|
2
|
+
use style::color::AbsoluteColor;
|
|
3
|
+
pub(crate) use style::computed_values::filter::single_value::T as StyloFilter;
|
|
4
|
+
|
|
5
|
+
use anyrender::filters::{Filter, FilterEffect};
|
|
6
|
+
|
|
7
|
+
pub(crate) fn convert_filters(filters: &[StyloFilter]) -> Option<Filter> {
|
|
8
|
+
if filters.is_empty() {
|
|
9
|
+
return None;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
Some(Filter::linear_list(
|
|
13
|
+
filters.iter().filter_map(convert_single_filter),
|
|
14
|
+
))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
pub(crate) fn convert_single_filter(filter: &StyloFilter) -> Option<FilterEffect> {
|
|
18
|
+
Some(match filter {
|
|
19
|
+
StyloFilter::Blur(radius) => FilterEffect::blur(radius.px()),
|
|
20
|
+
StyloFilter::Brightness(amount) => FilterEffect::brightness(amount.0),
|
|
21
|
+
StyloFilter::Contrast(amount) => FilterEffect::contrast(amount.0),
|
|
22
|
+
StyloFilter::Grayscale(amount) => FilterEffect::grayscale(amount.0),
|
|
23
|
+
StyloFilter::HueRotate(angle) => FilterEffect::hue_rotate(angle.radians()),
|
|
24
|
+
StyloFilter::Invert(amount) => FilterEffect::invert(amount.0),
|
|
25
|
+
StyloFilter::Opacity(amount) => FilterEffect::opacity(amount.0),
|
|
26
|
+
StyloFilter::Saturate(amount) => FilterEffect::saturate(amount.0),
|
|
27
|
+
StyloFilter::Sepia(amount) => FilterEffect::sepia(amount.0),
|
|
28
|
+
StyloFilter::DropShadow(shadow) => FilterEffect::drop_shadow(
|
|
29
|
+
shadow.horizontal.px(),
|
|
30
|
+
shadow.vertical.px(),
|
|
31
|
+
shadow.blur.px(),
|
|
32
|
+
// TODO: pass in correct currentColor
|
|
33
|
+
shadow
|
|
34
|
+
.color
|
|
35
|
+
.resolve_to_absolute(&AbsoluteColor::BLACK)
|
|
36
|
+
.as_color_color(),
|
|
37
|
+
),
|
|
38
|
+
StyloFilter::Url(_) => return None,
|
|
39
|
+
})
|
|
40
|
+
}
|