fullbleed 2.1.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.1.0 → fullbleed-2.2.0}/Cargo.toml +2 -1
  3. {fullbleed-2.1.0 → fullbleed-2.2.0}/PKG-INFO +30 -12
  4. {fullbleed-2.1.0 → fullbleed-2.2.0}/README.md +29 -11
  5. {fullbleed-2.1.0 → fullbleed-2.2.0}/pyproject.toml +1 -1
  6. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/_abi.py +19 -0
  7. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/core.py +21 -0
  8. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/assets.rs +7 -2
  9. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/canvas.rs +26 -0
  10. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/flowable.rs +5531 -470
  11. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/font.rs +427 -27
  12. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/font_subset.rs +1 -1
  13. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/html.rs +1943 -290
  14. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/image_native.rs +170 -0
  15. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/lib.rs +589 -16
  16. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/pdf.rs +681 -26
  17. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/python/abi_exports.rs +25 -0
  18. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/raster.rs +74 -11
  19. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/sfnt.rs +8 -0
  20. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/spill.rs +8 -3
  21. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/style.rs +4903 -371
  22. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/svg.rs +138 -10
  23. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/types.rs +1 -0
  24. fullbleed-2.1.0/Cargo.lock +0 -14
  25. {fullbleed-2.1.0 → fullbleed-2.2.0}/COPYRIGHT +0 -0
  26. {fullbleed-2.1.0 → fullbleed-2.2.0}/FONT_LICENSE_AUDIT.json +0 -0
  27. {fullbleed-2.1.0 → fullbleed-2.2.0}/FONT_LICENSE_AUDIT.md +0 -0
  28. {fullbleed-2.1.0 → fullbleed-2.2.0}/LICENSE +0 -0
  29. {fullbleed-2.1.0 → fullbleed-2.2.0}/LICENSING.md +0 -0
  30. {fullbleed-2.1.0 → fullbleed-2.2.0}/THIRD_PARTY_LICENSES.md +0 -0
  31. {fullbleed-2.1.0 → fullbleed-2.2.0}/build.rs +0 -0
  32. {fullbleed-2.1.0 → fullbleed-2.2.0}/build_backend/fullbleed_build_backend.py +0 -0
  33. {fullbleed-2.1.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/Cargo.lock +0 -0
  34. {fullbleed-2.1.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/Cargo.toml +0 -0
  35. {fullbleed-2.1.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/LICENSE +0 -0
  36. {fullbleed-2.1.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/README.md +0 -0
  37. {fullbleed-2.1.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/specs/fullbleed.audit_registry.v1.yaml +0 -0
  38. {fullbleed-2.1.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/specs/section508_html_registry.v1.yaml +0 -0
  39. {fullbleed-2.1.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/specs/wcag20aa_registry.v1.yaml +0 -0
  40. {fullbleed-2.1.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/src/json.rs +0 -0
  41. {fullbleed-2.1.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/src/lib.rs +0 -0
  42. {fullbleed-2.1.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/src/sha256.rs +0 -0
  43. {fullbleed-2.1.0 → fullbleed-2.2.0}/docs/specs/fullbleed.a11y.verify.v1.schema.json +0 -0
  44. {fullbleed-2.1.0 → fullbleed-2.2.0}/docs/specs/fullbleed.audit_registry.v1.yaml +0 -0
  45. {fullbleed-2.1.0 → fullbleed-2.2.0}/docs/specs/fullbleed.pmr.v1.schema.json +0 -0
  46. {fullbleed-2.1.0 → fullbleed-2.2.0}/docs/specs/section508_html_registry.v1.yaml +0 -0
  47. {fullbleed-2.1.0 → fullbleed-2.2.0}/docs/specs/wcag20aa_registry.v1.yaml +0 -0
  48. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/__init__.py +0 -0
  49. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/__main__.py +0 -0
  50. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/accessibility/__init__.py +0 -0
  51. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/accessibility/engine.py +0 -0
  52. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/accessibility/runtime.py +0 -0
  53. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/accessibility/types.py +0 -0
  54. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/audit_prototype.py +0 -0
  55. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/audit_section508.py +0 -0
  56. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/audit_wcag.py +0 -0
  57. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/__init__.py +0 -0
  58. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/accessibility.py +0 -0
  59. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/__init__.py +0 -0
  60. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/_core.py +0 -0
  61. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/agency_letter.py +0 -0
  62. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/court_motion_form.py +0 -0
  63. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/declaration_form.py +0 -0
  64. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/instruction_sheet.py +0 -0
  65. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/investment_portfolio_report.py +0 -0
  66. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/marriage_record.py +0 -0
  67. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/profiles.py +0 -0
  68. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/recorded_plat.py +0 -0
  69. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/redaction_request_form.py +0 -0
  70. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/warranty_deed.py +0 -0
  71. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/primitives.py +0 -0
  72. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed/ui/style.py +0 -0
  73. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_assets/__init__.py +0 -0
  74. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_assets/bootstrap.min.css +0 -0
  75. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_assets/fonts/Inter-Variable.ttf +0 -0
  76. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_assets/fonts/NotoSans-Regular.ttf +0 -0
  77. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_assets/fonts/NotoSansMath-Regular.ttf +0 -0
  78. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_assets/fonts/NotoSansSymbols-Regular.ttf +0 -0
  79. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_assets/fonts/NotoSansSymbols2-Regular.ttf +0 -0
  80. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_assets/icons/bootstrap-icons.svg +0 -0
  81. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/__init__.py +0 -0
  82. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/__main__.py +0 -0
  83. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/assets.py +0 -0
  84. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/cache.py +0 -0
  85. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/cli.py +0 -0
  86. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/finalize.py +0 -0
  87. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold.py +0 -0
  88. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/__init__.py +0 -0
  89. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/.gitignore +0 -0
  90. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/COMPLIANCE.md +0 -0
  91. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/SCAFFOLDING.md +0 -0
  92. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/__init__.py +0 -0
  93. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/body.py +0 -0
  94. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/fb_ui.py +0 -0
  95. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/footer.py +0 -0
  96. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/header.py +0 -0
  97. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/primitives.py +0 -0
  98. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/styles/body.css +0 -0
  99. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/styles/footer.css +0 -0
  100. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/styles/header.css +0 -0
  101. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/styles/primitives.css +0 -0
  102. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/report.py +0 -0
  103. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/styles/report.css +0 -0
  104. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/styles/tokens.css +0 -0
  105. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/README.md +0 -0
  106. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/output/.gitignore +0 -0
  107. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/output/.gitkeep +0 -0
  108. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/report.py +0 -0
  109. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/styles/report.css +0 -0
  110. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/vendor/fonts/Inter-Variable.ttf +0 -0
  111. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/invoice/output/.gitignore +0 -0
  112. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/invoice/output/.gitkeep +0 -0
  113. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/invoice/report.py +0 -0
  114. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/invoice/templates/invoice.css +0 -0
  115. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/invoice/templates/invoice.html +0 -0
  116. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/COMPLIANCE.md +0 -0
  117. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/README.md +0 -0
  118. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/SCAFFOLDING.md +0 -0
  119. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/assets/brand-mark.svg +0 -0
  120. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/assets/reference-pattern.svg +0 -0
  121. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/__init__.py +0 -0
  122. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/appendix.py +0 -0
  123. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/architecture.py +0 -0
  124. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/cover.py +0 -0
  125. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/data_pages.py +0 -0
  126. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/fb_ui.py +0 -0
  127. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/primitives.py +0 -0
  128. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/appendix.css +0 -0
  129. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/architecture.css +0 -0
  130. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/cover.css +0 -0
  131. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/data.css +0 -0
  132. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/primitives.css +0 -0
  133. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/visuals.css +0 -0
  134. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/visuals.py +0 -0
  135. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/data/reference.json +0 -0
  136. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/output/.gitignore +0 -0
  137. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/report.py +0 -0
  138. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/styles/report.css +0 -0
  139. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/styles/tokens.css +0 -0
  140. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/statement/output/.gitignore +0 -0
  141. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/statement/output/.gitkeep +0 -0
  142. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/statement/report.py +0 -0
  143. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/statement/templates/statement.css +0 -0
  144. {fullbleed-2.1.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/statement/templates/statement.html +0 -0
  145. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/base64.rs +0 -0
  146. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/css_native.rs +0 -0
  147. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/css_queries.rs +0 -0
  148. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/debug.rs +0 -0
  149. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/doc_context.rs +0 -0
  150. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/doc_template.rs +0 -0
  151. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/error.rs +0 -0
  152. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/finalize.rs +0 -0
  153. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/flate_native.rs +0 -0
  154. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/frame.rs +0 -0
  155. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/glyph_report.rs +0 -0
  156. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/html_dom.rs +0 -0
  157. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/html_entities.rs +0 -0
  158. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/html_entities_0.rs +0 -0
  159. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/html_entities_1.rs +0 -0
  160. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/html_entities_2.rs +0 -0
  161. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/html_entities_3.rs +0 -0
  162. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/html_entities_4.rs +0 -0
  163. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/html_entities_5.rs +0 -0
  164. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/jit.rs +0 -0
  165. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/jpeg_native.rs +0 -0
  166. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/math.rs +0 -0
  167. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/metrics.rs +0 -0
  168. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/native_shape.rs +0 -0
  169. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/page_data.rs +0 -0
  170. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/page_template.rs +0 -0
  171. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/parallel.rs +0 -0
  172. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/pdf_encodings.rs +0 -0
  173. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/pdf_native.rs +0 -0
  174. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/pdf_raster.rs +0 -0
  175. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/pdfinspect.rs +0 -0
  176. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/perf.rs +0 -0
  177. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/plan.rs +0 -0
  178. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/python.rs +0 -0
  179. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/python_abi.rs +0 -0
  180. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/raster_native.rs +0 -0
  181. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/sfnt_cff.rs +0 -0
  182. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/sfnt_outline.rs +0 -0
  183. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/text_shape.rs +0 -0
  184. {fullbleed-2.1.0 → fullbleed-2.2.0}/src/unicode_data.rs +0 -0
  185. {fullbleed-2.1.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.1.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.1.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
@@ -91,7 +91,8 @@ Additional focused references are in `docs/`:
91
91
  - Python-first extension surface for hackability and custom workflows.
92
92
  - Python render calls release the GIL while Rust rendering executes.
93
93
  - Ordered standard-library worker pools for batch rendering and selected internal workloads.
94
- - 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.
95
96
 
96
97
  ## Concurrency Model
97
98
 
@@ -100,11 +101,11 @@ Additional focused references are in `docs/`:
100
101
  - The same bounded worker implementation serves selected internal hotspots such as table layout and JIT paint paths.
101
102
  - Do not assume every single-document render path will fully saturate all cores end-to-end.
102
103
 
103
- ## Performance in 2.1
104
+ ## Performance in 2.2
104
105
 
105
- Fullbleed 2.1 embeds exact TrueType glyph subsets instead of complete source font programs. Across
106
- the five independent benchmark fixtures, PDFs are 95.5-97.3% smaller and ordinary warm rendering
107
- is 2.90x faster by geometric mean than released 2.0.0.
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.
108
109
 
109
110
  The new compile-once API freezes an immutable Q32.32 display document and can link it repeatedly
110
111
  without rerunning HTML parsing, selector matching, layout, pagination, or command planning. For
@@ -113,8 +114,20 @@ source page's content stream across the copied page dictionaries. The measured 2
113
114
  200.7x faster per page by geometric mean than the released 2.0.0 warm renderer; a 1,000-page stress
114
115
  run sustained 304,479-666,622 pages/s.
115
116
 
116
- That result is deliberately scoped to fixed compiled copies. It is not a claim that arbitrary new
117
- HTML or varying records render 200x faster. See
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
118
131
  [`docs/performance-pass-2026-08-04.md`](docs/performance-pass-2026-08-04.md) for measurements and
119
132
  [`docs/performance-architecture.md`](docs/performance-architecture.md) for the packed vector IR,
120
133
  typed-binding, virtual-linker, and shader roadmap.
@@ -130,7 +143,7 @@ python -m pip install fullbleed
130
143
  From a local wheel:
131
144
 
132
145
  ```bash
133
- python -m pip install C:\path\to\fullbleed-2.1.0-cp310-abi3-win_amd64.whl
146
+ python -m pip install C:\path\to\fullbleed-2.2.0-cp310-abi3-win_amd64.whl
134
147
  ```
135
148
 
136
149
  From a source checkout with Rust installed, no Python build package is needed:
@@ -972,9 +985,14 @@ Module exports:
972
985
  | `render_pdf(deterministic_hash=None)` | `bytes` |
973
986
  | `render_pdf_to_file(path, deterministic_hash=None)` | `int` |
974
987
  | `render_pdf_batch(copies, deterministic_hash=None)` | `bytes` |
975
-
976
- The compiled lane runs parsing/layout once. Its batch method writes one ordered PDF and virtualizes
977
- identical untagged page content to a shared stream; it is not a dynamic template-binding API.
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.
978
996
 
979
997
  When `deterministic_hash` is set, engine writes PDF SHA-256 to the provided file path.
980
998
 
@@ -54,7 +54,8 @@ Additional focused references are in `docs/`:
54
54
  - Python-first extension surface for hackability and custom workflows.
55
55
  - Python render calls release the GIL while Rust rendering executes.
56
56
  - Ordered standard-library worker pools for batch rendering and selected internal workloads.
57
- - 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.
58
59
 
59
60
  ## Concurrency Model
60
61
 
@@ -63,11 +64,11 @@ Additional focused references are in `docs/`:
63
64
  - The same bounded worker implementation serves selected internal hotspots such as table layout and JIT paint paths.
64
65
  - Do not assume every single-document render path will fully saturate all cores end-to-end.
65
66
 
66
- ## Performance in 2.1
67
+ ## Performance in 2.2
67
68
 
68
- Fullbleed 2.1 embeds exact TrueType glyph subsets instead of complete source font programs. Across
69
- the five independent benchmark fixtures, PDFs are 95.5-97.3% smaller and ordinary warm rendering
70
- is 2.90x faster by geometric mean than released 2.0.0.
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.
71
72
 
72
73
  The new compile-once API freezes an immutable Q32.32 display document and can link it repeatedly
73
74
  without rerunning HTML parsing, selector matching, layout, pagination, or command planning. For
@@ -76,8 +77,20 @@ source page's content stream across the copied page dictionaries. The measured 2
76
77
  200.7x faster per page by geometric mean than the released 2.0.0 warm renderer; a 1,000-page stress
77
78
  run sustained 304,479-666,622 pages/s.
78
79
 
79
- That result is deliberately scoped to fixed compiled copies. It is not a claim that arbitrary new
80
- HTML or varying records render 200x faster. See
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
81
94
  [`docs/performance-pass-2026-08-04.md`](docs/performance-pass-2026-08-04.md) for measurements and
82
95
  [`docs/performance-architecture.md`](docs/performance-architecture.md) for the packed vector IR,
83
96
  typed-binding, virtual-linker, and shader roadmap.
@@ -93,7 +106,7 @@ python -m pip install fullbleed
93
106
  From a local wheel:
94
107
 
95
108
  ```bash
96
- python -m pip install C:\path\to\fullbleed-2.1.0-cp310-abi3-win_amd64.whl
109
+ python -m pip install C:\path\to\fullbleed-2.2.0-cp310-abi3-win_amd64.whl
97
110
  ```
98
111
 
99
112
  From a source checkout with Rust installed, no Python build package is needed:
@@ -935,9 +948,14 @@ Module exports:
935
948
  | `render_pdf(deterministic_hash=None)` | `bytes` |
936
949
  | `render_pdf_to_file(path, deterministic_hash=None)` | `int` |
937
950
  | `render_pdf_batch(copies, deterministic_hash=None)` | `bytes` |
938
-
939
- The compiled lane runs parsing/layout once. Its batch method writes one ordered PDF and virtualizes
940
- identical untagged page content to a shared stream; it is not a dynamic template-binding API.
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.
941
959
 
942
960
  When `deterministic_hash` is set, engine writes PDF SHA-256 to the provided file path.
943
961
 
@@ -5,7 +5,7 @@ backend-path = ["build_backend"]
5
5
 
6
6
  [project]
7
7
  name = "fullbleed"
8
- version = "2.1.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"
@@ -200,6 +200,25 @@ class CompiledDocument(metaclass=_NativeFacadeType):
200
200
  deterministic_hash,
201
201
  )
202
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
+
203
222
 
204
223
  class PdfEngine(metaclass=_NativeFacadeType):
205
224
  __slots__ = ("_handle",)
@@ -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