docvortex 0.4.20__tar.gz → 0.4.21__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.
- {docvortex-0.4.20/src/docvortex.egg-info → docvortex-0.4.21}/PKG-INFO +1 -1
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/pdf/inline.py +12 -2
- docvortex-0.4.21/src/docvortex/render/_internal/pdf/paragraph.py +250 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/version.py +1 -1
- {docvortex-0.4.20 → docvortex-0.4.21/src/docvortex.egg-info}/PKG-INFO +1 -1
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex.egg-info/SOURCES.txt +1 -0
- docvortex-0.4.21/tests/unittest/test_pdf_cjk_objects.py +229 -0
- docvortex-0.4.20/src/docvortex/render/_internal/pdf/paragraph.py +0 -123
- {docvortex-0.4.20 → docvortex-0.4.21}/LICENSE.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/MANIFEST.in +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/README.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/README.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/demo.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/office_docs/README.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/office_docs/docx_01.doc +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/office_docs/docx_01.docx +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/office_docs/pptx_01.ppt +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/office_docs/pptx_01.pptx +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/office_docs/rtf_01.rtf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/office_docs/xlsx_01.xls +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/office_docs/xlsx_01.xlsx +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs/2407.00079v4_origi-10.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs/IEBM_A_2667169_O-5.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs/caibao1.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs/demo1.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs/demo2.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs/demo3.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs/demo4.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs/demo6.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs/mixed_elements_pages_03_06.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs/mixed_elements_pages_07_10.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs/mixed_elements_pages_11_15.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs/mixed_elements_pages_39_40.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs/small_ocr.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs//344/270/255/346/226/207/350/256/272/346/226/207.pdf" +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs//344/270/255/346/226/207/350/256/272/346/226/2072.pdf" +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs//344/270/255/346/226/207/350/256/272/346/226/2073.pdf" +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/demo/pdfs//344/270/255/346/226/207/350/256/272/346/226/2074.pdf" +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/docs/HTML_PROTOCOL.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/docs/JSON_PROTOCOL.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/docs/METADATA.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/docs/PDF_FONTS.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/docs/RENDER_OWNERSHIP.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/docs/USAGE.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/docs/flash-manual-annotations-2026-09-15.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/docs/flash-round2-annotations-2026-09-15.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/docs/flash-rule-generalization-2026-09-15.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/docs/flash-spatial-layout-followup-2026-09-16.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/docs/flash-spatial-layout-round3-2026-09-16.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/docs/flash-title-coverage-2026-09-16.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/docs/sdk-0.4.md +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/pyproject.toml +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/schemas/middle-2.0.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/schemas/model-2.0.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/setup.cfg +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/_shared/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/_shared/hyperlink.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/_shared/image.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/_shared/markup/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/_shared/markup/anchors.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/_shared/markup/formula.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/_shared/markup/projector.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/_shared/markup/styles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/_shared/mathml.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/_shared/names.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/_shared/xycut.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/contracts.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/csv.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/epub/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/epub/constants.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/epub/converter.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/epub/errors.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/epub/metadata.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/epub/package.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/epub/properties.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/epub/xhtml.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/html/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/html/anchors.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/html/constants.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/html/converter.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/html/document.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/html/errors.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/html/metadata.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/html/resources.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/html/selector.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/models.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/assembly.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/constants.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/converter.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/errors.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/geometry.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/images.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/metadata.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/models.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/package.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/path.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/reading_order.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/resources.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/scene.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/table.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/text.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/ofd/vector.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/doc/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/doc/bookmarks.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/doc/doc_converter.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/doc/fib.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/doc/fields.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/doc/formatting.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/doc/images.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/doc/lists.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/doc/models.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/doc/parser.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/doc/pieces.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/doc/records.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/doc/sprm.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/doc/styles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/docx/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/docx/context.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/docx/docx_converter.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/docx/equationxml.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/docx/fields.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/docx/formatting_types.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/docx/main.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/docx/numbering.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/docx/office_xml.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/docx/package_normalizer.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/docx/resources.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/docx/styles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/docx/tables.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/equation/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/equation/image.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/equation/latex_dict.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/equation/mtef.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/equation/mtef_v5.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/equation/omml.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/equation/ooxml.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/errors.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/image.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/legacy/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/legacy/binary.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/legacy/officeart.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/legacy/ole.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/limits.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/metadata.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/odf/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/odf/chart.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/odf/constants.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/odf/converters.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/odf/errors.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/odf/metadata.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/odf/models.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/odf/package.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/odf/styles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/odf/table.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/odf/text.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/ooxml_chart.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/opc.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/ppt/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/ppt/models.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/ppt/parser.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/ppt/ppt_converter.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/ppt/records.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/ppt/style_text.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/pptx/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/pptx/context.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/pptx/lists.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/pptx/main.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/pptx/package_normalizer.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/pptx/pptx_converter.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/pptx/resources.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/pptx/shapes.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/pptx/text_styles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/pptx/titles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/rich_text.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/rtf/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/rtf/converter.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/rtf/lexer.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/rtf/math.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/rtf/metadata.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/rtf/models.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/rtf/parser.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/spreadsheet/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/spreadsheet/html.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/spreadsheet/models.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/spreadsheet/projector.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/spreadsheet/region_discovery.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/streams.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/xls/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/xls/chart.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/xls/embedded_chart.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/xls/models.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/xls/number_format.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/xls/parser.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/xls/records.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/xls/strings.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/xls/xls_converter.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/xlsx/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/xlsx/main.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/xlsx/ooxml_ole.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/xlsx/package_normalizer.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/office/xlsx/xlsx_converter.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/_script_geometry.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/_table_recovery/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/_table_recovery/candidate.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/_table_recovery/contracts.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/_table_recovery/engine.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/_table_recovery/geometry.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/_table_recovery/rule_band.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/_table_recovery/sparse_common.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/_table_recovery/sparse_hybrid.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/_table_recovery/sparse_multiline.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/_table_recovery/text.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/_table_recovery/text_grid.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/_table_recovery/vector.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/annotation_bands.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/auxiliary_text.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/char_geometry.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/code_blocks.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/formulas.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/geometry.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/graphics.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/index_blocks.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/inline/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/inline/common.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/inline/detection.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/inline/matching.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/inline/materialize.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/inline/scripts.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/inline/types.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/layout_evidence.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/line_layout.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/line_merging.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/models.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/native_text.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/pipeline.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/spatial_text.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/table_annotations.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/table_constants.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/table_detection.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/table_filled_grid.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/table_geometry.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/table_materialization.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/table_rows.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/table_rules.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/table_text_styles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/tables.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/text_assembly/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/text_assembly/annotations.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/text_assembly/assembly.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/text_assembly/common.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/text_assembly/continuity.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/text_assembly/footnotes.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/text_assembly/merging.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/text_assembly/rows.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/text_blocks.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/text_roles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/title_analysis/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/title_analysis/body_profile.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/title_analysis/common.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/title_analysis/compact_titles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/title_analysis/document_profile.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/title_analysis/lane_titles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/title_analysis/page_titles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/title_analysis/prototype.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/title_analysis/structural.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/titles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/typography.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/native/pdf/visual_annotations.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/analyzers/pdf.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/api.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/assets/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/assets/images.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/assets/store.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/cli.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/codecs/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/codecs/html/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/codecs/html/contracts.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/codecs/html/materializer.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/codecs/html/parser.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/codecs/html/resources.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/codecs/json.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/inline.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/links.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/markup/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/markup/anchors.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/markup/formula.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/markup/projector.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/markup/styles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/mathml.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/normalization.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/spans.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/table/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/table/blocks.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/table/content.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/table/document.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/table/html.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/table/models.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/table/rules.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/table/structure.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/text.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/content/tree.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/contracts.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/detection.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/filetypes.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/page_range.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/_document.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/classify.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/constants.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/font_runtime.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/images.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/layout.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/metadata.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/native_annotations.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/native_contracts.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/native_coordinates.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/native_lifecycle.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/native_objects.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/native_text_geometry.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/pdfium.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/raster.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/text/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/text/_contracts.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/text/dedup.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/text/extract.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/text/geometry.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/text/groups.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/pdf/visuals.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/properties.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/document/source.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/errors.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/export/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/export/_images.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/export/bundle.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/export/files.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/export/middle.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/foundation/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/foundation/_coordinates.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/foundation/_geometry.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/foundation/_hyperlink.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/foundation/_image.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/foundation/_image_operations.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/foundation/_image_payload.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/foundation/_svg_raster.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/foundation/_text.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/foundation/image_encoding.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/foundation/language.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/foundation/type_identity.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/foundation/xml_names.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/geometry.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/metadata.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/options.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/postprocess/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/postprocess/content.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/postprocess/document.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/postprocess/lists.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/postprocess/page_blocks.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/postprocess/pages.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/postprocess/paragraphs.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/postprocess/visual.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/public_api.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/common/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/common/context.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/common/html_table.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/common/index.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/common/list_items.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/common/planner.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/docx/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/docx/assets.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/docx/inline.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/docx/math.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/docx/renderer.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/docx/styles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/docx/table.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/epub/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/epub/assets.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/epub/package.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/epub/renderer.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/html/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/html/inline.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/html/renderer.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/html/sanitizer.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/html/table.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/latex/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/latex/assets.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/latex/inline.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/latex/renderer.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/latex/table.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/markdown/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/markdown/assets.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/markdown/blocks.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/markdown/escaping.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/markdown/inline.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/markdown/renderer.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/markdown/table.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/pdf/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/pdf/assets.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/pdf/diagnostics.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/pdf/font_plan.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/pdf/formula.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/pdf/formula_layout.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/pdf/original.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/pdf/pagination.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/pdf/renderer.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/pdf/styles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/pdf/table.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/pdf/table_content.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/pdf/table_layout.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/pdf/title_layout.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/structured_content/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/_internal/structured_content/renderer.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/api.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/contracts.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/docx.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/epub.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/fragments.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/html.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/latex.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/markdown.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/pdf.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/render/structured_content.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/resources/epub/docvortex.css +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/resources/fonts/DroidSansFallbackFull.ttf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/resources/fonts/NOTICE +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/resources/fonts/manifest.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/resources/html/docvortex.css +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/resources/html/docvortex.min.css +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/resources/unicode/EquivalentUnifiedIdeograph-17.0.0.txt +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/result.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/schema.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex/visualization.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex.egg-info/dependency_links.txt +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex.egg-info/entry_points.txt +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex.egg-info/requires.txt +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/src/docvortex.egg-info/top_level.txt +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/benchmarks/flash_pdf.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/benchmarks/native_pdf_table.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/benchmarks/pdf_render.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/benchmarks/pipeline.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/evaluate_native_pdf_table_manifest.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/flash_layout_block_expectations.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/flash_layout_geometry_manifest.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/flash_layout_semantic_expectations.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/flash_manual_annotations.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/flash_manual_review_decisions.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/flash_reviewed_history.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/flash_round2_annotations.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/flash_round2_review_decisions.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/flash_round3_annotations.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/flash_round3_followup_review_decisions.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/flash_round3_review_decisions.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/flash_rule_generalization_review_decisions.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/flash_title_coverage_review_decisions.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/generate_synthetic_pdf_fixtures.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/native_pdf_table_cross_page_manifest.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/native_pdf_table_demo_manifest.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/native_pdf_table_script_truth.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/pdf_char_dedup.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/pdf_mixed_font_script_line.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/pdf_numeric_citations_review.json +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/fixtures/rtf/semantic.rtf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_architecture.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_benchmark_entrypoint.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_brand_protocol.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_cli_logging.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_complete_pipeline.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_converter_lifecycle.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_document_envelope.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_document_metadata.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_export_image_names.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_format_matrix.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_geometry_api.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_history_geometry_tools.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_html_namespace.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_mixed_font_script_reference.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_pdf_analysis_api.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_pdf_cpu_evidence.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_pdf_font_geometry.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_pdf_font_runtime.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_pdf_model_text_normalization.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_pdf_numeric_citations.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_pdf_output_text.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_pdf_render_pool.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_pdf_source_row_merging.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_pdf_symbol_normalization.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_public_export_api.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_public_image_api.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_public_pipeline.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_refactor_raster.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_refactor_rendering.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_refactor_resources.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_release_ci_gate.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_render_ownership.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_renderer_branding.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_shared_boundaries.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_system_font_pdf_pipeline.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/test_validated_geometry.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_docx_equationxml_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_epub_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_flash_pdf_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_image_mtef_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_legacy_doc_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_legacy_ppt_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_legacy_xls_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_metafile_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_mtef_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_mtef_v5_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_native_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_odf_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_ofd_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_office_image_mtef_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_ooxml_mtef_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/_span_test_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/flash_layout/annotated/connexin.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/flash_layout/annotated/fornax.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/flash_layout/annotated/frames_v1.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/flash_layout/annotated/frames_v2.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/flash_layout/annotated/k2_treap.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/flash_layout/annotated/mmlu_redux.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/flash_layout/annotated/nash_review.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/flash_layout/annotated/nougat.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/flash_layout/bloom_form_labels.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/flash_layout/journal_dual_caption.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/flash_layout/journal_layout_tables.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/flash_layout/math_display_formulas.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/flash_layout/mixed_text_layout_sample.pdf.xor +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/flash_layout/quantum_appendix_layout.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/flash_table_annotations_synthetic.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/metabolic_pathway_page_3.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/native_cjk_layout_synthetic.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/native_pdf_tables/annual_report_fundraising_projects_table.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/native_pdf_tables/annual_report_management_roles_table.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/native_pdf_tables/annual_report_research_projects_table.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/native_pdf_tables/conference_schedule_tables.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/native_pdf_tables/engineering_process_restrictions_table.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/native_pdf_tables/fund_asset_and_transaction_tables.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/native_pdf_tables/fund_manager_profile_table.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/native_pdf_tables/manufacturing_facilities_cross_page_table.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/native_pdf_tables/pollutant_discharge_tables.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/native_pdf_tables/procurement_contract_tables.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/native_pdf_tables/procurement_document_blank_page_tables.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/native_pdf_tables/quarterly_report_financial_tables.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/numeric_citations_introduction.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/pdfs/test.pdf +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_backend_architecture.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_backend_block_object_regressions.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_docx_assets.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_docx_complex_fields.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_docx_math.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_docx_render.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_docx_special_char_tables.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_docx_table.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_emfplus_integration.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_epub_backlinks.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_epub_quoted_note_types.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_epub_render.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_bbox_grid_comparison.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_csv.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_docx_equationxml.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_epub.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_html.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_image_mtef.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_legacy_chart_data.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_legacy_doc.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_legacy_doc_mtef.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_legacy_ppt.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_legacy_xls.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_legacy_xls_ppt_mtef.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_manual_annotations.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_markup_anchors.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_model.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_mtef_v5.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_odf.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_ofd.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_office_image_mtef.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_office_metafile.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_office_models.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_office_mtef_v5.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_office_package_normalizers.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_office_title_types.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_ooxml_mtef.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_auxiliary_text.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_char_geometry.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_code_blocks.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_document_profile.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_equation_images.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_extractor.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_formulas.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_graphics.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_index_blocks.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_layout_repairs.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_line_metadata.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_native_text.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_pipeline.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_reviewed_history.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_samples.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_scripts.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_semantics.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_short_tails.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_tables.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_text_blocks.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_text_visibility.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_titles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_pdf_visual_annotations.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_round2_annotations.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_round3_annotations.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_rtf.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_rule_generalization.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_shared_helpers.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_spatial_evidence.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_flash_spreadsheet_projector.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_guess_suffix_ole2.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_html_css_build.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_html_render.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_html_security.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_hybrid_script_source_pdfs.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_latex_render.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_markdown_render.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_middle_json_block_models.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_middle_json_export.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_middle_json_validator.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_model_json.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_native_pdf_table.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_native_pdf_table_demo_manifest.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_native_pdf_table_manifest.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_native_pdf_table_pipeline.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_native_pdf_table_scripts.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_native_table_performance_equivalence.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_ofd_assembly.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_ofd_vector_tables.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_office_demo_exports.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_office_demo_pages.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_office_parser_regressions.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_cjk_style.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_cjk_wrapping.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_classify.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_demo_links.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_diagnostic_levels.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_document.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_formula_layout.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_object_clipping.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_original_layout.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_pagination.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_paragraph_cache.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_render.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_render_diagnostics.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_structured_tables.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_table_cache.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_table_round2.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_text_dedup.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_text_styles.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_title_font_plan.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_title_space.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_pdf_visualization.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_postprocess_page_blocks.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_postprocess_pages.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_postprocess_paragraphs.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_postprocess_visual.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_render_api.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_render_html_table.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_render_image_renderer.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_render_list_index_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_structured_content_render.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_svg_raster.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_table_merge.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_table_merge_cell_merge.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_text_block_anchor.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_text_boundary_rules.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tests/unittest/test_text_utils.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tools/__init__.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tools/build_html_css.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tools/calibrate_pdf_geometry.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tools/capture_baseline.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tools/capture_platform_layout.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tools/compare_font_platforms.py +0 -0
- {docvortex-0.4.20 → docvortex-0.4.21}/tools/font_geometry.py +0 -0
|
@@ -16,7 +16,7 @@ from reportlab.platypus.paraparser import ParaParser
|
|
|
16
16
|
from ....schema import CodeInlineSpan, EquationInlineSpan, HyperlinkSpan, InlineSpan, TextSpan
|
|
17
17
|
from .formula import FormulaRenderer, InlineFormulaImage, PdfFormulaError
|
|
18
18
|
from .diagnostics import report_pdf_diagnostic
|
|
19
|
-
from .paragraph import MeasuredCJKParagraph, MeasuredParagraph, PlainCJKParagraph
|
|
19
|
+
from .paragraph import CJKParagraph, MeasuredCJKParagraph, MeasuredParagraph, PlainCJKParagraph
|
|
20
20
|
from .styles import ACCENT_COLOR, HAN_FONT, JAPANESE_FONT, KOREAN_FONT, MONO_FONT, UNICODE_FALLBACK_FONT
|
|
21
21
|
|
|
22
22
|
_BOOKMARK_SAFE_RE = re.compile(r"[^A-Za-z0-9_]+")
|
|
@@ -160,6 +160,14 @@ def build_pdf_paragraph(
|
|
|
160
160
|
getattr(fragment, "text", "") and fragment.fontName in (HAN_FONT, JAPANESE_FONT, KOREAN_FONT) for fragment in fragments
|
|
161
161
|
):
|
|
162
162
|
parsed_style = parsed_style.clone(parsed_style.name + " CJK", wordWrap="CJK")
|
|
163
|
+
if parsed_style.wordWrap == "CJK" and context.formula_images:
|
|
164
|
+
for fragment in fragments:
|
|
165
|
+
if isinstance(getattr(getattr(fragment, "cbDefn", None), "image", None), InlineFormulaImage):
|
|
166
|
+
fragment._pdf_location = context.location(page_idx, block_index, block_type)
|
|
167
|
+
fragment._pdf_page_idx = page_idx
|
|
168
|
+
# 公式的上下界参与实际行高,避免高分数与前后行重叠;不修改共享样式。
|
|
169
|
+
if getattr(parsed_style, "autoLeading", "") in ("", "off"):
|
|
170
|
+
parsed_style = parsed_style.clone(parsed_style.name + " Formula", autoLeading="max")
|
|
163
171
|
bullet_text = None
|
|
164
172
|
if bullet_fragments:
|
|
165
173
|
bullet_text = "".join(getattr(fragment, "text", "") for fragment in bullet_fragments)
|
|
@@ -169,7 +177,9 @@ def build_pdf_paragraph(
|
|
|
169
177
|
and not getattr(style, "keepWithNext", False)
|
|
170
178
|
and (parsed_style.wordWrap == "CJK" or sum(len(getattr(fragment, "text", "")) for fragment in fragments) >= 256)
|
|
171
179
|
)
|
|
172
|
-
paragraph_class =
|
|
180
|
+
paragraph_class = (
|
|
181
|
+
MeasuredParagraph if cache_measurement else (CJKParagraph if parsed_style.wordWrap == "CJK" else Paragraph)
|
|
182
|
+
)
|
|
173
183
|
if (
|
|
174
184
|
parsed_style.wordWrap == "CJK"
|
|
175
185
|
and not anchor
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"""局部修复 CJK 对象断行,并在普通段落上复用测量,保持 ReportLab 的拆分与绘制契约。"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
from copy import copy, deepcopy
|
|
7
|
+
from types import FunctionType
|
|
8
|
+
from unicodedata import category
|
|
9
|
+
|
|
10
|
+
from reportlab.platypus import Paragraph
|
|
11
|
+
from reportlab.platypus import paragraph as rl_paragraph
|
|
12
|
+
from reportlab.platypus.paraparser import ParaFrag
|
|
13
|
+
|
|
14
|
+
from .diagnostics import report_pdf_diagnostic
|
|
15
|
+
from .formula import InlineFormulaImage
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _natural_cjk_unit(fragment: ParaFrag, text: str) -> rl_paragraph.cjkU:
|
|
19
|
+
"""分页后的公式从未缩放的回调恢复几何,试排不修改原始片段或共享公式。"""
|
|
20
|
+
definition = getattr(fragment, "cbDefn", None)
|
|
21
|
+
original = getattr(definition, "_pdf_cjk_original", None)
|
|
22
|
+
if original is not None:
|
|
23
|
+
fragment = fragment.clone(cbDefn=original)
|
|
24
|
+
return rl_paragraph.cjkU(text, fragment, "utf8")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _fit_cjk_formula(unit: rl_paragraph.cjkU, width: float) -> rl_paragraph.cjkU:
|
|
28
|
+
"""仅在空行仍容不下时缩小自有公式,保留原始回调供后续宽窄试排和分页复用。"""
|
|
29
|
+
definition = getattr(unit.frag, "cbDefn", None)
|
|
30
|
+
if not isinstance(getattr(definition, "image", None), InlineFormulaImage) or not 0 < width < unit.width:
|
|
31
|
+
return unit
|
|
32
|
+
scale = width / unit.width
|
|
33
|
+
fitted = copy(definition)
|
|
34
|
+
fitted._pdf_cjk_original = definition
|
|
35
|
+
fitted.width = width
|
|
36
|
+
fitted.height = definition.height * scale
|
|
37
|
+
fitted.valign = definition.valign * scale
|
|
38
|
+
return rl_paragraph.cjkU(str(unit), unit.frag.clone(cbDefn=fitted), "utf8")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _safe_cjk_split(frags: list[ParaFrag], widths: list[float], calc_bounds: bool) -> rl_paragraph.ParaLines:
|
|
42
|
+
"""沿用上游 CJK 断行规则,但把空文本回调当作完整对象,安全移行并保留零宽标记。"""
|
|
43
|
+
# Adapted from ReportLab 4.4.4/5.0.1 cjkFragSplit (BSD); see licenses/REPORTLAB.txt.
|
|
44
|
+
units = []
|
|
45
|
+
for fragment in frags:
|
|
46
|
+
text = fragment.text
|
|
47
|
+
if isinstance(text, bytes):
|
|
48
|
+
text = text.decode("utf8")
|
|
49
|
+
units.extend(_natural_cjk_unit(fragment, character) for character in text or [""])
|
|
50
|
+
lines = []
|
|
51
|
+
index = start = 0
|
|
52
|
+
used = 0.0
|
|
53
|
+
width = widths[0]
|
|
54
|
+
while index < len(units):
|
|
55
|
+
unit = units[index]
|
|
56
|
+
if used == 0:
|
|
57
|
+
unit = units[index] = _fit_cjk_formula(unit, width)
|
|
58
|
+
index += 1
|
|
59
|
+
advance = unit.width
|
|
60
|
+
if hasattr(advance, "normalizedValue"):
|
|
61
|
+
advance = advance.normalizedValue(width)
|
|
62
|
+
used += advance
|
|
63
|
+
forced = hasattr(unit.frag, "lineBreak")
|
|
64
|
+
if (used > width + rl_paragraph._FUZZ and used > 0) or forced:
|
|
65
|
+
extra = width - used
|
|
66
|
+
if not forced:
|
|
67
|
+
if unit and ord(unit) < 0x3000:
|
|
68
|
+
limit = (start + index) >> 1
|
|
69
|
+
for candidate in range(index - 1, limit, -1):
|
|
70
|
+
previous = units[candidate]
|
|
71
|
+
if previous and (category(previous) == "Zs" or ord(previous) >= 0x3000):
|
|
72
|
+
following = candidate + 1
|
|
73
|
+
if following < index:
|
|
74
|
+
next_index = following + 1
|
|
75
|
+
extra += sum(item.width for item in units[next_index:index])
|
|
76
|
+
advance = units[following].width
|
|
77
|
+
unit = units[following]
|
|
78
|
+
index = next_index
|
|
79
|
+
break
|
|
80
|
+
# 空串属于任意字符串的子串,必须显式排除,不能当作悬挂的禁则标点。
|
|
81
|
+
if (not unit or unit not in rl_paragraph.ALL_CANNOT_START) and index > start + 1:
|
|
82
|
+
index -= 1
|
|
83
|
+
extra += advance
|
|
84
|
+
lines.append(rl_paragraph.makeCJKParaLine(units[start:index], width, width - extra, extra, forced, calc_bounds))
|
|
85
|
+
width = widths[min(len(lines), len(widths) - 1)]
|
|
86
|
+
start = index
|
|
87
|
+
used = 0.0
|
|
88
|
+
# 零宽 anchor 仍有绘制副作用,不能按累计宽度决定是否丢弃尾部片段。
|
|
89
|
+
if start < len(units):
|
|
90
|
+
lines.append(rl_paragraph.makeCJKParaLine(units[start:], width, used, width - used, False, calc_bounds))
|
|
91
|
+
return rl_paragraph.ParaLines(kind=1, lines=lines)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _split_cjk_lines(lines: rl_paragraph.ParaLines, start: int, stop: int) -> list[ParaFrag]:
|
|
95
|
+
"""直接复制已分行的 CJK 片段,避免上游给公式补空格或修改原段落的绘制状态。"""
|
|
96
|
+
return [fragment.clone() for line in lines.lines[start:stop] for fragment in line.words]
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class CJKParagraph(Paragraph):
|
|
100
|
+
"""为自有 CJK 特殊片段提供局部安全断行,其余内容继续遵守原生 Paragraph 契约。"""
|
|
101
|
+
|
|
102
|
+
def breakLinesCJK(self, maxWidths: float | list[float] | tuple[float, ...]) -> rl_paragraph.ParaLines:
|
|
103
|
+
"""只接管含空文本的片段;保留首行缩进、项目符号及分页首片的既有布局。"""
|
|
104
|
+
self._pdf_safe_cjk = False
|
|
105
|
+
if not any(getattr(fragment, "text", None) == "" for fragment in self.frags):
|
|
106
|
+
return super().breakLinesCJK(maxWidths)
|
|
107
|
+
self._pdf_safe_cjk = True
|
|
108
|
+
if hasattr(self, "blPara") and getattr(self, "_splitpara", False):
|
|
109
|
+
return self.blPara
|
|
110
|
+
widths = list(maxWidths) if isinstance(maxWidths, (list, tuple)) else [maxWidths]
|
|
111
|
+
self.height = 0
|
|
112
|
+
rl_paragraph._handleBulletWidth(self.bulletText, self.style, widths)
|
|
113
|
+
auto_leading = getattr(self, "autoLeading", getattr(self.style, "autoLeading", ""))
|
|
114
|
+
return _safe_cjk_split(self.frags, widths, auto_leading not in ("", "off"))
|
|
115
|
+
|
|
116
|
+
def _get_split_blParaFunc(self) -> Callable[[rl_paragraph.ParaLines, int, int], list[ParaFrag]]:
|
|
117
|
+
"""只对安全组行的富片段使用无补空格拆分,普通文本仍走原生拆分入口。"""
|
|
118
|
+
if getattr(self, "_pdf_safe_cjk", False):
|
|
119
|
+
return _split_cjk_lines
|
|
120
|
+
return super()._get_split_blParaFunc()
|
|
121
|
+
|
|
122
|
+
def draw(self) -> None:
|
|
123
|
+
"""仅对最终绘制的超小公式报告诊断,避免试排产生过时告警。"""
|
|
124
|
+
if getattr(self, "_pdf_safe_cjk", False):
|
|
125
|
+
for line in self.blPara.lines:
|
|
126
|
+
for fragment in line.words:
|
|
127
|
+
definition = getattr(fragment, "cbDefn", None)
|
|
128
|
+
original = getattr(definition, "_pdf_cjk_original", None)
|
|
129
|
+
if original is not None and fragment.fontSize * definition.width / original.width < 6:
|
|
130
|
+
report_pdf_diagnostic(
|
|
131
|
+
"pdf_layout_small_text",
|
|
132
|
+
f"Inline formula fitted below 6 pt ({getattr(fragment, '_pdf_location', '')})",
|
|
133
|
+
getattr(fragment, "_pdf_page_idx", None),
|
|
134
|
+
)
|
|
135
|
+
super().draw()
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
_STYLE_FIELDS = ("fontName", "fontSize", "textColor", "rise", "us_lines", "link", "backColor", "nobr")
|
|
139
|
+
_MISSING = object()
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _same_plain_style(first, second) -> bool:
|
|
143
|
+
"""普通片段按身份或样式字典比较,避免逐字符触发动态属性查找和缺失属性异常。"""
|
|
144
|
+
if first is second:
|
|
145
|
+
return True
|
|
146
|
+
left, right = first.__dict__, second.__dict__
|
|
147
|
+
# 保留原生比较中「属性不存在」与「属性值为 None」的区别。
|
|
148
|
+
return [left.get(name, _MISSING) for name in _STYLE_FIELDS] == [right.get(name, _MISSING) for name in _STYLE_FIELDS]
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _plain_cjk_breaker():
|
|
152
|
+
"""仅为自有段落绑定局部比较函数,不复制断行算法,也不修改 ReportLab 模块全局。"""
|
|
153
|
+
replacement = _same_plain_style
|
|
154
|
+
for function, dependency in (
|
|
155
|
+
(getattr(rl_paragraph, "makeCJKParaLine", None), "sameFrag"),
|
|
156
|
+
(getattr(rl_paragraph, "cjkFragSplit", None), "makeCJKParaLine"),
|
|
157
|
+
(Paragraph.breakLinesCJK, "cjkFragSplit"),
|
|
158
|
+
):
|
|
159
|
+
# ReportLab 内部实现变化或已被外部包装时,保守回到其原有入口。
|
|
160
|
+
if not isinstance(function, FunctionType) or dependency not in function.__code__.co_names:
|
|
161
|
+
return None
|
|
162
|
+
namespace = function.__globals__.copy()
|
|
163
|
+
namespace[dependency] = replacement
|
|
164
|
+
replacement = FunctionType(function.__code__, namespace, function.__name__, function.__defaults__, function.__closure__)
|
|
165
|
+
replacement.__kwdefaults__ = function.__kwdefaults__
|
|
166
|
+
return replacement
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
_PLAIN_CJK_BREAK = _plain_cjk_breaker()
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class PlainCJKParagraph(CJKParagraph):
|
|
173
|
+
"""仅普通 CJK 组行使用局部比较,复杂内容和拆分后的段落交给安全断行层。"""
|
|
174
|
+
|
|
175
|
+
def breakLinesCJK(self, maxWidths):
|
|
176
|
+
"""每次检查当前片段,内容变更后不沿用旧资格或样式比较缓存。"""
|
|
177
|
+
self._pdf_safe_cjk = False
|
|
178
|
+
if (
|
|
179
|
+
_PLAIN_CJK_BREAK is not None
|
|
180
|
+
and len(self.frags) > 1
|
|
181
|
+
and not self.bulletText
|
|
182
|
+
and not self.style.endDots
|
|
183
|
+
and not getattr(self, "_splitpara", False)
|
|
184
|
+
and all(
|
|
185
|
+
type(fragment) is ParaFrag
|
|
186
|
+
and type(getattr(fragment, "text", None)) is str
|
|
187
|
+
and bool(fragment.text)
|
|
188
|
+
and "cbDefn" not in fragment.__dict__
|
|
189
|
+
and "lineBreak" not in fragment.__dict__
|
|
190
|
+
and not any(fragment.__dict__.get(name) for name in ("link", "us_lines", "rise", "nobr"))
|
|
191
|
+
for fragment in self.frags
|
|
192
|
+
)
|
|
193
|
+
):
|
|
194
|
+
return _PLAIN_CJK_BREAK(self, maxWidths)
|
|
195
|
+
return super().breakLinesCJK(maxWidths)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
class MeasuredParagraph(CJKParagraph):
|
|
199
|
+
"""缓存仍保存在本对象中的完整排版状态,不跨段落分享 blPara 或 fragments。"""
|
|
200
|
+
|
|
201
|
+
def _measurement_key(self, width: float) -> tuple | None:
|
|
202
|
+
"""检查内容、样式及已保存几何;复杂回调和处理后的词列表保守重新测量。"""
|
|
203
|
+
if any(not hasattr(fragment, "__dict__") or hasattr(fragment, "cbDefn") for fragment in self.frags):
|
|
204
|
+
return None
|
|
205
|
+
style = vars(self.style).copy()
|
|
206
|
+
# ReportLab 已把继承值复制到当前样式,parent 本身不参与 wrap,不能按对象身份比较其深副本。
|
|
207
|
+
style.pop("parent", None)
|
|
208
|
+
return (
|
|
209
|
+
width,
|
|
210
|
+
style,
|
|
211
|
+
getattr(self, "autoLeading", None),
|
|
212
|
+
tuple(vars(fragment) for fragment in self.frags),
|
|
213
|
+
id(getattr(self, "blPara", None)),
|
|
214
|
+
getattr(self, "width", None),
|
|
215
|
+
getattr(self, "height", None),
|
|
216
|
+
tuple(getattr(self, "_wrapWidths", ())),
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
def wrap(self, availWidth: float, availHeight: float) -> tuple[float, float]:
|
|
220
|
+
"""同宽且状态未变时复用现有换行;Paragraph 本身不使用可用高度决定换行。"""
|
|
221
|
+
key = self._measurement_key(availWidth)
|
|
222
|
+
cached = getattr(self, "_measurement_cache", None)
|
|
223
|
+
if key is not None and cached is not None and key == cached[0]:
|
|
224
|
+
return cached[1]
|
|
225
|
+
self._measurement_cache = None
|
|
226
|
+
result = super().wrap(availWidth, availHeight)
|
|
227
|
+
key = self._measurement_key(availWidth)
|
|
228
|
+
if key is not None:
|
|
229
|
+
# 只在真实换行后保存独立快照;命中时用字典比较,避免逐次序列化样式和长文本。
|
|
230
|
+
self._measurement_cache = (deepcopy(key), result)
|
|
231
|
+
return result
|
|
232
|
+
|
|
233
|
+
def split(self, availWidth: float, availHeight: float) -> list:
|
|
234
|
+
"""拆分可能修改行布局,返回的新段落独立缓存,原对象随后重新测量。"""
|
|
235
|
+
self._measurement_cache = None
|
|
236
|
+
try:
|
|
237
|
+
return super().split(availWidth, availHeight)
|
|
238
|
+
finally:
|
|
239
|
+
self._measurement_cache = None
|
|
240
|
+
|
|
241
|
+
def draw(self) -> None:
|
|
242
|
+
"""绘制可能更新行内状态,绘制后不再把旧结果当作未改变的试排状态。"""
|
|
243
|
+
try:
|
|
244
|
+
super().draw()
|
|
245
|
+
finally:
|
|
246
|
+
self._measurement_cache = None
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
class MeasuredCJKParagraph(MeasuredParagraph, PlainCJKParagraph):
|
|
250
|
+
"""组合普通 CJK 比较与原有测量复用,拆分段落继续拥有独立排版状态。"""
|
|
@@ -606,6 +606,7 @@ tests/unittest/test_ofd_vector_tables.py
|
|
|
606
606
|
tests/unittest/test_office_demo_exports.py
|
|
607
607
|
tests/unittest/test_office_demo_pages.py
|
|
608
608
|
tests/unittest/test_office_parser_regressions.py
|
|
609
|
+
tests/unittest/test_pdf_cjk_objects.py
|
|
609
610
|
tests/unittest/test_pdf_cjk_style.py
|
|
610
611
|
tests/unittest/test_pdf_cjk_wrapping.py
|
|
611
612
|
tests/unittest/test_pdf_classify.py
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"""验证 CJK 非文本片段的移行、基线、宽度恢复与真实 PDF 输出。"""
|
|
2
|
+
|
|
3
|
+
from copy import deepcopy
|
|
4
|
+
from io import BytesIO
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
from pypdf import PdfReader
|
|
8
|
+
from reportlab.graphics.shapes import Drawing, Rect
|
|
9
|
+
from reportlab.lib import colors
|
|
10
|
+
from reportlab.platypus import Paragraph
|
|
11
|
+
from reportlab.platypus import paragraph as rl_paragraph
|
|
12
|
+
|
|
13
|
+
from docvortex.render import PdfLayout, render_pdf
|
|
14
|
+
from docvortex.render._internal.pdf.diagnostics import collect_pdf_diagnostics
|
|
15
|
+
from docvortex.render._internal.pdf.formula import FormulaRenderer, FormulaVector
|
|
16
|
+
from docvortex.render._internal.pdf.inline import PdfAnchorRegistry, PdfInlineContext, build_pdf_paragraph
|
|
17
|
+
from docvortex.render._internal.pdf.renderer import _PdfCanvas
|
|
18
|
+
from docvortex.render._internal.pdf.styles import build_pdf_styles
|
|
19
|
+
from docvortex.schema import EquationInlineSpan, TextSpan
|
|
20
|
+
from test_pdf_original_layout import _middle, _text
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class _SizedFormulas(FormulaRenderer):
|
|
24
|
+
"""以明确宽高的矢量替代字体度量,让边界与基线测试不依赖 ZiaMath 字形。"""
|
|
25
|
+
|
|
26
|
+
def render(self, latex: str, *, inline: bool, font_size: float, color: str = "#1f2937") -> FormulaVector:
|
|
27
|
+
"""构造包含实际墨迹的公式代理,绘制测试能检测静默丢失。"""
|
|
28
|
+
width = float(latex)
|
|
29
|
+
drawing = Drawing(width, 20)
|
|
30
|
+
drawing.add(Rect(0, 0, width, 20, fillColor=colors.red, strokeColor=None))
|
|
31
|
+
return FormulaVector(drawing, width, 20, 15, 5)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _paragraph(parts: list[str | float], *, cached: bool = False, anchor: str | None = None, indent: float = 0):
|
|
35
|
+
"""通过生产段落构造入口生成中文、公式、锚点和显式换行。"""
|
|
36
|
+
spans = [
|
|
37
|
+
TextSpan(type="text", content=part)
|
|
38
|
+
if isinstance(part, str)
|
|
39
|
+
else EquationInlineSpan(type="equation_inline", content=str(part))
|
|
40
|
+
for part in parts
|
|
41
|
+
]
|
|
42
|
+
context = PdfInlineContext(_SizedFormulas(), PdfAnchorRegistry([anchor] if anchor else []), cache_paragraphs=cached)
|
|
43
|
+
return build_pdf_paragraph(
|
|
44
|
+
spans,
|
|
45
|
+
build_pdf_styles().body.clone("object-test", fontSize=10, leading=12, firstLineIndent=indent),
|
|
46
|
+
context=context,
|
|
47
|
+
page_idx=2,
|
|
48
|
+
block_index=7,
|
|
49
|
+
block_type="text",
|
|
50
|
+
max_width=float("inf"),
|
|
51
|
+
preserve_newlines=True,
|
|
52
|
+
anchor=anchor,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _images(paragraph):
|
|
57
|
+
"""提取最终组行中保留下来的公式回调,而不是原始输入片段。"""
|
|
58
|
+
return [
|
|
59
|
+
f.cbDefn
|
|
60
|
+
for line in paragraph.blPara.lines
|
|
61
|
+
for f in line.words
|
|
62
|
+
if getattr(getattr(f, "cbDefn", None), "kind", None) == "img"
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _text_content(paragraph) -> str:
|
|
67
|
+
"""检查组行结果中的文字顺序及是否被分页插入了空格。"""
|
|
68
|
+
return "".join(f.text for line in paragraph.blPara.lines for f in line.words)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _assert_bounds(paragraph) -> None:
|
|
72
|
+
"""独立重算每行的真实对象宽度,不只信任 Paragraph 返回的框宽。"""
|
|
73
|
+
for line in paragraph.blPara.lines:
|
|
74
|
+
actual = sum(
|
|
75
|
+
getattr(fragment.cbDefn, "width", 0)
|
|
76
|
+
if hasattr(fragment, "cbDefn")
|
|
77
|
+
else rl_paragraph.stringWidth(fragment.text, fragment.fontName, fragment.fontSize)
|
|
78
|
+
for fragment in line.words
|
|
79
|
+
)
|
|
80
|
+
assert actual <= line.maxWidth + 1e-7
|
|
81
|
+
assert line.currentWidth == pytest.approx(actual)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@pytest.mark.parametrize("cached", [False, True])
|
|
85
|
+
def test_formula_moves_intact_to_next_line(cached):
|
|
86
|
+
"""公式放不进剩余空间时整体移行,不能被当作悬挂标点或缩到剩余空隙。"""
|
|
87
|
+
paragraph = _paragraph(["中文前", 80.0, "后文"], cached=cached)
|
|
88
|
+
paragraph.wrap(100, 1000)
|
|
89
|
+
assert not any(hasattr(f, "cbDefn") for f in paragraph.blPara.lines[0].words)
|
|
90
|
+
assert [image.width for image in _images(paragraph)] == [80]
|
|
91
|
+
assert _text_content(paragraph) == "中文前后文"
|
|
92
|
+
_assert_bounds(paragraph)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def test_latin_backtracking_crosses_formula_without_ord_error():
|
|
96
|
+
"""Latin 溢出向前回溯会经过空文本公式,覆盖第二处 ord 调用。"""
|
|
97
|
+
paragraph = _paragraph(["中AAAAAAAA", 20.0, "aaaaaaa"])
|
|
98
|
+
paragraph.wrap(100, 1000)
|
|
99
|
+
assert len(_images(paragraph)) == 1
|
|
100
|
+
assert _text_content(paragraph) == "中AAAAAAAAaaaaaaa"
|
|
101
|
+
_assert_bounds(paragraph)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@pytest.mark.parametrize("cached", [False, True])
|
|
105
|
+
def test_oversize_formula_fits_empty_line_and_restores_on_rewrap(cached):
|
|
106
|
+
"""只缩放临时回调,宽窄交替后宽高与基线从基准恢复,原始最小列宽不变。"""
|
|
107
|
+
paragraph = _paragraph([300.0, "中文"], cached=cached)
|
|
108
|
+
original = next(f.cbDefn for f in paragraph.frags if hasattr(f, "cbDefn"))
|
|
109
|
+
natural_minimum = paragraph.minWidth()
|
|
110
|
+
for width in [100, 40, 400]:
|
|
111
|
+
paragraph.wrap(width, 1000)
|
|
112
|
+
image = _images(paragraph)[0]
|
|
113
|
+
ratio = min(width / 300, 1)
|
|
114
|
+
assert (image.width, image.height, image.valign) == pytest.approx((300 * ratio, 20 * ratio, -5 * ratio))
|
|
115
|
+
assert paragraph.blPara.lines[0].ascent == pytest.approx(15 * ratio)
|
|
116
|
+
_assert_bounds(paragraph)
|
|
117
|
+
assert (original.width, original.height, original.valign) == (300, 20, -5)
|
|
118
|
+
assert paragraph.minWidth() == natural_minimum
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def test_first_line_indent_adjacent_formulas_and_explicit_breaks():
|
|
122
|
+
"""首行缩进、连续公式和显式换行共同作用时,所有对象只出现一次。"""
|
|
123
|
+
paragraph = _paragraph([120.0, 60.0, "中文\n结束"], anchor="target", indent=30)
|
|
124
|
+
paragraph.wrap(100, 1000)
|
|
125
|
+
assert [image.width for image in _images(paragraph)] == [70, 60]
|
|
126
|
+
assert _text_content(paragraph) == "中文结束"
|
|
127
|
+
assert paragraph.blPara.lines[-1].words[-1].text == "结束"
|
|
128
|
+
_assert_bounds(paragraph)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def test_zero_width_anchor_survives_after_forced_break():
|
|
132
|
+
"""宽度为零的末尾 anchor 仍需要绘制,不能被累计宽度判断丢弃。"""
|
|
133
|
+
from docvortex.render._internal.pdf.paragraph import CJKParagraph
|
|
134
|
+
|
|
135
|
+
style = build_pdf_styles().body.clone("anchor-test", wordWrap="CJK")
|
|
136
|
+
paragraph = CJKParagraph('中文<br/><a name="end"/>', style)
|
|
137
|
+
paragraph.wrap(100, 1000)
|
|
138
|
+
output = BytesIO()
|
|
139
|
+
canvas = _PdfCanvas(output, document_title="anchors")
|
|
140
|
+
paragraph.drawOn(canvas, 20, 100)
|
|
141
|
+
assert canvas._destinations["end"].fmt is not None
|
|
142
|
+
canvas.save()
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def test_page_split_preserves_objects_text_and_natural_geometry():
|
|
146
|
+
"""分页不修改父段落,不补空格,续段重新变宽后恢复原始公式尺寸。"""
|
|
147
|
+
paragraph = _paragraph(["中文", 180.0, "后文\n"] * 12, cached=True)
|
|
148
|
+
paragraph.wrap(100, 1000)
|
|
149
|
+
original_text = _text_content(paragraph)
|
|
150
|
+
pieces = paragraph.split(100, 90)
|
|
151
|
+
assert len(pieces) == 2
|
|
152
|
+
assert _text_content(paragraph) == original_text
|
|
153
|
+
for piece in pieces:
|
|
154
|
+
piece.wrap(100, 1000)
|
|
155
|
+
_assert_bounds(piece)
|
|
156
|
+
assert "".join(_text_content(piece) for piece in pieces) == original_text
|
|
157
|
+
assert sum(len(_images(piece)) for piece in pieces) == 12
|
|
158
|
+
pieces[1].wrap(300, 1000)
|
|
159
|
+
assert all(image.width == 180 for image in _images(pieces[1]))
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def test_small_formula_diagnostic_only_describes_final_drawing():
|
|
163
|
+
"""试排不报告低字号,最终绘制时诊断带有实际页块定位。"""
|
|
164
|
+
paragraph = _paragraph([300.0, "中文"])
|
|
165
|
+
with collect_pdf_diagnostics() as diagnostics:
|
|
166
|
+
paragraph.wrap(30, 1000)
|
|
167
|
+
assert not diagnostics
|
|
168
|
+
canvas = _PdfCanvas(BytesIO(), document_title="diagnostics")
|
|
169
|
+
paragraph.drawOn(canvas, 20, 100)
|
|
170
|
+
canvas.save()
|
|
171
|
+
assert len(diagnostics) == 1
|
|
172
|
+
assert diagnostics[0].code == "pdf_layout_small_text"
|
|
173
|
+
assert diagnostics[0].page_index == 2
|
|
174
|
+
assert "block_index=7" in diagnostics[0].message
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@pytest.mark.parametrize("layout", [PdfLayout.AUTO, PdfLayout.ORIGINAL, PdfLayout.REFLOW])
|
|
178
|
+
def test_public_render_preserves_vectors_links_and_input(layout):
|
|
179
|
+
"""真实长公式经过公开渲染入口,输出矢量与链接并保持 MiddleJson 不变。"""
|
|
180
|
+
block = _text("中文前文", bbox=(0.1, 0.1, 0.4, 0.8))
|
|
181
|
+
block["content"] += [
|
|
182
|
+
{"type": "equation_inline", "content": "+".join(["x_i"] * 80)},
|
|
183
|
+
{"type": "hyperlink", "url": "https://example.com", "content": [{"type": "text", "content": "中文后文"}]},
|
|
184
|
+
]
|
|
185
|
+
middle = _middle([{"page_idx": 0, "blocks": [block]}])
|
|
186
|
+
before = deepcopy(middle.to_dict())
|
|
187
|
+
payload = render_pdf(middle, layout=layout)
|
|
188
|
+
reader = PdfReader(BytesIO(payload))
|
|
189
|
+
assert "中文前文" in reader.pages[0].extract_text()
|
|
190
|
+
assert "中文后文" in reader.pages[0].extract_text()
|
|
191
|
+
assert reader.pages[0]["/Annots"][0].get_object()["/A"]["/URI"] == "https://example.com"
|
|
192
|
+
assert b" c" in reader.pages[0].get_contents().get_data()
|
|
193
|
+
assert middle.to_dict() == before
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def test_safe_path_does_not_change_reportlab_globals():
|
|
197
|
+
"""安全路径不修改第三方的断行、字符对象或 Paragraph 入口。"""
|
|
198
|
+
original = (rl_paragraph.cjkFragSplit, rl_paragraph.cjkU, Paragraph.breakLinesCJK)
|
|
199
|
+
_paragraph(["中文", 300.0]).wrap(100, 1000)
|
|
200
|
+
assert original == (rl_paragraph.cjkFragSplit, rl_paragraph.cjkU, Paragraph.breakLinesCJK)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def test_table_cell_keeps_natural_width_and_draws_fitted_formula():
|
|
204
|
+
"""表格列宽测量保留公式自然宽度,实际窄列绘制仍可缩放且不污染后续宽列。"""
|
|
205
|
+
from reportlab.platypus import Table
|
|
206
|
+
|
|
207
|
+
paragraph = _paragraph(["中文", 180.0, "后文"], cached=True)
|
|
208
|
+
minimum = paragraph.minWidth()
|
|
209
|
+
for width in (100, 300):
|
|
210
|
+
canvas = _PdfCanvas(BytesIO(), document_title="table")
|
|
211
|
+
table = Table([[paragraph]], colWidths=[width + 12])
|
|
212
|
+
table.wrapOn(canvas, width + 12, 1000)
|
|
213
|
+
table.drawOn(canvas, 20, 100)
|
|
214
|
+
canvas.save()
|
|
215
|
+
assert _images(paragraph)[0].width == min(180, width)
|
|
216
|
+
assert paragraph.minWidth() == minimum
|
|
217
|
+
_assert_bounds(paragraph)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def test_mutating_special_paragraph_back_to_plain_clears_safe_state():
|
|
221
|
+
"""可变段落恢复为单一纯文本后,绘制不能继续把普通行结构当作富片段处理。"""
|
|
222
|
+
paragraph = _paragraph(["中文", 180.0])
|
|
223
|
+
paragraph.wrap(100, 1000)
|
|
224
|
+
paragraph.frags = [paragraph.frags[0]]
|
|
225
|
+
paragraph.wrap(100, 1000)
|
|
226
|
+
canvas = _PdfCanvas(BytesIO(), document_title="mutated")
|
|
227
|
+
paragraph.drawOn(canvas, 20, 100)
|
|
228
|
+
canvas.save()
|
|
229
|
+
assert not paragraph._pdf_safe_cjk
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
"""只在自有普通段落上复用最近一次换行,保持 ReportLab 的拆分与绘制契约。"""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from copy import deepcopy
|
|
6
|
-
from types import FunctionType
|
|
7
|
-
|
|
8
|
-
from reportlab.platypus import Paragraph
|
|
9
|
-
from reportlab.platypus import paragraph as rl_paragraph
|
|
10
|
-
from reportlab.platypus.paraparser import ParaFrag
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
_STYLE_FIELDS = ("fontName", "fontSize", "textColor", "rise", "us_lines", "link", "backColor", "nobr")
|
|
14
|
-
_MISSING = object()
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def _same_plain_style(first, second) -> bool:
|
|
18
|
-
"""普通片段按身份或样式字典比较,避免逐字符触发动态属性查找和缺失属性异常。"""
|
|
19
|
-
if first is second:
|
|
20
|
-
return True
|
|
21
|
-
left, right = first.__dict__, second.__dict__
|
|
22
|
-
# 保留原生比较中「属性不存在」与「属性值为 None」的区别。
|
|
23
|
-
return [left.get(name, _MISSING) for name in _STYLE_FIELDS] == [right.get(name, _MISSING) for name in _STYLE_FIELDS]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def _plain_cjk_breaker():
|
|
27
|
-
"""仅为自有段落绑定局部比较函数,不复制断行算法,也不修改 ReportLab 模块全局。"""
|
|
28
|
-
replacement = _same_plain_style
|
|
29
|
-
for function, dependency in (
|
|
30
|
-
(getattr(rl_paragraph, "makeCJKParaLine", None), "sameFrag"),
|
|
31
|
-
(getattr(rl_paragraph, "cjkFragSplit", None), "makeCJKParaLine"),
|
|
32
|
-
(Paragraph.breakLinesCJK, "cjkFragSplit"),
|
|
33
|
-
):
|
|
34
|
-
# ReportLab 内部实现变化或已被外部包装时,保守回到其原有入口。
|
|
35
|
-
if not isinstance(function, FunctionType) or dependency not in function.__code__.co_names:
|
|
36
|
-
return None
|
|
37
|
-
namespace = function.__globals__.copy()
|
|
38
|
-
namespace[dependency] = replacement
|
|
39
|
-
replacement = FunctionType(function.__code__, namespace, function.__name__, function.__defaults__, function.__closure__)
|
|
40
|
-
replacement.__kwdefaults__ = function.__kwdefaults__
|
|
41
|
-
return replacement
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
_PLAIN_CJK_BREAK = _plain_cjk_breaker()
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class PlainCJKParagraph(Paragraph):
|
|
48
|
-
"""仅普通 CJK 组行使用局部比较,复杂内容和拆分后的段落仍交给原入口。"""
|
|
49
|
-
|
|
50
|
-
def breakLinesCJK(self, maxWidths):
|
|
51
|
-
"""每次检查当前片段,内容变更后不沿用旧资格或样式比较缓存。"""
|
|
52
|
-
if (
|
|
53
|
-
_PLAIN_CJK_BREAK is not None
|
|
54
|
-
and len(self.frags) > 1
|
|
55
|
-
and not self.bulletText
|
|
56
|
-
and not self.style.endDots
|
|
57
|
-
and not getattr(self, "_splitpara", False)
|
|
58
|
-
and all(
|
|
59
|
-
type(fragment) is ParaFrag
|
|
60
|
-
and type(getattr(fragment, "text", None)) is str
|
|
61
|
-
and "cbDefn" not in fragment.__dict__
|
|
62
|
-
and "lineBreak" not in fragment.__dict__
|
|
63
|
-
and not any(fragment.__dict__.get(name) for name in ("link", "us_lines", "rise", "nobr"))
|
|
64
|
-
for fragment in self.frags
|
|
65
|
-
)
|
|
66
|
-
):
|
|
67
|
-
return _PLAIN_CJK_BREAK(self, maxWidths)
|
|
68
|
-
return super().breakLinesCJK(maxWidths)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
class MeasuredParagraph(Paragraph):
|
|
72
|
-
"""缓存仍保存在本对象中的完整排版状态,不跨段落分享 blPara 或 fragments。"""
|
|
73
|
-
|
|
74
|
-
def _measurement_key(self, width: float) -> tuple | None:
|
|
75
|
-
"""检查内容、样式及已保存几何;复杂回调和处理后的词列表保守重新测量。"""
|
|
76
|
-
if any(not hasattr(fragment, "__dict__") or hasattr(fragment, "cbDefn") for fragment in self.frags):
|
|
77
|
-
return None
|
|
78
|
-
style = vars(self.style).copy()
|
|
79
|
-
# ReportLab 已把继承值复制到当前样式,parent 本身不参与 wrap,不能按对象身份比较其深副本。
|
|
80
|
-
style.pop("parent", None)
|
|
81
|
-
return (
|
|
82
|
-
width,
|
|
83
|
-
style,
|
|
84
|
-
getattr(self, "autoLeading", None),
|
|
85
|
-
tuple(vars(fragment) for fragment in self.frags),
|
|
86
|
-
id(getattr(self, "blPara", None)),
|
|
87
|
-
getattr(self, "width", None),
|
|
88
|
-
getattr(self, "height", None),
|
|
89
|
-
tuple(getattr(self, "_wrapWidths", ())),
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
def wrap(self, availWidth: float, availHeight: float) -> tuple[float, float]:
|
|
93
|
-
"""同宽且状态未变时复用现有换行;Paragraph 本身不使用可用高度决定换行。"""
|
|
94
|
-
key = self._measurement_key(availWidth)
|
|
95
|
-
cached = getattr(self, "_measurement_cache", None)
|
|
96
|
-
if key is not None and cached is not None and key == cached[0]:
|
|
97
|
-
return cached[1]
|
|
98
|
-
self._measurement_cache = None
|
|
99
|
-
result = super().wrap(availWidth, availHeight)
|
|
100
|
-
key = self._measurement_key(availWidth)
|
|
101
|
-
if key is not None:
|
|
102
|
-
# 只在真实换行后保存独立快照;命中时用字典比较,避免逐次序列化样式和长文本。
|
|
103
|
-
self._measurement_cache = (deepcopy(key), result)
|
|
104
|
-
return result
|
|
105
|
-
|
|
106
|
-
def split(self, availWidth: float, availHeight: float) -> list:
|
|
107
|
-
"""拆分可能修改行布局,返回的新段落独立缓存,原对象随后重新测量。"""
|
|
108
|
-
self._measurement_cache = None
|
|
109
|
-
try:
|
|
110
|
-
return super().split(availWidth, availHeight)
|
|
111
|
-
finally:
|
|
112
|
-
self._measurement_cache = None
|
|
113
|
-
|
|
114
|
-
def draw(self) -> None:
|
|
115
|
-
"""绘制可能更新行内状态,绘制后不再把旧结果当作未改变的试排状态。"""
|
|
116
|
-
try:
|
|
117
|
-
super().draw()
|
|
118
|
-
finally:
|
|
119
|
-
self._measurement_cache = None
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
class MeasuredCJKParagraph(MeasuredParagraph, PlainCJKParagraph):
|
|
123
|
-
"""组合普通 CJK 比较与原有测量复用,拆分段落继续拥有独立排版状态。"""
|
|
File without changes
|