blitz-pdf 0.1.2 → 0.1.4

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 (64) hide show
  1. package/README.md +26 -0
  2. package/THIRD_PARTY_NOTICES.md +5 -2
  3. package/docs/layout-regressions.md +65 -0
  4. package/docs/pagination-regressions.md +89 -0
  5. package/package.json +2 -1
  6. package/vendor/README.md +35 -0
  7. package/vendor/blitz-dom/Cargo.toml +113 -0
  8. package/vendor/blitz-dom/LICENSE-APACHE +176 -0
  9. package/vendor/blitz-dom/LICENSE-MIT +23 -0
  10. package/vendor/blitz-dom/assets/default.css +1142 -0
  11. package/vendor/blitz-dom/assets/moz-bullet-font.otf +0 -0
  12. package/vendor/blitz-dom/src/accessibility.rs +255 -0
  13. package/vendor/blitz-dom/src/config.rs +97 -0
  14. package/vendor/blitz-dom/src/cssom.rs +971 -0
  15. package/vendor/blitz-dom/src/debug.rs +206 -0
  16. package/vendor/blitz-dom/src/document.rs +3395 -0
  17. package/vendor/blitz-dom/src/events/driver.rs +427 -0
  18. package/vendor/blitz-dom/src/events/focus.rs +40 -0
  19. package/vendor/blitz-dom/src/events/ime.rs +31 -0
  20. package/vendor/blitz-dom/src/events/keyboard.rs +174 -0
  21. package/vendor/blitz-dom/src/events/mod.rs +315 -0
  22. package/vendor/blitz-dom/src/events/pointer.rs +849 -0
  23. package/vendor/blitz-dom/src/font_metrics.rs +177 -0
  24. package/vendor/blitz-dom/src/form.rs +463 -0
  25. package/vendor/blitz-dom/src/html.rs +38 -0
  26. package/vendor/blitz-dom/src/iframe.rs +186 -0
  27. package/vendor/blitz-dom/src/layout/construct.rs +1328 -0
  28. package/vendor/blitz-dom/src/layout/damage.rs +642 -0
  29. package/vendor/blitz-dom/src/layout/inline.rs +1160 -0
  30. package/vendor/blitz-dom/src/layout/list.rs +237 -0
  31. package/vendor/blitz-dom/src/layout/mod.rs +969 -0
  32. package/vendor/blitz-dom/src/layout/paint_tree.rs +462 -0
  33. package/vendor/blitz-dom/src/layout/replaced.rs +439 -0
  34. package/vendor/blitz-dom/src/layout/table.rs +967 -0
  35. package/vendor/blitz-dom/src/layout/text_transform.rs +979 -0
  36. package/vendor/blitz-dom/src/layout/writing_mode.rs +437 -0
  37. package/vendor/blitz-dom/src/lib.rs +160 -0
  38. package/vendor/blitz-dom/src/mutator.rs +1818 -0
  39. package/vendor/blitz-dom/src/net.rs +649 -0
  40. package/vendor/blitz-dom/src/node/attributes.rs +60 -0
  41. package/vendor/blitz-dom/src/node/custom_widget.rs +178 -0
  42. package/vendor/blitz-dom/src/node/element.rs +1106 -0
  43. package/vendor/blitz-dom/src/node/mod.rs +30 -0
  44. package/vendor/blitz-dom/src/node/node.rs +2036 -0
  45. package/vendor/blitz-dom/src/node/scrollbar.rs +237 -0
  46. package/vendor/blitz-dom/src/node/serialize.rs +225 -0
  47. package/vendor/blitz-dom/src/node/stylo_data.rs +142 -0
  48. package/vendor/blitz-dom/src/node/svg.rs +265 -0
  49. package/vendor/blitz-dom/src/node/text.rs +804 -0
  50. package/vendor/blitz-dom/src/query_selector.rs +275 -0
  51. package/vendor/blitz-dom/src/resolve.rs +474 -0
  52. package/vendor/blitz-dom/src/resolved_style.rs +797 -0
  53. package/vendor/blitz-dom/src/scrolling.rs +780 -0
  54. package/vendor/blitz-dom/src/selection.rs +122 -0
  55. package/vendor/blitz-dom/src/stylo.rs +1518 -0
  56. package/vendor/blitz-dom/src/stylo_device.rs +88 -0
  57. package/vendor/blitz-dom/src/stylo_to_cursor_icon.rs +49 -0
  58. package/vendor/blitz-dom/src/stylo_to_kurbo.rs +129 -0
  59. package/vendor/blitz-dom/src/stylo_to_parley.rs +655 -0
  60. package/vendor/blitz-dom/src/traversal.rs +600 -0
  61. package/vendor/blitz-dom/src/tree.rs +136 -0
  62. package/vendor/blitz-dom/src/url.rs +63 -0
  63. package/vendor/blitz-dom/src/util.rs +256 -0
  64. package/wasm/blitz_pdf_bg.wasm +0 -0
@@ -0,0 +1,88 @@
1
+ //! Management of the Stylo [`Device`]: constructing it from shell state and
2
+ //! coalescing changes to it (viewport resizes, zoom, color-scheme and media
3
+ //! type changes) so that the stylist device is rebuilt at most once per
4
+ //! [`resolve`](crate::BaseDocument::resolve), no matter how many changes
5
+ //! occurred since the last resolve.
6
+
7
+ use std::sync::{Arc, Mutex};
8
+
9
+ use bitflags::bitflags;
10
+ use blitz_traits::shell::{ColorScheme, Viewport};
11
+ use parley::FontContext;
12
+ use selectors::matching::QuirksMode;
13
+ use style::device::Device;
14
+ use style::media_queries::MediaType;
15
+ use style::properties::ComputedValues;
16
+ use style::properties::style_structs::Font;
17
+ use style::queries::values::PrefersColorScheme;
18
+ use style::servo::media_features::PointerCapabilities;
19
+
20
+ use crate::font_metrics::BlitzFontMetricsProvider;
21
+
22
+ bitflags! {
23
+ /// The set of changes to the [`Device`] that have accumulated since the
24
+ /// stylist device was last rebuilt. Only the *latest* values matter (they
25
+ /// live on [`BaseDocument`](crate::BaseDocument)); these flags record
26
+ /// which kinds of change occurred so that the flush can do the right
27
+ /// amount of invalidation work.
28
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
29
+ pub(crate) struct DeviceChanges: u8 {
30
+ /// The CSS pixel viewport size changed (window resize, zoom, or hidpi
31
+ /// scale change).
32
+ const VIEWPORT_SIZE = 0b0000_0001;
33
+ /// The total scale factor (hidpi scale * zoom) changed. Requires
34
+ /// invalidating cached inline layouts (text is shaped at a specific
35
+ /// scale) and a redraw.
36
+ const SCALE = 0b0000_0010;
37
+ /// The preferred color scheme changed.
38
+ const COLOR_SCHEME = 0b0000_0100;
39
+ /// The media type (e.g. screen/print) changed.
40
+ const MEDIA_TYPE = 0b0000_1000;
41
+ }
42
+ }
43
+
44
+ impl DeviceChanges {
45
+ /// Compute the [`DeviceChanges`] implied by moving from viewport `old` to
46
+ /// viewport `new`.
47
+ pub(crate) fn from_viewports(old: &Viewport, new: &Viewport) -> Self {
48
+ let mut changes = Self::empty();
49
+ if old.logical_size() != new.logical_size() {
50
+ changes |= Self::VIEWPORT_SIZE;
51
+ }
52
+ if old.scale_f64() != new.scale_f64() {
53
+ changes |= Self::SCALE;
54
+ }
55
+ if old.color_scheme != new.color_scheme {
56
+ changes |= Self::COLOR_SCHEME;
57
+ }
58
+ changes
59
+ }
60
+ }
61
+
62
+ pub(crate) fn make_device(
63
+ viewport: &Viewport,
64
+ layout_viewport: Option<(f32, f32)>,
65
+ media_type: MediaType,
66
+ font_ctx: Arc<Mutex<FontContext>>,
67
+ ) -> Device {
68
+ let (width, height) = layout_viewport.unwrap_or_else(|| viewport.logical_size());
69
+ let viewport_size = euclid::Size2D::new(width, height);
70
+ let device_size = euclid::Size2D::new(width, height) * viewport.scale();
71
+ let device_pixel_ratio = euclid::Scale::new(viewport.scale());
72
+
73
+ Device::new(
74
+ media_type,
75
+ QuirksMode::NoQuirks,
76
+ viewport_size,
77
+ device_size,
78
+ device_pixel_ratio,
79
+ Box::new(BlitzFontMetricsProvider { font_ctx }),
80
+ ComputedValues::initial_values_with_font_override(Font::initial_values()),
81
+ match viewport.color_scheme {
82
+ ColorScheme::Light => PrefersColorScheme::Light,
83
+ ColorScheme::Dark => PrefersColorScheme::Dark,
84
+ },
85
+ PointerCapabilities::default(),
86
+ PointerCapabilities::default(),
87
+ )
88
+ }
@@ -0,0 +1,49 @@
1
+ use cursor_icon::CursorIcon;
2
+ use style::values::computed::ui::CursorKind as StyloCursorKind;
3
+
4
+ pub(crate) fn stylo_to_cursor_icon(cursor: StyloCursorKind) -> Option<CursorIcon> {
5
+ match cursor {
6
+ // Auto needs special handling so this function should only really be called with
7
+ // non-Auto values. But better to return a default than panic if it is.
8
+ StyloCursorKind::Auto => {
9
+ #[cfg(feature = "tracing")]
10
+ tracing::warn!("stylo_to_cursor_icon was called with CursorKind::Auto");
11
+ Some(CursorIcon::Default)
12
+ }
13
+ StyloCursorKind::None => None,
14
+ StyloCursorKind::Default => Some(CursorIcon::Default),
15
+ StyloCursorKind::Pointer => Some(CursorIcon::Pointer),
16
+ StyloCursorKind::ContextMenu => Some(CursorIcon::ContextMenu),
17
+ StyloCursorKind::Help => Some(CursorIcon::Help),
18
+ StyloCursorKind::Progress => Some(CursorIcon::Progress),
19
+ StyloCursorKind::Wait => Some(CursorIcon::Wait),
20
+ StyloCursorKind::Cell => Some(CursorIcon::Cell),
21
+ StyloCursorKind::Crosshair => Some(CursorIcon::Crosshair),
22
+ StyloCursorKind::Text => Some(CursorIcon::Text),
23
+ StyloCursorKind::VerticalText => Some(CursorIcon::VerticalText),
24
+ StyloCursorKind::Alias => Some(CursorIcon::Alias),
25
+ StyloCursorKind::Copy => Some(CursorIcon::Copy),
26
+ StyloCursorKind::Move => Some(CursorIcon::Move),
27
+ StyloCursorKind::NoDrop => Some(CursorIcon::NoDrop),
28
+ StyloCursorKind::NotAllowed => Some(CursorIcon::NotAllowed),
29
+ StyloCursorKind::Grab => Some(CursorIcon::Grab),
30
+ StyloCursorKind::Grabbing => Some(CursorIcon::Grabbing),
31
+ StyloCursorKind::EResize => Some(CursorIcon::EResize),
32
+ StyloCursorKind::NResize => Some(CursorIcon::NResize),
33
+ StyloCursorKind::NeResize => Some(CursorIcon::NeResize),
34
+ StyloCursorKind::NwResize => Some(CursorIcon::NwResize),
35
+ StyloCursorKind::SResize => Some(CursorIcon::SResize),
36
+ StyloCursorKind::SeResize => Some(CursorIcon::SeResize),
37
+ StyloCursorKind::SwResize => Some(CursorIcon::SwResize),
38
+ StyloCursorKind::WResize => Some(CursorIcon::WResize),
39
+ StyloCursorKind::EwResize => Some(CursorIcon::EwResize),
40
+ StyloCursorKind::NsResize => Some(CursorIcon::NsResize),
41
+ StyloCursorKind::NeswResize => Some(CursorIcon::NeswResize),
42
+ StyloCursorKind::NwseResize => Some(CursorIcon::NwseResize),
43
+ StyloCursorKind::ColResize => Some(CursorIcon::ColResize),
44
+ StyloCursorKind::RowResize => Some(CursorIcon::RowResize),
45
+ StyloCursorKind::AllScroll => Some(CursorIcon::AllScroll),
46
+ StyloCursorKind::ZoomIn => Some(CursorIcon::ZoomIn),
47
+ StyloCursorKind::ZoomOut => Some(CursorIcon::ZoomOut),
48
+ }
49
+ }
@@ -0,0 +1,129 @@
1
+ use euclid::default::Rect;
2
+ use kurbo::{Affine, Vec2};
3
+ use style::{
4
+ properties::generated::style_structs::Box as BoxStyleStruct,
5
+ values::{
6
+ computed::{CSSPixelLength, Rotate},
7
+ generics::transform::{Scale, Translate},
8
+ },
9
+ };
10
+
11
+ // 6. Current Transformation Matrix
12
+ //
13
+ // The transformation matrix is computed from the transform, transform-origin, translate, rotate, scale, and offset properties as follows:
14
+ //
15
+ // - Start with the identity matrix.
16
+ // - Translate by the computed X, Y, and Z values of transform-origin.
17
+ // - Translate by the computed X, Y, and Z values of translate.
18
+ // - Rotate by the computed <angle> about the specified axis of rotate.
19
+ // - Scale by the computed X, Y, and Z values of scale.
20
+ // - Translate and rotate by the transform specified by offset.
21
+ // - Multiply by each of the transform functions in transform from left to right.
22
+ // - Translate by the negated computed X, Y and Z values of transform-origin.
23
+ //
24
+ // <https://drafts.csswg.org/css-transforms-2/#ctm>
25
+ pub fn resolve_2d_transform(
26
+ box_styles: &BoxStyleStruct,
27
+ reference_box: Rect<CSSPixelLength>,
28
+ ) -> Option<Affine> {
29
+ let translate = match &box_styles.translate {
30
+ Translate::None => None,
31
+ Translate::Translate(x, y, _z) => Some(Vec2 {
32
+ x: x.resolve(reference_box.width()).px() as f64,
33
+ y: y.resolve(reference_box.height()).px() as f64,
34
+ }),
35
+ };
36
+
37
+ let rotate = match &box_styles.rotate {
38
+ Rotate::None => None,
39
+ Rotate::Rotate(angle) => Some(angle.radians64()),
40
+ // A rotation about the z axis stays in the plane; the sign of the
41
+ // axis component decides the direction, its magnitude cancels out.
42
+ Rotate::Rotate3D(x, y, z, angle) if *x == 0.0 && *y == 0.0 && *z != 0.0 => {
43
+ Some(angle.radians64() * z.signum() as f64)
44
+ }
45
+ // TODO: support 3D transforms
46
+ Rotate::Rotate3D(_, _, _, _) => None,
47
+ };
48
+
49
+ let scale_transform = match &box_styles.scale {
50
+ Scale::None => None,
51
+ Scale::Scale(x, y, _z) => Some(Vec2 {
52
+ x: *x as f64,
53
+ y: *y as f64,
54
+ }),
55
+ };
56
+
57
+ let transform = if box_styles.transform.0.is_empty() {
58
+ None
59
+ } else {
60
+ box_styles
61
+ .transform
62
+ .to_transform_3d_matrix(Some(&reference_box))
63
+ .ok()
64
+ // The `has_3d` flag means a 3d function appeared in the list, not that the
65
+ // matrix needs 3d: `translate3d(x, y, 0)` sets it while resolving to a
66
+ // plain 2d translation.
67
+ //
68
+ // TODO: support 3D transforms. Outside a 3d rendering context the spec
69
+ // still applies the transform as a painting effect -- its own example
70
+ // paints `rotateY(50deg)` narrower -- so dropping one is wrong. `is_2d()`
71
+ // is closer than the flag, not the rule.
72
+ // See: https://drafts.csswg.org/css-transforms-2/#3d-transform-rendering
73
+ .filter(|(t, _has_3d)| t.is_2d())
74
+ .map(|(t, _)| {
75
+ // See: https://drafts.csswg.org/css-transforms-2/#two-dimensional-subset
76
+ // And https://docs.rs/kurbo/latest/kurbo/struct.Affine.html#method.new
77
+ Affine::new([t.m11, t.m12, t.m21, t.m22, t.m41, t.m42].map(|v| v as f64))
78
+ })
79
+ };
80
+
81
+ // TODO: support the "offset" property
82
+ // <https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/offset>
83
+
84
+ if translate.is_none() && rotate.is_none() && scale_transform.is_none() && transform.is_none() {
85
+ return None;
86
+ }
87
+
88
+ // Apply the transform origin by:
89
+ // - Translating by the origin offset
90
+ // - Applying our transform
91
+ // - Translating by the inverse of the origin offset
92
+ let transform_origin = &box_styles.transform_origin;
93
+ let origin_translation = Affine::translate(Vec2 {
94
+ x: transform_origin
95
+ .horizontal
96
+ .resolve(reference_box.width())
97
+ .px() as f64,
98
+ y: transform_origin
99
+ .vertical
100
+ .resolve(reference_box.height())
101
+ .px() as f64,
102
+ });
103
+
104
+ let mut resolved = Affine::IDENTITY;
105
+
106
+ if let Some(translation) = translate {
107
+ resolved *= Affine::translate(translation)
108
+ }
109
+
110
+ if let Some(rotation) = rotate {
111
+ resolved *= Affine::rotate(rotation)
112
+ }
113
+
114
+ if let Some(scale_transform) = scale_transform {
115
+ resolved *= Affine::scale_non_uniform(scale_transform.x, scale_transform.y)
116
+ }
117
+
118
+ if let Some(transform) = transform {
119
+ resolved *= transform;
120
+ }
121
+
122
+ resolved = origin_translation * resolved * origin_translation.inverse();
123
+
124
+ if resolved != Affine::IDENTITY {
125
+ Some(resolved)
126
+ } else {
127
+ None
128
+ }
129
+ }