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.
- fullbleed-2.2.0/Cargo.lock +30 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/Cargo.toml +2 -1
- {fullbleed-2.0.0 → fullbleed-2.2.0}/PKG-INFO +56 -3
- {fullbleed-2.0.0 → fullbleed-2.2.0}/README.md +55 -2
- {fullbleed-2.0.0 → fullbleed-2.2.0}/pyproject.toml +1 -1
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/_abi.py +73 -1
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/core.py +21 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/assets.rs +7 -2
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/canvas.rs +26 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/flowable.rs +5531 -470
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/font.rs +637 -21
- fullbleed-2.2.0/src/font_subset.rs +554 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html.rs +1943 -290
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/image_native.rs +170 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/jit.rs +15 -13
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/lib.rs +873 -17
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/pdf.rs +954 -39
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/python/abi_exports.rs +112 -1
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/raster.rs +74 -11
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/sfnt.rs +8 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/spill.rs +8 -3
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/style.rs +4903 -371
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/svg.rs +138 -10
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/types.rs +1 -0
- fullbleed-2.0.0/Cargo.lock +0 -14
- {fullbleed-2.0.0 → fullbleed-2.2.0}/COPYRIGHT +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/FONT_LICENSE_AUDIT.json +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/FONT_LICENSE_AUDIT.md +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/LICENSE +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/LICENSING.md +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/THIRD_PARTY_LICENSES.md +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/build.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/build_backend/fullbleed_build_backend.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/Cargo.lock +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/Cargo.toml +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/LICENSE +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/README.md +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/specs/fullbleed.audit_registry.v1.yaml +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/specs/section508_html_registry.v1.yaml +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/specs/wcag20aa_registry.v1.yaml +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/src/json.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/src/lib.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/crates/fullbleed_audit_contract/src/sha256.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/docs/specs/fullbleed.a11y.verify.v1.schema.json +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/docs/specs/fullbleed.audit_registry.v1.yaml +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/docs/specs/fullbleed.pmr.v1.schema.json +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/docs/specs/section508_html_registry.v1.yaml +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/docs/specs/wcag20aa_registry.v1.yaml +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/__init__.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/__main__.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/accessibility/__init__.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/accessibility/engine.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/accessibility/runtime.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/accessibility/types.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/audit_prototype.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/audit_section508.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/audit_wcag.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/__init__.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/accessibility.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/__init__.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/_core.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/agency_letter.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/court_motion_form.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/declaration_form.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/instruction_sheet.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/investment_portfolio_report.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/marriage_record.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/profiles.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/recorded_plat.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/redaction_request_form.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/cav/warranty_deed.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/primitives.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed/ui/style.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/__init__.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/bootstrap.min.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/fonts/Inter-Variable.ttf +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/fonts/NotoSans-Regular.ttf +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/fonts/NotoSansMath-Regular.ttf +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/fonts/NotoSansSymbols-Regular.ttf +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/fonts/NotoSansSymbols2-Regular.ttf +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_assets/icons/bootstrap-icons.svg +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/__init__.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/__main__.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/assets.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/cache.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/cli.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/finalize.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/__init__.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/.gitignore +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/COMPLIANCE.md +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/SCAFFOLDING.md +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/__init__.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/body.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/fb_ui.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/footer.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/header.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/primitives.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/styles/body.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/styles/footer.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/styles/header.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/components/styles/primitives.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/report.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/styles/report.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/init/styles/tokens.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/README.md +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/output/.gitignore +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/output/.gitkeep +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/report.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/styles/report.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/accessible/vendor/fonts/Inter-Variable.ttf +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/invoice/output/.gitignore +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/invoice/output/.gitkeep +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/invoice/report.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/invoice/templates/invoice.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/invoice/templates/invoice.html +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/COMPLIANCE.md +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/README.md +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/SCAFFOLDING.md +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/assets/brand-mark.svg +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/assets/reference-pattern.svg +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/__init__.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/appendix.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/architecture.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/cover.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/data_pages.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/fb_ui.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/primitives.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/appendix.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/architecture.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/cover.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/data.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/primitives.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/visuals.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/components/visuals.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/data/reference.json +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/output/.gitignore +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/report.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/styles/report.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/reference/styles/tokens.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/statement/output/.gitignore +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/statement/output/.gitkeep +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/statement/report.py +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/statement/templates/statement.css +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/python/fullbleed_cli/scaffold_templates/new/statement/templates/statement.html +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/base64.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/css_native.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/css_queries.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/debug.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/doc_context.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/doc_template.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/error.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/finalize.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/flate_native.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/frame.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/glyph_report.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_dom.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_entities.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_entities_0.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_entities_1.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_entities_2.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_entities_3.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_entities_4.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/html_entities_5.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/jpeg_native.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/math.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/metrics.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/native_shape.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/page_data.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/page_template.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/parallel.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/pdf_encodings.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/pdf_native.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/pdf_raster.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/pdfinspect.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/perf.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/plan.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/python.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/python_abi.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/raster_native.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/sfnt_cff.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/sfnt_outline.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/text_shape.rs +0 -0
- {fullbleed-2.0.0 → fullbleed-2.2.0}/src/unicode_data.rs +0 -0
- {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.
|
|
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.
|
|
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
|
-
-
|
|
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.
|
|
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
|
-
-
|
|
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.
|
|
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:
|
|
@@ -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 = {
|
|
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!(
|
|
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
|
|
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
|
|