fullbleed 2.3.0__tar.gz → 2.3.1__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.3.0 → fullbleed-2.3.1}/Cargo.lock +1 -1
- {fullbleed-2.3.0 → fullbleed-2.3.1}/Cargo.toml +1 -1
- {fullbleed-2.3.0 → fullbleed-2.3.1}/PKG-INFO +10 -4
- {fullbleed-2.3.0 → fullbleed-2.3.1}/README.md +9 -3
- {fullbleed-2.3.0 → fullbleed-2.3.1}/fullbleed-agent-contract.json +1 -1
- {fullbleed-2.3.0 → fullbleed-2.3.1}/llms.txt +1 -1
- {fullbleed-2.3.0 → fullbleed-2.3.1}/pyproject.toml +1 -1
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/flowable.rs +12 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/lib.rs +57 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/pdf.rs +150 -25
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/pdf_raster.rs +199 -12
- {fullbleed-2.3.0 → fullbleed-2.3.1}/COPYRIGHT +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/FONT_LICENSE_AUDIT.json +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/FONT_LICENSE_AUDIT.md +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/LICENSE +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/LICENSING.md +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/THIRD_PARTY_LICENSES.md +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/build.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/build_backend/fullbleed_build_backend.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/crates/fullbleed_audit_contract/Cargo.lock +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/crates/fullbleed_audit_contract/Cargo.toml +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/crates/fullbleed_audit_contract/LICENSE +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/crates/fullbleed_audit_contract/README.md +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/crates/fullbleed_audit_contract/specs/fullbleed.audit_registry.v1.yaml +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/crates/fullbleed_audit_contract/specs/section508_html_registry.v1.yaml +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/crates/fullbleed_audit_contract/specs/wcag20aa_registry.v1.yaml +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/crates/fullbleed_audit_contract/src/json.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/crates/fullbleed_audit_contract/src/lib.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/crates/fullbleed_audit_contract/src/sha256.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/docs/specs/fullbleed.a11y.verify.v1.schema.json +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/docs/specs/fullbleed.audit_registry.v1.yaml +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/docs/specs/fullbleed.pmr.v1.schema.json +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/docs/specs/section508_html_registry.v1.yaml +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/docs/specs/wcag20aa_registry.v1.yaml +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/__init__.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/__main__.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/_abi.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/accessibility/__init__.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/accessibility/engine.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/accessibility/runtime.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/accessibility/types.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/audit_prototype.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/audit_section508.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/audit_wcag.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/__init__.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/accessibility.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/cav/__init__.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/cav/_core.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/cav/agency_letter.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/cav/court_motion_form.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/cav/declaration_form.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/cav/instruction_sheet.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/cav/investment_portfolio_report.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/cav/marriage_record.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/cav/profiles.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/cav/recorded_plat.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/cav/redaction_request_form.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/cav/warranty_deed.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/core.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/primitives.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed/ui/style.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_assets/__init__.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_assets/bootstrap.min.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_assets/fonts/Inter-Variable.ttf +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_assets/fonts/NotoSans-Regular.ttf +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_assets/fonts/NotoSansMath-Regular.ttf +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_assets/fonts/NotoSansSymbols-Regular.ttf +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_assets/fonts/NotoSansSymbols2-Regular.ttf +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_assets/icons/bootstrap-icons.svg +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/__init__.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/__main__.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/agent.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/agent_acceptance.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/agent_contract.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/assets.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/cache.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/cli.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/finalize.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/mcp.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/__init__.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/.gitignore +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/AGENTS.md +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/COMPLIANCE.md +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/SCAFFOLDING.md +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/components/__init__.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/components/body.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/components/fb_ui.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/components/footer.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/components/header.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/components/primitives.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/components/styles/body.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/components/styles/footer.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/components/styles/header.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/components/styles/primitives.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/report.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/styles/report.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/init/styles/tokens.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/accessible/README.md +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/accessible/output/.gitignore +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/accessible/output/.gitkeep +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/accessible/report.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/accessible/styles/report.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/accessible/vendor/fonts/Inter-Variable.ttf +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/invoice/output/.gitignore +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/invoice/output/.gitkeep +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/invoice/report.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/invoice/templates/invoice.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/invoice/templates/invoice.html +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/COMPLIANCE.md +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/README.md +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/SCAFFOLDING.md +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/assets/brand-mark.svg +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/assets/reference-pattern.svg +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/components/__init__.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/components/appendix.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/components/architecture.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/components/cover.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/components/data_pages.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/components/fb_ui.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/components/primitives.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/appendix.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/architecture.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/cover.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/data.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/primitives.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/components/styles/visuals.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/components/visuals.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/data/reference.json +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/output/.gitignore +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/report.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/styles/report.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/reference/styles/tokens.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/statement/output/.gitignore +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/statement/output/.gitkeep +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/statement/report.py +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/statement/templates/statement.css +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/python/fullbleed_cli/scaffold_templates/new/statement/templates/statement.html +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/skills/fullbleed/SKILL.md +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/skills/fullbleed/agents/openai.yaml +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/skills/fullbleed/references/compliance.md +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/skills/fullbleed/references/selection.md +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/skills/fullbleed/references/workflows.md +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/assets.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/base64.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/canvas.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/css_native.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/css_queries.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/debug.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/doc_context.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/doc_template.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/error.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/finalize.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/flate_native.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/font.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/font_subset.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/frame.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/glyph_report.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/html.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/html_dom.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/html_entities.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/html_entities_0.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/html_entities_1.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/html_entities_2.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/html_entities_3.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/html_entities_4.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/html_entities_5.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/image_native.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/jit.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/jpeg_native.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/math.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/metrics.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/native_shape.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/page_data.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/page_template.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/parallel.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/pdf_encodings.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/pdf_native.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/pdfinspect.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/perf.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/plan.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/python/abi_exports.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/python.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/python_abi.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/raster.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/raster_native.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/sfnt.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/sfnt_cff.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/sfnt_outline.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/spill.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/style.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/svg.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/text_shape.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/types.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/unicode_data.rs +0 -0
- {fullbleed-2.3.0 → fullbleed-2.3.1}/src/xml.rs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fullbleed
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.1
|
|
4
4
|
Classifier: Development Status :: 5 - Production/Stable
|
|
5
5
|
Classifier: License :: OSI Approved :: MIT License
|
|
6
6
|
Classifier: Operating System :: MacOS
|
|
@@ -170,6 +170,11 @@ Fixed-geometry slots may remain inside immutable page-space transforms and clips
|
|
|
170
170
|
captures that active coordinate-state program once and replays it in each compact record overlay;
|
|
171
171
|
it does not rerun layout or clone the complete page display list.
|
|
172
172
|
|
|
173
|
+
Base-14/WinAnsi slot paint keeps the measured byte-patch linker. Registered embedded fonts use a
|
|
174
|
+
command-level overlay program so each bound value is shaped and included in the font subset while
|
|
175
|
+
the compiled layout, pagination, and static page stream remain shared. The throughput figures above
|
|
176
|
+
describe the Base-14 fast lane; they are not claims for registered-font shaping.
|
|
177
|
+
|
|
173
178
|
The fixed-copy result remains scoped to identical content; the variable-data result is scoped to
|
|
174
179
|
paint-only text whose geometry does not reflow. Neither is a claim that arbitrary new HTML or
|
|
175
180
|
size-changing records render 200x faster. See
|
|
@@ -208,7 +213,7 @@ python -m pip install fullbleed
|
|
|
208
213
|
From a local wheel:
|
|
209
214
|
|
|
210
215
|
```bash
|
|
211
|
-
python -m pip install C:\path\to\fullbleed-2.3.
|
|
216
|
+
python -m pip install C:\path\to\fullbleed-2.3.1-cp310-abi3-win_amd64.whl
|
|
212
217
|
```
|
|
213
218
|
|
|
214
219
|
From a source checkout with Rust installed, no Python build package is needed:
|
|
@@ -1079,8 +1084,9 @@ Module exports:
|
|
|
1079
1084
|
The compiled lane runs parsing/layout once. `render_pdf_batch` virtualizes identical untagged page
|
|
1080
1085
|
content. The fixed binding methods accept columnar `dict[str, list[str]]` data and emit distinct
|
|
1081
1086
|
fixed-geometry text overlays per record while sharing static paint. They require exact slot keys,
|
|
1082
|
-
equal non-zero column lengths, page-local
|
|
1083
|
-
|
|
1087
|
+
equal non-zero column lengths, page-local text, and an untagged profile. Base-14 text uses the
|
|
1088
|
+
direct byte-patch lane; registered fonts are shaped into a command-level overlay. Bound values do
|
|
1089
|
+
not trigger layout or reflow.
|
|
1084
1090
|
|
|
1085
1091
|
The reflow binding methods use the same exact-column contract but execute the compiled parsed-DOM
|
|
1086
1092
|
program. `{{slot}}` values are literal text and may reshape, wrap, resize blocks, and change page
|
|
@@ -127,6 +127,11 @@ Fixed-geometry slots may remain inside immutable page-space transforms and clips
|
|
|
127
127
|
captures that active coordinate-state program once and replays it in each compact record overlay;
|
|
128
128
|
it does not rerun layout or clone the complete page display list.
|
|
129
129
|
|
|
130
|
+
Base-14/WinAnsi slot paint keeps the measured byte-patch linker. Registered embedded fonts use a
|
|
131
|
+
command-level overlay program so each bound value is shaped and included in the font subset while
|
|
132
|
+
the compiled layout, pagination, and static page stream remain shared. The throughput figures above
|
|
133
|
+
describe the Base-14 fast lane; they are not claims for registered-font shaping.
|
|
134
|
+
|
|
130
135
|
The fixed-copy result remains scoped to identical content; the variable-data result is scoped to
|
|
131
136
|
paint-only text whose geometry does not reflow. Neither is a claim that arbitrary new HTML or
|
|
132
137
|
size-changing records render 200x faster. See
|
|
@@ -165,7 +170,7 @@ python -m pip install fullbleed
|
|
|
165
170
|
From a local wheel:
|
|
166
171
|
|
|
167
172
|
```bash
|
|
168
|
-
python -m pip install C:\path\to\fullbleed-2.3.
|
|
173
|
+
python -m pip install C:\path\to\fullbleed-2.3.1-cp310-abi3-win_amd64.whl
|
|
169
174
|
```
|
|
170
175
|
|
|
171
176
|
From a source checkout with Rust installed, no Python build package is needed:
|
|
@@ -1036,8 +1041,9 @@ Module exports:
|
|
|
1036
1041
|
The compiled lane runs parsing/layout once. `render_pdf_batch` virtualizes identical untagged page
|
|
1037
1042
|
content. The fixed binding methods accept columnar `dict[str, list[str]]` data and emit distinct
|
|
1038
1043
|
fixed-geometry text overlays per record while sharing static paint. They require exact slot keys,
|
|
1039
|
-
equal non-zero column lengths, page-local
|
|
1040
|
-
|
|
1044
|
+
equal non-zero column lengths, page-local text, and an untagged profile. Base-14 text uses the
|
|
1045
|
+
direct byte-patch lane; registered fonts are shaped into a command-level overlay. Bound values do
|
|
1046
|
+
not trigger layout or reflow.
|
|
1041
1047
|
|
|
1042
1048
|
The reflow binding methods use the same exact-column contract but execute the compiled parsed-DOM
|
|
1043
1049
|
program. `{{slot}}` values are literal text and may reshape, wrap, resize blocks, and change page
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Fullbleed PDF Engine
|
|
2
2
|
|
|
3
|
-
> Fullbleed 2.3.
|
|
3
|
+
> Fullbleed 2.3.1 is a deterministic, self-contained document-generation runtime for Python and Rust. It turns structured data plus static HTML/CSS into validated PDF documents without a browser.
|
|
4
4
|
|
|
5
5
|
The installed runtime is authoritative. Do not infer its API from this file or from remembered release knowledge. Start with:
|
|
6
6
|
|
|
@@ -5,7 +5,7 @@ backend-path = ["build_backend"]
|
|
|
5
5
|
|
|
6
6
|
[project]
|
|
7
7
|
name = "fullbleed"
|
|
8
|
-
version = "2.3.
|
|
8
|
+
version = "2.3.1"
|
|
9
9
|
description = "Deterministic Python PDF engine for reports, invoices, accessible documents, print-ready output, and compiled VDP"
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
requires-python = ">=3.10"
|
|
@@ -5600,6 +5600,7 @@ fn draw_registered_text_run(
|
|
|
5600
5600
|
y: Pt,
|
|
5601
5601
|
text: String,
|
|
5602
5602
|
) {
|
|
5603
|
+
let contains_binding_slot = !crate::binding_slot_names(&text).is_empty();
|
|
5603
5604
|
let text = crate::text_shape::encode_shape_options(&text, text_shape_options(style));
|
|
5604
5605
|
let synthetic_bold = style.font_synthesis_weight
|
|
5605
5606
|
&& !style.font_face_satisfies_weight
|
|
@@ -5614,6 +5615,17 @@ fn draw_registered_text_run(
|
|
|
5614
5615
|
&& registry.requires_synthetic_italic(font_name);
|
|
5615
5616
|
let strength = (style.font_size * (1.0 / 32.0)).max(Pt::from_f32(0.25));
|
|
5616
5617
|
let italic_shear = synthetic_italic_shear(style.font_style);
|
|
5618
|
+
// Fixed VDP substitutes slot values after layout. Keep binding-bearing
|
|
5619
|
+
// text as a patchable text command instead of compiling the placeholder's
|
|
5620
|
+
// glyph IDs into the reusable Type 3 synthetic-bold shader.
|
|
5621
|
+
if contains_binding_slot && synthetic_bold {
|
|
5622
|
+
if synthetic_italic {
|
|
5623
|
+
canvas.draw_string_synthetic_bold_italic(x, y, text, strength, italic_shear);
|
|
5624
|
+
} else {
|
|
5625
|
+
canvas.draw_string_synthetic_bold(x, y, text, strength);
|
|
5626
|
+
}
|
|
5627
|
+
return;
|
|
5628
|
+
}
|
|
5617
5629
|
match (synthetic_bold, synthetic_italic) {
|
|
5618
5630
|
(true, true) if style.css_pixel_snap_metrics => {
|
|
5619
5631
|
if draw_registered_synthetic_bold_outline_run(
|
|
@@ -14264,6 +14264,63 @@ h1 { font-size: 20pt; }
|
|
|
14264
14264
|
));
|
|
14265
14265
|
}
|
|
14266
14266
|
|
|
14267
|
+
#[test]
|
|
14268
|
+
fn compiled_document_binds_registered_identity_h_fonts_without_literal_slots() {
|
|
14269
|
+
let mut bundle = AssetBundle::default();
|
|
14270
|
+
bundle.add(Asset::new(
|
|
14271
|
+
"VdpCustom".to_string(),
|
|
14272
|
+
AssetKind::Font,
|
|
14273
|
+
std::fs::read(repo_font_path("NotoSans-Regular.ttf")).expect("read custom font"),
|
|
14274
|
+
None,
|
|
14275
|
+
true,
|
|
14276
|
+
));
|
|
14277
|
+
let engine = FullBleed::builder()
|
|
14278
|
+
.register_bundle(bundle)
|
|
14279
|
+
.build()
|
|
14280
|
+
.expect("engine");
|
|
14281
|
+
let compiled = engine
|
|
14282
|
+
.compile_document(
|
|
14283
|
+
"<main><h1>{{attendee}}</h1><p>{{role}}</p><strong>{{seat}}</strong></main>",
|
|
14284
|
+
"@page { size: 260pt 140pt; margin: 12pt; } body { margin: 0; font-family: VdpCustom; font-weight: 400; } h1 { font-size: 20pt; font-weight: 700; }",
|
|
14285
|
+
)
|
|
14286
|
+
.expect("compile registered-font template");
|
|
14287
|
+
let bindings = std::collections::HashMap::from([
|
|
14288
|
+
(
|
|
14289
|
+
"attendee".to_string(),
|
|
14290
|
+
vec!["ADA RIVERA".to_string(), "GRACE HOPPER".to_string()],
|
|
14291
|
+
),
|
|
14292
|
+
(
|
|
14293
|
+
"role".to_string(),
|
|
14294
|
+
vec!["RESEARCHER".to_string(), "ENGINEER".to_string()],
|
|
14295
|
+
),
|
|
14296
|
+
(
|
|
14297
|
+
"seat".to_string(),
|
|
14298
|
+
vec!["A12".to_string(), "B07".to_string()],
|
|
14299
|
+
),
|
|
14300
|
+
]);
|
|
14301
|
+
let pdf = compiled
|
|
14302
|
+
.render_bindings_to_buffer(&bindings)
|
|
14303
|
+
.expect("registered-font fixed bindings");
|
|
14304
|
+
let inspection = inspect_pdf_bytes(&pdf).expect("inspect binding output");
|
|
14305
|
+
assert_eq!(inspection.page_count, 2);
|
|
14306
|
+
|
|
14307
|
+
let parsed = crate::pdf_native::Document::load_mem(&pdf).expect("parse binding PDF");
|
|
14308
|
+
let page_numbers = parsed.get_pages().keys().copied().collect::<Vec<_>>();
|
|
14309
|
+
let text = parsed
|
|
14310
|
+
.extract_text_chunks(&page_numbers)
|
|
14311
|
+
.into_iter()
|
|
14312
|
+
.collect::<crate::pdf_native::Result<Vec<_>>>()
|
|
14313
|
+
.expect("extract registered-font bindings")
|
|
14314
|
+
.join("\n");
|
|
14315
|
+
assert!(text.contains("ADA RIVERA"));
|
|
14316
|
+
assert!(text.contains("GRACE HOPPER"));
|
|
14317
|
+
assert!(text.contains("RESEARCHER"));
|
|
14318
|
+
assert!(text.contains("ENGINEER"));
|
|
14319
|
+
assert!(text.contains("A12"));
|
|
14320
|
+
assert!(text.contains("B07"));
|
|
14321
|
+
assert!(!text.contains("{{"));
|
|
14322
|
+
}
|
|
14323
|
+
|
|
14267
14324
|
#[test]
|
|
14268
14325
|
fn compiled_reflow_bindings_reuse_dom_and_generate_variable_page_counts() {
|
|
14269
14326
|
let engine = FullBleed::builder().build().expect("engine");
|
|
@@ -438,14 +438,21 @@ struct BindingPageProgram {
|
|
|
438
438
|
static_content_id: usize,
|
|
439
439
|
static_content_len: usize,
|
|
440
440
|
geometry: PageGeometry,
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
441
|
+
dynamic: BindingDynamicProgram,
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
enum BindingDynamicProgram {
|
|
445
|
+
Patched {
|
|
446
|
+
segments: Vec<BindingContentSegment>,
|
|
447
|
+
capacity: usize,
|
|
448
|
+
},
|
|
449
|
+
Commands(Page),
|
|
444
450
|
}
|
|
445
451
|
|
|
446
452
|
struct CompiledBindingPage {
|
|
447
453
|
static_page: Page,
|
|
448
454
|
overlay_page: Page,
|
|
455
|
+
dynamic_slot_occurrences: usize,
|
|
449
456
|
}
|
|
450
457
|
|
|
451
458
|
/// Immutable command partition produced once for a compiled template.
|
|
@@ -558,10 +565,102 @@ fn instantiate_binding_content(
|
|
|
558
565
|
}
|
|
559
566
|
}
|
|
560
567
|
|
|
568
|
+
fn instantiate_binding_text(
|
|
569
|
+
template: &str,
|
|
570
|
+
slot_lookup: &HashMap<String, usize>,
|
|
571
|
+
columns: &[&[String]],
|
|
572
|
+
row: usize,
|
|
573
|
+
) -> String {
|
|
574
|
+
let spans = crate::binding_slot_spans(template);
|
|
575
|
+
if spans.is_empty() {
|
|
576
|
+
return template.to_string();
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
let mut output = String::with_capacity(template.len().saturating_add(32));
|
|
580
|
+
let mut cursor = 0usize;
|
|
581
|
+
for (start, end, name) in spans {
|
|
582
|
+
output.push_str(&template[cursor..start]);
|
|
583
|
+
if let Some(slot_index) = slot_lookup.get(name) {
|
|
584
|
+
output.push_str(&columns[*slot_index][row]);
|
|
585
|
+
} else {
|
|
586
|
+
output.push_str(&template[start..end]);
|
|
587
|
+
}
|
|
588
|
+
cursor = end;
|
|
589
|
+
}
|
|
590
|
+
output.push_str(&template[cursor..]);
|
|
591
|
+
output
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
fn instantiate_binding_overlay_page(
|
|
595
|
+
template: &Page,
|
|
596
|
+
slot_lookup: &HashMap<String, usize>,
|
|
597
|
+
columns: &[&[String]],
|
|
598
|
+
row: usize,
|
|
599
|
+
) -> Page {
|
|
600
|
+
let commands = template
|
|
601
|
+
.commands
|
|
602
|
+
.iter()
|
|
603
|
+
.map(|command| match command {
|
|
604
|
+
Command::DrawString { x, y, text } => Command::DrawString {
|
|
605
|
+
x: *x,
|
|
606
|
+
y: *y,
|
|
607
|
+
text: instantiate_binding_text(text, slot_lookup, columns, row),
|
|
608
|
+
},
|
|
609
|
+
Command::DrawStringTransformed {
|
|
610
|
+
x,
|
|
611
|
+
y,
|
|
612
|
+
text,
|
|
613
|
+
m00,
|
|
614
|
+
m01,
|
|
615
|
+
m10,
|
|
616
|
+
m11,
|
|
617
|
+
} => Command::DrawStringTransformed {
|
|
618
|
+
x: *x,
|
|
619
|
+
y: *y,
|
|
620
|
+
text: instantiate_binding_text(text, slot_lookup, columns, row),
|
|
621
|
+
m00: *m00,
|
|
622
|
+
m01: *m01,
|
|
623
|
+
m10: *m10,
|
|
624
|
+
m11: *m11,
|
|
625
|
+
},
|
|
626
|
+
_ => command.clone(),
|
|
627
|
+
})
|
|
628
|
+
.collect();
|
|
629
|
+
Page { commands }
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
fn binding_overlay_uses_registered_font(page: &Page, registry: Option<&FontRegistry>) -> bool {
|
|
633
|
+
let Some(registry) = registry else {
|
|
634
|
+
return false;
|
|
635
|
+
};
|
|
636
|
+
let mut font_name = "Helvetica".to_string();
|
|
637
|
+
let mut stack = Vec::new();
|
|
638
|
+
for command in &page.commands {
|
|
639
|
+
match command {
|
|
640
|
+
Command::SaveState => stack.push(font_name.clone()),
|
|
641
|
+
Command::RestoreState => {
|
|
642
|
+
if let Some(saved) = stack.pop() {
|
|
643
|
+
font_name = saved;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
Command::SetFontName(value) => font_name.clone_from(value),
|
|
647
|
+
Command::DrawString { text, .. } | Command::DrawStringTransformed { text, .. }
|
|
648
|
+
if !crate::binding_slot_names(text).is_empty()
|
|
649
|
+
&& registry.resolve(&font_name).is_some() =>
|
|
650
|
+
{
|
|
651
|
+
return true;
|
|
652
|
+
}
|
|
653
|
+
_ => {}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
false
|
|
657
|
+
}
|
|
658
|
+
|
|
561
659
|
#[derive(Clone)]
|
|
562
660
|
struct BindingPaintState {
|
|
563
661
|
font_name: String,
|
|
564
662
|
font_size: Pt,
|
|
663
|
+
line_width: Pt,
|
|
565
664
|
fill: Color,
|
|
566
665
|
stroke: Color,
|
|
567
666
|
opacity_fill: f32,
|
|
@@ -575,6 +674,7 @@ impl Default for BindingPaintState {
|
|
|
575
674
|
Self {
|
|
576
675
|
font_name: "Helvetica".to_string(),
|
|
577
676
|
font_size: Pt::from_f32(12.0),
|
|
677
|
+
line_width: Pt::from_f32(1.0),
|
|
578
678
|
fill: Color::BLACK,
|
|
579
679
|
stroke: Color::BLACK,
|
|
580
680
|
opacity_fill: 1.0,
|
|
@@ -683,6 +783,7 @@ fn binding_overlay_commands(
|
|
|
683
783
|
Command::SetBlendMode { mode } => state.blend_mode = *mode,
|
|
684
784
|
Command::SetFontName(value) => state.font_name.clone_from(value),
|
|
685
785
|
Command::SetFontSize(value) => state.font_size = *value,
|
|
786
|
+
Command::SetLineWidth(value) => state.line_width = *value,
|
|
686
787
|
Command::SetTextRenderingMode(value) => state.text_rendering_mode = *value,
|
|
687
788
|
Command::DefineForm { commands, .. } | Command::DefineIsolatedForm { commands, .. }
|
|
688
789
|
if commands_contain_binding_marker(commands) =>
|
|
@@ -724,6 +825,7 @@ fn binding_overlay_commands(
|
|
|
724
825
|
}
|
|
725
826
|
overlay.push(Command::SetFontName(state.font_name.clone()));
|
|
726
827
|
overlay.push(Command::SetFontSize(state.font_size));
|
|
828
|
+
overlay.push(Command::SetLineWidth(state.line_width));
|
|
727
829
|
if state.text_rendering_mode != 0 {
|
|
728
830
|
overlay.push(Command::SetTextRenderingMode(state.text_rendering_mode));
|
|
729
831
|
}
|
|
@@ -774,6 +876,7 @@ fn binding_overlay_commands(
|
|
|
774
876
|
}
|
|
775
877
|
overlay.push(Command::SetFontName(state.font_name.clone()));
|
|
776
878
|
overlay.push(Command::SetFontSize(state.font_size));
|
|
879
|
+
overlay.push(Command::SetLineWidth(state.line_width));
|
|
777
880
|
if state.text_rendering_mode != 0 {
|
|
778
881
|
overlay.push(Command::SetTextRenderingMode(state.text_rendering_mode));
|
|
779
882
|
}
|
|
@@ -812,7 +915,11 @@ pub(crate) fn compile_binding_plan(
|
|
|
812
915
|
let (overlay_commands, page_slot_counts) =
|
|
813
916
|
binding_overlay_commands(&page.commands, &slot_lookup)?;
|
|
814
917
|
let static_commands = binding_static_commands(&page.commands, &slot_lookup);
|
|
815
|
-
|
|
918
|
+
let dynamic_slot_occurrences = page_slot_counts.iter().copied().sum();
|
|
919
|
+
for (total, count) in total_slot_counts
|
|
920
|
+
.iter_mut()
|
|
921
|
+
.zip(page_slot_counts.iter().copied())
|
|
922
|
+
{
|
|
816
923
|
*total = total.saturating_add(count);
|
|
817
924
|
}
|
|
818
925
|
static_command_count = static_command_count.saturating_add(static_commands.len());
|
|
@@ -824,6 +931,7 @@ pub(crate) fn compile_binding_plan(
|
|
|
824
931
|
overlay_page: Page {
|
|
825
932
|
commands: overlay_commands,
|
|
826
933
|
},
|
|
934
|
+
dynamic_slot_occurrences,
|
|
827
935
|
});
|
|
828
936
|
}
|
|
829
937
|
|
|
@@ -1587,47 +1695,64 @@ impl<'a, W: Write> PdfStreamWriter<'a, W> {
|
|
|
1587
1695
|
self.write_content_stream_object(static_content_id, "", static_content.as_bytes())?;
|
|
1588
1696
|
self.page_content_stream_count = self.page_content_stream_count.saturating_add(1);
|
|
1589
1697
|
|
|
1590
|
-
let
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1698
|
+
let dynamic = if binding_overlay_uses_registered_font(&page.overlay_page, self.registry)
|
|
1699
|
+
{
|
|
1700
|
+
BindingDynamicProgram::Commands(page.overlay_page.clone())
|
|
1701
|
+
} else {
|
|
1702
|
+
let overlay_template =
|
|
1703
|
+
self.render_page_sized(&page.overlay_page, page_index, geometry)?;
|
|
1704
|
+
let (segments, occurrences, static_bytes) =
|
|
1705
|
+
compile_binding_content_segments(&overlay_template, &binding_plan.slot_lookup);
|
|
1706
|
+
if occurrences == page.dynamic_slot_occurrences {
|
|
1707
|
+
BindingDynamicProgram::Patched {
|
|
1708
|
+
segments,
|
|
1709
|
+
capacity: static_bytes.saturating_add(128),
|
|
1710
|
+
}
|
|
1711
|
+
} else {
|
|
1712
|
+
BindingDynamicProgram::Commands(page.overlay_page.clone())
|
|
1713
|
+
}
|
|
1714
|
+
};
|
|
1600
1715
|
programs.push(BindingPageProgram {
|
|
1601
1716
|
static_content_id,
|
|
1602
1717
|
static_content_len: static_content.len(),
|
|
1603
1718
|
geometry,
|
|
1604
|
-
|
|
1605
|
-
dynamic_capacity: dynamic_static_bytes.saturating_add(128),
|
|
1606
|
-
dynamic_slot_occurrences,
|
|
1719
|
+
dynamic,
|
|
1607
1720
|
});
|
|
1608
1721
|
}
|
|
1609
1722
|
|
|
1610
1723
|
let max_dynamic_capacity = programs
|
|
1611
1724
|
.iter()
|
|
1612
|
-
.
|
|
1725
|
+
.filter_map(|program| match &program.dynamic {
|
|
1726
|
+
BindingDynamicProgram::Patched { capacity, .. } => Some(*capacity),
|
|
1727
|
+
BindingDynamicProgram::Commands(_) => None,
|
|
1728
|
+
})
|
|
1613
1729
|
.max()
|
|
1614
1730
|
.unwrap_or(0);
|
|
1615
1731
|
let mut dynamic_content = Vec::with_capacity(max_dynamic_capacity);
|
|
1616
1732
|
for row in 0..record_count {
|
|
1617
1733
|
for program in &programs {
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1734
|
+
match &program.dynamic {
|
|
1735
|
+
BindingDynamicProgram::Patched { segments, .. } => {
|
|
1736
|
+
instantiate_binding_content(segments, columns, row, &mut dynamic_content);
|
|
1737
|
+
}
|
|
1738
|
+
BindingDynamicProgram::Commands(template) => {
|
|
1739
|
+
let overlay = instantiate_binding_overlay_page(
|
|
1740
|
+
template,
|
|
1741
|
+
&binding_plan.slot_lookup,
|
|
1742
|
+
columns,
|
|
1743
|
+
row,
|
|
1744
|
+
);
|
|
1745
|
+
dynamic_content = self
|
|
1746
|
+
.render_page_sized(&overlay, self.page_ids.len(), program.geometry)?
|
|
1747
|
+
.into_bytes();
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1624
1750
|
self.add_bound_page(
|
|
1625
1751
|
program.static_content_id,
|
|
1626
1752
|
program.static_content_len,
|
|
1627
1753
|
&dynamic_content,
|
|
1628
1754
|
program.geometry,
|
|
1629
1755
|
)?;
|
|
1630
|
-
debug_assert!(program.dynamic_slot_occurrences > 0);
|
|
1631
1756
|
}
|
|
1632
1757
|
}
|
|
1633
1758
|
Ok(())
|