blitz-pdf 0.0.0-stage → 0.1.1

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 (370) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +391 -2
  3. package/THIRD_PARTY_NOTICES.md +25 -0
  4. package/assets/icon.svg +4 -0
  5. package/dist/api.d.ts +7 -0
  6. package/dist/api.d.ts.map +1 -0
  7. package/dist/api.js +46 -0
  8. package/dist/api.js.map +1 -0
  9. package/dist/assets.d.ts +7 -0
  10. package/dist/assets.d.ts.map +1 -0
  11. package/dist/assets.js +52 -0
  12. package/dist/assets.js.map +1 -0
  13. package/dist/browser.d.ts +3 -0
  14. package/dist/browser.d.ts.map +1 -0
  15. package/dist/browser.js +3 -0
  16. package/dist/browser.js.map +1 -0
  17. package/dist/node.d.ts +3 -0
  18. package/dist/node.d.ts.map +1 -0
  19. package/dist/node.js +10 -0
  20. package/dist/node.js.map +1 -0
  21. package/dist/options.d.ts +24 -0
  22. package/dist/options.d.ts.map +1 -0
  23. package/dist/options.js +135 -0
  24. package/dist/options.js.map +1 -0
  25. package/dist/types.d.ts +51 -0
  26. package/dist/types.d.ts.map +1 -0
  27. package/dist/types.js +2 -0
  28. package/dist/types.js.map +1 -0
  29. package/examples/bun.ts +8 -0
  30. package/examples/german-invoice/README.md +70 -0
  31. package/examples/german-invoice/data.mjs +83 -0
  32. package/examples/german-invoice/invoice.css +59 -0
  33. package/examples/german-invoice/template.mjs +49 -0
  34. package/examples/german-invoice.mjs +20 -0
  35. package/examples/invoice.html +29 -0
  36. package/examples/node.mjs +8 -0
  37. package/examples/pagination.html +40 -0
  38. package/examples/pagination.mjs +8 -0
  39. package/licenses/DejaVu.txt +187 -0
  40. package/licenses/RUST_DEPENDENCIES.txt +11577 -0
  41. package/package.json +89 -4
  42. package/src/api.ts +44 -0
  43. package/src/assets.ts +43 -0
  44. package/src/browser.ts +6 -0
  45. package/src/node.ts +12 -0
  46. package/src/options.ts +101 -0
  47. package/src/types.ts +49 -0
  48. package/vendor/README.md +17 -0
  49. package/vendor/stylo/.cargo-ok +1 -0
  50. package/vendor/stylo/.cargo_vcs_info.json +6 -0
  51. package/vendor/stylo/Cargo.lock +1485 -0
  52. package/vendor/stylo/Cargo.toml +274 -0
  53. package/vendor/stylo/LICENSE +373 -0
  54. package/vendor/stylo/README.md +6 -0
  55. package/vendor/stylo/applicable_declarations.rs +328 -0
  56. package/vendor/stylo/author_styles.rs +79 -0
  57. package/vendor/stylo/bezier.rs +176 -0
  58. package/vendor/stylo/bloom.rs +414 -0
  59. package/vendor/stylo/build.rs +91 -0
  60. package/vendor/stylo/build_gecko.rs +393 -0
  61. package/vendor/stylo/color/color_function.rs +601 -0
  62. package/vendor/stylo/color/component.rs +207 -0
  63. package/vendor/stylo/color/convert.rs +935 -0
  64. package/vendor/stylo/color/gamut/raytrace.rs +265 -0
  65. package/vendor/stylo/color/gamut.rs +227 -0
  66. package/vendor/stylo/color/mix.rs +645 -0
  67. package/vendor/stylo/color/mod.rs +750 -0
  68. package/vendor/stylo/color/parsing.rs +770 -0
  69. package/vendor/stylo/color/to_css.rs +297 -0
  70. package/vendor/stylo/context.rs +716 -0
  71. package/vendor/stylo/counter_style/mod.rs +754 -0
  72. package/vendor/stylo/counter_style/predefined.rs +61 -0
  73. package/vendor/stylo/counter_style/update_predefined.py +35 -0
  74. package/vendor/stylo/custom_properties.rs +2023 -0
  75. package/vendor/stylo/custom_properties_map.rs +220 -0
  76. package/vendor/stylo/data.rs +693 -0
  77. package/vendor/stylo/device/gecko.rs +486 -0
  78. package/vendor/stylo/device/mod.rs +304 -0
  79. package/vendor/stylo/device/servo.rs +507 -0
  80. package/vendor/stylo/dom.rs +1164 -0
  81. package/vendor/stylo/dom_apis.rs +937 -0
  82. package/vendor/stylo/driver.rs +172 -0
  83. package/vendor/stylo/error_reporting.rs +484 -0
  84. package/vendor/stylo/font_face.rs +558 -0
  85. package/vendor/stylo/font_metrics.rs +124 -0
  86. package/vendor/stylo/gecko/anon_boxes.toml +113 -0
  87. package/vendor/stylo/gecko/arc_types.rs +211 -0
  88. package/vendor/stylo/gecko/conversions.rs +59 -0
  89. package/vendor/stylo/gecko/data.rs +222 -0
  90. package/vendor/stylo/gecko/media_features.rs +971 -0
  91. package/vendor/stylo/gecko/mod.rs +20 -0
  92. package/vendor/stylo/gecko/non_ts_pseudo_class_list.rs +119 -0
  93. package/vendor/stylo/gecko/pseudo_element.rs +640 -0
  94. package/vendor/stylo/gecko/pseudo_element_definition.mako.rs +298 -0
  95. package/vendor/stylo/gecko/pseudo_elements.py +137 -0
  96. package/vendor/stylo/gecko/pseudo_elements.toml +197 -0
  97. package/vendor/stylo/gecko/regen_pseudo_elements.py +33 -0
  98. package/vendor/stylo/gecko/restyle_damage.rs +127 -0
  99. package/vendor/stylo/gecko/selector_parser.rs +627 -0
  100. package/vendor/stylo/gecko/snapshot.rs +202 -0
  101. package/vendor/stylo/gecko/snapshot_helpers.rs +334 -0
  102. package/vendor/stylo/gecko/traversal.rs +52 -0
  103. package/vendor/stylo/gecko/wrapper.rs +2258 -0
  104. package/vendor/stylo/gecko_bindings/mod.rs +34 -0
  105. package/vendor/stylo/gecko_bindings/sugar/mod.rs +12 -0
  106. package/vendor/stylo/gecko_bindings/sugar/ns_com_ptr.rs +15 -0
  107. package/vendor/stylo/gecko_bindings/sugar/ns_compatibility.rs +19 -0
  108. package/vendor/stylo/gecko_bindings/sugar/ns_style_auto_array.rs +111 -0
  109. package/vendor/stylo/gecko_bindings/sugar/origin_flags.rs +31 -0
  110. package/vendor/stylo/gecko_bindings/sugar/ownership.rs +70 -0
  111. package/vendor/stylo/gecko_bindings/sugar/refptr.rs +299 -0
  112. package/vendor/stylo/gecko_string_cache/mod.rs +543 -0
  113. package/vendor/stylo/gecko_string_cache/namespace.rs +106 -0
  114. package/vendor/stylo/global_style_data.rs +224 -0
  115. package/vendor/stylo/invalidation/element/document_state.rs +156 -0
  116. package/vendor/stylo/invalidation/element/element_wrapper.rs +432 -0
  117. package/vendor/stylo/invalidation/element/invalidation_map.rs +1631 -0
  118. package/vendor/stylo/invalidation/element/invalidator.rs +1470 -0
  119. package/vendor/stylo/invalidation/element/mod.rs +13 -0
  120. package/vendor/stylo/invalidation/element/relative_selector.rs +1399 -0
  121. package/vendor/stylo/invalidation/element/restyle_hints.rs +226 -0
  122. package/vendor/stylo/invalidation/element/state_and_attributes.rs +756 -0
  123. package/vendor/stylo/invalidation/media_queries.rs +144 -0
  124. package/vendor/stylo/invalidation/mod.rs +10 -0
  125. package/vendor/stylo/invalidation/stylesheets.rs +745 -0
  126. package/vendor/stylo/invalidation/viewport_units.rs +71 -0
  127. package/vendor/stylo/lib.rs +336 -0
  128. package/vendor/stylo/logical_geometry.rs +1684 -0
  129. package/vendor/stylo/macros.rs +70 -0
  130. package/vendor/stylo/matching.rs +1226 -0
  131. package/vendor/stylo/media_queries/media_list.rs +168 -0
  132. package/vendor/stylo/media_queries/media_query.rs +190 -0
  133. package/vendor/stylo/media_queries/mod.rs +13 -0
  134. package/vendor/stylo/parallel.rs +205 -0
  135. package/vendor/stylo/parser.rs +276 -0
  136. package/vendor/stylo/piecewise_linear.rs +282 -0
  137. package/vendor/stylo/prefs.rs +33 -0
  138. package/vendor/stylo/properties/build.py +119 -0
  139. package/vendor/stylo/properties/cascade.rs +2704 -0
  140. package/vendor/stylo/properties/computed_value_flags.rs +206 -0
  141. package/vendor/stylo/properties/counted_unknown_properties.py +104 -0
  142. package/vendor/stylo/properties/counter_style_descriptors.toml +45 -0
  143. package/vendor/stylo/properties/data.py +1375 -0
  144. package/vendor/stylo/properties/declaration_block.rs +1788 -0
  145. package/vendor/stylo/properties/font_face_descriptors.toml +50 -0
  146. package/vendor/stylo/properties/gecko.mako.rs +1555 -0
  147. package/vendor/stylo/properties/helpers/animated_properties.mako.rs +800 -0
  148. package/vendor/stylo/properties/helpers.mako.rs +812 -0
  149. package/vendor/stylo/properties/longhands.toml +4305 -0
  150. package/vendor/stylo/properties/mod.rs +1857 -0
  151. package/vendor/stylo/properties/properties.html.mako +31 -0
  152. package/vendor/stylo/properties/properties.mako.rs +3103 -0
  153. package/vendor/stylo/properties/property_descriptors.toml +18 -0
  154. package/vendor/stylo/properties/shorthands.rs +4241 -0
  155. package/vendor/stylo/properties/shorthands.toml +575 -0
  156. package/vendor/stylo/properties/vendored_python/mako-1.3.10-py3-none-any.whl +0 -0
  157. package/vendor/stylo/properties/vendored_python/markupsafe/LICENSE.txt +28 -0
  158. package/vendor/stylo/properties/vendored_python/markupsafe/__init__.py +384 -0
  159. package/vendor/stylo/properties/vendored_python/toml-0.10.2-py2.py3-none-any.whl +0 -0
  160. package/vendor/stylo/properties/view_transition_descriptors.toml +11 -0
  161. package/vendor/stylo/properties_and_values/mod.rs +12 -0
  162. package/vendor/stylo/properties_and_values/registry.rs +65 -0
  163. package/vendor/stylo/properties_and_values/rule.rs +331 -0
  164. package/vendor/stylo/properties_and_values/syntax/ascii.rs +60 -0
  165. package/vendor/stylo/properties_and_values/syntax/data_type.rs +146 -0
  166. package/vendor/stylo/properties_and_values/syntax/mod.rs +437 -0
  167. package/vendor/stylo/properties_and_values/value.rs +758 -0
  168. package/vendor/stylo/queries/condition.rs +996 -0
  169. package/vendor/stylo/queries/feature.rs +199 -0
  170. package/vendor/stylo/queries/feature_expression.rs +1170 -0
  171. package/vendor/stylo/queries/mod.rs +19 -0
  172. package/vendor/stylo/queries/values.rs +46 -0
  173. package/vendor/stylo/rule_cache.rs +267 -0
  174. package/vendor/stylo/rule_collector.rs +554 -0
  175. package/vendor/stylo/rule_tree/core.rs +787 -0
  176. package/vendor/stylo/rule_tree/level.rs +396 -0
  177. package/vendor/stylo/rule_tree/map.rs +201 -0
  178. package/vendor/stylo/rule_tree/mod.rs +427 -0
  179. package/vendor/stylo/rule_tree/source.rs +80 -0
  180. package/vendor/stylo/rule_tree/unsafe_box.rs +78 -0
  181. package/vendor/stylo/scoped_tls.rs +80 -0
  182. package/vendor/stylo/selector_map.rs +1050 -0
  183. package/vendor/stylo/selector_parser.rs +305 -0
  184. package/vendor/stylo/servo/animation.rs +1922 -0
  185. package/vendor/stylo/servo/attr.rs +714 -0
  186. package/vendor/stylo/servo/encoding_support.rs +81 -0
  187. package/vendor/stylo/servo/media_features.rs +254 -0
  188. package/vendor/stylo/servo/mod.rs +16 -0
  189. package/vendor/stylo/servo/restyle_damage.rs +215 -0
  190. package/vendor/stylo/servo/selector_parser.rs +1036 -0
  191. package/vendor/stylo/servo/shadow_parts.rs +207 -0
  192. package/vendor/stylo/shared_lock.rs +271 -0
  193. package/vendor/stylo/sharing/checks.rs +281 -0
  194. package/vendor/stylo/sharing/mod.rs +1000 -0
  195. package/vendor/stylo/simple_buckets_map.rs +52 -0
  196. package/vendor/stylo/str.rs +168 -0
  197. package/vendor/stylo/style_adjuster.rs +1086 -0
  198. package/vendor/stylo/style_resolver.rs +658 -0
  199. package/vendor/stylo/stylesheet_set.rs +658 -0
  200. package/vendor/stylo/stylesheets/appearance_base_rule.rs +51 -0
  201. package/vendor/stylo/stylesheets/container_rule.rs +769 -0
  202. package/vendor/stylo/stylesheets/counter_style_rule.rs +7 -0
  203. package/vendor/stylo/stylesheets/document_rule.rs +272 -0
  204. package/vendor/stylo/stylesheets/font_face_rule.rs +7 -0
  205. package/vendor/stylo/stylesheets/font_feature_values_rule.rs +481 -0
  206. package/vendor/stylo/stylesheets/font_palette_values_rule.rs +304 -0
  207. package/vendor/stylo/stylesheets/import_rule.rs +259 -0
  208. package/vendor/stylo/stylesheets/keyframes_rule.rs +733 -0
  209. package/vendor/stylo/stylesheets/layer_rule.rs +221 -0
  210. package/vendor/stylo/stylesheets/loader.rs +29 -0
  211. package/vendor/stylo/stylesheets/margin_rule.rs +190 -0
  212. package/vendor/stylo/stylesheets/media_rule.rs +191 -0
  213. package/vendor/stylo/stylesheets/mod.rs +918 -0
  214. package/vendor/stylo/stylesheets/namespace_rule.rs +43 -0
  215. package/vendor/stylo/stylesheets/nested_declarations_rule.rs +51 -0
  216. package/vendor/stylo/stylesheets/origin.rs +249 -0
  217. package/vendor/stylo/stylesheets/page_rule.rs +354 -0
  218. package/vendor/stylo/stylesheets/position_try_rule.rs +68 -0
  219. package/vendor/stylo/stylesheets/property_rule.rs +5 -0
  220. package/vendor/stylo/stylesheets/rule_list.rs +167 -0
  221. package/vendor/stylo/stylesheets/rule_parser.rs +1189 -0
  222. package/vendor/stylo/stylesheets/rules_iterator.rs +397 -0
  223. package/vendor/stylo/stylesheets/scope_rule.rs +511 -0
  224. package/vendor/stylo/stylesheets/starting_style_rule.rs +54 -0
  225. package/vendor/stylo/stylesheets/style_rule.rs +80 -0
  226. package/vendor/stylo/stylesheets/stylesheet.rs +570 -0
  227. package/vendor/stylo/stylesheets/supports_rule.rs +486 -0
  228. package/vendor/stylo/stylesheets/view_transition_rule.rs +81 -0
  229. package/vendor/stylo/stylist.rs +5076 -0
  230. package/vendor/stylo/thread_state.rs +87 -0
  231. package/vendor/stylo/traversal.rs +765 -0
  232. package/vendor/stylo/traversal_flags.rs +68 -0
  233. package/vendor/stylo/typed_om/mod.rs +981 -0
  234. package/vendor/stylo/typed_om/numeric.rs +128 -0
  235. package/vendor/stylo/typed_om/numeric_declaration.rs +93 -0
  236. package/vendor/stylo/typed_om/numeric_type.rs +640 -0
  237. package/vendor/stylo/typed_om/sum_value.rs +426 -0
  238. package/vendor/stylo/url/gecko.rs +367 -0
  239. package/vendor/stylo/url/mod.rs +71 -0
  240. package/vendor/stylo/url/servo.rs +239 -0
  241. package/vendor/stylo/use_counters/mod.rs +137 -0
  242. package/vendor/stylo/values/animated/color.rs +103 -0
  243. package/vendor/stylo/values/animated/effects.rs +26 -0
  244. package/vendor/stylo/values/animated/font.rs +37 -0
  245. package/vendor/stylo/values/animated/grid.rs +161 -0
  246. package/vendor/stylo/values/animated/lists.rs +141 -0
  247. package/vendor/stylo/values/animated/mod.rs +550 -0
  248. package/vendor/stylo/values/animated/svg.rs +46 -0
  249. package/vendor/stylo/values/animated/text.rs +58 -0
  250. package/vendor/stylo/values/animated/transform.rs +1592 -0
  251. package/vendor/stylo/values/computed/align.rs +90 -0
  252. package/vendor/stylo/values/computed/angle.rs +130 -0
  253. package/vendor/stylo/values/computed/animation.rs +124 -0
  254. package/vendor/stylo/values/computed/background.rs +13 -0
  255. package/vendor/stylo/values/computed/basic_shape.rs +267 -0
  256. package/vendor/stylo/values/computed/border.rs +163 -0
  257. package/vendor/stylo/values/computed/box.rs +267 -0
  258. package/vendor/stylo/values/computed/calc.rs +334 -0
  259. package/vendor/stylo/values/computed/color.rs +161 -0
  260. package/vendor/stylo/values/computed/column.rs +11 -0
  261. package/vendor/stylo/values/computed/corner_shape.rs +155 -0
  262. package/vendor/stylo/values/computed/counters.rs +26 -0
  263. package/vendor/stylo/values/computed/easing.rs +109 -0
  264. package/vendor/stylo/values/computed/effects.rs +30 -0
  265. package/vendor/stylo/values/computed/flex.rs +19 -0
  266. package/vendor/stylo/values/computed/font.rs +1517 -0
  267. package/vendor/stylo/values/computed/image.rs +273 -0
  268. package/vendor/stylo/values/computed/length.rs +576 -0
  269. package/vendor/stylo/values/computed/length_percentage.rs +1055 -0
  270. package/vendor/stylo/values/computed/list.rs +16 -0
  271. package/vendor/stylo/values/computed/mod.rs +1141 -0
  272. package/vendor/stylo/values/computed/motion.rs +73 -0
  273. package/vendor/stylo/values/computed/outline.rs +7 -0
  274. package/vendor/stylo/values/computed/page.rs +77 -0
  275. package/vendor/stylo/values/computed/param.rs +9 -0
  276. package/vendor/stylo/values/computed/percentage.rs +143 -0
  277. package/vendor/stylo/values/computed/position.rs +273 -0
  278. package/vendor/stylo/values/computed/ratio.rs +88 -0
  279. package/vendor/stylo/values/computed/rect.rs +19 -0
  280. package/vendor/stylo/values/computed/resolution.rs +76 -0
  281. package/vendor/stylo/values/computed/svg.rs +66 -0
  282. package/vendor/stylo/values/computed/table.rs +7 -0
  283. package/vendor/stylo/values/computed/text.rs +199 -0
  284. package/vendor/stylo/values/computed/time.rs +83 -0
  285. package/vendor/stylo/values/computed/transform.rs +559 -0
  286. package/vendor/stylo/values/computed/tree_counting.rs +30 -0
  287. package/vendor/stylo/values/computed/ui.rs +23 -0
  288. package/vendor/stylo/values/computed/url.rs +12 -0
  289. package/vendor/stylo/values/distance.rs +139 -0
  290. package/vendor/stylo/values/generics/animation.rs +363 -0
  291. package/vendor/stylo/values/generics/background.rs +65 -0
  292. package/vendor/stylo/values/generics/basic_shape.rs +1389 -0
  293. package/vendor/stylo/values/generics/border.rs +303 -0
  294. package/vendor/stylo/values/generics/box.rs +552 -0
  295. package/vendor/stylo/values/generics/calc.rs +2986 -0
  296. package/vendor/stylo/values/generics/color.rs +318 -0
  297. package/vendor/stylo/values/generics/column.rs +44 -0
  298. package/vendor/stylo/values/generics/counters.rs +320 -0
  299. package/vendor/stylo/values/generics/easing.rs +132 -0
  300. package/vendor/stylo/values/generics/effects.rs +131 -0
  301. package/vendor/stylo/values/generics/flex.rs +34 -0
  302. package/vendor/stylo/values/generics/font.rs +376 -0
  303. package/vendor/stylo/values/generics/grid.rs +962 -0
  304. package/vendor/stylo/values/generics/image.rs +653 -0
  305. package/vendor/stylo/values/generics/length.rs +656 -0
  306. package/vendor/stylo/values/generics/mod.rs +303 -0
  307. package/vendor/stylo/values/generics/motion.rs +274 -0
  308. package/vendor/stylo/values/generics/page.rs +167 -0
  309. package/vendor/stylo/values/generics/position.rs +669 -0
  310. package/vendor/stylo/values/generics/ratio.rs +88 -0
  311. package/vendor/stylo/values/generics/rect.rs +147 -0
  312. package/vendor/stylo/values/generics/size.rs +102 -0
  313. package/vendor/stylo/values/generics/svg.rs +226 -0
  314. package/vendor/stylo/values/generics/text.rs +268 -0
  315. package/vendor/stylo/values/generics/transform.rs +1157 -0
  316. package/vendor/stylo/values/generics/ui.rs +147 -0
  317. package/vendor/stylo/values/generics/url.rs +51 -0
  318. package/vendor/stylo/values/mod.rs +820 -0
  319. package/vendor/stylo/values/resolved/animation.rs +33 -0
  320. package/vendor/stylo/values/resolved/color.rs +53 -0
  321. package/vendor/stylo/values/resolved/counters.rs +45 -0
  322. package/vendor/stylo/values/resolved/mod.rs +316 -0
  323. package/vendor/stylo/values/specified/align.rs +711 -0
  324. package/vendor/stylo/values/specified/angle.rs +407 -0
  325. package/vendor/stylo/values/specified/animation.rs +921 -0
  326. package/vendor/stylo/values/specified/background.rs +270 -0
  327. package/vendor/stylo/values/specified/basic_shape.rs +986 -0
  328. package/vendor/stylo/values/specified/border.rs +430 -0
  329. package/vendor/stylo/values/specified/box.rs +2231 -0
  330. package/vendor/stylo/values/specified/calc.rs +1657 -0
  331. package/vendor/stylo/values/specified/color.rs +1210 -0
  332. package/vendor/stylo/values/specified/column.rs +11 -0
  333. package/vendor/stylo/values/specified/corner_shape.rs +152 -0
  334. package/vendor/stylo/values/specified/counters.rs +242 -0
  335. package/vendor/stylo/values/specified/easing.rs +225 -0
  336. package/vendor/stylo/values/specified/effects.rs +421 -0
  337. package/vendor/stylo/values/specified/flex.rs +42 -0
  338. package/vendor/stylo/values/specified/font.rs +2103 -0
  339. package/vendor/stylo/values/specified/frequency.rs +39 -0
  340. package/vendor/stylo/values/specified/grid.rs +407 -0
  341. package/vendor/stylo/values/specified/image.rs +1385 -0
  342. package/vendor/stylo/values/specified/intersection_observer.rs +80 -0
  343. package/vendor/stylo/values/specified/length.rs +2024 -0
  344. package/vendor/stylo/values/specified/list.rs +190 -0
  345. package/vendor/stylo/values/specified/mod.rs +531 -0
  346. package/vendor/stylo/values/specified/motion.rs +316 -0
  347. package/vendor/stylo/values/specified/number.rs +603 -0
  348. package/vendor/stylo/values/specified/outline.rs +69 -0
  349. package/vendor/stylo/values/specified/page.rs +94 -0
  350. package/vendor/stylo/values/specified/param.rs +121 -0
  351. package/vendor/stylo/values/specified/percentage.rs +364 -0
  352. package/vendor/stylo/values/specified/position.rs +2247 -0
  353. package/vendor/stylo/values/specified/ratio.rs +29 -0
  354. package/vendor/stylo/values/specified/rect.rs +28 -0
  355. package/vendor/stylo/values/specified/resolution.rs +237 -0
  356. package/vendor/stylo/values/specified/source_size_list.rs +135 -0
  357. package/vendor/stylo/values/specified/svg.rs +427 -0
  358. package/vendor/stylo/values/specified/svg_path.rs +1115 -0
  359. package/vendor/stylo/values/specified/table.rs +38 -0
  360. package/vendor/stylo/values/specified/text.rs +1561 -0
  361. package/vendor/stylo/values/specified/time.rs +313 -0
  362. package/vendor/stylo/values/specified/transform.rs +599 -0
  363. package/vendor/stylo/values/specified/tree_counting.rs +32 -0
  364. package/vendor/stylo/values/specified/ui.rs +344 -0
  365. package/vendor/stylo/values/specified/url.rs +12 -0
  366. package/vendor/stylo/values/tagged_numeric.rs +253 -0
  367. package/wasm/blitz_pdf.d.ts +67 -0
  368. package/wasm/blitz_pdf.js +699 -0
  369. package/wasm/blitz_pdf_bg.wasm +0 -0
  370. package/wasm/blitz_pdf_bg.wasm.d.ts +20 -0
@@ -0,0 +1,3103 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+
5
+ // This file is a Mako template: http://www.makotemplates.org/
6
+
7
+ <%namespace name="helpers" file="/helpers.mako.rs" />
8
+ <% from itertools import groupby %>
9
+ <% from data import PropertyRestrictions, to_camel_case, RULE_VALUES, SYSTEM_FONT_LONGHANDS, PRIORITARY_PROPERTIES, PRIORITARY_PROPERTY_DEPENDENCIES %>
10
+
11
+ use servo_arc::{Arc, UniqueArc};
12
+ use std::{ops, ptr, fmt, mem};
13
+
14
+ #[cfg(feature = "servo")] use euclid::SideOffsets2D;
15
+ #[cfg(feature = "gecko")] use crate::gecko_bindings::structs::{self, NonCustomCSSPropertyId};
16
+ #[cfg(feature = "servo")] use crate::logical_geometry::LogicalMargin;
17
+ #[cfg(feature = "servo")] use crate::dom::AttributeReferences;
18
+ use crate::logical_geometry::WritingMode;
19
+ use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
20
+ use crate::computed_value_flags::*;
21
+ use cssparser::Parser;
22
+ use crate::device::Device;
23
+ use crate::parser::ParserContext;
24
+ use crate::selector_parser::PseudoElement;
25
+ use crate::stylist::Stylist;
26
+ use style_traits::{CssStringWriter, CssWriter, KeywordsCollectFn, ParseError, SpecifiedValueInfo, StyleParseErrorKind, ToCss};
27
+ use crate::derives::*;
28
+ use crate::stylesheets::{CssRuleType, CssRuleTypes, Origin};
29
+ use crate::logical_geometry::{LogicalAxis, LogicalCorner, LogicalSide};
30
+ use crate::typed_om::{ToTyped, TypedValueList};
31
+ use crate::use_counters::UseCounters;
32
+ use crate::rule_tree::StrongRuleNode;
33
+ use crate::values::{
34
+ computed::{self, ToComputedValue},
35
+ resolved::{self, ToResolvedValue},
36
+ specified::{font::SystemFont, length::LineHeightBase, color::ColorSchemeFlags},
37
+ };
38
+ use std::cell::Cell;
39
+ use super::{
40
+ PropertyDeclarationId, PropertyId, NonCustomPropertyId,
41
+ NonCustomPropertyIdSet, PrioritaryPropertyIdSet, PropertyFlags, SourcePropertyDeclaration,
42
+ LonghandIdSet, VariableDeclaration, CustomDeclaration,
43
+ WideKeywordDeclaration, NonCustomPropertyIterator, TransitionPropertyIterator,
44
+ };
45
+ use debug_unreachable::debug_unreachable;
46
+
47
+ /// Conversion with fewer impls than From/Into
48
+ pub trait MaybeBoxed<Out> {
49
+ /// Convert
50
+ fn maybe_boxed(self) -> Out;
51
+ }
52
+
53
+ impl<T> MaybeBoxed<T> for T {
54
+ #[inline]
55
+ fn maybe_boxed(self) -> T { self }
56
+ }
57
+
58
+ impl<T> MaybeBoxed<Box<T>> for T {
59
+ #[inline]
60
+ fn maybe_boxed(self) -> Box<T> { Box::new(self) }
61
+ }
62
+
63
+ /// A module with all the code for longhand properties.
64
+ #[allow(missing_docs)]
65
+ pub mod longhands {
66
+ <%
67
+ for longhand in data.longhands:
68
+ helpers.longhand(longhand)
69
+ %>
70
+ }
71
+
72
+
73
+ % if engine == "gecko":
74
+ #[allow(unsafe_code, missing_docs)]
75
+ pub mod gecko {
76
+ <%include file="/gecko.mako.rs" />
77
+ }
78
+ % endif
79
+
80
+
81
+ /// A module with code for all the shorthand css properties, and a few
82
+ /// serialization helpers.
83
+ #[allow(missing_docs)]
84
+ pub mod shorthands {
85
+ <%
86
+ for shorthand in data.shorthands_except_all():
87
+ helpers.shorthand(shorthand)
88
+ %>
89
+ }
90
+
91
+ /// Servo's representation for a property declaration.
92
+ #[derive(ToShmem)]
93
+ #[repr(u16)]
94
+ pub enum PropertyDeclaration {
95
+ % for variant in data.declaration_variants:
96
+ /// ${variant["doc"]}
97
+ ${variant["name"]}(${variant["type"]}),
98
+ % endfor
99
+ }
100
+
101
+ // There's one of these for each parsed declaration so it better be small.
102
+ size_of_test!(PropertyDeclaration, 32);
103
+
104
+ #[repr(C)]
105
+ struct PropertyDeclarationVariantRepr<T> {
106
+ tag: u16,
107
+ value: T
108
+ }
109
+
110
+ impl Clone for PropertyDeclaration {
111
+ #[inline]
112
+ fn clone(&self) -> Self {
113
+ use self::PropertyDeclaration::*;
114
+
115
+ <%
116
+ [copy, others] = [list(g) for _, g in groupby(data.declaration_variants, key=lambda x: not x["copy"])]
117
+ %>
118
+
119
+ let self_tag = unsafe {
120
+ (*(self as *const _ as *const PropertyDeclarationVariantRepr<()>)).tag
121
+ };
122
+ if self_tag <= LonghandId::${copy[-1]["name"]} as u16 {
123
+ #[derive(Clone, Copy)]
124
+ #[repr(u16)]
125
+ enum CopyVariants {
126
+ % for v in copy:
127
+ _${v["name"]}(${v["type"]}),
128
+ % endfor
129
+ }
130
+
131
+ unsafe {
132
+ let mut out = mem::MaybeUninit::uninit();
133
+ ptr::write(
134
+ out.as_mut_ptr() as *mut CopyVariants,
135
+ *(self as *const _ as *const CopyVariants),
136
+ );
137
+ return out.assume_init();
138
+ }
139
+ }
140
+
141
+ // This function ensures that all properties not handled above
142
+ // do not have a specified value implements Copy. If you hit
143
+ // compile error here, you may want to add the type name into
144
+ // Longhand.specified_is_copy in data.py.
145
+ fn _static_assert_others_are_not_copy() {
146
+ struct Helper<T>(T);
147
+ trait AssertCopy { fn assert() {} }
148
+ trait AssertNotCopy { fn assert() {} }
149
+ impl<T: Copy> AssertCopy for Helper<T> {}
150
+ % for ty in sorted(set(x["type"] for x in others)):
151
+ impl AssertNotCopy for Helper<${ty}> {}
152
+ Helper::<${ty}>::assert();
153
+ % endfor
154
+ }
155
+
156
+ match *self {
157
+ ${" |\n".join("{}(..)".format(v["name"]) for v in copy)} => {
158
+ unsafe { debug_unreachable!() }
159
+ }
160
+ % for ty, vs in groupby(others, key=lambda x: x["type"]):
161
+ <%
162
+ vs = list(vs)
163
+ %>
164
+ % if len(vs) == 1:
165
+ ${vs[0]["name"]}(ref value) => {
166
+ ${vs[0]["name"]}(value.clone())
167
+ }
168
+ % else:
169
+ ${" |\n".join("{}(ref value)".format(v["name"]) for v in vs)} => {
170
+ unsafe {
171
+ let mut out = mem::MaybeUninit::uninit();
172
+ ptr::write(
173
+ out.as_mut_ptr() as *mut PropertyDeclarationVariantRepr<${ty}>,
174
+ PropertyDeclarationVariantRepr {
175
+ tag: *(self as *const _ as *const u16),
176
+ value: value.clone(),
177
+ },
178
+ );
179
+ out.assume_init()
180
+ }
181
+ }
182
+ % endif
183
+ % endfor
184
+ }
185
+ }
186
+ }
187
+
188
+ impl PartialEq for PropertyDeclaration {
189
+ #[inline]
190
+ fn eq(&self, other: &Self) -> bool {
191
+ use self::PropertyDeclaration::*;
192
+
193
+ unsafe {
194
+ let this_repr =
195
+ &*(self as *const _ as *const PropertyDeclarationVariantRepr<()>);
196
+ let other_repr =
197
+ &*(other as *const _ as *const PropertyDeclarationVariantRepr<()>);
198
+ if this_repr.tag != other_repr.tag {
199
+ return false;
200
+ }
201
+ match *self {
202
+ % for ty, vs in groupby(data.declaration_variants, key=lambda x: x["type"]):
203
+ ${" |\n".join("{}(ref this)".format(v["name"]) for v in vs)} => {
204
+ let other_repr =
205
+ &*(other as *const _ as *const PropertyDeclarationVariantRepr<${ty}>);
206
+ *this == other_repr.value
207
+ }
208
+ % endfor
209
+ }
210
+ }
211
+ }
212
+ }
213
+
214
+ impl MallocSizeOf for PropertyDeclaration {
215
+ #[inline]
216
+ fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
217
+ use self::PropertyDeclaration::*;
218
+
219
+ match *self {
220
+ % for ty, vs in groupby(data.declaration_variants, key=lambda x: x["type"]):
221
+ ${" | ".join("{}(ref value)".format(v["name"]) for v in vs)} => {
222
+ value.size_of(ops)
223
+ }
224
+ % endfor
225
+ }
226
+ }
227
+ }
228
+
229
+
230
+ impl PropertyDeclaration {
231
+ /// Returns the given value for this declaration as a particular type.
232
+ /// It's the caller's responsibility to guarantee that the longhand id has the right specified
233
+ /// value representation.
234
+ pub(crate) unsafe fn unchecked_value_as<T>(&self) -> &T {
235
+ unsafe {
236
+ &(*(self as *const _ as *const PropertyDeclarationVariantRepr<T>)).value
237
+ }
238
+ }
239
+
240
+ /// Dumps the property declaration before crashing.
241
+ #[cold]
242
+ #[cfg(debug_assertions)]
243
+ pub(crate) fn debug_crash(&self, reason: &str) {
244
+ panic!("{}: {:?}", reason, self);
245
+ }
246
+ #[cfg(not(debug_assertions))]
247
+ #[inline(always)]
248
+ pub(crate) fn debug_crash(&self, _reason: &str) {}
249
+
250
+ /// Returns whether this is a variant of the Longhand(Value) type, rather
251
+ /// than one of the special variants in extra_variants.
252
+ fn is_longhand_value(&self) -> bool {
253
+ !matches!(
254
+ *self,
255
+ ${" | ".join("PropertyDeclaration::%s(..)" % v["name"] for v in data.declaration_extra_variants)}
256
+ )
257
+ }
258
+
259
+ /// Like the method on ToCss, but without the type parameter to avoid
260
+ /// accidentally monomorphizing this large function multiple times for
261
+ /// different writers.
262
+ pub fn to_css(&self, dest: &mut CssStringWriter) -> fmt::Result {
263
+ use self::PropertyDeclaration::*;
264
+
265
+ let mut dest = CssWriter::new(dest);
266
+ match *self {
267
+ % for ty, vs in groupby(data.declaration_variants, key=lambda x: x["type"]):
268
+ ${" | ".join("{}(ref value)".format(v["name"]) for v in vs)} => {
269
+ value.to_css(&mut dest)
270
+ }
271
+ % endfor
272
+ }
273
+ }
274
+
275
+ /// Like the method on ToTyped.
276
+ pub fn to_typed_value_list(&self) -> Option<TypedValueList> {
277
+ use self::PropertyDeclaration::*;
278
+
279
+ match *self {
280
+ % for ty, vs in groupby(data.declaration_variants, key=lambda x: x["type"]):
281
+ ${" | ".join("{}(ref value)".format(v["name"]) for v in vs)} => {
282
+ value.to_typed_value_list()
283
+ }
284
+ % endfor
285
+ }
286
+ }
287
+
288
+ /// Returns the color value of a given property, for high-contrast-mode tweaks.
289
+ pub(super) fn color_value(&self) -> Option<&crate::values::specified::Color> {
290
+ static COLOR_PROPERTIES: LonghandIdSet = ${longhand_id_set(lambda p: p.predefined_type == "Color")};
291
+ <%
292
+ # sanity check
293
+ assert data.longhands_by_name["background-color"].predefined_type == "Color"
294
+ color_specified_type = data.longhands_by_name["background-color"].specified_type()
295
+ %>
296
+ let id = self.id().as_longhand()?;
297
+ if !COLOR_PROPERTIES.contains(id) || !self.is_longhand_value() {
298
+ return None;
299
+ }
300
+ let repr = self as *const _ as *const PropertyDeclarationVariantRepr<${color_specified_type}>;
301
+ Some(unsafe { &(*repr).value })
302
+ }
303
+ }
304
+
305
+ /// A module with all the code related to animated properties.
306
+ ///
307
+ /// This needs to be "included" by mako at least after all longhand modules,
308
+ /// given they populate the global data.
309
+ pub mod animated_properties {
310
+ <%include file="/helpers/animated_properties.mako.rs" />
311
+ }
312
+
313
+ /// A module to group various interesting property counts.
314
+ pub mod property_counts {
315
+ /// The number of (non-alias) longhand properties.
316
+ pub const LONGHANDS: usize = ${len(data.longhands)};
317
+ /// The number of (non-alias) shorthand properties.
318
+ pub const SHORTHANDS: usize = ${len(data.shorthands)};
319
+ /// The number of aliases.
320
+ pub const ALIASES: usize = ${len(data.all_aliases())};
321
+ /// The number of counted unknown properties.
322
+ pub const COUNTED_UNKNOWN: usize = ${len(data.counted_unknown_properties)};
323
+ /// The number of (non-alias) longhands and shorthands.
324
+ pub const LONGHANDS_AND_SHORTHANDS: usize = LONGHANDS + SHORTHANDS;
325
+ /// The number of non-custom properties.
326
+ pub const NON_CUSTOM: usize = LONGHANDS_AND_SHORTHANDS + ALIASES;
327
+ <% longhand_property_names = set(list(map(lambda p: p.name, data.longhands))) %>
328
+ <% enabled_prioritary_properties = PRIORITARY_PROPERTIES.intersection(longhand_property_names) %>
329
+ /// The number of prioritary properties that we have.
330
+ pub const PRIORITARY: usize = ${len(enabled_prioritary_properties)};
331
+ /// The max number of longhands that a shorthand other than "all" expands to.
332
+ pub const MAX_SHORTHAND_EXPANDED: usize =
333
+ ${max(len(s.sub_properties) for s in data.shorthands_except_all())};
334
+ /// The max amount of longhands that the `all` shorthand will ever contain.
335
+ pub const ALL_SHORTHAND_EXPANDED: usize = ${data.all_shorthand_length};
336
+ /// The number of animatable properties.
337
+ pub const ANIMATABLE: usize = ${sum(1 for prop in data.longhands if prop.animatable)};
338
+ }
339
+
340
+ % if engine == "gecko":
341
+ const _: () = {
342
+ % for i, property in enumerate(data.longhands + data.shorthands + data.all_aliases()):
343
+ assert!(${i} == ${property.noncustomcsspropertyid()} as usize, "${property.name}");
344
+ % endfor
345
+ };
346
+ % endif
347
+
348
+ impl NonCustomPropertyId {
349
+ /// Get the property name.
350
+ #[inline]
351
+ pub fn name(self) -> &'static str {
352
+ static MAP: [&str; property_counts::NON_CUSTOM] = [
353
+ % for property in data.longhands + data.shorthands + data.all_aliases():
354
+ "${property.name}",
355
+ % endfor
356
+ ];
357
+ MAP[self.0 as usize]
358
+ }
359
+
360
+ /// Returns whether this property is animatable.
361
+ #[inline]
362
+ pub fn is_animatable(self) -> bool {
363
+ static ANIMATABLE: NonCustomPropertyIdSet =
364
+ ${non_custom_property_id_set(lambda p: p.animatable)};
365
+ ANIMATABLE.contains(self)
366
+ }
367
+
368
+ /// Whether this property is enabled for all content right now.
369
+ #[inline]
370
+ pub(super) fn enabled_for_all_content(self) -> bool {
371
+ static EXPERIMENTAL: NonCustomPropertyIdSet = ${non_custom_property_id_set(lambda p: p.experimental(engine))};
372
+ static ALWAYS_ENABLED: NonCustomPropertyIdSet = ${non_custom_property_id_set(
373
+ lambda p: (not p.experimental(engine)) and p.enabled_in_content()
374
+ )};
375
+
376
+ let passes_pref_check = || {
377
+ % if engine == "gecko":
378
+ unsafe { structs::nsCSSProps_gPropertyEnabled[self.0 as usize] }
379
+ % else:
380
+ match self.0 {
381
+ % for (index, property) in enumerate(data.longhands + data.shorthands + data.all_aliases()):
382
+ <% preference = getattr(property, "servo_pref") %>
383
+ % if preference:
384
+ ${index} => crate::pref!("${preference}"),
385
+ % endif %
386
+ % endfor
387
+ _ => true,
388
+ }
389
+ % endif
390
+ };
391
+
392
+ if ALWAYS_ENABLED.contains(self) {
393
+ return true
394
+ }
395
+
396
+ if EXPERIMENTAL.contains(self) && passes_pref_check() {
397
+ return true
398
+ }
399
+
400
+ false
401
+ }
402
+
403
+ /// Returns whether a given rule allows a given property.
404
+ #[inline]
405
+ pub fn allowed_in_rule(self, rule_types: CssRuleTypes) -> bool {
406
+ debug_assert!(
407
+ rule_types.contains(CssRuleType::Keyframe) ||
408
+ rule_types.contains(CssRuleType::Page) ||
409
+ rule_types.contains(CssRuleType::Style) ||
410
+ rule_types.contains(CssRuleType::Scope) ||
411
+ rule_types.contains(CssRuleType::PositionTry),
412
+ "Given rule type does not allow declarations."
413
+ );
414
+
415
+ static MAP: [u32; property_counts::NON_CUSTOM] = [
416
+ % for property in data.longhands + data.shorthands + data.all_aliases():
417
+ % for name in RULE_VALUES:
418
+ % if property.rule_types_allowed & RULE_VALUES[name] != 0:
419
+ CssRuleType::${to_camel_case(name)}.bit() |
420
+ % endif
421
+ % endfor
422
+ 0,
423
+ % endfor
424
+ ];
425
+ MAP[self.0 as usize] & rule_types.bits() != 0
426
+ }
427
+
428
+ pub(super) fn allowed_in(self, context: &ParserContext) -> bool {
429
+ if !self.allowed_in_rule(context.rule_types()) {
430
+ return false;
431
+ }
432
+
433
+ self.allowed_in_ignoring_rule_type(context)
434
+ }
435
+
436
+
437
+ pub(super) fn allowed_in_ignoring_rule_type(self, context: &ParserContext) -> bool {
438
+ // The semantics of these are kinda hard to reason about, what follows
439
+ // is a description of the different combinations that can happen with
440
+ // these three sets.
441
+ //
442
+ // Experimental properties are generally controlled by prefs, but an
443
+ // experimental property explicitly enabled in certain context (UA or
444
+ // chrome sheets) is always usable in the context regardless of the
445
+ // pref value.
446
+ //
447
+ // Non-experimental properties are either normal properties which are
448
+ // usable everywhere, or internal-only properties which are only usable
449
+ // in certain context they are explicitly enabled in.
450
+ if self.enabled_for_all_content() {
451
+ return true;
452
+ }
453
+ static ENABLED_IN_UA_SHEETS: NonCustomPropertyIdSet = ${non_custom_property_id_set(
454
+ lambda p: p.explicitly_enabled_in_ua_sheets()
455
+ )};
456
+ static ENABLED_IN_CHROME: NonCustomPropertyIdSet = ${non_custom_property_id_set(
457
+ lambda p: p.explicitly_enabled_in_chrome()
458
+ )};
459
+ if context.stylesheet_origin == Origin::UserAgent &&
460
+ ENABLED_IN_UA_SHEETS.contains(self)
461
+ {
462
+ return true
463
+ }
464
+
465
+ if context.chrome_rules_enabled() && ENABLED_IN_CHROME.contains(self) {
466
+ return true
467
+ }
468
+
469
+ false
470
+ }
471
+
472
+ /// The supported types of this property. The return value should be
473
+ /// style_traits::CssType when it can become a bitflags type.
474
+ pub(super) fn supported_types(&self) -> u8 {
475
+ const SUPPORTED_TYPES: [u8; property_counts::LONGHANDS_AND_SHORTHANDS] = [
476
+ % for prop in data.longhands:
477
+ <${prop.specified_type()} as SpecifiedValueInfo>::SUPPORTED_TYPES,
478
+ % endfor
479
+ % for prop in data.shorthands:
480
+ % if prop.name == "all":
481
+ 0, // 'all' accepts no value other than CSS-wide keywords
482
+ % else:
483
+ <shorthands::${prop.ident}::Longhands as SpecifiedValueInfo>::SUPPORTED_TYPES,
484
+ % endif
485
+ % endfor
486
+ ];
487
+ SUPPORTED_TYPES[self.0 as usize]
488
+ }
489
+
490
+ /// See PropertyId::collect_property_completion_keywords.
491
+ pub(super) fn collect_property_completion_keywords(&self, f: KeywordsCollectFn) {
492
+ fn do_nothing(_: KeywordsCollectFn) {}
493
+ const COLLECT_FUNCTIONS: [fn(KeywordsCollectFn);
494
+ property_counts::LONGHANDS_AND_SHORTHANDS] = [
495
+ % for prop in data.longhands:
496
+ <${prop.specified_type()} as SpecifiedValueInfo>::collect_completion_keywords,
497
+ % endfor
498
+ % for prop in data.shorthands:
499
+ % if prop.name == "all":
500
+ do_nothing, // 'all' accepts no value other than CSS-wide keywords
501
+ % else:
502
+ <shorthands::${prop.ident}::Longhands as SpecifiedValueInfo>::
503
+ collect_completion_keywords,
504
+ % endif
505
+ % endfor
506
+ ];
507
+ COLLECT_FUNCTIONS[self.0 as usize](f);
508
+ }
509
+ }
510
+
511
+ <%def name="id_set(set_type, ids, is_member)">
512
+ <%
513
+ storage = [0] * int((len(ids) - 1 + 32) / 32)
514
+ for i, property in enumerate(ids):
515
+ if is_member(property):
516
+ storage[int(i / 32)] |= 1 << (i % 32)
517
+ %>
518
+ ${set_type}::from_storage([${", ".join("0x%x" % word for word in storage)}])
519
+ </%def>
520
+
521
+ <%def name="non_custom_property_id_set(is_member)">
522
+ ${id_set("NonCustomPropertyIdSet", data.longhands + data.shorthands + data.all_aliases(), is_member)}
523
+ </%def>
524
+
525
+ <%def name="longhand_id_set(is_member)">
526
+ ${id_set("LonghandIdSet", data.longhands, is_member)}
527
+ </%def>
528
+
529
+ <%def name="prioritary_property_id_set(is_member)">
530
+ ${id_set("PrioritaryPropertyIdSet", [p for p in data.longhands if p.is_prioritary()], is_member)}
531
+ </%def>
532
+
533
+ <%
534
+ FIRST_LINE_RESTRICTIONS = PropertyRestrictions.first_line(data)
535
+ FIRST_LETTER_RESTRICTIONS = PropertyRestrictions.first_letter(data)
536
+ MARKER_RESTRICTIONS = PropertyRestrictions.marker(data)
537
+ PLACEHOLDER_RESTRICTIONS = PropertyRestrictions.placeholder(data)
538
+ CUE_RESTRICTIONS = PropertyRestrictions.cue(data)
539
+
540
+ def restriction_flags(property):
541
+ name = property.name
542
+ flags = []
543
+ if name in FIRST_LINE_RESTRICTIONS:
544
+ flags.append("APPLIES_TO_FIRST_LINE")
545
+ if name in FIRST_LETTER_RESTRICTIONS:
546
+ flags.append("APPLIES_TO_FIRST_LETTER")
547
+ if name in PLACEHOLDER_RESTRICTIONS:
548
+ flags.append("APPLIES_TO_PLACEHOLDER")
549
+ if name in MARKER_RESTRICTIONS:
550
+ flags.append("APPLIES_TO_MARKER")
551
+ if name in CUE_RESTRICTIONS:
552
+ flags.append("APPLIES_TO_CUE")
553
+ return flags
554
+
555
+ %>
556
+
557
+ /// A group for properties which may override each other via logical resolution.
558
+ #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
559
+ #[repr(u8)]
560
+ pub enum LogicalGroupId {
561
+ % for i, group in enumerate(data.logical_groups.keys()):
562
+ /// ${group}
563
+ ${to_camel_case(group)} = ${i},
564
+ % endfor
565
+ }
566
+
567
+ impl LogicalGroupId {
568
+ /// Return the list of physical mapped properties for a given logical group.
569
+ fn physical_properties(self) -> &'static [LonghandId] {
570
+ static PROPS: [[LonghandId; 4]; ${len(data.logical_groups)}] = [
571
+ % for group, props in data.logical_groups.items():
572
+ [
573
+ <% physical_props = [p for p in props if p.logical][0].all_physical_mapped_properties(data) %>
574
+ % for phys in physical_props:
575
+ LonghandId::${phys.camel_case},
576
+ % endfor
577
+ % for i in range(len(physical_props), 4):
578
+ LonghandId::${physical_props[0].camel_case},
579
+ % endfor
580
+ ],
581
+ % endfor
582
+ ];
583
+ &PROPS[self as usize]
584
+ }
585
+ }
586
+
587
+ /// A set of logical groups.
588
+ #[derive(Clone, Copy, Debug, Default, MallocSizeOf, PartialEq)]
589
+ pub struct LogicalGroupSet {
590
+ storage: [u32; (${len(data.logical_groups)} - 1 + 32) / 32]
591
+ }
592
+
593
+ impl LogicalGroupSet {
594
+ /// Creates an empty `NonCustomPropertyIdSet`.
595
+ pub fn new() -> Self {
596
+ Self {
597
+ storage: Default::default(),
598
+ }
599
+ }
600
+
601
+ /// Return whether the given group is in the set
602
+ #[inline]
603
+ pub fn contains(&self, g: LogicalGroupId) -> bool {
604
+ let bit = g as usize;
605
+ (self.storage[bit / 32] & (1 << (bit % 32))) != 0
606
+ }
607
+
608
+ /// Insert a group the set.
609
+ #[inline]
610
+ pub fn insert(&mut self, g: LogicalGroupId) {
611
+ let bit = g as usize;
612
+ self.storage[bit / 32] |= 1 << (bit % 32);
613
+ }
614
+ }
615
+
616
+
617
+ /// An id of a property that can be depended on by other properties.
618
+ #[repr(u8)]
619
+ #[derive(Copy, Clone, Debug)]
620
+ #[allow(missing_docs)]
621
+ pub enum PrioritaryPropertyId {
622
+ % for p in data.longhands:
623
+ % if p.is_prioritary():
624
+ ${p.camel_case},
625
+ % endif
626
+ % endfor
627
+ }
628
+
629
+ impl PrioritaryPropertyId {
630
+ /// Iterates over all prioritary properties, in declaration (longhand) order.
631
+ #[inline]
632
+ pub fn each() -> impl Iterator<Item = Self> {
633
+ // Safe because `PrioritaryPropertyId` is `#[repr(u8)]` with contiguous discriminants in
634
+ // `0..property_counts::PRIORITARY`.
635
+ (0..property_counts::PRIORITARY as u8).map(|i| unsafe { std::mem::transmute::<u8, Self>(i) })
636
+ }
637
+
638
+ /// Converts a PrioritaryPropertyId to a LonghandId.
639
+ #[inline]
640
+ pub fn to_longhand(self) -> LonghandId {
641
+ static PRIORITARY_TO_LONGHAND: [LonghandId; property_counts::PRIORITARY] = [
642
+ % for p in data.longhands:
643
+ % if p.is_prioritary():
644
+ LonghandId::${p.camel_case},
645
+ % endif
646
+ % endfor
647
+ ];
648
+ PRIORITARY_TO_LONGHAND[self as usize]
649
+ }
650
+
651
+ /// Converts a LonghandId to a PrioritaryPropertyId.
652
+ #[inline]
653
+ pub fn from_longhand(l: LonghandId) -> Option<Self> {
654
+ static LONGHAND_TO_PRIORITARY: [Option<PrioritaryPropertyId>; property_counts::LONGHANDS] = [
655
+ % for p in data.longhands:
656
+ % if p.is_prioritary():
657
+ Some(PrioritaryPropertyId::${p.camel_case}),
658
+ % else:
659
+ None,
660
+ % endif
661
+ % endfor
662
+ ];
663
+ LONGHAND_TO_PRIORITARY[l as usize]
664
+ }
665
+
666
+ /// Returns the set of prioritary properties that must be applied before
667
+ /// this one, i.e. the properties it depends on.
668
+ #[inline]
669
+ pub fn dependencies(self) -> &'static PrioritaryPropertyIdSet {
670
+ static DEPENDENCIES: [PrioritaryPropertyIdSet; property_counts::PRIORITARY] = [
671
+ % for p in data.longhands:
672
+ % if p.is_prioritary():
673
+ ${prioritary_property_id_set(
674
+ lambda dep, p=p: dep.name in PRIORITARY_PROPERTY_DEPENDENCIES[p.name]
675
+ )},
676
+ % endif
677
+ % endfor
678
+ ];
679
+ &DEPENDENCIES[self as usize]
680
+ }
681
+ }
682
+
683
+ impl LonghandIdSet {
684
+ /// The set of non-inherited longhands.
685
+ #[inline]
686
+ pub(super) fn reset() -> &'static Self {
687
+ static RESET: LonghandIdSet = ${longhand_id_set(lambda p: not p.style_struct.inherited)};
688
+ &RESET
689
+ }
690
+
691
+ #[inline]
692
+ pub(super) fn discrete_animatable() -> &'static Self {
693
+ static DISCRETE_ANIMATABLE: LonghandIdSet = ${longhand_id_set(lambda p: p.animation_type == "discrete")};
694
+ &DISCRETE_ANIMATABLE
695
+ }
696
+
697
+ #[inline]
698
+ pub(super) fn logical() -> &'static Self {
699
+ static LOGICAL: LonghandIdSet = ${longhand_id_set(lambda p: p.logical)};
700
+ &LOGICAL
701
+ }
702
+
703
+ /// Returns the set of longhands that are ignored when document colors are
704
+ /// disabled.
705
+ #[inline]
706
+ pub(super) fn ignored_when_colors_disabled() -> &'static Self {
707
+ static IGNORED_WHEN_COLORS_DISABLED: LonghandIdSet = ${longhand_id_set(lambda p: p.ignored_when_colors_disabled)};
708
+ &IGNORED_WHEN_COLORS_DISABLED
709
+ }
710
+
711
+ /// Only a few properties are allowed to depend on the visited state of links. When cascading
712
+ /// visited styles, we can save time by only processing these properties.
713
+ pub(super) fn visited_dependent() -> &'static Self {
714
+ static VISITED_DEPENDENT: LonghandIdSet = ${longhand_id_set(lambda p: p.is_visited_dependent())};
715
+ debug_assert!(Self::late_group().contains_all(&VISITED_DEPENDENT));
716
+ &VISITED_DEPENDENT
717
+ }
718
+
719
+ #[inline]
720
+ pub(super) fn prioritary_properties() -> &'static Self {
721
+ static PRIORITARY: LonghandIdSet = ${longhand_id_set(lambda p: p.is_prioritary())};
722
+ &PRIORITARY
723
+ }
724
+
725
+ #[inline]
726
+ pub(super) fn late_group_only_inherited() -> &'static Self {
727
+ static LATE_GROUP_ONLY_INHERITED: LonghandIdSet = ${longhand_id_set(lambda p: p.style_struct.inherited and not p.is_prioritary())};
728
+ &LATE_GROUP_ONLY_INHERITED
729
+ }
730
+
731
+ #[inline]
732
+ pub(super) fn late_group() -> &'static Self {
733
+ static LATE_GROUP: LonghandIdSet = ${longhand_id_set(lambda p: not p.is_prioritary())};
734
+ &LATE_GROUP
735
+ }
736
+
737
+ /// Returns the set of properties that are declared as having no effect on
738
+ /// Gecko <scrollbar> elements or their descendant scrollbar parts.
739
+ #[cfg(debug_assertions)]
740
+ #[cfg(feature = "gecko")]
741
+ #[inline]
742
+ pub fn has_no_effect_on_gecko_scrollbars() -> &'static Self {
743
+ // data.py asserts that has_no_effect_on_gecko_scrollbars is True or
744
+ // False for properties that are inherited and Gecko pref controlled,
745
+ // and is None for all other properties.
746
+ static HAS_NO_EFFECT_ON_SCROLLBARS: LonghandIdSet = ${longhand_id_set(
747
+ lambda p: p.has_effect_on_gecko_scrollbars is False
748
+ )};
749
+ &HAS_NO_EFFECT_ON_SCROLLBARS
750
+ }
751
+
752
+ /// Returns the set of margin properties, for the purposes of <h1> use counters / warnings.
753
+ #[inline]
754
+ pub fn margin_properties() -> &'static Self {
755
+ static MARGIN_PROPERTIES: LonghandIdSet = ${longhand_id_set(lambda p: p.logical_group == "margin")};
756
+ &MARGIN_PROPERTIES
757
+ }
758
+
759
+ /// Returns the set of border properties for the purpose of disabling native
760
+ /// appearance.
761
+ #[inline]
762
+ pub fn border_background_properties() -> &'static Self {
763
+ static BORDER_BACKGROUND_PROPERTIES: LonghandIdSet = ${longhand_id_set(
764
+ lambda p: (p.logical_group and p.logical_group.startswith("border")) or \
765
+ p in data.shorthands_by_name["border"].sub_properties or \
766
+ p in data.shorthands_by_name["background"].sub_properties and \
767
+ p.name not in ["background-blend-mode", "background-repeat"]
768
+ )};
769
+ &BORDER_BACKGROUND_PROPERTIES
770
+ }
771
+
772
+ /// Returns properties that are zoom dependent (basically, that contain lengths).
773
+ #[inline]
774
+ pub fn zoom_dependent() -> &'static Self {
775
+ static ZOOM_DEPENDENT: LonghandIdSet = ${longhand_id_set(lambda p: p.is_zoom_dependent())};
776
+ &ZOOM_DEPENDENT
777
+ }
778
+
779
+ /// Note that it's different from zoom_dependent(), as this only includes inherited, physical
780
+ /// properties.
781
+ #[inline]
782
+ pub fn zoom_dependent_inherited_properties() -> &'static Self {
783
+ static ZOOM_DEPENDENT_INHERITED: LonghandIdSet = ${longhand_id_set(lambda p: p.is_inherited_zoom_dependent_property())};
784
+ &ZOOM_DEPENDENT_INHERITED
785
+ }
786
+ }
787
+
788
+ /// An identifier for a given longhand property.
789
+ #[derive(Clone, Copy, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)]
790
+ #[repr(u16)]
791
+ pub enum LonghandId {
792
+ % for i, property in enumerate(data.longhands):
793
+ /// ${property.name}
794
+ ${property.camel_case} = ${i},
795
+ % endfor
796
+ }
797
+
798
+ enum LogicalMappingKind {
799
+ Side(LogicalSide),
800
+ Corner(LogicalCorner),
801
+ Axis(LogicalAxis),
802
+ }
803
+
804
+ struct LogicalMappingData {
805
+ group: LogicalGroupId,
806
+ kind: LogicalMappingKind,
807
+ }
808
+
809
+ impl LogicalMappingData {
810
+ fn to_physical(&self, wm: WritingMode) -> LonghandId {
811
+ let index = match self.kind {
812
+ LogicalMappingKind::Side(s) => s.to_physical(wm) as usize,
813
+ LogicalMappingKind::Corner(c) => c.to_physical(wm) as usize,
814
+ LogicalMappingKind::Axis(a) => a.to_physical(wm) as usize,
815
+ };
816
+ self.group.physical_properties()[index]
817
+ }
818
+ }
819
+
820
+ impl LonghandId {
821
+ /// Returns an iterator over all the shorthands that include this longhand.
822
+ pub fn shorthands(self) -> NonCustomPropertyIterator<ShorthandId> {
823
+ // first generate longhand to shorthands lookup map
824
+ //
825
+ // NOTE(emilio): This currently doesn't exclude the "all" shorthand. It
826
+ // could potentially do so, which would speed up serialization
827
+ // algorithms and what not, I guess.
828
+ <%
829
+ from functools import cmp_to_key
830
+ longhand_to_shorthand_map = {}
831
+ num_sub_properties = {}
832
+ for shorthand in data.shorthands:
833
+ num_sub_properties[shorthand.camel_case] = len(shorthand.sub_properties)
834
+ for sub_property in shorthand.sub_properties:
835
+ if sub_property.ident not in longhand_to_shorthand_map:
836
+ longhand_to_shorthand_map[sub_property.ident] = []
837
+
838
+ longhand_to_shorthand_map[sub_property.ident].append(shorthand.camel_case)
839
+
840
+ def cmp(a, b):
841
+ return (a > b) - (a < b)
842
+
843
+ def preferred_order(x, y):
844
+ # Since we want properties in order from most subproperties to least,
845
+ # reverse the arguments to cmp from the expected order.
846
+ result = cmp(num_sub_properties.get(y, 0), num_sub_properties.get(x, 0))
847
+ if result:
848
+ return result
849
+ # Fall back to lexicographic comparison.
850
+ return cmp(x, y)
851
+
852
+ # Sort the lists of shorthand properties according to preferred order:
853
+ # https://drafts.csswg.org/cssom/#concept-shorthands-preferred-order
854
+ for shorthand_list in longhand_to_shorthand_map.values():
855
+ shorthand_list.sort(key=cmp_to_key(preferred_order))
856
+ %>
857
+
858
+ // based on lookup results for each longhand, create result arrays
859
+ static MAP: [&[ShorthandId]; property_counts::LONGHANDS] = [
860
+ % for property in data.longhands:
861
+ &[
862
+ % for shorthand in longhand_to_shorthand_map.get(property.ident, []):
863
+ ShorthandId::${shorthand},
864
+ % endfor
865
+ ],
866
+ % endfor
867
+ ];
868
+
869
+ NonCustomPropertyIterator {
870
+ filter: NonCustomPropertyId::from(self).enabled_for_all_content(),
871
+ iter: MAP[self as usize].iter(),
872
+ }
873
+ }
874
+
875
+ pub(super) fn parse_value(
876
+ self,
877
+ context: &ParserContext,
878
+ input: &mut Parser,
879
+ ) -> Result<PropertyDeclaration, ParseError> {
880
+ type ParsePropertyFn = fn(
881
+ context: &ParserContext,
882
+ input: &mut Parser,
883
+ ) -> Result<PropertyDeclaration, ParseError>;
884
+ static PARSE_PROPERTY: [ParsePropertyFn; property_counts::LONGHANDS] = [
885
+ % for property in data.longhands:
886
+ longhands::${property.ident}::parse_declared,
887
+ % endfor
888
+ ];
889
+ (PARSE_PROPERTY[self as usize])(context, input)
890
+ }
891
+
892
+ /// Return the relevant data to map a particular logical property into physical.
893
+ fn logical_mapping_data(self) -> Option<&'static LogicalMappingData> {
894
+ const LOGICAL_MAPPING_DATA: [Option<LogicalMappingData>; property_counts::LONGHANDS] = [
895
+ % for prop in data.longhands:
896
+ % if prop.logical:
897
+ Some(LogicalMappingData {
898
+ group: LogicalGroupId::${to_camel_case(prop.logical_group)},
899
+ kind: ${prop.logical_mapping_kind(data)}
900
+ }),
901
+ % else:
902
+ None,
903
+ % endif
904
+ % endfor
905
+ ];
906
+ LOGICAL_MAPPING_DATA[self as usize].as_ref()
907
+ }
908
+
909
+ /// If this is a logical property, return the corresponding physical one in the given
910
+ /// writing mode. Otherwise, return unchanged.
911
+ #[inline]
912
+ pub fn to_physical(self, wm: WritingMode) -> Self {
913
+ let Some(data) = self.logical_mapping_data() else { return self };
914
+ data.to_physical(wm)
915
+ }
916
+
917
+ /// Return the logical group of this longhand property.
918
+ pub fn logical_group(self) -> Option<LogicalGroupId> {
919
+ const LOGICAL_GROUP_IDS: [Option<LogicalGroupId>; property_counts::LONGHANDS] = [
920
+ % for prop in data.longhands:
921
+ % if prop.logical_group:
922
+ Some(LogicalGroupId::${to_camel_case(prop.logical_group)}),
923
+ % else:
924
+ None,
925
+ % endif
926
+ % endfor
927
+ ];
928
+ LOGICAL_GROUP_IDS[self as usize]
929
+ }
930
+
931
+ /// Returns PropertyFlags for given longhand property.
932
+ #[inline(always)]
933
+ pub fn flags(self) -> PropertyFlags {
934
+ const FLAGS: [PropertyFlags; property_counts::LONGHANDS] = [
935
+ % for property in data.longhands:
936
+ PropertyFlags::empty()
937
+ % for flag in property.flags + restriction_flags(property):
938
+ .union(PropertyFlags::${flag})
939
+ % endfor
940
+ ,
941
+ % endfor
942
+ ];
943
+ FLAGS[self as usize]
944
+ }
945
+ }
946
+
947
+ /// An identifier for a given shorthand property.
948
+ #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)]
949
+ #[repr(u16)]
950
+ pub enum ShorthandId {
951
+ % for i, property in enumerate(data.shorthands):
952
+ /// ${property.name}
953
+ ${property.camel_case} = ${i},
954
+ % endfor
955
+ }
956
+
957
+ impl ShorthandId {
958
+ /// Get the longhand ids that form this shorthand.
959
+ pub fn longhands(self) -> NonCustomPropertyIterator<LonghandId> {
960
+ static MAP: [&[LonghandId]; property_counts::SHORTHANDS] = [
961
+ % for property in data.shorthands:
962
+ &[
963
+ % for sub in property.sub_properties:
964
+ LonghandId::${sub.camel_case},
965
+ % endfor
966
+ ],
967
+ % endfor
968
+ ];
969
+ NonCustomPropertyIterator {
970
+ filter: NonCustomPropertyId::from(self).enabled_for_all_content() &&
971
+ !self.allows_disabled_subproperties(),
972
+ iter: MAP[self as usize].iter(),
973
+ }
974
+ }
975
+
976
+ /// Try to serialize the given declarations as this shorthand.
977
+ ///
978
+ /// Returns an error if writing to the stream fails, or if the declarations
979
+ /// do not map to a shorthand.
980
+ pub fn longhands_to_css(
981
+ self,
982
+ declarations: &[&PropertyDeclaration],
983
+ dest: &mut CssStringWriter,
984
+ ) -> fmt::Result {
985
+ type LonghandsToCssFn = for<'a, 'b> fn(&'a [&'b PropertyDeclaration], &mut CssStringWriter) -> fmt::Result;
986
+ fn all_to_css(_: &[&PropertyDeclaration], _: &mut CssStringWriter) -> fmt::Result {
987
+ // No need to try to serialize the declarations as the 'all'
988
+ // shorthand, since it only accepts CSS-wide keywords (and variable
989
+ // references), which will be handled in
990
+ // get_shorthand_appendable_value.
991
+ Ok(())
992
+ }
993
+
994
+ static LONGHANDS_TO_CSS: [LonghandsToCssFn; property_counts::SHORTHANDS] = [
995
+ % for shorthand in data.shorthands:
996
+ % if shorthand.ident == "all":
997
+ all_to_css,
998
+ % else:
999
+ shorthands::${shorthand.ident}::to_css,
1000
+ % endif
1001
+ % endfor
1002
+ ];
1003
+
1004
+ LONGHANDS_TO_CSS[self as usize](declarations, dest)
1005
+ }
1006
+
1007
+ /// Returns PropertyFlags for the given shorthand property.
1008
+ #[inline]
1009
+ pub fn flags(self) -> PropertyFlags {
1010
+ const FLAGS: [u16; property_counts::SHORTHANDS] = [
1011
+ % for property in data.shorthands:
1012
+ % for flag in property.flags:
1013
+ PropertyFlags::${flag}.bits() |
1014
+ % endfor
1015
+ 0,
1016
+ % endfor
1017
+ ];
1018
+ PropertyFlags::from_bits_retain(FLAGS[self as usize])
1019
+ }
1020
+
1021
+ /// Returns the order in which this property appears relative to other
1022
+ /// shorthands in idl-name-sorting order.
1023
+ #[inline]
1024
+ pub fn idl_name_sort_order(self) -> u32 {
1025
+ <%
1026
+ from data import to_idl_name
1027
+ ordered = {}
1028
+ sorted_shorthands = sorted(data.shorthands, key=lambda p: to_idl_name(p.ident))
1029
+ for order, shorthand in enumerate(sorted_shorthands):
1030
+ ordered[shorthand.ident] = order
1031
+ %>
1032
+ static IDL_NAME_SORT_ORDER: [u32; property_counts::SHORTHANDS] = [
1033
+ % for property in data.shorthands:
1034
+ ${ordered[property.ident]},
1035
+ % endfor
1036
+ ];
1037
+ IDL_NAME_SORT_ORDER[self as usize]
1038
+ }
1039
+
1040
+ pub(super) fn parse_into(
1041
+ self,
1042
+ declarations: &mut SourcePropertyDeclaration,
1043
+ context: &ParserContext,
1044
+ input: &mut Parser,
1045
+ ) -> Result<(), ParseError> {
1046
+ type ParseIntoFn = fn(
1047
+ declarations: &mut SourcePropertyDeclaration,
1048
+ context: &ParserContext,
1049
+ input: &mut Parser,
1050
+ ) -> Result<(), ParseError>;
1051
+
1052
+ fn parse_all(
1053
+ _: &mut SourcePropertyDeclaration,
1054
+ _: &ParserContext,
1055
+ _input: &mut Parser
1056
+ ) -> Result<(), ParseError> {
1057
+ // 'all' accepts no value other than CSS-wide keywords
1058
+ Err(ParseError::custom(StyleParseErrorKind::UnspecifiedError))
1059
+ }
1060
+
1061
+ static PARSE_INTO: [ParseIntoFn; property_counts::SHORTHANDS] = [
1062
+ % for shorthand in data.shorthands:
1063
+ % if shorthand.ident == "all":
1064
+ parse_all,
1065
+ % else:
1066
+ shorthands::${shorthand.ident}::parse_into,
1067
+ % endif
1068
+ % endfor
1069
+ ];
1070
+
1071
+ (PARSE_INTO[self as usize])(declarations, context, input)
1072
+ }
1073
+ }
1074
+
1075
+ /// The counted unknown property list which is used for css use counters.
1076
+ ///
1077
+ /// FIXME: This should be just #[repr(u8)], but can't be because of ABI issues,
1078
+ /// see https://bugs.llvm.org/show_bug.cgi?id=44228.
1079
+ #[derive(Clone, Copy, Debug, Eq, FromPrimitive, Hash, PartialEq)]
1080
+ #[repr(u32)]
1081
+ pub enum CountedUnknownProperty {
1082
+ % for prop in data.counted_unknown_properties:
1083
+ /// ${prop.name}
1084
+ ${prop.camel_case},
1085
+ % endfor
1086
+ }
1087
+
1088
+ impl CountedUnknownProperty {
1089
+ /// Parse the counted unknown property, for testing purposes only.
1090
+ pub fn parse_for_testing(property_name: &str) -> Option<Self> {
1091
+ ::cssparser::ascii_case_insensitive_phf_map! {
1092
+ unknown_ids -> CountedUnknownProperty = {
1093
+ % for property in data.counted_unknown_properties:
1094
+ "${property.name}" => CountedUnknownProperty::${property.camel_case},
1095
+ % endfor
1096
+ }
1097
+ }
1098
+ unknown_ids::get(property_name).cloned()
1099
+ }
1100
+
1101
+ /// Returns the underlying index, used for use counter.
1102
+ #[inline]
1103
+ pub fn bit(self) -> usize {
1104
+ self as usize
1105
+ }
1106
+ }
1107
+
1108
+ impl PropertyId {
1109
+ /// Returns a given property from the given name, _regardless of whether it
1110
+ /// is enabled or not_, or Err(()) for unknown properties.
1111
+ pub fn parse_unchecked(
1112
+ property_name: &str,
1113
+ use_counters: Option<&UseCounters>,
1114
+ ) -> Result<Self, ()> {
1115
+ // A special id for css use counters. ShorthandAlias is not used in the Servo build.
1116
+ // That's why we need to allow dead_code.
1117
+ pub enum StaticId {
1118
+ NonCustom(NonCustomPropertyId),
1119
+ CountedUnknown(CountedUnknownProperty),
1120
+ }
1121
+ ::cssparser::ascii_case_insensitive_phf_map! {
1122
+ static_ids -> StaticId = {
1123
+ % for i, property in enumerate(data.longhands + data.shorthands + data.all_aliases()):
1124
+ "${property.name}" => StaticId::NonCustom(NonCustomPropertyId(${i})),
1125
+ % endfor
1126
+ % for property in data.counted_unknown_properties:
1127
+ "${property.name}" => {
1128
+ StaticId::CountedUnknown(CountedUnknownProperty::${property.camel_case})
1129
+ },
1130
+ % endfor
1131
+ }
1132
+ }
1133
+
1134
+ if let Some(id) = static_ids::get(property_name) {
1135
+ return Ok(match *id {
1136
+ StaticId::NonCustom(id) => PropertyId::NonCustom(id),
1137
+ StaticId::CountedUnknown(unknown_prop) => {
1138
+ if let Some(counters) = use_counters {
1139
+ counters.counted_unknown_properties.record(unknown_prop);
1140
+ }
1141
+ // Always return Err(()) because these aren't valid custom property names.
1142
+ return Err(());
1143
+ }
1144
+ });
1145
+ }
1146
+
1147
+ let name = crate::custom_properties::parse_name(property_name)?;
1148
+ Ok(PropertyId::Custom(crate::custom_properties::Name::from(name)))
1149
+ }
1150
+ }
1151
+
1152
+ impl PropertyDeclaration {
1153
+ /// Given a property declaration, return the property declaration id.
1154
+ #[inline]
1155
+ pub fn id(&self) -> PropertyDeclarationId<'_> {
1156
+ match *self {
1157
+ PropertyDeclaration::Custom(ref declaration) => {
1158
+ return PropertyDeclarationId::Custom(&declaration.name)
1159
+ }
1160
+ PropertyDeclaration::CSSWideKeyword(ref declaration) => {
1161
+ return PropertyDeclarationId::Longhand(declaration.id);
1162
+ }
1163
+ PropertyDeclaration::WithVariables(ref declaration) => {
1164
+ return PropertyDeclarationId::Longhand(declaration.id);
1165
+ }
1166
+ _ => {}
1167
+ }
1168
+ // This is just fine because PropertyDeclaration and LonghandId
1169
+ // have corresponding discriminants.
1170
+ let id = unsafe { *(self as *const _ as *const LonghandId) };
1171
+ debug_assert_eq!(id, match *self {
1172
+ % for property in data.longhands:
1173
+ PropertyDeclaration::${property.camel_case}(..) => LonghandId::${property.camel_case},
1174
+ % endfor
1175
+ _ => id,
1176
+ });
1177
+ PropertyDeclarationId::Longhand(id)
1178
+ }
1179
+
1180
+ /// Given a declaration, convert it into a declaration for a corresponding
1181
+ /// physical property.
1182
+ #[inline]
1183
+ pub fn to_physical(&self, wm: WritingMode) -> Self {
1184
+ match *self {
1185
+ PropertyDeclaration::WithVariables(VariableDeclaration {
1186
+ id,
1187
+ ref value,
1188
+ }) => {
1189
+ return PropertyDeclaration::WithVariables(VariableDeclaration {
1190
+ id: id.to_physical(wm),
1191
+ value: value.clone(),
1192
+ })
1193
+ }
1194
+ PropertyDeclaration::CSSWideKeyword(WideKeywordDeclaration {
1195
+ id,
1196
+ keyword,
1197
+ }) => {
1198
+ return PropertyDeclaration::CSSWideKeyword(WideKeywordDeclaration {
1199
+ id: id.to_physical(wm),
1200
+ keyword,
1201
+ })
1202
+ }
1203
+ PropertyDeclaration::Custom(..) => return self.clone(),
1204
+ % for prop in data.longhands:
1205
+ PropertyDeclaration::${prop.camel_case}(..) => {},
1206
+ % endfor
1207
+ }
1208
+
1209
+ let mut ret = self.clone();
1210
+
1211
+ % for prop in data.longhands:
1212
+ % for physical_property in prop.all_physical_mapped_properties(data):
1213
+ % if physical_property.specified_type() != prop.specified_type():
1214
+ <% raise "Logical property %s should share specified value with physical property %s" % \
1215
+ (prop.name, physical_property.name) %>
1216
+ % endif
1217
+ % endfor
1218
+ % endfor
1219
+
1220
+ unsafe {
1221
+ let longhand_id = *(&mut ret as *mut _ as *mut LonghandId);
1222
+
1223
+ debug_assert_eq!(
1224
+ PropertyDeclarationId::Longhand(longhand_id),
1225
+ ret.id()
1226
+ );
1227
+
1228
+ // This is just fine because PropertyDeclaration and LonghandId
1229
+ // have corresponding discriminants.
1230
+ *(&mut ret as *mut _ as *mut LonghandId) = longhand_id.to_physical(wm);
1231
+
1232
+ debug_assert_eq!(
1233
+ PropertyDeclarationId::Longhand(longhand_id.to_physical(wm)),
1234
+ ret.id()
1235
+ );
1236
+ }
1237
+
1238
+ ret
1239
+ }
1240
+
1241
+ /// Returns whether or not the property is set by a system font
1242
+ pub fn get_system(&self) -> Option<SystemFont> {
1243
+ match *self {
1244
+ % if engine == "gecko":
1245
+ % for prop in SYSTEM_FONT_LONGHANDS:
1246
+ PropertyDeclaration::${to_camel_case(prop)}(ref prop) => {
1247
+ prop.get_system()
1248
+ }
1249
+ % endfor
1250
+ % endif
1251
+ _ => None,
1252
+ }
1253
+ }
1254
+ }
1255
+
1256
+ #[cfg(feature = "gecko")]
1257
+ pub use super::gecko::style_structs;
1258
+
1259
+ /// The module where all the style structs are defined.
1260
+ #[cfg(feature = "servo")]
1261
+ pub mod style_structs {
1262
+ use rustc_hash::FxHasher;
1263
+ use super::longhands;
1264
+ use std::hash::{Hash, Hasher};
1265
+ use crate::logical_geometry::PhysicalSide;
1266
+ use crate::values::specified::color::ColorSchemeFlags;
1267
+ use crate::derives::*;
1268
+
1269
+ <%def name="impl_physical_sides(ident, props)">
1270
+ /// Gets the value of the longhand of `${ident}` on the `s` side`.
1271
+ pub fn get_${ident}(&self, s: PhysicalSide) -> &longhands::${data.longhands_by_name[props[0]].ident}::computed_value::T {
1272
+ match s {
1273
+ PhysicalSide::Top => &self.${data.longhands_by_name[props[0]].ident},
1274
+ PhysicalSide::Right => &self.${data.longhands_by_name[props[1]].ident},
1275
+ PhysicalSide::Bottom => &self.${data.longhands_by_name[props[2]].ident},
1276
+ PhysicalSide::Left => &self.${data.longhands_by_name[props[3]].ident},
1277
+ }
1278
+ }
1279
+ /// Sets the value of the longhand of `${ident}` on the `s` side to `v`.
1280
+ pub fn set_${ident}(&mut self, s: PhysicalSide, v: longhands::${data.longhands_by_name[props[0]].ident}::computed_value::T) {
1281
+ match s {
1282
+ PhysicalSide::Top => self.set_${data.longhands_by_name[props[0]].ident}(v),
1283
+ PhysicalSide::Right => self.set_${data.longhands_by_name[props[1]].ident}(v),
1284
+ PhysicalSide::Bottom => self.set_${data.longhands_by_name[props[2]].ident}(v),
1285
+ PhysicalSide::Left => self.set_${data.longhands_by_name[props[3]].ident}(v),
1286
+ }
1287
+ }
1288
+ </%def>
1289
+
1290
+ % for style_struct in data.active_style_structs():
1291
+ % if style_struct.name == "Font":
1292
+ #[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
1293
+ % else:
1294
+ #[derive(Clone, Debug, MallocSizeOf, PartialEq)]
1295
+ % endif
1296
+ /// The ${style_struct.name} style struct.
1297
+ pub struct ${style_struct.name} {
1298
+ % for longhand in style_struct.longhands:
1299
+ % if not longhand.logical:
1300
+ /// The ${longhand.name} computed value.
1301
+ pub ${longhand.ident}: longhands::${longhand.ident}::computed_value::T,
1302
+ % endif
1303
+ % endfor
1304
+ % if style_struct.name == "Font":
1305
+ /// The font hash, used for font caching.
1306
+ pub hash: u64,
1307
+ % endif
1308
+ % if style_struct.name == "Box":
1309
+ /// The display value specified by the CSS stylesheets (without any style adjustments),
1310
+ /// which is needed for hypothetical layout boxes.
1311
+ pub original_display: longhands::display::computed_value::T,
1312
+ % endif
1313
+ }
1314
+ % if style_struct.name == "Font":
1315
+ impl PartialEq for Font {
1316
+ fn eq(&self, other: &Font) -> bool {
1317
+ self.hash == other.hash
1318
+ % for longhand in style_struct.longhands:
1319
+ && self.${longhand.ident} == other.${longhand.ident}
1320
+ % endfor
1321
+ }
1322
+ }
1323
+ % endif
1324
+
1325
+ impl ${style_struct.name} {
1326
+ % for longhand in style_struct.longhands:
1327
+ % if not longhand.logical:
1328
+ % if longhand.ident == "display":
1329
+ /// Set `display`.
1330
+ ///
1331
+ /// We need to keep track of the original display for hypothetical boxes,
1332
+ /// so we need to special-case this.
1333
+ #[allow(non_snake_case)]
1334
+ #[inline]
1335
+ pub fn set_display(&mut self, v: longhands::display::computed_value::T) {
1336
+ self.display = v;
1337
+ self.original_display = v;
1338
+ }
1339
+ % else:
1340
+ /// Set ${longhand.name}.
1341
+ #[allow(non_snake_case)]
1342
+ #[inline]
1343
+ pub fn set_${longhand.ident}(&mut self, v: longhands::${longhand.ident}::computed_value::T) {
1344
+ self.${longhand.ident} = v;
1345
+ }
1346
+ % endif
1347
+ % if longhand.ident == "display":
1348
+ /// Set `display` from other struct.
1349
+ ///
1350
+ /// Same as `set_display` above.
1351
+ /// Thus, we need to special-case this.
1352
+ #[allow(non_snake_case)]
1353
+ #[inline]
1354
+ pub fn copy_display_from(&mut self, other: &Self) {
1355
+ self.display = other.display.clone();
1356
+ self.original_display = other.display.clone();
1357
+ }
1358
+ % else:
1359
+ /// Set ${longhand.name} from other struct.
1360
+ #[allow(non_snake_case)]
1361
+ #[inline]
1362
+ pub fn copy_${longhand.ident}_from(&mut self, other: &Self) {
1363
+ self.${longhand.ident} = other.${longhand.ident}.clone();
1364
+ }
1365
+ % endif
1366
+ /// Reset ${longhand.name} from the initial struct.
1367
+ #[allow(non_snake_case)]
1368
+ #[inline]
1369
+ pub fn reset_${longhand.ident}(&mut self, other: &Self) {
1370
+ self.copy_${longhand.ident}_from(other)
1371
+ }
1372
+
1373
+ /// Get the computed value for ${longhand.name}.
1374
+ #[allow(non_snake_case)]
1375
+ #[inline]
1376
+ pub fn clone_${longhand.ident}(&self) -> longhands::${longhand.ident}::computed_value::T {
1377
+ self.${longhand.ident}.clone()
1378
+ }
1379
+
1380
+ /// Whether `self` and `other` have the same computed value for ${longhand.name}.
1381
+ #[allow(non_snake_case)]
1382
+ #[inline]
1383
+ pub fn ${longhand.ident}_equals(&self, other: &Self) -> bool {
1384
+ self.${longhand.ident} == other.${longhand.ident}
1385
+ }
1386
+ % endif
1387
+ % if longhand.vector and longhand.vector.need_index:
1388
+ /// If this longhand is indexed, get the number of elements.
1389
+ #[allow(non_snake_case)]
1390
+ pub fn ${longhand.ident}_count(&self) -> usize {
1391
+ self.${longhand.ident}.0.len()
1392
+ }
1393
+
1394
+ /// If this longhand is indexed, get the element at given
1395
+ /// index.
1396
+ #[allow(non_snake_case)]
1397
+ pub fn ${longhand.ident}_at(&self, index: usize)
1398
+ -> longhands::${longhand.ident}::computed_value::SingleComputedValue {
1399
+ self.${longhand.ident}.0[index].clone()
1400
+ }
1401
+ % endif
1402
+ % endfor
1403
+ % if style_struct.name == "Font":
1404
+ /// Computes a font hash in order to be able to cache fonts
1405
+ /// effectively in GFX and layout.
1406
+ pub fn compute_font_hash(&mut self) {
1407
+ let mut hasher: FxHasher = Default::default();
1408
+ self.font_weight.hash(&mut hasher);
1409
+ self.font_width.hash(&mut hasher);
1410
+ self.font_style.hash(&mut hasher);
1411
+ self.font_family.hash(&mut hasher);
1412
+ self.hash = hasher.finish()
1413
+ }
1414
+ /// Create a new Font with the initial values of all members.
1415
+ pub fn initial_values() -> Self {
1416
+ Self {
1417
+ % for longhand in style_struct.longhands:
1418
+ % if not longhand.logical:
1419
+ ${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
1420
+ % endif
1421
+ % endfor
1422
+ hash: 0,
1423
+ }
1424
+ }
1425
+ % elif style_struct.name == "InheritedUI":
1426
+ /// Returns the ColorSchemeFlags corresponding to the value of `color-scheme`.
1427
+ #[inline]
1428
+ pub fn color_scheme_bits(&self) -> ColorSchemeFlags {
1429
+ self.color_scheme.bits
1430
+ }
1431
+ % elif style_struct.name == "Box":
1432
+ /// Sets the display property, but without touching original_display,
1433
+ /// except when the adjustment comes from root or item display fixups.
1434
+ pub fn set_adjusted_display(
1435
+ &mut self,
1436
+ dpy: longhands::display::computed_value::T,
1437
+ is_item_or_root: bool
1438
+ ) {
1439
+ self.display = dpy;
1440
+ if is_item_or_root {
1441
+ self.original_display = dpy;
1442
+ }
1443
+ }
1444
+ % elif style_struct.name == "Margin":
1445
+ ${impl_physical_sides("margin", ["margin-top", "margin-right", "margin-bottom", "margin-left"])}
1446
+ % elif style_struct.name == "Position":
1447
+ ${impl_physical_sides("inset", ["top", "right", "bottom", "left"])}
1448
+ % endif
1449
+ }
1450
+
1451
+ % endfor
1452
+ }
1453
+
1454
+ % for style_struct in data.active_style_structs():
1455
+ impl style_structs::${style_struct.name} {
1456
+ % for longhand in style_struct.longhands:
1457
+ % if longhand.vector and longhand.vector.need_index:
1458
+ /// Iterate over the values of ${longhand.name}.
1459
+ #[allow(non_snake_case)]
1460
+ #[inline]
1461
+ pub fn ${longhand.ident}_iter(&self) -> ${longhand.camel_case}Iter<'_> {
1462
+ ${longhand.camel_case}Iter {
1463
+ style_struct: self,
1464
+ current: 0,
1465
+ max: self.${longhand.ident}_count(),
1466
+ }
1467
+ }
1468
+
1469
+ /// Get a value mod `index` for the property ${longhand.name}.
1470
+ #[allow(non_snake_case)]
1471
+ #[inline]
1472
+ pub fn ${longhand.ident}_mod(&self, index: usize)
1473
+ -> longhands::${longhand.ident}::computed_value::SingleComputedValue {
1474
+ self.${longhand.ident}_at(index % self.${longhand.ident}_count())
1475
+ }
1476
+
1477
+ /// Clone the computed value for the property.
1478
+ #[allow(non_snake_case)]
1479
+ #[inline]
1480
+ #[cfg(feature = "gecko")]
1481
+ pub fn clone_${longhand.ident}(
1482
+ &self,
1483
+ ) -> longhands::${longhand.ident}::computed_value::T {
1484
+ longhands::${longhand.ident}::computed_value::List(
1485
+ self.${longhand.ident}_iter().collect()
1486
+ )
1487
+ }
1488
+ % endif
1489
+ % endfor
1490
+
1491
+ % if style_struct.name == "UI":
1492
+ /// Returns whether there is any animation specified with
1493
+ /// animation-name other than `none`.
1494
+ pub fn specifies_animations(&self) -> bool {
1495
+ self.animation_name_iter().any(|name| !name.is_none())
1496
+ }
1497
+
1498
+ /// Returns whether there are any transitions specified.
1499
+ #[cfg(feature = "servo")]
1500
+ pub fn specifies_transitions(&self) -> bool {
1501
+ (0..self.transition_property_count()).any(|index| {
1502
+ let combined_duration =
1503
+ self.transition_duration_mod(index).seconds().max(0.) +
1504
+ self.transition_delay_mod(index).seconds();
1505
+ combined_duration > 0.
1506
+ })
1507
+ }
1508
+
1509
+ /// Returns whether animation-timeline is initial value. We need this information to
1510
+ /// resolve animation-duration.
1511
+ #[cfg(feature = "servo")]
1512
+ pub fn has_initial_animation_timeline(&self) -> bool {
1513
+ self.animation_timeline_count() == 1 && self.animation_timeline_at(0).is_auto()
1514
+ }
1515
+
1516
+ /// Returns whether there is any named progress timeline specified with
1517
+ /// scroll-timeline-name other than `none`.
1518
+ #[cfg(feature = "gecko")]
1519
+ pub fn specifies_scroll_timelines(&self) -> bool {
1520
+ self.scroll_timeline_name_iter().any(|name| !name.value.is_none())
1521
+ }
1522
+
1523
+ /// Returns whether there is any timeline scope specified.
1524
+ #[cfg(feature = "gecko")]
1525
+ pub fn specifies_timeline_scope(&self) -> bool {
1526
+ !self.mTimelineScope.is_none()
1527
+ }
1528
+
1529
+ /// Returns whether there is any named progress timeline specified with
1530
+ /// view-timeline-name other than `none`.
1531
+ #[cfg(feature = "gecko")]
1532
+ pub fn specifies_view_timelines(&self) -> bool {
1533
+ self.view_timeline_name_iter().any(|name| !name.value.is_none())
1534
+ }
1535
+
1536
+ /// Returns true if animation properties are equal between styles, but without
1537
+ /// considering keyframe data and animation-timeline.
1538
+ #[cfg(feature = "servo")]
1539
+ pub fn animations_equals(&self, other: &Self) -> bool {
1540
+ self.animation_name_iter().eq(other.animation_name_iter()) &&
1541
+ self.animation_composition_iter().eq(other.animation_composition_iter()) &&
1542
+ self.animation_delay_iter().eq(other.animation_delay_iter()) &&
1543
+ self.animation_direction_iter().eq(other.animation_direction_iter()) &&
1544
+ self.animation_duration_iter().eq(other.animation_duration_iter()) &&
1545
+ self.animation_fill_mode_iter().eq(other.animation_fill_mode_iter()) &&
1546
+ self.animation_iteration_count_iter().eq(other.animation_iteration_count_iter()) &&
1547
+ self.animation_play_state_iter().eq(other.animation_play_state_iter()) &&
1548
+ self.animation_timing_function_iter().eq(other.animation_timing_function_iter())
1549
+ }
1550
+
1551
+ % elif style_struct.name == "Column":
1552
+ /// Whether this is a multicol style.
1553
+ #[cfg(feature = "servo")]
1554
+ pub fn is_multicol(&self) -> bool {
1555
+ !self.column_width.is_auto() || !self.column_count.is_auto()
1556
+ }
1557
+ % endif
1558
+ }
1559
+
1560
+ % for longhand in style_struct.longhands:
1561
+ % if longhand.vector and longhand.vector.need_index:
1562
+ /// An iterator over the values of the ${longhand.name} properties.
1563
+ pub struct ${longhand.camel_case}Iter<'a> {
1564
+ style_struct: &'a style_structs::${style_struct.name},
1565
+ current: usize,
1566
+ max: usize,
1567
+ }
1568
+
1569
+ impl<'a> Iterator for ${longhand.camel_case}Iter<'a> {
1570
+ type Item = longhands::${longhand.ident}::computed_value::SingleComputedValue;
1571
+
1572
+ fn next(&mut self) -> Option<Self::Item> {
1573
+ self.current += 1;
1574
+ if self.current <= self.max {
1575
+ Some(self.style_struct.${longhand.ident}_at(self.current - 1))
1576
+ } else {
1577
+ None
1578
+ }
1579
+ }
1580
+ }
1581
+ % endif
1582
+ % endfor
1583
+ % endfor
1584
+
1585
+
1586
+ #[cfg(feature = "gecko")]
1587
+ pub use super::gecko::{ComputedValues, ComputedValuesInner};
1588
+
1589
+ #[cfg(feature = "servo")]
1590
+ #[derive(Clone, Debug)]
1591
+ /// Actual data of ComputedValues, to match up with Gecko
1592
+ pub struct ComputedValuesInner {
1593
+ % for style_struct in data.active_style_structs():
1594
+ ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
1595
+ % endfor
1596
+ custom_properties: crate::custom_properties::ComputedCustomProperties,
1597
+
1598
+ /// The set of attributes used as values in `attr()`
1599
+ pub attribute_references: AttributeReferences,
1600
+
1601
+ /// The effective zoom value.
1602
+ pub effective_zoom: computed::Zoom,
1603
+
1604
+ /// A set of flags we use to store misc information regarding this style.
1605
+ pub flags: ComputedValueFlags,
1606
+
1607
+ /// The writing mode of this computed values struct.
1608
+ pub writing_mode: WritingMode,
1609
+
1610
+ /// The rule node representing the ordered list of rules matched for this
1611
+ /// node. Can be None for default values and text nodes. This is
1612
+ /// essentially an optimization to avoid referencing the root rule node.
1613
+ pub rules: Option<StrongRuleNode>,
1614
+
1615
+ /// The element's computed values if visited, only computed if there's a
1616
+ /// relevant link for this element. A element's "relevant link" is the
1617
+ /// element being matched if it is a link or the nearest ancestor link.
1618
+ visited_style: Option<Arc<ComputedValues>>,
1619
+ }
1620
+
1621
+ /// The struct that Servo uses to represent computed values.
1622
+ ///
1623
+ /// This struct contains an immutable atomically-reference-counted pointer to
1624
+ /// every kind of style struct.
1625
+ ///
1626
+ /// When needed, the structs may be copied in order to get mutated.
1627
+ #[cfg(feature = "servo")]
1628
+ #[derive(Clone, Debug)]
1629
+ pub struct ComputedValues {
1630
+ /// The actual computed values
1631
+ ///
1632
+ /// In Gecko the outer ComputedValues is actually a ComputedStyle, whereas
1633
+ /// ComputedValuesInner is the core set of computed values.
1634
+ ///
1635
+ /// We maintain this distinction in servo to reduce the amount of special
1636
+ /// casing.
1637
+ inner: ComputedValuesInner,
1638
+
1639
+ /// The pseudo-element that we're using.
1640
+ pseudo: Option<PseudoElement>,
1641
+ }
1642
+
1643
+ impl ComputedValues {
1644
+ /// Returns the pseudo-element that this style represents.
1645
+ #[cfg(feature = "servo")]
1646
+ pub fn pseudo(&self) -> Option<PseudoElement> {
1647
+ self.pseudo
1648
+ }
1649
+
1650
+ /// Returns true if this is the style for a pseudo-element.
1651
+ #[cfg(feature = "servo")]
1652
+ pub fn is_pseudo_style(&self) -> bool {
1653
+ self.pseudo().is_some()
1654
+ }
1655
+
1656
+ /// Returns whether this style's display value is equal to contents.
1657
+ pub fn is_display_contents(&self) -> bool {
1658
+ self.clone_display().is_contents()
1659
+ }
1660
+
1661
+ /// Gets a reference to the rule node. Panic if no rule node exists.
1662
+ pub fn rules(&self) -> &StrongRuleNode {
1663
+ self.rules.as_ref().unwrap()
1664
+ }
1665
+
1666
+ /// Returns the visited rules, if applicable.
1667
+ pub fn visited_rules(&self) -> Option<&StrongRuleNode> {
1668
+ self.visited_style().and_then(|s| s.rules.as_ref())
1669
+ }
1670
+
1671
+ /// Gets a reference to the custom properties map (if one exists).
1672
+ pub fn custom_properties(&self) -> &crate::custom_properties::ComputedCustomProperties {
1673
+ &self.custom_properties
1674
+ }
1675
+
1676
+ % for prop in data.longhands:
1677
+ % if not prop.logical:
1678
+ /// Gets the computed value of a given property.
1679
+ #[inline(always)]
1680
+ #[allow(non_snake_case)]
1681
+ pub fn clone_${prop.ident}(
1682
+ &self,
1683
+ ) -> longhands::${prop.ident}::computed_value::T {
1684
+ self.get_${prop.style_struct.name_lower}().clone_${prop.ident}()
1685
+ }
1686
+
1687
+ /// Gets the computed value of a given property.
1688
+ #[inline(always)]
1689
+ #[allow(non_snake_case)]
1690
+ pub fn ${prop.ident}_equals(&self, other: &Self) -> bool {
1691
+ self.get_${prop.style_struct.name_lower}().${prop.ident}_equals(other.get_${prop.style_struct.name_lower}())
1692
+ }
1693
+ % endif
1694
+ % endfor
1695
+
1696
+ /// Writes the (resolved or computed) value of the given longhand as a string in `dest`.
1697
+ ///
1698
+ /// TODO(emilio): We should move all the special resolution from
1699
+ /// nsComputedDOMStyle to ToResolvedValue instead.
1700
+ pub fn computed_or_resolved_value(
1701
+ &self,
1702
+ property_id: LonghandId,
1703
+ context: Option<&mut resolved::Context>,
1704
+ dest: &mut CssStringWriter,
1705
+ ) -> fmt::Result {
1706
+ let mut dest = CssWriter::new(dest);
1707
+ let property_id = property_id.to_physical(self.writing_mode);
1708
+ match property_id {
1709
+ % for specified_type, props in groupby(data.longhands, key=lambda x: x.specified_type()):
1710
+ <% props = list(props) %>
1711
+ ${" |\n".join("LonghandId::{}".format(p.camel_case) for p in props)} => {
1712
+ let value = match property_id {
1713
+ % for prop in props:
1714
+ % if not prop.logical:
1715
+ LonghandId::${prop.camel_case} => self.clone_${prop.ident}(),
1716
+ % endif
1717
+ % endfor
1718
+ _ => unsafe { debug_unreachable!() },
1719
+ };
1720
+ if let Some(c) = context {
1721
+ c.current_longhand = Some(property_id);
1722
+ value.to_resolved_value(c).to_css(&mut dest)
1723
+ } else {
1724
+ value.to_css(&mut dest)
1725
+ }
1726
+ }
1727
+ % endfor
1728
+ }
1729
+ }
1730
+
1731
+ /// Returns the computed value of the given longhand as a
1732
+ /// [`TypedValueList`], if supported.
1733
+ pub fn property_value_to_typed_value_list(
1734
+ &self,
1735
+ property_id: LonghandId,
1736
+ ) -> Option<TypedValueList> {
1737
+ let property_id = property_id.to_physical(self.writing_mode);
1738
+ match property_id {
1739
+ % for specified_type, props in groupby(data.longhands, key=lambda x: x.specified_type()):
1740
+ <% props = list(props) %>
1741
+ ${" |\n".join("LonghandId::{}".format(p.camel_case) for p in props)} => {
1742
+ let value = match property_id {
1743
+ % for prop in props:
1744
+ % if not prop.logical:
1745
+ LonghandId::${prop.camel_case} => self.clone_${prop.ident}(),
1746
+ % endif
1747
+ % endfor
1748
+ _ => unsafe { debug_unreachable!() },
1749
+ };
1750
+ value.to_typed_value_list()
1751
+ }
1752
+ % endfor
1753
+ }
1754
+ }
1755
+
1756
+ /// Returns the given longhand's resolved value as a property declaration.
1757
+ pub fn computed_or_resolved_declaration(
1758
+ &self,
1759
+ property_id: LonghandId,
1760
+ context: Option<&mut resolved::Context>,
1761
+ ) -> PropertyDeclaration {
1762
+ let physical_property_id = property_id.to_physical(self.writing_mode);
1763
+ match physical_property_id {
1764
+ % for specified_type, props in groupby(data.longhands, key=lambda x: x.specified_type()):
1765
+ <% props = list(props) %>
1766
+ ${" |\n".join("LonghandId::{}".format(p.camel_case) for p in props)} => {
1767
+ let mut computed_value = match physical_property_id {
1768
+ % for prop in props:
1769
+ % if not prop.logical:
1770
+ LonghandId::${prop.camel_case} => self.clone_${prop.ident}(),
1771
+ % endif
1772
+ % endfor
1773
+ _ => unsafe { debug_unreachable!() },
1774
+ };
1775
+ if let Some(c) = context {
1776
+ c.current_longhand = Some(physical_property_id);
1777
+ let resolved = computed_value.to_resolved_value(c);
1778
+ computed_value = ToResolvedValue::from_resolved_value(resolved);
1779
+ }
1780
+ let specified = ToComputedValue::from_computed_value(&computed_value);
1781
+ % if props[0].boxed:
1782
+ let specified = Box::new(specified);
1783
+ % endif
1784
+ % if len(props) == 1:
1785
+ PropertyDeclaration::${props[0].camel_case}(specified)
1786
+ % else:
1787
+ unsafe {
1788
+ let mut out = mem::MaybeUninit::uninit();
1789
+ ptr::write(
1790
+ out.as_mut_ptr() as *mut PropertyDeclarationVariantRepr<${specified_type}>,
1791
+ PropertyDeclarationVariantRepr {
1792
+ tag: property_id as u16,
1793
+ value: specified,
1794
+ },
1795
+ );
1796
+ out.assume_init()
1797
+ }
1798
+ % endif
1799
+ }
1800
+ % endfor
1801
+ }
1802
+ }
1803
+
1804
+ /// Resolves the currentColor keyword.
1805
+ ///
1806
+ /// Any color value from computed values (except for the 'color' property
1807
+ /// itself) should go through this method.
1808
+ ///
1809
+ /// Usage example:
1810
+ /// let top_color =
1811
+ /// style.resolve_color(&style.get_border().clone_border_top_color());
1812
+ #[inline]
1813
+ pub fn resolve_color(&self, color: &computed::Color) -> crate::color::AbsoluteColor {
1814
+ let current_color = self.get_inherited_text().clone_color();
1815
+ color.resolve_to_absolute(&current_color)
1816
+ }
1817
+
1818
+ /// Returns which longhand properties have different values in the two
1819
+ /// ComputedValues.
1820
+ #[cfg(feature = "gecko_debug")]
1821
+ pub fn differing_properties(&self, other: &ComputedValues) -> LonghandIdSet {
1822
+ let mut set = LonghandIdSet::new();
1823
+ % for prop in data.longhands:
1824
+ % if not prop.logical:
1825
+ if self.clone_${prop.ident}() != other.clone_${prop.ident}() {
1826
+ set.insert(LonghandId::${prop.camel_case});
1827
+ }
1828
+ % endif
1829
+ % endfor
1830
+ set
1831
+ }
1832
+
1833
+ /// Create a `TransitionPropertyIterator` for this styles transition properties.
1834
+ pub fn transition_properties<'a>(&'a self) -> TransitionPropertyIterator<'a> {
1835
+ TransitionPropertyIterator::from_style(self)
1836
+ }
1837
+ }
1838
+
1839
+ #[cfg(feature = "servo")]
1840
+ impl ComputedValues {
1841
+ /// Create a new refcounted `ComputedValues`
1842
+ pub fn new(
1843
+ pseudo: Option<&PseudoElement>,
1844
+ custom_properties: crate::custom_properties::ComputedCustomProperties,
1845
+ attribute_references: crate::dom::AttributeReferences,
1846
+ writing_mode: WritingMode,
1847
+ effective_zoom: computed::Zoom,
1848
+ flags: ComputedValueFlags,
1849
+ rules: Option<StrongRuleNode>,
1850
+ visited_style: Option<Arc<ComputedValues>>,
1851
+ % for style_struct in data.active_style_structs():
1852
+ ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
1853
+ % endfor
1854
+ ) -> Arc<Self> {
1855
+ Arc::new(Self {
1856
+ inner: ComputedValuesInner {
1857
+ custom_properties,
1858
+ attribute_references,
1859
+ writing_mode,
1860
+ rules,
1861
+ visited_style,
1862
+ effective_zoom,
1863
+ flags,
1864
+ % for style_struct in data.active_style_structs():
1865
+ ${style_struct.ident},
1866
+ % endfor
1867
+ },
1868
+ pseudo: pseudo.cloned(),
1869
+ })
1870
+ }
1871
+
1872
+ /// Get the initial computed values.
1873
+ pub fn initial_values_with_font_override(default_font: super::style_structs::Font) -> Arc<Self> {
1874
+ use crate::computed_value_flags::ComputedValueFlags;
1875
+ use servo_arc::Arc;
1876
+ use super::{ComputedValues, ComputedValuesInner, longhands, style_structs};
1877
+
1878
+ Arc::new(ComputedValues {
1879
+ inner: ComputedValuesInner {
1880
+ % for style_struct in data.active_style_structs():
1881
+ % if style_struct.name == "Font":
1882
+ font: Arc::new(default_font),
1883
+ <% continue %>
1884
+ % endif %
1885
+
1886
+ ${style_struct.ident}: Arc::new(style_structs::${style_struct.name} {
1887
+ % for longhand in style_struct.longhands:
1888
+ % if not longhand.logical:
1889
+ ${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
1890
+ % endif
1891
+ % endfor
1892
+ % if style_struct.name == "Box":
1893
+ original_display: longhands::display::get_initial_value(),
1894
+ % endif
1895
+ }),
1896
+ % endfor
1897
+ custom_properties: crate::custom_properties::ComputedCustomProperties::default(),
1898
+ attribute_references: AttributeReferences::default(),
1899
+ writing_mode: WritingMode::empty(),
1900
+ rules: None,
1901
+ visited_style: None,
1902
+ effective_zoom: crate::values::computed::Zoom::ONE,
1903
+ flags: ComputedValueFlags::empty(),
1904
+ },
1905
+ pseudo: None,
1906
+ })
1907
+ }
1908
+
1909
+ /// Converts the computed values to an Arc<> from a reference.
1910
+ pub fn to_arc(&self) -> Arc<Self> {
1911
+ // SAFETY: We're guaranteed to be allocated as an Arc<> since the
1912
+ // functions above are the only ones that create ComputedValues
1913
+ // instances in Servo (and that must be the case since ComputedValues'
1914
+ // member is private).
1915
+ unsafe { Arc::from_raw_addrefed(self) }
1916
+ }
1917
+
1918
+ /// Serializes the computed value of this property as a string.
1919
+ pub fn computed_value_to_string(&self, property: PropertyDeclarationId) -> String {
1920
+ match property {
1921
+ PropertyDeclarationId::Longhand(id) => {
1922
+ let mut context = resolved::Context {
1923
+ style: self,
1924
+ for_property: PropertyId::NonCustom(id.into()),
1925
+ current_longhand: Some(id),
1926
+ };
1927
+ let mut s = String::new();
1928
+ self.computed_or_resolved_value(
1929
+ id,
1930
+ Some(&mut context),
1931
+ &mut s
1932
+ ).unwrap();
1933
+ s
1934
+ }
1935
+ PropertyDeclarationId::Custom(name) => {
1936
+ // FIXME(bug 1869476): This should use a stylist to determine
1937
+ // whether the name corresponds to an inherited custom property
1938
+ // and then choose the inherited/non_inherited map accordingly.
1939
+ let p = &self.custom_properties;
1940
+ let Some(value) = p.inherited.get(name).or_else(|| p.non_inherited.get(name))
1941
+ else {
1942
+ return String::new();
1943
+ };
1944
+ let mut context = resolved::Context {
1945
+ style: self,
1946
+ for_property: PropertyId::Custom(name.clone()),
1947
+ current_longhand: None,
1948
+ };
1949
+ value
1950
+ .clone()
1951
+ .to_resolved_value(&mut context)
1952
+ .to_css_string()
1953
+ }
1954
+ }
1955
+ }
1956
+
1957
+ /// Calls the given function for each cached lazy pseudo-element style.
1958
+ pub fn each_cached_lazy_pseudo<F>(&self, mut _f: F)
1959
+ where
1960
+ F: FnMut(&Self),
1961
+ {
1962
+ // Servo doesn't currently cache lazy pseudo-element styles.
1963
+ }
1964
+ }
1965
+
1966
+ #[cfg(feature = "servo")]
1967
+ impl ops::Deref for ComputedValues {
1968
+ type Target = ComputedValuesInner;
1969
+ fn deref(&self) -> &ComputedValuesInner {
1970
+ &self.inner
1971
+ }
1972
+ }
1973
+
1974
+ #[cfg(feature = "servo")]
1975
+ impl ops::DerefMut for ComputedValues {
1976
+ fn deref_mut(&mut self) -> &mut ComputedValuesInner {
1977
+ &mut self.inner
1978
+ }
1979
+ }
1980
+
1981
+ #[cfg(feature = "servo")]
1982
+ impl ComputedValuesInner {
1983
+ /// Share ComputedValues but with different flags.
1984
+ pub fn clone_with_flags(&self, flags: ComputedValueFlags, pseudo: Option<&PseudoElement>) -> Arc<ComputedValues> {
1985
+ Arc::new(ComputedValues {
1986
+ inner: Self {
1987
+ custom_properties: self.custom_properties.clone(),
1988
+ attribute_references: self.attribute_references.clone(),
1989
+ writing_mode: self.writing_mode.clone(),
1990
+ rules: self.rules.clone(),
1991
+ visited_style: self.visited_style.clone(),
1992
+ flags,
1993
+ effective_zoom: self.effective_zoom.clone(),
1994
+ % for style_struct in data.active_style_structs():
1995
+ ${style_struct.ident}: self.${style_struct.ident}.clone(),
1996
+ % endfor
1997
+ },
1998
+ pseudo: pseudo.cloned(),
1999
+ })
2000
+ }
2001
+
2002
+ /// Returns the visited style, if any.
2003
+ pub fn visited_style(&self) -> Option<&ComputedValues> {
2004
+ self.visited_style.as_deref()
2005
+ }
2006
+
2007
+ % for style_struct in data.active_style_structs():
2008
+ /// Clone the ${style_struct.name} struct.
2009
+ #[inline]
2010
+ pub fn clone_${style_struct.name_lower}(&self) -> Arc<style_structs::${style_struct.name}> {
2011
+ self.${style_struct.ident}.clone()
2012
+ }
2013
+
2014
+ /// Get a immutable reference to the ${style_struct.name} struct.
2015
+ #[inline]
2016
+ pub fn get_${style_struct.name_lower}(&self) -> &style_structs::${style_struct.name} {
2017
+ &self.${style_struct.ident}
2018
+ }
2019
+
2020
+ /// Get a mutable reference to the ${style_struct.name} struct.
2021
+ #[inline]
2022
+ pub fn mutate_${style_struct.name_lower}(&mut self) -> &mut style_structs::${style_struct.name} {
2023
+ Arc::make_mut(&mut self.${style_struct.ident})
2024
+ }
2025
+ % endfor
2026
+
2027
+ /// Gets a reference to the rule node. Panic if no rule node exists.
2028
+ pub fn rules(&self) -> &StrongRuleNode {
2029
+ self.rules.as_ref().unwrap()
2030
+ }
2031
+
2032
+ #[inline]
2033
+ /// Returns whether the "content" property for the given style is completely
2034
+ /// ineffective, and would yield an empty `::before` or `::after`
2035
+ /// pseudo-element.
2036
+ pub fn ineffective_content_property(&self) -> bool {
2037
+ use crate::values::generics::counters::Content;
2038
+ match self.get_counters().content {
2039
+ Content::Normal | Content::None => true,
2040
+ Content::Items(ref items) => items.items.is_empty()
2041
+ }
2042
+ }
2043
+
2044
+ /// Whether the current style is multicolumn.
2045
+ #[inline]
2046
+ pub fn is_multicol(&self) -> bool {
2047
+ self.get_column().is_multicol()
2048
+ }
2049
+
2050
+ /// Get the logical computed inline size.
2051
+ #[inline]
2052
+ pub fn content_inline_size(&self) -> &computed::Size {
2053
+ let position_style = self.get_position();
2054
+ if self.writing_mode.is_vertical() {
2055
+ &position_style.height
2056
+ } else {
2057
+ &position_style.width
2058
+ }
2059
+ }
2060
+
2061
+ /// Get the logical computed block size.
2062
+ #[inline]
2063
+ pub fn content_block_size(&self) -> &computed::Size {
2064
+ let position_style = self.get_position();
2065
+ if self.writing_mode.is_vertical() { &position_style.width } else { &position_style.height }
2066
+ }
2067
+
2068
+ /// Get the logical computed min inline size.
2069
+ #[inline]
2070
+ pub fn min_inline_size(&self) -> &computed::Size {
2071
+ let position_style = self.get_position();
2072
+ if self.writing_mode.is_vertical() { &position_style.min_height } else { &position_style.min_width }
2073
+ }
2074
+
2075
+ /// Get the logical computed min block size.
2076
+ #[inline]
2077
+ pub fn min_block_size(&self) -> &computed::Size {
2078
+ let position_style = self.get_position();
2079
+ if self.writing_mode.is_vertical() { &position_style.min_width } else { &position_style.min_height }
2080
+ }
2081
+
2082
+ /// Get the logical computed max inline size.
2083
+ #[inline]
2084
+ pub fn max_inline_size(&self) -> &computed::MaxSize {
2085
+ let position_style = self.get_position();
2086
+ if self.writing_mode.is_vertical() { &position_style.max_height } else { &position_style.max_width }
2087
+ }
2088
+
2089
+ /// Get the logical computed max block size.
2090
+ #[inline]
2091
+ pub fn max_block_size(&self) -> &computed::MaxSize {
2092
+ let position_style = self.get_position();
2093
+ if self.writing_mode.is_vertical() { &position_style.max_width } else { &position_style.max_height }
2094
+ }
2095
+
2096
+ /// Get the logical computed padding for this writing mode.
2097
+ #[inline]
2098
+ pub fn logical_padding(&self) -> LogicalMargin<&computed::LengthPercentage> {
2099
+ let padding_style = self.get_padding();
2100
+ LogicalMargin::from_physical(self.writing_mode, SideOffsets2D::new(
2101
+ &padding_style.padding_top.0,
2102
+ &padding_style.padding_right.0,
2103
+ &padding_style.padding_bottom.0,
2104
+ &padding_style.padding_left.0,
2105
+ ))
2106
+ }
2107
+
2108
+ /// Gets the logical computed margin from this style.
2109
+ #[inline]
2110
+ pub fn logical_margin(&self) -> LogicalMargin<&computed::Margin> {
2111
+ let margin_style = self.get_margin();
2112
+ LogicalMargin::from_physical(self.writing_mode, SideOffsets2D::new(
2113
+ &margin_style.margin_top,
2114
+ &margin_style.margin_right,
2115
+ &margin_style.margin_bottom,
2116
+ &margin_style.margin_left,
2117
+ ))
2118
+ }
2119
+
2120
+ /// Gets the logical position from this style.
2121
+ #[inline]
2122
+ pub fn logical_position(&self) -> LogicalMargin<&computed::Inset> {
2123
+ // FIXME(SimonSapin): should be the writing mode of the containing block, maybe?
2124
+ let position_style = self.get_position();
2125
+ LogicalMargin::from_physical(self.writing_mode, SideOffsets2D::new(
2126
+ &position_style.top,
2127
+ &position_style.right,
2128
+ &position_style.bottom,
2129
+ &position_style.left,
2130
+ ))
2131
+ }
2132
+ }
2133
+
2134
+ /// A reference to a style struct of the parent, or our own style struct.
2135
+ pub enum StyleStructRef<'a, T: 'static> {
2136
+ /// A borrowed struct from the parent, for example, for inheriting style.
2137
+ Borrowed(&'a T),
2138
+ /// An owned struct, that we've already mutated.
2139
+ Owned(UniqueArc<T>),
2140
+ /// Temporarily vacated, will panic if accessed
2141
+ Vacated,
2142
+ }
2143
+
2144
+ impl<'a, T: 'a> StyleStructRef<'a, T>
2145
+ where
2146
+ T: Clone,
2147
+ {
2148
+ /// Ensure a mutable reference of this value exists, either cloning the
2149
+ /// borrowed value, or returning the owned one.
2150
+ pub fn mutate(&mut self) -> &mut T {
2151
+ if let StyleStructRef::Borrowed(v) = *self {
2152
+ *self = StyleStructRef::Owned(UniqueArc::new(v.clone()));
2153
+ }
2154
+
2155
+ match *self {
2156
+ StyleStructRef::Owned(ref mut v) => v,
2157
+ StyleStructRef::Borrowed(..) => unreachable!(),
2158
+ StyleStructRef::Vacated => panic!("Accessed vacated style struct")
2159
+ }
2160
+ }
2161
+
2162
+ /// Whether this is pointer-equal to the struct we're going to copy the
2163
+ /// value from.
2164
+ ///
2165
+ /// This is used to avoid allocations when people write stuff like `font:
2166
+ /// inherit` or such `all: initial`.
2167
+ #[inline]
2168
+ pub fn ptr_eq(&self, struct_to_copy_from: &T) -> bool {
2169
+ match *self {
2170
+ StyleStructRef::Owned(..) => false,
2171
+ StyleStructRef::Borrowed(s) => {
2172
+ std::ptr::eq(s, struct_to_copy_from)
2173
+ }
2174
+ StyleStructRef::Vacated => panic!("Accessed vacated style struct")
2175
+ }
2176
+ }
2177
+
2178
+ /// Extract a unique Arc from this struct, vacating it.
2179
+ ///
2180
+ /// The vacated state is a transient one, please put the Arc back
2181
+ /// when done via `put()`. This function is to be used to separate
2182
+ /// the struct being mutated from the computed context
2183
+ pub fn take(&mut self) -> UniqueArc<T> {
2184
+ use std::mem::replace;
2185
+ let inner = replace(self, StyleStructRef::Vacated);
2186
+
2187
+ match inner {
2188
+ StyleStructRef::Owned(arc) => arc,
2189
+ StyleStructRef::Borrowed(s) => UniqueArc::new(s.clone()),
2190
+ StyleStructRef::Vacated => panic!("Accessed vacated style struct"),
2191
+ }
2192
+ }
2193
+
2194
+ /// Replace vacated ref with an arc
2195
+ pub fn put(&mut self, arc: UniqueArc<T>) {
2196
+ debug_assert!(matches!(*self, StyleStructRef::Vacated));
2197
+ *self = StyleStructRef::Owned(arc);
2198
+ }
2199
+
2200
+ /// Get a mutable reference to the owned struct, or `None` if the struct
2201
+ /// hasn't been mutated.
2202
+ pub fn get_if_mutated(&mut self) -> Option<&mut T> {
2203
+ match *self {
2204
+ StyleStructRef::Owned(ref mut v) => Some(v),
2205
+ StyleStructRef::Borrowed(..) => None,
2206
+ StyleStructRef::Vacated => panic!("Accessed vacated style struct")
2207
+ }
2208
+ }
2209
+
2210
+ /// Returns an `Arc` to the internal struct, constructing one if
2211
+ /// appropriate.
2212
+ pub fn build(self) -> Arc<T> {
2213
+ match self {
2214
+ StyleStructRef::Owned(v) => v.shareable(),
2215
+ // SAFETY: We know all style structs are arc-allocated.
2216
+ StyleStructRef::Borrowed(v) => unsafe { Arc::from_raw_addrefed(v) },
2217
+ StyleStructRef::Vacated => panic!("Accessed vacated style struct")
2218
+ }
2219
+ }
2220
+ }
2221
+
2222
+ impl<'a, T: 'a> ops::Deref for StyleStructRef<'a, T> {
2223
+ type Target = T;
2224
+
2225
+ fn deref(&self) -> &T {
2226
+ match *self {
2227
+ StyleStructRef::Owned(ref v) => v,
2228
+ StyleStructRef::Borrowed(v) => v,
2229
+ StyleStructRef::Vacated => panic!("Accessed vacated style struct")
2230
+ }
2231
+ }
2232
+ }
2233
+
2234
+ /// A type used to compute a struct with minimal overhead.
2235
+ ///
2236
+ /// This allows holding references to the parent/default computed values without
2237
+ /// actually cloning them, until we either build the style, or mutate the
2238
+ /// inherited value.
2239
+ pub struct StyleBuilder<'a> {
2240
+ /// The device we're using to compute style.
2241
+ ///
2242
+ /// This provides access to viewport unit ratios, etc.
2243
+ pub device: &'a Device,
2244
+
2245
+ /// The stylist we're using to compute style except for media queries.
2246
+ /// device is used in media queries instead.
2247
+ pub stylist: Option<&'a Stylist>,
2248
+
2249
+ /// The style we're inheriting from.
2250
+ ///
2251
+ /// This is effectively
2252
+ /// `parent_style.unwrap_or(device.default_computed_values())`.
2253
+ pub inherited_style: &'a ComputedValues,
2254
+
2255
+ /// The style we're getting reset structs from.
2256
+ reset_style: &'a ComputedValues,
2257
+
2258
+ /// The rule node representing the ordered list of rules matched for this
2259
+ /// node.
2260
+ pub rules: Option<StrongRuleNode>,
2261
+
2262
+ /// The computed custom properties and attributes.
2263
+ pub substitution_functions: crate::custom_properties::ComputedSubstitutionFunctions,
2264
+
2265
+ /// The set of attributes used as values in `attr()`
2266
+ pub attribute_references: crate::dom::AttributeReferences,
2267
+
2268
+ /// Non-custom properties that are considered invalid at compute time due to cyclic
2269
+ /// dependencies with custom properties, e.g. `--foo: 1em; font-size: var(--foo)` where
2270
+ /// `--foo` is registered. Such a property uses its inherited/initial value.
2271
+ pub invalid_non_custom_properties: LonghandIdSet,
2272
+
2273
+ /// The pseudo-element this style will represent.
2274
+ pub pseudo: Option<&'a PseudoElement>,
2275
+
2276
+ /// Whether we have mutated any reset structs since the the last time
2277
+ /// `clear_modified_reset` was called. This is used to tell whether the
2278
+ /// `StyleAdjuster` did any work.
2279
+ modified_reset: bool,
2280
+
2281
+ /// Whether this is the style for the root element.
2282
+ pub is_root_element: bool,
2283
+
2284
+ /// The writing mode flags.
2285
+ ///
2286
+ /// TODO(emilio): Make private.
2287
+ pub writing_mode: WritingMode,
2288
+
2289
+ /// The color-scheme bits. Needed because they may otherwise be different between visited and
2290
+ /// unvisited colors.
2291
+ pub color_scheme: ColorSchemeFlags,
2292
+
2293
+ /// The effective zoom.
2294
+ pub effective_zoom: computed::Zoom,
2295
+
2296
+ /// The effective zoom for inheritance (the "specified" zoom on this element).
2297
+ pub effective_zoom_for_inheritance: computed::Zoom,
2298
+
2299
+ /// Flags for the computed value.
2300
+ pub flags: Cell<ComputedValueFlags>,
2301
+
2302
+ /// The element's style if visited, only computed if there's a relevant link
2303
+ /// for this element. A element's "relevant link" is the element being
2304
+ /// matched if it is a link or the nearest ancestor link.
2305
+ pub visited_style: Option<Arc<ComputedValues>>,
2306
+ % for style_struct in data.active_style_structs():
2307
+ ${style_struct.ident}: StyleStructRef<'a, style_structs::${style_struct.name}>,
2308
+ % endfor
2309
+ }
2310
+
2311
+ impl<'a> StyleBuilder<'a> {
2312
+ /// Trivially construct a `StyleBuilder`.
2313
+ pub fn new(
2314
+ device: &'a Device,
2315
+ stylist: Option<&'a Stylist>,
2316
+ parent_style: Option<&'a ComputedValues>,
2317
+ pseudo: Option<&'a PseudoElement>,
2318
+ rules: Option<StrongRuleNode>,
2319
+ is_root_element: bool,
2320
+ ) -> Self {
2321
+ let reset_style = device.default_computed_values();
2322
+ let inherited_style = parent_style.unwrap_or(reset_style);
2323
+
2324
+ let flags = inherited_style.flags.inherited();
2325
+ Self {
2326
+ device,
2327
+ stylist,
2328
+ inherited_style,
2329
+ reset_style,
2330
+ pseudo,
2331
+ rules,
2332
+ modified_reset: false,
2333
+ is_root_element,
2334
+ substitution_functions: crate::custom_properties::ComputedSubstitutionFunctions::default(),
2335
+ attribute_references: crate::dom::AttributeReferences::default(),
2336
+ invalid_non_custom_properties: LonghandIdSet::default(),
2337
+ writing_mode: inherited_style.writing_mode,
2338
+ effective_zoom: inherited_style.effective_zoom,
2339
+ effective_zoom_for_inheritance: computed::Zoom::ONE,
2340
+ color_scheme: inherited_style.get_inherited_ui().color_scheme_bits(),
2341
+ flags: Cell::new(flags),
2342
+ visited_style: None,
2343
+ % for style_struct in data.active_style_structs():
2344
+ % if style_struct.inherited:
2345
+ ${style_struct.ident}: StyleStructRef::Borrowed(inherited_style.get_${style_struct.name_lower}()),
2346
+ % else:
2347
+ ${style_struct.ident}: StyleStructRef::Borrowed(reset_style.get_${style_struct.name_lower}()),
2348
+ % endif
2349
+ % endfor
2350
+ }
2351
+ }
2352
+
2353
+ /// NOTE(emilio): This is done so we can compute relative units with respect
2354
+ /// to the parent style, but all the early properties / writing-mode / etc
2355
+ /// are already set to the right ones on the kid.
2356
+ ///
2357
+ /// Do _not_ actually call this to construct a style, this should mostly be
2358
+ /// used for animations.
2359
+ pub fn for_derived_style(
2360
+ device: &'a Device,
2361
+ stylist: Option<&'a Stylist>,
2362
+ style_to_derive_from: &'a ComputedValues,
2363
+ parent_style: Option<&'a ComputedValues>,
2364
+ ) -> Self {
2365
+ let reset_style = device.default_computed_values();
2366
+ let inherited_style = parent_style.unwrap_or(reset_style);
2367
+ let map = crate::custom_properties::ComputedSubstitutionFunctions::new(
2368
+ Some(style_to_derive_from.custom_properties().clone()),
2369
+ None,
2370
+ );
2371
+ Self {
2372
+ device,
2373
+ stylist,
2374
+ inherited_style,
2375
+ reset_style,
2376
+ pseudo: None,
2377
+ modified_reset: false,
2378
+ is_root_element: false,
2379
+ rules: None,
2380
+ attribute_references: crate::dom::AttributeReferences::default(),
2381
+ substitution_functions: map,
2382
+ invalid_non_custom_properties: LonghandIdSet::default(),
2383
+ writing_mode: style_to_derive_from.writing_mode,
2384
+ effective_zoom: style_to_derive_from.effective_zoom,
2385
+ effective_zoom_for_inheritance: Self::zoom_for_inheritance(style_to_derive_from.get_box().clone_zoom(), inherited_style),
2386
+ color_scheme: style_to_derive_from.get_inherited_ui().color_scheme_bits(),
2387
+ flags: Cell::new(style_to_derive_from.flags),
2388
+ visited_style: None,
2389
+ % for style_struct in data.active_style_structs():
2390
+ ${style_struct.ident}: StyleStructRef::Borrowed(
2391
+ style_to_derive_from.get_${style_struct.name_lower}()
2392
+ ),
2393
+ % endfor
2394
+ }
2395
+ }
2396
+
2397
+ /// Copy the reset properties from `style`.
2398
+ pub fn copy_reset_from(&mut self, style: &'a ComputedValues) {
2399
+ % for style_struct in data.active_style_structs():
2400
+ % if not style_struct.inherited:
2401
+ self.${style_struct.ident} =
2402
+ StyleStructRef::Borrowed(style.get_${style_struct.name_lower}());
2403
+ % endif
2404
+ % endfor
2405
+ }
2406
+
2407
+ % for property in data.longhands:
2408
+ % if not property.logical:
2409
+ % if not property.style_struct.inherited:
2410
+ /// Inherit `${property.ident}` from our parent style.
2411
+ #[allow(non_snake_case)]
2412
+ pub fn inherit_${property.ident}(&mut self) {
2413
+ let inherited_struct =
2414
+ self.inherited_style.get_${property.style_struct.name_lower}();
2415
+
2416
+ self.modified_reset = true;
2417
+ self.add_flags(ComputedValueFlags::INHERITS_RESET_STYLE);
2418
+
2419
+ % if property.ident == "content" or property.ident == "display":
2420
+ self.add_flags(ComputedValueFlags::DISPLAY_OR_CONTENT_DEPEND_ON_INHERITED_STYLE);
2421
+ % endif
2422
+
2423
+ if self.${property.style_struct.ident}.ptr_eq(inherited_struct) {
2424
+ return;
2425
+ }
2426
+
2427
+ self.${property.style_struct.ident}.mutate()
2428
+ .copy_${property.ident}_from(inherited_struct);
2429
+ }
2430
+ % else:
2431
+ /// Reset `${property.ident}` to the initial value.
2432
+ #[allow(non_snake_case)]
2433
+ pub fn reset_${property.ident}(&mut self) {
2434
+ let reset_struct =
2435
+ self.reset_style.get_${property.style_struct.name_lower}();
2436
+
2437
+ if self.${property.style_struct.ident}.ptr_eq(reset_struct) {
2438
+ return;
2439
+ }
2440
+
2441
+ self.${property.style_struct.ident}.mutate()
2442
+ .reset_${property.ident}(reset_struct);
2443
+ }
2444
+ % endif
2445
+
2446
+ % if not property.vector or property.vector.simple_bindings or engine == "servo":
2447
+ /// Set the `${property.ident}` to the computed value `value`.
2448
+ #[allow(non_snake_case)]
2449
+ pub fn set_${property.ident}(
2450
+ &mut self,
2451
+ value: longhands::${property.ident}::computed_value::T
2452
+ ) {
2453
+ % if not property.style_struct.inherited:
2454
+ self.modified_reset = true;
2455
+ % endif
2456
+
2457
+ self.${property.style_struct.ident}.mutate()
2458
+ .set_${property.ident}(
2459
+ value,
2460
+ % if property.logical:
2461
+ self.writing_mode,
2462
+ % endif
2463
+ );
2464
+ }
2465
+ % endif
2466
+ % endif
2467
+ % endfor
2468
+ <% del property %>
2469
+
2470
+ /// Inherits style from the parent element, accounting for the default
2471
+ /// computed values that need to be provided as well.
2472
+ pub fn for_inheritance(
2473
+ device: &'a Device,
2474
+ stylist: Option<&'a Stylist>,
2475
+ parent: Option<&'a ComputedValues>,
2476
+ pseudo: Option<&'a PseudoElement>,
2477
+ ) -> Self {
2478
+ // Rebuild the visited style from the parent, ensuring that it will also
2479
+ // not have rules. This matches the unvisited style that will be
2480
+ // produced by this builder. This assumes that the caller doesn't need
2481
+ // to adjust or process visited style, so we can just build visited
2482
+ // style here for simplicity.
2483
+ let visited_style = parent.and_then(|parent| {
2484
+ parent.visited_style().map(|style| {
2485
+ Self::for_inheritance(
2486
+ device,
2487
+ stylist,
2488
+ Some(style),
2489
+ pseudo,
2490
+ ).build()
2491
+ })
2492
+ });
2493
+ let custom_properties = if let Some(p) = parent { p.custom_properties().clone() } else { crate::custom_properties::ComputedCustomProperties::default() };
2494
+ let mut ret = Self::new(
2495
+ device,
2496
+ stylist,
2497
+ parent,
2498
+ pseudo,
2499
+ /* rules = */ None,
2500
+ /* is_root_element = */ false,
2501
+ );
2502
+ ret.substitution_functions.custom_properties = custom_properties;
2503
+ ret.visited_style = visited_style;
2504
+ ret
2505
+ }
2506
+
2507
+ /// Returns whether we have a visited style.
2508
+ pub fn has_visited_style(&self) -> bool {
2509
+ self.visited_style.is_some()
2510
+ }
2511
+
2512
+ /// Returns whether we're a pseudo-elements style.
2513
+ pub fn is_pseudo_element(&self) -> bool {
2514
+ self.pseudo.is_some_and(|p| !p.is_anon_box())
2515
+ }
2516
+
2517
+ /// Returns the style we're getting reset properties from.
2518
+ pub fn default_style(&self) -> &'a ComputedValues {
2519
+ self.reset_style
2520
+ }
2521
+
2522
+ % for style_struct in data.active_style_structs():
2523
+ /// Gets an immutable view of the current `${style_struct.name}` style.
2524
+ pub fn get_${style_struct.name_lower}(&self) -> &style_structs::${style_struct.name} {
2525
+ &self.${style_struct.ident}
2526
+ }
2527
+
2528
+ /// Gets a mutable view of the current `${style_struct.name}` style.
2529
+ pub fn mutate_${style_struct.name_lower}(&mut self) -> &mut style_structs::${style_struct.name} {
2530
+ % if not style_struct.inherited:
2531
+ self.modified_reset = true;
2532
+ % endif
2533
+ self.${style_struct.ident}.mutate()
2534
+ }
2535
+
2536
+ /// Gets a mutable view of the current `${style_struct.name}` style.
2537
+ pub fn take_${style_struct.name_lower}(&mut self) -> UniqueArc<style_structs::${style_struct.name}> {
2538
+ % if not style_struct.inherited:
2539
+ self.modified_reset = true;
2540
+ % endif
2541
+ self.${style_struct.ident}.take()
2542
+ }
2543
+
2544
+ /// Gets a mutable view of the current `${style_struct.name}` style.
2545
+ pub fn put_${style_struct.name_lower}(&mut self, s: UniqueArc<style_structs::${style_struct.name}>) {
2546
+ self.${style_struct.ident}.put(s)
2547
+ }
2548
+
2549
+ /// Gets a mutable view of the current `${style_struct.name}` style,
2550
+ /// only if it's been mutated before.
2551
+ pub fn get_${style_struct.name_lower}_if_mutated(&mut self)
2552
+ -> Option<&mut style_structs::${style_struct.name}> {
2553
+ self.${style_struct.ident}.get_if_mutated()
2554
+ }
2555
+
2556
+ /// Reset the current `${style_struct.name}` style to its default value.
2557
+ pub fn reset_${style_struct.name_lower}_struct(&mut self) {
2558
+ self.${style_struct.ident} =
2559
+ StyleStructRef::Borrowed(self.reset_style.get_${style_struct.name_lower}());
2560
+ }
2561
+ % endfor
2562
+ <% del style_struct %>
2563
+
2564
+ /// Returns whether this computed style represents a floated object.
2565
+ pub fn is_floating(&self) -> bool {
2566
+ self.get_box().clone_float().is_floating()
2567
+ }
2568
+
2569
+ /// Returns whether this computed style represents an absolutely-positioned
2570
+ /// object.
2571
+ pub fn is_absolutely_positioned(&self) -> bool {
2572
+ self.get_box().clone_position().is_absolutely_positioned()
2573
+ }
2574
+
2575
+ /// Whether this style has a top-layer style.
2576
+ #[cfg(feature = "servo")]
2577
+ pub fn in_top_layer(&self) -> bool {
2578
+ matches!(self.get_box().clone__servo_top_layer(),
2579
+ longhands::_servo_top_layer::computed_value::T::Top)
2580
+ }
2581
+
2582
+ /// Whether this style has a top-layer style.
2583
+ #[cfg(feature = "gecko")]
2584
+ pub fn in_top_layer(&self) -> bool {
2585
+ matches!(self.get_box().clone__moz_top_layer(),
2586
+ longhands::_moz_top_layer::computed_value::T::Auto)
2587
+ }
2588
+
2589
+ /// Clears the "have any reset structs been modified" flag.
2590
+ pub fn clear_modified_reset(&mut self) {
2591
+ self.modified_reset = false;
2592
+ }
2593
+
2594
+ /// Returns whether we have mutated any reset structs since the the last
2595
+ /// time `clear_modified_reset` was called.
2596
+ pub fn modified_reset(&self) -> bool {
2597
+ self.modified_reset
2598
+ }
2599
+
2600
+ /// Return the current flags.
2601
+ #[inline]
2602
+ pub fn flags(&self) -> ComputedValueFlags {
2603
+ self.flags.get()
2604
+ }
2605
+
2606
+ /// Add a flag to the current builder.
2607
+ #[inline]
2608
+ pub fn add_flags(&self, flag: ComputedValueFlags) {
2609
+ let flags = self.flags() | flag;
2610
+ self.flags.set(flags);
2611
+ }
2612
+
2613
+ /// Removes a flag to the current builder.
2614
+ #[inline]
2615
+ pub fn remove_flags(&self, flag: ComputedValueFlags) {
2616
+ let flags = self.flags() & !flag;
2617
+ self.flags.set(flags);
2618
+ }
2619
+
2620
+ /// Turns this `StyleBuilder` into a proper `ComputedValues` instance.
2621
+ pub fn build(self) -> Arc<ComputedValues> {
2622
+ ComputedValues::new(
2623
+ self.pseudo,
2624
+ self.substitution_functions.custom_properties,
2625
+ self.attribute_references,
2626
+ self.writing_mode,
2627
+ self.effective_zoom,
2628
+ self.flags.get(),
2629
+ self.rules,
2630
+ self.visited_style,
2631
+ % for style_struct in data.active_style_structs():
2632
+ self.${style_struct.ident}.build(),
2633
+ % endfor
2634
+ )
2635
+ }
2636
+
2637
+ /// Get the substitution function maps if necessary.
2638
+ pub fn substitution_functions(&self) -> &crate::custom_properties::ComputedSubstitutionFunctions {
2639
+ &self.substitution_functions
2640
+ }
2641
+
2642
+ /// Get the custom properties map if necessary.
2643
+ pub fn custom_properties(&self) -> &crate::custom_properties::ComputedCustomProperties {
2644
+ &self.substitution_functions.custom_properties
2645
+ }
2646
+
2647
+ /// Get the inherited custom properties map.
2648
+ pub fn inherited_custom_properties(&self) -> &crate::custom_properties::ComputedCustomProperties {
2649
+ &self.inherited_style.custom_properties
2650
+ }
2651
+
2652
+ // Access to various information about our inherited styles. We don't
2653
+ // expose an inherited ComputedValues directly, because in the
2654
+ // ::first-line case some of the inherited information needs to come from
2655
+ // one ComputedValues instance and some from a different one.
2656
+
2657
+ /// Inherited writing-mode.
2658
+ pub fn inherited_writing_mode(&self) -> &WritingMode {
2659
+ &self.inherited_style.writing_mode
2660
+ }
2661
+
2662
+ /// The effective zoom value that we should multiply absolute lengths by.
2663
+ pub fn effective_zoom(&self) -> computed::Zoom {
2664
+ self.effective_zoom
2665
+ }
2666
+
2667
+ /// The zoom specified on this element.
2668
+ pub fn specified_zoom(&self) -> computed::Zoom {
2669
+ self.get_box().clone_zoom()
2670
+ }
2671
+
2672
+ /// Computes effective_zoom and effective_zoom_for_inheritance based on the current style
2673
+ /// information.
2674
+ pub fn recompute_effective_zooms(&mut self) {
2675
+ let specified = self.specified_zoom();
2676
+ self.effective_zoom = self.inherited_style.effective_zoom.compute_effective(specified);
2677
+ self.effective_zoom_for_inheritance = Self::zoom_for_inheritance(specified, self.inherited_style);
2678
+ }
2679
+
2680
+ fn zoom_for_inheritance(specified: computed::Zoom, inherited_style: &ComputedValues) -> computed::Zoom {
2681
+ if specified.is_document() {
2682
+ // If our inherited effective zoom has derived to zero, there's not much we can do.
2683
+ // This value is not exposed to content anyways (it's used for scrollbars and to avoid
2684
+ // zoom affecting canvas).
2685
+ inherited_style.effective_zoom.inverted().unwrap_or(computed::Zoom::ONE)
2686
+ } else {
2687
+ specified
2688
+ }
2689
+ }
2690
+
2691
+ /// The computed value flags of our parent.
2692
+ #[inline]
2693
+ pub fn get_parent_flags(&self) -> ComputedValueFlags {
2694
+ self.inherited_style.flags
2695
+ }
2696
+
2697
+ /// Calculate the line height, given the currently resolved line-height and font.
2698
+ pub fn calc_line_height(
2699
+ &self,
2700
+ device: &Device,
2701
+ line_height_base: LineHeightBase,
2702
+ writing_mode: WritingMode,
2703
+ ) -> computed::NonNegativeLength {
2704
+ use crate::computed_value_flags::ComputedValueFlags;
2705
+ let (font, flag) = match line_height_base {
2706
+ LineHeightBase::CurrentStyle => (
2707
+ self.get_font(),
2708
+ ComputedValueFlags::DEPENDS_ON_SELF_FONT_METRICS,
2709
+ ),
2710
+ LineHeightBase::InheritedStyle => (
2711
+ self.get_parent_font(),
2712
+ ComputedValueFlags::DEPENDS_ON_INHERITED_FONT_METRICS,
2713
+ ),
2714
+ };
2715
+ let line_height = font.clone_line_height();
2716
+ if matches!(line_height, computed::LineHeight::Normal) {
2717
+ self.add_flags(flag);
2718
+ }
2719
+ let lh = device.calc_line_height(font, writing_mode, None);
2720
+ if line_height_base == LineHeightBase::InheritedStyle {
2721
+ // Apply our own zoom if our style source is the parent style.
2722
+ computed::NonNegativeLength::new(self.effective_zoom_for_inheritance.zoom(lh.px()))
2723
+ } else {
2724
+ lh
2725
+ }
2726
+ }
2727
+
2728
+ /// And access to inherited style structs.
2729
+ % for style_struct in data.active_style_structs():
2730
+ /// Gets our inherited `${style_struct.name}`. We don't name these
2731
+ /// accessors `inherited_${style_struct.name_lower}` because we already
2732
+ /// have things like "box" vs "inherited_box" as struct names. Do the
2733
+ /// next-best thing and call them `parent_${style_struct.name_lower}`
2734
+ /// instead.
2735
+ pub fn get_parent_${style_struct.name_lower}(&self) -> &style_structs::${style_struct.name} {
2736
+ self.inherited_style.get_${style_struct.name_lower}()
2737
+ }
2738
+ % endfor
2739
+ }
2740
+
2741
+ /// A per-longhand function that performs the CSS cascade for that longhand.
2742
+ pub type CascadePropertyFn =
2743
+ unsafe extern "Rust" fn(
2744
+ declaration: &PropertyDeclaration,
2745
+ context: &mut computed::Context,
2746
+ );
2747
+
2748
+ /// A per-longhand array of functions to perform the CSS cascade on each of
2749
+ /// them, effectively doing virtual dispatch.
2750
+ pub static CASCADE_PROPERTY: [CascadePropertyFn; property_counts::LONGHANDS] = [
2751
+ % for property in data.longhands:
2752
+ longhands::${property.ident}::cascade_property,
2753
+ % endfor
2754
+ ];
2755
+
2756
+ /// An identifier for a given alias property.
2757
+ #[derive(Clone, Copy, Eq, PartialEq, MallocSizeOf)]
2758
+ #[repr(u16)]
2759
+ pub enum AliasId {
2760
+ % for i, property in enumerate(data.all_aliases()):
2761
+ /// ${property.name}
2762
+ ${property.camel_case} = ${i},
2763
+ % endfor
2764
+ }
2765
+
2766
+ impl fmt::Debug for AliasId {
2767
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2768
+ let name = NonCustomPropertyId::from(*self).name();
2769
+ formatter.write_str(name)
2770
+ }
2771
+ }
2772
+
2773
+ impl AliasId {
2774
+ /// Returns the property we're aliasing, as a longhand or a shorthand.
2775
+ #[inline]
2776
+ pub fn aliased_property(self) -> NonCustomPropertyId {
2777
+ static MAP: [NonCustomPropertyId; property_counts::ALIASES] = [
2778
+ % for alias in data.all_aliases():
2779
+ % if alias.original.type() == "longhand":
2780
+ NonCustomPropertyId::from_longhand(LonghandId::${alias.original.camel_case}),
2781
+ % else:
2782
+ <% assert alias.original.type() == "shorthand" %>
2783
+ NonCustomPropertyId::from_shorthand(ShorthandId::${alias.original.camel_case}),
2784
+ % endif
2785
+ % endfor
2786
+ ];
2787
+ MAP[self as usize]
2788
+ }
2789
+ }
2790
+
2791
+ /// Call the given macro with tokens like this for each longhand and shorthand properties
2792
+ /// that is enabled in content:
2793
+ ///
2794
+ /// ```
2795
+ /// [CamelCaseName, SetCamelCaseName, PropertyId::Longhand(LonghandId::CamelCaseName)],
2796
+ /// ```
2797
+ ///
2798
+ /// NOTE(emilio): Callers are responsible to deal with prefs.
2799
+ #[macro_export]
2800
+ macro_rules! css_properties_accessors {
2801
+ ($macro_name: ident) => {
2802
+ $macro_name! {
2803
+ % for kind, props in [("Longhand", data.longhands), ("Shorthand", data.shorthands)]:
2804
+ % for property in props:
2805
+ % if property.enabled_in_content():
2806
+ % for prop in [property] + property.aliases:
2807
+ % if '-' in prop.name:
2808
+ [${prop.ident.capitalize()}, Set${prop.ident.capitalize()},
2809
+ PropertyId::NonCustom(${kind}Id::${property.camel_case}.into())],
2810
+ % endif
2811
+ [${prop.camel_case}, Set${prop.camel_case},
2812
+ PropertyId::NonCustom(${kind}Id::${property.camel_case}.into())],
2813
+ % endfor
2814
+ % endif
2815
+ % endfor
2816
+ % endfor
2817
+ }
2818
+ }
2819
+ }
2820
+
2821
+ /// Call the given macro with tokens like this for each longhand properties:
2822
+ ///
2823
+ /// ```
2824
+ /// { snake_case_ident }
2825
+ /// ```
2826
+ #[macro_export]
2827
+ macro_rules! longhand_properties_idents {
2828
+ ($macro_name: ident) => {
2829
+ $macro_name! {
2830
+ % for property in data.longhands:
2831
+ { ${property.ident} }
2832
+ % endfor
2833
+ }
2834
+ }
2835
+ }
2836
+
2837
+ // Large pages generate tens of thousands of ComputedValues.
2838
+ #[cfg(feature = "gecko")]
2839
+ size_of_test!(ComputedValues, 248);
2840
+ #[cfg(feature = "servo")]
2841
+ size_of_test!(ComputedValues, 232);
2842
+
2843
+ // FFI relies on this.
2844
+ size_of_test!(Option<Arc<ComputedValues>>, 8);
2845
+
2846
+ // There are two reasons for this test to fail:
2847
+ //
2848
+ // * Your changes made a specified value type for a given property go
2849
+ // over the threshold. In that case, you should try to shrink it again
2850
+ // or, if not possible, mark the property as boxed in the property
2851
+ // definition.
2852
+ //
2853
+ // * Your changes made a specified value type smaller, so that it no
2854
+ // longer needs to be boxed. In this case you just need to remove
2855
+ // boxed=True from the property definition. Nice job!
2856
+ #[cfg(target_pointer_width = "64")]
2857
+ #[allow(dead_code)] // https://github.com/rust-lang/rust/issues/96952
2858
+ const BOX_THRESHOLD: usize = 24;
2859
+ % for longhand in data.longhands:
2860
+ #[cfg(target_pointer_width = "64")]
2861
+ % if longhand.boxed:
2862
+ const_assert!(std::mem::size_of::<longhands::${longhand.ident}::SpecifiedValue>() > BOX_THRESHOLD);
2863
+ % else:
2864
+ const_assert!(std::mem::size_of::<longhands::${longhand.ident}::SpecifiedValue>() <= BOX_THRESHOLD);
2865
+ % endif
2866
+ % endfor
2867
+
2868
+ % if engine == "servo":
2869
+ % for effect_name in ["repaint", "recalculate_overflow", "rebuild_stacking_context", "rebuild_box"]:
2870
+ pub(crate) fn restyle_damage_${effect_name} (old: &ComputedValues, new: &ComputedValues) -> bool {
2871
+ % for style_struct in data.active_style_structs():
2872
+ <% longhands_affected = [effect_name in longhand.servo_restyle_damage.split() for longhand in style_struct.longhands if not longhand.logical] %>
2873
+ % if any(longhands_affected):
2874
+ let old_${style_struct.name_lower} = old.get_${style_struct.name_lower}();
2875
+ let new_${style_struct.name_lower} = new.get_${style_struct.name_lower}();
2876
+ if !std::ptr::eq(old_${style_struct.name_lower}, new_${style_struct.name_lower}) {
2877
+ if
2878
+ % for longhand in style_struct.longhands:
2879
+ % if effect_name in longhand.servo_restyle_damage.split() and not longhand.logical:
2880
+ old_${style_struct.name_lower}.${longhand.ident} != new_${style_struct.name_lower}.${longhand.ident} ||
2881
+ % endif
2882
+ % endfor
2883
+ false {
2884
+ return true;
2885
+ }
2886
+ }
2887
+ % endif
2888
+ % endfor
2889
+ false
2890
+ }
2891
+ % endfor
2892
+ % endif
2893
+
2894
+ ## Descriptor types for @-rules like @font-face and @counter-style.
2895
+ <%def name="generate_descriptors(descriptors)">
2896
+ use super::*;
2897
+ #[allow(unused_imports)]
2898
+ use crate::values::specified;
2899
+
2900
+ /// Descriptor identifier.
2901
+ #[derive(Clone, Copy, Debug, Eq, Hash, FromPrimitive, Parse, PartialEq)]
2902
+ #[repr(u8)]
2903
+ pub enum DescriptorId {
2904
+ % for descriptor in descriptors:
2905
+ /// The "${descriptor.name}" descriptor.
2906
+ % if descriptor.aliases:
2907
+ #[parse(aliases="${','.join(descriptor.aliases)}")]
2908
+ % endif
2909
+ ${descriptor.camel_case},
2910
+ % endfor
2911
+ }
2912
+
2913
+ impl DescriptorId {
2914
+ /// The total number of descriptors.
2915
+ pub const COUNT: usize = ${len(descriptors)};
2916
+
2917
+ /// The CSS name of this descriptor.
2918
+ pub fn name(&self) -> &'static str {
2919
+ const NAMES: [&str; DescriptorId::COUNT] = [
2920
+ % for descriptor in descriptors:
2921
+ "${descriptor.name}",
2922
+ % endfor
2923
+ ];
2924
+ NAMES[*self as usize]
2925
+ }
2926
+ }
2927
+
2928
+ /// All descriptor values.
2929
+ #[derive(Clone, Debug, Default, ToShmem, PartialEq, MallocSizeOf)]
2930
+ pub struct Descriptors {
2931
+ % for descriptor in descriptors:
2932
+ /// The "${descriptor.name}" descriptor value.
2933
+ % if descriptor.ignore_malloc_size_of:
2934
+ #[ignore_malloc_size_of = "${descriptor.ignore_malloc_size_of}"]
2935
+ % endif
2936
+ pub ${descriptor.ident}: Option<${descriptor.type}>,
2937
+ % endfor
2938
+ }
2939
+
2940
+ impl Descriptors {
2941
+ /// Gets a descriptor in CSS syntax.
2942
+ pub fn get(&self, id: DescriptorId, dest: &mut CssStringWriter) -> fmt::Result {
2943
+ let mut dest = CssWriter::new(dest);
2944
+ match id {
2945
+ % for descriptor in descriptors:
2946
+ DescriptorId::${descriptor.camel_case} => self.${descriptor.ident}.to_css(&mut dest),
2947
+ % endfor
2948
+ }
2949
+ }
2950
+
2951
+ /// Parses a given descriptor. Returns whether the descriptor changed.
2952
+ pub fn set(&mut self, id: DescriptorId, context: &ParserContext, input: &mut Parser) -> Result<bool, ParseError> {
2953
+ use crate::parser::Parse;
2954
+ // DeclarationParser also calls parse_entirely so we’d normally not need to, but in this
2955
+ // case we do because we set the value as a side effect rather than returning it.
2956
+ match id {
2957
+ % for descriptor in descriptors:
2958
+ DescriptorId::${descriptor.camel_case} => {
2959
+ let value = Some(input.parse_entirely(|i|
2960
+ % if descriptor.parser:
2961
+ ${descriptor.type}::${descriptor.parser}(context, i)
2962
+ % else:
2963
+ Parse::parse(context, i)
2964
+ % endif
2965
+ )?);
2966
+ let change = self.${descriptor.ident} != value;
2967
+ self.${descriptor.ident} = value;
2968
+ Ok(change)
2969
+ },
2970
+ % endfor
2971
+ }
2972
+ }
2973
+
2974
+ /// Removes a descriptor. Returns true if it used to be set.
2975
+ pub fn remove(&mut self, id: DescriptorId) -> bool {
2976
+ match id {
2977
+ % for descriptor in descriptors:
2978
+ DescriptorId::${descriptor.camel_case} => self.${descriptor.ident}.take().is_some(),
2979
+ % endfor
2980
+ }
2981
+ }
2982
+
2983
+ /// Returns the count of set descriptors.
2984
+ pub fn len(&self) -> usize {
2985
+ let mut count = 0;
2986
+ % for descriptor in descriptors:
2987
+ if self.${descriptor.ident}.is_some() {
2988
+ count += 1;
2989
+ }
2990
+ % endfor
2991
+ count
2992
+ }
2993
+
2994
+ /// Returns the descriptor at position `i`.
2995
+ pub fn at(&self, i: usize) -> Option<DescriptorId> {
2996
+ let mut cur = 0;
2997
+ % for descriptor in descriptors:
2998
+ if self.${descriptor.ident}.is_some() {
2999
+ if cur == i {
3000
+ return Some(DescriptorId::${descriptor.camel_case});
3001
+ }
3002
+ cur += 1;
3003
+ }
3004
+ % endfor
3005
+ let _ = cur; // Silences warning on the last descriptor
3006
+ None
3007
+ }
3008
+ }
3009
+
3010
+ impl ToCss for Descriptors {
3011
+ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
3012
+ where
3013
+ W: fmt::Write,
3014
+ {
3015
+ use std::fmt::Write;
3016
+ % for descriptor in descriptors:
3017
+ if let Some(ref value) = self.${descriptor.ident} {
3018
+ dest.write_str("${descriptor.name}: ")?;
3019
+ value.to_css(dest)?;
3020
+ dest.write_str("; ")?;
3021
+ }
3022
+ % endfor
3023
+ Ok(())
3024
+ }
3025
+ }
3026
+
3027
+ /// Parser for descriptor declarations in at-rules.
3028
+ pub struct DescriptorParser<'a, 'b: 'a> {
3029
+ /// The parser context.
3030
+ pub context: &'a ParserContext<'b>,
3031
+ /// The descriptors to parse into.
3032
+ pub descriptors: &'a mut Descriptors,
3033
+ }
3034
+
3035
+ impl<'a, 'b, 'i> cssparser::AtRuleParser<'i> for DescriptorParser<'a, 'b> {
3036
+ type Prelude = ();
3037
+ type AtRule = ();
3038
+ type Error = StyleParseErrorKind;
3039
+ }
3040
+
3041
+ impl<'a, 'b, 'i> cssparser::QualifiedRuleParser<'i> for DescriptorParser<'a, 'b> {
3042
+ type Prelude = ();
3043
+ type QualifiedRule = ();
3044
+ type Error = StyleParseErrorKind;
3045
+ }
3046
+
3047
+ impl<'a, 'b, 'i> cssparser::RuleBodyItemParser<'i, (), StyleParseErrorKind>
3048
+ for DescriptorParser<'a, 'b>
3049
+ {
3050
+ fn parse_qualified(&self) -> bool {
3051
+ false
3052
+ }
3053
+ fn parse_declarations(&self) -> bool {
3054
+ true
3055
+ }
3056
+ }
3057
+
3058
+ impl<'a, 'b, 'i> cssparser::DeclarationParser<'i> for DescriptorParser<'a, 'b> {
3059
+ type Declaration = ();
3060
+ type Error = StyleParseErrorKind;
3061
+
3062
+ fn parse_value(
3063
+ &mut self,
3064
+ name: cssparser::CowRcStr<'i>,
3065
+ input: &mut Parser<'i>,
3066
+ _declaration_start: &cssparser::ParserState,
3067
+ ) -> Result<(), ParseError> {
3068
+ let Ok(id) = DescriptorId::from_ident(name.as_ref()) else {
3069
+ return Err(
3070
+ ParseError::custom(
3071
+ selectors::parser::SelectorParseErrorKind::UnexpectedIdent
3072
+ )
3073
+ );
3074
+ };
3075
+ self.descriptors.set(id, self.context, input)?;
3076
+ Ok(())
3077
+ }
3078
+ }
3079
+ </%def>
3080
+
3081
+ /// Generated code for @font-face descriptors.
3082
+ pub mod font_face {
3083
+ use crate::font_face::*;
3084
+ ${generate_descriptors(data.font_face_descriptors)}
3085
+ }
3086
+
3087
+ /// Generated code for @counter-style descriptors.
3088
+ pub mod counter_style {
3089
+ use crate::counter_style::*;
3090
+ ${generate_descriptors(data.counter_style_descriptors)}
3091
+ }
3092
+
3093
+ /// Generated code for @property descriptors.
3094
+ pub mod property {
3095
+ use crate::properties_and_values::rule::*;
3096
+ ${generate_descriptors(data.property_descriptors)}
3097
+ }
3098
+
3099
+ /// Generated code for @view-transition descriptors.
3100
+ pub mod view_transition {
3101
+ use crate::stylesheets::view_transition_rule::*;
3102
+ ${generate_descriptors(data.view_transition_descriptors)}
3103
+ }