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.
Files changed (76) hide show
  1. package/README.md +67 -3
  2. package/THIRD_PARTY_NOTICES.md +2 -0
  3. package/dist/api.d.ts +9 -1
  4. package/dist/api.d.ts.map +1 -1
  5. package/dist/api.js +25 -27
  6. package/dist/api.js.map +1 -1
  7. package/dist/browser.d.ts +1 -1
  8. package/dist/browser.d.ts.map +1 -1
  9. package/dist/browser.js +13 -1
  10. package/dist/browser.js.map +1 -1
  11. package/dist/node-worker.d.ts +2 -0
  12. package/dist/node-worker.d.ts.map +1 -0
  13. package/dist/node-worker.js +10 -0
  14. package/dist/node-worker.js.map +1 -0
  15. package/dist/node.d.ts +1 -1
  16. package/dist/node.d.ts.map +1 -1
  17. package/dist/node.js +18 -6
  18. package/dist/node.js.map +1 -1
  19. package/dist/render.d.ts +8 -0
  20. package/dist/render.d.ts.map +1 -0
  21. package/dist/render.js +28 -0
  22. package/dist/render.js.map +1 -0
  23. package/dist/wasm.d.ts +3 -0
  24. package/dist/wasm.d.ts.map +1 -0
  25. package/dist/wasm.js +18 -0
  26. package/dist/wasm.js.map +1 -0
  27. package/dist/worker-host.d.ts +16 -0
  28. package/dist/worker-host.d.ts.map +1 -0
  29. package/dist/worker-host.js +31 -0
  30. package/dist/worker-host.js.map +1 -0
  31. package/dist/worker-protocol.d.ts +22 -0
  32. package/dist/worker-protocol.d.ts.map +1 -0
  33. package/dist/worker-protocol.js +2 -0
  34. package/dist/worker-protocol.js.map +1 -0
  35. package/dist/worker-runtime.d.ts +8 -0
  36. package/dist/worker-runtime.d.ts.map +1 -0
  37. package/dist/worker-runtime.js +34 -0
  38. package/dist/worker-runtime.js.map +1 -0
  39. package/dist/worker.d.ts +2 -0
  40. package/dist/worker.d.ts.map +1 -0
  41. package/dist/worker.js +7 -0
  42. package/dist/worker.js.map +1 -0
  43. package/package.json +5 -2
  44. package/src/api.ts +33 -22
  45. package/src/browser.ts +13 -3
  46. package/src/node-worker.ts +9 -0
  47. package/src/node.ts +13 -4
  48. package/src/render.ts +28 -0
  49. package/src/wasm.ts +17 -0
  50. package/src/worker-host.ts +45 -0
  51. package/src/worker-protocol.ts +10 -0
  52. package/src/worker-runtime.ts +35 -0
  53. package/src/worker.ts +12 -0
  54. package/vendor/README.md +24 -0
  55. package/vendor/blitz-paint/Cargo.toml +50 -0
  56. package/vendor/blitz-paint/LICENSE-APACHE +176 -0
  57. package/vendor/blitz-paint/LICENSE-MIT +23 -0
  58. package/vendor/blitz-paint/src/color.rs +66 -0
  59. package/vendor/blitz-paint/src/debug_overlay.rs +168 -0
  60. package/vendor/blitz-paint/src/filters.rs +40 -0
  61. package/vendor/blitz-paint/src/gradient.rs +536 -0
  62. package/vendor/blitz-paint/src/kurbo_css/css_box.rs +847 -0
  63. package/vendor/blitz-paint/src/kurbo_css/mod.rs +77 -0
  64. package/vendor/blitz-paint/src/kurbo_css/non_uniform_radii.rs +60 -0
  65. package/vendor/blitz-paint/src/layers.rs +95 -0
  66. package/vendor/blitz-paint/src/lib.rs +190 -0
  67. package/vendor/blitz-paint/src/render/background.rs +968 -0
  68. package/vendor/blitz-paint/src/render/border.rs +631 -0
  69. package/vendor/blitz-paint/src/render/box_shadow.rs +157 -0
  70. package/vendor/blitz-paint/src/render/clip_path.rs +492 -0
  71. package/vendor/blitz-paint/src/render/form_controls.rs +103 -0
  72. package/vendor/blitz-paint/src/render/mask.rs +144 -0
  73. package/vendor/blitz-paint/src/render.rs +1351 -0
  74. package/vendor/blitz-paint/src/sizing.rs +63 -0
  75. package/vendor/blitz-paint/src/text.rs +747 -0
  76. 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
+ }