blitz-pdf 0.0.0-stage → 0.1.0

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 +355 -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,2024 @@
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
+ //! [Length values][length].
6
+ //!
7
+ //! [length]: https://drafts.csswg.org/css-values/#lengths
8
+
9
+ use super::{AllowQuirks, Number, ToComputedValue};
10
+ use crate::computed_value_flags::ComputedValueFlags;
11
+ use crate::derives::*;
12
+ use crate::font_metrics::{FontMetrics, FontMetricsOrientation};
13
+ #[cfg(feature = "gecko")]
14
+ use crate::gecko_bindings::structs::GeckoFontMetrics;
15
+ use crate::parser::{Parse, ParserContext};
16
+ use crate::typed_om::{NumericType, NumericValue, ToTyped, TypedValue, UnitValue};
17
+ use crate::values::computed::{self, CSSPixelLength, Context, FontSize};
18
+ use crate::values::generics::length as generics;
19
+ use crate::values::generics::length::{
20
+ GenericAnchorSizeFunction, GenericLengthOrNumber, GenericLengthPercentageOrNormal,
21
+ GenericMargin, GenericMaxSize, GenericSize,
22
+ };
23
+ use crate::values::generics::NonNegative;
24
+ use crate::values::specified::calc::{
25
+ AllowAnchorPositioningFunctions, CalcLengthPercentage, CalcNode, PercentageContext,
26
+ };
27
+ use crate::values::specified::font::QueryFontMetricsFlags;
28
+ use crate::values::specified::percentage::NoCalcPercentage;
29
+ use crate::values::specified::NonNegativeNumber;
30
+ use crate::values::tagged_numeric::{Extracted, NumericUnion, Unpacked};
31
+ use crate::values::CSSFloat;
32
+ use crate::{Zero, ZeroNoPercent};
33
+ use app_units::AU_PER_PX;
34
+ use cssparser::{match_ignore_ascii_case, Parser, Token};
35
+ use std::cmp;
36
+ use std::fmt::{self, Write};
37
+ use style_traits::values::specified::AllowedNumericType;
38
+ use style_traits::{
39
+ CssString, CssWriter, ParseError, ParsingMode, SpecifiedValueInfo, StyleParseErrorKind, ToCss,
40
+ };
41
+ use thin_vec::ThinVec;
42
+
43
+ pub use super::image::Image;
44
+ pub use super::image::{EndingShape as GradientEndingShape, Gradient};
45
+
46
+ /// Number of pixels per inch
47
+ pub const PX_PER_IN: CSSFloat = 96.;
48
+ /// Number of pixels per centimeter
49
+ pub const PX_PER_CM: CSSFloat = PX_PER_IN / 2.54;
50
+ /// Number of pixels per millimeter
51
+ pub const PX_PER_MM: CSSFloat = PX_PER_IN / 25.4;
52
+ /// Number of pixels per quarter
53
+ pub const PX_PER_Q: CSSFloat = PX_PER_MM / 4.;
54
+ /// Number of pixels per point
55
+ pub const PX_PER_PT: CSSFloat = PX_PER_IN / 72.;
56
+ /// Number of pixels per pica
57
+ pub const PX_PER_PC: CSSFloat = PX_PER_PT * 12.;
58
+
59
+ /// The unit of a `<length>` value. Note that if any new font-relative value is
60
+ /// added here, `custom_properties::NonCustomReferences::from_unit`
61
+ /// must also be updated. Consult the comment in that function as to why.
62
+ ///
63
+ /// The variants are grouped (absolute, font-relative, viewport, container,
64
+ /// servo-internal) so that `is_*` predicates can be implemented with simple
65
+ /// range checks.
66
+ #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, ToShmem)]
67
+ #[repr(u8)]
68
+ #[allow(missing_docs)]
69
+ pub enum LengthUnit {
70
+ // Absolute lengths.
71
+ Px,
72
+ In,
73
+ Cm,
74
+ Mm,
75
+ Q,
76
+ Pt,
77
+ Pc,
78
+ // Font-relative lengths.
79
+ Em,
80
+ Ex,
81
+ Rex,
82
+ Ch,
83
+ Rch,
84
+ Cap,
85
+ Rcap,
86
+ Ic,
87
+ Ric,
88
+ Rem,
89
+ Lh,
90
+ Rlh,
91
+ // Viewport-percentage lengths.
92
+ Vw,
93
+ Svw,
94
+ Lvw,
95
+ Dvw,
96
+ Vh,
97
+ Svh,
98
+ Lvh,
99
+ Dvh,
100
+ Vmin,
101
+ Svmin,
102
+ Lvmin,
103
+ Dvmin,
104
+ Vmax,
105
+ Svmax,
106
+ Lvmax,
107
+ Dvmax,
108
+ Vb,
109
+ Svb,
110
+ Lvb,
111
+ Dvb,
112
+ Vi,
113
+ Svi,
114
+ Lvi,
115
+ Dvi,
116
+ // Container-relative lengths.
117
+ Cqw,
118
+ Cqh,
119
+ Cqi,
120
+ Cqb,
121
+ Cqmin,
122
+ Cqmax,
123
+ /// HTML5 "character width", as defined in HTML5 § 14.5.4. Internal-only.
124
+ ServoCharacterWidth,
125
+ }
126
+
127
+ impl LengthUnit {
128
+ /// Returns the length unit for the given string.
129
+ #[inline]
130
+ pub fn from_str(unit: &str) -> Result<Self, ()> {
131
+ Self::from_str_with_flags(ParsingMode::DEFAULT, /* in_page_rule = */ false, unit)
132
+ }
133
+
134
+ /// Returns the length unit for the given flags and string.
135
+ #[inline]
136
+ pub fn from_str_with_flags(
137
+ parsing_mode: ParsingMode,
138
+ in_page_rule: bool,
139
+ unit: &str,
140
+ ) -> Result<Self, ()> {
141
+ let allows_computational_dependence = parsing_mode.allows_computational_dependence();
142
+
143
+ Ok(match_ignore_ascii_case! { unit,
144
+ "px" => Self::Px,
145
+ "in" => Self::In,
146
+ "cm" => Self::Cm,
147
+ "mm" => Self::Mm,
148
+ "q" => Self::Q,
149
+ "pt" => Self::Pt,
150
+ "pc" => Self::Pc,
151
+ // font-relative
152
+ "em" if allows_computational_dependence => Self::Em,
153
+ "ex" if allows_computational_dependence => Self::Ex,
154
+ "rex" if allows_computational_dependence => Self::Rex,
155
+ "ch" if allows_computational_dependence => Self::Ch,
156
+ "rch" if allows_computational_dependence => Self::Rch,
157
+ "cap" if allows_computational_dependence => Self::Cap,
158
+ "rcap" if allows_computational_dependence => Self::Rcap,
159
+ "ic" if allows_computational_dependence => Self::Ic,
160
+ "ric" if allows_computational_dependence => Self::Ric,
161
+ "rem" if allows_computational_dependence => Self::Rem,
162
+ "lh" if allows_computational_dependence => Self::Lh,
163
+ "rlh" if allows_computational_dependence => Self::Rlh,
164
+ // viewport percentages
165
+ "vw" if !in_page_rule => Self::Vw,
166
+ "svw" if !in_page_rule => Self::Svw,
167
+ "lvw" if !in_page_rule => Self::Lvw,
168
+ "dvw" if !in_page_rule => Self::Dvw,
169
+ "vh" if !in_page_rule => Self::Vh,
170
+ "svh" if !in_page_rule => Self::Svh,
171
+ "lvh" if !in_page_rule => Self::Lvh,
172
+ "dvh" if !in_page_rule => Self::Dvh,
173
+ "vmin" if !in_page_rule => Self::Vmin,
174
+ "svmin" if !in_page_rule => Self::Svmin,
175
+ "lvmin" if !in_page_rule => Self::Lvmin,
176
+ "dvmin" if !in_page_rule => Self::Dvmin,
177
+ "vmax" if !in_page_rule => Self::Vmax,
178
+ "svmax" if !in_page_rule => Self::Svmax,
179
+ "lvmax" if !in_page_rule => Self::Lvmax,
180
+ "dvmax" if !in_page_rule => Self::Dvmax,
181
+ "vb" if !in_page_rule => Self::Vb,
182
+ "svb" if !in_page_rule => Self::Svb,
183
+ "lvb" if !in_page_rule => Self::Lvb,
184
+ "dvb" if !in_page_rule => Self::Dvb,
185
+ "vi" if !in_page_rule => Self::Vi,
186
+ "svi" if !in_page_rule => Self::Svi,
187
+ "lvi" if !in_page_rule => Self::Lvi,
188
+ "dvi" if !in_page_rule => Self::Dvi,
189
+ // Container query lengths. Inherit the limitation from viewport units since
190
+ // we may fall back to them.
191
+ "cqw" if !in_page_rule && cfg!(feature = "gecko") => Self::Cqw,
192
+ "cqh" if !in_page_rule && cfg!(feature = "gecko") => Self::Cqh,
193
+ "cqi" if !in_page_rule && cfg!(feature = "gecko") => Self::Cqi,
194
+ "cqb" if !in_page_rule && cfg!(feature = "gecko") => Self::Cqb,
195
+ "cqmin" if !in_page_rule && cfg!(feature = "gecko") => Self::Cqmin,
196
+ "cqmax" if !in_page_rule && cfg!(feature = "gecko") => Self::Cqmax,
197
+ _ => return Err(()),
198
+ })
199
+ }
200
+
201
+ /// Returns this unit as a string.
202
+ #[inline]
203
+ pub fn as_str(self) -> &'static str {
204
+ match self {
205
+ Self::Px => "px",
206
+ Self::In => "in",
207
+ Self::Cm => "cm",
208
+ Self::Mm => "mm",
209
+ Self::Q => "q",
210
+ Self::Pt => "pt",
211
+ Self::Pc => "pc",
212
+ Self::Em => NoCalcLength::EM,
213
+ Self::Ex => NoCalcLength::EX,
214
+ Self::Rex => NoCalcLength::REX,
215
+ Self::Ch => NoCalcLength::CH,
216
+ Self::Rch => NoCalcLength::RCH,
217
+ Self::Cap => NoCalcLength::CAP,
218
+ Self::Rcap => NoCalcLength::RCAP,
219
+ Self::Ic => NoCalcLength::IC,
220
+ Self::Ric => NoCalcLength::RIC,
221
+ Self::Rem => NoCalcLength::REM,
222
+ Self::Lh => NoCalcLength::LH,
223
+ Self::Rlh => NoCalcLength::RLH,
224
+ Self::Vw => "vw",
225
+ Self::Svw => "svw",
226
+ Self::Lvw => "lvw",
227
+ Self::Dvw => "dvw",
228
+ Self::Vh => "vh",
229
+ Self::Svh => "svh",
230
+ Self::Lvh => "lvh",
231
+ Self::Dvh => "dvh",
232
+ Self::Vmin => "vmin",
233
+ Self::Svmin => "svmin",
234
+ Self::Lvmin => "lvmin",
235
+ Self::Dvmin => "dvmin",
236
+ Self::Vmax => "vmax",
237
+ Self::Svmax => "svmax",
238
+ Self::Lvmax => "lvmax",
239
+ Self::Dvmax => "dvmax",
240
+ Self::Vb => "vb",
241
+ Self::Svb => "svb",
242
+ Self::Lvb => "lvb",
243
+ Self::Dvb => "dvb",
244
+ Self::Vi => "vi",
245
+ Self::Svi => "svi",
246
+ Self::Lvi => "lvi",
247
+ Self::Dvi => "dvi",
248
+ Self::Cqw => "cqw",
249
+ Self::Cqh => "cqh",
250
+ Self::Cqi => "cqi",
251
+ Self::Cqb => "cqb",
252
+ Self::Cqmin => "cqmin",
253
+ Self::Cqmax => "cqmax",
254
+ Self::ServoCharacterWidth => "",
255
+ }
256
+ }
257
+
258
+ /// Whether this is an absolute length unit (px, in, cm, mm, q, pt, pc).
259
+ #[inline]
260
+ pub fn is_absolute(self) -> bool {
261
+ matches!(
262
+ self,
263
+ Self::Px | Self::In | Self::Cm | Self::Mm | Self::Q | Self::Pt | Self::Pc
264
+ )
265
+ }
266
+
267
+ /// Whether this is a font-relative unit.
268
+ #[inline]
269
+ pub fn is_font_relative(self) -> bool {
270
+ matches!(
271
+ self,
272
+ Self::Em
273
+ | Self::Ex
274
+ | Self::Rex
275
+ | Self::Ch
276
+ | Self::Rch
277
+ | Self::Cap
278
+ | Self::Rcap
279
+ | Self::Ic
280
+ | Self::Ric
281
+ | Self::Rem
282
+ | Self::Lh
283
+ | Self::Rlh
284
+ )
285
+ }
286
+
287
+ /// Whether this is a viewport-percentage unit.
288
+ #[inline]
289
+ pub fn is_viewport_percentage(self) -> bool {
290
+ matches!(
291
+ self,
292
+ Self::Vw
293
+ | Self::Svw
294
+ | Self::Lvw
295
+ | Self::Dvw
296
+ | Self::Vh
297
+ | Self::Svh
298
+ | Self::Lvh
299
+ | Self::Dvh
300
+ | Self::Vmin
301
+ | Self::Svmin
302
+ | Self::Lvmin
303
+ | Self::Dvmin
304
+ | Self::Vmax
305
+ | Self::Svmax
306
+ | Self::Lvmax
307
+ | Self::Dvmax
308
+ | Self::Vb
309
+ | Self::Svb
310
+ | Self::Lvb
311
+ | Self::Dvb
312
+ | Self::Vi
313
+ | Self::Svi
314
+ | Self::Lvi
315
+ | Self::Dvi
316
+ )
317
+ }
318
+
319
+ /// Whether this is a container-relative unit.
320
+ #[inline]
321
+ pub fn is_container_relative(self) -> bool {
322
+ matches!(
323
+ self,
324
+ Self::Cqw | Self::Cqh | Self::Cqi | Self::Cqb | Self::Cqmin | Self::Cqmax
325
+ )
326
+ }
327
+
328
+ /// Returns the sort key for this unit. Must not be called for the internal
329
+ /// `ServoCharacterWidth` unit.
330
+ fn sort_key(self) -> crate::values::generics::calc::SortKey {
331
+ use crate::values::generics::calc::SortKey;
332
+ match self {
333
+ Self::Px | Self::In | Self::Cm | Self::Mm | Self::Q | Self::Pt | Self::Pc => {
334
+ SortKey::Px
335
+ },
336
+ Self::Em => SortKey::Em,
337
+ Self::Ex => SortKey::Ex,
338
+ Self::Rex => SortKey::Rex,
339
+ Self::Ch => SortKey::Ch,
340
+ Self::Rch => SortKey::Rch,
341
+ Self::Cap => SortKey::Cap,
342
+ Self::Rcap => SortKey::Rcap,
343
+ Self::Ic => SortKey::Ic,
344
+ Self::Ric => SortKey::Ric,
345
+ Self::Rem => SortKey::Rem,
346
+ Self::Lh => SortKey::Lh,
347
+ Self::Rlh => SortKey::Rlh,
348
+ Self::Vw => SortKey::Vw,
349
+ Self::Svw => SortKey::Svw,
350
+ Self::Lvw => SortKey::Lvw,
351
+ Self::Dvw => SortKey::Dvw,
352
+ Self::Vh => SortKey::Vh,
353
+ Self::Svh => SortKey::Svh,
354
+ Self::Lvh => SortKey::Lvh,
355
+ Self::Dvh => SortKey::Dvh,
356
+ Self::Vmin => SortKey::Vmin,
357
+ Self::Svmin => SortKey::Svmin,
358
+ Self::Lvmin => SortKey::Lvmin,
359
+ Self::Dvmin => SortKey::Dvmin,
360
+ Self::Vmax => SortKey::Vmax,
361
+ Self::Svmax => SortKey::Svmax,
362
+ Self::Lvmax => SortKey::Lvmax,
363
+ Self::Dvmax => SortKey::Dvmax,
364
+ Self::Vb => SortKey::Vb,
365
+ Self::Svb => SortKey::Svb,
366
+ Self::Lvb => SortKey::Lvb,
367
+ Self::Dvb => SortKey::Dvb,
368
+ Self::Vi => SortKey::Vi,
369
+ Self::Svi => SortKey::Svi,
370
+ Self::Lvi => SortKey::Lvi,
371
+ Self::Dvi => SortKey::Dvi,
372
+ Self::Cqw => SortKey::Cqw,
373
+ Self::Cqh => SortKey::Cqh,
374
+ Self::Cqi => SortKey::Cqi,
375
+ Self::Cqb => SortKey::Cqb,
376
+ Self::Cqmin => SortKey::Cqmin,
377
+ Self::Cqmax => SortKey::Cqmax,
378
+ Self::ServoCharacterWidth => unreachable!(),
379
+ }
380
+ }
381
+ }
382
+
383
+ /// A source to resolve font-relative units against
384
+ #[derive(Clone, Copy, Debug, PartialEq)]
385
+ pub enum FontBaseSize {
386
+ /// Use the font-size of the current element.
387
+ CurrentStyle,
388
+ /// Use the inherited font-size.
389
+ InheritedStyle,
390
+ }
391
+
392
+ /// A source to resolve font-relative line-height units against.
393
+ #[derive(Clone, Copy, Debug, PartialEq)]
394
+ pub enum LineHeightBase {
395
+ /// Use the line-height of the current element.
396
+ CurrentStyle,
397
+ /// Use the inherited line-height.
398
+ InheritedStyle,
399
+ }
400
+
401
+ impl FontBaseSize {
402
+ /// Calculate the actual size for a given context
403
+ pub fn resolve(&self, context: &Context) -> computed::FontSize {
404
+ let style = context.style();
405
+ match *self {
406
+ Self::CurrentStyle => style.get_font().clone_font_size(),
407
+ Self::InheritedStyle => {
408
+ // If we're using the size from our inherited style, we still need to apply our
409
+ // own zoom.
410
+ let zoom = style.effective_zoom_for_inheritance;
411
+ style.get_parent_font().clone_font_size().zoom(zoom)
412
+ },
413
+ }
414
+ }
415
+ }
416
+
417
+ /// https://drafts.csswg.org/css-values/#viewport-variants
418
+ pub enum ViewportVariant {
419
+ /// https://drafts.csswg.org/css-values/#ua-default-viewport-size
420
+ UADefault,
421
+ /// https://drafts.csswg.org/css-values/#small-viewport-percentage-units
422
+ Small,
423
+ /// https://drafts.csswg.org/css-values/#large-viewport-percentage-units
424
+ Large,
425
+ /// https://drafts.csswg.org/css-values/#dynamic-viewport-percentage-units
426
+ Dynamic,
427
+ }
428
+
429
+ /// https://drafts.csswg.org/css-values/#viewport-relative-units
430
+ #[derive(PartialEq)]
431
+ enum ViewportUnit {
432
+ /// *vw units.
433
+ Vw,
434
+ /// *vh units.
435
+ Vh,
436
+ /// *vmin units.
437
+ Vmin,
438
+ /// *vmax units.
439
+ Vmax,
440
+ /// *vb units.
441
+ Vb,
442
+ /// *vi units.
443
+ Vi,
444
+ }
445
+
446
+ /// A `<length>` without taking `calc` expressions into account
447
+ ///
448
+ /// <https://drafts.csswg.org/css-values/#lengths>
449
+ #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToShmem)]
450
+ #[repr(C)]
451
+ pub struct NoCalcLength {
452
+ unit: LengthUnit,
453
+ value: CSSFloat,
454
+ }
455
+
456
+ impl NoCalcLength {
457
+ /// Unit identifier for `em`.
458
+ pub const EM: &'static str = "em";
459
+ /// Unit identifier for `ex`.
460
+ pub const EX: &'static str = "ex";
461
+ /// Unit identifier for `rex`.
462
+ pub const REX: &'static str = "rex";
463
+ /// Unit identifier for `ch`.
464
+ pub const CH: &'static str = "ch";
465
+ /// Unit identifier for `rch`.
466
+ pub const RCH: &'static str = "rch";
467
+ /// Unit identifier for `cap`.
468
+ pub const CAP: &'static str = "cap";
469
+ /// Unit identifier for `rcap`.
470
+ pub const RCAP: &'static str = "rcap";
471
+ /// Unit identifier for `ic`.
472
+ pub const IC: &'static str = "ic";
473
+ /// Unit identifier for `ric`.
474
+ pub const RIC: &'static str = "ric";
475
+ /// Unit identifier for `rem`.
476
+ pub const REM: &'static str = "rem";
477
+ /// Unit identifier for `lh`.
478
+ pub const LH: &'static str = "lh";
479
+ /// Unit identifier for `rlh`.
480
+ pub const RLH: &'static str = "rlh";
481
+
482
+ /// Creates a length with the given unit and value.
483
+ #[inline]
484
+ pub fn new(unit: LengthUnit, value: CSSFloat) -> Self {
485
+ Self { unit, value }
486
+ }
487
+
488
+ /// Returns the unit of this length.
489
+ #[inline]
490
+ pub fn length_unit(&self) -> LengthUnit {
491
+ self.unit
492
+ }
493
+
494
+ /// Return the unitless, raw value.
495
+ #[inline]
496
+ pub fn unitless_value(&self) -> CSSFloat {
497
+ self.value
498
+ }
499
+
500
+ /// Return the unit, as a string.
501
+ #[inline]
502
+ pub fn unit(&self) -> &'static str {
503
+ self.unit.as_str()
504
+ }
505
+
506
+ /// Return the canonical unit for this value, if one exists.
507
+ pub fn canonical_unit(&self) -> Option<&'static str> {
508
+ if self.unit.is_absolute() {
509
+ Some("px")
510
+ } else {
511
+ None
512
+ }
513
+ }
514
+
515
+ /// Convert this value to the specified unit, if possible.
516
+ pub fn to(&self, unit: &str) -> Result<Self, ()> {
517
+ let px = self.to_px_if_absolute().ok_or(())?;
518
+ let (target, divisor) = match_ignore_ascii_case! { unit,
519
+ "px" => (LengthUnit::Px, 1.0),
520
+ "in" => (LengthUnit::In, PX_PER_IN),
521
+ "cm" => (LengthUnit::Cm, PX_PER_CM),
522
+ "mm" => (LengthUnit::Mm, PX_PER_MM),
523
+ "q" => (LengthUnit::Q, PX_PER_Q),
524
+ "pt" => (LengthUnit::Pt, PX_PER_PT),
525
+ "pc" => (LengthUnit::Pc, PX_PER_PC),
526
+ _ => return Err(()),
527
+ };
528
+ Ok(Self::new(target, px / divisor))
529
+ }
530
+
531
+ /// Returns whether the value of this length without unit is less than zero.
532
+ pub fn is_negative(&self) -> bool {
533
+ self.value.is_sign_negative()
534
+ }
535
+
536
+ /// Returns whether the value of this length without unit is equal to zero.
537
+ pub fn is_zero(&self) -> bool {
538
+ self.value == 0.0
539
+ }
540
+
541
+ /// Returns whether the value of this length without unit is infinite.
542
+ pub fn is_infinite(&self) -> bool {
543
+ self.value.is_infinite()
544
+ }
545
+
546
+ /// Returns whether the value of this length without unit is NaN.
547
+ pub fn is_nan(&self) -> bool {
548
+ self.value.is_nan()
549
+ }
550
+
551
+ /// Whether text-only zoom should be applied to this length.
552
+ ///
553
+ /// Generally, font-dependent/relative units don't get text-only-zoomed,
554
+ /// because the font they're relative to should be zoomed already.
555
+ pub fn should_zoom_text(&self) -> bool {
556
+ !self.unit.is_font_relative() && self.unit != LengthUnit::ServoCharacterWidth
557
+ }
558
+
559
+ /// Returns the SortKey for this length. Must not be called on the internal
560
+ /// `ServoCharacterWidth` unit.
561
+ pub(crate) fn sort_key(&self) -> crate::values::generics::calc::SortKey {
562
+ self.unit.sort_key()
563
+ }
564
+
565
+ /// Parse a given absolute or relative dimension.
566
+ pub fn parse_dimension_with_flags(
567
+ parsing_mode: ParsingMode,
568
+ in_page_rule: bool,
569
+ value: CSSFloat,
570
+ unit: &str,
571
+ ) -> Result<Self, ()> {
572
+ let length_unit = LengthUnit::from_str_with_flags(parsing_mode, in_page_rule, unit)?;
573
+ Ok(Self::new(length_unit, value))
574
+ }
575
+
576
+ /// Parse a given absolute or relative dimension.
577
+ pub fn parse_dimension_with_context(
578
+ context: &ParserContext,
579
+ value: CSSFloat,
580
+ unit: &str,
581
+ ) -> Result<Self, ()> {
582
+ Self::parse_dimension_with_flags(context.parsing_mode, context.in_page_rule(), value, unit)
583
+ }
584
+
585
+ pub(crate) fn try_op<O>(&self, other: &Self, op: O) -> Result<Self, ()>
586
+ where
587
+ O: Fn(f32, f32) -> f32,
588
+ {
589
+ // For absolute lengths, normalize both to px and produce a px result.
590
+ if let (Some(a), Some(b)) = (self.to_px_if_absolute(), other.to_px_if_absolute()) {
591
+ return Ok(Self::new(LengthUnit::Px, op(a, b)));
592
+ }
593
+ if self.unit != other.unit {
594
+ return Err(());
595
+ }
596
+ Ok(Self::new(self.unit, op(self.value, other.value)))
597
+ }
598
+
599
+ pub(crate) fn map(&self, mut op: impl FnMut(f32) -> f32) -> Self {
600
+ // For absolute lengths, normalize to px.
601
+ if let Some(px) = self.to_px_if_absolute() {
602
+ return Self::new(LengthUnit::Px, op(px));
603
+ }
604
+ Self::new(self.unit, op(self.value))
605
+ }
606
+
607
+ /// Get a px value without context (so only absolute units can be handled).
608
+ #[inline]
609
+ pub fn to_computed_pixel_length_without_context(&self) -> Result<CSSFloat, ()> {
610
+ self.to_px_if_absolute().ok_or(())
611
+ }
612
+
613
+ /// Get a px value without a full style context; this can handle either
614
+ /// absolute or (if a font metrics getter is provided) font-relative units.
615
+ #[cfg(feature = "gecko")]
616
+ #[inline]
617
+ pub fn to_computed_pixel_length_with_font_metrics(
618
+ &self,
619
+ get_font_metrics: Option<impl Fn() -> GeckoFontMetrics>,
620
+ ) -> Result<CSSFloat, ()> {
621
+ if let Some(px) = self.to_px_if_absolute() {
622
+ return Ok(CSSPixelLength::new(px).finite().px());
623
+ }
624
+ if !self.unit.is_font_relative() {
625
+ return Err(());
626
+ }
627
+ let getter = match get_font_metrics {
628
+ Some(g) => g,
629
+ None => return Err(()),
630
+ };
631
+ let metrics = getter();
632
+ Ok(match self.unit {
633
+ LengthUnit::Em => self.value * metrics.mComputedEmSize.px(),
634
+ LengthUnit::Ex => self.value * metrics.mXSize.px(),
635
+ LengthUnit::Ch => self.value * metrics.mChSize.px(),
636
+ LengthUnit::Cap => self.value * metrics.mCapHeight.px(),
637
+ LengthUnit::Ic => self.value * metrics.mIcWidth.px(),
638
+ // `lh`, `rlh` are unsupported as we have no line-height context
639
+ // `rem`, `rex`, `rch`, `rcap`, and `ric` are unsupported as we have no root font context.
640
+ _ => return Err(()),
641
+ })
642
+ }
643
+
644
+ /// Get an absolute length from a px value.
645
+ #[inline]
646
+ pub fn from_px(px_value: CSSFloat) -> NoCalcLength {
647
+ Self::new(LengthUnit::Px, px_value)
648
+ }
649
+
650
+ /// Returns the value as a px-canonical length (absolute lengths only).
651
+ #[inline]
652
+ pub fn to_px_if_absolute(&self) -> Option<CSSFloat> {
653
+ let factor = match self.unit {
654
+ LengthUnit::Px => 1.0,
655
+ LengthUnit::In => PX_PER_IN,
656
+ LengthUnit::Cm => PX_PER_CM,
657
+ LengthUnit::Mm => PX_PER_MM,
658
+ LengthUnit::Q => PX_PER_Q,
659
+ LengthUnit::Pt => PX_PER_PT,
660
+ LengthUnit::Pc => PX_PER_PC,
661
+ _ => return None,
662
+ };
663
+ Some(self.value * factor)
664
+ }
665
+
666
+ /// Construct a font-relative em value.
667
+ #[inline]
668
+ pub fn from_em(value: CSSFloat) -> Self {
669
+ Self::new(LengthUnit::Em, value)
670
+ }
671
+
672
+ /// Construct an internal ServoCharacterWidth length from an i32 column count.
673
+ #[inline]
674
+ pub fn from_servo_character_width(value: i32) -> Self {
675
+ Self::new(LengthUnit::ServoCharacterWidth, value as CSSFloat)
676
+ }
677
+
678
+ /// Compute a font-relative length against the given base sizes. Must only
679
+ /// be called on a font-relative unit.
680
+ fn font_relative_to_computed_value(
681
+ &self,
682
+ context: &Context,
683
+ base_size: FontBaseSize,
684
+ line_height_base: LineHeightBase,
685
+ ) -> computed::Length {
686
+ let (reference_size, length) =
687
+ self.reference_font_size_and_length(context, base_size, line_height_base);
688
+ (reference_size * length).finite()
689
+ }
690
+
691
+ fn reference_font_size_and_length(
692
+ &self,
693
+ context: &Context,
694
+ base_size: FontBaseSize,
695
+ line_height_base: LineHeightBase,
696
+ ) -> (computed::Length, CSSFloat) {
697
+ fn query_font_metrics(
698
+ context: &Context,
699
+ base_size: FontBaseSize,
700
+ orientation: FontMetricsOrientation,
701
+ flags: QueryFontMetricsFlags,
702
+ ) -> FontMetrics {
703
+ context.query_font_metrics(base_size, orientation, flags)
704
+ }
705
+
706
+ fn ex_size(
707
+ context: &Context,
708
+ base_size: FontBaseSize,
709
+ reference_font_size: &FontSize,
710
+ ) -> computed::Length {
711
+ let metrics = query_font_metrics(
712
+ context,
713
+ base_size,
714
+ FontMetricsOrientation::Horizontal,
715
+ QueryFontMetricsFlags::empty(),
716
+ );
717
+ metrics.x_height_or_default(reference_font_size.used_size())
718
+ }
719
+
720
+ fn ch_size(
721
+ context: &Context,
722
+ base_size: FontBaseSize,
723
+ reference_font_size: &FontSize,
724
+ ) -> computed::Length {
725
+ let metrics = query_font_metrics(
726
+ context,
727
+ base_size,
728
+ FontMetricsOrientation::MatchContextPreferHorizontal,
729
+ QueryFontMetricsFlags::NEEDS_CH,
730
+ );
731
+ metrics.zero_advance_measure_or_default(
732
+ reference_font_size.used_size(),
733
+ context.style().writing_mode.is_upright(),
734
+ )
735
+ }
736
+
737
+ fn cap_size(context: &Context, base_size: FontBaseSize) -> computed::Length {
738
+ let metrics = query_font_metrics(
739
+ context,
740
+ base_size,
741
+ FontMetricsOrientation::Horizontal,
742
+ QueryFontMetricsFlags::empty(),
743
+ );
744
+ metrics.cap_height_or_default()
745
+ }
746
+
747
+ fn ic_size(
748
+ context: &Context,
749
+ base_size: FontBaseSize,
750
+ reference_font_size: &FontSize,
751
+ ) -> computed::Length {
752
+ let metrics = query_font_metrics(
753
+ context,
754
+ base_size,
755
+ FontMetricsOrientation::MatchContextPreferVertical,
756
+ QueryFontMetricsFlags::NEEDS_IC,
757
+ );
758
+ metrics.ic_width_or_default(reference_font_size.used_size())
759
+ }
760
+
761
+ context
762
+ .builder
763
+ .add_flags(ComputedValueFlags::USES_FONT_OR_WM_RELATIVE_UNITS);
764
+
765
+ let reference_font_size = base_size.resolve(context);
766
+ let length = self.value;
767
+ match self.unit {
768
+ LengthUnit::Em => {
769
+ if context.for_non_inherited_property && base_size == FontBaseSize::CurrentStyle {
770
+ context
771
+ .rule_cache_conditions
772
+ .borrow_mut()
773
+ .set_font_size_dependency(reference_font_size.computed_size);
774
+ }
775
+
776
+ (reference_font_size.computed_size(), length)
777
+ },
778
+ LengthUnit::Lh => {
779
+ let reference_size = if context.in_media_query {
780
+ context
781
+ .device()
782
+ .calc_line_height(
783
+ context.default_style().get_font(),
784
+ context.style().writing_mode,
785
+ None,
786
+ )
787
+ .0
788
+ } else {
789
+ let line_height = context.builder.calc_line_height(
790
+ context.device(),
791
+ line_height_base,
792
+ context.style().writing_mode,
793
+ );
794
+ if context.for_non_inherited_property
795
+ && line_height_base == LineHeightBase::CurrentStyle
796
+ {
797
+ context
798
+ .rule_cache_conditions
799
+ .borrow_mut()
800
+ .set_line_height_dependency(line_height)
801
+ }
802
+ line_height.0
803
+ };
804
+ (reference_size, length)
805
+ },
806
+ LengthUnit::Ex => (ex_size(context, base_size, &reference_font_size), length),
807
+ LengthUnit::Ch => (ch_size(context, base_size, &reference_font_size), length),
808
+ LengthUnit::Cap => (cap_size(context, base_size), length),
809
+ LengthUnit::Ic => (ic_size(context, base_size, &reference_font_size), length),
810
+ LengthUnit::Rex => {
811
+ let reference_size = if context.builder.is_root_element || context.in_media_query {
812
+ ex_size(context, base_size, &reference_font_size)
813
+ } else {
814
+ context
815
+ .device()
816
+ .root_font_metrics_ex()
817
+ .zoom(context.builder.effective_zoom)
818
+ };
819
+ (reference_size, length)
820
+ },
821
+ LengthUnit::Rch => {
822
+ let reference_size = if context.builder.is_root_element || context.in_media_query {
823
+ ch_size(context, base_size, &reference_font_size)
824
+ } else {
825
+ context
826
+ .device()
827
+ .root_font_metrics_ch()
828
+ .zoom(context.builder.effective_zoom)
829
+ };
830
+ (reference_size, length)
831
+ },
832
+ LengthUnit::Rcap => {
833
+ let reference_size = if context.builder.is_root_element || context.in_media_query {
834
+ cap_size(context, base_size)
835
+ } else {
836
+ context
837
+ .device()
838
+ .root_font_metrics_cap()
839
+ .zoom(context.builder.effective_zoom)
840
+ };
841
+ (reference_size, length)
842
+ },
843
+ LengthUnit::Ric => {
844
+ let reference_size = if context.builder.is_root_element || context.in_media_query {
845
+ ic_size(context, base_size, &reference_font_size)
846
+ } else {
847
+ context
848
+ .device()
849
+ .root_font_metrics_ic()
850
+ .zoom(context.builder.effective_zoom)
851
+ };
852
+ (reference_size, length)
853
+ },
854
+ LengthUnit::Rem => {
855
+ let reference_size = if context.builder.is_root_element || context.in_media_query {
856
+ reference_font_size.computed_size()
857
+ } else {
858
+ context
859
+ .device()
860
+ .root_font_size()
861
+ .zoom(context.builder.effective_zoom)
862
+ };
863
+ (reference_size, length)
864
+ },
865
+ LengthUnit::Rlh => {
866
+ let reference_size = if context.builder.is_root_element {
867
+ context
868
+ .builder
869
+ .calc_line_height(
870
+ context.device(),
871
+ line_height_base,
872
+ context.style().writing_mode,
873
+ )
874
+ .0
875
+ } else if context.in_media_query {
876
+ context
877
+ .device()
878
+ .calc_line_height(
879
+ context.default_style().get_font(),
880
+ context.style().writing_mode,
881
+ None,
882
+ )
883
+ .0
884
+ } else {
885
+ context.device().root_line_height()
886
+ };
887
+ let reference_size = reference_size.zoom(context.builder.effective_zoom);
888
+ (reference_size, length)
889
+ },
890
+ _ => unreachable!("reference_font_size_and_length: not a font-relative unit"),
891
+ }
892
+ }
893
+
894
+ /// Compute the viewport-percentage length. Must only be called on a
895
+ /// viewport-relative unit.
896
+ fn viewport_percentage_to_computed_value(&self, context: &Context) -> CSSPixelLength {
897
+ let (variant, unit) = match self.unit {
898
+ LengthUnit::Vw => (ViewportVariant::UADefault, ViewportUnit::Vw),
899
+ LengthUnit::Svw => (ViewportVariant::Small, ViewportUnit::Vw),
900
+ LengthUnit::Lvw => (ViewportVariant::Large, ViewportUnit::Vw),
901
+ LengthUnit::Dvw => (ViewportVariant::Dynamic, ViewportUnit::Vw),
902
+ LengthUnit::Vh => (ViewportVariant::UADefault, ViewportUnit::Vh),
903
+ LengthUnit::Svh => (ViewportVariant::Small, ViewportUnit::Vh),
904
+ LengthUnit::Lvh => (ViewportVariant::Large, ViewportUnit::Vh),
905
+ LengthUnit::Dvh => (ViewportVariant::Dynamic, ViewportUnit::Vh),
906
+ LengthUnit::Vmin => (ViewportVariant::UADefault, ViewportUnit::Vmin),
907
+ LengthUnit::Svmin => (ViewportVariant::Small, ViewportUnit::Vmin),
908
+ LengthUnit::Lvmin => (ViewportVariant::Large, ViewportUnit::Vmin),
909
+ LengthUnit::Dvmin => (ViewportVariant::Dynamic, ViewportUnit::Vmin),
910
+ LengthUnit::Vmax => (ViewportVariant::UADefault, ViewportUnit::Vmax),
911
+ LengthUnit::Svmax => (ViewportVariant::Small, ViewportUnit::Vmax),
912
+ LengthUnit::Lvmax => (ViewportVariant::Large, ViewportUnit::Vmax),
913
+ LengthUnit::Dvmax => (ViewportVariant::Dynamic, ViewportUnit::Vmax),
914
+ LengthUnit::Vb => (ViewportVariant::UADefault, ViewportUnit::Vb),
915
+ LengthUnit::Svb => (ViewportVariant::Small, ViewportUnit::Vb),
916
+ LengthUnit::Lvb => (ViewportVariant::Large, ViewportUnit::Vb),
917
+ LengthUnit::Dvb => (ViewportVariant::Dynamic, ViewportUnit::Vb),
918
+ LengthUnit::Vi => (ViewportVariant::UADefault, ViewportUnit::Vi),
919
+ LengthUnit::Svi => (ViewportVariant::Small, ViewportUnit::Vi),
920
+ LengthUnit::Lvi => (ViewportVariant::Large, ViewportUnit::Vi),
921
+ LengthUnit::Dvi => (ViewportVariant::Dynamic, ViewportUnit::Vi),
922
+ _ => {
923
+ unreachable!("viewport_percentage_to_computed_value: not a viewport-relative unit")
924
+ },
925
+ };
926
+ let factor = self.value;
927
+ let size = context.viewport_size_for_viewport_unit_resolution(variant);
928
+ let length: app_units::Au = match unit {
929
+ ViewportUnit::Vw => size.width,
930
+ ViewportUnit::Vh => size.height,
931
+ ViewportUnit::Vmin => cmp::min(size.width, size.height),
932
+ ViewportUnit::Vmax => cmp::max(size.width, size.height),
933
+ ViewportUnit::Vi | ViewportUnit::Vb => {
934
+ context
935
+ .builder
936
+ .add_flags(ComputedValueFlags::USES_FONT_OR_WM_RELATIVE_UNITS);
937
+ context
938
+ .rule_cache_conditions
939
+ .borrow_mut()
940
+ .set_writing_mode_dependency(context.builder.writing_mode);
941
+ if (unit == ViewportUnit::Vb) == context.style().writing_mode.is_vertical() {
942
+ size.width
943
+ } else {
944
+ size.height
945
+ }
946
+ },
947
+ };
948
+ let length = context.builder.effective_zoom.zoom(length.0 as f32);
949
+
950
+ let trunc_scaled =
951
+ ((length as f64 * factor as f64 / 100.).trunc() / AU_PER_PX as f64) as f32;
952
+ CSSPixelLength::new(crate::values::normalize(trunc_scaled))
953
+ }
954
+
955
+ /// Compute the container-relative length. Must only be called on a
956
+ /// container-relative unit.
957
+ fn container_relative_to_computed_value(&self, context: &Context) -> CSSPixelLength {
958
+ if context.for_non_inherited_property {
959
+ context.rule_cache_conditions.borrow_mut().set_uncacheable();
960
+ }
961
+ context
962
+ .builder
963
+ .add_flags(ComputedValueFlags::USES_CONTAINER_UNITS);
964
+
965
+ let size = context.get_container_size_query();
966
+ let factor = self.value;
967
+ let container_length = match self.unit {
968
+ LengthUnit::Cqw => size.get_container_width(context),
969
+ LengthUnit::Cqh => size.get_container_height(context),
970
+ LengthUnit::Cqi => size.get_container_inline_size(context),
971
+ LengthUnit::Cqb => size.get_container_block_size(context),
972
+ LengthUnit::Cqmin => cmp::min(
973
+ size.get_container_inline_size(context),
974
+ size.get_container_block_size(context),
975
+ ),
976
+ LengthUnit::Cqmax => cmp::max(
977
+ size.get_container_inline_size(context),
978
+ size.get_container_block_size(context),
979
+ ),
980
+ _ => {
981
+ unreachable!("container_relative_to_computed_value: not a container-relative unit")
982
+ },
983
+ };
984
+ CSSPixelLength::new((container_length.to_f64_px() * factor as f64 / 100.0) as f32).finite()
985
+ }
986
+
987
+ /// Computes a ServoCharacterWidth length against a reference font size.
988
+ fn servo_character_width_to_computed_value(
989
+ &self,
990
+ reference_font_size: computed::Length,
991
+ ) -> computed::Length {
992
+ debug_assert_eq!(self.unit, LengthUnit::ServoCharacterWidth);
993
+ let cols = self.value as i32 as CSSFloat;
994
+ // This applies the *converting a character width to pixels* algorithm
995
+ // as specified in HTML5 § 14.5.4.
996
+ let average_advance = reference_font_size * 0.5;
997
+ let max_advance = reference_font_size;
998
+ (average_advance * (cols - 1.0) + max_advance).finite()
999
+ }
1000
+
1001
+ /// Computes a length with a given font-relative base size.
1002
+ pub fn to_computed_value_with_base_size(
1003
+ &self,
1004
+ context: &Context,
1005
+ base_size: FontBaseSize,
1006
+ line_height_base: LineHeightBase,
1007
+ ) -> CSSPixelLength {
1008
+ if let Some(px) = self.to_px_if_absolute() {
1009
+ return CSSPixelLength::new(px)
1010
+ .zoom(context.builder.effective_zoom)
1011
+ .finite();
1012
+ }
1013
+ let unit = self.length_unit();
1014
+ if unit.is_font_relative() {
1015
+ return self.font_relative_to_computed_value(context, base_size, line_height_base);
1016
+ }
1017
+ if unit.is_viewport_percentage() {
1018
+ return self.viewport_percentage_to_computed_value(context);
1019
+ }
1020
+ if unit.is_container_relative() {
1021
+ return self.container_relative_to_computed_value(context);
1022
+ }
1023
+ debug_assert_eq!(unit, LengthUnit::ServoCharacterWidth);
1024
+ self.servo_character_width_to_computed_value(
1025
+ context.style().get_font().clone_font_size().computed_size(),
1026
+ )
1027
+ }
1028
+ }
1029
+
1030
+ impl ToComputedValue for NoCalcLength {
1031
+ type ComputedValue = computed::Length;
1032
+
1033
+ #[inline]
1034
+ fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
1035
+ self.to_computed_value_with_base_size(
1036
+ context,
1037
+ FontBaseSize::CurrentStyle,
1038
+ LineHeightBase::CurrentStyle,
1039
+ )
1040
+ }
1041
+
1042
+ #[inline]
1043
+ fn from_computed_value(computed: &Self::ComputedValue) -> Self {
1044
+ Self::from_px(computed.px())
1045
+ }
1046
+ }
1047
+
1048
+ impl ToCss for NoCalcLength {
1049
+ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
1050
+ where
1051
+ W: Write,
1052
+ {
1053
+ crate::values::serialize_specified_dimension(
1054
+ self.unitless_value(),
1055
+ self.unit(),
1056
+ false,
1057
+ dest,
1058
+ )
1059
+ }
1060
+ }
1061
+
1062
+ impl ToTyped for NoCalcLength {
1063
+ fn to_typed(&self, dest: &mut ThinVec<TypedValue>) -> Result<(), ()> {
1064
+ let numeric_type = NumericType::length();
1065
+ let value = self.unitless_value();
1066
+ let unit = CssString::from(self.unit());
1067
+ dest.push(TypedValue::Numeric(NumericValue::Unit(UnitValue {
1068
+ numeric_type,
1069
+ value,
1070
+ unit,
1071
+ })));
1072
+ Ok(())
1073
+ }
1074
+ }
1075
+
1076
+ impl SpecifiedValueInfo for NoCalcLength {}
1077
+
1078
+ impl PartialOrd for NoCalcLength {
1079
+ fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
1080
+ // For absolute units, compare in px.
1081
+ if let (Some(a), Some(b)) = (self.to_px_if_absolute(), other.to_px_if_absolute()) {
1082
+ return a.partial_cmp(&b);
1083
+ }
1084
+ if self.unit != other.unit {
1085
+ return None;
1086
+ }
1087
+ self.value.partial_cmp(&other.value)
1088
+ }
1089
+ }
1090
+
1091
+ impl Zero for NoCalcLength {
1092
+ fn zero() -> Self {
1093
+ Self::from_px(0.)
1094
+ }
1095
+
1096
+ fn is_zero(&self) -> bool {
1097
+ NoCalcLength::is_zero(self)
1098
+ }
1099
+ }
1100
+
1101
+ /// An extension to `NoCalcLength` to parse `calc` expressions.
1102
+ /// This is commonly used for the `<length>` values.
1103
+ ///
1104
+ /// Either stored inline as length + unit without calc or as a boxed calc node.
1105
+ ///
1106
+ /// <https://drafts.csswg.org/css-values/#lengths>
1107
+ #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
1108
+ pub struct Length(NumericUnion<LengthUnit, f32, CalcLengthPercentage>);
1109
+
1110
+ impl ToCss for Length {
1111
+ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
1112
+ where
1113
+ W: Write,
1114
+ {
1115
+ match self.0.unpack() {
1116
+ Unpacked::Inline(unit, value) => NoCalcLength::new(unit, value).to_css(dest),
1117
+ Unpacked::Boxed(calc) => calc.to_css(dest),
1118
+ }
1119
+ }
1120
+ }
1121
+
1122
+ impl ToTyped for Length {
1123
+ fn to_typed(&self, dest: &mut ThinVec<TypedValue>) -> Result<(), ()> {
1124
+ match self.0.unpack() {
1125
+ Unpacked::Inline(unit, value) => NoCalcLength::new(unit, value).to_typed(dest),
1126
+ Unpacked::Boxed(calc) => calc.to_typed(dest),
1127
+ }
1128
+ }
1129
+ }
1130
+
1131
+ impl SpecifiedValueInfo for Length {}
1132
+
1133
+ impl From<NoCalcLength> for Length {
1134
+ #[inline]
1135
+ fn from(len: NoCalcLength) -> Self {
1136
+ Self::new(len)
1137
+ }
1138
+ }
1139
+
1140
+ impl Length {
1141
+ /// Creates a length from a non-calc `NoCalcLength`.
1142
+ #[inline]
1143
+ pub fn new(len: NoCalcLength) -> Self {
1144
+ Self(NumericUnion::inline(len.unit, len.value))
1145
+ }
1146
+
1147
+ /// Creates a length from a `calc()` expression.
1148
+ #[inline]
1149
+ pub fn new_calc(calc: Box<CalcLengthPercentage>) -> Self {
1150
+ Self(NumericUnion::boxed(calc))
1151
+ }
1152
+
1153
+ /// Returns true if this is a `calc()` expression.
1154
+ #[inline]
1155
+ pub fn is_calc(&self) -> bool {
1156
+ self.0.is_boxed()
1157
+ }
1158
+
1159
+ #[inline]
1160
+ fn parse_internal(
1161
+ context: &ParserContext,
1162
+ input: &mut Parser,
1163
+ num_context: AllowedNumericType,
1164
+ allow_quirks: AllowQuirks,
1165
+ ) -> Result<Self, ParseError> {
1166
+ let token = input.next()?;
1167
+ match *token {
1168
+ Token::Dimension {
1169
+ value, ref unit, ..
1170
+ } if num_context.is_ok(context.parsing_mode, value) => {
1171
+ NoCalcLength::parse_dimension_with_context(context, value, unit)
1172
+ .map(Self::new)
1173
+ .map_err(|()| ParseError::unexpected_token())
1174
+ },
1175
+ Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => {
1176
+ let allowed = context.parsing_mode.allows_unitless_lengths()
1177
+ || allow_quirks.allowed(context.quirks_mode)
1178
+ || (value == 0. && context.parsing_mode.allows_unitless_zero_lengths());
1179
+
1180
+ if !allowed {
1181
+ return Err(ParseError::custom(StyleParseErrorKind::UnspecifiedError));
1182
+ }
1183
+
1184
+ Ok(Self::new(NoCalcLength::from_px(value)))
1185
+ },
1186
+ Token::Function(ref name) => {
1187
+ let function = CalcNode::math_function(context, name)?;
1188
+ let calc = CalcNode::parse_length(
1189
+ context,
1190
+ input,
1191
+ num_context,
1192
+ function,
1193
+ PercentageContext::not_allowed(),
1194
+ )?;
1195
+ Ok(Self::new_calc(Box::new(calc)))
1196
+ },
1197
+ _ => Err(ParseError::unexpected_token()),
1198
+ }
1199
+ }
1200
+
1201
+ /// Parse a non-negative length
1202
+ #[inline]
1203
+ pub fn parse_non_negative(
1204
+ context: &ParserContext,
1205
+ input: &mut Parser,
1206
+ ) -> Result<Self, ParseError> {
1207
+ Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
1208
+ }
1209
+
1210
+ /// Parse a non-negative length, allowing quirks.
1211
+ #[inline]
1212
+ pub fn parse_non_negative_quirky(
1213
+ context: &ParserContext,
1214
+ input: &mut Parser,
1215
+ allow_quirks: AllowQuirks,
1216
+ ) -> Result<Self, ParseError> {
1217
+ Self::parse_internal(
1218
+ context,
1219
+ input,
1220
+ AllowedNumericType::NonNegative,
1221
+ allow_quirks,
1222
+ )
1223
+ }
1224
+
1225
+ /// Get an absolute length from a px value.
1226
+ #[inline]
1227
+ pub fn from_px(px_value: CSSFloat) -> Length {
1228
+ Self::new(NoCalcLength::from_px(px_value))
1229
+ }
1230
+
1231
+ /// Get a px value without context.
1232
+ pub fn to_computed_pixel_length_without_context(&self) -> Result<CSSFloat, ()> {
1233
+ match self.0.unpack() {
1234
+ Unpacked::Inline(unit, value) => {
1235
+ NoCalcLength::new(unit, value).to_computed_pixel_length_without_context()
1236
+ },
1237
+ Unpacked::Boxed(calc) => calc.to_computed_pixel_length_without_context(),
1238
+ }
1239
+ }
1240
+
1241
+ /// Get a px value, with an optional GeckoFontMetrics getter to resolve font-relative units.
1242
+ #[cfg(feature = "gecko")]
1243
+ pub fn to_computed_pixel_length_with_font_metrics(
1244
+ &self,
1245
+ get_font_metrics: Option<impl Fn() -> GeckoFontMetrics>,
1246
+ ) -> Result<CSSFloat, ()> {
1247
+ match self.0.unpack() {
1248
+ Unpacked::Inline(unit, value) => NoCalcLength::new(unit, value)
1249
+ .to_computed_pixel_length_with_font_metrics(get_font_metrics),
1250
+ Unpacked::Boxed(calc) => {
1251
+ calc.to_computed_pixel_length_with_font_metrics(get_font_metrics)
1252
+ },
1253
+ }
1254
+ }
1255
+ }
1256
+
1257
+ impl Parse for Length {
1258
+ fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ParseError> {
1259
+ Self::parse_quirky(context, input, AllowQuirks::No)
1260
+ }
1261
+ }
1262
+
1263
+ impl ToComputedValue for Length {
1264
+ type ComputedValue = computed::Length;
1265
+
1266
+ #[inline]
1267
+ fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
1268
+ match self.0.unpack() {
1269
+ Unpacked::Inline(unit, value) => {
1270
+ NoCalcLength::new(unit, value).to_computed_value(context)
1271
+ },
1272
+ Unpacked::Boxed(calc) => {
1273
+ let result = calc.to_computed_value(context);
1274
+ debug_assert!(
1275
+ result.to_length().is_some(),
1276
+ "{:?} didn't resolve to a length: {:?}",
1277
+ calc,
1278
+ result,
1279
+ );
1280
+ result.to_length().unwrap_or_else(computed::Length::zero)
1281
+ },
1282
+ }
1283
+ }
1284
+
1285
+ #[inline]
1286
+ fn from_computed_value(computed: &Self::ComputedValue) -> Self {
1287
+ Self::new(NoCalcLength::from_computed_value(computed))
1288
+ }
1289
+ }
1290
+
1291
+ impl Zero for Length {
1292
+ fn zero() -> Self {
1293
+ Self::new(NoCalcLength::zero())
1294
+ }
1295
+
1296
+ fn is_zero(&self) -> bool {
1297
+ // FIXME(emilio): Seems a bit weird to treat calc() unconditionally as
1298
+ // non-zero here?
1299
+ match self.0.unpack() {
1300
+ Unpacked::Inline(_, value) => value == 0.0,
1301
+ Unpacked::Boxed(_) => false,
1302
+ }
1303
+ }
1304
+ }
1305
+
1306
+ impl Length {
1307
+ /// Parses a length, with quirks.
1308
+ pub fn parse_quirky(
1309
+ context: &ParserContext,
1310
+ input: &mut Parser,
1311
+ allow_quirks: AllowQuirks,
1312
+ ) -> Result<Self, ParseError> {
1313
+ Self::parse_internal(context, input, AllowedNumericType::All, allow_quirks)
1314
+ }
1315
+ }
1316
+
1317
+ /// A wrapper of Length, whose value must be >= 0.
1318
+ pub type NonNegativeLength = NonNegative<Length>;
1319
+
1320
+ impl Parse for NonNegativeLength {
1321
+ #[inline]
1322
+ fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ParseError> {
1323
+ Ok(NonNegative(Length::parse_non_negative(context, input)?))
1324
+ }
1325
+ }
1326
+
1327
+ impl From<NoCalcLength> for NonNegativeLength {
1328
+ #[inline]
1329
+ fn from(len: NoCalcLength) -> Self {
1330
+ NonNegative(Length::new(len))
1331
+ }
1332
+ }
1333
+
1334
+ impl From<Length> for NonNegativeLength {
1335
+ #[inline]
1336
+ fn from(len: Length) -> Self {
1337
+ NonNegative(len)
1338
+ }
1339
+ }
1340
+
1341
+ impl NonNegativeLength {
1342
+ /// Get an absolute length from a px value.
1343
+ #[inline]
1344
+ pub fn from_px(px_value: CSSFloat) -> Self {
1345
+ Length::from_px(px_value.max(0.)).into()
1346
+ }
1347
+
1348
+ /// Parses a non-negative length, optionally with quirks.
1349
+ #[inline]
1350
+ pub fn parse_quirky(
1351
+ context: &ParserContext,
1352
+ input: &mut Parser,
1353
+ allow_quirks: AllowQuirks,
1354
+ ) -> Result<Self, ParseError> {
1355
+ Ok(NonNegative(Length::parse_non_negative_quirky(
1356
+ context,
1357
+ input,
1358
+ allow_quirks,
1359
+ )?))
1360
+ }
1361
+ }
1362
+
1363
+ /// A `<length-percentage>` value. This can be either a `<length>`, a
1364
+ /// `<percentage>`, or a combination of both via `calc()`.
1365
+ ///
1366
+ /// https://drafts.csswg.org/css-values-4/#typedef-length-percentage
1367
+ #[allow(missing_docs)]
1368
+ #[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem, ToTyped)]
1369
+ pub enum LengthPercentage {
1370
+ Length(NoCalcLength),
1371
+ Percentage(NoCalcPercentage),
1372
+ Calc(Box<CalcLengthPercentage>),
1373
+ }
1374
+
1375
+ impl From<Length> for LengthPercentage {
1376
+ fn from(len: Length) -> LengthPercentage {
1377
+ match len.0.extract() {
1378
+ Extracted::Inline(unit, value) => {
1379
+ LengthPercentage::Length(NoCalcLength::new(unit, value))
1380
+ },
1381
+ Extracted::Boxed(calc) => LengthPercentage::Calc(calc),
1382
+ }
1383
+ }
1384
+ }
1385
+
1386
+ impl From<NoCalcLength> for LengthPercentage {
1387
+ #[inline]
1388
+ fn from(len: NoCalcLength) -> Self {
1389
+ LengthPercentage::Length(len)
1390
+ }
1391
+ }
1392
+
1393
+ impl From<computed::Percentage> for LengthPercentage {
1394
+ #[inline]
1395
+ fn from(pc: computed::Percentage) -> Self {
1396
+ LengthPercentage::Percentage(NoCalcPercentage::new(pc.0))
1397
+ }
1398
+ }
1399
+
1400
+ impl Parse for LengthPercentage {
1401
+ #[inline]
1402
+ fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ParseError> {
1403
+ Self::parse_quirky(context, input, AllowQuirks::No)
1404
+ }
1405
+ }
1406
+
1407
+ impl LengthPercentage {
1408
+ #[inline]
1409
+ /// Returns a `0%` value.
1410
+ pub fn zero_percent() -> LengthPercentage {
1411
+ LengthPercentage::Percentage(NoCalcPercentage::zero())
1412
+ }
1413
+
1414
+ #[inline]
1415
+ /// Returns a `100%` value.
1416
+ pub fn hundred_percent() -> LengthPercentage {
1417
+ LengthPercentage::Percentage(NoCalcPercentage::hundred())
1418
+ }
1419
+
1420
+ fn parse_internal(
1421
+ context: &ParserContext,
1422
+ input: &mut Parser,
1423
+ num_context: AllowedNumericType,
1424
+ allow_quirks: AllowQuirks,
1425
+ allow_anchor: AllowAnchorPositioningFunctions,
1426
+ ) -> Result<Self, ParseError> {
1427
+ let token = input.next()?;
1428
+ match *token {
1429
+ Token::Dimension {
1430
+ value, ref unit, ..
1431
+ } if num_context.is_ok(context.parsing_mode, value) => {
1432
+ NoCalcLength::parse_dimension_with_context(context, value, unit)
1433
+ .map(LengthPercentage::Length)
1434
+ .map_err(|()| ParseError::unexpected_token())
1435
+ },
1436
+ Token::Percentage { unit_value, .. }
1437
+ if num_context.is_ok(context.parsing_mode, unit_value) =>
1438
+ {
1439
+ Ok(LengthPercentage::Percentage(NoCalcPercentage::new(
1440
+ unit_value,
1441
+ )))
1442
+ },
1443
+ Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => {
1444
+ let allowed = context.parsing_mode.allows_unitless_lengths()
1445
+ || allow_quirks.allowed(context.quirks_mode)
1446
+ || (value == 0. && context.parsing_mode.allows_unitless_zero_lengths());
1447
+
1448
+ if !allowed {
1449
+ return Err(ParseError::custom(StyleParseErrorKind::UnspecifiedError));
1450
+ }
1451
+
1452
+ Ok(LengthPercentage::Length(NoCalcLength::from_px(value)))
1453
+ },
1454
+ Token::Function(ref name) => {
1455
+ let function = CalcNode::math_function(context, name)?;
1456
+ let calc = CalcNode::parse_length_or_percentage(
1457
+ context,
1458
+ input,
1459
+ num_context,
1460
+ function,
1461
+ allow_anchor,
1462
+ )?;
1463
+ Ok(LengthPercentage::Calc(Box::new(calc)))
1464
+ },
1465
+ _ => Err(ParseError::unexpected_token()),
1466
+ }
1467
+ }
1468
+
1469
+ /// Parses allowing the unitless length quirk.
1470
+ /// <https://quirks.spec.whatwg.org/#the-unitless-length-quirk>
1471
+ #[inline]
1472
+ pub fn parse_quirky(
1473
+ context: &ParserContext,
1474
+ input: &mut Parser,
1475
+ allow_quirks: AllowQuirks,
1476
+ ) -> Result<Self, ParseError> {
1477
+ Self::parse_internal(
1478
+ context,
1479
+ input,
1480
+ AllowedNumericType::All,
1481
+ allow_quirks,
1482
+ AllowAnchorPositioningFunctions::No,
1483
+ )
1484
+ }
1485
+
1486
+ /// Parses allowing the unitless length quirk, as well as allowing
1487
+ /// anchor-positioning related function, `anchor-size()`.
1488
+ #[inline]
1489
+ fn parse_quirky_with_anchor_size_function(
1490
+ context: &ParserContext,
1491
+ input: &mut Parser,
1492
+ allow_quirks: AllowQuirks,
1493
+ ) -> Result<Self, ParseError> {
1494
+ Self::parse_internal(
1495
+ context,
1496
+ input,
1497
+ AllowedNumericType::All,
1498
+ allow_quirks,
1499
+ AllowAnchorPositioningFunctions::AllowAnchorSize,
1500
+ )
1501
+ }
1502
+
1503
+ /// Parses allowing the unitless length quirk, as well as allowing
1504
+ /// anchor-positioning related functions, `anchor()` and `anchor-size()`.
1505
+ #[inline]
1506
+ pub fn parse_quirky_with_anchor_functions(
1507
+ context: &ParserContext,
1508
+ input: &mut Parser,
1509
+ allow_quirks: AllowQuirks,
1510
+ ) -> Result<Self, ParseError> {
1511
+ Self::parse_internal(
1512
+ context,
1513
+ input,
1514
+ AllowedNumericType::All,
1515
+ allow_quirks,
1516
+ AllowAnchorPositioningFunctions::AllowAnchorAndAnchorSize,
1517
+ )
1518
+ }
1519
+
1520
+ /// Parses non-negative length, allowing the unitless length quirk,
1521
+ /// as well as allowing `anchor-size()`.
1522
+ pub fn parse_non_negative_with_anchor_size(
1523
+ context: &ParserContext,
1524
+ input: &mut Parser,
1525
+ allow_quirks: AllowQuirks,
1526
+ ) -> Result<Self, ParseError> {
1527
+ Self::parse_internal(
1528
+ context,
1529
+ input,
1530
+ AllowedNumericType::NonNegative,
1531
+ allow_quirks,
1532
+ AllowAnchorPositioningFunctions::AllowAnchorSize,
1533
+ )
1534
+ }
1535
+
1536
+ /// Parse a non-negative length.
1537
+ ///
1538
+ /// FIXME(emilio): This should be not public and we should use
1539
+ /// NonNegativeLengthPercentage instead.
1540
+ #[inline]
1541
+ pub fn parse_non_negative(
1542
+ context: &ParserContext,
1543
+ input: &mut Parser,
1544
+ ) -> Result<Self, ParseError> {
1545
+ Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
1546
+ }
1547
+
1548
+ /// Parse a non-negative length, with quirks.
1549
+ #[inline]
1550
+ pub fn parse_non_negative_quirky(
1551
+ context: &ParserContext,
1552
+ input: &mut Parser,
1553
+ allow_quirks: AllowQuirks,
1554
+ ) -> Result<Self, ParseError> {
1555
+ Self::parse_internal(
1556
+ context,
1557
+ input,
1558
+ AllowedNumericType::NonNegative,
1559
+ allow_quirks,
1560
+ AllowAnchorPositioningFunctions::No,
1561
+ )
1562
+ }
1563
+
1564
+ /// Computes this specified value without style context. This succeeds for
1565
+ /// absolute lengths, percentages, and calc() expressions combining only
1566
+ /// those; it fails (returns None) for anything that needs a context to
1567
+ /// resolve, e.g. font- or viewport-relative units.
1568
+ pub fn compute_without_context(&self) -> Option<computed::LengthPercentage> {
1569
+ use crate::values::normalize;
1570
+ match self {
1571
+ Self::Length(length) => length
1572
+ .to_computed_pixel_length_without_context()
1573
+ .map(|v| computed::LengthPercentage::new_length(computed::Length::new(v)))
1574
+ .ok(),
1575
+ Self::Percentage(pc) => Some(computed::LengthPercentage::new_percent(
1576
+ computed::Percentage(normalize(pc.get())),
1577
+ )),
1578
+ Self::Calc(calc) => calc.compute_without_context(),
1579
+ }
1580
+ }
1581
+ }
1582
+
1583
+ impl Zero for LengthPercentage {
1584
+ fn zero() -> Self {
1585
+ LengthPercentage::Length(NoCalcLength::zero())
1586
+ }
1587
+
1588
+ fn is_zero(&self) -> bool {
1589
+ match *self {
1590
+ LengthPercentage::Length(l) => l.is_zero(),
1591
+ LengthPercentage::Percentage(p) => p.get() == 0.0,
1592
+ LengthPercentage::Calc(_) => false,
1593
+ }
1594
+ }
1595
+ }
1596
+
1597
+ impl ZeroNoPercent for LengthPercentage {
1598
+ fn is_zero_no_percent(&self) -> bool {
1599
+ match *self {
1600
+ LengthPercentage::Percentage(_) => false,
1601
+ _ => self.is_zero(),
1602
+ }
1603
+ }
1604
+ }
1605
+
1606
+ /// Check if this equal to a specific percentage.
1607
+ pub trait EqualsPercentage {
1608
+ /// Returns true if this is a specific percentage value. This should exclude calc() even if it
1609
+ /// only contains percentage component.
1610
+ fn equals_percentage(&self, v: CSSFloat) -> bool;
1611
+ }
1612
+
1613
+ impl EqualsPercentage for LengthPercentage {
1614
+ fn equals_percentage(&self, v: CSSFloat) -> bool {
1615
+ match *self {
1616
+ LengthPercentage::Percentage(p) => p.get() == v,
1617
+ _ => false,
1618
+ }
1619
+ }
1620
+ }
1621
+
1622
+ /// A specified type for `<length-percentage> | auto`.
1623
+ pub type LengthPercentageOrAuto = generics::LengthPercentageOrAuto<LengthPercentage>;
1624
+
1625
+ impl LengthPercentageOrAuto {
1626
+ /// Returns a value representing `0%`.
1627
+ #[inline]
1628
+ pub fn zero_percent() -> Self {
1629
+ generics::LengthPercentageOrAuto::LengthPercentage(LengthPercentage::zero_percent())
1630
+ }
1631
+
1632
+ /// Parses a length or a percentage, allowing the unitless length quirk.
1633
+ /// <https://quirks.spec.whatwg.org/#the-unitless-length-quirk>
1634
+ #[inline]
1635
+ pub fn parse_quirky(
1636
+ context: &ParserContext,
1637
+ input: &mut Parser,
1638
+ allow_quirks: AllowQuirks,
1639
+ ) -> Result<Self, ParseError> {
1640
+ Self::parse_with(context, input, |context, input| {
1641
+ LengthPercentage::parse_quirky(context, input, allow_quirks)
1642
+ })
1643
+ }
1644
+ }
1645
+
1646
+ /// A wrapper of LengthPercentageOrAuto, whose value must be >= 0.
1647
+ pub type NonNegativeLengthPercentageOrAuto =
1648
+ generics::LengthPercentageOrAuto<NonNegativeLengthPercentage>;
1649
+
1650
+ impl NonNegativeLengthPercentageOrAuto {
1651
+ /// Returns a value representing `0%`.
1652
+ #[inline]
1653
+ pub fn zero_percent() -> Self {
1654
+ generics::LengthPercentageOrAuto::LengthPercentage(
1655
+ NonNegativeLengthPercentage::zero_percent(),
1656
+ )
1657
+ }
1658
+
1659
+ /// Parses a non-negative length-percentage, allowing the unitless length
1660
+ /// quirk.
1661
+ #[inline]
1662
+ pub fn parse_quirky(
1663
+ context: &ParserContext,
1664
+ input: &mut Parser,
1665
+ allow_quirks: AllowQuirks,
1666
+ ) -> Result<Self, ParseError> {
1667
+ Self::parse_with(context, input, |context, input| {
1668
+ NonNegativeLengthPercentage::parse_quirky(context, input, allow_quirks)
1669
+ })
1670
+ }
1671
+ }
1672
+
1673
+ /// A wrapper of LengthPercentage, whose value must be >= 0.
1674
+ pub type NonNegativeLengthPercentage = NonNegative<LengthPercentage>;
1675
+
1676
+ /// Either a NonNegativeLengthPercentage or the `normal` keyword.
1677
+ pub type NonNegativeLengthPercentageOrNormal =
1678
+ GenericLengthPercentageOrNormal<NonNegativeLengthPercentage>;
1679
+
1680
+ impl From<NoCalcLength> for NonNegativeLengthPercentage {
1681
+ #[inline]
1682
+ fn from(len: NoCalcLength) -> Self {
1683
+ NonNegative(LengthPercentage::from(len))
1684
+ }
1685
+ }
1686
+
1687
+ impl Parse for NonNegativeLengthPercentage {
1688
+ #[inline]
1689
+ fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ParseError> {
1690
+ Self::parse_quirky(context, input, AllowQuirks::No)
1691
+ }
1692
+ }
1693
+
1694
+ impl NonNegativeLengthPercentage {
1695
+ #[inline]
1696
+ /// Returns a `0%` value.
1697
+ pub fn zero_percent() -> Self {
1698
+ NonNegative(LengthPercentage::zero_percent())
1699
+ }
1700
+
1701
+ /// Parses a length or a percentage, allowing the unitless length quirk.
1702
+ /// <https://quirks.spec.whatwg.org/#the-unitless-length-quirk>
1703
+ #[inline]
1704
+ pub fn parse_quirky(
1705
+ context: &ParserContext,
1706
+ input: &mut Parser,
1707
+ allow_quirks: AllowQuirks,
1708
+ ) -> Result<Self, ParseError> {
1709
+ LengthPercentage::parse_non_negative_quirky(context, input, allow_quirks).map(NonNegative)
1710
+ }
1711
+
1712
+ /// Parses a length or a percentage, allowing the unitless length quirk,
1713
+ /// as well as allowing `anchor-size()`.
1714
+ #[inline]
1715
+ pub fn parse_non_negative_with_anchor_size(
1716
+ context: &ParserContext,
1717
+ input: &mut Parser,
1718
+ allow_quirks: AllowQuirks,
1719
+ ) -> Result<Self, ParseError> {
1720
+ LengthPercentage::parse_non_negative_with_anchor_size(context, input, allow_quirks)
1721
+ .map(NonNegative)
1722
+ }
1723
+ }
1724
+
1725
+ /// Either a `<length>` or the `auto` keyword.
1726
+ ///
1727
+ /// Note that we use LengthPercentage just for convenience, since it pretty much
1728
+ /// is everything we care about, but we could just add a similar LengthOrAuto
1729
+ /// instead if we think getting rid of this weirdness is worth it.
1730
+ pub type LengthOrAuto = generics::LengthPercentageOrAuto<Length>;
1731
+
1732
+ impl LengthOrAuto {
1733
+ /// Parses a length, allowing the unitless length quirk.
1734
+ /// <https://quirks.spec.whatwg.org/#the-unitless-length-quirk>
1735
+ #[inline]
1736
+ pub fn parse_quirky(
1737
+ context: &ParserContext,
1738
+ input: &mut Parser,
1739
+ allow_quirks: AllowQuirks,
1740
+ ) -> Result<Self, ParseError> {
1741
+ Self::parse_with(context, input, |context, input| {
1742
+ Length::parse_quirky(context, input, allow_quirks)
1743
+ })
1744
+ }
1745
+ }
1746
+
1747
+ /// Either a non-negative `<length>` or the `auto` keyword.
1748
+ pub type NonNegativeLengthOrAuto = generics::LengthPercentageOrAuto<NonNegativeLength>;
1749
+
1750
+ /// Either a `<length>` or a `<number>`.
1751
+ pub type LengthOrNumber = GenericLengthOrNumber<Length, Number>;
1752
+
1753
+ /// A specified value for `min-width`, `min-height`, `width` or `height` property.
1754
+ pub type Size = GenericSize<NonNegativeLengthPercentage>;
1755
+
1756
+ impl Parse for Size {
1757
+ fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ParseError> {
1758
+ Size::parse_quirky(context, input, AllowQuirks::No)
1759
+ }
1760
+ }
1761
+
1762
+ macro_rules! parse_size_non_length {
1763
+ ($size:ident, $input:expr, $allow_webkit_fill_available:expr,
1764
+ $auto_or_none:expr => $auto_or_none_ident:ident) => {{
1765
+ let size = $input.try_parse(|input| {
1766
+ Ok(try_match_ident_ignore_ascii_case! { input,
1767
+ "min-content" | "-moz-min-content" => $size::MinContent,
1768
+ "max-content" | "-moz-max-content" => $size::MaxContent,
1769
+ "fit-content" | "-moz-fit-content" => $size::FitContent,
1770
+ #[cfg(feature = "gecko")]
1771
+ "-moz-available" => $size::MozAvailable,
1772
+ "-webkit-fill-available" if $allow_webkit_fill_available => $size::WebkitFillAvailable,
1773
+ "stretch" if is_stretch_enabled() => $size::Stretch,
1774
+ $auto_or_none => $size::$auto_or_none_ident,
1775
+ })
1776
+ });
1777
+ if size.is_ok() {
1778
+ return size;
1779
+ }
1780
+ }};
1781
+ }
1782
+
1783
+ fn is_webkit_fill_available_enabled_in_width_and_height() -> bool {
1784
+ crate::pref!("layout.css.webkit-fill-available.enabled")
1785
+ }
1786
+
1787
+ fn is_webkit_fill_available_enabled_in_all_size_properties() -> bool {
1788
+ // For convenience at the callsites, we check both prefs here,
1789
+ // since both must be 'true' in order for the keyword to be
1790
+ // enabled in all size properties.
1791
+ crate::pref!("layout.css.webkit-fill-available.enabled")
1792
+ && crate::pref!("layout.css.webkit-fill-available.all-size-properties.enabled")
1793
+ }
1794
+
1795
+ fn is_stretch_enabled() -> bool {
1796
+ crate::pref!("layout.css.stretch-size-keyword.enabled")
1797
+ }
1798
+
1799
+ fn is_fit_content_function_enabled() -> bool {
1800
+ crate::pref!("layout.css.fit-content-function.enabled")
1801
+ }
1802
+
1803
+ macro_rules! parse_fit_content_function {
1804
+ ($size:ident, $input:expr, $context:expr, $allow_quirks:expr) => {
1805
+ if is_fit_content_function_enabled() {
1806
+ if let Ok(length) = $input.try_parse(|input| {
1807
+ input.expect_function_matching("fit-content")?;
1808
+ input.parse_nested_block(|i| {
1809
+ NonNegativeLengthPercentage::parse_quirky($context, i, $allow_quirks)
1810
+ })
1811
+ }) {
1812
+ return Ok($size::FitContentFunction(length));
1813
+ }
1814
+ }
1815
+ };
1816
+ }
1817
+
1818
+ #[derive(Clone, Copy, PartialEq, Eq)]
1819
+ enum ParseAnchorFunctions {
1820
+ Yes,
1821
+ No,
1822
+ }
1823
+
1824
+ impl Size {
1825
+ /// Parses, with quirks.
1826
+ pub fn parse_quirky(
1827
+ context: &ParserContext,
1828
+ input: &mut Parser,
1829
+ allow_quirks: AllowQuirks,
1830
+ ) -> Result<Self, ParseError> {
1831
+ let allow_webkit_fill_available = is_webkit_fill_available_enabled_in_all_size_properties();
1832
+ Self::parse_quirky_internal(
1833
+ context,
1834
+ input,
1835
+ allow_quirks,
1836
+ allow_webkit_fill_available,
1837
+ ParseAnchorFunctions::Yes,
1838
+ )
1839
+ }
1840
+
1841
+ /// Parses for flex-basis: <width>
1842
+ pub fn parse_size_for_flex_basis_width(
1843
+ context: &ParserContext,
1844
+ input: &mut Parser,
1845
+ ) -> Result<Self, ParseError> {
1846
+ Self::parse_quirky_internal(
1847
+ context,
1848
+ input,
1849
+ AllowQuirks::No,
1850
+ true,
1851
+ ParseAnchorFunctions::No,
1852
+ )
1853
+ }
1854
+
1855
+ /// Parses, with quirks and configurable support for
1856
+ /// whether the '-webkit-fill-available' keyword is allowed.
1857
+ /// TODO(dholbert) Fold this function into callsites in bug 1989073 when
1858
+ /// removing 'layout.css.webkit-fill-available.all-size-properties.enabled'.
1859
+ fn parse_quirky_internal(
1860
+ context: &ParserContext,
1861
+ input: &mut Parser,
1862
+ allow_quirks: AllowQuirks,
1863
+ allow_webkit_fill_available: bool,
1864
+ allow_anchor_functions: ParseAnchorFunctions,
1865
+ ) -> Result<Self, ParseError> {
1866
+ parse_size_non_length!(Size, input, allow_webkit_fill_available,
1867
+ "auto" => Auto);
1868
+ parse_fit_content_function!(Size, input, context, allow_quirks);
1869
+
1870
+ let allow_anchor = allow_anchor_functions == ParseAnchorFunctions::Yes
1871
+ && crate::pref!("layout.css.anchor-positioning.enabled", gecko = true);
1872
+ match input
1873
+ .try_parse(|i| NonNegativeLengthPercentage::parse_quirky(context, i, allow_quirks))
1874
+ {
1875
+ Ok(length) => return Ok(GenericSize::LengthPercentage(length)),
1876
+ Err(e) if !allow_anchor => return Err(e.into()),
1877
+ Err(_) => (),
1878
+ };
1879
+ if let Ok(length) = input.try_parse(|i| {
1880
+ NonNegativeLengthPercentage::parse_non_negative_with_anchor_size(
1881
+ context,
1882
+ i,
1883
+ allow_quirks,
1884
+ )
1885
+ }) {
1886
+ return Ok(GenericSize::AnchorContainingCalcFunction(length));
1887
+ }
1888
+ Ok(Self::AnchorSizeFunction(Box::new(
1889
+ GenericAnchorSizeFunction::parse(context, input)?,
1890
+ )))
1891
+ }
1892
+
1893
+ /// Parse a size for width or height, where -webkit-fill-available
1894
+ /// support is only controlled by one pref (vs. other properties where
1895
+ /// there's an additional pref check):
1896
+ /// TODO(dholbert) Remove this custom parse func in bug 1989073, along with
1897
+ /// 'layout.css.webkit-fill-available.all-size-properties.enabled'.
1898
+ pub fn parse_size_for_width_or_height_quirky(
1899
+ context: &ParserContext,
1900
+ input: &mut Parser,
1901
+ allow_quirks: AllowQuirks,
1902
+ ) -> Result<Self, ParseError> {
1903
+ let allow_webkit_fill_available = is_webkit_fill_available_enabled_in_width_and_height();
1904
+ Self::parse_quirky_internal(
1905
+ context,
1906
+ input,
1907
+ allow_quirks,
1908
+ allow_webkit_fill_available,
1909
+ ParseAnchorFunctions::Yes,
1910
+ )
1911
+ }
1912
+
1913
+ /// Parse a size for width or height, where -webkit-fill-available
1914
+ /// support is only controlled by one pref (vs. other properties where
1915
+ /// there's an additional pref check):
1916
+ /// TODO(dholbert) Remove this custom parse func in bug 1989073, along with
1917
+ /// 'layout.css.webkit-fill-available.all-size-properties.enabled'.
1918
+ pub fn parse_size_for_width_or_height(
1919
+ context: &ParserContext,
1920
+ input: &mut Parser,
1921
+ ) -> Result<Self, ParseError> {
1922
+ let allow_webkit_fill_available = is_webkit_fill_available_enabled_in_width_and_height();
1923
+ Self::parse_quirky_internal(
1924
+ context,
1925
+ input,
1926
+ AllowQuirks::No,
1927
+ allow_webkit_fill_available,
1928
+ ParseAnchorFunctions::Yes,
1929
+ )
1930
+ }
1931
+
1932
+ /// Returns `0%`.
1933
+ #[inline]
1934
+ pub fn zero_percent() -> Self {
1935
+ GenericSize::LengthPercentage(NonNegativeLengthPercentage::zero_percent())
1936
+ }
1937
+ }
1938
+
1939
+ /// A specified value for `max-width` or `max-height` property.
1940
+ pub type MaxSize = GenericMaxSize<NonNegativeLengthPercentage>;
1941
+
1942
+ impl Parse for MaxSize {
1943
+ fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ParseError> {
1944
+ MaxSize::parse_quirky(context, input, AllowQuirks::No)
1945
+ }
1946
+ }
1947
+
1948
+ impl MaxSize {
1949
+ /// Parses, with quirks.
1950
+ pub fn parse_quirky(
1951
+ context: &ParserContext,
1952
+ input: &mut Parser,
1953
+ allow_quirks: AllowQuirks,
1954
+ ) -> Result<Self, ParseError> {
1955
+ let allow_webkit_fill_available = is_webkit_fill_available_enabled_in_all_size_properties();
1956
+ parse_size_non_length!(MaxSize, input, allow_webkit_fill_available,
1957
+ "none" => None);
1958
+ parse_fit_content_function!(MaxSize, input, context, allow_quirks);
1959
+
1960
+ match input
1961
+ .try_parse(|i| NonNegativeLengthPercentage::parse_quirky(context, i, allow_quirks))
1962
+ {
1963
+ Ok(length) => return Ok(GenericMaxSize::LengthPercentage(length)),
1964
+ Err(e) if !crate::pref!("layout.css.anchor-positioning.enabled", gecko = true) => {
1965
+ return Err(e.into())
1966
+ },
1967
+ Err(_) => (),
1968
+ };
1969
+ if let Ok(length) = input.try_parse(|i| {
1970
+ NonNegativeLengthPercentage::parse_non_negative_with_anchor_size(
1971
+ context,
1972
+ i,
1973
+ allow_quirks,
1974
+ )
1975
+ }) {
1976
+ return Ok(GenericMaxSize::AnchorContainingCalcFunction(length));
1977
+ }
1978
+ Ok(Self::AnchorSizeFunction(Box::new(
1979
+ GenericAnchorSizeFunction::parse(context, input)?,
1980
+ )))
1981
+ }
1982
+ }
1983
+
1984
+ /// A specified non-negative `<length>` | `<number>`.
1985
+ pub type NonNegativeLengthOrNumber = GenericLengthOrNumber<NonNegativeLength, NonNegativeNumber>;
1986
+
1987
+ /// A specified value for `margin` properties.
1988
+ pub type Margin = GenericMargin<LengthPercentage>;
1989
+
1990
+ impl Margin {
1991
+ /// Parses a margin type, allowing the unitless length quirk.
1992
+ /// <https://quirks.spec.whatwg.org/#the-unitless-length-quirk>
1993
+ #[inline]
1994
+ pub fn parse_quirky(
1995
+ context: &ParserContext,
1996
+ input: &mut Parser,
1997
+ allow_quirks: AllowQuirks,
1998
+ ) -> Result<Self, ParseError> {
1999
+ if let Ok(l) = input.try_parse(|i| LengthPercentage::parse_quirky(context, i, allow_quirks))
2000
+ {
2001
+ return Ok(Self::LengthPercentage(l));
2002
+ }
2003
+ match input.try_parse(|i| i.expect_ident_matching("auto")) {
2004
+ Ok(_) => return Ok(Self::Auto),
2005
+ Err(e) if !crate::pref!("layout.css.anchor-positioning.enabled", gecko = true) => {
2006
+ return Err(e.into())
2007
+ },
2008
+ Err(_) => (),
2009
+ };
2010
+ if let Ok(l) = input.try_parse(|i| {
2011
+ LengthPercentage::parse_quirky_with_anchor_size_function(context, i, allow_quirks)
2012
+ }) {
2013
+ return Ok(Self::AnchorContainingCalcFunction(l));
2014
+ }
2015
+ let inner = GenericAnchorSizeFunction::<Margin>::parse(context, input)?;
2016
+ Ok(Self::AnchorSizeFunction(Box::new(inner)))
2017
+ }
2018
+ }
2019
+
2020
+ impl Parse for Margin {
2021
+ fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ParseError> {
2022
+ Self::parse_quirky(context, input, AllowQuirks::No)
2023
+ }
2024
+ }