fullbleed 2.0.0__tar.gz → 2.2.0__tar.gz

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 (185) hide show
  1. fullbleed-2.2.0/Cargo.lock +30 -0
  2. {fullbleed-2.0.0 → fullbleed-2.2.0}/Cargo.toml +2 -1
  3. {fullbleed-2.0.0 → fullbleed-2.2.0}/PKG-INFO +56 -3
  4. {fullbleed-2.0.0 → fullbleed-2.2.0}/README.md +55 -2
  5. {fullbleed-2.0.0 → fullbleed-2.2.0}/pyproject.toml +1 -1
  6. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/_abi.py +73 -1
  7. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/core.py +21 -0
  8. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/assets.rs +7 -2
  9. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/canvas.rs +26 -0
  10. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/flowable.rs +5531 -470
  11. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/font.rs +637 -21
  12. fullbleed-2.2.0/src/font_subset.rs +554 -0
  13. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html.rs +1943 -290
  14. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/image_native.rs +170 -0
  15. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/jit.rs +15 -13
  16. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/lib.rs +873 -17
  17. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/pdf.rs +954 -39
  18. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/python/abi_exports.rs +112 -1
  19. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/raster.rs +74 -11
  20. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/sfnt.rs +8 -0
  21. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/spill.rs +8 -3
  22. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/style.rs +4903 -371
  23. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/svg.rs +138 -10
  24. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/types.rs +1 -0
  25. fullbleed-2.0.0/Cargo.lock +0 -14
  26. {fullbleed-2.0.0 → fullbleed-2.2.0}/COPYRIGHT +0 -0
  27. {fullbleed-2.0.0 → fullbleed-2.2.0}/FONT_LICENSE_AUDIT.json +0 -0
  28. {fullbleed-2.0.0 → fullbleed-2.2.0}/FONT_LICENSE_AUDIT.md +0 -0
  29. {fullbleed-2.0.0 → fullbleed-2.2.0}/LICENSE +0 -0
  30. {fullbleed-2.0.0 → fullbleed-2.2.0}/LICENSING.md +0 -0
  31. {fullbleed-2.0.0 → fullbleed-2.2.0}/THIRD_PARTY_LICENSES.md +0 -0
  32. {fullbleed-2.0.0 → fullbleed-2.2.0}/build.rs +0 -0
  33. {fullbleed-2.0.0 → fullbleed-2.2.0}/build_backend/fullbleed_build_backend.py +0 -0
  34. {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/Cargo.lock +0 -0
  35. {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/Cargo.toml +0 -0
  36. {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/LICENSE +0 -0
  37. {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/README.md +0 -0
  38. {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/specs/fullbleed.audit_registry.v1.yaml +0 -0
  39. {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/specs/section508_html_registry.v1.yaml +0 -0
  40. {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/specs/wcag20aa_registry.v1.yaml +0 -0
  41. {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/src/json.rs +0 -0
  42. {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/src/lib.rs +0 -0
  43. {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/src/sha256.rs +0 -0
  44. {fullbleed-2.0.0 → fullbleed-2.2.0}/docs/specs/fullbleed.a11y.verify.v1.schema.json +0 -0
  45. {fullbleed-2.0.0 → fullbleed-2.2.0}/docs/specs/fullbleed.audit_registry.v1.yaml +0 -0
  46. {fullbleed-2.0.0 → fullbleed-2.2.0}/docs/specs/fullbleed.pmr.v1.schema.json +0 -0
  47. {fullbleed-2.0.0 → fullbleed-2.2.0}/docs/specs/section508_html_registry.v1.yaml +0 -0
  48. {fullbleed-2.0.0 → fullbleed-2.2.0}/docs/specs/wcag20aa_registry.v1.yaml +0 -0
  49. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/__init__.py +0 -0
  50. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/__main__.py +0 -0
  51. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/accessibility/__init__.py +0 -0
  52. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/accessibility/engine.py +0 -0
  53. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/accessibility/runtime.py +0 -0
  54. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/accessibility/types.py +0 -0
  55. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/audit_prototype.py +0 -0
  56. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/audit_section508.py +0 -0
  57. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/audit_wcag.py +0 -0
  58. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/__init__.py +0 -0
  59. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/accessibility.py +0 -0
  60. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/__init__.py +0 -0
  61. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/_core.py +0 -0
  62. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/agency_letter.py +0 -0
  63. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/court_motion_form.py +0 -0
  64. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/declaration_form.py +0 -0
  65. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/instruction_sheet.py +0 -0
  66. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/investment_portfolio_report.py +0 -0
  67. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/marriage_record.py +0 -0
  68. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/profiles.py +0 -0
  69. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/recorded_plat.py +0 -0
  70. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/redaction_request_form.py +0 -0
  71. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/warranty_deed.py +0 -0
  72. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/primitives.py +0 -0
  73. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/style.py +0 -0
  74. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/__init__.py +0 -0
  75. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/bootstrap.min.css +0 -0
  76. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/fonts/Inter-Variable.ttf +0 -0
  77. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/fonts/NotoSans-Regular.ttf +0 -0
  78. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/fonts/NotoSansMath-Regular.ttf +0 -0
  79. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/fonts/NotoSansSymbols-Regular.ttf +0 -0
  80. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/fonts/NotoSansSymbols2-Regular.ttf +0 -0
  81. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/icons/bootstrap-icons.svg +0 -0
  82. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/__init__.py +0 -0
  83. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/__main__.py +0 -0
  84. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/assets.py +0 -0
  85. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/cache.py +0 -0
  86. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/cli.py +0 -0
  87. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/finalize.py +0 -0
  88. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold.py +0 -0
  89. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/__init__.py +0 -0
  90. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/.gitignore +0 -0
  91. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/COMPLIANCE.md +0 -0
  92. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/SCAFFOLDING.md +0 -0
  93. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/__init__.py +0 -0
  94. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/body.py +0 -0
  95. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/fb_ui.py +0 -0
  96. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/footer.py +0 -0
  97. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/header.py +0 -0
  98. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/primitives.py +0 -0
  99. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/styles/body.css +0 -0
  100. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/styles/footer.css +0 -0
  101. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/styles/header.css +0 -0
  102. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/styles/primitives.css +0 -0
  103. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/report.py +0 -0
  104. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/styles/report.css +0 -0
  105. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/styles/tokens.css +0 -0
  106. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/README.md +0 -0
  107. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/output/.gitignore +0 -0
  108. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/output/.gitkeep +0 -0
  109. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/report.py +0 -0
  110. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/styles/report.css +0 -0
  111. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/vendor/fonts/Inter-Variable.ttf +0 -0
  112. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/invoice/output/.gitignore +0 -0
  113. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/invoice/output/.gitkeep +0 -0
  114. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/invoice/report.py +0 -0
  115. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/invoice/templates/invoice.css +0 -0
  116. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/invoice/templates/invoice.html +0 -0
  117. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/COMPLIANCE.md +0 -0
  118. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/README.md +0 -0
  119. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/SCAFFOLDING.md +0 -0
  120. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/assets/brand-mark.svg +0 -0
  121. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/assets/reference-pattern.svg +0 -0
  122. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/__init__.py +0 -0
  123. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/appendix.py +0 -0
  124. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/architecture.py +0 -0
  125. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/cover.py +0 -0
  126. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/data_pages.py +0 -0
  127. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/fb_ui.py +0 -0
  128. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/primitives.py +0 -0
  129. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/appendix.css +0 -0
  130. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/architecture.css +0 -0
  131. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/cover.css +0 -0
  132. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/data.css +0 -0
  133. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/primitives.css +0 -0
  134. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/visuals.css +0 -0
  135. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/visuals.py +0 -0
  136. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/data/reference.json +0 -0
  137. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/output/.gitignore +0 -0
  138. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/report.py +0 -0
  139. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/styles/report.css +0 -0
  140. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/styles/tokens.css +0 -0
  141. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/statement/output/.gitignore +0 -0
  142. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/statement/output/.gitkeep +0 -0
  143. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/statement/report.py +0 -0
  144. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/statement/templates/statement.css +0 -0
  145. {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/statement/templates/statement.html +0 -0
  146. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/base64.rs +0 -0
  147. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/css_native.rs +0 -0
  148. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/css_queries.rs +0 -0
  149. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/debug.rs +0 -0
  150. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/doc_context.rs +0 -0
  151. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/doc_template.rs +0 -0
  152. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/error.rs +0 -0
  153. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/finalize.rs +0 -0
  154. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/flate_native.rs +0 -0
  155. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/frame.rs +0 -0
  156. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/glyph_report.rs +0 -0
  157. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_dom.rs +0 -0
  158. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_entities.rs +0 -0
  159. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_entities_0.rs +0 -0
  160. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_entities_1.rs +0 -0
  161. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_entities_2.rs +0 -0
  162. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_entities_3.rs +0 -0
  163. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_entities_4.rs +0 -0
  164. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_entities_5.rs +0 -0
  165. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/jpeg_native.rs +0 -0
  166. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/math.rs +0 -0
  167. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/metrics.rs +0 -0
  168. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/native_shape.rs +0 -0
  169. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/page_data.rs +0 -0
  170. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/page_template.rs +0 -0
  171. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/parallel.rs +0 -0
  172. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/pdf_encodings.rs +0 -0
  173. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/pdf_native.rs +0 -0
  174. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/pdf_raster.rs +0 -0
  175. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/pdfinspect.rs +0 -0
  176. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/perf.rs +0 -0
  177. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/plan.rs +0 -0
  178. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/python.rs +0 -0
  179. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/python_abi.rs +0 -0
  180. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/raster_native.rs +0 -0
  181. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/sfnt_cff.rs +0 -0
  182. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/sfnt_outline.rs +0 -0
  183. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/text_shape.rs +0 -0
  184. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/unicode_data.rs +0 -0
  185. {fullbleed-2.0.0 → fullbleed-2.2.0}/src/xml.rs +0 -0
@@ -0,0 +1,30 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "fullbleed"
7
+ version = "2.2.0"
8
+ dependencies = [
9
+ "fullbleed_audit_contract",
10
+ "subsetter",
11
+ ]
12
+
13
+ [[package]]
14
+ name = "fullbleed_audit_contract"
15
+ version = "0.1.2"
16
+
17
+ [[package]]
18
+ name = "rustc-hash"
19
+ version = "2.1.3"
20
+ source = "registry+https://github.com/rust-lang/crates.io-index"
21
+ checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d"
22
+
23
+ [[package]]
24
+ name = "subsetter"
25
+ version = "0.2.6"
26
+ source = "registry+https://github.com/rust-lang/crates.io-index"
27
+ checksum = "38803281d1c23166c5ebcb455439a5d2afe711cc909cf88af72448c297756ad6"
28
+ dependencies = [
29
+ "rustc-hash",
30
+ ]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "fullbleed"
3
- version = "2.0.0"
3
+ version = "2.2.0"
4
4
  edition = "2024"
5
5
  rust-version = "1.85"
6
6
  license = "MIT"
@@ -38,3 +38,4 @@ debug = true
38
38
 
39
39
  [dependencies]
40
40
  fullbleed_audit_contract = { version = "0.1.2", path = "crates/fullbleed_audit_contract" }
41
+ subsetter = { version = "0.2.6", default-features = false }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fullbleed
3
- Version: 2.0.0
3
+ Version: 2.2.0
4
4
  Classifier: Development Status :: 5 - Production/Stable
5
5
  Classifier: License :: OSI Approved :: MIT License
6
6
  Classifier: Operating System :: MacOS
@@ -69,6 +69,8 @@ Additional focused references are in `docs/`:
69
69
  - `docs/css-coverage.md` (validated CSS coverage, parity status, and active gaps)
70
70
  - `docs/README.md`
71
71
  - `docs/engine.md`
72
+ - `docs/performance-architecture.md`
73
+ - `docs/performance-pass-2026-08-04.md`
72
74
  - `docs/python-api.md`
73
75
  - `docs/ui-accessibility.md`
74
76
  - `docs/cli.md`
@@ -89,7 +91,8 @@ Additional focused references are in `docs/`:
89
91
  - Python-first extension surface for hackability and custom workflows.
90
92
  - Python render calls release the GIL while Rust rendering executes.
91
93
  - Ordered standard-library worker pools for batch rendering and selected internal workloads.
92
- - No third-party Rust crate graph and no required third-party Python runtime or build packages.
94
+ - A deliberately small, license-audited Rust dependency graph and no required third-party Python
95
+ runtime or build packages.
93
96
 
94
97
  ## Concurrency Model
95
98
 
@@ -98,6 +101,37 @@ Additional focused references are in `docs/`:
98
101
  - The same bounded worker implementation serves selected internal hotspots such as table layout and JIT paint paths.
99
102
  - Do not assume every single-document render path will fully saturate all cores end-to-end.
100
103
 
104
+ ## Performance in 2.2
105
+
106
+ Fullbleed 2.2 retains exact TrueType glyph subsetting and adds compiled fixed-geometry variable-data
107
+ binding. Across the five independent benchmark fixtures, PDFs are 95.5-97.3% smaller and ordinary
108
+ warm rendering is 2.90x faster by geometric mean than released 2.0.0.
109
+
110
+ The new compile-once API freezes an immutable Q32.32 display document and can link it repeatedly
111
+ without rerunning HTML parsing, selector matching, layout, pagination, or command planning. For
112
+ identical untagged copies in one ordered PDF, `CompiledDocument.render_pdf_batch(...)` shares each
113
+ source page's content stream across the copied page dictionaries. The measured 20-copy lane is
114
+ 200.7x faster per page by geometric mean than the released 2.0.0 warm renderer; a 1,000-page stress
115
+ run sustained 304,479-666,622 pages/s.
116
+
117
+ The 2.2 compiler includes a genuine fixed-geometry variable-data lane. A compiled invoice
118
+ with six bound fields rendered 100,000 distinct records in a five-run median of 283.807 ms to
119
+ memory (**352,352 pages/s**) and 295.999 ms directly to a flushed 88.1 MB PDF
120
+ (**337,839 pages/s**). Including the one-time 4.168 ms compile gives 333,147 direct-file pages/s.
121
+ The harness verified all 100,000 unique invoice IDs in page order, exact page count, resolved
122
+ markers, deterministic bytes, and equal buffer/file SHA-256. Reproduce it with:
123
+
124
+ ```bash
125
+ python tools/benchmark_fullbleed_vdp.py --records 100000 --repeats 5
126
+ ```
127
+
128
+ The fixed-copy result remains scoped to identical content; the variable-data result is scoped to
129
+ paint-only text whose geometry does not reflow. Neither is a claim that arbitrary new HTML or
130
+ size-changing records render 200x faster. See
131
+ [`docs/performance-pass-2026-08-04.md`](docs/performance-pass-2026-08-04.md) for measurements and
132
+ [`docs/performance-architecture.md`](docs/performance-architecture.md) for the packed vector IR,
133
+ typed-binding, virtual-linker, and shader roadmap.
134
+
101
135
  ## Install
102
136
 
103
137
  New to Python or setting up on a fresh machine? Start with `docs/install-non-technical.md`.
@@ -109,7 +143,7 @@ python -m pip install fullbleed
109
143
  From a local wheel:
110
144
 
111
145
  ```bash
112
- python -m pip install C:\path\to\fullbleed-2.0.0-cp310-abi3-win_amd64.whl
146
+ python -m pip install C:\path\to\fullbleed-2.2.0-cp310-abi3-win_amd64.whl
113
147
  ```
114
148
 
115
149
  From a source checkout with Rust installed, no Python build package is needed:
@@ -904,6 +938,7 @@ PdfEngine(
904
938
  Module exports:
905
939
 
906
940
  - `PdfEngine`
941
+ - `CompiledDocument`
907
942
  - `AssetBundle`
908
943
  - `Asset`
909
944
  - `AssetKind`
@@ -921,6 +956,7 @@ Module exports:
921
956
  | Method | Return shape |
922
957
  | --- | --- |
923
958
  | `register_bundle(bundle)` | `None` |
959
+ | `compile_pdf(html, css)` | `CompiledDocument` |
924
960
  | `render_pdf(html, css, deterministic_hash=None)` | `bytes` |
925
961
  | `render_pdf_to_file(html, css, path, deterministic_hash=None)` | `int` (bytes written) |
926
962
  | `render_image_pages(html, css, dpi=150)` | `list[bytes]` |
@@ -941,6 +977,23 @@ Module exports:
941
977
  | `render_pdf_batch_with_css(jobs, deterministic_hash=None)` | `bytes` |
942
978
  | `render_pdf_batch_with_css_to_file(jobs, path, deterministic_hash=None)` | `int` |
943
979
 
980
+ `CompiledDocument` methods:
981
+
982
+ | Method | Return shape |
983
+ | --- | --- |
984
+ | `stats()` | `dict` |
985
+ | `render_pdf(deterministic_hash=None)` | `bytes` |
986
+ | `render_pdf_to_file(path, deterministic_hash=None)` | `int` |
987
+ | `render_pdf_batch(copies, deterministic_hash=None)` | `bytes` |
988
+ | `render_pdf_bindings(bindings, deterministic_hash=None)` | `bytes` |
989
+ | `render_pdf_bindings_to_file(bindings, path, deterministic_hash=None)` | `int` |
990
+
991
+ The compiled lane runs parsing/layout once. `render_pdf_batch` virtualizes identical untagged page
992
+ content. The binding methods instead accept columnar `dict[str, list[str]]` data and emit distinct
993
+ fixed-geometry text overlays per record while sharing static paint. They require exact slot keys,
994
+ equal non-zero column lengths, page-local WinAnsi-compatible text, and an untagged profile; bound
995
+ values do not trigger reflow.
996
+
944
997
  When `deterministic_hash` is set, engine writes PDF SHA-256 to the provided file path.
945
998
 
946
999
  `AssetBundle` methods:
@@ -32,6 +32,8 @@ Additional focused references are in `docs/`:
32
32
  - `docs/css-coverage.md` (validated CSS coverage, parity status, and active gaps)
33
33
  - `docs/README.md`
34
34
  - `docs/engine.md`
35
+ - `docs/performance-architecture.md`
36
+ - `docs/performance-pass-2026-08-04.md`
35
37
  - `docs/python-api.md`
36
38
  - `docs/ui-accessibility.md`
37
39
  - `docs/cli.md`
@@ -52,7 +54,8 @@ Additional focused references are in `docs/`:
52
54
  - Python-first extension surface for hackability and custom workflows.
53
55
  - Python render calls release the GIL while Rust rendering executes.
54
56
  - Ordered standard-library worker pools for batch rendering and selected internal workloads.
55
- - No third-party Rust crate graph and no required third-party Python runtime or build packages.
57
+ - A deliberately small, license-audited Rust dependency graph and no required third-party Python
58
+ runtime or build packages.
56
59
 
57
60
  ## Concurrency Model
58
61
 
@@ -61,6 +64,37 @@ Additional focused references are in `docs/`:
61
64
  - The same bounded worker implementation serves selected internal hotspots such as table layout and JIT paint paths.
62
65
  - Do not assume every single-document render path will fully saturate all cores end-to-end.
63
66
 
67
+ ## Performance in 2.2
68
+
69
+ Fullbleed 2.2 retains exact TrueType glyph subsetting and adds compiled fixed-geometry variable-data
70
+ binding. Across the five independent benchmark fixtures, PDFs are 95.5-97.3% smaller and ordinary
71
+ warm rendering is 2.90x faster by geometric mean than released 2.0.0.
72
+
73
+ The new compile-once API freezes an immutable Q32.32 display document and can link it repeatedly
74
+ without rerunning HTML parsing, selector matching, layout, pagination, or command planning. For
75
+ identical untagged copies in one ordered PDF, `CompiledDocument.render_pdf_batch(...)` shares each
76
+ source page's content stream across the copied page dictionaries. The measured 20-copy lane is
77
+ 200.7x faster per page by geometric mean than the released 2.0.0 warm renderer; a 1,000-page stress
78
+ run sustained 304,479-666,622 pages/s.
79
+
80
+ The 2.2 compiler includes a genuine fixed-geometry variable-data lane. A compiled invoice
81
+ with six bound fields rendered 100,000 distinct records in a five-run median of 283.807 ms to
82
+ memory (**352,352 pages/s**) and 295.999 ms directly to a flushed 88.1 MB PDF
83
+ (**337,839 pages/s**). Including the one-time 4.168 ms compile gives 333,147 direct-file pages/s.
84
+ The harness verified all 100,000 unique invoice IDs in page order, exact page count, resolved
85
+ markers, deterministic bytes, and equal buffer/file SHA-256. Reproduce it with:
86
+
87
+ ```bash
88
+ python tools/benchmark_fullbleed_vdp.py --records 100000 --repeats 5
89
+ ```
90
+
91
+ The fixed-copy result remains scoped to identical content; the variable-data result is scoped to
92
+ paint-only text whose geometry does not reflow. Neither is a claim that arbitrary new HTML or
93
+ size-changing records render 200x faster. See
94
+ [`docs/performance-pass-2026-08-04.md`](docs/performance-pass-2026-08-04.md) for measurements and
95
+ [`docs/performance-architecture.md`](docs/performance-architecture.md) for the packed vector IR,
96
+ typed-binding, virtual-linker, and shader roadmap.
97
+
64
98
  ## Install
65
99
 
66
100
  New to Python or setting up on a fresh machine? Start with `docs/install-non-technical.md`.
@@ -72,7 +106,7 @@ python -m pip install fullbleed
72
106
  From a local wheel:
73
107
 
74
108
  ```bash
75
- python -m pip install C:\path\to\fullbleed-2.0.0-cp310-abi3-win_amd64.whl
109
+ python -m pip install C:\path\to\fullbleed-2.2.0-cp310-abi3-win_amd64.whl
76
110
  ```
77
111
 
78
112
  From a source checkout with Rust installed, no Python build package is needed:
@@ -867,6 +901,7 @@ PdfEngine(
867
901
  Module exports:
868
902
 
869
903
  - `PdfEngine`
904
+ - `CompiledDocument`
870
905
  - `AssetBundle`
871
906
  - `Asset`
872
907
  - `AssetKind`
@@ -884,6 +919,7 @@ Module exports:
884
919
  | Method | Return shape |
885
920
  | --- | --- |
886
921
  | `register_bundle(bundle)` | `None` |
922
+ | `compile_pdf(html, css)` | `CompiledDocument` |
887
923
  | `render_pdf(html, css, deterministic_hash=None)` | `bytes` |
888
924
  | `render_pdf_to_file(html, css, path, deterministic_hash=None)` | `int` (bytes written) |
889
925
  | `render_image_pages(html, css, dpi=150)` | `list[bytes]` |
@@ -904,6 +940,23 @@ Module exports:
904
940
  | `render_pdf_batch_with_css(jobs, deterministic_hash=None)` | `bytes` |
905
941
  | `render_pdf_batch_with_css_to_file(jobs, path, deterministic_hash=None)` | `int` |
906
942
 
943
+ `CompiledDocument` methods:
944
+
945
+ | Method | Return shape |
946
+ | --- | --- |
947
+ | `stats()` | `dict` |
948
+ | `render_pdf(deterministic_hash=None)` | `bytes` |
949
+ | `render_pdf_to_file(path, deterministic_hash=None)` | `int` |
950
+ | `render_pdf_batch(copies, deterministic_hash=None)` | `bytes` |
951
+ | `render_pdf_bindings(bindings, deterministic_hash=None)` | `bytes` |
952
+ | `render_pdf_bindings_to_file(bindings, path, deterministic_hash=None)` | `int` |
953
+
954
+ The compiled lane runs parsing/layout once. `render_pdf_batch` virtualizes identical untagged page
955
+ content. The binding methods instead accept columnar `dict[str, list[str]]` data and emit distinct
956
+ fixed-geometry text overlays per record while sharing static paint. They require exact slot keys,
957
+ equal non-zero column lengths, page-local WinAnsi-compatible text, and an untagged profile; bound
958
+ values do not trigger reflow.
959
+
907
960
  When `deterministic_hash` is set, engine writes PDF SHA-256 to the provided file path.
908
961
 
909
962
  `AssetBundle` methods:
@@ -5,7 +5,7 @@ backend-path = ["build_backend"]
5
5
 
6
6
  [project]
7
7
  name = "fullbleed"
8
- version = "2.0.0"
8
+ version = "2.2.0"
9
9
  description = "Deterministic static HTML/CSS-to-PDF renderer built in Rust"
10
10
  readme = "README.md"
11
11
  requires-python = ">=3.10"
@@ -160,6 +160,66 @@ class WatermarkSpec(metaclass=_NativeFacadeType):
160
160
  }
161
161
 
162
162
 
163
+ class CompiledDocument(metaclass=_NativeFacadeType):
164
+ """Immutable fixed-point display document produced by ``PdfEngine.compile_pdf``."""
165
+
166
+ __slots__ = ("_handle",)
167
+
168
+ def __init__(self, /):
169
+ raise TypeError("No constructor defined for CompiledDocument")
170
+
171
+ @classmethod
172
+ def _from_handle(cls, /, handle):
173
+ instance = object.__new__(cls)
174
+ instance._handle = handle
175
+ return instance
176
+
177
+ def stats(self, /):
178
+ return _call(self._handle, "CompiledDocument.stats")
179
+
180
+ def render_pdf(self, /, deterministic_hash=None):
181
+ return _call(
182
+ self._handle,
183
+ "CompiledDocument.render_pdf",
184
+ deterministic_hash,
185
+ )
186
+
187
+ def render_pdf_to_file(self, /, path, deterministic_hash=None):
188
+ return _call(
189
+ self._handle,
190
+ "CompiledDocument.render_pdf_to_file",
191
+ path,
192
+ deterministic_hash,
193
+ )
194
+
195
+ def render_pdf_batch(self, /, copies, deterministic_hash=None):
196
+ return _call(
197
+ self._handle,
198
+ "CompiledDocument.render_pdf_batch",
199
+ copies,
200
+ deterministic_hash,
201
+ )
202
+
203
+ def render_pdf_bindings(self, /, bindings, deterministic_hash=None):
204
+ """Render one fixed-geometry page set per row of columnar text bindings."""
205
+ return _call(
206
+ self._handle,
207
+ "CompiledDocument.render_pdf_bindings",
208
+ bindings,
209
+ deterministic_hash,
210
+ )
211
+
212
+ def render_pdf_bindings_to_file(self, /, bindings, path, deterministic_hash=None):
213
+ """Stream a columnar fixed-geometry binding batch directly to ``path``."""
214
+ return _call(
215
+ self._handle,
216
+ "CompiledDocument.render_pdf_bindings_to_file",
217
+ bindings,
218
+ path,
219
+ deterministic_hash,
220
+ )
221
+
222
+
163
223
  class PdfEngine(metaclass=_NativeFacadeType):
164
224
  __slots__ = ("_handle",)
165
225
 
@@ -500,6 +560,10 @@ class PdfEngine(metaclass=_NativeFacadeType):
500
560
  def render_pdf(self, /, html, css, deterministic_hash=None):
501
561
  return _call(self._handle, "PdfEngine.render_pdf", html, css, deterministic_hash)
502
562
 
563
+ def compile_pdf(self, /, html, css):
564
+ handle = _call(self._handle, "PdfEngine.compile_pdf", html, css)
565
+ return CompiledDocument._from_handle(handle)
566
+
503
567
  def render_image_pages(self, /, html, css, dpi=150):
504
568
  return _call(self._handle, "PdfEngine.render_image_pages", html, css, dpi)
505
569
 
@@ -811,6 +875,7 @@ def audit_sparse_page_visual_pair(source_png_path, render_png_path):
811
875
 
812
876
  __all__ = [
813
877
  "PdfEngine",
878
+ "CompiledDocument",
814
879
  "AssetKind",
815
880
  "Asset",
816
881
  "AssetBundle",
@@ -836,7 +901,14 @@ __all__ = [
836
901
  ]
837
902
 
838
903
 
839
- _CLASS_NAMES = {"PdfEngine", "AssetKind", "Asset", "AssetBundle", "WatermarkSpec"}
904
+ _CLASS_NAMES = {
905
+ "PdfEngine",
906
+ "CompiledDocument",
907
+ "AssetKind",
908
+ "Asset",
909
+ "AssetBundle",
910
+ "WatermarkSpec",
911
+ }
840
912
  for _name in __all__:
841
913
  globals()[_name].__module__ = (
842
914
  "builtins" if _name in _CLASS_NAMES else "fullbleed._fullbleed"
@@ -9,6 +9,25 @@ from typing import Any, Callable
9
9
  from .style import style_to_css
10
10
 
11
11
 
12
+ _HTML_VOID_ELEMENTS = frozenset(
13
+ {
14
+ "area",
15
+ "base",
16
+ "br",
17
+ "col",
18
+ "embed",
19
+ "hr",
20
+ "img",
21
+ "input",
22
+ "link",
23
+ "meta",
24
+ "source",
25
+ "track",
26
+ "wbr",
27
+ }
28
+ )
29
+
30
+
12
31
  def _normalize_css_href(value: str | None) -> str | None:
13
32
  if value is None:
14
33
  return None
@@ -256,6 +275,8 @@ def render_node(node: Any) -> str:
256
275
  return ""
257
276
  if isinstance(node, Element):
258
277
  attrs = _render_attrs(node.props)
278
+ if node.tag.casefold() in _HTML_VOID_ELEMENTS:
279
+ return f"<{node.tag}{attrs}>"
259
280
  children_html = "".join(render_node(child) for child in node.children)
260
281
  return f"<{node.tag}{attrs}>{children_html}</{node.tag}>"
261
282
  return escape(str(node))
@@ -115,7 +115,10 @@ pub fn is_supported_font_path(path: &Path) -> bool {
115
115
  let Some(ext) = path.extension().and_then(|v| v.to_str()) else {
116
116
  return false;
117
117
  };
118
- matches!(ext.to_ascii_lowercase().as_str(), "ttf" | "otf")
118
+ matches!(
119
+ ext.to_ascii_lowercase().as_str(),
120
+ "ttf" | "otf" | "ttc" | "otc"
121
+ )
119
122
  }
120
123
 
121
124
  #[cfg_attr(not(feature = "python"), allow(dead_code))]
@@ -512,9 +515,11 @@ mod tests {
512
515
  }
513
516
 
514
517
  #[test]
515
- fn supported_font_path_accepts_ttf_and_otf() {
518
+ fn supported_font_path_accepts_sfnt_fonts_and_collections() {
516
519
  assert!(super::is_supported_font_path(Path::new("demo.ttf")));
517
520
  assert!(super::is_supported_font_path(Path::new("demo.otf")));
521
+ assert!(super::is_supported_font_path(Path::new("demo.ttc")));
522
+ assert!(super::is_supported_font_path(Path::new("demo.otc")));
518
523
  assert!(!super::is_supported_font_path(Path::new("demo.woff2")));
519
524
  }
520
525
 
@@ -164,6 +164,7 @@ pub enum Command {
164
164
  height: Pt,
165
165
  resource_id: String,
166
166
  filter: PaintFilterSpec,
167
+ css_shadow: bool,
167
168
  },
168
169
  BeginTag {
169
170
  role: String,
@@ -365,6 +366,10 @@ impl Canvas {
365
366
  self.current.commands.push(Command::SetStrokeColor(color));
366
367
  }
367
368
 
369
+ pub(crate) fn set_stroke_color_to_fill(&mut self) {
370
+ self.set_stroke_color(self.current_state.fill_color);
371
+ }
372
+
368
373
  pub fn set_line_width(&mut self, width: Pt) {
369
374
  let width = if width < Pt::ZERO { Pt::ZERO } else { width };
370
375
  if self.current_state.line_width == width {
@@ -703,6 +708,27 @@ impl Canvas {
703
708
  height,
704
709
  resource_id: resource_id.into(),
705
710
  filter,
711
+ css_shadow: false,
712
+ });
713
+ }
714
+
715
+ pub fn draw_css_shadow_filtered_form(
716
+ &mut self,
717
+ x: Pt,
718
+ y: Pt,
719
+ width: Pt,
720
+ height: Pt,
721
+ resource_id: impl Into<String>,
722
+ filter: PaintFilterSpec,
723
+ ) {
724
+ self.current.commands.push(Command::DrawFilteredForm {
725
+ x,
726
+ y,
727
+ width,
728
+ height,
729
+ resource_id: resource_id.into(),
730
+ filter,
731
+ css_shadow: true,
706
732
  });
707
733
  }
708
734