blitz-pdf 0.1.6 → 0.1.8

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 (88) hide show
  1. package/README.md +66 -11
  2. package/THIRD_PARTY_NOTICES.md +19 -1
  3. package/dist/api.d.ts +2 -1
  4. package/dist/api.d.ts.map +1 -1
  5. package/dist/api.js +31 -6
  6. package/dist/api.js.map +1 -1
  7. package/dist/browser.d.ts +2 -1
  8. package/dist/browser.d.ts.map +1 -1
  9. package/dist/browser.js +1 -1
  10. package/dist/browser.js.map +1 -1
  11. package/dist/node.d.ts +2 -1
  12. package/dist/node.d.ts.map +1 -1
  13. package/dist/node.js +6 -2
  14. package/dist/node.js.map +1 -1
  15. package/dist/types.d.ts +16 -1
  16. package/dist/types.d.ts.map +1 -1
  17. package/dist/worker-host.d.ts +10 -5
  18. package/dist/worker-host.d.ts.map +1 -1
  19. package/dist/worker-host.js +149 -28
  20. package/dist/worker-host.js.map +1 -1
  21. package/dist/worker-protocol.d.ts +5 -0
  22. package/dist/worker-protocol.d.ts.map +1 -1
  23. package/dist/worker-runtime.d.ts +1 -1
  24. package/dist/worker-runtime.d.ts.map +1 -1
  25. package/dist/worker-runtime.js +22 -6
  26. package/dist/worker-runtime.js.map +1 -1
  27. package/licenses/Noto-OFL.txt +94 -0
  28. package/licenses/NotoCJK-OFL.txt +92 -0
  29. package/licenses/NotoEmoji-OFL.txt +93 -0
  30. package/licenses/RUST_DEPENDENCIES.txt +34 -40
  31. package/licenses/Unifont-OFL.txt +90 -0
  32. package/licenses/font-sources.json +106 -0
  33. package/package.json +1 -1
  34. package/src/api.ts +32 -7
  35. package/src/browser.ts +2 -1
  36. package/src/node.ts +7 -2
  37. package/src/types.ts +17 -1
  38. package/src/worker-host.ts +148 -29
  39. package/src/worker-protocol.ts +5 -5
  40. package/src/worker-runtime.ts +20 -6
  41. package/vendor/README.md +38 -5
  42. package/vendor/blitz-dom/Cargo.toml +6 -6
  43. package/vendor/blitz-dom/src/accessibility.rs +175 -2
  44. package/vendor/blitz-dom/src/config.rs +8 -10
  45. package/vendor/blitz-dom/src/document.rs +66 -3
  46. package/vendor/blitz-dom/src/events/keyboard.rs +2 -6
  47. package/vendor/blitz-dom/src/layout/construct.rs +5 -300
  48. package/vendor/blitz-dom/src/layout/inline/build.rs +309 -0
  49. package/vendor/blitz-dom/src/layout/{inline.rs → inline/layout.rs} +1 -1
  50. package/vendor/blitz-dom/src/layout/inline/mod.rs +4 -0
  51. package/vendor/blitz-dom/src/layout/mod.rs +3 -1
  52. package/vendor/blitz-dom/src/layout/replaced.rs +13 -4
  53. package/vendor/blitz-dom/src/mutator.rs +47 -0
  54. package/vendor/blitz-dom/src/node/element.rs +17 -0
  55. package/vendor/blitz-dom/src/node/mod.rs +1 -0
  56. package/vendor/blitz-dom/src/node/node.rs +46 -5
  57. package/vendor/blitz-dom/src/node/text.rs +11 -11
  58. package/vendor/blitz-dom/src/resolve.rs +2 -2
  59. package/vendor/blitz-dom/src/stylo.rs +30 -22
  60. package/vendor/blitz-dom/src/util.rs +1 -1
  61. package/vendor/blitz-paint/Cargo.toml +4 -4
  62. package/vendor/fontique/Cargo.toml +194 -0
  63. package/vendor/fontique/LICENSE-APACHE +201 -0
  64. package/vendor/fontique/LICENSE-MIT +25 -0
  65. package/vendor/fontique/README.md +54 -0
  66. package/vendor/fontique/examples/generic_families.rs +37 -0
  67. package/vendor/fontique/src/attributes.rs +42 -0
  68. package/vendor/fontique/src/backend/android.rs +218 -0
  69. package/vendor/fontique/src/backend/coretext.rs +206 -0
  70. package/vendor/fontique/src/backend/dwrite.rs +395 -0
  71. package/vendor/fontique/src/backend/fontconfig.rs +844 -0
  72. package/vendor/fontique/src/backend/mod.rs +75 -0
  73. package/vendor/fontique/src/charmap.rs +127 -0
  74. package/vendor/fontique/src/collection/mod.rs +1016 -0
  75. package/vendor/fontique/src/collection/query.rs +392 -0
  76. package/vendor/fontique/src/fallback.rs +293 -0
  77. package/vendor/fontique/src/family.rs +111 -0
  78. package/vendor/fontique/src/family_name.rs +153 -0
  79. package/vendor/fontique/src/font.rs +562 -0
  80. package/vendor/fontique/src/generic.rs +36 -0
  81. package/vendor/fontique/src/impl_fontconfig.rs +159 -0
  82. package/vendor/fontique/src/lib.rs +87 -0
  83. package/vendor/fontique/src/matching.rs +483 -0
  84. package/vendor/fontique/src/scan.rs +312 -0
  85. package/vendor/fontique/src/script.rs +271 -0
  86. package/vendor/fontique/src/source.rs +108 -0
  87. package/vendor/fontique/src/source_cache.rs +254 -0
  88. package/wasm/blitz_pdf_bg.wasm +0 -0
@@ -3,10 +3,7 @@ use core::str;
3
3
  use std::sync::Arc;
4
4
 
5
5
  use markup5ever::{QualName, local_name};
6
- use parley::{
7
- FontContext, InlineBox, InlineBoxKind, LayoutContext, StyleProperty, TreeBuilder,
8
- WhiteSpaceCollapse,
9
- };
6
+ use parley::StyleProperty;
10
7
  use style::{
11
8
  computed_values::position::T as PositionProperty,
12
9
  data::ElementData as StyloElementData,
@@ -23,20 +20,14 @@ use crate::{
23
20
  layout::damage::{
24
21
  CONSTRUCT_BOX, CONSTRUCT_DESCENDENT, CONSTRUCT_FC, sort_layout_children_by_order,
25
22
  },
26
- node::{
27
- ListItemLayout, ListItemLayoutPosition, Marker, NodeFlags, NodeKind, SpecialElementData,
28
- TextBrush, TextInputData, TextLayout,
29
- },
23
+ node::{NodeFlags, NodeKind, SpecialElementData, TextInputData, TextLayout},
30
24
  qual_name, stylo_to_parley,
31
25
  traversal::{iter_children, iter_children_and_pseudos},
32
26
  };
33
27
 
34
28
  use super::{
35
- damage::ALL_DAMAGE,
36
- list::{BULLET_FONT_FAMILY, collect_list_item_children},
37
- replaced::is_inline_box_element,
29
+ damage::ALL_DAMAGE, list::collect_list_item_children, replaced::is_inline_box_element,
38
30
  table::build_table_context,
39
- text_transform::{CaseTransform, TextTransformer},
40
31
  };
41
32
 
42
33
  const DUMMY_NAME: QualName = qual_name!("div", html);
@@ -733,6 +724,7 @@ fn flush_pseudo_elements(doc: &mut BaseDocument, node_id: NodeId) {
733
724
  doc.nodes[new_node_id].children.push(text_node_id);
734
725
  }
735
726
 
727
+ doc.nodes[new_node_id].record_out_of_flow(pe_style);
736
728
  let mut element_data = StyloElementData::default();
737
729
  element_data.styles.primary = Some(pe_style.clone());
738
730
  element_data.set_restyled();
@@ -787,6 +779,7 @@ fn flush_pseudo_elements(doc: &mut BaseDocument, node_id: NodeId) {
787
779
  (None, None) => {}
788
780
  }
789
781
 
782
+ doc.nodes[pe_node_id].record_out_of_flow(&pe_style);
790
783
  let mut node_styles = doc.nodes[pe_node_id]
791
784
  .try_stylo_element_data_mut()
792
785
  .and_then(|s| s.get_mut());
@@ -1038,291 +1031,3 @@ pub(crate) fn find_inline_layout_embedded_boxes(
1038
1031
  }
1039
1032
  }
1040
1033
  }
1041
-
1042
- pub(crate) fn build_inline_layout_into(
1043
- nodes: &crate::NodeTree,
1044
- layout_ctx: &mut LayoutContext<TextBrush>,
1045
- font_ctx: &mut FontContext,
1046
- text_layout: &mut TextLayout,
1047
- scale: f32,
1048
- inline_context_root_node_id: NodeId,
1049
- ) {
1050
- // Get the inline context's root node's text styles
1051
- let root_node = &nodes[inline_context_root_node_id];
1052
- let root_node_style = root_node.primary_styles().or_else(|| {
1053
- root_node
1054
- .parent
1055
- .and_then(|parent_id| nodes[parent_id].primary_styles())
1056
- });
1057
-
1058
- let mut parley_style = root_node_style
1059
- .as_ref()
1060
- .map(|s| stylo_to_parley::style(inline_context_root_node_id, s))
1061
- .unwrap_or_else(|| parley::TextStyle {
1062
- white_space_collapse: WhiteSpaceCollapse::Collapse,
1063
- ..Default::default()
1064
- });
1065
-
1066
- // The formatting-context root's vertical-align positions its box in its
1067
- // parent (for example a middle-aligned table cell), not its own text runs.
1068
- // Passing it to Parley shifts the root against its own strut and inflates
1069
- // every line. Descendant inline spans still use their own vertical-align.
1070
- parley_style.vertical_align = parley::VerticalAlign::BASELINE;
1071
-
1072
- // Create a parley tree builder
1073
- let mut builder = layout_ctx.tree_builder(font_ctx, scale, true, &parley_style);
1074
- if let Some(style) = root_node_style.as_deref() {
1075
- builder.set_base_direction(stylo_to_parley::base_direction(
1076
- style.clone_direction(),
1077
- style.clone_unicode_bidi(),
1078
- ));
1079
- }
1080
-
1081
- let text_transform = root_node_style
1082
- .as_deref()
1083
- .map(|s| CaseTransform::from_style(s))
1084
- .unwrap_or(CaseTransform::NONE);
1085
-
1086
- // Render position-inside list items
1087
- if let Some(ListItemLayout {
1088
- marker,
1089
- position: ListItemLayoutPosition::Inside,
1090
- }) = root_node
1091
- .element_data()
1092
- .and_then(|el| el.list_item_data.as_deref())
1093
- {
1094
- match marker {
1095
- // Bullet glyphs live in the bundled bullet font. The position-outside
1096
- // path already asks for it; without the same span here a marker like
1097
- // disclosure-closed (U+25B8) falls back to the element's own font and
1098
- // renders as a missing glyph.
1099
- Marker::Char(char) => {
1100
- let mut marker_style = parley_style.clone();
1101
- marker_style.font_family = BULLET_FONT_FAMILY.into();
1102
- builder.push_style_span(marker_style);
1103
- builder.push_text(&format!("{char} "));
1104
- builder.pop_style_span();
1105
- }
1106
- Marker::String(str) => builder.push_text(str),
1107
- }
1108
- };
1109
- // The marker is a separate box, so words in the content don't continue from it.
1110
- let mut text_transformer = TextTransformer::default();
1111
- text_transformer.word_break(&builder);
1112
-
1113
- if let Some(before_id) = root_node.before() {
1114
- build_inline_layout_recursive(
1115
- &mut builder,
1116
- &mut text_transformer,
1117
- nodes,
1118
- before_id,
1119
- &text_transform,
1120
- );
1121
- }
1122
- for child_id in root_node.children.iter().copied() {
1123
- build_inline_layout_recursive(
1124
- &mut builder,
1125
- &mut text_transformer,
1126
- nodes,
1127
- child_id,
1128
- &text_transform,
1129
- );
1130
- }
1131
- if let Some(after_id) = root_node.after() {
1132
- build_inline_layout_recursive(
1133
- &mut builder,
1134
- &mut text_transformer,
1135
- nodes,
1136
- after_id,
1137
- &text_transform,
1138
- );
1139
- }
1140
-
1141
- text_layout.text = builder.build_into(&mut text_layout.layout);
1142
- return;
1143
-
1144
- fn build_inline_layout_recursive(
1145
- builder: &mut TreeBuilder<TextBrush>,
1146
- text_transformer: &mut TextTransformer,
1147
- nodes: &crate::NodeTree,
1148
- node_id: NodeId,
1149
- parent_text_transform: &CaseTransform,
1150
- ) {
1151
- let node = &nodes[node_id];
1152
-
1153
- let style = node.primary_styles();
1154
- let style = style.as_ref();
1155
-
1156
- let text_transform = style
1157
- .map(|s| CaseTransform::from_style(s))
1158
- .unwrap_or(CaseTransform::NONE);
1159
-
1160
- match &node.data {
1161
- NodeData::Element(element_data) | NodeData::AnonymousBlock(element_data) => {
1162
- // if the input type is hidden, hide it
1163
- if *element_data.name.local == *"input" {
1164
- if let Some("hidden") = element_data.attr(local_name!("type")) {
1165
- return;
1166
- }
1167
- }
1168
-
1169
- let display = node.display_style().unwrap_or(Display::inline());
1170
- let position = style
1171
- .map(|s| s.clone_position())
1172
- .unwrap_or(PositionProperty::Static);
1173
- let float = style.map(|s| s.clone_float()).unwrap_or(Float::None);
1174
- let box_kind = if position.is_absolutely_positioned() {
1175
- InlineBoxKind::OutOfFlow
1176
- } else if float.is_floating() {
1177
- InlineBoxKind::CustomOutOfFlow
1178
- } else {
1179
- InlineBoxKind::InFlow
1180
- };
1181
-
1182
- match (display.outside(), display.inside()) {
1183
- (DisplayOutside::None, DisplayInside::None) => {
1184
- // node.remove_damage(CONSTRUCT_DESCENDENT | CONSTRUCT_FC | CONSTRUCT_BOX);
1185
- }
1186
- (DisplayOutside::None, DisplayInside::Contents) => {
1187
- let whitespace = style.map(|s| {
1188
- [
1189
- parley::StyleProperty::WhiteSpaceCollapse(
1190
- stylo_to_parley::white_space_collapse(
1191
- s.clone_white_space_collapse(),
1192
- ),
1193
- ),
1194
- parley::StyleProperty::TextWrapMode(
1195
- stylo_to_parley::text_wrap_mode(s.clone_text_wrap_mode()),
1196
- ),
1197
- ]
1198
- });
1199
- builder.push_style_modification_span(
1200
- whitespace
1201
- .as_ref()
1202
- .map_or(&[][..], |styles| styles.as_slice()),
1203
- );
1204
- for child_id in node.children.iter().copied() {
1205
- // node.remove_damage(CONSTRUCT_DESCENDENT | CONSTRUCT_FC | CONSTRUCT_BOX);
1206
- build_inline_layout_recursive(
1207
- builder,
1208
- text_transformer,
1209
- nodes,
1210
- child_id,
1211
- &text_transform,
1212
- );
1213
- }
1214
- builder.pop_style_span();
1215
- }
1216
- (DisplayOutside::Inline, DisplayInside::Flow) => {
1217
- let tag_name = &element_data.name.local;
1218
-
1219
- if is_inline_box_element(tag_name) {
1220
- if box_kind == InlineBoxKind::InFlow {
1221
- text_transformer.word_break(builder);
1222
- }
1223
- builder.push_inline_box(InlineBox {
1224
- id: node_id.as_u64(),
1225
- kind: box_kind,
1226
- // Overridden by push_inline_box method
1227
- index: 0,
1228
- // Width and height are set during layout
1229
- width: 0.0,
1230
- height: 0.0,
1231
- baseline: None,
1232
- vertical_align: node
1233
- .primary_styles()
1234
- .map(|s| stylo_to_parley::vertical_align(&s))
1235
- .unwrap_or_default(),
1236
- });
1237
- } else if *tag_name == local_name!("br") {
1238
- // node.remove_damage(CONSTRUCT_DESCENDENT | CONSTRUCT_FC | CONSTRUCT_BOX);
1239
- // TODO: update span id for br spans
1240
- builder.push_style_modification_span(&[
1241
- parley::StyleProperty::WhiteSpaceCollapse(
1242
- WhiteSpaceCollapse::Preserve,
1243
- ),
1244
- ]);
1245
- builder.push_text("\n");
1246
- builder.pop_style_span();
1247
- text_transformer.word_break(builder);
1248
- } else {
1249
- // node.remove_damage(CONSTRUCT_DESCENDENT | CONSTRUCT_FC | CONSTRUCT_BOX);
1250
- let style = node
1251
- .primary_styles()
1252
- .map(|s| stylo_to_parley::style(node.id, &s))
1253
- .unwrap_or_else(|| parley::TextStyle {
1254
- white_space_collapse: WhiteSpaceCollapse::Collapse,
1255
- ..Default::default()
1256
- });
1257
-
1258
- builder.push_style_span(style);
1259
-
1260
- if let Some(before_id) = node.before() {
1261
- build_inline_layout_recursive(
1262
- builder,
1263
- text_transformer,
1264
- nodes,
1265
- before_id,
1266
- &text_transform,
1267
- );
1268
- }
1269
-
1270
- for child_id in node.children.iter().copied() {
1271
- build_inline_layout_recursive(
1272
- builder,
1273
- text_transformer,
1274
- nodes,
1275
- child_id,
1276
- &text_transform,
1277
- );
1278
- }
1279
- if let Some(after_id) = node.after() {
1280
- build_inline_layout_recursive(
1281
- builder,
1282
- text_transformer,
1283
- nodes,
1284
- after_id,
1285
- &text_transform,
1286
- );
1287
- }
1288
-
1289
- builder.pop_style_span();
1290
- }
1291
- }
1292
- // Inline box
1293
- (_, _) => {
1294
- if box_kind == InlineBoxKind::InFlow {
1295
- text_transformer.word_break(builder);
1296
- }
1297
- builder.push_inline_box(InlineBox {
1298
- id: node_id.as_u64(),
1299
- kind: box_kind,
1300
- // Overridden by push_inline_box method
1301
- index: 0,
1302
- // Width and height are set during layout
1303
- width: 0.0,
1304
- height: 0.0,
1305
- baseline: None,
1306
- vertical_align: node
1307
- .primary_styles()
1308
- .map(|s| stylo_to_parley::vertical_align(&s))
1309
- .unwrap_or_default(),
1310
- });
1311
- }
1312
- };
1313
- }
1314
- NodeData::Text(data) => {
1315
- // node.remove_damage(CONSTRUCT_DESCENDENT | CONSTRUCT_FC | CONSTRUCT_BOX);
1316
- // dbg!(&data.content);
1317
-
1318
- let text =
1319
- text_transformer.transform(&data.content, parent_text_transform, builder);
1320
- builder.push_text(text);
1321
- }
1322
- NodeData::Comment { .. } => {
1323
- // node.remove_damage(CONSTRUCT_DESCENDENT | CONSTRUCT_FC | CONSTRUCT_BOX);
1324
- }
1325
- NodeData::Document(_) => unreachable!(),
1326
- }
1327
- }
1328
- }
@@ -0,0 +1,309 @@
1
+ use blitz_traits::node_id::NodeId;
2
+ use markup5ever::local_name;
3
+ use parley::{
4
+ FontContext, InlineBox, InlineBoxKind, LayoutContext, TreeBuilder, WhiteSpaceCollapse,
5
+ };
6
+ use style::{
7
+ computed_values::position::T as PositionProperty,
8
+ values::{
9
+ computed::{Display, Float},
10
+ specified::box_::{DisplayInside, DisplayOutside},
11
+ },
12
+ };
13
+
14
+ use crate::{
15
+ NodeData,
16
+ layout::list::BULLET_FONT_FAMILY,
17
+ layout::replaced::is_inline_box_element,
18
+ layout::text_transform::{CaseTransform, TextTransformer},
19
+ node::{ListItemLayout, ListItemLayoutPosition, Marker, TextBrush, TextLayout},
20
+ stylo_to_parley,
21
+ };
22
+
23
+ pub(crate) fn build_inline_layout_into(
24
+ nodes: &crate::NodeTree,
25
+ layout_ctx: &mut LayoutContext<TextBrush>,
26
+ font_ctx: &mut FontContext,
27
+ text_layout: &mut TextLayout,
28
+ scale: f32,
29
+ inline_context_root_node_id: NodeId,
30
+ ) {
31
+ // Get the inline context's root node's text styles
32
+ let root_node = &nodes[inline_context_root_node_id];
33
+ let root_node_style = root_node.primary_styles().or_else(|| {
34
+ root_node
35
+ .parent
36
+ .and_then(|parent_id| nodes[parent_id].primary_styles())
37
+ });
38
+
39
+ let mut parley_style = root_node_style
40
+ .as_ref()
41
+ .map(|s| stylo_to_parley::style(inline_context_root_node_id, s))
42
+ .unwrap_or_else(|| parley::TextStyle {
43
+ white_space_collapse: WhiteSpaceCollapse::Collapse,
44
+ ..Default::default()
45
+ });
46
+
47
+ // The formatting-context root's vertical-align positions its box in its
48
+ // parent (for example a middle-aligned table cell), not its own text runs.
49
+ // Passing it to Parley shifts the root against its own strut and inflates
50
+ // every line. Descendant inline spans still use their own vertical-align.
51
+ parley_style.vertical_align = parley::VerticalAlign::BASELINE;
52
+
53
+ // Create a parley tree builder
54
+ let mut builder = layout_ctx.tree_builder(font_ctx, scale, true, &parley_style);
55
+ if let Some(style) = root_node_style.as_deref() {
56
+ builder.set_base_direction(stylo_to_parley::base_direction(
57
+ style.clone_direction(),
58
+ style.clone_unicode_bidi(),
59
+ ));
60
+ }
61
+
62
+ let text_transform = root_node_style
63
+ .as_deref()
64
+ .map(|s| CaseTransform::from_style(s))
65
+ .unwrap_or(CaseTransform::NONE);
66
+
67
+ // Render position-inside list items
68
+ if let Some(ListItemLayout {
69
+ marker,
70
+ position: ListItemLayoutPosition::Inside,
71
+ }) = root_node
72
+ .element_data()
73
+ .and_then(|el| el.list_item_data.as_deref())
74
+ {
75
+ match marker {
76
+ // Bullet glyphs live in the bundled bullet font. The position-outside
77
+ // path already asks for it; without the same span here a marker like
78
+ // disclosure-closed (U+25B8) falls back to the element's own font and
79
+ // renders as a missing glyph.
80
+ Marker::Char(char) => {
81
+ let mut marker_style = parley_style.clone();
82
+ marker_style.font_family = BULLET_FONT_FAMILY.into();
83
+ builder.push_style_span(marker_style);
84
+ builder.push_text(&format!("{char} "));
85
+ builder.pop_style_span();
86
+ }
87
+ Marker::String(str) => builder.push_text(str),
88
+ }
89
+ };
90
+ // The marker is a separate box, so words in the content don't continue from it.
91
+ let mut text_transformer = TextTransformer::default();
92
+ text_transformer.word_break(&builder);
93
+
94
+ if let Some(before_id) = root_node.before() {
95
+ build_inline_layout_recursive(
96
+ &mut builder,
97
+ &mut text_transformer,
98
+ nodes,
99
+ before_id,
100
+ &text_transform,
101
+ );
102
+ }
103
+ for child_id in root_node.children.iter().copied() {
104
+ build_inline_layout_recursive(
105
+ &mut builder,
106
+ &mut text_transformer,
107
+ nodes,
108
+ child_id,
109
+ &text_transform,
110
+ );
111
+ }
112
+ if let Some(after_id) = root_node.after() {
113
+ build_inline_layout_recursive(
114
+ &mut builder,
115
+ &mut text_transformer,
116
+ nodes,
117
+ after_id,
118
+ &text_transform,
119
+ );
120
+ }
121
+
122
+ text_layout.text = builder.build_into(&mut text_layout.layout);
123
+ return;
124
+
125
+ fn build_inline_layout_recursive(
126
+ builder: &mut TreeBuilder<TextBrush>,
127
+ text_transformer: &mut TextTransformer,
128
+ nodes: &crate::NodeTree,
129
+ node_id: NodeId,
130
+ parent_text_transform: &CaseTransform,
131
+ ) {
132
+ let node = &nodes[node_id];
133
+
134
+ let style = node.primary_styles();
135
+ let style = style.as_ref();
136
+
137
+ let text_transform = style
138
+ .map(|s| CaseTransform::from_style(s))
139
+ .unwrap_or(CaseTransform::NONE);
140
+
141
+ match &node.data {
142
+ NodeData::Element(element_data) | NodeData::AnonymousBlock(element_data) => {
143
+ // if the input type is hidden, hide it
144
+ if *element_data.name.local == *"input" {
145
+ if let Some("hidden") = element_data.attr(local_name!("type")) {
146
+ return;
147
+ }
148
+ }
149
+
150
+ let display = node.display_style().unwrap_or(Display::inline());
151
+ let position = style
152
+ .map(|s| s.clone_position())
153
+ .unwrap_or(PositionProperty::Static);
154
+ let float = style.map(|s| s.clone_float()).unwrap_or(Float::None);
155
+ let box_kind = if position.is_absolutely_positioned() {
156
+ InlineBoxKind::OutOfFlow
157
+ } else if float.is_floating() {
158
+ InlineBoxKind::CustomOutOfFlow
159
+ } else {
160
+ InlineBoxKind::InFlow
161
+ };
162
+
163
+ match (display.outside(), display.inside()) {
164
+ (DisplayOutside::None, DisplayInside::None) => {
165
+ // node.remove_damage(CONSTRUCT_DESCENDENT | CONSTRUCT_FC | CONSTRUCT_BOX);
166
+ }
167
+ (DisplayOutside::None, DisplayInside::Contents) => {
168
+ let whitespace = style.map(|s| {
169
+ [
170
+ parley::StyleProperty::WhiteSpaceCollapse(
171
+ stylo_to_parley::white_space_collapse(
172
+ s.clone_white_space_collapse(),
173
+ ),
174
+ ),
175
+ parley::StyleProperty::TextWrapMode(
176
+ stylo_to_parley::text_wrap_mode(s.clone_text_wrap_mode()),
177
+ ),
178
+ ]
179
+ });
180
+ builder.push_style_modification_span(
181
+ whitespace
182
+ .as_ref()
183
+ .map_or(&[][..], |styles| styles.as_slice()),
184
+ );
185
+ for child_id in node.children.iter().copied() {
186
+ // node.remove_damage(CONSTRUCT_DESCENDENT | CONSTRUCT_FC | CONSTRUCT_BOX);
187
+ build_inline_layout_recursive(
188
+ builder,
189
+ text_transformer,
190
+ nodes,
191
+ child_id,
192
+ &text_transform,
193
+ );
194
+ }
195
+ builder.pop_style_span();
196
+ }
197
+ (DisplayOutside::Inline, DisplayInside::Flow) => {
198
+ let tag_name = &element_data.name.local;
199
+
200
+ if is_inline_box_element(tag_name) {
201
+ if box_kind == InlineBoxKind::InFlow {
202
+ text_transformer.word_break(builder);
203
+ }
204
+ builder.push_inline_box(InlineBox {
205
+ id: node_id.as_u64(),
206
+ kind: box_kind,
207
+ // Overridden by push_inline_box method
208
+ index: 0,
209
+ // Width and height are set during layout
210
+ width: 0.0,
211
+ height: 0.0,
212
+ baseline: None,
213
+ vertical_align: node
214
+ .primary_styles()
215
+ .map(|s| stylo_to_parley::vertical_align(&s))
216
+ .unwrap_or_default(),
217
+ });
218
+ } else if *tag_name == local_name!("br") {
219
+ // node.remove_damage(CONSTRUCT_DESCENDENT | CONSTRUCT_FC | CONSTRUCT_BOX);
220
+ // TODO: update span id for br spans
221
+ builder.push_style_modification_span(&[
222
+ parley::StyleProperty::WhiteSpaceCollapse(
223
+ WhiteSpaceCollapse::Preserve,
224
+ ),
225
+ ]);
226
+ builder.push_text("\n");
227
+ builder.pop_style_span();
228
+ text_transformer.word_break(builder);
229
+ } else {
230
+ // node.remove_damage(CONSTRUCT_DESCENDENT | CONSTRUCT_FC | CONSTRUCT_BOX);
231
+ let style = node
232
+ .primary_styles()
233
+ .map(|s| stylo_to_parley::style(node.id, &s))
234
+ .unwrap_or_else(|| parley::TextStyle {
235
+ white_space_collapse: WhiteSpaceCollapse::Collapse,
236
+ ..Default::default()
237
+ });
238
+
239
+ builder.push_style_span(style);
240
+
241
+ if let Some(before_id) = node.before() {
242
+ build_inline_layout_recursive(
243
+ builder,
244
+ text_transformer,
245
+ nodes,
246
+ before_id,
247
+ &text_transform,
248
+ );
249
+ }
250
+
251
+ for child_id in node.children.iter().copied() {
252
+ build_inline_layout_recursive(
253
+ builder,
254
+ text_transformer,
255
+ nodes,
256
+ child_id,
257
+ &text_transform,
258
+ );
259
+ }
260
+ if let Some(after_id) = node.after() {
261
+ build_inline_layout_recursive(
262
+ builder,
263
+ text_transformer,
264
+ nodes,
265
+ after_id,
266
+ &text_transform,
267
+ );
268
+ }
269
+
270
+ builder.pop_style_span();
271
+ }
272
+ }
273
+ // Inline box
274
+ (_, _) => {
275
+ if box_kind == InlineBoxKind::InFlow {
276
+ text_transformer.word_break(builder);
277
+ }
278
+ builder.push_inline_box(InlineBox {
279
+ id: node_id.as_u64(),
280
+ kind: box_kind,
281
+ // Overridden by push_inline_box method
282
+ index: 0,
283
+ // Width and height are set during layout
284
+ width: 0.0,
285
+ height: 0.0,
286
+ baseline: None,
287
+ vertical_align: node
288
+ .primary_styles()
289
+ .map(|s| stylo_to_parley::vertical_align(&s))
290
+ .unwrap_or_default(),
291
+ });
292
+ }
293
+ };
294
+ }
295
+ NodeData::Text(data) => {
296
+ // node.remove_damage(CONSTRUCT_DESCENDENT | CONSTRUCT_FC | CONSTRUCT_BOX);
297
+ // dbg!(&data.content);
298
+
299
+ let text =
300
+ text_transformer.transform(&data.content, parent_text_transform, builder);
301
+ builder.push_text(text);
302
+ }
303
+ NodeData::Comment { .. } => {
304
+ // node.remove_damage(CONSTRUCT_DESCENDENT | CONSTRUCT_FC | CONSTRUCT_BOX);
305
+ }
306
+ NodeData::Document(_) => unreachable!(),
307
+ }
308
+ }
309
+ }
@@ -20,8 +20,8 @@ use taffy::{BlockItemStyle as _, Clear, Float, prelude::TaffyMaxContent};
20
20
 
21
21
  use stylo_taffy::StyleFlags;
22
22
 
23
- use super::resolve_calc_value;
24
23
  use crate::layout::LayoutPassState;
24
+ use crate::layout::resolve_calc_value;
25
25
  use crate::stylo_to_parley;
26
26
 
27
27
  /// Subtract a child's margins from the definite axes of the available space it is laid out in.
@@ -0,0 +1,4 @@
1
+ mod build;
2
+ mod layout;
3
+
4
+ pub(crate) use build::build_inline_layout_into;
@@ -853,7 +853,9 @@ impl RoundTree for LayoutPassState<'_> {
853
853
  }
854
854
 
855
855
  fn is_out_of_flow(&self, node_id: NodeId) -> bool {
856
- self.node_from_id(node_id).is_out_of_flow()
856
+ self.node_from_id(node_id)
857
+ .out_of_flow
858
+ .load(core::sync::atomic::Ordering::Relaxed)
857
859
  }
858
860
 
859
861
  fn hoisted_child_count(&self, node_id: NodeId) -> usize {