From 322d66201127e9dd9b2b255ea51d986b690dcaea Mon Sep 17 00:00:00 2001 From: root Date: Wed, 9 Apr 2025 16:49:59 +0000 Subject: [PATCH] =?UTF-8?q?Fixed=20=C2=B0=20and=20the=20overload=20ssue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cursorignore | 1 + ...Equipment Manifest REV6(Conveyor List).csv | 16 +- app.py | 130 +- cloned_repo | 2 +- templates/index.html | 691 +- .../pypdf-5.4.0.dist-info/INSTALLER | 1 + .../pypdf-5.4.0.dist-info/METADATA | 173 + .../pypdf-5.4.0.dist-info/RECORD | 113 + .../pypdf-5.4.0.dist-info/REQUESTED | 0 .../site-packages/pypdf-5.4.0.dist-info/WHEEL | 4 + .../pypdf-5.4.0.dist-info/licenses/LICENSE | 29 + .../site-packages/pypdf/__init__.py | 49 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1518 bytes .../pypdf/__pycache__/_cmap.cpython-312.pyc | Bin 0 -> 20325 bytes .../__pycache__/_doc_common.cpython-312.pyc | Bin 0 -> 60385 bytes .../__pycache__/_encryption.cpython-312.pyc | Bin 0 -> 54010 bytes .../pypdf/__pycache__/_merger.cpython-312.pyc | Bin 0 -> 697 bytes .../pypdf/__pycache__/_page.cpython-312.pyc | Bin 0 -> 108700 bytes .../__pycache__/_page_labels.cpython-312.pyc | Bin 0 -> 9837 bytes .../__pycache__/_protocols.cpython-312.pyc | Bin 0 -> 4552 bytes .../pypdf/__pycache__/_reader.cpython-312.pyc | Bin 0 -> 52841 bytes .../pypdf/__pycache__/_utils.cpython-312.pyc | Bin 0 -> 21615 bytes .../__pycache__/_version.cpython-312.pyc | Bin 0 -> 205 bytes .../pypdf/__pycache__/_writer.cpython-312.pyc | Bin 0 -> 142757 bytes .../_xobj_image_helpers.cpython-312.pyc | Bin 0 -> 15810 bytes .../__pycache__/constants.cpython-312.pyc | Bin 0 -> 22959 bytes .../pypdf/__pycache__/errors.cpython-312.pyc | Bin 0 -> 3300 bytes .../pypdf/__pycache__/filters.cpython-312.pyc | Bin 0 -> 29342 bytes .../__pycache__/pagerange.cpython-312.pyc | Bin 0 -> 9142 bytes .../__pycache__/papersizes.cpython-312.pyc | Bin 0 -> 1486 bytes .../pypdf/__pycache__/types.cpython-312.pyc | Bin 0 -> 1861 bytes .../pypdf/__pycache__/xmp.cpython-312.pyc | Bin 0 -> 15476 bytes .../python3.12/site-packages/pypdf/_cmap.py | 544 + .../site-packages/pypdf/_codecs/__init__.py | 61 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 2231 bytes .../__pycache__/_codecs.cpython-312.pyc | Bin 0 -> 9812 bytes .../__pycache__/adobe_glyphs.cpython-312.pyc | Bin 0 -> 691154 bytes .../__pycache__/pdfdoc.cpython-312.pyc | Bin 0 -> 1614 bytes .../_codecs/__pycache__/std.cpython-312.pyc | Bin 0 -> 1507 bytes .../__pycache__/symbol.cpython-312.pyc | Bin 0 -> 1906 bytes .../__pycache__/zapfding.cpython-312.pyc | Bin 0 -> 2142 bytes .../site-packages/pypdf/_codecs/_codecs.py | 268 + .../pypdf/_codecs/adobe_glyphs.py | 13969 ++++++++++++++++ .../site-packages/pypdf/_codecs/pdfdoc.py | 264 + .../site-packages/pypdf/_codecs/std.py | 258 + .../site-packages/pypdf/_codecs/symbol.py | 260 + .../site-packages/pypdf/_codecs/zapfding.py | 261 + .../pypdf/_crypt_providers/__init__.py | 86 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1185 bytes .../__pycache__/_base.cpython-312.pyc | Bin 0 -> 838 bytes .../__pycache__/_cryptography.cpython-312.pyc | Bin 0 -> 5976 bytes .../__pycache__/_fallback.cpython-312.pyc | Bin 0 -> 4016 bytes .../__pycache__/_pycryptodome.cpython-312.pyc | Bin 0 -> 4373 bytes .../pypdf/_crypt_providers/_base.py | 38 + .../pypdf/_crypt_providers/_cryptography.py | 118 + .../pypdf/_crypt_providers/_fallback.py | 93 + .../pypdf/_crypt_providers/_pycryptodome.py | 97 + .../site-packages/pypdf/_doc_common.py | 1446 ++ .../site-packages/pypdf/_encryption.py | 1178 ++ .../python3.12/site-packages/pypdf/_merger.py | 42 + .../python3.12/site-packages/pypdf/_page.py | 2686 +++ .../site-packages/pypdf/_page_labels.py | 289 + .../site-packages/pypdf/_protocols.py | 86 + .../python3.12/site-packages/pypdf/_reader.py | 1273 ++ .../pypdf/_text_extraction/__init__.py | 248 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 9580 bytes .../_text_extraction/_layout_mode/__init__.py | 16 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 518 bytes .../_fixed_width_page.cpython-312.pyc | Bin 0 -> 18033 bytes .../__pycache__/_font.cpython-312.pyc | Bin 0 -> 6722 bytes .../__pycache__/_font_widths.cpython-312.pyc | Bin 0 -> 4725 bytes .../_text_state_manager.cpython-312.pyc | Bin 0 -> 11742 bytes .../_text_state_params.cpython-312.pyc | Bin 0 -> 7394 bytes .../_layout_mode/_fixed_width_page.py | 394 + .../_text_extraction/_layout_mode/_font.py | 152 + .../_layout_mode/_font_widths.py | 208 + .../_layout_mode/_text_state_manager.py | 217 + .../_layout_mode/_text_state_params.py | 129 + .../python3.12/site-packages/pypdf/_utils.py | 605 + .../site-packages/pypdf/_version.py | 1 + .../python3.12/site-packages/pypdf/_writer.py | 3380 ++++ .../pypdf/_xobj_image_helpers.py | 379 + .../pypdf/annotations/__init__.py | 42 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1158 bytes .../__pycache__/_base.cpython-312.pyc | Bin 0 -> 1488 bytes .../_markup_annotations.cpython-312.pyc | Bin 0 -> 12990 bytes .../_non_markup_annotations.cpython-312.pyc | Bin 0 -> 4505 bytes .../site-packages/pypdf/annotations/_base.py | 27 + .../pypdf/annotations/_markup_annotations.py | 315 + .../annotations/_non_markup_annotations.py | 106 + .../site-packages/pypdf/constants.py | 722 + .../python3.12/site-packages/pypdf/errors.py | 66 + .../python3.12/site-packages/pypdf/filters.py | 836 + .../site-packages/pypdf/generic/__init__.py | 238 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 6766 bytes .../generic/__pycache__/_base.cpython-312.pyc | Bin 0 -> 38704 bytes .../_data_structures.cpython-312.pyc | Bin 0 -> 72306 bytes .../__pycache__/_files.cpython-312.pyc | Bin 0 -> 8151 bytes .../generic/__pycache__/_fit.cpython-312.pyc | Bin 0 -> 7105 bytes .../__pycache__/_image_inline.cpython-312.pyc | Bin 0 -> 8990 bytes .../__pycache__/_outline.cpython-312.pyc | Bin 0 -> 1827 bytes .../__pycache__/_rectangle.cpython-312.pyc | Bin 0 -> 7814 bytes .../__pycache__/_utils.cpython-312.pyc | Bin 0 -> 7990 bytes .../__pycache__/_viewerpref.cpython-312.pyc | Bin 0 -> 9067 bytes .../site-packages/pypdf/generic/_base.py | 910 + .../pypdf/generic/_data_structures.py | 1781 ++ .../site-packages/pypdf/generic/_files.py | 148 + .../site-packages/pypdf/generic/_fit.py | 174 + .../pypdf/generic/_image_inline.py | 299 + .../site-packages/pypdf/generic/_outline.py | 33 + .../site-packages/pypdf/generic/_rectangle.py | 132 + .../site-packages/pypdf/generic/_utils.py | 209 + .../pypdf/generic/_viewerpref.py | 164 + .../site-packages/pypdf/pagerange.py | 197 + .../site-packages/pypdf/papersizes.py | 52 + .../python3.12/site-packages/pypdf/py.typed | 0 .../python3.12/site-packages/pypdf/types.py | 77 + .../lib/python3.12/site-packages/pypdf/xmp.py | 394 + 118 files changed, 36900 insertions(+), 277 deletions(-) create mode 100644 venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/INSTALLER create mode 100644 venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/METADATA create mode 100644 venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/RECORD create mode 100644 venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/REQUESTED create mode 100644 venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/WHEEL create mode 100644 venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/licenses/LICENSE create mode 100644 venv/lib/python3.12/site-packages/pypdf/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/_cmap.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/_doc_common.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/_encryption.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/_merger.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/_page.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/_page_labels.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/_protocols.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/_reader.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/_utils.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/_version.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/_writer.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/_xobj_image_helpers.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/constants.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/errors.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/filters.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/pagerange.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/papersizes.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/types.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/__pycache__/xmp.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_cmap.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_codecs/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/_codecs.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/adobe_glyphs.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/pdfdoc.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/std.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/symbol.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/zapfding.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_codecs/_codecs.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_codecs/adobe_glyphs.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_codecs/pdfdoc.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_codecs/std.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_codecs/symbol.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_codecs/zapfding.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__pycache__/_base.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__pycache__/_cryptography.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__pycache__/_fallback.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__pycache__/_pycryptodome.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_crypt_providers/_base.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_crypt_providers/_cryptography.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_crypt_providers/_fallback.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_crypt_providers/_pycryptodome.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_doc_common.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_encryption.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_merger.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_page.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_page_labels.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_protocols.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_reader.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_text_extraction/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_text_extraction/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/_fixed_width_page.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/_font.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/_font_widths.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/_text_state_manager.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/_text_state_params.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_fixed_width_page.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_font.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_font_widths.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_text_state_manager.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_text_state_params.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_utils.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_version.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_writer.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/_xobj_image_helpers.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/annotations/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/annotations/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/annotations/__pycache__/_base.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/annotations/__pycache__/_markup_annotations.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/annotations/__pycache__/_non_markup_annotations.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/annotations/_base.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/annotations/_markup_annotations.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/annotations/_non_markup_annotations.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/constants.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/errors.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/filters.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_base.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_data_structures.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_files.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_fit.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_image_inline.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_outline.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_rectangle.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_utils.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_viewerpref.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/_base.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/_data_structures.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/_files.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/_fit.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/_image_inline.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/_outline.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/_rectangle.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/_utils.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/generic/_viewerpref.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/pagerange.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/papersizes.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/py.typed create mode 100644 venv/lib/python3.12/site-packages/pypdf/types.py create mode 100644 venv/lib/python3.12/site-packages/pypdf/xmp.py diff --git a/.cursorignore b/.cursorignore index 589f1da..53c77b8 100644 --- a/.cursorignore +++ b/.cursorignore @@ -3,3 +3,4 @@ pdfs/ node_modules/ pycache/ cloned_repo/ +extracted_texts/ \ No newline at end of file diff --git a/MTN6 Equipment Manifest REV6(Conveyor List).csv b/MTN6 Equipment Manifest REV6(Conveyor List).csv index f0018de..14e7591 100644 --- a/MTN6 Equipment Manifest REV6(Conveyor List).csv +++ b/MTN6 Equipment Manifest REV6(Conveyor List).csv @@ -2,7 +2,7 @@ Control Panel,Unit Number,Alias,Equipment Type,Type of Conveyor,Speed,Drive Hand BULK INBOUND NORTH,BS1-005,PS10-1,Powered-Belted,Level Belt,150,RH,460/3/60,25,5,Y,N,RPH3200BXB-FR,NA,24,12,N,Y,NA,NA,"36"" SG, Bi-directional" BULK INBOUND NORTH,BS1-010,PS10-2,Powered-Belted,Incline Belt,200,LH,460/3/60,25,15,Y,N,APH150MFOXLN,NA,24,,N,Y,NA,NA,"36"" SG" BULK INBOUND NORTH,BS1-011,PS10-3,Powered-Belted,Incline Belt,240,RH,460/3/60,25,15,Y,N,APH150MFOXLN,NA,24.00'',12'',,,,, -BULK INBOUND NORTH,BS1-015-CH,PS10-4CH,90� Spiral Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, +BULK INBOUND NORTH,BS1-015-CH,PS10-4CH,90° Spiral Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, BULK INBOUND NORTH,BS1-020,PS10-5,Powered-Belted,Level Belt,240,LH,460/3/60,25,15,Y,N,RPH3200BXB-FR,NA,24.00'',12'',N,Y,Y,QTY 4, BULK INBOUND NORTH,BS1-020-CH1,PS10-5CH1,Induct Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, BULK INBOUND NORTH,BS1-020-CH2,PS10-5CH2,Induct Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, @@ -12,17 +12,17 @@ BULK INBOUND NORTH,BS1-020-DIV1,PS10-5DIV1,Sorter,Divert Arm,NA,NA,NA,NA,NA,NA,N BULK INBOUND NORTH,BS1-020-DIV2,PS10-5DIV2,Sorter,Divert Arm,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, BULK INBOUND NORTH,BS1-020-DIV3,PS10-5DIV3,Sorter,Divert Arm,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, BULK INBOUND NORTH,BS1-020-DIV4,PS10-5DIV5,Sorter,Divert Arm,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, -BULK INBOUND NORTH,BS1-025-CH,PS10-6CH,90� Straight Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, +BULK INBOUND NORTH,BS1-025-CH,PS10-6CH,90° Straight Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, BULK INBOUND NORTH,BS2-005,PS11-1,Powered-Belted,Level Belt,150,RH,460/3/60,25,5,Y,N,RPH3200BXB-FR,NA,24.00'',12'',N,Y,NA,NA,"36"" SG" BULK INBOUND NORTH,BS2-010,PS11-2,Powered-Belted,Incline Belt,200,RH,460/3/60,25,5,Y,N,APH150MFOXLN,NA,24.00'',12'',Y,Y,NA,NA,"36"" SG" BULK INBOUND NORTH,BS2-015,PS11-3,Powered-Belted,Level Belt,240,RH,460/3/60,25,10,Y,N,RPH3200BXB-FR,NA,24.00'',12'',Y,Y,NA,NA, BULK INBOUND NORTH,BS2-020,PS11-4,Powered-Belted,Incline Belt,240,LH,460/3/60,25,10,Y,N,APH150MFOXLN,NA,24.00'',-,N,Y,NA,NA, -BULK INBOUND NORTH,BS2-025-CH,PS11-5CH,90� Spiral Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, +BULK INBOUND NORTH,BS2-025-CH,PS11-5CH,90° Spiral Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, BULK INBOUND NORTH,BS2-030,PS11-6,Powered-Belted,Incline Belt,240,RH,460/3/60,25,10,Y,N,APH150MFOXLN,NA,24.00'',-,N,Y,NA,NA,"36"" SG" BULK INBOUND NORTH,BS2-035,PS11-7,Powered-Belted,Incline Belt,240,RH,460/3/60,25,20,Y,N,APH150MFOXLN,NA,24.00'',-,N,Y,NA,NA,"36"" SG" BULK INBOUND NORTH,BS2-040,PS11-8,Powered-Belted,Incline Belt,240,RH,460/3/60,25,15,Y,N,APH150MFOXLN,NA,24.00'',-,N,Y,NA,NA,"36"" SG" BULK INBOUND NORTH,BS2-045,PS11-9,Powered-Belted,Incline Belt,240,RH,460/3/60,25,15,Y,N,APH150MFOXLN,NA,24.00'',12'',N,Y,NA,NA,"36"" SG" -BULK INBOUND NORTH,BS2-050-CH,PS11-10CH,90� Spiral Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, +BULK INBOUND NORTH,BS2-050-CH,PS11-10CH,90° Spiral Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, BULK INBOUND NORTH,BS2-055,PS11-11,Powered-Belted,Level Belt,240,LH,460/3/60,25,15,Y,N,RPH3200BXB-FR,NA,24.00'',12'',N,Y,Y,QTY 6, BULK INBOUND NORTH,BS2-055-CH1,PS11-11CH1,Induct Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, BULK INBOUND NORTH,BS2-055-CH2,PS11-11CH2,Induct Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, @@ -36,17 +36,17 @@ BULK INBOUND NORTH,BS2-055-DIV3,PS11-11DIV3,Sorter,Divert Arm,NA,NA,NA,NA,NA,NA, BULK INBOUND NORTH,BS2-055-DIV4,PS11-11DIV4,Sorter,Divert Arm,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, BULK INBOUND NORTH,BS2-055-DIV5,PS11-11DIV5,Sorter,Divert Arm,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, BULK INBOUND NORTH,BS2-055-DIV6,PS11-11DIV6,Sorter,Divert Arm,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, -BULK INBOUND NORTH,BS2-060-CH,PS1-12CH,90� Straight Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, +BULK INBOUND NORTH,BS2-060-CH,PS1-12CH,90° Straight Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, BULK INBOUND SOUTH,BS3-005,PS8-1,Powered-Belted,Level Belt,150,LH,460/3/60,25,7.5,Y,N,RPH3200BXB-FR,NA,24.00'',12'',N,Y,NA,NA, BULK INBOUND SOUTH,BS3-010,PS8-2,Powered-Belted,Incline Belt,200,LH,460/3/60,25,10,Y,N,RPH3200BXB-FR,NA,24.00'',12'',Y,Y,NA,NA, -BULK INBOUND SOUTH,BS3-015-CH,PS8-3CH,90� Spiral Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, +BULK INBOUND SOUTH,BS3-015-CH,PS8-3CH,90° Spiral Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, BULK INBOUND SOUTH,BS3-020,PS8-4,Powered-Belted,Incline Belt,240,LH,460/3/60,25,15,Y,N,APH150MFOXLN,NA,24.00'',-,N,Y,NA,NA,"36"" SG" BULK INBOUND SOUTH,BS3-025,PS8-5,Powered-Belted,Incline Belt,240,LH,460/3/60,25,15,Y,N,APH150MFOXLN,NA,24.00'',12'',N,Y,NA,NA,"36"" SG" BULK INBOUND SOUTH,BS3-030,PS8-6,Sorter,Intralox Flowsplitter,240,LH,460/3/60,25,5,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, BULK INBOUND SOUTH,BS3-035-CH,PS8-7CH,Straight Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, BULK INBOUND SOUTH,BS3-040,PS8-8,Powered-Belted,Incline Belt,240,RH,460/3/60,25,7.5,Y,N,APH150MFOXLN,NA,24.00'',-,N,Y,NA,NA, BULK INBOUND SOUTH,BS3-045,PS8-9,Powered-Belted,Incline Belt,240,LH,460/3/60,25,15,Y,N,APH150MFOXLN,NA,24.00'',-,N,Y,NA,NA, -BULK INBOUND SOUTH,BS3-050-CH,PS8-10CH,90� Spiral Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, +BULK INBOUND SOUTH,BS3-050-CH,PS8-10CH,90° Spiral Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, BULK INBOUND SOUTH,BS3-055,PS8-11,Powered-Belted,Level Belt,240,RH,460/3/60,25,10,Y,N,RPH3200BXB-FR,NA,24.00'',12'',N,Y,Y,QTY 4, BULK INBOUND SOUTH,BS3-055-CH1,PS8-11CH1,Induct Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, BULK INBOUND SOUTH,BS3-055-CH2,PS8-11CH2,Induct Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, @@ -56,7 +56,7 @@ BULK INBOUND SOUTH,BS3-055-DIV1,PS8-11DIV1,Sorter,Divert Arm,NA,NA,NA,NA,NA,NA,N BULK INBOUND SOUTH,BS3-055-DIV2,PS8-11DIV2,Sorter,Divert Arm,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, BULK INBOUND SOUTH,BS3-055-DIV3,PS8-11DIV3,Sorter,Divert Arm,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, BULK INBOUND SOUTH,BS3-055-DIV4,PS8-11DIV4,Sorter,Divert Arm,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, -BULK INBOUND SOUTH,BS3-060-CH,PS8-12CH,90� Straight Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, +BULK INBOUND SOUTH,BS3-060-CH,PS8-12CH,90° Straight Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, BULK INBOUND SOUTH,BS4-005-CH,PS9-1CH,Straight Chute,Chute,NA,NA,NA,25,NA,NA,NA,NA,NA,24.00'',24.00'',NA,NA,NA,NA, BULK INBOUND SOUTH,BS4-010,PS9-2,Powered-Belted,Decline Belt,240,RH,460/3/60,25,7.5,Y,N,APH150MFOXLN,NA,24.00'',-,N,Y,NA,NA, BULK INBOUND SOUTH,BS4-015,PS9-3,Powered-Belted,Level Belt,240,RH,460/3/60,25,7.5,Y,N,RPH3200BXB-FR,NA,24.00'',12'',N,Y,Y,QTY 4, diff --git a/app.py b/app.py index 11650d6..b981e3c 100644 --- a/app.py +++ b/app.py @@ -54,7 +54,8 @@ def get_views_dir_path(): def get_text_output_dir_path(): # Construct absolute path based on the script's directory script_dir = os.path.dirname(os.path.abspath(__file__)) - return os.path.join(script_dir, TEXT_OUTPUT_FOLDER) + # Use os.path.join to handle path separators correctly and avoid './' + return os.path.abspath(os.path.join(script_dir, TEXT_OUTPUT_FOLDER)) def normalize(text): """Normalize string for comparison: lowercase, treat '-' and '_' the same, remove all whitespace.""" @@ -68,12 +69,14 @@ def normalize(text): def read_manifest(csv_filepath): """Reads the manifest CSV into a list of dictionaries.""" manifest_items = [] + # Only require Alias and Panel now for basic grouping required_cols = {CSV_ALIAS_COL, CSV_PANEL_COL} optional_cols = {CSV_EQ_TYPE_COL, CSV_CONV_TYPE_COL} try: - with open(csv_filepath, mode='r', newline='', encoding='utf-8') as infile: + # Revert back to 'utf-8-sig' to handle potential BOM from Excel + with open(csv_filepath, mode='r', newline='', encoding='utf-8-sig') as infile: reader = csv.DictReader(infile) - headers = set(h.strip() for h in reader.fieldnames) # Handle potential whitespace in headers + headers = set(h.strip() for h in reader.fieldnames) # Check for required columns missing_required = required_cols - headers @@ -85,12 +88,16 @@ def read_manifest(csv_filepath): for row in reader: alias = row.get(CSV_ALIAS_COL, "").strip() panel = row.get(CSV_PANEL_COL, "").strip() - if alias and panel: # Only add if Alias and Control Panel are present + # unit_number = row.get('Unit Number', "").strip() # No longer needed for filename + + # Add if Alias and Control Panel are present (Panel needed for grouping results later) + if alias and panel: item = { "alias": alias, "normalized_alias": normalize(alias), "control_panel": panel, - "expected_drawing_filename": f"{panel}.txt", # Assuming .txt file matches panel name + # "unit_number": unit_number, # Removed + # "expected_drawing_filename": f"MTN6_SYSDL-{unit_number}.txt", # Removed # Add optional data if columns exist "equipment_type": row.get(CSV_EQ_TYPE_COL, "").strip() if CSV_EQ_TYPE_COL in headers else "N/A", "conveyor_type": row.get(CSV_CONV_TYPE_COL, "").strip() if CSV_CONV_TYPE_COL in headers else "N/A", @@ -99,8 +106,11 @@ def read_manifest(csv_filepath): "found_drawing": False } manifest_items.append(item) + # elif alias and panel: # If Unit Number is missing but others are present # Condition removed + # print(f"Warning: Alias '{alias}' in Panel '{panel}' is missing 'Unit Number' in CSV. Skipping drawing check for this item.") elif alias and not panel: print(f"Warning: Alias '{alias}' found in CSV but is missing its '{CSV_PANEL_COL}'. Skipping.") + # Add other specific warnings if needed except FileNotFoundError: print(f"Error: Manifest file not found at {csv_filepath}") @@ -154,44 +164,50 @@ def check_scada(manifest_data, views_dir): def check_drawings(manifest_data, text_output_dir): - """Checks for aliases in extracted drawing text files, one file per panel.""" + """Checks if aliases from manifest exist in *any* extracted drawing text file.""" if not manifest_data: return - print(f"Starting Drawings check in directory: {text_output_dir}...") - found_count = 0 - file_cache = {} # Cache normalized content of processed text files + print(f"Starting Drawings check: Scanning all .txt files in directory: {text_output_dir}...") - for item in manifest_data: - normalized_alias = item['normalized_alias'] - txt_filename = item['expected_drawing_filename'] - txt_filepath = os.path.join(text_output_dir, txt_filename) + all_normalized_content = "" # Combine all text content here + processed_files = 0 + found_files = [] - try: - # Check cache first - if txt_filepath in file_cache: - normalized_content = file_cache[txt_filepath] - # Read and cache if not already processed - elif os.path.exists(txt_filepath): - with open(txt_filepath, 'r', encoding='utf-8') as f: - content = f.read() - normalized_content = normalize(content) - file_cache[txt_filepath] = normalized_content # Cache it - else: - # File doesn't exist, mark as not found in cache to avoid re-checking - file_cache[txt_filepath] = None - # print(f" Info: Expected drawing text file not found: {txt_filepath}") - continue # Cannot find alias if file doesn't exist + try: + # Step 1: Read and combine content of all .txt files in the directory + for filename in os.listdir(text_output_dir): + if filename.lower().endswith('.txt'): + filepath = os.path.join(text_output_dir, filename) + processed_files += 1 + try: + with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() + # Add a separator to prevent false matches across file boundaries + all_normalized_content += normalize(content) + "\n--file-separator--\n" + found_files.append(filename) + except Exception as e: + print(f" Warning: Could not read or process text file {filepath}: {e}") - # Perform check if file content exists - if normalized_content is not None and normalized_alias in normalized_content: - if not item['found_drawing']: # Avoid double counting if alias appears multiple times in manifest - item['found_drawing'] = True - found_count += 1 + if processed_files == 0: + print(" Warning: No .txt files found in the directory. Cannot perform drawing check.") + return + else: + print(f" Successfully read and normalized content from {len(found_files)} out of {processed_files} .txt files found.") - except Exception as e: - print(f" Warning: Could not read or process text file {txt_filepath}: {e}") - file_cache[txt_filepath] = None # Mark as failed in cache + # Step 2: Check each manifest alias against the combined content + found_count = 0 + for item in manifest_data: + normalized_alias = item['normalized_alias'] + if normalized_alias and normalized_alias in all_normalized_content: + item['found_drawing'] = True + found_count += 1 + # else: item['found_drawing'] is already False by default - print(f"Drawings check finished. Processed {len(file_cache)} unique text files. Found {found_count} manifest aliases.") + print(f"Drawings check finished. Found {found_count} manifest aliases within the combined text content.") + + except FileNotFoundError: + print(f" Error: Drawings text directory not found: {text_output_dir}") + except Exception as e: + print(f" Error during drawings check: {e}") def calculate_combined_progress(manifest_data): @@ -323,10 +339,9 @@ def update_progress_data(): status_message = current_status # Update status regardless of calculation success/failure if new_data_calculated is not None: progress_data = new_data_calculated - - # Signal that an update attempt finished - data_updated_event.set() - data_updated_event.clear() + # Signal that an update attempt finished WITH new data + data_updated_event.set() + data_updated_event.clear() # --- Git Repo Handling (Modified slightly to use updated status messages) --- @@ -342,8 +357,6 @@ def check_and_update_repo(): if not repo_existed: print(f"Cloning repository {REPO_URL} into {repo_path}...") status_message = f"Cloning repository {REPO_URL}..." - # Signal status change during long operation - data_updated_event.set(); data_updated_event.clear() git.Repo.clone_from(REPO_URL, repo_path, branch=BRANCH) repo = git.Repo(repo_path) last_commit_hash = repo.head.commit.hexsha @@ -368,8 +381,6 @@ def check_and_update_repo(): if current_local_commit != current_remote_commit: print("New commit detected! Pulling changes...") status_message = "Pulling updates..." - # Signal status change during potentially long operation - data_updated_event.set(); data_updated_event.clear() try: pull_info = origin.pull() new_commit_hash = repo.head.commit.hexsha @@ -392,9 +403,10 @@ def check_and_update_repo(): # Status will be updated within update_progress_data update_progress_data() # If no git update, signal any status change (e.g., "No changes" or error) - else: - data_updated_event.set() # Signal status change event - data_updated_event.clear() + # else: # REMOVED block that signaled event for no changes + # REMOVED: data_updated_event.set() # Signal status change event + # REMOVED: data_updated_event.clear() + # Status message is still updated globally, just won't trigger event except git.GitCommandError as e: status_message = f"Git command error: {e}" @@ -407,14 +419,14 @@ def check_and_update_repo(): if last_commit_hash is None: last_commit_hash = repo.head.commit.hexsha except Exception: if last_commit_hash is None: last_commit_hash = "Error reading commit" - data_updated_event.set() # Signal error status change - data_updated_event.clear() + # REMOVED: data_updated_event.set() # Signal error status change + # REMOVED: data_updated_event.clear() except Exception as e: status_message = f"Error checking repository: {e}" print(status_message) if last_commit_hash is None: last_commit_hash = "Error checking repo" - data_updated_event.set() # Signal error status change - data_updated_event.clear() + # REMOVED: data_updated_event.set() # Signal error status change + # REMOVED: data_updated_event.clear() # Return true if analysis was run (because repo changed), false otherwise return did_update @@ -439,6 +451,16 @@ def periodic_repo_check(): def index(): return render_template('index.html') +@app.route('/drawings') +def drawings_page(): + # Render the main index template which now contains all content + return render_template('index.html') + +@app.route('/conflicts') +def conflicts_page(): + # Render the main index template which now contains all content + return render_template('index.html') + @app.route('/stream') def stream(): def event_stream(): @@ -479,11 +501,11 @@ def stream(): }) yield f"data: {data_payload}\n\n" last_sent_hash_to_client = current_global_hash # Update the hash sent to this client - else: + # else: # No need for the else block logging here anymore, as the event shouldn't trigger if hash is same # If hash is the same, maybe only the status message changed (e.g., error occurred) # Option: Send update only if status is different from last sent status? # For simplicity now, we only send if hash differs. Client UI shows last known status. - print(f"Data updated event triggered, but hash {current_global_hash} unchanged for this client. Status: '{current_global_status}'") + # print(f"Data updated event triggered, but hash {current_global_hash} unchanged for this client. Status: '{current_global_status}'") # Removed log return Response(event_stream(), mimetype="text/event-stream") diff --git a/cloned_repo b/cloned_repo index c8aa368..456de12 160000 --- a/cloned_repo +++ b/cloned_repo @@ -1 +1 @@ -Subproject commit c8aa36809970e0557f46ee80b7f7cf3735efb487 +Subproject commit 456de12cca56c09bc1881660b163ac3b5dff593a diff --git a/templates/index.html b/templates/index.html index 640278e..42d8986 100644 --- a/templates/index.html +++ b/templates/index.html @@ -3,7 +3,7 @@ - Ignition SCADA & Drawing Progress Monitor + SCADA Progress Monitor
-

SCADA & Drawing Device Placement Progress

+ + -
- Overall Progress - -
Found Both: 0/0 (0%)
+ +
+

SCADA Device Placement Progress

+

Compares the Equipment Manifest against the SCADA view.json files.

+ +
+ Overall SCADA Progress + +
Found in SCADA: 0/0 (0%)
+
+ +
+ +

SCADA Progress by Control Panel

+
+

Loading panel data...

+
-
+ + @@ -89,7 +130,6 @@ Panel SCADA Status Drawing Status - Expected Drawing File Equipment Type Type of Conveyor @@ -108,84 +148,332 @@ diff --git a/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/INSTALLER b/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/METADATA b/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/METADATA new file mode 100644 index 0000000..2eeaf52 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/METADATA @@ -0,0 +1,173 @@ +Metadata-Version: 2.4 +Name: pypdf +Version: 5.4.0 +Summary: A pure-python PDF library capable of splitting, merging, cropping, and transforming PDF files +Author-email: Mathieu Fenniak +Maintainer: stefan6419846 +Maintainer-email: Martin Thoma +Requires-Python: >=3.8 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Operating System :: OS Independent +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Typing :: Typed +License-File: LICENSE +Requires-Dist: typing_extensions >= 4.0; python_version < '3.11' +Requires-Dist: cryptography ; extra == "crypto" +Requires-Dist: PyCryptodome ; extra == "cryptodome" +Requires-Dist: black ; extra == "dev" +Requires-Dist: flit ; extra == "dev" +Requires-Dist: pip-tools ; extra == "dev" +Requires-Dist: pre-commit<2.18.0 ; extra == "dev" +Requires-Dist: pytest-cov ; extra == "dev" +Requires-Dist: pytest-socket ; extra == "dev" +Requires-Dist: pytest-timeout ; extra == "dev" +Requires-Dist: pytest-xdist ; extra == "dev" +Requires-Dist: wheel ; extra == "dev" +Requires-Dist: myst_parser ; extra == "docs" +Requires-Dist: sphinx ; extra == "docs" +Requires-Dist: sphinx_rtd_theme ; extra == "docs" +Requires-Dist: cryptography ; extra == "full" +Requires-Dist: Pillow>=8.0.0 ; extra == "full" +Requires-Dist: Pillow>=8.0.0 ; extra == "image" +Project-URL: Bug Reports, https://github.com/py-pdf/pypdf/issues +Project-URL: Changelog, https://pypdf.readthedocs.io/en/latest/meta/CHANGELOG.html +Project-URL: Documentation, https://pypdf.readthedocs.io/en/latest/ +Project-URL: Source, https://github.com/py-pdf/pypdf +Provides-Extra: crypto +Provides-Extra: cryptodome +Provides-Extra: dev +Provides-Extra: docs +Provides-Extra: full +Provides-Extra: image + +[![PyPI version](https://badge.fury.io/py/pypdf.svg)](https://badge.fury.io/py/pypdf) +[![Python Support](https://img.shields.io/pypi/pyversions/pypdf.svg)](https://pypi.org/project/pypdf/) +[![](https://img.shields.io/badge/-documentation-green)](https://pypdf.readthedocs.io/en/stable/) +[![GitHub last commit](https://img.shields.io/github/last-commit/py-pdf/pypdf)](https://github.com/py-pdf/pypdf) +[![codecov](https://codecov.io/gh/py-pdf/pypdf/branch/main/graph/badge.svg?token=id42cGNZ5Z)](https://codecov.io/gh/py-pdf/pypdf) + +# pypdf + +pypdf is a free and open-source pure-python PDF library capable of splitting, +[merging](https://pypdf.readthedocs.io/en/stable/user/merging-pdfs.html), +[cropping, and transforming](https://pypdf.readthedocs.io/en/stable/user/cropping-and-transforming.html) +the pages of PDF files. It can also add +custom data, viewing options, and +[passwords](https://pypdf.readthedocs.io/en/stable/user/encryption-decryption.html) +to PDF files. pypdf can +[retrieve text](https://pypdf.readthedocs.io/en/stable/user/extract-text.html) +and +[metadata](https://pypdf.readthedocs.io/en/stable/user/metadata.html) +from PDFs as well. + +See [pdfly](https://github.com/py-pdf/pdfly) for a CLI application that uses pypdf to interact with PDFs. + +## Installation + +Install pypdf using pip: + +``` +pip install pypdf +``` + +For using pypdf with AES encryption or decryption, install extra dependencies: + +``` +pip install pypdf[crypto] +``` + +> **NOTE**: `pypdf` 3.1.0 and above include significant improvements compared to +> previous versions. Please refer to [the migration +> guide](https://pypdf.readthedocs.io/en/latest/user/migration-1-to-2.html) for +> more information. + +## Usage + +```python +from pypdf import PdfReader + +reader = PdfReader("example.pdf") +number_of_pages = len(reader.pages) +page = reader.pages[0] +text = page.extract_text() +``` + +pypdf can do a lot more, e.g. splitting, merging, reading and creating +annotations, decrypting and encrypting, and more. Check out [the +documentation](https://pypdf.readthedocs.io/en/stable/) for additional usage +examples! + +For questions and answers, visit +[StackOverflow](https://stackoverflow.com/questions/tagged/pypdf) +(tagged with [pypdf](https://stackoverflow.com/questions/tagged/pypdf)). + +## Contributions + +Maintaining pypdf is a collaborative effort. You can support the project by +writing documentation, helping to narrow down issues, and submitting code. +See the [CONTRIBUTING.md](https://github.com/py-pdf/pypdf/blob/main/CONTRIBUTING.md) file for more information. + +### Q&A + +The experience pypdf users have covers the whole range from beginners who +want to make their live easier to experts who developed software before PDF +existed. You can contribute to the pypdf community by answering questions +on [StackOverflow](https://stackoverflow.com/questions/tagged/pypdf), +helping in [discussions](https://github.com/py-pdf/pypdf/discussions), +and asking users who report issues for [MCVE](https://stackoverflow.com/help/minimal-reproducible-example)'s (Code + example PDF!). + + +### Issues + +A good bug ticket includes a MCVE - a minimal complete verifiable example. +For pypdf, this means that you must upload a PDF that causes the bug to occur +as well as the code you're executing with all of the output. Use +`print(pypdf.__version__)` to tell us which version you're using. + +### Code + +All code contributions are welcome, but smaller ones have a better chance to +get included in a timely manner. Adding unit tests for new features or test +cases for bugs you've fixed help us to ensure that the Pull Request (PR) is fine. + +pypdf includes a test suite which can be executed with `pytest`: + +```bash +$ pytest +===================== test session starts ===================== +platform linux -- Python 3.6.15, pytest-7.0.1, pluggy-1.0.0 +rootdir: /home/moose/GitHub/Martin/pypdf +plugins: cov-3.0.0 +collected 233 items + +tests/test_basic_features.py .. [ 0%] +tests/test_constants.py . [ 1%] +tests/test_filters.py .................x..... [ 11%] +tests/test_generic.py ................................. [ 25%] +............. [ 30%] +tests/test_javascript.py .. [ 31%] +tests/test_merger.py . [ 32%] +tests/test_page.py ......................... [ 42%] +tests/test_pagerange.py ................ [ 49%] +tests/test_papersizes.py .................. [ 57%] +tests/test_reader.py .................................. [ 72%] +............... [ 78%] +tests/test_utils.py .................... [ 87%] +tests/test_workflows.py .......... [ 91%] +tests/test_writer.py ................. [ 98%] +tests/test_xmp.py ... [100%] + +========== 232 passed, 1 xfailed, 1 warning in 4.52s ========== +``` + diff --git a/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/RECORD b/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/RECORD new file mode 100644 index 0000000..3e0f771 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/RECORD @@ -0,0 +1,113 @@ +pypdf-5.4.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pypdf-5.4.0.dist-info/METADATA,sha256=E-D5PSflgLScgSvyNJcLdhpDBX4H0QUafueJFd7PDSA,7262 +pypdf-5.4.0.dist-info/RECORD,, +pypdf-5.4.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pypdf-5.4.0.dist-info/WHEEL,sha256=_2ozNFCLWc93bK4WKHCO-eDUENDlo-dgc9cU3qokYO4,82 +pypdf-5.4.0.dist-info/licenses/LICENSE,sha256=qXrCMOXzPvEKU2eoUOsB-R8aCwZONHQsd5TSKUVX9SQ,1605 +pypdf/__init__.py,sha256=WYkiisiLw4TrsrobuzUkEFGwAUbPF8V8ei_HJSdEJNY,1302 +pypdf/__pycache__/__init__.cpython-312.pyc,, +pypdf/__pycache__/_cmap.cpython-312.pyc,, +pypdf/__pycache__/_doc_common.cpython-312.pyc,, +pypdf/__pycache__/_encryption.cpython-312.pyc,, +pypdf/__pycache__/_merger.cpython-312.pyc,, +pypdf/__pycache__/_page.cpython-312.pyc,, +pypdf/__pycache__/_page_labels.cpython-312.pyc,, +pypdf/__pycache__/_protocols.cpython-312.pyc,, +pypdf/__pycache__/_reader.cpython-312.pyc,, +pypdf/__pycache__/_utils.cpython-312.pyc,, +pypdf/__pycache__/_version.cpython-312.pyc,, +pypdf/__pycache__/_writer.cpython-312.pyc,, +pypdf/__pycache__/_xobj_image_helpers.cpython-312.pyc,, +pypdf/__pycache__/constants.cpython-312.pyc,, +pypdf/__pycache__/errors.cpython-312.pyc,, +pypdf/__pycache__/filters.cpython-312.pyc,, +pypdf/__pycache__/pagerange.cpython-312.pyc,, +pypdf/__pycache__/papersizes.cpython-312.pyc,, +pypdf/__pycache__/types.cpython-312.pyc,, +pypdf/__pycache__/xmp.cpython-312.pyc,, +pypdf/_cmap.py,sha256=Q4_EJC73QZ-0_I4jtLeHD-rkT5GASW9zehhNcums_0A,18642 +pypdf/_codecs/__init__.py,sha256=WXMkzlMCDlmG5U6ixQk8MrYxaQeJxEfig5DTaGlklLk,1676 +pypdf/_codecs/__pycache__/__init__.cpython-312.pyc,, +pypdf/_codecs/__pycache__/_codecs.cpython-312.pyc,, +pypdf/_codecs/__pycache__/adobe_glyphs.cpython-312.pyc,, +pypdf/_codecs/__pycache__/pdfdoc.cpython-312.pyc,, +pypdf/_codecs/__pycache__/std.cpython-312.pyc,, +pypdf/_codecs/__pycache__/symbol.cpython-312.pyc,, +pypdf/_codecs/__pycache__/zapfding.cpython-312.pyc,, +pypdf/_codecs/_codecs.py,sha256=zduPFkHbt9BjCpAc7Mx_rSOTEoSOZkUayr8EL5l82VM,9966 +pypdf/_codecs/adobe_glyphs.py,sha256=t3cDFPDqwIz1w9B0gdVzjdc8eEK9AuRjk5f7laEw_fY,447213 +pypdf/_codecs/pdfdoc.py,sha256=xfSvMFYsvxuaSQ0Uu9vZDKaB0Wu85h1uCiB1i9rAcUU,4269 +pypdf/_codecs/std.py,sha256=DyQMuEpAGEpS9uy1jWf4cnj-kqShPOAij5sI7Q1YD8E,2630 +pypdf/_codecs/symbol.py,sha256=nIaGQIlhWCJiPMHrwUlmGHH-_fOXyEKvguRmuKXcGAk,3734 +pypdf/_codecs/zapfding.py,sha256=PQxjxRC616d41xF3exVxP1W8nM4QrZfjO3lmtLxpE_s,3742 +pypdf/_crypt_providers/__init__.py,sha256=K3Z6AuXhXVeXgLet-Tukq2gt9H66OgdupsvxIS1CmkI,3054 +pypdf/_crypt_providers/__pycache__/__init__.cpython-312.pyc,, +pypdf/_crypt_providers/__pycache__/_base.cpython-312.pyc,, +pypdf/_crypt_providers/__pycache__/_cryptography.cpython-312.pyc,, +pypdf/_crypt_providers/__pycache__/_fallback.cpython-312.pyc,, +pypdf/_crypt_providers/__pycache__/_pycryptodome.cpython-312.pyc,, +pypdf/_crypt_providers/_base.py,sha256=_f53Mj6vivhEZMQ4vNxN5G0IOgFY-n5_leke0c_qiNU,1711 +pypdf/_crypt_providers/_cryptography.py,sha256=zT3WmbPzesvgHRkGcKAldqJ24MY3BwZViVbSc55Zxhw,4557 +pypdf/_crypt_providers/_fallback.py,sha256=vsYoowR1YCAV_q-HrdIZhkUcrCb6HvRBNMYm03QtCU8,3334 +pypdf/_crypt_providers/_pycryptodome.py,sha256=U1aQZ9iYBrZo-hKCjJUhGOPhwEFToiitowQ316TNrrA,3381 +pypdf/_doc_common.py,sha256=lyM-6je3IbNfzL6gfYdFU2VvX3pkxj5AWHcEZRCFMQk,51871 +pypdf/_encryption.py,sha256=pPg7fIfqdL96Tc6RVoBytEVjMrmZFecr_6l7dbtDFrE,48775 +pypdf/_merger.py,sha256=YfSQKDiiQz2WtCmVZjxP_nv2pR2shiBf2tDiAb41c7s,1744 +pypdf/_page.py,sha256=6Pts2harKZyD_qhKdbNjWLwy07Gw0QLTWIf_fAMENaA,102235 +pypdf/_page_labels.py,sha256=nEU0knE7IRQ6LPhzwgw1RjJgm8WxXIfkmiHuv7ep2ow,8546 +pypdf/_protocols.py,sha256=noE1y2fVE-z1wq-FkQzaS5exa8ovOFTUXqdQSvqi57c,2142 +pypdf/_reader.py,sha256=tf8l66t8DmoeuZviN2YOdFHAwahnTu92ABAXiK9zCUA,51503 +pypdf/_text_extraction/__init__.py,sha256=0zxSe5aXqO15dpOg5Q24FawupoTbvJCiHfBzGsWgpJE,8556 +pypdf/_text_extraction/__pycache__/__init__.cpython-312.pyc,, +pypdf/_text_extraction/_layout_mode/__init__.py,sha256=k1tN46gDX1zhAatD8oTGMuCJUp-pgbHjyQ8H6axXRgU,338 +pypdf/_text_extraction/_layout_mode/__pycache__/__init__.cpython-312.pyc,, +pypdf/_text_extraction/_layout_mode/__pycache__/_fixed_width_page.cpython-312.pyc,, +pypdf/_text_extraction/_layout_mode/__pycache__/_font.cpython-312.pyc,, +pypdf/_text_extraction/_layout_mode/__pycache__/_font_widths.cpython-312.pyc,, +pypdf/_text_extraction/_layout_mode/__pycache__/_text_state_manager.cpython-312.pyc,, +pypdf/_text_extraction/_layout_mode/__pycache__/_text_state_params.cpython-312.pyc,, +pypdf/_text_extraction/_layout_mode/_fixed_width_page.py,sha256=xXC6BwQvrOXMZmSKQ6UPnPtCnjjZ9jCCWTbEJ35E3ko,15424 +pypdf/_text_extraction/_layout_mode/_font.py,sha256=F0uvly32AcFeTE4jBFg7JvuAQZSMUjO6HZgQYYFDQ40,7048 +pypdf/_text_extraction/_layout_mode/_font_widths.py,sha256=Hfgsd2ftGw8Ajl7IcwNIlfLYnum-ekaadfwErcUdWtI,4265 +pypdf/_text_extraction/_layout_mode/_text_state_manager.py,sha256=ugOJRALDNXW3snNAjKKKT8xmWt7D3GZZbcMVaGuVfFM,7989 +pypdf/_text_extraction/_layout_mode/_text_state_params.py,sha256=b8DSoJ2easCZW_JvMl84WFFIANKGhLD1zjMVAlqScyU,5318 +pypdf/_utils.py,sha256=h97CvvcQpxq7px__GzaMGzJWqJGZt2FYsZYR6wFiU3w,19300 +pypdf/_version.py,sha256=xjYaBGUFGg0kGZj_WhuoFyPD8NILPsr79SaMwmYQGSg,22 +pypdf/_writer.py,sha256=Kjrk1_uMUyZBlsze0qQhS-We90GIk3WtclKLzb373-s,128663 +pypdf/_xobj_image_helpers.py,sha256=KVC80bgNcHBdqGEOfQbmQO4in6Foayt_lPTgSOgb-BA,14020 +pypdf/annotations/__init__.py,sha256=f2k_-jAn39CCB27KxQ_e93GinnzkAHbUnnSeGJl1jyE,990 +pypdf/annotations/__pycache__/__init__.cpython-312.pyc,, +pypdf/annotations/__pycache__/_base.cpython-312.pyc,, +pypdf/annotations/__pycache__/_markup_annotations.cpython-312.pyc,, +pypdf/annotations/__pycache__/_non_markup_annotations.cpython-312.pyc,, +pypdf/annotations/_base.py,sha256=7rQJyOMPtKkd_Yp2CXGT6KN17W3WOj8Albx6ehMki3w,916 +pypdf/annotations/_markup_annotations.py,sha256=F4qMyS15OqXNLL9OTR5Wj2_4vO7ScG60yqNh-wayIFQ,10116 +pypdf/annotations/_non_markup_annotations.py,sha256=qX51TJMTRUyWz1ogIK-cXXGK7k5oKhgYQhemA_sVxGE,3622 +pypdf/constants.py,sha256=gwFz97ZB5j0Nn5R7LbWBUqBOcyEjIQRV7O598eLZSKc,20959 +pypdf/errors.py,sha256=x0J5mTIbp5YcXA1pdYa5DO83uAhXP5NCO0Ankf4DsUY,1740 +pypdf/filters.py,sha256=hT6e4odOa6WTpXYOxRm2r6fYOS2cocLsVdNPpjEPhn8,27869 +pypdf/generic/__init__.py,sha256=nnLmD7bnhSJu1qZ774pj0eE7lmeRuYDEUcpa52-Mk5A,7168 +pypdf/generic/__pycache__/__init__.cpython-312.pyc,, +pypdf/generic/__pycache__/_base.cpython-312.pyc,, +pypdf/generic/__pycache__/_data_structures.cpython-312.pyc,, +pypdf/generic/__pycache__/_files.cpython-312.pyc,, +pypdf/generic/__pycache__/_fit.cpython-312.pyc,, +pypdf/generic/__pycache__/_image_inline.cpython-312.pyc,, +pypdf/generic/__pycache__/_outline.cpython-312.pyc,, +pypdf/generic/__pycache__/_rectangle.cpython-312.pyc,, +pypdf/generic/__pycache__/_utils.cpython-312.pyc,, +pypdf/generic/__pycache__/_viewerpref.cpython-312.pyc,, +pypdf/generic/_base.py,sha256=u8oX747OyUZ5KPG8IYWUGD6lgeL-_MzWX0J-LsY0DjA,30885 +pypdf/generic/_data_structures.py,sha256=kqIGv06r3p0BeUrmTePeFrEoB4v0LiulDvEkTt45TN8,63998 +pypdf/generic/_files.py,sha256=UcyL_mCDpVh_dRuxxH8bENWA76rYt5eFw0emFcOE79Y,5655 +pypdf/generic/_fit.py,sha256=lLkLgW0AQ36sVG4py-HXV__EPQYkLA1bNLoCwGJ_ijI,5511 +pypdf/generic/_image_inline.py,sha256=OyP1GDpg-zgH-UWA--vsLIUriV_07-VqpFZ9mL31vl8,11447 +pypdf/generic/_outline.py,sha256=qKbMX42OWfqnopIiE6BUy6EvdTLGe3ZtjaiWN85JpaY,1094 +pypdf/generic/_rectangle.py,sha256=5KJRbQESqdzrYvJOFcwfp0_v_bhCDVj9r4yMyGXSGyc,3808 +pypdf/generic/_utils.py,sha256=8T_2fGpRt9tZpN-06fa-7Wma9gFAkdtgJW2SuD7Yqfk,7415 +pypdf/generic/_viewerpref.py,sha256=40YdivA2MAW6hTZEB-b_8Y84-tlNJNwXEusPmHMgS64,6739 +pypdf/pagerange.py,sha256=9QqjrP6VrR2m8BN_sbbjZQ8Fi476xPpRiKqd8CxGoKM,6996 +pypdf/papersizes.py,sha256=6Tz5sfNN_3JOUapY83U-lakohnpXYA0hSEQNmOVLFL8,1413 +pypdf/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pypdf/types.py,sha256=6B6pMncEhcqFfq-iKs5IBPg6guWXffU6YHpeYzCJH-s,1963 +pypdf/xmp.py,sha256=0G9Gmb5lc7jdcGG-MYDSxYPg5P7SU_RswVRipuDY7lU,14246 diff --git a/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/REQUESTED b/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/WHEEL b/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/WHEEL new file mode 100644 index 0000000..23d2d7e --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.11.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/licenses/LICENSE b/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/licenses/LICENSE new file mode 100644 index 0000000..ab327d0 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf-5.4.0.dist-info/licenses/LICENSE @@ -0,0 +1,29 @@ +Copyright (c) 2006-2008, Mathieu Fenniak +Some contributions copyright (c) 2007, Ashish Kulkarni +Some contributions copyright (c) 2014, Steve Witham + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +* The name of the author may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/venv/lib/python3.12/site-packages/pypdf/__init__.py b/venv/lib/python3.12/site-packages/pypdf/__init__.py new file mode 100644 index 0000000..87accc4 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/__init__.py @@ -0,0 +1,49 @@ +""" +pypdf is a free and open-source pure-python PDF library capable of splitting, +merging, cropping, and transforming the pages of PDF files. It can also add +custom data, viewing options, and passwords to PDF files. pypdf can retrieve +text and metadata from PDFs as well. + +You can read the full docs at https://pypdf.readthedocs.io/. +""" + +from ._crypt_providers import crypt_provider +from ._doc_common import DocumentInformation +from ._encryption import PasswordType +from ._merger import PdfMerger +from ._page import PageObject, Transformation, mult +from ._reader import PdfReader +from ._version import __version__ +from ._writer import ObjectDeletionFlag, PdfWriter +from .constants import ImageType +from .pagerange import PageRange, parse_filename_page_ranges +from .papersizes import PaperSize + +try: + import PIL + + pil_version = PIL.__version__ +except ImportError: + pil_version = "none" + +_debug_versions = ( + f"pypdf=={__version__}, {crypt_provider=}, PIL={pil_version}" +) + +__all__ = [ + "DocumentInformation", + "ImageType", + "ObjectDeletionFlag", + "PageObject", + "PageRange", + "PaperSize", + "PasswordType", + "PdfMerger", + "PdfReader", + "PdfWriter", + "Transformation", + "__version__", + "_debug_versions", + "mult", + "parse_filename_page_ranges", +] diff --git a/venv/lib/python3.12/site-packages/pypdf/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac32b380f7355b9acc288e5ef56123816eea3e7a GIT binary patch literal 1518 zcmY*Y&1)n@6tAA|=}BfLlVmqvt|clMm`vm5pvXoD#DyWQ4slV^piO1EX41P=T}@TZ z%uYa1PkRu=(+a_hC%x^zkh7O~lU_muPkW2IxJXXEs>$Hmhu6QVdLO^{t5?6y&bkP` zC*Qs3U&|x(r&&zD!WDS_0>C2_A|HiLm|+gj_!-CGEX(qopR+i}^1R>|EY7ncFZm^l z3#`mt-{lp*!e{&$yH{khyy{miF0mS~`*n-UY>qel2A}um?b>Ave9>RDxWcaS>;84V zlFKNOUA()wDbl zqSQ#pP+=`z&NS)CB$HIjhz_Z%=>u(JIMu|Ygl-`@l!wk09#O_xuDdS=mV=}ONCVH_ zfH543E;wm?sCA;=^E{irWqiQJ9JV6iwcMv5Ct7#XYFCaE9VAi=qmWA2ncorJ0jIHU z$3_HVT7d1D&K3W==y}^i{wf(6B`+ zK`^9JLFyn_&!mk>><(qrl)KGH-xl~xM%wz9+Z-y`(iu1byhq|bO;-{k6%EX##Dvqp zTvY(|;lgZ5l2G|cbVQ$;Is7Qi#UiFhMXSly*3q1~`j^|^Iw~}Ar~Tp9dQIjaLRO8L zF{Wrt&6qi3;E^I}UZyk;SI!z!GNuA1tpy=H81$z-Dp@v1bujBVEd~MHLlC6(;Q!T? z%$neeJ?;w5MQmBX4vnoVXk#lw4l}$|S_*02_C29!NtklrV{RRM48ycEB{N}I3`SPl zNppsNTJFNEY7%Q@+fK_yOsnOjZ$m$I6C@76iYb=deVVd)}eo)QkFYWUkx0BLE25k)kiDQr?ipLl53A46k|0o2|ERdI~0C zBO%@UKuS%f+6#gR0)wEHj4w;KxCjS~zAxW`5@x#9mtZckj^q55DLT2o8_3x>L(Mbv z<{7$ijy8Won*h$xYv<_Z8N%o27T}9q-dTQ)S1K O(kgDhn>~5Q0sAkA(8K)z literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/__pycache__/_cmap.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/__pycache__/_cmap.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..73d7e260b45f74cd75d5c625e1260d056896e3b5 GIT binary patch literal 20325 zcmdUX3ve4}e%~$@i#I@k00_PbK1E6*DUp&a%aUyIWxZvIlFyPKJdg`gkVueTfO_yi zpK?tb(pDCNGF~uFnJ$=+ zFG{*e^OWU+Wy*TN%HsM-+f>8}{qRAHb>h!oK;=3(c!$Z`yl_1Co*s#puQzfTL}T2@~t zm7#vMWS1QNnoCcr%Ts)7IDef~{sFI~NX`#53KZbRwHNAt)$uC5`5PqHepC-|l3S{{ z%}X8@R!UWXt65kh)dH?#VLeM}V4+uPM0yhoo23@Ott@O~;T9IQv(`FTxRsUMCN&25 zf5u<%V(lu_)x;>a=SR^gb)lth7Vco-P8Rk^y-451!rd&~!@?(|y-0tOh5K0e6btuD z2atY{g-^5a85SO5VV~5?M$yPdQJLSt2C1J$A*s9ewR@gF3tDLaJJyu1w`r|$tu%-- z&4sp0PmbPSSv*rHIfRle(z7^)hc`cW(h-ciaPn|QE5;4dQPgV9x8H_Vjv>B9I___i zPWaoUllYzT8zmm+qtc(Bu`>QgT6@l)9}heG?f&-7YmEzR%r@yX`srZ(Y#ddwov-TG z@)a$cq%&x9>toxrNId2|jB?x9oX-MZEo@ah`CZXT=a9QydcHJO`UY0j;`fZ}q!*Ce z`AF{hLhc3RcCnVfYF0!UN_IhAwS4ae=|!~AeVy-k>2pHQlO254I2*j^zcv{dzmAA@ z%paKS&}D@~!RuM=KwvDK)gBLo!dda`?98M;E1nAmrh_Qv3xz)?T<_3iEk0>_)ITyY zd41+$C~F_P=#xYK@Q6P+HZ28$6I5bydSb#akN9PITF%PVj!erV!ReqsYaE{rhDUYK zN3I5>@Wre!J$fmtll|dYIXEWJwDXUMH^tXM^g-Jr8i}XVBQaVU;Rv1=!g-3uaS=Wu zs8sDGaD#d6yg09$*GIGwF`|p;Bf_{i%ykI9@1lyyi)X+e_RCX&px+w^j!(-|KAMl$ zH#$8V_WHau+%6L^IdHXD?>3bnB;`@AnGYwMksz0dh3{NAe<{j%SCeR|eA<_mhq z13?MhcAxQwrf20bzgH^ki8AmrY*kCfK7>hmL$jlu;p;R0?aE-3eejOS0W3$r=WXA; zqt!b-u8gr`yH`Ca+r3l1884k5-xx}EBDS5aKxeVr;_%O2^go*E4TMAf$#I%%Xf_b` zjZRV#*&9aDu~|7VJsZj|_?)RQr_h|(O{2!?uN<8XOiCj(f)R8+GA>U~jZohm2HAzv zAd@s8S0Ko0#=}_)+bB$y=9;y!*hSyuINO1&mBrP$WeqHfRzn8Vr){R^;i>M6(^LNL zz(g=Whok$%G=OROIeB_Q_J=~%-IIaQ?wRZ1i_^j0uAM#IA*^F34)|qkSO^(2 z(s=jC7@F>yxt_IcoP+E|Zw~xI{RnPwIWJe+5R0U0wkN)ks@c69NYy-Zqi=2h*^I#% zJ+m%o4(L+aCvO~&cEvlFD|0%|QW>jH)ZH_D+>|sAB(($UXoi!k5sc+IJSA`iT>3*q z-sXx}6E2jB@CtriqOy-XALQdIe$8vbdbLP|{~(WpFQKh@VO|?Hs(F$oB1E(w2ugfj z44c&)U@N4uIrLR%Qx~=ta&-|=O-Cuz0v>A!ha=i?EwEVYyZjHt;>RLq_+lw;GQ=$4 zB|8}HL82Fvlh?g;qSy&mP#SpSE8<8;5g*3G`@BPheMP$Ye~zPn4-_qq;2(sM4-MVJ z3MM_|y?>qGr)N6!GRfvy0hBLmngCk?)gta-A-I5CZ zH=w)RfG%WWEG%dT5Sm4BgL~lR9PYPFV8S`<@#|)~Z_Lqv@)S zl(yo=;f0Gob#F-si5HfyrQOfmIJxHTNHirb-|J6xJ*^~owk8hVJDBzy{d73xc`m7S z0f~*}8AD~pV83s$=gc~bF30Iao!p3?v-)$v%facZ!9dv-j{BU$p`Rse`k(*y-(>Bx zN>+g&&Y8Q9Nd90r5We1d_@Qw&Jl?r;Pv@w=H2wKGWB0RtorCB4I}c}tiP6i&`12_D zY~RdSK2tX_+S9wUr!?_-(B)_QjwuC7;OFNIl-_d;ZR#gRckbQMyQ7dql?KoHgPnc5 zku8qRJh^*ENz(Ik7M48~Vg)wDo}Vl0hD6hUa=7!{*&)p3@S_RO&)KL1W~3I_7=J!% zADNN;V7_4UU>!Ip7+62JWdOYH1rV$`s~YX>o1T>BTpOaNMkfQW&id!>l_o%BHtyZZT0vCVVtUrJ|#tlczOZLIQ_ za@8D5_u0UdKh$|U9VL+?Vc%q649lZb$w&3w!`G)qrzeqq!8bEL z0C{KB7Y=2sNAd#B2w`-n6vf7{I)w*%=6(q!+=m%NM+1L1A(u= zo+5l$r?#sy3%MpD3~(<)2AJ1Iv=Vp(czyk|sD37+kJFuc}%s8sQ<5}R?fg# zT+tVj=DMV|j?t72`#}tuR(t&!?9AKT1UC;cAi`bYRo)OOn2Kt7H!HATLYO!= zdy3-dWl(q7687dZxCk?qk(x+Y9}y(m9L@<^ctXpS^u&jo)EesOO6@3~oDy_PXDEGT+xsI}v5GMwMie=%UvAfR~@{`aj_hMpMJ!x*l zfpwkd`iFZuWo$AxXADk<72S8P{E&2oXsJ}tIlXf(sK{Y&U<&4qDNs=4UH6B|^lchqErF$SSJ`Qae?S*986q#sUM>&&N-H5ojE|Hs+rp9Z&W^Q64}2C=cGfme#v1G_NTq~9BDM!1SM@dz&;iZO5P1};;rxgux zbGl-C(!Tv?4-A~i742WC>R2&uO?>;~=2Z7!PNO#t@N1qeA8J1wUT$8VPW23>+n-H& z4zGGnq&z3mo>Pm5AJ{opOS0vOlymQ@^FYdZAnkm5!I06rV@_HZNBIK(Q->Qv{7}2n zdEj0s-QNH4$yEDr+Hv+v&S>;399k=@iZ#AFyi(Sfak-cHoL1{-$#^Q??TuY~=fG#4 z_O-U2<(+q@V}`inju{hnlt)i5=}^##>JMB+ZoB66yeqsr7;k>(Xu^=L+?jUvU?gVe zjZ;5+@DyjSB34|pW~ofpbSB0U=aM}`$*O1nv~tCACgZ7o{V=iPnqPo@Q%R9#ZmGg4{YzWv#9?uWJ2hb@{Pbv8U(Cj2`aPht74!$#p# z15csFcDPRbw3bJ>K_npUorwew0lW<>|2z+|0M<7q7PLjUOQixG%FrWez}EAmPtsn7 zI3rt2#W)hMR6D>h+MK{`2pG3GFW{$@IM@b?f?bh#>LR*J1xtg{6YEWbRIKPqax+@Ya&x-w zvoI&^99pMEFokH!UL%=gq2p%DM@Tc>IpUjyfh-7n;uXk<&_5ta`k{Pe#n8-TAe=3m zk*7hGLP#2!gkpkpSPo~P=n`vWBBMM=-Jz~hP@c$IRG6q})-nZSVt^`-AWws~wG`Pz zojpWNQtT>CRe$3++AvykA}2Z^vjWBY-l)IPm$8?> zZCEnI+_%fV*(Uq=#{jkK4YoK;PlgoO1_1GPDbT=4?H<9*wBmCnG zUIW}M?JaRk2*8~7GB`HVLU2%UfH*qj&@C(xu_zrBwTs)Dn^oHUu?luXG{15$U@x2Z z649bfyV_<%xKuE+Vb=L4LK;&Z4d;P8!x%TujR`P?Yp-sAJNT1eP<^PUa6l1O%c+n& zKnX7(fN5up;Gz;^AghX^s>mUbe>-@q@3r$+-^k{BeA0iQ@X4d zY?O%f&)1EdYlQ##Updc*$VmLV);>Y^eH(&Ls;qrR-6vZ_gd0d9ktBAWObBrWk=HMv zp%V792U=);y^Gq3+*BlHMIBYGt?tie`&ZB+G(nA|fv!^QM-yh(;MA$wf^5gRdaSO4 z{DQWljF;8VgPUmpk|1f-_BYMP1^Hw1^^)PS`9{g~*nG2Od2GH_vZ?v=8qCjGoRh5}iV`<2it_8KzQIPGBaMTY1JiXVc;u1nYH7lM$#MB5hW~X8CWa?S<@35= zrP_wXMa1e&wJgagxe9XtmP*b!^rhBAdv1zLTs5brGdsl@EhjlI)jTpRR#P3>raM+4 zdDPxE&Bw+4WAm$}8a1C*99ELrlkz$A8`_Rw)ISjjj*c_g*|dKLo`YU`?NnYn4x0Qy zDWAVioH<{C(F{7grji5`aFpX%1(r|cmHHGlt&?If)7+c@Z!h=j}U|<&uy>cV!Fg1e3Uu2cMFM3(*<&YM+-j_{E z)GB`i(GHtJV#yq!C?0k|Spylw>E4g&Az2-i0}?S_raV2wg-KkG$}du#V-(XmM7BIy{pzkDeIxMwSQ3qUT=GPK|{p5>8-I9 zeRalKcI*7&`8Qr%(7?`QG~Y5T8s0GdrP03ViPk3@d(*~UN~AW~(498!P$CVdz6SfW=I7O~aD@esyi^^qtnYChmxJtX6MJ!Ll~6 z+?=l76V+#2H8E-FWc*Bmzk4pRGx6&CyAw~uUrD)o7y1@neSHwxfVeAH!I^BgsuruF zJ#W-0!*oHOG1jZ_wY1Tz4qrri&Pc`sf{hVgw!^|iBVrGv3=*M*59q|>nHPd(5e)?X0xwcZr~*Ii z1rWEDal(F)uLTQK>713OI9Nx#^SYuq54#fgjz+RZbnkG#t^H*l$aCjGDd%;s>2CHa z@2h;l9$`DFEIM)M&!H!93{#D=3{ajza8?c?9Fi|n!X$z@_wePw%nZ!h-cfn_vOnl0 zvD!PQ+2;k;T|{veY3sqqS8#* z7n%RXFC#A43@20I#bF2~0YHqha|X*o=sVwvO0k_w6Y=slr!r7;_a|zTWxJDx-5GP) zt^JGpV`40vHn-du$mlC#Eh&9{#$B~&$`~nPM5LM`p4hIGu_5EBS+rz~?wBiOtb=&J zX!(iJnbQcy=lHdn_Jk{O?OxT#$I~^Z7mt4dLBC?n;EJA&?Tw#bF?46l?r0?bQqsIL zsonXr2S(T#ZoRhn8njfZZK+Py^(^mNZok)b@7%p-lQjc>d~wxsDrGtK3uvw=@i0Vo zuTQkLLtD5{wmAE$g-`ZX^tpvUbc=w;3daS73IhI7q!MCmdgu!`(j>l*X(mW`2TIYE z00eejM7yN9X@nq6nx_V0vhZvFSQ2pm%~-!A(yjCyjwbG$VV)&PVBP>o&mbe%vyNCZ zM22zXm?9?0pdcd3(v1sHk zAqDwX)IK-luol#uLNDeLbF3Nr0VzN&L$juteZ_u>67#2&Y-~+}m_b>7ulyVKN~`Qu z@NY`i{QsYwn$U8=I~#UFnRRiWERs;%3(3A=%~@G>J=Ha5=iN%H5-~)KbZsVIELj_C z#PW6LvGnZyzdp+mOa4?_3bWyFUX18ujl_XfVuoaWVydx*6ypxZNyZa~Ld20;TX(cd zFMR%Ycs?i2QM4Y*VMNa|yLHwYngzL^@P%RB35Db%$oZUvJ2^xUq4MWMxnR^`f*d7e zbrSQW%j$eHGZ0bbQSrCBoJQAvT(rVpEGvvp zg|oab%a3L?p;xm)a1?Uj7^KCia1WD?^D6lU&HNvsHJO3~#8TeEB*9WFoTujPOG}sH zu5?A)pPRNv9sj)X^_@x6_8a{OGOnr{Co+0xQs0oVc|iF4?(9!ArfRmOY}*$ESaM>H z#Zx4SsX)0q>Whv>w|vQ&jn0L>OqnBk_Vu}pw!8mXy6E{^D|X z+TNElb5{47y(-om=kIJu+nZMH9VvT9rV(BgcWaj&pEdR@9l2-DxSH2R!BPH&AX;r0 zx3yx`Qk$|sxLdI_WGvRGV{vHl(3c)`{Ggh%+M`1B(2_2uc>@Dnvy^R!+8l2+N5^7~ zOXIhQ%cpW%tG%EB5A$ z-Jw{lzwn@A%-8`-dyHQiiuK(t!_}~}78Bcvi-YEb@BOy#T~0Ujq+q%p$kcja$t!n8 zUwyMp8J!eAedl7@wPn@Sm2!0@zIE?Z+I9T@;t->JeymYg*Ey#v`s(erFI=3fabZ_d zyFLDDqA@-W;OAdX@SM3bM4H@N`omuByIKSrEPaHhgi`B2%1g*!D+mZBf`AYam>?kJ z1p(Y6mJmA#1;qAL5(x)1Ac)F%O3M{Wh?fU|PbE5hqQA;$X4Fv!b0iZ|G&i=r`-7AUcS7(czIc^P&T(;*UH$Z{ zrxXyiWn@@>gP@xTI&=!5C1qKrZsl7PL@6LTi~Lc7i-eVEs{AH`td1PW!qbfUD}++9 zVEz*-LBVyRlm7z%bmofcucne~&WdOV68V+ePsJNk&Sp4locXomYbNW$*c6r$e)?|3J1-`7{?^Enae3RlZ{rHD!nQD! zvvF1@bV{RR&Ei(5R@zdxYH3MXS~7L5@zFakB~E`<*M&;QK5jrItL+OxYc#>$Z!BLm zRHh7-?>b|{xafL5e&(Hq6+=hH=7=^%n-(S(gaK|@n?OOah=Kj}z(54q@=_-s z#cz0nn`r?n?SPp59oI&<;^F7D&>yjU%2PZQMO{$UY&ScvALQ$)!U_{gne!;TRkWn3 zMtM1o78C(q@d4RH@KxKHhnN@m<^_%oM712Yj(n-dzZOKs5lA+jAQKKI(c!Pwh!v(7@>=Fj}G??KXQShKp z=L|}tlPrwV=x+W_seKm|$S{YwsU@MTVa4W+5dAb^8Y+7tMwMpK9^Nd+qOIR#rw*1=jhPj&g>m%P-I zO>^FCoq~V+)hA5WMERRN!T%!Jn9b)u1CMN9yPNpnjFs+&a#5i1;d*sQXrqkUP*)4M zR;{K<_OENbfK>-TIn4N3B08*d6IRF?u|9U4k+0wl_)>HA5j#R@id01-onx zH>x9r6|BI)NYPaLE}2yU*DwP|>8whnhT@4vsqzh_v|n>Fx6sbRi%AzTMua)gp|4vX zm?Iu{jyvGbgfpo;FaeB6b50onRtuOp)idtjT>lD#de zx%mUt#)f?Ci}Dmpj%!d>pt3h-)RG;plL~7;jM6d<5N@>t{?HgSAzv^|enO!+p?lyP zS$&?(%xSv6p|F3F2IkrZug$=@94RShxp;5)PQX`a&er8UG64sD zGU5foUGi^I2S#h0F-zZ(UNBk$NblsNiZvpPfq*7ijvnyB}pJD z8VVIFKZrfNEm=jl75Qi6ymOJfL}{iYLCJqju`m*GR4!?4ipRijQ^F1^rh$g2@du$6 zhIeN9t65zL8Yk35ku6YGH#Wi?S2b6!X8EbCFgAnY*RFk~qPUeBrr;(CK;HzWvn$;8 ztv60)Y-PCUrvO$$(YjXm#1FJT82-5F;}<{aUhR7+)%Q}m@0Il4kyPC`lVjtly78o; z8g_U?b?nS%`UYGVlsS@)=9H}^emZ5_vTEx|*?Q8pUC<@XaAjTGzt+C}!*k31_r#Bm zuI@UL+I1wo>sY$|_`=E9lb=~y@3-$GC}nAdsWaNU_*BO3j1DXr6?HOgZ(BTc-(C*q zAChn07>~aC#-+8Y=J=tw@9w~d%_~)1QAc#=o37Q=ENLO->dv^TW4@(hOG7z53Sy-(D^kVL*iY^C8COSQc-i&-`PJ>uq_#hk z-rkpT^{u&T;d%ts(!eLwx(L16ws3v%gd%LFEp2qiQXAK# z%uVrc|Da_J+V^O(u_smE3$gPl(-)kk-GuG#*p}S3Kh=KV-gK({Y-9OoPJk_!%dFI@LEqXm=Xv~`DJvgO-CkwV(v}O$!?5=42 z#e+T#=Wckpe;5$6I zKQpqgL2>pJ1$Rc)EfBk4f2GzWE&Dc0bDq^H5PDG|^mC>QetB9Uxbk;VoDqF|aB6y< z9C;L4_B%-L5ZG+wj{s*4p&3Q9P;OUMXOeAHpMw8Hl!z|Sh!W{VQ^wgC-r&DT_c=i{-M3UT`jHS)mTg}M(5Z0v zsbJ2G+=uMm_&e@u?zcRX{Ck$V5JOP6+E_b8W9WT zZjKM6+#L%hx|pm;YTdLnbVN&5g%-p~3qtuNEAs22nR~-lC%nto2^$PDWGrAOZWJM{ z1;j&MCO2XBVMXz*72RcUirAS{g~ZKVq>3jK!j>L=u&3z2QS2ci+|VDzxl~2r@4(Uf zaV|ESc?qg@>85Bi#~QfCU`^>!RK%|=R}ioAw?@=nnNqVflnj!wF#CcESS*3ue1Bx- zfe0J}29r;uqgY0T;8v3_3(?n&GMlw$R?FaKOrJN1LEywqmtL}v!3uSu)W9re!Tp#4 zew779taxiAS(&*D%9LbfRKUheUHr}GpyU_aZRlo+a@8J5#4S3wBbO-%o4K>7yTIrb z?$>aeP;~DvtVrHS)u_(D_%5n-Ja_ZAiXNSLd%ylF3AN+_#-4(p`Y%-ah1}Yb+#%qs zI@-l-8e`G{V%!cs%b9GFB{|>+3P~#oW zlX4t`gg8oq^H2a^|7)kN&s=9VEWiJnf6TgLe1<8L*v;Hpy79%6VtHexHishW(rPd{RAv$>3BB?a3fPSYyDT^1>nJ%Kx*7;y zRK#B<`Tjl?BF7xXMn|Mh@jQ$I>M%d*2CE;3w+w{ytPsA2|8>9|U9+0WKvpwy6_V|= zEQREG)Xef%LT0>6t~?Yw-g)YPg8u~+39TRiNi=bWD#$PTCU^_Rs*+_*Nkh|`t$fAV z96yt6e=^m&FKv5j)%JAC_VmZ*wC(tfXV>%<(W@)C04Y|;n9G@qYFk{F*0ur6m>jF7 z+LWm_ZK_{2ZAqE7q)i<+`ZFf$t&YWx=+U&PAX?ku%^Ud+R}4lFk^Fm$+<-Df`;654=f&tRs5ORn`vtKz4p89iCy38`g7O8 zSl@Erz2@IP^5&VO>)^s5f;9+oyWg0L9eVw>cq=?x+7siSHSNmSDP1dD=fxKT`25vz`*~cmz+qRtZ}~GzL#_j( z%54P$QN4A4{^b_V{q)Zsm^fEGDoPa_@AxSw4yb4W46+Z*4&K`AvL+{ zzA$oC)ey?8bq_;lvBQ7lG7Xw_f7GC*@PKX5uK8n2^PBYayd7enk}x$8pUwJ%q|(Y{Y+&D%$joPq zAyylueUAc$Jzj!{I4YjI2Kqk;@W>4*YUD0t;N!&+Ul1S8uzzV0f+D$(iZdk@qM!1$ z33Cc({<&Fk^m-Uy$y}hS+R^FhN#<|DZU~wAo2h_I`eK3wL#6jQ#kYnC-b2IwscC6; z(tl9?4~PQ4xX^o873>qwuW@C6!PWl-=l)A>&nma)uesj8bJGt~y?qaa804de_3G9PeMPA@iY>*tagCd~Sf}L|aB{z~672__Y&Dtuf*D z)|fx7ZOLeLIiontYm%HjisaZi9NOkY82YMn`SAO%CAS_(wH*9d`|{4Ji!4*_yOU^@Zr2AHj^KJutcZRq z*FdmWfg1^K;zV~ekZUHmg~4C60;Z*C!R<$X^x9I_I_JXHb~(E+Ra;cZ34rcvozdZ( z2#BVNyVabYU`*8$6LLm^F;#qjlrs~Isp2vvXC)X@#T99;j9^R^7sNRS!I)}g%$ai% zjH%YfhI4L$G1caHf6hZNrrHn}a#aMgsrKh;2*y;)qrJI0f-zNUr-5Kh)rE035{#+Z z7DBmZf-zO3f6)p!$yLV&a7!~5ue@_|opWNU+spWRe8ry=@TP;dJL-gQR&QL0?Oh5c z9W5zyYdoCjUv?%A-+e7<-klQntcxg{YuUrQSVg>*6RM34$C{%rEZM+LQewlph@70v zH}DOt9NtuJ7p}2~qlU$Uv0ZWD&XY-VOG<2A7m_o{1}SMtfsIbnjv?XQmW< z1cf{5#p^jM#cZ6;jQO~L;%DQ#6Ha_RReASmc#Wkzy-9O#O5C+xM&?+FLG>;9(}4Ger9ix7DJW)8 Prn|{$d0<37qvHP?Q@19p literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/__pycache__/_doc_common.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/__pycache__/_doc_common.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..83072fe5ccbccc24232dfca32e5572128b27c28d GIT binary patch literal 60385 zcmd443s_rMo+qd$2qcg|yr1G_BV&Y(!4Lcj25jR8I0nZKsVXdUFScxioGTF<0#&X| zbr)1+*N~*!c*^~Sba^(olb*so*^O&DGnINwReGoQ`=p38DlNO??(yt5_4PbRoUTr# zXQ%h~KldpiJ4sd7^xn_D9NqIi=YP)sfBvuYZ?m#8b$I^I>%Tnz>i@3O{d@W$KP(16 z9vTcf-3=Y5s{#mVqt)tpi)xZ|6v} zf7`$|f6G9NzjdJ1zkOi4f5*TM|IUG({#^sR{A~km{@nw+{d)%X`1cO%_3s;y<3r3Fm zj}06{xR5{274bb>F>mL4_-sCnD;YKvW3r@o8dv%a(?G95cSy&TeM85U^E=)!iW56< zf_<&P*UC3Av-Au+$-cSpt%|qtX?&Vkj*{o(xZYj;3rgDK*2lBG=Yk=@I~4Nsp$h>H zUo4zA#D{!--ffK=+egRarcU2bD4ubMALRvaC?Lcw-64d|jqp;4zL}2sf}wc&aqs2J zzR~k>OYh~7FEHvIiJSY!E+eJ+)F^((O+(&b=oflaj+!#NMu&uPme6g8XP)q$=X=jx z#PHTzzFXhm3}%7jEDF>jLPVF>5H|K z4~BfBtdVht+9oO5iCGMAJcm5I*DrlEv-Zc02YsQq_25Xr8a+d z_M@Nl3yHJO_%CZFFRtg}rl4yZc@+bFLmm4 zf;B`-fjykz4JrJBo-u-HoUR0+khJD?x{Fj=(!-f2b@C3trP1!ur*o(G z{KA6JL`C=LbKVgj=b{F>e50AIX-}zA=L37jb00IHbMBu!D zbod2+O_so zYtHq(GkfRr=AVsPs}`yv*4nVC_94p94be+}%u?Xtf5Bwj(D6D#jspfxKVakvITJQw z6KCeloB)9xA?@dkq~U>iU*HhOF)uFwVE zbffY)f|mlX`(>yspba;5i@m6Iya!*NM)9F4|c&3G^V&7R$rr6+-5myMiB{k$S*1L}nx&p(j z$?F??!TTJ~a%~D-32f42+3eyy=RGd(7?!Qz@{V#+a8U4G@wocYf9#))_#x*RcU|#~ zjIgr2BUilRG-9+RVhqlnP2RoFp55&7doR&Y`a&*@mUqMjl!&yT6nNK_3)se~#jH5F z>n;r0IiB)xz93NlIM0bKNod88chnWcoN9h?-Fa~}ZrT-5-2;9)A*yJMZ z%1I9}gp^mW8`s^@_h1{ZN1C{05NN;`8XUX>3MI&o3k#k)^ zil76pYr0iS(Tb%iVyRlF{lKzO0E*MajhFcG)X4A!L<1S>E^51kZ}b2~DhO@Lpd!CX zLr6h?GQtxKlZHMGf<&4$u@s$B22gE={B2S}wS5=};V{0t&2i&-J`~UN1%0EzkQbDL z(2VcG2E5`%%sWuwQTlLSHZ>^RN5PL8 z)sO-fsfY*}JcJ(1Nji#2dOlz7tNLK0{t>hK`AWE`%#_*y8JqUu=nB%tF!3r|6SOZA zmD?B?#d?wUIeFp8`?I{+(Yp18Xb0BhrJV`OHRaai!bWuVY!Ar8vu9~{p!Lg2&@NbN zLhv#_|y-v|9dGIpW2oYLJz5bNwS>z5D;)Ov> zOBlqcy((;}`t6U!YZ?Ij{J<-s;NJ*(B`mJNH;({c3^ze58}4{o`>FoJy(ia=c$!$; zL`f=m72|$SGu93o>#xpy_13vpeK&nkdwtka|Jxty{VCy2Y~2?Iyk}@kk^wJMEQ~>3 z#iNIU;$PJahX(XAZe~R7)nQBZZ+|$x`)h$-aEu+Be|6X9Do0_nkU$q^qNU z-LR)i1x}Qv8gnV~wr0RJ@OSa%#i-pKwzz-$1O7xx_>-FVg#qwvDgd-fr7;Mse9UN2 zf`5(@9`ZxQqXzuOg{=Uw9P_r(8u+X^&n-nglxEA6{8g_XoPRpr5B2uBo*eTEp$U2Ahzv+# zjfAjD6(GlI{Typz9ZfEG^oybv%ZZb{ou@jw)>AeXxyaNZc)U1n3H!nr) zo5Ge&zjff4Xite<eZTT8C(Da&c^BxKiO4ZHh3;NP%FiH?2{7ZP-$~eo%<( zN=NC3L~?4`7&wR0_oPSV09;hg`D&6kByNKImmNOZzQ`ewEpyuUNm%4@n*_p^8ge*` z?WNtlJ%gR?{ax#ZD@)GLgiRAwsm3cI$p-G!uWOEX0&hB{!Ol%jW?t^_&f<36SXs&gc>wOhm(2 z$(?Oa<2io3v-83Qzdsm!reUD*%NH(e^!stK#3yI2M(5{&>P&M?4v3!Y#%IF-0tRX_i9|(qUY##zI95X8xrsaXG zUpkiKy`8C7O^&uL;>t-mAM27mp!q0c^YL-EX7#*Xdbc!My*Fy#7q;yC?XR5=lnF?= zcC^h-v3``ysW{Ub{QZx*j-JCHuUkj?+McOv$(?E~rA+#tY5t`1NUq9_c?`Pvhu-%7 zP#OI%vUb4Mz7i0)pk{VHlbTPUT;u{=UPu6B_CIZ2DY%IVw7lhL*VCtaPj>dLn+%Iw zW@@rUj{QV4_ ziC$l!mzQ2c^g2&3AH7ECHA*iNy##uN=yio&Hh!ebFgGZ<8*8K@BKDNnW(dKd#~ttvpAg4hKr5QYI0Z-$1Nku*OzruM*R5G{mn zX7S@=Av zZ`j0XRUYz@(#AWvEItou@`lqmt@1*FRF8$vVtEamMtwo4t&q2}@{6Q2S~Z4ZDXv6{ z)2cC)N^xaUoK}sY9Ai|0Hdpd4ilzS;DJL7LbUqjThVsHd6_?NFqHY&@1*L?6YUy_k zpG9d{xhAdV97mhTMmS@=yXCFQB(H^_CeZ{6OS;I_8ipm!I$+w`DyO90>=V7p5;ajAd z+wir6wOt-*1Gih#nocRs&e9vWJ({>Ksn2rUUQOIVDejPzZ=WXaumbM`+_ zOZ6mbuH;XOwMcax*QDxWsrva-&_*L3PYvP{7 z*E1NYXSkCXLzWit)V>`4q>@gn`)uO+Fmg}xHnu07=K9(E49N9ROSw}izKNyEdt@5- z)Hlq^xI8m%a({`b$Kr_6!BlM~{OklE{%{SCjWT`SpvYH%g4JmOii)Dnj-qbm5=Hnj z`OoyZgg^jN0j4D83%Z~*5*R&CYCMvPwR|)_$n+_pWZVyNyT8I2rX7R>e0kNA7A&7v^W<; zU1#QHZg}tln$HUpg$Y%v5hX-nzep|a#4DZ)rEaDQjBZQXx(RwhkE#BSK~%=Mjx>@2 zs!0Dng%3&ftLhf8Do}cC(MdgyTjXZMjhNCQ8f5MBh(X8k<0z5|FVpK4yn>Vvhc{6d z$S&)o%hOPnFeXW{b<{B85na>Ww^)C(i7-Q#YdA2Gn^+%xb0-Xc0(4Q^Sw}A-pk=_y zt7b|MR;;2tghbMFO+T)m)L)dzg)XahY^5MpXPUOPT$j^EJH=ARQeO-ynJ zeMxBTC`>2nhNLbJ)jwHFpK0zvkicJswSc@J=^)(`0Q-uG>PQbzlm((hDE9?F=1_9D~349-;Z#Jb5S>;+M^&vXcvqvr^ z_)I8E{x+$X!5g{k>Q|`tOG`(nz_Q4ZW7NM`Lb>WMIfU}0eByGMq(vx4YW{}uw)~6}9Wu*`WY}!|kkZ^bBMKLoz0lAKKyeGU9Hi2$u0BtXK-;j}DtsG%B%Qa8 z&Uo%q-Cd`$k%WLHl|SD!%Jv(QVg7QEu=7ra3)EO3P1r%zOhK#(fIdR!k! zfb`twm~F=(w6A63j)}?y&|06MouHpeXGkt9XT??)v6ZdZToIe=cJ4~m_DI$Cd#0#u z@3cN^T5jH_Q>Y;Xw`v; zqa$W_Oj{V($L+%-7zLPDaf6r15+e21{62c|sC6LZrrvHjJtL7AN!3SNvI&JGJ=aR{ zJ%zR>zG@9aq+BwDGY!vFr5TRsUeKO zW{G^miXhE+Xnq5ONz^0Y6h<$iRyQ?9e%Q7Ti#tddHSPa2t%(_N;crJ^Y&7Ifi`!tM zq?9kNu78GU07Fs&7-5Ef8b|oibu?fWkv-_T2vHLy3F{;w?j$Xdb0`Q)q(WzNtXRw5 zx0YcctT<~T&YFe85ohD#g@|)U*tX-o-MM0~i9k=t-T>ggku{e!&%HW&b9C9!$Z~9q zI5&o!+rqYOc$3C*Xr-_rQrHl6ZVuZvi{NghxumwizAJ&?Q>YN4ryd3B3|uK?(vupv zWk6%#nv{cnUQ0g$&X!E&yzqz(c9Jb4QakqU*8(dxPmx}Mtq1x#pc7{pNsma&IV4k%`Y6_H~1gV`$ z5pq-NS-qf7pu6OPM$-f@1l(#(5^_jf3hge%CIx-&WqN^lfBZ6RECqsU;g9G=04-fo@JXG3iL74 zAZ-W)^e`9%0uYFD7j0%FNS4t6=zS79i<)y(U?^~zHDj}@ajROe@H$2*ZldA zr(@G^oHA*0Du6XYlMIdFFG^u1ME7LrcHfjEP&SV;wehH&1q)qAw zWQKs&L2{TUVSg@#)28$<9yIAx0OTxk8(+}7GkSzY)GRpgnlLw!o$aS)h7*4QlhnUQ zm|%&SrA}0z8s)FT<|4#%;IF`VfKFM%ILI^jq8azNEdr6?aU=E`ktogJ0Y_xQ&I`3v z5vE8dQlvEqxif{k^x;qN0=RgQk-G}xB_9{pkH+;rfwrS~HnbhaV7%}gKS=5|HDAtHwv3$v~kZ!0Hp-?c@j(g9oonK8U=j96oPUK zUKyHiA&ZWM!;9W%>6U2D*69P-tY#0*Of96pZ{HYmRxDJ%@2riLRxaeu@0{(uUsyVS za-r(xQ?rv{M@`I8I)4r%=)y^sws3yiOS@yG6$^&>9kV@R((0S1XQ#rB+SRhU+uWPG z@0sqM{(e?;!@+3TAxNFF3g;}d#@W8rf|BLZhQ+?`edW$qqK$i_1^Z@=KQF9X7+P$O z7JBAPv-;VsF=yWF-dJJL{MMJoVwE)uee>h*7uDY{Et~hwx4d*TmR~SuSj$0?IE^~X z!{zPK+yi0T0k+k$$&H&BRuHF8oTP7KEQGh|MPMpQR<}}!juP%P@nlT%BTnJJq!3Mj zKw6qX2(ompvo6;YPl&vkoOKg1QStbRdY&faYbfSZOo&5gcP@i2>R+jAjnuU+U5M1} zk7hqHZCo=IW_0LRbF0^kEKuJd1|DSPzOwUHcf`5jO=H;E5Xsv7w`NN4VY4p3W?|c+ zKAN{_CIegd5S=$_mt9+y?OVf^T}#`emR(`{R+{O)>G80oNW@2IjPlTS#_&-!0*}%F zlNU16gd0zDhCG_6 zeP@-rU@>3FhMkJ!207KEKyV%Dn!7$t(m8K^f>#Ob&Z{2%2bapnPGNiW0tpGlzU3$ zGpH0n>UMl~4RX0aS%!0JbE8$xy`}8@= zQrd3<>Pppqv!?x+&cZ5P>6m9$%u2 z0%fj@%FO{nS2#dIpUQ_)>H%4Cu~4o>{X1!r%bYR;0UJ`bB*iSrxx|+IgZJQ-6g>dR zl(Gkkh3=Gb63#GEt+tfCN-@{kUZrTk|4+xzZ6M(gtjHw+g4@Q3mbjs#J#Ox4KMrQv zw=v@)GmTL)MC~vhTHM^()z{z0SZTr^($}BjC85c9rn-5?%@hvCGuR)J!oU zLtjMf$*3Co{ya845$bhl2vdgkVth;74i{m#EJ8X7Y{PSfQVFBiKPTUHu&M;dm&bKnPu zzkfK=&=t))INcR1Dqktu5-Hj;-MwnhA)DCw)`;D8dtk}@*15MY+`VwuzTE!ga^1-X zMPZ( zPVNtizF%~Af3&J&_Q=`>oueddDgL-dSKavC^4TM?<~_4rw>I5A`TCjH&O}Q*k-Vlg zmz1Vbms<>nBU8&cjjK=%F4{y@xmL{HqTGTY%9c$e;-6;*?z?%lL z{f(Ayjo6wWnPJnm>8@8ci6b7(-4L;DjBRR3{&e47jBYbb8aF{+!V6CVrV@l@3Q~QC zA=OF4wM8EeoLIa_nfxRmm=ue4(ufVZT65m9$R$i_QB#VXi5v9jux9gB(5hS(PF_?` zzos6A!Jkl1iku1cd5Zy&Zyr3C3bE<7yMoe(9AdwGx-HWv*oNs|9Re~bLXtFl{RMTd49<-!b zik#XuPnkG9PNQid`p6y?6<$L9!poW(O4Kxy?A-jg9?AWgO2;|ZFo9#pR9dK9DIqR;^2(BZWFnPpE|QkH2^**$WZf)$>jESTN2NsGv7n6ixOUmV9ARmp8p|4yb) zTI8Hl8Iu`bH&13v8Ya^jdVlm7>0f-A<_jVzIu<8A@(cqy&PY6k%qi=n^>Jf2Wz&q5 zEk&=2(JLEzl{aY!xFp4`g#-JrvK(bkjEI8J%JJ+*oY5z>* zse+jWcOq?{$$9;p$24mE7d@(JTFj2&j1Tjvp{diID^eOi!U-}tMdQ@Y&2b7Q`dgwtT$3{4w<(48fo z>BE$nFikuiMk?g6Px!a==}+nPujqA*BFz}QF+OghnE}fN+S$hE*bB@R;uy%2$^MG` z8EW7}Z35Zyi1X?HL8QxW>>fB;R_koJ)B9rih0_OP1tlv58zKc8rVoKQapW?pV@JeZ zy;@j$>&RmITZXqScP)|nUD3j}In!#6llgf$9m%O(6^W25ZwYT-y?Zs%^hC6%eb%fc zJyuIAZ)Yxcy;c2o{oVRIz0uM=vz_;?_US#$C(Hv-PCI6H%yKjPAE2(Ii+OLJ``-CG z=kJt93wL~^(`Oyh&l;I%a&yG7S>e{)d+r0r!8IdAuN~Cu90k)^AGhmu*^cXHX3os# zMY76Q^NJXWB{u!ezGz+>2n@(F+he&-@Sy5mzW9;{JfK_K7R(FY*DNcpZ4uYDsH-(v zu$^kmnSF9DZC1ZpShY}dJGflf5X&oDGZ=G9Kw*Iyb$F$$DN@!HE!#TV1sQ2hu9Vza zKF=@LwJtli$H2B4o12Qc>K3@ytT)Z~i(L4$Qs{{kdKQCAT^Pz)6XZ-`XHBen!|cKN zZF5K0YIM##v2ibZ*4kLV*79}bRj(eodE`6CpwpeTQRH653W{%x&W%P3Hq07VQR&cf z&9-G{3soANdp=eHr$sk?D;3R=isooV%S~fa?H$p=ovd~U#iZI_I=bdW@#KjGqxs3l zjk=<0OaMBZSG=}KY)T`3ei|ec{8N*&J6rc>*%{rX#y>03;~h^YF(R~%;%4|98oD&3 zd5AC@35Gh90+(QgX1f)+{7RN8qR zc*zPrzNp}9IR$8|H05(d`cY^c%}8|6r0E(HH*+$Jm;t|CTLLh6IrR};e@=C$qC6L0~5TfQX1NmCG_X&9&LoF4D%Q18i6hs zNl95B(PXxFOD}2Fw7J?54LQ72c>P!q7CEGFDZ0I*I2fD#!gAGxeiyYKaGrc3kOoa<7@-_<{GS*$~NQ00dPg99_zg?q8 zBN@B$UT|MwmqdavuQbC%cZiy16r0cyhWW&_GR9}FSChE1>>I?fV!J%91LFy$aQv`$ zY=n8mfF7IZ!v&)Xh5ZBBE5;V zXT72e5fu+N;Prd@qdGlfXnz^I52|!77&VOw0E5B z9X!~3^0-Jv(Y7ftQi_pHL@~j#OeBj~yW&Rg=s09kM=7B~4hjD^{rq>7+QE_ys+9{d z`kW^ADy|1lM-0*)OJWf55t%v67nvBHLTgrxD5OyUk<6q~ExNLbmD0vYX=Ah$qVu8{ zIsB`PSSpuYdske?Bd+67SMRdrM9iAAo=%G86-;+M0E1?7W^(>Y#J+(@rNg%eB4t~a zHojB+gU#RH9BDojEj&DDf>a7RiW0#Sv*(5FuCT?0cg&hMZ;DvUR`ZK*H7tY{yI=cS zG=B%kvHVh)UuE^_XZ5k7;#X}qZQscTzl9XEsv^+cs#`2rDh#(Bd9UjO$H_G_r6fTC z5kcv??3}1$cX(6VvSash*6#bng({EO%ICR-gNuj4tzGYqE!&Q(YLW3Yta5B>3Cb%9 zx~8Fmi*4Yc)cIzr}}%4GAmyk;Qcr9RCh7 z!0V#bF?(=k|Eja_mT~^6g|3@ljyfB{wuV?%!Tg3umg_!&jVI#pNEGq*C3mD@Pc(1u zL!%)l7qqLh;KOudPQk|(owM+j;QT?NH35t#qh(v7xm!QXFy%C_8Pl?|AuP-*qB>q3 zxH+(BT093{T-4bdwl$0L&i{hu2!D;&kTS9OL19Muy#ruKr2H6Fq5lS)4X2&(88C5YgZPF;zrUtV~Bj^v4>?a-+pfQzNAZL_8O|Mf0Kxz%3VA2?e0e=ZVFDkU1 z+Nj5A8xVbVk-#JAQK`p^3iYTa;Y>2{a%QGM(J+~=3Q{zA3)DPvNbV1{mRe7L)x1!k zk(L(g)o<3ebk??KIm=`^HV41TrwS=_<77H#p%!q=uJWS7W0G47@skvk+a>?~thRHR zatcvTn>!cF;GsvfiXt5j>2Lz=Xia_#b8J%pg6qrc%CvT;J|j(lc0F1bzWU(PDS zf@a>U)p$8{kx*{ZGl9A0te1A^NR(^E8ONf|5x8j*Bs^}+J{Ob_iIepB6tN;sC&Qq5 zz_EMmI?2$$OvV?58PrjPIx;6S!B5nKS4n4~6f-@k%rEG!66o#_NU-PgkH(7^a5nm^ zb>otX)%^L~^H{IRBn8!Z6zbQ(y$)*l(mEGcLgKHB4eQI}lyTTgdu-$S6!O{a4I&Hi zkdI}zZN0nZ$CJ4F$C0?gU!h##-_wf_M*@i}JiwQU&55W`Lr1E*Mhba5NC=VkLy5f2 z-o4O29hz@lw!0$PyMHD82Sfq${tf;JAK~?>K2!K5{WUgqT$spc8te;!vJVb^YHB(V z8l5mUwV#+UH1$lFn&2f*ygr~1!-Lj;9?QKH!7U(#&q?02dN!V)3jV+{}#~`%2f-qQML^Z>~#A6hRYQn~hvSzGBX4*yOdeqan{!&~Y z3|f&wC8S*Un>PO3n#*LNj0!!!Fc$XgTej_w*_@&p>$0tKwV-sq>*bN@wCUiCHI|(>+c$Gb zEMg^lMYXF+ zJ{R57^B0cZSeE1Z>6z27oV;;r?$rE&XjbLI_Gp%Safmpb5bE-G`Fl@BJ^RrO_Yd7a zYx-eR#PekM)KgKi<^L)>}#=IMoV(R}wuI&;=h zIyU6x-#9jR?ByPCFpJCQy$j}>7ZyS{M^`GgMk=;OE4D?8TX4k4anH6xy=@`wrLV<` zDqhXHnYG~kpr{^4iX1l>!8<$j?{1IoI5L~2>EHW~mNhHYvX-sO$-9w0mkyuJ=9^|* zM&YQsec<)(*Sc3~cSrEgvHRY$?>nA|<(142!&}Cs#fC`5_DJ6L`}hE6=Ylnow|ViY zrH(t#+$)VVcC9oXjWiy8?_jjCFPztZ-(p*_6h$mW^Z5&Di|I@GA6RyX%1_!u1?iA7 z>Jk?;(Fq$gA83&p^~jK#hE$E4zJtTfAEa=@PCFjdaTFa@)FVA=UeJtmP-0Ii%8(s{ z_Ciki*i?jsfWd%88Ml*I{7KIn(r+feOhHYOS`2u2CUv)dv7WdJ*s~2i6ZRx_4s=Or zpJe-(Kze{AG|~xC3N6!%ZC?KsAz2wQ#YvqBEt1tK1S<+kveDJ-QD3KR|M2$FjI@I5$D#W+9>QYa(CXdhaHFiy#8aOAuAiJEz23RWL>w-*k=2eEhVIB zA;}AHtiE;N)k8NAk&_og)?RS!HB51`=&;Y(7mN!}EuLQDKXB~%5C`SGYi6CTRD>f5 zx1m8gopRtkgGPRC?lcs(LJBlKjuTCX&?%(GJpWXj=MbxwUMbaq)K~>}luyvM28`=p z+(3L=f}W`~$Y#x&5>uQ~7_GjUG`%?^9g}aFa5gcB`5FB_fg^Pa*qcnl3Q2?XRZ2_s z;Y<1-C~8@H-RPGRYR^_%Du-C@O=zW5il(g&IgR?4^~v(s_E^@nq2#gYrFxTdz4#uj z6Ub1NQy65Z#Uw8fM@G}mJhgptNNnfRx)-04rL9RN8A%%Z;-_+~+tL$H6EEG0o9OP4 zcv{DW09^3KGx~7VkQY2v9$x1D8_FkU!&Tw$5CR2)$WIMzF5y%B1fpjoMW%*FR)X(> z1#2&EXm1xltm%Zm$ESFj$f}4N`j5vgNBMD4P^s^CXNbfCkh2c9goxo{J zJNfFh78DHY}CjI~T5QU(P%5$%n1z;wK+()|J&l=%y{YI`r3p#cher#+;_{TddJ4?(z zDKsGblVUxEONNrbm?mvnqHFYLeFsKCtZ|vonEnlY-SJr^Sx?Wl48~Y&X&_5<#2v zfGLQ!)5E3FPJ|O;>7*WVtJJB}<(?e(L z7YA{gG=aUC;e8!V%#>FWnCUhW z7eQ$CzP#3DMugf|&tP`kY=c%mAEcuzZLVP{~vE zE}&^0M63pgSoQ0fp&}n#21_b|#Hc;O#|RBcppBqTN5lv_lanTiM(hNJ9EqJ$-Ay!O z;Mnzia_LwcMVx$cF9&)wkZ=lijZ_)aqoJENGjWI%LP0W)L)2d(DsH%Ri49DOlYDo= zNuG(RAi!m}3#}7av9m3#Dgak0j`?9i9xhZT9rMeNE*w}o@b>Y$$KS1bcj$*3KWI5} z%Nr>_`l}$(P5-30R{sa-wfbMslEdkr@#u}gF+ak}95NpKSrKCs{mw?q>fP zwQ)bS5zKkJV?J%>YdB-gS_n53fJFTe8+pltg5p~>(ek5<8szkNa$Lav7BhLIBJIa&H56#8Zra;Z7G-kkU|vKr=27u`aC8tA}26L_ngW6s{sr zC1)w|Oj?qn6fAB4PlF-;pCe6>wqjamctlBBUaG!MRDI?wexG{2gwjCayDS;Gx3;b6 z@aIj_n|*K9ES|ZO&3?YK?IC@IB5*;;jlsFWX#R%j%$PNwIq=Ab)^C=5+7K(-ASxF} z%RD&LW}MW|9GmW%ZH4&k`uNQFe16nkxzLJhSAOo?02Q0pGhWMBto^Qi_Q34eOWpSm z9HN8td!0XSnmsW0{Oy)Ejf+iPzMX>6=jeAH z(U)w_F876w(jX1KL5HK%$Xgy?7N4pG>qZ7UqnmR;5r|mK9*h#H1Qp>BmiBqZiK*Ed zUp#{JpKr9%e)G{9GEAAIdVd#$h7mK8F3kw2kE!%fp*&X*FoA_GKJpl1)YC^drfx01 zDncGP9|TV6soE?EC}uR^j-8eTAPX;X%;8m{Q& zgA|$IQs1uNofJyHqI2hXe-|K~Deh=4*9r0F%Alf!LuRW%NkfHjJ=+vXIfSfW6SO;0 z5K*M1)P}n+Nm;3vDaLFjgAp-EcdS7tRC6aV)N(}sE<|B?#eAPZW64@LteJ@_Hq@m? zSC{`Xu3#hv^7>dx(XaFgE@_~;0?LNNjt&)^5ESz+@SHLxthgawWk&y9hrh(ua1zsVnkAkL>L>z>-3XGF`m(Nb%`X z=&R&DV({EJ{NIVYiOjPhsx5BhuMWkHP&AC|FGGezo&<=Tjq9%pG$#p6nI}Y&u8>H& z6f={gHvWiI_i3K~8bxEC);yMsGT3z!Em!tdko|cl_&4-xEzgv(|ADA@-MZ4y5ozdH zY3PYG^h6s@MDw1U?t)CgR(f;aV%<`Hv~E4%o0*CgmJzdNrLZwl*cdHr3KwjdGh)^&s!1Q^mu6F8?){=-q*^I# ziWD|2ZGF4-ZtK0`cMn9j9f}kl`p69G8+3JH?yT`c9sYpy%PYRIYi`#(iB6nu@R#z7 z;VnF?Btd*al9aBwuK7(!l;>W2I-0lrUjKVJ|MJV^Yv9?r@mNvmf_|a)we%HNbHvpg zb+v>mTO&oSq;g$)zs~*oz-!bvSIK=>RjksrQn@Wsxozp$x5w^|-Fx~yLv+W{Naay9 zuDs$SBT}Jh#U(e5Yj(6_&7~_S{$+;QkxA^W+>gz$oSUz@HLz^2{}8uhX5Y^(xUp$& z(|rF*`MyZ`zI)HE?C*>0?~9iAM{-XQxBImIBO~Po{hay9$Gdb6^iQ9$pAC9TG`IC0 zd>ifiJ1~|q_W!q!axo^q`lt+T_|-?5$Q2}U=6C83Ht2p-vGI__^pn<&hq5gHW@Eel zP_F5x4H<{b#-Fy>4(W_P)0q)YIET{C#+XKQ;$-?`DGldvF4m7f!l+K%*Fg1BIqZQT zMWM9iJq>O~^r?h2^4^z}U!lE~{8rV9Ru$|(Urbx8LZv9V>cPs^f5ku^XrMT*P%SXC zQ)qNBdeC=zPgs-4WNb;8XDA40Zg(KQ#B5>Gg#MfKk^-&%6NYP z{DP^pucoPVkvmOe>;tlg`ROMXkLak8F*fj#`L59z{i)g^rsaia_gaXWw?Ch@>a}_tA8z$cUlNwMd)4>)?sbJ-2ciWXVMhmTGl>5*Nau_nHf%WH)cweraiH1wqq3X>jm94} znh_S_h)kf7XdTl3hm=h#n1eR~X??-n4#b=lJpmUW3i|y_y*qjAz_W7p1VY_(i<=(+ z%8TyrWMxdMH$fS*3x$8ibac^lWFzA>-Gl6^FmATWPJOc#QERLZ)vOOVJ4r3aPvwz! zEO7Sp6L*y5LXP^9?t=y&M_kEcp%LFG$Zk05BMz$MrAp=wD@D}%JiG@Q_h7Z+c*B-B zacMUOr2NcCZ6hdia+N}+5im3hxGs$buE35Us1&pDTp)1C?-ecuH);rRjH`{&EmCRg z9H6925fgcduq{^JO=CzjFp~+Bs}mP&-8I+8icWBjV89aWvlRqWg24shY`FF@HZsEXL~q>Ed#e9fcMrTz(4>g;JRt$0iC&CS|1qU?GP!4h zX=e~0MTIm8ya#C&iJBC2#ih)Cy-Ot#^ooWIW?HbpxK+*s3zj(DcRMJ3ScfA7DlA!; zN<_Mp;Uuk}9Hhbe0d4J^-XAL{nm)A7p7Z&c=jYEy>~$J*&FAkvA8G1{7In^=ACT4J z?SW-;PAAYZ4+40oRofR<%PJ8Bh7IrV^HQl!t%yY0y zjXCnEkizL~P{lZKK=NC=c;!xG)VXuIbFCar5Lvny8RelPGKNd{kOU~qy_6EA20qhS z5*b32tMEtbK{Y8zqoC|ZT7Ty zwyAVa2HI1`sJOy~kN$F1~$#Aww`-AL~RVxl;tBx!?q;jmIToZE@Ue8daWrtqEvI4i|b zrD8FgA%-KIgfl$2SM17r;IXmLg@7Phkjd8`vPVMB1D>b%kV>)8AVP{WWVe#mkcOf=V7Kg>NzoNW4)ZDfR|IA&DCRg+d+N2vOrUwt-H!zUO~XY<(0q`UG&GZ;DeJc|cQjw}j`4Kz z+?CSoXj;d(it;?xC#=`Ur2J=^IfX|k5dLgVOQmaq?FYgZ$&Kb|OuW#6RwNt%h(t#b zx`)3+3~`v&yM%>8jq&IcF;dBq25Nu16ena~!pRg*9{0g}>k29lBn;kxLW zTjdhT#5ax_R=FH-^Np%XP%6)UaxRq*G-&`=2|T4K1LVh#C<$swhBu9JE7iQRYPPmPM_SPi_k zxjxmq+}R@Iol*LXhhK}93p61DW9&3gs1tK8R8xqCMpTymCWW?9#C3#ZI$r@&hIoVn zhzA$Qf0-p(Pu2egvL?9!UGF~TPiTq!2c*Qdm#fRK6y2(VIL|7a9lJI0=C*J})3R;L zDwx8pw?Qj=-rBY__AlDr&H0o4(2|&*0#*O=p6Sk2XT|*30{3Re_YU1T^hS5oxjk&# ze&1CWwv|tJ&eqJE*9;k1-EeeLz0kT?`*`hbs^MxnBtqD*jW(1^8h@;Q^!WN5=N%j-AFI z@6h9&u#M9iWvl)yCGFWPIbTsH(E{u{fgOydX=>=rx0+l;v>t^ zrP>iDnRWNYGP%d#$a)daQ0Ru&TVVuiivsI&0 zcmJevp&|DunAFZ3)banFrUVjku?H=K6%1Ubp~Z5%+lkAodVpXEKY)$Y?+cCa6ZO3k z+q8?xNRIo0K|0Qgv7})ky3K&nz%MDAp{X65r$eyc!=Fxw9)$PlbD`?Xz*k0F+Rox4C})|H|o0>i}&KNBE|K4R&d5ZCv` z^_?Pyuca8mx1ubk2l?WeG9&0Q87NDH8|Tk+mNF`d3PuBc;ttt@mo9rTb@&kzC1iYiK#E8h3S*T&c2V zrE+_uayy8H`IeQ^ZIRM#OP!I@T`Q${cS4uLl{;rcH?ni5zXbLk{L3a5h#PyZKmV=g zR|~4cb$jmh-#Z+x>53K{3_A`!a8$$!T9>$`GvU2G;k@3}yt0qYMy3^#RLbZn`Hi8yebw_$ts^s!qd3&*0x$^s!|dJ#^CsS+luS`#G zSH|H+<9nO+c(2=r7_oK$#c4%%*r;h)Cq1c=x{Rb4?}ZGHGiAPqD&M|<%YJz1b&*-K z%d4pQeF090%1G;{YYZhmB7AR=Z2(;wz>FlMi;=(w@j@kR6dWJ$Tj)@(>To5_MY>N_@LB>ngoUbPz9CTB-f*Ko4U^!0n)8ZqQ;#I z?!pKSQE?nU;vzn%7fO2&)B~aLbURg>s~1(X6qG-qKv80ko{N=p;I5+AC`;sA1i}6t zg|gcP#u7cpi(a(&ks#01`8=-ngwle6kui364tfL4JxE+bJZhFYhGPBD859|^7-Ghc z4T(j*hNkVJUL`W)+W?GUU1O!~Ii}J8=l^T?WkT(P`v_!<~lGOSL4Cry2;%2ri#N#^6 zOFW+%Ny>8k)n*oCb;>*}a;~bSU*h7eZDPBU43^d0!A6={@{YmW9PHZn&d|HHKil-f zO@A7Q?(F#sd+!o1NUU4n7TZ5?c;2`7hAq9n!XHM&yyo0tO4tk);gdMu+S95^AE%yi zl{1w}yIOndWYjiUF0cnQt&wQjaYb($SHAsM?G}1SGIpXqyGFd@AY)v(5s3U-VZEN? zX-6T4d78QQco>*8hP>xS__j6|R2zMq>+D%E_t~?eaaY3HZG)z7=t8i~)w;#iyk(2Z zD#l!H!cNfC6FA1|Rv>^)bE8ZA3jLwWBfcRJ-?)$t>O?_YmBhSjX_K>ZL^b3S$(tJ~ zC_@<)db$!n8&C&9l@G>ltRnHnO6VQsJFt2ARmCT%DM|s*p+GcUFZYNd`mY4UB98IH zA#DXrQJUI8qfJ_=uFw_QAE`Vj6$d!3QM?)q#J`vXip8`#Mv@9*Emf*H={tYnAEq85 zxg@zF8qr7ghB_fOR~eIEr!!Q?qr372D@p805BwP5@FSfMzD=P8yyDgq?T5MskF`Gy zH2{H~Cz7^&Wt*Udk$Rh;m>slD5Xl5SoyV9_M4s3(7dlr!uh+KVa)z(m{Ys>^GwSRL z+qynkwHFe}RrGUbA?aNfeHtX5(hHj!b$^_(%Xm+}>k%~66G(MK#~3dNB|oBu$hyO} zxcm*uf!644e&q7^;|{N1ckxr+UvKH33i2dVN?s?O0dc9bWhCE6VE?(!&JHmqk#&u1V|4I0(zy zKFF#0b$bfM1X+xW?)qJqlls!3{i^f=UW9NpA#8p-B;(mbLSXE&tG>76&||uSqb#gH zNck;we?;pL7N0a8@Q+06^Ejrt2RM~2p_B_IgT`c#z+s{wfjgjl@1w;+Y!@t+O;{|< z`v<$4^=QPoC2ZUBs1=f(qnpbpH{Q~h8{-+I7%@ncG~>j_(-O?)B-1O^~ZFvv}C@8Lk}%t)OtD)zr+I zjW)Za2Nyg_{YrIX_Zw2`&*C2kt*XVC>N@cS{dw@-29?&R*GHt{_%e=lwaSfEd9dJd zE7GJ?Ikl9|RQhP4CUtdEckvVTKwXT3o0Cxk^rYd4QIy;X&oj$Fj1jrarq;lk4}T{a z&mGoz7UFfj2yU3BjkR+532jVKtG11>KRke1GT_7@Q^Qfu2yKu{lc{rX@G~YeIp%Bt zj`DKkc=fL`L%5y-?QP7^!Qp@|CI3}FX~mV5MxSmn^S1tf*2C3ZCpde0^k2Nlb2y|p ze1mI+CbbSZB-bTF4Ell5V)9knRMw=8Miybz!q6zNP!3U=8ggu~mZIF5@{Cm~i&{dDB1IiP8^D7ob2lBJ$169t1oUj-qqRNexUbEJRPp2Pf#H3WN&|a zf0u}4$WTi3N7YLq#^t3|Ctk7~MF@^`o<7kf(sxXbyG+rvUIhYkb`f(t`=mH1fl<*2 z3r3@oy*wFSiN3AL36|R~8qGgP@l3{hg+kYnC|)W}1D$(Bl?R2_9~6~4^&!!nVLS4` zc{j&}M2CCnln`fA;pbG2g`q+WaS)42M^mnOn5`CTbJDHQGRXLW%Ywf^1vrw{LJ<6l zaAR_AGHR<`wG|-z{M_?VTa6f=n45^&s>Sg5+<4ShwU%Mtm>IUz5TjVp6tz00$vqBk zrjRZGA$7~6@Xls|xzkEsOC+xaCQs8{bjgHtvjy>AYv{t%uw!4Wrj8UqUGhC1e8gG` zk9x24&DY&Fyq^AA`b|&N;ht%KkYy(qc=KJ6tSYF2&a~fm6iv6^x7ubc-`X21+D0yI zwy+y1=Hag=R_k7@eeLM%q5002juXFf3&h^V<+q+$tiydC>37rbc%ntSKGNA>tYwN7 z7SEcfdED)uW#_io*4Ek1aB*WK&jU5s8-ck%v|!_`G43o_Gnw;CVnucHCg$nRx8z(p zA1ONcZeFzL;DfU#5jMZ(L?V8{CQqNijV&RsjsCuC`T;B$}i0Q*Wcb3H*Ma=)0dD*c6xw3LrY_5pS zwPM?dOUV{3AK13873#7}KKVF9SGEb9-Tac(icPVyQ{WI+mcXL1xMa#k2yHLo9?6f&T`&->1I!@DX#V~KUpCJ!tI%+pG;Zz`ytWN8LaU|; zQc%V)(3VlTRYq01F6R&CsJ2ybHl)bT<#@sXlg0#|mp(*Gnmux=VA-RNO&9a!wCZ0~ zE;a>E4wK-mT{T<+T_O}|+{LCGUl}i5!W;yhqk3Q>TH@^C%#Ub&YI(V6(_1FzR{z2s z(j#)fm8$`|1E#N+B84LBR&zqGTP6RJ$6p>H5tA}pN{TM*0WNhW^uU;^2MOGzG_M_9 z&y@EwFrFdFlu&^X@Jm>g5T%Bpv>ubv2APQLsKiZ*W+S+|XTd=y3?tp84m<~@w8Xnk z#HWc_zj}H6GB@mD`?rTm=w-MN#Zje%FE!=Jeur3;$dnA?K8aD_Rq&3I&QPq=4CfQN z7j>qI;l!K@X$n08Vc)`8@Q3|(HBD%|5*nt;a#Lfk2 z*QKGBeFupE$bc(}TcnBkUkQUt78@HNuwAiMMy!=#>qZFSM2EPqdTx4_ZEgtqR_rwq zdrjDm%PE@hCgVNsR?o7vL2_;hhpW@=g!#O;OO~CRNkyx&`_FeSJNn_07I&9Rg4^51 zWqa+K!IV|VE}&|Fx4V_Xt&u|VxLLSk*2Juf;a$_wdaHwM3R@zsmS|Zke#1RyxOC?` z^~<&nIQG4toqPS_%tc(Um0huty)}}(753U_^^ut)v!Sr9?B}?Npl^1NIr}ACx8S^e z@w+1**tWrwUqRh;>n9&Ob$O6D8nOymQ`_D-yzJ=uxubwEe4%)+)Q>VtJIi%HDKGBa zW&FubJ>GF6R(afrWsw@??Zhl-1t?HcfgPBv7Mbb>0eSmlGDR|&R~99sps~6b+0S83 zj07$dLqr45OxOX~(n5fXF54 z0E>xbfCr@0-U7&D{zVizo`InBLScSh_x zqxQD2rA<`&c0ktYCp8>6=NKFU?57n%ER99!;#mL`hjP8Ji|On!E~mq$bhCDrAuw3oo!1c4>MFGDuz{5HA|x z#tG~MxN$=LvYIs*B~S-rp6S!*hJlww0VAm{8zm7V3q#15KC!Rgdr3TDYo>}s%*=Kn z#GmJ3&m*uqr5K1au{+MPqS?A9o-0~o4{CD93&(=IFes+bMogGnJzG3maEFp5fa@5^ z|6kk!39uN-l!ycz$J`dU;J{%OURc4f^bL>4O+$gp<51gCksz)cf*BJWu#5FbQu?^X z8w^6GKElUySqXy|AUYA9Xoki`ePpXZgDMaN$IT~BcK7th(~kFcb{~8?p5Aq)|73ed ze>|(bvvaWbE3aj^T?F?OBO;KA;$W1W5RVkzZdKLUg8J)MJxPPU&o+}+U^x3%~6 zbsax&tZT5dw|sF9-N`OdwZBuI2ncgPgnqPr)CTXrOUB|W7J9$ zSOw>kaGG!(d6E>B*U!a=v{wHYl!3Ks(Ph-c^4+m~Ppq)wZ_-T}nIC8C3K~}Ow?y){ ztRhg*94Wy4%{W?ajpS`zE#0zGx-U|?Z#93@O8)Lh{_Y3m%`4@{BIUy3=^ki!7IVA?3_U}F--Ihd?$=wCI>?@TPjG(9PHvX#Sn)CqDn#!^c96^ zv_k|t{fTut46`(yi5G=FVj0;$+{k=-=u3f2DaFY?Y^?#qe$@`Qw<~q6k-FBEx*d_a z9Z~zvuw^IPjT1(chJ=kMZKtsJf}#Gzf7IX`*|Z&k7&_9bdN-2uAo3Oklt+ReU|h0p zWO^QiedWQ?U}n<1K}x1mfF!aK&t|4-B8VER|sERMD@D7!{jso^(ZZC z!##l)+Rg&fX$I=uk_8nc8Yf}g$O|4R26xa=$^ev2ROewbI_?pj1sy@xg9K)h8p$05 zlMH&H+o<%%N#jn3Vy5(;VOu|_id^G&Q7Uxcq4V*$tI1)YY6QO)vI9{_7}Sqzyql<_oCdBDiyvOUh3ht^V0yL1BPPdZUq_LGz4BI6yd?Vn3LmwXg=B(%#dsLHhScGIL zU(-SgijzwQr@2bg0tLyb=X~P1!^huakeFN+ar{wUx5^<-W!ZwuV-z`r+%i?)hOV*! zfypkOesL6D_2^1Vn3-oZwGRma=z96#vHQ%yc37Bv8@WZ!ByqnPQ!;LXowxws*)T=d z98d`D3vPPRQ6+Ag81bDWEmhKFFGhL(6TL{sMflH@+ZghmXWl*I z24p3ALk3Ctq++}}?458V2Gb>70@#pS>)=lR znfDvpu@OA5J6}1nkiKZ81B1PF+H~KVGuuCd&0M_C?%->a(fk(NUx6z&o_g7at9SDY z$eP3r4@(7wa3%r`)|{6Q;f@M+hN<|#xn;G?b-QSJ)80tczIXLMv;ENaqP3j_#iB?yu+b{1sw2u!h(Y_M5y^++)gvSByG5w#>4YAa!sY~mqVXUDr+ zWl?#oQrSw$&WltkNw<|mT4kx#ztrYWT8tf%{gv;#-Sb5Lkss-jPM^Mg=f3(r&N=to zbNtc;-t!}d1erww0?8!-At_;a!IeY$K>8yIAMD7`elFs3CM&pZsjoXg{sb)js_)uM zN`ao$?w4#wlpw>i8?ACaBZ(r}X-q+vHF;u~EC(r=;}>t<7=!!8^@@nxU&#J4x^7X{ z*$^2ct?|^1QsiqqWg|ulnA4m$gX{u7gZg15=NWyeow{1T$Ee@4Qs4hy!U>~O!D_6s z6`|PdYSk{IYS&_mUO8m=hn_m|GLJ?c#g8U;*|p>dCLOZJdFR;1prGwJ-gfb ze^3pzTlxr2|M8&mZ#f<~-W5WjG;2t?C#2nC$IYg3j5tc|DJsa;HLcnx7flebAk!k$ z8?;7k!K^L)VcMJLvYiVKtY(vyZx6E>xlbXr+|iQ3=G8!}5rDGT>drx9=O7$itd?QzoJZIJNJe56_bU~Fc>&vUtD$y-9(tVa zFg%f$Rs6>ByT{|9_i7hvVL)T8x?#1t2hIz0e^1P{IPm@9N5d<=gCDoR(#321um;l$XA7du0Sw|Cx2Y1q^^`)S`QP&q%b<`2xz+0DWepjJ1^Ynu$^ltc+0 z(7C|p7!1N_TE=K{W?Ln_CP;S#nf8$lCIKiN^{a=mLO8b?Nw>r$p4037y!Y~)VAI=A=c5-B#~`9+R3F`*Ucrw7W=BBl1dr z|0pRQc|!6H3fGFb=bsLFGqcBG|A_CLZ)WJUY-qNu_l|5GBc1lWNtbf(W1F^8FMcC` zS0O!ZKuSQH1dy%aa6Q;0O9wow|2`DHw5?_7@3A9rrSq@mn5=P)B*Z04~7tewcr zlTIdm@0O`$^6rK>hidm=g>1F7!qVq7-Yb{Qe}a8SSWn!(7B0!d{G*oB3gc*+wq`#0bw zfBy1xo+>mqgeP_bvsE?h(D~P`ng^n(FqoU=w`r1zT5xUGxYy`QiBw&eLH|Tla_MAC$*lOt?M? zwr*A+akB=1QhF|Gcz>3H$0r3WjNF>&Cb3Z9q#SDjIv$2cD08Fme5-v6^iy; zzScW)wHMZ3K;QPFlf8cVjb7Bmsukv|OS50js_dWbf{zGDO<0zn|B6@(!9Nj5X8$jV z{U^aQf}aqSqDeG*$I`lqbr2gS_5!gz1Um_6dlGIsr7=s5+gp|eIhumgCJA~O)=!L1 znY42RyBPMb1Uy-4ZDqbqjKU{vA79K7`wp>rV)qCr;FaP+jj}WRcM%f+ZoRac271nEn~n5@QyO>aA?55$}VG2B0 zNd&nk7{9d8X!zUAVg{Ee+iK(C`wga>PaYZ>bj8ms_zYj0$wbiUJlkR|v1oiWcKv>j z;ohDqXYjOICi?VUhfOqT-}1>6Z)Sa)*t_8i#?I>7ck7|uhHsB45X8Jga2Okooxbli ziy4A!L#CUUN2zNxONqg+OfWWn_m|9aK6z2cl#kdcwL%<}t%A;?2X|o;-4qC7vO%+$ zn3Wtc)WAxlluszUH&sq-XIO;zA#q!D%G+{O-X71U7`Qp1wu)^_E>pqnaq#h!e)84F zm;SCX#by=MU|_f-VpWd#$#$?GT9FeySJ8y^-ehTJHZh&rs^kO zW6vH_`O5|?ChE>?ibObG_f)~nP8FEBP5D`MQr&dEAgVx8U>1N{pDCXXAA215s9fS3 z?qEtFhWSOSvj#*p4qbN|HEsUZelaB<%-RMqu5S3YnSu!F z=&$BEYkw$qC2?YLY^g&(`l?>}s^Ncalb%jDoi6NB70bAO#S=@CUQ;2m zbb9$MA^JIVM&q@K3wp56@b;SmVay3*hZrZ5l$+RT)hqTVF*oAwlehez0VxL`cU>J+`vQvx+ zdz$TL{zxA9Avg&urgI;3f~LmaCR6p; z5rNqWI>g>YP4WP&q|WN_u&{j$`ZQv%9SxXSQjW=?Kk0n9FQouA8=>`@449}uXfe1r z^QbOG6jM@r_olN=)U8!RQD*@I3Aoh|1JbO-2T)l?oMIytHbog0aT>) z_Q6uYX0Z=TXhkJ@pX@z)6;|+0Qy>&kwpA5`Gq(Id>Dm6N8zC%taMJ#pfyJQo2ko{@H- zUUy8FAfyB#Zs2a<9^eAF2YBfX7p%bl5oi=BZo_aGoY}o2efyor6UTzkReUT8iM_my z1Z=_Ga`3nX4#FT6>$+hJ%N*-2a<=R4h<5Rv2+=eR{tqOX{*j~+NmcS34qVr)80~i zo3RWnH9laJjvg*=WrVtEL7+o3*lMK_GNiPD9Eqgms4NV$3g)iDR|y-{g=bXJuHy=R zb~Bh$$IS14ht*^YL+}@@rs?0+U=ODKWOOCiXBk2JA*^?de*K1CQZ4J9_mMJH?vhoW zMLyOA$vFf`h1YlO_t^@42O+Xn+5{q#d{(S7ub1FUfIW;v@;{CYdXJ?he}a#L(v7j) zD^T7m3I9J7k>bd$i&z|qK=O$a`g59AhWvhR0k_5aAB@}|$uYE^*M^8{bsI|hXlE_2 z71_cC7YoEI-J0-L;rLxB0&!>5n=VNkghV`$WXSuh zK?8C@$EaxfmMd}U+h-o0`Ga#S&AaucJ&W6QU%y_`FPpo)tdPrOl{5}4i%n$r)7*Sq zB_?^r9}@c!!5zLBBamDSCk8n?JYWf4L--wqq)TUfid0P}r&rt-gDKw3B8RAngCN5# z0n!^cvqTjw@wP>(yOXUQr{nSkWE`}jh#{sY7Y0oJ{CK0WYX1uM}O=i9{6Nq(H{^t$sp zHs_`AK(fiQ3ym^`qXh2~$c~fWnSNSw0P1FQS7t`Ee@A-wQ=&fsz-e$*O^qn3_urJ# zCraZJrQw;QOm#d{(qNO=XZ4EO@?)j*i8Auc;Zhy&7lc5MqV_&fdh$bdJW+<9D1%QJ zx$DPD*E2_u$vqD?8TMI+qP8Q}6Q#*45^8H~25y7Y)xTc}&_`s=U%RaJkOpPwh;`RSW~aqb&`AW45r zKeWfCdLH%JBt(dQU(_Bn0zJ!jZ8lG~R%;_h>g zc=|jed3|{!-ahY$ug}N6JBIT|3i=90{C)nB!oI?hqQ0V$Kwn@a*cTir?kgTC=_?s2 z?JFHA>nlTiXT&vJK2p(F!Thy!>-&Pi{0P*~KygC+E zh_E6(EX2YB2n$A?w{z4S>se?qLQA6CqK?}RHN1g^mm<7O&!Lfpl_RV|4{N$=3spX# zL_HyU#?d`GK9b2jG8!jO$d$?I9KD)xbPWx}Gwu_Y;zMJj;o*$)^!TOWXvTSF6u&c$ zfp9Dy%FDP9DpxPXJG*-`9_Bj`jzu&1%zGpf9gPpguc~oQ9o(MrhoiCnfwKesk>~)W zGXkQcLO^ujtT_e+XfeFXz;^vB`=Ne$0C zqp!wI*%lArb3ED~V`cS^vEm2#NO9M#{&>^{&)ZT|BJc)i+oCxUJN|R-$4P!||w+@xV938#fJUn!^ z`O?++`LWUVrq;IR*iby$cqu$^F?=o>!-q?e!DbCYkVn%cKwW?T5HjlTpC}f(q)7{X z62-?V;9QrMd{X7cgyW5ZbVV(DmCFgo@8mziM=6toaU0N^h!7|KS@#6segnf6H@d?X z*JEmPO=-I!T@bsMa>a8Ym%l}K(sn@u2_g8ln*TL>oXTa-q+JiSP1<_Rbzr!aqUm+m z@ww`d&&v?q+v*R!)W@w$ftHJ2m%kVH>tU+rTFzw7g(5A~cu(52@@x`f1dT765A7<} z{Kk8QzAZIkXg)1}?TvD57YHh{9 za<15vt@unRUPbvTQVr!~>`g5h+p9_)zQ<^m$nte1g!gBjz2~B%(N`}i`z9JiJYdeD zY47mZKzKN|uSt*oB4tGb^vge$etBK`sOG?(qUp%Oy4K{n*0~J}>$WFr4*Vs>WAGr8KjRWPOuog2bR+J6=cP)wnI&J>-C#tCnYMWPWk zoW?)n8ow05+L3X`@EyJ|!=4!@^JkpEej_oZnF=9bRm$LmT&(p<1EqIRnv4Uut1Xjr zF?u!Qyc`}LkH(0&`U;S)EVJHWSxi)}+%HcfevAk)^uVIGWNP4E)wX-yhIFv(?R_`* zEd)c!U}$#ZLjB%k{oYjY$wb#;pmt_^Do~d=xU@+s3?}kE-6$25Pv_jLX}p);v@G3I z$@-^K^_{8U0aMa-JZTL}`kgP|%dcMyuK(7)L|58Z_~x-2$B>_|n*7Ia9G~9wy{31X z7Ajkkl`V6@_bT44NL4;@&$l1uhQx;a_hJm*YR z@0fB-^?uW{l!MRr1Er{OAurZ1)OaztF%{g5f>EN0+J>q}f;QwHri_Gp`wE@<>Ka@C#-9?fUGfm8H#!U)yp zvOTV^0;{ey%klg3s6(NVqvl(o4gu}E@z&}vY3tYPjoJcXWIq}P60ma4H3!P4`H=NY zI*fcLbN1pZ!^+ufCrw=T=zZGsYb(2QS=lYdYGB}C13hXj;_biYT%qN*Nhe_mEj9=` zr`UduR0|ct(j0LSYErS6N~kLx6hzB_LimZ(a=Xd52TrCyji%yb11V*kN_g~KG?OzN z9TgFj@&u(N8cf+o8Q6vxYGRm4MNORuH=`zVAur>549pn_IF6aB8}2pjo3DE6o_GH; zJR{(zEi>^{paHYJl+Vu+1IeVztG`$9PQgNXQ?k5iHuj^dx2~qjcP9?Mal|zJcc{pu zYW+f0Q?jaQc05(p0rYb4n{GlTJ2X6!FW`~Smq8w{TCRXPN-Dq8J{|k^u5a}dKI@pW zr7LO{DjJd%4YR#-MYok(YeMCC=bXXi36r&hv;~OHBnl2(LNMrxISgJSrt7!>RkA=jER9 z*E=Ip&vXCfGn>1qN&4sW=l5N2_TBn_BfUct9FjI8rittz8i4*E(WD}RBaSzJCh&?t zs!%EQN}yIA$oLJK!rgzev#aY!&(k3r%QI#}IEO`iyA+N@z%eS%AaET2F(O8hE8>ni z1`8u#>ogqKmx~m6LJErEj(CL_Zp82*M!p)0$0!hDco4&{ex;Ilj6xws9%5+ewR#mH zW_H~Ik${lOn^iYzjdiM^kji(pI8>5xb`GC=ZhOXkDIAMk8B-#e93^@=;|9^v9~+v8 zW^%_sAjOrd8QaN>XDHID{tApl<6)w5G`24qQ5Y16d=;&Q3<~}!>wAGy)3M>TT!X8! z;?pK`HN1JvJ?XaOEON9M;2tbv#PxN|YR!$1#TJNakqpbcJtYDKIPD<39sJ%Hzv{ECWJ7Jjc(E$ZdP%gJUC?#^acaa(Gl$iEFU@G61G2 zPfrpK$tS}Rc}$Vx%J}F2XlXfqJ}PTKCUc>T93PXTuZ9QW!&l|@HklFTP4baJimPXZ zT4X01ipe8m3T25pXbI)vvC(r4VzTjAR2~~e-b3-2JUFDp;(FvK&UF`{T`w2oQKKfkDLXXRF zmfBew=vcu^bmUU}s+dLHL{u4T1YLA4em>M7k3_?4JWv<_i&`-z1AY`eFB4?N#?Qte zTOC)yngp##l~whjQ3iOIhQk9BL;>p1}emsPe&uB$aLM7w|?#AJLBnJknVxU9Iku`8oOZ-;nAYvtJa zu`4kd4t0f?;R&@VXz>6;Nzq7?(J_$_5Y_1AsDge0_zaE4qmW6PTYu7MV;G2`@htGc z_-G7*P)z8v5EUpUfKjKoI5fa73}-z~H#Go1U1`Jui)v6JJ_U?HiVB0oXGe56I)YKq z25WF=ILgL`Jn|5e?hg(jw=hZ96BS%F{ zW(?00ax5B^PlwN<%+`*OHXoNmfu4LYB-iyu2gb2tTm@KOa&tBw6U~D{2vshmu zE>U-ljhp&G?{yIfRa~lJU3J9O>~!pa889Y?<PXB^hm z0tDQFrC&xtk?7zMn>s)n8Z2tSYs40dH^7Vm;xh~xb4WG%eJCXNM)@>0av^d<8&5u4 ztlO`3r&ua#86MX0n9=mu`S9?t93H+Bz8V9#$sMLd0NL28P!0NJJl-G=t`JeoOrHrN z#54fcQ3WDVqA)znbK;^1C zGDSMMNAAQZF_bwt96lG5W0#@>LxWcdbzC_=G;m%XyA)Nzw8r8a>uwA*f<}ho@u-Q! zpnB4*Fe6NwAIO5hoKOxY5yArlpdlIcL2F1GMWR|@#kVP0!N|El-*hAh^^p@<;msL+Hfe* zkudNfdXIOfHpMYSd`W2AZmyHgAeuoJRH{;oPd%vu zCYE=Dy*S16rdjYzP(0qx2&u>r^pXq=IDw}_oRP(6_Ps|QkP!C~IsXOE15*AyAb#~h z8=Rhyn~57Txs)XopqZSJNQbf$pE52?h;b;h9i#)zxOj2O0elMiloNOCfA{k|GA>@>jIBRLG9hi8>CJ>d8Lvw1^kb?_6fx$#Nen`w z*zd!+E`8c#m-0)do=^GKC2WgD@O5TdK7Fo_m`XW$2z;PJ0WcHoU$oS>2TO1xV&UU)gxi*OV?__r3gg^1tm*G+}?Y_Ty`b*P;^Zw2A?#)b$lPO^H9I_uyBknLk|T5Hh0;))-VvuQ+G zCk(|>|B5ssmLv-@P$z(l{vxJ{QRO7sfxVE1dWmMIg?StbRxbBgh2#<|u2EkgQCA_k z#1sPcwIU^DFcKCdmzbF)^C1p^N^*&5Ow^Z|UtD=|nMp1U{1`{KTn1(aT2&Cn$Y+b` zgoRkF-4~fo;K#bTbr+j6+0uk4gdcohmk+uoN?^2(SPx9jY~UC>8waT%B7;cC04*?9 zf3=Cxx?AO##A=9#@_e*Bo?wUx-Dp6HSX-Jx zWDEiN6Ws(^Vmy42CR8*Gx|E3otXV6eXT|I|#>JdvHIFKw^hPKhvRQ)0}z=&J+6 z7~{(zv%zrd>pGLTWAe~@~VKDZ$#qgIudD43M9N|+o*le(1iHnZSF2VuzdD=$Q=gTSICQzT{>%ZrH$2-&c zZD@BJljV)6^5#VT{bj^rmq;w8=XHxD2xyY%+E*mtQg*DUt)3469zH@Ef-#G7X zur*FOu_t1O zipS3Vpag3r>2+6JrzR6Fm}@y;t|eKRYY7zNq|;DAU30v#iD*EmVVn~`(*dIw4D}vD zG<&{cF(hAE6}Z)|F+;Vfo6Mg+FTm@SToroNNeM1nkI!Ma1l{+5%m|lhklPXX2+A(e za1FXVvUIy)p8$WP8mM_q25QP-q_~x%wBV(*lG6ppWR|87gEvuU3C9+;XvI)pKB8)> zwrExDGvVpZ8QXWelU411$r#Ar^apGq2cLq}7B=xRPA13* zb{MRV1Ua01*w48=f7W16lvvi;jta&I3;YrjubSrFODW$*%)3C%^tqW=Qh`t+S76Or zr_X-t%MT@c{&w(YrB$h__Sv2Hs@hYf?Nd36m78Y%h6qk%v zy+$m}r*U@LyuIcyjIAu^vtLWO#(Y+5NhYY-^Es}Y*BXXUG{eXL639cJ4+dwqT~MR2 z1=(^*V^Y&Ia-E5!R8=PeMp%RLY6}@N5*zX-q1smsmjZ2PlkMGkqDNsR@!0$YtD%xU*0!hwCtHr>~jvqYv{U?9- zsZ^jnk-Jz_I`ztQ?YFA2Sa`N4I@w~;JllS+syS8KoOpV%bi>S6EEc8hH=f2~;o1Hv z7K`%f+>~FQcgreeHqK3k1|Y-IA41|xeD{yw0U@S;xF8Do)KHLNHf(&!0a|sz9!Mpx zuDOL&Izgsq1Y01aa%p?EU|*w&@$z8l05*nj%yD%cqNx`e7@Qbw)mm@XjT7h%j44=ZV7(wN%1unIM+>(gKrq%w*b9K^ zXO=vpVg)HbF5Y7ThSh;nfJiZqW!+{85@L!qNfZK3F~Jvv(`;Hv%#y>y8Z|MEP;JOi zBBJk2`a_70RD)?YjGD!TfEbo9%rt&F>&jJ~rXeNDKvl^S=wtVzSpUD3Dp?iz3yt|Z zwe8=jZAAj|G!PE3l)-~AsX)(zLM-Ksg20y69`c_fX97+rPhh1D9qU)=yIIl72(C=- zIH&SrwByDonseC2FcO1>K)-43O;mC=+v*$ST2kx+assRU6`SNQUMN_fELflRRZO?f zxM#P{wayLAclJKYvHSB9IUtCF0(UOZh2f@@lt8csYddcA?E zb02wY(t#4w9wm`}qLwiF=`Y~1=N?$cza0HB~Wn|%sS{YPWw4j>QC(jMxXWI zhmHXa`fR5qeP&i73V4`!UT#51vU7tFU^*|InOlkYSe5CeB{W7Bn?!TeK~`@j282aS zw3}oLhER{J<#f3!SMLJ=H(SL7Z7N8jHI}qCW+V+|BtH~@l`hgoV(zQeiXnD03%x?p zHCbp?>SfX_8&n=zxki&rtMqa$Ynx_%C)RJJ=8F)qY$Q~AkP}S0Ld0b41frT~s+H{f zU?Z%lQR;|4Ak$)ysmR#)5(}Bkh#pH_2SOn-G&l$)I&u<*jR?Z9$*P^{pY&Q7WTS2$ zWu>%YO;UH%GW2cWRahD<(*=e@E9j}@m6TKB&}e$9WtuY9n3Yskm~7PZVn%u^vsG5m zE{@49g31aq8d{jL*$B+0OXJF=F$I=eNCD$9>If5&W`a|JPo$_|K}>P+3rvJqLjff` z2Ae6&bM!x0A1E(ThRP4D%s{YOYh1&Mh;ccA`Zug56JSh!EQ7$mqdv)OPV6@F15WZG!vqB8VRKBQGUie9QxszfD=&2^oqTBRXx64Cq*ksB$f&f6GG zye%2nHrsRO;N9|6;AkRO(*{>>oz0yqOI7c_ar}Pu#>8=EOE|5}w53Y6kj`p9>4>wH zR`RylgL5@0`6(!hp|sj>BSB=zfhd`O9eg3qsIPD9vzx=eXB<)-GsK`^8w^-0AQOZm)OAk}PG@-uItl;?j~MBYa^k}JToUpjAR{uXD`Z1<9c*PR^p zx*KD!562%;pqc`{rHG9s2s+DVN|q$N=Em9UZaaH@*zu48)dcV@)wB4!og1dlEJ=9H z2HEQlQsdWM#K%jG58u*dUcfGAFkM!?l!G^GI^Jr_$;TT`zC7vzFZq1b1Nr1Dpbqep zuaMebM7{tuKM0>%6oo+zNgdH`bLOSXYnF1z!wMshS{n26;+U70$Gp5i=H(?aFE5gL zd70#8g?_?H;v-MvJ%E4x(X@b%UIqZHvKiT_ZuoT$`Xaf)mR%P%`fA&jX-lx1ZCQ2> z<}KT*ti{Sh46h!`C*(!jmGkkX0ROZpxiIR%_Gb_BDiUJRhGfbsfLJ&JjioSRd!xRn zZ_rN18w?giiiLFfLQSa@R}|&o>?|JF9Vrpw`m^Hl&CX){yhy1Kzfi5YQ4cz!t4xSd zbhSKG!M8SdWNfFHNjB|dW^7HyJr?CYlh2CfgBGG%yu|?W)UQh%vsBz-GH|12X8bV56OnRX#S0 zFE9U^%V5=^L~(-ES6cu^+B5FJ?qHovFc|6frnc~7ZumWo?UJL|+r~D0F!D02?;1WE z#nw0M7-h8SD0HH+81~jNF+7=@ve+k>8QU4X65KA5_BOK5-KrYcV8BQgIuee6_`bvm zeFYXWkgl`69R|%qL_Fut^nJp#2O`WjT&f~poKG~&jTc!}L!1Y~u|;ut7nkVk^`gWB z;M1UmAjVjU6k2Is}( z5IFmfjw(W@&{i>65MENos5eOwf!gSm#8S?I?t{f>7)A4i2Bg zXsdyo`yoaW{mJDHYIn-LhdUeFI(9Hn5sOjHG^aRlEi$n zfTw}F(jtrPySUlI8BN`#>bS(LG}8!`UmXd@2hK;i89^5GtCc^YW=1?B0ByNWiT8`v zI-^4YTY|KVHr6U5Fmgbvc>|f$Y}KyJ5`xjle4(zCwW(whjy!H3o<^}*y@q~3WyEeJ zumHo3xo+0xXbDertKG;Mc^Lm z7V~4klnvT!@|)x?M%SzY&X3nA7E-3q3(c$`4VX<;TY0?KfK0JZ&a4fj+?Ht>WQw`0 z4x~(2rp*c!3GwN~AXCg}B_Qo+GD)CYcW|r++ldiur{qf_mwXDdtoz^rHp_Se%&Wnw zHP+TItBIo-V4;sqqwyTm6aku4Yx$VGyRo%Z1pp0Hi9jGI95^3VaIy*QegFCO=`idE z8pspTJZIrC<$i#UC6rqlA-m=#466DV*oXH4lQjchvn@J69Ha{##=ce9>C=%U*^Or> z9$=kT>%-w+-xwM*l?^z%3RU*l_;3V771j>c1Wp~P6xc~Z?1I*0xp43l?deocNm#b; zR<|=z8>ejy);Cp)Ac9FLYexr|HSC0l*_s0)ffjYZm_ZVnvd~s8amTP0W{RkC1yp$r zfH|}^7#5Fbv0;~W311ZnZ=3K*%(Mit>N60S1>iyk#)mi#fKS9oKlk)~S#35(wLzgqT@sUfk z!6HWHcLbJrxM+*SU0nFLLe+ml!oLJ!!7_2uCKXptcTM+B?Mt{n_7yGo(+Bab?y}bmwfBSHssd`jJtTODFtuKoE zC=cz?Kz)ya>nt&1mO7+I`3IN<3gJWLO>#(}{l!tC@=eNvNyfhgUu+oyY$O$ejzwtn zbaOZh{I?6~mA5EM(kw7sr%aKLjEZsGse#X!obMmgr)hHDfs?(}jfw8L-H&wzHlVZ^ zN&11s>I5XV=q+6Eu1|W`&)8;m&3T^$1_{vOeMGV2-h~XEK-9Lu+j$cLIGzlIv@3I~j}XD0q#2 zfGnHs0`wtAH>F1}I44j#GpMqS+TM7BwHZ=alCAbUprK(T0N?3AOEQ~L5B8IfZR7kp zd{}^K4*|{=IUk19iSHnw)t!a3@7m7Z9j!P~JcesRJOX%smooZqD5~vZ#>sZ$X6zSR zGd3LGNr#v8501uYHPEnux^TaZpowBW<;=9fUV`=e_zZ2GOUf^Pv*$+7^sbr6J5SA? zNmjL`eC-RqJxSl5ly7gsmiGD*ue{!o4i+a4rwfY`&U8T_?JJsk_QugfH=PX9d9!-P znJn6zIIvhqvt;8;+l*`0Hd{M;YSukhJEy$6HC4DL(fM&<+1mv-3l>eUrCdi@!KZG? zADG%Ob#Us`)Ry1AINf<;>=TcpY<=SCPx7Rq@@d<*@)im=BnvmB3O6P?)BfUV`|Dqw zeq|=`&iJfz&VDQJqxEg+!jh#j$sb%QmkNuff>X7L%ZYrhr+E@B%{b}QoLI(oi5<~m znq0J+Gn#7Gc1 zyR^pouOG@}#Ct@`!)fLoQoaPg@&X*_IwdI_IotDqYy@DU+fQGT{p_xc{ZcFb+m`VW8J|jgGSHd`m`DK@_AFtgBgp5v^htwMT6g30>}gQ{`N20| zyz%06@$@UH{0;M)b|&+8-lOnwAAn^6;sc?WWwnoaQs#@SK3>ME7T|=97f@uz8udL~h1FWR9`-pMB?uBjn}Fj^1T_OPfBzT%-Dr zDWl&ehw+dE1TilhZEE7pjj#Qhf{W)K<9pjWnzDk2Y2b;51L+lzDz?l-W@7W@+i>nw z#nxHJY;eA!F;TEsy@n(S!HBv= zY6|dW*J(HpAkH&r2c)^iH)FNbkr^hjdUSMq(=I`kOvp`;ei<@6b)Qw%h9NyalDt8l z%|8nnV98SVJwvdm$A)6{Y4yMr8GEyE7eWLFFf$&9a4Hees^TV05@skBwK%F6Q-#AZ z#f0lmqw-v`T zA}39}xq=>X<;tlVMlml{;EqbihH%s|?R4W(X{|2ooIQTHDMXuenhh#SMTog%bp?)e zqGPVj@pUyGDZFEJObnB4v+TIcSwkC87;CD>HF{;0t`MuIRavh>6I#Hvzo-jqAq1)v z3-HyT0W1q3eVdq-85UPo2mWd_EnLGwHPwbg9WT8L#k#3&z`Q{-gy~@=!WYx&y=bQM zkjYwNgibk5w-sWZHZl?hy8={VMmTGLG3@;Cn!j$j0z2uWLq8``-7;+cFSRUQFi2`d3?uy$tW?18zQ zRB$^A@t01!=ZziUCRU1gc*aWQeZCdbfwhmXm=I>FE9PUZdJueKL851pt(B85#(L#G z#)|1;t2C^+v>dSI{EMuc9%0=is?1n7^FXKNsq5xXKo07&Ph2;5KlZx0%FZBKIAN`z z9s+5`R(}mEr`{0YZetN;T4L*!^8{1kWUUu4TQJ*Wm{(DK>EwwYYwZ*(#t^)^tgW$j zT2_ykY%xD96wDmzF>H89d#e$-q!<*l5yyTP>jGIb0eY-eS7HDlcKp&@H<>IdqWc2>8K#`)4n5D`@r*+gDDH;gRGOA|`23yRlyCptT}j`u56>rk&n@LhoNtjh`nUTYkD2nC$LXVfV@nqJ^k3j!A(n$|$x< zs*CJNX1fE+UA7+@cMP!;@XwmAS%CnVv75wo;lva0(_{-sC*{L>grv8vBqA{J<8`OW z4hY}qsu(gT863y8+7K{Mwb&{6WO#`UxMY+yikp|zLyU1?YB(-j8Uz0F6xeiyw?yOZ zQFo(JXaGa|T!zrnxKnG|SzKUy(PX-U+ThHRm9Be%U2-ohm?$3z1<*8VZ)fkpBS$#y zkhjXG@sGxAl@H+`cMKpiR&^Fv9~_|IZf+cZT)RBw06$mX=p)#FYK5sbYo-DPQ#BMM zZ*4$%5&k+WZ#A-kg`Sa3Yg=P$2UQ%S$Sl{;PpW{0^GytoD!o*LKf^g=R(8btga) z5NN`f8;E9zOU<2M4qXa{)srDx2+i0PMR@|AWi}E25`h!!xL-qf!eE}u>;Ek+;wKRY3Yh~oK_gSV zkS{0mVb+z(-v|wizvRuY-uUYDcKr5loZqrL>EC_lK+?bOZfVm0^oO-c|1${(nP|mk zx>EkoygS6?K|P^B)`m>ww@{Yy_sJoJ2;XSQEcTcz<{K3D-;+afd4-l)<@d=Up@X5= zP^eYe`!ktDhnzIl=~x~brtZ(g#=admI+g7k+>x$auX^g6RnHUqRnM`L+;iVk@X$%A z)IEsgUBXoyv4ZdQ(Ptv*dWIso`7N&e8^)rPCXiB)n#^s}irdD0|(- zmQMWoF#3>QYBKm>q{54=N#_SB>zZ_x%-@^q_ zVz(&vlj1eInZ2k%_;uHLH~Qh3yTi%-y$|WPnh?IF!+bC2Hs=ObFM3lq(tFD`{@(Ef zd!ri@<5SVZWYSap(1{3YF7PekLUrnyjm~=7-HO*Ns)5(tF82EH%tQLc5`03j7&J2N z*Z=@Te^i1_dPJ928=E;Jwmv9y`XHq0b6$0XoEhIq^#YUAS23FbS?ZCOwAH)^GqRgP z4w3UToJ@YtiPQaE-3L#-aPo9_S0?{VZ}%zOjoaJ%r4y&RG6g5T)Fb@P2ID`ZY{>b4 zXljxs7GPXla{V}WN=m=h!&^gftXm`Fi*;)vjy_k!*_V6O70S&Ns;jpyt$+@=1W6TY z7Bdz@0P~ZD%Y*B15b!*GWKNO=JYbXbBlsUk=ugBTzcNEk3JzVulhr>i9EIM$y(N=N z@7A_mnOtz%%#%kRn9lT{>fnK7Mst|5+D1-@oO#W$gN~0?;n!=@{rs})htdTV*PrH2 zQT6qs@O|xRo{o~3x(X@T^JqU_MpvDYqB+r}5$ z&W(7YZd{s-Ym)Kri+ZAYWG@xTj}#1+NBplj`n=dr>>9L3a0POo4_6lFW1q1D`;6%l z<$Ubv#g5{>0*i3$9`5r;3)vUS!C~4TTqNWY7m@OGnJ5l3J_)>!}x%h${(O<5}W`wOn{kEWg-7Hi>=vJX->+!WNDn~-- zKP`qkQZK~VaJ3+`Et98CUBFxTC|FuX{T_sB4ja$FM}dkR36F+xgBBD(3T`fEn^=g7 zr5oL}gA6q?hJ;>}MBS}|pDHbD)-F9q#zAcJs<1VLi1M(mAqFo2Mgc~jY^Q`uB@qpk zC1%x1QrS4ILI!IAi{#VDdCe^++7=TdCBMjpCs%I{Q(0H7I_gz8U;~LKHB$a6ub%rn zx6bLD3)>yUYcAB)P^{w=&x4rIl+L)2 zE{w}@^^R1Zlfh=jp9OK50yFSr90UgBDu*&T=&6j07tc;;=o#>_ zC5SsjMbR?+=>LL4##xgRaXS2g36<2ZQD9@F!(nw45YoIo;V%G!=Bsf8?kf~<#?$Y zC|%H&RxJQ;#Dq~beKx73fX&xwJJNLkYD*@eB(;zkIC0d&VL~1G&z4t&I5A( zPjVP7@Mq*B`cL`Sa54qDiG6<@1Zu`XyL@nNP#wjv%KcC111sV`k}s1r8kEX zj^FVxdS{t1o;vsu5o&-e=>p!_k8w4{1s!6HICRKIucT~62ngE$8!w}~LpIj2F#=E3 z2+lVY>(}>sPLv7#BYrqaeMIEbbt&x+F8IMU*Z$t{!j}C>{Q39KyZ3Y2tpQOo&Y=h_ zm@;{)vI~7}Qo>W6SsO>;VQtiB3j)*!VrVrqW}me6QcqBttcT1MHSsex2{^2b=Z&27 zUdfd7qj3f*>F29cCeS~E3z7R7TI%PRUui~>*u%!)ky@vGLe4`t8T-Isj3y~V`<%e1 z*b@~(C#r?0B^*Z^9_>P$>(YJdMmivBcH=#N6Lx4Mj^58NTFBp&%-=L~X7*?*e`mrD zi_rzYob<~x!IW_|<=?X2R6a$6ls_k@lbpYRlie@$!PGA*$f^Bu2K}P^k`ix&W110e z1TbiM1|HL;Ns=)S40DROjwj=kl09)9^9>5h3O++zN;~2xga?&% zJ;ZifZBvQhP9kj{sD>(Qsf1uiETn*$32m~m!Y48NQR(Yg;jF%4>y2coMsm{50jQ^3 zqXmeej|BQdeXs!r?V`N~5&NVIM+ULYK&pZ%H}2KqUGQl><85q~p}P_;_>C``@3!iR z*oCWaXzLHcBW|tT><$L^1%0j5QX`H>!#*}_&iN~qkT>bP=0zWnbRz3PsJ;>#pU7}} z(tDe*B%W)&71LU+-R89UE2gdFxr=UAxdm~W3GA8lP3BJ)Xy&$1^W}{{@K~A)weArn z1`*PNkt?xVbdMZ3IY>$j&Pz0z#Zkp4*y*iIA;qz>wyB@kJYz-CLiH1pd1R5k9EyPQ z8yW;fsgd-YK&BdSN|h8yVER-XZPuHxOT>3JwKuh56GiP2$kf>-2PYUG6RX83P1tWi zZBjEO9Ux8vV3BxTO!_!5mMr%2N|Cr;NJZwebeAO)-wO;A&VD_Fii>nU^$2fBjM;WD z9iws;8{Ac{MJK7B;O90VPqBlj_K(xYuogOtD^zi479D;71!@e|s7&d)EH{n48s*1l z7)vY}>QHx&%G=})Rc8kdDhwSf+RvG3F*oQh8@c|n-O%t^SC~SL=up?H3PCYDinAPe zm^u}V9V@6o$b>0I8Gm3fBUt6@a9U0b)gK=n#<^E)JQ=P6AUL2geRh!jTWuX)81oCVk@yQVYF_vzL!(M zJZbm_7@inkLU`AWAtN9J)kjiyRiyWzgb6@(IRZt70SI-rCO*yRX3^BLQ z0VD>+VgVV98|BVvOe^)|e?T8iG6ST9`Kp2?TMeU3%ueHPOx_9m-k~18Rs2;Dgj~_a zG-ZAC^BSBOk*l;UKqh1;{r?kv{$p}JCg&w`UM43DCzFFyg%k)Yq)cA_xoDiT-Pr=2 z4fu{c!A*#qxAPL#fL3gp#;c8Avtk>~uw4z*F76`(Yj(9=CNCU~L089a=p{dC>455# zTFP}JIh)|bh>;L_kG!0#C*F3VrkfiKF_v$coPeYgu?8FQd!OR+zM`_Xy*ItnUD)|q zST`G(-7sI+kZ>**ma4(^slvwDv)J`l*orNG{@|NeU%xuB#=?)5i^ZVV-I(nTe2 zm)47x>-L`9Mb^7fN(b(VPAo{^{I%ZaH02 z^LGEuejIN-zjfyigR{@h72P^Bci{HA`I21;Qn;5^B=YVTm%n}D=82iE9~}Aqk=ZME z^6nl@6`x3u$jdrBSoZc)sND7+?D{^PN^#+CeJXeyNACD5r+3c`&6TJ8d*qd;4?WkWzS}?ZG#_C+M*J!yZN#!FBso<`V2TZ`PHKv| zQEZwRaP^-NaiT}*MD8%zGBvhNILG6Ijl0mXB(cFU z6mccv0zShjml;p@s{_$XbP#UH&YGFYxpXBWp74?>BzYg=>hk7^DzW3UKK^s+{^wcu zf9x%pI{$k)_q>~y>^b?(>C$y?kKG)b8A_G5Oy$7%q%eqSk|PDH)a#Od`Kd=Lu6Zcg zjJW4grA;?;Fqc?d559cHkj*!XLej0u&fJ_IyKHa=bUlGOE^KTF(XK5ey#}p=wPc7L z3{qs>^TwnZEkq1mtAHZa$B4l;gXfTx)sU=R&?ReHd>ljql&%zDOSq`BAT5ZVJG)-o z-oq?0U}52>dGg1|AmdT@;9uTucsmT~H5X>nq5@+Cwj!K>Un!vUPf~ijGLR*Bgc64x zn>bM<3^ot?F%2hb2wGd2;3WL{88zx(z(`uS~a!l?WUVeGr@a- z&386^(DZ)Ohr!gI<2P~>If+wgZ~j}=3q{+KMcY2|ZcEp0N_5@xtxuO%CA!`?0?}Wt){K5~2Tp=o1UU9Q8@WCiGi% zR+r!>+r@_|wGDodOFejT`^4AD_c1wtM$S*kStN(4>Q0mIKalf>c71Gf2HX~#X$gG5L_q-B@1vD25!M9eDlzaL-aa! zZC_p08ldT-sk>yS8DkT{6V zTY+_aJx?4!Vin042mldqWQ%`8(!XJ5<4pVqU;X}97q;$7ZrugaV9Wbk?rvH*@Lcl1 zbNBpTTJ%-USMB+ihwu5ifiBvLGkeVMCIoR#3WNffbO81rE5aVjt))afl#M8Hi_r1q@3V#B;0? zPsb&69N#MObX_IlxmJm%lUInByGlI0-{PCK9=xr3a10{ZfUpOxvlx4QOk8oYPG%3Z zqbf}8#cxv%7NeoXofLD>b*Ia6uz(KB9P+f#WjR=kuol-;2d@^&axhxw)51-$^R-YG zn@}lxtYPAU1&OAmH|44e93CszYOPe`ZJDb>3#DAG#}#w>%Rn;!!U868g^@1Ma+(xF z{aPriwcc|msllk3=F{Suawyb7Sq>r$T8w`db`Wb~hJxkrjYBgh-9mec#By;!ln9dn z@tai|Q|#d9id`(mUSUK^*ob^Bz7}j*PzhS@rW!i6P}aw5QDSQ z36WcG9NIUi{}6tN8Rt&8o4dvaPC$`7k=IODo_1e`;{P*8^T9*MCtQdhId}+%&B1Zv z#|VEZhuB_^P?;cpDAEqL;c7}SF~U~1kEve&iJTkc{60CalVcDex>vk={@F8-_j-%xz18V*IdSB^*Z<~@8#|_+efq17gR zwK#$Jg@5bY`7zD_D&LkY-!|Lzqhq&@-DyoW>`j$FNm3D9r?^m3pDd|2=&=yUxfgD| zaL4h1>wVW<$HM;8$^EB6k(CxC4xw5#8)vq^^Gu?P*u^)Fr>kpCKk>EuotM5r-rMr-mel6m3HMu-(_N{e4M}(HisAJ;=Hl;t z_1&+g>JPH`M^Z&wlJ2c5$KO8pVyeDVj0@Uv%Z|Codl%om_}<97BdN_@=8`*B{3i7D z$0eInC0i4R7Mpk9sZTX`Cl0-}XL>jl+?Mn;EQZ?Wy52kT?vYez9}6EuTa&&miw(Q( z6n{|le$|JzhNJA`5EKPTUudytL#k+F;y`+9W8%OY6Vr9rBAN7UO4m0e4!_km zD#*4uw(AkRKtE2mYXVJDJ{ZCQeCJ)#bW)QJKH~a;{7K+*!TXvRQ*v?hO2#R zeDY4@gNyH9T-bLax$i`(@gz&>PL+g`zWTJkEaB&TH_^-5Lokhg55c*u?02Wuk-z61#d;K8+7~G z`yq0;E-@Zdy>7PagG28hy4&@yj{W#pDsU1fg3u{vTay90b++cN<6pUc>`Dcm#_4Ay z&RU-=SkJDHHH*w}jjSGEl8^b_Bp>@U!0xwYndShuK6mT6xzq2x{O-%CKvyF7esLMh z(LL$%^$EwD-W%RG@^$a;@bjoMg;8D6$=45)ULqfDVl(YLTDTIYYG{O@h$DS~*HE-Y zbh`NKHXJu1T{eH!DI0usU4sSbwH*8ttXuH95gdZ9@u!TJ^IWzmexWQ_Uw&JPc)u%@ z369FgsIl)tO_)!sGOSRob1#Va_1p<(Sk<6VhyyK$Wt<}L*Au@)B54~AV?a*85ULjV6DHe9KSoT?Eq)N{Tdt5BzRBQAmENs1B^G$lKq!N&V z)Lio#7R9$wM|!ULg!&m6NQ$fz>u0I{@EJR9R>))hW8|T)AuF^_HV*F7>a6w13boSt zs}*wG@VRsJ^1fo6rWN$pe(oIgo{keO%pR-~ZrD6~CcRhzeOO0v$-|`d!;QDq(!nuo z>QQP?zETZmqIGO^7}uDpd;l|8F;JGat&*8$U54N@e0Der#-MlntjaEw8-5wP-Q^e# z`WaK=(FmA?=h~EVDu-q(l#Irf@)r@nw~muOb|T-v{ql29P866k;t|(VMlv}bayG!3 za5Q6QnX(RE2uoS;Hu{!Jj+-L*h(nRFEfN+H@`T@p zpNnx@A=*x>FMJd~Om;-9%`sZ>IBTW4oWpX!oHsI|Z7U?JAPU$|>;7wur@HU0QmU*DT9-7+(t zENx6YeZL~KP|=vIXv7^?UrkjUOdL%w4=Jx(C~ruXH_Sda*Ow~a5B|0^!cE>aK)w|8}^`}y$z4L{=9|ua`ip^Iy z%$`nGx1|E@prlGFzO!+Dee;|nxxOP+vI89$+_(_jnhb88^~|-Uf;(UrRkdxQsySKJ zJl}F4Rdo;sSNFH-dDZgtNqAV`=NtQajPIjKrQh_uEk*4z4E$wVpo#&`%}Tr zh2Y6#@MOaE228G2{FE-Z#{9T80Q+o2wY*Bp zAc6i|1R1U5M(jq4(K=Ha%!}+t;5jV#u0cB}Lsuln$k90dmT3WS?GNZjJNBsNf|7DC zU*Uh~6jl&d4^-I<+3F4g7~<6(1P~H7oYM-K^x>2gI)y{|cjPRPlO~6d6yGG~QT9-> zCp2`Ww2`laoSoz}lhZ;@D;z6vje`sdO~`}-zDCG|5IHjf+Y*9^0#^!@P1oITcq-`* zCGw_@&Uo&73+@qus80s!Kl0Y6Tb@b!8WTsS^S*y1onLsbWb;BvOR}WpUfY3%wxh|m zqw~eblKIDsXfsD>gPH+U73pf30acj}REwAmflXO(6{^iT5G0e^-;X`#I0NMGYdxcU zgM2j3ikF(7OFp&;)RS+CoN98K$>}8Lx5)XFoDJlV>7_z6gYuurA)1Lx?Ea8^#gwU= zd}N5AkZw`gN)9n-%5HMl$URBE!xV2DIU#b`@R1V)z{f@b)2~UN*h`)6rIu=EJ$iM? zi8oqsEB+4+#9qMBwsQ4O2}6# z6%;L%k*{1Ts+h09{SWm^74*9jXBIuGBHvz{v(q*mc_h($$>nlxnF-+z2$Q@*MnGY*0)dt19M-d1_qW2E1k_VIHd`%+3vZ`cdF;x zx|0ou9#O#3u7I%_IDeZ|GuZHHcx)haLD zzz){ROLrb(zwdiW=#(p-=o1{pmB&Gm05H_dO{0HIU`f`~8AlX52NXif3gOL+3wz^X z_RkL$BV5U65`%m;C5X<-lwP`eDKglk?q60nz9=znnabu6kuuCYm0h~2kVJ@Gn4^$x zPYIG!3@792ACC_W#}pFQWOCWYsi6VBE0$4j#NBW)HWBfB3fGX2^cTu{ayF22j2t%o zpCMllIXB3m*_&~)WBU0FWk`WdN%J)Q%)J-)n2!%f_bJ_&#Q2k9KZ3KAW3$;F?T~E# zpGpNkmGb{cTK7lNo&{;oFC1Q*{TGtv{CTBh+xQE69)-dAb8>!B*LXo(NOXqXlQ5*9TgoAKBTLdwUdmrvv2mz%+5aT$KkLKXkXs^O+NJizUg3N<{GSa z5iEfNCmG}+`R)^~!@IcaWkQArU;by^neEUhO@iYkj@k&B{^ z*L~Y6aw6UOE{TTQ&pnTxlotLR?C zS9|yE^Y?c?oPD+rR(Jv~ZF*AFQ(25qP;65~xnQj6GnSWpnrS>>?A0{N*32cwco{P$ zuVDE($N_Frf0$N**4@TP4bd&&Cp9hm_kdW3q|4MYja;MYv1y%VO6m{QRqklC?RH^5 h>;`xwuOXq8Q`gb`FbE-k0!rw=zD*9vFVMcN`wyVfs!jj^ literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/__pycache__/_page.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/__pycache__/_page.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..432a5ecde71925c649e4ebe798be94b1d34682b0 GIT binary patch literal 108700 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/__pycache__/_page_labels.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/__pycache__/_page_labels.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..031ce29c0fc94aabbc406f8ae8132ed50f3cb7a6 GIT binary patch literal 9837 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 PpUBz=zH&k{-O~R7*+MPY literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/__pycache__/_protocols.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/__pycache__/_protocols.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0263ba02297bd3f31753d30bd8d5730cb0ef51a2 GIT binary patch literal 4552 zcmb_fO>7(25q``4;VysmZ`raP#ZJ;PvB}1Y5v54nCUP7Zh$YoOh(Vy;Qu`jIjk&w* z+m&4kC}5x}(DqXIWad(+HyOG3D4>`07Ni#mI#k`FsDPpTy?H+~-<$V`bUH!c`SY*-z4QZ}kiX%_!K1a9<`=*`CX^Hjm1wLYIk93)LSC-O zj#5+vuT)e=D{4->7{vFvyiwA0tAZ1^Gaae6%*08(KX- z%PLjI{mHV&Cm(qHp6xD8KCpx3$%U)eCWBg)`S~xgr<@dKN{fELOIF~pVA-P}Q5H(U za!wCp*XKj|UAGo0S8Xc@l@Dz{2=)1DV0&(<66y=w3p~rKgzD{;YK4XB9TzlTO4x5K zOx_Ckd$oYw25(^kK3K^?-il@rQL#C|HaCDgCX5s%*oN30!epjU>1~i2@S_7X#$+lp zl`2eQai&wX96JeGW-uM!R4dEk9cOY`r}~;&Oi%;bU^|p)G_j@>lfb7aLCbQCCP9)0 zNe1{7@LBLQNYiWp7F(kl(?Qef75dj`7J415X}O_raDkTR7e8iJ&|ZWg+od)KiOE@+ zapqbq)T^{?QU=SGg`KdNNnxREs}!&>Z7;bVXJ*-E73$~bLXERvg}YX3hhc=#gHh8& z;bT%GPo%jgB&URm&njg;3{pOVWE6;xMw9S-b-S?aIjjI4Y}~8D4G$QP!%&wv^Zmko z=H4$_!@Y6u7R^X#RJUvt5;~?X>BRQF$LLS?Qx%p@a6XFx_4hK35Yeqvk zcX%lMHn=cN705%ft0(yx;4BQ#?&mqfc_NA7_-Ni5LSl&prYH7&_4Hxq9j%ztBs4sh zM}7`k^!QsY`OD`0Qe}l5<*%c~1>$Xgp#~WZ=@w=n3VBT=ta*>sj=K@BV6Wf6G4*Uj z_5p`rF$2$x+^oKMcq#f!&O#^6R&Zz#9Aa5=v1?-AMFc=n>89zH9A=tf!ZaO^u2hgu zndXmHN|i{%5wpXrX_j2q3rZN>KG-OWo>$>19BvW~WEdC+xNpVM3&28C*x=8ch;viWRHMvUTR2?GslT*akXCq?<|P1|&7LZZ!zJp579# z&09_UYG^>}vs*7uZ=ZgvOY(li>*R*?J?WV&tEt_w$%c4edUI3Rv_8AMH9fn1>AH~Z z8R>l$Y@&JLY%KVvZKj{e$C`4BE`3`qBbaMM2Xx(z4jdEa@oF|fx>`$P@n}h{w*BUn@9v+A-?f%BM|_E1yBdMcmY4ZgQPF% z#N3d46aM}$fk4u!=|&7uWagiUC{3AY86g0yYH^Q(`pmCu&sA@o$sf`|Pa6?ZJ-xei zWq$keLJOS^`m8IRHqX$1l=(Qgp3KMT;?w*XNO$IA;m1@c^Y9;!%De;GjR$R9fZT7j zF*^3N3mw{)iJFpAMe%l1J@zC3A9_3eHcKlT&$EiIIC374~bh`ow za`Ld7mTIQQ(_Aju7j*o)Xn?83@gxpq+YQ8d%CDkK1mZR1`eN%nlp%Qs{{9bvh}hay zheb3!qV=hDW&PI1`SrWM&1_BNx5oVr|Qd}ob5AxhNe-( zpv$8p<~N|}L`-y9z(K?HKwKHb6#=gaJ<$W&80Hg{^(vJGr{IM`a0Z+d2{SQuu#IfJGv+7t=iEKGp0>V z*f-a&z-54jNgE0^<}f#ai&Y$oSUfGbsK3P7gJ9SF;4c0bfW(H~02!*H9uu{D@0jvJ zu>kfROb%rzagU41*hP=aq*u-e+~pHyv)#}sbAPT%8A{P@%nI`w#qnn>*R&) zk&8RZ#l6AN9c6SkJ@C^H_gWcHe}Da@jpWw3sqNEmL^aJg~&*k5LwE2_mw{CPo zybZr25i79BuRfFxxbUMe<9<4C9{7dvpZz=ALO-t?Sz!7>-z*=`)^2+0Y}O{f%m>X1d8c> d0)jduvAc}rPF?lv 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

N3k8qUO3$dEw%P79(5qJ#5hjqpf)Me_Z_-e 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 Q&*cU^wCumH5vyE&0FkcXyGo;Jb~EdAI)zPd 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 Lw|q=dw&(mml5|hG literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/__pycache__/_version.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/__pycache__/_version.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b435d835ccb1f9cd419af2ad6a36c3d548d4ac4e GIT binary patch literal 205 zcmX@j%ge<81h@OYrHcXS#~=<2FhUuhIe?7m3@Hpz43&(UOjWF=dM0`XewvK8xZ~r? zQj3Z+^Yh~4S2BDCss9zEpOK%Ns-KyjmstXo(D%&;GV+T8it^KoQj3fA%Tn{o^m8(k z^b0CWGV=3`^$d;li!)17bqf-cvlG)(i-8gaDQWsJll2NJe{tC4=BJeAq}mm+0j&VJ Ws~F_$56p~=j5qj18@Y>EfLs7@ZaCHe literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/__pycache__/_writer.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/__pycache__/_writer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b1b7fcdd7a3b6d030e615950800f683e52e226fc GIT binary patch literal 142757 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

NBUsuxLY!f?Q^lje@N0 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

f`yp+<|#MIF-9F&lf$pFAwCQ>W}0x%*Vqs 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 BNy-2K literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/pdfdoc.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/pdfdoc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..60b115236dd942aac53bcfa6095fdd8172da4610 GIT binary patch literal 1614 zcmYk+TW}Lq9LMqVOVHNVYE>K`^g*p)tI`N~7g4;Rq9EQ8FSR5~8rx=L(pKwj+FH4I zLkmhS|o{ z`gzko+1>Td{Z^j*_e#ct<8!0IR+n`dH-*(M;Q|D17qpr|d!uuu#4O&Y80H!-G&CBTh>Hvt8!j=-Gc+4g#HGZ1Vga#` zxQw`*xPrKnxQe*iaE;+w!y?0VhQ)^K4L1-=h#QHUh?|L9h^54>#BIdw#4_Rz;!a{Y zv4XgZSV`PX+(X<;+(+C`JU~21tRfyFRvR8RJYsm%@EFlzc${b@)(~kTLj=THB1^Op zIpPVTo#-Gsi98V!1>#AfNR)^!qMPU;o+6$mdWmNY&l;XHJa2fRa&f!Md4KJjik*m^ zjNK8tC3bV=!hS!bY5!ond4KEyxglQf+Y@i!9y=C09y=U65<4mfbvnnU`z!Nf(*u>m z9_bfDVnXZ_2P=HHSF`vBI^83a+IZ-H|9D{f@A5tM?WC9z?~3=t`(lUqKzt~6ijTxD zF5#Mj~*aZnr*hb#C#(JuzXi(*i`B-V-b zVuRQyUKX#2SH)}Mb+JjjA>I^2VzbyH-V$$%tzuY=h*7akjEQlvUA!YEgz9mYm*+q#PATFu$3NI92;P|9|04*ta_&?c`bFph`es}BJ_ukXhN3+=xL3;hZ=45_$ zTKcPAIdx@x;rOVuus+BKxu6e=f-W>>CIturL;8auV`wl8F`Q-?YB=36%rM+A!Z6Y> z%8)gTHk@HN(=f&`)^L_#oZ)Q4Ifio$=NZm7Twu7+aFO9+!+66bhD!~X87?yYv=TWYB9;(&qKzmJ&l5|DcA|qQ5;0LCULX>p zOjL*}(Mh~WyhL;nFB@JlylQyO@Va5yiF#DOc8i*LL%b>85^sy;Vug4|tQ4!nyJEF? zPrNVIh!4bCu}<`e55-5~W3gWJiVb3;*d#s?o5dFKsn{w$6Mf=y9dONWaC^0W6i57G zc52Kv!&N>9KmQlL`h)k-pnvbJdHvz_`|cj^Re0ZsqC*zY_0yc@k+ynatV`sxmE zzwZ7;3=HDB4bQ3JyJ~$yN0$q~{C%qR3V)EhPSi)bm1^|IdQgq4)wo$~5-a=)l$BGC zPDkgIqw{^r(J4o#9G!A>dc4yEopN+qsMDUEa&*ekDMzQ5(D@wqXrbH0cCkb3tk!pS zxRwm0sO$qiqyc-ym*Ok2PxL3p(z{gtMtm!Dw7-3=+J14MI`}NT0Pdh_J;{;(=lDtE zein+&4a{oonvvAM+3D9fC}-2Ze;NS%o0&OeOs1Ai{zzN?1ID5C`2YX_ literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/symbol.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/symbol.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7b07c9ae2cd428708278a24badbf79c9a67c3c99 GIT binary patch literal 1906 zcmXxlOKcle6b9h=?Lb09N`Ufgc`0g@2*}WuH>C)P6;csP1VT}p46fD0w(O)*1PI4* z?6G4=^K=|1ZQ5zth8E}}eZM4-*dWCLcEc{LSPf8>#aS`-e{4nh?z#8ex%b>VmVaq! z*F>!2^O;!GnT_1P==~2_6wVDtJur zxZnxFlY-5HErO>6PYa$AJS%u^pt`|zJ1J<>=CEL^V4Fsxf_6cNMn%E%f)_NJ5OfMm z7caTk?qY|Foi1K>@rsLAUA*Svbr)|4-W0qg*d=&duv_pBXXi!+0{+sg<79%IBvWLX zoFJ2=NJ=#-I(?3vWin3|$PuzgX30_FkmF>jMkU2)nH(mk$c*3POC7y~)no%uF)6!f1#LlQiK; zS7sRHYOLO3WHY)X_+0RX;7cv;hTyBawN;a3h@{9cNs|$hAz5OR9LbYWQXpTGZ^#%q zM8?SknIuzWn#_H@*G~S=dAGdn6_T1FT=;L7kDb3qqkGwt$NNSeJpR? zbFOH7RlTNOS8u2{)mvQl_FvUsmk&AuZfjR!uy0?qx66ujM|;ANkQ?l^BFn}d|Lb7L zN9O)$pJj$ak#K)F8Zq}o{YEtYVLTd&TZx2u(25*1d&B$8*kJ$uXk=&S_8n#-+;6=Y z+uMC$Z^%mc1F@dZ%r5`gR(HbWTAi^$Y1-8n?HTB`cE{uXLe<~E#8&^`-$4NXHoV)g kDX?a={_|dw(bT-wy!rRWEsMe58r#;4wqG0D;xRw-e}d>vbpQYW literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/zapfding.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/zapfding.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..46c7ba8f61f73c7aebea93d8629669bc05f896ad GIT binary patch literal 2142 zcmXw)ONZtexP0ScrNJZWHh>0r`jcYcOak^+a4BegXfn?l>pyQjN zc=QA29FW2XqT&mDL!wJJqwa8rD_5lwUEGz`oUb~a{_5VUI(57LuTK3uIk_$>KEE&j zSGV<1^v7sWeyVI-eW2LrNA;){osw-)B}ycT&Wi7?$7-UnBdxPA!d$hVMD=)!)a6f$6IXJ+03BC$ngReUW$DuL*7JM6) zb(R?)geg1(55ptyDD1&L9Kazw23g0-3S))kx=t`Y3EzRIU=isOCGx$0D0)7e4!wc{$_%-|neha^Y-@_l^MR>`ndm;HN`78M=`78fZ z$zRD|$zRD|-=N-`&OSLS`S-ZrTF#TdlE0FFkNePL{r&Q~iMBgJ#YbH#JTbH#JTbHx+IbH#JT zbKC3n4bKhFZ9nsPZg_6^W_WIRZg_5ZZg_6=Im2_K&l#Q@o*SMUo*RA6=yOZVFO_5Z zp5eLSx#79tx#79txzXp$CB0(gW8`DxW8`DxW8`DxW8`DxW8`D>Iit@Rea`4}MxV2D z*Yx{|HfOXs`zhPUvqqQrE8}(*mq0wr_&$Nn-R_D1+tKLbv-FQ#Z z+!N0?o{!s$3p-lPN47rnaNKPyBoDS{=XTE4lWwu2UE3bd6t$DNZd_h%YkM(_Kf0?` z+dZE=-g%<9)aZTRoi2XVyn*L>M Jy7O3Z bytes: + """ + Encode the input data. + + Args: + data: Data to encode. + + Returns: + Encoded data. + + """ + + @abstractmethod + def decode(self, data: bytes) -> bytes: + """ + Decode the input data. + + Args: + data: Data to decode. + + Returns: + Decoded data. + + """ + + +class LzwCodec(Codec): + """Lempel-Ziv-Welch (LZW) adaptive compression codec.""" + + CLEAR_TABLE_MARKER = 256 # Special code to indicate table reset + EOD_MARKER = 257 # End-of-data marker + INITIAL_BITS_PER_CODE = 9 # Initial code bit width + MAX_BITS_PER_CODE = 12 # Maximum code bit width + + def _initialize_encoding_table(self) -> None: + """Initialize the encoding table and state to initial conditions.""" + self.encoding_table: Dict[bytes, int] = {bytes([i]): i for i in range(256)} + self.next_code = self.EOD_MARKER + 1 + self.bits_per_code = self.INITIAL_BITS_PER_CODE + self.max_code_value = (1 << self.bits_per_code) - 1 + + def _increase_next_code(self) -> None: + """Update bits_per_code and max_code_value if necessary.""" + self.next_code += 1 + if ( + self.next_code > self.max_code_value + and self.bits_per_code < self.MAX_BITS_PER_CODE + ): + self.bits_per_code += 1 + self.max_code_value = (1 << self.bits_per_code) - 1 + + def encode(self, data: bytes) -> bytes: + """ + Encode data using the LZW compression algorithm. + + Taken from PDF 1.7 specs, "7.4.4.2 Details of LZW Encoding". + """ + result_codes: List[int] = [] + + # The encoder shall begin by issuing a clear-table code + result_codes.append(self.CLEAR_TABLE_MARKER) + self._initialize_encoding_table() + + current_sequence = b"" + for byte in data: + next_sequence = current_sequence + bytes([byte]) + + if next_sequence in self.encoding_table: + # Extend current sequence if already in the table + current_sequence = next_sequence + else: + # Output code for the current sequence + result_codes.append(self.encoding_table[current_sequence]) + + # Add the new sequence to the table if there's room + if self.next_code <= (1 << self.MAX_BITS_PER_CODE) - 1: + self.encoding_table[next_sequence] = self.next_code + self._increase_next_code() + else: + # If the table is full, emit a clear-table command + result_codes.append(self.CLEAR_TABLE_MARKER) + self._initialize_encoding_table() + + # Start new sequence + current_sequence = bytes([byte]) + + # Ensure everything actually is encoded + if current_sequence: + result_codes.append(self.encoding_table[current_sequence]) + result_codes.append(self.EOD_MARKER) + + return self._pack_codes_into_bytes(result_codes) + + def _pack_codes_into_bytes(self, codes: List[int]) -> bytes: + """ + Convert the list of result codes into a continuous byte stream, with codes packed as per the code bit-width. + The bit-width starts at 9 bits and expands as needed. + """ + self._initialize_encoding_table() + buffer = 0 + bits_in_buffer = 0 + output = bytearray() + + for code in codes: + buffer = (buffer << self.bits_per_code) | code + bits_in_buffer += self.bits_per_code + + # Codes shall be packed into a continuous bit stream, high-order bit + # first. This stream shall then be divided into bytes, high-order bit + # first. + while bits_in_buffer >= 8: + bits_in_buffer -= 8 + output.append((buffer >> bits_in_buffer) & 0xFF) + + if code == self.CLEAR_TABLE_MARKER: + self._initialize_encoding_table() + elif code == self.EOD_MARKER: + continue + else: + self._increase_next_code() + + # Flush any remaining bits in the buffer + if bits_in_buffer > 0: + output.append((buffer << (8 - bits_in_buffer)) & 0xFF) + + return bytes(output) + + def _initialize_decoding_table(self) -> None: + self.max_code_value = (1 << self.MAX_BITS_PER_CODE) - 1 + self.decoding_table = [bytes([i]) for i in range(self.CLEAR_TABLE_MARKER)] + [ + b"" + ] * (self.max_code_value - self.CLEAR_TABLE_MARKER + 1) + self._table_index = self.EOD_MARKER + 1 + self._bits_to_get = 9 + + def _next_code_decode(self, data: bytes) -> int: + self._next_data: int + try: + while self._next_bits < self._bits_to_get: + self._next_data = (self._next_data << 8) | ( + data[self._byte_pointer] & 0xFF + ) + self._byte_pointer += 1 + self._next_bits += 8 + + code = ( + self._next_data >> (self._next_bits - self._bits_to_get) + ) & self._and_table[self._bits_to_get - 9] + self._next_bits -= self._bits_to_get + + return code + except IndexError: + return self.EOD_MARKER + + # The following method has been converted to Python from PDFsharp: + # https://github.com/empira/PDFsharp/blob/5fbf6ed14740bc4e16786816882d32e43af3ff5d/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Filters/LzwDecode.cs + # + # Original license: + # + # ------------------------------------------------------------------------- + # Copyright (c) 2001-2024 empira Software GmbH, Troisdorf (Cologne Area), + # Germany + # + # http://docs.pdfsharp.net + # + # MIT License + # + # Permission is hereby granted, free of charge, to any person obtaining a + # copy of this software and associated documentation files (the "Software"), + # to deal in the Software without restriction, including without limitation + # the rights to use, copy, modify, merge, publish, distribute, sublicense, + # and/or sell copies of the Software, and to permit persons to whom the + # Software is furnished to do so, subject to the following conditions: + # + # The above copyright notice and this permission notice shall be included + # in all copies or substantial portions of the Software. + # + # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + # DEALINGS IN THE SOFTWARE. + # -------------------------------------------------------------------------- + def decode(self, data: bytes) -> bytes: + """ + The following code was converted to Python from the following code: + https://github.com/empira/PDFsharp/blob/master/src/foundation/src/PDFsharp/src/PdfSharp/Pdf.Filters/LzwDecode.cs + """ + self._and_table = [511, 1023, 2047, 4095] + self._table_index = 0 + self._bits_to_get = 9 + self._byte_pointer = 0 + self._next_data = 0 + self._next_bits = 0 + + output_stream = io.BytesIO() + + self._initialize_decoding_table() + self._byte_pointer = 0 + self._next_data = 0 + self._next_bits = 0 + old_code = self.CLEAR_TABLE_MARKER + + while True: + code = self._next_code_decode(data) + if code == self.EOD_MARKER: + break + + if code == self.CLEAR_TABLE_MARKER: + self._initialize_decoding_table() + code = self._next_code_decode(data) + if code == self.EOD_MARKER: + break + output_stream.write(self.decoding_table[code]) + old_code = code + elif code < self._table_index: + string = self.decoding_table[code] + output_stream.write(string) + if old_code != self.CLEAR_TABLE_MARKER: + self._add_entry_decode(self.decoding_table[old_code], string[0]) + old_code = code + else: + # The code is not in the table and not one of the special codes + string = ( + self.decoding_table[old_code] + self.decoding_table[old_code][:1] + ) + output_stream.write(string) + self._add_entry_decode(self.decoding_table[old_code], string[0]) + old_code = code + + output = output_stream.getvalue() + return output + + def _add_entry_decode(self, old_string: bytes, new_char: int) -> None: + new_string = old_string + bytes([new_char]) + if self._table_index > self.max_code_value: + logger_warning("Ignoring too large LZW table index.", __name__) + return + self.decoding_table[self._table_index] = new_string + self._table_index += 1 + + # Update the number of bits to get based on the table index + if self._table_index == 511: + self._bits_to_get = 10 + elif self._table_index == 1023: + self._bits_to_get = 11 + elif self._table_index == 2047: + self._bits_to_get = 12 diff --git a/venv/lib/python3.12/site-packages/pypdf/_codecs/adobe_glyphs.py b/venv/lib/python3.12/site-packages/pypdf/_codecs/adobe_glyphs.py new file mode 100644 index 0000000..72d5ed3 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_codecs/adobe_glyphs.py @@ -0,0 +1,13969 @@ +# https://raw.githubusercontent.com/adobe-type-tools/agl-aglfn/master/glyphlist.txt + +# converted manually to python +# Extended with data from GlyphNameFormatter: +# https://github.com/LettError/glyphNameFormatter + +# ----------------------------------------------------------- +# Copyright 2002-2019 Adobe (http://www.adobe.com/). +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the +# following conditions are met: +# +# Redistributions of source code must retain the above +# copyright notice, this list of conditions and the following +# disclaimer. +# +# Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials +# provided with the distribution. +# +# Neither the name of Adobe nor the names of its contributors +# may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# ----------------------------------------------------------- +# Name: Adobe Glyph List +# Table version: 2.0 +# Date: September 20, 2002 +# URL: https://github.com/adobe-type-tools/agl-aglfn +# +# Format: two semicolon-delimited fields: +# (1) glyph name--upper/lowercase letters and digits +# (2) Unicode scalar value--four uppercase hexadecimal digits +# +adobe_glyphs = { + "/A": "\u0041", + "/AA": "\uA732", + "/AE": "\u00C6", + "/AEacute": "\u01FC", + "/AEmacron": "\u01E2", + "/AEsmall": "\uF7E6", + "/AO": "\uA734", + "/AU": "\uA736", + "/AV": "\uA738", + "/AVhorizontalbar": "\uA73A", + "/AY": "\uA73C", + "/Aacute": "\u00C1", + "/Aacutesmall": "\uF7E1", + "/Abreve": "\u0102", + "/Abreveacute": "\u1EAE", + "/Abrevecyr": "\u04D0", + "/Abrevecyrillic": "\u04D0", + "/Abrevedotbelow": "\u1EB6", + "/Abrevegrave": "\u1EB0", + "/Abrevehoi": "\u1EB2", + "/Abrevehookabove": "\u1EB2", + "/Abrevetilde": "\u1EB4", + "/Acaron": "\u01CD", + "/Acircle": "\u24B6", + "/Acircleblack": "\u1F150", + "/Acircumflex": "\u00C2", + "/Acircumflexacute": "\u1EA4", + "/Acircumflexdotbelow": "\u1EAC", + "/Acircumflexgrave": "\u1EA6", + "/Acircumflexhoi": "\u1EA8", + "/Acircumflexhookabove": "\u1EA8", + "/Acircumflexsmall": "\uF7E2", + "/Acircumflextilde": "\u1EAA", + "/Acute": "\uF6C9", + "/Acutesmall": "\uF7B4", + "/Acyr": "\u0410", + "/Acyrillic": "\u0410", + "/Adblgrave": "\u0200", + "/Adieresis": "\u00C4", + "/Adieresiscyr": "\u04D2", + "/Adieresiscyrillic": "\u04D2", + "/Adieresismacron": "\u01DE", + "/Adieresissmall": "\uF7E4", + "/Adot": "\u0226", + "/Adotbelow": "\u1EA0", + "/Adotmacron": "\u01E0", + "/Agrave": "\u00C0", + "/Agravedbl": "\u0200", + "/Agravesmall": "\uF7E0", + "/Ahoi": "\u1EA2", + "/Ahookabove": "\u1EA2", + "/Aiecyr": "\u04D4", + "/Aiecyrillic": "\u04D4", + "/Ainvertedbreve": "\u0202", + "/Akbar": "\uFDF3", + "/Alayhe": "\uFDF7", + "/Allah": "\uFDF2", + "/Alpha": "\u0391", + "/Alphaacute": "\u1FBB", + "/Alphaasper": "\u1F09", + "/Alphaasperacute": "\u1F0D", + "/Alphaasperacuteiotasub": "\u1F8D", + "/Alphaaspergrave": "\u1F0B", + "/Alphaaspergraveiotasub": "\u1F8B", + "/Alphaasperiotasub": "\u1F89", + "/Alphaaspertilde": "\u1F0F", + "/Alphaaspertildeiotasub": "\u1F8F", + "/Alphabreve": "\u1FB8", + "/Alphagrave": "\u1FBA", + "/Alphaiotasub": "\u1FBC", + "/Alphalenis": "\u1F08", + "/Alphalenisacute": "\u1F0C", + "/Alphalenisacuteiotasub": "\u1F8C", + "/Alphalenisgrave": "\u1F0A", + "/Alphalenisgraveiotasub": "\u1F8A", + "/Alphalenisiotasub": "\u1F88", + "/Alphalenistilde": "\u1F0E", + "/Alphalenistildeiotasub": "\u1F8E", + "/Alphatonos": "\u0386", + "/Alphawithmacron": "\u1FB9", + "/Amacron": "\u0100", + "/Amonospace": "\uFF21", + "/Aogonek": "\u0104", + "/Aparens": "\u1F110", + "/Aring": "\u00C5", + "/Aringacute": "\u01FA", + "/Aringbelow": "\u1E00", + "/Aringsmall": "\uF7E5", + "/Asmall": "\uF761", + "/Asquare": "\u1F130", + "/Asquareblack": "\u1F170", + "/Astroke": "\u023A", + "/Atilde": "\u00C3", + "/Atildesmall": "\uF7E3", + "/Aturned": "\u2C6F", + "/Ayahend": "\u06DD", + "/Aybarmenian": "\u0531", + "/B": "\u0042", + "/Bcircle": "\u24B7", + "/Bcircleblack": "\u1F151", + "/Bdot": "\u1E02", + "/Bdotaccent": "\u1E02", + "/Bdotbelow": "\u1E04", + "/Becyr": "\u0411", + "/Becyrillic": "\u0411", + "/Benarmenian": "\u0532", + "/Beta": "\u0392", + "/Bflourish": "\uA796", + "/Bhook": "\u0181", + "/BismillahArRahmanArRaheem": "\uFDFD", + "/Blinebelow": "\u1E06", + "/Bmonospace": "\uFF22", + "/Bparens": "\u1F111", + "/Brevesmall": "\uF6F4", + "/Bscript": "\u212C", + "/Bsmall": "\uF762", + "/Bsquare": "\u1F131", + "/Bsquareblack": "\u1F171", + "/Bstroke": "\u0243", + "/Btopbar": "\u0182", + "/C": "\u0043", + "/CDcircle": "\u1F12D", + "/Caarmenian": "\u053E", + "/Cacute": "\u0106", + "/Caron": "\uF6CA", + "/Caronsmall": "\uF6F5", + "/Cbar": "\uA792", + "/Ccaron": "\u010C", + "/Ccedilla": "\u00C7", + "/Ccedillaacute": "\u1E08", + "/Ccedillasmall": "\uF7E7", + "/Ccircle": "\u24B8", + "/Ccircleblack": "\u1F152", + "/Ccircumflex": "\u0108", + "/Cdblstruck": "\u2102", + "/Cdot": "\u010A", + "/Cdotaccent": "\u010A", + "/Cdotreversed": "\uA73E", + "/Cedillasmall": "\uF7B8", + "/Cfraktur": "\u212D", + "/Chaarmenian": "\u0549", + "/Cheabkhasiancyrillic": "\u04BC", + "/Cheabkhcyr": "\u04BC", + "/Cheabkhtailcyr": "\u04BE", + "/Checyr": "\u0427", + "/Checyrillic": "\u0427", + "/Chedescenderabkhasiancyrillic": "\u04BE", + "/Chedescendercyrillic": "\u04B6", + "/Chedieresiscyr": "\u04F4", + "/Chedieresiscyrillic": "\u04F4", + "/Cheharmenian": "\u0543", + "/Chekhakascyr": "\u04CB", + "/Chekhakassiancyrillic": "\u04CB", + "/Chetailcyr": "\u04B6", + "/Chevertcyr": "\u04B8", + "/Cheverticalstrokecyrillic": "\u04B8", + "/Chi": "\u03A7", + "/Chook": "\u0187", + "/Circumflexsmall": "\uF6F6", + "/Citaliccircle": "\u1F12B", + "/Cmonospace": "\uFF23", + "/Coarmenian": "\u0551", + "/Con": "\uA76E", + "/Cparens": "\u1F112", + "/Csmall": "\uF763", + "/Csquare": "\u1F132", + "/Csquareblack": "\u1F172", + "/Cstretched": "\u0297", + "/Cstroke": "\u023B", + "/Cuatrillo": "\uA72C", + "/Cuatrillocomma": "\uA72E", + "/D": "\u0044", + "/DZ": "\u01F1", + "/DZcaron": "\u01C4", + "/Daarmenian": "\u0534", + "/Dafrican": "\u0189", + "/Dcaron": "\u010E", + "/Dcedilla": "\u1E10", + "/Dchecyr": "\u052C", + "/Dcircle": "\u24B9", + "/Dcircleblack": "\u1F153", + "/Dcircumflexbelow": "\u1E12", + "/Dcroat": "\u0110", + "/Ddblstruckitalic": "\u2145", + "/Ddot": "\u1E0A", + "/Ddotaccent": "\u1E0A", + "/Ddotbelow": "\u1E0C", + "/Decyr": "\u0414", + "/Decyrillic": "\u0414", + "/Deicoptic": "\u03EE", + "/Dekomicyr": "\u0500", + "/Delta": "\u2206", + "/Deltagreek": "\u0394", + "/Dhook": "\u018A", + "/Dieresis": "\uF6CB", + "/DieresisAcute": "\uF6CC", + "/DieresisGrave": "\uF6CD", + "/Dieresissmall": "\uF7A8", + "/Digamma": "\u03DC", + "/Digammagreek": "\u03DC", + "/Digammapamphylian": "\u0376", + "/Dinsular": "\uA779", + "/Djecyr": "\u0402", + "/Djecyrillic": "\u0402", + "/Djekomicyr": "\u0502", + "/Dlinebelow": "\u1E0E", + "/Dmonospace": "\uFF24", + "/Dotaccentsmall": "\uF6F7", + "/Dparens": "\u1F113", + "/Dslash": "\u0110", + "/Dsmall": "\uF764", + "/Dsquare": "\u1F133", + "/Dsquareblack": "\u1F173", + "/Dtopbar": "\u018B", + "/Dz": "\u01F2", + "/Dzcaron": "\u01C5", + "/Dzeabkhasiancyrillic": "\u04E0", + "/Dzeabkhcyr": "\u04E0", + "/Dzecyr": "\u0405", + "/Dzecyrillic": "\u0405", + "/Dzhecyr": "\u040F", + "/Dzhecyrillic": "\u040F", + "/Dzjekomicyr": "\u0506", + "/Dzzhecyr": "\u052A", + "/E": "\u0045", + "/Eacute": "\u00C9", + "/Eacutesmall": "\uF7E9", + "/Ebreve": "\u0114", + "/Ecaron": "\u011A", + "/Ecedilla": "\u0228", + "/Ecedillabreve": "\u1E1C", + "/Echarmenian": "\u0535", + "/Ecircle": "\u24BA", + "/Ecircleblack": "\u1F154", + "/Ecircumflex": "\u00CA", + "/Ecircumflexacute": "\u1EBE", + "/Ecircumflexbelow": "\u1E18", + "/Ecircumflexdotbelow": "\u1EC6", + "/Ecircumflexgrave": "\u1EC0", + "/Ecircumflexhoi": "\u1EC2", + "/Ecircumflexhookabove": "\u1EC2", + "/Ecircumflexsmall": "\uF7EA", + "/Ecircumflextilde": "\u1EC4", + "/Ecyrillic": "\u0404", + "/Edblgrave": "\u0204", + "/Edieresis": "\u00CB", + "/Edieresissmall": "\uF7EB", + "/Edot": "\u0116", + "/Edotaccent": "\u0116", + "/Edotbelow": "\u1EB8", + "/Efcyr": "\u0424", + "/Efcyrillic": "\u0424", + "/Egrave": "\u00C8", + "/Egravedbl": "\u0204", + "/Egravesmall": "\uF7E8", + "/Egyptain": "\uA724", + "/Egyptalef": "\uA722", + "/Eharmenian": "\u0537", + "/Ehoi": "\u1EBA", + "/Ehookabove": "\u1EBA", + "/Eightroman": "\u2167", + "/Einvertedbreve": "\u0206", + "/Eiotifiedcyr": "\u0464", + "/Eiotifiedcyrillic": "\u0464", + "/Elcyr": "\u041B", + "/Elcyrillic": "\u041B", + "/Elevenroman": "\u216A", + "/Elhookcyr": "\u0512", + "/Elmiddlehookcyr": "\u0520", + "/Elsharptailcyr": "\u04C5", + "/Eltailcyr": "\u052E", + "/Emacron": "\u0112", + "/Emacronacute": "\u1E16", + "/Emacrongrave": "\u1E14", + "/Emcyr": "\u041C", + "/Emcyrillic": "\u041C", + "/Emonospace": "\uFF25", + "/Emsharptailcyr": "\u04CD", + "/Encyr": "\u041D", + "/Encyrillic": "\u041D", + "/Endescendercyrillic": "\u04A2", + "/Eng": "\u014A", + "/Engecyr": "\u04A4", + "/Enghecyrillic": "\u04A4", + "/Enhookcyr": "\u04C7", + "/Enhookcyrillic": "\u04C7", + "/Enhookleftcyr": "\u0528", + "/Enmiddlehookcyr": "\u0522", + "/Ensharptailcyr": "\u04C9", + "/Entailcyr": "\u04A2", + "/Eogonek": "\u0118", + "/Eopen": "\u0190", + "/Eparens": "\u1F114", + "/Epsilon": "\u0395", + "/Epsilonacute": "\u1FC9", + "/Epsilonasper": "\u1F19", + "/Epsilonasperacute": "\u1F1D", + "/Epsilonaspergrave": "\u1F1B", + "/Epsilongrave": "\u1FC8", + "/Epsilonlenis": "\u1F18", + "/Epsilonlenisacute": "\u1F1C", + "/Epsilonlenisgrave": "\u1F1A", + "/Epsilontonos": "\u0388", + "/Ercyr": "\u0420", + "/Ercyrillic": "\u0420", + "/Ereversed": "\u018E", + "/Ereversedcyr": "\u042D", + "/Ereversedcyrillic": "\u042D", + "/Ereverseddieresiscyr": "\u04EC", + "/Ereversedopen": "\uA7AB", + "/Ertickcyr": "\u048E", + "/Escript": "\u2130", + "/Escyr": "\u0421", + "/Escyrillic": "\u0421", + "/Esdescendercyrillic": "\u04AA", + "/Esh": "\u01A9", + "/Esmall": "\uF765", + "/Esmallturned": "\u2C7B", + "/Esquare": "\u1F134", + "/Esquareblack": "\u1F174", + "/Estailcyr": "\u04AA", + "/Estroke": "\u0246", + "/Et": "\uA76A", + "/Eta": "\u0397", + "/Etaacute": "\u1FCB", + "/Etaasper": "\u1F29", + "/Etaasperacute": "\u1F2D", + "/Etaasperacuteiotasub": "\u1F9D", + "/Etaaspergrave": "\u1F2B", + "/Etaaspergraveiotasub": "\u1F9B", + "/Etaasperiotasub": "\u1F99", + "/Etaaspertilde": "\u1F2F", + "/Etaaspertildeiotasub": "\u1F9F", + "/Etagrave": "\u1FCA", + "/Etaiotasub": "\u1FCC", + "/Etalenis": "\u1F28", + "/Etalenisacute": "\u1F2C", + "/Etalenisacuteiotasub": "\u1F9C", + "/Etalenisgrave": "\u1F2A", + "/Etalenisgraveiotasub": "\u1F9A", + "/Etalenisiotasub": "\u1F98", + "/Etalenistilde": "\u1F2E", + "/Etalenistildeiotasub": "\u1F9E", + "/Etarmenian": "\u0538", + "/Etatonos": "\u0389", + "/Eth": "\u00D0", + "/Ethsmall": "\uF7F0", + "/Etilde": "\u1EBC", + "/Etildebelow": "\u1E1A", + "/Eukrcyr": "\u0404", + "/Euro": "\u20AC", + "/Ezh": "\u01B7", + "/Ezhcaron": "\u01EE", + "/Ezhreversed": "\u01B8", + "/F": "\u0046", + "/Fcircle": "\u24BB", + "/Fcircleblack": "\u1F155", + "/Fdot": "\u1E1E", + "/Fdotaccent": "\u1E1E", + "/Feharmenian": "\u0556", + "/Feicoptic": "\u03E4", + "/Fhook": "\u0191", + "/Finsular": "\uA77B", + "/Fitacyr": "\u0472", + "/Fitacyrillic": "\u0472", + "/Fiveroman": "\u2164", + "/Fmonospace": "\uFF26", + "/Fourroman": "\u2163", + "/Fparens": "\u1F115", + "/Fscript": "\u2131", + "/Fsmall": "\uF766", + "/Fsquare": "\u1F135", + "/Fsquareblack": "\u1F175", + "/Fstroke": "\uA798", + "/Fturned": "\u2132", + "/G": "\u0047", + "/GBsquare": "\u3387", + "/Gacute": "\u01F4", + "/Gamma": "\u0393", + "/Gammaafrican": "\u0194", + "/Gammadblstruck": "\u213E", + "/Gangiacoptic": "\u03EA", + "/Gbreve": "\u011E", + "/Gcaron": "\u01E6", + "/Gcedilla": "\u0122", + "/Gcircle": "\u24BC", + "/Gcircleblack": "\u1F156", + "/Gcircumflex": "\u011C", + "/Gcommaaccent": "\u0122", + "/Gdot": "\u0120", + "/Gdotaccent": "\u0120", + "/Gecyr": "\u0413", + "/Gecyrillic": "\u0413", + "/Gehookcyr": "\u0494", + "/Gehookstrokecyr": "\u04FA", + "/Germandbls": "\u1E9E", + "/Gestrokecyr": "\u0492", + "/Getailcyr": "\u04F6", + "/Geupcyr": "\u0490", + "/Ghadarmenian": "\u0542", + "/Ghemiddlehookcyrillic": "\u0494", + "/Ghestrokecyrillic": "\u0492", + "/Gheupturncyrillic": "\u0490", + "/Ghook": "\u0193", + "/Ghooksmall": "\u029B", + "/Gimarmenian": "\u0533", + "/Ginsular": "\uA77D", + "/Ginsularturned": "\uA77E", + "/Gjecyr": "\u0403", + "/Gjecyrillic": "\u0403", + "/Glottalstop": "\u0241", + "/Gmacron": "\u1E20", + "/Gmonospace": "\uFF27", + "/Gobliquestroke": "\uA7A0", + "/Gparens": "\u1F116", + "/Grave": "\uF6CE", + "/Gravesmall": "\uF760", + "/Gsmall": "\uF767", + "/Gsmallhook": "\u029B", + "/Gsquare": "\u1F136", + "/Gsquareblack": "\u1F176", + "/Gstroke": "\u01E4", + "/Gturnedsans": "\u2141", + "/H": "\u0048", + "/H18533": "\u25CF", + "/H18543": "\u25AA", + "/H18551": "\u25AB", + "/H22073": "\u25A1", + "/HPsquare": "\u33CB", + "/HVsquare": "\u1F14A", + "/Haabkhasiancyrillic": "\u04A8", + "/Haabkhcyr": "\u04A8", + "/Hacyr": "\u0425", + "/Hadescendercyrillic": "\u04B2", + "/Hahookcyr": "\u04FC", + "/Hardcyr": "\u042A", + "/Hardsigncyrillic": "\u042A", + "/Hastrokecyr": "\u04FE", + "/Hbar": "\u0126", + "/Hbrevebelow": "\u1E2A", + "/Hcaron": "\u021E", + "/Hcedilla": "\u1E28", + "/Hcircle": "\u24BD", + "/Hcircleblack": "\u1F157", + "/Hcircumflex": "\u0124", + "/Hdblstruck": "\u210D", + "/Hdescender": "\u2C67", + "/Hdieresis": "\u1E26", + "/Hdot": "\u1E22", + "/Hdotaccent": "\u1E22", + "/Hdotbelow": "\u1E24", + "/Heng": "\uA726", + "/Heta": "\u0370", + "/Hfraktur": "\u210C", + "/Hgfullwidth": "\u32CC", + "/Hhalf": "\u2C75", + "/Hhook": "\uA7AA", + "/Hmonospace": "\uFF28", + "/Hoarmenian": "\u0540", + "/HonAA": "\u0611", + "/HonRA": "\u0612", + "/HonSAW": "\u0610", + "/Horicoptic": "\u03E8", + "/Hparens": "\u1F117", + "/Hscript": "\u210B", + "/Hsmall": "\uF768", + "/Hsquare": "\u1F137", + "/Hsquareblack": "\u1F177", + "/Hstrokemod": "\uA7F8", + "/Hturned": "\uA78D", + "/Hungarumlaut": "\uF6CF", + "/Hungarumlautsmall": "\uF6F8", + "/Hwair": "\u01F6", + "/Hzsquare": "\u3390", + "/I": "\u0049", + "/IAcyrillic": "\u042F", + "/ICsquareblack": "\u1F18B", + "/IJ": "\u0132", + "/IUcyrillic": "\u042E", + "/Iacute": "\u00CD", + "/Iacutesmall": "\uF7ED", + "/Ibreve": "\u012C", + "/Icaron": "\u01CF", + "/Icircle": "\u24BE", + "/Icircleblack": "\u1F158", + "/Icircumflex": "\u00CE", + "/Icircumflexsmall": "\uF7EE", + "/Icyr": "\u0418", + "/Icyrillic": "\u0406", + "/Idblgrave": "\u0208", + "/Idieresis": "\u00CF", + "/Idieresisacute": "\u1E2E", + "/Idieresiscyr": "\u04E4", + "/Idieresiscyrillic": "\u04E4", + "/Idieresissmall": "\uF7EF", + "/Idot": "\u0130", + "/Idotaccent": "\u0130", + "/Idotbelow": "\u1ECA", + "/Iebrevecyr": "\u04D6", + "/Iebrevecyrillic": "\u04D6", + "/Iecyr": "\u0415", + "/Iecyrillic": "\u0415", + "/Iegravecyr": "\u0400", + "/Ifraktur": "\u2111", + "/Igrave": "\u00CC", + "/Igravecyr": "\u040D", + "/Igravedbl": "\u0208", + "/Igravesmall": "\uF7EC", + "/Ihoi": "\u1EC8", + "/Ihookabove": "\u1EC8", + "/Iicyrillic": "\u0418", + "/Iinvertedbreve": "\u020A", + "/Iishortcyrillic": "\u0419", + "/Imacron": "\u012A", + "/Imacroncyr": "\u04E2", + "/Imacroncyrillic": "\u04E2", + "/Imonospace": "\uFF29", + "/Iniarmenian": "\u053B", + "/Iocyr": "\u0401", + "/Iocyrillic": "\u0401", + "/Iogonek": "\u012E", + "/Iota": "\u0399", + "/Iotaacute": "\u1FDB", + "/Iotaafrican": "\u0196", + "/Iotaasper": "\u1F39", + "/Iotaasperacute": "\u1F3D", + "/Iotaaspergrave": "\u1F3B", + "/Iotaaspertilde": "\u1F3F", + "/Iotabreve": "\u1FD8", + "/Iotadieresis": "\u03AA", + "/Iotagrave": "\u1FDA", + "/Iotalenis": "\u1F38", + "/Iotalenisacute": "\u1F3C", + "/Iotalenisgrave": "\u1F3A", + "/Iotalenistilde": "\u1F3E", + "/Iotatonos": "\u038A", + "/Iotawithmacron": "\u1FD9", + "/Iparens": "\u1F118", + "/Is": "\uA76C", + "/Iscript": "\u2110", + "/Ishortcyr": "\u0419", + "/Ishortsharptailcyr": "\u048A", + "/Ismall": "\uF769", + "/Isquare": "\u1F138", + "/Isquareblack": "\u1F178", + "/Istroke": "\u0197", + "/Itilde": "\u0128", + "/Itildebelow": "\u1E2C", + "/Iukrcyr": "\u0406", + "/Izhitsacyr": "\u0474", + "/Izhitsacyrillic": "\u0474", + "/Izhitsadblgravecyrillic": "\u0476", + "/Izhitsagravedblcyr": "\u0476", + "/J": "\u004A", + "/Jaarmenian": "\u0541", + "/Jallajalalouhou": "\uFDFB", + "/Jcircle": "\u24BF", + "/Jcircleblack": "\u1F159", + "/Jcircumflex": "\u0134", + "/Jcrossed-tail": "\uA7B2", + "/Jecyr": "\u0408", + "/Jecyrillic": "\u0408", + "/Jheharmenian": "\u054B", + "/Jmonospace": "\uFF2A", + "/Jparens": "\u1F119", + "/Jsmall": "\uF76A", + "/Jsquare": "\u1F139", + "/Jsquareblack": "\u1F179", + "/Jstroke": "\u0248", + "/K": "\u004B", + "/KBsquare": "\u3385", + "/KKsquare": "\u33CD", + "/KORONIS": "\u1FBD", + "/Kaaleutcyr": "\u051E", + "/Kabashkcyr": "\u04A0", + "/Kabashkircyrillic": "\u04A0", + "/Kacute": "\u1E30", + "/Kacyr": "\u041A", + "/Kacyrillic": "\u041A", + "/Kadescendercyrillic": "\u049A", + "/Kahookcyr": "\u04C3", + "/Kahookcyrillic": "\u04C3", + "/Kaisymbol": "\u03CF", + "/Kappa": "\u039A", + "/Kastrokecyr": "\u049E", + "/Kastrokecyrillic": "\u049E", + "/Katailcyr": "\u049A", + "/Kaverticalstrokecyr": "\u049C", + "/Kaverticalstrokecyrillic": "\u049C", + "/Kcaron": "\u01E8", + "/Kcedilla": "\u0136", + "/Kcircle": "\u24C0", + "/Kcircleblack": "\u1F15A", + "/Kcommaaccent": "\u0136", + "/Kdescender": "\u2C69", + "/Kdiagonalstroke": "\uA742", + "/Kdotbelow": "\u1E32", + "/Keharmenian": "\u0554", + "/Kenarmenian": "\u053F", + "/Khacyrillic": "\u0425", + "/Kheicoptic": "\u03E6", + "/Khook": "\u0198", + "/Kjecyr": "\u040C", + "/Kjecyrillic": "\u040C", + "/Klinebelow": "\u1E34", + "/Kmonospace": "\uFF2B", + "/Kobliquestroke": "\uA7A2", + "/Koppa": "\u03DE", + "/Koppaarchaic": "\u03D8", + "/Koppacyr": "\u0480", + "/Koppacyrillic": "\u0480", + "/Koppagreek": "\u03DE", + "/Kparens": "\u1F11A", + "/Ksicyr": "\u046E", + "/Ksicyrillic": "\u046E", + "/Ksmall": "\uF76B", + "/Ksquare": "\u1F13A", + "/Ksquareblack": "\u1F17A", + "/Kstroke": "\uA740", + "/Kstrokediagonalstroke": "\uA744", + "/Kturned": "\uA7B0", + "/L": "\u004C", + "/LJ": "\u01C7", + "/LL": "\uF6BF", + "/LLwelsh": "\u1EFA", + "/LTDfullwidth": "\u32CF", + "/Lacute": "\u0139", + "/Lambda": "\u039B", + "/Lbar": "\u023D", + "/Lbelt": "\uA7AD", + "/Lbroken": "\uA746", + "/Lcaron": "\u013D", + "/Lcedilla": "\u013B", + "/Lcircle": "\u24C1", + "/Lcircleblack": "\u1F15B", + "/Lcircumflexbelow": "\u1E3C", + "/Lcommaaccent": "\u013B", + "/Ldblbar": "\u2C60", + "/Ldot": "\u013F", + "/Ldotaccent": "\u013F", + "/Ldotbelow": "\u1E36", + "/Ldotbelowmacron": "\u1E38", + "/Lhacyr": "\u0514", + "/Liwnarmenian": "\u053C", + "/Lj": "\u01C8", + "/Ljecyr": "\u0409", + "/Ljecyrillic": "\u0409", + "/Ljekomicyr": "\u0508", + "/Llinebelow": "\u1E3A", + "/Lmacrondot": "\u1E38", + "/Lmiddletilde": "\u2C62", + "/Lmonospace": "\uFF2C", + "/Lparens": "\u1F11B", + "/Lreversedsans": "\u2143", + "/Lscript": "\u2112", + "/Lslash": "\u0141", + "/Lslashsmall": "\uF6F9", + "/Lsmall": "\uF76C", + "/Lsquare": "\u1F13B", + "/Lsquareblack": "\u1F17B", + "/Lstroke": "\uA748", + "/Lturned": "\uA780", + "/Lturnedsans": "\u2142", + "/M": "\u004D", + "/MBsquare": "\u3386", + "/MVsquare": "\u1F14B", + "/Macron": "\uF6D0", + "/Macronsmall": "\uF7AF", + "/Macute": "\u1E3E", + "/Mcircle": "\u24C2", + "/Mcircleblack": "\u1F15C", + "/Mdot": "\u1E40", + "/Mdotaccent": "\u1E40", + "/Mdotbelow": "\u1E42", + "/Menarmenian": "\u0544", + "/Mhook": "\u2C6E", + "/Mmonospace": "\uFF2D", + "/Mohammad": "\uFDF4", + "/Mparens": "\u1F11C", + "/Mscript": "\u2133", + "/Msmall": "\uF76D", + "/Msquare": "\u1F13C", + "/Msquareblack": "\u1F17C", + "/Mturned": "\u019C", + "/Mturnedsmall": "\uA7FA", + "/Mu": "\u039C", + "/N": "\u004E", + "/NJ": "\u01CA", + "/Nacute": "\u0143", + "/Ncaron": "\u0147", + "/Ncedilla": "\u0145", + "/Ncircle": "\u24C3", + "/Ncircleblack": "\u1F15D", + "/Ncircumflexbelow": "\u1E4A", + "/Ncommaaccent": "\u0145", + "/Ndblstruck": "\u2115", + "/Ndescender": "\uA790", + "/Ndot": "\u1E44", + "/Ndotaccent": "\u1E44", + "/Ndotbelow": "\u1E46", + "/Ngrave": "\u01F8", + "/Nhookleft": "\u019D", + "/Nineroman": "\u2168", + "/Nj": "\u01CB", + "/Njecyr": "\u040A", + "/Njecyrillic": "\u040A", + "/Njekomicyr": "\u050A", + "/Nlinebelow": "\u1E48", + "/Nlongrightleg": "\u0220", + "/Nmonospace": "\uFF2E", + "/Nobliquestroke": "\uA7A4", + "/Nowarmenian": "\u0546", + "/Nparens": "\u1F11D", + "/Nsmall": "\uF76E", + "/Nsquare": "\u1F13D", + "/Nsquareblack": "\u1F17D", + "/Ntilde": "\u00D1", + "/Ntildesmall": "\uF7F1", + "/Nu": "\u039D", + "/O": "\u004F", + "/OE": "\u0152", + "/OEsmall": "\uF6FA", + "/OO": "\uA74E", + "/Oacute": "\u00D3", + "/Oacutesmall": "\uF7F3", + "/Obar": "\u019F", + "/Obarcyr": "\u04E8", + "/Obardieresiscyr": "\u04EA", + "/Obarredcyrillic": "\u04E8", + "/Obarreddieresiscyrillic": "\u04EA", + "/Obreve": "\u014E", + "/Ocaron": "\u01D1", + "/Ocenteredtilde": "\u019F", + "/Ocircle": "\u24C4", + "/Ocircleblack": "\u1F15E", + "/Ocircumflex": "\u00D4", + "/Ocircumflexacute": "\u1ED0", + "/Ocircumflexdotbelow": "\u1ED8", + "/Ocircumflexgrave": "\u1ED2", + "/Ocircumflexhoi": "\u1ED4", + "/Ocircumflexhookabove": "\u1ED4", + "/Ocircumflexsmall": "\uF7F4", + "/Ocircumflextilde": "\u1ED6", + "/Ocyr": "\u041E", + "/Ocyrillic": "\u041E", + "/Odblacute": "\u0150", + "/Odblgrave": "\u020C", + "/Odieresis": "\u00D6", + "/Odieresiscyr": "\u04E6", + "/Odieresiscyrillic": "\u04E6", + "/Odieresismacron": "\u022A", + "/Odieresissmall": "\uF7F6", + "/Odot": "\u022E", + "/Odotbelow": "\u1ECC", + "/Odotmacron": "\u0230", + "/Ogoneksmall": "\uF6FB", + "/Ograve": "\u00D2", + "/Ogravedbl": "\u020C", + "/Ogravesmall": "\uF7F2", + "/Oharmenian": "\u0555", + "/Ohm": "\u2126", + "/Ohoi": "\u1ECE", + "/Ohookabove": "\u1ECE", + "/Ohorn": "\u01A0", + "/Ohornacute": "\u1EDA", + "/Ohorndotbelow": "\u1EE2", + "/Ohorngrave": "\u1EDC", + "/Ohornhoi": "\u1EDE", + "/Ohornhookabove": "\u1EDE", + "/Ohorntilde": "\u1EE0", + "/Ohungarumlaut": "\u0150", + "/Oi": "\u01A2", + "/Oinvertedbreve": "\u020E", + "/Oloop": "\uA74C", + "/Omacron": "\u014C", + "/Omacronacute": "\u1E52", + "/Omacrongrave": "\u1E50", + "/Omega": "\u2126", + "/Omegaacute": "\u1FFB", + "/Omegaasper": "\u1F69", + "/Omegaasperacute": "\u1F6D", + "/Omegaasperacuteiotasub": "\u1FAD", + "/Omegaaspergrave": "\u1F6B", + "/Omegaaspergraveiotasub": "\u1FAB", + "/Omegaasperiotasub": "\u1FA9", + "/Omegaaspertilde": "\u1F6F", + "/Omegaaspertildeiotasub": "\u1FAF", + "/Omegacyr": "\u0460", + "/Omegacyrillic": "\u0460", + "/Omegagrave": "\u1FFA", + "/Omegagreek": "\u03A9", + "/Omegaiotasub": "\u1FFC", + "/Omegalenis": "\u1F68", + "/Omegalenisacute": "\u1F6C", + "/Omegalenisacuteiotasub": "\u1FAC", + "/Omegalenisgrave": "\u1F6A", + "/Omegalenisgraveiotasub": "\u1FAA", + "/Omegalenisiotasub": "\u1FA8", + "/Omegalenistilde": "\u1F6E", + "/Omegalenistildeiotasub": "\u1FAE", + "/Omegaroundcyr": "\u047A", + "/Omegaroundcyrillic": "\u047A", + "/Omegatitlocyr": "\u047C", + "/Omegatitlocyrillic": "\u047C", + "/Omegatonos": "\u038F", + "/Omicron": "\u039F", + "/Omicronacute": "\u1FF9", + "/Omicronasper": "\u1F49", + "/Omicronasperacute": "\u1F4D", + "/Omicronaspergrave": "\u1F4B", + "/Omicrongrave": "\u1FF8", + "/Omicronlenis": "\u1F48", + "/Omicronlenisacute": "\u1F4C", + "/Omicronlenisgrave": "\u1F4A", + "/Omicrontonos": "\u038C", + "/Omonospace": "\uFF2F", + "/Oneroman": "\u2160", + "/Oogonek": "\u01EA", + "/Oogonekmacron": "\u01EC", + "/Oopen": "\u0186", + "/Oparens": "\u1F11E", + "/Oslash": "\u00D8", + "/Oslashacute": "\u01FE", + "/Oslashsmall": "\uF7F8", + "/Osmall": "\uF76F", + "/Osquare": "\u1F13E", + "/Osquareblack": "\u1F17E", + "/Ostroke": "\uA74A", + "/Ostrokeacute": "\u01FE", + "/Otcyr": "\u047E", + "/Otcyrillic": "\u047E", + "/Otilde": "\u00D5", + "/Otildeacute": "\u1E4C", + "/Otildedieresis": "\u1E4E", + "/Otildemacron": "\u022C", + "/Otildesmall": "\uF7F5", + "/Ou": "\u0222", + "/P": "\u0050", + "/PAsquareblack": "\u1F18C", + "/PPVsquare": "\u1F14E", + "/Pacute": "\u1E54", + "/Palochkacyr": "\u04C0", + "/Pcircle": "\u24C5", + "/Pcircleblack": "\u1F15F", + "/Pcrosssquareblack": "\u1F18A", + "/Pdblstruck": "\u2119", + "/Pdot": "\u1E56", + "/Pdotaccent": "\u1E56", + "/Pecyr": "\u041F", + "/Pecyrillic": "\u041F", + "/Peharmenian": "\u054A", + "/Pehookcyr": "\u04A6", + "/Pemiddlehookcyrillic": "\u04A6", + "/Petailcyr": "\u0524", + "/Pflourish": "\uA752", + "/Phi": "\u03A6", + "/Phook": "\u01A4", + "/Pi": "\u03A0", + "/Pidblstruck": "\u213F", + "/Piwrarmenian": "\u0553", + "/Pmonospace": "\uFF30", + "/Pparens": "\u1F11F", + "/Psi": "\u03A8", + "/Psicyr": "\u0470", + "/Psicyrillic": "\u0470", + "/Psmall": "\uF770", + "/Psquare": "\u1F13F", + "/Psquareblack": "\u1F17F", + "/Pstroke": "\u2C63", + "/Pstrokedescender": "\uA750", + "/Ptail": "\uA754", + "/Q": "\u0051", + "/Qacyr": "\u051A", + "/QalaUsedAsKoranicStopSign": "\uFDF1", + "/Qcircle": "\u24C6", + "/Qcircleblack": "\u1F160", + "/Qdblstruck": "\u211A", + "/Qdiagonalstroke": "\uA758", + "/Qmonospace": "\uFF31", + "/Qparens": "\u1F120", + "/Qrotated": "\u213A", + "/Qsmall": "\uF771", + "/Qsmallhooktail": "\u024A", + "/Qsquare": "\u1F140", + "/Qsquareblack": "\u1F180", + "/Qstrokedescender": "\uA756", + "/R": "\u0052", + "/Raarmenian": "\u054C", + "/Racute": "\u0154", + "/Rasoul": "\uFDF6", + "/Rcaron": "\u0158", + "/Rcedilla": "\u0156", + "/Rcircle": "\u24C7", + "/Rcircleblack": "\u1F161", + "/Rcommaaccent": "\u0156", + "/Rdblgrave": "\u0210", + "/Rdblstruck": "\u211D", + "/Rdot": "\u1E58", + "/Rdotaccent": "\u1E58", + "/Rdotbelow": "\u1E5A", + "/Rdotbelowmacron": "\u1E5C", + "/Reharmenian": "\u0550", + "/Reverseddottedsigmalunatesymbol": "\u03FF", + "/Reversedzecyr": "\u0510", + "/Rfraktur": "\u211C", + "/Rgravedbl": "\u0210", + "/Rhacyr": "\u0516", + "/Rho": "\u03A1", + "/Rhoasper": "\u1FEC", + "/Ringsmall": "\uF6FC", + "/Rinsular": "\uA782", + "/Rinvertedbreve": "\u0212", + "/Rinvertedsmall": "\u0281", + "/Ritaliccircle": "\u1F12C", + "/Rlinebelow": "\u1E5E", + "/Rmacrondot": "\u1E5C", + "/Rmonospace": "\uFF32", + "/Robliquestroke": "\uA7A6", + "/Rparens": "\u1F121", + "/Rrotunda": "\uA75A", + "/Rscript": "\u211B", + "/Rsmall": "\uF772", + "/Rsmallinverted": "\u0281", + "/Rsmallinvertedsuperior": "\u02B6", + "/Rsquare": "\u1F141", + "/Rsquareblack": "\u1F181", + "/Rstroke": "\u024C", + "/Rsupinvertedmod": "\u02B6", + "/Rtail": "\u2C64", + "/RubElHizbstart": "\u06DE", + "/Rumrotunda": "\uA75C", + "/Rumsmall": "\uA776", + "/S": "\u0053", + "/SAsquareblack": "\u1F18D", + "/SDsquare": "\u1F14C", + "/SF010000": "\u250C", + "/SF020000": "\u2514", + "/SF030000": "\u2510", + "/SF040000": "\u2518", + "/SF050000": "\u253C", + "/SF060000": "\u252C", + "/SF070000": "\u2534", + "/SF080000": "\u251C", + "/SF090000": "\u2524", + "/SF100000": "\u2500", + "/SF110000": "\u2502", + "/SF190000": "\u2561", + "/SF200000": "\u2562", + "/SF210000": "\u2556", + "/SF220000": "\u2555", + "/SF230000": "\u2563", + "/SF240000": "\u2551", + "/SF250000": "\u2557", + "/SF260000": "\u255D", + "/SF270000": "\u255C", + "/SF280000": "\u255B", + "/SF360000": "\u255E", + "/SF370000": "\u255F", + "/SF380000": "\u255A", + "/SF390000": "\u2554", + "/SF400000": "\u2569", + "/SF410000": "\u2566", + "/SF420000": "\u2560", + "/SF430000": "\u2550", + "/SF440000": "\u256C", + "/SF450000": "\u2567", + "/SF460000": "\u2568", + "/SF470000": "\u2564", + "/SF480000": "\u2565", + "/SF490000": "\u2559", + "/SF500000": "\u2558", + "/SF510000": "\u2552", + "/SF520000": "\u2553", + "/SF530000": "\u256B", + "/SF540000": "\u256A", + "/SSsquare": "\u1F14D", + "/Sacute": "\u015A", + "/Sacutedotaccent": "\u1E64", + "/Safha": "\u0603", + "/Sajdah": "\u06E9", + "/Salam": "\uFDF5", + "/Salla": "\uFDF9", + "/SallaUsedAsKoranicStopSign": "\uFDF0", + "/SallallahouAlayheWasallam": "\uFDFA", + "/Saltillo": "\uA78B", + "/Sampi": "\u03E0", + "/Sampiarchaic": "\u0372", + "/Sampigreek": "\u03E0", + "/San": "\u03FA", + "/Sanah": "\u0601", + "/Scaron": "\u0160", + "/Scarondot": "\u1E66", + "/Scarondotaccent": "\u1E66", + "/Scaronsmall": "\uF6FD", + "/Scedilla": "\u015E", + "/Schwa": "\u018F", + "/Schwacyr": "\u04D8", + "/Schwacyrillic": "\u04D8", + "/Schwadieresiscyr": "\u04DA", + "/Schwadieresiscyrillic": "\u04DA", + "/Scircle": "\u24C8", + "/Scircleblack": "\u1F162", + "/Scircumflex": "\u015C", + "/Scommaaccent": "\u0218", + "/Scriptg": "\uA7AC", + "/Sdot": "\u1E60", + "/Sdotaccent": "\u1E60", + "/Sdotbelow": "\u1E62", + "/Sdotbelowdotabove": "\u1E68", + "/Sdotbelowdotaccent": "\u1E68", + "/Seharmenian": "\u054D", + "/Semisoftcyr": "\u048C", + "/Sevenroman": "\u2166", + "/Shaarmenian": "\u0547", + "/Shacyr": "\u0428", + "/Shacyrillic": "\u0428", + "/Shchacyr": "\u0429", + "/Shchacyrillic": "\u0429", + "/Sheicoptic": "\u03E2", + "/SheneGerishin:hb": "\u059E", + "/Shhacyr": "\u04BA", + "/Shhacyrillic": "\u04BA", + "/Shhatailcyr": "\u0526", + "/Shimacoptic": "\u03EC", + "/Sho": "\u03F7", + "/Sigma": "\u03A3", + "/Sigmalunatesymbol": "\u03F9", + "/Sigmalunatesymboldotted": "\u03FE", + "/Sigmareversedlunatesymbol": "\u03FD", + "/Sinsular": "\uA784", + "/Sixroman": "\u2165", + "/Sjekomicyr": "\u050C", + "/Smonospace": "\uFF33", + "/Sobliquestroke": "\uA7A8", + "/Softcyr": "\u042C", + "/Softsigncyrillic": "\u042C", + "/Sparens": "\u1F122", + "/Sshell": "\u1F12A", + "/Ssmall": "\uF773", + "/Ssquare": "\u1F142", + "/Ssquareblack": "\u1F182", + "/Sswashtail": "\u2C7E", + "/Stigma": "\u03DA", + "/Stigmagreek": "\u03DA", + "/T": "\u0054", + "/Tau": "\u03A4", + "/Tbar": "\u0166", + "/Tcaron": "\u0164", + "/Tcedilla": "\u0162", + "/Tcircle": "\u24C9", + "/Tcircleblack": "\u1F163", + "/Tcircumflexbelow": "\u1E70", + "/Tcommaaccent": "\u0162", + "/Tdot": "\u1E6A", + "/Tdotaccent": "\u1E6A", + "/Tdotbelow": "\u1E6C", + "/Tecyr": "\u0422", + "/Tecyrillic": "\u0422", + "/Tedescendercyrillic": "\u04AC", + "/Tenroman": "\u2169", + "/Tetailcyr": "\u04AC", + "/Tetsecyr": "\u04B4", + "/Tetsecyrillic": "\u04B4", + "/Theta": "\u0398", + "/Thetasymbol": "\u03F4", + "/Thook": "\u01AC", + "/Thorn": "\u00DE", + "/Thornsmall": "\uF7FE", + "/Thornstroke": "\uA764", + "/Thornstrokedescender": "\uA766", + "/Threeroman": "\u2162", + "/Tildesmall": "\uF6FE", + "/Tinsular": "\uA786", + "/Tiwnarmenian": "\u054F", + "/Tjekomicyr": "\u050E", + "/Tlinebelow": "\u1E6E", + "/Tmonospace": "\uFF34", + "/Toarmenian": "\u0539", + "/Tonefive": "\u01BC", + "/Tonesix": "\u0184", + "/Tonetwo": "\u01A7", + "/Tparens": "\u1F123", + "/Tresillo": "\uA72A", + "/Tretroflexhook": "\u01AE", + "/Tsecyr": "\u0426", + "/Tsecyrillic": "\u0426", + "/Tshecyr": "\u040B", + "/Tshecyrillic": "\u040B", + "/Tsmall": "\uF774", + "/Tsquare": "\u1F143", + "/Tsquareblack": "\u1F183", + "/Tturned": "\uA7B1", + "/Twelveroman": "\u216B", + "/Twithdiagonalstroke": "\u023E", + "/Tworoman": "\u2161", + "/Tz": "\uA728", + "/U": "\u0055", + "/Uacute": "\u00DA", + "/Uacutedblcyr": "\u04F2", + "/Uacutesmall": "\uF7FA", + "/Ubar": "\u0244", + "/Ubreve": "\u016C", + "/Ucaron": "\u01D3", + "/Ucircle": "\u24CA", + "/Ucircleblack": "\u1F164", + "/Ucircumflex": "\u00DB", + "/Ucircumflexbelow": "\u1E76", + "/Ucircumflexsmall": "\uF7FB", + "/Ucyr": "\u0423", + "/Ucyrillic": "\u0423", + "/Udblacute": "\u0170", + "/Udblgrave": "\u0214", + "/Udieresis": "\u00DC", + "/Udieresisacute": "\u01D7", + "/Udieresisbelow": "\u1E72", + "/Udieresiscaron": "\u01D9", + "/Udieresiscyr": "\u04F0", + "/Udieresiscyrillic": "\u04F0", + "/Udieresisgrave": "\u01DB", + "/Udieresismacron": "\u01D5", + "/Udieresissmall": "\uF7FC", + "/Udotbelow": "\u1EE4", + "/Ugrave": "\u00D9", + "/Ugravedbl": "\u0214", + "/Ugravesmall": "\uF7F9", + "/Uhoi": "\u1EE6", + "/Uhookabove": "\u1EE6", + "/Uhorn": "\u01AF", + "/Uhornacute": "\u1EE8", + "/Uhorndotbelow": "\u1EF0", + "/Uhorngrave": "\u1EEA", + "/Uhornhoi": "\u1EEC", + "/Uhornhookabove": "\u1EEC", + "/Uhorntilde": "\u1EEE", + "/Uhungarumlaut": "\u0170", + "/Uhungarumlautcyrillic": "\u04F2", + "/Uinvertedbreve": "\u0216", + "/Ukcyr": "\u0478", + "/Ukcyrillic": "\u0478", + "/Umacron": "\u016A", + "/Umacroncyr": "\u04EE", + "/Umacroncyrillic": "\u04EE", + "/Umacrondieresis": "\u1E7A", + "/Umonospace": "\uFF35", + "/Uogonek": "\u0172", + "/Uparens": "\u1F124", + "/Upsilon": "\u03A5", + "/Upsilon1": "\u03D2", + "/Upsilonacute": "\u1FEB", + "/Upsilonacutehooksymbol": "\u03D3", + "/Upsilonacutehooksymbolgreek": "\u03D3", + "/Upsilonadieresishooksymbol": "\u03D4", + "/Upsilonafrican": "\u01B1", + "/Upsilonasper": "\u1F59", + "/Upsilonasperacute": "\u1F5D", + "/Upsilonaspergrave": "\u1F5B", + "/Upsilonaspertilde": "\u1F5F", + "/Upsilonbreve": "\u1FE8", + "/Upsilondieresis": "\u03AB", + "/Upsilondieresishooksymbolgreek": "\u03D4", + "/Upsilongrave": "\u1FEA", + "/Upsilonhooksymbol": "\u03D2", + "/Upsilontonos": "\u038E", + "/Upsilonwithmacron": "\u1FE9", + "/Uring": "\u016E", + "/Ushortcyr": "\u040E", + "/Ushortcyrillic": "\u040E", + "/Usmall": "\uF775", + "/Usquare": "\u1F144", + "/Usquareblack": "\u1F184", + "/Ustraightcyr": "\u04AE", + "/Ustraightcyrillic": "\u04AE", + "/Ustraightstrokecyr": "\u04B0", + "/Ustraightstrokecyrillic": "\u04B0", + "/Utilde": "\u0168", + "/Utildeacute": "\u1E78", + "/Utildebelow": "\u1E74", + "/V": "\u0056", + "/Vcircle": "\u24CB", + "/Vcircleblack": "\u1F165", + "/Vdiagonalstroke": "\uA75E", + "/Vdotbelow": "\u1E7E", + "/Vecyr": "\u0412", + "/Vecyrillic": "\u0412", + "/Vend": "\uA768", + "/Vewarmenian": "\u054E", + "/Vhook": "\u01B2", + "/Visigothicz": "\uA762", + "/Vmod": "\u2C7D", + "/Vmonospace": "\uFF36", + "/Voarmenian": "\u0548", + "/Volapukae": "\uA79A", + "/Volapukoe": "\uA79C", + "/Volapukue": "\uA79E", + "/Vparens": "\u1F125", + "/Vsmall": "\uF776", + "/Vsquare": "\u1F145", + "/Vsquareblack": "\u1F185", + "/Vtilde": "\u1E7C", + "/Vturned": "\u0245", + "/Vwelsh": "\u1EFC", + "/Vy": "\uA760", + "/W": "\u0057", + "/WZcircle": "\u1F12E", + "/Wacute": "\u1E82", + "/Wasallam": "\uFDF8", + "/Wcircle": "\u24CC", + "/Wcircleblack": "\u1F166", + "/Wcircumflex": "\u0174", + "/Wdieresis": "\u1E84", + "/Wdot": "\u1E86", + "/Wdotaccent": "\u1E86", + "/Wdotbelow": "\u1E88", + "/Wecyr": "\u051C", + "/Wgrave": "\u1E80", + "/Whook": "\u2C72", + "/Wmonospace": "\uFF37", + "/Wparens": "\u1F126", + "/Wsmall": "\uF777", + "/Wsquare": "\u1F146", + "/Wsquareblack": "\u1F186", + "/Wynn": "\u01F7", + "/X": "\u0058", + "/Xatailcyr": "\u04B2", + "/Xcircle": "\u24CD", + "/Xcircleblack": "\u1F167", + "/Xdieresis": "\u1E8C", + "/Xdot": "\u1E8A", + "/Xdotaccent": "\u1E8A", + "/Xeharmenian": "\u053D", + "/Xi": "\u039E", + "/Xmonospace": "\uFF38", + "/Xparens": "\u1F127", + "/Xsmall": "\uF778", + "/Xsquare": "\u1F147", + "/Xsquareblack": "\u1F187", + "/Y": "\u0059", + "/Yacute": "\u00DD", + "/Yacutesmall": "\uF7FD", + "/Yacyr": "\u042F", + "/Yaecyr": "\u0518", + "/Yatcyr": "\u0462", + "/Yatcyrillic": "\u0462", + "/Ycircle": "\u24CE", + "/Ycircleblack": "\u1F168", + "/Ycircumflex": "\u0176", + "/Ydieresis": "\u0178", + "/Ydieresissmall": "\uF7FF", + "/Ydot": "\u1E8E", + "/Ydotaccent": "\u1E8E", + "/Ydotbelow": "\u1EF4", + "/Yericyrillic": "\u042B", + "/Yerudieresiscyrillic": "\u04F8", + "/Ygrave": "\u1EF2", + "/Yhoi": "\u1EF6", + "/Yhook": "\u01B3", + "/Yhookabove": "\u1EF6", + "/Yiarmenian": "\u0545", + "/Yicyrillic": "\u0407", + "/Yiwnarmenian": "\u0552", + "/Ylongcyr": "\u042B", + "/Ylongdieresiscyr": "\u04F8", + "/Yloop": "\u1EFE", + "/Ymacron": "\u0232", + "/Ymonospace": "\uFF39", + "/Yogh": "\u021C", + "/Yot": "\u037F", + "/Yparens": "\u1F128", + "/Ysmall": "\uF779", + "/Ysquare": "\u1F148", + "/Ysquareblack": "\u1F188", + "/Ystroke": "\u024E", + "/Ytilde": "\u1EF8", + "/Yturnedsans": "\u2144", + "/Yucyr": "\u042E", + "/Yukrcyr": "\u0407", + "/Yusbigcyr": "\u046A", + "/Yusbigcyrillic": "\u046A", + "/Yusbigiotifiedcyr": "\u046C", + "/Yusbigiotifiedcyrillic": "\u046C", + "/Yuslittlecyr": "\u0466", + "/Yuslittlecyrillic": "\u0466", + "/Yuslittleiotifiedcyr": "\u0468", + "/Yuslittleiotifiedcyrillic": "\u0468", + "/Z": "\u005A", + "/Zaarmenian": "\u0536", + "/Zacute": "\u0179", + "/Zcaron": "\u017D", + "/Zcaronsmall": "\uF6FF", + "/Zcircle": "\u24CF", + "/Zcircleblack": "\u1F169", + "/Zcircumflex": "\u1E90", + "/Zdblstruck": "\u2124", + "/Zdescender": "\u2C6B", + "/Zdot": "\u017B", + "/Zdotaccent": "\u017B", + "/Zdotbelow": "\u1E92", + "/Zecyr": "\u0417", + "/Zecyrillic": "\u0417", + "/Zedescendercyrillic": "\u0498", + "/Zedieresiscyr": "\u04DE", + "/Zedieresiscyrillic": "\u04DE", + "/Zeta": "\u0396", + "/Zetailcyr": "\u0498", + "/Zfraktur": "\u2128", + "/Zhearmenian": "\u053A", + "/Zhebrevecyr": "\u04C1", + "/Zhebrevecyrillic": "\u04C1", + "/Zhecyr": "\u0416", + "/Zhecyrillic": "\u0416", + "/Zhedescendercyrillic": "\u0496", + "/Zhedieresiscyr": "\u04DC", + "/Zhedieresiscyrillic": "\u04DC", + "/Zhetailcyr": "\u0496", + "/Zhook": "\u0224", + "/Zjekomicyr": "\u0504", + "/Zlinebelow": "\u1E94", + "/Zmonospace": "\uFF3A", + "/Zparens": "\u1F129", + "/Zsmall": "\uF77A", + "/Zsquare": "\u1F149", + "/Zsquareblack": "\u1F189", + "/Zstroke": "\u01B5", + "/Zswashtail": "\u2C7F", + "/a": "\u0061", + "/a.inferior": "\u2090", + "/aHonRAA": "\u0613", + "/aa": "\uA733", + "/aabengali": "\u0986", + "/aacute": "\u00E1", + "/aadeva": "\u0906", + "/aagujarati": "\u0A86", + "/aagurmukhi": "\u0A06", + "/aamatragurmukhi": "\u0A3E", + "/aarusquare": "\u3303", + "/aavowelsignbengali": "\u09BE", + "/aavowelsigndeva": "\u093E", + "/aavowelsigngujarati": "\u0ABE", + "/abbreviationmarkarmenian": "\u055F", + "/abbreviationsigndeva": "\u0970", + "/abengali": "\u0985", + "/abopomofo": "\u311A", + "/abreve": "\u0103", + "/abreveacute": "\u1EAF", + "/abrevecyr": "\u04D1", + "/abrevecyrillic": "\u04D1", + "/abrevedotbelow": "\u1EB7", + "/abrevegrave": "\u1EB1", + "/abrevehoi": "\u1EB3", + "/abrevehookabove": "\u1EB3", + "/abrevetilde": "\u1EB5", + "/absquareblack": "\u1F18E", + "/acaron": "\u01CE", + "/accountof": "\u2100", + "/accurrent": "\u23E6", + "/acircle": "\u24D0", + "/acirclekatakana": "\u32D0", + "/acircumflex": "\u00E2", + "/acircumflexacute": "\u1EA5", + "/acircumflexdotbelow": "\u1EAD", + "/acircumflexgrave": "\u1EA7", + "/acircumflexhoi": "\u1EA9", + "/acircumflexhookabove": "\u1EA9", + "/acircumflextilde": "\u1EAB", + "/activatearabicformshaping": "\u206D", + "/activatesymmetricswapping": "\u206B", + "/acute": "\u00B4", + "/acutebelowcmb": "\u0317", + "/acutecmb": "\u0301", + "/acutecomb": "\u0301", + "/acutedblmiddlemod": "\u02F6", + "/acutedeva": "\u0954", + "/acutelowmod": "\u02CF", + "/acutemod": "\u02CA", + "/acutetonecmb": "\u0341", + "/acyr": "\u0430", + "/acyrillic": "\u0430", + "/adblgrave": "\u0201", + "/addakgurmukhi": "\u0A71", + "/addressedsubject": "\u2101", + "/adegadegpada": "\uA9CB", + "/adegpada": "\uA9CA", + "/adeva": "\u0905", + "/adieresis": "\u00E4", + "/adieresiscyr": "\u04D3", + "/adieresiscyrillic": "\u04D3", + "/adieresismacron": "\u01DF", + "/adishakti": "\u262C", + "/admissionTickets": "\u1F39F", + "/adot": "\u0227", + "/adotbelow": "\u1EA1", + "/adotmacron": "\u01E1", + "/ae": "\u00E6", + "/aeacute": "\u01FD", + "/aekorean": "\u3150", + "/aemacron": "\u01E3", + "/aerialTramway": "\u1F6A1", + "/afghani": "\u060B", + "/afii00208": "\u2015", + "/afii08941": "\u20A4", + "/afii10017": "\u0410", + "/afii10018": "\u0411", + "/afii10019": "\u0412", + "/afii10020": "\u0413", + "/afii10021": "\u0414", + "/afii10022": "\u0415", + "/afii10023": "\u0401", + "/afii10024": "\u0416", + "/afii10025": "\u0417", + "/afii10026": "\u0418", + "/afii10027": "\u0419", + "/afii10028": "\u041A", + "/afii10029": "\u041B", + "/afii10030": "\u041C", + "/afii10031": "\u041D", + "/afii10032": "\u041E", + "/afii10033": "\u041F", + "/afii10034": "\u0420", + "/afii10035": "\u0421", + "/afii10036": "\u0422", + "/afii10037": "\u0423", + "/afii10038": "\u0424", + "/afii10039": "\u0425", + "/afii10040": "\u0426", + "/afii10041": "\u0427", + "/afii10042": "\u0428", + "/afii10043": "\u0429", + "/afii10044": "\u042A", + "/afii10045": "\u042B", + "/afii10046": "\u042C", + "/afii10047": "\u042D", + "/afii10048": "\u042E", + "/afii10049": "\u042F", + "/afii10050": "\u0490", + "/afii10051": "\u0402", + "/afii10052": "\u0403", + "/afii10053": "\u0404", + "/afii10054": "\u0405", + "/afii10055": "\u0406", + "/afii10056": "\u0407", + "/afii10057": "\u0408", + "/afii10058": "\u0409", + "/afii10059": "\u040A", + "/afii10060": "\u040B", + "/afii10061": "\u040C", + "/afii10062": "\u040E", + "/afii10063": "\uF6C4", + "/afii10064": "\uF6C5", + "/afii10065": "\u0430", + "/afii10066": "\u0431", + "/afii10067": "\u0432", + "/afii10068": "\u0433", + "/afii10069": "\u0434", + "/afii10070": "\u0435", + "/afii10071": "\u0451", + "/afii10072": "\u0436", + "/afii10073": "\u0437", + "/afii10074": "\u0438", + "/afii10075": "\u0439", + "/afii10076": "\u043A", + "/afii10077": "\u043B", + "/afii10078": "\u043C", + "/afii10079": "\u043D", + "/afii10080": "\u043E", + "/afii10081": "\u043F", + "/afii10082": "\u0440", + "/afii10083": "\u0441", + "/afii10084": "\u0442", + "/afii10085": "\u0443", + "/afii10086": "\u0444", + "/afii10087": "\u0445", + "/afii10088": "\u0446", + "/afii10089": "\u0447", + "/afii10090": "\u0448", + "/afii10091": "\u0449", + "/afii10092": "\u044A", + "/afii10093": "\u044B", + "/afii10094": "\u044C", + "/afii10095": "\u044D", + "/afii10096": "\u044E", + "/afii10097": "\u044F", + "/afii10098": "\u0491", + "/afii10099": "\u0452", + "/afii10100": "\u0453", + "/afii10101": "\u0454", + "/afii10102": "\u0455", + "/afii10103": "\u0456", + "/afii10104": "\u0457", + "/afii10105": "\u0458", + "/afii10106": "\u0459", + "/afii10107": "\u045A", + "/afii10108": "\u045B", + "/afii10109": "\u045C", + "/afii10110": "\u045E", + "/afii10145": "\u040F", + "/afii10146": "\u0462", + "/afii10147": "\u0472", + "/afii10148": "\u0474", + "/afii10192": "\uF6C6", + "/afii10193": "\u045F", + "/afii10194": "\u0463", + "/afii10195": "\u0473", + "/afii10196": "\u0475", + "/afii10831": "\uF6C7", + "/afii10832": "\uF6C8", + "/afii10846": "\u04D9", + "/afii299": "\u200E", + "/afii300": "\u200F", + "/afii301": "\u200D", + "/afii57381": "\u066A", + "/afii57388": "\u060C", + "/afii57392": "\u0660", + "/afii57393": "\u0661", + "/afii57394": "\u0662", + "/afii57395": "\u0663", + "/afii57396": "\u0664", + "/afii57397": "\u0665", + "/afii57398": "\u0666", + "/afii57399": "\u0667", + "/afii57400": "\u0668", + "/afii57401": "\u0669", + "/afii57403": "\u061B", + "/afii57407": "\u061F", + "/afii57409": "\u0621", + "/afii57410": "\u0622", + "/afii57411": "\u0623", + "/afii57412": "\u0624", + "/afii57413": "\u0625", + "/afii57414": "\u0626", + "/afii57415": "\u0627", + "/afii57416": "\u0628", + "/afii57417": "\u0629", + "/afii57418": "\u062A", + "/afii57419": "\u062B", + "/afii57420": "\u062C", + "/afii57421": "\u062D", + "/afii57422": "\u062E", + "/afii57423": "\u062F", + "/afii57424": "\u0630", + "/afii57425": "\u0631", + "/afii57426": "\u0632", + "/afii57427": "\u0633", + "/afii57428": "\u0634", + "/afii57429": "\u0635", + "/afii57430": "\u0636", + "/afii57431": "\u0637", + "/afii57432": "\u0638", + "/afii57433": "\u0639", + "/afii57434": "\u063A", + "/afii57440": "\u0640", + "/afii57441": "\u0641", + "/afii57442": "\u0642", + "/afii57443": "\u0643", + "/afii57444": "\u0644", + "/afii57445": "\u0645", + "/afii57446": "\u0646", + "/afii57448": "\u0648", + "/afii57449": "\u0649", + "/afii57450": "\u064A", + "/afii57451": "\u064B", + "/afii57452": "\u064C", + "/afii57453": "\u064D", + "/afii57454": "\u064E", + "/afii57455": "\u064F", + "/afii57456": "\u0650", + "/afii57457": "\u0651", + "/afii57458": "\u0652", + "/afii57470": "\u0647", + "/afii57505": "\u06A4", + "/afii57506": "\u067E", + "/afii57507": "\u0686", + "/afii57508": "\u0698", + "/afii57509": "\u06AF", + "/afii57511": "\u0679", + "/afii57512": "\u0688", + "/afii57513": "\u0691", + "/afii57514": "\u06BA", + "/afii57519": "\u06D2", + "/afii57534": "\u06D5", + "/afii57636": "\u20AA", + "/afii57645": "\u05BE", + "/afii57658": "\u05C3", + "/afii57664": "\u05D0", + "/afii57665": "\u05D1", + "/afii57666": "\u05D2", + "/afii57667": "\u05D3", + "/afii57668": "\u05D4", + "/afii57669": "\u05D5", + "/afii57670": "\u05D6", + "/afii57671": "\u05D7", + "/afii57672": "\u05D8", + "/afii57673": "\u05D9", + "/afii57674": "\u05DA", + "/afii57675": "\u05DB", + "/afii57676": "\u05DC", + "/afii57677": "\u05DD", + "/afii57678": "\u05DE", + "/afii57679": "\u05DF", + "/afii57680": "\u05E0", + "/afii57681": "\u05E1", + "/afii57682": "\u05E2", + "/afii57683": "\u05E3", + "/afii57684": "\u05E4", + "/afii57685": "\u05E5", + "/afii57686": "\u05E6", + "/afii57687": "\u05E7", + "/afii57688": "\u05E8", + "/afii57689": "\u05E9", + "/afii57690": "\u05EA", + "/afii57694": "\uFB2A", + "/afii57695": "\uFB2B", + "/afii57700": "\uFB4B", + "/afii57705": "\uFB1F", + "/afii57716": "\u05F0", + "/afii57717": "\u05F1", + "/afii57718": "\u05F2", + "/afii57723": "\uFB35", + "/afii57793": "\u05B4", + "/afii57794": "\u05B5", + "/afii57795": "\u05B6", + "/afii57796": "\u05BB", + "/afii57797": "\u05B8", + "/afii57798": "\u05B7", + "/afii57799": "\u05B0", + "/afii57800": "\u05B2", + "/afii57801": "\u05B1", + "/afii57802": "\u05B3", + "/afii57803": "\u05C2", + "/afii57804": "\u05C1", + "/afii57806": "\u05B9", + "/afii57807": "\u05BC", + "/afii57839": "\u05BD", + "/afii57841": "\u05BF", + "/afii57842": "\u05C0", + "/afii57929": "\u02BC", + "/afii61248": "\u2105", + "/afii61289": "\u2113", + "/afii61352": "\u2116", + "/afii61573": "\u202C", + "/afii61574": "\u202D", + "/afii61575": "\u202E", + "/afii61664": "\u200C", + "/afii63167": "\u066D", + "/afii64937": "\u02BD", + "/agrave": "\u00E0", + "/agravedbl": "\u0201", + "/agujarati": "\u0A85", + "/agurmukhi": "\u0A05", + "/ahiragana": "\u3042", + "/ahoi": "\u1EA3", + "/ahookabove": "\u1EA3", + "/aibengali": "\u0990", + "/aibopomofo": "\u311E", + "/aideva": "\u0910", + "/aiecyr": "\u04D5", + "/aiecyrillic": "\u04D5", + "/aigujarati": "\u0A90", + "/aigurmukhi": "\u0A10", + "/aimatragurmukhi": "\u0A48", + "/ain.fina": "\uFECA", + "/ain.init": "\uFECB", + "/ain.init_alefmaksura.fina": "\uFCF7", + "/ain.init_jeem.fina": "\uFC29", + "/ain.init_jeem.medi": "\uFCBA", + "/ain.init_jeem.medi_meem.medi": "\uFDC4", + "/ain.init_meem.fina": "\uFC2A", + "/ain.init_meem.medi": "\uFCBB", + "/ain.init_meem.medi_meem.medi": "\uFD77", + "/ain.init_yeh.fina": "\uFCF8", + "/ain.isol": "\uFEC9", + "/ain.medi": "\uFECC", + "/ain.medi_alefmaksura.fina": "\uFD13", + "/ain.medi_jeem.medi_meem.fina": "\uFD75", + "/ain.medi_meem.medi_alefmaksura.fina": "\uFD78", + "/ain.medi_meem.medi_meem.fina": "\uFD76", + "/ain.medi_meem.medi_yeh.fina": "\uFDB6", + "/ain.medi_yeh.fina": "\uFD14", + "/ainThreeDotsDownAbove": "\u075E", + "/ainTwoDotsAbove": "\u075D", + "/ainTwoDotsVerticallyAbove": "\u075F", + "/ainarabic": "\u0639", + "/ainfinalarabic": "\uFECA", + "/aininitialarabic": "\uFECB", + "/ainmedialarabic": "\uFECC", + "/ainthreedotsabove": "\u06A0", + "/ainvertedbreve": "\u0203", + "/airplaneArriving": "\u1F6EC", + "/airplaneDeparture": "\u1F6EB", + "/aivowelsignbengali": "\u09C8", + "/aivowelsigndeva": "\u0948", + "/aivowelsigngujarati": "\u0AC8", + "/akatakana": "\u30A2", + "/akatakanahalfwidth": "\uFF71", + "/akorean": "\u314F", + "/aktieselskab": "\u214D", + "/alarmclock": "\u23F0", + "/alef": "\u05D0", + "/alef.fina": "\uFE8E", + "/alef.init_fathatan.fina": "\uFD3D", + "/alef.isol": "\uFE8D", + "/alef.medi_fathatan.fina": "\uFD3C", + "/alef:hb": "\u05D0", + "/alefDigitThreeAbove": "\u0774", + "/alefDigitTwoAbove": "\u0773", + "/alefLamYehabove": "\u0616", + "/alefabove": "\u0670", + "/alefarabic": "\u0627", + "/alefdageshhebrew": "\uFB30", + "/aleffinalarabic": "\uFE8E", + "/alefhamza": "\u0623", + "/alefhamza.fina": "\uFE84", + "/alefhamza.isol": "\uFE83", + "/alefhamzaabovearabic": "\u0623", + "/alefhamzaabovefinalarabic": "\uFE84", + "/alefhamzabelow": "\u0625", + "/alefhamzabelow.fina": "\uFE88", + "/alefhamzabelow.isol": "\uFE87", + "/alefhamzabelowarabic": "\u0625", + "/alefhamzabelowfinalarabic": "\uFE88", + "/alefhebrew": "\u05D0", + "/alefhighhamza": "\u0675", + "/aleflamedhebrew": "\uFB4F", + "/alefmadda": "\u0622", + "/alefmadda.fina": "\uFE82", + "/alefmadda.isol": "\uFE81", + "/alefmaddaabovearabic": "\u0622", + "/alefmaddaabovefinalarabic": "\uFE82", + "/alefmaksura": "\u0649", + "/alefmaksura.fina": "\uFEF0", + "/alefmaksura.init_superscriptalef.fina": "\uFC5D", + "/alefmaksura.isol": "\uFEEF", + "/alefmaksura.medi_superscriptalef.fina": "\uFC90", + "/alefmaksuraarabic": "\u0649", + "/alefmaksurafinalarabic": "\uFEF0", + "/alefmaksurainitialarabic": "\uFEF3", + "/alefmaksuramedialarabic": "\uFEF4", + "/alefpatahhebrew": "\uFB2E", + "/alefqamatshebrew": "\uFB2F", + "/alefwasla": "\u0671", + "/alefwasla.fina": "\uFB51", + "/alefwasla.isol": "\uFB50", + "/alefwavyhamza": "\u0672", + "/alefwavyhamzabelow": "\u0673", + "/alefwide:hb": "\uFB21", + "/alefwithmapiq:hb": "\uFB30", + "/alefwithpatah:hb": "\uFB2E", + "/alefwithqamats:hb": "\uFB2F", + "/alembic": "\u2697", + "/aleph": "\u2135", + "/alienMonster": "\u1F47E", + "/allaroundprofile": "\u232E", + "/allequal": "\u224C", + "/allianceideographiccircled": "\u32AF", + "/allianceideographicparen": "\u323F", + "/almostequalorequal": "\u224A", + "/alpha": "\u03B1", + "/alphaacute": "\u1F71", + "/alphaacuteiotasub": "\u1FB4", + "/alphaasper": "\u1F01", + "/alphaasperacute": "\u1F05", + "/alphaasperacuteiotasub": "\u1F85", + "/alphaaspergrave": "\u1F03", + "/alphaaspergraveiotasub": "\u1F83", + "/alphaasperiotasub": "\u1F81", + "/alphaaspertilde": "\u1F07", + "/alphaaspertildeiotasub": "\u1F87", + "/alphabreve": "\u1FB0", + "/alphafunc": "\u237A", + "/alphagrave": "\u1F70", + "/alphagraveiotasub": "\u1FB2", + "/alphaiotasub": "\u1FB3", + "/alphalenis": "\u1F00", + "/alphalenisacute": "\u1F04", + "/alphalenisacuteiotasub": "\u1F84", + "/alphalenisgrave": "\u1F02", + "/alphalenisgraveiotasub": "\u1F82", + "/alphalenisiotasub": "\u1F80", + "/alphalenistilde": "\u1F06", + "/alphalenistildeiotasub": "\u1F86", + "/alphatilde": "\u1FB6", + "/alphatildeiotasub": "\u1FB7", + "/alphatonos": "\u03AC", + "/alphaturned": "\u0252", + "/alphaunderlinefunc": "\u2376", + "/alphawithmacron": "\u1FB1", + "/alternateonewayleftwaytraffic": "\u26D5", + "/alternative": "\u2387", + "/amacron": "\u0101", + "/ambulance": "\u1F691", + "/americanFootball": "\u1F3C8", + "/amfullwidth": "\u33C2", + "/amonospace": "\uFF41", + "/amountofcheck": "\u2447", + "/ampersand": "\u0026", + "/ampersandSindhi": "\u06FD", + "/ampersandmonospace": "\uFF06", + "/ampersandsmall": "\uF726", + "/ampersandturned": "\u214B", + "/amphora": "\u1F3FA", + "/amsquare": "\u33C2", + "/anbopomofo": "\u3122", + "/anchor": "\u2693", + "/ancoradown": "\u2E14", + "/ancoraup": "\u2E15", + "/andappada": "\uA9C3", + "/angbopomofo": "\u3124", + "/anger": "\u1F4A2", + "/angkhankhuthai": "\u0E5A", + "/angle": "\u2220", + "/anglearcright": "\u22BE", + "/anglebracketleft": "\u3008", + "/anglebracketleftvertical": "\uFE3F", + "/anglebracketright": "\u3009", + "/anglebracketrightvertical": "\uFE40", + "/angledottedright": "\u2E16", + "/angleleft": "\u2329", + "/anglemarkerdottedsubstitutionright": "\u2E01", + "/anglemarkersubstitutionright": "\u2E00", + "/angleright": "\u232A", + "/anglezigzagarrowdownright": "\u237C", + "/angryFace": "\u1F620", + "/angstrom": "\u212B", + "/anguishedFace": "\u1F627", + "/ankh": "\u2625", + "/anoteleia": "\u0387", + "/anpeasquare": "\u3302", + "/ant": "\u1F41C", + "/antennaBars": "\u1F4F6", + "/anticlockwiseDownwardsAndUpwardsOpenCircleArrows": "\u1F504", + "/anudattadeva": "\u0952", + "/anusvarabengali": "\u0982", + "/anusvaradeva": "\u0902", + "/anusvaragujarati": "\u0A82", + "/ao": "\uA735", + "/aogonek": "\u0105", + "/aovermfullwidth": "\u33DF", + "/apaatosquare": "\u3300", + "/aparen": "\u249C", + "/aparenthesized": "\u249C", + "/apostrophearmenian": "\u055A", + "/apostrophedblmod": "\u02EE", + "/apostrophemod": "\u02BC", + "/apple": "\uF8FF", + "/approaches": "\u2250", + "/approacheslimit": "\u2250", + "/approxequal": "\u2248", + "/approxequalorimage": "\u2252", + "/approximatelybutnotactuallyequal": "\u2246", + "/approximatelyequal": "\u2245", + "/approximatelyequalorimage": "\u2252", + "/apriltelegraph": "\u32C3", + "/aquarius": "\u2652", + "/ar:ae": "\u06D5", + "/ar:ain": "\u0639", + "/ar:alef": "\u0627", + "/ar:comma": "\u060C", + "/ar:cuberoot": "\u0606", + "/ar:decimalseparator": "\u066B", + "/ar:e": "\u06D0", + "/ar:eight": "\u0668", + "/ar:feh": "\u0641", + "/ar:five": "\u0665", + "/ar:four": "\u0664", + "/ar:fourthroot": "\u0607", + "/ar:kaf": "\u0643", + "/ar:ng": "\u06AD", + "/ar:nine": "\u0669", + "/ar:numbersign": "\u0600", + "/ar:oe": "\u06C6", + "/ar:one": "\u0661", + "/ar:peh": "\u067E", + "/ar:percent": "\u066A", + "/ar:perthousand": "\u060A", + "/ar:question": "\u061F", + "/ar:reh": "\u0631", + "/ar:semicolon": "\u061B", + "/ar:seven": "\u0667", + "/ar:shadda": "\u0651", + "/ar:six": "\u0666", + "/ar:sukun": "\u0652", + "/ar:three": "\u0663", + "/ar:two": "\u0662", + "/ar:u": "\u06C7", + "/ar:ve": "\u06CB", + "/ar:yu": "\u06C8", + "/ar:zero": "\u0660", + "/araeaekorean": "\u318E", + "/araeakorean": "\u318D", + "/arc": "\u2312", + "/archaicmepigraphic": "\uA7FF", + "/aries": "\u2648", + "/arighthalfring": "\u1E9A", + "/aring": "\u00E5", + "/aringacute": "\u01FB", + "/aringbelow": "\u1E01", + "/armn:Ayb": "\u0531", + "/armn:Ben": "\u0532", + "/armn:Ca": "\u053E", + "/armn:Cha": "\u0549", + "/armn:Cheh": "\u0543", + "/armn:Co": "\u0551", + "/armn:DRAMSIGN": "\u058F", + "/armn:Da": "\u0534", + "/armn:Ech": "\u0535", + "/armn:Eh": "\u0537", + "/armn:Et": "\u0538", + "/armn:Feh": "\u0556", + "/armn:Ghad": "\u0542", + "/armn:Gim": "\u0533", + "/armn:Ho": "\u0540", + "/armn:Ini": "\u053B", + "/armn:Ja": "\u0541", + "/armn:Jheh": "\u054B", + "/armn:Keh": "\u0554", + "/armn:Ken": "\u053F", + "/armn:Liwn": "\u053C", + "/armn:Men": "\u0544", + "/armn:Now": "\u0546", + "/armn:Oh": "\u0555", + "/armn:Peh": "\u054A", + "/armn:Piwr": "\u0553", + "/armn:Ra": "\u054C", + "/armn:Reh": "\u0550", + "/armn:Seh": "\u054D", + "/armn:Sha": "\u0547", + "/armn:Tiwn": "\u054F", + "/armn:To": "\u0539", + "/armn:Vew": "\u054E", + "/armn:Vo": "\u0548", + "/armn:Xeh": "\u053D", + "/armn:Yi": "\u0545", + "/armn:Yiwn": "\u0552", + "/armn:Za": "\u0536", + "/armn:Zhe": "\u053A", + "/armn:abbreviationmark": "\u055F", + "/armn:apostrophe": "\u055A", + "/armn:ayb": "\u0561", + "/armn:ben": "\u0562", + "/armn:ca": "\u056E", + "/armn:cha": "\u0579", + "/armn:cheh": "\u0573", + "/armn:co": "\u0581", + "/armn:comma": "\u055D", + "/armn:da": "\u0564", + "/armn:ech": "\u0565", + "/armn:ech_yiwn": "\u0587", + "/armn:eh": "\u0567", + "/armn:emphasismark": "\u055B", + "/armn:et": "\u0568", + "/armn:exclam": "\u055C", + "/armn:feh": "\u0586", + "/armn:ghad": "\u0572", + "/armn:gim": "\u0563", + "/armn:ho": "\u0570", + "/armn:hyphen": "\u058A", + "/armn:ini": "\u056B", + "/armn:ja": "\u0571", + "/armn:jheh": "\u057B", + "/armn:keh": "\u0584", + "/armn:ken": "\u056F", + "/armn:leftfacingeternitysign": "\u058E", + "/armn:liwn": "\u056C", + "/armn:men": "\u0574", + "/armn:men_ech": "\uFB14", + "/armn:men_ini": "\uFB15", + "/armn:men_now": "\uFB13", + "/armn:men_xeh": "\uFB17", + "/armn:now": "\u0576", + "/armn:oh": "\u0585", + "/armn:peh": "\u057A", + "/armn:period": "\u0589", + "/armn:piwr": "\u0583", + "/armn:question": "\u055E", + "/armn:ra": "\u057C", + "/armn:reh": "\u0580", + "/armn:rightfacingeternitysign": "\u058D", + "/armn:ringhalfleft": "\u0559", + "/armn:seh": "\u057D", + "/armn:sha": "\u0577", + "/armn:tiwn": "\u057F", + "/armn:to": "\u0569", + "/armn:vew": "\u057E", + "/armn:vew_now": "\uFB16", + "/armn:vo": "\u0578", + "/armn:xeh": "\u056D", + "/armn:yi": "\u0575", + "/armn:yiwn": "\u0582", + "/armn:za": "\u0566", + "/armn:zhe": "\u056A", + "/arrowNE": "\u2197", + "/arrowNW": "\u2196", + "/arrowSE": "\u2198", + "/arrowSW": "\u2199", + "/arrowanticlockwiseopencircle": "\u21BA", + "/arrowanticlockwisesemicircle": "\u21B6", + "/arrowboth": "\u2194", + "/arrowclockwiseopencircle": "\u21BB", + "/arrowclockwisesemicircle": "\u21B7", + "/arrowdashdown": "\u21E3", + "/arrowdashleft": "\u21E0", + "/arrowdashright": "\u21E2", + "/arrowdashup": "\u21E1", + "/arrowdblboth": "\u21D4", + "/arrowdbldown": "\u21D3", + "/arrowdblleft": "\u21D0", + "/arrowdblright": "\u21D2", + "/arrowdblup": "\u21D1", + "/arrowdown": "\u2193", + "/arrowdowndashed": "\u21E3", + "/arrowdownfrombar": "\u21A7", + "/arrowdownleft": "\u2199", + "/arrowdownright": "\u2198", + "/arrowdowntwoheaded": "\u21A1", + "/arrowdownwhite": "\u21E9", + "/arrowdownzigzag": "\u21AF", + "/arrowheaddown": "\u2304", + "/arrowheaddownlowmod": "\u02EF", + "/arrowheaddownmod": "\u02C5", + "/arrowheadleftlowmod": "\u02F1", + "/arrowheadleftmod": "\u02C2", + "/arrowheadrightlowmod": "\u02F2", + "/arrowheadrightmod": "\u02C3", + "/arrowheadtwobarsuphorizontal": "\u2324", + "/arrowheadup": "\u2303", + "/arrowheaduplowmod": "\u02F0", + "/arrowheadupmod": "\u02C4", + "/arrowhorizex": "\uF8E7", + "/arrowleft": "\u2190", + "/arrowleftdashed": "\u21E0", + "/arrowleftdbl": "\u21D0", + "/arrowleftdblstroke": "\u21CD", + "/arrowleftdowncorner": "\u21B5", + "/arrowleftdowntip": "\u21B2", + "/arrowleftfrombar": "\u21A4", + "/arrowlefthook": "\u21A9", + "/arrowleftloop": "\u21AB", + "/arrowleftlowmod": "\u02FF", + "/arrowleftoverright": "\u21C6", + "/arrowleftoverrighttobar": "\u21B9", + "/arrowleftright": "\u2194", + "/arrowleftrightstroke": "\u21AE", + "/arrowleftrightwave": "\u21AD", + "/arrowleftsquiggle": "\u21DC", + "/arrowleftstroke": "\u219A", + "/arrowlefttail": "\u21A2", + "/arrowlefttobar": "\u21E4", + "/arrowlefttwoheaded": "\u219E", + "/arrowleftuptip": "\u21B0", + "/arrowleftwave": "\u219C", + "/arrowleftwhite": "\u21E6", + "/arrowlongNWtobar": "\u21B8", + "/arrowright": "\u2192", + "/arrowrightdashed": "\u21E2", + "/arrowrightdblstroke": "\u21CF", + "/arrowrightdowncorner": "\u21B4", + "/arrowrightdowntip": "\u21B3", + "/arrowrightfrombar": "\u21A6", + "/arrowrightheavy": "\u279E", + "/arrowrighthook": "\u21AA", + "/arrowrightloop": "\u21AC", + "/arrowrightoverleft": "\u21C4", + "/arrowrightsmallcircle": "\u21F4", + "/arrowrightsquiggle": "\u21DD", + "/arrowrightstroke": "\u219B", + "/arrowrighttail": "\u21A3", + "/arrowrighttobar": "\u21E5", + "/arrowrighttwoheaded": "\u21A0", + "/arrowrightwave": "\u219D", + "/arrowrightwhite": "\u21E8", + "/arrowspaireddown": "\u21CA", + "/arrowspairedleft": "\u21C7", + "/arrowspairedright": "\u21C9", + "/arrowspairedup": "\u21C8", + "/arrowtableft": "\u21E4", + "/arrowtabright": "\u21E5", + "/arrowup": "\u2191", + "/arrowupdashed": "\u21E1", + "/arrowupdn": "\u2195", + "/arrowupdnbse": "\u21A8", + "/arrowupdown": "\u2195", + "/arrowupdownbase": "\u21A8", + "/arrowupdownwithbase": "\u21A8", + "/arrowupfrombar": "\u21A5", + "/arrowupleft": "\u2196", + "/arrowupleftofdown": "\u21C5", + "/arrowupright": "\u2197", + "/arrowuprighttip": "\u21B1", + "/arrowuptwoheaded": "\u219F", + "/arrowupwhite": "\u21E7", + "/arrowvertex": "\uF8E6", + "/articulatedLorry": "\u1F69B", + "/artistPalette": "\u1F3A8", + "/aruhuasquare": "\u3301", + "/asciicircum": "\u005E", + "/asciicircummonospace": "\uFF3E", + "/asciitilde": "\u007E", + "/asciitildemonospace": "\uFF5E", + "/ascript": "\u0251", + "/ascriptturned": "\u0252", + "/asmallhiragana": "\u3041", + "/asmallkatakana": "\u30A1", + "/asmallkatakanahalfwidth": "\uFF67", + "/asper": "\u1FFE", + "/asperacute": "\u1FDE", + "/aspergrave": "\u1FDD", + "/aspertilde": "\u1FDF", + "/assertion": "\u22A6", + "/asterisk": "\u002A", + "/asteriskaltonearabic": "\u066D", + "/asteriskarabic": "\u066D", + "/asteriskmath": "\u2217", + "/asteriskmonospace": "\uFF0A", + "/asterisksmall": "\uFE61", + "/asterism": "\u2042", + "/astonishedFace": "\u1F632", + "/astroke": "\u2C65", + "/astronomicaluranus": "\u26E2", + "/asuperior": "\uF6E9", + "/asympticallyequal": "\u2243", + "/asymptoticallyequal": "\u2243", + "/at": "\u0040", + "/athleticShoe": "\u1F45F", + "/atilde": "\u00E3", + "/atmonospace": "\uFF20", + "/atnachHafukh:hb": "\u05A2", + "/atom": "\u269B", + "/atsmall": "\uFE6B", + "/attentionideographiccircled": "\u329F", + "/aturned": "\u0250", + "/au": "\uA737", + "/aubengali": "\u0994", + "/aubergine": "\u1F346", + "/aubopomofo": "\u3120", + "/audeva": "\u0914", + "/aufullwidth": "\u3373", + "/augujarati": "\u0A94", + "/augurmukhi": "\u0A14", + "/augusttelegraph": "\u32C7", + "/aulengthmarkbengali": "\u09D7", + "/aumatragurmukhi": "\u0A4C", + "/austral": "\u20B3", + "/automatedTellerMachine": "\u1F3E7", + "/automobile": "\u1F697", + "/auvowelsignbengali": "\u09CC", + "/auvowelsigndeva": "\u094C", + "/auvowelsigngujarati": "\u0ACC", + "/av": "\uA739", + "/avagrahadeva": "\u093D", + "/avhorizontalbar": "\uA73B", + "/ay": "\uA73D", + "/aybarmenian": "\u0561", + "/ayin": "\u05E2", + "/ayin:hb": "\u05E2", + "/ayinalt:hb": "\uFB20", + "/ayinaltonehebrew": "\uFB20", + "/ayinhebrew": "\u05E2", + "/azla:hb": "\u059C", + "/b": "\u0062", + "/baarerusquare": "\u332D", + "/babengali": "\u09AC", + "/babyAngel": "\u1F47C", + "/babyBottle": "\u1F37C", + "/babyChick": "\u1F424", + "/backLeftwardsArrowAbove": "\u1F519", + "/backOfEnvelope": "\u1F582", + "/backslash": "\u005C", + "/backslashbarfunc": "\u2340", + "/backslashdbl": "\u244A", + "/backslashmonospace": "\uFF3C", + "/bactrianCamel": "\u1F42B", + "/badeva": "\u092C", + "/badmintonRacquetAndShuttlecock": "\u1F3F8", + "/bagdelimitersshapeleft": "\u27C5", + "/bagdelimitersshaperight": "\u27C6", + "/baggageClaim": "\u1F6C4", + "/bagujarati": "\u0AAC", + "/bagurmukhi": "\u0A2C", + "/bahiragana": "\u3070", + "/bahtthai": "\u0E3F", + "/bakatakana": "\u30D0", + "/balloon": "\u1F388", + "/ballotBoldScriptX": "\u1F5F6", + "/ballotBoxBallot": "\u1F5F3", + "/ballotBoxBoldCheck": "\u1F5F9", + "/ballotBoxBoldScriptX": "\u1F5F7", + "/ballotBoxScriptX": "\u1F5F5", + "/ballotScriptX": "\u1F5F4", + "/bamurda": "\uA9A8", + "/banana": "\u1F34C", + "/bank": "\u1F3E6", + "/banknoteDollarSign": "\u1F4B5", + "/banknoteEuroSign": "\u1F4B6", + "/banknotePoundSign": "\u1F4B7", + "/banknoteYenSign": "\u1F4B4", + "/bar": "\u007C", + "/barChart": "\u1F4CA", + "/barberPole": "\u1F488", + "/barfullwidth": "\u3374", + "/barmonospace": "\uFF5C", + "/barquillverticalleft": "\u2E20", + "/barquillverticalright": "\u2E21", + "/baseball": "\u26BE", + "/basketballAndHoop": "\u1F3C0", + "/bath": "\u1F6C0", + "/bathtub": "\u1F6C1", + "/battery": "\u1F50B", + "/bbopomofo": "\u3105", + "/bcircle": "\u24D1", + "/bdot": "\u1E03", + "/bdotaccent": "\u1E03", + "/bdotbelow": "\u1E05", + "/beachUmbrella": "\u1F3D6", + "/beamedAscendingMusicalNotes": "\u1F39C", + "/beamedDescendingMusicalNotes": "\u1F39D", + "/beamedeighthnotes": "\u266B", + "/beamedsixteenthnotes": "\u266C", + "/beamfunc": "\u2336", + "/bearFace": "\u1F43B", + "/beatingHeart": "\u1F493", + "/because": "\u2235", + "/becyr": "\u0431", + "/becyrillic": "\u0431", + "/bed": "\u1F6CF", + "/beeh": "\u067B", + "/beeh.fina": "\uFB53", + "/beeh.init": "\uFB54", + "/beeh.isol": "\uFB52", + "/beeh.medi": "\uFB55", + "/beerMug": "\u1F37A", + "/beetasquare": "\u333C", + "/beh": "\u0628", + "/beh.fina": "\uFE90", + "/beh.init": "\uFE91", + "/beh.init_alefmaksura.fina": "\uFC09", + "/beh.init_hah.fina": "\uFC06", + "/beh.init_hah.medi": "\uFC9D", + "/beh.init_heh.medi": "\uFCA0", + "/beh.init_jeem.fina": "\uFC05", + "/beh.init_jeem.medi": "\uFC9C", + "/beh.init_khah.fina": "\uFC07", + "/beh.init_khah.medi": "\uFC9E", + "/beh.init_meem.fina": "\uFC08", + "/beh.init_meem.medi": "\uFC9F", + "/beh.init_yeh.fina": "\uFC0A", + "/beh.isol": "\uFE8F", + "/beh.medi": "\uFE92", + "/beh.medi_alefmaksura.fina": "\uFC6E", + "/beh.medi_hah.medi_yeh.fina": "\uFDC2", + "/beh.medi_heh.medi": "\uFCE2", + "/beh.medi_khah.medi_yeh.fina": "\uFD9E", + "/beh.medi_meem.fina": "\uFC6C", + "/beh.medi_meem.medi": "\uFCE1", + "/beh.medi_noon.fina": "\uFC6D", + "/beh.medi_reh.fina": "\uFC6A", + "/beh.medi_yeh.fina": "\uFC6F", + "/beh.medi_zain.fina": "\uFC6B", + "/behDotBelowThreeDotsAbove": "\u0751", + "/behInvertedSmallVBelow": "\u0755", + "/behSmallV": "\u0756", + "/behThreeDotsHorizontallyBelow": "\u0750", + "/behThreeDotsUpBelow": "\u0752", + "/behThreeDotsUpBelowTwoDotsAbove": "\u0753", + "/behTwoDotsBelowDotAbove": "\u0754", + "/beharabic": "\u0628", + "/beheh": "\u0680", + "/beheh.fina": "\uFB5B", + "/beheh.init": "\uFB5C", + "/beheh.isol": "\uFB5A", + "/beheh.medi": "\uFB5D", + "/behfinalarabic": "\uFE90", + "/behinitialarabic": "\uFE91", + "/behiragana": "\u3079", + "/behmedialarabic": "\uFE92", + "/behmeeminitialarabic": "\uFC9F", + "/behmeemisolatedarabic": "\uFC08", + "/behnoonfinalarabic": "\uFC6D", + "/bekatakana": "\u30D9", + "/bellCancellationStroke": "\u1F515", + "/bellhopBell": "\u1F6CE", + "/beltbuckle": "\u2444", + "/benarmenian": "\u0562", + "/beng:a": "\u0985", + "/beng:aa": "\u0986", + "/beng:aasign": "\u09BE", + "/beng:abbreviationsign": "\u09FD", + "/beng:ai": "\u0990", + "/beng:aisign": "\u09C8", + "/beng:anji": "\u0980", + "/beng:anusvara": "\u0982", + "/beng:au": "\u0994", + "/beng:aulengthmark": "\u09D7", + "/beng:ausign": "\u09CC", + "/beng:avagraha": "\u09BD", + "/beng:ba": "\u09AC", + "/beng:bha": "\u09AD", + "/beng:ca": "\u099A", + "/beng:candrabindu": "\u0981", + "/beng:cha": "\u099B", + "/beng:currencyoneless": "\u09F8", + "/beng:da": "\u09A6", + "/beng:dda": "\u09A1", + "/beng:ddha": "\u09A2", + "/beng:dha": "\u09A7", + "/beng:e": "\u098F", + "/beng:eight": "\u09EE", + "/beng:esign": "\u09C7", + "/beng:five": "\u09EB", + "/beng:four": "\u09EA", + "/beng:fourcurrencynumerator": "\u09F7", + "/beng:ga": "\u0997", + "/beng:gandamark": "\u09FB", + "/beng:gha": "\u0998", + "/beng:ha": "\u09B9", + "/beng:i": "\u0987", + "/beng:ii": "\u0988", + "/beng:iisign": "\u09C0", + "/beng:isign": "\u09BF", + "/beng:isshar": "\u09FA", + "/beng:ja": "\u099C", + "/beng:jha": "\u099D", + "/beng:ka": "\u0995", + "/beng:kha": "\u0996", + "/beng:khandata": "\u09CE", + "/beng:la": "\u09B2", + "/beng:llvocal": "\u09E1", + "/beng:llvocalsign": "\u09E3", + "/beng:lvocal": "\u098C", + "/beng:lvocalsign": "\u09E2", + "/beng:ma": "\u09AE", + "/beng:na": "\u09A8", + "/beng:nga": "\u0999", + "/beng:nine": "\u09EF", + "/beng:nna": "\u09A3", + "/beng:nukta": "\u09BC", + "/beng:nya": "\u099E", + "/beng:o": "\u0993", + "/beng:one": "\u09E7", + "/beng:onecurrencynumerator": "\u09F4", + "/beng:osign": "\u09CB", + "/beng:pa": "\u09AA", + "/beng:pha": "\u09AB", + "/beng:ra": "\u09B0", + "/beng:ralowdiagonal": "\u09F1", + "/beng:ramiddiagonal": "\u09F0", + "/beng:rha": "\u09DD", + "/beng:rra": "\u09DC", + "/beng:rrvocal": "\u09E0", + "/beng:rrvocalsign": "\u09C4", + "/beng:rupee": "\u09F3", + "/beng:rupeemark": "\u09F2", + "/beng:rvocal": "\u098B", + "/beng:rvocalsign": "\u09C3", + "/beng:sa": "\u09B8", + "/beng:seven": "\u09ED", + "/beng:sha": "\u09B6", + "/beng:six": "\u09EC", + "/beng:sixteencurrencydenominator": "\u09F9", + "/beng:ssa": "\u09B7", + "/beng:ta": "\u09A4", + "/beng:tha": "\u09A5", + "/beng:three": "\u09E9", + "/beng:threecurrencynumerator": "\u09F6", + "/beng:tta": "\u099F", + "/beng:ttha": "\u09A0", + "/beng:two": "\u09E8", + "/beng:twocurrencynumerator": "\u09F5", + "/beng:u": "\u0989", + "/beng:usign": "\u09C1", + "/beng:uu": "\u098A", + "/beng:uusign": "\u09C2", + "/beng:vedicanusvara": "\u09FC", + "/beng:virama": "\u09CD", + "/beng:visarga": "\u0983", + "/beng:ya": "\u09AF", + "/beng:yya": "\u09DF", + "/beng:zero": "\u09E6", + "/bentoBox": "\u1F371", + "/benzenering": "\u232C", + "/benzeneringcircle": "\u23E3", + "/bet": "\u05D1", + "/bet:hb": "\u05D1", + "/beta": "\u03B2", + "/betasymbol": "\u03D0", + "/betasymbolgreek": "\u03D0", + "/betdagesh": "\uFB31", + "/betdageshhebrew": "\uFB31", + "/bethebrew": "\u05D1", + "/betrafehebrew": "\uFB4C", + "/between": "\u226C", + "/betwithdagesh:hb": "\uFB31", + "/betwithrafe:hb": "\uFB4C", + "/bflourish": "\uA797", + "/bhabengali": "\u09AD", + "/bhadeva": "\u092D", + "/bhagujarati": "\u0AAD", + "/bhagurmukhi": "\u0A2D", + "/bhook": "\u0253", + "/bicycle": "\u1F6B2", + "/bicyclist": "\u1F6B4", + "/bihiragana": "\u3073", + "/bikatakana": "\u30D3", + "/bikini": "\u1F459", + "/bilabialclick": "\u0298", + "/billiards": "\u1F3B1", + "/bindigurmukhi": "\u0A02", + "/biohazard": "\u2623", + "/bird": "\u1F426", + "/birthdayCake": "\u1F382", + "/birusquare": "\u3331", + "/bishopblack": "\u265D", + "/bishopwhite": "\u2657", + "/bitcoin": "\u20BF", + "/blackDownPointingBackhandIndex": "\u1F5A3", + "/blackDroplet": "\u1F322", + "/blackFolder": "\u1F5BF", + "/blackHardShellFloppyDisk": "\u1F5AA", + "/blackHeart": "\u1F5A4", + "/blackLeftPointingBackhandIndex": "\u1F59C", + "/blackPennant": "\u1F3F2", + "/blackPushpin": "\u1F588", + "/blackRightPointingBackhandIndex": "\u1F59D", + "/blackRosette": "\u1F3F6", + "/blackSkullAndCrossbones": "\u1F571", + "/blackSquareButton": "\u1F532", + "/blackTouchtoneTelephone": "\u1F57F", + "/blackUpPointingBackhandIndex": "\u1F5A2", + "/blackcircle": "\u25CF", + "/blackcircleforrecord": "\u23FA", + "/blackdiamond": "\u25C6", + "/blackdownpointingtriangle": "\u25BC", + "/blackforstopsquare": "\u23F9", + "/blackleftpointingpointer": "\u25C4", + "/blackleftpointingtriangle": "\u25C0", + "/blacklenticularbracketleft": "\u3010", + "/blacklenticularbracketleftvertical": "\uFE3B", + "/blacklenticularbracketright": "\u3011", + "/blacklenticularbracketrightvertical": "\uFE3C", + "/blacklowerlefttriangle": "\u25E3", + "/blacklowerrighttriangle": "\u25E2", + "/blackmediumpointingtriangledown": "\u23F7", + "/blackmediumpointingtriangleleft": "\u23F4", + "/blackmediumpointingtriangleright": "\u23F5", + "/blackmediumpointingtriangleup": "\u23F6", + "/blackpointingdoubletrianglebarverticalleft": "\u23EE", + "/blackpointingdoubletrianglebarverticalright": "\u23ED", + "/blackpointingdoubletriangledown": "\u23EC", + "/blackpointingdoubletriangleleft": "\u23EA", + "/blackpointingdoubletriangleright": "\u23E9", + "/blackpointingdoubletriangleup": "\u23EB", + "/blackpointingtriangledoublebarverticalright": "\u23EF", + "/blackrectangle": "\u25AC", + "/blackrightpointingpointer": "\u25BA", + "/blackrightpointingtriangle": "\u25B6", + "/blacksmallsquare": "\u25AA", + "/blacksmilingface": "\u263B", + "/blacksquare": "\u25A0", + "/blackstar": "\u2605", + "/blackupperlefttriangle": "\u25E4", + "/blackupperrighttriangle": "\u25E5", + "/blackuppointingsmalltriangle": "\u25B4", + "/blackuppointingtriangle": "\u25B2", + "/blackwardsbulletleft": "\u204C", + "/blackwardsbulletright": "\u204D", + "/blank": "\u2423", + "/blinebelow": "\u1E07", + "/block": "\u2588", + "/blossom": "\u1F33C", + "/blowfish": "\u1F421", + "/blueBook": "\u1F4D8", + "/blueHeart": "\u1F499", + "/bmonospace": "\uFF42", + "/boar": "\u1F417", + "/board": "\u2328", + "/bobaimaithai": "\u0E1A", + "/bohiragana": "\u307C", + "/bokatakana": "\u30DC", + "/bomb": "\u1F4A3", + "/book": "\u1F56E", + "/bookmark": "\u1F516", + "/bookmarkTabs": "\u1F4D1", + "/books": "\u1F4DA", + "/bopo:a": "\u311A", + "/bopo:ai": "\u311E", + "/bopo:an": "\u3122", + "/bopo:ang": "\u3124", + "/bopo:au": "\u3120", + "/bopo:b": "\u3105", + "/bopo:c": "\u3118", + "/bopo:ch": "\u3114", + "/bopo:d": "\u3109", + "/bopo:e": "\u311C", + "/bopo:eh": "\u311D", + "/bopo:ei": "\u311F", + "/bopo:en": "\u3123", + "/bopo:eng": "\u3125", + "/bopo:er": "\u3126", + "/bopo:f": "\u3108", + "/bopo:g": "\u310D", + "/bopo:gn": "\u312C", + "/bopo:h": "\u310F", + "/bopo:i": "\u3127", + "/bopo:ih": "\u312D", + "/bopo:iu": "\u3129", + "/bopo:j": "\u3110", + "/bopo:k": "\u310E", + "/bopo:l": "\u310C", + "/bopo:m": "\u3107", + "/bopo:n": "\u310B", + "/bopo:ng": "\u312B", + "/bopo:o": "\u311B", + "/bopo:ou": "\u3121", + "/bopo:owithdotabove": "\u312E", + "/bopo:p": "\u3106", + "/bopo:q": "\u3111", + "/bopo:r": "\u3116", + "/bopo:s": "\u3119", + "/bopo:sh": "\u3115", + "/bopo:t": "\u310A", + "/bopo:u": "\u3128", + "/bopo:v": "\u312A", + "/bopo:x": "\u3112", + "/bopo:z": "\u3117", + "/bopo:zh": "\u3113", + "/borutosquare": "\u333E", + "/bottlePoppingCork": "\u1F37E", + "/bouquet": "\u1F490", + "/bouquetOfFlowers": "\u1F395", + "/bowAndArrow": "\u1F3F9", + "/bowlOfHygieia": "\u1F54F", + "/bowling": "\u1F3B3", + "/boxlineverticalleft": "\u23B8", + "/boxlineverticalright": "\u23B9", + "/boy": "\u1F466", + "/boys": "\u1F6C9", + "/bparen": "\u249D", + "/bparenthesized": "\u249D", + "/bqfullwidth": "\u33C3", + "/bqsquare": "\u33C3", + "/braceex": "\uF8F4", + "/braceleft": "\u007B", + "/braceleftbt": "\uF8F3", + "/braceleftmid": "\uF8F2", + "/braceleftmonospace": "\uFF5B", + "/braceleftsmall": "\uFE5B", + "/bracelefttp": "\uF8F1", + "/braceleftvertical": "\uFE37", + "/braceright": "\u007D", + "/bracerightbt": "\uF8FE", + "/bracerightmid": "\uF8FD", + "/bracerightmonospace": "\uFF5D", + "/bracerightsmall": "\uFE5C", + "/bracerighttp": "\uF8FC", + "/bracerightvertical": "\uFE38", + "/bracketangledblleft": "\u27EA", + "/bracketangledblright": "\u27EB", + "/bracketangleleft": "\u27E8", + "/bracketangleright": "\u27E9", + "/bracketbottomcurly": "\u23DF", + "/bracketbottomsquare": "\u23B5", + "/bracketcornerupleftsquare": "\u23A1", + "/bracketcorneruprightsquare": "\u23A4", + "/bracketdottedsubstitutionleft": "\u2E04", + "/bracketdottedsubstitutionright": "\u2E05", + "/bracketextensioncurly": "\u23AA", + "/bracketextensionleftsquare": "\u23A2", + "/bracketextensionrightsquare": "\u23A5", + "/brackethalfbottomleft": "\u2E24", + "/brackethalfbottomright": "\u2E25", + "/brackethalftopleft": "\u2E22", + "/brackethalftopright": "\u2E23", + "/brackethookupleftcurly": "\u23A7", + "/brackethookuprightcurly": "\u23AB", + "/bracketleft": "\u005B", + "/bracketleftbt": "\uF8F0", + "/bracketleftex": "\uF8EF", + "/bracketleftmonospace": "\uFF3B", + "/bracketleftsquarequill": "\u2045", + "/bracketlefttp": "\uF8EE", + "/bracketlowercornerleftsquare": "\u23A3", + "/bracketlowercornerrightsquare": "\u23A6", + "/bracketlowerhookleftcurly": "\u23A9", + "/bracketlowerhookrightcurly": "\u23AD", + "/bracketmiddlepieceleftcurly": "\u23A8", + "/bracketmiddlepiecerightcurly": "\u23AC", + "/bracketoverbrackettopbottomsquare": "\u23B6", + "/bracketparaphraselowleft": "\u2E1C", + "/bracketparaphraselowright": "\u2E1D", + "/bracketraisedleft": "\u2E0C", + "/bracketraisedright": "\u2E0D", + "/bracketright": "\u005D", + "/bracketrightbt": "\uF8FB", + "/bracketrightex": "\uF8FA", + "/bracketrightmonospace": "\uFF3D", + "/bracketrightsquarequill": "\u2046", + "/bracketrighttp": "\uF8F9", + "/bracketsectionupleftlowerrightcurly": "\u23B0", + "/bracketsectionuprightlowerleftcurly": "\u23B1", + "/bracketshellbottom": "\u23E1", + "/bracketshelltop": "\u23E0", + "/bracketshellwhiteleft": "\u27EC", + "/bracketshellwhiteright": "\u27ED", + "/bracketsubstitutionleft": "\u2E02", + "/bracketsubstitutionright": "\u2E03", + "/brackettopcurly": "\u23DE", + "/brackettopsquare": "\u23B4", + "/brackettranspositionleft": "\u2E09", + "/brackettranspositionright": "\u2E0A", + "/bracketwhitesquareleft": "\u27E6", + "/bracketwhitesquareright": "\u27E7", + "/branchbankidentification": "\u2446", + "/bread": "\u1F35E", + "/breve": "\u02D8", + "/brevebelowcmb": "\u032E", + "/brevecmb": "\u0306", + "/breveinvertedbelowcmb": "\u032F", + "/breveinvertedcmb": "\u0311", + "/breveinverteddoublecmb": "\u0361", + "/brevemetrical": "\u23D1", + "/brideVeil": "\u1F470", + "/bridgeAtNight": "\u1F309", + "/bridgebelowcmb": "\u032A", + "/bridgeinvertedbelowcmb": "\u033A", + "/briefcase": "\u1F4BC", + "/brll:blank": "\u2800", + "/brokenHeart": "\u1F494", + "/brokenbar": "\u00A6", + "/brokencirclenorthwestarrow": "\u238B", + "/bstroke": "\u0180", + "/bsuperior": "\uF6EA", + "/btopbar": "\u0183", + "/bug": "\u1F41B", + "/buhiragana": "\u3076", + "/buildingConstruction": "\u1F3D7", + "/bukatakana": "\u30D6", + "/bullet": "\u2022", + "/bulletinverse": "\u25D8", + "/bulletoperator": "\u2219", + "/bullhorn": "\u1F56B", + "/bullhornSoundWaves": "\u1F56C", + "/bullseye": "\u25CE", + "/burrito": "\u1F32F", + "/bus": "\u1F68C", + "/busStop": "\u1F68F", + "/bussyerusquare": "\u3334", + "/bustInSilhouette": "\u1F464", + "/bustsInSilhouette": "\u1F465", + "/c": "\u0063", + "/caarmenian": "\u056E", + "/cabengali": "\u099A", + "/cactus": "\u1F335", + "/cacute": "\u0107", + "/cadauna": "\u2106", + "/cadeva": "\u091A", + "/caduceus": "\u2624", + "/cagujarati": "\u0A9A", + "/cagurmukhi": "\u0A1A", + "/cakraconsonant": "\uA9BF", + "/calendar": "\u1F4C5", + "/calfullwidth": "\u3388", + "/callideographicparen": "\u323A", + "/calsquare": "\u3388", + "/camera": "\u1F4F7", + "/cameraFlash": "\u1F4F8", + "/camping": "\u1F3D5", + "/camurda": "\uA996", + "/cancellationX": "\u1F5D9", + "/cancer": "\u264B", + "/candle": "\u1F56F", + "/candrabindubengali": "\u0981", + "/candrabinducmb": "\u0310", + "/candrabindudeva": "\u0901", + "/candrabindugujarati": "\u0A81", + "/candy": "\u1F36C", + "/canoe": "\u1F6F6", + "/capitulum": "\u2E3F", + "/capricorn": "\u2651", + "/capslock": "\u21EA", + "/cardFileBox": "\u1F5C3", + "/cardIndex": "\u1F4C7", + "/cardIndexDividers": "\u1F5C2", + "/careof": "\u2105", + "/caret": "\u2038", + "/caretinsertionpoint": "\u2041", + "/carettildedownfunc": "\u2371", + "/carettildeupfunc": "\u2372", + "/caron": "\u02C7", + "/caronbelowcmb": "\u032C", + "/caroncmb": "\u030C", + "/carouselHorse": "\u1F3A0", + "/carpStreamer": "\u1F38F", + "/carriagereturn": "\u21B5", + "/carsliding": "\u26D0", + "/castle": "\u26EB", + "/cat": "\u1F408", + "/catFace": "\u1F431", + "/catFaceWithTearsOfJoy": "\u1F639", + "/catFaceWithWrySmile": "\u1F63C", + "/caution": "\u2621", + "/cbar": "\uA793", + "/cbopomofo": "\u3118", + "/ccaron": "\u010D", + "/ccedilla": "\u00E7", + "/ccedillaacute": "\u1E09", + "/ccfullwidth": "\u33C4", + "/ccircle": "\u24D2", + "/ccircumflex": "\u0109", + "/ccurl": "\u0255", + "/cdfullwidth": "\u33C5", + "/cdot": "\u010B", + "/cdotaccent": "\u010B", + "/cdotreversed": "\uA73F", + "/cdsquare": "\u33C5", + "/cecak": "\uA981", + "/cecaktelu": "\uA9B3", + "/cedi": "\u20B5", + "/cedilla": "\u00B8", + "/cedillacmb": "\u0327", + "/ceilingleft": "\u2308", + "/ceilingright": "\u2309", + "/celticCross": "\u1F548", + "/cent": "\u00A2", + "/centigrade": "\u2103", + "/centinferior": "\uF6DF", + "/centmonospace": "\uFFE0", + "/centoldstyle": "\uF7A2", + "/centreddotwhitediamond": "\u27D0", + "/centreideographiccircled": "\u32A5", + "/centreline": "\u2104", + "/centrelineverticalsquarewhite": "\u2385", + "/centsuperior": "\uF6E0", + "/ceres": "\u26B3", + "/chaarmenian": "\u0579", + "/chabengali": "\u099B", + "/chadeva": "\u091B", + "/chagujarati": "\u0A9B", + "/chagurmukhi": "\u0A1B", + "/chains": "\u26D3", + "/chair": "\u2441", + "/chamkocircle": "\u327C", + "/charactertie": "\u2040", + "/chartDownwardsTrend": "\u1F4C9", + "/chartUpwardsTrend": "\u1F4C8", + "/chartUpwardsTrendAndYenSign": "\u1F4B9", + "/chbopomofo": "\u3114", + "/cheabkhasiancyrillic": "\u04BD", + "/cheabkhcyr": "\u04BD", + "/cheabkhtailcyr": "\u04BF", + "/checkbox": "\u2610", + "/checkboxchecked": "\u2611", + "/checkboxx": "\u2612", + "/checkmark": "\u2713", + "/checyr": "\u0447", + "/checyrillic": "\u0447", + "/chedescenderabkhasiancyrillic": "\u04BF", + "/chedescendercyrillic": "\u04B7", + "/chedieresiscyr": "\u04F5", + "/chedieresiscyrillic": "\u04F5", + "/cheeringMegaphone": "\u1F4E3", + "/cheharmenian": "\u0573", + "/chekhakascyr": "\u04CC", + "/chekhakassiancyrillic": "\u04CC", + "/chequeredFlag": "\u1F3C1", + "/cherries": "\u1F352", + "/cherryBlossom": "\u1F338", + "/chestnut": "\u1F330", + "/chetailcyr": "\u04B7", + "/chevertcyr": "\u04B9", + "/cheverticalstrokecyrillic": "\u04B9", + "/chi": "\u03C7", + "/chicken": "\u1F414", + "/chieuchacirclekorean": "\u3277", + "/chieuchaparenkorean": "\u3217", + "/chieuchcirclekorean": "\u3269", + "/chieuchkorean": "\u314A", + "/chieuchparenkorean": "\u3209", + "/childrenCrossing": "\u1F6B8", + "/chipmunk": "\u1F43F", + "/chirho": "\u2627", + "/chiron": "\u26B7", + "/chochangthai": "\u0E0A", + "/chochanthai": "\u0E08", + "/chochingthai": "\u0E09", + "/chochoethai": "\u0E0C", + "/chocolateBar": "\u1F36B", + "/chook": "\u0188", + "/christmasTree": "\u1F384", + "/church": "\u26EA", + "/cieucacirclekorean": "\u3276", + "/cieucaparenkorean": "\u3216", + "/cieuccirclekorean": "\u3268", + "/cieuckorean": "\u3148", + "/cieucparenkorean": "\u3208", + "/cieucuparenkorean": "\u321C", + "/cinema": "\u1F3A6", + "/circle": "\u25CB", + "/circleallbutupperquadrantleftblack": "\u25D5", + "/circlebackslashfunc": "\u2349", + "/circleblack": "\u25CF", + "/circledCrossPommee": "\u1F540", + "/circledInformationSource": "\u1F6C8", + "/circledasteriskoperator": "\u229B", + "/circledbarnotchhorizontal": "\u2389", + "/circledcrossinglanes": "\u26D2", + "/circleddash": "\u229D", + "/circleddivisionslash": "\u2298", + "/circleddotoperator": "\u2299", + "/circledequals": "\u229C", + "/circlediaeresisfunc": "\u2365", + "/circledminus": "\u2296", + "/circledot": "\u2299", + "/circledotrightwhite": "\u2686", + "/circledotted": "\u25CC", + "/circledringoperator": "\u229A", + "/circledtriangledown": "\u238A", + "/circlehalfleftblack": "\u25D0", + "/circlehalfrightblack": "\u25D1", + "/circleinversewhite": "\u25D9", + "/circlejotfunc": "\u233E", + "/circlelowerhalfblack": "\u25D2", + "/circlelowerquadrantleftwhite": "\u25F5", + "/circlelowerquadrantrightwhite": "\u25F6", + "/circlemultiply": "\u2297", + "/circleot": "\u2299", + "/circleplus": "\u2295", + "/circlepostalmark": "\u3036", + "/circlestarfunc": "\u235F", + "/circlestilefunc": "\u233D", + "/circlestroketwodotsaboveheavy": "\u26E3", + "/circletwodotsblackwhite": "\u2689", + "/circletwodotswhite": "\u2687", + "/circleunderlinefunc": "\u235C", + "/circleupperhalfblack": "\u25D3", + "/circleupperquadrantleftwhite": "\u25F4", + "/circleupperquadrantrightblack": "\u25D4", + "/circleupperquadrantrightwhite": "\u25F7", + "/circleverticalfill": "\u25CD", + "/circlewhite": "\u25CB", + "/circlewhitedotrightblack": "\u2688", + "/circlewithlefthalfblack": "\u25D0", + "/circlewithrighthalfblack": "\u25D1", + "/circumflex": "\u02C6", + "/circumflexbelowcmb": "\u032D", + "/circumflexcmb": "\u0302", + "/circumflexlow": "\uA788", + "/circusTent": "\u1F3AA", + "/cityscape": "\u1F3D9", + "/cityscapeAtDusk": "\u1F306", + "/cjk:ideographiccomma": "\u3001", + "/cjk:tortoiseshellbracketleft": "\u3014", + "/cjk:tortoiseshellbracketright": "\u3015", + "/clamshellMobilePhone": "\u1F581", + "/clapperBoard": "\u1F3AC", + "/clappingHandsSign": "\u1F44F", + "/classicalBuilding": "\u1F3DB", + "/clear": "\u2327", + "/clearscreen": "\u239A", + "/clickalveolar": "\u01C2", + "/clickbilabial": "\u0298", + "/clickdental": "\u01C0", + "/clicklateral": "\u01C1", + "/clickretroflex": "\u01C3", + "/clinkingBeerMugs": "\u1F37B", + "/clipboard": "\u1F4CB", + "/clockFaceEight-thirty": "\u1F563", + "/clockFaceEightOclock": "\u1F557", + "/clockFaceEleven-thirty": "\u1F566", + "/clockFaceElevenOclock": "\u1F55A", + "/clockFaceFive-thirty": "\u1F560", + "/clockFaceFiveOclock": "\u1F554", + "/clockFaceFour-thirty": "\u1F55F", + "/clockFaceFourOclock": "\u1F553", + "/clockFaceNine-thirty": "\u1F564", + "/clockFaceNineOclock": "\u1F558", + "/clockFaceOne-thirty": "\u1F55C", + "/clockFaceOneOclock": "\u1F550", + "/clockFaceSeven-thirty": "\u1F562", + "/clockFaceSevenOclock": "\u1F556", + "/clockFaceSix-thirty": "\u1F561", + "/clockFaceSixOclock": "\u1F555", + "/clockFaceTen-thirty": "\u1F565", + "/clockFaceTenOclock": "\u1F559", + "/clockFaceThree-thirty": "\u1F55E", + "/clockFaceThreeOclock": "\u1F552", + "/clockFaceTwelve-thirty": "\u1F567", + "/clockFaceTwelveOclock": "\u1F55B", + "/clockFaceTwo-thirty": "\u1F55D", + "/clockFaceTwoOclock": "\u1F551", + "/clockwiseDownwardsAndUpwardsOpenCircleArrows": "\u1F503", + "/clockwiseRightAndLeftSemicircleArrows": "\u1F5D8", + "/clockwiseRightwardsAndLeftwardsOpenCircleArrows": "\u1F501", + "/clockwiseRightwardsAndLeftwardsOpenCircleArrowsCircledOneOverlay": "\u1F502", + "/closedBook": "\u1F4D5", + "/closedLockKey": "\u1F510", + "/closedMailboxLoweredFlag": "\u1F4EA", + "/closedMailboxRaisedFlag": "\u1F4EB", + "/closedUmbrella": "\u1F302", + "/closedentryleft": "\u26DC", + "/closeup": "\u2050", + "/cloud": "\u2601", + "/cloudLightning": "\u1F329", + "/cloudRain": "\u1F327", + "/cloudSnow": "\u1F328", + "/cloudTornado": "\u1F32A", + "/clsquare": "\u1F191", + "/club": "\u2663", + "/clubblack": "\u2663", + "/clubsuitblack": "\u2663", + "/clubsuitwhite": "\u2667", + "/clubwhite": "\u2667", + "/cm2fullwidth": "\u33A0", + "/cm3fullwidth": "\u33A4", + "/cmb:a": "\u0363", + "/cmb:aaboveflat": "\u1DD3", + "/cmb:aboveogonek": "\u1DCE", + "/cmb:acute": "\u0301", + "/cmb:acutebelow": "\u0317", + "/cmb:acutegraveacute": "\u1DC9", + "/cmb:acutemacron": "\u1DC7", + "/cmb:acutetone": "\u0341", + "/cmb:adieresis": "\u1DF2", + "/cmb:ae": "\u1DD4", + "/cmb:almostequalabove": "\u034C", + "/cmb:almostequaltobelow": "\u1DFD", + "/cmb:alpha": "\u1DE7", + "/cmb:ao": "\u1DD5", + "/cmb:arrowheadleftbelow": "\u0354", + "/cmb:arrowheadrightabove": "\u0350", + "/cmb:arrowheadrightarrowheadupbelow": "\u0356", + "/cmb:arrowheadrightbelow": "\u0355", + "/cmb:arrowleftrightbelow": "\u034D", + "/cmb:arrowrightdoublebelow": "\u0362", + "/cmb:arrowupbelow": "\u034E", + "/cmb:asteriskbelow": "\u0359", + "/cmb:av": "\u1DD6", + "/cmb:b": "\u1DE8", + "/cmb:belowbreve": "\u032E", + "/cmb:beta": "\u1DE9", + "/cmb:breve": "\u0306", + "/cmb:brevemacron": "\u1DCB", + "/cmb:bridgeabove": "\u0346", + "/cmb:bridgebelow": "\u032A", + "/cmb:c": "\u0368", + "/cmb:candrabindu": "\u0310", + "/cmb:caron": "\u030C", + "/cmb:caronbelow": "\u032C", + "/cmb:ccedilla": "\u1DD7", + "/cmb:cedilla": "\u0327", + "/cmb:circumflex": "\u0302", + "/cmb:circumflexbelow": "\u032D", + "/cmb:commaaccentbelow": "\u0326", + "/cmb:commaturnedabove": "\u0312", + "/cmb:d": "\u0369", + "/cmb:dblarchinvertedbelow": "\u032B", + "/cmb:dbloverline": "\u033F", + "/cmb:dblverticallineabove": "\u030E", + "/cmb:dblverticallinebelow": "\u0348", + "/cmb:deletionmark": "\u1DFB", + "/cmb:dialytikatonos": "\u0344", + "/cmb:dieresis": "\u0308", + "/cmb:dieresisbelow": "\u0324", + "/cmb:dotaboveleft": "\u1DF8", + "/cmb:dotaccent": "\u0307", + "/cmb:dotbelowcomb": "\u0323", + "/cmb:dotrightabove": "\u0358", + "/cmb:dottedacute": "\u1DC1", + "/cmb:dottedgrave": "\u1DC0", + "/cmb:doubleabovecircumflex": "\u1DCD", + "/cmb:doublebelowbreve": "\u035C", + "/cmb:doublebreve": "\u035D", + "/cmb:doubleinvertedbelowbreve": "\u1DFC", + "/cmb:doubleringbelow": "\u035A", + "/cmb:downtackbelow": "\u031E", + "/cmb:e": "\u0364", + "/cmb:equalbelow": "\u0347", + "/cmb:esh": "\u1DEF", + "/cmb:eth": "\u1DD9", + "/cmb:f": "\u1DEB", + "/cmb:fermata": "\u0352", + "/cmb:g": "\u1DDA", + "/cmb:graphemejoiner": "\u034F", + "/cmb:grave": "\u0300", + "/cmb:graveacutegrave": "\u1DC8", + "/cmb:gravebelow": "\u0316", + "/cmb:gravedouble": "\u030F", + "/cmb:gravemacron": "\u1DC5", + "/cmb:gravetone": "\u0340", + "/cmb:gsmall": "\u1DDB", + "/cmb:h": "\u036A", + "/cmb:halfleftringabove": "\u0351", + "/cmb:halfleftringbelow": "\u031C", + "/cmb:halfrightringabove": "\u0357", + "/cmb:halfrightringbelow": "\u0339", + "/cmb:homotheticabove": "\u034B", + "/cmb:hookabove": "\u0309", + "/cmb:horn": "\u031B", + "/cmb:hungarumlaut": "\u030B", + "/cmb:i": "\u0365", + "/cmb:insulard": "\u1DD8", + "/cmb:invertedbelowbreve": "\u032F", + "/cmb:invertedbreve": "\u0311", + "/cmb:invertedbridgebelow": "\u033A", + "/cmb:inverteddoublebreve": "\u0361", + "/cmb:iotasub": "\u0345", + "/cmb:isbelow": "\u1DD0", + "/cmb:k": "\u1DDC", + "/cmb:kavykaaboveleft": "\u1DF7", + "/cmb:kavykaaboveright": "\u1DF6", + "/cmb:koronis": "\u0343", + "/cmb:l": "\u1DDD", + "/cmb:leftangleabove": "\u031A", + "/cmb:leftanglebelow": "\u0349", + "/cmb:leftarrowheadabove": "\u1DFE", + "/cmb:lefttackbelow": "\u0318", + "/cmb:lineverticalabove": "\u030D", + "/cmb:lineverticalbelow": "\u0329", + "/cmb:longs": "\u1DE5", + "/cmb:lowline": "\u0332", + "/cmb:lowlinedouble": "\u0333", + "/cmb:lsmall": "\u1DDE", + "/cmb:lwithdoublemiddletilde": "\u1DEC", + "/cmb:m": "\u036B", + "/cmb:macron": "\u0304", + "/cmb:macronacute": "\u1DC4", + "/cmb:macronbelow": "\u0331", + "/cmb:macronbreve": "\u1DCC", + "/cmb:macrondouble": "\u035E", + "/cmb:macrondoublebelow": "\u035F", + "/cmb:macrongrave": "\u1DC6", + "/cmb:minusbelow": "\u0320", + "/cmb:msmall": "\u1DDF", + "/cmb:n": "\u1DE0", + "/cmb:nottildeabove": "\u034A", + "/cmb:nsmall": "\u1DE1", + "/cmb:o": "\u0366", + "/cmb:odieresis": "\u1DF3", + "/cmb:ogonek": "\u0328", + "/cmb:overlaystrokelong": "\u0336", + "/cmb:overlaystrokeshort": "\u0335", + "/cmb:overline": "\u0305", + "/cmb:owithlightcentralizationstroke": "\u1DED", + "/cmb:p": "\u1DEE", + "/cmb:palatalizedhookbelow": "\u0321", + "/cmb:perispomeni": "\u0342", + "/cmb:plusbelow": "\u031F", + "/cmb:r": "\u036C", + "/cmb:rbelow": "\u1DCA", + "/cmb:retroflexhookbelow": "\u0322", + "/cmb:reversedcommaabove": "\u0314", + "/cmb:rightarrowheadanddownarrowheadbelow": "\u1DFF", + "/cmb:righttackbelow": "\u0319", + "/cmb:ringabove": "\u030A", + "/cmb:ringbelow": "\u0325", + "/cmb:rrotunda": "\u1DE3", + "/cmb:rsmall": "\u1DE2", + "/cmb:s": "\u1DE4", + "/cmb:schwa": "\u1DEA", + "/cmb:seagullbelow": "\u033C", + "/cmb:snakebelow": "\u1DC2", + "/cmb:soliduslongoverlay": "\u0338", + "/cmb:solidusshortoverlay": "\u0337", + "/cmb:squarebelow": "\u033B", + "/cmb:suspensionmark": "\u1DC3", + "/cmb:t": "\u036D", + "/cmb:tilde": "\u0303", + "/cmb:tildebelow": "\u0330", + "/cmb:tildedouble": "\u0360", + "/cmb:tildeoverlay": "\u0334", + "/cmb:tildevertical": "\u033E", + "/cmb:turnedabove": "\u0313", + "/cmb:turnedcommaabove": "\u0315", + "/cmb:u": "\u0367", + "/cmb:udieresis": "\u1DF4", + "/cmb:uptackabove": "\u1DF5", + "/cmb:uptackbelow": "\u031D", + "/cmb:urabove": "\u1DD1", + "/cmb:usabove": "\u1DD2", + "/cmb:uwithlightcentralizationstroke": "\u1DF0", + "/cmb:v": "\u036E", + "/cmb:w": "\u1DF1", + "/cmb:wideinvertedbridgebelow": "\u1DF9", + "/cmb:x": "\u036F", + "/cmb:xabove": "\u033D", + "/cmb:xbelow": "\u0353", + "/cmb:z": "\u1DE6", + "/cmb:zigzagabove": "\u035B", + "/cmb:zigzagbelow": "\u1DCF", + "/cmcubedsquare": "\u33A4", + "/cmfullwidth": "\u339D", + "/cmonospace": "\uFF43", + "/cmsquaredsquare": "\u33A0", + "/cntr:acknowledge": "\u2406", + "/cntr:backspace": "\u2408", + "/cntr:bell": "\u2407", + "/cntr:blank": "\u2422", + "/cntr:cancel": "\u2418", + "/cntr:carriagereturn": "\u240D", + "/cntr:datalinkescape": "\u2410", + "/cntr:delete": "\u2421", + "/cntr:deleteformtwo": "\u2425", + "/cntr:devicecontrolfour": "\u2414", + "/cntr:devicecontrolone": "\u2411", + "/cntr:devicecontrolthree": "\u2413", + "/cntr:devicecontroltwo": "\u2412", + "/cntr:endofmedium": "\u2419", + "/cntr:endoftext": "\u2403", + "/cntr:endoftransmission": "\u2404", + "/cntr:endoftransmissionblock": "\u2417", + "/cntr:enquiry": "\u2405", + "/cntr:escape": "\u241B", + "/cntr:fileseparator": "\u241C", + "/cntr:formfeed": "\u240C", + "/cntr:groupseparator": "\u241D", + "/cntr:horizontaltab": "\u2409", + "/cntr:linefeed": "\u240A", + "/cntr:negativeacknowledge": "\u2415", + "/cntr:newline": "\u2424", + "/cntr:null": "\u2400", + "/cntr:openbox": "\u2423", + "/cntr:recordseparator": "\u241E", + "/cntr:shiftin": "\u240F", + "/cntr:shiftout": "\u240E", + "/cntr:space": "\u2420", + "/cntr:startofheading": "\u2401", + "/cntr:startoftext": "\u2402", + "/cntr:substitute": "\u241A", + "/cntr:substituteformtwo": "\u2426", + "/cntr:synchronousidle": "\u2416", + "/cntr:unitseparator": "\u241F", + "/cntr:verticaltab": "\u240B", + "/coarmenian": "\u0581", + "/cocktailGlass": "\u1F378", + "/coffin": "\u26B0", + "/cofullwidth": "\u33C7", + "/collision": "\u1F4A5", + "/colon": "\u003A", + "/colonequals": "\u2254", + "/colonmod": "\uA789", + "/colonmonetary": "\u20A1", + "/colonmonospace": "\uFF1A", + "/colonraisedmod": "\u02F8", + "/colonsign": "\u20A1", + "/colonsmall": "\uFE55", + "/colontriangularhalfmod": "\u02D1", + "/colontriangularmod": "\u02D0", + "/comet": "\u2604", + "/comma": "\u002C", + "/commaabovecmb": "\u0313", + "/commaaboverightcmb": "\u0315", + "/commaaccent": "\uF6C3", + "/commaarabic": "\u060C", + "/commaarmenian": "\u055D", + "/commabarfunc": "\u236A", + "/commainferior": "\uF6E1", + "/commamonospace": "\uFF0C", + "/commaraised": "\u2E34", + "/commareversed": "\u2E41", + "/commareversedabovecmb": "\u0314", + "/commareversedmod": "\u02BD", + "/commasmall": "\uFE50", + "/commasuperior": "\uF6E2", + "/commaturnedabovecmb": "\u0312", + "/commaturnedmod": "\u02BB", + "/commercialat": "\uFE6B", + "/commercialminussign": "\u2052", + "/compass": "\u263C", + "/complement": "\u2201", + "/composition": "\u2384", + "/compression": "\u1F5DC", + "/con": "\uA76F", + "/confettiBall": "\u1F38A", + "/confoundedFace": "\u1F616", + "/confusedFace": "\u1F615", + "/congratulationideographiccircled": "\u3297", + "/congratulationideographicparen": "\u3237", + "/congruent": "\u2245", + "/conicaltaper": "\u2332", + "/conjunction": "\u260C", + "/consquareupblack": "\u26FE", + "/constructionSign": "\u1F6A7", + "/constructionWorker": "\u1F477", + "/containsasmembersmall": "\u220D", + "/containsasnormalsubgroorequalup": "\u22B5", + "/containsasnormalsubgroup": "\u22B3", + "/containslonghorizontalstroke": "\u22FA", + "/containsoverbar": "\u22FD", + "/containsoverbarsmall": "\u22FE", + "/containssmallverticalbarhorizontalstroke": "\u22FC", + "/containsverticalbarhorizontalstroke": "\u22FB", + "/continuousunderline": "\u2381", + "/contourintegral": "\u222E", + "/control": "\u2303", + "/controlACK": "\u0006", + "/controlBEL": "\u0007", + "/controlBS": "\u0008", + "/controlCAN": "\u0018", + "/controlCR": "\u000D", + "/controlDC1": "\u0011", + "/controlDC2": "\u0012", + "/controlDC3": "\u0013", + "/controlDC4": "\u0014", + "/controlDEL": "\u007F", + "/controlDLE": "\u0010", + "/controlEM": "\u0019", + "/controlENQ": "\u0005", + "/controlEOT": "\u0004", + "/controlESC": "\u001B", + "/controlETB": "\u0017", + "/controlETX": "\u0003", + "/controlFF": "\u000C", + "/controlFS": "\u001C", + "/controlGS": "\u001D", + "/controlHT": "\u0009", + "/controlKnobs": "\u1F39B", + "/controlLF": "\u000A", + "/controlNAK": "\u0015", + "/controlRS": "\u001E", + "/controlSI": "\u000F", + "/controlSO": "\u000E", + "/controlSOT": "\u0002", + "/controlSTX": "\u0001", + "/controlSUB": "\u001A", + "/controlSYN": "\u0016", + "/controlUS": "\u001F", + "/controlVT": "\u000B", + "/convavediamondwhite": "\u27E1", + "/convenienceStore": "\u1F3EA", + "/cookedRice": "\u1F35A", + "/cookie": "\u1F36A", + "/cooking": "\u1F373", + "/coolsquare": "\u1F192", + "/coproductarray": "\u2210", + "/copyideographiccircled": "\u32A2", + "/copyright": "\u00A9", + "/copyrightsans": "\uF8E9", + "/copyrightserif": "\uF6D9", + "/cornerbottomleft": "\u231E", + "/cornerbottomright": "\u231F", + "/cornerbracketleft": "\u300C", + "/cornerbracketlefthalfwidth": "\uFF62", + "/cornerbracketleftvertical": "\uFE41", + "/cornerbracketright": "\u300D", + "/cornerbracketrighthalfwidth": "\uFF63", + "/cornerbracketrightvertical": "\uFE42", + "/cornerdotupleft": "\u27D4", + "/cornertopleft": "\u231C", + "/cornertopright": "\u231D", + "/coroniseditorial": "\u2E0E", + "/corporationsquare": "\u337F", + "/correctideographiccircled": "\u32A3", + "/corresponds": "\u2258", + "/cosquare": "\u33C7", + "/couchAndLamp": "\u1F6CB", + "/counterbore": "\u2334", + "/countersink": "\u2335", + "/coupleHeart": "\u1F491", + "/coverkgfullwidth": "\u33C6", + "/coverkgsquare": "\u33C6", + "/cow": "\u1F404", + "/cowFace": "\u1F42E", + "/cpalatalhook": "\uA794", + "/cparen": "\u249E", + "/cparenthesized": "\u249E", + "/creditCard": "\u1F4B3", + "/crescentMoon": "\u1F319", + "/creversed": "\u2184", + "/cricketBatAndBall": "\u1F3CF", + "/crocodile": "\u1F40A", + "/cropbottomleft": "\u230D", + "/cropbottomright": "\u230C", + "/croptopleft": "\u230F", + "/croptopright": "\u230E", + "/crossPommee": "\u1F542", + "/crossPommeeHalf-circleBelow": "\u1F541", + "/crossedFlags": "\u1F38C", + "/crossedswords": "\u2694", + "/crossinglanes": "\u26CC", + "/crossmod": "\u02DF", + "/crossofjerusalem": "\u2629", + "/crossoflorraine": "\u2628", + "/crossonshieldblack": "\u26E8", + "/crown": "\u1F451", + "/crrn:rupee": "\u20A8", + "/cruzeiro": "\u20A2", + "/cryingCatFace": "\u1F63F", + "/cryingFace": "\u1F622", + "/crystalBall": "\u1F52E", + "/cstretched": "\u0297", + "/cstroke": "\u023C", + "/cuatrillo": "\uA72D", + "/cuatrillocomma": "\uA72F", + "/curlyand": "\u22CF", + "/curlylogicaland": "\u22CF", + "/curlylogicalor": "\u22CE", + "/curlyor": "\u22CE", + "/currency": "\u00A4", + "/currencyExchange": "\u1F4B1", + "/curryAndRice": "\u1F35B", + "/custard": "\u1F36E", + "/customeraccountnumber": "\u2449", + "/customs": "\u1F6C3", + "/cyclone": "\u1F300", + "/cylindricity": "\u232D", + "/cyrBreve": "\uF6D1", + "/cyrFlex": "\uF6D2", + "/cyrbreve": "\uF6D4", + "/cyrflex": "\uF6D5", + "/d": "\u0064", + "/daarmenian": "\u0564", + "/daasusquare": "\u3324", + "/dabengali": "\u09A6", + "/dad": "\u0636", + "/dad.fina": "\uFEBE", + "/dad.init": "\uFEBF", + "/dad.init_alefmaksura.fina": "\uFD07", + "/dad.init_hah.fina": "\uFC23", + "/dad.init_hah.medi": "\uFCB5", + "/dad.init_jeem.fina": "\uFC22", + "/dad.init_jeem.medi": "\uFCB4", + "/dad.init_khah.fina": "\uFC24", + "/dad.init_khah.medi": "\uFCB6", + "/dad.init_khah.medi_meem.medi": "\uFD70", + "/dad.init_meem.fina": "\uFC25", + "/dad.init_meem.medi": "\uFCB7", + "/dad.init_reh.fina": "\uFD10", + "/dad.init_yeh.fina": "\uFD08", + "/dad.isol": "\uFEBD", + "/dad.medi": "\uFEC0", + "/dad.medi_alefmaksura.fina": "\uFD23", + "/dad.medi_hah.medi_alefmaksura.fina": "\uFD6E", + "/dad.medi_hah.medi_yeh.fina": "\uFDAB", + "/dad.medi_khah.medi_meem.fina": "\uFD6F", + "/dad.medi_reh.fina": "\uFD2C", + "/dad.medi_yeh.fina": "\uFD24", + "/dadarabic": "\u0636", + "/daddotbelow": "\u06FB", + "/dadeva": "\u0926", + "/dadfinalarabic": "\uFEBE", + "/dadinitialarabic": "\uFEBF", + "/dadmedialarabic": "\uFEC0", + "/dafullwidth": "\u3372", + "/dagesh": "\u05BC", + "/dagesh:hb": "\u05BC", + "/dageshhebrew": "\u05BC", + "/dagger": "\u2020", + "/daggerKnife": "\u1F5E1", + "/daggerdbl": "\u2021", + "/daggerwithguardleft": "\u2E36", + "/daggerwithguardright": "\u2E37", + "/dagujarati": "\u0AA6", + "/dagurmukhi": "\u0A26", + "/dahal": "\u068C", + "/dahal.fina": "\uFB85", + "/dahal.isol": "\uFB84", + "/dahiragana": "\u3060", + "/dakatakana": "\u30C0", + "/dal": "\u062F", + "/dal.fina": "\uFEAA", + "/dal.isol": "\uFEA9", + "/dalInvertedSmallVBelow": "\u075A", + "/dalTwoDotsVerticallyBelowSmallTah": "\u0759", + "/dalarabic": "\u062F", + "/daldotbelow": "\u068A", + "/daldotbelowtahsmall": "\u068B", + "/daldownthreedotsabove": "\u068F", + "/dalet": "\u05D3", + "/dalet:hb": "\u05D3", + "/daletdagesh": "\uFB33", + "/daletdageshhebrew": "\uFB33", + "/dalethatafpatah": "\u05D3", + "/dalethatafpatahhebrew": "\u05D3", + "/dalethatafsegol": "\u05D3", + "/dalethatafsegolhebrew": "\u05D3", + "/dalethebrew": "\u05D3", + "/dalethiriq": "\u05D3", + "/dalethiriqhebrew": "\u05D3", + "/daletholam": "\u05D3", + "/daletholamhebrew": "\u05D3", + "/daletpatah": "\u05D3", + "/daletpatahhebrew": "\u05D3", + "/daletqamats": "\u05D3", + "/daletqamatshebrew": "\u05D3", + "/daletqubuts": "\u05D3", + "/daletqubutshebrew": "\u05D3", + "/daletsegol": "\u05D3", + "/daletsegolhebrew": "\u05D3", + "/daletsheva": "\u05D3", + "/daletshevahebrew": "\u05D3", + "/dalettsere": "\u05D3", + "/dalettserehebrew": "\u05D3", + "/daletwide:hb": "\uFB22", + "/daletwithdagesh:hb": "\uFB33", + "/dalfinalarabic": "\uFEAA", + "/dalfourdotsabove": "\u0690", + "/dalinvertedV": "\u06EE", + "/dalring": "\u0689", + "/damahaprana": "\uA9A3", + "/damma": "\u064F", + "/dammaIsol": "\uFE78", + "/dammaMedi": "\uFE79", + "/dammaarabic": "\u064F", + "/dammalowarabic": "\u064F", + "/dammareversed": "\u065D", + "/dammasmall": "\u0619", + "/dammatan": "\u064C", + "/dammatanIsol": "\uFE72", + "/dammatanaltonearabic": "\u064C", + "/dammatanarabic": "\u064C", + "/dancer": "\u1F483", + "/danda": "\u0964", + "/dango": "\u1F361", + "/darga:hb": "\u05A7", + "/dargahebrew": "\u05A7", + "/dargalefthebrew": "\u05A7", + "/darkShade": "\u2593", + "/darkSunglasses": "\u1F576", + "/dashwithupturnleft": "\u2E43", + "/dasiacmbcyr": "\u0485", + "/dasiapneumatacyrilliccmb": "\u0485", + "/dateseparator": "\u060D", + "/dayeighteentelegraph": "\u33F1", + "/dayeighttelegraph": "\u33E7", + "/dayeleventelegraph": "\u33EA", + "/dayfifteentelegraph": "\u33EE", + "/dayfivetelegraph": "\u33E4", + "/dayfourteentelegraph": "\u33ED", + "/dayfourtelegraph": "\u33E3", + "/daynineteentelegraph": "\u33F2", + "/dayninetelegraph": "\u33E8", + "/dayonetelegraph": "\u33E0", + "/dayseventeentelegraph": "\u33F0", + "/dayseventelegraph": "\u33E6", + "/daysixteentelegraph": "\u33EF", + "/daysixtelegraph": "\u33E5", + "/daytentelegraph": "\u33E9", + "/daythirteentelegraph": "\u33EC", + "/daythirtyonetelegraph": "\u33FE", + "/daythirtytelegraph": "\u33FD", + "/daythreetelegraph": "\u33E2", + "/daytwelvetelegraph": "\u33EB", + "/daytwentyeighttelegraph": "\u33FB", + "/daytwentyfivetelegraph": "\u33F8", + "/daytwentyfourtelegraph": "\u33F7", + "/daytwentyninetelegraph": "\u33FC", + "/daytwentyonetelegraph": "\u33F4", + "/daytwentyseventelegraph": "\u33FA", + "/daytwentysixtelegraph": "\u33F9", + "/daytwentytelegraph": "\u33F3", + "/daytwentythreetelegraph": "\u33F6", + "/daytwentytwotelegraph": "\u33F5", + "/daytwotelegraph": "\u33E1", + "/dbdigraph": "\u0238", + "/dbfullwidth": "\u33C8", + "/dblGrave": "\uF6D3", + "/dblanglebracketleft": "\u300A", + "/dblanglebracketleftvertical": "\uFE3D", + "/dblanglebracketright": "\u300B", + "/dblanglebracketrightvertical": "\uFE3E", + "/dblarchinvertedbelowcmb": "\u032B", + "/dblarrowNE": "\u21D7", + "/dblarrowNW": "\u21D6", + "/dblarrowSE": "\u21D8", + "/dblarrowSW": "\u21D9", + "/dblarrowdown": "\u21D3", + "/dblarrowleft": "\u21D4", + "/dblarrowleftright": "\u21D4", + "/dblarrowleftrightstroke": "\u21CE", + "/dblarrowleftstroke": "\u21CD", + "/dblarrowright": "\u21D2", + "/dblarrowrightstroke": "\u21CF", + "/dblarrowup": "\u21D1", + "/dblarrowupdown": "\u21D5", + "/dbldanda": "\u0965", + "/dbldnhorz": "\u2566", + "/dbldnleft": "\u2557", + "/dbldnright": "\u2554", + "/dblgrave": "\uF6D6", + "/dblgravecmb": "\u030F", + "/dblhorz": "\u2550", + "/dblintegral": "\u222C", + "/dbllowline": "\u2017", + "/dbllowlinecmb": "\u0333", + "/dbloverlinecmb": "\u033F", + "/dblprimemod": "\u02BA", + "/dblstrokearrowdown": "\u21DF", + "/dblstrokearrowup": "\u21DE", + "/dbluphorz": "\u2569", + "/dblupleft": "\u255D", + "/dblupright": "\u255A", + "/dblvert": "\u2551", + "/dblverthorz": "\u256C", + "/dblverticalbar": "\u2016", + "/dblverticallineabovecmb": "\u030E", + "/dblvertleft": "\u2563", + "/dblvertright": "\u2560", + "/dbopomofo": "\u3109", + "/dbsquare": "\u33C8", + "/dcaron": "\u010F", + "/dcedilla": "\u1E11", + "/dchecyr": "\u052D", + "/dcircle": "\u24D3", + "/dcircumflexbelow": "\u1E13", + "/dcroat": "\u0111", + "/dcurl": "\u0221", + "/ddabengali": "\u09A1", + "/ddadeva": "\u0921", + "/ddagujarati": "\u0AA1", + "/ddagurmukhi": "\u0A21", + "/ddahal": "\u068D", + "/ddahal.fina": "\uFB83", + "/ddahal.isol": "\uFB82", + "/ddal": "\u0688", + "/ddal.fina": "\uFB89", + "/ddal.isol": "\uFB88", + "/ddalarabic": "\u0688", + "/ddalfinalarabic": "\uFB89", + "/ddamahaprana": "\uA99E", + "/ddblstruckitalic": "\u2146", + "/dddhadeva": "\u095C", + "/ddhabengali": "\u09A2", + "/ddhadeva": "\u0922", + "/ddhagujarati": "\u0AA2", + "/ddhagurmukhi": "\u0A22", + "/ddot": "\u1E0B", + "/ddotaccent": "\u1E0B", + "/ddotbelow": "\u1E0D", + "/decembertelegraph": "\u32CB", + "/deciduousTree": "\u1F333", + "/decimalexponent": "\u23E8", + "/decimalseparatorarabic": "\u066B", + "/decimalseparatorpersian": "\u066B", + "/decreaseFontSize": "\u1F5DB", + "/decyr": "\u0434", + "/decyrillic": "\u0434", + "/degree": "\u00B0", + "/degreecelsius": "\u2103", + "/degreefahrenheit": "\u2109", + "/dehi:hb": "\u05AD", + "/dehihebrew": "\u05AD", + "/dehiragana": "\u3067", + "/deicoptic": "\u03EF", + "/dekatakana": "\u30C7", + "/dekomicyr": "\u0501", + "/deldiaeresisfunc": "\u2362", + "/deleteleft": "\u232B", + "/deleteright": "\u2326", + "/deliveryTruck": "\u1F69A", + "/delstilefunc": "\u2352", + "/delta": "\u03B4", + "/deltaequal": "\u225C", + "/deltastilefunc": "\u234B", + "/deltaturned": "\u018D", + "/deltaunderlinefunc": "\u2359", + "/deltildefunc": "\u236B", + "/denominatorminusonenumeratorbengali": "\u09F8", + "/dentistrybottomverticalleft": "\u23CC", + "/dentistrybottomverticalright": "\u23BF", + "/dentistrycircledownhorizontal": "\u23C1", + "/dentistrycircleuphorizontal": "\u23C2", + "/dentistrycirclevertical": "\u23C0", + "/dentistrydownhorizontal": "\u23C9", + "/dentistrytopverticalleft": "\u23CB", + "/dentistrytopverticalright": "\u23BE", + "/dentistrytriangledownhorizontal": "\u23C4", + "/dentistrytriangleuphorizontal": "\u23C5", + "/dentistrytrianglevertical": "\u23C3", + "/dentistryuphorizontal": "\u23CA", + "/dentistrywavedownhorizontal": "\u23C7", + "/dentistrywaveuphorizontal": "\u23C8", + "/dentistrywavevertical": "\u23C6", + "/departmentStore": "\u1F3EC", + "/derelictHouseBuilding": "\u1F3DA", + "/desert": "\u1F3DC", + "/desertIsland": "\u1F3DD", + "/desisquare": "\u3325", + "/desktopComputer": "\u1F5A5", + "/desktopWindow": "\u1F5D4", + "/deva:a": "\u0905", + "/deva:aa": "\u0906", + "/deva:aasign": "\u093E", + "/deva:abbreviation": "\u0970", + "/deva:acandra": "\u0972", + "/deva:acute": "\u0954", + "/deva:ai": "\u0910", + "/deva:aisign": "\u0948", + "/deva:anudatta": "\u0952", + "/deva:anusvara": "\u0902", + "/deva:ashort": "\u0904", + "/deva:au": "\u0914", + "/deva:ausign": "\u094C", + "/deva:avagraha": "\u093D", + "/deva:aw": "\u0975", + "/deva:awsign": "\u094F", + "/deva:ba": "\u092C", + "/deva:bba": "\u097F", + "/deva:bha": "\u092D", + "/deva:ca": "\u091A", + "/deva:candrabindu": "\u0901", + "/deva:candrabinduinverted": "\u0900", + "/deva:cha": "\u091B", + "/deva:da": "\u0926", + "/deva:danda": "\u0964", + "/deva:dbldanda": "\u0965", + "/deva:dda": "\u0921", + "/deva:ddda": "\u097E", + "/deva:dddha": "\u095C", + "/deva:ddha": "\u0922", + "/deva:dha": "\u0927", + "/deva:dothigh": "\u0971", + "/deva:e": "\u090F", + "/deva:ecandra": "\u090D", + "/deva:eight": "\u096E", + "/deva:eshort": "\u090E", + "/deva:esign": "\u0947", + "/deva:esigncandra": "\u0945", + "/deva:esignprishthamatra": "\u094E", + "/deva:esignshort": "\u0946", + "/deva:fa": "\u095E", + "/deva:five": "\u096B", + "/deva:four": "\u096A", + "/deva:ga": "\u0917", + "/deva:gga": "\u097B", + "/deva:gha": "\u0918", + "/deva:ghha": "\u095A", + "/deva:glottalstop": "\u097D", + "/deva:grave": "\u0953", + "/deva:ha": "\u0939", + "/deva:i": "\u0907", + "/deva:ii": "\u0908", + "/deva:iisign": "\u0940", + "/deva:isign": "\u093F", + "/deva:ja": "\u091C", + "/deva:jha": "\u091D", + "/deva:jja": "\u097C", + "/deva:ka": "\u0915", + "/deva:kha": "\u0916", + "/deva:khha": "\u0959", + "/deva:la": "\u0932", + "/deva:lla": "\u0933", + "/deva:llla": "\u0934", + "/deva:llvocal": "\u0961", + "/deva:llvocalsign": "\u0963", + "/deva:lvocal": "\u090C", + "/deva:lvocalsign": "\u0962", + "/deva:ma": "\u092E", + "/deva:marwaridda": "\u0978", + "/deva:na": "\u0928", + "/deva:nga": "\u0919", + "/deva:nine": "\u096F", + "/deva:nna": "\u0923", + "/deva:nnna": "\u0929", + "/deva:nukta": "\u093C", + "/deva:nya": "\u091E", + "/deva:o": "\u0913", + "/deva:ocandra": "\u0911", + "/deva:oe": "\u0973", + "/deva:oesign": "\u093A", + "/deva:om": "\u0950", + "/deva:one": "\u0967", + "/deva:ooe": "\u0974", + "/deva:ooesign": "\u093B", + "/deva:oshort": "\u0912", + "/deva:osign": "\u094B", + "/deva:osigncandra": "\u0949", + "/deva:osignshort": "\u094A", + "/deva:pa": "\u092A", + "/deva:pha": "\u092B", + "/deva:qa": "\u0958", + "/deva:ra": "\u0930", + "/deva:rha": "\u095D", + "/deva:rra": "\u0931", + "/deva:rrvocal": "\u0960", + "/deva:rrvocalsign": "\u0944", + "/deva:rvocal": "\u090B", + "/deva:rvocalsign": "\u0943", + "/deva:sa": "\u0938", + "/deva:seven": "\u096D", + "/deva:sha": "\u0936", + "/deva:signelongcandra": "\u0955", + "/deva:six": "\u096C", + "/deva:ssa": "\u0937", + "/deva:ta": "\u0924", + "/deva:tha": "\u0925", + "/deva:three": "\u0969", + "/deva:tta": "\u091F", + "/deva:ttha": "\u0920", + "/deva:two": "\u0968", + "/deva:u": "\u0909", + "/deva:udatta": "\u0951", + "/deva:ue": "\u0976", + "/deva:uesign": "\u0956", + "/deva:usign": "\u0941", + "/deva:uu": "\u090A", + "/deva:uue": "\u0977", + "/deva:uuesign": "\u0957", + "/deva:uusign": "\u0942", + "/deva:va": "\u0935", + "/deva:virama": "\u094D", + "/deva:visarga": "\u0903", + "/deva:ya": "\u092F", + "/deva:yaheavy": "\u097A", + "/deva:yya": "\u095F", + "/deva:za": "\u095B", + "/deva:zero": "\u0966", + "/deva:zha": "\u0979", + "/dezh": "\u02A4", + "/dfemaledbl": "\u26A2", + "/dhabengali": "\u09A7", + "/dhadeva": "\u0927", + "/dhagujarati": "\u0AA7", + "/dhagurmukhi": "\u0A27", + "/dhook": "\u0257", + "/diaeresisgreaterfunc": "\u2369", + "/dialytikatonos": "\u0385", + "/dialytikatonoscmb": "\u0344", + "/diametersign": "\u2300", + "/diamond": "\u2666", + "/diamondShapeADotInside": "\u1F4A0", + "/diamondinsquarewhite": "\u26CB", + "/diamondoperator": "\u22C4", + "/diamondsuitwhite": "\u2662", + "/diamondunderlinefunc": "\u235A", + "/diamondwhitewithdiamondsmallblack": "\u25C8", + "/diefive": "\u2684", + "/diefour": "\u2683", + "/dieone": "\u2680", + "/dieresis": "\u00A8", + "/dieresisacute": "\uF6D7", + "/dieresisbelowcmb": "\u0324", + "/dieresiscmb": "\u0308", + "/dieresisgrave": "\uF6D8", + "/dieresistilde": "\u1FC1", + "/dieresistonos": "\u0385", + "/dieselLocomotive": "\u1F6F2", + "/diesix": "\u2685", + "/diethree": "\u2682", + "/dietwo": "\u2681", + "/differencebetween": "\u224F", + "/digamma": "\u03DD", + "/digammapamphylian": "\u0377", + "/digramgreateryang": "\u268C", + "/digramgreateryin": "\u268F", + "/digramlesseryang": "\u268E", + "/digramlesseryin": "\u268D", + "/dihiragana": "\u3062", + "/dikatakana": "\u30C2", + "/dimensionorigin": "\u2331", + "/dingbatSAns-serifzerocircle": "\u1F10B", + "/dingbatSAns-serifzerocircleblack": "\u1F10C", + "/dinsular": "\uA77A", + "/directHit": "\u1F3AF", + "/directcurrentformtwo": "\u2393", + "/dirgamurevowel": "\uA9BB", + "/disabledcar": "\u26CD", + "/disappointedButRelievedFace": "\u1F625", + "/disappointedFace": "\u1F61E", + "/discontinuousunderline": "\u2382", + "/dittomark": "\u3003", + "/divide": "\u00F7", + "/divides": "\u2223", + "/divisionslash": "\u2215", + "/divisiontimes": "\u22C7", + "/divorce": "\u26AE", + "/dizzy": "\u1F4AB", + "/dizzyFace": "\u1F635", + "/djecyr": "\u0452", + "/djecyrillic": "\u0452", + "/djekomicyr": "\u0503", + "/dkshade": "\u2593", + "/dlfullwidth": "\u3397", + "/dlinebelow": "\u1E0F", + "/dlogicalorsquare": "\u27CF", + "/dlogicalsquare": "\u27CE", + "/dlsquare": "\u3397", + "/dm2fullwidth": "\u3378", + "/dm3fullwidth": "\u3379", + "/dmacron": "\u0111", + "/dmaledbl": "\u26A3", + "/dmfullwidth": "\u3377", + "/dmonospace": "\uFF44", + "/dnblock": "\u2584", + "/dndblhorzsng": "\u2565", + "/dndblleftsng": "\u2556", + "/dndblrightsng": "\u2553", + "/dngb:airplane": "\u2708", + "/dngb:arrowfeatheredblackNE": "\u27B6", + "/dngb:arrowfeatheredblackSE": "\u27B4", + "/dngb:arrowfeatheredblackheavyNE": "\u27B9", + "/dngb:arrowfeatheredblackheavySE": "\u27B7", + "/dngb:arrowheadrightblack": "\u27A4", + "/dngb:arrowheadrightthreeDbottomlight": "\u27A3", + "/dngb:arrowheadrightthreeDtoplight": "\u27A2", + "/dngb:arrowheavyNE": "\u279A", + "/dngb:arrowheavySE": "\u2798", + "/dngb:arrowrightbacktiltedshadowedwhite": "\u27AB", + "/dngb:arrowrightblack": "\u27A1", + "/dngb:arrowrightcircledwhiteheavy": "\u27B2", + "/dngb:arrowrightcurvedownblackheavy": "\u27A5", + "/dngb:arrowrightcurveupblackheavy": "\u27A6", + "/dngb:arrowrightfeatheredblack": "\u27B5", + "/dngb:arrowrightfeatheredblackheavy": "\u27B8", + "/dngb:arrowrightfeatheredwhite": "\u27B3", + "/dngb:arrowrightfronttiltedshadowedwhite": "\u27AC", + "/dngb:arrowrightheavy": "\u2799", + "/dngb:arrowrightleftshadedwhite": "\u27AA", + "/dngb:arrowrightoutlinedopen": "\u27BE", + "/dngb:arrowrightpointed": "\u279B", + "/dngb:arrowrightpointedblackheavy": "\u27A8", + "/dngb:arrowrightrightshadedwhite": "\u27A9", + "/dngb:arrowrightroundheavy": "\u279C", + "/dngb:arrowrightsquatblack": "\u27A7", + "/dngb:arrowrighttriangle": "\u279D", + "/dngb:arrowrighttriangledashed": "\u279F", + "/dngb:arrowrighttriangledashedheavy": "\u27A0", + "/dngb:arrowrighttriangleheavy": "\u279E", + "/dngb:arrowrightwedge": "\u27BC", + "/dngb:arrowrightwedgeheavy": "\u27BD", + "/dngb:arrowrightwideheavy": "\u2794", + "/dngb:arrowshadowrightlowerwhiteheavy": "\u27AD", + "/dngb:arrowshadowrightnotchedlowerwhite": "\u27AF", + "/dngb:arrowshadowrightnotchedupperwhite": "\u27B1", + "/dngb:arrowshadowrightupperwhiteheavy": "\u27AE", + "/dngb:arrowteardropright": "\u27BA", + "/dngb:arrowteardroprightheavy": "\u27BB", + "/dngb:asteriskballoon": "\u2749", + "/dngb:asteriskballoonfour": "\u2723", + "/dngb:asteriskballoonheavyfour": "\u2724", + "/dngb:asteriskcentreopen": "\u2732", + "/dngb:asteriskclubfour": "\u2725", + "/dngb:asteriskheavy": "\u2731", + "/dngb:asteriskpointedsixteen": "\u273A", + "/dngb:asteriskteardrop": "\u273B", + "/dngb:asteriskteardropcentreopen": "\u273C", + "/dngb:asteriskteardropfour": "\u2722", + "/dngb:asteriskteardropheavy": "\u273D", + "/dngb:asteriskteardroppinwheelheavy": "\u2743", + "/dngb:asteriskteardroppropellereight": "\u274A", + "/dngb:asteriskteardroppropellerheavyeight": "\u274B", + "/dngb:ballotx": "\u2717", + "/dngb:ballotxheavy": "\u2718", + "/dngb:bracketleftpointedangleheavyornament": "\u2770", + "/dngb:bracketleftpointedanglemediumornament": "\u276C", + "/dngb:bracketrightpointedangleheavyornament": "\u2771", + "/dngb:bracketrightpointedanglemediumornament": "\u276D", + "/dngb:bracketshellleftlightornament": "\u2772", + "/dngb:bracketshellrightlightornament": "\u2773", + "/dngb:check": "\u2713", + "/dngb:checkheavy": "\u2714", + "/dngb:checkwhiteheavy": "\u2705", + "/dngb:chevronsnowflakeheavy": "\u2746", + "/dngb:circleshadowedwhite": "\u274D", + "/dngb:commaheavydoubleornament": "\u275E", + "/dngb:commaheavydoubleturnedornament": "\u275D", + "/dngb:commaheavyornament": "\u275C", + "/dngb:commaheavyturnedornament": "\u275B", + "/dngb:compasstarpointedblackeight": "\u2737", + "/dngb:compasstarpointedblackheavyeight": "\u2738", + "/dngb:cross": "\u274C", + "/dngb:crosscentreopen": "\u271B", + "/dngb:crosscentreopenheavy": "\u271C", + "/dngb:curlybracketleftmediumornament": "\u2774", + "/dngb:curlybracketrightmediumornament": "\u2775", + "/dngb:curlyloop": "\u27B0", + "/dngb:curlyloopdouble": "\u27BF", + "/dngb:curvedstemparagraphsignornament": "\u2761", + "/dngb:diamondminusxblackwhite": "\u2756", + "/dngb:divisionsignheavy": "\u2797", + "/dngb:eightnegativecircled": "\u277D", + "/dngb:eightsanscircled": "\u2787", + "/dngb:eightsansnegativecircled": "\u2791", + "/dngb:envelope": "\u2709", + "/dngb:exclamationheavy": "\u2757", + "/dngb:exclamationheavyornament": "\u2762", + "/dngb:exclamationwhiteornament": "\u2755", + "/dngb:fivenegativecircled": "\u277A", + "/dngb:fivesanscircled": "\u2784", + "/dngb:fivesansnegativecircled": "\u278E", + "/dngb:floralheart": "\u2766", + "/dngb:floralheartbulletrotated": "\u2767", + "/dngb:floretteblack": "\u273F", + "/dngb:floretteoutlinedpetalledblackeight": "\u2741", + "/dngb:florettepetalledblackwhitesix": "\u273E", + "/dngb:florettewhite": "\u2740", + "/dngb:fournegativecircled": "\u2779", + "/dngb:foursanscircled": "\u2783", + "/dngb:foursansnegativecircled": "\u278D", + "/dngb:greekcrossheavy": "\u271A", + "/dngb:greekcrossoutlined": "\u2719", + "/dngb:heartblackheavy": "\u2764", + "/dngb:heartbulletrotatedblackheavy": "\u2765", + "/dngb:heartexclamationheavyornament": "\u2763", + "/dngb:hvictory": "\u270C", + "/dngb:hwriting": "\u270D", + "/dngb:latincross": "\u271D", + "/dngb:latincrossoutlined": "\u271F", + "/dngb:latincrossshadowedwhite": "\u271E", + "/dngb:lowcommaheavydoubleornament": "\u2760", + "/dngb:lowcommaheavyornament": "\u275F", + "/dngb:maltesecross": "\u2720", + "/dngb:minussignheavy": "\u2796", + "/dngb:multiplicationx": "\u2715", + "/dngb:multiplicationxheavy": "\u2716", + "/dngb:nibblack": "\u2712", + "/dngb:nibwhite": "\u2711", + "/dngb:ninenegativecircled": "\u277E", + "/dngb:ninesanscircled": "\u2788", + "/dngb:ninesansnegativecircled": "\u2792", + "/dngb:onenegativecircled": "\u2776", + "/dngb:onesanscircled": "\u2780", + "/dngb:onesansnegativecircled": "\u278A", + "/dngb:parenthesisleftflattenedmediumornament": "\u276A", + "/dngb:parenthesisleftmediumornament": "\u2768", + "/dngb:parenthesisrightflattenedmediumornament": "\u276B", + "/dngb:parenthesisrightmediumornament": "\u2769", + "/dngb:pencil": "\u270F", + "/dngb:pencillowerright": "\u270E", + "/dngb:pencilupperright": "\u2710", + "/dngb:plussignheavy": "\u2795", + "/dngb:questionblackornament": "\u2753", + "/dngb:questionwhiteornament": "\u2754", + "/dngb:quotationleftpointedangleheavyornament": "\u276E", + "/dngb:quotationrightpointedangleheavyornament": "\u276F", + "/dngb:raisedfist": "\u270A", + "/dngb:raisedh": "\u270B", + "/dngb:safetyscissorsblack": "\u2700", + "/dngb:scissorsblack": "\u2702", + "/dngb:scissorslowerblade": "\u2703", + "/dngb:scissorsupperblade": "\u2701", + "/dngb:scissorswhite": "\u2704", + "/dngb:sevennegativecircled": "\u277C", + "/dngb:sevensanscircled": "\u2786", + "/dngb:sevensansnegativecircled": "\u2790", + "/dngb:sixnegativecircled": "\u277B", + "/dngb:sixsanscircled": "\u2785", + "/dngb:sixsansnegativecircled": "\u278F", + "/dngb:snowflake": "\u2744", + "/dngb:snowflaketight": "\u2745", + "/dngb:sparkle": "\u2747", + "/dngb:sparkleheavy": "\u2748", + "/dngb:sparkles": "\u2728", + "/dngb:spokedasteriskeight": "\u2733", + "/dngb:squaredcrossnegative": "\u274E", + "/dngb:squarelowerrightshadowedwhite": "\u2751", + "/dngb:squareshadowlowerrightwhite": "\u274F", + "/dngb:squareshadowupperrightwhite": "\u2750", + "/dngb:squareupperrightshadowedwhite": "\u2752", + "/dngb:starcentreblackwhite": "\u272C", + "/dngb:starcentreopenblack": "\u272B", + "/dngb:starcentreopenpointedcircledeight": "\u2742", + "/dngb:starcircledwhite": "\u272A", + "/dngb:starofdavid": "\u2721", + "/dngb:staroutlinedblack": "\u272D", + "/dngb:staroutlinedblackheavy": "\u272E", + "/dngb:staroutlinedstresswhite": "\u2729", + "/dngb:starpinwheel": "\u272F", + "/dngb:starpointedblackeight": "\u2734", + "/dngb:starpointedblackfour": "\u2726", + "/dngb:starpointedblacksix": "\u2736", + "/dngb:starpointedblacktwelve": "\u2739", + "/dngb:starpointedpinwheeleight": "\u2735", + "/dngb:starpointedwhitefour": "\u2727", + "/dngb:starshadowedwhite": "\u2730", + "/dngb:tapedrive": "\u2707", + "/dngb:telephonelocationsign": "\u2706", + "/dngb:tennegativecircled": "\u277F", + "/dngb:tensanscircled": "\u2789", + "/dngb:tensansnegativecircled": "\u2793", + "/dngb:threenegativecircled": "\u2778", + "/dngb:threesanscircled": "\u2782", + "/dngb:threesansnegativecircled": "\u278C", + "/dngb:twonegativecircled": "\u2777", + "/dngb:twosanscircled": "\u2781", + "/dngb:twosansnegativecircled": "\u278B", + "/dngb:verticalbarheavy": "\u275A", + "/dngb:verticalbarlight": "\u2758", + "/dngb:verticalbarmedium": "\u2759", + "/dnheavyhorzlight": "\u2530", + "/dnheavyleftlight": "\u2512", + "/dnheavyleftuplight": "\u2527", + "/dnheavyrightlight": "\u250E", + "/dnheavyrightuplight": "\u251F", + "/dnheavyuphorzlight": "\u2541", + "/dnlighthorzheavy": "\u252F", + "/dnlightleftheavy": "\u2511", + "/dnlightleftupheavy": "\u2529", + "/dnlightrightheavy": "\u250D", + "/dnlightrightupheavy": "\u2521", + "/dnlightuphorzheavy": "\u2547", + "/dnsnghorzdbl": "\u2564", + "/dnsngleftdbl": "\u2555", + "/dnsngrightdbl": "\u2552", + "/doNotLitter": "\u1F6AF", + "/dochadathai": "\u0E0E", + "/document": "\u1F5CE", + "/documentPicture": "\u1F5BB", + "/documentText": "\u1F5B9", + "/documentTextAndPicture": "\u1F5BA", + "/dodekthai": "\u0E14", + "/doesnotcontainasnormalsubgroorequalup": "\u22ED", + "/doesnotcontainasnormalsubgroup": "\u22EB", + "/doesnotdivide": "\u2224", + "/doesnotforce": "\u22AE", + "/doesnotprecede": "\u2280", + "/doesnotprecedeorequal": "\u22E0", + "/doesnotprove": "\u22AC", + "/doesnotsucceed": "\u2281", + "/doesnotsucceedorequal": "\u22E1", + "/dog": "\u1F415", + "/dogFace": "\u1F436", + "/dohiragana": "\u3069", + "/dokatakana": "\u30C9", + "/dollar": "\u0024", + "/dollarinferior": "\uF6E3", + "/dollarmonospace": "\uFF04", + "/dollaroldstyle": "\uF724", + "/dollarsmall": "\uFE69", + "/dollarsuperior": "\uF6E4", + "/dolphin": "\u1F42C", + "/dominohorizontal_00_00": "\u1F031", + "/dominohorizontal_00_01": "\u1F032", + "/dominohorizontal_00_02": "\u1F033", + "/dominohorizontal_00_03": "\u1F034", + "/dominohorizontal_00_04": "\u1F035", + "/dominohorizontal_00_05": "\u1F036", + "/dominohorizontal_00_06": "\u1F037", + "/dominohorizontal_01_00": "\u1F038", + "/dominohorizontal_01_01": "\u1F039", + "/dominohorizontal_01_02": "\u1F03A", + "/dominohorizontal_01_03": "\u1F03B", + "/dominohorizontal_01_04": "\u1F03C", + "/dominohorizontal_01_05": "\u1F03D", + "/dominohorizontal_01_06": "\u1F03E", + "/dominohorizontal_02_00": "\u1F03F", + "/dominohorizontal_02_01": "\u1F040", + "/dominohorizontal_02_02": "\u1F041", + "/dominohorizontal_02_03": "\u1F042", + "/dominohorizontal_02_04": "\u1F043", + "/dominohorizontal_02_05": "\u1F044", + "/dominohorizontal_02_06": "\u1F045", + "/dominohorizontal_03_00": "\u1F046", + "/dominohorizontal_03_01": "\u1F047", + "/dominohorizontal_03_02": "\u1F048", + "/dominohorizontal_03_03": "\u1F049", + "/dominohorizontal_03_04": "\u1F04A", + "/dominohorizontal_03_05": "\u1F04B", + "/dominohorizontal_03_06": "\u1F04C", + "/dominohorizontal_04_00": "\u1F04D", + "/dominohorizontal_04_01": "\u1F04E", + "/dominohorizontal_04_02": "\u1F04F", + "/dominohorizontal_04_03": "\u1F050", + "/dominohorizontal_04_04": "\u1F051", + "/dominohorizontal_04_05": "\u1F052", + "/dominohorizontal_04_06": "\u1F053", + "/dominohorizontal_05_00": "\u1F054", + "/dominohorizontal_05_01": "\u1F055", + "/dominohorizontal_05_02": "\u1F056", + "/dominohorizontal_05_03": "\u1F057", + "/dominohorizontal_05_04": "\u1F058", + "/dominohorizontal_05_05": "\u1F059", + "/dominohorizontal_05_06": "\u1F05A", + "/dominohorizontal_06_00": "\u1F05B", + "/dominohorizontal_06_01": "\u1F05C", + "/dominohorizontal_06_02": "\u1F05D", + "/dominohorizontal_06_03": "\u1F05E", + "/dominohorizontal_06_04": "\u1F05F", + "/dominohorizontal_06_05": "\u1F060", + "/dominohorizontal_06_06": "\u1F061", + "/dominohorizontalback": "\u1F030", + "/dominovertical_00_00": "\u1F063", + "/dominovertical_00_01": "\u1F064", + "/dominovertical_00_02": "\u1F065", + "/dominovertical_00_03": "\u1F066", + "/dominovertical_00_04": "\u1F067", + "/dominovertical_00_05": "\u1F068", + "/dominovertical_00_06": "\u1F069", + "/dominovertical_01_00": "\u1F06A", + "/dominovertical_01_01": "\u1F06B", + "/dominovertical_01_02": "\u1F06C", + "/dominovertical_01_03": "\u1F06D", + "/dominovertical_01_04": "\u1F06E", + "/dominovertical_01_05": "\u1F06F", + "/dominovertical_01_06": "\u1F070", + "/dominovertical_02_00": "\u1F071", + "/dominovertical_02_01": "\u1F072", + "/dominovertical_02_02": "\u1F073", + "/dominovertical_02_03": "\u1F074", + "/dominovertical_02_04": "\u1F075", + "/dominovertical_02_05": "\u1F076", + "/dominovertical_02_06": "\u1F077", + "/dominovertical_03_00": "\u1F078", + "/dominovertical_03_01": "\u1F079", + "/dominovertical_03_02": "\u1F07A", + "/dominovertical_03_03": "\u1F07B", + "/dominovertical_03_04": "\u1F07C", + "/dominovertical_03_05": "\u1F07D", + "/dominovertical_03_06": "\u1F07E", + "/dominovertical_04_00": "\u1F07F", + "/dominovertical_04_01": "\u1F080", + "/dominovertical_04_02": "\u1F081", + "/dominovertical_04_03": "\u1F082", + "/dominovertical_04_04": "\u1F083", + "/dominovertical_04_05": "\u1F084", + "/dominovertical_04_06": "\u1F085", + "/dominovertical_05_00": "\u1F086", + "/dominovertical_05_01": "\u1F087", + "/dominovertical_05_02": "\u1F088", + "/dominovertical_05_03": "\u1F089", + "/dominovertical_05_04": "\u1F08A", + "/dominovertical_05_05": "\u1F08B", + "/dominovertical_05_06": "\u1F08C", + "/dominovertical_06_00": "\u1F08D", + "/dominovertical_06_01": "\u1F08E", + "/dominovertical_06_02": "\u1F08F", + "/dominovertical_06_03": "\u1F090", + "/dominovertical_06_04": "\u1F091", + "/dominovertical_06_05": "\u1F092", + "/dominovertical_06_06": "\u1F093", + "/dominoverticalback": "\u1F062", + "/dong": "\u20AB", + "/door": "\u1F6AA", + "/dorusquare": "\u3326", + "/dot": "\u27D1", + "/dotaccent": "\u02D9", + "/dotaccentcmb": "\u0307", + "/dotbelowcmb": "\u0323", + "/dotbelowcomb": "\u0323", + "/dotkatakana": "\u30FB", + "/dotlessbeh": "\u066E", + "/dotlessfeh": "\u06A1", + "/dotlessi": "\u0131", + "/dotlessj": "\uF6BE", + "/dotlessjstroke": "\u025F", + "/dotlessjstrokehook": "\u0284", + "/dotlesskhahabove": "\u06E1", + "/dotlessqaf": "\u066F", + "/dotlower:hb": "\u05C5", + "/dotmath": "\u22C5", + "/dotminus": "\u2238", + "/dotplus": "\u2214", + "/dotraised": "\u2E33", + "/dots1": "\u2801", + "/dots12": "\u2803", + "/dots123": "\u2807", + "/dots1234": "\u280F", + "/dots12345": "\u281F", + "/dots123456": "\u283F", + "/dots1234567": "\u287F", + "/dots12345678": "\u28FF", + "/dots1234568": "\u28BF", + "/dots123457": "\u285F", + "/dots1234578": "\u28DF", + "/dots123458": "\u289F", + "/dots12346": "\u282F", + "/dots123467": "\u286F", + "/dots1234678": "\u28EF", + "/dots123468": "\u28AF", + "/dots12347": "\u284F", + "/dots123478": "\u28CF", + "/dots12348": "\u288F", + "/dots1235": "\u2817", + "/dots12356": "\u2837", + "/dots123567": "\u2877", + "/dots1235678": "\u28F7", + "/dots123568": "\u28B7", + "/dots12357": "\u2857", + "/dots123578": "\u28D7", + "/dots12358": "\u2897", + "/dots1236": "\u2827", + "/dots12367": "\u2867", + "/dots123678": "\u28E7", + "/dots12368": "\u28A7", + "/dots1237": "\u2847", + "/dots12378": "\u28C7", + "/dots1238": "\u2887", + "/dots124": "\u280B", + "/dots1245": "\u281B", + "/dots12456": "\u283B", + "/dots124567": "\u287B", + "/dots1245678": "\u28FB", + "/dots124568": "\u28BB", + "/dots12457": "\u285B", + "/dots124578": "\u28DB", + "/dots12458": "\u289B", + "/dots1246": "\u282B", + "/dots12467": "\u286B", + "/dots124678": "\u28EB", + "/dots12468": "\u28AB", + "/dots1247": "\u284B", + "/dots12478": "\u28CB", + "/dots1248": "\u288B", + "/dots125": "\u2813", + "/dots1256": "\u2833", + "/dots12567": "\u2873", + "/dots125678": "\u28F3", + "/dots12568": "\u28B3", + "/dots1257": "\u2853", + "/dots12578": "\u28D3", + "/dots1258": "\u2893", + "/dots126": "\u2823", + "/dots1267": "\u2863", + "/dots12678": "\u28E3", + "/dots1268": "\u28A3", + "/dots127": "\u2843", + "/dots1278": "\u28C3", + "/dots128": "\u2883", + "/dots13": "\u2805", + "/dots134": "\u280D", + "/dots1345": "\u281D", + "/dots13456": "\u283D", + "/dots134567": "\u287D", + "/dots1345678": "\u28FD", + "/dots134568": "\u28BD", + "/dots13457": "\u285D", + "/dots134578": "\u28DD", + "/dots13458": "\u289D", + "/dots1346": "\u282D", + "/dots13467": "\u286D", + "/dots134678": "\u28ED", + "/dots13468": "\u28AD", + "/dots1347": "\u284D", + "/dots13478": "\u28CD", + "/dots1348": "\u288D", + "/dots135": "\u2815", + "/dots1356": "\u2835", + "/dots13567": "\u2875", + "/dots135678": "\u28F5", + "/dots13568": "\u28B5", + "/dots1357": "\u2855", + "/dots13578": "\u28D5", + "/dots1358": "\u2895", + "/dots136": "\u2825", + "/dots1367": "\u2865", + "/dots13678": "\u28E5", + "/dots1368": "\u28A5", + "/dots137": "\u2845", + "/dots1378": "\u28C5", + "/dots138": "\u2885", + "/dots14": "\u2809", + "/dots145": "\u2819", + "/dots1456": "\u2839", + "/dots14567": "\u2879", + "/dots145678": "\u28F9", + "/dots14568": "\u28B9", + "/dots1457": "\u2859", + "/dots14578": "\u28D9", + "/dots1458": "\u2899", + "/dots146": "\u2829", + "/dots1467": "\u2869", + "/dots14678": "\u28E9", + "/dots1468": "\u28A9", + "/dots147": "\u2849", + "/dots1478": "\u28C9", + "/dots148": "\u2889", + "/dots15": "\u2811", + "/dots156": "\u2831", + "/dots1567": "\u2871", + "/dots15678": "\u28F1", + "/dots1568": "\u28B1", + "/dots157": "\u2851", + "/dots1578": "\u28D1", + "/dots158": "\u2891", + "/dots16": "\u2821", + "/dots167": "\u2861", + "/dots1678": "\u28E1", + "/dots168": "\u28A1", + "/dots17": "\u2841", + "/dots178": "\u28C1", + "/dots18": "\u2881", + "/dots2": "\u2802", + "/dots23": "\u2806", + "/dots234": "\u280E", + "/dots2345": "\u281E", + "/dots23456": "\u283E", + "/dots234567": "\u287E", + "/dots2345678": "\u28FE", + "/dots234568": "\u28BE", + "/dots23457": "\u285E", + "/dots234578": "\u28DE", + "/dots23458": "\u289E", + "/dots2346": "\u282E", + "/dots23467": "\u286E", + "/dots234678": "\u28EE", + "/dots23468": "\u28AE", + "/dots2347": "\u284E", + "/dots23478": "\u28CE", + "/dots2348": "\u288E", + "/dots235": "\u2816", + "/dots2356": "\u2836", + "/dots23567": "\u2876", + "/dots235678": "\u28F6", + "/dots23568": "\u28B6", + "/dots2357": "\u2856", + "/dots23578": "\u28D6", + "/dots2358": "\u2896", + "/dots236": "\u2826", + "/dots2367": "\u2866", + "/dots23678": "\u28E6", + "/dots2368": "\u28A6", + "/dots237": "\u2846", + "/dots2378": "\u28C6", + "/dots238": "\u2886", + "/dots24": "\u280A", + "/dots245": "\u281A", + "/dots2456": "\u283A", + "/dots24567": "\u287A", + "/dots245678": "\u28FA", + "/dots24568": "\u28BA", + "/dots2457": "\u285A", + "/dots24578": "\u28DA", + "/dots2458": "\u289A", + "/dots246": "\u282A", + "/dots2467": "\u286A", + "/dots24678": "\u28EA", + "/dots2468": "\u28AA", + "/dots247": "\u284A", + "/dots2478": "\u28CA", + "/dots248": "\u288A", + "/dots25": "\u2812", + "/dots256": "\u2832", + "/dots2567": "\u2872", + "/dots25678": "\u28F2", + "/dots2568": "\u28B2", + "/dots257": "\u2852", + "/dots2578": "\u28D2", + "/dots258": "\u2892", + "/dots26": "\u2822", + "/dots267": "\u2862", + "/dots2678": "\u28E2", + "/dots268": "\u28A2", + "/dots27": "\u2842", + "/dots278": "\u28C2", + "/dots28": "\u2882", + "/dots3": "\u2804", + "/dots34": "\u280C", + "/dots345": "\u281C", + "/dots3456": "\u283C", + "/dots34567": "\u287C", + "/dots345678": "\u28FC", + "/dots34568": "\u28BC", + "/dots3457": "\u285C", + "/dots34578": "\u28DC", + "/dots3458": "\u289C", + "/dots346": "\u282C", + "/dots3467": "\u286C", + "/dots34678": "\u28EC", + "/dots3468": "\u28AC", + "/dots347": "\u284C", + "/dots3478": "\u28CC", + "/dots348": "\u288C", + "/dots35": "\u2814", + "/dots356": "\u2834", + "/dots3567": "\u2874", + "/dots35678": "\u28F4", + "/dots3568": "\u28B4", + "/dots357": "\u2854", + "/dots3578": "\u28D4", + "/dots358": "\u2894", + "/dots36": "\u2824", + "/dots367": "\u2864", + "/dots3678": "\u28E4", + "/dots368": "\u28A4", + "/dots37": "\u2844", + "/dots378": "\u28C4", + "/dots38": "\u2884", + "/dots4": "\u2808", + "/dots45": "\u2818", + "/dots456": "\u2838", + "/dots4567": "\u2878", + "/dots45678": "\u28F8", + "/dots4568": "\u28B8", + "/dots457": "\u2858", + "/dots4578": "\u28D8", + "/dots458": "\u2898", + "/dots46": "\u2828", + "/dots467": "\u2868", + "/dots4678": "\u28E8", + "/dots468": "\u28A8", + "/dots47": "\u2848", + "/dots478": "\u28C8", + "/dots48": "\u2888", + "/dots5": "\u2810", + "/dots56": "\u2830", + "/dots567": "\u2870", + "/dots5678": "\u28F0", + "/dots568": "\u28B0", + "/dots57": "\u2850", + "/dots578": "\u28D0", + "/dots58": "\u2890", + "/dots6": "\u2820", + "/dots67": "\u2860", + "/dots678": "\u28E0", + "/dots68": "\u28A0", + "/dots7": "\u2840", + "/dots78": "\u28C0", + "/dots8": "\u2880", + "/dotsquarefour": "\u2E2C", + "/dottedcircle": "\u25CC", + "/dottedcross": "\u205C", + "/dotupper:hb": "\u05C4", + "/doublebarvertical": "\u23F8", + "/doubleyodpatah": "\uFB1F", + "/doubleyodpatahhebrew": "\uFB1F", + "/doughnut": "\u1F369", + "/doveOfPeace": "\u1F54A", + "/downtackbelowcmb": "\u031E", + "/downtackmod": "\u02D5", + "/downwarrowleftofuparrow": "\u21F5", + "/dparen": "\u249F", + "/dparenthesized": "\u249F", + "/drachma": "\u20AF", + "/dragon": "\u1F409", + "/dragonFace": "\u1F432", + "/draughtskingblack": "\u26C3", + "/draughtskingwhite": "\u26C1", + "/draughtsmanblack": "\u26C2", + "/draughtsmanwhite": "\u26C0", + "/dress": "\u1F457", + "/driveslow": "\u26DA", + "/dromedaryCamel": "\u1F42A", + "/droplet": "\u1F4A7", + "/dsquare": "\u1F1A5", + "/dsuperior": "\uF6EB", + "/dtail": "\u0256", + "/dtopbar": "\u018C", + "/duhiragana": "\u3065", + "/dukatakana": "\u30C5", + "/dul": "\u068E", + "/dul.fina": "\uFB87", + "/dul.isol": "\uFB86", + "/dum": "\uA771", + "/dvd": "\u1F4C0", + "/dyeh": "\u0684", + "/dyeh.fina": "\uFB73", + "/dyeh.init": "\uFB74", + "/dyeh.isol": "\uFB72", + "/dyeh.medi": "\uFB75", + "/dz": "\u01F3", + "/dzaltone": "\u02A3", + "/dzcaron": "\u01C6", + "/dzcurl": "\u02A5", + "/dzeabkhasiancyrillic": "\u04E1", + "/dzeabkhcyr": "\u04E1", + "/dzecyr": "\u0455", + "/dzecyrillic": "\u0455", + "/dzed": "\u02A3", + "/dzedcurl": "\u02A5", + "/dzhecyr": "\u045F", + "/dzhecyrillic": "\u045F", + "/dzjekomicyr": "\u0507", + "/dzzhecyr": "\u052B", + "/e": "\u0065", + "/e-mail": "\u1F4E7", + "/e.fina": "\uFBE5", + "/e.inferior": "\u2091", + "/e.init": "\uFBE6", + "/e.isol": "\uFBE4", + "/e.medi": "\uFBE7", + "/eVfullwidth": "\u32CE", + "/eacute": "\u00E9", + "/earOfMaize": "\u1F33D", + "/earOfRice": "\u1F33E", + "/earth": "\u2641", + "/earthGlobeAmericas": "\u1F30E", + "/earthGlobeAsiaAustralia": "\u1F30F", + "/earthGlobeEuropeAfrica": "\u1F30D", + "/earthground": "\u23DA", + "/earthideographiccircled": "\u328F", + "/earthideographicparen": "\u322F", + "/eastsyriaccross": "\u2671", + "/ebengali": "\u098F", + "/ebopomofo": "\u311C", + "/ebreve": "\u0115", + "/ecandradeva": "\u090D", + "/ecandragujarati": "\u0A8D", + "/ecandravowelsigndeva": "\u0945", + "/ecandravowelsigngujarati": "\u0AC5", + "/ecaron": "\u011B", + "/ecedilla": "\u0229", + "/ecedillabreve": "\u1E1D", + "/echarmenian": "\u0565", + "/echyiwnarmenian": "\u0587", + "/ecircle": "\u24D4", + "/ecirclekatakana": "\u32D3", + "/ecircumflex": "\u00EA", + "/ecircumflexacute": "\u1EBF", + "/ecircumflexbelow": "\u1E19", + "/ecircumflexdotbelow": "\u1EC7", + "/ecircumflexgrave": "\u1EC1", + "/ecircumflexhoi": "\u1EC3", + "/ecircumflexhookabove": "\u1EC3", + "/ecircumflextilde": "\u1EC5", + "/ecyrillic": "\u0454", + "/edblgrave": "\u0205", + "/edblstruckitalic": "\u2147", + "/edeva": "\u090F", + "/edieresis": "\u00EB", + "/edot": "\u0117", + "/edotaccent": "\u0117", + "/edotbelow": "\u1EB9", + "/eegurmukhi": "\u0A0F", + "/eekaasquare": "\u3308", + "/eematragurmukhi": "\u0A47", + "/efcyr": "\u0444", + "/efcyrillic": "\u0444", + "/egrave": "\u00E8", + "/egravedbl": "\u0205", + "/egujarati": "\u0A8F", + "/egyptain": "\uA725", + "/egyptalef": "\uA723", + "/eharmenian": "\u0567", + "/ehbopomofo": "\u311D", + "/ehiragana": "\u3048", + "/ehoi": "\u1EBB", + "/ehookabove": "\u1EBB", + "/eibopomofo": "\u311F", + "/eight": "\u0038", + "/eight.inferior": "\u2088", + "/eight.roman": "\u2167", + "/eight.romansmall": "\u2177", + "/eight.superior": "\u2078", + "/eightarabic": "\u0668", + "/eightbengali": "\u09EE", + "/eightcircle": "\u2467", + "/eightcircledbl": "\u24FC", + "/eightcircleinversesansserif": "\u2791", + "/eightcomma": "\u1F109", + "/eightdeva": "\u096E", + "/eighteencircle": "\u2471", + "/eighteencircleblack": "\u24F2", + "/eighteenparen": "\u2485", + "/eighteenparenthesized": "\u2485", + "/eighteenperiod": "\u2499", + "/eightfar": "\u06F8", + "/eightgujarati": "\u0AEE", + "/eightgurmukhi": "\u0A6E", + "/eighthackarabic": "\u0668", + "/eighthangzhou": "\u3028", + "/eighthnote": "\u266A", + "/eighthnotebeamed": "\u266B", + "/eightideographiccircled": "\u3287", + "/eightideographicparen": "\u3227", + "/eightinferior": "\u2088", + "/eightksquare": "\u1F19F", + "/eightmonospace": "\uFF18", + "/eightoldstyle": "\uF738", + "/eightparen": "\u247B", + "/eightparenthesized": "\u247B", + "/eightperiod": "\u248F", + "/eightpersian": "\u06F8", + "/eightroman": "\u2177", + "/eightsuperior": "\u2078", + "/eightthai": "\u0E58", + "/eightycirclesquare": "\u324F", + "/einvertedbreve": "\u0207", + "/eiotifiedcyr": "\u0465", + "/eiotifiedcyrillic": "\u0465", + "/eject": "\u23CF", + "/ekatakana": "\u30A8", + "/ekatakanahalfwidth": "\uFF74", + "/ekonkargurmukhi": "\u0A74", + "/ekorean": "\u3154", + "/elcyr": "\u043B", + "/elcyrillic": "\u043B", + "/electricLightBulb": "\u1F4A1", + "/electricPlug": "\u1F50C", + "/electricTorch": "\u1F526", + "/electricalintersection": "\u23E7", + "/electricarrow": "\u2301", + "/element": "\u2208", + "/elementdotabove": "\u22F5", + "/elementlonghorizontalstroke": "\u22F2", + "/elementopeningup": "\u27D2", + "/elementoverbar": "\u22F6", + "/elementoverbarsmall": "\u22F7", + "/elementsmall": "\u220A", + "/elementsmallverticalbarhorizontalstroke": "\u22F4", + "/elementtwoshorizontalstroke": "\u22F9", + "/elementunderbar": "\u22F8", + "/elementverticalbarhorizontalstroke": "\u22F3", + "/elephant": "\u1F418", + "/eleven.roman": "\u216A", + "/eleven.romansmall": "\u217A", + "/elevencircle": "\u246A", + "/elevencircleblack": "\u24EB", + "/elevenparen": "\u247E", + "/elevenparenthesized": "\u247E", + "/elevenperiod": "\u2492", + "/elevenroman": "\u217A", + "/elhookcyr": "\u0513", + "/ellipsis": "\u2026", + "/ellipsisdiagonaldownright": "\u22F1", + "/ellipsisdiagonalupright": "\u22F0", + "/ellipsismidhorizontal": "\u22EF", + "/ellipsisvertical": "\u22EE", + "/elmiddlehookcyr": "\u0521", + "/elsharptailcyr": "\u04C6", + "/eltailcyr": "\u052F", + "/emacron": "\u0113", + "/emacronacute": "\u1E17", + "/emacrongrave": "\u1E15", + "/emcyr": "\u043C", + "/emcyrillic": "\u043C", + "/emdash": "\u2014", + "/emdashdbl": "\u2E3A", + "/emdashtpl": "\u2E3B", + "/emdashvertical": "\uFE31", + "/emojiModifierFitzpatrickType-1-2": "\u1F3FB", + "/emojiModifierFitzpatrickType-3": "\u1F3FC", + "/emojiModifierFitzpatrickType-4": "\u1F3FD", + "/emojiModifierFitzpatrickType-5": "\u1F3FE", + "/emojiModifierFitzpatrickType-6": "\u1F3FF", + "/emonospace": "\uFF45", + "/emphasis": "\u2383", + "/emphasismarkarmenian": "\u055B", + "/emptyDocument": "\u1F5CB", + "/emptyNote": "\u1F5C5", + "/emptyNotePad": "\u1F5C7", + "/emptyNotePage": "\u1F5C6", + "/emptyPage": "\u1F5CC", + "/emptyPages": "\u1F5CD", + "/emptyset": "\u2205", + "/emquad": "\u2001", + "/emsharptailcyr": "\u04CE", + "/emspace": "\u2003", + "/enbopomofo": "\u3123", + "/encyr": "\u043D", + "/encyrillic": "\u043D", + "/endLeftwardsArrowAbove": "\u1F51A", + "/endash": "\u2013", + "/endashvertical": "\uFE32", + "/endescendercyrillic": "\u04A3", + "/endpro": "\u220E", + "/eng": "\u014B", + "/engbopomofo": "\u3125", + "/engecyr": "\u04A5", + "/enghecyrillic": "\u04A5", + "/enhookcyr": "\u04C8", + "/enhookcyrillic": "\u04C8", + "/enhookleftcyr": "\u0529", + "/enmiddlehookcyr": "\u0523", + "/enotch": "\u2C78", + "/enquad": "\u2000", + "/ensharptailcyr": "\u04CA", + "/enspace": "\u2002", + "/entailcyr": "\u04A3", + "/enter": "\u2386", + "/enterpriseideographiccircled": "\u32AD", + "/enterpriseideographicparen": "\u323D", + "/envelopeDownwardsArrowAbove": "\u1F4E9", + "/envelopeLightning": "\u1F584", + "/eogonek": "\u0119", + "/eokorean": "\u3153", + "/eopen": "\u025B", + "/eopenclosed": "\u029A", + "/eopenreversed": "\u025C", + "/eopenreversedclosed": "\u025E", + "/eopenreversedhook": "\u025D", + "/eparen": "\u24A0", + "/eparenthesized": "\u24A0", + "/epsilon": "\u03B5", + "/epsilonacute": "\u1F73", + "/epsilonasper": "\u1F11", + "/epsilonasperacute": "\u1F15", + "/epsilonaspergrave": "\u1F13", + "/epsilongrave": "\u1F72", + "/epsilonlenis": "\u1F10", + "/epsilonlenisacute": "\u1F14", + "/epsilonlenisgrave": "\u1F12", + "/epsilonlunatesymbol": "\u03F5", + "/epsilonreversedlunatesymbol": "\u03F6", + "/epsilontonos": "\u03AD", + "/epsilonunderlinefunc": "\u2377", + "/equal": "\u003D", + "/equal.inferior": "\u208C", + "/equal.superior": "\u207C", + "/equalandparallel": "\u22D5", + "/equalbydefinition": "\u225D", + "/equalmonospace": "\uFF1D", + "/equalorgreater": "\u22DD", + "/equalorless": "\u22DC", + "/equalorprecedes": "\u22DE", + "/equalorsucceeds": "\u22DF", + "/equalscolon": "\u2255", + "/equalsmall": "\uFE66", + "/equalsuperior": "\u207C", + "/equiangular": "\u225A", + "/equivalence": "\u2261", + "/equivalent": "\u224D", + "/eranameheiseisquare": "\u337B", + "/eranamemeizisquare": "\u337E", + "/eranamesyouwasquare": "\u337C", + "/eranametaisyousquare": "\u337D", + "/eraseleft": "\u232B", + "/eraseright": "\u2326", + "/erbopomofo": "\u3126", + "/ercyr": "\u0440", + "/ercyrillic": "\u0440", + "/ereversed": "\u0258", + "/ereversedcyr": "\u044D", + "/ereversedcyrillic": "\u044D", + "/ereverseddieresiscyr": "\u04ED", + "/ergfullwidth": "\u32CD", + "/ertickcyr": "\u048F", + "/escript": "\u212F", + "/escyr": "\u0441", + "/escyrillic": "\u0441", + "/esdescendercyrillic": "\u04AB", + "/esh": "\u0283", + "/eshcurl": "\u0286", + "/eshortdeva": "\u090E", + "/eshortvowelsigndeva": "\u0946", + "/eshreversedloop": "\u01AA", + "/eshsquatreversed": "\u0285", + "/esmallhiragana": "\u3047", + "/esmallkatakana": "\u30A7", + "/esmallkatakanahalfwidth": "\uFF6A", + "/estailcyr": "\u04AB", + "/estimated": "\u212E", + "/estimates": "\u2259", + "/estroke": "\u0247", + "/esukuudosquare": "\u3307", + "/esuperior": "\uF6EC", + "/et": "\uA76B", + "/eta": "\u03B7", + "/etaacute": "\u1F75", + "/etaacuteiotasub": "\u1FC4", + "/etaasper": "\u1F21", + "/etaasperacute": "\u1F25", + "/etaasperacuteiotasub": "\u1F95", + "/etaaspergrave": "\u1F23", + "/etaaspergraveiotasub": "\u1F93", + "/etaasperiotasub": "\u1F91", + "/etaaspertilde": "\u1F27", + "/etaaspertildeiotasub": "\u1F97", + "/etagrave": "\u1F74", + "/etagraveiotasub": "\u1FC2", + "/etaiotasub": "\u1FC3", + "/etalenis": "\u1F20", + "/etalenisacute": "\u1F24", + "/etalenisacuteiotasub": "\u1F94", + "/etalenisgrave": "\u1F22", + "/etalenisgraveiotasub": "\u1F92", + "/etalenisiotasub": "\u1F90", + "/etalenistilde": "\u1F26", + "/etalenistildeiotasub": "\u1F96", + "/etarmenian": "\u0568", + "/etatilde": "\u1FC6", + "/etatildeiotasub": "\u1FC7", + "/etatonos": "\u03AE", + "/eth": "\u00F0", + "/ethi:aaglottal": "\u12A3", + "/ethi:aglottal": "\u12A0", + "/ethi:ba": "\u1260", + "/ethi:baa": "\u1263", + "/ethi:be": "\u1265", + "/ethi:bee": "\u1264", + "/ethi:bi": "\u1262", + "/ethi:bo": "\u1266", + "/ethi:bu": "\u1261", + "/ethi:bwa": "\u1267", + "/ethi:ca": "\u1278", + "/ethi:caa": "\u127B", + "/ethi:ce": "\u127D", + "/ethi:cee": "\u127C", + "/ethi:cha": "\u1328", + "/ethi:chaa": "\u132B", + "/ethi:che": "\u132D", + "/ethi:chee": "\u132C", + "/ethi:chi": "\u132A", + "/ethi:cho": "\u132E", + "/ethi:chu": "\u1329", + "/ethi:chwa": "\u132F", + "/ethi:ci": "\u127A", + "/ethi:co": "\u127E", + "/ethi:colon": "\u1365", + "/ethi:comma": "\u1363", + "/ethi:cu": "\u1279", + "/ethi:cwa": "\u127F", + "/ethi:da": "\u12F0", + "/ethi:daa": "\u12F3", + "/ethi:dda": "\u12F8", + "/ethi:ddaa": "\u12FB", + "/ethi:dde": "\u12FD", + "/ethi:ddee": "\u12FC", + "/ethi:ddi": "\u12FA", + "/ethi:ddo": "\u12FE", + "/ethi:ddu": "\u12F9", + "/ethi:ddwa": "\u12FF", + "/ethi:de": "\u12F5", + "/ethi:dee": "\u12F4", + "/ethi:di": "\u12F2", + "/ethi:do": "\u12F6", + "/ethi:du": "\u12F1", + "/ethi:dwa": "\u12F7", + "/ethi:eeglottal": "\u12A4", + "/ethi:eglottal": "\u12A5", + "/ethi:eight": "\u1370", + "/ethi:eighty": "\u1379", + "/ethi:fa": "\u1348", + "/ethi:faa": "\u134B", + "/ethi:fe": "\u134D", + "/ethi:fee": "\u134C", + "/ethi:fi": "\u134A", + "/ethi:fifty": "\u1376", + "/ethi:five": "\u136D", + "/ethi:fo": "\u134E", + "/ethi:forty": "\u1375", + "/ethi:four": "\u136C", + "/ethi:fu": "\u1349", + "/ethi:fullstop": "\u1362", + "/ethi:fwa": "\u134F", + "/ethi:fya": "\u135A", + "/ethi:ga": "\u1308", + "/ethi:gaa": "\u130B", + "/ethi:ge": "\u130D", + "/ethi:gee": "\u130C", + "/ethi:geminationandvowellengthmarkcmb": "\u135D", + "/ethi:geminationmarkcmb": "\u135F", + "/ethi:gga": "\u1318", + "/ethi:ggaa": "\u131B", + "/ethi:gge": "\u131D", + "/ethi:ggee": "\u131C", + "/ethi:ggi": "\u131A", + "/ethi:ggo": "\u131E", + "/ethi:ggu": "\u1319", + "/ethi:ggwaa": "\u131F", + "/ethi:gi": "\u130A", + "/ethi:go": "\u130E", + "/ethi:goa": "\u130F", + "/ethi:gu": "\u1309", + "/ethi:gwa": "\u1310", + "/ethi:gwaa": "\u1313", + "/ethi:gwe": "\u1315", + "/ethi:gwee": "\u1314", + "/ethi:gwi": "\u1312", + "/ethi:ha": "\u1200", + "/ethi:haa": "\u1203", + "/ethi:he": "\u1205", + "/ethi:hee": "\u1204", + "/ethi:hha": "\u1210", + "/ethi:hhaa": "\u1213", + "/ethi:hhe": "\u1215", + "/ethi:hhee": "\u1214", + "/ethi:hhi": "\u1212", + "/ethi:hho": "\u1216", + "/ethi:hhu": "\u1211", + "/ethi:hhwa": "\u1217", + "/ethi:hi": "\u1202", + "/ethi:ho": "\u1206", + "/ethi:hoa": "\u1207", + "/ethi:hu": "\u1201", + "/ethi:hundred": "\u137B", + "/ethi:iglottal": "\u12A2", + "/ethi:ja": "\u1300", + "/ethi:jaa": "\u1303", + "/ethi:je": "\u1305", + "/ethi:jee": "\u1304", + "/ethi:ji": "\u1302", + "/ethi:jo": "\u1306", + "/ethi:ju": "\u1301", + "/ethi:jwa": "\u1307", + "/ethi:ka": "\u12A8", + "/ethi:kaa": "\u12AB", + "/ethi:ke": "\u12AD", + "/ethi:kee": "\u12AC", + "/ethi:ki": "\u12AA", + "/ethi:ko": "\u12AE", + "/ethi:koa": "\u12AF", + "/ethi:ku": "\u12A9", + "/ethi:kwa": "\u12B0", + "/ethi:kwaa": "\u12B3", + "/ethi:kwe": "\u12B5", + "/ethi:kwee": "\u12B4", + "/ethi:kwi": "\u12B2", + "/ethi:kxa": "\u12B8", + "/ethi:kxaa": "\u12BB", + "/ethi:kxe": "\u12BD", + "/ethi:kxee": "\u12BC", + "/ethi:kxi": "\u12BA", + "/ethi:kxo": "\u12BE", + "/ethi:kxu": "\u12B9", + "/ethi:kxwa": "\u12C0", + "/ethi:kxwaa": "\u12C3", + "/ethi:kxwe": "\u12C5", + "/ethi:kxwee": "\u12C4", + "/ethi:kxwi": "\u12C2", + "/ethi:la": "\u1208", + "/ethi:laa": "\u120B", + "/ethi:le": "\u120D", + "/ethi:lee": "\u120C", + "/ethi:li": "\u120A", + "/ethi:lo": "\u120E", + "/ethi:lu": "\u1209", + "/ethi:lwa": "\u120F", + "/ethi:ma": "\u1218", + "/ethi:maa": "\u121B", + "/ethi:me": "\u121D", + "/ethi:mee": "\u121C", + "/ethi:mi": "\u121A", + "/ethi:mo": "\u121E", + "/ethi:mu": "\u1219", + "/ethi:mwa": "\u121F", + "/ethi:mya": "\u1359", + "/ethi:na": "\u1290", + "/ethi:naa": "\u1293", + "/ethi:ne": "\u1295", + "/ethi:nee": "\u1294", + "/ethi:ni": "\u1292", + "/ethi:nine": "\u1371", + "/ethi:ninety": "\u137A", + "/ethi:no": "\u1296", + "/ethi:nu": "\u1291", + "/ethi:nwa": "\u1297", + "/ethi:nya": "\u1298", + "/ethi:nyaa": "\u129B", + "/ethi:nye": "\u129D", + "/ethi:nyee": "\u129C", + "/ethi:nyi": "\u129A", + "/ethi:nyo": "\u129E", + "/ethi:nyu": "\u1299", + "/ethi:nywa": "\u129F", + "/ethi:oglottal": "\u12A6", + "/ethi:one": "\u1369", + "/ethi:pa": "\u1350", + "/ethi:paa": "\u1353", + "/ethi:paragraphseparator": "\u1368", + "/ethi:pe": "\u1355", + "/ethi:pee": "\u1354", + "/ethi:pha": "\u1330", + "/ethi:phaa": "\u1333", + "/ethi:pharyngeala": "\u12D0", + "/ethi:pharyngealaa": "\u12D3", + "/ethi:pharyngeale": "\u12D5", + "/ethi:pharyngealee": "\u12D4", + "/ethi:pharyngeali": "\u12D2", + "/ethi:pharyngealo": "\u12D6", + "/ethi:pharyngealu": "\u12D1", + "/ethi:phe": "\u1335", + "/ethi:phee": "\u1334", + "/ethi:phi": "\u1332", + "/ethi:pho": "\u1336", + "/ethi:phu": "\u1331", + "/ethi:phwa": "\u1337", + "/ethi:pi": "\u1352", + "/ethi:po": "\u1356", + "/ethi:prefacecolon": "\u1366", + "/ethi:pu": "\u1351", + "/ethi:pwa": "\u1357", + "/ethi:qa": "\u1240", + "/ethi:qaa": "\u1243", + "/ethi:qe": "\u1245", + "/ethi:qee": "\u1244", + "/ethi:qha": "\u1250", + "/ethi:qhaa": "\u1253", + "/ethi:qhe": "\u1255", + "/ethi:qhee": "\u1254", + "/ethi:qhi": "\u1252", + "/ethi:qho": "\u1256", + "/ethi:qhu": "\u1251", + "/ethi:qhwa": "\u1258", + "/ethi:qhwaa": "\u125B", + "/ethi:qhwe": "\u125D", + "/ethi:qhwee": "\u125C", + "/ethi:qhwi": "\u125A", + "/ethi:qi": "\u1242", + "/ethi:qo": "\u1246", + "/ethi:qoa": "\u1247", + "/ethi:qu": "\u1241", + "/ethi:questionmark": "\u1367", + "/ethi:qwa": "\u1248", + "/ethi:qwaa": "\u124B", + "/ethi:qwe": "\u124D", + "/ethi:qwee": "\u124C", + "/ethi:qwi": "\u124A", + "/ethi:ra": "\u1228", + "/ethi:raa": "\u122B", + "/ethi:re": "\u122D", + "/ethi:ree": "\u122C", + "/ethi:ri": "\u122A", + "/ethi:ro": "\u122E", + "/ethi:ru": "\u1229", + "/ethi:rwa": "\u122F", + "/ethi:rya": "\u1358", + "/ethi:sa": "\u1230", + "/ethi:saa": "\u1233", + "/ethi:se": "\u1235", + "/ethi:sectionmark": "\u1360", + "/ethi:see": "\u1234", + "/ethi:semicolon": "\u1364", + "/ethi:seven": "\u136F", + "/ethi:seventy": "\u1378", + "/ethi:sha": "\u1238", + "/ethi:shaa": "\u123B", + "/ethi:she": "\u123D", + "/ethi:shee": "\u123C", + "/ethi:shi": "\u123A", + "/ethi:sho": "\u123E", + "/ethi:shu": "\u1239", + "/ethi:shwa": "\u123F", + "/ethi:si": "\u1232", + "/ethi:six": "\u136E", + "/ethi:sixty": "\u1377", + "/ethi:so": "\u1236", + "/ethi:su": "\u1231", + "/ethi:swa": "\u1237", + "/ethi:sza": "\u1220", + "/ethi:szaa": "\u1223", + "/ethi:sze": "\u1225", + "/ethi:szee": "\u1224", + "/ethi:szi": "\u1222", + "/ethi:szo": "\u1226", + "/ethi:szu": "\u1221", + "/ethi:szwa": "\u1227", + "/ethi:ta": "\u1270", + "/ethi:taa": "\u1273", + "/ethi:te": "\u1275", + "/ethi:tee": "\u1274", + "/ethi:ten": "\u1372", + "/ethi:tenthousand": "\u137C", + "/ethi:tha": "\u1320", + "/ethi:thaa": "\u1323", + "/ethi:the": "\u1325", + "/ethi:thee": "\u1324", + "/ethi:thi": "\u1322", + "/ethi:thirty": "\u1374", + "/ethi:tho": "\u1326", + "/ethi:three": "\u136B", + "/ethi:thu": "\u1321", + "/ethi:thwa": "\u1327", + "/ethi:ti": "\u1272", + "/ethi:to": "\u1276", + "/ethi:tsa": "\u1338", + "/ethi:tsaa": "\u133B", + "/ethi:tse": "\u133D", + "/ethi:tsee": "\u133C", + "/ethi:tsi": "\u133A", + "/ethi:tso": "\u133E", + "/ethi:tsu": "\u1339", + "/ethi:tswa": "\u133F", + "/ethi:tu": "\u1271", + "/ethi:twa": "\u1277", + "/ethi:twenty": "\u1373", + "/ethi:two": "\u136A", + "/ethi:tza": "\u1340", + "/ethi:tzaa": "\u1343", + "/ethi:tze": "\u1345", + "/ethi:tzee": "\u1344", + "/ethi:tzi": "\u1342", + "/ethi:tzo": "\u1346", + "/ethi:tzoa": "\u1347", + "/ethi:tzu": "\u1341", + "/ethi:uglottal": "\u12A1", + "/ethi:va": "\u1268", + "/ethi:vaa": "\u126B", + "/ethi:ve": "\u126D", + "/ethi:vee": "\u126C", + "/ethi:vi": "\u126A", + "/ethi:vo": "\u126E", + "/ethi:vowellengthmarkcmb": "\u135E", + "/ethi:vu": "\u1269", + "/ethi:vwa": "\u126F", + "/ethi:wa": "\u12C8", + "/ethi:waa": "\u12CB", + "/ethi:waglottal": "\u12A7", + "/ethi:we": "\u12CD", + "/ethi:wee": "\u12CC", + "/ethi:wi": "\u12CA", + "/ethi:wo": "\u12CE", + "/ethi:woa": "\u12CF", + "/ethi:wordspace": "\u1361", + "/ethi:wu": "\u12C9", + "/ethi:xa": "\u1280", + "/ethi:xaa": "\u1283", + "/ethi:xe": "\u1285", + "/ethi:xee": "\u1284", + "/ethi:xi": "\u1282", + "/ethi:xo": "\u1286", + "/ethi:xoa": "\u1287", + "/ethi:xu": "\u1281", + "/ethi:xwa": "\u1288", + "/ethi:xwaa": "\u128B", + "/ethi:xwe": "\u128D", + "/ethi:xwee": "\u128C", + "/ethi:xwi": "\u128A", + "/ethi:ya": "\u12E8", + "/ethi:yaa": "\u12EB", + "/ethi:ye": "\u12ED", + "/ethi:yee": "\u12EC", + "/ethi:yi": "\u12EA", + "/ethi:yo": "\u12EE", + "/ethi:yoa": "\u12EF", + "/ethi:yu": "\u12E9", + "/ethi:za": "\u12D8", + "/ethi:zaa": "\u12DB", + "/ethi:ze": "\u12DD", + "/ethi:zee": "\u12DC", + "/ethi:zha": "\u12E0", + "/ethi:zhaa": "\u12E3", + "/ethi:zhe": "\u12E5", + "/ethi:zhee": "\u12E4", + "/ethi:zhi": "\u12E2", + "/ethi:zho": "\u12E6", + "/ethi:zhu": "\u12E1", + "/ethi:zhwa": "\u12E7", + "/ethi:zi": "\u12DA", + "/ethi:zo": "\u12DE", + "/ethi:zu": "\u12D9", + "/ethi:zwa": "\u12DF", + "/etilde": "\u1EBD", + "/etildebelow": "\u1E1B", + "/etnahta:hb": "\u0591", + "/etnahtafoukhhebrew": "\u0591", + "/etnahtafoukhlefthebrew": "\u0591", + "/etnahtahebrew": "\u0591", + "/etnahtalefthebrew": "\u0591", + "/eturned": "\u01DD", + "/eukorean": "\u3161", + "/eukrcyr": "\u0454", + "/euler": "\u2107", + "/euro": "\u20AC", + "/euroarchaic": "\u20A0", + "/europeanCastle": "\u1F3F0", + "/europeanPostOffice": "\u1F3E4", + "/evergreenTree": "\u1F332", + "/evowelsignbengali": "\u09C7", + "/evowelsigndeva": "\u0947", + "/evowelsigngujarati": "\u0AC7", + "/excellentideographiccircled": "\u329D", + "/excess": "\u2239", + "/exclam": "\u0021", + "/exclamarmenian": "\u055C", + "/exclamationquestion": "\u2049", + "/exclamdbl": "\u203C", + "/exclamdown": "\u00A1", + "/exclamdownsmall": "\uF7A1", + "/exclammonospace": "\uFF01", + "/exclamsmall": "\uF721", + "/existential": "\u2203", + "/expressionlessFace": "\u1F611", + "/extraterrestrialAlien": "\u1F47D", + "/eye": "\u1F441", + "/eyeglasses": "\u1F453", + "/eyes": "\u1F440", + "/ezh": "\u0292", + "/ezhcaron": "\u01EF", + "/ezhcurl": "\u0293", + "/ezhreversed": "\u01B9", + "/ezhtail": "\u01BA", + "/f": "\u0066", + "/f_f": "\uFB00", + "/f_f_i": "\uFB03", + "/f_f_l": "\uFB04", + "/faceMassage": "\u1F486", + "/faceSavouringDeliciousFood": "\u1F60B", + "/faceScreamingInFear": "\u1F631", + "/faceThrowingAKiss": "\u1F618", + "/faceWithColdSweat": "\u1F613", + "/faceWithLookOfTriumph": "\u1F624", + "/faceWithMedicalMask": "\u1F637", + "/faceWithNoGoodGesture": "\u1F645", + "/faceWithOkGesture": "\u1F646", + "/faceWithOpenMouth": "\u1F62E", + "/faceWithOpenMouthAndColdSweat": "\u1F630", + "/faceWithRollingEyes": "\u1F644", + "/faceWithStuckOutTongue": "\u1F61B", + "/faceWithStuckOutTongueAndTightlyClosedEyes": "\u1F61D", + "/faceWithStuckOutTongueAndWinkingEye": "\u1F61C", + "/faceWithTearsOfJoy": "\u1F602", + "/faceWithoutMouth": "\u1F636", + "/facsimile": "\u213B", + "/factory": "\u1F3ED", + "/fadeva": "\u095E", + "/fagurmukhi": "\u0A5E", + "/fahrenheit": "\u2109", + "/fallenLeaf": "\u1F342", + "/fallingdiagonal": "\u27CD", + "/fallingdiagonalincircleinsquareblackwhite": "\u26DE", + "/family": "\u1F46A", + "/farsi": "\u262B", + "/farsiYehDigitFourBelow": "\u0777", + "/farsiYehDigitThreeAbove": "\u0776", + "/farsiYehDigitTwoAbove": "\u0775", + "/fatha": "\u064E", + "/fathaIsol": "\uFE76", + "/fathaMedi": "\uFE77", + "/fathaarabic": "\u064E", + "/fathalowarabic": "\u064E", + "/fathasmall": "\u0618", + "/fathatan": "\u064B", + "/fathatanIsol": "\uFE70", + "/fathatanarabic": "\u064B", + "/fathatwodotsdots": "\u065E", + "/fatherChristmas": "\u1F385", + "/faxIcon": "\u1F5B7", + "/faxMachine": "\u1F4E0", + "/fbopomofo": "\u3108", + "/fcircle": "\u24D5", + "/fdot": "\u1E1F", + "/fdotaccent": "\u1E1F", + "/fearfulFace": "\u1F628", + "/februarytelegraph": "\u32C1", + "/feh.fina": "\uFED2", + "/feh.init": "\uFED3", + "/feh.init_alefmaksura.fina": "\uFC31", + "/feh.init_hah.fina": "\uFC2E", + "/feh.init_hah.medi": "\uFCBF", + "/feh.init_jeem.fina": "\uFC2D", + "/feh.init_jeem.medi": "\uFCBE", + "/feh.init_khah.fina": "\uFC2F", + "/feh.init_khah.medi": "\uFCC0", + "/feh.init_khah.medi_meem.medi": "\uFD7D", + "/feh.init_meem.fina": "\uFC30", + "/feh.init_meem.medi": "\uFCC1", + "/feh.init_yeh.fina": "\uFC32", + "/feh.isol": "\uFED1", + "/feh.medi": "\uFED4", + "/feh.medi_alefmaksura.fina": "\uFC7C", + "/feh.medi_khah.medi_meem.fina": "\uFD7C", + "/feh.medi_meem.medi_yeh.fina": "\uFDC1", + "/feh.medi_yeh.fina": "\uFC7D", + "/fehThreeDotsUpBelow": "\u0761", + "/fehTwoDotsBelow": "\u0760", + "/feharabic": "\u0641", + "/feharmenian": "\u0586", + "/fehdotbelow": "\u06A3", + "/fehdotbelowright": "\u06A2", + "/fehfinalarabic": "\uFED2", + "/fehinitialarabic": "\uFED3", + "/fehmedialarabic": "\uFED4", + "/fehthreedotsbelow": "\u06A5", + "/feicoptic": "\u03E5", + "/female": "\u2640", + "/femaleideographiccircled": "\u329B", + "/feng": "\u02A9", + "/ferrisWheel": "\u1F3A1", + "/ferry": "\u26F4", + "/festivalideographicparen": "\u3240", + "/ff": "\uFB00", + "/ffi": "\uFB03", + "/ffl": "\uFB04", + "/fhook": "\u0192", + "/fi": "\uFB01", # ligature "fi" + "/fieldHockeyStickAndBall": "\u1F3D1", + "/fifteencircle": "\u246E", + "/fifteencircleblack": "\u24EF", + "/fifteenparen": "\u2482", + "/fifteenparenthesized": "\u2482", + "/fifteenperiod": "\u2496", + "/fifty.roman": "\u216C", + "/fifty.romansmall": "\u217C", + "/fiftycircle": "\u32BF", + "/fiftycirclesquare": "\u324C", + "/fiftyearlyform.roman": "\u2186", + "/fiftythousand.roman": "\u2187", + "/figuredash": "\u2012", + "/figurespace": "\u2007", + "/fileCabinet": "\u1F5C4", + "/fileFolder": "\u1F4C1", + "/filledbox": "\u25A0", + "/filledrect": "\u25AC", + "/filledstopabove": "\u06EC", + "/filmFrames": "\u1F39E", + "/filmProjector": "\u1F4FD", + "/finalkaf": "\u05DA", + "/finalkaf:hb": "\u05DA", + "/finalkafdagesh": "\uFB3A", + "/finalkafdageshhebrew": "\uFB3A", + "/finalkafhebrew": "\u05DA", + "/finalkafqamats": "\u05DA", + "/finalkafqamatshebrew": "\u05DA", + "/finalkafsheva": "\u05DA", + "/finalkafshevahebrew": "\u05DA", + "/finalkafwithdagesh:hb": "\uFB3A", + "/finalmem": "\u05DD", + "/finalmem:hb": "\u05DD", + "/finalmemhebrew": "\u05DD", + "/finalmemwide:hb": "\uFB26", + "/finalnun": "\u05DF", + "/finalnun:hb": "\u05DF", + "/finalnunhebrew": "\u05DF", + "/finalpe": "\u05E3", + "/finalpe:hb": "\u05E3", + "/finalpehebrew": "\u05E3", + "/finalpewithdagesh:hb": "\uFB43", + "/finalsigma": "\u03C2", + "/finaltsadi": "\u05E5", + "/finaltsadi:hb": "\u05E5", + "/finaltsadihebrew": "\u05E5", + "/financialideographiccircled": "\u3296", + "/financialideographicparen": "\u3236", + "/finsular": "\uA77C", + "/fire": "\u1F525", + "/fireEngine": "\u1F692", + "/fireideographiccircled": "\u328B", + "/fireideographicparen": "\u322B", + "/fireworkSparkler": "\u1F387", + "/fireworks": "\u1F386", + "/firstQuarterMoon": "\u1F313", + "/firstQuarterMoonFace": "\u1F31B", + "/firstquartermoon": "\u263D", + "/firststrongisolate": "\u2068", + "/firsttonechinese": "\u02C9", + "/fish": "\u1F41F", + "/fishCakeSwirlDesign": "\u1F365", + "/fisheye": "\u25C9", + "/fishingPoleAndFish": "\u1F3A3", + "/fistedHandSign": "\u1F44A", + "/fitacyr": "\u0473", + "/fitacyrillic": "\u0473", + "/five": "\u0035", + "/five.inferior": "\u2085", + "/five.roman": "\u2164", + "/five.romansmall": "\u2174", + "/five.superior": "\u2075", + "/fivearabic": "\u0665", + "/fivebengali": "\u09EB", + "/fivecircle": "\u2464", + "/fivecircledbl": "\u24F9", + "/fivecircleinversesansserif": "\u278E", + "/fivecomma": "\u1F106", + "/fivedeva": "\u096B", + "/fivedot": "\u2E2D", + "/fivedotpunctuation": "\u2059", + "/fiveeighths": "\u215D", + "/fivefar": "\u06F5", + "/fivegujarati": "\u0AEB", + "/fivegurmukhi": "\u0A6B", + "/fivehackarabic": "\u0665", + "/fivehangzhou": "\u3025", + "/fivehundred.roman": "\u216E", + "/fivehundred.romansmall": "\u217E", + "/fiveideographiccircled": "\u3284", + "/fiveideographicparen": "\u3224", + "/fiveinferior": "\u2085", + "/fivemonospace": "\uFF15", + "/fiveoldstyle": "\uF735", + "/fiveparen": "\u2478", + "/fiveparenthesized": "\u2478", + "/fiveperiod": "\u248C", + "/fivepersian": "\u06F5", + "/fivepointedstar": "\u066D", + "/fivepointonesquare": "\u1F1A0", + "/fiveroman": "\u2174", + "/fivesixths": "\u215A", + "/fivesuperior": "\u2075", + "/fivethai": "\u0E55", + "/fivethousand.roman": "\u2181", + "/fl": "\uFB02", + "/flagblack": "\u2691", + "/flaghorizontalmiddlestripeblackwhite": "\u26FF", + "/flaginhole": "\u26F3", + "/flagwhite": "\u2690", + "/flatness": "\u23E5", + "/fleurdelis": "\u269C", + "/flexedBiceps": "\u1F4AA", + "/floorleft": "\u230A", + "/floorright": "\u230B", + "/floppyDisk": "\u1F4BE", + "/floralheartbulletreversedrotated": "\u2619", + "/florin": "\u0192", + "/flower": "\u2698", + "/flowerPlayingCards": "\u1F3B4", + "/flowerpunctuationmark": "\u2055", + "/flushedFace": "\u1F633", + "/flyingEnvelope": "\u1F585", + "/flyingSaucer": "\u1F6F8", + "/fmfullwidth": "\u3399", + "/fmonospace": "\uFF46", + "/fmsquare": "\u3399", + "/fofanthai": "\u0E1F", + "/fofathai": "\u0E1D", + "/fog": "\u1F32B", + "/foggy": "\u1F301", + "/folder": "\u1F5C0", + "/fongmanthai": "\u0E4F", + "/footnote": "\u0602", + "/footprints": "\u1F463", + "/footsquare": "\u23CD", + "/forall": "\u2200", + "/forces": "\u22A9", + "/fork": "\u2442", + "/forkKnife": "\u1F374", + "/forkKnifePlate": "\u1F37D", + "/forsamaritan": "\u214F", + "/fortycircle": "\u32B5", + "/fortycirclesquare": "\u324B", + "/fortyeightcircle": "\u32BD", + "/fortyfivecircle": "\u32BA", + "/fortyfourcircle": "\u32B9", + "/fortyninecircle": "\u32BE", + "/fortyonecircle": "\u32B6", + "/fortysevencircle": "\u32BC", + "/fortysixcircle": "\u32BB", + "/fortythreecircle": "\u32B8", + "/fortytwocircle": "\u32B7", + "/fountain": "\u26F2", + "/four": "\u0034", + "/four.inferior": "\u2084", + "/four.roman": "\u2163", + "/four.romansmall": "\u2173", + "/four.superior": "\u2074", + "/fourLeafClover": "\u1F340", + "/fourarabic": "\u0664", + "/fourbengali": "\u09EA", + "/fourcircle": "\u2463", + "/fourcircledbl": "\u24F8", + "/fourcircleinversesansserif": "\u278D", + "/fourcomma": "\u1F105", + "/fourdeva": "\u096A", + "/fourdotmark": "\u205B", + "/fourdotpunctuation": "\u2058", + "/fourfar": "\u06F4", + "/fourfifths": "\u2158", + "/fourgujarati": "\u0AEA", + "/fourgurmukhi": "\u0A6A", + "/fourhackarabic": "\u0664", + "/fourhangzhou": "\u3024", + "/fourideographiccircled": "\u3283", + "/fourideographicparen": "\u3223", + "/fourinferior": "\u2084", + "/fourksquare": "\u1F19E", + "/fourmonospace": "\uFF14", + "/fournumeratorbengali": "\u09F7", + "/fouroldstyle": "\uF734", + "/fourparen": "\u2477", + "/fourparenthesized": "\u2477", + "/fourperemspace": "\u2005", + "/fourperiod": "\u248B", + "/fourpersian": "\u06F4", + "/fourroman": "\u2173", + "/foursuperior": "\u2074", + "/fourteencircle": "\u246D", + "/fourteencircleblack": "\u24EE", + "/fourteenparen": "\u2481", + "/fourteenparenthesized": "\u2481", + "/fourteenperiod": "\u2495", + "/fourthai": "\u0E54", + "/fourthtonechinese": "\u02CB", + "/fparen": "\u24A1", + "/fparenthesized": "\u24A1", + "/fraction": "\u2044", + "/frameAnX": "\u1F5BE", + "/framePicture": "\u1F5BC", + "/frameTiles": "\u1F5BD", + "/franc": "\u20A3", + "/freesquare": "\u1F193", + "/frenchFries": "\u1F35F", + "/freversedepigraphic": "\uA7FB", + "/friedShrimp": "\u1F364", + "/frogFace": "\u1F438", + "/front-facingBabyChick": "\u1F425", + "/frown": "\u2322", + "/frowningFaceWithOpenMouth": "\u1F626", + "/frowningfacewhite": "\u2639", + "/fstroke": "\uA799", + "/fturned": "\u214E", + "/fuelpump": "\u26FD", + "/fullBlock": "\u2588", + "/fullMoon": "\u1F315", + "/fullMoonFace": "\u1F31D", + "/functionapplication": "\u2061", + "/funeralurn": "\u26B1", + "/fuse": "\u23DB", + "/fwd:A": "\uFF21", + "/fwd:B": "\uFF22", + "/fwd:C": "\uFF23", + "/fwd:D": "\uFF24", + "/fwd:E": "\uFF25", + "/fwd:F": "\uFF26", + "/fwd:G": "\uFF27", + "/fwd:H": "\uFF28", + "/fwd:I": "\uFF29", + "/fwd:J": "\uFF2A", + "/fwd:K": "\uFF2B", + "/fwd:L": "\uFF2C", + "/fwd:M": "\uFF2D", + "/fwd:N": "\uFF2E", + "/fwd:O": "\uFF2F", + "/fwd:P": "\uFF30", + "/fwd:Q": "\uFF31", + "/fwd:R": "\uFF32", + "/fwd:S": "\uFF33", + "/fwd:T": "\uFF34", + "/fwd:U": "\uFF35", + "/fwd:V": "\uFF36", + "/fwd:W": "\uFF37", + "/fwd:X": "\uFF38", + "/fwd:Y": "\uFF39", + "/fwd:Z": "\uFF3A", + "/fwd:a": "\uFF41", + "/fwd:ampersand": "\uFF06", + "/fwd:asciicircum": "\uFF3E", + "/fwd:asciitilde": "\uFF5E", + "/fwd:asterisk": "\uFF0A", + "/fwd:at": "\uFF20", + "/fwd:b": "\uFF42", + "/fwd:backslash": "\uFF3C", + "/fwd:bar": "\uFF5C", + "/fwd:braceleft": "\uFF5B", + "/fwd:braceright": "\uFF5D", + "/fwd:bracketleft": "\uFF3B", + "/fwd:bracketright": "\uFF3D", + "/fwd:brokenbar": "\uFFE4", + "/fwd:c": "\uFF43", + "/fwd:centsign": "\uFFE0", + "/fwd:colon": "\uFF1A", + "/fwd:comma": "\uFF0C", + "/fwd:d": "\uFF44", + "/fwd:dollar": "\uFF04", + "/fwd:e": "\uFF45", + "/fwd:eight": "\uFF18", + "/fwd:equal": "\uFF1D", + "/fwd:exclam": "\uFF01", + "/fwd:f": "\uFF46", + "/fwd:five": "\uFF15", + "/fwd:four": "\uFF14", + "/fwd:g": "\uFF47", + "/fwd:grave": "\uFF40", + "/fwd:greater": "\uFF1E", + "/fwd:h": "\uFF48", + "/fwd:hyphen": "\uFF0D", + "/fwd:i": "\uFF49", + "/fwd:j": "\uFF4A", + "/fwd:k": "\uFF4B", + "/fwd:l": "\uFF4C", + "/fwd:leftwhiteparenthesis": "\uFF5F", + "/fwd:less": "\uFF1C", + "/fwd:m": "\uFF4D", + "/fwd:macron": "\uFFE3", + "/fwd:n": "\uFF4E", + "/fwd:nine": "\uFF19", + "/fwd:notsign": "\uFFE2", + "/fwd:numbersign": "\uFF03", + "/fwd:o": "\uFF4F", + "/fwd:one": "\uFF11", + "/fwd:p": "\uFF50", + "/fwd:parenthesisleft": "\uFF08", + "/fwd:parenthesisright": "\uFF09", + "/fwd:percent": "\uFF05", + "/fwd:period": "\uFF0E", + "/fwd:plus": "\uFF0B", + "/fwd:poundsign": "\uFFE1", + "/fwd:q": "\uFF51", + "/fwd:question": "\uFF1F", + "/fwd:quotedbl": "\uFF02", + "/fwd:quotesingle": "\uFF07", + "/fwd:r": "\uFF52", + "/fwd:rightwhiteparenthesis": "\uFF60", + "/fwd:s": "\uFF53", + "/fwd:semicolon": "\uFF1B", + "/fwd:seven": "\uFF17", + "/fwd:six": "\uFF16", + "/fwd:slash": "\uFF0F", + "/fwd:t": "\uFF54", + "/fwd:three": "\uFF13", + "/fwd:two": "\uFF12", + "/fwd:u": "\uFF55", + "/fwd:underscore": "\uFF3F", + "/fwd:v": "\uFF56", + "/fwd:w": "\uFF57", + "/fwd:wonsign": "\uFFE6", + "/fwd:x": "\uFF58", + "/fwd:y": "\uFF59", + "/fwd:yensign": "\uFFE5", + "/fwd:z": "\uFF5A", + "/fwd:zero": "\uFF10", + "/g": "\u0067", + "/gabengali": "\u0997", + "/gacute": "\u01F5", + "/gadeva": "\u0917", + "/gaf": "\u06AF", + "/gaf.fina": "\uFB93", + "/gaf.init": "\uFB94", + "/gaf.isol": "\uFB92", + "/gaf.medi": "\uFB95", + "/gafarabic": "\u06AF", + "/gaffinalarabic": "\uFB93", + "/gafinitialarabic": "\uFB94", + "/gafmedialarabic": "\uFB95", + "/gafring": "\u06B0", + "/gafthreedotsabove": "\u06B4", + "/gaftwodotsbelow": "\u06B2", + "/gagujarati": "\u0A97", + "/gagurmukhi": "\u0A17", + "/gahiragana": "\u304C", + "/gakatakana": "\u30AC", + "/galsquare": "\u33FF", + "/gameDie": "\u1F3B2", + "/gamma": "\u03B3", + "/gammadblstruck": "\u213D", + "/gammalatinsmall": "\u0263", + "/gammasuperior": "\u02E0", + "/gammasupmod": "\u02E0", + "/gamurda": "\uA993", + "/gangiacoptic": "\u03EB", + "/ganmasquare": "\u330F", + "/garonsquare": "\u330E", + "/gbfullwidth": "\u3387", + "/gbopomofo": "\u310D", + "/gbreve": "\u011F", + "/gcaron": "\u01E7", + "/gcedilla": "\u0123", + "/gcircle": "\u24D6", + "/gcircumflex": "\u011D", + "/gcommaaccent": "\u0123", + "/gdot": "\u0121", + "/gdotaccent": "\u0121", + "/gear": "\u2699", + "/gearhles": "\u26EE", + "/gearouthub": "\u26ED", + "/gecyr": "\u0433", + "/gecyrillic": "\u0433", + "/gehiragana": "\u3052", + "/gehookcyr": "\u0495", + "/gehookstrokecyr": "\u04FB", + "/gekatakana": "\u30B2", + "/gemStone": "\u1F48E", + "/gemini": "\u264A", + "/geometricallyequal": "\u2251", + "/geometricallyequivalent": "\u224E", + "/geometricproportion": "\u223A", + "/geresh:hb": "\u05F3", + "/gereshMuqdam:hb": "\u059D", + "/gereshaccenthebrew": "\u059C", + "/gereshhebrew": "\u05F3", + "/gereshmuqdamhebrew": "\u059D", + "/germandbls": "\u00DF", + "/germanpenny": "\u20B0", + "/gershayim:hb": "\u05F4", + "/gershayimaccenthebrew": "\u059E", + "/gershayimhebrew": "\u05F4", + "/gestrokecyr": "\u0493", + "/getailcyr": "\u04F7", + "/getamark": "\u3013", + "/geupcyr": "\u0491", + "/ghabengali": "\u0998", + "/ghadarmenian": "\u0572", + "/ghadeva": "\u0918", + "/ghagujarati": "\u0A98", + "/ghagurmukhi": "\u0A18", + "/ghain": "\u063A", + "/ghain.fina": "\uFECE", + "/ghain.init": "\uFECF", + "/ghain.init_alefmaksura.fina": "\uFCF9", + "/ghain.init_jeem.fina": "\uFC2B", + "/ghain.init_jeem.medi": "\uFCBC", + "/ghain.init_meem.fina": "\uFC2C", + "/ghain.init_meem.medi": "\uFCBD", + "/ghain.init_yeh.fina": "\uFCFA", + "/ghain.isol": "\uFECD", + "/ghain.medi": "\uFED0", + "/ghain.medi_alefmaksura.fina": "\uFD15", + "/ghain.medi_meem.medi_alefmaksura.fina": "\uFD7B", + "/ghain.medi_meem.medi_meem.fina": "\uFD79", + "/ghain.medi_meem.medi_yeh.fina": "\uFD7A", + "/ghain.medi_yeh.fina": "\uFD16", + "/ghainarabic": "\u063A", + "/ghaindotbelow": "\u06FC", + "/ghainfinalarabic": "\uFECE", + "/ghaininitialarabic": "\uFECF", + "/ghainmedialarabic": "\uFED0", + "/ghemiddlehookcyrillic": "\u0495", + "/ghestrokecyrillic": "\u0493", + "/gheupturncyrillic": "\u0491", + "/ghhadeva": "\u095A", + "/ghhagurmukhi": "\u0A5A", + "/ghook": "\u0260", + "/ghost": "\u1F47B", + "/ghzfullwidth": "\u3393", + "/ghzsquare": "\u3393", + "/gigasquare": "\u3310", + "/gihiragana": "\u304E", + "/gikatakana": "\u30AE", + "/gimarmenian": "\u0563", + "/gimel": "\u05D2", + "/gimel:hb": "\u05D2", + "/gimeldagesh": "\uFB32", + "/gimeldageshhebrew": "\uFB32", + "/gimelhebrew": "\u05D2", + "/gimelwithdagesh:hb": "\uFB32", + "/giniisquare": "\u3311", + "/ginsularturned": "\uA77F", + "/girl": "\u1F467", + "/girls": "\u1F6CA", + "/girudaasquare": "\u3313", + "/gjecyr": "\u0453", + "/gjecyrillic": "\u0453", + "/globeMeridians": "\u1F310", + "/glottalinvertedstroke": "\u01BE", + "/glottalstop": "\u0294", + "/glottalstopinverted": "\u0296", + "/glottalstopmod": "\u02C0", + "/glottalstopreversed": "\u0295", + "/glottalstopreversedmod": "\u02C1", + "/glottalstopreversedsuperior": "\u02E4", + "/glottalstopstroke": "\u02A1", + "/glottalstopstrokereversed": "\u02A2", + "/glottalstopsupreversedmod": "\u02E4", + "/glowingStar": "\u1F31F", + "/gmacron": "\u1E21", + "/gmonospace": "\uFF47", + "/gmtr:diamondblack": "\u25C6", + "/gmtr:diamondwhite": "\u25C7", + "/gnrl:hyphen": "\u2010", + "/goat": "\u1F410", + "/gobliquestroke": "\uA7A1", + "/gohiragana": "\u3054", + "/gokatakana": "\u30B4", + "/golfer": "\u1F3CC", + "/gpafullwidth": "\u33AC", + "/gparen": "\u24A2", + "/gparenthesized": "\u24A2", + "/gpasquare": "\u33AC", + "/gr:acute": "\u1FFD", + "/gr:grave": "\u1FEF", + "/gr:question": "\u037E", + "/gr:tilde": "\u1FC0", + "/gradient": "\u2207", + "/graduationCap": "\u1F393", + "/grapes": "\u1F347", + "/grave": "\u0060", + "/gravebelowcmb": "\u0316", + "/gravecmb": "\u0300", + "/gravecomb": "\u0300", + "/gravedblmiddlemod": "\u02F5", + "/gravedeva": "\u0953", + "/gravelowmod": "\u02CE", + "/gravemiddlemod": "\u02F4", + "/gravemod": "\u02CB", + "/gravemonospace": "\uFF40", + "/gravetonecmb": "\u0340", + "/greater": "\u003E", + "/greaterbutnotequal": "\u2269", + "/greaterbutnotequivalent": "\u22E7", + "/greaterdot": "\u22D7", + "/greaterequal": "\u2265", + "/greaterequalorless": "\u22DB", + "/greatermonospace": "\uFF1E", + "/greaterorequivalent": "\u2273", + "/greaterorless": "\u2277", + "/greateroverequal": "\u2267", + "/greatersmall": "\uFE65", + "/greenApple": "\u1F34F", + "/greenBook": "\u1F4D7", + "/greenHeart": "\u1F49A", + "/grimacingFace": "\u1F62C", + "/grinningCatFaceWithSmilingEyes": "\u1F638", + "/grinningFace": "\u1F600", + "/grinningFaceWithSmilingEyes": "\u1F601", + "/growingHeart": "\u1F497", + "/gscript": "\u0261", + "/gstroke": "\u01E5", + "/guarani": "\u20B2", + "/guardsman": "\u1F482", + "/gueh": "\u06B3", + "/gueh.fina": "\uFB97", + "/gueh.init": "\uFB98", + "/gueh.isol": "\uFB96", + "/gueh.medi": "\uFB99", + "/guhiragana": "\u3050", + "/guillemetleft": "\u00AB", + "/guillemetright": "\u00BB", + "/guillemotleft": "\u00AB", + "/guillemotright": "\u00BB", + "/guilsinglleft": "\u2039", + "/guilsinglright": "\u203A", + "/guitar": "\u1F3B8", + "/gujr:a": "\u0A85", + "/gujr:aa": "\u0A86", + "/gujr:aasign": "\u0ABE", + "/gujr:abbreviation": "\u0AF0", + "/gujr:ai": "\u0A90", + "/gujr:aisign": "\u0AC8", + "/gujr:anusvara": "\u0A82", + "/gujr:au": "\u0A94", + "/gujr:ausign": "\u0ACC", + "/gujr:avagraha": "\u0ABD", + "/gujr:ba": "\u0AAC", + "/gujr:bha": "\u0AAD", + "/gujr:binducandra": "\u0A81", + "/gujr:ca": "\u0A9A", + "/gujr:cha": "\u0A9B", + "/gujr:circlenuktaabove": "\u0AFE", + "/gujr:da": "\u0AA6", + "/gujr:dda": "\u0AA1", + "/gujr:ddha": "\u0AA2", + "/gujr:dha": "\u0AA7", + "/gujr:e": "\u0A8F", + "/gujr:ecandra": "\u0A8D", + "/gujr:eight": "\u0AEE", + "/gujr:esign": "\u0AC7", + "/gujr:esigncandra": "\u0AC5", + "/gujr:five": "\u0AEB", + "/gujr:four": "\u0AEA", + "/gujr:ga": "\u0A97", + "/gujr:gha": "\u0A98", + "/gujr:ha": "\u0AB9", + "/gujr:i": "\u0A87", + "/gujr:ii": "\u0A88", + "/gujr:iisign": "\u0AC0", + "/gujr:isign": "\u0ABF", + "/gujr:ja": "\u0A9C", + "/gujr:jha": "\u0A9D", + "/gujr:ka": "\u0A95", + "/gujr:kha": "\u0A96", + "/gujr:la": "\u0AB2", + "/gujr:lla": "\u0AB3", + "/gujr:llvocal": "\u0AE1", + "/gujr:llvocalsign": "\u0AE3", + "/gujr:lvocal": "\u0A8C", + "/gujr:lvocalsign": "\u0AE2", + "/gujr:ma": "\u0AAE", + "/gujr:maddah": "\u0AFC", + "/gujr:na": "\u0AA8", + "/gujr:nga": "\u0A99", + "/gujr:nine": "\u0AEF", + "/gujr:nna": "\u0AA3", + "/gujr:nukta": "\u0ABC", + "/gujr:nya": "\u0A9E", + "/gujr:o": "\u0A93", + "/gujr:ocandra": "\u0A91", + "/gujr:om": "\u0AD0", + "/gujr:one": "\u0AE7", + "/gujr:osign": "\u0ACB", + "/gujr:osigncandra": "\u0AC9", + "/gujr:pa": "\u0AAA", + "/gujr:pha": "\u0AAB", + "/gujr:ra": "\u0AB0", + "/gujr:rrvocal": "\u0AE0", + "/gujr:rrvocalsign": "\u0AC4", + "/gujr:rupee": "\u0AF1", + "/gujr:rvocal": "\u0A8B", + "/gujr:rvocalsign": "\u0AC3", + "/gujr:sa": "\u0AB8", + "/gujr:seven": "\u0AED", + "/gujr:sha": "\u0AB6", + "/gujr:shadda": "\u0AFB", + "/gujr:six": "\u0AEC", + "/gujr:ssa": "\u0AB7", + "/gujr:sukun": "\u0AFA", + "/gujr:ta": "\u0AA4", + "/gujr:tha": "\u0AA5", + "/gujr:three": "\u0AE9", + "/gujr:three-dotnuktaabove": "\u0AFD", + "/gujr:tta": "\u0A9F", + "/gujr:ttha": "\u0AA0", + "/gujr:two": "\u0AE8", + "/gujr:two-circlenuktaabove": "\u0AFF", + "/gujr:u": "\u0A89", + "/gujr:usign": "\u0AC1", + "/gujr:uu": "\u0A8A", + "/gujr:uusign": "\u0AC2", + "/gujr:va": "\u0AB5", + "/gujr:virama": "\u0ACD", + "/gujr:visarga": "\u0A83", + "/gujr:ya": "\u0AAF", + "/gujr:zero": "\u0AE6", + "/gujr:zha": "\u0AF9", + "/gukatakana": "\u30B0", + "/guramusquare": "\u3318", + "/guramutonsquare": "\u3319", + "/guru:a": "\u0A05", + "/guru:aa": "\u0A06", + "/guru:aasign": "\u0A3E", + "/guru:adakbindisign": "\u0A01", + "/guru:addak": "\u0A71", + "/guru:ai": "\u0A10", + "/guru:aisign": "\u0A48", + "/guru:au": "\u0A14", + "/guru:ausign": "\u0A4C", + "/guru:ba": "\u0A2C", + "/guru:bha": "\u0A2D", + "/guru:bindisign": "\u0A02", + "/guru:ca": "\u0A1A", + "/guru:cha": "\u0A1B", + "/guru:da": "\u0A26", + "/guru:dda": "\u0A21", + "/guru:ddha": "\u0A22", + "/guru:dha": "\u0A27", + "/guru:ee": "\u0A0F", + "/guru:eesign": "\u0A47", + "/guru:eight": "\u0A6E", + "/guru:ekonkar": "\u0A74", + "/guru:fa": "\u0A5E", + "/guru:five": "\u0A6B", + "/guru:four": "\u0A6A", + "/guru:ga": "\u0A17", + "/guru:gha": "\u0A18", + "/guru:ghha": "\u0A5A", + "/guru:ha": "\u0A39", + "/guru:i": "\u0A07", + "/guru:ii": "\u0A08", + "/guru:iisign": "\u0A40", + "/guru:iri": "\u0A72", + "/guru:isign": "\u0A3F", + "/guru:ja": "\u0A1C", + "/guru:jha": "\u0A1D", + "/guru:ka": "\u0A15", + "/guru:kha": "\u0A16", + "/guru:khha": "\u0A59", + "/guru:la": "\u0A32", + "/guru:lla": "\u0A33", + "/guru:ma": "\u0A2E", + "/guru:na": "\u0A28", + "/guru:nga": "\u0A19", + "/guru:nine": "\u0A6F", + "/guru:nna": "\u0A23", + "/guru:nukta": "\u0A3C", + "/guru:nya": "\u0A1E", + "/guru:one": "\u0A67", + "/guru:oo": "\u0A13", + "/guru:oosign": "\u0A4B", + "/guru:pa": "\u0A2A", + "/guru:pha": "\u0A2B", + "/guru:ra": "\u0A30", + "/guru:rra": "\u0A5C", + "/guru:sa": "\u0A38", + "/guru:seven": "\u0A6D", + "/guru:sha": "\u0A36", + "/guru:six": "\u0A6C", + "/guru:ta": "\u0A24", + "/guru:tha": "\u0A25", + "/guru:three": "\u0A69", + "/guru:tippi": "\u0A70", + "/guru:tta": "\u0A1F", + "/guru:ttha": "\u0A20", + "/guru:two": "\u0A68", + "/guru:u": "\u0A09", + "/guru:udaatsign": "\u0A51", + "/guru:ura": "\u0A73", + "/guru:usign": "\u0A41", + "/guru:uu": "\u0A0A", + "/guru:uusign": "\u0A42", + "/guru:va": "\u0A35", + "/guru:virama": "\u0A4D", + "/guru:visarga": "\u0A03", + "/guru:ya": "\u0A2F", + "/guru:yakashsign": "\u0A75", + "/guru:za": "\u0A5B", + "/guru:zero": "\u0A66", + "/gyfullwidth": "\u33C9", + "/gysquare": "\u33C9", + "/h": "\u0068", + "/h.inferior": "\u2095", + "/haabkhasiancyrillic": "\u04A9", + "/haabkhcyr": "\u04A9", + "/haaltonearabic": "\u06C1", + "/habengali": "\u09B9", + "/hacirclekatakana": "\u32E9", + "/hacyr": "\u0445", + "/hadescendercyrillic": "\u04B3", + "/hadeva": "\u0939", + "/hafullwidth": "\u33CA", + "/hagujarati": "\u0AB9", + "/hagurmukhi": "\u0A39", + "/hah": "\u062D", + "/hah.fina": "\uFEA2", + "/hah.init": "\uFEA3", + "/hah.init_alefmaksura.fina": "\uFCFF", + "/hah.init_jeem.fina": "\uFC17", + "/hah.init_jeem.medi": "\uFCA9", + "/hah.init_meem.fina": "\uFC18", + "/hah.init_meem.medi": "\uFCAA", + "/hah.init_yeh.fina": "\uFD00", + "/hah.isol": "\uFEA1", + "/hah.medi": "\uFEA4", + "/hah.medi_alefmaksura.fina": "\uFD1B", + "/hah.medi_jeem.medi_yeh.fina": "\uFDBF", + "/hah.medi_meem.medi_alefmaksura.fina": "\uFD5B", + "/hah.medi_meem.medi_yeh.fina": "\uFD5A", + "/hah.medi_yeh.fina": "\uFD1C", + "/hahDigitFourBelow": "\u077C", + "/hahSmallTahAbove": "\u0772", + "/hahSmallTahBelow": "\u076E", + "/hahSmallTahTwoDots": "\u076F", + "/hahThreeDotsUpBelow": "\u0758", + "/hahTwoDotsAbove": "\u0757", + "/haharabic": "\u062D", + "/hahfinalarabic": "\uFEA2", + "/hahhamza": "\u0681", + "/hahinitialarabic": "\uFEA3", + "/hahiragana": "\u306F", + "/hahmedialarabic": "\uFEA4", + "/hahookcyr": "\u04FD", + "/hahthreedotsabove": "\u0685", + "/hahtwodotsvertical": "\u0682", + "/haircut": "\u1F487", + "/hairspace": "\u200A", + "/haitusquare": "\u332A", + "/hakatakana": "\u30CF", + "/hakatakanahalfwidth": "\uFF8A", + "/halantgurmukhi": "\u0A4D", + "/halfcircleleftblack": "\u25D6", + "/halfcirclerightblack": "\u25D7", + "/hamburger": "\u1F354", + "/hammer": "\u1F528", + "/hammerAndWrench": "\u1F6E0", + "/hammerpick": "\u2692", + "/hammersickle": "\u262D", + "/hamsterFace": "\u1F439", + "/hamza": "\u0621", + "/hamzaIsol": "\uFE80", + "/hamzaabove": "\u0654", + "/hamzaarabic": "\u0621", + "/hamzabelow": "\u0655", + "/hamzadammaarabic": "\u0621", + "/hamzadammatanarabic": "\u0621", + "/hamzafathaarabic": "\u0621", + "/hamzafathatanarabic": "\u0621", + "/hamzalowarabic": "\u0621", + "/hamzalowkasraarabic": "\u0621", + "/hamzalowkasratanarabic": "\u0621", + "/hamzasukunarabic": "\u0621", + "/handbag": "\u1F45C", + "/handtailfishhookturned": "\u02AF", + "/hangulchieuchaparen": "\u3217", + "/hangulchieuchparen": "\u3209", + "/hangulcieucaparen": "\u3216", + "/hangulcieucparen": "\u3208", + "/hangulcieucuparen": "\u321C", + "/hanguldottonemarkdbl": "\u302F", + "/hangulfiller": "\u3164", + "/hangulhieuhaparen": "\u321B", + "/hangulhieuhparen": "\u320D", + "/hangulieungaparen": "\u3215", + "/hangulieungparen": "\u3207", + "/hangulkhieukhaparen": "\u3218", + "/hangulkhieukhparen": "\u320A", + "/hangulkiyeokaparen": "\u320E", + "/hangulkiyeokparen": "\u3200", + "/hangulmieumaparen": "\u3212", + "/hangulmieumparen": "\u3204", + "/hangulnieunaparen": "\u320F", + "/hangulnieunparen": "\u3201", + "/hangulphieuphaparen": "\u321A", + "/hangulphieuphparen": "\u320C", + "/hangulpieupaparen": "\u3213", + "/hangulpieupparen": "\u3205", + "/hangulrieulaparen": "\u3211", + "/hangulrieulparen": "\u3203", + "/hangulsingledottonemark": "\u302E", + "/hangulsiosaparen": "\u3214", + "/hangulsiosparen": "\u3206", + "/hangulthieuthaparen": "\u3219", + "/hangulthieuthparen": "\u320B", + "/hangultikeutaparen": "\u3210", + "/hangultikeutparen": "\u3202", + "/happyPersonRaisingOneHand": "\u1F64B", + "/hardDisk": "\u1F5B4", + "/hardcyr": "\u044A", + "/hardsigncyrillic": "\u044A", + "/harpoondownbarbleft": "\u21C3", + "/harpoondownbarbright": "\u21C2", + "/harpoonleftbarbdown": "\u21BD", + "/harpoonleftbarbup": "\u21BC", + "/harpoonrightbarbdown": "\u21C1", + "/harpoonrightbarbup": "\u21C0", + "/harpoonupbarbleft": "\u21BF", + "/harpoonupbarbright": "\u21BE", + "/hasquare": "\u33CA", + "/hastrokecyr": "\u04FF", + "/hatafPatah:hb": "\u05B2", + "/hatafQamats:hb": "\u05B3", + "/hatafSegol:hb": "\u05B1", + "/hatafpatah": "\u05B2", + "/hatafpatah16": "\u05B2", + "/hatafpatah23": "\u05B2", + "/hatafpatah2f": "\u05B2", + "/hatafpatahhebrew": "\u05B2", + "/hatafpatahnarrowhebrew": "\u05B2", + "/hatafpatahquarterhebrew": "\u05B2", + "/hatafpatahwidehebrew": "\u05B2", + "/hatafqamats": "\u05B3", + "/hatafqamats1b": "\u05B3", + "/hatafqamats28": "\u05B3", + "/hatafqamats34": "\u05B3", + "/hatafqamatshebrew": "\u05B3", + "/hatafqamatsnarrowhebrew": "\u05B3", + "/hatafqamatsquarterhebrew": "\u05B3", + "/hatafqamatswidehebrew": "\u05B3", + "/hatafsegol": "\u05B1", + "/hatafsegol17": "\u05B1", + "/hatafsegol24": "\u05B1", + "/hatafsegol30": "\u05B1", + "/hatafsegolhebrew": "\u05B1", + "/hatafsegolnarrowhebrew": "\u05B1", + "/hatafsegolquarterhebrew": "\u05B1", + "/hatafsegolwidehebrew": "\u05B1", + "/hatchingChick": "\u1F423", + "/haveideographiccircled": "\u3292", + "/haveideographicparen": "\u3232", + "/hbar": "\u0127", + "/hbopomofo": "\u310F", + "/hbrevebelow": "\u1E2B", + "/hcaron": "\u021F", + "/hcedilla": "\u1E29", + "/hcircle": "\u24D7", + "/hcircumflex": "\u0125", + "/hcsquare": "\u1F1A6", + "/hdescender": "\u2C68", + "/hdieresis": "\u1E27", + "/hdot": "\u1E23", + "/hdotaccent": "\u1E23", + "/hdotbelow": "\u1E25", + "/hdrsquare": "\u1F1A7", + "/he": "\u05D4", + "/he:hb": "\u05D4", + "/headphone": "\u1F3A7", + "/headstonegraveyard": "\u26FC", + "/hearNoEvilMonkey": "\u1F649", + "/heart": "\u2665", + "/heartArrow": "\u1F498", + "/heartDecoration": "\u1F49F", + "/heartRibbon": "\u1F49D", + "/heartTipOnTheLeft": "\u1F394", + "/heartblack": "\u2665", + "/heartsuitblack": "\u2665", + "/heartsuitwhite": "\u2661", + "/heartwhite": "\u2661", + "/heavyDollarSign": "\u1F4B2", + "/heavyLatinCross": "\u1F547", + "/heavydbldashhorz": "\u254D", + "/heavydbldashvert": "\u254F", + "/heavydn": "\u257B", + "/heavydnhorz": "\u2533", + "/heavydnleft": "\u2513", + "/heavydnright": "\u250F", + "/heavyhorz": "\u2501", + "/heavyleft": "\u2578", + "/heavyleftlightright": "\u257E", + "/heavyquaddashhorz": "\u2509", + "/heavyquaddashvert": "\u250B", + "/heavyright": "\u257A", + "/heavytrpldashhorz": "\u2505", + "/heavytrpldashvert": "\u2507", + "/heavyup": "\u2579", + "/heavyuphorz": "\u253B", + "/heavyupleft": "\u251B", + "/heavyuplightdn": "\u257F", + "/heavyupright": "\u2517", + "/heavyvert": "\u2503", + "/heavyverthorz": "\u254B", + "/heavyvertleft": "\u252B", + "/heavyvertright": "\u2523", + "/hecirclekatakana": "\u32EC", + "/hedagesh": "\uFB34", + "/hedageshhebrew": "\uFB34", + "/hedinterlacedpentagramleft": "\u26E6", + "/hedinterlacedpentagramright": "\u26E5", + "/heh": "\u0647", + "/heh.fina": "\uFEEA", + "/heh.init": "\uFEEB", + "/heh.init_alefmaksura.fina": "\uFC53", + "/heh.init_jeem.fina": "\uFC51", + "/heh.init_jeem.medi": "\uFCD7", + "/heh.init_meem.fina": "\uFC52", + "/heh.init_meem.medi": "\uFCD8", + "/heh.init_meem.medi_jeem.medi": "\uFD93", + "/heh.init_meem.medi_meem.medi": "\uFD94", + "/heh.init_superscriptalef.medi": "\uFCD9", + "/heh.init_yeh.fina": "\uFC54", + "/heh.isol": "\uFEE9", + "/heh.medi": "\uFEEC", + "/hehaltonearabic": "\u06C1", + "/heharabic": "\u0647", + "/hehdoachashmee": "\u06BE", + "/hehdoachashmee.fina": "\uFBAB", + "/hehdoachashmee.init": "\uFBAC", + "/hehdoachashmee.isol": "\uFBAA", + "/hehdoachashmee.medi": "\uFBAD", + "/hehebrew": "\u05D4", + "/hehfinalaltonearabic": "\uFBA7", + "/hehfinalalttwoarabic": "\uFEEA", + "/hehfinalarabic": "\uFEEA", + "/hehgoal": "\u06C1", + "/hehgoal.fina": "\uFBA7", + "/hehgoal.init": "\uFBA8", + "/hehgoal.isol": "\uFBA6", + "/hehgoal.medi": "\uFBA9", + "/hehgoalhamza": "\u06C2", + "/hehhamzaabovefinalarabic": "\uFBA5", + "/hehhamzaaboveisolatedarabic": "\uFBA4", + "/hehinitialaltonearabic": "\uFBA8", + "/hehinitialarabic": "\uFEEB", + "/hehinvertedV": "\u06FF", + "/hehiragana": "\u3078", + "/hehmedialaltonearabic": "\uFBA9", + "/hehmedialarabic": "\uFEEC", + "/hehyeh": "\u06C0", + "/hehyeh.fina": "\uFBA5", + "/hehyeh.isol": "\uFBA4", + "/heiseierasquare": "\u337B", + "/hekatakana": "\u30D8", + "/hekatakanahalfwidth": "\uFF8D", + "/hekutaarusquare": "\u3336", + "/helicopter": "\u1F681", + "/helm": "\u2388", + "/helmetcrosswhite": "\u26D1", + "/heng": "\uA727", + "/henghook": "\u0267", + "/herb": "\u1F33F", + "/hermitianconjugatematrix": "\u22B9", + "/herutusquare": "\u3339", + "/het": "\u05D7", + "/het:hb": "\u05D7", + "/heta": "\u0371", + "/hethebrew": "\u05D7", + "/hewide:hb": "\uFB23", + "/hewithmapiq:hb": "\uFB34", + "/hfishhookturned": "\u02AE", + "/hhalf": "\u2C76", + "/hhook": "\u0266", + "/hhooksuperior": "\u02B1", + "/hhooksupmod": "\u02B1", + "/hi-ressquare": "\u1F1A8", + "/hibiscus": "\u1F33A", + "/hicirclekatakana": "\u32EA", + "/hieuhacirclekorean": "\u327B", + "/hieuhaparenkorean": "\u321B", + "/hieuhcirclekorean": "\u326D", + "/hieuhkorean": "\u314E", + "/hieuhparenkorean": "\u320D", + "/high-heeledShoe": "\u1F460", + "/highBrightness": "\u1F506", + "/highSpeedTrain": "\u1F684", + "/highSpeedTrainWithBulletNose": "\u1F685", + "/highhamza": "\u0674", + "/highideographiccircled": "\u32A4", + "/highvoltage": "\u26A1", + "/hihiragana": "\u3072", + "/hikatakana": "\u30D2", + "/hikatakanahalfwidth": "\uFF8B", + "/hira:a": "\u3042", + "/hira:asmall": "\u3041", + "/hira:ba": "\u3070", + "/hira:be": "\u3079", + "/hira:bi": "\u3073", + "/hira:bo": "\u307C", + "/hira:bu": "\u3076", + "/hira:da": "\u3060", + "/hira:de": "\u3067", + "/hira:di": "\u3062", + "/hira:digraphyori": "\u309F", + "/hira:do": "\u3069", + "/hira:du": "\u3065", + "/hira:e": "\u3048", + "/hira:esmall": "\u3047", + "/hira:ga": "\u304C", + "/hira:ge": "\u3052", + "/hira:gi": "\u304E", + "/hira:go": "\u3054", + "/hira:gu": "\u3050", + "/hira:ha": "\u306F", + "/hira:he": "\u3078", + "/hira:hi": "\u3072", + "/hira:ho": "\u307B", + "/hira:hu": "\u3075", + "/hira:i": "\u3044", + "/hira:ismall": "\u3043", + "/hira:iterationhiragana": "\u309D", + "/hira:ka": "\u304B", + "/hira:kasmall": "\u3095", + "/hira:ke": "\u3051", + "/hira:kesmall": "\u3096", + "/hira:ki": "\u304D", + "/hira:ko": "\u3053", + "/hira:ku": "\u304F", + "/hira:ma": "\u307E", + "/hira:me": "\u3081", + "/hira:mi": "\u307F", + "/hira:mo": "\u3082", + "/hira:mu": "\u3080", + "/hira:n": "\u3093", + "/hira:na": "\u306A", + "/hira:ne": "\u306D", + "/hira:ni": "\u306B", + "/hira:no": "\u306E", + "/hira:nu": "\u306C", + "/hira:o": "\u304A", + "/hira:osmall": "\u3049", + "/hira:pa": "\u3071", + "/hira:pe": "\u307A", + "/hira:pi": "\u3074", + "/hira:po": "\u307D", + "/hira:pu": "\u3077", + "/hira:ra": "\u3089", + "/hira:re": "\u308C", + "/hira:ri": "\u308A", + "/hira:ro": "\u308D", + "/hira:ru": "\u308B", + "/hira:sa": "\u3055", + "/hira:se": "\u305B", + "/hira:semivoicedmarkkana": "\u309C", + "/hira:semivoicedmarkkanacmb": "\u309A", + "/hira:si": "\u3057", + "/hira:so": "\u305D", + "/hira:su": "\u3059", + "/hira:ta": "\u305F", + "/hira:te": "\u3066", + "/hira:ti": "\u3061", + "/hira:to": "\u3068", + "/hira:tu": "\u3064", + "/hira:tusmall": "\u3063", + "/hira:u": "\u3046", + "/hira:usmall": "\u3045", + "/hira:voicediterationhiragana": "\u309E", + "/hira:voicedmarkkana": "\u309B", + "/hira:voicedmarkkanacmb": "\u3099", + "/hira:vu": "\u3094", + "/hira:wa": "\u308F", + "/hira:wasmall": "\u308E", + "/hira:we": "\u3091", + "/hira:wi": "\u3090", + "/hira:wo": "\u3092", + "/hira:ya": "\u3084", + "/hira:yasmall": "\u3083", + "/hira:yo": "\u3088", + "/hira:yosmall": "\u3087", + "/hira:yu": "\u3086", + "/hira:yusmall": "\u3085", + "/hira:za": "\u3056", + "/hira:ze": "\u305C", + "/hira:zi": "\u3058", + "/hira:zo": "\u305E", + "/hira:zu": "\u305A", + "/hiriq": "\u05B4", + "/hiriq14": "\u05B4", + "/hiriq21": "\u05B4", + "/hiriq2d": "\u05B4", + "/hiriq:hb": "\u05B4", + "/hiriqhebrew": "\u05B4", + "/hiriqnarrowhebrew": "\u05B4", + "/hiriqquarterhebrew": "\u05B4", + "/hiriqwidehebrew": "\u05B4", + "/historicsite": "\u26EC", + "/hlinebelow": "\u1E96", + "/hmonospace": "\uFF48", + "/hoarmenian": "\u0570", + "/hocho": "\u1F52A", + "/hocirclekatakana": "\u32ED", + "/hohipthai": "\u0E2B", + "/hohiragana": "\u307B", + "/hokatakana": "\u30DB", + "/hokatakanahalfwidth": "\uFF8E", + "/holam": "\u05B9", + "/holam19": "\u05B9", + "/holam26": "\u05B9", + "/holam32": "\u05B9", + "/holam:hb": "\u05B9", + "/holamHaser:hb": "\u05BA", + "/holamhebrew": "\u05B9", + "/holamnarrowhebrew": "\u05B9", + "/holamquarterhebrew": "\u05B9", + "/holamwidehebrew": "\u05B9", + "/hole": "\u1F573", + "/homotic": "\u223B", + "/honeyPot": "\u1F36F", + "/honeybee": "\u1F41D", + "/honokhukthai": "\u0E2E", + "/honsquare": "\u333F", + "/hook": "\u2440", + "/hookabovecomb": "\u0309", + "/hookcmb": "\u0309", + "/hookpalatalizedbelowcmb": "\u0321", + "/hookretroflexbelowcmb": "\u0322", + "/hoonsquare": "\u3342", + "/hoorusquare": "\u3341", + "/horicoptic": "\u03E9", + "/horizontalTrafficLight": "\u1F6A5", + "/horizontalbar": "\u2015", + "/horizontalbarwhitearrowonpedestalup": "\u21EC", + "/horizontalmalestroke": "\u26A9", + "/horncmb": "\u031B", + "/horse": "\u1F40E", + "/horseFace": "\u1F434", + "/horseRacing": "\u1F3C7", + "/hospital": "\u1F3E5", + "/hotDog": "\u1F32D", + "/hotPepper": "\u1F336", + "/hotbeverage": "\u2615", + "/hotel": "\u1F3E8", + "/hotsprings": "\u2668", + "/hourglass": "\u231B", + "/hourglassflowings": "\u23F3", + "/house": "\u2302", + "/houseBuilding": "\u1F3E0", + "/houseBuildings": "\u1F3D8", + "/houseGarden": "\u1F3E1", + "/hpafullwidth": "\u3371", + "/hpalatalhook": "\uA795", + "/hparen": "\u24A3", + "/hparenthesized": "\u24A3", + "/hpfullwidth": "\u33CB", + "/hryvnia": "\u20B4", + "/hsuperior": "\u02B0", + "/hsupmod": "\u02B0", + "/hturned": "\u0265", + "/htypeopencircuit": "\u238F", + "/huaraddosquare": "\u3332", + "/hucirclekatakana": "\u32EB", + "/huhiragana": "\u3075", + "/huiitosquare": "\u3333", + "/hukatakana": "\u30D5", + "/hukatakanahalfwidth": "\uFF8C", + "/hundredPoints": "\u1F4AF", + "/hundredthousandscmbcyr": "\u0488", + "/hungarumlaut": "\u02DD", + "/hungarumlautcmb": "\u030B", + "/huransquare": "\u3335", + "/hushedFace": "\u1F62F", + "/hv": "\u0195", + "/hwd:a": "\uFFC2", + "/hwd:ae": "\uFFC3", + "/hwd:blacksquare": "\uFFED", + "/hwd:chieuch": "\uFFBA", + "/hwd:cieuc": "\uFFB8", + "/hwd:downwardsarrow": "\uFFEC", + "/hwd:e": "\uFFC7", + "/hwd:eo": "\uFFC6", + "/hwd:eu": "\uFFDA", + "/hwd:formslightvertical": "\uFFE8", + "/hwd:hangulfiller": "\uFFA0", + "/hwd:hieuh": "\uFFBE", + "/hwd:i": "\uFFDC", + "/hwd:ideographiccomma": "\uFF64", + "/hwd:ideographicfullstop": "\uFF61", + "/hwd:ieung": "\uFFB7", + "/hwd:kata:a": "\uFF71", + "/hwd:kata:asmall": "\uFF67", + "/hwd:kata:e": "\uFF74", + "/hwd:kata:esmall": "\uFF6A", + "/hwd:kata:ha": "\uFF8A", + "/hwd:kata:he": "\uFF8D", + "/hwd:kata:hi": "\uFF8B", + "/hwd:kata:ho": "\uFF8E", + "/hwd:kata:hu": "\uFF8C", + "/hwd:kata:i": "\uFF72", + "/hwd:kata:ismall": "\uFF68", + "/hwd:kata:ka": "\uFF76", + "/hwd:kata:ke": "\uFF79", + "/hwd:kata:ki": "\uFF77", + "/hwd:kata:ko": "\uFF7A", + "/hwd:kata:ku": "\uFF78", + "/hwd:kata:ma": "\uFF8F", + "/hwd:kata:me": "\uFF92", + "/hwd:kata:mi": "\uFF90", + "/hwd:kata:middledot": "\uFF65", + "/hwd:kata:mo": "\uFF93", + "/hwd:kata:mu": "\uFF91", + "/hwd:kata:n": "\uFF9D", + "/hwd:kata:na": "\uFF85", + "/hwd:kata:ne": "\uFF88", + "/hwd:kata:ni": "\uFF86", + "/hwd:kata:no": "\uFF89", + "/hwd:kata:nu": "\uFF87", + "/hwd:kata:o": "\uFF75", + "/hwd:kata:osmall": "\uFF6B", + "/hwd:kata:prolongedkana": "\uFF70", + "/hwd:kata:ra": "\uFF97", + "/hwd:kata:re": "\uFF9A", + "/hwd:kata:ri": "\uFF98", + "/hwd:kata:ro": "\uFF9B", + "/hwd:kata:ru": "\uFF99", + "/hwd:kata:sa": "\uFF7B", + "/hwd:kata:se": "\uFF7E", + "/hwd:kata:semi-voiced": "\uFF9F", + "/hwd:kata:si": "\uFF7C", + "/hwd:kata:so": "\uFF7F", + "/hwd:kata:su": "\uFF7D", + "/hwd:kata:ta": "\uFF80", + "/hwd:kata:te": "\uFF83", + "/hwd:kata:ti": "\uFF81", + "/hwd:kata:to": "\uFF84", + "/hwd:kata:tu": "\uFF82", + "/hwd:kata:tusmall": "\uFF6F", + "/hwd:kata:u": "\uFF73", + "/hwd:kata:usmall": "\uFF69", + "/hwd:kata:voiced": "\uFF9E", + "/hwd:kata:wa": "\uFF9C", + "/hwd:kata:wo": "\uFF66", + "/hwd:kata:ya": "\uFF94", + "/hwd:kata:yasmall": "\uFF6C", + "/hwd:kata:yo": "\uFF96", + "/hwd:kata:yosmall": "\uFF6E", + "/hwd:kata:yu": "\uFF95", + "/hwd:kata:yusmall": "\uFF6D", + "/hwd:khieukh": "\uFFBB", + "/hwd:kiyeok": "\uFFA1", + "/hwd:kiyeoksios": "\uFFA3", + "/hwd:leftcornerbracket": "\uFF62", + "/hwd:leftwardsarrow": "\uFFE9", + "/hwd:mieum": "\uFFB1", + "/hwd:nieun": "\uFFA4", + "/hwd:nieuncieuc": "\uFFA5", + "/hwd:nieunhieuh": "\uFFA6", + "/hwd:o": "\uFFCC", + "/hwd:oe": "\uFFCF", + "/hwd:phieuph": "\uFFBD", + "/hwd:pieup": "\uFFB2", + "/hwd:pieupsios": "\uFFB4", + "/hwd:rieul": "\uFFA9", + "/hwd:rieulhieuh": "\uFFB0", + "/hwd:rieulkiyeok": "\uFFAA", + "/hwd:rieulmieum": "\uFFAB", + "/hwd:rieulphieuph": "\uFFAF", + "/hwd:rieulpieup": "\uFFAC", + "/hwd:rieulsios": "\uFFAD", + "/hwd:rieulthieuth": "\uFFAE", + "/hwd:rightcornerbracket": "\uFF63", + "/hwd:rightwardsarrow": "\uFFEB", + "/hwd:sios": "\uFFB5", + "/hwd:ssangcieuc": "\uFFB9", + "/hwd:ssangkiyeok": "\uFFA2", + "/hwd:ssangpieup": "\uFFB3", + "/hwd:ssangsios": "\uFFB6", + "/hwd:ssangtikeut": "\uFFA8", + "/hwd:thieuth": "\uFFBC", + "/hwd:tikeut": "\uFFA7", + "/hwd:u": "\uFFD3", + "/hwd:upwardsarrow": "\uFFEA", + "/hwd:wa": "\uFFCD", + "/hwd:wae": "\uFFCE", + "/hwd:we": "\uFFD5", + "/hwd:weo": "\uFFD4", + "/hwd:whitecircle": "\uFFEE", + "/hwd:wi": "\uFFD6", + "/hwd:ya": "\uFFC4", + "/hwd:yae": "\uFFC5", + "/hwd:ye": "\uFFCB", + "/hwd:yeo": "\uFFCA", + "/hwd:yi": "\uFFDB", + "/hwd:yo": "\uFFD2", + "/hwd:yu": "\uFFD7", + "/hyphen": "\u002D", + "/hyphenationpoint": "\u2027", + "/hyphenbullet": "\u2043", + "/hyphendbl": "\u2E40", + "/hyphendbloblique": "\u2E17", + "/hyphendieresis": "\u2E1A", + "/hypheninferior": "\uF6E5", + "/hyphenminus": "\u002D", + "/hyphenmonospace": "\uFF0D", + "/hyphensmall": "\uFE63", + "/hyphensoft": "\u00AD", + "/hyphensuperior": "\uF6E6", + "/hyphentwo": "\u2010", + "/hypodiastole": "\u2E12", + "/hysteresis": "\u238E", + "/hzfullwidth": "\u3390", + "/i": "\u0069", + "/i.superior": "\u2071", + "/iacute": "\u00ED", + "/iacyrillic": "\u044F", + "/iaepigraphic": "\uA7FE", + "/ibengali": "\u0987", + "/ibopomofo": "\u3127", + "/ibreve": "\u012D", + "/icaron": "\u01D0", + "/iceCream": "\u1F368", + "/iceHockeyStickAndPuck": "\u1F3D2", + "/iceskate": "\u26F8", + "/icircle": "\u24D8", + "/icirclekatakana": "\u32D1", + "/icircumflex": "\u00EE", + "/icyr": "\u0438", + "/icyrillic": "\u0456", + "/idblgrave": "\u0209", + "/idblstruckitalic": "\u2148", + "/ideographearthcircle": "\u328F", + "/ideographfirecircle": "\u328B", + "/ideographicallianceparen": "\u323F", + "/ideographiccallparen": "\u323A", + "/ideographiccentrecircle": "\u32A5", + "/ideographicclose": "\u3006", + "/ideographiccomma": "\u3001", + "/ideographiccommaleft": "\uFF64", + "/ideographiccongratulationparen": "\u3237", + "/ideographiccorrectcircle": "\u32A3", + "/ideographicdepartingtonemark": "\u302C", + "/ideographicearthparen": "\u322F", + "/ideographicenteringtonemark": "\u302D", + "/ideographicenterpriseparen": "\u323D", + "/ideographicexcellentcircle": "\u329D", + "/ideographicfestivalparen": "\u3240", + "/ideographicfinancialcircle": "\u3296", + "/ideographicfinancialparen": "\u3236", + "/ideographicfireparen": "\u322B", + "/ideographichalffillspace": "\u303F", + "/ideographichaveparen": "\u3232", + "/ideographichighcircle": "\u32A4", + "/ideographiciterationmark": "\u3005", + "/ideographiclaborcircle": "\u3298", + "/ideographiclaborparen": "\u3238", + "/ideographicleftcircle": "\u32A7", + "/ideographicleveltonemark": "\u302A", + "/ideographiclowcircle": "\u32A6", + "/ideographicmedicinecircle": "\u32A9", + "/ideographicmetalparen": "\u322E", + "/ideographicmoonparen": "\u322A", + "/ideographicnameparen": "\u3234", + "/ideographicperiod": "\u3002", + "/ideographicprintcircle": "\u329E", + "/ideographicreachparen": "\u3243", + "/ideographicrepresentparen": "\u3239", + "/ideographicresourceparen": "\u323E", + "/ideographicrightcircle": "\u32A8", + "/ideographicrisingtonemark": "\u302B", + "/ideographicsecretcircle": "\u3299", + "/ideographicselfparen": "\u3242", + "/ideographicsocietyparen": "\u3233", + "/ideographicspace": "\u3000", + "/ideographicspecialparen": "\u3235", + "/ideographicstockparen": "\u3231", + "/ideographicstudyparen": "\u323B", + "/ideographicsunparen": "\u3230", + "/ideographicsuperviseparen": "\u323C", + "/ideographictelegraphlinefeedseparatorsymbol": "\u3037", + "/ideographictelegraphsymbolforhoureight": "\u3360", + "/ideographictelegraphsymbolforhoureighteen": "\u336A", + "/ideographictelegraphsymbolforhoureleven": "\u3363", + "/ideographictelegraphsymbolforhourfifteen": "\u3367", + "/ideographictelegraphsymbolforhourfive": "\u335D", + "/ideographictelegraphsymbolforhourfour": "\u335C", + "/ideographictelegraphsymbolforhourfourteen": "\u3366", + "/ideographictelegraphsymbolforhournine": "\u3361", + "/ideographictelegraphsymbolforhournineteen": "\u336B", + "/ideographictelegraphsymbolforhourone": "\u3359", + "/ideographictelegraphsymbolforhourseven": "\u335F", + "/ideographictelegraphsymbolforhourseventeen": "\u3369", + "/ideographictelegraphsymbolforhoursix": "\u335E", + "/ideographictelegraphsymbolforhoursixteen": "\u3368", + "/ideographictelegraphsymbolforhourten": "\u3362", + "/ideographictelegraphsymbolforhourthirteen": "\u3365", + "/ideographictelegraphsymbolforhourthree": "\u335B", + "/ideographictelegraphsymbolforhourtwelve": "\u3364", + "/ideographictelegraphsymbolforhourtwenty": "\u336C", + "/ideographictelegraphsymbolforhourtwentyfour": "\u3370", + "/ideographictelegraphsymbolforhourtwentyone": "\u336D", + "/ideographictelegraphsymbolforhourtwentythree": "\u336F", + "/ideographictelegraphsymbolforhourtwentytwo": "\u336E", + "/ideographictelegraphsymbolforhourtwo": "\u335A", + "/ideographictelegraphsymbolforhourzero": "\u3358", + "/ideographicvariationindicator": "\u303E", + "/ideographicwaterparen": "\u322C", + "/ideographicwoodparen": "\u322D", + "/ideographiczero": "\u3007", + "/ideographmetalcircle": "\u328E", + "/ideographmooncircle": "\u328A", + "/ideographnamecircle": "\u3294", + "/ideographsuncircle": "\u3290", + "/ideographwatercircle": "\u328C", + "/ideographwoodcircle": "\u328D", + "/ideva": "\u0907", + "/idieresis": "\u00EF", + "/idieresisacute": "\u1E2F", + "/idieresiscyr": "\u04E5", + "/idieresiscyrillic": "\u04E5", + "/idotbelow": "\u1ECB", + "/idsquare": "\u1F194", + "/iebrevecyr": "\u04D7", + "/iebrevecyrillic": "\u04D7", + "/iecyr": "\u0435", + "/iecyrillic": "\u0435", + "/iegravecyr": "\u0450", + "/iepigraphicsideways": "\uA7F7", + "/ieungacirclekorean": "\u3275", + "/ieungaparenkorean": "\u3215", + "/ieungcirclekorean": "\u3267", + "/ieungkorean": "\u3147", + "/ieungparenkorean": "\u3207", + "/ieungucirclekorean": "\u327E", + "/igrave": "\u00EC", + "/igravecyr": "\u045D", + "/igravedbl": "\u0209", + "/igujarati": "\u0A87", + "/igurmukhi": "\u0A07", + "/ihiragana": "\u3044", + "/ihoi": "\u1EC9", + "/ihookabove": "\u1EC9", + "/iibengali": "\u0988", + "/iicyrillic": "\u0438", + "/iideva": "\u0908", + "/iigujarati": "\u0A88", + "/iigurmukhi": "\u0A08", + "/iimatragurmukhi": "\u0A40", + "/iinvertedbreve": "\u020B", + "/iishortcyrillic": "\u0439", + "/iivowelsignbengali": "\u09C0", + "/iivowelsigndeva": "\u0940", + "/iivowelsigngujarati": "\u0AC0", + "/ij": "\u0133", + "/ikatakana": "\u30A4", + "/ikatakanahalfwidth": "\uFF72", + "/ikawi": "\uA985", + "/ikorean": "\u3163", + "/ilde": "\u02DC", + "/iluy:hb": "\u05AC", + "/iluyhebrew": "\u05AC", + "/imacron": "\u012B", + "/imacroncyr": "\u04E3", + "/imacroncyrillic": "\u04E3", + "/image": "\u22B7", + "/imageorapproximatelyequal": "\u2253", + "/imatragurmukhi": "\u0A3F", + "/imonospace": "\uFF49", + "/imp": "\u1F47F", + "/inboxTray": "\u1F4E5", + "/incomingEnvelope": "\u1F4E8", + "/increaseFontSize": "\u1F5DA", + "/increment": "\u2206", + "/indianrupee": "\u20B9", + "/infinity": "\u221E", + "/information": "\u2139", + "/infullwidth": "\u33CC", + "/inhibitarabicformshaping": "\u206C", + "/inhibitsymmetricswapping": "\u206A", + "/iniarmenian": "\u056B", + "/iningusquare": "\u3304", + "/inmationDeskPerson": "\u1F481", + "/inputLatinCapitalLetters": "\u1F520", + "/inputLatinLetters": "\u1F524", + "/inputLatinSmallLetters": "\u1F521", + "/inputNumbers": "\u1F522", + "/inputS": "\u1F523", + "/insertion": "\u2380", + "/integral": "\u222B", + "/integralbottom": "\u2321", + "/integralbt": "\u2321", + "/integralclockwise": "\u2231", + "/integralcontour": "\u222E", + "/integralcontouranticlockwise": "\u2233", + "/integralcontourclockwise": "\u2232", + "/integraldbl": "\u222C", + "/integralex": "\uF8F5", + "/integralextension": "\u23AE", + "/integralsurface": "\u222F", + "/integraltop": "\u2320", + "/integraltp": "\u2320", + "/integraltpl": "\u222D", + "/integralvolume": "\u2230", + "/intercalate": "\u22BA", + "/interlinearanchor": "\uFFF9", + "/interlinearseparator": "\uFFFA", + "/interlinearterminator": "\uFFFB", + "/interlockedfemalemale": "\u26A4", + "/interrobang": "\u203D", + "/interrobanginverted": "\u2E18", + "/intersection": "\u2229", + "/intersectionarray": "\u22C2", + "/intersectiondbl": "\u22D2", + "/intisquare": "\u3305", + "/invbullet": "\u25D8", + "/invcircle": "\u25D9", + "/inverteddamma": "\u0657", + "/invertedfork": "\u2443", + "/invertedpentagram": "\u26E7", + "/invertedundertie": "\u2054", + "/invisibleplus": "\u2064", + "/invisibleseparator": "\u2063", + "/invisibletimes": "\u2062", + "/invsmileface": "\u263B", + "/iocyr": "\u0451", + "/iocyrillic": "\u0451", + "/iogonek": "\u012F", + "/iota": "\u03B9", + "/iotaacute": "\u1F77", + "/iotaadscript": "\u1FBE", + "/iotaasper": "\u1F31", + "/iotaasperacute": "\u1F35", + "/iotaaspergrave": "\u1F33", + "/iotaaspertilde": "\u1F37", + "/iotabreve": "\u1FD0", + "/iotadieresis": "\u03CA", + "/iotadieresisacute": "\u1FD3", + "/iotadieresisgrave": "\u1FD2", + "/iotadieresistilde": "\u1FD7", + "/iotadieresistonos": "\u0390", + "/iotafunc": "\u2373", + "/iotagrave": "\u1F76", + "/iotalatin": "\u0269", + "/iotalenis": "\u1F30", + "/iotalenisacute": "\u1F34", + "/iotalenisgrave": "\u1F32", + "/iotalenistilde": "\u1F36", + "/iotasub": "\u037A", + "/iotatilde": "\u1FD6", + "/iotatonos": "\u03AF", + "/iotaturned": "\u2129", + "/iotaunderlinefunc": "\u2378", + "/iotawithmacron": "\u1FD1", + "/ipa:Ismall": "\u026A", + "/ipa:alpha": "\u0251", + "/ipa:ereversed": "\u0258", + "/ipa:esh": "\u0283", + "/ipa:gamma": "\u0263", + "/ipa:glottalstop": "\u0294", + "/ipa:gscript": "\u0261", + "/ipa:iota": "\u0269", + "/ipa:phi": "\u0278", + "/ipa:rtail": "\u027D", + "/ipa:schwa": "\u0259", + "/ipa:upsilon": "\u028A", + "/iparen": "\u24A4", + "/iparenthesized": "\u24A4", + "/irigurmukhi": "\u0A72", + "/is": "\uA76D", + "/isen-isenpada": "\uA9DF", + "/ishortcyr": "\u0439", + "/ishortsharptailcyr": "\u048B", + "/ismallhiragana": "\u3043", + "/ismallkatakana": "\u30A3", + "/ismallkatakanahalfwidth": "\uFF68", + "/issharbengali": "\u09FA", + "/istroke": "\u0268", + "/isuperior": "\uF6ED", + "/itemideographiccircled": "\u32A0", + "/iterationhiragana": "\u309D", + "/iterationkatakana": "\u30FD", + "/itilde": "\u0129", + "/itildebelow": "\u1E2D", + "/iubopomofo": "\u3129", + "/iucyrillic": "\u044E", + "/iufullwidth": "\u337A", + "/iukrcyr": "\u0456", + "/ivowelsignbengali": "\u09BF", + "/ivowelsigndeva": "\u093F", + "/ivowelsigngujarati": "\u0ABF", + "/izakayaLantern": "\u1F3EE", + "/izhitsacyr": "\u0475", + "/izhitsacyrillic": "\u0475", + "/izhitsadblgravecyrillic": "\u0477", + "/izhitsagravedblcyr": "\u0477", + "/j": "\u006A", + "/j.inferior": "\u2C7C", + "/jaarmenian": "\u0571", + "/jabengali": "\u099C", + "/jackOLantern": "\u1F383", + "/jadeva": "\u091C", + "/jagujarati": "\u0A9C", + "/jagurmukhi": "\u0A1C", + "/jamahaprana": "\uA999", + "/januarytelegraph": "\u32C0", + "/japaneseBeginner": "\u1F530", + "/japaneseCastle": "\u1F3EF", + "/japaneseDolls": "\u1F38E", + "/japaneseGoblin": "\u1F47A", + "/japaneseOgre": "\u1F479", + "/japanesePostOffice": "\u1F3E3", + "/japanesebank": "\u26FB", + "/java:a": "\uA984", + "/java:ai": "\uA98D", + "/java:ba": "\uA9A7", + "/java:ca": "\uA995", + "/java:da": "\uA9A2", + "/java:dda": "\uA99D", + "/java:e": "\uA98C", + "/java:eight": "\uA9D8", + "/java:five": "\uA9D5", + "/java:four": "\uA9D4", + "/java:ga": "\uA992", + "/java:ha": "\uA9B2", + "/java:i": "\uA986", + "/java:ii": "\uA987", + "/java:ja": "\uA997", + "/java:ka": "\uA98F", + "/java:la": "\uA9AD", + "/java:ma": "\uA9A9", + "/java:na": "\uA9A4", + "/java:nga": "\uA994", + "/java:nine": "\uA9D9", + "/java:nya": "\uA99A", + "/java:o": "\uA98E", + "/java:one": "\uA9D1", + "/java:pa": "\uA9A5", + "/java:ra": "\uA9AB", + "/java:sa": "\uA9B1", + "/java:seven": "\uA9D7", + "/java:six": "\uA9D6", + "/java:ta": "\uA9A0", + "/java:three": "\uA9D3", + "/java:tta": "\uA99B", + "/java:two": "\uA9D2", + "/java:u": "\uA988", + "/java:wa": "\uA9AE", + "/java:ya": "\uA9AA", + "/java:zero": "\uA9D0", + "/jbopomofo": "\u3110", + "/jcaron": "\u01F0", + "/jcircle": "\u24D9", + "/jcircumflex": "\u0135", + "/jcrossedtail": "\u029D", + "/jdblstruckitalic": "\u2149", + "/jdotlessstroke": "\u025F", + "/jeans": "\u1F456", + "/jecyr": "\u0458", + "/jecyrillic": "\u0458", + "/jeem": "\u062C", + "/jeem.fina": "\uFE9E", + "/jeem.init": "\uFE9F", + "/jeem.init_alefmaksura.fina": "\uFD01", + "/jeem.init_hah.fina": "\uFC15", + "/jeem.init_hah.medi": "\uFCA7", + "/jeem.init_meem.fina": "\uFC16", + "/jeem.init_meem.medi": "\uFCA8", + "/jeem.init_meem.medi_hah.medi": "\uFD59", + "/jeem.init_yeh.fina": "\uFD02", + "/jeem.isol": "\uFE9D", + "/jeem.medi": "\uFEA0", + "/jeem.medi_alefmaksura.fina": "\uFD1D", + "/jeem.medi_hah.medi_alefmaksura.fina": "\uFDA6", + "/jeem.medi_hah.medi_yeh.fina": "\uFDBE", + "/jeem.medi_meem.medi_alefmaksura.fina": "\uFDA7", + "/jeem.medi_meem.medi_hah.fina": "\uFD58", + "/jeem.medi_meem.medi_yeh.fina": "\uFDA5", + "/jeem.medi_yeh.fina": "\uFD1E", + "/jeemabove": "\u06DA", + "/jeemarabic": "\u062C", + "/jeemfinalarabic": "\uFE9E", + "/jeeminitialarabic": "\uFE9F", + "/jeemmedialarabic": "\uFEA0", + "/jeh": "\u0698", + "/jeh.fina": "\uFB8B", + "/jeh.isol": "\uFB8A", + "/jeharabic": "\u0698", + "/jehfinalarabic": "\uFB8B", + "/jhabengali": "\u099D", + "/jhadeva": "\u091D", + "/jhagujarati": "\u0A9D", + "/jhagurmukhi": "\u0A1D", + "/jheharmenian": "\u057B", + "/jis": "\u3004", + "/jiterup": "\u2643", + "/jmonospace": "\uFF4A", + "/jotdiaeresisfunc": "\u2364", + "/jotunderlinefunc": "\u235B", + "/joystick": "\u1F579", + "/jparen": "\u24A5", + "/jparenthesized": "\u24A5", + "/jstroke": "\u0249", + "/jsuperior": "\u02B2", + "/jsupmod": "\u02B2", + "/jueuicircle": "\u327D", + "/julytelegraph": "\u32C6", + "/junetelegraph": "\u32C5", + "/juno": "\u26B5", + "/k": "\u006B", + "/k.inferior": "\u2096", + "/kaaba": "\u1F54B", + "/kaaleutcyr": "\u051F", + "/kabashkcyr": "\u04A1", + "/kabashkircyrillic": "\u04A1", + "/kabengali": "\u0995", + "/kacirclekatakana": "\u32D5", + "/kacute": "\u1E31", + "/kacyr": "\u043A", + "/kacyrillic": "\u043A", + "/kadescendercyrillic": "\u049B", + "/kadeva": "\u0915", + "/kaf": "\u05DB", + "/kaf.fina": "\uFEDA", + "/kaf.init": "\uFEDB", + "/kaf.init_alef.fina": "\uFC37", + "/kaf.init_alefmaksura.fina": "\uFC3D", + "/kaf.init_hah.fina": "\uFC39", + "/kaf.init_hah.medi": "\uFCC5", + "/kaf.init_jeem.fina": "\uFC38", + "/kaf.init_jeem.medi": "\uFCC4", + "/kaf.init_khah.fina": "\uFC3A", + "/kaf.init_khah.medi": "\uFCC6", + "/kaf.init_lam.fina": "\uFC3B", + "/kaf.init_lam.medi": "\uFCC7", + "/kaf.init_meem.fina": "\uFC3C", + "/kaf.init_meem.medi": "\uFCC8", + "/kaf.init_meem.medi_meem.medi": "\uFDC3", + "/kaf.init_yeh.fina": "\uFC3E", + "/kaf.isol": "\uFED9", + "/kaf.medi": "\uFEDC", + "/kaf.medi_alef.fina": "\uFC80", + "/kaf.medi_alefmaksura.fina": "\uFC83", + "/kaf.medi_lam.fina": "\uFC81", + "/kaf.medi_lam.medi": "\uFCEB", + "/kaf.medi_meem.fina": "\uFC82", + "/kaf.medi_meem.medi": "\uFCEC", + "/kaf.medi_meem.medi_meem.fina": "\uFDBB", + "/kaf.medi_meem.medi_yeh.fina": "\uFDB7", + "/kaf.medi_yeh.fina": "\uFC84", + "/kaf:hb": "\u05DB", + "/kafTwoDotsAbove": "\u077F", + "/kafarabic": "\u0643", + "/kafdagesh": "\uFB3B", + "/kafdageshhebrew": "\uFB3B", + "/kafdotabove": "\u06AC", + "/kaffinalarabic": "\uFEDA", + "/kafhebrew": "\u05DB", + "/kafinitialarabic": "\uFEDB", + "/kafmedialarabic": "\uFEDC", + "/kafrafehebrew": "\uFB4D", + "/kafring": "\u06AB", + "/kafswash": "\u06AA", + "/kafthreedotsbelow": "\u06AE", + "/kafullwidth": "\u3384", + "/kafwide:hb": "\uFB24", + "/kafwithdagesh:hb": "\uFB3B", + "/kafwithrafe:hb": "\uFB4D", + "/kagujarati": "\u0A95", + "/kagurmukhi": "\u0A15", + "/kahiragana": "\u304B", + "/kahookcyr": "\u04C4", + "/kahookcyrillic": "\u04C4", + "/kairisquare": "\u330B", + "/kaisymbol": "\u03D7", + "/kakatakana": "\u30AB", + "/kakatakanahalfwidth": "\uFF76", + "/kamurda": "\uA991", + "/kappa": "\u03BA", + "/kappa.math": "\u03F0", + "/kappasymbolgreek": "\u03F0", + "/kapyeounmieumkorean": "\u3171", + "/kapyeounphieuphkorean": "\u3184", + "/kapyeounpieupkorean": "\u3178", + "/kapyeounssangpieupkorean": "\u3179", + "/karattosquare": "\u330C", + "/karoriisquare": "\u330D", + "/kasasak": "\uA990", + "/kashida": "\u0640", + "/kashidaFina": "\uFE73", + "/kashidaautoarabic": "\u0640", + "/kashidaautonosidebearingarabic": "\u0640", + "/kashmiriyeh": "\u0620", + "/kasmallkatakana": "\u30F5", + "/kasquare": "\u3384", + "/kasra": "\u0650", + "/kasraIsol": "\uFE7A", + "/kasraMedi": "\uFE7B", + "/kasraarabic": "\u0650", + "/kasrasmall": "\u061A", + "/kasratan": "\u064D", + "/kasratanIsol": "\uFE74", + "/kasratanarabic": "\u064D", + "/kastrokecyr": "\u049F", + "/kastrokecyrillic": "\u049F", + "/kata:a": "\u30A2", + "/kata:asmall": "\u30A1", + "/kata:ba": "\u30D0", + "/kata:be": "\u30D9", + "/kata:bi": "\u30D3", + "/kata:bo": "\u30DC", + "/kata:bu": "\u30D6", + "/kata:da": "\u30C0", + "/kata:de": "\u30C7", + "/kata:di": "\u30C2", + "/kata:digraphkoto": "\u30FF", + "/kata:do": "\u30C9", + "/kata:doublehyphenkana": "\u30A0", + "/kata:du": "\u30C5", + "/kata:e": "\u30A8", + "/kata:esmall": "\u30A7", + "/kata:ga": "\u30AC", + "/kata:ge": "\u30B2", + "/kata:gi": "\u30AE", + "/kata:go": "\u30B4", + "/kata:gu": "\u30B0", + "/kata:ha": "\u30CF", + "/kata:he": "\u30D8", + "/kata:hi": "\u30D2", + "/kata:ho": "\u30DB", + "/kata:hu": "\u30D5", + "/kata:i": "\u30A4", + "/kata:ismall": "\u30A3", + "/kata:iteration": "\u30FD", + "/kata:ka": "\u30AB", + "/kata:kasmall": "\u30F5", + "/kata:ke": "\u30B1", + "/kata:kesmall": "\u30F6", + "/kata:ki": "\u30AD", + "/kata:ko": "\u30B3", + "/kata:ku": "\u30AF", + "/kata:ma": "\u30DE", + "/kata:me": "\u30E1", + "/kata:mi": "\u30DF", + "/kata:middledot": "\u30FB", + "/kata:mo": "\u30E2", + "/kata:mu": "\u30E0", + "/kata:n": "\u30F3", + "/kata:na": "\u30CA", + "/kata:ne": "\u30CD", + "/kata:ni": "\u30CB", + "/kata:no": "\u30CE", + "/kata:nu": "\u30CC", + "/kata:o": "\u30AA", + "/kata:osmall": "\u30A9", + "/kata:pa": "\u30D1", + "/kata:pe": "\u30DA", + "/kata:pi": "\u30D4", + "/kata:po": "\u30DD", + "/kata:prolongedkana": "\u30FC", + "/kata:pu": "\u30D7", + "/kata:ra": "\u30E9", + "/kata:re": "\u30EC", + "/kata:ri": "\u30EA", + "/kata:ro": "\u30ED", + "/kata:ru": "\u30EB", + "/kata:sa": "\u30B5", + "/kata:se": "\u30BB", + "/kata:si": "\u30B7", + "/kata:so": "\u30BD", + "/kata:su": "\u30B9", + "/kata:ta": "\u30BF", + "/kata:te": "\u30C6", + "/kata:ti": "\u30C1", + "/kata:to": "\u30C8", + "/kata:tu": "\u30C4", + "/kata:tusmall": "\u30C3", + "/kata:u": "\u30A6", + "/kata:usmall": "\u30A5", + "/kata:va": "\u30F7", + "/kata:ve": "\u30F9", + "/kata:vi": "\u30F8", + "/kata:vo": "\u30FA", + "/kata:voicediteration": "\u30FE", + "/kata:vu": "\u30F4", + "/kata:wa": "\u30EF", + "/kata:wasmall": "\u30EE", + "/kata:we": "\u30F1", + "/kata:wi": "\u30F0", + "/kata:wo": "\u30F2", + "/kata:ya": "\u30E4", + "/kata:yasmall": "\u30E3", + "/kata:yo": "\u30E8", + "/kata:yosmall": "\u30E7", + "/kata:yu": "\u30E6", + "/kata:yusmall": "\u30E5", + "/kata:za": "\u30B6", + "/kata:ze": "\u30BC", + "/kata:zi": "\u30B8", + "/kata:zo": "\u30BE", + "/kata:zu": "\u30BA", + "/katahiraprolongmarkhalfwidth": "\uFF70", + "/katailcyr": "\u049B", + "/kaverticalstrokecyr": "\u049D", + "/kaverticalstrokecyrillic": "\u049D", + "/kavykainvertedlow": "\u2E45", + "/kavykalow": "\u2E47", + "/kavykawithdotlow": "\u2E48", + "/kavykawithkavykaaboveinvertedlow": "\u2E46", + "/kbfullwidth": "\u3385", + "/kbopomofo": "\u310E", + "/kcalfullwidth": "\u3389", + "/kcalsquare": "\u3389", + "/kcaron": "\u01E9", + "/kcedilla": "\u0137", + "/kcircle": "\u24DA", + "/kcommaaccent": "\u0137", + "/kdescender": "\u2C6A", + "/kdiagonalstroke": "\uA743", + "/kdotbelow": "\u1E33", + "/kecirclekatakana": "\u32D8", + "/keesusquare": "\u331C", + "/keharmenian": "\u0584", + "/keheh": "\u06A9", + "/keheh.fina": "\uFB8F", + "/keheh.init": "\uFB90", + "/keheh.isol": "\uFB8E", + "/keheh.medi": "\uFB91", + "/kehehDotAbove": "\u0762", + "/kehehThreeDotsAbove": "\u0763", + "/kehehThreeDotsUpBelow": "\u0764", + "/kehehthreedotsbelow": "\u063C", + "/kehehtwodotsabove": "\u063B", + "/kehiragana": "\u3051", + "/kekatakana": "\u30B1", + "/kekatakanahalfwidth": "\uFF79", + "/kelvin": "\u212A", + "/kenarmenian": "\u056F", + "/keretconsonant": "\uA9BD", + "/kesmallkatakana": "\u30F6", + "/key": "\u1F511", + "/keyboardAndMouse": "\u1F5A6", + "/keycapTen": "\u1F51F", + "/kgfullwidth": "\u338F", + "/kgreenlandic": "\u0138", + "/khabengali": "\u0996", + "/khacyrillic": "\u0445", + "/khadeva": "\u0916", + "/khagujarati": "\u0A96", + "/khagurmukhi": "\u0A16", + "/khah": "\u062E", + "/khah.fina": "\uFEA6", + "/khah.init": "\uFEA7", + "/khah.init_alefmaksura.fina": "\uFD03", + "/khah.init_hah.fina": "\uFC1A", + "/khah.init_jeem.fina": "\uFC19", + "/khah.init_jeem.medi": "\uFCAB", + "/khah.init_meem.fina": "\uFC1B", + "/khah.init_meem.medi": "\uFCAC", + "/khah.init_yeh.fina": "\uFD04", + "/khah.isol": "\uFEA5", + "/khah.medi": "\uFEA8", + "/khah.medi_alefmaksura.fina": "\uFD1F", + "/khah.medi_yeh.fina": "\uFD20", + "/khaharabic": "\u062E", + "/khahfinalarabic": "\uFEA6", + "/khahinitialarabic": "\uFEA7", + "/khahmedialarabic": "\uFEA8", + "/kheicoptic": "\u03E7", + "/khhadeva": "\u0959", + "/khhagurmukhi": "\u0A59", + "/khieukhacirclekorean": "\u3278", + "/khieukhaparenkorean": "\u3218", + "/khieukhcirclekorean": "\u326A", + "/khieukhkorean": "\u314B", + "/khieukhparenkorean": "\u320A", + "/khokhaithai": "\u0E02", + "/khokhonthai": "\u0E05", + "/khokhuatthai": "\u0E03", + "/khokhwaithai": "\u0E04", + "/khomutthai": "\u0E5B", + "/khook": "\u0199", + "/khorakhangthai": "\u0E06", + "/khzfullwidth": "\u3391", + "/khzsquare": "\u3391", + "/kicirclekatakana": "\u32D6", + "/kihiragana": "\u304D", + "/kikatakana": "\u30AD", + "/kikatakanahalfwidth": "\uFF77", + "/kimono": "\u1F458", + "/kindergartenideographiccircled": "\u3245", + "/kingblack": "\u265A", + "/kingwhite": "\u2654", + "/kip": "\u20AD", + "/kiroguramusquare": "\u3315", + "/kiromeetorusquare": "\u3316", + "/kirosquare": "\u3314", + "/kirowattosquare": "\u3317", + "/kiss": "\u1F48F", + "/kissMark": "\u1F48B", + "/kissingCatFaceWithClosedEyes": "\u1F63D", + "/kissingFace": "\u1F617", + "/kissingFaceWithClosedEyes": "\u1F61A", + "/kissingFaceWithSmilingEyes": "\u1F619", + "/kiyeokacirclekorean": "\u326E", + "/kiyeokaparenkorean": "\u320E", + "/kiyeokcirclekorean": "\u3260", + "/kiyeokkorean": "\u3131", + "/kiyeokparenkorean": "\u3200", + "/kiyeoksioskorean": "\u3133", + "/kjecyr": "\u045C", + "/kjecyrillic": "\u045C", + "/kkfullwidth": "\u33CD", + "/klfullwidth": "\u3398", + "/klinebelow": "\u1E35", + "/klsquare": "\u3398", + "/km2fullwidth": "\u33A2", + "/km3fullwidth": "\u33A6", + "/kmcapitalfullwidth": "\u33CE", + "/kmcubedsquare": "\u33A6", + "/kmfullwidth": "\u339E", + "/kmonospace": "\uFF4B", + "/kmsquaredsquare": "\u33A2", + "/knda:a": "\u0C85", + "/knda:aa": "\u0C86", + "/knda:aasign": "\u0CBE", + "/knda:ai": "\u0C90", + "/knda:ailength": "\u0CD6", + "/knda:aisign": "\u0CC8", + "/knda:anusvara": "\u0C82", + "/knda:au": "\u0C94", + "/knda:ausign": "\u0CCC", + "/knda:avagraha": "\u0CBD", + "/knda:ba": "\u0CAC", + "/knda:bha": "\u0CAD", + "/knda:ca": "\u0C9A", + "/knda:cha": "\u0C9B", + "/knda:da": "\u0CA6", + "/knda:dda": "\u0CA1", + "/knda:ddha": "\u0CA2", + "/knda:dha": "\u0CA7", + "/knda:e": "\u0C8E", + "/knda:ee": "\u0C8F", + "/knda:eesign": "\u0CC7", + "/knda:eight": "\u0CEE", + "/knda:esign": "\u0CC6", + "/knda:fa": "\u0CDE", + "/knda:five": "\u0CEB", + "/knda:four": "\u0CEA", + "/knda:ga": "\u0C97", + "/knda:gha": "\u0C98", + "/knda:ha": "\u0CB9", + "/knda:i": "\u0C87", + "/knda:ii": "\u0C88", + "/knda:iisign": "\u0CC0", + "/knda:isign": "\u0CBF", + "/knda:ja": "\u0C9C", + "/knda:jha": "\u0C9D", + "/knda:jihvamuliya": "\u0CF1", + "/knda:ka": "\u0C95", + "/knda:kha": "\u0C96", + "/knda:la": "\u0CB2", + "/knda:length": "\u0CD5", + "/knda:lla": "\u0CB3", + "/knda:llvocal": "\u0CE1", + "/knda:llvocalsign": "\u0CE3", + "/knda:lvocal": "\u0C8C", + "/knda:lvocalsign": "\u0CE2", + "/knda:ma": "\u0CAE", + "/knda:na": "\u0CA8", + "/knda:nga": "\u0C99", + "/knda:nine": "\u0CEF", + "/knda:nna": "\u0CA3", + "/knda:nukta": "\u0CBC", + "/knda:nya": "\u0C9E", + "/knda:o": "\u0C92", + "/knda:one": "\u0CE7", + "/knda:oo": "\u0C93", + "/knda:oosign": "\u0CCB", + "/knda:osign": "\u0CCA", + "/knda:pa": "\u0CAA", + "/knda:pha": "\u0CAB", + "/knda:ra": "\u0CB0", + "/knda:rra": "\u0CB1", + "/knda:rrvocal": "\u0CE0", + "/knda:rrvocalsign": "\u0CC4", + "/knda:rvocal": "\u0C8B", + "/knda:rvocalsign": "\u0CC3", + "/knda:sa": "\u0CB8", + "/knda:seven": "\u0CED", + "/knda:sha": "\u0CB6", + "/knda:signcandrabindu": "\u0C81", + "/knda:signspacingcandrabindu": "\u0C80", + "/knda:six": "\u0CEC", + "/knda:ssa": "\u0CB7", + "/knda:ta": "\u0CA4", + "/knda:tha": "\u0CA5", + "/knda:three": "\u0CE9", + "/knda:tta": "\u0C9F", + "/knda:ttha": "\u0CA0", + "/knda:two": "\u0CE8", + "/knda:u": "\u0C89", + "/knda:upadhmaniya": "\u0CF2", + "/knda:usign": "\u0CC1", + "/knda:uu": "\u0C8A", + "/knda:uusign": "\u0CC2", + "/knda:va": "\u0CB5", + "/knda:virama": "\u0CCD", + "/knda:visarga": "\u0C83", + "/knda:ya": "\u0CAF", + "/knda:zero": "\u0CE6", + "/knightblack": "\u265E", + "/knightwhite": "\u2658", + "/ko:a": "\u314F", + "/ko:ae": "\u3150", + "/ko:aejungseong": "\u1162", + "/ko:aeujungseong": "\u11A3", + "/ko:ajungseong": "\u1161", + "/ko:aojungseong": "\u1176", + "/ko:araea": "\u318D", + "/ko:araeae": "\u318E", + "/ko:araeaeojungseong": "\u119F", + "/ko:araeaijungseong": "\u11A1", + "/ko:araeajungseong": "\u119E", + "/ko:araeaujungseong": "\u11A0", + "/ko:aujungseong": "\u1177", + "/ko:ceongchieumchieuchchoseong": "\u1155", + "/ko:ceongchieumcieucchoseong": "\u1150", + "/ko:ceongchieumsioschoseong": "\u113E", + "/ko:ceongchieumssangcieucchoseong": "\u1151", + "/ko:ceongchieumssangsioschoseong": "\u113F", + "/ko:chieuch": "\u314A", + "/ko:chieuchchoseong": "\u110E", + "/ko:chieuchhieuhchoseong": "\u1153", + "/ko:chieuchjongseong": "\u11BE", + "/ko:chieuchkhieukhchoseong": "\u1152", + "/ko:chitueumchieuchchoseong": "\u1154", + "/ko:chitueumcieucchoseong": "\u114E", + "/ko:chitueumsioschoseong": "\u113C", + "/ko:chitueumssangcieucchoseong": "\u114F", + "/ko:chitueumssangsioschoseong": "\u113D", + "/ko:cieuc": "\u3148", + "/ko:cieucchoseong": "\u110C", + "/ko:cieucieungchoseong": "\u114D", + "/ko:cieucjongseong": "\u11BD", + "/ko:e": "\u3154", + "/ko:ejungseong": "\u1166", + "/ko:eo": "\u3153", + "/ko:eo_eujungseong": "\u117C", + "/ko:eojungseong": "\u1165", + "/ko:eoojungseong": "\u117A", + "/ko:eoujungseong": "\u117B", + "/ko:eu": "\u3161", + "/ko:eueujungseong": "\u1196", + "/ko:eujungseong": "\u1173", + "/ko:euujungseong": "\u1195", + "/ko:filler": "\u3164", + "/ko:fillerchoseong": "\u115F", + "/ko:fillerjungseong": "\u1160", + "/ko:hieuh": "\u314E", + "/ko:hieuhchoseong": "\u1112", + "/ko:hieuhjongseong": "\u11C2", + "/ko:hieuhmieumjongseong": "\u11F7", + "/ko:hieuhnieunjongseong": "\u11F5", + "/ko:hieuhpieupjongseong": "\u11F8", + "/ko:hieuhrieuljongseong": "\u11F6", + "/ko:i": "\u3163", + "/ko:iajungseong": "\u1198", + "/ko:iaraeajungseong": "\u119D", + "/ko:ieujungseong": "\u119C", + "/ko:ieung": "\u3147", + "/ko:ieungchieuchchoseong": "\u1149", + "/ko:ieungchoseong": "\u110B", + "/ko:ieungcieucchoseong": "\u1148", + "/ko:ieungjongseong": "\u11BC", + "/ko:ieungkhieukhjongseong": "\u11EF", + "/ko:ieungkiyeokchoseong": "\u1141", + "/ko:ieungkiyeokjongseong": "\u11EC", + "/ko:ieungmieumchoseong": "\u1143", + "/ko:ieungpansioschoseong": "\u1146", + "/ko:ieungphieuphchoseong": "\u114B", + "/ko:ieungpieupchoseong": "\u1144", + "/ko:ieungsioschoseong": "\u1145", + "/ko:ieungssangkiyeokjongseong": "\u11ED", + "/ko:ieungthieuthchoseong": "\u114A", + "/ko:ieungtikeutchoseong": "\u1142", + "/ko:ijungseong": "\u1175", + "/ko:iojungseong": "\u119A", + "/ko:iujungseong": "\u119B", + "/ko:iyajungseong": "\u1199", + "/ko:kapyeounmieum": "\u3171", + "/ko:kapyeounmieumchoseong": "\u111D", + "/ko:kapyeounmieumjongseong": "\u11E2", + "/ko:kapyeounphieuph": "\u3184", + "/ko:kapyeounphieuphchoseong": "\u1157", + "/ko:kapyeounphieuphjongseong": "\u11F4", + "/ko:kapyeounpieup": "\u3178", + "/ko:kapyeounpieupchoseong": "\u112B", + "/ko:kapyeounpieupjongseong": "\u11E6", + "/ko:kapyeounrieulchoseong": "\u111B", + "/ko:kapyeounssangpieup": "\u3179", + "/ko:kapyeounssangpieupchoseong": "\u112C", + "/ko:khieukh": "\u314B", + "/ko:khieukhchoseong": "\u110F", + "/ko:khieukhjongseong": "\u11BF", + "/ko:kiyeok": "\u3131", + "/ko:kiyeokchieuchjongseong": "\u11FC", + "/ko:kiyeokchoseong": "\u1100", + "/ko:kiyeokhieuhjongseong": "\u11FE", + "/ko:kiyeokjongseong": "\u11A8", + "/ko:kiyeokkhieukhjongseong": "\u11FD", + "/ko:kiyeoknieunjongseong": "\u11FA", + "/ko:kiyeokpieupjongseong": "\u11FB", + "/ko:kiyeokrieuljongseong": "\u11C3", + "/ko:kiyeoksios": "\u3133", + "/ko:kiyeoksiosjongseong": "\u11AA", + "/ko:kiyeoksioskiyeokjongseong": "\u11C4", + "/ko:kiyeoktikeutchoseong": "\u115A", + "/ko:mieum": "\u3141", + "/ko:mieumchieuchjongseong": "\u11E0", + "/ko:mieumchoseong": "\u1106", + "/ko:mieumhieuhjongseong": "\u11E1", + "/ko:mieumjongseong": "\u11B7", + "/ko:mieumkiyeokjongseong": "\u11DA", + "/ko:mieumpansios": "\u3170", + "/ko:mieumpansiosjongseong": "\u11DF", + "/ko:mieumpieup": "\u316E", + "/ko:mieumpieupchoseong": "\u111C", + "/ko:mieumpieupjongseong": "\u11DC", + "/ko:mieumrieuljongseong": "\u11DB", + "/ko:mieumsios": "\u316F", + "/ko:mieumsiosjongseong": "\u11DD", + "/ko:mieumssangsiosjongseong": "\u11DE", + "/ko:nieun": "\u3134", + "/ko:nieunchoseong": "\u1102", + "/ko:nieuncieuc": "\u3135", + "/ko:nieuncieucchoseong": "\u115C", + "/ko:nieuncieucjongseong": "\u11AC", + "/ko:nieunhieuh": "\u3136", + "/ko:nieunhieuhchoseong": "\u115D", + "/ko:nieunhieuhjongseong": "\u11AD", + "/ko:nieunjongseong": "\u11AB", + "/ko:nieunkiyeokchoseong": "\u1113", + "/ko:nieunkiyeokjongseong": "\u11C5", + "/ko:nieunpansios": "\u3168", + "/ko:nieunpansiosjongseong": "\u11C8", + "/ko:nieunpieupchoseong": "\u1116", + "/ko:nieunsios": "\u3167", + "/ko:nieunsioschoseong": "\u115B", + "/ko:nieunsiosjongseong": "\u11C7", + "/ko:nieunthieuthjongseong": "\u11C9", + "/ko:nieuntikeut": "\u3166", + "/ko:nieuntikeutchoseong": "\u1115", + "/ko:nieuntikeutjongseong": "\u11C6", + "/ko:o": "\u3157", + "/ko:o_ejungseong": "\u1180", + "/ko:o_eojungseong": "\u117F", + "/ko:oe": "\u315A", + "/ko:oejungseong": "\u116C", + "/ko:ojungseong": "\u1169", + "/ko:oojungseong": "\u1182", + "/ko:oujungseong": "\u1183", + "/ko:oyaejungseong": "\u11A7", + "/ko:oyajungseong": "\u11A6", + "/ko:oyejungseong": "\u1181", + "/ko:pansios": "\u317F", + "/ko:pansioschoseong": "\u1140", + "/ko:pansiosjongseong": "\u11EB", + "/ko:phieuph": "\u314D", + "/ko:phieuphchoseong": "\u1111", + "/ko:phieuphjongseong": "\u11C1", + "/ko:phieuphpieupchoseong": "\u1156", + "/ko:phieuphpieupjongseong": "\u11F3", + "/ko:pieup": "\u3142", + "/ko:pieupchieuchchoseong": "\u1128", + "/ko:pieupchoseong": "\u1107", + "/ko:pieupcieuc": "\u3176", + "/ko:pieupcieucchoseong": "\u1127", + "/ko:pieuphieuhjongseong": "\u11E5", + "/ko:pieupjongseong": "\u11B8", + "/ko:pieupkiyeok": "\u3172", + "/ko:pieupkiyeokchoseong": "\u111E", + "/ko:pieupnieunchoseong": "\u111F", + "/ko:pieupphieuphchoseong": "\u112A", + "/ko:pieupphieuphjongseong": "\u11E4", + "/ko:pieuprieuljongseong": "\u11E3", + "/ko:pieupsios": "\u3144", + "/ko:pieupsioschoseong": "\u1121", + "/ko:pieupsioscieucchoseong": "\u1126", + "/ko:pieupsiosjongseong": "\u11B9", + "/ko:pieupsioskiyeok": "\u3174", + "/ko:pieupsioskiyeokchoseong": "\u1122", + "/ko:pieupsiospieupchoseong": "\u1124", + "/ko:pieupsiostikeut": "\u3175", + "/ko:pieupsiostikeutchoseong": "\u1123", + "/ko:pieupssangsioschoseong": "\u1125", + "/ko:pieupthieuth": "\u3177", + "/ko:pieupthieuthchoseong": "\u1129", + "/ko:pieuptikeut": "\u3173", + "/ko:pieuptikeutchoseong": "\u1120", + "/ko:rieul": "\u3139", + "/ko:rieulchoseong": "\u1105", + "/ko:rieulhieuh": "\u3140", + "/ko:rieulhieuhchoseong": "\u111A", + "/ko:rieulhieuhjongseong": "\u11B6", + "/ko:rieuljongseong": "\u11AF", + "/ko:rieulkapyeounpieupjongseong": "\u11D5", + "/ko:rieulkhieukhjongseong": "\u11D8", + "/ko:rieulkiyeok": "\u313A", + "/ko:rieulkiyeokjongseong": "\u11B0", + "/ko:rieulkiyeoksios": "\u3169", + "/ko:rieulkiyeoksiosjongseong": "\u11CC", + "/ko:rieulmieum": "\u313B", + "/ko:rieulmieumjongseong": "\u11B1", + "/ko:rieulmieumkiyeokjongseong": "\u11D1", + "/ko:rieulmieumsiosjongseong": "\u11D2", + "/ko:rieulnieunchoseong": "\u1118", + "/ko:rieulnieunjongseong": "\u11CD", + "/ko:rieulpansios": "\u316C", + "/ko:rieulpansiosjongseong": "\u11D7", + "/ko:rieulphieuph": "\u313F", + "/ko:rieulphieuphjongseong": "\u11B5", + "/ko:rieulpieup": "\u313C", + "/ko:rieulpieuphieuhjongseong": "\u11D4", + "/ko:rieulpieupjongseong": "\u11B2", + "/ko:rieulpieupsios": "\u316B", + "/ko:rieulpieupsiosjongseong": "\u11D3", + "/ko:rieulsios": "\u313D", + "/ko:rieulsiosjongseong": "\u11B3", + "/ko:rieulssangsiosjongseong": "\u11D6", + "/ko:rieulthieuth": "\u313E", + "/ko:rieulthieuthjongseong": "\u11B4", + "/ko:rieultikeut": "\u316A", + "/ko:rieultikeuthieuhjongseong": "\u11CF", + "/ko:rieultikeutjongseong": "\u11CE", + "/ko:rieulyeorinhieuh": "\u316D", + "/ko:rieulyeorinhieuhjongseong": "\u11D9", + "/ko:sios": "\u3145", + "/ko:sioschieuchchoseong": "\u1137", + "/ko:sioschoseong": "\u1109", + "/ko:sioscieuc": "\u317E", + "/ko:sioscieucchoseong": "\u1136", + "/ko:sioshieuhchoseong": "\u113B", + "/ko:siosieungchoseong": "\u1135", + "/ko:siosjongseong": "\u11BA", + "/ko:sioskhieukhchoseong": "\u1138", + "/ko:sioskiyeok": "\u317A", + "/ko:sioskiyeokchoseong": "\u112D", + "/ko:sioskiyeokjongseong": "\u11E7", + "/ko:siosmieumchoseong": "\u1131", + "/ko:siosnieun": "\u317B", + "/ko:siosnieunchoseong": "\u112E", + "/ko:siosphieuphchoseong": "\u113A", + "/ko:siospieup": "\u317D", + "/ko:siospieupchoseong": "\u1132", + "/ko:siospieupjongseong": "\u11EA", + "/ko:siospieupkiyeokchoseong": "\u1133", + "/ko:siosrieulchoseong": "\u1130", + "/ko:siosrieuljongseong": "\u11E9", + "/ko:siosssangsioschoseong": "\u1134", + "/ko:siosthieuthchoseong": "\u1139", + "/ko:siostikeut": "\u317C", + "/ko:siostikeutchoseong": "\u112F", + "/ko:siostikeutjongseong": "\u11E8", + "/ko:ssangaraeajungseong": "\u11A2", + "/ko:ssangcieuc": "\u3149", + "/ko:ssangcieucchoseong": "\u110D", + "/ko:ssanghieuh": "\u3185", + "/ko:ssanghieuhchoseong": "\u1158", + "/ko:ssangieung": "\u3180", + "/ko:ssangieungchoseong": "\u1147", + "/ko:ssangieungjongseong": "\u11EE", + "/ko:ssangkiyeok": "\u3132", + "/ko:ssangkiyeokchoseong": "\u1101", + "/ko:ssangkiyeokjongseong": "\u11A9", + "/ko:ssangnieun": "\u3165", + "/ko:ssangnieunchoseong": "\u1114", + "/ko:ssangnieunjongseong": "\u11FF", + "/ko:ssangpieup": "\u3143", + "/ko:ssangpieupchoseong": "\u1108", + "/ko:ssangrieulchoseong": "\u1119", + "/ko:ssangrieuljongseong": "\u11D0", + "/ko:ssangsios": "\u3146", + "/ko:ssangsioschoseong": "\u110A", + "/ko:ssangsiosjongseong": "\u11BB", + "/ko:ssangtikeut": "\u3138", + "/ko:ssangtikeutchoseong": "\u1104", + "/ko:thieuth": "\u314C", + "/ko:thieuthchoseong": "\u1110", + "/ko:thieuthjongseong": "\u11C0", + "/ko:tikeut": "\u3137", + "/ko:tikeutchoseong": "\u1103", + "/ko:tikeutjongseong": "\u11AE", + "/ko:tikeutkiyeokchoseong": "\u1117", + "/ko:tikeutkiyeokjongseong": "\u11CA", + "/ko:tikeutrieulchoseong": "\u115E", + "/ko:tikeutrieuljongseong": "\u11CB", + "/ko:u": "\u315C", + "/ko:uaejungseong": "\u118A", + "/ko:uajungseong": "\u1189", + "/ko:ueo_eujungseong": "\u118B", + "/ko:ujungseong": "\u116E", + "/ko:uujungseong": "\u118D", + "/ko:uyejungseong": "\u118C", + "/ko:wa": "\u3158", + "/ko:wae": "\u3159", + "/ko:waejungseong": "\u116B", + "/ko:wajungseong": "\u116A", + "/ko:we": "\u315E", + "/ko:wejungseong": "\u1170", + "/ko:weo": "\u315D", + "/ko:weojungseong": "\u116F", + "/ko:wi": "\u315F", + "/ko:wijungseong": "\u1171", + "/ko:ya": "\u3151", + "/ko:yae": "\u3152", + "/ko:yaejungseong": "\u1164", + "/ko:yajungseong": "\u1163", + "/ko:yaojungseong": "\u1178", + "/ko:yaujungseong": "\u11A4", + "/ko:yayojungseong": "\u1179", + "/ko:ye": "\u3156", + "/ko:yejungseong": "\u1168", + "/ko:yeo": "\u3155", + "/ko:yeojungseong": "\u1167", + "/ko:yeoojungseong": "\u117D", + "/ko:yeorinhieuh": "\u3186", + "/ko:yeorinhieuhchoseong": "\u1159", + "/ko:yeorinhieuhjongseong": "\u11F9", + "/ko:yeoujungseong": "\u117E", + "/ko:yeoyajungseong": "\u11A5", + "/ko:yesieung": "\u3181", + "/ko:yesieungchoseong": "\u114C", + "/ko:yesieungjongseong": "\u11F0", + "/ko:yesieungpansios": "\u3183", + "/ko:yesieungpansiosjongseong": "\u11F2", + "/ko:yesieungsios": "\u3182", + "/ko:yesieungsiosjongseong": "\u11F1", + "/ko:yi": "\u3162", + "/ko:yijungseong": "\u1174", + "/ko:yiujungseong": "\u1197", + "/ko:yo": "\u315B", + "/ko:yoi": "\u3189", + "/ko:yoijungseong": "\u1188", + "/ko:yojungseong": "\u116D", + "/ko:yoojungseong": "\u1187", + "/ko:yoya": "\u3187", + "/ko:yoyae": "\u3188", + "/ko:yoyaejungseong": "\u1185", + "/ko:yoyajungseong": "\u1184", + "/ko:yoyeojungseong": "\u1186", + "/ko:yu": "\u3160", + "/ko:yuajungseong": "\u118E", + "/ko:yuejungseong": "\u1190", + "/ko:yueojungseong": "\u118F", + "/ko:yui": "\u318C", + "/ko:yuijungseong": "\u1194", + "/ko:yujungseong": "\u1172", + "/ko:yuujungseong": "\u1193", + "/ko:yuye": "\u318B", + "/ko:yuyejungseong": "\u1192", + "/ko:yuyeo": "\u318A", + "/ko:yuyeojungseong": "\u1191", + "/koala": "\u1F428", + "/kobliquestroke": "\uA7A3", + "/kocirclekatakana": "\u32D9", + "/kohiragana": "\u3053", + "/kohmfullwidth": "\u33C0", + "/kohmsquare": "\u33C0", + "/kokaithai": "\u0E01", + "/kokatakana": "\u30B3", + "/kokatakanahalfwidth": "\uFF7A", + "/kooposquare": "\u331E", + "/koppa": "\u03DF", + "/koppaarchaic": "\u03D9", + "/koppacyr": "\u0481", + "/koppacyrillic": "\u0481", + "/koreanstandardsymbol": "\u327F", + "/koroniscmb": "\u0343", + "/korunasquare": "\u331D", + "/kotoideographiccircled": "\u3247", + "/kpafullwidth": "\u33AA", + "/kparen": "\u24A6", + "/kparenthesized": "\u24A6", + "/kpasquare": "\u33AA", + "/kra": "\u0138", + "/ksicyr": "\u046F", + "/ksicyrillic": "\u046F", + "/kstroke": "\uA741", + "/kstrokediagonalstroke": "\uA745", + "/ktfullwidth": "\u33CF", + "/ktsquare": "\u33CF", + "/kturned": "\u029E", + "/kucirclekatakana": "\u32D7", + "/kuhiragana": "\u304F", + "/kukatakana": "\u30AF", + "/kukatakanahalfwidth": "\uFF78", + "/kuroonesquare": "\u331B", + "/kuruzeirosquare": "\u331A", + "/kvfullwidth": "\u33B8", + "/kvsquare": "\u33B8", + "/kwfullwidth": "\u33BE", + "/kwsquare": "\u33BE", + "/kyuriisquare": "\u3312", + "/l": "\u006C", + "/l.inferior": "\u2097", + "/label": "\u1F3F7", + "/labengali": "\u09B2", + "/laborideographiccircled": "\u3298", + "/laborideographicparen": "\u3238", + "/lacute": "\u013A", + "/ladeva": "\u0932", + "/ladyBeetle": "\u1F41E", + "/lagujarati": "\u0AB2", + "/lagurmukhi": "\u0A32", + "/lakkhangyaothai": "\u0E45", + "/lam": "\u0644", + "/lam.fina": "\uFEDE", + "/lam.init": "\uFEDF", + "/lam.init_alef.fina": "\uFEFB", + "/lam.init_alef.medi_hamzaabove.fina": "\uFEF7", + "/lam.init_alef.medi_hamzabelow.fina": "\uFEF9", + "/lam.init_alef.medi_maddaabove.fina": "\uFEF5", + "/lam.init_alefmaksura.fina": "\uFC43", + "/lam.init_hah.fina": "\uFC40", + "/lam.init_hah.medi": "\uFCCA", + "/lam.init_hah.medi_meem.medi": "\uFDB5", + "/lam.init_heh.medi": "\uFCCD", + "/lam.init_jeem.fina": "\uFC3F", + "/lam.init_jeem.medi": "\uFCC9", + "/lam.init_jeem.medi_jeem.medi": "\uFD83", + "/lam.init_jeem.medi_meem.medi": "\uFDBA", + "/lam.init_khah.fina": "\uFC41", + "/lam.init_khah.medi": "\uFCCB", + "/lam.init_khah.medi_meem.medi": "\uFD86", + "/lam.init_meem.fina": "\uFC42", + "/lam.init_meem.medi": "\uFCCC", + "/lam.init_meem.medi_hah.medi": "\uFD88", + "/lam.init_yeh.fina": "\uFC44", + "/lam.isol": "\uFEDD", + "/lam.medi": "\uFEE0", + "/lam.medi_alef.fina": "\uFEFC", + "/lam.medi_alef.medi_hamzaabove.fina": "\uFEF8", + "/lam.medi_alef.medi_hamzabelow.fina": "\uFEFA", + "/lam.medi_alef.medi_maddaabove.fina": "\uFEF6", + "/lam.medi_alefmaksura.fina": "\uFC86", + "/lam.medi_hah.medi_alefmaksura.fina": "\uFD82", + "/lam.medi_hah.medi_meem.fina": "\uFD80", + "/lam.medi_hah.medi_yeh.fina": "\uFD81", + "/lam.medi_jeem.medi_jeem.fina": "\uFD84", + "/lam.medi_jeem.medi_meem.fina": "\uFDBC", + "/lam.medi_jeem.medi_yeh.fina": "\uFDAC", + "/lam.medi_khah.medi_meem.fina": "\uFD85", + "/lam.medi_meem.fina": "\uFC85", + "/lam.medi_meem.medi": "\uFCED", + "/lam.medi_meem.medi_hah.fina": "\uFD87", + "/lam.medi_meem.medi_yeh.fina": "\uFDAD", + "/lam.medi_yeh.fina": "\uFC87", + "/lamBar": "\u076A", + "/lamVabove": "\u06B5", + "/lamalefabove": "\u06D9", + "/lamaleffinalarabic": "\uFEFC", + "/lamalefhamzaabovefinalarabic": "\uFEF8", + "/lamalefhamzaaboveisolatedarabic": "\uFEF7", + "/lamalefhamzabelowfinalarabic": "\uFEFA", + "/lamalefhamzabelowisolatedarabic": "\uFEF9", + "/lamalefisolatedarabic": "\uFEFB", + "/lamalefmaddaabovefinalarabic": "\uFEF6", + "/lamalefmaddaaboveisolatedarabic": "\uFEF5", + "/lamarabic": "\u0644", + "/lambda": "\u03BB", + "/lambdastroke": "\u019B", + "/lamdotabove": "\u06B6", + "/lamed": "\u05DC", + "/lamed:hb": "\u05DC", + "/lameddagesh": "\uFB3C", + "/lameddageshhebrew": "\uFB3C", + "/lamedhebrew": "\u05DC", + "/lamedholam": "\u05DC", + "/lamedholamdagesh": "\u05DC", + "/lamedholamdageshhebrew": "\u05DC", + "/lamedholamhebrew": "\u05DC", + "/lamedwide:hb": "\uFB25", + "/lamedwithdagesh:hb": "\uFB3C", + "/lamfinalarabic": "\uFEDE", + "/lamhahinitialarabic": "\uFCCA", + "/laminitialarabic": "\uFEDF", + "/lamjeeminitialarabic": "\uFCC9", + "/lamkhahinitialarabic": "\uFCCB", + "/lamlamhehisolatedarabic": "\uFDF2", + "/lammedialarabic": "\uFEE0", + "/lammeemhahinitialarabic": "\uFD88", + "/lammeeminitialarabic": "\uFCCC", + "/lammeemjeeminitialarabic": "\uFEDF", + "/lammeemkhahinitialarabic": "\uFEDF", + "/lamthreedotsabove": "\u06B7", + "/lamthreedotsbelow": "\u06B8", + "/lanemergeleftblack": "\u26D8", + "/lanemergeleftwhite": "\u26D9", + "/largeBlueCircle": "\u1F535", + "/largeBlueDiamond": "\u1F537", + "/largeOrangeDiamond": "\u1F536", + "/largeRedCircle": "\u1F534", + "/largecircle": "\u25EF", + "/largetackdown": "\u27D9", + "/largetackup": "\u27D8", + "/lari": "\u20BE", + "/lastQuarterMoon": "\u1F317", + "/lastQuarterMoonFace": "\u1F31C", + "/lastquartermoon": "\u263E", + "/layar": "\uA982", + "/lazysinverted": "\u223E", + "/lbar": "\u019A", + "/lbbar": "\u2114", + "/lbelt": "\u026C", + "/lbeltretroflex": "\uA78E", + "/lbopomofo": "\u310C", + "/lbroken": "\uA747", + "/lcaron": "\u013E", + "/lcedilla": "\u013C", + "/lcircle": "\u24DB", + "/lcircumflexbelow": "\u1E3D", + "/lcommaaccent": "\u013C", + "/lcurl": "\u0234", + "/ldblbar": "\u2C61", + "/ldot": "\u0140", + "/ldotaccent": "\u0140", + "/ldotbelow": "\u1E37", + "/ldotbelowmacron": "\u1E39", + "/leafFlutteringInWind": "\u1F343", + "/ledger": "\u1F4D2", + "/left-pointingMagnifyingGlass": "\u1F50D", + "/leftAngerBubble": "\u1F5EE", + "/leftFiveEighthsBlock": "\u258B", + "/leftHalfBlock": "\u258C", + "/leftHandTelephoneReceiver": "\u1F57B", + "/leftLuggage": "\u1F6C5", + "/leftOneEighthBlock": "\u258F", + "/leftOneQuarterBlock": "\u258E", + "/leftSevenEighthsBlock": "\u2589", + "/leftSpeechBubble": "\u1F5E8", + "/leftThoughtBubble": "\u1F5EC", + "/leftThreeEighthsBlock": "\u258D", + "/leftThreeQuartersBlock": "\u258A", + "/leftWritingHand": "\u1F58E", + "/leftangleabovecmb": "\u031A", + "/leftarrowoverrightarrow": "\u21C6", + "/leftdnheavyrightuplight": "\u2545", + "/leftharpoonoverrightharpoon": "\u21CB", + "/leftheavyrightdnlight": "\u252D", + "/leftheavyrightuplight": "\u2535", + "/leftheavyrightvertlight": "\u253D", + "/leftideographiccircled": "\u32A7", + "/leftlightrightdnheavy": "\u2532", + "/leftlightrightupheavy": "\u253A", + "/leftlightrightvertheavy": "\u254A", + "/lefttackbelowcmb": "\u0318", + "/lefttorightembed": "\u202A", + "/lefttorightisolate": "\u2066", + "/lefttorightmark": "\u200E", + "/lefttorightoverride": "\u202D", + "/leftupheavyrightdnlight": "\u2543", + "/lemon": "\u1F34B", + "/lenis": "\u1FBF", + "/lenisacute": "\u1FCE", + "/lenisgrave": "\u1FCD", + "/lenistilde": "\u1FCF", + "/leo": "\u264C", + "/leopard": "\u1F406", + "/less": "\u003C", + "/lessbutnotequal": "\u2268", + "/lessbutnotequivalent": "\u22E6", + "/lessdot": "\u22D6", + "/lessequal": "\u2264", + "/lessequalorgreater": "\u22DA", + "/lessmonospace": "\uFF1C", + "/lessorequivalent": "\u2272", + "/lessorgreater": "\u2276", + "/lessoverequal": "\u2266", + "/lesssmall": "\uFE64", + "/levelSlider": "\u1F39A", + "/lezh": "\u026E", + "/lfblock": "\u258C", + "/lhacyr": "\u0515", + "/lhookretroflex": "\u026D", + "/libra": "\u264E", + "/ligaturealeflamed:hb": "\uFB4F", + "/ligatureoemod": "\uA7F9", + "/lightCheckMark": "\u1F5F8", + "/lightRail": "\u1F688", + "/lightShade": "\u2591", + "/lightarcdnleft": "\u256E", + "/lightarcdnright": "\u256D", + "/lightarcupleft": "\u256F", + "/lightarcupright": "\u2570", + "/lightdbldashhorz": "\u254C", + "/lightdbldashvert": "\u254E", + "/lightdiagcross": "\u2573", + "/lightdiagupleftdnright": "\u2572", + "/lightdiaguprightdnleft": "\u2571", + "/lightdn": "\u2577", + "/lightdnhorz": "\u252C", + "/lightdnleft": "\u2510", + "/lightdnright": "\u250C", + "/lighthorz": "\u2500", + "/lightleft": "\u2574", + "/lightleftheavyright": "\u257C", + "/lightning": "\u2607", + "/lightningMood": "\u1F5F2", + "/lightningMoodBubble": "\u1F5F1", + "/lightquaddashhorz": "\u2508", + "/lightquaddashvert": "\u250A", + "/lightright": "\u2576", + "/lighttrpldashhorz": "\u2504", + "/lighttrpldashvert": "\u2506", + "/lightup": "\u2575", + "/lightupheavydn": "\u257D", + "/lightuphorz": "\u2534", + "/lightupleft": "\u2518", + "/lightupright": "\u2514", + "/lightvert": "\u2502", + "/lightverthorz": "\u253C", + "/lightvertleft": "\u2524", + "/lightvertright": "\u251C", + "/lineextensionhorizontal": "\u23AF", + "/lineextensionvertical": "\u23D0", + "/linemiddledotvertical": "\u237F", + "/lineseparator": "\u2028", + "/lingsapada": "\uA9C8", + "/link": "\u1F517", + "/linkedPaperclips": "\u1F587", + "/lips": "\u1F5E2", + "/lipstick": "\u1F484", + "/lira": "\u20A4", + "/litre": "\u2113", + "/livretournois": "\u20B6", + "/liwnarmenian": "\u056C", + "/lj": "\u01C9", + "/ljecyr": "\u0459", + "/ljecyrillic": "\u0459", + "/ljekomicyr": "\u0509", + "/ll": "\uF6C0", + "/lladeva": "\u0933", + "/llagujarati": "\u0AB3", + "/llinebelow": "\u1E3B", + "/llladeva": "\u0934", + "/llvocalicbengali": "\u09E1", + "/llvocalicdeva": "\u0961", + "/llvocalicvowelsignbengali": "\u09E3", + "/llvocalicvowelsigndeva": "\u0963", + "/llwelsh": "\u1EFB", + "/lmacrondot": "\u1E39", + "/lmfullwidth": "\u33D0", + "/lmiddletilde": "\u026B", + "/lmonospace": "\uFF4C", + "/lmsquare": "\u33D0", + "/lnfullwidth": "\u33D1", + "/lochulathai": "\u0E2C", + "/lock": "\u1F512", + "/lockInkPen": "\u1F50F", + "/logfullwidth": "\u33D2", + "/logicaland": "\u2227", + "/logicalandarray": "\u22C0", + "/logicalnot": "\u00AC", + "/logicalnotreversed": "\u2310", + "/logicalor": "\u2228", + "/logicalorarray": "\u22C1", + "/lolingthai": "\u0E25", + "/lollipop": "\u1F36D", + "/longdivision": "\u27CC", + "/longovershortmetrical": "\u23D2", + "/longovertwoshortsmetrical": "\u23D4", + "/longs": "\u017F", + "/longs_t": "\uFB05", + "/longsdot": "\u1E9B", + "/longswithdiagonalstroke": "\u1E9C", + "/longswithhighstroke": "\u1E9D", + "/longtackleft": "\u27DE", + "/longtackright": "\u27DD", + "/losslesssquare": "\u1F1A9", + "/loudlyCryingFace": "\u1F62D", + "/loveHotel": "\u1F3E9", + "/loveLetter": "\u1F48C", + "/lowBrightness": "\u1F505", + "/lowasterisk": "\u204E", + "/lowerFiveEighthsBlock": "\u2585", + "/lowerHalfBlock": "\u2584", + "/lowerLeftBallpointPen": "\u1F58A", + "/lowerLeftCrayon": "\u1F58D", + "/lowerLeftFountainPen": "\u1F58B", + "/lowerLeftPaintbrush": "\u1F58C", + "/lowerLeftPencil": "\u1F589", + "/lowerOneEighthBlock": "\u2581", + "/lowerOneQuarterBlock": "\u2582", + "/lowerRightShadowedWhiteCircle": "\u1F53E", + "/lowerSevenEighthsBlock": "\u2587", + "/lowerThreeEighthsBlock": "\u2583", + "/lowerThreeQuartersBlock": "\u2586", + "/lowercornerdotright": "\u27D3", + "/lowerhalfcircle": "\u25E1", + "/lowerhalfcircleinversewhite": "\u25DB", + "/lowerquadrantcirculararcleft": "\u25DF", + "/lowerquadrantcirculararcright": "\u25DE", + "/lowertriangleleft": "\u25FA", + "/lowertriangleleftblack": "\u25E3", + "/lowertriangleright": "\u25FF", + "/lowertrianglerightblack": "\u25E2", + "/lowideographiccircled": "\u32A6", + "/lowlinecenterline": "\uFE4E", + "/lowlinecmb": "\u0332", + "/lowlinedashed": "\uFE4D", + "/lownumeralsign": "\u0375", + "/lowquotedblprime": "\u301F", + "/lozenge": "\u25CA", + "/lozengedividedbyrulehorizontal": "\u27E0", + "/lozengesquare": "\u2311", + "/lparen": "\u24A7", + "/lparenthesized": "\u24A7", + "/lretroflex": "\u026D", + "/ls": "\u02AA", + "/lslash": "\u0142", + "/lsquare": "\u2113", + "/lstroke": "\uA749", + "/lsuperior": "\uF6EE", + "/lsupmod": "\u02E1", + "/lt:Alpha": "\u2C6D", + "/lt:Alphaturned": "\u2C70", + "/lt:Beta": "\uA7B4", + "/lt:Chi": "\uA7B3", + "/lt:Gamma": "\u0194", + "/lt:Iota": "\u0196", + "/lt:Omega": "\uA7B6", + "/lt:Upsilon": "\u01B1", + "/lt:beta": "\uA7B5", + "/lt:delta": "\u1E9F", + "/lt:omega": "\uA7B7", + "/ltshade": "\u2591", + "/lttr:bet": "\u2136", + "/lttr:dalet": "\u2138", + "/lttr:gimel": "\u2137", + "/lttr:gscript": "\u210A", + "/lturned": "\uA781", + "/ltypeopencircuit": "\u2390", + "/luhurpada": "\uA9C5", + "/lum": "\uA772", + "/lungsipada": "\uA9C9", + "/luthai": "\u0E26", + "/lvocalicbengali": "\u098C", + "/lvocalicdeva": "\u090C", + "/lvocalicvowelsignbengali": "\u09E2", + "/lvocalicvowelsigndeva": "\u0962", + "/lxfullwidth": "\u33D3", + "/lxsquare": "\u33D3", + "/lzed": "\u02AB", + "/m": "\u006D", + "/m.inferior": "\u2098", + "/m2fullwidth": "\u33A1", + "/m3fullwidth": "\u33A5", + "/mabengali": "\u09AE", + "/macirclekatakana": "\u32EE", + "/macron": "\u00AF", + "/macronbelowcmb": "\u0331", + "/macroncmb": "\u0304", + "/macronlowmod": "\u02CD", + "/macronmod": "\u02C9", + "/macronmonospace": "\uFFE3", + "/macute": "\u1E3F", + "/madda": "\u0653", + "/maddaabove": "\u06E4", + "/madeva": "\u092E", + "/madyapada": "\uA9C4", + "/mafullwidth": "\u3383", + "/magujarati": "\u0AAE", + "/magurmukhi": "\u0A2E", + "/mahapakhhebrew": "\u05A4", + "/mahapakhlefthebrew": "\u05A4", + "/mahhasquare": "\u3345", + "/mahiragana": "\u307E", + "/mahpach:hb": "\u05A4", + "/maichattawalowleftthai": "\uF895", + "/maichattawalowrightthai": "\uF894", + "/maichattawathai": "\u0E4B", + "/maichattawaupperleftthai": "\uF893", + "/maieklowleftthai": "\uF88C", + "/maieklowrightthai": "\uF88B", + "/maiekthai": "\u0E48", + "/maiekupperleftthai": "\uF88A", + "/maihanakatleftthai": "\uF884", + "/maihanakatthai": "\u0E31", + "/maikurosquare": "\u3343", + "/mairusquare": "\u3344", + "/maitaikhuleftthai": "\uF889", + "/maitaikhuthai": "\u0E47", + "/maitholowleftthai": "\uF88F", + "/maitholowrightthai": "\uF88E", + "/maithothai": "\u0E49", + "/maithoupperleftthai": "\uF88D", + "/maitrilowleftthai": "\uF892", + "/maitrilowrightthai": "\uF891", + "/maitrithai": "\u0E4A", + "/maitriupperleftthai": "\uF890", + "/maiyamokthai": "\u0E46", + "/makatakana": "\u30DE", + "/makatakanahalfwidth": "\uFF8F", + "/male": "\u2642", + "/malefemale": "\u26A5", + "/maleideographiccircled": "\u329A", + "/malestroke": "\u26A6", + "/malestrokemalefemale": "\u26A7", + "/man": "\u1F468", + "/manAndWomanHoldingHands": "\u1F46B", + "/manDancing": "\u1F57A", + "/manGuaPiMao": "\u1F472", + "/manInBusinessSuitLevitating": "\u1F574", + "/manTurban": "\u1F473", + "/manat": "\u20BC", + "/mansShoe": "\u1F45E", + "/mansyonsquare": "\u3347", + "/mantelpieceClock": "\u1F570", + "/mapleLeaf": "\u1F341", + "/maplighthouse": "\u26EF", + "/maqaf:hb": "\u05BE", + "/maqafhebrew": "\u05BE", + "/marchtelegraph": "\u32C2", + "/mark": "\u061C", + "/markerdottedraisedinterpolation": "\u2E07", + "/markerdottedtransposition": "\u2E08", + "/markerraisedinterpolation": "\u2E06", + "/marknoonghunna": "\u0658", + "/marksChapter": "\u1F545", + "/marriage": "\u26AD", + "/mars": "\u2642", + "/marukusquare": "\u3346", + "/masoraCircle:hb": "\u05AF", + "/masoracirclehebrew": "\u05AF", + "/masquare": "\u3383", + "/masumark": "\u303C", + "/math:bowtie": "\u22C8", + "/math:cuberoot": "\u221B", + "/math:fourthroot": "\u221C", + "/maximize": "\u1F5D6", + "/maytelegraph": "\u32C4", + "/mbfullwidth": "\u3386", + "/mbopomofo": "\u3107", + "/mbsmallfullwidth": "\u33D4", + "/mbsquare": "\u33D4", + "/mcircle": "\u24DC", + "/mcubedsquare": "\u33A5", + "/mdot": "\u1E41", + "/mdotaccent": "\u1E41", + "/mdotbelow": "\u1E43", + "/measuredangle": "\u2221", + "/measuredby": "\u225E", + "/meatOnBone": "\u1F356", + "/mecirclekatakana": "\u32F1", + "/medicineideographiccircled": "\u32A9", + "/mediumShade": "\u2592", + "/mediumcircleblack": "\u26AB", + "/mediumcirclewhite": "\u26AA", + "/mediummathematicalspace": "\u205F", + "/mediumsmallcirclewhite": "\u26AC", + "/meem": "\u0645", + "/meem.fina": "\uFEE2", + "/meem.init": "\uFEE3", + "/meem.init_alefmaksura.fina": "\uFC49", + "/meem.init_hah.fina": "\uFC46", + "/meem.init_hah.medi": "\uFCCF", + "/meem.init_hah.medi_jeem.medi": "\uFD89", + "/meem.init_hah.medi_meem.medi": "\uFD8A", + "/meem.init_jeem.fina": "\uFC45", + "/meem.init_jeem.medi": "\uFCCE", + "/meem.init_jeem.medi_hah.medi": "\uFD8C", + "/meem.init_jeem.medi_khah.medi": "\uFD92", + "/meem.init_jeem.medi_meem.medi": "\uFD8D", + "/meem.init_khah.fina": "\uFC47", + "/meem.init_khah.medi": "\uFCD0", + "/meem.init_khah.medi_jeem.medi": "\uFD8E", + "/meem.init_khah.medi_meem.medi": "\uFD8F", + "/meem.init_meem.fina": "\uFC48", + "/meem.init_meem.medi": "\uFCD1", + "/meem.init_yeh.fina": "\uFC4A", + "/meem.isol": "\uFEE1", + "/meem.medi": "\uFEE4", + "/meem.medi_alef.fina": "\uFC88", + "/meem.medi_hah.medi_yeh.fina": "\uFD8B", + "/meem.medi_jeem.medi_yeh.fina": "\uFDC0", + "/meem.medi_khah.medi_yeh.fina": "\uFDB9", + "/meem.medi_meem.fina": "\uFC89", + "/meem.medi_meem.medi_yeh.fina": "\uFDB1", + "/meemDotAbove": "\u0765", + "/meemDotBelow": "\u0766", + "/meemabove": "\u06E2", + "/meemabove.init": "\u06D8", + "/meemarabic": "\u0645", + "/meembelow": "\u06ED", + "/meemfinalarabic": "\uFEE2", + "/meeminitialarabic": "\uFEE3", + "/meemmedialarabic": "\uFEE4", + "/meemmeeminitialarabic": "\uFCD1", + "/meemmeemisolatedarabic": "\uFC48", + "/meetorusquare": "\u334D", + "/megasquare": "\u334B", + "/megatonsquare": "\u334C", + "/mehiragana": "\u3081", + "/meizierasquare": "\u337E", + "/mekatakana": "\u30E1", + "/mekatakanahalfwidth": "\uFF92", + "/melon": "\u1F348", + "/mem": "\u05DE", + "/mem:hb": "\u05DE", + "/memdagesh": "\uFB3E", + "/memdageshhebrew": "\uFB3E", + "/memhebrew": "\u05DE", + "/memo": "\u1F4DD", + "/memwithdagesh:hb": "\uFB3E", + "/menarmenian": "\u0574", + "/menorahNineBranches": "\u1F54E", + "/menpostSindhi": "\u06FE", + "/mens": "\u1F6B9", + "/mepigraphicinverted": "\uA7FD", + "/mercha:hb": "\u05A5", + "/merchaKefulah:hb": "\u05A6", + "/mercury": "\u263F", + "/merkhahebrew": "\u05A5", + "/merkhakefulahebrew": "\u05A6", + "/merkhakefulalefthebrew": "\u05A6", + "/merkhalefthebrew": "\u05A5", + "/metalideographiccircled": "\u328E", + "/metalideographicparen": "\u322E", + "/meteg:hb": "\u05BD", + "/metro": "\u1F687", + "/mgfullwidth": "\u338E", + "/mhook": "\u0271", + "/mhzfullwidth": "\u3392", + "/mhzsquare": "\u3392", + "/micirclekatakana": "\u32EF", + "/microphone": "\u1F3A4", + "/microscope": "\u1F52C", + "/middledotkatakanahalfwidth": "\uFF65", + "/middot": "\u00B7", + "/mieumacirclekorean": "\u3272", + "/mieumaparenkorean": "\u3212", + "/mieumcirclekorean": "\u3264", + "/mieumkorean": "\u3141", + "/mieumpansioskorean": "\u3170", + "/mieumparenkorean": "\u3204", + "/mieumpieupkorean": "\u316E", + "/mieumsioskorean": "\u316F", + "/mihiragana": "\u307F", + "/mikatakana": "\u30DF", + "/mikatakanahalfwidth": "\uFF90", + "/mikuronsquare": "\u3348", + "/milfullwidth": "\u33D5", + "/militaryMedal": "\u1F396", + "/milkyWay": "\u1F30C", + "/mill": "\u20A5", + "/millionscmbcyr": "\u0489", + "/millisecond": "\u2034", + "/millisecondreversed": "\u2037", + "/minibus": "\u1F690", + "/minidisc": "\u1F4BD", + "/minimize": "\u1F5D5", + "/minus": "\u2212", + "/minus.inferior": "\u208B", + "/minus.superior": "\u207B", + "/minusbelowcmb": "\u0320", + "/minuscircle": "\u2296", + "/minusmod": "\u02D7", + "/minusplus": "\u2213", + "/minussignmod": "\u02D7", + "/minustilde": "\u2242", + "/minute": "\u2032", + "/minutereversed": "\u2035", + "/miribaarusquare": "\u334A", + "/mirisquare": "\u3349", + "/misc:baby": "\u1F476", + "/misc:bell": "\u1F514", + "/misc:dash": "\u1F4A8", + "/misc:decimalseparator": "\u2396", + "/misc:diamondblack": "\u2666", + "/misc:diamondwhite": "\u2662", + "/misc:ear": "\u1F442", + "/misc:om": "\u1F549", + "/misc:ring": "\u1F48D", + "/misra": "\u060F", + "/mlfullwidth": "\u3396", + "/mlonglegturned": "\u0270", + "/mlsquare": "\u3396", + "/mlym:a": "\u0D05", + "/mlym:aa": "\u0D06", + "/mlym:aasign": "\u0D3E", + "/mlym:ai": "\u0D10", + "/mlym:aisign": "\u0D48", + "/mlym:anusvarasign": "\u0D02", + "/mlym:archaicii": "\u0D5F", + "/mlym:au": "\u0D14", + "/mlym:aulength": "\u0D57", + "/mlym:ausign": "\u0D4C", + "/mlym:avagrahasign": "\u0D3D", + "/mlym:ba": "\u0D2C", + "/mlym:bha": "\u0D2D", + "/mlym:ca": "\u0D1A", + "/mlym:candrabindusign": "\u0D01", + "/mlym:cha": "\u0D1B", + "/mlym:circularviramasign": "\u0D3C", + "/mlym:combininganusvaraabovesign": "\u0D00", + "/mlym:da": "\u0D26", + "/mlym:date": "\u0D79", + "/mlym:dda": "\u0D21", + "/mlym:ddha": "\u0D22", + "/mlym:dha": "\u0D27", + "/mlym:dotreph": "\u0D4E", + "/mlym:e": "\u0D0E", + "/mlym:ee": "\u0D0F", + "/mlym:eesign": "\u0D47", + "/mlym:eight": "\u0D6E", + "/mlym:esign": "\u0D46", + "/mlym:five": "\u0D6B", + "/mlym:four": "\u0D6A", + "/mlym:ga": "\u0D17", + "/mlym:gha": "\u0D18", + "/mlym:ha": "\u0D39", + "/mlym:i": "\u0D07", + "/mlym:ii": "\u0D08", + "/mlym:iisign": "\u0D40", + "/mlym:isign": "\u0D3F", + "/mlym:ja": "\u0D1C", + "/mlym:jha": "\u0D1D", + "/mlym:ka": "\u0D15", + "/mlym:kchillu": "\u0D7F", + "/mlym:kha": "\u0D16", + "/mlym:la": "\u0D32", + "/mlym:lchillu": "\u0D7D", + "/mlym:lla": "\u0D33", + "/mlym:llchillu": "\u0D7E", + "/mlym:llla": "\u0D34", + "/mlym:lllchillu": "\u0D56", + "/mlym:llvocal": "\u0D61", + "/mlym:llvocalsign": "\u0D63", + "/mlym:lvocal": "\u0D0C", + "/mlym:lvocalsign": "\u0D62", + "/mlym:ma": "\u0D2E", + "/mlym:mchillu": "\u0D54", + "/mlym:na": "\u0D28", + "/mlym:nchillu": "\u0D7B", + "/mlym:nga": "\u0D19", + "/mlym:nine": "\u0D6F", + "/mlym:nna": "\u0D23", + "/mlym:nnchillu": "\u0D7A", + "/mlym:nnna": "\u0D29", + "/mlym:nya": "\u0D1E", + "/mlym:o": "\u0D12", + "/mlym:one": "\u0D67", + "/mlym:oneeighth": "\u0D77", + "/mlym:onefifth": "\u0D5E", + "/mlym:onefortieth": "\u0D59", + "/mlym:onehalf": "\u0D74", + "/mlym:onehundred": "\u0D71", + "/mlym:oneone-hundred-and-sixtieth": "\u0D58", + "/mlym:onequarter": "\u0D73", + "/mlym:onesixteenth": "\u0D76", + "/mlym:onetenth": "\u0D5C", + "/mlym:onethousand": "\u0D72", + "/mlym:onetwentieth": "\u0D5B", + "/mlym:oo": "\u0D13", + "/mlym:oosign": "\u0D4B", + "/mlym:osign": "\u0D4A", + "/mlym:pa": "\u0D2A", + "/mlym:parasign": "\u0D4F", + "/mlym:pha": "\u0D2B", + "/mlym:ra": "\u0D30", + "/mlym:rra": "\u0D31", + "/mlym:rrchillu": "\u0D7C", + "/mlym:rrvocal": "\u0D60", + "/mlym:rrvocalsign": "\u0D44", + "/mlym:rvocal": "\u0D0B", + "/mlym:rvocalsign": "\u0D43", + "/mlym:sa": "\u0D38", + "/mlym:seven": "\u0D6D", + "/mlym:sha": "\u0D36", + "/mlym:six": "\u0D6C", + "/mlym:ssa": "\u0D37", + "/mlym:ta": "\u0D24", + "/mlym:ten": "\u0D70", + "/mlym:tha": "\u0D25", + "/mlym:three": "\u0D69", + "/mlym:threeeightieths": "\u0D5A", + "/mlym:threequarters": "\u0D75", + "/mlym:threesixteenths": "\u0D78", + "/mlym:threetwentieths": "\u0D5D", + "/mlym:tta": "\u0D1F", + "/mlym:ttha": "\u0D20", + "/mlym:ttta": "\u0D3A", + "/mlym:two": "\u0D68", + "/mlym:u": "\u0D09", + "/mlym:usign": "\u0D41", + "/mlym:uu": "\u0D0A", + "/mlym:uusign": "\u0D42", + "/mlym:va": "\u0D35", + "/mlym:verticalbarviramasign": "\u0D3B", + "/mlym:viramasign": "\u0D4D", + "/mlym:visargasign": "\u0D03", + "/mlym:ya": "\u0D2F", + "/mlym:ychillu": "\u0D55", + "/mlym:zero": "\u0D66", + "/mm2fullwidth": "\u339F", + "/mm3fullwidth": "\u33A3", + "/mmcubedsquare": "\u33A3", + "/mmfullwidth": "\u339C", + "/mmonospace": "\uFF4D", + "/mmsquaredsquare": "\u339F", + "/mobilePhone": "\u1F4F1", + "/mobilePhoneOff": "\u1F4F4", + "/mobilePhoneRightwardsArrowAtLeft": "\u1F4F2", + "/mocirclekatakana": "\u32F2", + "/models": "\u22A7", + "/mohiragana": "\u3082", + "/mohmfullwidth": "\u33C1", + "/mohmsquare": "\u33C1", + "/mokatakana": "\u30E2", + "/mokatakanahalfwidth": "\uFF93", + "/molfullwidth": "\u33D6", + "/molsquare": "\u33D6", + "/momathai": "\u0E21", + "/moneyBag": "\u1F4B0", + "/moneyWings": "\u1F4B8", + "/mong:a": "\u1820", + "/mong:aaligali": "\u1887", + "/mong:ahaligali": "\u1897", + "/mong:ang": "\u1829", + "/mong:angsibe": "\u1862", + "/mong:angtodo": "\u184A", + "/mong:anusvaraonealigali": "\u1880", + "/mong:ba": "\u182A", + "/mong:baludaaligali": "\u1885", + "/mong:baludaaligalithree": "\u1886", + "/mong:batodo": "\u184B", + "/mong:bhamanchualigali": "\u18A8", + "/mong:birga": "\u1800", + "/mong:caaligali": "\u188B", + "/mong:camanchualigali": "\u189C", + "/mong:cha": "\u1834", + "/mong:chasibe": "\u1871", + "/mong:chatodo": "\u1852", + "/mong:chi": "\u1842", + "/mong:colon": "\u1804", + "/mong:comma": "\u1802", + "/mong:commamanchu": "\u1808", + "/mong:cyamanchualigali": "\u18A3", + "/mong:da": "\u1833", + "/mong:daaligali": "\u1891", + "/mong:dagalgaaligali": "\u18A9", + "/mong:damarualigali": "\u1882", + "/mong:dasibe": "\u1869", + "/mong:datodo": "\u1851", + "/mong:ddaaligali": "\u188E", + "/mong:ddhamanchualigali": "\u189F", + "/mong:dhamanchualigali": "\u18A1", + "/mong:dzatodo": "\u185C", + "/mong:e": "\u1821", + "/mong:ee": "\u1827", + "/mong:eight": "\u1818", + "/mong:ellipsis": "\u1801", + "/mong:esibe": "\u185D", + "/mong:etodo": "\u1844", + "/mong:fa": "\u1839", + "/mong:famanchu": "\u1876", + "/mong:fasibe": "\u186B", + "/mong:five": "\u1815", + "/mong:four": "\u1814", + "/mong:fourdots": "\u1805", + "/mong:freevariationselectorone": "\u180B", + "/mong:freevariationselectorthree": "\u180D", + "/mong:freevariationselectortwo": "\u180C", + "/mong:ga": "\u182D", + "/mong:gaasibe": "\u186C", + "/mong:gaatodo": "\u1858", + "/mong:gasibe": "\u1864", + "/mong:gatodo": "\u184E", + "/mong:ghamanchualigali": "\u189A", + "/mong:haa": "\u183E", + "/mong:haasibe": "\u186D", + "/mong:haatodo": "\u1859", + "/mong:hasibe": "\u1865", + "/mong:i": "\u1822", + "/mong:ialigali": "\u1888", + "/mong:imanchu": "\u1873", + "/mong:isibe": "\u185E", + "/mong:itodo": "\u1845", + "/mong:iysibe": "\u185F", + "/mong:ja": "\u1835", + "/mong:jasibe": "\u186A", + "/mong:jatodo": "\u1853", + "/mong:jhamanchualigali": "\u189D", + "/mong:jiatodo": "\u185A", + "/mong:ka": "\u183A", + "/mong:kaaligali": "\u1889", + "/mong:kamanchu": "\u1874", + "/mong:kasibe": "\u1863", + "/mong:katodo": "\u1857", + "/mong:kha": "\u183B", + "/mong:la": "\u182F", + "/mong:lha": "\u1840", + "/mong:lhamanchualigali": "\u18AA", + "/mong:longvowelsigntodo": "\u1843", + "/mong:ma": "\u182E", + "/mong:matodo": "\u184F", + "/mong:na": "\u1828", + "/mong:ngaaligali": "\u188A", + "/mong:ngamanchualigali": "\u189B", + "/mong:niatodo": "\u185B", + "/mong:nine": "\u1819", + "/mong:nirugu": "\u180A", + "/mong:nnaaligali": "\u188F", + "/mong:o": "\u1823", + "/mong:oe": "\u1825", + "/mong:oetodo": "\u1848", + "/mong:one": "\u1811", + "/mong:otodo": "\u1846", + "/mong:pa": "\u182B", + "/mong:paaligali": "\u1892", + "/mong:pasibe": "\u1866", + "/mong:patodo": "\u184C", + "/mong:period": "\u1803", + "/mong:periodmanchu": "\u1809", + "/mong:phaaligali": "\u1893", + "/mong:qa": "\u182C", + "/mong:qatodo": "\u184D", + "/mong:ra": "\u1837", + "/mong:raasibe": "\u1870", + "/mong:ramanchu": "\u1875", + "/mong:sa": "\u1830", + "/mong:seven": "\u1817", + "/mong:sha": "\u1831", + "/mong:shasibe": "\u1867", + "/mong:six": "\u1816", + "/mong:softhyphentodo": "\u1806", + "/mong:ssaaligali": "\u1894", + "/mong:ssamanchualigali": "\u18A2", + "/mong:syllableboundarymarkersibe": "\u1807", + "/mong:ta": "\u1832", + "/mong:taaligali": "\u1890", + "/mong:tamanchualigali": "\u18A0", + "/mong:tasibe": "\u1868", + "/mong:tatodo": "\u1850", + "/mong:tatodoaligali": "\u1898", + "/mong:three": "\u1813", + "/mong:tsa": "\u183C", + "/mong:tsasibe": "\u186E", + "/mong:tsatodo": "\u1854", + "/mong:ttaaligali": "\u188C", + "/mong:ttamanchualigali": "\u189E", + "/mong:tthaaligali": "\u188D", + "/mong:two": "\u1812", + "/mong:u": "\u1824", + "/mong:ualigalihalf": "\u18A6", + "/mong:ubadamaaligali": "\u1883", + "/mong:ubadamaaligaliinverted": "\u1884", + "/mong:ue": "\u1826", + "/mong:uesibe": "\u1860", + "/mong:uetodo": "\u1849", + "/mong:usibe": "\u1861", + "/mong:utodo": "\u1847", + "/mong:visargaonealigali": "\u1881", + "/mong:vowelseparator": "\u180E", + "/mong:wa": "\u1838", + "/mong:watodo": "\u1856", + "/mong:ya": "\u1836", + "/mong:yaaligalihalf": "\u18A7", + "/mong:yatodo": "\u1855", + "/mong:za": "\u183D", + "/mong:zaaligali": "\u1896", + "/mong:zamanchualigali": "\u18A5", + "/mong:zasibe": "\u186F", + "/mong:zero": "\u1810", + "/mong:zhaaligali": "\u1895", + "/mong:zhamanchu": "\u1877", + "/mong:zhamanchualigali": "\u18A4", + "/mong:zhasibe": "\u1872", + "/mong:zhatodoaligali": "\u1899", + "/mong:zhi": "\u1841", + "/mong:zra": "\u183F", + "/monkey": "\u1F412", + "/monkeyFace": "\u1F435", + "/monogramyang": "\u268A", + "/monogramyin": "\u268B", + "/monorail": "\u1F69D", + "/monostable": "\u238D", + "/moodBubble": "\u1F5F0", + "/moonViewingCeremony": "\u1F391", + "/moonideographiccircled": "\u328A", + "/moonideographicparen": "\u322A", + "/moonlilithblack": "\u26B8", + "/mosque": "\u1F54C", + "/motorBoat": "\u1F6E5", + "/motorScooter": "\u1F6F5", + "/motorway": "\u1F6E3", + "/mountFuji": "\u1F5FB", + "/mountain": "\u26F0", + "/mountainBicyclist": "\u1F6B5", + "/mountainCableway": "\u1F6A0", + "/mountainRailway": "\u1F69E", + "/mouse": "\u1F401", + "/mouseFace": "\u1F42D", + "/mouth": "\u1F444", + "/movers2fullwidth": "\u33A8", + "/moversfullwidth": "\u33A7", + "/moverssquare": "\u33A7", + "/moverssquaredsquare": "\u33A8", + "/movieCamera": "\u1F3A5", + "/moyai": "\u1F5FF", + "/mpafullwidth": "\u33AB", + "/mparen": "\u24A8", + "/mparenthesized": "\u24A8", + "/mpasquare": "\u33AB", + "/msfullwidth": "\u33B3", + "/mssquare": "\u33B3", + "/msuperior": "\uF6EF", + "/mturned": "\u026F", + "/mu": "\u00B5", + "/mu.math": "\u00B5", + "/mu1": "\u00B5", + "/muafullwidth": "\u3382", + "/muasquare": "\u3382", + "/muchgreater": "\u226B", + "/muchless": "\u226A", + "/mucirclekatakana": "\u32F0", + "/muffullwidth": "\u338C", + "/mufsquare": "\u338C", + "/mugfullwidth": "\u338D", + "/mugreek": "\u03BC", + "/mugsquare": "\u338D", + "/muhiragana": "\u3080", + "/mukatakana": "\u30E0", + "/mukatakanahalfwidth": "\uFF91", + "/mulfullwidth": "\u3395", + "/mulsquare": "\u3395", + "/multimap": "\u22B8", + "/multimapleft": "\u27DC", + "/multipleMusicalNotes": "\u1F3B6", + "/multiply": "\u00D7", + "/multiset": "\u228C", + "/multisetmultiplication": "\u228D", + "/multisetunion": "\u228E", + "/mum": "\uA773", + "/mumfullwidth": "\u339B", + "/mumsquare": "\u339B", + "/munach:hb": "\u05A3", + "/munahhebrew": "\u05A3", + "/munahlefthebrew": "\u05A3", + "/musfullwidth": "\u33B2", + "/mushroom": "\u1F344", + "/musicalKeyboard": "\u1F3B9", + "/musicalKeyboardJacks": "\u1F398", + "/musicalNote": "\u1F3B5", + "/musicalScore": "\u1F3BC", + "/musicalnote": "\u266A", + "/musicalnotedbl": "\u266B", + "/musicflat": "\u266D", + "/musicflatsign": "\u266D", + "/musicnatural": "\u266E", + "/musicsharp": "\u266F", + "/musicsharpsign": "\u266F", + "/mussquare": "\u33B2", + "/muvfullwidth": "\u33B6", + "/muvsquare": "\u33B6", + "/muwfullwidth": "\u33BC", + "/muwsquare": "\u33BC", + "/mvfullwidth": "\u33B7", + "/mvmegafullwidth": "\u33B9", + "/mvmegasquare": "\u33B9", + "/mvsquare": "\u33B7", + "/mwfullwidth": "\u33BD", + "/mwmegafullwidth": "\u33BF", + "/mwmegasquare": "\u33BF", + "/mwsquare": "\u33BD", + "/n": "\u006E", + "/n.inferior": "\u2099", + "/n.superior": "\u207F", + "/nabengali": "\u09A8", + "/nabla": "\u2207", + "/nacirclekatakana": "\u32E4", + "/nacute": "\u0144", + "/nadeva": "\u0928", + "/nafullwidth": "\u3381", + "/nagujarati": "\u0AA8", + "/nagurmukhi": "\u0A28", + "/nahiragana": "\u306A", + "/nailPolish": "\u1F485", + "/naira": "\u20A6", + "/nakatakana": "\u30CA", + "/nakatakanahalfwidth": "\uFF85", + "/nameBadge": "\u1F4DB", + "/nameideographiccircled": "\u3294", + "/nameideographicparen": "\u3234", + "/namurda": "\uA99F", + "/nand": "\u22BC", + "/nanosquare": "\u3328", + "/napostrophe": "\u0149", + "/narrownobreakspace": "\u202F", + "/nasquare": "\u3381", + "/nationalPark": "\u1F3DE", + "/nationaldigitshapes": "\u206E", + "/nbopomofo": "\u310B", + "/nbspace": "\u00A0", + "/ncaron": "\u0148", + "/ncedilla": "\u0146", + "/ncircle": "\u24DD", + "/ncircumflexbelow": "\u1E4B", + "/ncommaaccent": "\u0146", + "/ncurl": "\u0235", + "/ndescender": "\uA791", + "/ndot": "\u1E45", + "/ndotaccent": "\u1E45", + "/ndotbelow": "\u1E47", + "/necirclekatakana": "\u32E7", + "/necktie": "\u1F454", + "/negatedturnstiledblverticalbarright": "\u22AF", + "/nehiragana": "\u306D", + "/neirapproximatelynoractuallyequal": "\u2247", + "/neirasersetnorequalup": "\u2289", + "/neirasubsetnorequal": "\u2288", + "/neirgreaternorequal": "\u2271", + "/neirgreaternorequivalent": "\u2275", + "/neirgreaternorless": "\u2279", + "/neirlessnorequal": "\u2270", + "/neirlessnorequivalent": "\u2274", + "/neirlessnorgreater": "\u2278", + "/nekatakana": "\u30CD", + "/nekatakanahalfwidth": "\uFF88", + "/neptune": "\u2646", + "/neuter": "\u26B2", + "/neutralFace": "\u1F610", + "/newMoon": "\u1F311", + "/newMoonFace": "\u1F31A", + "/newsheqel": "\u20AA", + "/newsheqelsign": "\u20AA", + "/newspaper": "\u1F4F0", + "/newsquare": "\u1F195", + "/nextpage": "\u2398", + "/nffullwidth": "\u338B", + "/nfsquare": "\u338B", + "/ng.fina": "\uFBD4", + "/ng.init": "\uFBD5", + "/ng.isol": "\uFBD3", + "/ng.medi": "\uFBD6", + "/ngabengali": "\u0999", + "/ngadeva": "\u0919", + "/ngagujarati": "\u0A99", + "/ngagurmukhi": "\u0A19", + "/ngalelet": "\uA98A", + "/ngaleletraswadi": "\uA98B", + "/ngoeh": "\u06B1", + "/ngoeh.fina": "\uFB9B", + "/ngoeh.init": "\uFB9C", + "/ngoeh.isol": "\uFB9A", + "/ngoeh.medi": "\uFB9D", + "/ngonguthai": "\u0E07", + "/ngrave": "\u01F9", + "/ngsquare": "\u1F196", + "/nhiragana": "\u3093", + "/nhookleft": "\u0272", + "/nhookretroflex": "\u0273", + "/nicirclekatakana": "\u32E5", + "/nieunacirclekorean": "\u326F", + "/nieunaparenkorean": "\u320F", + "/nieuncieuckorean": "\u3135", + "/nieuncirclekorean": "\u3261", + "/nieunhieuhkorean": "\u3136", + "/nieunkorean": "\u3134", + "/nieunpansioskorean": "\u3168", + "/nieunparenkorean": "\u3201", + "/nieunsioskorean": "\u3167", + "/nieuntikeutkorean": "\u3166", + "/nightStars": "\u1F303", + "/nightideographiccircled": "\u32B0", + "/nihiragana": "\u306B", + "/nikatakana": "\u30CB", + "/nikatakanahalfwidth": "\uFF86", + "/nikhahitleftthai": "\uF899", + "/nikhahitthai": "\u0E4D", + "/nine": "\u0039", + "/nine.inferior": "\u2089", + "/nine.roman": "\u2168", + "/nine.romansmall": "\u2178", + "/nine.superior": "\u2079", + "/ninearabic": "\u0669", + "/ninebengali": "\u09EF", + "/ninecircle": "\u2468", + "/ninecircledbl": "\u24FD", + "/ninecircleinversesansserif": "\u2792", + "/ninecomma": "\u1F10A", + "/ninedeva": "\u096F", + "/ninefar": "\u06F9", + "/ninegujarati": "\u0AEF", + "/ninegurmukhi": "\u0A6F", + "/ninehackarabic": "\u0669", + "/ninehangzhou": "\u3029", + "/nineideographiccircled": "\u3288", + "/nineideographicparen": "\u3228", + "/nineinferior": "\u2089", + "/ninemonospace": "\uFF19", + "/nineoldstyle": "\uF739", + "/nineparen": "\u247C", + "/nineparenthesized": "\u247C", + "/nineperiod": "\u2490", + "/ninepersian": "\u06F9", + "/nineroman": "\u2178", + "/ninesuperior": "\u2079", + "/nineteencircle": "\u2472", + "/nineteencircleblack": "\u24F3", + "/nineteenparen": "\u2486", + "/nineteenparenthesized": "\u2486", + "/nineteenperiod": "\u249A", + "/ninethai": "\u0E59", + "/nj": "\u01CC", + "/njecyr": "\u045A", + "/njecyrillic": "\u045A", + "/njekomicyr": "\u050B", + "/nkatakana": "\u30F3", + "/nkatakanahalfwidth": "\uFF9D", + "/nlegrightlong": "\u019E", + "/nlinebelow": "\u1E49", + "/nlongrightleg": "\u019E", + "/nmbr:oneeighth": "\u215B", + "/nmbr:onefifth": "\u2155", + "/nmbr:onetenth": "\u2152", + "/nmfullwidth": "\u339A", + "/nmonospace": "\uFF4E", + "/nmsquare": "\u339A", + "/nnabengali": "\u09A3", + "/nnadeva": "\u0923", + "/nnagujarati": "\u0AA3", + "/nnagurmukhi": "\u0A23", + "/nnnadeva": "\u0929", + "/noBicycles": "\u1F6B3", + "/noEntrySign": "\u1F6AB", + "/noMobilePhones": "\u1F4F5", + "/noOneUnderEighteen": "\u1F51E", + "/noPedestrians": "\u1F6B7", + "/noPiracy": "\u1F572", + "/noSmoking": "\u1F6AD", + "/nobliquestroke": "\uA7A5", + "/nocirclekatakana": "\u32E8", + "/nodeascending": "\u260A", + "/nodedescending": "\u260B", + "/noentry": "\u26D4", + "/nohiragana": "\u306E", + "/nokatakana": "\u30CE", + "/nokatakanahalfwidth": "\uFF89", + "/nominaldigitshapes": "\u206F", + "/nonPotableWater": "\u1F6B1", + "/nonbreakinghyphen": "\u2011", + "/nonbreakingspace": "\u00A0", + "/nonenthai": "\u0E13", + "/nonuthai": "\u0E19", + "/noon": "\u0646", + "/noon.fina": "\uFEE6", + "/noon.init": "\uFEE7", + "/noon.init_alefmaksura.fina": "\uFC4F", + "/noon.init_hah.fina": "\uFC4C", + "/noon.init_hah.medi": "\uFCD3", + "/noon.init_hah.medi_meem.medi": "\uFD95", + "/noon.init_heh.medi": "\uFCD6", + "/noon.init_jeem.fina": "\uFC4B", + "/noon.init_jeem.medi": "\uFCD2", + "/noon.init_jeem.medi_hah.medi": "\uFDB8", + "/noon.init_jeem.medi_meem.medi": "\uFD98", + "/noon.init_khah.fina": "\uFC4D", + "/noon.init_khah.medi": "\uFCD4", + "/noon.init_meem.fina": "\uFC4E", + "/noon.init_meem.medi": "\uFCD5", + "/noon.init_yeh.fina": "\uFC50", + "/noon.isol": "\uFEE5", + "/noon.medi": "\uFEE8", + "/noon.medi_alefmaksura.fina": "\uFC8E", + "/noon.medi_hah.medi_alefmaksura.fina": "\uFD96", + "/noon.medi_hah.medi_yeh.fina": "\uFDB3", + "/noon.medi_heh.medi": "\uFCEF", + "/noon.medi_jeem.medi_alefmaksura.fina": "\uFD99", + "/noon.medi_jeem.medi_hah.fina": "\uFDBD", + "/noon.medi_jeem.medi_meem.fina": "\uFD97", + "/noon.medi_jeem.medi_yeh.fina": "\uFDC7", + "/noon.medi_meem.fina": "\uFC8C", + "/noon.medi_meem.medi": "\uFCEE", + "/noon.medi_meem.medi_alefmaksura.fina": "\uFD9B", + "/noon.medi_meem.medi_yeh.fina": "\uFD9A", + "/noon.medi_noon.fina": "\uFC8D", + "/noon.medi_reh.fina": "\uFC8A", + "/noon.medi_yeh.fina": "\uFC8F", + "/noon.medi_zain.fina": "\uFC8B", + "/noonSmallTah": "\u0768", + "/noonSmallV": "\u0769", + "/noonTwoDotsBelow": "\u0767", + "/noonabove": "\u06E8", + "/noonarabic": "\u0646", + "/noondotbelow": "\u06B9", + "/noonfinalarabic": "\uFEE6", + "/noonghunna": "\u06BA", + "/noonghunna.fina": "\uFB9F", + "/noonghunna.isol": "\uFB9E", + "/noonghunnaarabic": "\u06BA", + "/noonghunnafinalarabic": "\uFB9F", + "/noonhehinitialarabic": "\uFEE7", + "/nooninitialarabic": "\uFEE7", + "/noonjeeminitialarabic": "\uFCD2", + "/noonjeemisolatedarabic": "\uFC4B", + "/noonmedialarabic": "\uFEE8", + "/noonmeeminitialarabic": "\uFCD5", + "/noonmeemisolatedarabic": "\uFC4E", + "/noonnoonfinalarabic": "\uFC8D", + "/noonring": "\u06BC", + "/noonthreedotsabove": "\u06BD", + "/nor": "\u22BD", + "/nordicmark": "\u20BB", + "/normalfacrsemidirectproductleft": "\u22C9", + "/normalfacrsemidirectproductright": "\u22CA", + "/normalsubgroorequalup": "\u22B4", + "/normalsubgroup": "\u22B2", + "/northeastPointingAirplane": "\u1F6EA", + "/nose": "\u1F443", + "/notalmostequal": "\u2249", + "/notasersetup": "\u2285", + "/notasympticallyequal": "\u2244", + "/notcheckmark": "\u237B", + "/notchedLeftSemicircleThreeDots": "\u1F543", + "/notchedRightSemicircleThreeDots": "\u1F544", + "/notcontains": "\u220C", + "/note": "\u1F5C8", + "/notePad": "\u1F5CA", + "/notePage": "\u1F5C9", + "/notebook": "\u1F4D3", + "/notebookDecorativeCover": "\u1F4D4", + "/notelement": "\u2209", + "/notelementof": "\u2209", + "/notequal": "\u2260", + "/notequivalent": "\u226D", + "/notexistential": "\u2204", + "/notgreater": "\u226F", + "/notgreaternorequal": "\u2271", + "/notgreaternorless": "\u2279", + "/notidentical": "\u2262", + "/notless": "\u226E", + "/notlessnorequal": "\u2270", + "/notnormalsubgroorequalup": "\u22EC", + "/notnormalsubgroup": "\u22EA", + "/notparallel": "\u2226", + "/notprecedes": "\u2280", + "/notsignturned": "\u2319", + "/notsquareimageorequal": "\u22E2", + "/notsquareoriginalorequal": "\u22E3", + "/notsubset": "\u2284", + "/notsucceeds": "\u2281", + "/notsuperset": "\u2285", + "/nottilde": "\u2241", + "/nottosquare": "\u3329", + "/nottrue": "\u22AD", + "/novembertelegraph": "\u32CA", + "/nowarmenian": "\u0576", + "/nparen": "\u24A9", + "/nparenthesized": "\u24A9", + "/nretroflex": "\u0273", + "/nsfullwidth": "\u33B1", + "/nssquare": "\u33B1", + "/nsuperior": "\u207F", + "/ntilde": "\u00F1", + "/nu": "\u03BD", + "/nucirclekatakana": "\u32E6", + "/nuhiragana": "\u306C", + "/nukatakana": "\u30CC", + "/nukatakanahalfwidth": "\uFF87", + "/nuktabengali": "\u09BC", + "/nuktadeva": "\u093C", + "/nuktagujarati": "\u0ABC", + "/nuktagurmukhi": "\u0A3C", + "/num": "\uA774", + "/numbermarkabove": "\u0605", + "/numbersign": "\u0023", + "/numbersignmonospace": "\uFF03", + "/numbersignsmall": "\uFE5F", + "/numeralsign": "\u0374", + "/numeralsigngreek": "\u0374", + "/numeralsignlowergreek": "\u0375", + "/numero": "\u2116", + "/nun": "\u05E0", + "/nun:hb": "\u05E0", + "/nunHafukha:hb": "\u05C6", + "/nundagesh": "\uFB40", + "/nundageshhebrew": "\uFB40", + "/nunhebrew": "\u05E0", + "/nunwithdagesh:hb": "\uFB40", + "/nutAndBolt": "\u1F529", + "/nvfullwidth": "\u33B5", + "/nvsquare": "\u33B5", + "/nwfullwidth": "\u33BB", + "/nwsquare": "\u33BB", + "/nyabengali": "\u099E", + "/nyadeva": "\u091E", + "/nyagujarati": "\u0A9E", + "/nyagurmukhi": "\u0A1E", + "/nyamurda": "\uA998", + "/nyeh": "\u0683", + "/nyeh.fina": "\uFB77", + "/nyeh.init": "\uFB78", + "/nyeh.isol": "\uFB76", + "/nyeh.medi": "\uFB79", + "/o": "\u006F", + "/o.inferior": "\u2092", + "/oacute": "\u00F3", + "/oangthai": "\u0E2D", + "/obarcyr": "\u04E9", + "/obardieresiscyr": "\u04EB", + "/obarred": "\u0275", + "/obarredcyrillic": "\u04E9", + "/obarreddieresiscyrillic": "\u04EB", + "/obelosdotted": "\u2E13", + "/obengali": "\u0993", + "/obopomofo": "\u311B", + "/obreve": "\u014F", + "/observereye": "\u23FF", + "/ocandradeva": "\u0911", + "/ocandragujarati": "\u0A91", + "/ocandravowelsigndeva": "\u0949", + "/ocandravowelsigngujarati": "\u0AC9", + "/ocaron": "\u01D2", + "/ocircle": "\u24DE", + "/ocirclekatakana": "\u32D4", + "/ocircumflex": "\u00F4", + "/ocircumflexacute": "\u1ED1", + "/ocircumflexdotbelow": "\u1ED9", + "/ocircumflexgrave": "\u1ED3", + "/ocircumflexhoi": "\u1ED5", + "/ocircumflexhookabove": "\u1ED5", + "/ocircumflextilde": "\u1ED7", + "/ocr:bowtie": "\u2445", + "/ocr:dash": "\u2448", + "/octagonalSign": "\u1F6D1", + "/octobertelegraph": "\u32C9", + "/octopus": "\u1F419", + "/ocyr": "\u043E", + "/ocyrillic": "\u043E", + "/odblacute": "\u0151", + "/odblgrave": "\u020D", + "/oden": "\u1F362", + "/odeva": "\u0913", + "/odieresis": "\u00F6", + "/odieresiscyr": "\u04E7", + "/odieresiscyrillic": "\u04E7", + "/odieresismacron": "\u022B", + "/odot": "\u022F", + "/odotbelow": "\u1ECD", + "/odotmacron": "\u0231", + "/oe": "\u0153", + "/oe.fina": "\uFBDA", + "/oe.isol": "\uFBD9", + "/oekirghiz": "\u06C5", + "/oekirghiz.fina": "\uFBE1", + "/oekirghiz.isol": "\uFBE0", + "/oekorean": "\u315A", + "/officeBuilding": "\u1F3E2", + "/ogonek": "\u02DB", + "/ogonekcmb": "\u0328", + "/ograve": "\u00F2", + "/ogravedbl": "\u020D", + "/ogujarati": "\u0A93", + "/oharmenian": "\u0585", + "/ohiragana": "\u304A", + "/ohm": "\u2126", + "/ohminverted": "\u2127", + "/ohoi": "\u1ECF", + "/ohookabove": "\u1ECF", + "/ohorn": "\u01A1", + "/ohornacute": "\u1EDB", + "/ohorndotbelow": "\u1EE3", + "/ohorngrave": "\u1EDD", + "/ohornhoi": "\u1EDF", + "/ohornhookabove": "\u1EDF", + "/ohorntilde": "\u1EE1", + "/ohungarumlaut": "\u0151", + "/ohuparen": "\u321E", + "/oi": "\u01A3", + "/oilDrum": "\u1F6E2", + "/oinvertedbreve": "\u020F", + "/ojeonparen": "\u321D", + "/okHandSign": "\u1F44C", + "/okatakana": "\u30AA", + "/okatakanahalfwidth": "\uFF75", + "/okorean": "\u3157", + "/oksquare": "\u1F197", + "/oldKey": "\u1F5DD", + "/oldPersonalComputer": "\u1F5B3", + "/olderMan": "\u1F474", + "/olderWoman": "\u1F475", + "/ole:hb": "\u05AB", + "/olehebrew": "\u05AB", + "/oloop": "\uA74D", + "/olowringinside": "\u2C7A", + "/omacron": "\u014D", + "/omacronacute": "\u1E53", + "/omacrongrave": "\u1E51", + "/omdeva": "\u0950", + "/omega": "\u03C9", + "/omega1": "\u03D6", + "/omegaacute": "\u1F7D", + "/omegaacuteiotasub": "\u1FF4", + "/omegaasper": "\u1F61", + "/omegaasperacute": "\u1F65", + "/omegaasperacuteiotasub": "\u1FA5", + "/omegaaspergrave": "\u1F63", + "/omegaaspergraveiotasub": "\u1FA3", + "/omegaasperiotasub": "\u1FA1", + "/omegaaspertilde": "\u1F67", + "/omegaaspertildeiotasub": "\u1FA7", + "/omegaclosed": "\u0277", + "/omegacyr": "\u0461", + "/omegacyrillic": "\u0461", + "/omegafunc": "\u2375", + "/omegagrave": "\u1F7C", + "/omegagraveiotasub": "\u1FF2", + "/omegaiotasub": "\u1FF3", + "/omegalatinclosed": "\u0277", + "/omegalenis": "\u1F60", + "/omegalenisacute": "\u1F64", + "/omegalenisacuteiotasub": "\u1FA4", + "/omegalenisgrave": "\u1F62", + "/omegalenisgraveiotasub": "\u1FA2", + "/omegalenisiotasub": "\u1FA0", + "/omegalenistilde": "\u1F66", + "/omegalenistildeiotasub": "\u1FA6", + "/omegaroundcyr": "\u047B", + "/omegaroundcyrillic": "\u047B", + "/omegatilde": "\u1FF6", + "/omegatildeiotasub": "\u1FF7", + "/omegatitlocyr": "\u047D", + "/omegatitlocyrillic": "\u047D", + "/omegatonos": "\u03CE", + "/omegaunderlinefunc": "\u2379", + "/omgujarati": "\u0AD0", + "/omicron": "\u03BF", + "/omicronacute": "\u1F79", + "/omicronasper": "\u1F41", + "/omicronasperacute": "\u1F45", + "/omicronaspergrave": "\u1F43", + "/omicrongrave": "\u1F78", + "/omicronlenis": "\u1F40", + "/omicronlenisacute": "\u1F44", + "/omicronlenisgrave": "\u1F42", + "/omicrontonos": "\u03CC", + "/omonospace": "\uFF4F", + "/onExclamationMarkLeftRightArrowAbove": "\u1F51B", + "/oncomingAutomobile": "\u1F698", + "/oncomingBus": "\u1F68D", + "/oncomingFireEngine": "\u1F6F1", + "/oncomingPoliceCar": "\u1F694", + "/oncomingTaxi": "\u1F696", + "/one": "\u0031", + "/one.inferior": "\u2081", + "/one.roman": "\u2160", + "/one.romansmall": "\u2170", + "/oneButtonMouse": "\u1F5AF", + "/onearabic": "\u0661", + "/onebengali": "\u09E7", + "/onecircle": "\u2460", + "/onecircledbl": "\u24F5", + "/onecircleinversesansserif": "\u278A", + "/onecomma": "\u1F102", + "/onedeva": "\u0967", + "/onedotenleader": "\u2024", + "/onedotovertwodots": "\u2E2B", + "/oneeighth": "\u215B", + "/onefar": "\u06F1", + "/onefitted": "\uF6DC", + "/onefraction": "\u215F", + "/onegujarati": "\u0AE7", + "/onegurmukhi": "\u0A67", + "/onehackarabic": "\u0661", + "/onehalf": "\u00BD", + "/onehangzhou": "\u3021", + "/onehundred.roman": "\u216D", + "/onehundred.romansmall": "\u217D", + "/onehundredthousand.roman": "\u2188", + "/onehundredtwentypsquare": "\u1F1A4", + "/oneideographiccircled": "\u3280", + "/oneideographicparen": "\u3220", + "/oneinferior": "\u2081", + "/onemonospace": "\uFF11", + "/oneninth": "\u2151", + "/onenumeratorbengali": "\u09F4", + "/oneoldstyle": "\uF731", + "/oneparen": "\u2474", + "/oneparenthesized": "\u2474", + "/oneperiod": "\u2488", + "/onepersian": "\u06F1", + "/onequarter": "\u00BC", + "/oneroman": "\u2170", + "/oneseventh": "\u2150", + "/onesixth": "\u2159", + "/onesuperior": "\u00B9", + "/onethai": "\u0E51", + "/onethird": "\u2153", + "/onethousand.roman": "\u216F", + "/onethousand.romansmall": "\u217F", + "/onethousandcd.roman": "\u2180", + "/onsusquare": "\u3309", + "/oo": "\uA74F", + "/oogonek": "\u01EB", + "/oogonekmacron": "\u01ED", + "/oogurmukhi": "\u0A13", + "/oomatragurmukhi": "\u0A4B", + "/oomusquare": "\u330A", + "/oopen": "\u0254", + "/oparen": "\u24AA", + "/oparenthesized": "\u24AA", + "/openBook": "\u1F4D6", + "/openFileFolder": "\u1F4C2", + "/openFolder": "\u1F5C1", + "/openHandsSign": "\u1F450", + "/openLock": "\u1F513", + "/openMailboxLoweredFlag": "\u1F4ED", + "/openMailboxRaisedFlag": "\u1F4EC", + "/openbullet": "\u25E6", + "/openheadarrowleft": "\u21FD", + "/openheadarrowleftright": "\u21FF", + "/openheadarrowright": "\u21FE", + "/opensubset": "\u27C3", + "/opensuperset": "\u27C4", + "/ophiuchus": "\u26CE", + "/opposition": "\u260D", + "/opticalDisc": "\u1F4BF", + "/opticalDiscIcon": "\u1F5B8", + "/option": "\u2325", + "/orangeBook": "\u1F4D9", + "/ordfeminine": "\u00AA", + "/ordmasculine": "\u00BA", + "/ordotinside": "\u27C7", + "/original": "\u22B6", + "/ornateleftparenthesis": "\uFD3E", + "/ornaterightparenthesis": "\uFD3F", + "/orthodoxcross": "\u2626", + "/orthogonal": "\u221F", + "/orya:a": "\u0B05", + "/orya:aa": "\u0B06", + "/orya:aasign": "\u0B3E", + "/orya:ai": "\u0B10", + "/orya:ailengthmark": "\u0B56", + "/orya:aisign": "\u0B48", + "/orya:anusvara": "\u0B02", + "/orya:au": "\u0B14", + "/orya:aulengthmark": "\u0B57", + "/orya:ausign": "\u0B4C", + "/orya:avagraha": "\u0B3D", + "/orya:ba": "\u0B2C", + "/orya:bha": "\u0B2D", + "/orya:ca": "\u0B1A", + "/orya:candrabindu": "\u0B01", + "/orya:cha": "\u0B1B", + "/orya:da": "\u0B26", + "/orya:dda": "\u0B21", + "/orya:ddha": "\u0B22", + "/orya:dha": "\u0B27", + "/orya:e": "\u0B0F", + "/orya:eight": "\u0B6E", + "/orya:esign": "\u0B47", + "/orya:five": "\u0B6B", + "/orya:four": "\u0B6A", + "/orya:fractiononeeighth": "\u0B76", + "/orya:fractiononehalf": "\u0B73", + "/orya:fractiononequarter": "\u0B72", + "/orya:fractiononesixteenth": "\u0B75", + "/orya:fractionthreequarters": "\u0B74", + "/orya:fractionthreesixteenths": "\u0B77", + "/orya:ga": "\u0B17", + "/orya:gha": "\u0B18", + "/orya:ha": "\u0B39", + "/orya:i": "\u0B07", + "/orya:ii": "\u0B08", + "/orya:iisign": "\u0B40", + "/orya:isign": "\u0B3F", + "/orya:isshar": "\u0B70", + "/orya:ja": "\u0B1C", + "/orya:jha": "\u0B1D", + "/orya:ka": "\u0B15", + "/orya:kha": "\u0B16", + "/orya:la": "\u0B32", + "/orya:lla": "\u0B33", + "/orya:llvocal": "\u0B61", + "/orya:llvocalsign": "\u0B63", + "/orya:lvocal": "\u0B0C", + "/orya:lvocalsign": "\u0B62", + "/orya:ma": "\u0B2E", + "/orya:na": "\u0B28", + "/orya:nga": "\u0B19", + "/orya:nine": "\u0B6F", + "/orya:nna": "\u0B23", + "/orya:nukta": "\u0B3C", + "/orya:nya": "\u0B1E", + "/orya:o": "\u0B13", + "/orya:one": "\u0B67", + "/orya:osign": "\u0B4B", + "/orya:pa": "\u0B2A", + "/orya:pha": "\u0B2B", + "/orya:ra": "\u0B30", + "/orya:rha": "\u0B5D", + "/orya:rra": "\u0B5C", + "/orya:rrvocal": "\u0B60", + "/orya:rrvocalsign": "\u0B44", + "/orya:rvocal": "\u0B0B", + "/orya:rvocalsign": "\u0B43", + "/orya:sa": "\u0B38", + "/orya:seven": "\u0B6D", + "/orya:sha": "\u0B36", + "/orya:six": "\u0B6C", + "/orya:ssa": "\u0B37", + "/orya:ta": "\u0B24", + "/orya:tha": "\u0B25", + "/orya:three": "\u0B69", + "/orya:tta": "\u0B1F", + "/orya:ttha": "\u0B20", + "/orya:two": "\u0B68", + "/orya:u": "\u0B09", + "/orya:usign": "\u0B41", + "/orya:uu": "\u0B0A", + "/orya:uusign": "\u0B42", + "/orya:va": "\u0B35", + "/orya:virama": "\u0B4D", + "/orya:visarga": "\u0B03", + "/orya:wa": "\u0B71", + "/orya:ya": "\u0B2F", + "/orya:yya": "\u0B5F", + "/orya:zero": "\u0B66", + "/oscript": "\u2134", + "/oshortdeva": "\u0912", + "/oshortvowelsigndeva": "\u094A", + "/oslash": "\u00F8", + "/oslashacute": "\u01FF", + "/osmallhiragana": "\u3049", + "/osmallkatakana": "\u30A9", + "/osmallkatakanahalfwidth": "\uFF6B", + "/ostroke": "\uA74B", + "/ostrokeacute": "\u01FF", + "/osuperior": "\uF6F0", + "/otcyr": "\u047F", + "/otcyrillic": "\u047F", + "/otilde": "\u00F5", + "/otildeacute": "\u1E4D", + "/otildedieresis": "\u1E4F", + "/otildemacron": "\u022D", + "/ou": "\u0223", + "/oubopomofo": "\u3121", + "/ounce": "\u2125", + "/outboxTray": "\u1F4E4", + "/outerjoinfull": "\u27D7", + "/outerjoinleft": "\u27D5", + "/outerjoinright": "\u27D6", + "/outputpassiveup": "\u2392", + "/overlap": "\u1F5D7", + "/overline": "\u203E", + "/overlinecenterline": "\uFE4A", + "/overlinecmb": "\u0305", + "/overlinedashed": "\uFE49", + "/overlinedblwavy": "\uFE4C", + "/overlinewavy": "\uFE4B", + "/overscore": "\u00AF", + "/ovfullwidth": "\u3375", + "/ovowelsignbengali": "\u09CB", + "/ovowelsigndeva": "\u094B", + "/ovowelsigngujarati": "\u0ACB", + "/ox": "\u1F402", + "/p": "\u0070", + "/p.inferior": "\u209A", + "/paampsfullwidth": "\u3380", + "/paampssquare": "\u3380", + "/paasentosquare": "\u332B", + "/paatusquare": "\u332C", + "/pabengali": "\u09AA", + "/pacerek": "\uA989", + "/package": "\u1F4E6", + "/pacute": "\u1E55", + "/padeva": "\u092A", + "/pafullwidth": "\u33A9", + "/page": "\u1F5CF", + "/pageCircledText": "\u1F5DF", + "/pageCurl": "\u1F4C3", + "/pageFacingUp": "\u1F4C4", + "/pagedown": "\u21DF", + "/pager": "\u1F4DF", + "/pages": "\u1F5D0", + "/pageup": "\u21DE", + "/pagoda": "\u1F6D4", + "/pagujarati": "\u0AAA", + "/pagurmukhi": "\u0A2A", + "/pahiragana": "\u3071", + "/paiyannoithai": "\u0E2F", + "/pakatakana": "\u30D1", + "/palatalizationcyrilliccmb": "\u0484", + "/palatcmbcyr": "\u0484", + "/pallas": "\u26B4", + "/palmTree": "\u1F334", + "/palmbranch": "\u2E19", + "/palochkacyr": "\u04CF", + "/palochkacyrillic": "\u04C0", + "/pamurda": "\uA9A6", + "/pandaFace": "\u1F43C", + "/pangkatpada": "\uA9C7", + "/pangkon": "\uA9C0", + "/pangrangkep": "\uA9CF", + "/pansioskorean": "\u317F", + "/panyangga": "\uA980", + "/paperclip": "\u1F4CE", + "/paragraph": "\u00B6", + "/paragraphos": "\u2E0F", + "/paragraphosforked": "\u2E10", + "/paragraphosforkedreversed": "\u2E11", + "/paragraphseparator": "\u2029", + "/parallel": "\u2225", + "/parallelogramblack": "\u25B0", + "/parallelogramwhite": "\u25B1", + "/parenbottom": "\u23DD", + "/parendblleft": "\u2E28", + "/parendblright": "\u2E29", + "/parenextensionleft": "\u239C", + "/parenextensionright": "\u239F", + "/parenflatleft": "\u27EE", + "/parenflatright": "\u27EF", + "/parenhookupleft": "\u239B", + "/parenhookupright": "\u239E", + "/parenleft": "\u0028", + "/parenleft.inferior": "\u208D", + "/parenleft.superior": "\u207D", + "/parenleftaltonearabic": "\uFD3E", + "/parenleftbt": "\uF8ED", + "/parenleftex": "\uF8EC", + "/parenleftinferior": "\u208D", + "/parenleftmonospace": "\uFF08", + "/parenleftsmall": "\uFE59", + "/parenleftsuperior": "\u207D", + "/parenlefttp": "\uF8EB", + "/parenleftvertical": "\uFE35", + "/parenlowerhookleft": "\u239D", + "/parenlowerhookright": "\u23A0", + "/parenright": "\u0029", + "/parenright.inferior": "\u208E", + "/parenright.superior": "\u207E", + "/parenrightaltonearabic": "\uFD3F", + "/parenrightbt": "\uF8F8", + "/parenrightex": "\uF8F7", + "/parenrightinferior": "\u208E", + "/parenrightmonospace": "\uFF09", + "/parenrightsmall": "\uFE5A", + "/parenrightsuperior": "\u207E", + "/parenrighttp": "\uF8F6", + "/parenrightvertical": "\uFE36", + "/parentop": "\u23DC", + "/partalternationmark": "\u303D", + "/partialdiff": "\u2202", + "/partnership": "\u3250", + "/partyPopper": "\u1F389", + "/paseq:hb": "\u05C0", + "/paseqhebrew": "\u05C0", + "/pashta:hb": "\u0599", + "/pashtahebrew": "\u0599", + "/pasquare": "\u33A9", + "/passengerShip": "\u1F6F3", + "/passivedown": "\u2391", + "/passportControl": "\u1F6C2", + "/patah": "\u05B7", + "/patah11": "\u05B7", + "/patah1d": "\u05B7", + "/patah2a": "\u05B7", + "/patah:hb": "\u05B7", + "/patahhebrew": "\u05B7", + "/patahnarrowhebrew": "\u05B7", + "/patahquarterhebrew": "\u05B7", + "/patahwidehebrew": "\u05B7", + "/pawPrints": "\u1F43E", + "/pawnblack": "\u265F", + "/pawnwhite": "\u2659", + "/pazer:hb": "\u05A1", + "/pazerhebrew": "\u05A1", + "/pbopomofo": "\u3106", + "/pcfullwidth": "\u3376", + "/pcircle": "\u24DF", + "/pdot": "\u1E57", + "/pdotaccent": "\u1E57", + "/pe": "\u05E4", + "/pe:hb": "\u05E4", + "/peace": "\u262E", + "/peach": "\u1F351", + "/pear": "\u1F350", + "/pecyr": "\u043F", + "/pecyrillic": "\u043F", + "/pedagesh": "\uFB44", + "/pedageshhebrew": "\uFB44", + "/pedestrian": "\u1F6B6", + "/peezisquare": "\u333B", + "/pefinaldageshhebrew": "\uFB43", + "/peh.fina": "\uFB57", + "/peh.init": "\uFB58", + "/peh.isol": "\uFB56", + "/peh.medi": "\uFB59", + "/peharabic": "\u067E", + "/peharmenian": "\u057A", + "/pehebrew": "\u05E4", + "/peheh": "\u06A6", + "/peheh.fina": "\uFB6F", + "/peheh.init": "\uFB70", + "/peheh.isol": "\uFB6E", + "/peheh.medi": "\uFB71", + "/pehfinalarabic": "\uFB57", + "/pehinitialarabic": "\uFB58", + "/pehiragana": "\u307A", + "/pehmedialarabic": "\uFB59", + "/pehookcyr": "\u04A7", + "/pekatakana": "\u30DA", + "/pemiddlehookcyrillic": "\u04A7", + "/penOverStampedEnvelope": "\u1F586", + "/pengkalconsonant": "\uA9BE", + "/penguin": "\u1F427", + "/penihisquare": "\u3338", + "/pensiveFace": "\u1F614", + "/pensusquare": "\u333A", + "/pentagram": "\u26E4", + "/pentasememetrical": "\u23D9", + "/pepetvowel": "\uA9BC", + "/per": "\u214C", + "/perafehebrew": "\uFB4E", + "/percent": "\u0025", + "/percentarabic": "\u066A", + "/percentmonospace": "\uFF05", + "/percentsmall": "\uFE6A", + "/percussivebidental": "\u02AD", + "/percussivebilabial": "\u02AC", + "/performingArts": "\u1F3AD", + "/period": "\u002E", + "/periodarmenian": "\u0589", + "/periodcentered": "\u00B7", + "/periodhalfwidth": "\uFF61", + "/periodinferior": "\uF6E7", + "/periodmonospace": "\uFF0E", + "/periodsmall": "\uFE52", + "/periodsuperior": "\uF6E8", + "/periodurdu": "\u06D4", + "/perispomenigreekcmb": "\u0342", + "/permanentpaper": "\u267E", + "/permille": "\u0609", + "/perpendicular": "\u22A5", + "/perseveringFace": "\u1F623", + "/personBlondHair": "\u1F471", + "/personBowingDeeply": "\u1F647", + "/personFrowning": "\u1F64D", + "/personRaisingBothHandsInCelebration": "\u1F64C", + "/personWithFoldedHands": "\u1F64F", + "/personWithPoutingFace": "\u1F64E", + "/personalComputer": "\u1F4BB", + "/personball": "\u26F9", + "/perspective": "\u2306", + "/pertenthousandsign": "\u2031", + "/perthousand": "\u2030", + "/peseta": "\u20A7", + "/peso": "\u20B1", + "/pesosquare": "\u3337", + "/petailcyr": "\u0525", + "/pewithdagesh:hb": "\uFB44", + "/pewithrafe:hb": "\uFB4E", + "/pffullwidth": "\u338A", + "/pflourish": "\uA753", + "/pfsquare": "\u338A", + "/phabengali": "\u09AB", + "/phadeva": "\u092B", + "/phagujarati": "\u0AAB", + "/phagurmukhi": "\u0A2B", + "/pharyngealvoicedfricative": "\u0295", + "/phfullwidth": "\u33D7", + "/phi": "\u03C6", + "/phi.math": "\u03D5", + "/phi1": "\u03D5", + "/phieuphacirclekorean": "\u327A", + "/phieuphaparenkorean": "\u321A", + "/phieuphcirclekorean": "\u326C", + "/phieuphkorean": "\u314D", + "/phieuphparenkorean": "\u320C", + "/philatin": "\u0278", + "/phinthuthai": "\u0E3A", + "/phisymbolgreek": "\u03D5", + "/phitailless": "\u2C77", + "/phon:AEsmall": "\u1D01", + "/phon:Aemod": "\u1D2D", + "/phon:Amod": "\u1D2C", + "/phon:Asmall": "\u1D00", + "/phon:Bbarmod": "\u1D2F", + "/phon:Bbarsmall": "\u1D03", + "/phon:Bmod": "\u1D2E", + "/phon:Csmall": "\u1D04", + "/phon:Dmod": "\u1D30", + "/phon:Dsmall": "\u1D05", + "/phon:ENcyrmod": "\u1D78", + "/phon:Elsmallcyr": "\u1D2B", + "/phon:Emod": "\u1D31", + "/phon:Ereversedmod": "\u1D32", + "/phon:Esmall": "\u1D07", + "/phon:Ethsmall": "\u1D06", + "/phon:Ezhsmall": "\u1D23", + "/phon:Gmod": "\u1D33", + "/phon:Hmod": "\u1D34", + "/phon:Imod": "\u1D35", + "/phon:Ismallmod": "\u1DA6", + "/phon:Ismallstroke": "\u1D7B", + "/phon:Istrokesmallmod": "\u1DA7", + "/phon:Jmod": "\u1D36", + "/phon:Jsmall": "\u1D0A", + "/phon:Kmod": "\u1D37", + "/phon:Ksmall": "\u1D0B", + "/phon:Lmod": "\u1D38", + "/phon:Lsmallmod": "\u1DAB", + "/phon:Lsmallstroke": "\u1D0C", + "/phon:Mmod": "\u1D39", + "/phon:Msmall": "\u1D0D", + "/phon:Nmod": "\u1D3A", + "/phon:Nreversedmod": "\u1D3B", + "/phon:Nsmallmod": "\u1DB0", + "/phon:Nsmallreversed": "\u1D0E", + "/phon:OUsmall": "\u1D15", + "/phon:Omod": "\u1D3C", + "/phon:Oopensmall": "\u1D10", + "/phon:Osmall": "\u1D0F", + "/phon:Oumod": "\u1D3D", + "/phon:Pmod": "\u1D3E", + "/phon:Psmall": "\u1D18", + "/phon:Rmod": "\u1D3F", + "/phon:Rsmallreversed": "\u1D19", + "/phon:Rsmallturned": "\u1D1A", + "/phon:Tmod": "\u1D40", + "/phon:Tsmall": "\u1D1B", + "/phon:Umod": "\u1D41", + "/phon:Usmall": "\u1D1C", + "/phon:Usmallmod": "\u1DB8", + "/phon:Usmallstroke": "\u1D7E", + "/phon:Vsmall": "\u1D20", + "/phon:Wmod": "\u1D42", + "/phon:Wsmall": "\u1D21", + "/phon:Zsmall": "\u1D22", + "/phon:aeturned": "\u1D02", + "/phon:aeturnedmod": "\u1D46", + "/phon:ain": "\u1D25", + "/phon:ainmod": "\u1D5C", + "/phon:alphamod": "\u1D45", + "/phon:alpharetroflexhook": "\u1D90", + "/phon:alphaturnedmod": "\u1D9B", + "/phon:amod": "\u1D43", + "/phon:aretroflexhook": "\u1D8F", + "/phon:aturnedmod": "\u1D44", + "/phon:betamod": "\u1D5D", + "/phon:bmiddletilde": "\u1D6C", + "/phon:bmod": "\u1D47", + "/phon:bpalatalhook": "\u1D80", + "/phon:ccurlmod": "\u1D9D", + "/phon:chimod": "\u1D61", + "/phon:cmod": "\u1D9C", + "/phon:deltamod": "\u1D5F", + "/phon:dhooktail": "\u1D91", + "/phon:dmiddletilde": "\u1D6D", + "/phon:dmod": "\u1D48", + "/phon:dotlessjstrokemod": "\u1DA1", + "/phon:dpalatalhook": "\u1D81", + "/phon:emod": "\u1D49", + "/phon:engmod": "\u1D51", + "/phon:eopenmod": "\u1D4B", + "/phon:eopenretroflexhook": "\u1D93", + "/phon:eopenreversedmod": "\u1D9F", + "/phon:eopenreversedretroflexhook": "\u1D94", + "/phon:eopenturned": "\u1D08", + "/phon:eopenturnedmod": "\u1D4C", + "/phon:eretroflexhook": "\u1D92", + "/phon:eshmod": "\u1DB4", + "/phon:eshpalatalhook": "\u1D8B", + "/phon:eshretroflexhook": "\u1D98", + "/phon:ethmod": "\u1D9E", + "/phon:ezhmod": "\u1DBE", + "/phon:ezhretroflexhook": "\u1D9A", + "/phon:fmiddletilde": "\u1D6E", + "/phon:fmod": "\u1DA0", + "/phon:fpalatalhook": "\u1D82", + "/phon:ginsular": "\u1D79", + "/phon:gmod": "\u1D4D", + "/phon:gpalatalhook": "\u1D83", + "/phon:gr:Gammasmall": "\u1D26", + "/phon:gr:Lambdasmall": "\u1D27", + "/phon:gr:Pismall": "\u1D28", + "/phon:gr:Psismall": "\u1D2A", + "/phon:gr:RsmallHO": "\u1D29", + "/phon:gr:betasubscript": "\u1D66", + "/phon:gr:chisubscript": "\u1D6A", + "/phon:gr:gammamod": "\u1D5E", + "/phon:gr:gammasubscript": "\u1D67", + "/phon:gr:phimod": "\u1D60", + "/phon:gr:phisubscript": "\u1D69", + "/phon:gr:rhosubscript": "\u1D68", + "/phon:gscriptmod": "\u1DA2", + "/phon:gturned": "\u1D77", + "/phon:hturnedmod": "\u1DA3", + "/phon:iotamod": "\u1DA5", + "/phon:iotastroke": "\u1D7C", + "/phon:iretroflexhook": "\u1D96", + "/phon:istrokemod": "\u1DA4", + "/phon:isubscript": "\u1D62", + "/phon:iturned": "\u1D09", + "/phon:iturnedmod": "\u1D4E", + "/phon:jcrossedtailmod": "\u1DA8", + "/phon:kmod": "\u1D4F", + "/phon:kpalatalhook": "\u1D84", + "/phon:lpalatalhook": "\u1D85", + "/phon:lpalatalhookmod": "\u1DAA", + "/phon:lretroflexhookmod": "\u1DA9", + "/phon:mhookmod": "\u1DAC", + "/phon:mlonglegturnedmod": "\u1DAD", + "/phon:mmiddletilde": "\u1D6F", + "/phon:mmod": "\u1D50", + "/phon:mpalatalhook": "\u1D86", + "/phon:mturnedmod": "\u1D5A", + "/phon:mturnedsideways": "\u1D1F", + "/phon:nlefthookmod": "\u1DAE", + "/phon:nmiddletilde": "\u1D70", + "/phon:npalatalhook": "\u1D87", + "/phon:nretroflexhookmod": "\u1DAF", + "/phon:obarmod": "\u1DB1", + "/phon:obottomhalf": "\u1D17", + "/phon:obottomhalfmod": "\u1D55", + "/phon:oeturned": "\u1D14", + "/phon:omod": "\u1D52", + "/phon:oopenmod": "\u1D53", + "/phon:oopenretroflexhook": "\u1D97", + "/phon:oopensideways": "\u1D12", + "/phon:osideways": "\u1D11", + "/phon:ostrokesideways": "\u1D13", + "/phon:otophalf": "\u1D16", + "/phon:otophalfmod": "\u1D54", + "/phon:phimod": "\u1DB2", + "/phon:pmiddletilde": "\u1D71", + "/phon:pmod": "\u1D56", + "/phon:ppalatalhook": "\u1D88", + "/phon:pstroke": "\u1D7D", + "/phon:rfishmiddletilde": "\u1D73", + "/phon:rmiddletilde": "\u1D72", + "/phon:rpalatalhook": "\u1D89", + "/phon:rsubscript": "\u1D63", + "/phon:schwamod": "\u1D4A", + "/phon:schwaretroflexhook": "\u1D95", + "/phon:shookmod": "\u1DB3", + "/phon:smiddletilde": "\u1D74", + "/phon:spalatalhook": "\u1D8A", + "/phon:spirantvoicedlaryngeal": "\u1D24", + "/phon:thetamod": "\u1DBF", + "/phon:thstrike": "\u1D7A", + "/phon:tmiddletilde": "\u1D75", + "/phon:tmod": "\u1D57", + "/phon:tpalatalhookmod": "\u1DB5", + "/phon:ubarmod": "\u1DB6", + "/phon:ue": "\u1D6B", + "/phon:umod": "\u1D58", + "/phon:upsilonmod": "\u1DB7", + "/phon:upsilonstroke": "\u1D7F", + "/phon:uretroflexhook": "\u1D99", + "/phon:usideways": "\u1D1D", + "/phon:usidewaysdieresised": "\u1D1E", + "/phon:usidewaysmod": "\u1D59", + "/phon:usubscript": "\u1D64", + "/phon:vhookmod": "\u1DB9", + "/phon:vmod": "\u1D5B", + "/phon:vpalatalhook": "\u1D8C", + "/phon:vsubscript": "\u1D65", + "/phon:vturnedmod": "\u1DBA", + "/phon:xpalatalhook": "\u1D8D", + "/phon:zcurlmod": "\u1DBD", + "/phon:zmiddletilde": "\u1D76", + "/phon:zmod": "\u1DBB", + "/phon:zpalatalhook": "\u1D8E", + "/phon:zretroflexhookmod": "\u1DBC", + "/phook": "\u01A5", + "/phophanthai": "\u0E1E", + "/phophungthai": "\u0E1C", + "/phosamphaothai": "\u0E20", + "/pi": "\u03C0", + "/pi.math": "\u03D6", + "/piasutorusquare": "\u332E", + "/pick": "\u26CF", + "/pidblstruck": "\u213C", + "/pieupacirclekorean": "\u3273", + "/pieupaparenkorean": "\u3213", + "/pieupcieuckorean": "\u3176", + "/pieupcirclekorean": "\u3265", + "/pieupkiyeokkorean": "\u3172", + "/pieupkorean": "\u3142", + "/pieupparenkorean": "\u3205", + "/pieupsioskiyeokkorean": "\u3174", + "/pieupsioskorean": "\u3144", + "/pieupsiostikeutkorean": "\u3175", + "/pieupthieuthkorean": "\u3177", + "/pieuptikeutkorean": "\u3173", + "/pig": "\u1F416", + "/pigFace": "\u1F437", + "/pigNose": "\u1F43D", + "/pihiragana": "\u3074", + "/pikatakana": "\u30D4", + "/pikosquare": "\u3330", + "/pikurusquare": "\u332F", + "/pilcrowsignreversed": "\u204B", + "/pileOfPoo": "\u1F4A9", + "/pill": "\u1F48A", + "/pineDecoration": "\u1F38D", + "/pineapple": "\u1F34D", + "/pisces": "\u2653", + "/piselehpada": "\uA9CC", + "/pistol": "\u1F52B", + "/pisymbolgreek": "\u03D6", + "/pitchfork": "\u22D4", + "/piwrarmenian": "\u0583", + "/placeOfWorship": "\u1F6D0", + "/placeofinterestsign": "\u2318", + "/planck": "\u210E", + "/plancktwopi": "\u210F", + "/plus": "\u002B", + "/plus.inferior": "\u208A", + "/plus.superior": "\u207A", + "/plusbelowcmb": "\u031F", + "/pluscircle": "\u2295", + "/plusminus": "\u00B1", + "/plusmod": "\u02D6", + "/plusmonospace": "\uFF0B", + "/plussignalt:hb": "\uFB29", + "/plussignmod": "\u02D6", + "/plussmall": "\uFE62", + "/plussuperior": "\u207A", + "/pluto": "\u2647", + "/pmfullwidth": "\u33D8", + "/pmonospace": "\uFF50", + "/pmsquare": "\u33D8", + "/pocketCalculator": "\u1F5A9", + "/poeticverse": "\u060E", + "/pohiragana": "\u307D", + "/pointerleftblack": "\u25C4", + "/pointerleftwhite": "\u25C5", + "/pointerrightblack": "\u25BA", + "/pointerrightwhite": "\u25BB", + "/pointingindexdownwhite": "\u261F", + "/pointingindexleftblack": "\u261A", + "/pointingindexleftwhite": "\u261C", + "/pointingindexrightblack": "\u261B", + "/pointingindexrightwhite": "\u261E", + "/pointingindexupwhite": "\u261D", + "/pointingtriangledownheavywhite": "\u26DB", + "/pointosquare": "\u333D", + "/pointring": "\u2E30", + "/pokatakana": "\u30DD", + "/pokrytiecmbcyr": "\u0487", + "/policeCar": "\u1F693", + "/policeCarsRevolvingLight": "\u1F6A8", + "/policeOfficer": "\u1F46E", + "/pondosquare": "\u3340", + "/poodle": "\u1F429", + "/popcorn": "\u1F37F", + "/popdirectionalformatting": "\u202C", + "/popdirectionalisolate": "\u2069", + "/poplathai": "\u0E1B", + "/portableStereo": "\u1F4FE", + "/positionindicator": "\u2316", + "/postalHorn": "\u1F4EF", + "/postalmark": "\u3012", + "/postalmarkface": "\u3020", + "/postbox": "\u1F4EE", + "/potOfFood": "\u1F372", + "/potableWater": "\u1F6B0", + "/pouch": "\u1F45D", + "/poultryLeg": "\u1F357", + "/poutingCatFace": "\u1F63E", + "/poutingFace": "\u1F621", + "/power": "\u23FB", + "/poweron": "\u23FD", + "/poweronoff": "\u23FC", + "/powersleep": "\u23FE", + "/pparen": "\u24AB", + "/pparenthesized": "\u24AB", + "/ppmfullwidth": "\u33D9", + "/prayerBeads": "\u1F4FF", + "/precedes": "\u227A", + "/precedesbutnotequivalent": "\u22E8", + "/precedesorequal": "\u227C", + "/precedesorequivalent": "\u227E", + "/precedesunderrelation": "\u22B0", + "/prescription": "\u211E", + "/preversedepigraphic": "\uA7FC", + "/previouspage": "\u2397", + "/prfullwidth": "\u33DA", + "/primedblmod": "\u02BA", + "/primemod": "\u02B9", + "/primereversed": "\u2035", + "/princess": "\u1F478", + "/printer": "\u1F5A8", + "/printerIcon": "\u1F5B6", + "/printideographiccircled": "\u329E", + "/printscreen": "\u2399", + "/product": "\u220F", + "/prohibitedSign": "\u1F6C7", + "/projective": "\u2305", + "/prolongedkana": "\u30FC", + "/propellor": "\u2318", + "/propersubset": "\u2282", + "/propersuperset": "\u2283", + "/propertyline": "\u214A", + "/proportion": "\u2237", + "/proportional": "\u221D", + "/psfullwidth": "\u33B0", + "/psi": "\u03C8", + "/psicyr": "\u0471", + "/psicyrillic": "\u0471", + "/psilicmbcyr": "\u0486", + "/psilipneumatacyrilliccmb": "\u0486", + "/pssquare": "\u33B0", + "/pstrokedescender": "\uA751", + "/ptail": "\uA755", + "/publicAddressLoudspeaker": "\u1F4E2", + "/puhiragana": "\u3077", + "/pukatakana": "\u30D7", + "/punctuationspace": "\u2008", + "/purpleHeart": "\u1F49C", + "/purse": "\u1F45B", + "/pushpin": "\u1F4CC", + "/putLitterInItsPlace": "\u1F6AE", + "/pvfullwidth": "\u33B4", + "/pvsquare": "\u33B4", + "/pwfullwidth": "\u33BA", + "/pwsquare": "\u33BA", + "/q": "\u0071", + "/qacyr": "\u051B", + "/qadeva": "\u0958", + "/qadma:hb": "\u05A8", + "/qadmahebrew": "\u05A8", + "/qaf": "\u0642", + "/qaf.fina": "\uFED6", + "/qaf.init": "\uFED7", + "/qaf.init_alefmaksura.fina": "\uFC35", + "/qaf.init_hah.fina": "\uFC33", + "/qaf.init_hah.medi": "\uFCC2", + "/qaf.init_meem.fina": "\uFC34", + "/qaf.init_meem.medi": "\uFCC3", + "/qaf.init_meem.medi_hah.medi": "\uFDB4", + "/qaf.init_yeh.fina": "\uFC36", + "/qaf.isol": "\uFED5", + "/qaf.medi": "\uFED8", + "/qaf.medi_alefmaksura.fina": "\uFC7E", + "/qaf.medi_meem.medi_hah.fina": "\uFD7E", + "/qaf.medi_meem.medi_meem.fina": "\uFD7F", + "/qaf.medi_meem.medi_yeh.fina": "\uFDB2", + "/qaf.medi_yeh.fina": "\uFC7F", + "/qaf_lam_alefmaksuraabove": "\u06D7", + "/qafarabic": "\u0642", + "/qafdotabove": "\u06A7", + "/qaffinalarabic": "\uFED6", + "/qafinitialarabic": "\uFED7", + "/qafmedialarabic": "\uFED8", + "/qafthreedotsabove": "\u06A8", + "/qamats": "\u05B8", + "/qamats10": "\u05B8", + "/qamats1a": "\u05B8", + "/qamats1c": "\u05B8", + "/qamats27": "\u05B8", + "/qamats29": "\u05B8", + "/qamats33": "\u05B8", + "/qamats:hb": "\u05B8", + "/qamatsQatan:hb": "\u05C7", + "/qamatsde": "\u05B8", + "/qamatshebrew": "\u05B8", + "/qamatsnarrowhebrew": "\u05B8", + "/qamatsqatanhebrew": "\u05B8", + "/qamatsqatannarrowhebrew": "\u05B8", + "/qamatsqatanquarterhebrew": "\u05B8", + "/qamatsqatanwidehebrew": "\u05B8", + "/qamatsquarterhebrew": "\u05B8", + "/qamatswidehebrew": "\u05B8", + "/qarneFarah:hb": "\u059F", + "/qarneyparahebrew": "\u059F", + "/qbopomofo": "\u3111", + "/qcircle": "\u24E0", + "/qdiagonalstroke": "\uA759", + "/qhook": "\u02A0", + "/qhooktail": "\u024B", + "/qmonospace": "\uFF51", + "/qof": "\u05E7", + "/qof:hb": "\u05E7", + "/qofdagesh": "\uFB47", + "/qofdageshhebrew": "\uFB47", + "/qofhatafpatah": "\u05E7", + "/qofhatafpatahhebrew": "\u05E7", + "/qofhatafsegol": "\u05E7", + "/qofhatafsegolhebrew": "\u05E7", + "/qofhebrew": "\u05E7", + "/qofhiriq": "\u05E7", + "/qofhiriqhebrew": "\u05E7", + "/qofholam": "\u05E7", + "/qofholamhebrew": "\u05E7", + "/qofpatah": "\u05E7", + "/qofpatahhebrew": "\u05E7", + "/qofqamats": "\u05E7", + "/qofqamatshebrew": "\u05E7", + "/qofqubuts": "\u05E7", + "/qofqubutshebrew": "\u05E7", + "/qofsegol": "\u05E7", + "/qofsegolhebrew": "\u05E7", + "/qofsheva": "\u05E7", + "/qofshevahebrew": "\u05E7", + "/qoftsere": "\u05E7", + "/qoftserehebrew": "\u05E7", + "/qofwithdagesh:hb": "\uFB47", + "/qparen": "\u24AC", + "/qparenthesized": "\u24AC", + "/qpdigraph": "\u0239", + "/qstrokedescender": "\uA757", + "/quadarrowdownfunc": "\u2357", + "/quadarrowleftfunc": "\u2347", + "/quadarrowrightfunc": "\u2348", + "/quadarrowupfunc": "\u2350", + "/quadbackslashfunc": "\u2342", + "/quadcaretdownfunc": "\u234C", + "/quadcaretupfunc": "\u2353", + "/quadcirclefunc": "\u233C", + "/quadcolonfunc": "\u2360", + "/quaddelfunc": "\u2354", + "/quaddeltafunc": "\u234D", + "/quaddiamondfunc": "\u233A", + "/quaddividefunc": "\u2339", + "/quadequalfunc": "\u2338", + "/quadfunc": "\u2395", + "/quadgreaterfunc": "\u2344", + "/quadjotfunc": "\u233B", + "/quadlessfunc": "\u2343", + "/quadnotequalfunc": "\u236F", + "/quadquestionfunc": "\u2370", + "/quadrantLowerLeft": "\u2596", + "/quadrantLowerRight": "\u2597", + "/quadrantUpperLeft": "\u2598", + "/quadrantUpperLeftAndLowerLeftAndLowerRight": "\u2599", + "/quadrantUpperLeftAndLowerRight": "\u259A", + "/quadrantUpperLeftAndUpperRightAndLowerLeft": "\u259B", + "/quadrantUpperLeftAndUpperRightAndLowerRight": "\u259C", + "/quadrantUpperRight": "\u259D", + "/quadrantUpperRightAndLowerLeft": "\u259E", + "/quadrantUpperRightAndLowerLeftAndLowerRight": "\u259F", + "/quadrupleminute": "\u2057", + "/quadslashfunc": "\u2341", + "/quarternote": "\u2669", + "/qubuts": "\u05BB", + "/qubuts18": "\u05BB", + "/qubuts25": "\u05BB", + "/qubuts31": "\u05BB", + "/qubuts:hb": "\u05BB", + "/qubutshebrew": "\u05BB", + "/qubutsnarrowhebrew": "\u05BB", + "/qubutsquarterhebrew": "\u05BB", + "/qubutswidehebrew": "\u05BB", + "/queenblack": "\u265B", + "/queenwhite": "\u2655", + "/question": "\u003F", + "/questionarabic": "\u061F", + "/questionarmenian": "\u055E", + "/questiondbl": "\u2047", + "/questiondown": "\u00BF", + "/questiondownsmall": "\uF7BF", + "/questionedequal": "\u225F", + "/questionexclamationmark": "\u2048", + "/questiongreek": "\u037E", + "/questionideographiccircled": "\u3244", + "/questionmonospace": "\uFF1F", + "/questionreversed": "\u2E2E", + "/questionsmall": "\uF73F", + "/quincunx": "\u26BB", + "/quotedbl": "\u0022", + "/quotedblbase": "\u201E", + "/quotedblleft": "\u201C", + "/quotedbllowreversed": "\u2E42", + "/quotedblmonospace": "\uFF02", + "/quotedblprime": "\u301E", + "/quotedblprimereversed": "\u301D", + "/quotedblreversed": "\u201F", + "/quotedblright": "\u201D", + "/quoteleft": "\u2018", + "/quoteleftreversed": "\u201B", + "/quotequadfunc": "\u235E", + "/quotereversed": "\u201B", + "/quoteright": "\u2019", + "/quoterightn": "\u0149", + "/quotesinglbase": "\u201A", + "/quotesingle": "\u0027", + "/quotesinglemonospace": "\uFF07", + "/quoteunderlinefunc": "\u2358", + "/r": "\u0072", + "/raagung": "\uA9AC", + "/raarmenian": "\u057C", + "/rabbit": "\u1F407", + "/rabbitFace": "\u1F430", + "/rabengali": "\u09B0", + "/racingCar": "\u1F3CE", + "/racingMotorcycle": "\u1F3CD", + "/racirclekatakana": "\u32F6", + "/racute": "\u0155", + "/radeva": "\u0930", + "/radfullwidth": "\u33AD", + "/radical": "\u221A", + "/radicalbottom": "\u23B7", + "/radicalex": "\uF8E5", + "/radio": "\u1F4FB", + "/radioButton": "\u1F518", + "/radioactive": "\u2622", + "/radovers2fullwidth": "\u33AF", + "/radoversfullwidth": "\u33AE", + "/radoverssquare": "\u33AE", + "/radoverssquaredsquare": "\u33AF", + "/radsquare": "\u33AD", + "/rafe": "\u05BF", + "/rafe:hb": "\u05BF", + "/rafehebrew": "\u05BF", + "/ragujarati": "\u0AB0", + "/ragurmukhi": "\u0A30", + "/rahiragana": "\u3089", + "/railwayCar": "\u1F683", + "/railwayTrack": "\u1F6E4", + "/rain": "\u26C6", + "/rainbow": "\u1F308", + "/raisedHandFingersSplayed": "\u1F590", + "/raisedHandPartBetweenMiddleAndRingFingers": "\u1F596", + "/raisedmcsign": "\u1F16A", + "/raisedmdsign": "\u1F16B", + "/rakatakana": "\u30E9", + "/rakatakanahalfwidth": "\uFF97", + "/ralowerdiagonalbengali": "\u09F1", + "/ram": "\u1F40F", + "/ramiddlediagonalbengali": "\u09F0", + "/ramshorn": "\u0264", + "/rat": "\u1F400", + "/ratio": "\u2236", + "/ray": "\u0608", + "/rbopomofo": "\u3116", + "/rcaron": "\u0159", + "/rcedilla": "\u0157", + "/rcircle": "\u24E1", + "/rcommaaccent": "\u0157", + "/rdblgrave": "\u0211", + "/rdot": "\u1E59", + "/rdotaccent": "\u1E59", + "/rdotbelow": "\u1E5B", + "/rdotbelowmacron": "\u1E5D", + "/reachideographicparen": "\u3243", + "/recirclekatakana": "\u32F9", + "/recreationalVehicle": "\u1F699", + "/rectangleblack": "\u25AC", + "/rectangleverticalblack": "\u25AE", + "/rectangleverticalwhite": "\u25AF", + "/rectanglewhite": "\u25AD", + "/recycledpaper": "\u267C", + "/recyclefiveplastics": "\u2677", + "/recyclefourplastics": "\u2676", + "/recyclegeneric": "\u267A", + "/recycleoneplastics": "\u2673", + "/recyclepartiallypaper": "\u267D", + "/recyclesevenplastics": "\u2679", + "/recyclesixplastics": "\u2678", + "/recyclethreeplastics": "\u2675", + "/recycletwoplastics": "\u2674", + "/recycleuniversal": "\u2672", + "/recycleuniversalblack": "\u267B", + "/redApple": "\u1F34E", + "/redTriangleDOwn": "\u1F53B", + "/redTriangleUp": "\u1F53A", + "/referencemark": "\u203B", + "/reflexsubset": "\u2286", + "/reflexsuperset": "\u2287", + "/regionalindicatorsymbollettera": "\u1F1E6", + "/regionalindicatorsymbolletterb": "\u1F1E7", + "/regionalindicatorsymbolletterc": "\u1F1E8", + "/regionalindicatorsymbolletterd": "\u1F1E9", + "/regionalindicatorsymbollettere": "\u1F1EA", + "/regionalindicatorsymbolletterf": "\u1F1EB", + "/regionalindicatorsymbolletterg": "\u1F1EC", + "/regionalindicatorsymbolletterh": "\u1F1ED", + "/regionalindicatorsymbolletteri": "\u1F1EE", + "/regionalindicatorsymbolletterj": "\u1F1EF", + "/regionalindicatorsymbolletterk": "\u1F1F0", + "/regionalindicatorsymbolletterl": "\u1F1F1", + "/regionalindicatorsymbolletterm": "\u1F1F2", + "/regionalindicatorsymbollettern": "\u1F1F3", + "/regionalindicatorsymbollettero": "\u1F1F4", + "/regionalindicatorsymbolletterp": "\u1F1F5", + "/regionalindicatorsymbolletterq": "\u1F1F6", + "/regionalindicatorsymbolletterr": "\u1F1F7", + "/regionalindicatorsymbolletters": "\u1F1F8", + "/regionalindicatorsymbollettert": "\u1F1F9", + "/regionalindicatorsymbolletteru": "\u1F1FA", + "/regionalindicatorsymbolletterv": "\u1F1FB", + "/regionalindicatorsymbolletterw": "\u1F1FC", + "/regionalindicatorsymbolletterx": "\u1F1FD", + "/regionalindicatorsymbollettery": "\u1F1FE", + "/regionalindicatorsymbolletterz": "\u1F1FF", + "/registered": "\u00AE", + "/registersans": "\uF8E8", + "/registerserif": "\uF6DA", + "/reh.fina": "\uFEAE", + "/reh.init_superscriptalef.fina": "\uFC5C", + "/reh.isol": "\uFEAD", + "/rehHamzaAbove": "\u076C", + "/rehSmallTahTwoDots": "\u0771", + "/rehStroke": "\u075B", + "/rehTwoDotsVerticallyAbove": "\u076B", + "/rehVabove": "\u0692", + "/rehVbelow": "\u0695", + "/reharabic": "\u0631", + "/reharmenian": "\u0580", + "/rehdotbelow": "\u0694", + "/rehdotbelowdotabove": "\u0696", + "/rehfinalarabic": "\uFEAE", + "/rehfourdotsabove": "\u0699", + "/rehinvertedV": "\u06EF", + "/rehiragana": "\u308C", + "/rehring": "\u0693", + "/rehtwodotsabove": "\u0697", + "/rehyehaleflamarabic": "\u0631", + "/rekatakana": "\u30EC", + "/rekatakanahalfwidth": "\uFF9A", + "/relievedFace": "\u1F60C", + "/religionideographiccircled": "\u32AA", + "/reminderRibbon": "\u1F397", + "/remusquare": "\u3355", + "/rentogensquare": "\u3356", + "/replacementchar": "\uFFFD", + "/replacementcharobj": "\uFFFC", + "/representideographicparen": "\u3239", + "/rerengganleft": "\uA9C1", + "/rerengganright": "\uA9C2", + "/resh": "\u05E8", + "/resh:hb": "\u05E8", + "/reshdageshhebrew": "\uFB48", + "/reshhatafpatah": "\u05E8", + "/reshhatafpatahhebrew": "\u05E8", + "/reshhatafsegol": "\u05E8", + "/reshhatafsegolhebrew": "\u05E8", + "/reshhebrew": "\u05E8", + "/reshhiriq": "\u05E8", + "/reshhiriqhebrew": "\u05E8", + "/reshholam": "\u05E8", + "/reshholamhebrew": "\u05E8", + "/reshpatah": "\u05E8", + "/reshpatahhebrew": "\u05E8", + "/reshqamats": "\u05E8", + "/reshqamatshebrew": "\u05E8", + "/reshqubuts": "\u05E8", + "/reshqubutshebrew": "\u05E8", + "/reshsegol": "\u05E8", + "/reshsegolhebrew": "\u05E8", + "/reshsheva": "\u05E8", + "/reshshevahebrew": "\u05E8", + "/reshtsere": "\u05E8", + "/reshtserehebrew": "\u05E8", + "/reshwide:hb": "\uFB27", + "/reshwithdagesh:hb": "\uFB48", + "/resourceideographiccircled": "\u32AE", + "/resourceideographicparen": "\u323E", + "/response": "\u211F", + "/restideographiccircled": "\u32A1", + "/restideographicparen": "\u3241", + "/restrictedentryoneleft": "\u26E0", + "/restrictedentrytwoleft": "\u26E1", + "/restroom": "\u1F6BB", + "/return": "\u23CE", + "/reversedHandMiddleFingerExtended": "\u1F595", + "/reversedRaisedHandFingersSplayed": "\u1F591", + "/reversedThumbsDownSign": "\u1F593", + "/reversedThumbsUpSign": "\u1F592", + "/reversedVictoryHand": "\u1F594", + "/reversedonehundred.roman": "\u2183", + "/reversedtilde": "\u223D", + "/reversedzecyr": "\u0511", + "/revia:hb": "\u0597", + "/reviahebrew": "\u0597", + "/reviamugrashhebrew": "\u0597", + "/revlogicalnot": "\u2310", + "/revolvingHearts": "\u1F49E", + "/rfishhook": "\u027E", + "/rfishhookreversed": "\u027F", + "/rgravedbl": "\u0211", + "/rhabengali": "\u09DD", + "/rhacyr": "\u0517", + "/rhadeva": "\u095D", + "/rho": "\u03C1", + "/rhoasper": "\u1FE5", + "/rhofunc": "\u2374", + "/rholenis": "\u1FE4", + "/rhook": "\u027D", + "/rhookturned": "\u027B", + "/rhookturnedsuperior": "\u02B5", + "/rhookturnedsupmod": "\u02B5", + "/rhostrokesymbol": "\u03FC", + "/rhosymbol": "\u03F1", + "/rhosymbolgreek": "\u03F1", + "/rhotichookmod": "\u02DE", + "/rial": "\uFDFC", + "/ribbon": "\u1F380", + "/riceBall": "\u1F359", + "/riceCracker": "\u1F358", + "/ricirclekatakana": "\u32F7", + "/rieulacirclekorean": "\u3271", + "/rieulaparenkorean": "\u3211", + "/rieulcirclekorean": "\u3263", + "/rieulhieuhkorean": "\u3140", + "/rieulkiyeokkorean": "\u313A", + "/rieulkiyeoksioskorean": "\u3169", + "/rieulkorean": "\u3139", + "/rieulmieumkorean": "\u313B", + "/rieulpansioskorean": "\u316C", + "/rieulparenkorean": "\u3203", + "/rieulphieuphkorean": "\u313F", + "/rieulpieupkorean": "\u313C", + "/rieulpieupsioskorean": "\u316B", + "/rieulsioskorean": "\u313D", + "/rieulthieuthkorean": "\u313E", + "/rieultikeutkorean": "\u316A", + "/rieulyeorinhieuhkorean": "\u316D", + "/right-pointingMagnifyingGlass": "\u1F50E", + "/rightAngerBubble": "\u1F5EF", + "/rightHalfBlock": "\u2590", + "/rightHandTelephoneReceiver": "\u1F57D", + "/rightOneEighthBlock": "\u2595", + "/rightSpeaker": "\u1F568", + "/rightSpeakerOneSoundWave": "\u1F569", + "/rightSpeakerThreeSoundWaves": "\u1F56A", + "/rightSpeechBubble": "\u1F5E9", + "/rightThoughtBubble": "\u1F5ED", + "/rightangle": "\u221F", + "/rightarrowoverleftarrow": "\u21C4", + "/rightdnheavyleftuplight": "\u2546", + "/rightharpoonoverleftharpoon": "\u21CC", + "/rightheavyleftdnlight": "\u252E", + "/rightheavyleftuplight": "\u2536", + "/rightheavyleftvertlight": "\u253E", + "/rightideographiccircled": "\u32A8", + "/rightlightleftdnheavy": "\u2531", + "/rightlightleftupheavy": "\u2539", + "/rightlightleftvertheavy": "\u2549", + "/righttackbelowcmb": "\u0319", + "/righttoleftembed": "\u202B", + "/righttoleftisolate": "\u2067", + "/righttoleftmark": "\u200F", + "/righttoleftoverride": "\u202E", + "/righttriangle": "\u22BF", + "/rightupheavyleftdnlight": "\u2544", + "/rihiragana": "\u308A", + "/rikatakana": "\u30EA", + "/rikatakanahalfwidth": "\uFF98", + "/ring": "\u02DA", + "/ringbelowcmb": "\u0325", + "/ringcmb": "\u030A", + "/ringequal": "\u2257", + "/ringhalfleft": "\u02BF", + "/ringhalfleftarmenian": "\u0559", + "/ringhalfleftbelowcmb": "\u031C", + "/ringhalfleftcentered": "\u02D3", + "/ringhalfleftcentredmod": "\u02D3", + "/ringhalfleftmod": "\u02BF", + "/ringhalfright": "\u02BE", + "/ringhalfrightbelowcmb": "\u0339", + "/ringhalfrightcentered": "\u02D2", + "/ringhalfrightcentredmod": "\u02D2", + "/ringhalfrightmod": "\u02BE", + "/ringinequal": "\u2256", + "/ringingBell": "\u1F56D", + "/ringlowmod": "\u02F3", + "/ringoperator": "\u2218", + "/rinsular": "\uA783", + "/rinvertedbreve": "\u0213", + "/rirasquare": "\u3352", + "/risingdiagonal": "\u27CB", + "/rittorusquare": "\u3351", + "/rlinebelow": "\u1E5F", + "/rlongleg": "\u027C", + "/rlonglegturned": "\u027A", + "/rmacrondot": "\u1E5D", + "/rmonospace": "\uFF52", + "/rnoon": "\u06BB", + "/rnoon.fina": "\uFBA1", + "/rnoon.init": "\uFBA2", + "/rnoon.isol": "\uFBA0", + "/rnoon.medi": "\uFBA3", + "/roastedSweetPotato": "\u1F360", + "/robliquestroke": "\uA7A7", + "/rocirclekatakana": "\u32FA", + "/rocket": "\u1F680", + "/rohiragana": "\u308D", + "/rokatakana": "\u30ED", + "/rokatakanahalfwidth": "\uFF9B", + "/rolled-upNewspaper": "\u1F5DE", + "/rollerCoaster": "\u1F3A2", + "/rookblack": "\u265C", + "/rookwhite": "\u2656", + "/rooster": "\u1F413", + "/roruathai": "\u0E23", + "/rose": "\u1F339", + "/rosette": "\u1F3F5", + "/roundPushpin": "\u1F4CD", + "/roundedzeroabove": "\u06DF", + "/rowboat": "\u1F6A3", + "/rparen": "\u24AD", + "/rparenthesized": "\u24AD", + "/rrabengali": "\u09DC", + "/rradeva": "\u0931", + "/rragurmukhi": "\u0A5C", + "/rreh": "\u0691", + "/rreh.fina": "\uFB8D", + "/rreh.isol": "\uFB8C", + "/rreharabic": "\u0691", + "/rrehfinalarabic": "\uFB8D", + "/rrotunda": "\uA75B", + "/rrvocalicbengali": "\u09E0", + "/rrvocalicdeva": "\u0960", + "/rrvocalicgujarati": "\u0AE0", + "/rrvocalicvowelsignbengali": "\u09C4", + "/rrvocalicvowelsigndeva": "\u0944", + "/rrvocalicvowelsigngujarati": "\u0AC4", + "/rstroke": "\u024D", + "/rsuperior": "\uF6F1", + "/rsupmod": "\u02B3", + "/rtailturned": "\u2C79", + "/rtblock": "\u2590", + "/rturned": "\u0279", + "/rturnedsuperior": "\u02B4", + "/rturnedsupmod": "\u02B4", + "/ruble": "\u20BD", + "/rucirclekatakana": "\u32F8", + "/rugbyFootball": "\u1F3C9", + "/ruhiragana": "\u308B", + "/rukatakana": "\u30EB", + "/rukatakanahalfwidth": "\uFF99", + "/rum": "\uA775", + "/rumrotunda": "\uA75D", + "/runner": "\u1F3C3", + "/runningShirtSash": "\u1F3BD", + "/rupeemarkbengali": "\u09F2", + "/rupeesignbengali": "\u09F3", + "/rupiah": "\uF6DD", + "/rupiisquare": "\u3353", + "/ruthai": "\u0E24", + "/ruuburusquare": "\u3354", + "/rvocalicbengali": "\u098B", + "/rvocalicdeva": "\u090B", + "/rvocalicgujarati": "\u0A8B", + "/rvocalicvowelsignbengali": "\u09C3", + "/rvocalicvowelsigndeva": "\u0943", + "/rvocalicvowelsigngujarati": "\u0AC3", + "/s": "\u0073", + "/s.inferior": "\u209B", + "/s_t": "\uFB06", + "/sabengali": "\u09B8", + "/sacirclekatakana": "\u32DA", + "/sacute": "\u015B", + "/sacutedotaccent": "\u1E65", + "/sad": "\u0635", + "/sad.fina": "\uFEBA", + "/sad.init": "\uFEBB", + "/sad.init_alefmaksura.fina": "\uFD05", + "/sad.init_hah.fina": "\uFC20", + "/sad.init_hah.medi": "\uFCB1", + "/sad.init_hah.medi_hah.medi": "\uFD65", + "/sad.init_khah.medi": "\uFCB2", + "/sad.init_meem.fina": "\uFC21", + "/sad.init_meem.medi": "\uFCB3", + "/sad.init_meem.medi_meem.medi": "\uFDC5", + "/sad.init_reh.fina": "\uFD0F", + "/sad.init_yeh.fina": "\uFD06", + "/sad.isol": "\uFEB9", + "/sad.medi": "\uFEBC", + "/sad.medi_alefmaksura.fina": "\uFD21", + "/sad.medi_hah.medi_hah.fina": "\uFD64", + "/sad.medi_hah.medi_yeh.fina": "\uFDA9", + "/sad.medi_meem.medi_meem.fina": "\uFD66", + "/sad.medi_reh.fina": "\uFD2B", + "/sad.medi_yeh.fina": "\uFD22", + "/sad_lam_alefmaksuraabove": "\u06D6", + "/sadarabic": "\u0635", + "/sadeva": "\u0938", + "/sadfinalarabic": "\uFEBA", + "/sadinitialarabic": "\uFEBB", + "/sadmedialarabic": "\uFEBC", + "/sadthreedotsabove": "\u069E", + "/sadtwodotsbelow": "\u069D", + "/sagittarius": "\u2650", + "/sagujarati": "\u0AB8", + "/sagurmukhi": "\u0A38", + "/sahiragana": "\u3055", + "/saikurusquare": "\u331F", + "/sailboat": "\u26F5", + "/sakatakana": "\u30B5", + "/sakatakanahalfwidth": "\uFF7B", + "/sakeBottleAndCup": "\u1F376", + "/sallallahoualayhewasallamarabic": "\uFDFA", + "/saltillo": "\uA78C", + "/saltire": "\u2613", + "/samahaprana": "\uA9B0", + "/samekh": "\u05E1", + "/samekh:hb": "\u05E1", + "/samekhdagesh": "\uFB41", + "/samekhdageshhebrew": "\uFB41", + "/samekhhebrew": "\u05E1", + "/samekhwithdagesh:hb": "\uFB41", + "/sampi": "\u03E1", + "/sampiarchaic": "\u0373", + "/samurda": "\uA9AF", + "/samvat": "\u0604", + "/san": "\u03FB", + "/santiimusquare": "\u3320", + "/saraaathai": "\u0E32", + "/saraaethai": "\u0E41", + "/saraaimaimalaithai": "\u0E44", + "/saraaimaimuanthai": "\u0E43", + "/saraamthai": "\u0E33", + "/saraathai": "\u0E30", + "/saraethai": "\u0E40", + "/saraiileftthai": "\uF886", + "/saraiithai": "\u0E35", + "/saraileftthai": "\uF885", + "/saraithai": "\u0E34", + "/saraothai": "\u0E42", + "/saraueeleftthai": "\uF888", + "/saraueethai": "\u0E37", + "/saraueleftthai": "\uF887", + "/sarauethai": "\u0E36", + "/sarauthai": "\u0E38", + "/sarauuthai": "\u0E39", + "/satellite": "\u1F6F0", + "/satelliteAntenna": "\u1F4E1", + "/saturn": "\u2644", + "/saxophone": "\u1F3B7", + "/sbopomofo": "\u3119", + "/scales": "\u2696", + "/scanninehorizontal": "\u23BD", + "/scanonehorizontal": "\u23BA", + "/scansevenhorizontal": "\u23BC", + "/scanthreehorizontal": "\u23BB", + "/scaron": "\u0161", + "/scarondot": "\u1E67", + "/scarondotaccent": "\u1E67", + "/scedilla": "\u015F", + "/school": "\u1F3EB", + "/schoolSatchel": "\u1F392", + "/schoolideographiccircled": "\u3246", + "/schwa": "\u0259", + "/schwa.inferior": "\u2094", + "/schwacyr": "\u04D9", + "/schwacyrillic": "\u04D9", + "/schwadieresiscyr": "\u04DB", + "/schwadieresiscyrillic": "\u04DB", + "/schwahook": "\u025A", + "/scircle": "\u24E2", + "/scircumflex": "\u015D", + "/scommaaccent": "\u0219", + "/scooter": "\u1F6F4", + "/scorpius": "\u264F", + "/screen": "\u1F5B5", + "/scroll": "\u1F4DC", + "/scruple": "\u2108", + "/sdot": "\u1E61", + "/sdotaccent": "\u1E61", + "/sdotbelow": "\u1E63", + "/sdotbelowdotabove": "\u1E69", + "/sdotbelowdotaccent": "\u1E69", + "/seagullbelowcmb": "\u033C", + "/seat": "\u1F4BA", + "/secirclekatakana": "\u32DD", + "/second": "\u2033", + "/secondreversed": "\u2036", + "/secondscreensquare": "\u1F19C", + "/secondtonechinese": "\u02CA", + "/secretideographiccircled": "\u3299", + "/section": "\u00A7", + "/sectionsignhalftop": "\u2E39", + "/sector": "\u2314", + "/seeNoEvilMonkey": "\u1F648", + "/seedling": "\u1F331", + "/seen": "\u0633", + "/seen.fina": "\uFEB2", + "/seen.init": "\uFEB3", + "/seen.init_alefmaksura.fina": "\uFCFB", + "/seen.init_hah.fina": "\uFC1D", + "/seen.init_hah.medi": "\uFCAE", + "/seen.init_hah.medi_jeem.medi": "\uFD5C", + "/seen.init_heh.medi": "\uFD31", + "/seen.init_jeem.fina": "\uFC1C", + "/seen.init_jeem.medi": "\uFCAD", + "/seen.init_jeem.medi_hah.medi": "\uFD5D", + "/seen.init_khah.fina": "\uFC1E", + "/seen.init_khah.medi": "\uFCAF", + "/seen.init_meem.fina": "\uFC1F", + "/seen.init_meem.medi": "\uFCB0", + "/seen.init_meem.medi_hah.medi": "\uFD60", + "/seen.init_meem.medi_jeem.medi": "\uFD61", + "/seen.init_meem.medi_meem.medi": "\uFD63", + "/seen.init_reh.fina": "\uFD0E", + "/seen.init_yeh.fina": "\uFCFC", + "/seen.isol": "\uFEB1", + "/seen.medi": "\uFEB4", + "/seen.medi_alefmaksura.fina": "\uFD17", + "/seen.medi_hah.medi": "\uFD35", + "/seen.medi_heh.medi": "\uFCE8", + "/seen.medi_jeem.medi": "\uFD34", + "/seen.medi_jeem.medi_alefmaksura.fina": "\uFD5E", + "/seen.medi_khah.medi": "\uFD36", + "/seen.medi_khah.medi_alefmaksura.fina": "\uFDA8", + "/seen.medi_khah.medi_yeh.fina": "\uFDC6", + "/seen.medi_meem.medi": "\uFCE7", + "/seen.medi_meem.medi_hah.fina": "\uFD5F", + "/seen.medi_meem.medi_meem.fina": "\uFD62", + "/seen.medi_reh.fina": "\uFD2A", + "/seen.medi_yeh.fina": "\uFD18", + "/seenDigitFourAbove": "\u077D", + "/seenFourDotsAbove": "\u075C", + "/seenInvertedV": "\u077E", + "/seenSmallTahTwoDots": "\u0770", + "/seenTwoDotsVerticallyAbove": "\u076D", + "/seenabove": "\u06DC", + "/seenarabic": "\u0633", + "/seendotbelowdotabove": "\u069A", + "/seenfinalarabic": "\uFEB2", + "/seeninitialarabic": "\uFEB3", + "/seenlow": "\u06E3", + "/seenmedialarabic": "\uFEB4", + "/seenthreedotsbelow": "\u069B", + "/seenthreedotsbelowthreedotsabove": "\u069C", + "/segment": "\u2313", + "/segol": "\u05B6", + "/segol13": "\u05B6", + "/segol1f": "\u05B6", + "/segol2c": "\u05B6", + "/segol:hb": "\u05B6", + "/segolhebrew": "\u05B6", + "/segolnarrowhebrew": "\u05B6", + "/segolquarterhebrew": "\u05B6", + "/segolta:hb": "\u0592", + "/segoltahebrew": "\u0592", + "/segolwidehebrew": "\u05B6", + "/seharmenian": "\u057D", + "/sehiragana": "\u305B", + "/sekatakana": "\u30BB", + "/sekatakanahalfwidth": "\uFF7E", + "/selfideographicparen": "\u3242", + "/semicolon": "\u003B", + "/semicolonarabic": "\u061B", + "/semicolonmonospace": "\uFF1B", + "/semicolonreversed": "\u204F", + "/semicolonsmall": "\uFE54", + "/semicolonunderlinefunc": "\u236E", + "/semidirectproductleft": "\u22CB", + "/semidirectproductright": "\u22CC", + "/semisextile": "\u26BA", + "/semisoftcyr": "\u048D", + "/semivoicedmarkkana": "\u309C", + "/semivoicedmarkkanahalfwidth": "\uFF9F", + "/sentisquare": "\u3322", + "/sentosquare": "\u3323", + "/septembertelegraph": "\u32C8", + "/sersetdblup": "\u22D1", + "/sersetnotequalup": "\u228B", + "/servicemark": "\u2120", + "/sesamedot": "\uFE45", + "/sesquiquadrate": "\u26BC", + "/setminus": "\u2216", + "/seven": "\u0037", + "/seven.inferior": "\u2087", + "/seven.roman": "\u2166", + "/seven.romansmall": "\u2176", + "/seven.superior": "\u2077", + "/sevenarabic": "\u0667", + "/sevenbengali": "\u09ED", + "/sevencircle": "\u2466", + "/sevencircledbl": "\u24FB", + "/sevencircleinversesansserif": "\u2790", + "/sevencomma": "\u1F108", + "/sevendeva": "\u096D", + "/seveneighths": "\u215E", + "/sevenfar": "\u06F7", + "/sevengujarati": "\u0AED", + "/sevengurmukhi": "\u0A6D", + "/sevenhackarabic": "\u0667", + "/sevenhangzhou": "\u3027", + "/sevenideographiccircled": "\u3286", + "/sevenideographicparen": "\u3226", + "/seveninferior": "\u2087", + "/sevenmonospace": "\uFF17", + "/sevenoldstyle": "\uF737", + "/sevenparen": "\u247A", + "/sevenparenthesized": "\u247A", + "/sevenperiod": "\u248E", + "/sevenpersian": "\u06F7", + "/sevenpointonesquare": "\u1F1A1", + "/sevenroman": "\u2176", + "/sevensuperior": "\u2077", + "/seventeencircle": "\u2470", + "/seventeencircleblack": "\u24F1", + "/seventeenparen": "\u2484", + "/seventeenparenthesized": "\u2484", + "/seventeenperiod": "\u2498", + "/seventhai": "\u0E57", + "/seventycirclesquare": "\u324E", + "/sextile": "\u26B9", + "/sfthyphen": "\u00AD", + "/shaarmenian": "\u0577", + "/shabengali": "\u09B6", + "/shacyr": "\u0448", + "/shacyrillic": "\u0448", + "/shaddaAlefIsol": "\uFC63", + "/shaddaDammaIsol": "\uFC61", + "/shaddaDammaMedi": "\uFCF3", + "/shaddaDammatanIsol": "\uFC5E", + "/shaddaFathaIsol": "\uFC60", + "/shaddaFathaMedi": "\uFCF2", + "/shaddaIsol": "\uFE7C", + "/shaddaKasraIsol": "\uFC62", + "/shaddaKasraMedi": "\uFCF4", + "/shaddaKasratanIsol": "\uFC5F", + "/shaddaMedi": "\uFE7D", + "/shaddaarabic": "\u0651", + "/shaddadammaarabic": "\uFC61", + "/shaddadammatanarabic": "\uFC5E", + "/shaddafathaarabic": "\uFC60", + "/shaddafathatanarabic": "\u0651", + "/shaddakasraarabic": "\uFC62", + "/shaddakasratanarabic": "\uFC5F", + "/shade": "\u2592", + "/shadedark": "\u2593", + "/shadelight": "\u2591", + "/shademedium": "\u2592", + "/shadeva": "\u0936", + "/shagujarati": "\u0AB6", + "/shagurmukhi": "\u0A36", + "/shalshelet:hb": "\u0593", + "/shalshelethebrew": "\u0593", + "/shamrock": "\u2618", + "/shavedIce": "\u1F367", + "/shbopomofo": "\u3115", + "/shchacyr": "\u0449", + "/shchacyrillic": "\u0449", + "/sheen": "\u0634", + "/sheen.fina": "\uFEB6", + "/sheen.init": "\uFEB7", + "/sheen.init_alefmaksura.fina": "\uFCFD", + "/sheen.init_hah.fina": "\uFD0A", + "/sheen.init_hah.medi": "\uFD2E", + "/sheen.init_hah.medi_meem.medi": "\uFD68", + "/sheen.init_heh.medi": "\uFD32", + "/sheen.init_jeem.fina": "\uFD09", + "/sheen.init_jeem.medi": "\uFD2D", + "/sheen.init_khah.fina": "\uFD0B", + "/sheen.init_khah.medi": "\uFD2F", + "/sheen.init_meem.fina": "\uFD0C", + "/sheen.init_meem.medi": "\uFD30", + "/sheen.init_meem.medi_khah.medi": "\uFD6B", + "/sheen.init_meem.medi_meem.medi": "\uFD6D", + "/sheen.init_reh.fina": "\uFD0D", + "/sheen.init_yeh.fina": "\uFCFE", + "/sheen.isol": "\uFEB5", + "/sheen.medi": "\uFEB8", + "/sheen.medi_alefmaksura.fina": "\uFD19", + "/sheen.medi_hah.fina": "\uFD26", + "/sheen.medi_hah.medi": "\uFD38", + "/sheen.medi_hah.medi_meem.fina": "\uFD67", + "/sheen.medi_hah.medi_yeh.fina": "\uFDAA", + "/sheen.medi_heh.medi": "\uFCEA", + "/sheen.medi_jeem.fina": "\uFD25", + "/sheen.medi_jeem.medi": "\uFD37", + "/sheen.medi_jeem.medi_yeh.fina": "\uFD69", + "/sheen.medi_khah.fina": "\uFD27", + "/sheen.medi_khah.medi": "\uFD39", + "/sheen.medi_meem.fina": "\uFD28", + "/sheen.medi_meem.medi": "\uFCE9", + "/sheen.medi_meem.medi_khah.fina": "\uFD6A", + "/sheen.medi_meem.medi_meem.fina": "\uFD6C", + "/sheen.medi_reh.fina": "\uFD29", + "/sheen.medi_yeh.fina": "\uFD1A", + "/sheenarabic": "\u0634", + "/sheendotbelow": "\u06FA", + "/sheenfinalarabic": "\uFEB6", + "/sheeninitialarabic": "\uFEB7", + "/sheenmedialarabic": "\uFEB8", + "/sheep": "\u1F411", + "/sheicoptic": "\u03E3", + "/shelfmod": "\u02FD", + "/shelfopenmod": "\u02FE", + "/sheqel": "\u20AA", + "/sheqelhebrew": "\u20AA", + "/sheva": "\u05B0", + "/sheva115": "\u05B0", + "/sheva15": "\u05B0", + "/sheva22": "\u05B0", + "/sheva2e": "\u05B0", + "/sheva:hb": "\u05B0", + "/shevahebrew": "\u05B0", + "/shevanarrowhebrew": "\u05B0", + "/shevaquarterhebrew": "\u05B0", + "/shevawidehebrew": "\u05B0", + "/shhacyr": "\u04BB", + "/shhacyrillic": "\u04BB", + "/shhatailcyr": "\u0527", + "/shield": "\u1F6E1", + "/shimacoptic": "\u03ED", + "/shin": "\u05E9", + "/shin:hb": "\u05E9", + "/shinDot:hb": "\u05C1", + "/shindagesh": "\uFB49", + "/shindageshhebrew": "\uFB49", + "/shindageshshindot": "\uFB2C", + "/shindageshshindothebrew": "\uFB2C", + "/shindageshsindot": "\uFB2D", + "/shindageshsindothebrew": "\uFB2D", + "/shindothebrew": "\u05C1", + "/shinhebrew": "\u05E9", + "/shinshindot": "\uFB2A", + "/shinshindothebrew": "\uFB2A", + "/shinsindot": "\uFB2B", + "/shinsindothebrew": "\uFB2B", + "/shintoshrine": "\u26E9", + "/shinwithdagesh:hb": "\uFB49", + "/shinwithdageshandshinDot:hb": "\uFB2C", + "/shinwithdageshandsinDot:hb": "\uFB2D", + "/shinwithshinDot:hb": "\uFB2A", + "/shinwithsinDot:hb": "\uFB2B", + "/ship": "\u1F6A2", + "/sho": "\u03F8", + "/shoejotupfunc": "\u235D", + "/shoestiledownfunc": "\u2366", + "/shoestileleftfunc": "\u2367", + "/shogipieceblack": "\u2617", + "/shogipiecewhite": "\u2616", + "/shook": "\u0282", + "/shootingStar": "\u1F320", + "/shoppingBags": "\u1F6CD", + "/shoppingTrolley": "\u1F6D2", + "/shortcake": "\u1F370", + "/shortequalsmod": "\uA78A", + "/shortoverlongmetrical": "\u23D3", + "/shoulderedopenbox": "\u237D", + "/shower": "\u1F6BF", + "/shvsquare": "\u1F1AA", + "/sicirclekatakana": "\u32DB", + "/sidewaysBlackDownPointingIndex": "\u1F5A1", + "/sidewaysBlackLeftPointingIndex": "\u1F59A", + "/sidewaysBlackRightPointingIndex": "\u1F59B", + "/sidewaysBlackUpPointingIndex": "\u1F5A0", + "/sidewaysWhiteDownPointingIndex": "\u1F59F", + "/sidewaysWhiteLeftPointingIndex": "\u1F598", + "/sidewaysWhiteRightPointingIndex": "\u1F599", + "/sidewaysWhiteUpPointingIndex": "\u1F59E", + "/sigma": "\u03C3", + "/sigma1": "\u03C2", + "/sigmafinal": "\u03C2", + "/sigmalunatedottedreversedsymbol": "\u037D", + "/sigmalunatedottedsymbol": "\u037C", + "/sigmalunatereversedsymbol": "\u037B", + "/sigmalunatesymbol": "\u03F2", + "/sigmalunatesymbolgreek": "\u03F2", + "/sihiragana": "\u3057", + "/sikatakana": "\u30B7", + "/sikatakanahalfwidth": "\uFF7C", + "/silhouetteOfJapan": "\u1F5FE", + "/siluqhebrew": "\u05BD", + "/siluqlefthebrew": "\u05BD", + "/similar": "\u223C", + "/sinDot:hb": "\u05C2", + "/sindothebrew": "\u05C2", + "/sinewave": "\u223F", + "/sinh:a": "\u0D85", + "/sinh:aa": "\u0D86", + "/sinh:aae": "\u0D88", + "/sinh:aaesign": "\u0DD1", + "/sinh:aasign": "\u0DCF", + "/sinh:ae": "\u0D87", + "/sinh:aesign": "\u0DD0", + "/sinh:ai": "\u0D93", + "/sinh:aisign": "\u0DDB", + "/sinh:anusvara": "\u0D82", + "/sinh:au": "\u0D96", + "/sinh:ausign": "\u0DDE", + "/sinh:ba": "\u0DB6", + "/sinh:bha": "\u0DB7", + "/sinh:ca": "\u0DA0", + "/sinh:cha": "\u0DA1", + "/sinh:da": "\u0DAF", + "/sinh:dda": "\u0DA9", + "/sinh:ddha": "\u0DAA", + "/sinh:dha": "\u0DB0", + "/sinh:e": "\u0D91", + "/sinh:ee": "\u0D92", + "/sinh:eesign": "\u0DDA", + "/sinh:esign": "\u0DD9", + "/sinh:fa": "\u0DC6", + "/sinh:ga": "\u0D9C", + "/sinh:gha": "\u0D9D", + "/sinh:ha": "\u0DC4", + "/sinh:i": "\u0D89", + "/sinh:ii": "\u0D8A", + "/sinh:iisign": "\u0DD3", + "/sinh:isign": "\u0DD2", + "/sinh:ja": "\u0DA2", + "/sinh:jha": "\u0DA3", + "/sinh:jnya": "\u0DA5", + "/sinh:ka": "\u0D9A", + "/sinh:kha": "\u0D9B", + "/sinh:kunddaliya": "\u0DF4", + "/sinh:la": "\u0DBD", + "/sinh:litheight": "\u0DEE", + "/sinh:lithfive": "\u0DEB", + "/sinh:lithfour": "\u0DEA", + "/sinh:lithnine": "\u0DEF", + "/sinh:lithone": "\u0DE7", + "/sinh:lithseven": "\u0DED", + "/sinh:lithsix": "\u0DEC", + "/sinh:liththree": "\u0DE9", + "/sinh:lithtwo": "\u0DE8", + "/sinh:lithzero": "\u0DE6", + "/sinh:lla": "\u0DC5", + "/sinh:llvocal": "\u0D90", + "/sinh:llvocalsign": "\u0DF3", + "/sinh:lvocal": "\u0D8F", + "/sinh:lvocalsign": "\u0DDF", + "/sinh:ma": "\u0DB8", + "/sinh:mba": "\u0DB9", + "/sinh:na": "\u0DB1", + "/sinh:nda": "\u0DB3", + "/sinh:nga": "\u0D9E", + "/sinh:nna": "\u0DAB", + "/sinh:nndda": "\u0DAC", + "/sinh:nnga": "\u0D9F", + "/sinh:nya": "\u0DA4", + "/sinh:nyja": "\u0DA6", + "/sinh:o": "\u0D94", + "/sinh:oo": "\u0D95", + "/sinh:oosign": "\u0DDD", + "/sinh:osign": "\u0DDC", + "/sinh:pa": "\u0DB4", + "/sinh:pha": "\u0DB5", + "/sinh:ra": "\u0DBB", + "/sinh:rrvocal": "\u0D8E", + "/sinh:rrvocalsign": "\u0DF2", + "/sinh:rvocal": "\u0D8D", + "/sinh:rvocalsign": "\u0DD8", + "/sinh:sa": "\u0DC3", + "/sinh:sha": "\u0DC1", + "/sinh:ssa": "\u0DC2", + "/sinh:ta": "\u0DAD", + "/sinh:tha": "\u0DAE", + "/sinh:tta": "\u0DA7", + "/sinh:ttha": "\u0DA8", + "/sinh:u": "\u0D8B", + "/sinh:usign": "\u0DD4", + "/sinh:uu": "\u0D8C", + "/sinh:uusign": "\u0DD6", + "/sinh:va": "\u0DC0", + "/sinh:virama": "\u0DCA", + "/sinh:visarga": "\u0D83", + "/sinh:ya": "\u0DBA", + "/sinologicaldot": "\uA78F", + "/sinsular": "\uA785", + "/siosacirclekorean": "\u3274", + "/siosaparenkorean": "\u3214", + "/sioscieuckorean": "\u317E", + "/sioscirclekorean": "\u3266", + "/sioskiyeokkorean": "\u317A", + "/sioskorean": "\u3145", + "/siosnieunkorean": "\u317B", + "/siosparenkorean": "\u3206", + "/siospieupkorean": "\u317D", + "/siostikeutkorean": "\u317C", + "/siringusquare": "\u3321", + "/six": "\u0036", + "/six.inferior": "\u2086", + "/six.roman": "\u2165", + "/six.romansmall": "\u2175", + "/six.superior": "\u2076", + "/sixPointedStarMiddleDot": "\u1F52F", + "/sixarabic": "\u0666", + "/sixbengali": "\u09EC", + "/sixcircle": "\u2465", + "/sixcircledbl": "\u24FA", + "/sixcircleinversesansserif": "\u278F", + "/sixcomma": "\u1F107", + "/sixdeva": "\u096C", + "/sixdotsvertical": "\u2E3D", + "/sixfar": "\u06F6", + "/sixgujarati": "\u0AEC", + "/sixgurmukhi": "\u0A6C", + "/sixhackarabic": "\u0666", + "/sixhangzhou": "\u3026", + "/sixideographiccircled": "\u3285", + "/sixideographicparen": "\u3225", + "/sixinferior": "\u2086", + "/sixlateform.roman": "\u2185", + "/sixmonospace": "\uFF16", + "/sixoldstyle": "\uF736", + "/sixparen": "\u2479", + "/sixparenthesized": "\u2479", + "/sixperemspace": "\u2006", + "/sixperiod": "\u248D", + "/sixpersian": "\u06F6", + "/sixroman": "\u2175", + "/sixsuperior": "\u2076", + "/sixteencircle": "\u246F", + "/sixteencircleblack": "\u24F0", + "/sixteencurrencydenominatorbengali": "\u09F9", + "/sixteenparen": "\u2483", + "/sixteenparenthesized": "\u2483", + "/sixteenperiod": "\u2497", + "/sixthai": "\u0E56", + "/sixtycirclesquare": "\u324D", + "/sixtypsquare": "\u1F1A3", + "/sjekomicyr": "\u050D", + "/skiAndSkiBoot": "\u1F3BF", + "/skier": "\u26F7", + "/skull": "\u1F480", + "/skullcrossbones": "\u2620", + "/slash": "\u002F", + "/slashbarfunc": "\u233F", + "/slashmonospace": "\uFF0F", + "/sled": "\u1F6F7", + "/sleeping": "\u1F4A4", + "/sleepingAccommodation": "\u1F6CC", + "/sleepingFace": "\u1F634", + "/sleepyFace": "\u1F62A", + "/sleuthOrSpy": "\u1F575", + "/sliceOfPizza": "\u1F355", + "/slightlyFrowningFace": "\u1F641", + "/slightlySmilingFace": "\u1F642", + "/slong": "\u017F", + "/slongdotaccent": "\u1E9B", + "/slope": "\u2333", + "/slotMachine": "\u1F3B0", + "/smallAirplane": "\u1F6E9", + "/smallBlueDiamond": "\u1F539", + "/smallOrangeDiamond": "\u1F538", + "/smallRedTriangleDOwn": "\u1F53D", + "/smallRedTriangleUp": "\u1F53C", + "/smile": "\u2323", + "/smileface": "\u263A", + "/smilingCatFaceWithHeartShapedEyes": "\u1F63B", + "/smilingCatFaceWithOpenMouth": "\u1F63A", + "/smilingFaceWithHalo": "\u1F607", + "/smilingFaceWithHeartShapedEyes": "\u1F60D", + "/smilingFaceWithHorns": "\u1F608", + "/smilingFaceWithOpenMouth": "\u1F603", + "/smilingFaceWithOpenMouthAndColdSweat": "\u1F605", + "/smilingFaceWithOpenMouthAndSmilingEyes": "\u1F604", + "/smilingFaceWithOpenMouthAndTightlyClosedEyes": "\u1F606", + "/smilingFaceWithSmilingEyes": "\u1F60A", + "/smilingFaceWithSunglasses": "\u1F60E", + "/smilingfaceblack": "\u263B", + "/smilingfacewhite": "\u263A", + "/smirkingFace": "\u1F60F", + "/smll:ampersand": "\uFE60", + "/smll:asterisk": "\uFE61", + "/smll:backslash": "\uFE68", + "/smll:braceleft": "\uFE5B", + "/smll:braceright": "\uFE5C", + "/smll:colon": "\uFE55", + "/smll:comma": "\uFE50", + "/smll:dollar": "\uFE69", + "/smll:emdash": "\uFE58", + "/smll:equal": "\uFE66", + "/smll:exclam": "\uFE57", + "/smll:greater": "\uFE65", + "/smll:hyphen": "\uFE63", + "/smll:ideographiccomma": "\uFE51", + "/smll:less": "\uFE64", + "/smll:numbersign": "\uFE5F", + "/smll:parenthesisleft": "\uFE59", + "/smll:parenthesisright": "\uFE5A", + "/smll:percent": "\uFE6A", + "/smll:period": "\uFE52", + "/smll:plus": "\uFE62", + "/smll:question": "\uFE56", + "/smll:semicolon": "\uFE54", + "/smll:tortoiseshellbracketleft": "\uFE5D", + "/smll:tortoiseshellbracketright": "\uFE5E", + "/smoking": "\u1F6AC", + "/smonospace": "\uFF53", + "/snail": "\u1F40C", + "/snake": "\u1F40D", + "/snowboarder": "\u1F3C2", + "/snowcappedMountain": "\u1F3D4", + "/snowman": "\u2603", + "/snowmanblack": "\u26C7", + "/snowmanoutsnow": "\u26C4", + "/sobliquestroke": "\uA7A9", + "/soccerball": "\u26BD", + "/societyideographiccircled": "\u3293", + "/societyideographicparen": "\u3233", + "/socirclekatakana": "\u32DE", + "/sofPasuq:hb": "\u05C3", + "/sofpasuqhebrew": "\u05C3", + "/softIceCream": "\u1F366", + "/softShellFloppyDisk": "\u1F5AC", + "/softcyr": "\u044C", + "/softhyphen": "\u00AD", + "/softsigncyrillic": "\u044C", + "/softwarefunction": "\u2394", + "/sohiragana": "\u305D", + "/sokatakana": "\u30BD", + "/sokatakanahalfwidth": "\uFF7F", + "/soliduslongoverlaycmb": "\u0338", + "/solidusshortoverlaycmb": "\u0337", + "/solidussubsetreversepreceding": "\u27C8", + "/solidussupersetpreceding": "\u27C9", + "/soonRightwardsArrowAbove": "\u1F51C", + "/sorusithai": "\u0E29", + "/sosalathai": "\u0E28", + "/sosothai": "\u0E0B", + "/sossquare": "\u1F198", + "/sosuathai": "\u0E2A", + "/soundcopyright": "\u2117", + "/space": "\u0020", + "/spacehackarabic": "\u0020", + "/spade": "\u2660", + "/spadeblack": "\u2660", + "/spadesuitblack": "\u2660", + "/spadesuitwhite": "\u2664", + "/spadewhite": "\u2664", + "/spaghetti": "\u1F35D", + "/sparen": "\u24AE", + "/sparenthesized": "\u24AE", + "/sparklingHeart": "\u1F496", + "/speakNoEvilMonkey": "\u1F64A", + "/speaker": "\u1F508", + "/speakerCancellationStroke": "\u1F507", + "/speakerOneSoundWave": "\u1F509", + "/speakerThreeSoundWaves": "\u1F50A", + "/speakingHeadInSilhouette": "\u1F5E3", + "/specialideographiccircled": "\u3295", + "/specialideographicparen": "\u3235", + "/speechBalloon": "\u1F4AC", + "/speedboat": "\u1F6A4", + "/spesmilo": "\u20B7", + "/sphericalangle": "\u2222", + "/spider": "\u1F577", + "/spiderWeb": "\u1F578", + "/spiralCalendarPad": "\u1F5D3", + "/spiralNotePad": "\u1F5D2", + "/spiralShell": "\u1F41A", + "/splashingSweat": "\u1F4A6", + "/sportsMedal": "\u1F3C5", + "/spoutingWhale": "\u1F433", + "/sppl:tildevertical": "\u2E2F", + "/squarebelowcmb": "\u033B", + "/squareblack": "\u25A0", + "/squarebracketleftvertical": "\uFE47", + "/squarebracketrightvertical": "\uFE48", + "/squarecap": "\u2293", + "/squarecc": "\u33C4", + "/squarecm": "\u339D", + "/squarecup": "\u2294", + "/squareddotoperator": "\u22A1", + "/squarediagonalcrosshatchfill": "\u25A9", + "/squaredj": "\u1F190", + "/squaredkey": "\u26BF", + "/squaredminus": "\u229F", + "/squaredplus": "\u229E", + "/squaredsaltire": "\u26DD", + "/squaredtimes": "\u22A0", + "/squarefourcorners": "\u26F6", + "/squarehalfleftblack": "\u25E7", + "/squarehalfrightblack": "\u25E8", + "/squarehorizontalfill": "\u25A4", + "/squareimage": "\u228F", + "/squareimageorequal": "\u2291", + "/squareimageornotequal": "\u22E4", + "/squarekg": "\u338F", + "/squarekm": "\u339E", + "/squarekmcapital": "\u33CE", + "/squareln": "\u33D1", + "/squarelog": "\u33D2", + "/squarelowerdiagonalhalfrightblack": "\u25EA", + "/squaremediumblack": "\u25FC", + "/squaremediumwhite": "\u25FB", + "/squaremg": "\u338E", + "/squaremil": "\u33D5", + "/squaremm": "\u339C", + "/squaremsquared": "\u33A1", + "/squareoriginal": "\u2290", + "/squareoriginalorequal": "\u2292", + "/squareoriginalornotequal": "\u22E5", + "/squareorthogonalcrosshatchfill": "\u25A6", + "/squareraised": "\u2E0B", + "/squaresmallblack": "\u25AA", + "/squaresmallmediumblack": "\u25FE", + "/squaresmallmediumwhite": "\u25FD", + "/squaresmallwhite": "\u25AB", + "/squareupperdiagonalhalfleftblack": "\u25E9", + "/squareupperlefttolowerrightfill": "\u25A7", + "/squareupperrighttolowerleftfill": "\u25A8", + "/squareverticalfill": "\u25A5", + "/squarewhite": "\u25A1", + "/squarewhitebisectinglinevertical": "\u25EB", + "/squarewhitelowerquadrantleft": "\u25F1", + "/squarewhitelowerquadrantright": "\u25F2", + "/squarewhiteround": "\u25A2", + "/squarewhiteupperquadrantleft": "\u25F0", + "/squarewhiteupperquadrantright": "\u25F3", + "/squarewhitewithsmallblack": "\u25A3", + "/squarewhitewithsquaresmallblack": "\u25A3", + "/squishquadfunc": "\u2337", + "/srfullwidth": "\u33DB", + "/srsquare": "\u33DB", + "/ssabengali": "\u09B7", + "/ssadeva": "\u0937", + "/ssagujarati": "\u0AB7", + "/ssangcieuckorean": "\u3149", + "/ssanghieuhkorean": "\u3185", + "/ssangieungkorean": "\u3180", + "/ssangkiyeokkorean": "\u3132", + "/ssangnieunkorean": "\u3165", + "/ssangpieupkorean": "\u3143", + "/ssangsioskorean": "\u3146", + "/ssangtikeutkorean": "\u3138", + "/ssuperior": "\uF6F2", + "/ssupmod": "\u02E2", + "/sswashtail": "\u023F", + "/stackedcommadbl": "\u2E49", + "/stadium": "\u1F3DF", + "/staffofaesculapius": "\u2695", + "/staffofhermes": "\u269A", + "/stampedEnvelope": "\u1F583", + "/star": "\u22C6", + "/starblack": "\u2605", + "/starcrescent": "\u262A", + "/stardiaeresisfunc": "\u2363", + "/starequals": "\u225B", + "/staroperator": "\u22C6", + "/staroutlinedwhite": "\u269D", + "/starwhite": "\u2606", + "/station": "\u1F689", + "/statueOfLiberty": "\u1F5FD", + "/steamLocomotive": "\u1F682", + "/steamingBowl": "\u1F35C", + "/stenographicfullstop": "\u2E3C", + "/sterling": "\u00A3", + "/sterlingmonospace": "\uFFE1", + "/stigma": "\u03DB", + "/stiletildefunc": "\u236D", + "/stockChart": "\u1F5E0", + "/stockideographiccircled": "\u3291", + "/stockideographicparen": "\u3231", + "/stopabove": "\u06EB", + "/stopbelow": "\u06EA", + "/straightRuler": "\u1F4CF", + "/straightness": "\u23E4", + "/strawberry": "\u1F353", + "/stresslowtonemod": "\uA721", + "/stresstonemod": "\uA720", + "/strictlyequivalent": "\u2263", + "/strokelongoverlaycmb": "\u0336", + "/strokeshortoverlaycmb": "\u0335", + "/studioMicrophone": "\u1F399", + "/studyideographiccircled": "\u32AB", + "/studyideographicparen": "\u323B", + "/stupa": "\u1F6D3", + "/subscriptalef": "\u0656", + "/subset": "\u2282", + "/subsetdbl": "\u22D0", + "/subsetnotequal": "\u228A", + "/subsetorequal": "\u2286", + "/succeeds": "\u227B", + "/succeedsbutnotequivalent": "\u22E9", + "/succeedsorequal": "\u227D", + "/succeedsorequivalent": "\u227F", + "/succeedsunderrelation": "\u22B1", + "/suchthat": "\u220B", + "/sucirclekatakana": "\u32DC", + "/suhiragana": "\u3059", + "/suitableideographiccircled": "\u329C", + "/sukatakana": "\u30B9", + "/sukatakanahalfwidth": "\uFF7D", + "/sukumendutvowel": "\uA9B9", + "/sukunIsol": "\uFE7E", + "/sukunMedi": "\uFE7F", + "/sukunarabic": "\u0652", + "/sukuvowel": "\uA9B8", + "/summation": "\u2211", + "/summationbottom": "\u23B3", + "/summationdblstruck": "\u2140", + "/summationtop": "\u23B2", + "/sun": "\u263C", + "/sunFace": "\u1F31E", + "/sunbehindcloud": "\u26C5", + "/sunflower": "\u1F33B", + "/sunideographiccircled": "\u3290", + "/sunideographicparen": "\u3230", + "/sunraysblack": "\u2600", + "/sunrayswhite": "\u263C", + "/sunrise": "\u1F305", + "/sunriseOverMountains": "\u1F304", + "/sunsetOverBuildings": "\u1F307", + "/superset": "\u2283", + "/supersetnotequal": "\u228B", + "/supersetorequal": "\u2287", + "/superviseideographiccircled": "\u32AC", + "/superviseideographicparen": "\u323C", + "/surfer": "\u1F3C4", + "/sushi": "\u1F363", + "/suspensionRailway": "\u1F69F", + "/suspensiondbl": "\u2E44", + "/svfullwidth": "\u33DC", + "/svsquare": "\u33DC", + "/swatchtop": "\u23F1", + "/swimmer": "\u1F3CA", + "/swungdash": "\u2053", + "/symbolabovethreedotsabove": "\uFBB6", + "/symbolbelowthreedotsabove": "\uFBB7", + "/symboldotabove": "\uFBB2", + "/symboldotbelow": "\uFBB3", + "/symboldoubleverticalbarbelow": "\uFBBC", + "/symbolfourdotsabove": "\uFBBA", + "/symbolfourdotsbelow": "\uFBBB", + "/symbolpointingabovedownthreedotsabove": "\uFBB8", + "/symbolpointingbelowdownthreedotsabove": "\uFBB9", + "/symbolring": "\uFBBF", + "/symboltahabovesmall": "\uFBC0", + "/symboltahbelowsmall": "\uFBC1", + "/symboltwodotsabove": "\uFBB4", + "/symboltwodotsbelow": "\uFBB5", + "/symboltwodotsverticallyabove": "\uFBBD", + "/symboltwodotsverticallybelow": "\uFBBE", + "/symmetry": "\u232F", + "/synagogue": "\u1F54D", + "/syouwaerasquare": "\u337C", + "/syringe": "\u1F489", + "/t": "\u0074", + "/t-shirt": "\u1F455", + "/t.inferior": "\u209C", + "/tabengali": "\u09A4", + "/tableTennisPaddleAndBall": "\u1F3D3", + "/tacirclekatakana": "\u32DF", + "/tackcircleaboveup": "\u27DF", + "/tackdiaeresisupfunc": "\u2361", + "/tackdown": "\u22A4", + "/tackdownmod": "\u02D5", + "/tackjotdownfunc": "\u234E", + "/tackjotupfunc": "\u2355", + "/tackleft": "\u22A3", + "/tackleftright": "\u27DB", + "/tackoverbarupfunc": "\u2351", + "/tackright": "\u22A2", + "/tackunderlinedownfunc": "\u234A", + "/tackup": "\u22A5", + "/tackupmod": "\u02D4", + "/taco": "\u1F32E", + "/tadeva": "\u0924", + "/tagujarati": "\u0AA4", + "/tagurmukhi": "\u0A24", + "/tah": "\u0637", + "/tah.fina": "\uFEC2", + "/tah.init": "\uFEC3", + "/tah.init_alefmaksura.fina": "\uFCF5", + "/tah.init_hah.fina": "\uFC26", + "/tah.init_hah.medi": "\uFCB8", + "/tah.init_meem.fina": "\uFC27", + "/tah.init_meem.medi": "\uFD33", + "/tah.init_meem.medi_hah.medi": "\uFD72", + "/tah.init_meem.medi_meem.medi": "\uFD73", + "/tah.init_yeh.fina": "\uFCF6", + "/tah.isol": "\uFEC1", + "/tah.medi": "\uFEC4", + "/tah.medi_alefmaksura.fina": "\uFD11", + "/tah.medi_meem.medi": "\uFD3A", + "/tah.medi_meem.medi_hah.fina": "\uFD71", + "/tah.medi_meem.medi_yeh.fina": "\uFD74", + "/tah.medi_yeh.fina": "\uFD12", + "/tahabove": "\u0615", + "/taharabic": "\u0637", + "/tahfinalarabic": "\uFEC2", + "/tahinitialarabic": "\uFEC3", + "/tahiragana": "\u305F", + "/tahmedialarabic": "\uFEC4", + "/tahthreedotsabove": "\u069F", + "/taisyouerasquare": "\u337D", + "/takatakana": "\u30BF", + "/takatakanahalfwidth": "\uFF80", + "/takhallus": "\u0614", + "/talingvowel": "\uA9BA", + "/taml:a": "\u0B85", + "/taml:aa": "\u0B86", + "/taml:aasign": "\u0BBE", + "/taml:ai": "\u0B90", + "/taml:aisign": "\u0BC8", + "/taml:anusvarasign": "\u0B82", + "/taml:asabovesign": "\u0BF8", + "/taml:au": "\u0B94", + "/taml:aulengthmark": "\u0BD7", + "/taml:ausign": "\u0BCC", + "/taml:ca": "\u0B9A", + "/taml:creditsign": "\u0BF7", + "/taml:daysign": "\u0BF3", + "/taml:debitsign": "\u0BF6", + "/taml:e": "\u0B8E", + "/taml:ee": "\u0B8F", + "/taml:eesign": "\u0BC7", + "/taml:eight": "\u0BEE", + "/taml:esign": "\u0BC6", + "/taml:five": "\u0BEB", + "/taml:four": "\u0BEA", + "/taml:ha": "\u0BB9", + "/taml:i": "\u0B87", + "/taml:ii": "\u0B88", + "/taml:iisign": "\u0BC0", + "/taml:isign": "\u0BBF", + "/taml:ja": "\u0B9C", + "/taml:ka": "\u0B95", + "/taml:la": "\u0BB2", + "/taml:lla": "\u0BB3", + "/taml:llla": "\u0BB4", + "/taml:ma": "\u0BAE", + "/taml:monthsign": "\u0BF4", + "/taml:na": "\u0BA8", + "/taml:nga": "\u0B99", + "/taml:nine": "\u0BEF", + "/taml:nna": "\u0BA3", + "/taml:nnna": "\u0BA9", + "/taml:nya": "\u0B9E", + "/taml:o": "\u0B92", + "/taml:om": "\u0BD0", + "/taml:one": "\u0BE7", + "/taml:onehundred": "\u0BF1", + "/taml:onethousand": "\u0BF2", + "/taml:oo": "\u0B93", + "/taml:oosign": "\u0BCB", + "/taml:osign": "\u0BCA", + "/taml:pa": "\u0BAA", + "/taml:ra": "\u0BB0", + "/taml:rra": "\u0BB1", + "/taml:rupeesign": "\u0BF9", + "/taml:sa": "\u0BB8", + "/taml:seven": "\u0BED", + "/taml:sha": "\u0BB6", + "/taml:sign": "\u0BFA", + "/taml:six": "\u0BEC", + "/taml:ssa": "\u0BB7", + "/taml:ta": "\u0BA4", + "/taml:ten": "\u0BF0", + "/taml:three": "\u0BE9", + "/taml:tta": "\u0B9F", + "/taml:two": "\u0BE8", + "/taml:u": "\u0B89", + "/taml:usign": "\u0BC1", + "/taml:uu": "\u0B8A", + "/taml:uusign": "\u0BC2", + "/taml:va": "\u0BB5", + "/taml:viramasign": "\u0BCD", + "/taml:visargasign": "\u0B83", + "/taml:ya": "\u0BAF", + "/taml:yearsign": "\u0BF5", + "/taml:zero": "\u0BE6", + "/tamurda": "\uA9A1", + "/tanabataTree": "\u1F38B", + "/tangerine": "\u1F34A", + "/tapeCartridge": "\u1F5AD", + "/tarungvowel": "\uA9B4", + "/tatweelFathatanAbove": "\uFE71", + "/tatweelarabic": "\u0640", + "/tau": "\u03C4", + "/taurus": "\u2649", + "/tav": "\u05EA", + "/tav:hb": "\u05EA", + "/tavdages": "\uFB4A", + "/tavdagesh": "\uFB4A", + "/tavdageshhebrew": "\uFB4A", + "/tavhebrew": "\u05EA", + "/tavwide:hb": "\uFB28", + "/tavwithdagesh:hb": "\uFB4A", + "/taxi": "\u1F695", + "/tbar": "\u0167", + "/tbopomofo": "\u310A", + "/tcaron": "\u0165", + "/tccurl": "\u02A8", + "/tcedilla": "\u0163", + "/tcheh": "\u0686", + "/tcheh.fina": "\uFB7B", + "/tcheh.init": "\uFB7C", + "/tcheh.isol": "\uFB7A", + "/tcheh.medi": "\uFB7D", + "/tcheharabic": "\u0686", + "/tchehdotabove": "\u06BF", + "/tcheheh": "\u0687", + "/tcheheh.fina": "\uFB7F", + "/tcheheh.init": "\uFB80", + "/tcheheh.isol": "\uFB7E", + "/tcheheh.medi": "\uFB81", + "/tchehfinalarabic": "\uFB7B", + "/tchehinitialarabic": "\uFB7C", + "/tchehmedialarabic": "\uFB7D", + "/tchehmeeminitialarabic": "\uFB7C", + "/tcircle": "\u24E3", + "/tcircumflexbelow": "\u1E71", + "/tcommaaccent": "\u0163", + "/tcurl": "\u0236", + "/tdieresis": "\u1E97", + "/tdot": "\u1E6B", + "/tdotaccent": "\u1E6B", + "/tdotbelow": "\u1E6D", + "/teacupOutHandle": "\u1F375", + "/tear-offCalendar": "\u1F4C6", + "/tecirclekatakana": "\u32E2", + "/tecyr": "\u0442", + "/tecyrillic": "\u0442", + "/tedescendercyrillic": "\u04AD", + "/teh": "\u062A", + "/teh.fina": "\uFE96", + "/teh.init": "\uFE97", + "/teh.init_alefmaksura.fina": "\uFC0F", + "/teh.init_hah.fina": "\uFC0C", + "/teh.init_hah.medi": "\uFCA2", + "/teh.init_hah.medi_jeem.medi": "\uFD52", + "/teh.init_hah.medi_meem.medi": "\uFD53", + "/teh.init_heh.medi": "\uFCA5", + "/teh.init_jeem.fina": "\uFC0B", + "/teh.init_jeem.medi": "\uFCA1", + "/teh.init_jeem.medi_meem.medi": "\uFD50", + "/teh.init_khah.fina": "\uFC0D", + "/teh.init_khah.medi": "\uFCA3", + "/teh.init_khah.medi_meem.medi": "\uFD54", + "/teh.init_meem.fina": "\uFC0E", + "/teh.init_meem.medi": "\uFCA4", + "/teh.init_meem.medi_hah.medi": "\uFD56", + "/teh.init_meem.medi_jeem.medi": "\uFD55", + "/teh.init_meem.medi_khah.medi": "\uFD57", + "/teh.init_yeh.fina": "\uFC10", + "/teh.isol": "\uFE95", + "/teh.medi": "\uFE98", + "/teh.medi_alefmaksura.fina": "\uFC74", + "/teh.medi_hah.medi_jeem.fina": "\uFD51", + "/teh.medi_heh.medi": "\uFCE4", + "/teh.medi_jeem.medi_alefmaksura.fina": "\uFDA0", + "/teh.medi_jeem.medi_yeh.fina": "\uFD9F", + "/teh.medi_khah.medi_alefmaksura.fina": "\uFDA2", + "/teh.medi_khah.medi_yeh.fina": "\uFDA1", + "/teh.medi_meem.fina": "\uFC72", + "/teh.medi_meem.medi": "\uFCE3", + "/teh.medi_meem.medi_alefmaksura.fina": "\uFDA4", + "/teh.medi_meem.medi_yeh.fina": "\uFDA3", + "/teh.medi_noon.fina": "\uFC73", + "/teh.medi_reh.fina": "\uFC70", + "/teh.medi_yeh.fina": "\uFC75", + "/teh.medi_zain.fina": "\uFC71", + "/teharabic": "\u062A", + "/tehdownthreedotsabove": "\u067D", + "/teheh": "\u067F", + "/teheh.fina": "\uFB63", + "/teheh.init": "\uFB64", + "/teheh.isol": "\uFB62", + "/teheh.medi": "\uFB65", + "/tehfinalarabic": "\uFE96", + "/tehhahinitialarabic": "\uFCA2", + "/tehhahisolatedarabic": "\uFC0C", + "/tehinitialarabic": "\uFE97", + "/tehiragana": "\u3066", + "/tehjeeminitialarabic": "\uFCA1", + "/tehjeemisolatedarabic": "\uFC0B", + "/tehmarbuta": "\u0629", + "/tehmarbuta.fina": "\uFE94", + "/tehmarbuta.isol": "\uFE93", + "/tehmarbutaarabic": "\u0629", + "/tehmarbutafinalarabic": "\uFE94", + "/tehmarbutagoal": "\u06C3", + "/tehmedialarabic": "\uFE98", + "/tehmeeminitialarabic": "\uFCA4", + "/tehmeemisolatedarabic": "\uFC0E", + "/tehnoonfinalarabic": "\uFC73", + "/tehring": "\u067C", + "/tekatakana": "\u30C6", + "/tekatakanahalfwidth": "\uFF83", + "/telephone": "\u2121", + "/telephoneOnTopOfModem": "\u1F580", + "/telephoneReceiver": "\u1F4DE", + "/telephoneReceiverPage": "\u1F57C", + "/telephoneblack": "\u260E", + "/telephonerecorder": "\u2315", + "/telephonewhite": "\u260F", + "/telescope": "\u1F52D", + "/television": "\u1F4FA", + "/telishaGedolah:hb": "\u05A0", + "/telishaQetannah:hb": "\u05A9", + "/telishagedolahebrew": "\u05A0", + "/telishaqetanahebrew": "\u05A9", + "/telu:a": "\u0C05", + "/telu:aa": "\u0C06", + "/telu:aasign": "\u0C3E", + "/telu:ai": "\u0C10", + "/telu:ailengthmark": "\u0C56", + "/telu:aisign": "\u0C48", + "/telu:anusvarasign": "\u0C02", + "/telu:au": "\u0C14", + "/telu:ausign": "\u0C4C", + "/telu:avagrahasign": "\u0C3D", + "/telu:ba": "\u0C2C", + "/telu:bha": "\u0C2D", + "/telu:bindusigncandra": "\u0C01", + "/telu:ca": "\u0C1A", + "/telu:cha": "\u0C1B", + "/telu:combiningbinduabovesigncandra": "\u0C00", + "/telu:da": "\u0C26", + "/telu:dda": "\u0C21", + "/telu:ddha": "\u0C22", + "/telu:dha": "\u0C27", + "/telu:dza": "\u0C59", + "/telu:e": "\u0C0E", + "/telu:ee": "\u0C0F", + "/telu:eesign": "\u0C47", + "/telu:eight": "\u0C6E", + "/telu:esign": "\u0C46", + "/telu:five": "\u0C6B", + "/telu:four": "\u0C6A", + "/telu:fractiononeforevenpowersoffour": "\u0C7C", + "/telu:fractiononeforoddpowersoffour": "\u0C79", + "/telu:fractionthreeforevenpowersoffour": "\u0C7E", + "/telu:fractionthreeforoddpowersoffour": "\u0C7B", + "/telu:fractiontwoforevenpowersoffour": "\u0C7D", + "/telu:fractiontwoforoddpowersoffour": "\u0C7A", + "/telu:fractionzeroforoddpowersoffour": "\u0C78", + "/telu:ga": "\u0C17", + "/telu:gha": "\u0C18", + "/telu:ha": "\u0C39", + "/telu:i": "\u0C07", + "/telu:ii": "\u0C08", + "/telu:iisign": "\u0C40", + "/telu:isign": "\u0C3F", + "/telu:ja": "\u0C1C", + "/telu:jha": "\u0C1D", + "/telu:ka": "\u0C15", + "/telu:kha": "\u0C16", + "/telu:la": "\u0C32", + "/telu:lengthmark": "\u0C55", + "/telu:lla": "\u0C33", + "/telu:llla": "\u0C34", + "/telu:llsignvocal": "\u0C63", + "/telu:llvocal": "\u0C61", + "/telu:lsignvocal": "\u0C62", + "/telu:lvocal": "\u0C0C", + "/telu:ma": "\u0C2E", + "/telu:na": "\u0C28", + "/telu:nga": "\u0C19", + "/telu:nine": "\u0C6F", + "/telu:nna": "\u0C23", + "/telu:nya": "\u0C1E", + "/telu:o": "\u0C12", + "/telu:one": "\u0C67", + "/telu:oo": "\u0C13", + "/telu:oosign": "\u0C4B", + "/telu:osign": "\u0C4A", + "/telu:pa": "\u0C2A", + "/telu:pha": "\u0C2B", + "/telu:ra": "\u0C30", + "/telu:rra": "\u0C31", + "/telu:rrra": "\u0C5A", + "/telu:rrsignvocal": "\u0C44", + "/telu:rrvocal": "\u0C60", + "/telu:rsignvocal": "\u0C43", + "/telu:rvocal": "\u0C0B", + "/telu:sa": "\u0C38", + "/telu:seven": "\u0C6D", + "/telu:sha": "\u0C36", + "/telu:six": "\u0C6C", + "/telu:ssa": "\u0C37", + "/telu:ta": "\u0C24", + "/telu:tha": "\u0C25", + "/telu:three": "\u0C69", + "/telu:tsa": "\u0C58", + "/telu:tta": "\u0C1F", + "/telu:ttha": "\u0C20", + "/telu:tuumusign": "\u0C7F", + "/telu:two": "\u0C68", + "/telu:u": "\u0C09", + "/telu:usign": "\u0C41", + "/telu:uu": "\u0C0A", + "/telu:uusign": "\u0C42", + "/telu:va": "\u0C35", + "/telu:viramasign": "\u0C4D", + "/telu:visargasign": "\u0C03", + "/telu:ya": "\u0C2F", + "/telu:zero": "\u0C66", + "/ten.roman": "\u2169", + "/ten.romansmall": "\u2179", + "/tencircle": "\u2469", + "/tencircledbl": "\u24FE", + "/tencirclesquare": "\u3248", + "/tenge": "\u20B8", + "/tenhangzhou": "\u3038", + "/tenideographiccircled": "\u3289", + "/tenideographicparen": "\u3229", + "/tennisRacquetAndBall": "\u1F3BE", + "/tenparen": "\u247D", + "/tenparenthesized": "\u247D", + "/tenperiod": "\u2491", + "/tenroman": "\u2179", + "/tent": "\u26FA", + "/tenthousand.roman": "\u2182", + "/tesh": "\u02A7", + "/tet": "\u05D8", + "/tet:hb": "\u05D8", + "/tetailcyr": "\u04AD", + "/tetdagesh": "\uFB38", + "/tetdageshhebrew": "\uFB38", + "/tethebrew": "\u05D8", + "/tetrasememetrical": "\u23D8", + "/tetsecyr": "\u04B5", + "/tetsecyrillic": "\u04B5", + "/tetwithdagesh:hb": "\uFB38", + "/tevir:hb": "\u059B", + "/tevirhebrew": "\u059B", + "/tevirlefthebrew": "\u059B", + "/thabengali": "\u09A5", + "/thadeva": "\u0925", + "/thagujarati": "\u0AA5", + "/thagurmukhi": "\u0A25", + "/thai:angkhankhu": "\u0E5A", + "/thai:baht": "\u0E3F", + "/thai:bobaimai": "\u0E1A", + "/thai:chochan": "\u0E08", + "/thai:chochang": "\u0E0A", + "/thai:choching": "\u0E09", + "/thai:chochoe": "\u0E0C", + "/thai:dochada": "\u0E0E", + "/thai:dodek": "\u0E14", + "/thai:eight": "\u0E58", + "/thai:five": "\u0E55", + "/thai:fofa": "\u0E1D", + "/thai:fofan": "\u0E1F", + "/thai:fongman": "\u0E4F", + "/thai:four": "\u0E54", + "/thai:hohip": "\u0E2B", + "/thai:honokhuk": "\u0E2E", + "/thai:khokhai": "\u0E02", + "/thai:khokhon": "\u0E05", + "/thai:khokhuat": "\u0E03", + "/thai:khokhwai": "\u0E04", + "/thai:khomut": "\u0E5B", + "/thai:khorakhang": "\u0E06", + "/thai:kokai": "\u0E01", + "/thai:lakkhangyao": "\u0E45", + "/thai:lochula": "\u0E2C", + "/thai:loling": "\u0E25", + "/thai:lu": "\u0E26", + "/thai:maichattawa": "\u0E4B", + "/thai:maiek": "\u0E48", + "/thai:maihan-akat": "\u0E31", + "/thai:maitaikhu": "\u0E47", + "/thai:maitho": "\u0E49", + "/thai:maitri": "\u0E4A", + "/thai:maiyamok": "\u0E46", + "/thai:moma": "\u0E21", + "/thai:ngongu": "\u0E07", + "/thai:nikhahit": "\u0E4D", + "/thai:nine": "\u0E59", + "/thai:nonen": "\u0E13", + "/thai:nonu": "\u0E19", + "/thai:oang": "\u0E2D", + "/thai:one": "\u0E51", + "/thai:paiyannoi": "\u0E2F", + "/thai:phinthu": "\u0E3A", + "/thai:phophan": "\u0E1E", + "/thai:phophung": "\u0E1C", + "/thai:phosamphao": "\u0E20", + "/thai:popla": "\u0E1B", + "/thai:rorua": "\u0E23", + "/thai:ru": "\u0E24", + "/thai:saraa": "\u0E30", + "/thai:saraaa": "\u0E32", + "/thai:saraae": "\u0E41", + "/thai:saraaimaimalai": "\u0E44", + "/thai:saraaimaimuan": "\u0E43", + "/thai:saraam": "\u0E33", + "/thai:sarae": "\u0E40", + "/thai:sarai": "\u0E34", + "/thai:saraii": "\u0E35", + "/thai:sarao": "\u0E42", + "/thai:sarau": "\u0E38", + "/thai:saraue": "\u0E36", + "/thai:sarauee": "\u0E37", + "/thai:sarauu": "\u0E39", + "/thai:seven": "\u0E57", + "/thai:six": "\u0E56", + "/thai:sorusi": "\u0E29", + "/thai:sosala": "\u0E28", + "/thai:soso": "\u0E0B", + "/thai:sosua": "\u0E2A", + "/thai:thanthakhat": "\u0E4C", + "/thai:thonangmontho": "\u0E11", + "/thai:thophuthao": "\u0E12", + "/thai:thothahan": "\u0E17", + "/thai:thothan": "\u0E10", + "/thai:thothong": "\u0E18", + "/thai:thothung": "\u0E16", + "/thai:three": "\u0E53", + "/thai:topatak": "\u0E0F", + "/thai:totao": "\u0E15", + "/thai:two": "\u0E52", + "/thai:wowaen": "\u0E27", + "/thai:yamakkan": "\u0E4E", + "/thai:yoyak": "\u0E22", + "/thai:yoying": "\u0E0D", + "/thai:zero": "\u0E50", + "/thal": "\u0630", + "/thal.fina": "\uFEAC", + "/thal.init_superscriptalef.fina": "\uFC5B", + "/thal.isol": "\uFEAB", + "/thalarabic": "\u0630", + "/thalfinalarabic": "\uFEAC", + "/thanthakhatlowleftthai": "\uF898", + "/thanthakhatlowrightthai": "\uF897", + "/thanthakhatthai": "\u0E4C", + "/thanthakhatupperleftthai": "\uF896", + "/theh": "\u062B", + "/theh.fina": "\uFE9A", + "/theh.init": "\uFE9B", + "/theh.init_alefmaksura.fina": "\uFC13", + "/theh.init_jeem.fina": "\uFC11", + "/theh.init_meem.fina": "\uFC12", + "/theh.init_meem.medi": "\uFCA6", + "/theh.init_yeh.fina": "\uFC14", + "/theh.isol": "\uFE99", + "/theh.medi": "\uFE9C", + "/theh.medi_alefmaksura.fina": "\uFC7A", + "/theh.medi_heh.medi": "\uFCE6", + "/theh.medi_meem.fina": "\uFC78", + "/theh.medi_meem.medi": "\uFCE5", + "/theh.medi_noon.fina": "\uFC79", + "/theh.medi_reh.fina": "\uFC76", + "/theh.medi_yeh.fina": "\uFC7B", + "/theh.medi_zain.fina": "\uFC77", + "/theharabic": "\u062B", + "/thehfinalarabic": "\uFE9A", + "/thehinitialarabic": "\uFE9B", + "/thehmedialarabic": "\uFE9C", + "/thereexists": "\u2203", + "/therefore": "\u2234", + "/thermometer": "\u1F321", + "/theta": "\u03B8", + "/theta.math": "\u03D1", + "/theta1": "\u03D1", + "/thetasymbolgreek": "\u03D1", + "/thieuthacirclekorean": "\u3279", + "/thieuthaparenkorean": "\u3219", + "/thieuthcirclekorean": "\u326B", + "/thieuthkorean": "\u314C", + "/thieuthparenkorean": "\u320B", + "/thinspace": "\u2009", + "/thirteencircle": "\u246C", + "/thirteencircleblack": "\u24ED", + "/thirteenparen": "\u2480", + "/thirteenparenthesized": "\u2480", + "/thirteenperiod": "\u2494", + "/thirtycircle": "\u325A", + "/thirtycirclesquare": "\u324A", + "/thirtyeightcircle": "\u32B3", + "/thirtyfivecircle": "\u325F", + "/thirtyfourcircle": "\u325E", + "/thirtyhangzhou": "\u303A", + "/thirtyninecircle": "\u32B4", + "/thirtyonecircle": "\u325B", + "/thirtysevencircle": "\u32B2", + "/thirtysixcircle": "\u32B1", + "/thirtythreecircle": "\u325D", + "/thirtytwocircle": "\u325C", + "/thonangmonthothai": "\u0E11", + "/thook": "\u01AD", + "/thophuthaothai": "\u0E12", + "/thorn": "\u00FE", + "/thornstroke": "\uA765", + "/thornstrokedescender": "\uA767", + "/thothahanthai": "\u0E17", + "/thothanthai": "\u0E10", + "/thothongthai": "\u0E18", + "/thothungthai": "\u0E16", + "/thoughtBalloon": "\u1F4AD", + "/thousandcyrillic": "\u0482", + "/thousandscyr": "\u0482", + "/thousandsseparator": "\u066C", + "/thousandsseparatorarabic": "\u066C", + "/thousandsseparatorpersian": "\u066C", + "/three": "\u0033", + "/three.inferior": "\u2083", + "/three.roman": "\u2162", + "/three.romansmall": "\u2172", + "/threeButtonMouse": "\u1F5B1", + "/threeNetworkedComputers": "\u1F5A7", + "/threeRaysAbove": "\u1F5E4", + "/threeRaysBelow": "\u1F5E5", + "/threeRaysLeft": "\u1F5E6", + "/threeRaysRight": "\u1F5E7", + "/threeSpeechBubbles": "\u1F5EB", + "/threearabic": "\u0663", + "/threebengali": "\u09E9", + "/threecircle": "\u2462", + "/threecircledbl": "\u24F7", + "/threecircleinversesansserif": "\u278C", + "/threecomma": "\u1F104", + "/threedeva": "\u0969", + "/threedimensionalangle": "\u27C0", + "/threedotpunctuation": "\u2056", + "/threedotsaboveabove": "\u06DB", + "/threedsquare": "\u1F19B", + "/threeeighths": "\u215C", + "/threefar": "\u06F3", + "/threefifths": "\u2157", + "/threegujarati": "\u0AE9", + "/threegurmukhi": "\u0A69", + "/threehackarabic": "\u0663", + "/threehangzhou": "\u3023", + "/threeideographiccircled": "\u3282", + "/threeideographicparen": "\u3222", + "/threeinferior": "\u2083", + "/threelinesconvergingleft": "\u269F", + "/threelinesconvergingright": "\u269E", + "/threemonospace": "\uFF13", + "/threenumeratorbengali": "\u09F6", + "/threeoldstyle": "\uF733", + "/threeparen": "\u2476", + "/threeparenthesized": "\u2476", + "/threeperemspace": "\u2004", + "/threeperiod": "\u248A", + "/threepersian": "\u06F3", + "/threequarters": "\u00BE", + "/threequartersemdash": "\uF6DE", + "/threerightarrows": "\u21F6", + "/threeroman": "\u2172", + "/threesuperior": "\u00B3", + "/threethai": "\u0E53", + "/thumbsDownSign": "\u1F44E", + "/thumbsUpSign": "\u1F44D", + "/thundercloudrain": "\u26C8", + "/thunderstorm": "\u2608", + "/thzfullwidth": "\u3394", + "/thzsquare": "\u3394", + "/tibt:AA": "\u0F60", + "/tibt:a": "\u0F68", + "/tibt:aavowelsign": "\u0F71", + "/tibt:angkhanggyasmark": "\u0F3D", + "/tibt:angkhanggyonmark": "\u0F3C", + "/tibt:astrologicalkhyudpasign": "\u0F18", + "/tibt:astrologicalsdongtshugssign": "\u0F19", + "/tibt:astrologicalsgragcancharrtagssign": "\u0F17", + "/tibt:asubjoined": "\u0FB8", + "/tibt:ba": "\u0F56", + "/tibt:basubjoined": "\u0FA6", + "/tibt:bha": "\u0F57", + "/tibt:bhasubjoined": "\u0FA7", + "/tibt:bkashogyigmgomark": "\u0F0A", + "/tibt:brdarnyingyigmgomdunmainitialmark": "\u0FD3", + "/tibt:brdarnyingyigmgosgabmaclosingmark": "\u0FD4", + "/tibt:bsdusrtagsmark": "\u0F34", + "/tibt:bskashoggimgorgyanmark": "\u0FD0", + "/tibt:bskuryigmgomark": "\u0F09", + "/tibt:ca": "\u0F45", + "/tibt:cangteucantillationsign": "\u0FC2", + "/tibt:caretdzudrtagsbzhimigcanmark": "\u0F36", + "/tibt:caretdzudrtagsmelongcanmark": "\u0F13", + "/tibt:caretyigmgophurshadmamark": "\u0F06", + "/tibt:casubjoined": "\u0F95", + "/tibt:cha": "\u0F46", + "/tibt:chadrtagslogotypesign": "\u0F15", + "/tibt:chasubjoined": "\u0F96", + "/tibt:chemgomark": "\u0F38", + "/tibt:da": "\u0F51", + "/tibt:dasubjoined": "\u0FA1", + "/tibt:dda": "\u0F4C", + "/tibt:ddasubjoined": "\u0F9C", + "/tibt:ddha": "\u0F4D", + "/tibt:ddhasubjoined": "\u0F9D", + "/tibt:delimitertshegbstarmark": "\u0F0C", + "/tibt:dha": "\u0F52", + "/tibt:dhasubjoined": "\u0FA2", + "/tibt:drilbusymbol": "\u0FC4", + "/tibt:dza": "\u0F5B", + "/tibt:dzasubjoined": "\u0FAB", + "/tibt:dzha": "\u0F5C", + "/tibt:dzhasubjoined": "\u0FAC", + "/tibt:eevowelsign": "\u0F7B", + "/tibt:eight": "\u0F28", + "/tibt:evowelsign": "\u0F7A", + "/tibt:five": "\u0F25", + "/tibt:four": "\u0F24", + "/tibt:ga": "\u0F42", + "/tibt:gasubjoined": "\u0F92", + "/tibt:gha": "\u0F43", + "/tibt:ghasubjoined": "\u0F93", + "/tibt:grucanrgyingssign": "\u0F8A", + "/tibt:grumedrgyingssign": "\u0F8B", + "/tibt:gtertshegmark": "\u0F14", + "/tibt:gteryigmgotruncatedamark": "\u0F01", + "/tibt:gteryigmgoumgtertshegmamark": "\u0F03", + "/tibt:gteryigmgoumrnambcadmamark": "\u0F02", + "/tibt:gugrtagsgyasmark": "\u0F3B", + "/tibt:gugrtagsgyonmark": "\u0F3A", + "/tibt:ha": "\u0F67", + "/tibt:halantamark": "\u0F84", + "/tibt:halfeight": "\u0F31", + "/tibt:halffive": "\u0F2E", + "/tibt:halffour": "\u0F2D", + "/tibt:halfnine": "\u0F32", + "/tibt:halfone": "\u0F2A", + "/tibt:halfseven": "\u0F30", + "/tibt:halfsix": "\u0F2F", + "/tibt:halfthree": "\u0F2C", + "/tibt:halftwo": "\u0F2B", + "/tibt:halfzero": "\u0F33", + "/tibt:hasubjoined": "\u0FB7", + "/tibt:heavybeatcantillationsign": "\u0FC0", + "/tibt:iivowelsign": "\u0F73", + "/tibt:intersyllabictshegmark": "\u0F0B", + "/tibt:invertedmchucansign": "\u0F8C", + "/tibt:invertedmchucansubjoinedsign": "\u0F8F", + "/tibt:ivowelsign": "\u0F72", + "/tibt:ja": "\u0F47", + "/tibt:jasubjoined": "\u0F97", + "/tibt:ka": "\u0F40", + "/tibt:kasubjoined": "\u0F90", + "/tibt:kha": "\u0F41", + "/tibt:khasubjoined": "\u0F91", + "/tibt:kka": "\u0F6B", + "/tibt:kssa": "\u0F69", + "/tibt:kssasubjoined": "\u0FB9", + "/tibt:kurukha": "\u0FBE", + "/tibt:kurukhabzhimigcan": "\u0FBF", + "/tibt:la": "\u0F63", + "/tibt:lasubjoined": "\u0FB3", + "/tibt:lcetsacansign": "\u0F88", + "/tibt:lcetsacansubjoinedsign": "\u0F8D", + "/tibt:lcirtagssign": "\u0F86", + "/tibt:leadingmchanrtagsmark": "\u0FD9", + "/tibt:lhagrtagslogotypesign": "\u0F16", + "/tibt:lightbeatcantillationsign": "\u0FC1", + "/tibt:llvocalicvowelsign": "\u0F79", + "/tibt:lvocalicvowelsign": "\u0F78", + "/tibt:ma": "\u0F58", + "/tibt:martshessign": "\u0F3F", + "/tibt:masubjoined": "\u0FA8", + "/tibt:mchucansign": "\u0F89", + "/tibt:mchucansubjoinedsign": "\u0F8E", + "/tibt:mnyamyiggimgorgyanmark": "\u0FD1", + "/tibt:na": "\u0F53", + "/tibt:nasubjoined": "\u0FA3", + "/tibt:nga": "\u0F44", + "/tibt:ngasbzungnyizlamark": "\u0F35", + "/tibt:ngasbzungsgorrtagsmark": "\u0F37", + "/tibt:ngasubjoined": "\u0F94", + "/tibt:nine": "\u0F29", + "/tibt:nna": "\u0F4E", + "/tibt:nnasubjoined": "\u0F9E", + "/tibt:norbubzhikhyilsymbol": "\u0FCC", + "/tibt:norbugsumkhyilsymbol": "\u0FCB", + "/tibt:norbunyiskhyilsymbol": "\u0FCA", + "/tibt:norbusymbol": "\u0FC9", + "/tibt:nya": "\u0F49", + "/tibt:nyasubjoined": "\u0F99", + "/tibt:nyisshadmark": "\u0F0E", + "/tibt:nyistshegmark": "\u0FD2", + "/tibt:nyistshegshadmark": "\u0F10", + "/tibt:nyizlanaadasign": "\u0F82", + "/tibt:omsyllable": "\u0F00", + "/tibt:one": "\u0F21", + "/tibt:oovowelsign": "\u0F7D", + "/tibt:ovowelsign": "\u0F7C", + "/tibt:pa": "\u0F54", + "/tibt:padmagdansymbol": "\u0FC6", + "/tibt:palutamark": "\u0F85", + "/tibt:pasubjoined": "\u0FA4", + "/tibt:pha": "\u0F55", + "/tibt:phasubjoined": "\u0FA5", + "/tibt:phurpasymbol": "\u0FC8", + "/tibt:ra": "\u0F62", + "/tibt:rafixed": "\u0F6A", + "/tibt:rasubjoined": "\u0FB2", + "/tibt:rasubjoinedfixed": "\u0FBC", + "/tibt:rdeldkargcigsign": "\u0F1A", + "/tibt:rdeldkargnyissign": "\u0F1B", + "/tibt:rdeldkargsumsign": "\u0F1C", + "/tibt:rdeldkarrdelnagsign": "\u0F1F", + "/tibt:rdelnaggcigsign": "\u0F1D", + "/tibt:rdelnaggnyissign": "\u0F1E", + "/tibt:rdelnaggsumsign": "\u0FCF", + "/tibt:rdelnagrdeldkarsign": "\u0FCE", + "/tibt:rdorjergyagramsymbol": "\u0FC7", + "/tibt:rdorjesymbol": "\u0FC5", + "/tibt:reversediivowelsign": "\u0F81", + "/tibt:reversedivowelsign": "\u0F80", + "/tibt:rgyagramshadmark": "\u0F12", + "/tibt:rinchenspungsshadmark": "\u0F11", + "/tibt:rjessungarosign": "\u0F7E", + "/tibt:rnambcadsign": "\u0F7F", + "/tibt:rra": "\u0F6C", + "/tibt:rrvocalicvowelsign": "\u0F77", + "/tibt:rvocalicvowelsign": "\u0F76", + "/tibt:sa": "\u0F66", + "/tibt:sasubjoined": "\u0FB6", + "/tibt:sbrulshadmark": "\u0F08", + "/tibt:sbubchalcantillationsign": "\u0FC3", + "/tibt:seven": "\u0F27", + "/tibt:sha": "\u0F64", + "/tibt:shadmark": "\u0F0D", + "/tibt:shasubjoined": "\u0FB4", + "/tibt:six": "\u0F26", + "/tibt:snaldansign": "\u0F83", + "/tibt:ssa": "\u0F65", + "/tibt:ssasubjoined": "\u0FB5", + "/tibt:subjoinedAA": "\u0FB0", + "/tibt:svastileft": "\u0FD6", + "/tibt:svastileftdot": "\u0FD8", + "/tibt:svastiright": "\u0FD5", + "/tibt:svastirightdot": "\u0FD7", + "/tibt:ta": "\u0F4F", + "/tibt:tasubjoined": "\u0F9F", + "/tibt:tha": "\u0F50", + "/tibt:thasubjoined": "\u0FA0", + "/tibt:three": "\u0F23", + "/tibt:trailingmchanrtagsmark": "\u0FDA", + "/tibt:tsa": "\u0F59", + "/tibt:tsaphrumark": "\u0F39", + "/tibt:tsasubjoined": "\u0FA9", + "/tibt:tsha": "\u0F5A", + "/tibt:tshasubjoined": "\u0FAA", + "/tibt:tshegshadmark": "\u0F0F", + "/tibt:tta": "\u0F4A", + "/tibt:ttasubjoined": "\u0F9A", + "/tibt:ttha": "\u0F4B", + "/tibt:tthasubjoined": "\u0F9B", + "/tibt:two": "\u0F22", + "/tibt:uuvowelsign": "\u0F75", + "/tibt:uvowelsign": "\u0F74", + "/tibt:wa": "\u0F5D", + "/tibt:wasubjoined": "\u0FAD", + "/tibt:wasubjoinedfixed": "\u0FBA", + "/tibt:ya": "\u0F61", + "/tibt:yangrtagssign": "\u0F87", + "/tibt:yartshessign": "\u0F3E", + "/tibt:yasubjoined": "\u0FB1", + "/tibt:yasubjoinedfixed": "\u0FBB", + "/tibt:yigmgomdunmainitialmark": "\u0F04", + "/tibt:yigmgosgabmaclosingmark": "\u0F05", + "/tibt:yigmgotshegshadmamark": "\u0F07", + "/tibt:za": "\u0F5F", + "/tibt:zasubjoined": "\u0FAF", + "/tibt:zero": "\u0F20", + "/tibt:zha": "\u0F5E", + "/tibt:zhasubjoined": "\u0FAE", + "/ticirclekatakana": "\u32E0", + "/tickconvavediamondleftwhite": "\u27E2", + "/tickconvavediamondrightwhite": "\u27E3", + "/ticket": "\u1F3AB", + "/tickleftwhitesquare": "\u27E4", + "/tickrightwhitesquare": "\u27E5", + "/tifcha:hb": "\u0596", + "/tiger": "\u1F405", + "/tigerFace": "\u1F42F", + "/tihiragana": "\u3061", + "/tikatakana": "\u30C1", + "/tikatakanahalfwidth": "\uFF81", + "/tikeutacirclekorean": "\u3270", + "/tikeutaparenkorean": "\u3210", + "/tikeutcirclekorean": "\u3262", + "/tikeutkorean": "\u3137", + "/tikeutparenkorean": "\u3202", + "/tilde": "\u02DC", + "/tildebelowcmb": "\u0330", + "/tildecmb": "\u0303", + "/tildecomb": "\u0303", + "/tildediaeresisfunc": "\u2368", + "/tildedotaccent": "\u2E1E", + "/tildedotbelow": "\u2E1F", + "/tildedoublecmb": "\u0360", + "/tildeequalsreversed": "\u22CD", + "/tildelowmod": "\u02F7", + "/tildeoperator": "\u223C", + "/tildeoverlaycmb": "\u0334", + "/tildereversed": "\u223D", + "/tildering": "\u2E1B", + "/tildetpl": "\u224B", + "/tildeverticalcmb": "\u033E", + "/timerclock": "\u23F2", + "/timescircle": "\u2297", + "/tinsular": "\uA787", + "/tipehahebrew": "\u0596", + "/tipehalefthebrew": "\u0596", + "/tippigurmukhi": "\u0A70", + "/tiredFace": "\u1F62B", + "/tironiansignet": "\u204A", + "/tirtatumetespada": "\uA9DE", + "/titlocmbcyr": "\u0483", + "/titlocyrilliccmb": "\u0483", + "/tiwnarmenian": "\u057F", + "/tjekomicyr": "\u050F", + "/tlinebelow": "\u1E6F", + "/tmonospace": "\uFF54", + "/toarmenian": "\u0569", + "/tocirclekatakana": "\u32E3", + "/tocornerarrowNW": "\u21F1", + "/tocornerarrowSE": "\u21F2", + "/tohiragana": "\u3068", + "/toilet": "\u1F6BD", + "/tokatakana": "\u30C8", + "/tokatakanahalfwidth": "\uFF84", + "/tokyoTower": "\u1F5FC", + "/tolongvowel": "\uA9B5", + "/tomato": "\u1F345", + "/tonebarextrahighmod": "\u02E5", + "/tonebarextralowmod": "\u02E9", + "/tonebarhighmod": "\u02E6", + "/tonebarlowmod": "\u02E8", + "/tonebarmidmod": "\u02E7", + "/tonefive": "\u01BD", + "/tonehighbeginmod": "\u02F9", + "/tonehighendmod": "\u02FA", + "/tonelowbeginmod": "\u02FB", + "/tonelowendmod": "\u02FC", + "/tonesix": "\u0185", + "/tonetwo": "\u01A8", + "/tongue": "\u1F445", + "/tonos": "\u0384", + "/tonsquare": "\u3327", + "/topHat": "\u1F3A9", + "/topUpwardsArrowAbove": "\u1F51D", + "/topatakthai": "\u0E0F", + "/tortoiseshellbracketleft": "\u3014", + "/tortoiseshellbracketleftsmall": "\uFE5D", + "/tortoiseshellbracketleftvertical": "\uFE39", + "/tortoiseshellbracketright": "\u3015", + "/tortoiseshellbracketrightsmall": "\uFE5E", + "/tortoiseshellbracketrightvertical": "\uFE3A", + "/totalrunout": "\u2330", + "/totaothai": "\u0E15", + "/tpalatalhook": "\u01AB", + "/tparen": "\u24AF", + "/tparenthesized": "\u24AF", + "/trackball": "\u1F5B2", + "/tractor": "\u1F69C", + "/trademark": "\u2122", + "/trademarksans": "\uF8EA", + "/trademarkserif": "\uF6DB", + "/train": "\u1F686", + "/tram": "\u1F68A", + "/tramCar": "\u1F68B", + "/trapeziumwhite": "\u23E2", + "/tresillo": "\uA72B", + "/tretroflex": "\u0288", + "/tretroflexhook": "\u0288", + "/triagdn": "\u25BC", + "/triaglf": "\u25C4", + "/triagrt": "\u25BA", + "/triagup": "\u25B2", + "/triangleWithRoundedCorners": "\u1F6C6", + "/triangledotupwhite": "\u25EC", + "/triangledownblack": "\u25BC", + "/triangledownsmallblack": "\u25BE", + "/triangledownsmallwhite": "\u25BF", + "/triangledownwhite": "\u25BD", + "/trianglehalfupleftblack": "\u25ED", + "/trianglehalfuprightblack": "\u25EE", + "/triangleleftblack": "\u25C0", + "/triangleleftsmallblack": "\u25C2", + "/triangleleftsmallwhite": "\u25C3", + "/triangleleftwhite": "\u25C1", + "/triangleright": "\u22BF", + "/trianglerightblack": "\u25B6", + "/trianglerightsmallblack": "\u25B8", + "/trianglerightsmallwhite": "\u25B9", + "/trianglerightwhite": "\u25B7", + "/triangleupblack": "\u25B2", + "/triangleupsmallblack": "\u25B4", + "/triangleupsmallwhite": "\u25B5", + "/triangleupwhite": "\u25B3", + "/triangularFlagOnPost": "\u1F6A9", + "/triangularRuler": "\u1F4D0", + "/triangularbullet": "\u2023", + "/tricolon": "\u205D", + "/tricontainingtriwhiteanglesmall": "\u27C1", + "/tridentEmblem": "\u1F531", + "/trigramearth": "\u2637", + "/trigramfire": "\u2632", + "/trigramheaven": "\u2630", + "/trigramlake": "\u2631", + "/trigrammountain": "\u2636", + "/trigramthunder": "\u2633", + "/trigramwater": "\u2635", + "/trigramwind": "\u2634", + "/triplearrowleft": "\u21DA", + "/triplearrowright": "\u21DB", + "/tripledot": "\u061E", + "/trisememetrical": "\u23D7", + "/trns:baby": "\u1F6BC", + "/trolleybus": "\u1F68E", + "/trophy": "\u1F3C6", + "/tropicalDrink": "\u1F379", + "/tropicalFish": "\u1F420", + "/truckblack": "\u26DF", + "/true": "\u22A8", + "/trumpet": "\u1F3BA", + "/ts": "\u02A6", + "/tsadi": "\u05E6", + "/tsadi:hb": "\u05E6", + "/tsadidagesh": "\uFB46", + "/tsadidageshhebrew": "\uFB46", + "/tsadihebrew": "\u05E6", + "/tsadiwithdagesh:hb": "\uFB46", + "/tsecyr": "\u0446", + "/tsecyrillic": "\u0446", + "/tsere": "\u05B5", + "/tsere12": "\u05B5", + "/tsere1e": "\u05B5", + "/tsere2b": "\u05B5", + "/tsere:hb": "\u05B5", + "/tserehebrew": "\u05B5", + "/tserenarrowhebrew": "\u05B5", + "/tserequarterhebrew": "\u05B5", + "/tserewidehebrew": "\u05B5", + "/tshecyr": "\u045B", + "/tshecyrillic": "\u045B", + "/tsinnorit:hb": "\u05AE", + "/tstroke": "\u2C66", + "/tsuperior": "\uF6F3", + "/ttabengali": "\u099F", + "/ttadeva": "\u091F", + "/ttagujarati": "\u0A9F", + "/ttagurmukhi": "\u0A1F", + "/ttamahaprana": "\uA99C", + "/tteh": "\u0679", + "/tteh.fina": "\uFB67", + "/tteh.init": "\uFB68", + "/tteh.isol": "\uFB66", + "/tteh.medi": "\uFB69", + "/tteharabic": "\u0679", + "/tteheh": "\u067A", + "/tteheh.fina": "\uFB5F", + "/tteheh.init": "\uFB60", + "/tteheh.isol": "\uFB5E", + "/tteheh.medi": "\uFB61", + "/ttehfinalarabic": "\uFB67", + "/ttehinitialarabic": "\uFB68", + "/ttehmedialarabic": "\uFB69", + "/tthabengali": "\u09A0", + "/tthadeva": "\u0920", + "/tthagujarati": "\u0AA0", + "/tthagurmukhi": "\u0A20", + "/tturned": "\u0287", + "/tucirclekatakana": "\u32E1", + "/tugrik": "\u20AE", + "/tuhiragana": "\u3064", + "/tukatakana": "\u30C4", + "/tukatakanahalfwidth": "\uFF82", + "/tulip": "\u1F337", + "/tum": "\uA777", + "/turkishlira": "\u20BA", + "/turnedOkHandSign": "\u1F58F", + "/turnedcomma": "\u2E32", + "/turneddagger": "\u2E38", + "/turneddigitthree": "\u218B", + "/turneddigittwo": "\u218A", + "/turnedpiselehpada": "\uA9CD", + "/turnedsemicolon": "\u2E35", + "/turnedshogipieceblack": "\u26CA", + "/turnedshogipiecewhite": "\u26C9", + "/turnstiledblverticalbarright": "\u22AB", + "/turnstileleftrightdbl": "\u27DA", + "/turnstiletplverticalbarright": "\u22AA", + "/turtle": "\u1F422", + "/tusmallhiragana": "\u3063", + "/tusmallkatakana": "\u30C3", + "/tusmallkatakanahalfwidth": "\uFF6F", + "/twelve.roman": "\u216B", + "/twelve.romansmall": "\u217B", + "/twelvecircle": "\u246B", + "/twelvecircleblack": "\u24EC", + "/twelveparen": "\u247F", + "/twelveparenthesized": "\u247F", + "/twelveperiod": "\u2493", + "/twelveroman": "\u217B", + "/twenty-twopointtwosquare": "\u1F1A2", + "/twentycircle": "\u2473", + "/twentycircleblack": "\u24F4", + "/twentycirclesquare": "\u3249", + "/twentyeightcircle": "\u3258", + "/twentyfivecircle": "\u3255", + "/twentyfourcircle": "\u3254", + "/twentyhangzhou": "\u5344", + "/twentyninecircle": "\u3259", + "/twentyonecircle": "\u3251", + "/twentyparen": "\u2487", + "/twentyparenthesized": "\u2487", + "/twentyperiod": "\u249B", + "/twentysevencircle": "\u3257", + "/twentysixcircle": "\u3256", + "/twentythreecircle": "\u3253", + "/twentytwocircle": "\u3252", + "/twistedRightwardsArrows": "\u1F500", + "/two": "\u0032", + "/two.inferior": "\u2082", + "/two.roman": "\u2161", + "/two.romansmall": "\u2171", + "/twoButtonMouse": "\u1F5B0", + "/twoHearts": "\u1F495", + "/twoMenHoldingHands": "\u1F46C", + "/twoSpeechBubbles": "\u1F5EA", + "/twoWomenHoldingHands": "\u1F46D", + "/twoarabic": "\u0662", + "/twoasterisksalignedvertically": "\u2051", + "/twobengali": "\u09E8", + "/twocircle": "\u2461", + "/twocircledbl": "\u24F6", + "/twocircleinversesansserif": "\u278B", + "/twocomma": "\u1F103", + "/twodeva": "\u0968", + "/twodotenleader": "\u2025", + "/twodotleader": "\u2025", + "/twodotleadervertical": "\uFE30", + "/twodotpunctuation": "\u205A", + "/twodotsoveronedot": "\u2E2A", + "/twofar": "\u06F2", + "/twofifths": "\u2156", + "/twogujarati": "\u0AE8", + "/twogurmukhi": "\u0A68", + "/twohackarabic": "\u0662", + "/twohangzhou": "\u3022", + "/twoideographiccircled": "\u3281", + "/twoideographicparen": "\u3221", + "/twoinferior": "\u2082", + "/twoksquare": "\u1F19D", + "/twomonospace": "\uFF12", + "/twonumeratorbengali": "\u09F5", + "/twooldstyle": "\uF732", + "/twoparen": "\u2475", + "/twoparenthesized": "\u2475", + "/twoperiod": "\u2489", + "/twopersian": "\u06F2", + "/tworoman": "\u2171", + "/twoshortsjoinedmetrical": "\u23D6", + "/twoshortsoverlongmetrical": "\u23D5", + "/twostroke": "\u01BB", + "/twosuperior": "\u00B2", + "/twothai": "\u0E52", + "/twothirds": "\u2154", + "/twowayleftwaytrafficblack": "\u26D6", + "/twowayleftwaytrafficwhite": "\u26D7", + "/tz": "\uA729", + "/u": "\u0075", + "/u.fina": "\uFBD8", + "/u.isol": "\uFBD7", + "/uacute": "\u00FA", + "/uacutedblcyr": "\u04F3", + "/ubar": "\u0289", + "/ubengali": "\u0989", + "/ubopomofo": "\u3128", + "/ubracketleft": "\u2E26", + "/ubracketright": "\u2E27", + "/ubreve": "\u016D", + "/ucaron": "\u01D4", + "/ucircle": "\u24E4", + "/ucirclekatakana": "\u32D2", + "/ucircumflex": "\u00FB", + "/ucircumflexbelow": "\u1E77", + "/ucyr": "\u0443", + "/ucyrillic": "\u0443", + "/udattadeva": "\u0951", + "/udblacute": "\u0171", + "/udblgrave": "\u0215", + "/udeva": "\u0909", + "/udieresis": "\u00FC", + "/udieresisacute": "\u01D8", + "/udieresisbelow": "\u1E73", + "/udieresiscaron": "\u01DA", + "/udieresiscyr": "\u04F1", + "/udieresiscyrillic": "\u04F1", + "/udieresisgrave": "\u01DC", + "/udieresismacron": "\u01D6", + "/udotbelow": "\u1EE5", + "/ugrave": "\u00F9", + "/ugravedbl": "\u0215", + "/ugujarati": "\u0A89", + "/ugurmukhi": "\u0A09", + "/uhamza": "\u0677", + "/uhamza.isol": "\uFBDD", + "/uhdsquare": "\u1F1AB", + "/uhiragana": "\u3046", + "/uhoi": "\u1EE7", + "/uhookabove": "\u1EE7", + "/uhorn": "\u01B0", + "/uhornacute": "\u1EE9", + "/uhorndotbelow": "\u1EF1", + "/uhorngrave": "\u1EEB", + "/uhornhoi": "\u1EED", + "/uhornhookabove": "\u1EED", + "/uhorntilde": "\u1EEF", + "/uhungarumlaut": "\u0171", + "/uhungarumlautcyrillic": "\u04F3", + "/uighurkazakhkirghizalefmaksura.init": "\uFBE8", + "/uighurkazakhkirghizalefmaksura.medi": "\uFBE9", + "/uighurkirghizyeh.init_hamzaabove.medi_alefmaksura.fina": "\uFBF9", + "/uighurkirghizyeh.init_hamzaabove.medi_alefmaksura.medi": "\uFBFB", + "/uighurkirghizyeh.medi_hamzaabove.medi_alefmaksura.fina": "\uFBFA", + "/uinvertedbreve": "\u0217", + "/ukatakana": "\u30A6", + "/ukatakanahalfwidth": "\uFF73", + "/ukcyr": "\u0479", + "/ukcyrillic": "\u0479", + "/ukorean": "\u315C", + "/um": "\uA778", + "/umacron": "\u016B", + "/umacroncyr": "\u04EF", + "/umacroncyrillic": "\u04EF", + "/umacrondieresis": "\u1E7B", + "/umatragurmukhi": "\u0A41", + "/umbrella": "\u2602", + "/umbrellaonground": "\u26F1", + "/umbrellaraindrops": "\u2614", + "/umonospace": "\uFF55", + "/unamusedFace": "\u1F612", + "/unaspiratedmod": "\u02ED", + "/underscore": "\u005F", + "/underscorecenterline": "\uFE4E", + "/underscoredashed": "\uFE4D", + "/underscoredbl": "\u2017", + "/underscoremonospace": "\uFF3F", + "/underscorevertical": "\uFE33", + "/underscorewavy": "\uFE4F", + "/underscorewavyvertical": "\uFE34", + "/undertie": "\u203F", + "/undo": "\u238C", + "/union": "\u222A", + "/unionarray": "\u22C3", + "/uniondbl": "\u22D3", + "/universal": "\u2200", + "/unmarriedpartnership": "\u26AF", + "/uogonek": "\u0173", + "/uonsquare": "\u3306", + "/upPointingAirplane": "\u1F6E7", + "/upPointingMilitaryAirplane": "\u1F6E6", + "/upPointingSmallAirplane": "\u1F6E8", + "/uparen": "\u24B0", + "/uparenthesized": "\u24B0", + "/uparrowleftofdownarrow": "\u21C5", + "/upblock": "\u2580", + "/updblhorzsng": "\u2568", + "/updblleftsng": "\u255C", + "/updblrightsng": "\u2559", + "/upheavydnhorzlight": "\u2540", + "/upheavyhorzlight": "\u2538", + "/upheavyleftdnlight": "\u2526", + "/upheavyleftlight": "\u251A", + "/upheavyrightdnlight": "\u251E", + "/upheavyrightlight": "\u2516", + "/uplightdnhorzheavy": "\u2548", + "/uplighthorzheavy": "\u2537", + "/uplightleftdnheavy": "\u252A", + "/uplightleftheavy": "\u2519", + "/uplightrightdnheavy": "\u2522", + "/uplightrightheavy": "\u2515", + "/upperHalfBlock": "\u2580", + "/upperOneEighthBlock": "\u2594", + "/upperRightShadowedWhiteCircle": "\u1F53F", + "/upperdothebrew": "\u05C4", + "/upperhalfcircle": "\u25E0", + "/upperhalfcircleinversewhite": "\u25DA", + "/upperquadrantcirculararcleft": "\u25DC", + "/upperquadrantcirculararcright": "\u25DD", + "/uppertriangleleft": "\u25F8", + "/uppertriangleleftblack": "\u25E4", + "/uppertriangleright": "\u25F9", + "/uppertrianglerightblack": "\u25E5", + "/upsideDownFace": "\u1F643", + "/upsilon": "\u03C5", + "/upsilonacute": "\u1F7B", + "/upsilonasper": "\u1F51", + "/upsilonasperacute": "\u1F55", + "/upsilonaspergrave": "\u1F53", + "/upsilonaspertilde": "\u1F57", + "/upsilonbreve": "\u1FE0", + "/upsilondieresis": "\u03CB", + "/upsilondieresisacute": "\u1FE3", + "/upsilondieresisgrave": "\u1FE2", + "/upsilondieresistilde": "\u1FE7", + "/upsilondieresistonos": "\u03B0", + "/upsilongrave": "\u1F7A", + "/upsilonlatin": "\u028A", + "/upsilonlenis": "\u1F50", + "/upsilonlenisacute": "\u1F54", + "/upsilonlenisgrave": "\u1F52", + "/upsilonlenistilde": "\u1F56", + "/upsilontilde": "\u1FE6", + "/upsilontonos": "\u03CD", + "/upsilonwithmacron": "\u1FE1", + "/upsnghorzdbl": "\u2567", + "/upsngleftdbl": "\u255B", + "/upsngrightdbl": "\u2558", + "/uptackbelowcmb": "\u031D", + "/uptackmod": "\u02D4", + "/upwithexclamationmarksquare": "\u1F199", + "/uragurmukhi": "\u0A73", + "/uranus": "\u2645", + "/uring": "\u016F", + "/ushortcyr": "\u045E", + "/ushortcyrillic": "\u045E", + "/usmallhiragana": "\u3045", + "/usmallkatakana": "\u30A5", + "/usmallkatakanahalfwidth": "\uFF69", + "/usmod": "\uA770", + "/ustraightcyr": "\u04AF", + "/ustraightcyrillic": "\u04AF", + "/ustraightstrokecyr": "\u04B1", + "/ustraightstrokecyrillic": "\u04B1", + "/utilde": "\u0169", + "/utildeacute": "\u1E79", + "/utildebelow": "\u1E75", + "/uubengali": "\u098A", + "/uudeva": "\u090A", + "/uugujarati": "\u0A8A", + "/uugurmukhi": "\u0A0A", + "/uumatragurmukhi": "\u0A42", + "/uuvowelsignbengali": "\u09C2", + "/uuvowelsigndeva": "\u0942", + "/uuvowelsigngujarati": "\u0AC2", + "/uvowelsignbengali": "\u09C1", + "/uvowelsigndeva": "\u0941", + "/uvowelsigngujarati": "\u0AC1", + "/v": "\u0076", + "/vadeva": "\u0935", + "/vagujarati": "\u0AB5", + "/vagurmukhi": "\u0A35", + "/vakatakana": "\u30F7", + "/vanedownfunc": "\u2356", + "/vaneleftfunc": "\u2345", + "/vanerightfunc": "\u2346", + "/vaneupfunc": "\u234F", + "/varikajudeospanish:hb": "\uFB1E", + "/vav": "\u05D5", + "/vav:hb": "\u05D5", + "/vav_vav:hb": "\u05F0", + "/vav_yod:hb": "\u05F1", + "/vavdagesh": "\uFB35", + "/vavdagesh65": "\uFB35", + "/vavdageshhebrew": "\uFB35", + "/vavhebrew": "\u05D5", + "/vavholam": "\uFB4B", + "/vavholamhebrew": "\uFB4B", + "/vavvavhebrew": "\u05F0", + "/vavwithdagesh:hb": "\uFB35", + "/vavwithholam:hb": "\uFB4B", + "/vavyodhebrew": "\u05F1", + "/vcircle": "\u24E5", + "/vcurl": "\u2C74", + "/vdiagonalstroke": "\uA75F", + "/vdotbelow": "\u1E7F", + "/ve.fina": "\uFBDF", + "/ve.isol": "\uFBDE", + "/ve:abovetonecandra": "\u1CF4", + "/ve:anusvaraantargomukhasign": "\u1CE9", + "/ve:anusvarabahirgomukhasign": "\u1CEA", + "/ve:anusvarasignlong": "\u1CEF", + "/ve:anusvaraubhayatomukhasign": "\u1CF1", + "/ve:anusvaravamagomukhasign": "\u1CEB", + "/ve:anusvaravamagomukhawithtailsign": "\u1CEC", + "/ve:ardhavisargasign": "\u1CF2", + "/ve:atharvaindependentsvaritatone": "\u1CE1", + "/ve:atikramasign": "\u1CF7", + "/ve:belowtonecandra": "\u1CD8", + "/ve:dotbelowtone": "\u1CDD", + "/ve:hexiformanusvarasignlong": "\u1CEE", + "/ve:jihvamuliyasign": "\u1CF5", + "/ve:karshanatone": "\u1CD0", + "/ve:kathakaanudattatone": "\u1CDC", + "/ve:nihshvasasign": "\u1CD3", + "/ve:prenkhatone": "\u1CD2", + "/ve:rigkashmiriindependentsvaritatone": "\u1CE0", + "/ve:ringabovetone": "\u1CF8", + "/ve:ringabovetonedbl": "\u1CF9", + "/ve:rotatedardhavisargasign": "\u1CF3", + "/ve:rthanganusvarasignlong": "\u1CF0", + "/ve:sharatone": "\u1CD1", + "/ve:svaritatonedbl": "\u1CDA", + "/ve:svaritatonetpl": "\u1CDB", + "/ve:threedotsbelowtone": "\u1CDF", + "/ve:tiryaksign": "\u1CED", + "/ve:twodotsbelowtone": "\u1CDE", + "/ve:upadhmaniyasign": "\u1CF6", + "/ve:visargaanudattasign": "\u1CE5", + "/ve:visargaanudattasignreversed": "\u1CE6", + "/ve:visargaanudattawithtailsign": "\u1CE8", + "/ve:visargasvaritasign": "\u1CE2", + "/ve:visargaudattasign": "\u1CE3", + "/ve:visargaudattasignreversed": "\u1CE4", + "/ve:visargaudattawithtailsign": "\u1CE7", + "/ve:yajuraggravatedindependentsvaritatone": "\u1CD5", + "/ve:yajurindependentsvaritatone": "\u1CD6", + "/ve:yajurkathakaindependentsvaritaschroedertone": "\u1CD9", + "/ve:yajurkathakaindependentsvaritatone": "\u1CD7", + "/ve:yajurmidlinesvaritasign": "\u1CD4", + "/vecyr": "\u0432", + "/vecyrillic": "\u0432", + "/veh": "\u06A4", + "/veh.fina": "\uFB6B", + "/veh.init": "\uFB6C", + "/veh.isol": "\uFB6A", + "/veh.medi": "\uFB6D", + "/veharabic": "\u06A4", + "/vehfinalarabic": "\uFB6B", + "/vehinitialarabic": "\uFB6C", + "/vehmedialarabic": "\uFB6D", + "/vekatakana": "\u30F9", + "/vend": "\uA769", + "/venus": "\u2640", + "/versicle": "\u2123", + "/vert:bracketwhiteleft": "\uFE17", + "/vert:brakcetwhiteright": "\uFE18", + "/vert:colon": "\uFE13", + "/vert:comma": "\uFE10", + "/vert:ellipsishor": "\uFE19", + "/vert:exclam": "\uFE15", + "/vert:ideographiccomma": "\uFE11", + "/vert:ideographicfullstop": "\uFE12", + "/vert:question": "\uFE16", + "/vert:semicolon": "\uFE14", + "/vertdblhorzsng": "\u256B", + "/vertdblleftsng": "\u2562", + "/vertdblrightsng": "\u255F", + "/vertheavyhorzlight": "\u2542", + "/vertheavyleftlight": "\u2528", + "/vertheavyrightlight": "\u2520", + "/verticalTrafficLight": "\u1F6A6", + "/verticalbar": "\u007C", + "/verticalbardbl": "\u2016", + "/verticalbarhorizontalstroke": "\u27CA", + "/verticalbarwhitearrowonpedestalup": "\u21ED", + "/verticalfourdots": "\u205E", + "/verticalideographiciterationmark": "\u303B", + "/verticalkanarepeatmark": "\u3031", + "/verticalkanarepeatmarklowerhalf": "\u3035", + "/verticalkanarepeatmarkupperhalf": "\u3033", + "/verticalkanarepeatwithvoicedsoundmark": "\u3032", + "/verticalkanarepeatwithvoicedsoundmarkupperhalf": "\u3034", + "/verticallineabovecmb": "\u030D", + "/verticallinebelowcmb": "\u0329", + "/verticallinelowmod": "\u02CC", + "/verticallinemod": "\u02C8", + "/verticalmalestroke": "\u26A8", + "/verticalsdbltrokearrowleft": "\u21FA", + "/verticalsdbltrokearrowleftright": "\u21FC", + "/verticalsdbltrokearrowright": "\u21FB", + "/verticalstrokearrowleft": "\u21F7", + "/verticalstrokearrowleftright": "\u21F9", + "/verticalstrokearrowright": "\u21F8", + "/vertlighthorzheavy": "\u253F", + "/vertlightleftheavy": "\u2525", + "/vertlightrightheavy": "\u251D", + "/vertsnghorzdbl": "\u256A", + "/vertsngleftdbl": "\u2561", + "/vertsngrightdbl": "\u255E", + "/verymuchgreater": "\u22D9", + "/verymuchless": "\u22D8", + "/vesta": "\u26B6", + "/vewarmenian": "\u057E", + "/vhook": "\u028B", + "/vibrationMode": "\u1F4F3", + "/videoCamera": "\u1F4F9", + "/videoGame": "\u1F3AE", + "/videocassette": "\u1F4FC", + "/viewdatasquare": "\u2317", + "/vikatakana": "\u30F8", + "/violin": "\u1F3BB", + "/viramabengali": "\u09CD", + "/viramadeva": "\u094D", + "/viramagujarati": "\u0ACD", + "/virgo": "\u264D", + "/visargabengali": "\u0983", + "/visargadeva": "\u0903", + "/visargagujarati": "\u0A83", + "/visigothicz": "\uA763", + "/vmonospace": "\uFF56", + "/voarmenian": "\u0578", + "/vodsquare": "\u1F1AC", + "/voicediterationhiragana": "\u309E", + "/voicediterationkatakana": "\u30FE", + "/voicedmarkkana": "\u309B", + "/voicedmarkkanahalfwidth": "\uFF9E", + "/voicingmod": "\u02EC", + "/vokatakana": "\u30FA", + "/volapukae": "\uA79B", + "/volapukoe": "\uA79D", + "/volapukue": "\uA79F", + "/volcano": "\u1F30B", + "/volleyball": "\u1F3D0", + "/vovermfullwidth": "\u33DE", + "/vowelVabove": "\u065A", + "/voweldotbelow": "\u065C", + "/vowelinvertedVabove": "\u065B", + "/vparen": "\u24B1", + "/vparenthesized": "\u24B1", + "/vrighthook": "\u2C71", + "/vssquare": "\u1F19A", + "/vtilde": "\u1E7D", + "/vturned": "\u028C", + "/vuhiragana": "\u3094", + "/vukatakana": "\u30F4", + "/vwelsh": "\u1EFD", + "/vy": "\uA761", + "/w": "\u0077", + "/wacirclekatakana": "\u32FB", + "/wacute": "\u1E83", + "/waekorean": "\u3159", + "/wahiragana": "\u308F", + "/wakatakana": "\u30EF", + "/wakatakanahalfwidth": "\uFF9C", + "/wakorean": "\u3158", + "/waningCrescentMoon": "\u1F318", + "/waningGibbousMoon": "\u1F316", + "/warning": "\u26A0", + "/wasmallhiragana": "\u308E", + "/wasmallkatakana": "\u30EE", + "/wastebasket": "\u1F5D1", + "/watch": "\u231A", + "/waterBuffalo": "\u1F403", + "/waterCloset": "\u1F6BE", + "/waterWave": "\u1F30A", + "/waterideographiccircled": "\u328C", + "/waterideographicparen": "\u322C", + "/watermelon": "\u1F349", + "/wattosquare": "\u3357", + "/wavedash": "\u301C", + "/wavingBlackFlag": "\u1F3F4", + "/wavingHandSign": "\u1F44B", + "/wavingWhiteFlag": "\u1F3F3", + "/wavydash": "\u3030", + "/wavyhamzabelow": "\u065F", + "/wavyline": "\u2307", + "/wavyunderscorevertical": "\uFE34", + "/waw": "\u0648", + "/waw.fina": "\uFEEE", + "/waw.isol": "\uFEED", + "/wawDigitThreeAbove": "\u0779", + "/wawDigitTwoAbove": "\u0778", + "/wawarabic": "\u0648", + "/wawdotabove": "\u06CF", + "/wawfinalarabic": "\uFEEE", + "/wawhamza": "\u0624", + "/wawhamza.fina": "\uFE86", + "/wawhamza.isol": "\uFE85", + "/wawhamzaabovearabic": "\u0624", + "/wawhamzaabovefinalarabic": "\uFE86", + "/wawhighhamza": "\u0676", + "/wawring": "\u06C4", + "/wawsmall": "\u06E5", + "/wawtwodotsabove": "\u06CA", + "/waxingCrescentMoon": "\u1F312", + "/waxingGibbousMoon": "\u1F314", + "/wbfullwidth": "\u33DD", + "/wbsquare": "\u33DD", + "/wcircle": "\u24E6", + "/wcircumflex": "\u0175", + "/wcsquare": "\u1F14F", + "/wcsquareblack": "\u1F18F", + "/wdieresis": "\u1E85", + "/wdot": "\u1E87", + "/wdotaccent": "\u1E87", + "/wdotbelow": "\u1E89", + "/wearyCatFace": "\u1F640", + "/wearyFace": "\u1F629", + "/wecirclekatakana": "\u32FD", + "/wecyr": "\u051D", + "/wedding": "\u1F492", + "/wehiragana": "\u3091", + "/weierstrass": "\u2118", + "/weightLifter": "\u1F3CB", + "/wekatakana": "\u30F1", + "/wekorean": "\u315E", + "/weokorean": "\u315D", + "/westsyriaccross": "\u2670", + "/wgrave": "\u1E81", + "/whale": "\u1F40B", + "/wheelchair": "\u267F", + "/wheelofdharma": "\u2638", + "/whiteDownPointingBackhandIndex": "\u1F447", + "/whiteDownPointingLeftHandIndex": "\u1F597", + "/whiteFlower": "\u1F4AE", + "/whiteHardShellFloppyDisk": "\u1F5AB", + "/whiteLatinCross": "\u1F546", + "/whiteLeftPointingBackhandIndex": "\u1F448", + "/whitePennant": "\u1F3F1", + "/whiteRightPointingBackhandIndex": "\u1F449", + "/whiteSquareButton": "\u1F533", + "/whiteSun": "\u1F323", + "/whiteSunBehindCloud": "\u1F325", + "/whiteSunBehindCloudRain": "\u1F326", + "/whiteSunSmallCloud": "\u1F324", + "/whiteTouchtoneTelephone": "\u1F57E", + "/whiteUpPointingBackhandIndex": "\u1F446", + "/whitearrowdown": "\u21E9", + "/whitearrowfromwallright": "\u21F0", + "/whitearrowleft": "\u21E6", + "/whitearrowonpedestalup": "\u21EB", + "/whitearrowright": "\u21E8", + "/whitearrowup": "\u21E7", + "/whitearrowupdown": "\u21F3", + "/whitearrowupfrombar": "\u21EA", + "/whitebullet": "\u25E6", + "/whitecircle": "\u25CB", + "/whitecircleinverse": "\u25D9", + "/whitecornerbracketleft": "\u300E", + "/whitecornerbracketleftvertical": "\uFE43", + "/whitecornerbracketright": "\u300F", + "/whitecornerbracketrightvertical": "\uFE44", + "/whitedblarrowonpedestalup": "\u21EF", + "/whitedblarrowup": "\u21EE", + "/whitediamond": "\u25C7", + "/whitediamondcontainingblacksmalldiamond": "\u25C8", + "/whitedownpointingsmalltriangle": "\u25BF", + "/whitedownpointingtriangle": "\u25BD", + "/whiteleftpointingsmalltriangle": "\u25C3", + "/whiteleftpointingtriangle": "\u25C1", + "/whitelenticularbracketleft": "\u3016", + "/whitelenticularbracketright": "\u3017", + "/whiterightpointingsmalltriangle": "\u25B9", + "/whiterightpointingtriangle": "\u25B7", + "/whitesesamedot": "\uFE46", + "/whitesmallsquare": "\u25AB", + "/whitesmilingface": "\u263A", + "/whitesquare": "\u25A1", + "/whitesquarebracketleft": "\u301A", + "/whitesquarebracketright": "\u301B", + "/whitestar": "\u2606", + "/whitetelephone": "\u260F", + "/whitetortoiseshellbracketleft": "\u3018", + "/whitetortoiseshellbracketright": "\u3019", + "/whiteuppointingsmalltriangle": "\u25B5", + "/whiteuppointingtriangle": "\u25B3", + "/whook": "\u2C73", + "/wicirclekatakana": "\u32FC", + "/wigglylinevertical": "\u2E3E", + "/wignyan": "\uA983", + "/wihiragana": "\u3090", + "/wikatakana": "\u30F0", + "/wikorean": "\u315F", + "/windBlowingFace": "\u1F32C", + "/windChime": "\u1F390", + "/windupada": "\uA9C6", + "/wineGlass": "\u1F377", + "/winkingFace": "\u1F609", + "/wiredKeyboard": "\u1F5AE", + "/wmonospace": "\uFF57", + "/wocirclekatakana": "\u32FE", + "/wohiragana": "\u3092", + "/wokatakana": "\u30F2", + "/wokatakanahalfwidth": "\uFF66", + "/wolfFace": "\u1F43A", + "/woman": "\u1F469", + "/womanBunnyEars": "\u1F46F", + "/womansBoots": "\u1F462", + "/womansClothes": "\u1F45A", + "/womansHat": "\u1F452", + "/womansSandal": "\u1F461", + "/womens": "\u1F6BA", + "/won": "\u20A9", + "/wonmonospace": "\uFFE6", + "/woodideographiccircled": "\u328D", + "/woodideographicparen": "\u322D", + "/wordjoiner": "\u2060", + "/wordseparatormiddledot": "\u2E31", + "/worldMap": "\u1F5FA", + "/worriedFace": "\u1F61F", + "/wowaenthai": "\u0E27", + "/wparen": "\u24B2", + "/wparenthesized": "\u24B2", + "/wrappedPresent": "\u1F381", + "/wreathproduct": "\u2240", + "/wrench": "\u1F527", + "/wring": "\u1E98", + "/wsuperior": "\u02B7", + "/wsupmod": "\u02B7", + "/wturned": "\u028D", + "/wulumelikvowel": "\uA9B7", + "/wuluvowel": "\uA9B6", + "/wynn": "\u01BF", + "/x": "\u0078", + "/x.inferior": "\u2093", + "/xabovecmb": "\u033D", + "/xatailcyr": "\u04B3", + "/xbopomofo": "\u3112", + "/xcircle": "\u24E7", + "/xdieresis": "\u1E8D", + "/xdot": "\u1E8B", + "/xdotaccent": "\u1E8B", + "/xeharmenian": "\u056D", + "/xi": "\u03BE", + "/xmonospace": "\uFF58", + "/xor": "\u22BB", + "/xparen": "\u24B3", + "/xparenthesized": "\u24B3", + "/xsuperior": "\u02E3", + "/xsupmod": "\u02E3", + "/y": "\u0079", + "/yaadosquare": "\u334E", + "/yaarusquare": "\u334F", + "/yabengali": "\u09AF", + "/yacirclekatakana": "\u32F3", + "/yacute": "\u00FD", + "/yacyr": "\u044F", + "/yadeva": "\u092F", + "/yaecyr": "\u0519", + "/yaekorean": "\u3152", + "/yagujarati": "\u0AAF", + "/yagurmukhi": "\u0A2F", + "/yahiragana": "\u3084", + "/yakatakana": "\u30E4", + "/yakatakanahalfwidth": "\uFF94", + "/yakorean": "\u3151", + "/yamakkanthai": "\u0E4E", + "/yangtonemod": "\u02EB", + "/yasmallhiragana": "\u3083", + "/yasmallkatakana": "\u30E3", + "/yasmallkatakanahalfwidth": "\uFF6C", + "/yatcyr": "\u0463", + "/yatcyrillic": "\u0463", + "/ycircle": "\u24E8", + "/ycircumflex": "\u0177", + "/ydieresis": "\u00FF", + "/ydot": "\u1E8F", + "/ydotaccent": "\u1E8F", + "/ydotbelow": "\u1EF5", + "/yeh": "\u064A", + "/yeh.fina": "\uFEF2", + "/yeh.init": "\uFEF3", + "/yeh.init_alefmaksura.fina": "\uFC59", + "/yeh.init_hah.fina": "\uFC56", + "/yeh.init_hah.medi": "\uFCDB", + "/yeh.init_hamzaabove.medi_ae.fina": "\uFBEC", + "/yeh.init_hamzaabove.medi_alef.fina": "\uFBEA", + "/yeh.init_hamzaabove.medi_alefmaksura.fina": "\uFC03", + "/yeh.init_hamzaabove.medi_e.fina": "\uFBF6", + "/yeh.init_hamzaabove.medi_e.medi": "\uFBF8", + "/yeh.init_hamzaabove.medi_hah.fina": "\uFC01", + "/yeh.init_hamzaabove.medi_hah.medi": "\uFC98", + "/yeh.init_hamzaabove.medi_heh.medi": "\uFC9B", + "/yeh.init_hamzaabove.medi_jeem.fina": "\uFC00", + "/yeh.init_hamzaabove.medi_jeem.medi": "\uFC97", + "/yeh.init_hamzaabove.medi_khah.medi": "\uFC99", + "/yeh.init_hamzaabove.medi_meem.fina": "\uFC02", + "/yeh.init_hamzaabove.medi_meem.medi": "\uFC9A", + "/yeh.init_hamzaabove.medi_oe.fina": "\uFBF2", + "/yeh.init_hamzaabove.medi_u.fina": "\uFBF0", + "/yeh.init_hamzaabove.medi_waw.fina": "\uFBEE", + "/yeh.init_hamzaabove.medi_yeh.fina": "\uFC04", + "/yeh.init_hamzaabove.medi_yu.fina": "\uFBF4", + "/yeh.init_heh.medi": "\uFCDE", + "/yeh.init_jeem.fina": "\uFC55", + "/yeh.init_jeem.medi": "\uFCDA", + "/yeh.init_khah.fina": "\uFC57", + "/yeh.init_khah.medi": "\uFCDC", + "/yeh.init_meem.fina": "\uFC58", + "/yeh.init_meem.medi": "\uFCDD", + "/yeh.init_meem.medi_meem.medi": "\uFD9D", + "/yeh.init_yeh.fina": "\uFC5A", + "/yeh.isol": "\uFEF1", + "/yeh.medi": "\uFEF4", + "/yeh.medi_alefmaksura.fina": "\uFC95", + "/yeh.medi_hah.medi_yeh.fina": "\uFDAE", + "/yeh.medi_hamzaabove.medi_ae.fina": "\uFBED", + "/yeh.medi_hamzaabove.medi_alef.fina": "\uFBEB", + "/yeh.medi_hamzaabove.medi_alefmaksura.fina": "\uFC68", + "/yeh.medi_hamzaabove.medi_e.fina": "\uFBF7", + "/yeh.medi_hamzaabove.medi_heh.medi": "\uFCE0", + "/yeh.medi_hamzaabove.medi_meem.fina": "\uFC66", + "/yeh.medi_hamzaabove.medi_meem.medi": "\uFCDF", + "/yeh.medi_hamzaabove.medi_noon.fina": "\uFC67", + "/yeh.medi_hamzaabove.medi_oe.fina": "\uFBF3", + "/yeh.medi_hamzaabove.medi_reh.fina": "\uFC64", + "/yeh.medi_hamzaabove.medi_u.fina": "\uFBF1", + "/yeh.medi_hamzaabove.medi_waw.fina": "\uFBEF", + "/yeh.medi_hamzaabove.medi_yeh.fina": "\uFC69", + "/yeh.medi_hamzaabove.medi_yu.fina": "\uFBF5", + "/yeh.medi_hamzaabove.medi_zain.fina": "\uFC65", + "/yeh.medi_heh.medi": "\uFCF1", + "/yeh.medi_jeem.medi_yeh.fina": "\uFDAF", + "/yeh.medi_meem.fina": "\uFC93", + "/yeh.medi_meem.medi": "\uFCF0", + "/yeh.medi_meem.medi_meem.fina": "\uFD9C", + "/yeh.medi_meem.medi_yeh.fina": "\uFDB0", + "/yeh.medi_noon.fina": "\uFC94", + "/yeh.medi_reh.fina": "\uFC91", + "/yeh.medi_yeh.fina": "\uFC96", + "/yeh.medi_zain.fina": "\uFC92", + "/yehBarreeDigitThreeAbove": "\u077B", + "/yehBarreeDigitTwoAbove": "\u077A", + "/yehVabove": "\u06CE", + "/yehabove": "\u06E7", + "/yeharabic": "\u064A", + "/yehbarree": "\u06D2", + "/yehbarree.fina": "\uFBAF", + "/yehbarree.isol": "\uFBAE", + "/yehbarreearabic": "\u06D2", + "/yehbarreefinalarabic": "\uFBAF", + "/yehbarreehamza": "\u06D3", + "/yehbarreehamza.fina": "\uFBB1", + "/yehbarreehamza.isol": "\uFBB0", + "/yehfarsi": "\u06CC", + "/yehfarsi.fina": "\uFBFD", + "/yehfarsi.init": "\uFBFE", + "/yehfarsi.isol": "\uFBFC", + "/yehfarsi.medi": "\uFBFF", + "/yehfarsiinvertedV": "\u063D", + "/yehfarsithreedotsabove": "\u063F", + "/yehfarsitwodotsabove": "\u063E", + "/yehfinalarabic": "\uFEF2", + "/yehhamza": "\u0626", + "/yehhamza.fina": "\uFE8A", + "/yehhamza.init": "\uFE8B", + "/yehhamza.isol": "\uFE89", + "/yehhamza.medi": "\uFE8C", + "/yehhamzaabovearabic": "\u0626", + "/yehhamzaabovefinalarabic": "\uFE8A", + "/yehhamzaaboveinitialarabic": "\uFE8B", + "/yehhamzaabovemedialarabic": "\uFE8C", + "/yehhighhamza": "\u0678", + "/yehinitialarabic": "\uFEF3", + "/yehmedialarabic": "\uFEF4", + "/yehmeeminitialarabic": "\uFCDD", + "/yehmeemisolatedarabic": "\uFC58", + "/yehnoonfinalarabic": "\uFC94", + "/yehsmall": "\u06E6", + "/yehtail": "\u06CD", + "/yehthreedotsbelow": "\u06D1", + "/yehthreedotsbelowarabic": "\u06D1", + "/yekorean": "\u3156", + "/yellowHeart": "\u1F49B", + "/yen": "\u00A5", + "/yenmonospace": "\uFFE5", + "/yeokorean": "\u3155", + "/yeorinhieuhkorean": "\u3186", + "/yerachBenYomo:hb": "\u05AA", + "/yerahbenyomohebrew": "\u05AA", + "/yerahbenyomolefthebrew": "\u05AA", + "/yericyrillic": "\u044B", + "/yerudieresiscyrillic": "\u04F9", + "/yesieungkorean": "\u3181", + "/yesieungpansioskorean": "\u3183", + "/yesieungsioskorean": "\u3182", + "/yetiv:hb": "\u059A", + "/yetivhebrew": "\u059A", + "/ygrave": "\u1EF3", + "/yhoi": "\u1EF7", + "/yhook": "\u01B4", + "/yhookabove": "\u1EF7", + "/yiarmenian": "\u0575", + "/yicyrillic": "\u0457", + "/yikorean": "\u3162", + "/yintonemod": "\u02EA", + "/yinyang": "\u262F", + "/yiwnarmenian": "\u0582", + "/ylongcyr": "\u044B", + "/ylongdieresiscyr": "\u04F9", + "/yloop": "\u1EFF", + "/ymacron": "\u0233", + "/ymonospace": "\uFF59", + "/yocirclekatakana": "\u32F5", + "/yod": "\u05D9", + "/yod:hb": "\u05D9", + "/yod_yod:hb": "\u05F2", + "/yod_yod_patah:hb": "\uFB1F", + "/yoddagesh": "\uFB39", + "/yoddageshhebrew": "\uFB39", + "/yodhebrew": "\u05D9", + "/yodwithdagesh:hb": "\uFB39", + "/yodwithhiriq:hb": "\uFB1D", + "/yodyodhebrew": "\u05F2", + "/yodyodpatahhebrew": "\uFB1F", + "/yogh": "\u021D", + "/yohiragana": "\u3088", + "/yoikorean": "\u3189", + "/yokatakana": "\u30E8", + "/yokatakanahalfwidth": "\uFF96", + "/yokorean": "\u315B", + "/yosmallhiragana": "\u3087", + "/yosmallkatakana": "\u30E7", + "/yosmallkatakanahalfwidth": "\uFF6E", + "/yot": "\u03F3", + "/yotgreek": "\u03F3", + "/yoyaekorean": "\u3188", + "/yoyakorean": "\u3187", + "/yoyakthai": "\u0E22", + "/yoyingthai": "\u0E0D", + "/yparen": "\u24B4", + "/yparenthesized": "\u24B4", + "/ypogegrammeni": "\u037A", + "/ypogegrammenigreekcmb": "\u0345", + "/yr": "\u01A6", + "/yring": "\u1E99", + "/ystroke": "\u024F", + "/ysuperior": "\u02B8", + "/ysupmod": "\u02B8", + "/ytilde": "\u1EF9", + "/yturned": "\u028E", + "/yu.fina": "\uFBDC", + "/yu.isol": "\uFBDB", + "/yuansquare": "\u3350", + "/yucirclekatakana": "\u32F4", + "/yucyr": "\u044E", + "/yuhiragana": "\u3086", + "/yuikorean": "\u318C", + "/yukatakana": "\u30E6", + "/yukatakanahalfwidth": "\uFF95", + "/yukirghiz": "\u06C9", + "/yukirghiz.fina": "\uFBE3", + "/yukirghiz.isol": "\uFBE2", + "/yukorean": "\u3160", + "/yukrcyr": "\u0457", + "/yusbigcyr": "\u046B", + "/yusbigcyrillic": "\u046B", + "/yusbigiotifiedcyr": "\u046D", + "/yusbigiotifiedcyrillic": "\u046D", + "/yuslittlecyr": "\u0467", + "/yuslittlecyrillic": "\u0467", + "/yuslittleiotifiedcyr": "\u0469", + "/yuslittleiotifiedcyrillic": "\u0469", + "/yusmallhiragana": "\u3085", + "/yusmallkatakana": "\u30E5", + "/yusmallkatakanahalfwidth": "\uFF6D", + "/yuyekorean": "\u318B", + "/yuyeokorean": "\u318A", + "/yyabengali": "\u09DF", + "/yyadeva": "\u095F", + "/z": "\u007A", + "/zaarmenian": "\u0566", + "/zacute": "\u017A", + "/zadeva": "\u095B", + "/zagurmukhi": "\u0A5B", + "/zah": "\u0638", + "/zah.fina": "\uFEC6", + "/zah.init": "\uFEC7", + "/zah.init_meem.fina": "\uFC28", + "/zah.init_meem.medi": "\uFCB9", + "/zah.isol": "\uFEC5", + "/zah.medi": "\uFEC8", + "/zah.medi_meem.medi": "\uFD3B", + "/zaharabic": "\u0638", + "/zahfinalarabic": "\uFEC6", + "/zahinitialarabic": "\uFEC7", + "/zahiragana": "\u3056", + "/zahmedialarabic": "\uFEC8", + "/zain": "\u0632", + "/zain.fina": "\uFEB0", + "/zain.isol": "\uFEAF", + "/zainabove": "\u0617", + "/zainarabic": "\u0632", + "/zainfinalarabic": "\uFEB0", + "/zakatakana": "\u30B6", + "/zaqefGadol:hb": "\u0595", + "/zaqefQatan:hb": "\u0594", + "/zaqefgadolhebrew": "\u0595", + "/zaqefqatanhebrew": "\u0594", + "/zarqa:hb": "\u0598", + "/zarqahebrew": "\u0598", + "/zayin": "\u05D6", + "/zayin:hb": "\u05D6", + "/zayindagesh": "\uFB36", + "/zayindageshhebrew": "\uFB36", + "/zayinhebrew": "\u05D6", + "/zayinwithdagesh:hb": "\uFB36", + "/zbopomofo": "\u3117", + "/zcaron": "\u017E", + "/zcircle": "\u24E9", + "/zcircumflex": "\u1E91", + "/zcurl": "\u0291", + "/zdescender": "\u2C6C", + "/zdot": "\u017C", + "/zdotaccent": "\u017C", + "/zdotbelow": "\u1E93", + "/zecyr": "\u0437", + "/zecyrillic": "\u0437", + "/zedescendercyrillic": "\u0499", + "/zedieresiscyr": "\u04DF", + "/zedieresiscyrillic": "\u04DF", + "/zehiragana": "\u305C", + "/zekatakana": "\u30BC", + "/zero": "\u0030", + "/zero.inferior": "\u2080", + "/zero.superior": "\u2070", + "/zeroarabic": "\u0660", + "/zerobengali": "\u09E6", + "/zerocircle": "\u24EA", + "/zerocircleblack": "\u24FF", + "/zerocomma": "\u1F101", + "/zerodeva": "\u0966", + "/zerofar": "\u06F0", + "/zerofullstop": "\u1F100", + "/zerogujarati": "\u0AE6", + "/zerogurmukhi": "\u0A66", + "/zerohackarabic": "\u0660", + "/zeroinferior": "\u2080", + "/zeromonospace": "\uFF10", + "/zerooldstyle": "\uF730", + "/zeropersian": "\u06F0", + "/zerosquareabove": "\u06E0", + "/zerosuperior": "\u2070", + "/zerothai": "\u0E50", + "/zerothirds": "\u2189", + "/zerowidthjoiner": "\uFEFF", + "/zerowidthnobreakspace": "\uFEFF", + "/zerowidthnonjoiner": "\u200C", + "/zerowidthspace": "\u200B", + "/zeta": "\u03B6", + "/zetailcyr": "\u0499", + "/zhbopomofo": "\u3113", + "/zhearmenian": "\u056A", + "/zhebrevecyr": "\u04C2", + "/zhebrevecyrillic": "\u04C2", + "/zhecyr": "\u0436", + "/zhecyrillic": "\u0436", + "/zhedescendercyrillic": "\u0497", + "/zhedieresiscyr": "\u04DD", + "/zhedieresiscyrillic": "\u04DD", + "/zhetailcyr": "\u0497", + "/zhook": "\u0225", + "/zihiragana": "\u3058", + "/zikatakana": "\u30B8", + "/zildefunc": "\u236C", + "/zinorhebrew": "\u05AE", + "/zjekomicyr": "\u0505", + "/zlinebelow": "\u1E95", + "/zmonospace": "\uFF5A", + "/znotationbagmembership": "\u22FF", + "/zohiragana": "\u305E", + "/zokatakana": "\u30BE", + "/zparen": "\u24B5", + "/zparenthesized": "\u24B5", + "/zretroflex": "\u0290", + "/zretroflexhook": "\u0290", + "/zstroke": "\u01B6", + "/zswashtail": "\u0240", + "/zuhiragana": "\u305A", + "/zukatakana": "\u30BA", + "/zwarakay": "\u0659", + # manually added from + # https://github.com/serviceprototypinglab/latex-pdfa/blob/master/glyphtounicode-cmr.tex + "/angbracketleftBig": "\u28E8", + "/angbracketleftBigg": "\u27E8", + "/angbracketleftbig": "\u27E8", + "/angbracketleftbigg": "\u27E8", + "/angbracketrightBig": "\u27E9", + "/angbracketrightBigg": "\u27E9", + "/angbracketrightbig": "\u27E9", + "/angbracketrightbigg": "\u27E9", + "/arrowbt": "\u2193", + "/arrowdblbt": "\u21D3", + "/arrowdbltp": "\u21D1", + "/arrowhookleft": "\u21AA", + "/arrowhookright": "\u21A9", + "/arrowtp": "\u2191", + # diff : "/arrowvertex": "\u23D0", + "/arrowvertexdbl": "\uED12", + "/backslashBig": "\u005C", + "/backslashBigg": "\u005C", + "/backslashbig": "\u005C", + "/backslashbigg": "\u005C", + # diff : "/braceex": "\u23AA", + "/bracehtipdownleft": "\uED17", + "/bracehtipdownright": "\uED18", + "/bracehtipupleft": "\uED19", + "/bracehtipupright": "\uED1A", + "/braceleftBig": "\u007B", + "/braceleftBigg": "\u007B", + "/braceleftbig": "\u007B", + "/braceleftbigg": "\u007B", + # diff : "/braceleftbt": "\u23A9", + # diff : "/braceleftmid": "\u23A8", + # diff : "/bracelefttp": "\u23A7", + "/bracerightBig": "\u007D", + "/bracerightBigg": "\u007D", + "/bracerightbig": "\u007D", + "/bracerightbigg": "\u007D", + # diff : "/bracerightbt": "\u23AD", + # diff : "/bracerightmid": "\u23AC", + # diff : "/bracerighttp": "\u23AB", + "/bracketleftBig": "\u005B", + "/bracketleftBigg": "\u005B", + "/bracketleftbig": "\u005B", + "/bracketleftbigg": "\u005B", + # diff : "/bracketleftbt": "\u23A3", + # diff : "/bracketleftex": "\u23A2", + # diff : "/bracketlefttp": "\u23A1", + "/bracketrightBig": "\u005D", + "/bracketrightBigg": "\u005D", + "/bracketrightbig": "\u005D", + "/bracketrightbigg": "\u005D", + # diff : "/bracketrightbt": "\u23A6", + # diff : "/bracketrightex": "\u23A5", + # diff : "/bracketrighttp": "\u23A4", + "/ceilingleftBig": "\u2308", + "/ceilingleftBigg": "\u2308", + "/ceilingleftbig": "\u2308", + "/ceilingleftbigg": "\u2308", + "/ceilingrightBig": "\u2309", + "/ceilingrightBigg": "\u2309", + "/ceilingrightbig": "\u2309", + "/ceilingrightbigg": "\u2309", + "/circledotdisplay": "\u2A00", + "/circledottext": "\u2A00", + "/circlemultiplydisplay": "\u2A02", + "/circlemultiplytext": "\u2A02", + "/circleplusdisplay": "\u2A01", + "/circleplustext": "\u2A01", + "/contintegraldisplay": "\u222E", + "/contintegraltext": "\u222E", + "/coproductdisplay": "\u2210", + "/coproducttext": "\u2210", + "/floorleftBig": "\u230A", + "/floorleftBigg": "\u230A", + "/floorleftbig": "\u230A", + "/floorleftbigg": "\u230A", + "/floorrightBig": "\u230B", + "/floorrightBigg": "\u230B", + "/floorrightbig": "\u230B", + "/floorrightbigg": "\u230B", + "/hatwide": "\u02C6", + "/hatwider": "\u02C6", + "/hatwidest": "\u02C6", + "/integraldisplay": "\u222B", + "/integraltext": "\u222B", + "/intersectiondisplay": "\u22C2", + "/intersectiontext": "\u22C2", + "/logicalanddisplay": "\u22C0", + "/logicalandtext": "\u22C0", + "/logicalordisplay": "\u22C1", + "/logicalortext": "\u22C1", + "/mapsto": "\u21A6", + "/parenleftBig": "\u0028", + "/parenleftBigg": "\u0028", + "/parenleftbig": "\u0028", + "/parenleftbigg": "\u0028", + # diff : "/parenleftbt": "\u239D", + # diff : "/parenleftex": "\u239C", + # diff : "/parenlefttp": "\u239B", + "/parenrightBig": "\u0029", + "/parenrightBigg": "\u0029", + "/parenrightbig": "\u0029", + "/parenrightbigg": "\u0029", + # diff : "/parenrightbt": "\u23A0", + # diff : "/parenrightex": "\u239F", + # diff : "/parenrighttp": "\u239E", + "/productdisplay": "\u220F", + "/producttext": "\u220F", + "/radicalBig": "\u221A", + "/radicalBigg": "\u221A", + "/radicalbig": "\u221A", + "/radicalbigg": "\u221A", + "/radicalbt": "\u221A", + "/radicaltp": "\uED6A", + "/radicalvertex": "\uED6B", + "/slashBig": "\u002F", + "/slashBigg": "\u002F", + "/slashbig": "\u002F", + "/slashbigg": "\u002F", + "/summationdisplay": "\u2211", + "/summationtext": "\u2211", + "/tie": "\u2040", + "/tildewide": "\u02DC", + "/tildewider": "\u02DC", + "/tildewidest": "\u02DC", + "/uniondisplay": "\u22C3", + "/unionmultidisplay": "\u2A04", + "/unionmultitext": "\u2A04", + "/unionsqdisplay": "\u2A06", + "/unionsqtext": "\u2A06", + "/uniontext": "\u22C3", + "/vextenddouble": "\uED79", + "/vextendsingle": "\u23D0", + "/a1": "\u25C1", + "/a2": "\u22B4", + "/a3": "\u25B7", + "/a4": "\u22B5", + "/a40": "\u02C2", + "/a41": "\u02C3", + "/a42": "\u2303", + "/a43": "\u2304", + "/a48": "\u2127", + "/a49": "\u22C8", + "/a50": "\u25A1", + "/a51": "\u25C7", + "/a58": "\u2053", + "/a59": "\u219D", + "/a60": "\u228F", + "/a61": "\u2290", + "/d0": "\u2199", + "/d1": "\u2199", + "/d2": "\u2199", + "/d3": "\u2199", + "/d4": "\u2199", + "/d5": "\u2199", + "/d6": "\u2199", + "/d7": "\u2193", + "/d8": "\u2193", + "/d9": "\u2193", + "/d10": "\u2193", + "/d11": "\u2193", + "/d12": "\u2193", + "/d13": "\u2193", + "/d14": "\u2193", + "/d15": "\u2193", + "/d16": "\u2193", + "/d17": "\u2193", + "/d18": "\u2193", + "/d19": "\u2193", + "/d20": "\u2193", + "/d21": "\u2193", + "/d22": "\u2193", + "/d23": "\u2193", + "/d24": "\u2198", + "/d25": "\u2198", + "/d26": "\u2198", + "/d27": "\u2198", + "/d28": "\u2198", + "/d29": "\u2198", + "/d30": "\u2198", + "/d31": "\u2198", + "/d32": "\u2198", + "/d33": "\u2198", + "/d34": "\u2198", + "/d35": "\u2198", + "/d36": "\u2198", + "/d37": "\u2198", + "/d38": "\u2198", + "/d39": "\u2192", + "/d40": "\u2192", + "/d41": "\u2192", + "/d42": "\u2192", + "/d43": "\u2192", + "/d44": "\u2192", + "/d45": "\u2192", + "/d46": "\u2192", + "/d47": "\u2192", + "/d48": "\u2192", + "/d49": "\u2192", + "/d50": "\u2192", + "/d51": "\u2192", + "/d52": "\u2192", + "/d53": "\u2192", + "/d54": "\u2192", + "/d55": "\u2192", + "/d56": "\u2197", + "/d57": "\u2197", + "/d58": "\u2197", + "/d59": "\u2197", + "/d60": "\u2197", + "/d61": "\u2197", + "/d62": "\u2197", + "/d63": "\u2197", + "/d64": "\u2197", + "/d65": "\u2197", + "/d66": "\u2197", + "/d67": "\u2197", + "/d68": "\u2197", + "/d69": "\u2197", + "/d70": "\u2197", + "/d71": "\u2191", + "/d72": "\u2191", + "/d73": "\u2191", + "/d74": "\u2191", + "/d75": "\u2191", + "/d76": "\u2191", + "/d77": "\u2191", + "/d78": "\u2191", + "/d79": "\u2191", + "/d80": "\u2191", + "/d81": "\u2191", + "/d82": "\u2191", + "/d83": "\u2191", + "/d84": "\u2191", + "/d85": "\u2191", + "/d86": "\u2191", + "/d87": "\u2191", + "/d88": "\u2196", + "/d89": "\u2196", + "/d90": "\u2196", + "/d91": "\u2196", + "/d92": "\u2196", + "/d93": "\u2196", + "/d94": "\u2196", + "/d95": "\u2196", + "/d96": "\u2196", + "/d97": "\u2196", + "/d98": "\u2196", + "/d99": "\u2196", + "/d100": "\u2196", + "/d101": "\u2196", + "/d102": "\u2196", + "/d103": "\u2190", + "/d104": "\u2190", + "/d105": "\u2190", + "/d106": "\u2190", + "/d107": "\u2190", + "/d108": "\u2190", + "/d109": "\u2190", + "/d110": "\u2190", + "/d111": "\u2190", + "/d112": "\u2190", + "/d113": "\u2190", + "/d114": "\u2190", + "/d115": "\u2190", + "/d116": "\u2190", + "/d117": "\u2190", + "/d118": "\u2190", + "/d119": "\u2190", + "/d120": "\u2199", + "/d121": "\u2199", + "/d122": "\u2199", + "/d123": "\u2199", + "/d124": "\u2199", + "/d125": "\u2199", + "/d126": "\u2199", + "/d127": "\u2199", + # manually added from + # https://github.com/kohler/lcdf-typetools/blob/master/texglyphlist.txt + "/Ifractur": "\u2111", + "/FFsmall": "\uF766", + "/FFIsmall": "\uF766", + "/FFLsmall": "\uF766", + "/FIsmall": "\uF766", + "/FLsmall": "\uF766", + # diff : "/Germandbls": "\u0053", + "/Germandblssmall": "\uF773", + "/Ng": "\u014A", + "/Rfractur": "\u211C", + "/SS": "\u0053", + "/SSsmall": "\uF773", + "/altselector": "\uD802", + "/angbracketleft": "\u27E8", + "/angbracketright": "\u27E9", + "/arrowbothv": "\u2195", + "/arrowdblbothv": "\u21D5", + "/arrowleftbothalf": "\u21BD", + "/arrowlefttophalf": "\u21BC", + "/arrownortheast": "\u2197", + "/arrownorthwest": "\u2196", + "/arrowrightbothalf": "\u21C1", + "/arrowrighttophalf": "\u21C0", + "/arrowsoutheast": "\u2198", + "/arrowsouthwest": "\u2199", + "/ascendercompwordmark": "\uD80A", + "/asteriskcentered": "\u2217", + "/bardbl": "\u2225", + "/capitalcompwordmark": "\uD809", + "/circlecopyrt": "\u20DD", + "/circledivide": "\u2298", + "/circleminus": "\u2296", + "/coproduct": "\u2A3F", + "/ct": "\u0063", + "/cwm": "\u200C", + "/dblbracketleft": "\u27E6", + "/dblbracketright": "\u27E7", + # diff : "/diamond": "\u2662", + "/diamondmath": "\u22C4", + # diff : "/dotlessj": "\u0237", + "/emptyslot": "\uD801", + "/epsilon1": "\u03F5", + "/epsiloninv": "\u03F6", + "/equivasymptotic": "\u224D", + "/flat": "\u266D", + "/follows": "\u227B", + "/followsequal": "\u2AB0", + "/followsorcurly": "\u227D", + "/greatermuch": "\u226B", + # diff : "/heart": "\u2661", + "/interrobangdown": "\u2E18", + "/intersectionsq": "\u2293", + "/latticetop": "\u22A4", + "/lessmuch": "\u226A", + "/longdbls": "\u017F", + "/longsh": "\u017F", + "/longsi": "\u017F", + "/longsl": "\u017F", + "/longst": "\uFB05", + "/lscript": "\u2113", + "/natural": "\u266E", + "/negationslash": "\u0338", + "/ng": "\u014B", + "/owner": "\u220B", + "/pertenthousand": "\u2031", + # diff : "/phi": "\u03D5", + # diff : "/phi1": "\u03C6", + "/pi1": "\u03D6", + "/precedesequal": "\u2AAF", + "/precedesorcurly": "\u227C", + "/prime": "\u2032", + "/rho1": "\u03F1", + "/ringfitted": "\uD80D", + "/sharp": "\u266F", + "/similarequal": "\u2243", + "/slurabove": "\u2322", + "/slurbelow": "\u2323", + "/st": "\uFB06", + "/subsetsqequal": "\u2291", + "/supersetsqequal": "\u2292", + "/triangle": "\u25B3", + "/triangleinv": "\u25BD", + "/triangleleft": "\u25C1", + # diff : "/triangleright": "\u25B7", + "/turnstileleft": "\u22A2", + "/turnstileright": "\u22A3", + "/twelveudash": "\uD80C", + "/unionmulti": "\u228E", + "/unionsq": "\u2294", + "/vector": "\u20D7", + "/visualspace": "\u2423", + "/Dbar": "\u0110", + "/compwordmark": "\u200C", + "/dbar": "\u0111", + "/rangedash": "\u2013", + "/hyphenchar": "\u002D", + "/punctdash": "\u2014", + "/visiblespace": "\u2423", + "/Yen": "\u00A5", + "/anticlockwise": "\u27F2", + "/arrowparrleftright": "\u21C6", + "/arrowparrrightleft": "\u21C4", + "/arrowtailleft": "\u21A2", + "/arrowtailright": "\u21A3", + "/arrowtripleleft": "\u21DA", + "/arrowtripleright": "\u21DB", + "/check": "\u2713", + "/circleR": "\u00AE", + "/circleS": "\u24C8", + "/circleasterisk": "\u229B", + "/circleequal": "\u229C", + "/circlering": "\u229A", + "/clockwise": "\u27F3", + "/curlyleft": "\u21AB", + "/curlyright": "\u21AC", + "/dblarrowdwn": "\u21CA", + "/dblarrowheadleft": "\u219E", + "/dblarrowheadright": "\u21A0", + # diff : "/dblarrowup": "\u21C8", + "/defines": "\u225C", + "/diamondsolid": "\u2666", + "/difference": "\u224F", + "/downfall": "\u22CE", + "/equaldotleftright": "\u2252", + "/equaldotrightleft": "\u2253", + "/equalorfollows": "\u22DF", + # diff : "/equalorgreater": "\u2A96", + # diff : "/equalorless": "\u2A95", + "/equalsdots": "\u2251", + "/followsorequal": "\u227F", + "/forcesbar": "\u22AA", + # diff : "/fork": "\u22D4", + "/geomequivalent": "\u224E", + "/greaterdbleqlless": "\u2A8C", + "/greaterdblequal": "\u2267", + "/greaterlessequal": "\u22DB", + "/greaterorapproxeql": "\u2A86", + "/greaterorequalslant": "\u2A7E", + "/greaterorsimilar": "\u2273", + "/harpoondownleft": "\u21C3", + "/harpoondownright": "\u21C2", + "/harpoonleftright": "\u21CC", + "/harpoonrightleft": "\u21CB", + "/harpoonupleft": "\u21BF", + "/harpoonupright": "\u21BE", + "/intercal": "\u22BA", + "/lessdbleqlgreater": "\u2A8B", + "/lessdblequal": "\u2266", + "/lessequalgreater": "\u22DA", + "/lessorapproxeql": "\u2A85", + "/lessorequalslant": "\u2A7D", + "/lessorsimilar": "\u2272", + "/maltesecross": "\u2720", + "/multiopenleft": "\u22CB", + "/multiopenright": "\u22CC", + "/orunderscore": "\u22BB", + "/perpcorrespond": "\u2A5E", + # diff : "/precedesorequal": "\u227E", + "/primereverse": "\u2035", + "/revasymptequal": "\u22CD", + "/revsimilar": "\u223D", + "/rightanglene": "\u231D", + "/rightanglenw": "\u231C", + "/rightanglese": "\u231F", + "/rightanglesw": "\u231E", + "/satisfies": "\u22A8", + "/shiftleft": "\u21B0", + "/shiftright": "\u21B1", + "/square": "\u25A1", + "/squaredot": "\u22A1", + "/squareminus": "\u229F", + "/squaremultiply": "\u22A0", + "/squareplus": "\u229E", + "/squaresolid": "\u25A0", + "/squiggleleftright": "\u21AD", + "/squiggleright": "\u21DD", + "/subsetdblequal": "\u2AC5", + "/supersetdbl": "\u22D1", + "/supersetdblequal": "\u2AC6", + "/triangledownsld": "\u25BC", + "/triangleleftequal": "\u22B4", + "/triangleleftsld": "\u25C0", + "/trianglerightequal": "\u22B5", + "/trianglerightsld": "\u25B6", + "/trianglesolid": "\u25B2", + "/uprise": "\u22CF", + # diff : "/Digamma": "\u1D7C", + "/Finv": "\u2132", + "/Gmir": "\u2141", + "/Omegainv": "\u2127", + "/approxorequal": "\u224A", + "/archleftdown": "\u21B6", + "/archrightdown": "\u21B7", + "/beth": "\u2136", + "/daleth": "\u2138", + "/dividemultiply": "\u22C7", + "/downslope": "\u29F9", + "/equalorsimilar": "\u2242", + "/follownotdbleqv": "\u2ABA", + "/follownotslnteql": "\u2AB6", + "/followornoteqvlnt": "\u22E9", + "/greaternotdblequal": "\u2A8A", + "/greaternotequal": "\u2A88", + "/greaterornotdbleql": "\u2269", + "/greaterornotequal": "\u2269", + "/integerdivide": "\u2216", + "/lessnotdblequal": "\u2A89", + "/lessnotequal": "\u2A87", + "/lessornotdbleql": "\u2268", + "/lessornotequal": "\u2268", + "/multicloseleft": "\u22C9", + "/multicloseright": "\u22CA", + "/notapproxequal": "\u2247", + "/notarrowboth": "\u21AE", + "/notarrowleft": "\u219A", + "/notarrowright": "\u219B", + "/notbar": "\u2224", + "/notdblarrowboth": "\u21CE", + "/notdblarrowleft": "\u21CD", + "/notdblarrowright": "\u21CF", + "/notfollows": "\u2281", + "/notfollowsoreql": "\u2AB0", + "/notforces": "\u22AE", + "/notforcesextra": "\u22AF", + "/notgreaterdblequal": "\u2267", + "/notgreaterequal": "\u2271", + "/notgreaterorslnteql": "\u2A7E", + "/notlessdblequal": "\u2266", + "/notlessequal": "\u2270", + "/notlessorslnteql": "\u2A7D", + "/notprecedesoreql": "\u2AAF", + "/notsatisfies": "\u22AD", + "/notsimilar": "\u2241", + "/notsubseteql": "\u2288", + "/notsubsetordbleql": "\u2AC5", + "/notsubsetoreql": "\u228A", + "/notsuperseteql": "\u2289", + "/notsupersetordbleql": "\u2AC6", + "/notsupersetoreql": "\u228B", + "/nottriangeqlleft": "\u22EC", + "/nottriangeqlright": "\u22ED", + "/nottriangleleft": "\u22EA", + "/nottriangleright": "\u22EB", + "/notturnstile": "\u22AC", + "/planckover2pi": "\u210F", + "/planckover2pi1": "\u210F", + "/precedenotdbleqv": "\u2AB9", + "/precedenotslnteql": "\u2AB5", + "/precedeornoteqvlnt": "\u22E8", + "/subsetnoteql": "\u228A", + "/subsetornotdbleql": "\u2ACB", + "/supersetnoteql": "\u228B", + "/supersetornotdbleql": "\u2ACC", + "/upslope": "\u29F8", +} + + +def _complete() -> None: + for i in range(256): + adobe_glyphs[f"/a{i}"] = chr(i) + adobe_glyphs["/.notdef"] = "□" + + +_complete() diff --git a/venv/lib/python3.12/site-packages/pypdf/_codecs/pdfdoc.py b/venv/lib/python3.12/site-packages/pypdf/_codecs/pdfdoc.py new file mode 100644 index 0000000..306357a --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_codecs/pdfdoc.py @@ -0,0 +1,264 @@ +# PDFDocEncoding Character Set: Table D.2 of PDF Reference 1.7 +# C.1 Predefined encodings sorted by character name of another PDF reference +# Some indices have '\u0000' although they should have something else: +# 22: should be '\u0017' +_pdfdoc_encoding = [ + "\u0000", + "\u0001", + "\u0002", + "\u0003", + "\u0004", + "\u0005", + "\u0006", + "\u0007", # 0 - 7 + "\u0008", + "\u0009", + "\u000a", + "\u000b", + "\u000c", + "\u000d", + "\u000e", + "\u000f", # 8 - 15 + "\u0010", + "\u0011", + "\u0012", + "\u0013", + "\u0014", + "\u0015", + "\u0000", + "\u0017", # 16 - 23 + "\u02d8", + "\u02c7", + "\u02c6", + "\u02d9", + "\u02dd", + "\u02db", + "\u02da", + "\u02dc", # 24 - 31 + "\u0020", + "\u0021", + "\u0022", + "\u0023", + "\u0024", + "\u0025", + "\u0026", + "\u0027", # 32 - 39 + "\u0028", + "\u0029", + "\u002a", + "\u002b", + "\u002c", + "\u002d", + "\u002e", + "\u002f", # 40 - 47 + "\u0030", + "\u0031", + "\u0032", + "\u0033", + "\u0034", + "\u0035", + "\u0036", + "\u0037", # 48 - 55 + "\u0038", + "\u0039", + "\u003a", + "\u003b", + "\u003c", + "\u003d", + "\u003e", + "\u003f", # 56 - 63 + "\u0040", + "\u0041", + "\u0042", + "\u0043", + "\u0044", + "\u0045", + "\u0046", + "\u0047", # 64 - 71 + "\u0048", + "\u0049", + "\u004a", + "\u004b", + "\u004c", + "\u004d", + "\u004e", + "\u004f", # 72 - 79 + "\u0050", + "\u0051", + "\u0052", + "\u0053", + "\u0054", + "\u0055", + "\u0056", + "\u0057", # 80 - 87 + "\u0058", + "\u0059", + "\u005a", + "\u005b", + "\u005c", + "\u005d", + "\u005e", + "\u005f", # 88 - 95 + "\u0060", + "\u0061", + "\u0062", + "\u0063", + "\u0064", + "\u0065", + "\u0066", + "\u0067", # 96 - 103 + "\u0068", + "\u0069", + "\u006a", + "\u006b", + "\u006c", + "\u006d", + "\u006e", + "\u006f", # 104 - 111 + "\u0070", + "\u0071", + "\u0072", + "\u0073", + "\u0074", + "\u0075", + "\u0076", + "\u0077", # 112 - 119 + "\u0078", + "\u0079", + "\u007a", + "\u007b", + "\u007c", + "\u007d", + "\u007e", + "\u0000", # 120 - 127 + "\u2022", + "\u2020", + "\u2021", + "\u2026", + "\u2014", + "\u2013", + "\u0192", + "\u2044", # 128 - 135 + "\u2039", + "\u203a", + "\u2212", + "\u2030", + "\u201e", + "\u201c", + "\u201d", + "\u2018", # 136 - 143 + "\u2019", + "\u201a", + "\u2122", + "\ufb01", + "\ufb02", + "\u0141", + "\u0152", + "\u0160", # 144 - 151 + "\u0178", + "\u017d", + "\u0131", + "\u0142", + "\u0153", + "\u0161", + "\u017e", + "\u0000", # 152 - 159 + "\u20ac", + "\u00a1", + "\u00a2", + "\u00a3", + "\u00a4", + "\u00a5", + "\u00a6", + "\u00a7", # 160 - 167 + "\u00a8", + "\u00a9", + "\u00aa", + "\u00ab", + "\u00ac", + "\u0000", + "\u00ae", + "\u00af", # 168 - 175 + "\u00b0", + "\u00b1", + "\u00b2", + "\u00b3", + "\u00b4", + "\u00b5", + "\u00b6", + "\u00b7", # 176 - 183 + "\u00b8", + "\u00b9", + "\u00ba", + "\u00bb", + "\u00bc", + "\u00bd", + "\u00be", + "\u00bf", # 184 - 191 + "\u00c0", + "\u00c1", + "\u00c2", + "\u00c3", + "\u00c4", + "\u00c5", + "\u00c6", + "\u00c7", # 192 - 199 + "\u00c8", + "\u00c9", + "\u00ca", + "\u00cb", + "\u00cc", + "\u00cd", + "\u00ce", + "\u00cf", # 200 - 207 + "\u00d0", + "\u00d1", + "\u00d2", + "\u00d3", + "\u00d4", + "\u00d5", + "\u00d6", + "\u00d7", # 208 - 215 + "\u00d8", + "\u00d9", + "\u00da", + "\u00db", + "\u00dc", + "\u00dd", + "\u00de", + "\u00df", # 216 - 223 + "\u00e0", + "\u00e1", + "\u00e2", + "\u00e3", + "\u00e4", + "\u00e5", + "\u00e6", + "\u00e7", # 224 - 231 + "\u00e8", + "\u00e9", + "\u00ea", + "\u00eb", + "\u00ec", + "\u00ed", + "\u00ee", + "\u00ef", # 232 - 239 + "\u00f0", + "\u00f1", + "\u00f2", + "\u00f3", + "\u00f4", + "\u00f5", + "\u00f6", + "\u00f7", # 240 - 247 + "\u00f8", + "\u00f9", + "\u00fa", + "\u00fb", + "\u00fc", + "\u00fd", + "\u00fe", + "\u00ff", # 248 - 255 +] + +assert len(_pdfdoc_encoding) == 256 diff --git a/venv/lib/python3.12/site-packages/pypdf/_codecs/std.py b/venv/lib/python3.12/site-packages/pypdf/_codecs/std.py new file mode 100644 index 0000000..a6057ff --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_codecs/std.py @@ -0,0 +1,258 @@ +_std_encoding = [ + "\x00", + "\x01", + "\x02", + "\x03", + "\x04", + "\x05", + "\x06", + "\x07", + "\x08", + "\t", + "\n", + "\x0b", + "\x0c", + "\r", + "\x0e", + "\x0f", + "\x10", + "\x11", + "\x12", + "\x13", + "\x14", + "\x15", + "\x16", + "\x17", + "\x18", + "\x19", + "\x1a", + "\x1b", + "\x1c", + "\x1d", + "\x1e", + "\x1f", + " ", + "!", + '"', + "#", + "$", + "%", + "&", + "’", + "(", + ")", + "*", + "+", + ",", + "-", + ".", + "/", + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + ":", + ";", + "<", + "=", + ">", + "?", + "@", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "[", + "\\", + "]", + "^", + "_", + "‘", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "{", + "|", + "}", + "~", + "\x7f", + "\x80", + "\x81", + "\x82", + "\x83", + "\x84", + "\x85", + "\x86", + "\x87", + "\x88", + "\x89", + "\x8a", + "\x8b", + "\x8c", + "\x8d", + "\x8e", + "\x8f", + "\x90", + "\x91", + "\x92", + "\x93", + "\x94", + "\x95", + "\x96", + "\x97", + "\x98", + "\x99", + "\x9a", + "\x9b", + "\x9c", + "\x9d", + "\x9e", + "\x9f", + "\xa0", + "¡", + "¢", + "£", + "⁄", + "¥", + "ƒ", + "§", + "¤", + "'", + "“", + "«", + "‹", + "›", + "fi", + "fl", + "°", + "–", + "†", + "‡", + "·", + "µ", + "¶", + "•", + "‚", + "„", + "”", + "»", + "…", + "‰", + "¾", + "¿", + "À", + "`", + "´", + "ˆ", + "˜", + "¯", + "˘", + "˙", + "¨", + "É", + "˚", + "¸", + "Ì", + "˝", + "˛", + "ˇ", + "—", + "Ñ", + "Ò", + "Ó", + "Ô", + "Õ", + "Ö", + "×", + "Ø", + "Ù", + "Ú", + "Û", + "Ü", + "Ý", + "Þ", + "ß", + "à", + "Æ", + "â", + "ª", + "ä", + "å", + "æ", + "ç", + "Ł", + "Ø", + "Œ", + "º", + "ì", + "í", + "î", + "ï", + "ð", + "æ", + "ò", + "ó", + "ô", + "ı", + "ö", + "÷", + "ł", + "ø", + "œ", + "ß", + "ü", + "ý", + "þ", + "ÿ", +] diff --git a/venv/lib/python3.12/site-packages/pypdf/_codecs/symbol.py b/venv/lib/python3.12/site-packages/pypdf/_codecs/symbol.py new file mode 100644 index 0000000..4c0d680 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_codecs/symbol.py @@ -0,0 +1,260 @@ +# manually generated from https://www.unicode.org/Public/MAPPINGS/VENDORS/ADOBE/symbol.txt +_symbol_encoding = [ + "\u0000", + "\u0001", + "\u0002", + "\u0003", + "\u0004", + "\u0005", + "\u0006", + "\u0007", + "\u0008", + "\u0009", + "\u000A", + "\u000B", + "\u000C", + "\u000D", + "\u000E", + "\u000F", + "\u0010", + "\u0011", + "\u0012", + "\u0013", + "\u0014", + "\u0015", + "\u0016", + "\u0017", + "\u0018", + "\u0019", + "\u001A", + "\u001B", + "\u001C", + "\u001D", + "\u001E", + "\u001F", + "\u0020", + "\u0021", + "\u2200", + "\u0023", + "\u2203", + "\u0025", + "\u0026", + "\u220B", + "\u0028", + "\u0029", + "\u2217", + "\u002B", + "\u002C", + "\u2212", + "\u002E", + "\u002F", + "\u0030", + "\u0031", + "\u0032", + "\u0033", + "\u0034", + "\u0035", + "\u0036", + "\u0037", + "\u0038", + "\u0039", + "\u003A", + "\u003B", + "\u003C", + "\u003D", + "\u003E", + "\u003F", + "\u2245", + "\u0391", + "\u0392", + "\u03A7", + "\u0394", + "\u0395", + "\u03A6", + "\u0393", + "\u0397", + "\u0399", + "\u03D1", + "\u039A", + "\u039B", + "\u039C", + "\u039D", + "\u039F", + "\u03A0", + "\u0398", + "\u03A1", + "\u03A3", + "\u03A4", + "\u03A5", + "\u03C2", + "\u03A9", + "\u039E", + "\u03A8", + "\u0396", + "\u005B", + "\u2234", + "\u005D", + "\u22A5", + "\u005F", + "\uF8E5", + "\u03B1", + "\u03B2", + "\u03C7", + "\u03B4", + "\u03B5", + "\u03C6", + "\u03B3", + "\u03B7", + "\u03B9", + "\u03D5", + "\u03BA", + "\u03BB", + "\u00B5", + "\u03BD", + "\u03BF", + "\u03C0", + "\u03B8", + "\u03C1", + "\u03C3", + "\u03C4", + "\u03C5", + "\u03D6", + "\u03C9", + "\u03BE", + "\u03C8", + "\u03B6", + "\u007B", + "\u007C", + "\u007D", + "\u223C", + "\u007F", + "\u0080", + "\u0081", + "\u0082", + "\u0083", + "\u0084", + "\u0085", + "\u0086", + "\u0087", + "\u0088", + "\u0089", + "\u008A", + "\u008B", + "\u008C", + "\u008D", + "\u008E", + "\u008F", + "\u0090", + "\u0091", + "\u0092", + "\u0093", + "\u0094", + "\u0095", + "\u0096", + "\u0097", + "\u0098", + "\u0099", + "\u009A", + "\u009B", + "\u009C", + "\u009D", + "\u009E", + "\u009F", + "\u20AC", + "\u03D2", + "\u2032", + "\u2264", + "\u2044", + "\u221E", + "\u0192", + "\u2663", + "\u2666", + "\u2665", + "\u2660", + "\u2194", + "\u2190", + "\u2191", + "\u2192", + "\u2193", + "\u00B0", + "\u00B1", + "\u2033", + "\u2265", + "\u00D7", + "\u221D", + "\u2202", + "\u2022", + "\u00F7", + "\u2260", + "\u2261", + "\u2248", + "\u2026", + "\uF8E6", + "\uF8E7", + "\u21B5", + "\u2135", + "\u2111", + "\u211C", + "\u2118", + "\u2297", + "\u2295", + "\u2205", + "\u2229", + "\u222A", + "\u2283", + "\u2287", + "\u2284", + "\u2282", + "\u2286", + "\u2208", + "\u2209", + "\u2220", + "\u2207", + "\uF6DA", + "\uF6D9", + "\uF6DB", + "\u220F", + "\u221A", + "\u22C5", + "\u00AC", + "\u2227", + "\u2228", + "\u21D4", + "\u21D0", + "\u21D1", + "\u21D2", + "\u21D3", + "\u25CA", + "\u2329", + "\uF8E8", + "\uF8E9", + "\uF8EA", + "\u2211", + "\uF8EB", + "\uF8EC", + "\uF8ED", + "\uF8EE", + "\uF8EF", + "\uF8F0", + "\uF8F1", + "\uF8F2", + "\uF8F3", + "\uF8F4", + "\u00F0", + "\u232A", + "\u222B", + "\u2320", + "\uF8F5", + "\u2321", + "\uF8F6", + "\uF8F7", + "\uF8F8", + "\uF8F9", + "\uF8FA", + "\uF8FB", + "\uF8FC", + "\uF8FD", + "\uF8FE", + "\u00FF", +] +assert len(_symbol_encoding) == 256 diff --git a/venv/lib/python3.12/site-packages/pypdf/_codecs/zapfding.py b/venv/lib/python3.12/site-packages/pypdf/_codecs/zapfding.py new file mode 100644 index 0000000..9b6cdbc --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_codecs/zapfding.py @@ -0,0 +1,261 @@ +# manually generated from https://www.unicode.org/Public/MAPPINGS/VENDORS/ADOBE/zdingbat.txt + +_zapfding_encoding = [ + "\u0000", + "\u0001", + "\u0002", + "\u0003", + "\u0004", + "\u0005", + "\u0006", + "\u0007", + "\u0008", + "\u0009", + "\u000A", + "\u000B", + "\u000C", + "\u000D", + "\u000E", + "\u000F", + "\u0010", + "\u0011", + "\u0012", + "\u0013", + "\u0014", + "\u0015", + "\u0016", + "\u0017", + "\u0018", + "\u0019", + "\u001A", + "\u001B", + "\u001C", + "\u001D", + "\u001E", + "\u001F", + "\u0020", + "\u2701", + "\u2702", + "\u2703", + "\u2704", + "\u260E", + "\u2706", + "\u2707", + "\u2708", + "\u2709", + "\u261B", + "\u261E", + "\u270C", + "\u270D", + "\u270E", + "\u270F", + "\u2710", + "\u2711", + "\u2712", + "\u2713", + "\u2714", + "\u2715", + "\u2716", + "\u2717", + "\u2718", + "\u2719", + "\u271A", + "\u271B", + "\u271C", + "\u271D", + "\u271E", + "\u271F", + "\u2720", + "\u2721", + "\u2722", + "\u2723", + "\u2724", + "\u2725", + "\u2726", + "\u2727", + "\u2605", + "\u2729", + "\u272A", + "\u272B", + "\u272C", + "\u272D", + "\u272E", + "\u272F", + "\u2730", + "\u2731", + "\u2732", + "\u2733", + "\u2734", + "\u2735", + "\u2736", + "\u2737", + "\u2738", + "\u2739", + "\u273A", + "\u273B", + "\u273C", + "\u273D", + "\u273E", + "\u273F", + "\u2740", + "\u2741", + "\u2742", + "\u2743", + "\u2744", + "\u2745", + "\u2746", + "\u2747", + "\u2748", + "\u2749", + "\u274A", + "\u274B", + "\u25CF", + "\u274D", + "\u25A0", + "\u274F", + "\u2750", + "\u2751", + "\u2752", + "\u25B2", + "\u25BC", + "\u25C6", + "\u2756", + "\u25D7", + "\u2758", + "\u2759", + "\u275A", + "\u275B", + "\u275C", + "\u275D", + "\u275E", + "\u007F", + "\uF8D7", + "\uF8D8", + "\uF8D9", + "\uF8DA", + "\uF8DB", + "\uF8DC", + "\uF8DD", + "\uF8DE", + "\uF8DF", + "\uF8E0", + "\uF8E1", + "\uF8E2", + "\uF8E3", + "\uF8E4", + "\u008E", + "\u008F", + "\u0090", + "\u0091", + "\u0092", + "\u0093", + "\u0094", + "\u0095", + "\u0096", + "\u0097", + "\u0098", + "\u0099", + "\u009A", + "\u009B", + "\u009C", + "\u009D", + "\u009E", + "\u009F", + "\u00A0", + "\u2761", + "\u2762", + "\u2763", + "\u2764", + "\u2765", + "\u2766", + "\u2767", + "\u2663", + "\u2666", + "\u2665", + "\u2660", + "\u2460", + "\u2461", + "\u2462", + "\u2463", + "\u2464", + "\u2465", + "\u2466", + "\u2467", + "\u2468", + "\u2469", + "\u2776", + "\u2777", + "\u2778", + "\u2779", + "\u277A", + "\u277B", + "\u277C", + "\u277D", + "\u277E", + "\u277F", + "\u2780", + "\u2781", + "\u2782", + "\u2783", + "\u2784", + "\u2785", + "\u2786", + "\u2787", + "\u2788", + "\u2789", + "\u278A", + "\u278B", + "\u278C", + "\u278D", + "\u278E", + "\u278F", + "\u2790", + "\u2791", + "\u2792", + "\u2793", + "\u2794", + "\u2192", + "\u2194", + "\u2195", + "\u2798", + "\u2799", + "\u279A", + "\u279B", + "\u279C", + "\u279D", + "\u279E", + "\u279F", + "\u27A0", + "\u27A1", + "\u27A2", + "\u27A3", + "\u27A4", + "\u27A5", + "\u27A6", + "\u27A7", + "\u27A8", + "\u27A9", + "\u27AA", + "\u27AB", + "\u27AC", + "\u27AD", + "\u27AE", + "\u27AF", + "\u00F0", + "\u27B1", + "\u27B2", + "\u27B3", + "\u27B4", + "\u27B5", + "\u27B6", + "\u27B7", + "\u27B8", + "\u27B9", + "\u27BA", + "\u27BB", + "\u27BC", + "\u27BD", + "\u27BE", + "\u00FF", +] +assert len(_zapfding_encoding) == 256 diff --git a/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__init__.py b/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__init__.py new file mode 100644 index 0000000..215a258 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__init__.py @@ -0,0 +1,86 @@ +# Copyright (c) 2023, exiledkingcc +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +from pypdf._crypt_providers._base import CryptBase, CryptIdentity + +try: + from pypdf._crypt_providers._cryptography import ( + CryptAES, + CryptRC4, + aes_cbc_decrypt, + aes_cbc_encrypt, + aes_ecb_decrypt, + aes_ecb_encrypt, + crypt_provider, + rc4_decrypt, + rc4_encrypt, + ) + from pypdf._utils import Version + + if Version(crypt_provider[1]) <= Version("3.0"): + # This is due to the backend parameter being required back then: + # https://cryptography.io/en/latest/changelog/#v3-1 + raise ImportError("cryptography<=3.0 is not supported") # pragma: no cover +except ImportError: + try: + from pypdf._crypt_providers._pycryptodome import ( # type: ignore + CryptAES, + CryptRC4, + aes_cbc_decrypt, + aes_cbc_encrypt, + aes_ecb_decrypt, + aes_ecb_encrypt, + crypt_provider, + rc4_decrypt, + rc4_encrypt, + ) + except ImportError: + from pypdf._crypt_providers._fallback import ( # type: ignore + CryptAES, + CryptRC4, + aes_cbc_decrypt, + aes_cbc_encrypt, + aes_ecb_decrypt, + aes_ecb_encrypt, + crypt_provider, + rc4_decrypt, + rc4_encrypt, + ) + +__all__ = [ + "CryptAES", + "CryptBase", + "CryptIdentity", + "CryptRC4", + "aes_cbc_decrypt", + "aes_cbc_encrypt", + "aes_ecb_decrypt", + "aes_ecb_encrypt", + "crypt_provider", + "rc4_decrypt", + "rc4_encrypt", +] diff --git a/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0dbdcaa4519ebf8a60079c192c5b1496129d10ce GIT binary patch literal 1185 zcma)5J5Ll*82#?d&dzIhRwdzSu_zR4;*JU=6e|P>1%<|F)G&pU-JQ!aVP3g2fJ0%T zl`$rkYN<9Fe+9HQDBV~YD;l#x1VSvlci81&Lc%Rh&OP7j?6-Hm?JXp!x11n?Rxu#f{TGLXv|90HjsoWr{rBjXB&;AV}iD;lCJ8Img-va1-1s~W1C zGjfRK@=o5>3=IJXSi_2y>7fHY)86bb%@W$Tg!*zhqmO zBr2&7A7-bQR%Qt$;sZ=V+xIrv##i{E^0k#qX}RAZ)nGoZ+@w;`4vU^26~o0K@JWQN zl1kV+AUuN%gDeA)fy6*&z#b8y?*~YZL7u|xQb%$zhy!b`Y@T!(mdzU7(oxG~;IzEs z{tkScae9(#wOovBCnOp*l&CW<`%Tk?_~i7FL3}XO@?D%1Pct@Gb(~tYzL1EfNvUam zf^9kj_UrmQE!6FXXGe6|`YoRlpWGpI%Qy`6CG0Kfj$PA(IGXppq4M<`dT2-ZYCyYH z8#tr^x-YApe-&xhZKA8P<#DEPJ9 z$|>6D9DxPTK)?(HJGRP9x8yA3YzfD9#j?!t+}IZ4%bQPBmZXmZEptZ%X^_{HOeZSpS0c>O43XLwI0H7=XD?ySI&+v? zxufN1ph$tHimk1)SN?81mVP*l!ZeH{|9Ol~tX`;isHE2ZR7O*O6!!ciOLybwLHpi) zUx%r@n*{yW!BA>UBx2z6J}Kjgil?EFO8dNrD%(kx*JWgKduzYNw=3!fsjMTsg_Fx0 z2g?Pz@V{9U6{rS56QLSJEu){;h5V;iMct%=7QrQi4qj%1^C%cg&hsVC$FZ1<$Y0_7 z%_JCA8Ml|EQmYlJTO}}k=>*eI(LEcuj*h;KFoT7~+|Bn-7l7u2EXXWs=c!Yoj0{tH z;dRi@qg7DLKd&QWo|U)E1?~tLrD2+NJX@{dCbdqmLGYKjE5s4p!cWr+p23OJC_5A1 w@vL$Jv-4v0S>s`OCy&%s+)BFiHH3xD82hp9vdyo6aJtG^^WDxjKw}R634c7a*8l(j literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__pycache__/_cryptography.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__pycache__/_cryptography.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ea33409d5fba95498404b40f84d832e0d84f2ebb GIT binary patch literal 5976 zcmds5OH5nY89w*ni@_KhFoXb2XmFZ11T%RI0ZNhqhe=V?XxgL;T&b?{y?}{dJ@{mjBpE$ltJ1Np`caJIxWYNn|2(F%ra_k8yE6 z$a7d0VnSRDimWWgY;h?laikSnY_XQOJ!oewQmifR2s&7~CDtBy2A%PaU#X5+%N>eGcERUXJWG26oVE?>8ev)~gd>|~4 z_c>qRbNq>`K2CRpLTd_Dqsc@l1l5*QSeB!SWhe?WbJrjfXTBXc3%L}CrdAZ{<8>i0 z8_CzBvAbBZAIvalq| zBJ5n0ZCF>ZE84|MQNt1^>3P_A6WyL4Z7MOxcKy)d>B=L~fMOBF{(GFm$ zIBsa@#md-9GOmn8mlIJ9WIFcEBovbLJqmJBRCR1kNvw^B=objJJJ*GxA zWi%Cz+z2l#Dm0|zrLhnbW++9IYf%}_$7Gn&^{3LhJrs(<+@a8VXGJ9b3hOQ0kq5{v z^0asGSJw-}zg&25{YmfXtoT#MF7Syi%3&>BCpDA}liE5IHc5u8V#kKGYDuu#@W?D~ z@ELv;W#5phvW9jPV?(Np$91ofhul@4NV}n|w<-w(Q&g93reMR0ZeNNf!m;Q&o=6Y$ zp$Cx+0#R{iLqkKf7jnJD9J=ndgky5fK=Uq=TV&hQw|V8>m9ocI^!Q4ik!tFP=j zTyz~Sh$Yw22d(AfQ^n&`rQ_2@*YsoiH0^_N|BFJS1F$hmY_ejCjeZ5#^boeyit7k4 z8pLG|sS%gSIfpY0A;Eut*n+rAgyTvmq_>4apc^-1SZ)u6esD7!Gh1wnX-!e-0UUN1 z$uN#JreNnooybKp2A}$MAh*d5&)Lr8=XMBW1$h^<9f`M{M;2rSWf!v@do61ZS!`=; zwg^mQr7zy>fJJ25PF=7_z0E=N;kWArvPr5orw08bWLcs#F^-I*4{7yU{D0K{#JB}4Q zj+HumSz+7Nb$9*Fdfr+7zJ_MBGdFM43)f4Y6GhjF2MguVi^b84rO}z9Yv!?i=4D%ILG?!rsu>6p zWUilpTj69VLy609D%7quRWF%ahZ$u42AC{5S9SHPDDj3Q3l@C$aYzilP2gPz-zM;` zfXjrh1ss4c#tIEdgD}@fuYj)w?@GTK1+xJ#_upYtaM$fn%1APSPekM4067DcZC5E; zW{O6FVmR^qKahNFx)4(m6eUX0htji1EHBdtUvxCSmMVPd+t_^^3H}ttcAb+|JOhT{ z3WkS)QG;RA7tI4#{T&c+-OkS3aPD+=A|A)HRw7YpBy{FthSZp86UoW*EDJ+zao+}+b(ymFE^80yf>E{&;IbS zz2C6UUf4bLAwhR)DC`K9kYISMUI1eF!a>6q4jR62a7Svf&2q@Y9K9jtJ6$f@05Tyf zD0`S0Q?pqSZbpcNHnh$$SV8j7przJfRW&C=Dq2z-BsUB3DtKZcU=xk1(HOoNUMu5` z5Rjrq_-xgXn;E()%pMAc7k)+T=b(|ZA=B(pbe7+RkKF~p_PKk1uH^&w(*^B``()WY zUUZL_+!MFvw;i6cW1#35$X_ZszFL?sd&i63@sf9<=$LpcPP}ZbzEtuHgBUPX{Hg8=D{4rIELxBXK&t}ZF7`DbrRLAv|KOv@mhwe`>PsumdZf{JKt%QE zvcy?I*t^gLubT7{5@r_BO+@ezD#;2B3cz`Dm{rZr8v+gE)n-7m;>zan?CXGL#d1|0 zgv%N;&deiL4Vei4hn|pm1_OGL#fSyHZ$NVrzFpMDI_Nz(vbFrg?Jv70itdS$d+H4> z+W(u7>*4pZkeRi6g^(+NyaKY-;G^?M5RkqBdJ4-9Bq%cdka5E{9=rT2;q`b}^QUMu z4$nSoaP`F{^i%tH@*D3+svjRM`!x8u#rW&^s)D(S?Jy`i0AFTW#HZ?xx>K$xq>oLo?{Et8j zJ&pujH1jhQEh|NPKoRH^527JhdSRb7-W)E_>(Gk#X|)aLj=*u;?gZgn&xrRka{4ne zvm=V!W$u}H>7NqeE`CmCo{`gk=^84GJnr=0>e!RoxbxZc9)WDHe~=r%GGsd!cy2QH z9e8ozCJRSd_FxVk9=OS!wtZXjJ;oS?WuMrpV_x3^;Tz2Ti7~_P-+p;$LkD>E;3ogQ o1CN#V?tc&te)DtjT@=A(?uClMQ(l^Nl24tE*#Y6xeh%n=0SK{G7XSbN literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__pycache__/_fallback.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__pycache__/_fallback.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..82f31d9837f5d4262b87c1a33bbb0039665a48e4 GIT binary patch literal 4016 zcmcgv-EUh-6`#2u{)j&kCvj;ay4d|lFuNPqO;Xz3ZMA8f!mc1RNmdNuGPTe|o zGS>+>vQdTl;Othay^9oA@Zbt08g(W5$REHPFOIT;>QW>mp896$fW$s=&fI%lCrztL zR7`ZwoH=La%$ak3bH@3T&(}qu{q@ej7acxA{(%F#xh$sD0A`b@M5P(BMCU0*UdRYb z;=BmFI4`NvyeyFK5LLcKREI_%i00aP2bVfQ>gtd>Rk!9+yWsO^u9QRd-je3s`(!?l zb?uY+LFU;f>js&Z%X&I&y3_#3eFw;ULGCZ~Mf#thixFzLCs|=Re<7i3FzAkJ%UV{| zvdO{}V>z}SO`JM~J;bz?)il%8P%6hl6H{}cL}oF^()nvk5y9xs zg0Ov*SV@E-ZxC|FR#q8vmA>PmmhJ$JORhFGj3LP6dfyczO1}W~B2Wqywl`aA) zeqc%MzDSg|4OJ)!2hEL>s|$pb#G+6n*X>i;#-T5Y13=f2qeU@~e(+Xo@3!tB#Ga#4 z9F<;VOTc+A+b8*=l_JLZ1uF&A-Bu-1AQ5r;34tguJak6$1nny|dM&r4MbnGfbUvNSM!%l}CdV!@z>=ox(KRi* z7R{s=qRWN+wOkf}btJ^!@O?v-j2C zr?yfLXSUJ}Z>Su~loRmbBR)yORiIgPZg)6W_NiI2F)z;Mu zFyC2}RS{9FN*tkb(E*5;+qgBQD06U(S~|cZa2$J}v3g5q&wXYUSC(9GPn_I_YuyW& zm5NS|&$vYLZu9IYwa+>Sr=;+e#GjIgJZ%D3;2kGV@J=%ikciB{9$|hYQ1A)s24ctv zaXsQ@Jt#Va1ZNmjF~rw`cUD7nu(=yy{8RCOY%0T^*;gu z9D0Klbu(2>?Rbv>00+PETd^MhjeBSCTYvVyS(*7{rQv_GECPAd-M1l?X*mWU{iR+T z`@FCd2tOsVJ8U9#rW&jrtNN@#WuX-4g=Iz+f$Qx4*Vh58Ta{KP*p_6C3eL zxH3^a{-`HViB)E*W3_N?;_mV4yY*w+y(hMNhG122pcbzFsJ2r5NqMqDKe^cSz-GH% z(i5!AeY)Oo4gBY6fONm5Blx~>UkFKiz>GlVU_K7aCKeg1jKZ+po|U^fvPGvOl)VAE zE#XB6l?LF?r_5uW9)?^TqQ)kMbBFvJ(@M}ls!qqvfA1AKpmWtx){!07J+xkZ|SET5@OH3@WewS`^N z-z5*C2)eq~!mfFk%12QIU0vJ7&a{grlkl~hWO1+W353^}*JFkl-TVIGUOY*->n2os z76OJ11BqBkz)Iek1Rfu&wu0q$Z9R|k5DJh1m)ATTUYmnK5dzJg_ZHL4n|*_SLAfu0 z1@z4bD)FgHQ`7OO>B*0ksoB{d%qnx2XIU6@d%VNMSr-nyvo72ONLzS+;llZkeEG)c zj(@D-8slF6j}Ef8!0hvWAa*+ZuwWX;xg$srmFyT247NGMs=*>QIR{J|V^sE;=}#Eum*)x~!*7Un zhub@LCdlxx#=dzXL8@hL4>=g6B7c^jfkL70Bb)3ITcb7;K4Val&fK@u{N`ct*{V z&jXTNNVWrlb>_!7x9!R6@PhH%cJR)24Bm%buk6`*I?`=?o&P8u+5e+-L|K6UpBP#+ zyyg@Q|9#SVIb-+>!0_|OOtF8+nwN)PR{jv-<>0_$2m*#FV0e1=K9ap<<15#D=9_k& zVU5A3R(}knDN;)Rb%xN3W$aRtw_fSY6}YLmAh^aLp@d@L{B}ho*%;j6c70-vlUb IG{#~0U$B`Twg3PC literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__pycache__/_pycryptodome.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/__pycache__/_pycryptodome.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5e9b005425c0d3667fbe1b1792be10267d7d3755 GIT binary patch literal 4373 zcmd5<&2Jk;6rb5$e4DDX#)EOEjX-!{knhDtuplKLj*^JpAHFV3D$;Pmg*3uJt%vRH; zlG7<42WFP&BtkV35j3icnxKiJk|x2oCC!C>9s6$RyK4F#=)1FG&}(`52jL8sctOuv zZl;?TS!y^Y)O-+mv~#(Ye=kRKM6C{I$vhpNr%VRPykJR&o*d;J1DCb8KN=5@g973B zSSoIU>fzIAVAAXiOOG+#Fv631YBHRRkAyQ>b3C2u3LQQYHsYq`f)hjI(twI&i0XR�mwD79N3zdKJ}KNLo7*) zn$dOIqNZHi4}qB_CdGMJ616t5MI=WO6*L?PHg}yh2~UmCVRN)HdXBIr5C$dYg2rmZ zn=la1jO&cs&+_OguJXLVT3`a(3dAugLnPR9K&~`bRduEx1ZlY)$Tf0b3CvubzB*^# zzI^L)Njb2j99mQk-D@i;#}>TD*cO=dEU3=5!$BOKHJ$6sc7SM|vb#Z0qpUM8ge!L< zL1pGWcn4C^30+mKMpd0iYZsHq`&9Mgi_xSr;u^`Cy1@dt3~k78?|FL*+p-wX7?S-^ zjaPwOCo2MVZJQfhAgusYJw+WwJ?llQDB?%syZy&r4Dp0pk@?`j|Hy^; zMPv#rW6h|s?Yg!t&`gd)!3U}i)rFJWkf7!HUPRNM~G(cThbJr^{a*hOr z;fH7<2%R1S?y7DYmTaak=qc5{Rrp1QF~Jg3`X&2Tdr!Z8YET{MAK=#w9KPz$mJpw` z#3;l;T+$9@gKMMF9oIevbBrM%;M)GSC4c*(zrEO6^6$$F_m$Q{_gw3Zsl0T*sbywt zdaR($j^7;rQvAyIh40Qtsp)WDTvl2N1G7Unhl*0Etz%K?Snzgii~?2Ueupp35m6eam`K|y#hASgbO`j2%m{}fR{Qnt0*U`7*%F+G&jN6L>uw4 z8P@C26cg|esV{41oRV^qMxcu5|1#(V$V$TuvjoE%_wY|BL60RS^%Sc@$}qOtF7^^~ z7&n5hH8fc#N--u`R5MURMAU(_CV(NNP5{FcZd?KadCA{W*jqS~e?KoQD}h3PVIZH) zOFt`t<-oT5(5jpGl)QQ4}Rj#PyP0I$bHJp(DcxpRPyc4 z(`BW(u)WY%7`ZuEIF|op!Mnru-aT*twigL^W}aO-u#4mf)F;J2$@L<}Kxi-qLbKxY zyLO@onxejnjlD155+4dYT<|cpE@t3e;W6V)V4fB;a%*W8EnQdEu&$(8k*8TZ*C6VU zR;x#;4S1H!V%@6aaqK9}d<$xM7Z7keS(!OGeR8g=BtO3-?_ZSn-;qjk=YrI^(U1N& zZSZEXZXg@gsHD?g7(Ij2FobM8DmoT7{5UXAH@pe6?6T?W#|hbg_w|Dx=bmNRadL2= z-%iULR8k;Ns(NgsiVkMxccGSF0D|Z=&Gbz76uLeaZ~JcfN^-}N+_@-s-qA{O*Mijb ztSZi4K@)5aV^!x0lqX>BdpI9MhwWDwc4CNMrJzG_JQKkDTRg#)oV_9lW_S2v2SrTJb( bytes: # pragma: no cover + return data + + def decrypt(self, data: bytes) -> bytes: # pragma: no cover + return data + + +class CryptIdentity(CryptBase): + pass diff --git a/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/_cryptography.py b/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/_cryptography.py new file mode 100644 index 0000000..f553761 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/_cryptography.py @@ -0,0 +1,118 @@ +# Copyright (c) 2023, exiledkingcc +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import secrets + +from cryptography import __version__ +from cryptography.hazmat.primitives import padding +from cryptography.hazmat.primitives.ciphers.algorithms import AES + +try: + # 43.0.0 - https://cryptography.io/en/latest/changelog/#v43-0-0 + from cryptography.hazmat.decrepit.ciphers.algorithms import ARC4 +except ImportError: + from cryptography.hazmat.primitives.ciphers.algorithms import ARC4 +from cryptography.hazmat.primitives.ciphers.base import Cipher +from cryptography.hazmat.primitives.ciphers.modes import CBC, ECB + +from pypdf._crypt_providers._base import CryptBase + +crypt_provider = ("cryptography", __version__) + + +class CryptRC4(CryptBase): + def __init__(self, key: bytes) -> None: + self.cipher = Cipher(ARC4(key), mode=None) + + def encrypt(self, data: bytes) -> bytes: + encryptor = self.cipher.encryptor() + return encryptor.update(data) + encryptor.finalize() + + def decrypt(self, data: bytes) -> bytes: + decryptor = self.cipher.decryptor() + return decryptor.update(data) + decryptor.finalize() + + +class CryptAES(CryptBase): + def __init__(self, key: bytes) -> None: + self.alg = AES(key) + + def encrypt(self, data: bytes) -> bytes: + iv = secrets.token_bytes(16) + pad = padding.PKCS7(128).padder() + data = pad.update(data) + pad.finalize() + + cipher = Cipher(self.alg, CBC(iv)) + encryptor = cipher.encryptor() + return iv + encryptor.update(data) + encryptor.finalize() + + def decrypt(self, data: bytes) -> bytes: + iv = data[:16] + data = data[16:] + # for empty encrypted data + if not data: + return data + + # just for robustness, it does not happen under normal circumstances + if len(data) % 16 != 0: + pad = padding.PKCS7(128).padder() + data = pad.update(data) + pad.finalize() + + cipher = Cipher(self.alg, CBC(iv)) + decryptor = cipher.decryptor() + d = decryptor.update(data) + decryptor.finalize() + return d[: -d[-1]] + + +def rc4_encrypt(key: bytes, data: bytes) -> bytes: + encryptor = Cipher(ARC4(key), mode=None).encryptor() + return encryptor.update(data) + encryptor.finalize() + + +def rc4_decrypt(key: bytes, data: bytes) -> bytes: + decryptor = Cipher(ARC4(key), mode=None).decryptor() + return decryptor.update(data) + decryptor.finalize() + + +def aes_ecb_encrypt(key: bytes, data: bytes) -> bytes: + encryptor = Cipher(AES(key), mode=ECB()).encryptor() + return encryptor.update(data) + encryptor.finalize() + + +def aes_ecb_decrypt(key: bytes, data: bytes) -> bytes: + decryptor = Cipher(AES(key), mode=ECB()).decryptor() + return decryptor.update(data) + decryptor.finalize() + + +def aes_cbc_encrypt(key: bytes, iv: bytes, data: bytes) -> bytes: + encryptor = Cipher(AES(key), mode=CBC(iv)).encryptor() + return encryptor.update(data) + encryptor.finalize() + + +def aes_cbc_decrypt(key: bytes, iv: bytes, data: bytes) -> bytes: + decryptor = Cipher(AES(key), mode=CBC(iv)).decryptor() + return decryptor.update(data) + decryptor.finalize() diff --git a/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/_fallback.py b/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/_fallback.py new file mode 100644 index 0000000..0412211 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/_fallback.py @@ -0,0 +1,93 @@ +# Copyright (c) 2023, exiledkingcc +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +from pypdf._crypt_providers._base import CryptBase +from pypdf.errors import DependencyError + +_DEPENDENCY_ERROR_STR = "cryptography>=3.1 is required for AES algorithm" + + +crypt_provider = ("local_crypt_fallback", "0.0.0") + + +class CryptRC4(CryptBase): + def __init__(self, key: bytes) -> None: + self.s = bytearray(range(256)) + j = 0 + for i in range(256): + j = (j + self.s[i] + key[i % len(key)]) % 256 + self.s[i], self.s[j] = self.s[j], self.s[i] + + def encrypt(self, data: bytes) -> bytes: + s = bytearray(self.s) + out = [0 for _ in range(len(data))] + i, j = 0, 0 + for k in range(len(data)): + i = (i + 1) % 256 + j = (j + s[i]) % 256 + s[i], s[j] = s[j], s[i] + x = s[(s[i] + s[j]) % 256] + out[k] = data[k] ^ x + return bytes(out) + + def decrypt(self, data: bytes) -> bytes: + return self.encrypt(data) + + +class CryptAES(CryptBase): + def __init__(self, key: bytes) -> None: + pass + + def encrypt(self, data: bytes) -> bytes: + raise DependencyError(_DEPENDENCY_ERROR_STR) + + def decrypt(self, data: bytes) -> bytes: + raise DependencyError(_DEPENDENCY_ERROR_STR) + + +def rc4_encrypt(key: bytes, data: bytes) -> bytes: + return CryptRC4(key).encrypt(data) + + +def rc4_decrypt(key: bytes, data: bytes) -> bytes: + return CryptRC4(key).decrypt(data) + + +def aes_ecb_encrypt(key: bytes, data: bytes) -> bytes: + raise DependencyError(_DEPENDENCY_ERROR_STR) + + +def aes_ecb_decrypt(key: bytes, data: bytes) -> bytes: + raise DependencyError(_DEPENDENCY_ERROR_STR) + + +def aes_cbc_encrypt(key: bytes, iv: bytes, data: bytes) -> bytes: + raise DependencyError(_DEPENDENCY_ERROR_STR) + + +def aes_cbc_decrypt(key: bytes, iv: bytes, data: bytes) -> bytes: + raise DependencyError(_DEPENDENCY_ERROR_STR) diff --git a/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/_pycryptodome.py b/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/_pycryptodome.py new file mode 100644 index 0000000..30a13e1 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_crypt_providers/_pycryptodome.py @@ -0,0 +1,97 @@ +# Copyright (c) 2023, exiledkingcc +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import secrets + +from Crypto import __version__ +from Crypto.Cipher import AES, ARC4 +from Crypto.Util.Padding import pad + +from pypdf._crypt_providers._base import CryptBase + +crypt_provider = ("pycryptodome", __version__) + + +class CryptRC4(CryptBase): + def __init__(self, key: bytes) -> None: + self.key = key + + def encrypt(self, data: bytes) -> bytes: + return ARC4.ARC4Cipher(self.key).encrypt(data) + + def decrypt(self, data: bytes) -> bytes: + return ARC4.ARC4Cipher(self.key).decrypt(data) + + +class CryptAES(CryptBase): + def __init__(self, key: bytes) -> None: + self.key = key + + def encrypt(self, data: bytes) -> bytes: + iv = secrets.token_bytes(16) + data = pad(data, 16) + aes = AES.new(self.key, AES.MODE_CBC, iv) + return iv + aes.encrypt(data) + + def decrypt(self, data: bytes) -> bytes: + iv = data[:16] + data = data[16:] + # for empty encrypted data + if not data: + return data + + # just for robustness, it does not happen under normal circumstances + if len(data) % 16 != 0: + data = pad(data, 16) + + aes = AES.new(self.key, AES.MODE_CBC, iv) + d = aes.decrypt(data) + return d[: -d[-1]] + + +def rc4_encrypt(key: bytes, data: bytes) -> bytes: + return ARC4.ARC4Cipher(key).encrypt(data) + + +def rc4_decrypt(key: bytes, data: bytes) -> bytes: + return ARC4.ARC4Cipher(key).decrypt(data) + + +def aes_ecb_encrypt(key: bytes, data: bytes) -> bytes: + return AES.new(key, AES.MODE_ECB).encrypt(data) + + +def aes_ecb_decrypt(key: bytes, data: bytes) -> bytes: + return AES.new(key, AES.MODE_ECB).decrypt(data) + + +def aes_cbc_encrypt(key: bytes, iv: bytes, data: bytes) -> bytes: + return AES.new(key, AES.MODE_CBC, iv).encrypt(data) + + +def aes_cbc_decrypt(key: bytes, iv: bytes, data: bytes) -> bytes: + return AES.new(key, AES.MODE_CBC, iv).decrypt(data) diff --git a/venv/lib/python3.12/site-packages/pypdf/_doc_common.py b/venv/lib/python3.12/site-packages/pypdf/_doc_common.py new file mode 100644 index 0000000..1ba8af2 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_doc_common.py @@ -0,0 +1,1446 @@ +# Copyright (c) 2006, Mathieu Fenniak +# Copyright (c) 2007, Ashish Kulkarni +# Copyright (c) 2024, Pubpub-ZZ +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import struct +import zlib +from abc import abstractmethod +from datetime import datetime +from typing import ( + Any, + Dict, + Generator, + Iterable, + Iterator, + List, + Mapping, + Optional, + Tuple, + Union, + cast, +) + +from ._encryption import Encryption +from ._page import PageObject, _VirtualList +from ._page_labels import index2label as page_index2page_label +from ._utils import ( + deprecate_with_replacement, + logger_warning, + parse_iso8824_date, +) +from .constants import CatalogAttributes as CA +from .constants import CatalogDictionary as CD +from .constants import ( + CheckboxRadioButtonAttributes, + GoToActionArguments, + UserAccessPermissions, +) +from .constants import Core as CO +from .constants import DocumentInformationAttributes as DI +from .constants import FieldDictionaryAttributes as FA +from .constants import PageAttributes as PG +from .constants import PagesAttributes as PA +from .errors import PdfReadError, PyPdfError +from .generic import ( + ArrayObject, + BooleanObject, + ByteStringObject, + Destination, + DictionaryObject, + EncodedStreamObject, + Field, + Fit, + FloatObject, + IndirectObject, + NameObject, + NullObject, + NumberObject, + PdfObject, + TextStringObject, + TreeObject, + ViewerPreferences, + create_string_object, + is_null_or_none, +) +from .generic._files import EmbeddedFile +from .types import OutlineType, PagemodeType +from .xmp import XmpInformation + + +def convert_to_int(d: bytes, size: int) -> Union[int, Tuple[Any, ...]]: + if size > 8: + raise PdfReadError("Invalid size in convert_to_int") + d = b"\x00\x00\x00\x00\x00\x00\x00\x00" + d + d = d[-8:] + return struct.unpack(">q", d)[0] + + +class DocumentInformation(DictionaryObject): + """ + A class representing the basic document metadata provided in a PDF File. + This class is accessible through + :py:class:`PdfReader.metadata`. + + All text properties of the document metadata have + *two* properties, e.g. author and author_raw. The non-raw property will + always return a ``TextStringObject``, making it ideal for a case where the + metadata is being displayed. The raw property can sometimes return a + ``ByteStringObject``, if pypdf was unable to decode the string's text + encoding; this requires additional safety in the caller and therefore is not + as commonly accessed. + """ + + def __init__(self) -> None: + DictionaryObject.__init__(self) + + def _get_text(self, key: str) -> Optional[str]: + retval = self.get(key, None) + if isinstance(retval, TextStringObject): + return retval + if isinstance(retval, ByteStringObject): + return str(retval) + return None + + @property + def title(self) -> Optional[str]: + """ + Read-only property accessing the document's title. + + Returns a ``TextStringObject`` or ``None`` if the title is not + specified. + """ + return ( + self._get_text(DI.TITLE) or self.get(DI.TITLE).get_object() # type: ignore + if self.get(DI.TITLE) + else None + ) + + @property + def title_raw(self) -> Optional[str]: + """The "raw" version of title; can return a ``ByteStringObject``.""" + return self.get(DI.TITLE) + + @property + def author(self) -> Optional[str]: + """ + Read-only property accessing the document's author. + + Returns a ``TextStringObject`` or ``None`` if the author is not + specified. + """ + return self._get_text(DI.AUTHOR) + + @property + def author_raw(self) -> Optional[str]: + """The "raw" version of author; can return a ``ByteStringObject``.""" + return self.get(DI.AUTHOR) + + @property + def subject(self) -> Optional[str]: + """ + Read-only property accessing the document's subject. + + Returns a ``TextStringObject`` or ``None`` if the subject is not + specified. + """ + return self._get_text(DI.SUBJECT) + + @property + def subject_raw(self) -> Optional[str]: + """The "raw" version of subject; can return a ``ByteStringObject``.""" + return self.get(DI.SUBJECT) + + @property + def creator(self) -> Optional[str]: + """ + Read-only property accessing the document's creator. + + If the document was converted to PDF from another format, this is the + name of the application (e.g. OpenOffice) that created the original + document from which it was converted. Returns a ``TextStringObject`` or + ``None`` if the creator is not specified. + """ + return self._get_text(DI.CREATOR) + + @property + def creator_raw(self) -> Optional[str]: + """The "raw" version of creator; can return a ``ByteStringObject``.""" + return self.get(DI.CREATOR) + + @property + def producer(self) -> Optional[str]: + """ + Read-only property accessing the document's producer. + + If the document was converted to PDF from another format, this is the + name of the application (for example, macOS Quartz) that converted it to + PDF. Returns a ``TextStringObject`` or ``None`` if the producer is not + specified. + """ + return self._get_text(DI.PRODUCER) + + @property + def producer_raw(self) -> Optional[str]: + """The "raw" version of producer; can return a ``ByteStringObject``.""" + return self.get(DI.PRODUCER) + + @property + def creation_date(self) -> Optional[datetime]: + """Read-only property accessing the document's creation date.""" + return parse_iso8824_date(self._get_text(DI.CREATION_DATE)) + + @property + def creation_date_raw(self) -> Optional[str]: + """ + The "raw" version of creation date; can return a ``ByteStringObject``. + + Typically in the format ``D:YYYYMMDDhhmmss[+Z-]hh'mm`` where the suffix + is the offset from UTC. + """ + return self.get(DI.CREATION_DATE) + + @property + def modification_date(self) -> Optional[datetime]: + """ + Read-only property accessing the document's modification date. + + The date and time the document was most recently modified. + """ + return parse_iso8824_date(self._get_text(DI.MOD_DATE)) + + @property + def modification_date_raw(self) -> Optional[str]: + """ + The "raw" version of modification date; can return a + ``ByteStringObject``. + + Typically in the format ``D:YYYYMMDDhhmmss[+Z-]hh'mm`` where the suffix + is the offset from UTC. + """ + return self.get(DI.MOD_DATE) + + @property + def keywords(self) -> Optional[str]: + """ + Read-only property accessing the document's keywords. + + Returns a ``TextStringObject`` or ``None`` if keywords are not + specified. + """ + return self._get_text(DI.KEYWORDS) + + @property + def keywords_raw(self) -> Optional[str]: + """The "raw" version of keywords; can return a ``ByteStringObject``.""" + return self.get(DI.KEYWORDS) + + +class PdfDocCommon: + """ + Common functions from PdfWriter and PdfReader objects. + + This root class is strongly abstracted. + """ + + strict: bool = False # default + + _encryption: Optional[Encryption] = None + + _readonly: bool = False + + @property + @abstractmethod + def root_object(self) -> DictionaryObject: + ... # pragma: no cover + + @property + @abstractmethod + def pdf_header(self) -> str: + ... # pragma: no cover + + @abstractmethod + def get_object( + self, indirect_reference: Union[int, IndirectObject] + ) -> Optional[PdfObject]: + ... # pragma: no cover + + @abstractmethod + def _replace_object(self, indirect: IndirectObject, obj: PdfObject) -> PdfObject: + ... # pragma: no cover + + @property + @abstractmethod + def _info(self) -> Optional[DictionaryObject]: + ... # pragma: no cover + + @property + def metadata(self) -> Optional[DocumentInformation]: + """ + Retrieve the PDF file's document information dictionary, if it exists. + + Note that some PDF files use metadata streams instead of document + information dictionaries, and these metadata streams will not be + accessed by this function. + """ + retval = DocumentInformation() + if self._info is None: + return None + retval.update(self._info) + return retval + + @property + def xmp_metadata(self) -> Optional[XmpInformation]: + ... # pragma: no cover + + @property + def viewer_preferences(self) -> Optional[ViewerPreferences]: + """Returns the existing ViewerPreferences as an overloaded dictionary.""" + o = self.root_object.get(CD.VIEWER_PREFERENCES, None) + if o is None: + return None + o = o.get_object() + if not isinstance(o, ViewerPreferences): + o = ViewerPreferences(o) + if hasattr(o, "indirect_reference"): + self._replace_object(o.indirect_reference, o) + else: + self.root_object[NameObject(CD.VIEWER_PREFERENCES)] = o + return o + + flattened_pages: Optional[List[PageObject]] = None + + def get_num_pages(self) -> int: + """ + Calculate the number of pages in this PDF file. + + Returns: + The number of pages of the parsed PDF file. + + Raises: + PdfReadError: if file is encrypted and restrictions prevent + this action. + + """ + # Flattened pages will not work on an encrypted PDF; + # the PDF file's page count is used in this case. Otherwise, + # the original method (flattened page count) is used. + if self.is_encrypted: + return self.root_object["/Pages"]["/Count"] # type: ignore + else: + if self.flattened_pages is None: + self._flatten(self._readonly) + assert self.flattened_pages is not None + return len(self.flattened_pages) + + def get_page(self, page_number: int) -> PageObject: + """ + Retrieve a page by number from this PDF file. + Most of the time ``.pages[page_number]`` is preferred. + + Args: + page_number: The page number to retrieve + (pages begin at zero) + + Returns: + A :class:`PageObject` instance. + + """ + if self.flattened_pages is None: + self._flatten(self._readonly) + assert self.flattened_pages is not None, "hint for mypy" + return self.flattened_pages[page_number] + + def _get_page_in_node( + self, + page_number: int, + ) -> Tuple[DictionaryObject, int]: + """ + Retrieve the node and position within the /Kids containing the page. + If page_number is greater than the number of pages, it returns the top node, -1. + """ + top = cast(DictionaryObject, self.root_object["/Pages"]) + + def recursive_call( + node: DictionaryObject, mi: int + ) -> Tuple[Optional[PdfObject], int]: + ma = cast(int, node.get("/Count", 1)) # default 1 for /Page types + if node["/Type"] == "/Page": + if page_number == mi: + return node, -1 + # else + return None, mi + 1 + if (page_number - mi) >= ma: # not in nodes below + if node == top: + return top, -1 + # else + return None, mi + ma + for idx, kid in enumerate(cast(ArrayObject, node["/Kids"])): + kid = cast(DictionaryObject, kid.get_object()) + n, i = recursive_call(kid, mi) + if n is not None: # page has just been found ... + if i < 0: # ... just below! + return node, idx + # else: # ... at lower levels + return n, i + mi = i + raise PyPdfError("Unexpectedly cannot find the node.") + + node, idx = recursive_call(top, 0) + assert isinstance(node, DictionaryObject), "mypy" + return node, idx + + @property + def named_destinations(self) -> Dict[str, Any]: + """ + A read-only dictionary which maps names to + :class:`Destinations` + """ + return self._get_named_destinations() + + def get_named_dest_root(self) -> ArrayObject: + named_dest = ArrayObject() + if CA.NAMES in self.root_object and isinstance( + self.root_object[CA.NAMES], DictionaryObject + ): + names = cast(DictionaryObject, self.root_object[CA.NAMES]) + names_ref = names.indirect_reference + if CA.DESTS in names and isinstance(names[CA.DESTS], DictionaryObject): + # 3.6.3 Name Dictionary (PDF spec 1.7) + dests = cast(DictionaryObject, names[CA.DESTS]) + dests_ref = dests.indirect_reference + if CA.NAMES in dests: + # §7.9.6, entries in a name tree node dictionary + named_dest = cast(ArrayObject, dests[CA.NAMES]) + else: + named_dest = ArrayObject() + dests[NameObject(CA.NAMES)] = named_dest + elif hasattr(self, "_add_object"): + dests = DictionaryObject() + dests_ref = self._add_object(dests) + names[NameObject(CA.DESTS)] = dests_ref + dests[NameObject(CA.NAMES)] = named_dest + + elif hasattr(self, "_add_object"): + names = DictionaryObject() + names_ref = self._add_object(names) + self.root_object[NameObject(CA.NAMES)] = names_ref + dests = DictionaryObject() + dests_ref = self._add_object(dests) + names[NameObject(CA.DESTS)] = dests_ref + dests[NameObject(CA.NAMES)] = named_dest + + return named_dest + + ## common + def _get_named_destinations( + self, + tree: Union[TreeObject, None] = None, + retval: Optional[Any] = None, + ) -> Dict[str, Any]: + """ + Retrieve the named destinations present in the document. + + Args: + tree: + retval: + + Returns: + A dictionary which maps names to + :class:`Destinations`. + + """ + if retval is None: + retval = {} + catalog = self.root_object + + # get the name tree + if CA.DESTS in catalog: + tree = cast(TreeObject, catalog[CA.DESTS]) + elif CA.NAMES in catalog: + names = cast(DictionaryObject, catalog[CA.NAMES]) + if CA.DESTS in names: + tree = cast(TreeObject, names[CA.DESTS]) + + if tree is None: + return retval + + if PA.KIDS in tree: + # recurse down the tree + for kid in cast(ArrayObject, tree[PA.KIDS]): + self._get_named_destinations(kid.get_object(), retval) + # §7.9.6, entries in a name tree node dictionary + elif CA.NAMES in tree: # /Kids and /Names are exclusives (§7.9.6) + names = cast(DictionaryObject, tree[CA.NAMES]) + i = 0 + while i < len(names): + key = cast(str, names[i].get_object()) + i += 1 + if not isinstance(key, str): + continue + try: + value = names[i].get_object() + except IndexError: + break + i += 1 + if isinstance(value, DictionaryObject): + if "/D" in value: + value = value["/D"] + else: + continue + dest = self._build_destination(key, value) # type: ignore + if dest is not None: + retval[key] = dest + else: # case where Dests is in root catalog (PDF 1.7 specs, §2 about PDF 1.1) + for k__, v__ in tree.items(): + val = v__.get_object() + if isinstance(val, DictionaryObject): + if "/D" in val: + val = val["/D"].get_object() + else: + continue + dest = self._build_destination(k__, val) + if dest is not None: + retval[k__] = dest + return retval + + # A select group of relevant field attributes. For the complete list. + # See §12.3.2 of the PDF 1.7 or PDF 2.0 specification. + + def get_fields( + self, + tree: Optional[TreeObject] = None, + retval: Optional[Dict[Any, Any]] = None, + fileobj: Optional[Any] = None, + stack: Optional[List[PdfObject]] = None, + ) -> Optional[Dict[str, Any]]: + """ + Extract field data if this PDF contains interactive form fields. + + The *tree*, *retval*, *stack* parameters are for recursive use. + + Args: + tree: Current object to parse. + retval: In-progress list of fields. + fileobj: A file object (usually a text file) to write + a report to on all interactive form fields found. + stack: List of already parsed objects. + + Returns: + A dictionary where each key is a field name, and each + value is a :class:`Field` object. By + default, the mapping name is used for keys. + ``None`` if form data could not be located. + + """ + field_attributes = FA.attributes_dict() + field_attributes.update(CheckboxRadioButtonAttributes.attributes_dict()) + if retval is None: + retval = {} + catalog = self.root_object + stack = [] + # get the AcroForm tree + if CD.ACRO_FORM in catalog: + tree = cast(Optional[TreeObject], catalog[CD.ACRO_FORM]) + else: + return None + if tree is None: + return retval + assert stack is not None + if "/Fields" in tree: + fields = cast(ArrayObject, tree["/Fields"]) + for f in fields: + field = f.get_object() + self._build_field(field, retval, fileobj, field_attributes, stack) + elif any(attr in tree for attr in field_attributes): + # Tree is a field + self._build_field(tree, retval, fileobj, field_attributes, stack) + return retval + + def _get_qualified_field_name(self, parent: DictionaryObject) -> str: + if "/TM" in parent: + return cast(str, parent["/TM"]) + elif "/Parent" in parent: + return ( + self._get_qualified_field_name( + cast(DictionaryObject, parent["/Parent"]) + ) + + "." + + cast(str, parent.get("/T", "")) + ) + else: + return cast(str, parent.get("/T", "")) + + def _build_field( + self, + field: Union[TreeObject, DictionaryObject], + retval: Dict[Any, Any], + fileobj: Any, + field_attributes: Any, + stack: List[PdfObject], + ) -> None: + if all(attr not in field for attr in ("/T", "/TM")): + return + key = self._get_qualified_field_name(field) + if fileobj: + self._write_field(fileobj, field, field_attributes) + fileobj.write("\n") + retval[key] = Field(field) + obj = retval[key].indirect_reference.get_object() # to get the full object + if obj.get(FA.FT, "") == "/Ch": + retval[key][NameObject("/_States_")] = obj[NameObject(FA.Opt)] + if obj.get(FA.FT, "") == "/Btn" and "/AP" in obj: + # Checkbox + retval[key][NameObject("/_States_")] = ArrayObject( + list(obj["/AP"]["/N"].keys()) + ) + if "/Off" not in retval[key]["/_States_"]: + retval[key][NameObject("/_States_")].append(NameObject("/Off")) + elif obj.get(FA.FT, "") == "/Btn" and obj.get(FA.Ff, 0) & FA.FfBits.Radio != 0: + states: List[str] = [] + retval[key][NameObject("/_States_")] = ArrayObject(states) + for k in obj.get(FA.Kids, {}): + k = k.get_object() + for s in list(k["/AP"]["/N"].keys()): + if s not in states: + states.append(s) + retval[key][NameObject("/_States_")] = ArrayObject(states) + if ( + obj.get(FA.Ff, 0) & FA.FfBits.NoToggleToOff != 0 + and "/Off" in retval[key]["/_States_"] + ): + del retval[key]["/_States_"][retval[key]["/_States_"].index("/Off")] + # at last for order + self._check_kids(field, retval, fileobj, stack) + + def _check_kids( + self, + tree: Union[TreeObject, DictionaryObject], + retval: Any, + fileobj: Any, + stack: List[PdfObject], + ) -> None: + if tree in stack: + logger_warning( + f"{self._get_qualified_field_name(tree)} already parsed", __name__ + ) + return + stack.append(tree) + if PA.KIDS in tree: + # recurse down the tree + for kid in tree[PA.KIDS]: # type: ignore + kid = kid.get_object() + self.get_fields(kid, retval, fileobj, stack) + + def _write_field(self, fileobj: Any, field: Any, field_attributes: Any) -> None: + field_attributes_tuple = FA.attributes() + field_attributes_tuple = ( + field_attributes_tuple + CheckboxRadioButtonAttributes.attributes() + ) + + for attr in field_attributes_tuple: + if attr in ( + FA.Kids, + FA.AA, + ): + continue + attr_name = field_attributes[attr] + try: + if attr == FA.FT: + # Make the field type value more clear + types = { + "/Btn": "Button", + "/Tx": "Text", + "/Ch": "Choice", + "/Sig": "Signature", + } + if field[attr] in types: + fileobj.write(f"{attr_name}: {types[field[attr]]}\n") + elif attr == FA.Parent: + # Let's just write the name of the parent + try: + name = field[attr][FA.TM] + except KeyError: + name = field[attr][FA.T] + fileobj.write(f"{attr_name}: {name}\n") + else: + fileobj.write(f"{attr_name}: {field[attr]}\n") + except KeyError: + # Field attribute is N/A or unknown, so don't write anything + pass + + def get_form_text_fields(self, full_qualified_name: bool = False) -> Dict[str, Any]: + """ + Retrieve form fields from the document with textual data. + + Args: + full_qualified_name: to get full name + + Returns: + A dictionary. The key is the name of the form field, + the value is the content of the field. + + If the document contains multiple form fields with the same name, the + second and following will get the suffix .2, .3, ... + + """ + + def indexed_key(k: str, fields: Dict[Any, Any]) -> str: + if k not in fields: + return k + else: + return ( + k + + "." + + str(sum(1 for kk in fields if kk.startswith(k + ".")) + 2) + ) + + # Retrieve document form fields + formfields = self.get_fields() + if formfields is None: + return {} + ff = {} + for field, value in formfields.items(): + if value.get("/FT") == "/Tx": + if full_qualified_name: + ff[field] = value.get("/V") + else: + ff[indexed_key(cast(str, value["/T"]), ff)] = value.get("/V") + return ff + + def get_pages_showing_field( + self, field: Union[Field, PdfObject, IndirectObject] + ) -> List[PageObject]: + """ + Provides list of pages where the field is called. + + Args: + field: Field Object, PdfObject or IndirectObject referencing a Field + + Returns: + List of pages: + - Empty list: + The field has no widgets attached + (either hidden field or ancestor field). + - Single page list: + Page where the widget is present + (most common). + - Multi-page list: + Field with multiple kids widgets + (example: radio buttons, field repeated on multiple pages). + + """ + + def _get_inherited(obj: DictionaryObject, key: str) -> Any: + if key in obj: + return obj[key] + elif "/Parent" in obj: + return _get_inherited( + cast(DictionaryObject, obj["/Parent"].get_object()), key + ) + else: + return None + + try: + # to cope with all types + field = cast(DictionaryObject, field.indirect_reference.get_object()) # type: ignore + except Exception as exc: + raise ValueError("Field type is invalid") from exc + if is_null_or_none(_get_inherited(field, "/FT")): + raise ValueError("Field is not valid") + ret = [] + if field.get("/Subtype", "") == "/Widget": + if "/P" in field: + ret = [field["/P"].get_object()] + else: + ret = [ + p + for p in self.pages + if field.indirect_reference in p.get("/Annots", "") + ] + else: + kids = field.get("/Kids", ()) + for k in kids: + k = k.get_object() + if (k.get("/Subtype", "") == "/Widget") and ("/T" not in k): + # Kid that is just a widget, not a field: + if "/P" in k: + ret += [k["/P"].get_object()] + else: + ret += [ + p + for p in self.pages + if k.indirect_reference in p.get("/Annots", "") + ] + return [ + x + if isinstance(x, PageObject) + else (self.pages[self._get_page_number_by_indirect(x.indirect_reference)]) # type: ignore + for x in ret + ] + + @property + def open_destination( + self, + ) -> Union[None, Destination, TextStringObject, ByteStringObject]: + """ + Property to access the opening destination (``/OpenAction`` entry in + the PDF catalog). It returns ``None`` if the entry does not exist + or is not set. + + Raises: + Exception: If a destination is invalid. + + """ + if "/OpenAction" not in self.root_object: + return None + oa: Any = self.root_object["/OpenAction"] + if isinstance(oa, bytes): # pragma: no cover + oa = oa.decode() + if isinstance(oa, str): + return create_string_object(oa) + elif isinstance(oa, ArrayObject): + try: + page, typ, *array = oa + fit = Fit(typ, tuple(array)) + return Destination("OpenAction", page, fit) + except Exception as exc: + raise Exception(f"Invalid Destination {oa}: {exc}") + else: + return None + + @open_destination.setter + def open_destination(self, dest: Union[None, str, Destination, PageObject]) -> None: + raise NotImplementedError("No setter for open_destination") + + @property + def outline(self) -> OutlineType: + """ + Read-only property for the outline present in the document + (i.e., a collection of 'outline items' which are also known as + 'bookmarks'). + """ + return self._get_outline() + + def _get_outline( + self, node: Optional[DictionaryObject] = None, outline: Optional[Any] = None + ) -> OutlineType: + if outline is None: + outline = [] + catalog = self.root_object + + # get the outline dictionary and named destinations + if CO.OUTLINES in catalog: + lines = cast(DictionaryObject, catalog[CO.OUTLINES]) + + if isinstance(lines, NullObject): + return outline + + # §12.3.3 Document outline, entries in the outline dictionary + if not is_null_or_none(lines) and "/First" in lines: + node = cast(DictionaryObject, lines["/First"]) + self._named_destinations = self._get_named_destinations() + + if node is None: + return outline + + # see if there are any more outline items + while True: + outline_obj = self._build_outline_item(node) + if outline_obj: + outline.append(outline_obj) + + # check for sub-outline + if "/First" in node: + sub_outline: List[Any] = [] + self._get_outline(cast(DictionaryObject, node["/First"]), sub_outline) + if sub_outline: + outline.append(sub_outline) + + if "/Next" not in node: + break + node = cast(DictionaryObject, node["/Next"]) + + return outline + + @property + def threads(self) -> Optional[ArrayObject]: + """ + Read-only property for the list of threads. + + See §12.4.3 from the PDF 1.7 or 2.0 specification. + + It is an array of dictionaries with "/F" (the first bead in the thread) + and "/I" (a thread information dictionary containing information about + the thread, such as its title, author, and creation date) properties or + None if there are no articles. + + Since PDF 2.0 it can also contain an indirect reference to a metadata + stream containing information about the thread, such as its title, + author, and creation date. + """ + catalog = self.root_object + if CO.THREADS in catalog: + return cast("ArrayObject", catalog[CO.THREADS]) + else: + return None + + @abstractmethod + def _get_page_number_by_indirect( + self, indirect_reference: Union[None, int, NullObject, IndirectObject] + ) -> Optional[int]: + ... # pragma: no cover + + def get_page_number(self, page: PageObject) -> Optional[int]: + """ + Retrieve page number of a given PageObject. + + Args: + page: The page to get page number. Should be + an instance of :class:`PageObject` + + Returns: + The page number or None if page is not found + + """ + return self._get_page_number_by_indirect(page.indirect_reference) + + def get_destination_page_number(self, destination: Destination) -> Optional[int]: + """ + Retrieve page number of a given Destination object. + + Args: + destination: The destination to get page number. + + Returns: + The page number or None if page is not found + + """ + return self._get_page_number_by_indirect(destination.page) + + def _build_destination( + self, + title: str, + array: Optional[ + List[ + Union[NumberObject, IndirectObject, None, NullObject, DictionaryObject] + ] + ], + ) -> Destination: + page, typ = None, None + # handle outline items with missing or invalid destination + if ( + isinstance(array, (NullObject, str)) + or (isinstance(array, ArrayObject) and len(array) == 0) + or array is None + ): + page = NullObject() + return Destination(title, page, Fit.fit()) + else: + page, typ, *array = array # type: ignore + try: + return Destination(title, page, Fit(fit_type=typ, fit_args=array)) # type: ignore + except PdfReadError: + logger_warning(f"Unknown destination: {title} {array}", __name__) + if self.strict: + raise + # create a link to first Page + tmp = self.pages[0].indirect_reference + indirect_reference = NullObject() if tmp is None else tmp + return Destination(title, indirect_reference, Fit.fit()) + + def _build_outline_item(self, node: DictionaryObject) -> Optional[Destination]: + dest, title, outline_item = None, None, None + + # title required for valid outline + # § 12.3.3, entries in an outline item dictionary + try: + title = cast("str", node["/Title"]) + except KeyError: + if self.strict: + raise PdfReadError(f"Outline Entry Missing /Title attribute: {node!r}") + title = "" + + if "/A" in node: + # Action, PDFv1.7 Section 12.6 (only type GoTo supported) + action = cast(DictionaryObject, node["/A"]) + action_type = cast(NameObject, action[GoToActionArguments.S]) + if action_type == "/GoTo": + dest = action[GoToActionArguments.D] + elif "/Dest" in node: + # Destination, PDFv1.7 Section 12.3.2 + dest = node["/Dest"] + # if array was referenced in another object, will be a dict w/ key "/D" + if isinstance(dest, DictionaryObject) and "/D" in dest: + dest = dest["/D"] + + if isinstance(dest, ArrayObject): + outline_item = self._build_destination(title, dest) + elif isinstance(dest, str): + # named destination, addresses NameObject Issue #193 + # TODO : keep named destination instead of replacing it ? + try: + outline_item = self._build_destination( + title, self._named_destinations[dest].dest_array + ) + except KeyError: + # named destination not found in Name Dict + outline_item = self._build_destination(title, None) + elif dest is None: + # outline item not required to have destination or action + # PDFv1.7 Table 153 + outline_item = self._build_destination(title, dest) + else: + if self.strict: + raise PdfReadError(f"Unexpected destination {dest!r}") + else: + logger_warning( + f"Removed unexpected destination {dest!r} from destination", + __name__, + ) + outline_item = self._build_destination(title, None) + + # if outline item created, add color, format, and child count if present + if outline_item: + if "/C" in node: + # Color of outline item font in (R, G, B) with values ranging 0.0-1.0 + outline_item[NameObject("/C")] = ArrayObject(FloatObject(c) for c in node["/C"]) # type: ignore + if "/F" in node: + # specifies style characteristics bold and/or italic + # with 1=italic, 2=bold, 3=both + outline_item[NameObject("/F")] = node["/F"] + if "/Count" in node: + # absolute value = num. visible children + # with positive = open/unfolded, negative = closed/folded + outline_item[NameObject("/Count")] = node["/Count"] + # if count is 0 we will consider it as open ( in order to have always an is_open to simplify + outline_item[NameObject("/%is_open%")] = BooleanObject( + node.get("/Count", 0) >= 0 + ) + outline_item.node = node + try: + outline_item.indirect_reference = node.indirect_reference + except AttributeError: + pass + return outline_item + + @property + def pages(self) -> List[PageObject]: + """ + Property that emulates a list of :class:`PageObject`. + This property allows to get a page or a range of pages. + + Note: + For PdfWriter only: Provides the capability to remove a page/range of + page from the list (using the del operator). Remember: Only the page + entry is removed, as the objects beneath can be used elsewhere. A + solution to completely remove them - if they are not used anywhere - is + to write to a buffer/temporary file and then load it into a new + PdfWriter. + + """ + return _VirtualList(self.get_num_pages, self.get_page) # type: ignore + + @property + def page_labels(self) -> List[str]: + """ + A list of labels for the pages in this document. + + This property is read-only. The labels are in the order that the pages + appear in the document. + """ + return [page_index2page_label(self, i) for i in range(len(self.pages))] + + @property + def page_layout(self) -> Optional[str]: + """ + Get the page layout currently being used. + + .. list-table:: Valid ``layout`` values + :widths: 50 200 + + * - /NoLayout + - Layout explicitly not specified + * - /SinglePage + - Show one page at a time + * - /OneColumn + - Show one column at a time + * - /TwoColumnLeft + - Show pages in two columns, odd-numbered pages on the left + * - /TwoColumnRight + - Show pages in two columns, odd-numbered pages on the right + * - /TwoPageLeft + - Show two pages at a time, odd-numbered pages on the left + * - /TwoPageRight + - Show two pages at a time, odd-numbered pages on the right + """ + try: + return cast(NameObject, self.root_object[CD.PAGE_LAYOUT]) + except KeyError: + return None + + @property + def page_mode(self) -> Optional[PagemodeType]: + """ + Get the page mode currently being used. + + .. list-table:: Valid ``mode`` values + :widths: 50 200 + + * - /UseNone + - Do not show outline or thumbnails panels + * - /UseOutlines + - Show outline (aka bookmarks) panel + * - /UseThumbs + - Show page thumbnails panel + * - /FullScreen + - Fullscreen view + * - /UseOC + - Show Optional Content Group (OCG) panel + * - /UseAttachments + - Show attachments panel + """ + try: + return self.root_object["/PageMode"] # type: ignore + except KeyError: + return None + + def _flatten( + self, + list_only: bool = False, + pages: Union[None, DictionaryObject, PageObject] = None, + inherit: Optional[Dict[str, Any]] = None, + indirect_reference: Optional[IndirectObject] = None, + ) -> None: + """ + Prepare the document pages to ease searching + + Args: + list_only: Will only list the pages within _flatten_pages. + pages: + inherit: + indirect_reference: Used recursively to flatten the /Pages object. + + """ + inheritable_page_attributes = ( + NameObject(PG.RESOURCES), + NameObject(PG.MEDIABOX), + NameObject(PG.CROPBOX), + NameObject(PG.ROTATE), + ) + if inherit is None: + inherit = {} + if pages is None: + # Fix issue 327: set flattened_pages attribute only for + # decrypted file + catalog = self.root_object + pages = catalog.get("/Pages").get_object() # type: ignore + if not isinstance(pages, DictionaryObject): + raise PdfReadError("Invalid object in /Pages") + self.flattened_pages = [] + + if PA.TYPE in pages: + t = cast(str, pages[PA.TYPE]) + # if pdf has no type, considered as a page if /Kids is missing + elif PA.KIDS not in pages: + t = "/Page" + else: + t = "/Pages" + + if t == "/Pages": + for attr in inheritable_page_attributes: + if attr in pages: + inherit[attr] = pages[attr] + for page in cast(ArrayObject, pages[PA.KIDS]): + addt = {} + if isinstance(page, IndirectObject): + addt["indirect_reference"] = page + obj = page.get_object() + if obj: + # damaged file may have invalid child in /Pages + try: + self._flatten(list_only, obj, inherit, **addt) + except RecursionError: + raise PdfReadError( + "Maximum recursion depth reached during page flattening." + ) + elif t == "/Page": + for attr_in, value in list(inherit.items()): + # if the page has it's own value, it does not inherit the + # parent's value: + if attr_in not in pages: + pages[attr_in] = value + page_obj = PageObject(self, indirect_reference) + if not list_only: + page_obj.update(pages) + + # TODO: Could flattened_pages be None at this point? + self.flattened_pages.append(page_obj) # type: ignore + + def remove_page( + self, + page: Union[int, PageObject, IndirectObject], + clean: bool = False, + ) -> None: + """ + Remove page from pages list. + + Args: + page: + * :class:`int`: Page number to be removed. + * :class:`~pypdf._page.PageObject`: page to be removed. If the page appears many times + only the first one will be removed. + * :class:`~pypdf.generic.IndirectObject`: Reference to page to be removed. + + clean: replace PageObject with NullObject to prevent annotations + or destinations to reference a detached page. + + """ + if self.flattened_pages is None: + self._flatten(self._readonly) + assert self.flattened_pages is not None + if isinstance(page, IndirectObject): + p = page.get_object() + if not isinstance(p, PageObject): + logger_warning("IndirectObject is not referencing a page", __name__) + return + page = p + + if not isinstance(page, int): + try: + page = self.flattened_pages.index(page) + except ValueError: + logger_warning("Cannot find page in pages", __name__) + return + if not (0 <= page < len(self.flattened_pages)): + logger_warning("Page number is out of range", __name__) + return + + ind = self.pages[page].indirect_reference + del self.pages[page] + if clean and ind is not None: + self._replace_object(ind, NullObject()) + + def _get_indirect_object(self, num: int, gen: int) -> Optional[PdfObject]: + """ + Used to ease development. + + This is equivalent to generic.IndirectObject(num,gen,self).get_object() + + Args: + num: The object number of the indirect object. + gen: The generation number of the indirect object. + + Returns: + A PdfObject + + """ + return IndirectObject(num, gen, self).get_object() + + def decode_permissions( + self, permissions_code: int + ) -> Dict[str, bool]: # pragma: no cover + """Take the permissions as an integer, return the allowed access.""" + deprecate_with_replacement( + old_name="decode_permissions", + new_name="user_access_permissions", + removed_in="5.0.0", + ) + + permissions_mapping = { + "print": UserAccessPermissions.PRINT, + "modify": UserAccessPermissions.MODIFY, + "copy": UserAccessPermissions.EXTRACT, + "annotations": UserAccessPermissions.ADD_OR_MODIFY, + "forms": UserAccessPermissions.FILL_FORM_FIELDS, + # Do not fix typo, as part of official, but deprecated API. + "accessability": UserAccessPermissions.EXTRACT_TEXT_AND_GRAPHICS, + "assemble": UserAccessPermissions.ASSEMBLE_DOC, + "print_high_quality": UserAccessPermissions.PRINT_TO_REPRESENTATION, + } + + return { + key: permissions_code & flag != 0 + for key, flag in permissions_mapping.items() + } + + @property + def user_access_permissions(self) -> Optional[UserAccessPermissions]: + """Get the user access permissions for encrypted documents. Returns None if not encrypted.""" + if self._encryption is None: + return None + return UserAccessPermissions(self._encryption.P) + + @property + @abstractmethod + def is_encrypted(self) -> bool: + """ + Read-only boolean property showing whether this PDF file is encrypted. + + Note that this property, if true, will remain true even after the + :meth:`decrypt()` method is called. + """ + ... # pragma: no cover + + @property + def xfa(self) -> Optional[Dict[str, Any]]: + tree: Optional[TreeObject] = None + retval: Dict[str, Any] = {} + catalog = self.root_object + + if "/AcroForm" not in catalog or not catalog["/AcroForm"]: + return None + + tree = cast(TreeObject, catalog["/AcroForm"]) + + if "/XFA" in tree: + fields = cast(ArrayObject, tree["/XFA"]) + i = iter(fields) + for f in i: + tag = f + f = next(i) + if isinstance(f, IndirectObject): + field = cast(Optional[EncodedStreamObject], f.get_object()) + if field: + es = zlib.decompress(field._data) + retval[tag] = es + return retval + + @property + def attachments(self) -> Mapping[str, List[bytes]]: + """Mapping of attachment filenames to their content.""" + return LazyDict( + { + name: (self._get_attachment_list, name) + for name in self._list_attachments() + } + ) + + @property + def attachment_list(self) -> Generator[EmbeddedFile, None, None]: + """Iterable of attachment objects.""" + yield from EmbeddedFile._load(self.root_object) + + def _list_attachments(self) -> List[str]: + """ + Retrieves the list of filenames of file attachments. + + Returns: + list of filenames + + """ + names = [] + for entry in self.attachment_list: + names.append(entry.name) + if (name := entry.alternative_name) != entry.name and name: + names.append(name) + return names + + def _get_attachment_list(self, name: str) -> List[bytes]: + out = self._get_attachments(name)[name] + if isinstance(out, list): + return out + return [out] + + def _get_attachments( + self, filename: Optional[str] = None + ) -> Dict[str, Union[bytes, List[bytes]]]: + """ + Retrieves all or selected file attachments of the PDF as a dictionary of file names + and the file data as a bytestring. + + Args: + filename: If filename is None, then a dictionary of all attachments + will be returned, where the key is the filename and the value + is the content. Otherwise, a dictionary with just a single key + - the filename - and its content will be returned. + + Returns: + dictionary of filename -> Union[bytestring or List[ByteString]] + If the filename exists multiple times a list of the different versions will be provided. + + """ + attachments: Dict[str, Union[bytes, List[bytes]]] = {} + for entry in self.attachment_list: + names = set() + alternative_name = entry.alternative_name + if filename is not None: + if filename in {entry.name, alternative_name}: + name = entry.name if filename == entry.name else alternative_name + names.add(name) + else: + continue + else: + names = {entry.name, alternative_name} + + for name in names: + if name is None: + continue + if name in attachments: + if not isinstance(attachments[name], list): + attachments[name] = [attachments[name]] # type:ignore + attachments[name].append(entry.content) # type:ignore + else: + attachments[name] = entry.content + return attachments + + @abstractmethod + def _repr_mimebundle_( + self, + include: Union[None, Iterable[str]] = None, + exclude: Union[None, Iterable[str]] = None, + ) -> Dict[str, Any]: + """ + Integration into Jupyter Notebooks. + + This method returns a dictionary that maps a mime-type to its + representation. + + .. seealso:: + + https://ipython.readthedocs.io/en/stable/config/integrating.html + """ + ... # pragma: no cover + + +class LazyDict(Mapping[Any, Any]): + def __init__(self, *args: Any, **kw: Any) -> None: + self._raw_dict = dict(*args, **kw) + + def __getitem__(self, key: str) -> Any: + func, arg = self._raw_dict.__getitem__(key) + return func(arg) + + def __iter__(self) -> Iterator[Any]: + return iter(self._raw_dict) + + def __len__(self) -> int: + return len(self._raw_dict) + + def __str__(self) -> str: + return f"LazyDict(keys={list(self.keys())})" diff --git a/venv/lib/python3.12/site-packages/pypdf/_encryption.py b/venv/lib/python3.12/site-packages/pypdf/_encryption.py new file mode 100644 index 0000000..b02a0dd --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_encryption.py @@ -0,0 +1,1178 @@ +# Copyright (c) 2022, exiledkingcc +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +import hashlib +import secrets +import struct +from enum import Enum, IntEnum +from typing import Any, Dict, Optional, Tuple, Union, cast + +from pypdf._crypt_providers import ( + CryptAES, + CryptBase, + CryptIdentity, + CryptRC4, + aes_cbc_decrypt, + aes_cbc_encrypt, + aes_ecb_decrypt, + aes_ecb_encrypt, + rc4_decrypt, + rc4_encrypt, +) + +from ._utils import logger_warning +from .generic import ( + ArrayObject, + ByteStringObject, + DictionaryObject, + NameObject, + NumberObject, + PdfObject, + StreamObject, + TextStringObject, + create_string_object, +) + + +class CryptFilter: + def __init__( + self, + stm_crypt: CryptBase, + str_crypt: CryptBase, + ef_crypt: CryptBase, + ) -> None: + self.stm_crypt = stm_crypt + self.str_crypt = str_crypt + self.ef_crypt = ef_crypt + + def encrypt_object(self, obj: PdfObject) -> PdfObject: + if isinstance(obj, ByteStringObject): + data = self.str_crypt.encrypt(obj.original_bytes) + obj = ByteStringObject(data) + elif isinstance(obj, TextStringObject): + data = self.str_crypt.encrypt(obj.get_encoded_bytes()) + obj = ByteStringObject(data) + elif isinstance(obj, StreamObject): + obj2 = StreamObject() + obj2.update(obj) + obj2.set_data(self.stm_crypt.encrypt(obj._data)) + for key, value in obj.items(): # Dont forget the Stream dict. + obj2[key] = self.encrypt_object(value) + obj = obj2 + elif isinstance(obj, DictionaryObject): + obj2 = DictionaryObject() # type: ignore + for key, value in obj.items(): + obj2[key] = self.encrypt_object(value) + obj = obj2 + elif isinstance(obj, ArrayObject): + obj = ArrayObject(self.encrypt_object(x) for x in obj) + return obj + + def decrypt_object(self, obj: PdfObject) -> PdfObject: + if isinstance(obj, (ByteStringObject, TextStringObject)): + data = self.str_crypt.decrypt(obj.original_bytes) + obj = create_string_object(data) + elif isinstance(obj, StreamObject): + obj._data = self.stm_crypt.decrypt(obj._data) + for key, value in obj.items(): # Dont forget the Stream dict. + obj[key] = self.decrypt_object(value) + elif isinstance(obj, DictionaryObject): + for key, value in obj.items(): + obj[key] = self.decrypt_object(value) + elif isinstance(obj, ArrayObject): + for i in range(len(obj)): + obj[i] = self.decrypt_object(obj[i]) + return obj + + +_PADDING = ( + b"\x28\xbf\x4e\x5e\x4e\x75\x8a\x41\x64\x00\x4e\x56\xff\xfa\x01\x08" + b"\x2e\x2e\x00\xb6\xd0\x68\x3e\x80\x2f\x0c\xa9\xfe\x64\x53\x69\x7a" +) + + +def _padding(data: bytes) -> bytes: + return (data + _PADDING)[:32] + + +class AlgV4: + @staticmethod + def compute_key( + password: bytes, + rev: int, + key_size: int, + o_entry: bytes, + P: int, + id1_entry: bytes, + metadata_encrypted: bool, + ) -> bytes: + """ + Algorithm 2: Computing an encryption key. + + a) Pad or truncate the password string to exactly 32 bytes. If the + password string is more than 32 bytes long, + use only its first 32 bytes; if it is less than 32 bytes long, pad it + by appending the required number of + additional bytes from the beginning of the following padding string: + < 28 BF 4E 5E 4E 75 8A 41 64 00 4E 56 FF FA 01 08 + 2E 2E 00 B6 D0 68 3E 80 2F 0C A9 FE 64 53 69 7A > + That is, if the password string is n bytes long, append + the first 32 - n bytes of the padding string to the end + of the password string. If the password string is empty + (zero-length), meaning there is no user password, + substitute the entire padding string in its place. + + b) Initialize the MD5 hash function and pass the result of step (a) + as input to this function. + c) Pass the value of the encryption dictionary’s O entry to the + MD5 hash function. ("Algorithm 3: Computing + the encryption dictionary’s O (owner password) value" shows how the + O value is computed.) + d) Convert the integer value of the P entry to a 32-bit unsigned binary + number and pass these bytes to the + MD5 hash function, low-order byte first. + e) Pass the first element of the file’s file identifier array (the value + of the ID entry in the document’s trailer + dictionary; see Table 15) to the MD5 hash function. + f) (Security handlers of revision 4 or greater) If document metadata is + not being encrypted, pass 4 bytes with + the value 0xFFFFFFFF to the MD5 hash function. + g) Finish the hash. + h) (Security handlers of revision 3 or greater) Do the following + 50 times: Take the output from the previous + MD5 hash and pass the first n bytes of the output as input into a new + MD5 hash, where n is the number of + bytes of the encryption key as defined by the value of the encryption + dictionary’s Length entry. + i) Set the encryption key to the first n bytes of the output from the + final MD5 hash, where n shall always be 5 + for security handlers of revision 2 but, for security handlers of + revision 3 or greater, shall depend on the + value of the encryption dictionary’s Length entry. + + Args: + password: The encryption secret as a bytes-string + rev: The encryption revision (see PDF standard) + key_size: The size of the key in bytes + o_entry: The owner entry + P: A set of flags specifying which operations shall be permitted + when the document is opened with user access. If bit 2 is set to 1, + all other bits are ignored and all operations are permitted. + If bit 2 is set to 0, permission for operations are based on the + values of the remaining flags defined in Table 24. + id1_entry: + metadata_encrypted: A boolean indicating if the metadata is encrypted. + + Returns: + The u_hash digest of length key_size + + """ + a = _padding(password) + u_hash = hashlib.md5(a) + u_hash.update(o_entry) + u_hash.update(struct.pack("= 4 and not metadata_encrypted: + u_hash.update(b"\xff\xff\xff\xff") + u_hash_digest = u_hash.digest() + length = key_size // 8 + if rev >= 3: + for _ in range(50): + u_hash_digest = hashlib.md5(u_hash_digest[:length]).digest() + return u_hash_digest[:length] + + @staticmethod + def compute_O_value_key(owner_password: bytes, rev: int, key_size: int) -> bytes: + """ + Algorithm 3: Computing the encryption dictionary’s O (owner password) value. + + a) Pad or truncate the owner password string as described in step (a) + of "Algorithm 2: Computing an encryption key". + If there is no owner password, use the user password instead. + b) Initialize the MD5 hash function and pass the result of step (a) as + input to this function. + c) (Security handlers of revision 3 or greater) Do the following 50 times: + Take the output from the previous + MD5 hash and pass it as input into a new MD5 hash. + d) Create an RC4 encryption key using the first n bytes of the output + from the final MD5 hash, where n shall + always be 5 for security handlers of revision 2 but, for security + handlers of revision 3 or greater, shall + depend on the value of the encryption dictionary’s Length entry. + e) Pad or truncate the user password string as described in step (a) of + "Algorithm 2: Computing an encryption key". + f) Encrypt the result of step (e), using an RC4 encryption function with + the encryption key obtained in step (d). + g) (Security handlers of revision 3 or greater) Do the following 19 times: + Take the output from the previous + invocation of the RC4 function and pass it as input to a new + invocation of the function; use an encryption + key generated by taking each byte of the encryption key obtained in + step (d) and performing an XOR + (exclusive or) operation between that byte and the single-byte value + of the iteration counter (from 1 to 19). + h) Store the output from the final invocation of the RC4 function as + the value of the O entry in the encryption dictionary. + + Args: + owner_password: + rev: The encryption revision (see PDF standard) + key_size: The size of the key in bytes + + Returns: + The RC4 key + + """ + a = _padding(owner_password) + o_hash_digest = hashlib.md5(a).digest() + + if rev >= 3: + for _ in range(50): + o_hash_digest = hashlib.md5(o_hash_digest).digest() + + return o_hash_digest[: key_size // 8] + + @staticmethod + def compute_O_value(rc4_key: bytes, user_password: bytes, rev: int) -> bytes: + """ + See :func:`compute_O_value_key`. + + Args: + rc4_key: + user_password: + rev: The encryption revision (see PDF standard) + + Returns: + The RC4 encrypted + + """ + a = _padding(user_password) + rc4_enc = rc4_encrypt(rc4_key, a) + if rev >= 3: + for i in range(1, 20): + key = bytes(x ^ i for x in rc4_key) + rc4_enc = rc4_encrypt(key, rc4_enc) + return rc4_enc + + @staticmethod + def compute_U_value(key: bytes, rev: int, id1_entry: bytes) -> bytes: + """ + Algorithm 4: Computing the encryption dictionary’s U (user password) value. + + (Security handlers of revision 2) + + a) Create an encryption key based on the user password string, as + described in "Algorithm 2: Computing an encryption key". + b) Encrypt the 32-byte padding string shown in step (a) of + "Algorithm 2: Computing an encryption key", using an RC4 encryption + function with the encryption key from the preceding step. + c) Store the result of step (b) as the value of the U entry in the + encryption dictionary. + + Args: + key: + rev: The encryption revision (see PDF standard) + id1_entry: + + Returns: + The value + + """ + if rev <= 2: + return rc4_encrypt(key, _PADDING) + + """ + Algorithm 5: Computing the encryption dictionary’s U (user password) value. + + (Security handlers of revision 3 or greater) + + a) Create an encryption key based on the user password string, as + described in "Algorithm 2: Computing an encryption key". + b) Initialize the MD5 hash function and pass the 32-byte padding string + shown in step (a) of "Algorithm 2: + Computing an encryption key" as input to this function. + c) Pass the first element of the file’s file identifier array (the value + of the ID entry in the document’s trailer + dictionary; see Table 15) to the hash function and finish the hash. + d) Encrypt the 16-byte result of the hash, using an RC4 encryption + function with the encryption key from step (a). + e) Do the following 19 times: Take the output from the previous + invocation of the RC4 function and pass it as input to a new + invocation of the function; use an encryption key generated by + taking each byte of the original encryption key obtained in + step (a) and performing an XOR (exclusive or) operation between that + byte and the single-byte value of the iteration counter (from 1 to 19). + f) Append 16 bytes of arbitrary padding to the output from the final + invocation of the RC4 function and store the 32-byte result as the + value of the U entry in the encryption dictionary. + """ + u_hash = hashlib.md5(_PADDING) + u_hash.update(id1_entry) + rc4_enc = rc4_encrypt(key, u_hash.digest()) + for i in range(1, 20): + rc4_key = bytes(x ^ i for x in key) + rc4_enc = rc4_encrypt(rc4_key, rc4_enc) + return _padding(rc4_enc) + + @staticmethod + def verify_user_password( + user_password: bytes, + rev: int, + key_size: int, + o_entry: bytes, + u_entry: bytes, + P: int, + id1_entry: bytes, + metadata_encrypted: bool, + ) -> bytes: + """ + Algorithm 6: Authenticating the user password. + + a) Perform all but the last step of "Algorithm 4: Computing the + encryption dictionary’s U (user password) value (Security handlers of + revision 2)" or "Algorithm 5: Computing the encryption dictionary’s U + (user password) value (Security handlers of revision 3 or greater)" + using the supplied password string. + b) If the result of step (a) is equal to the value of the encryption + dictionary’s U entry (comparing on the first 16 bytes in the case of + security handlers of revision 3 or greater), the password supplied is + the correct user password. The key obtained in step (a) (that is, in + the first step of "Algorithm 4: Computing the encryption + dictionary’s U (user password) value + (Security handlers of revision 2)" or + "Algorithm 5: Computing the encryption dictionary’s U (user password) + value (Security handlers of revision 3 or greater)") shall be used + to decrypt the document. + + Args: + user_password: The user password as a bytes stream + rev: The encryption revision (see PDF standard) + key_size: The size of the key in bytes + o_entry: The owner entry + u_entry: The user entry + P: A set of flags specifying which operations shall be permitted + when the document is opened with user access. If bit 2 is set to 1, + all other bits are ignored and all operations are permitted. + If bit 2 is set to 0, permission for operations are based on the + values of the remaining flags defined in Table 24. + id1_entry: + metadata_encrypted: A boolean indicating if the metadata is encrypted. + + Returns: + The key + + """ + key = AlgV4.compute_key( + user_password, rev, key_size, o_entry, P, id1_entry, metadata_encrypted + ) + u_value = AlgV4.compute_U_value(key, rev, id1_entry) + if rev >= 3: + u_value = u_value[:16] + u_entry = u_entry[:16] + if u_value != u_entry: + key = b"" + return key + + @staticmethod + def verify_owner_password( + owner_password: bytes, + rev: int, + key_size: int, + o_entry: bytes, + u_entry: bytes, + P: int, + id1_entry: bytes, + metadata_encrypted: bool, + ) -> bytes: + """ + Algorithm 7: Authenticating the owner password. + + a) Compute an encryption key from the supplied password string, as + described in steps (a) to (d) of + "Algorithm 3: Computing the encryption dictionary’s O (owner password) + value". + b) (Security handlers of revision 2 only) Decrypt the value of the + encryption dictionary’s O entry, using an RC4 + encryption function with the encryption key computed in step (a). + (Security handlers of revision 3 or greater) Do the following 20 times: + Decrypt the value of the encryption dictionary’s O entry (first iteration) + or the output from the previous iteration (all subsequent iterations), + using an RC4 encryption function with a different encryption key at + each iteration. The key shall be generated by taking the original key + (obtained in step (a)) and performing an XOR (exclusive or) operation + between each byte of the key and the single-byte value of the + iteration counter (from 19 to 0). + c) The result of step (b) purports to be the user password. + Authenticate this user password using + "Algorithm 6: Authenticating the user password". + If it is correct, the password supplied is the correct owner password. + + Args: + owner_password: + rev: The encryption revision (see PDF standard) + key_size: The size of the key in bytes + o_entry: The owner entry + u_entry: The user entry + P: A set of flags specifying which operations shall be permitted + when the document is opened with user access. If bit 2 is set to 1, + all other bits are ignored and all operations are permitted. + If bit 2 is set to 0, permission for operations are based on the + values of the remaining flags defined in Table 24. + id1_entry: + metadata_encrypted: A boolean indicating if the metadata is encrypted. + + Returns: + bytes + + """ + rc4_key = AlgV4.compute_O_value_key(owner_password, rev, key_size) + + if rev <= 2: + user_password = rc4_decrypt(rc4_key, o_entry) + else: + user_password = o_entry + for i in range(19, -1, -1): + key = bytes(x ^ i for x in rc4_key) + user_password = rc4_decrypt(key, user_password) + return AlgV4.verify_user_password( + user_password, + rev, + key_size, + o_entry, + u_entry, + P, + id1_entry, + metadata_encrypted, + ) + + +class AlgV5: + @staticmethod + def verify_owner_password( + R: int, password: bytes, o_value: bytes, oe_value: bytes, u_value: bytes + ) -> bytes: + """ + Algorithm 3.2a Computing an encryption key. + + To understand the algorithm below, it is necessary to treat the O and U + strings in the Encrypt dictionary as made up of three sections. + The first 32 bytes are a hash value (explained below). The next 8 bytes + are called the Validation Salt. The final 8 bytes are called the Key Salt. + + 1. The password string is generated from Unicode input by processing the + input string with the SASLprep (IETF RFC 4013) profile of + stringprep (IETF RFC 3454), and then converting to a UTF-8 + representation. + 2. Truncate the UTF-8 representation to 127 bytes if it is longer than + 127 bytes. + 3. Test the password against the owner key by computing the SHA-256 hash + of the UTF-8 password concatenated with the 8 bytes of owner + Validation Salt, concatenated with the 48-byte U string. If the + 32-byte result matches the first 32 bytes of the O string, this is + the owner password. + Compute an intermediate owner key by computing the SHA-256 hash of + the UTF-8 password concatenated with the 8 bytes of owner Key Salt, + concatenated with the 48-byte U string. The 32-byte result is the + key used to decrypt the 32-byte OE string using AES-256 in CBC mode + with no padding and an initialization vector of zero. + The 32-byte result is the file encryption key. + 4. Test the password against the user key by computing the SHA-256 hash + of the UTF-8 password concatenated with the 8 bytes of user + Validation Salt. If the 32 byte result matches the first 32 bytes of + the U string, this is the user password. + Compute an intermediate user key by computing the SHA-256 hash of the + UTF-8 password concatenated with the 8 bytes of user Key Salt. + The 32-byte result is the key used to decrypt the 32-byte + UE string using AES-256 in CBC mode with no padding and an + initialization vector of zero. The 32-byte result is the file + encryption key. + 5. Decrypt the 16-byte Perms string using AES-256 in ECB mode with an + initialization vector of zero and the file encryption key as the key. + Verify that bytes 9-11 of the result are the characters ‘a’, ‘d’, ‘b’. + Bytes 0-3 of the decrypted Perms entry, treated as a little-endian + integer, are the user permissions. + They should match the value in the P key. + + Args: + R: A number specifying which revision of the standard security + handler shall be used to interpret this dictionary + password: The owner password + o_value: A 32-byte string, based on both the owner and user passwords, + that shall be used in computing the encryption key and in + determining whether a valid owner password was entered + oe_value: + u_value: A 32-byte string, based on the user password, that shall be + used in determining whether to prompt the user for a password and, + if so, whether a valid user or owner password was entered. + + Returns: + The key + + """ + password = password[:127] + if ( + AlgV5.calculate_hash(R, password, o_value[32:40], u_value[:48]) + != o_value[:32] + ): + return b"" + iv = bytes(0 for _ in range(16)) + tmp_key = AlgV5.calculate_hash(R, password, o_value[40:48], u_value[:48]) + return aes_cbc_decrypt(tmp_key, iv, oe_value) + + @staticmethod + def verify_user_password( + R: int, password: bytes, u_value: bytes, ue_value: bytes + ) -> bytes: + """ + See :func:`verify_owner_password`. + + Args: + R: A number specifying which revision of the standard security + handler shall be used to interpret this dictionary + password: The user password + u_value: A 32-byte string, based on the user password, that shall be + used in determining whether to prompt the user for a password + and, if so, whether a valid user or owner password was entered. + ue_value: + + Returns: + bytes + + """ + password = password[:127] + if AlgV5.calculate_hash(R, password, u_value[32:40], b"") != u_value[:32]: + return b"" + iv = bytes(0 for _ in range(16)) + tmp_key = AlgV5.calculate_hash(R, password, u_value[40:48], b"") + return aes_cbc_decrypt(tmp_key, iv, ue_value) + + @staticmethod + def calculate_hash(R: int, password: bytes, salt: bytes, udata: bytes) -> bytes: + # https://github.com/qpdf/qpdf/blob/main/libqpdf/QPDF_encryption.cc + k = hashlib.sha256(password + salt + udata).digest() + if R < 6: + return k + count = 0 + while True: + count += 1 + k1 = password + k + udata + e = aes_cbc_encrypt(k[:16], k[16:32], k1 * 64) + hash_fn = ( + hashlib.sha256, + hashlib.sha384, + hashlib.sha512, + )[sum(e[:16]) % 3] + k = hash_fn(e).digest() + if count >= 64 and e[-1] <= count - 32: + break + return k[:32] + + @staticmethod + def verify_perms( + key: bytes, perms: bytes, p: int, metadata_encrypted: bool + ) -> bool: + """ + See :func:`verify_owner_password` and :func:`compute_perms_value`. + + Args: + key: The owner password + perms: + p: A set of flags specifying which operations shall be permitted + when the document is opened with user access. + If bit 2 is set to 1, all other bits are ignored and all + operations are permitted. + If bit 2 is set to 0, permission for operations are based on + the values of the remaining flags defined in Table 24. + metadata_encrypted: + + Returns: + A boolean + + """ + b8 = b"T" if metadata_encrypted else b"F" + p1 = struct.pack(" Dict[Any, Any]: + user_password = user_password[:127] + owner_password = owner_password[:127] + u_value, ue_value = AlgV5.compute_U_value(R, user_password, key) + o_value, oe_value = AlgV5.compute_O_value(R, owner_password, key, u_value) + perms = AlgV5.compute_Perms_value(key, p, metadata_encrypted) + return { + "/U": u_value, + "/UE": ue_value, + "/O": o_value, + "/OE": oe_value, + "/Perms": perms, + } + + @staticmethod + def compute_U_value(R: int, password: bytes, key: bytes) -> Tuple[bytes, bytes]: + """ + Algorithm 3.8 Computing the encryption dictionary’s U (user password) + and UE (user encryption key) values. + + 1. Generate 16 random bytes of data using a strong random number generator. + The first 8 bytes are the User Validation Salt. The second 8 bytes + are the User Key Salt. Compute the 32-byte SHA-256 hash of the + password concatenated with the User Validation Salt. The 48-byte + string consisting of the 32-byte hash followed by the User + Validation Salt followed by the User Key Salt is stored as the U key. + 2. Compute the 32-byte SHA-256 hash of the password concatenated with + the User Key Salt. Using this hash as the key, encrypt the file + encryption key using AES-256 in CBC mode with no padding and an + initialization vector of zero. The resulting 32-byte string is stored + as the UE key. + + Args: + R: + password: + key: + + Returns: + A tuple (u-value, ue value) + + """ + random_bytes = secrets.token_bytes(16) + val_salt = random_bytes[:8] + key_salt = random_bytes[8:] + u_value = AlgV5.calculate_hash(R, password, val_salt, b"") + val_salt + key_salt + + tmp_key = AlgV5.calculate_hash(R, password, key_salt, b"") + iv = bytes(0 for _ in range(16)) + ue_value = aes_cbc_encrypt(tmp_key, iv, key) + return u_value, ue_value + + @staticmethod + def compute_O_value( + R: int, password: bytes, key: bytes, u_value: bytes + ) -> Tuple[bytes, bytes]: + """ + Algorithm 3.9 Computing the encryption dictionary’s O (owner password) + and OE (owner encryption key) values. + + 1. Generate 16 random bytes of data using a strong random number + generator. The first 8 bytes are the Owner Validation Salt. The + second 8 bytes are the Owner Key Salt. Compute the 32-byte SHA-256 + hash of the password concatenated with the Owner Validation Salt and + then concatenated with the 48-byte U string as generated in + Algorithm 3.8. The 48-byte string consisting of the 32-byte hash + followed by the Owner Validation Salt followed by the Owner Key Salt + is stored as the O key. + 2. Compute the 32-byte SHA-256 hash of the password concatenated with + the Owner Key Salt and then concatenated with the 48-byte U string as + generated in Algorithm 3.8. Using this hash as the key, + encrypt the file encryption key using AES-256 in CBC mode with + no padding and an initialization vector of zero. + The resulting 32-byte string is stored as the OE key. + + Args: + R: + password: + key: + u_value: A 32-byte string, based on the user password, that shall be + used in determining whether to prompt the user for a password + and, if so, whether a valid user or owner password was entered. + + Returns: + A tuple (O value, OE value) + + """ + random_bytes = secrets.token_bytes(16) + val_salt = random_bytes[:8] + key_salt = random_bytes[8:] + o_value = ( + AlgV5.calculate_hash(R, password, val_salt, u_value) + val_salt + key_salt + ) + tmp_key = AlgV5.calculate_hash(R, password, key_salt, u_value[:48]) + iv = bytes(0 for _ in range(16)) + oe_value = aes_cbc_encrypt(tmp_key, iv, key) + return o_value, oe_value + + @staticmethod + def compute_Perms_value(key: bytes, p: int, metadata_encrypted: bool) -> bytes: + """ + Algorithm 3.10 Computing the encryption dictionary’s Perms + (permissions) value. + + 1. Extend the permissions (contents of the P integer) to 64 bits by + setting the upper 32 bits to all 1’s. + (This allows for future extension without changing the format.) + 2. Record the 8 bytes of permission in the bytes 0-7 of the block, + low order byte first. + 3. Set byte 8 to the ASCII value ' T ' or ' F ' according to the + EncryptMetadata Boolean. + 4. Set bytes 9-11 to the ASCII characters ' a ', ' d ', ' b '. + 5. Set bytes 12-15 to 4 bytes of random data, which will be ignored. + 6. Encrypt the 16-byte block using AES-256 in ECB mode with an + initialization vector of zero, using the file encryption key as the + key. The result (16 bytes) is stored as the Perms string, and checked + for validity when the file is opened. + + Args: + key: + p: A set of flags specifying which operations shall be permitted + when the document is opened with user access. If bit 2 is set to 1, + all other bits are ignored and all operations are permitted. + If bit 2 is set to 0, permission for operations are based on the + values of the remaining flags defined in Table 24. + metadata_encrypted: A boolean indicating if the metadata is encrypted. + + Returns: + The perms value + + """ + b8 = b"T" if metadata_encrypted else b"F" + rr = secrets.token_bytes(4) + data = struct.pack(" None: + # §7.6.2, entries common to all encryption dictionaries + # use same name as keys of encryption dictionaries entries + self.V = V + self.R = R + self.Length = Length # key_size + self.P = (P + 0x100000000) % 0x100000000 # maybe P < 0 + self.EncryptMetadata = EncryptMetadata + self.id1_entry = first_id_entry + self.StmF = StmF + self.StrF = StrF + self.EFF = EFF + self.values: EncryptionValues = values if values else EncryptionValues() + + self._password_type = PasswordType.NOT_DECRYPTED + self._key: Optional[bytes] = None + + def is_decrypted(self) -> bool: + return self._password_type != PasswordType.NOT_DECRYPTED + + def encrypt_object(self, obj: PdfObject, idnum: int, generation: int) -> PdfObject: + # skip calculate key + if not self._is_encryption_object(obj): + return obj + + cf = self._make_crypt_filter(idnum, generation) + return cf.encrypt_object(obj) + + def decrypt_object(self, obj: PdfObject, idnum: int, generation: int) -> PdfObject: + # skip calculate key + if not self._is_encryption_object(obj): + return obj + + cf = self._make_crypt_filter(idnum, generation) + return cf.decrypt_object(obj) + + @staticmethod + def _is_encryption_object(obj: PdfObject) -> bool: + return isinstance( + obj, + ( + ByteStringObject, + TextStringObject, + StreamObject, + ArrayObject, + DictionaryObject, + ), + ) + + def _make_crypt_filter(self, idnum: int, generation: int) -> CryptFilter: + """ + Algorithm 1: Encryption of data using the RC4 or AES algorithms. + + a) Obtain the object number and generation number from the object + identifier of the string or stream to be encrypted + (see 7.3.10, "Indirect Objects"). If the string is a direct object, + use the identifier of the indirect object containing it. + b) For all strings and streams without crypt filter specifier; treating + the object number and generation number as binary integers, extend + the original n-byte encryption key to n + 5 bytes by appending the + low-order 3 bytes of the object number and the low-order 2 bytes of + the generation number in that order, low-order byte first. + (n is 5 unless the value of V in the encryption dictionary is greater + than 1, in which case n is the value of Length divided by 8.) + If using the AES algorithm, extend the encryption key an additional + 4 bytes by adding the value “sAlT”, which corresponds to the + hexadecimal values 0x73, 0x41, 0x6C, 0x54. (This addition is done for + backward compatibility and is not intended to provide additional + security.) + c) Initialize the MD5 hash function and pass the result of step (b) as + input to this function. + d) Use the first (n + 5) bytes, up to a maximum of 16, of the output + from the MD5 hash as the key for the RC4 or AES symmetric key + algorithms, along with the string or stream data to be encrypted. + If using the AES algorithm, the Cipher Block Chaining (CBC) mode, + which requires an initialization vector, is used. The block size + parameter is set to 16 bytes, and the initialization vector is a + 16-byte random number that is stored as the first 16 bytes of the + encrypted stream or string. + + Algorithm 3.1a Encryption of data using the AES algorithm + 1. Use the 32-byte file encryption key for the AES-256 symmetric key + algorithm, along with the string or stream data to be encrypted. + Use the AES algorithm in Cipher Block Chaining (CBC) mode, which + requires an initialization vector. The block size parameter is set to + 16 bytes, and the initialization vector is a 16-byte random number + that is stored as the first 16 bytes of the encrypted stream or string. + The output is the encrypted data to be stored in the PDF file. + """ + pack1 = struct.pack(" CryptBase: + if method == "/AESV2": + return CryptAES(aes128_key) + if method == "/AESV3": + return CryptAES(aes256_key) + if method == "/Identity": + return CryptIdentity() + + return CryptRC4(rc4_key) + + @staticmethod + def _encode_password(password: Union[bytes, str]) -> bytes: + if isinstance(password, str): + try: + pwd = password.encode("latin-1") + except Exception: + pwd = password.encode("utf-8") + else: + pwd = password + return pwd + + def verify(self, password: Union[bytes, str]) -> PasswordType: + pwd = self._encode_password(password) + key, rc = self.verify_v4(pwd) if self.V <= 4 else self.verify_v5(pwd) + if rc != PasswordType.NOT_DECRYPTED: + self._password_type = rc + self._key = key + return rc + + def verify_v4(self, password: bytes) -> Tuple[bytes, PasswordType]: + # verify owner password first + key = AlgV4.verify_owner_password( + password, + self.R, + self.Length, + self.values.O, + self.values.U, + self.P, + self.id1_entry, + self.EncryptMetadata, + ) + if key: + return key, PasswordType.OWNER_PASSWORD + key = AlgV4.verify_user_password( + password, + self.R, + self.Length, + self.values.O, + self.values.U, + self.P, + self.id1_entry, + self.EncryptMetadata, + ) + if key: + return key, PasswordType.USER_PASSWORD + return b"", PasswordType.NOT_DECRYPTED + + def verify_v5(self, password: bytes) -> Tuple[bytes, PasswordType]: + # TODO: use SASLprep process + # verify owner password first + key = AlgV5.verify_owner_password( + self.R, password, self.values.O, self.values.OE, self.values.U + ) + rc = PasswordType.OWNER_PASSWORD + if not key: + key = AlgV5.verify_user_password( + self.R, password, self.values.U, self.values.UE + ) + rc = PasswordType.USER_PASSWORD + if not key: + return b"", PasswordType.NOT_DECRYPTED + + # verify Perms + if not AlgV5.verify_perms(key, self.values.Perms, self.P, self.EncryptMetadata): + logger_warning("ignore '/Perms' verify failed", __name__) + return key, rc + + def write_entry( + self, user_password: str, owner_password: Optional[str] + ) -> DictionaryObject: + user_pwd = self._encode_password(user_password) + owner_pwd = self._encode_password(owner_password) if owner_password else None + if owner_pwd is None: + owner_pwd = user_pwd + + if self.V <= 4: + self.compute_values_v4(user_pwd, owner_pwd) + else: + self._key = secrets.token_bytes(self.Length // 8) + values = AlgV5.generate_values( + self.R, user_pwd, owner_pwd, self._key, self.P, self.EncryptMetadata + ) + self.values.O = values["/O"] + self.values.U = values["/U"] + self.values.OE = values["/OE"] + self.values.UE = values["/UE"] + self.values.Perms = values["/Perms"] + + dict_obj = DictionaryObject() + dict_obj[NameObject("/V")] = NumberObject(self.V) + dict_obj[NameObject("/R")] = NumberObject(self.R) + dict_obj[NameObject("/Length")] = NumberObject(self.Length) + dict_obj[NameObject("/P")] = NumberObject(self.P) + dict_obj[NameObject("/Filter")] = NameObject("/Standard") + # ignore /EncryptMetadata + + dict_obj[NameObject("/O")] = ByteStringObject(self.values.O) + dict_obj[NameObject("/U")] = ByteStringObject(self.values.U) + + if self.V >= 4: + # TODO: allow different method + std_cf = DictionaryObject() + std_cf[NameObject("/AuthEvent")] = NameObject("/DocOpen") + std_cf[NameObject("/CFM")] = NameObject(self.StmF) + std_cf[NameObject("/Length")] = NumberObject(self.Length // 8) + cf = DictionaryObject() + cf[NameObject("/StdCF")] = std_cf + dict_obj[NameObject("/CF")] = cf + dict_obj[NameObject("/StmF")] = NameObject("/StdCF") + dict_obj[NameObject("/StrF")] = NameObject("/StdCF") + # ignore EFF + # dict_obj[NameObject("/EFF")] = NameObject("/StdCF") + + if self.V >= 5: + dict_obj[NameObject("/OE")] = ByteStringObject(self.values.OE) + dict_obj[NameObject("/UE")] = ByteStringObject(self.values.UE) + dict_obj[NameObject("/Perms")] = ByteStringObject(self.values.Perms) + return dict_obj + + def compute_values_v4(self, user_password: bytes, owner_password: bytes) -> None: + rc4_key = AlgV4.compute_O_value_key(owner_password, self.R, self.Length) + o_value = AlgV4.compute_O_value(rc4_key, user_password, self.R) + + key = AlgV4.compute_key( + user_password, + self.R, + self.Length, + o_value, + self.P, + self.id1_entry, + self.EncryptMetadata, + ) + u_value = AlgV4.compute_U_value(key, self.R, self.id1_entry) + + self._key = key + self.values.O = o_value + self.values.U = u_value + + @staticmethod + def read(encryption_entry: DictionaryObject, first_id_entry: bytes) -> "Encryption": + if encryption_entry.get("/Filter") != "/Standard": + raise NotImplementedError( + "only Standard PDF encryption handler is available" + ) + if "/SubFilter" in encryption_entry: + raise NotImplementedError("/SubFilter NOT supported") + + stm_filter = "/V2" + str_filter = "/V2" + ef_filter = "/V2" + + alg_ver = encryption_entry.get("/V", 0) + if alg_ver not in (1, 2, 3, 4, 5): + raise NotImplementedError(f"Encryption V={alg_ver} NOT supported") + if alg_ver >= 4: + filters = encryption_entry["/CF"] + + stm_filter = encryption_entry.get("/StmF", "/Identity") + str_filter = encryption_entry.get("/StrF", "/Identity") + ef_filter = encryption_entry.get("/EFF", stm_filter) + + if stm_filter != "/Identity": + stm_filter = filters[stm_filter]["/CFM"] # type: ignore + if str_filter != "/Identity": + str_filter = filters[str_filter]["/CFM"] # type: ignore + if ef_filter != "/Identity": + ef_filter = filters[ef_filter]["/CFM"] # type: ignore + + allowed_methods = ("/Identity", "/V2", "/AESV2", "/AESV3") + if stm_filter not in allowed_methods: + raise NotImplementedError(f"StmF Method {stm_filter} NOT supported!") + if str_filter not in allowed_methods: + raise NotImplementedError(f"StrF Method {str_filter} NOT supported!") + if ef_filter not in allowed_methods: + raise NotImplementedError(f"EFF Method {ef_filter} NOT supported!") + + alg_rev = cast(int, encryption_entry["/R"]) + perm_flags = cast(int, encryption_entry["/P"]) + key_bits = encryption_entry.get("/Length", 40) + encrypt_metadata = encryption_entry.get("/EncryptMetadata") + encrypt_metadata = ( + encrypt_metadata.value if encrypt_metadata is not None else True + ) + values = EncryptionValues() + values.O = cast(ByteStringObject, encryption_entry["/O"]).original_bytes + values.U = cast(ByteStringObject, encryption_entry["/U"]).original_bytes + values.OE = encryption_entry.get("/OE", ByteStringObject()).original_bytes + values.UE = encryption_entry.get("/UE", ByteStringObject()).original_bytes + values.Perms = encryption_entry.get("/Perms", ByteStringObject()).original_bytes + return Encryption( + V=alg_ver, + R=alg_rev, + Length=key_bits, + P=perm_flags, + EncryptMetadata=encrypt_metadata, + first_id_entry=first_id_entry, + values=values, + StrF=str_filter, + StmF=stm_filter, + EFF=ef_filter, + entry=encryption_entry, # Dummy entry for the moment; will get removed + ) + + @staticmethod + def make( + alg: EncryptAlgorithm, permissions: int, first_id_entry: bytes + ) -> "Encryption": + alg_ver, alg_rev, key_bits = alg + + stm_filter, str_filter, ef_filter = "/V2", "/V2", "/V2" + + if alg == EncryptAlgorithm.AES_128: + stm_filter, str_filter, ef_filter = "/AESV2", "/AESV2", "/AESV2" + elif alg in (EncryptAlgorithm.AES_256_R5, EncryptAlgorithm.AES_256): + stm_filter, str_filter, ef_filter = "/AESV3", "/AESV3", "/AESV3" + + return Encryption( + V=alg_ver, + R=alg_rev, + Length=key_bits, + P=permissions, + EncryptMetadata=True, + first_id_entry=first_id_entry, + values=None, + StrF=str_filter, + StmF=stm_filter, + EFF=ef_filter, + entry=DictionaryObject(), # Dummy entry for the moment; will get removed + ) diff --git a/venv/lib/python3.12/site-packages/pypdf/_merger.py b/venv/lib/python3.12/site-packages/pypdf/_merger.py new file mode 100644 index 0000000..b6a8304 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_merger.py @@ -0,0 +1,42 @@ +# Copyright (c) 2006, Mathieu Fenniak +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + + +from ._utils import ( + deprecation_with_replacement, +) + + +class PdfMerger: + """ + Use :class:`PdfWriter` instead. + + .. deprecated:: 5.0.0 + """ + + def __init__(self) -> None: + deprecation_with_replacement("PdfMerger", "PdfWriter", "5.0.0") diff --git a/venv/lib/python3.12/site-packages/pypdf/_page.py b/venv/lib/python3.12/site-packages/pypdf/_page.py new file mode 100644 index 0000000..2a06fa8 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_page.py @@ -0,0 +1,2686 @@ +# Copyright (c) 2006, Mathieu Fenniak +# Copyright (c) 2007, Ashish Kulkarni +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import math +from dataclasses import dataclass +from decimal import Decimal +from io import BytesIO +from pathlib import Path +from typing import ( + Any, + Callable, + Dict, + Iterable, + Iterator, + List, + Literal, + Optional, + Sequence, + Set, + Tuple, + Union, + cast, + overload, +) + +from ._cmap import ( + build_char_map, + build_font_width_map, + compute_font_width, + get_actual_str_key, + unknown_char_map, +) +from ._protocols import PdfCommonDocProtocol +from ._text_extraction import ( + OrientationNotFoundError, + _layout_mode, + crlf_space_check, + get_display_str, + get_text_operands, + mult, +) +from ._utils import ( + CompressedTransformationMatrix, + TransformationMatrixType, + _human_readable_bytes, + logger_warning, + matrix_multiply, +) +from .constants import AnnotationDictionaryAttributes as ADA +from .constants import ImageAttributes as IA +from .constants import PageAttributes as PG +from .constants import Resources as RES +from .errors import PageSizeNotDefinedError, PdfReadError +from .filters import _xobj_to_image +from .generic import ( + ArrayObject, + ContentStream, + DictionaryObject, + EncodedStreamObject, + FloatObject, + IndirectObject, + NameObject, + NullObject, + NumberObject, + PdfObject, + RectangleObject, + StreamObject, + TextStringObject, + is_null_or_none, +) + +try: + from PIL.Image import Image + + pil_not_imported = False +except ImportError: + Image = object # type: ignore + pil_not_imported = True # error will be raised only when using images + +MERGE_CROP_BOX = "cropbox" # pypdf<=3.4.0 used 'trimbox' + + +def _get_rectangle(self: Any, name: str, defaults: Iterable[str]) -> RectangleObject: + retval: Union[None, RectangleObject, IndirectObject] = self.get(name) + if isinstance(retval, RectangleObject): + return retval + if is_null_or_none(retval): + for d in defaults: + retval = self.get(d) + if retval is not None: + break + if isinstance(retval, IndirectObject): + retval = self.pdf.get_object(retval) + retval = RectangleObject(retval) # type: ignore + _set_rectangle(self, name, retval) + return retval + + +def _set_rectangle(self: Any, name: str, value: Union[RectangleObject, float]) -> None: + name = NameObject(name) + self[name] = value + + +def _delete_rectangle(self: Any, name: str) -> None: + del self[name] + + +def _create_rectangle_accessor(name: str, fallback: Iterable[str]) -> property: + return property( + lambda self: _get_rectangle(self, name, fallback), + lambda self, value: _set_rectangle(self, name, value), + lambda self: _delete_rectangle(self, name), + ) + + +class Transformation: + """ + Represent a 2D transformation. + + The transformation between two coordinate systems is represented by a 3-by-3 + transformation matrix matrix with the following form:: + + a b 0 + c d 0 + e f 1 + + Because a transformation matrix has only six elements that can be changed, + it is usually specified in PDF as the six-element array [ a b c d e f ]. + + Coordinate transformations are expressed as matrix multiplications:: + + a b 0 + [ x′ y′ 1 ] = [ x y 1 ] × c d 0 + e f 1 + + + Example: + >>> from pypdf import Transformation + >>> op = Transformation().scale(sx=2, sy=3).translate(tx=10, ty=20) + >>> page.add_transformation(op) + + """ + + # 9.5.4 Coordinate Systems for 3D + # 4.2.2 Common Transformations + def __init__(self, ctm: CompressedTransformationMatrix = (1, 0, 0, 1, 0, 0)) -> None: + self.ctm = ctm + + @property + def matrix(self) -> TransformationMatrixType: + """ + Return the transformation matrix as a tuple of tuples in the form: + + ((a, b, 0), (c, d, 0), (e, f, 1)) + """ + return ( + (self.ctm[0], self.ctm[1], 0), + (self.ctm[2], self.ctm[3], 0), + (self.ctm[4], self.ctm[5], 1), + ) + + @staticmethod + def compress(matrix: TransformationMatrixType) -> CompressedTransformationMatrix: + """ + Compresses the transformation matrix into a tuple of (a, b, c, d, e, f). + + Args: + matrix: The transformation matrix as a tuple of tuples. + + Returns: + A tuple representing the transformation matrix as (a, b, c, d, e, f) + + """ + return ( + matrix[0][0], + matrix[0][1], + matrix[1][0], + matrix[1][1], + matrix[2][0], + matrix[2][1], + ) + + def transform(self, m: "Transformation") -> "Transformation": + """ + Apply one transformation to another. + + Args: + m: a Transformation to apply. + + Returns: + A new ``Transformation`` instance + + Example: + >>> from pypdf import Transformation + >>> op = Transformation((1, 0, 0, -1, 0, height)) # vertical mirror + >>> op = Transformation().transform(Transformation((-1, 0, 0, 1, iwidth, 0))) # horizontal mirror + >>> page.add_transformation(op) + + """ + ctm = Transformation.compress(matrix_multiply(self.matrix, m.matrix)) + return Transformation(ctm) + + def translate(self, tx: float = 0, ty: float = 0) -> "Transformation": + """ + Translate the contents of a page. + + Args: + tx: The translation along the x-axis. + ty: The translation along the y-axis. + + Returns: + A new ``Transformation`` instance + + """ + m = self.ctm + return Transformation(ctm=(m[0], m[1], m[2], m[3], m[4] + tx, m[5] + ty)) + + def scale( + self, sx: Optional[float] = None, sy: Optional[float] = None + ) -> "Transformation": + """ + Scale the contents of a page towards the origin of the coordinate system. + + Typically, that is the lower-left corner of the page. That can be + changed by translating the contents / the page boxes. + + Args: + sx: The scale factor along the x-axis. + sy: The scale factor along the y-axis. + + Returns: + A new Transformation instance with the scaled matrix. + + """ + if sx is None and sy is None: + raise ValueError("Either sx or sy must be specified") + if sx is None: + sx = sy + if sy is None: + sy = sx + assert sx is not None + assert sy is not None + op: TransformationMatrixType = ((sx, 0, 0), (0, sy, 0), (0, 0, 1)) + ctm = Transformation.compress(matrix_multiply(self.matrix, op)) + return Transformation(ctm) + + def rotate(self, rotation: float) -> "Transformation": + """ + Rotate the contents of a page. + + Args: + rotation: The angle of rotation in degrees. + + Returns: + A new ``Transformation`` instance with the rotated matrix. + + """ + rotation = math.radians(rotation) + op: TransformationMatrixType = ( + (math.cos(rotation), math.sin(rotation), 0), + (-math.sin(rotation), math.cos(rotation), 0), + (0, 0, 1), + ) + ctm = Transformation.compress(matrix_multiply(self.matrix, op)) + return Transformation(ctm) + + def __repr__(self) -> str: + return f"Transformation(ctm={self.ctm})" + + @overload + def apply_on(self, pt: List[float], as_object: bool = False) -> List[float]: + ... + + @overload + def apply_on( + self, pt: Tuple[float, float], as_object: bool = False + ) -> Tuple[float, float]: + ... + + def apply_on( + self, + pt: Union[Tuple[float, float], List[float]], + as_object: bool = False, + ) -> Union[Tuple[float, float], List[float]]: + """ + Apply the transformation matrix on the given point. + + Args: + pt: A tuple or list representing the point in the form (x, y) + + Returns: + A tuple or list representing the transformed point in the form (x', y') + + """ + typ = FloatObject if as_object else float + pt1 = ( + typ(float(pt[0]) * self.ctm[0] + float(pt[1]) * self.ctm[2] + self.ctm[4]), + typ(float(pt[0]) * self.ctm[1] + float(pt[1]) * self.ctm[3] + self.ctm[5]), + ) + return list(pt1) if isinstance(pt, list) else pt1 + + +@dataclass +class ImageFile: + """ + Image within the PDF file. *This object is not designed to be built.* + + This object should not be modified except using :func:`ImageFile.replace` to replace the image with a new one. + """ + + name: str = "" + """ + Filename as identified within the PDF file. + """ + + data: bytes = b"" + """ + Data as bytes. + """ + + image: Optional[Image] = None + """ + Data as PIL image. + """ + + indirect_reference: Optional[IndirectObject] = None + """ + Reference to the object storing the stream. + """ + + def replace(self, new_image: Image, **kwargs: Any) -> None: + """ + Replace the image with a new PIL image. + + Args: + new_image (PIL.Image.Image): The new PIL image to replace the existing image. + **kwargs: Additional keyword arguments to pass to `Image.save()`. + + Raises: + TypeError: If the image is inline or in a PdfReader. + TypeError: If the image does not belong to a PdfWriter. + TypeError: If `new_image` is not a PIL Image. + + Note: + This method replaces the existing image with a new image. + It is not allowed for inline images or images within a PdfReader. + The `kwargs` parameter allows passing additional parameters + to `Image.save()`, such as quality. + + """ + if pil_not_imported: + raise ImportError( + "pillow is required to do image extraction. " + "It can be installed via 'pip install pypdf[image]'" + ) + + from ._reader import PdfReader + + # to prevent circular import + from .filters import _xobj_to_image + from .generic import DictionaryObject, PdfObject + + if self.indirect_reference is None: + raise TypeError("Cannot update an inline image.") + if not hasattr(self.indirect_reference.pdf, "_id_translated"): + raise TypeError("Cannot update an image not belonging to a PdfWriter.") + if not isinstance(new_image, Image): + raise TypeError("new_image shall be a PIL Image") + b = BytesIO() + new_image.save(b, "PDF", **kwargs) + reader = PdfReader(b) + assert reader.pages[0].images[0].indirect_reference is not None + self.indirect_reference.pdf._objects[self.indirect_reference.idnum - 1] = ( + reader.pages[0].images[0].indirect_reference.get_object() + ) + cast( + PdfObject, self.indirect_reference.get_object() + ).indirect_reference = self.indirect_reference + # change the object attributes + extension, byte_stream, img = _xobj_to_image( + cast(DictionaryObject, self.indirect_reference.get_object()) + ) + assert extension is not None + self.name = self.name[: self.name.rfind(".")] + extension + self.data = byte_stream + self.image = img + + def __str__(self) -> str: + return f"{self.__class__.__name__}(name={self.name}, data: {_human_readable_bytes(len(self.data))})" + + def __repr__(self) -> str: + return self.__str__()[:-1] + f", hash: {hash(self.data)})" + + +class VirtualListImages(Sequence[ImageFile]): + """ + Provides access to images referenced within a page. + Only one copy will be returned if the usage is used on the same page multiple times. + See :func:`PageObject.images` for more details. + """ + + def __init__( + self, + ids_function: Callable[[], List[Union[str, List[str]]]], + get_function: Callable[[Union[str, List[str], Tuple[str]]], ImageFile], + ) -> None: + self.ids_function = ids_function + self.get_function = get_function + self.current = -1 + + def __len__(self) -> int: + return len(self.ids_function()) + + def keys(self) -> List[Union[str, List[str]]]: + return self.ids_function() + + def items(self) -> List[Tuple[Union[str, List[str]], ImageFile]]: + return [(x, self[x]) for x in self.ids_function()] + + @overload + def __getitem__(self, index: Union[int, str, List[str]]) -> ImageFile: + ... + + @overload + def __getitem__(self, index: slice) -> Sequence[ImageFile]: + ... + + def __getitem__( + self, index: Union[int, slice, str, List[str], Tuple[str]] + ) -> Union[ImageFile, Sequence[ImageFile]]: + lst = self.ids_function() + if isinstance(index, slice): + indices = range(*index.indices(len(self))) + lst = [lst[x] for x in indices] + cls = type(self) + return cls((lambda: lst), self.get_function) + if isinstance(index, (str, list, tuple)): + return self.get_function(index) + if not isinstance(index, int): + raise TypeError("Invalid sequence indices type") + len_self = len(lst) + if index < 0: + # support negative indexes + index = len_self + index + if index < 0 or index >= len_self: + raise IndexError("Sequence index out of range") + return self.get_function(lst[index]) + + def __iter__(self) -> Iterator[ImageFile]: + for i in range(len(self)): + yield self[i] + + def __str__(self) -> str: + p = [f"Image_{i}={n}" for i, n in enumerate(self.ids_function())] + return f"[{', '.join(p)}]" + + +class PageObject(DictionaryObject): + """ + PageObject represents a single page within a PDF file. + + Typically these objects will be created by accessing the + :attr:`pages` property of the + :class:`PdfReader` class, but it is + also possible to create an empty page with the + :meth:`create_blank_page()` static method. + + Args: + pdf: PDF file the page belongs to. + indirect_reference: Stores the original indirect reference to + this object in its source PDF + + """ + + original_page: "PageObject" # very local use in writer when appending + + def __init__( + self, + pdf: Optional[PdfCommonDocProtocol] = None, + indirect_reference: Optional[IndirectObject] = None, + ) -> None: + DictionaryObject.__init__(self) + self.pdf = pdf + self.inline_images: Optional[Dict[str, ImageFile]] = None + # below Union for mypy but actually Optional[List[str]] + self.indirect_reference = indirect_reference + if not is_null_or_none(indirect_reference): + assert indirect_reference is not None, "mypy" + self.update(cast(DictionaryObject, indirect_reference.get_object())) + self._font_width_maps: Dict[str, Tuple[Dict[str, float], str, float]] = {} + + def hash_bin(self) -> int: + """ + Used to detect modified object. + + Note: this function is overloaded to return the same results + as a DictionaryObject. + + Returns: + Hash considering type and value. + + """ + return hash( + (DictionaryObject, tuple(((k, v.hash_bin()) for k, v in self.items()))) + ) + + def hash_value_data(self) -> bytes: + data = super().hash_value_data() + data += b"%d" % id(self) + return data + + @property + def user_unit(self) -> float: + """ + A read-only positive number giving the size of user space units. + + It is in multiples of 1/72 inch. Hence a value of 1 means a user + space unit is 1/72 inch, and a value of 3 means that a user + space unit is 3/72 inch. + """ + return self.get(PG.USER_UNIT, 1) + + @staticmethod + def create_blank_page( + pdf: Optional[PdfCommonDocProtocol] = None, + width: Union[float, Decimal, None] = None, + height: Union[float, Decimal, None] = None, + ) -> "PageObject": + """ + Return a new blank page. + + If ``width`` or ``height`` is ``None``, try to get the page size + from the last page of *pdf*. + + Args: + pdf: PDF file the page is within. + width: The width of the new page expressed in default user + space units. + height: The height of the new page expressed in default user + space units. + + Returns: + The new blank page + + Raises: + PageSizeNotDefinedError: if ``pdf`` is ``None`` or contains + no page + + """ + page = PageObject(pdf) + + # Creates a new page (cf PDF Reference 7.7.3.3) + page.__setitem__(NameObject(PG.TYPE), NameObject("/Page")) + page.__setitem__(NameObject(PG.PARENT), NullObject()) + page.__setitem__(NameObject(PG.RESOURCES), DictionaryObject()) + if width is None or height is None: + if pdf is not None and len(pdf.pages) > 0: + lastpage = pdf.pages[len(pdf.pages) - 1] + width = lastpage.mediabox.width + height = lastpage.mediabox.height + else: + raise PageSizeNotDefinedError + page.__setitem__( + NameObject(PG.MEDIABOX), RectangleObject((0, 0, width, height)) # type: ignore + ) + + return page + + def _get_ids_image( + self, + obj: Optional[DictionaryObject] = None, + ancest: Optional[List[str]] = None, + call_stack: Optional[List[Any]] = None, + ) -> List[Union[str, List[str]]]: + if call_stack is None: + call_stack = [] + _i = getattr(obj, "indirect_reference", None) + if _i in call_stack: + return [] + else: + call_stack.append(_i) + if self.inline_images is None: + self.inline_images = self._get_inline_images() + if obj is None: + obj = self + if ancest is None: + ancest = [] + lst: List[Union[str, List[str]]] = [] + if PG.RESOURCES not in obj or RES.XOBJECT not in cast( + DictionaryObject, obj[PG.RESOURCES] + ): + return [] if self.inline_images is None else list(self.inline_images.keys()) + + x_object = obj[PG.RESOURCES][RES.XOBJECT].get_object() # type: ignore + for o in x_object: + if not isinstance(x_object[o], StreamObject): + continue + if x_object[o][IA.SUBTYPE] == "/Image": + lst.append(o if len(ancest) == 0 else [*ancest, o]) + else: # is a form with possible images inside + lst.extend(self._get_ids_image(x_object[o], [*ancest, o], call_stack)) + assert self.inline_images is not None + lst.extend(list(self.inline_images.keys())) + return lst + + def _get_image( + self, + id: Union[str, List[str], Tuple[str]], + obj: Optional[DictionaryObject] = None, + ) -> ImageFile: + if obj is None: + obj = cast(DictionaryObject, self) + if isinstance(id, tuple): + id = list(id) + if isinstance(id, List) and len(id) == 1: + id = id[0] + try: + xobjs = cast( + DictionaryObject, cast(DictionaryObject, obj[PG.RESOURCES])[RES.XOBJECT] + ) + except KeyError: + if not (id[0] == "~" and id[-1] == "~"): + raise + if isinstance(id, str): + if id[0] == "~" and id[-1] == "~": + if self.inline_images is None: + self.inline_images = self._get_inline_images() + if self.inline_images is None: # pragma: no cover + raise KeyError("No inline image can be found") + return self.inline_images[id] + + imgd = _xobj_to_image(cast(DictionaryObject, xobjs[id])) + extension, byte_stream = imgd[:2] + f = ImageFile( + name=f"{id[1:]}{extension}", + data=byte_stream, + image=imgd[2], + indirect_reference=xobjs[id].indirect_reference, + ) + return f + else: # in a sub object + ids = id[1:] + return self._get_image(ids, cast(DictionaryObject, xobjs[id[0]])) + + @property + def images(self) -> VirtualListImages: + """ + Read-only property emulating a list of images on a page. + + Get a list of all images on the page. The key can be: + - A string (for the top object) + - A tuple (for images within XObject forms) + - An integer + + Examples: + * `reader.pages[0].images[0]` # return first image + * `reader.pages[0].images['/I0']` # return image '/I0' + * `reader.pages[0].images['/TP1','/Image1']` # return image '/Image1' within '/TP1' Xobject/Form + * `for img in reader.pages[0].images:` # loops through all objects + + images.keys() and images.items() can be used. + + The ImageFile has the following properties: + + * `.name` : name of the object + * `.data` : bytes of the object + * `.image` : PIL Image Object + * `.indirect_reference` : object reference + + and the following methods: + `.replace(new_image: PIL.Image.Image, **kwargs)` : + replace the image in the pdf with the new image + applying the saving parameters indicated (such as quality) + + Example usage: + + reader.pages[0].images[0].replace(Image.open("new_image.jpg"), quality=20) + + Inline images are extracted and named ~0~, ~1~, ..., with the + indirect_reference set to None. + + """ + return VirtualListImages(self._get_ids_image, self._get_image) + + def _translate_value_inlineimage(self, k: str, v: PdfObject) -> PdfObject: + """Translate values used in inline image""" + try: + v = NameObject( + { + "/G": "/DeviceGray", + "/RGB": "/DeviceRGB", + "/CMYK": "/DeviceCMYK", + "/I": "/Indexed", + "/AHx": "/ASCIIHexDecode", + "/A85": "/ASCII85Decode", + "/LZW": "/LZWDecode", + "/Fl": "/FlateDecode", + "/RL": "/RunLengthDecode", + "/CCF": "/CCITTFaxDecode", + "/DCT": "/DCTDecode", + "/DeviceGray": "/DeviceGray", + "/DeviceRGB": "/DeviceRGB", + "/DeviceCMYK": "/DeviceCMYK", + "/Indexed": "/Indexed", + "/ASCIIHexDecode": "/ASCIIHexDecode", + "/ASCII85Decode": "/ASCII85Decode", + "/LZWDecode": "/LZWDecode", + "/FlateDecode": "/FlateDecode", + "/RunLengthDecode": "/RunLengthDecode", + "/CCITTFaxDecode": "/CCITTFaxDecode", + "/DCTDecode": "/DCTDecode", + }[cast(str, v)] + ) + except (TypeError, KeyError): + if isinstance(v, NameObject): + # It is a custom name, thus we have to look in resources. + # The only applicable case is for ColorSpace. + try: + res = cast(DictionaryObject, self["/Resources"])["/ColorSpace"] + v = cast(DictionaryObject, res)[v] + except KeyError: # for res and v + raise PdfReadError(f"Cannot find resource entry {v} for {k}") + return v + + def _get_inline_images(self) -> Dict[str, ImageFile]: + """Load inline images. Entries will be identified as `~1~`.""" + content = self.get_contents() + if is_null_or_none(content): + return {} + imgs_data = [] + assert content is not None, "mypy" + for param, ope in content.operations: + if ope == b"INLINE IMAGE": + imgs_data.append( + {"settings": param["settings"], "__streamdata__": param["data"]} + ) + elif ope in (b"BI", b"EI", b"ID"): # pragma: no cover + raise PdfReadError( + f"{ope!r} operator met whereas not expected, " + "please share usecase with pypdf dev team" + ) + """backup + elif ope == b"BI": + img_data["settings"] = {} + elif ope == b"EI": + imgs_data.append(img_data) + img_data = {} + elif ope == b"ID": + img_data["__streamdata__"] = b"" + elif "__streamdata__" in img_data: + if len(img_data["__streamdata__"]) > 0: + img_data["__streamdata__"] += b"\n" + raise Exception("check append") + img_data["__streamdata__"] += param + elif "settings" in img_data: + img_data["settings"][ope.decode()] = param + """ + files = {} + for num, ii in enumerate(imgs_data): + init = { + "__streamdata__": ii["__streamdata__"], + "/Length": len(ii["__streamdata__"]), + } + for k, v in ii["settings"].items(): + if k in {"/Length", "/L"}: # no length is expected + continue + if isinstance(v, list): + v = ArrayObject( + [self._translate_value_inlineimage(k, x) for x in v] + ) + else: + v = self._translate_value_inlineimage(k, v) + k = NameObject( + { + "/BPC": "/BitsPerComponent", + "/CS": "/ColorSpace", + "/D": "/Decode", + "/DP": "/DecodeParms", + "/F": "/Filter", + "/H": "/Height", + "/W": "/Width", + "/I": "/Interpolate", + "/Intent": "/Intent", + "/IM": "/ImageMask", + "/BitsPerComponent": "/BitsPerComponent", + "/ColorSpace": "/ColorSpace", + "/Decode": "/Decode", + "/DecodeParms": "/DecodeParms", + "/Filter": "/Filter", + "/Height": "/Height", + "/Width": "/Width", + "/Interpolate": "/Interpolate", + "/ImageMask": "/ImageMask", + }[k] + ) + if k not in init: + init[k] = v + ii["object"] = EncodedStreamObject.initialize_from_dictionary(init) + extension, byte_stream, img = _xobj_to_image(ii["object"]) + files[f"~{num}~"] = ImageFile( + name=f"~{num}~{extension}", + data=byte_stream, + image=img, + indirect_reference=None, + ) + return files + + @property + def rotation(self) -> int: + """ + The visual rotation of the page. + + This number has to be a multiple of 90 degrees: 0, 90, 180, or 270 are + valid values. This property does not affect ``/Contents``. + """ + rotate_obj = self.get(PG.ROTATE, 0) + return rotate_obj if isinstance(rotate_obj, int) else rotate_obj.get_object() + + @rotation.setter + def rotation(self, r: float) -> None: + self[NameObject(PG.ROTATE)] = NumberObject((((int(r) + 45) // 90) * 90) % 360) + + def transfer_rotation_to_content(self) -> None: + """ + Apply the rotation of the page to the content and the media/crop/... + boxes. + + It is recommended to apply this function before page merging. + """ + r = -self.rotation # rotation to apply is in the otherway + self.rotation = 0 + mb = RectangleObject(self.mediabox) + trsf = ( + Transformation() + .translate( + -float(mb.left + mb.width / 2), -float(mb.bottom + mb.height / 2) + ) + .rotate(r) + ) + pt1 = trsf.apply_on(mb.lower_left) + pt2 = trsf.apply_on(mb.upper_right) + trsf = trsf.translate(-min(pt1[0], pt2[0]), -min(pt1[1], pt2[1])) + self.add_transformation(trsf, False) + for b in ["/MediaBox", "/CropBox", "/BleedBox", "/TrimBox", "/ArtBox"]: + if b in self: + rr = RectangleObject(self[b]) # type: ignore + pt1 = trsf.apply_on(rr.lower_left) + pt2 = trsf.apply_on(rr.upper_right) + self[NameObject(b)] = RectangleObject( + ( + min(pt1[0], pt2[0]), + min(pt1[1], pt2[1]), + max(pt1[0], pt2[0]), + max(pt1[1], pt2[1]), + ) + ) + + def rotate(self, angle: int) -> "PageObject": + """ + Rotate a page clockwise by increments of 90 degrees. + + Args: + angle: Angle to rotate the page. Must be an increment of 90 deg. + + Returns: + The rotated PageObject + + """ + if angle % 90 != 0: + raise ValueError("Rotation angle must be a multiple of 90") + self[NameObject(PG.ROTATE)] = NumberObject(self.rotation + angle) + return self + + def _merge_resources( + self, + res1: DictionaryObject, + res2: DictionaryObject, + resource: Any, + new_res1: bool = True, + ) -> Tuple[Dict[str, Any], Dict[str, Any]]: + try: + assert isinstance(self.indirect_reference, IndirectObject) + pdf = self.indirect_reference.pdf + is_pdf_writer = hasattr( + pdf, "_add_object" + ) # ---------- expect isinstance(pdf,PdfWriter) + except (AssertionError, AttributeError): + pdf = None + is_pdf_writer = False + + def compute_unique_key(base_key: str) -> Tuple[str, bool]: + """ + Find a key that either doesn't already exist or has the same value + (indicated by the bool) + + Args: + base_key: An index is added to this to get the computed key + + Returns: + A tuple (computed key, bool) where the boolean indicates + if there is a resource of the given computed_key with the same + value. + + """ + value = page2res.raw_get(base_key) + # TODO : possible improvement : in case of writer, the indirect_reference + # can not be found because translated : this may be improved + + # try the current key first (e.g. "foo"), but otherwise iterate + # through "foo-0", "foo-1", etc. new_res can contain only finitely + # many keys, thus this'll eventually end, even if it's been crafted + # to be maximally annoying. + computed_key = base_key + idx = 0 + while computed_key in new_res: + if new_res.raw_get(computed_key) == value: + # there's already a resource of this name, with the exact + # same value + return computed_key, True + computed_key = f"{base_key}-{idx}" + idx += 1 + return computed_key, False + + if new_res1: + new_res = DictionaryObject() + new_res.update(res1.get(resource, DictionaryObject()).get_object()) + else: + new_res = cast(DictionaryObject, res1[resource]) + page2res = cast( + DictionaryObject, res2.get(resource, DictionaryObject()).get_object() + ) + rename_res = {} + for key in page2res: + unique_key, same_value = compute_unique_key(key) + newname = NameObject(unique_key) + if key != unique_key: + # we have to use a different name for this + rename_res[key] = newname + + if not same_value: + if is_pdf_writer: + new_res[newname] = page2res.raw_get(key).clone(pdf) + try: + new_res[newname] = new_res[newname].indirect_reference + except AttributeError: + pass + else: + new_res[newname] = page2res.raw_get(key) + lst = sorted(new_res.items()) + new_res.clear() + for el in lst: + new_res[el[0]] = el[1] + return new_res, rename_res + + @staticmethod + def _content_stream_rename( + stream: ContentStream, + rename: Dict[Any, Any], + pdf: Optional[PdfCommonDocProtocol], + ) -> ContentStream: + if not rename: + return stream + stream = ContentStream(stream, pdf) + for operands, _operator in stream.operations: + if isinstance(operands, list): + for i, op in enumerate(operands): + if isinstance(op, NameObject): + operands[i] = rename.get(op, op) + elif isinstance(operands, dict): + for i, op in operands.items(): + if isinstance(op, NameObject): + operands[i] = rename.get(op, op) + else: + raise KeyError(f"Type of operands is {type(operands)}") + return stream + + @staticmethod + def _add_transformation_matrix( + contents: Any, + pdf: Optional[PdfCommonDocProtocol], + ctm: CompressedTransformationMatrix, + ) -> ContentStream: + """Add transformation matrix at the beginning of the given contents stream.""" + contents = ContentStream(contents, pdf) + contents.operations.insert( + 0, + [ + [FloatObject(x) for x in ctm], + b"cm", + ], + ) + return contents + + def _get_contents_as_bytes(self) -> Optional[bytes]: + """ + Return the page contents as bytes. + + Returns: + The ``/Contents`` object as bytes, or ``None`` if it doesn't exist. + + """ + if PG.CONTENTS in self: + obj = self[PG.CONTENTS].get_object() + if isinstance(obj, list): + return b"".join(x.get_object().get_data() for x in obj) + else: + return cast(EncodedStreamObject, obj).get_data() + else: + return None + + def get_contents(self) -> Optional[ContentStream]: + """ + Access the page contents. + + Returns: + The ``/Contents`` object, or ``None`` if it does not exist. + ``/Contents`` is optional, as described in §7.7.3.3 of the PDF Reference. + + """ + if PG.CONTENTS in self: + try: + pdf = cast(IndirectObject, self.indirect_reference).pdf + except AttributeError: + pdf = None + obj = self[PG.CONTENTS].get_object() + if isinstance(obj, NullObject): + return None + else: + return ContentStream(obj, pdf) + else: + return None + + def replace_contents( + self, content: Union[None, ContentStream, EncodedStreamObject, ArrayObject] + ) -> None: + """ + Replace the page contents with the new content and nullify old objects + Args: + content: new content; if None delete the content field. + """ + if not hasattr(self, "indirect_reference") or self.indirect_reference is None: + # the page is not attached : the content is directly attached. + self[NameObject(PG.CONTENTS)] = content + return + if isinstance(self.get(PG.CONTENTS, None), ArrayObject): + for o in self[PG.CONTENTS]: # type: ignore[attr-defined] + try: + self._objects[o.indirect_reference.idnum - 1] = NullObject() # type: ignore + except AttributeError: + pass + + if isinstance(content, ArrayObject): + for i in range(len(content)): + content[i] = self.indirect_reference.pdf._add_object(content[i]) + + if is_null_or_none(content): + if PG.CONTENTS not in self: + return + else: + assert self.indirect_reference is not None + assert self[PG.CONTENTS].indirect_reference is not None + self.indirect_reference.pdf._objects[ + self[PG.CONTENTS].indirect_reference.idnum - 1 # type: ignore + ] = NullObject() + del self[PG.CONTENTS] + elif not hasattr(self.get(PG.CONTENTS, None), "indirect_reference"): + try: + self[NameObject(PG.CONTENTS)] = self.indirect_reference.pdf._add_object( + content + ) + except AttributeError: + # applies at least for page not in writer + # as a backup solution, we put content as an object although not in accordance with pdf ref + # this will be fixed with the _add_object + self[NameObject(PG.CONTENTS)] = content + else: + assert content is not None, "mypy" + content.indirect_reference = self[ + PG.CONTENTS + ].indirect_reference # TODO: in a future may required generation management + try: + self.indirect_reference.pdf._objects[ + content.indirect_reference.idnum - 1 # type: ignore + ] = content + except AttributeError: + # applies at least for page not in writer + # as a backup solution, we put content as an object although not in accordance with pdf ref + # this will be fixed with the _add_object + self[NameObject(PG.CONTENTS)] = content + # forces recalculation of inline_images + self.inline_images = None + + def merge_page( + self, page2: "PageObject", expand: bool = False, over: bool = True + ) -> None: + """ + Merge the content streams of two pages into one. + + Resource references + (i.e. fonts) are maintained from both pages. The mediabox/cropbox/etc + of this page are not altered. The parameter page's content stream will + be added to the end of this page's content stream, meaning that it will + be drawn after, or "on top" of this page. + + Args: + page2: The page to be merged into this one. Should be + an instance of :class:`PageObject`. + over: set the page2 content over page1 if True (default) else under + expand: If True, the current page dimensions will be + expanded to accommodate the dimensions of the page to be merged. + + """ + self._merge_page(page2, over=over, expand=expand) + + def _merge_page( + self, + page2: "PageObject", + page2transformation: Optional[Callable[[Any], ContentStream]] = None, + ctm: Optional[CompressedTransformationMatrix] = None, + over: bool = True, + expand: bool = False, + ) -> None: + # First we work on merging the resource dictionaries. This allows us + # to find out what symbols in the content streams we might need to + # rename. + try: + assert isinstance(self.indirect_reference, IndirectObject) + if hasattr( + self.indirect_reference.pdf, "_add_object" + ): # ---------- to detect PdfWriter + return self._merge_page_writer( + page2, page2transformation, ctm, over, expand + ) + except (AssertionError, AttributeError): + pass + + new_resources = DictionaryObject() + rename = {} + try: + original_resources = cast(DictionaryObject, self[PG.RESOURCES].get_object()) + except KeyError: + original_resources = DictionaryObject() + try: + page2resources = cast(DictionaryObject, page2[PG.RESOURCES].get_object()) + except KeyError: + page2resources = DictionaryObject() + new_annots = ArrayObject() + + for page in (self, page2): + if PG.ANNOTS in page: + annots = page[PG.ANNOTS] + if isinstance(annots, ArrayObject): + new_annots.extend(annots) + + for res in ( + RES.EXT_G_STATE, + RES.FONT, + RES.XOBJECT, + RES.COLOR_SPACE, + RES.PATTERN, + RES.SHADING, + RES.PROPERTIES, + ): + new, newrename = self._merge_resources( + original_resources, page2resources, res + ) + if new: + new_resources[NameObject(res)] = new + rename.update(newrename) + + # Combine /ProcSet sets, making sure there's a consistent order + new_resources[NameObject(RES.PROC_SET)] = ArrayObject( + sorted( + set( + original_resources.get(RES.PROC_SET, ArrayObject()).get_object() + ).union( + set(page2resources.get(RES.PROC_SET, ArrayObject()).get_object()) + ) + ) + ) + + new_content_array = ArrayObject() + original_content = self.get_contents() + if original_content is not None: + original_content.isolate_graphics_state() + new_content_array.append(original_content) + + page2content = page2.get_contents() + if page2content is not None: + rect = getattr(page2, MERGE_CROP_BOX) + page2content.operations.insert( + 0, + ( + map( + FloatObject, + [ + rect.left, + rect.bottom, + rect.width, + rect.height, + ], + ), + b"re", + ), + ) + page2content.operations.insert(1, ([], b"W")) + page2content.operations.insert(2, ([], b"n")) + if page2transformation is not None: + page2content = page2transformation(page2content) + page2content = PageObject._content_stream_rename( + page2content, rename, self.pdf + ) + page2content.isolate_graphics_state() + if over: + new_content_array.append(page2content) + else: + new_content_array.insert(0, page2content) + + # if expanding the page to fit a new page, calculate the new media box size + if expand: + self._expand_mediabox(page2, ctm) + + self.replace_contents(ContentStream(new_content_array, self.pdf)) + self[NameObject(PG.RESOURCES)] = new_resources + self[NameObject(PG.ANNOTS)] = new_annots + + def _merge_page_writer( + self, + page2: "PageObject", + page2transformation: Optional[Callable[[Any], ContentStream]] = None, + ctm: Optional[CompressedTransformationMatrix] = None, + over: bool = True, + expand: bool = False, + ) -> None: + # First we work on merging the resource dictionaries. This allows us + # to find which symbols in the content streams we might need to + # rename. + assert isinstance(self.indirect_reference, IndirectObject) + pdf = self.indirect_reference.pdf + + rename = {} + if PG.RESOURCES not in self: + self[NameObject(PG.RESOURCES)] = DictionaryObject() + original_resources = cast(DictionaryObject, self[PG.RESOURCES].get_object()) + if PG.RESOURCES not in page2: + page2resources = DictionaryObject() + else: + page2resources = cast(DictionaryObject, page2[PG.RESOURCES].get_object()) + + for res in ( + RES.EXT_G_STATE, + RES.FONT, + RES.XOBJECT, + RES.COLOR_SPACE, + RES.PATTERN, + RES.SHADING, + RES.PROPERTIES, + ): + if res in page2resources: + if res not in original_resources: + original_resources[NameObject(res)] = DictionaryObject() + _, newrename = self._merge_resources( + original_resources, page2resources, res, False + ) + rename.update(newrename) + # Combine /ProcSet sets. + if RES.PROC_SET in page2resources: + if RES.PROC_SET not in original_resources: + original_resources[NameObject(RES.PROC_SET)] = ArrayObject() + arr = cast(ArrayObject, original_resources[RES.PROC_SET]) + for x in cast(ArrayObject, page2resources[RES.PROC_SET]): + if x not in arr: + arr.append(x) + arr.sort() + + if PG.ANNOTS in page2: + if PG.ANNOTS not in self: + self[NameObject(PG.ANNOTS)] = ArrayObject() + annots = cast(ArrayObject, self[PG.ANNOTS].get_object()) + if ctm is None: + trsf = Transformation() + else: + trsf = Transformation(ctm) + for a in cast(ArrayObject, page2[PG.ANNOTS]): + a = a.get_object() + aa = a.clone( + pdf, + ignore_fields=("/P", "/StructParent", "/Parent"), + force_duplicate=True, + ) + r = cast(ArrayObject, a["/Rect"]) + pt1 = trsf.apply_on((r[0], r[1]), True) + pt2 = trsf.apply_on((r[2], r[3]), True) + aa[NameObject("/Rect")] = ArrayObject( + ( + min(pt1[0], pt2[0]), + min(pt1[1], pt2[1]), + max(pt1[0], pt2[0]), + max(pt1[1], pt2[1]), + ) + ) + if "/QuadPoints" in a: + q = cast(ArrayObject, a["/QuadPoints"]) + aa[NameObject("/QuadPoints")] = ArrayObject( + trsf.apply_on((q[0], q[1]), True) + + trsf.apply_on((q[2], q[3]), True) + + trsf.apply_on((q[4], q[5]), True) + + trsf.apply_on((q[6], q[7]), True) + ) + try: + aa["/Popup"][NameObject("/Parent")] = aa.indirect_reference + except KeyError: + pass + try: + aa[NameObject("/P")] = self.indirect_reference + annots.append(aa.indirect_reference) + except AttributeError: + pass + + new_content_array = ArrayObject() + original_content = self.get_contents() + if original_content is not None: + original_content.isolate_graphics_state() + new_content_array.append(original_content) + + page2content = page2.get_contents() + if page2content is not None: + rect = getattr(page2, MERGE_CROP_BOX) + page2content.operations.insert( + 0, + ( + map( + FloatObject, + [ + rect.left, + rect.bottom, + rect.width, + rect.height, + ], + ), + b"re", + ), + ) + page2content.operations.insert(1, ([], b"W")) + page2content.operations.insert(2, ([], b"n")) + if page2transformation is not None: + page2content = page2transformation(page2content) + page2content = PageObject._content_stream_rename( + page2content, rename, self.pdf + ) + page2content.isolate_graphics_state() + if over: + new_content_array.append(page2content) + else: + new_content_array.insert(0, page2content) + + # if expanding the page to fit a new page, calculate the new media box size + if expand: + self._expand_mediabox(page2, ctm) + + self.replace_contents(new_content_array) + # self[NameObject(PG.CONTENTS)] = ContentStream(new_content_array, pdf) + # self[NameObject(PG.RESOURCES)] = new_resources + # self[NameObject(PG.ANNOTS)] = new_annots + + def _expand_mediabox( + self, page2: "PageObject", ctm: Optional[CompressedTransformationMatrix] + ) -> None: + corners1 = ( + self.mediabox.left.as_numeric(), + self.mediabox.bottom.as_numeric(), + self.mediabox.right.as_numeric(), + self.mediabox.top.as_numeric(), + ) + corners2 = ( + page2.mediabox.left.as_numeric(), + page2.mediabox.bottom.as_numeric(), + page2.mediabox.left.as_numeric(), + page2.mediabox.top.as_numeric(), + page2.mediabox.right.as_numeric(), + page2.mediabox.top.as_numeric(), + page2.mediabox.right.as_numeric(), + page2.mediabox.bottom.as_numeric(), + ) + if ctm is not None: + ctm = tuple(float(x) for x in ctm) # type: ignore[assignment] + new_x = tuple( + ctm[0] * corners2[i] + ctm[2] * corners2[i + 1] + ctm[4] + for i in range(0, 8, 2) + ) + new_y = tuple( + ctm[1] * corners2[i] + ctm[3] * corners2[i + 1] + ctm[5] + for i in range(0, 8, 2) + ) + else: + new_x = corners2[0:8:2] + new_y = corners2[1:8:2] + lowerleft = (min(new_x), min(new_y)) + upperright = (max(new_x), max(new_y)) + lowerleft = (min(corners1[0], lowerleft[0]), min(corners1[1], lowerleft[1])) + upperright = ( + max(corners1[2], upperright[0]), + max(corners1[3], upperright[1]), + ) + + self.mediabox.lower_left = lowerleft + self.mediabox.upper_right = upperright + + def merge_transformed_page( + self, + page2: "PageObject", + ctm: Union[CompressedTransformationMatrix, Transformation], + over: bool = True, + expand: bool = False, + ) -> None: + """ + Similar to :meth:`~pypdf._page.PageObject.merge_page`, but a transformation + matrix is applied to the merged stream. + + Args: + page2: The page to be merged into this one. + ctm: a 6-element tuple containing the operands of the + transformation matrix + over: set the page2 content over page1 if True (default) else under + expand: Whether the page should be expanded to fit the dimensions + of the page to be merged. + + """ + if isinstance(ctm, Transformation): + ctm = ctm.ctm + self._merge_page( + page2, + lambda page2Content: PageObject._add_transformation_matrix( + page2Content, page2.pdf, cast(CompressedTransformationMatrix, ctm) + ), + ctm, + over, + expand, + ) + + def merge_scaled_page( + self, page2: "PageObject", scale: float, over: bool = True, expand: bool = False + ) -> None: + """ + Similar to :meth:`~pypdf._page.PageObject.merge_page`, but the stream to be merged + is scaled by applying a transformation matrix. + + Args: + page2: The page to be merged into this one. + scale: The scaling factor + over: set the page2 content over page1 if True (default) else under + expand: Whether the page should be expanded to fit the + dimensions of the page to be merged. + + """ + op = Transformation().scale(scale, scale) + self.merge_transformed_page(page2, op, over, expand) + + def merge_rotated_page( + self, + page2: "PageObject", + rotation: float, + over: bool = True, + expand: bool = False, + ) -> None: + """ + Similar to :meth:`~pypdf._page.PageObject.merge_page`, but the stream to be merged + is rotated by applying a transformation matrix. + + Args: + page2: The page to be merged into this one. + rotation: The angle of the rotation, in degrees + over: set the page2 content over page1 if True (default) else under + expand: Whether the page should be expanded to fit the + dimensions of the page to be merged. + + """ + op = Transformation().rotate(rotation) + self.merge_transformed_page(page2, op, over, expand) + + def merge_translated_page( + self, + page2: "PageObject", + tx: float, + ty: float, + over: bool = True, + expand: bool = False, + ) -> None: + """ + Similar to :meth:`~pypdf._page.PageObject.merge_page`, but the stream to be + merged is translated by applying a transformation matrix. + + Args: + page2: the page to be merged into this one. + tx: The translation on X axis + ty: The translation on Y axis + over: set the page2 content over page1 if True (default) else under + expand: Whether the page should be expanded to fit the + dimensions of the page to be merged. + + """ + op = Transformation().translate(tx, ty) + self.merge_transformed_page(page2, op, over, expand) + + def add_transformation( + self, + ctm: Union[Transformation, CompressedTransformationMatrix], + expand: bool = False, + ) -> None: + """ + Apply a transformation matrix to the page. + + Args: + ctm: A 6-element tuple containing the operands of the + transformation matrix. Alternatively, a + :py:class:`Transformation` + object can be passed. + + See :doc:`/user/cropping-and-transforming`. + + """ + if isinstance(ctm, Transformation): + ctm = ctm.ctm + content = self.get_contents() + if content is not None: + content = PageObject._add_transformation_matrix(content, self.pdf, ctm) + content.isolate_graphics_state() + self.replace_contents(content) + # if expanding the page to fit a new page, calculate the new media box size + if expand: + corners = [ + self.mediabox.left.as_numeric(), + self.mediabox.bottom.as_numeric(), + self.mediabox.left.as_numeric(), + self.mediabox.top.as_numeric(), + self.mediabox.right.as_numeric(), + self.mediabox.top.as_numeric(), + self.mediabox.right.as_numeric(), + self.mediabox.bottom.as_numeric(), + ] + + ctm = tuple(float(x) for x in ctm) # type: ignore[assignment] + new_x = [ + ctm[0] * corners[i] + ctm[2] * corners[i + 1] + ctm[4] + for i in range(0, 8, 2) + ] + new_y = [ + ctm[1] * corners[i] + ctm[3] * corners[i + 1] + ctm[5] + for i in range(0, 8, 2) + ] + + lowerleft = (min(new_x), min(new_y)) + upperright = (max(new_x), max(new_y)) + + self.mediabox.lower_left = lowerleft + self.mediabox.upper_right = upperright + + def scale(self, sx: float, sy: float) -> None: + """ + Scale a page by the given factors by applying a transformation matrix + to its content and updating the page size. + + This updates the mediabox, the cropbox, and the contents + of the page. + + Args: + sx: The scaling factor on horizontal axis. + sy: The scaling factor on vertical axis. + + """ + self.add_transformation((sx, 0, 0, sy, 0, 0)) + self.cropbox = self.cropbox.scale(sx, sy) + self.artbox = self.artbox.scale(sx, sy) + self.bleedbox = self.bleedbox.scale(sx, sy) + self.trimbox = self.trimbox.scale(sx, sy) + self.mediabox = self.mediabox.scale(sx, sy) + + if PG.ANNOTS in self: + annotations = self[PG.ANNOTS] + if isinstance(annotations, ArrayObject): + for annotation in annotations: + annotation_obj = annotation.get_object() + if ADA.Rect in annotation_obj: + rectangle = annotation_obj[ADA.Rect] + if isinstance(rectangle, ArrayObject): + rectangle[0] = FloatObject(float(rectangle[0]) * sx) + rectangle[1] = FloatObject(float(rectangle[1]) * sy) + rectangle[2] = FloatObject(float(rectangle[2]) * sx) + rectangle[3] = FloatObject(float(rectangle[3]) * sy) + + if PG.VP in self: + viewport = self[PG.VP] + if isinstance(viewport, ArrayObject): + bbox = viewport[0]["/BBox"] + else: + bbox = viewport["/BBox"] # type: ignore + scaled_bbox = RectangleObject( + ( + float(bbox[0]) * sx, + float(bbox[1]) * sy, + float(bbox[2]) * sx, + float(bbox[3]) * sy, + ) + ) + if isinstance(viewport, ArrayObject): + self[NameObject(PG.VP)][NumberObject(0)][ # type: ignore + NameObject("/BBox") + ] = scaled_bbox + else: + self[NameObject(PG.VP)][NameObject("/BBox")] = scaled_bbox # type: ignore + + def scale_by(self, factor: float) -> None: + """ + Scale a page by the given factor by applying a transformation matrix to + its content and updating the page size. + + Args: + factor: The scaling factor (for both X and Y axis). + + """ + self.scale(factor, factor) + + def scale_to(self, width: float, height: float) -> None: + """ + Scale a page to the specified dimensions by applying a transformation + matrix to its content and updating the page size. + + Args: + width: The new width. + height: The new height. + + """ + sx = width / float(self.mediabox.width) + sy = height / float(self.mediabox.height) + self.scale(sx, sy) + + def compress_content_streams(self, level: int = -1) -> None: + """ + Compress the size of this page by joining all content streams and + applying a FlateDecode filter. + + However, it is possible that this function will perform no action if + content stream compression becomes "automatic". + """ + content = self.get_contents() + if content is not None: + content_obj = content.flate_encode(level) + try: + content.indirect_reference.pdf._objects[ # type: ignore + content.indirect_reference.idnum - 1 # type: ignore + ] = content_obj + except AttributeError: + if self.indirect_reference is not None and hasattr( + self.indirect_reference.pdf, "_add_object" + ): + self.replace_contents(content_obj) + else: + raise ValueError("Page must be part of a PdfWriter") + + @property + def page_number(self) -> Optional[int]: + """ + Read-only property which returns the page number within the PDF file. + + Returns: + int : page number; None if the page is not attached to a PDF. + + """ + if self.indirect_reference is None: + return None + else: + try: + lst = self.indirect_reference.pdf.pages + return lst.index(self) + except ValueError: + return None + + def _debug_for_extract(self) -> str: # pragma: no cover + out = "" + for ope, op in ContentStream( + self["/Contents"].get_object(), self.pdf, "bytes" + ).operations: + if op == b"TJ": + s = [x for x in ope[0] if isinstance(x, str)] + else: + s = [] + out += op.decode("utf-8") + " " + "".join(s) + ope.__repr__() + "\n" + out += "\n=============================\n" + try: + for fo in self[PG.RESOURCES]["/Font"]: # type:ignore + out += fo + "\n" + out += self[PG.RESOURCES]["/Font"][fo].__repr__() + "\n" # type:ignore + try: + enc_repr = self[PG.RESOURCES]["/Font"][fo][ # type:ignore + "/Encoding" + ].__repr__() + out += enc_repr + "\n" + except Exception: + pass + try: + out += ( + self[PG.RESOURCES]["/Font"][fo][ # type:ignore + "/ToUnicode" + ] + .get_data() + .decode() + + "\n" + ) + except Exception: + pass + + except KeyError: + out += "No Font\n" + return out + + def _get_actual_font_widths( + self, + cmap: Tuple[ + Union[str, Dict[int, str]], Dict[str, str], str, Optional[DictionaryObject] + ], + text_operands: str, + font_size: float, + space_width: float + ) -> Tuple[float, float, float]: + font_widths: float = 0 + font_name: str = cmap[2] + if font_name not in self._font_width_maps: + if cmap[3] is None: + font_width_map: Dict[Any, float] = {} + space_char = " " + actual_space_width: float = space_width + font_width_map["default"] = actual_space_width * 2 + else: + space_char = get_actual_str_key(" ", cmap[0], cmap[1]) + font_width_map = build_font_width_map(cmap[3], space_width * 2) + actual_space_width = compute_font_width(font_width_map, space_char) + if actual_space_width == 0: + actual_space_width = space_width + self._font_width_maps[font_name] = (font_width_map, space_char, actual_space_width) + font_width_map = self._font_width_maps[font_name][0] + space_char = self._font_width_maps[font_name][1] + actual_space_width = self._font_width_maps[font_name][2] + + if text_operands: + for char in text_operands: + if char == space_char: + font_widths += actual_space_width + continue + font_widths += compute_font_width(font_width_map, char) + return (font_widths * font_size, space_width * font_size, font_size) + + def _handle_tj( + self, + text: str, + operands: List[Union[str, TextStringObject]], + cm_matrix: List[float], + tm_matrix: List[float], + cmap: Tuple[ + Union[str, Dict[int, str]], Dict[str, str], str, Optional[DictionaryObject] + ], + orientations: Tuple[int, ...], + font_size: float, + rtl_dir: bool, + visitor_text: Optional[Callable[[Any, Any, Any, Any, Any], None]], + space_width: float, + actual_str_size: Dict[str, float] + ) -> Tuple[str, bool, Dict[str, float]]: + text_operands, is_str_operands = get_text_operands( + operands, cm_matrix, tm_matrix, cmap, orientations) + if is_str_operands: + text += text_operands + else: + text, rtl_dir = get_display_str( + text, + cm_matrix, + tm_matrix, # text matrix + cmap, + text_operands, + font_size, + rtl_dir, + visitor_text) + font_widths, actual_str_size["space_width"], actual_str_size["str_height"] = ( + self._get_actual_font_widths(cmap, text_operands, font_size, space_width)) + actual_str_size["str_widths"] += font_widths + + return text, rtl_dir, actual_str_size + + def _extract_text( + self, + obj: Any, + pdf: Any, + orientations: Tuple[int, ...] = (0, 90, 180, 270), + space_width: float = 200.0, + content_key: Optional[str] = PG.CONTENTS, + visitor_operand_before: Optional[Callable[[Any, Any, Any, Any], None]] = None, + visitor_operand_after: Optional[Callable[[Any, Any, Any, Any], None]] = None, + visitor_text: Optional[Callable[[Any, Any, Any, Any, Any], None]] = None, + ) -> str: + """ + See extract_text for most arguments. + + Args: + content_key: indicate the default key where to extract data + None = the object; this allows reusing the function on an XObject + default = "/Content" + + """ + text: str = "" + output: str = "" + rtl_dir: bool = False # right-to-left + cmaps: Dict[ + str, + Tuple[ + str, float, Union[str, Dict[int, str]], Dict[str, str], DictionaryObject + ], + ] = {} + + try: + objr = obj + while NameObject(PG.RESOURCES) not in objr: + # /Resources can be inherited sometimes so we look to parents + objr = objr["/Parent"].get_object() + # If no parents then no /Resources will be available, + # so an exception will be raised + resources_dict = cast(DictionaryObject, objr[PG.RESOURCES]) + except Exception: + # No resources means no text is possible (no font); we consider the + # file as not damaged, no need to check for TJ or Tj + return "" + + if "/Font" in resources_dict: + for f in cast(DictionaryObject, resources_dict["/Font"]): + cmaps[f] = build_char_map(f, space_width, obj) + cmap: Tuple[ + Union[str, Dict[int, str]], Dict[str, str], str, Optional[DictionaryObject] + ] = ( + "charmap", + {}, + "NotInitialized", + None, + ) # (encoding, CMAP, font resource name, font) + + try: + content = ( + obj[content_key].get_object() if isinstance(content_key, str) else obj + ) + if not isinstance(content, ContentStream): + content = ContentStream(content, pdf, "bytes") + except KeyError: # no content can be extracted (certainly empty page) + return "" + # We check all strings are TextStringObjects. ByteStringObjects + # are strings where the byte->string encoding was unknown, so adding + # them to the text here would be gibberish. + + cm_matrix: List[float] = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] + tm_matrix: List[float] = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] + cm_stack = [] + + # Store the last modified matrices; can be an intermediate position + cm_prev: List[float] = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] + tm_prev: List[float] = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] + + # Store the position at the beginning of building the text + memo_cm: List[float] = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] + memo_tm: List[float] = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] + + char_scale = 1.0 + space_scale = 1.0 + _space_width: float = 500.0 # will be set correctly at first Tf + _actual_str_size: Dict[str, float] = { + "str_widths": 0.0, "space_width": 0.0, "str_height": 0.0 + } # will be set to string length calculation result + TL = 0.0 + font_size = 12.0 # init just in case of + + def compute_str_widths(str_widths: float) -> float: + return str_widths / 1000 + + def process_operation(operator: bytes, operands: List[Any]) -> None: + nonlocal cm_matrix, tm_matrix, cm_stack, cm_prev, tm_prev, memo_cm, memo_tm + nonlocal char_scale, space_scale, _space_width, TL, font_size, cmap + nonlocal orientations, rtl_dir, visitor_text, output, text, _actual_str_size + + check_crlf_space: bool = False + str_widths: float = 0.0 + # Table 5.4 page 405 + if operator == b"BT": + tm_matrix = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] + output += text + if visitor_text is not None: + visitor_text(text, memo_cm, memo_tm, cmap[3], font_size) + text = "" + memo_cm = cm_matrix.copy() + memo_tm = tm_matrix.copy() + return None + if operator == b"ET": + output += text + if visitor_text is not None: + visitor_text(text, memo_cm, memo_tm, cmap[3], font_size) + text = "" + memo_cm = cm_matrix.copy() + memo_tm = tm_matrix.copy() + # Table 4.7 "Graphics state operators", page 219 + # cm_matrix calculation is reserved for later + elif operator == b"q": + cm_stack.append( + ( + cm_matrix, + cmap, + font_size, + char_scale, + space_scale, + _space_width, + TL, + ) + ) + elif operator == b"Q": + try: + ( + cm_matrix, + cmap, + font_size, + char_scale, + space_scale, + _space_width, + TL, + ) = cm_stack.pop() + except Exception: + cm_matrix = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] + elif operator == b"cm": + output += text + if visitor_text is not None: + visitor_text(text, memo_cm, memo_tm, cmap[3], font_size) + text = "" + cm_matrix = mult( + [float(operand) for operand in operands[:6]], + cm_matrix + ) + memo_cm = cm_matrix.copy() + memo_tm = tm_matrix.copy() + # Table 5.2 page 398 + elif operator == b"Tz": + char_scale = float(operands[0]) / 100 if operands else 1.0 + elif operator == b"Tw": + space_scale = 1.0 + float(operands[0] if operands else 0.0) + elif operator == b"TL": + scale_x = math.sqrt(tm_matrix[0]**2 + tm_matrix[2]**2) + TL = float(operands[0] if operands else 0.0) * font_size * scale_x + elif operator == b"Tf": + if text != "": + output += text # .translate(cmap) + if visitor_text is not None: + visitor_text(text, memo_cm, memo_tm, cmap[3], font_size) + text = "" + memo_cm = cm_matrix.copy() + memo_tm = tm_matrix.copy() + try: + # char_map_tuple: font_type, + # float(sp_width / 2), + # encoding, + # map_dict, + # font_dict (describes the font) + char_map_tuple = cmaps[operands[0]] + # current cmap: encoding, + # map_dict, + # font resource name (internal name, not the real font name), + # font_dict + cmap = ( + char_map_tuple[2], + char_map_tuple[3], + operands[0], + char_map_tuple[4], + ) + _space_width = char_map_tuple[1] + except KeyError: # font not found + cmap = ( + unknown_char_map[2], + unknown_char_map[3], + f"???{operands[0]}", + None, + ) + _space_width = unknown_char_map[1] + try: + font_size = float(operands[1]) + except Exception: + pass # keep previous size + # Table 5.5 page 406 + elif operator == b"Td": + check_crlf_space = True + # A special case is a translating only tm: + # tm = [1, 0, 0, 1, e, f] + # i.e. tm[4] += tx, tm[5] += ty. + tx = float(operands[0]) + ty = float(operands[1]) + tm_matrix[4] += tx * tm_matrix[0] + ty * tm_matrix[2] + tm_matrix[5] += tx * tm_matrix[1] + ty * tm_matrix[3] + str_widths = compute_str_widths(_actual_str_size["str_widths"]) + _actual_str_size["str_widths"] = 0.0 + elif operator == b"Tm": + check_crlf_space = True + tm_matrix = [float(operand) for operand in operands[:6]] + str_widths = compute_str_widths(_actual_str_size["str_widths"]) + _actual_str_size["str_widths"] = 0.0 + elif operator == b"T*": + check_crlf_space = True + tm_matrix[5] -= TL + elif operator == b"Tj": + check_crlf_space = True + text, rtl_dir, _actual_str_size = self._handle_tj( + text, + operands, + cm_matrix, + tm_matrix, + cmap, + orientations, + font_size, + rtl_dir, + visitor_text, + _space_width, + _actual_str_size, + ) + else: + return None + + if check_crlf_space: + try: + text, output, cm_prev, tm_prev = crlf_space_check( + text, + (cm_prev, tm_prev), + (cm_matrix, tm_matrix), + (memo_cm, memo_tm), + cmap, + orientations, + output, + font_size, + visitor_text, + str_widths, + compute_str_widths(_actual_str_size["space_width"]), + _actual_str_size["str_height"] + ) + if text == "": + memo_cm = cm_matrix.copy() + memo_tm = tm_matrix.copy() + except OrientationNotFoundError: + return None + + for operands, operator in content.operations: + if visitor_operand_before is not None: + visitor_operand_before(operator, operands, cm_matrix, tm_matrix) + # Multiple operators are handled here + if operator == b"'": + process_operation(b"T*", []) + process_operation(b"Tj", operands) + elif operator == b'"': + process_operation(b"Tw", [operands[0]]) + process_operation(b"Tc", [operands[1]]) + process_operation(b"T*", []) + process_operation(b"Tj", operands[2:]) + elif operator == b"TJ": + # The space width may be smaller than the font width, so the width should be 95%. + _confirm_space_width = _space_width * 0.95 + if operands: + for op in operands[0]: + if isinstance(op, (str, bytes)): + process_operation(b"Tj", [op]) + if isinstance(op, (int, float, NumberObject, FloatObject)) and ( + abs(float(op)) >= _confirm_space_width + and text + and text[-1] != " " + ): + process_operation(b"Tj", [" "]) + elif operator == b"TD": + process_operation(b"TL", [-operands[1]]) + process_operation(b"Td", operands) + elif operator == b"Do": + output += text + if visitor_text is not None: + visitor_text(text, memo_cm, memo_tm, cmap[3], font_size) + try: + if output[-1] != "\n": + output += "\n" + if visitor_text is not None: + visitor_text( + "\n", + memo_cm, + memo_tm, + cmap[3], + font_size, + ) + except IndexError: + pass + try: + xobj = resources_dict["/XObject"] + if xobj[operands[0]]["/Subtype"] != "/Image": # type: ignore + text = self.extract_xform_text( + xobj[operands[0]], # type: ignore + orientations, + space_width, + visitor_operand_before, + visitor_operand_after, + visitor_text, + ) + output += text + if visitor_text is not None: + visitor_text( + text, + memo_cm, + memo_tm, + cmap[3], + font_size, + ) + except Exception as exception: + logger_warning( + f"Impossible to decode XFormObject {operands[0]}: {exception}", + __name__, + ) + finally: + text = "" + memo_cm = cm_matrix.copy() + memo_tm = tm_matrix.copy() + else: + process_operation(operator, operands) + if visitor_operand_after is not None: + visitor_operand_after(operator, operands, cm_matrix, tm_matrix) + output += text # just in case + if text != "" and visitor_text is not None: + visitor_text(text, memo_cm, memo_tm, cmap[3], font_size) + return output + + def _layout_mode_fonts(self) -> Dict[str, _layout_mode.Font]: + """ + Get fonts formatted for "layout" mode text extraction. + + Returns: + Dict[str, Font]: dictionary of _layout_mode.Font instances keyed by font name + + """ + # Font retrieval logic adapted from pypdf.PageObject._extract_text() + objr: Any = self + fonts: Dict[str, _layout_mode.Font] = {} + while objr is not None: + try: + resources_dict: Any = objr[PG.RESOURCES] + except KeyError: + resources_dict = {} + if "/Font" in resources_dict and self.pdf is not None: + for font_name in resources_dict["/Font"]: + *cmap, font_dict_obj = build_char_map(font_name, 200.0, self) + font_dict = { + k: v.get_object() + if isinstance(v, IndirectObject) + else [_v.get_object() for _v in v] + if isinstance(v, ArrayObject) + else v + for k, v in font_dict_obj.items() + } + # mypy really sucks at unpacking + fonts[font_name] = _layout_mode.Font(*cmap, font_dict) # type: ignore[call-arg,arg-type] + try: + objr = objr["/Parent"].get_object() + except KeyError: + objr = None + + return fonts + + def _layout_mode_text( + self, + space_vertically: bool = True, + scale_weight: float = 1.25, + strip_rotated: bool = True, + debug_path: Optional[Path] = None, + font_height_weight: float = 1, + ) -> str: + """ + Get text preserving fidelity to source PDF text layout. + + Args: + space_vertically: include blank lines inferred from y distance + font + height. Defaults to True. + scale_weight: multiplier for string length when calculating weighted + average character width. Defaults to 1.25. + strip_rotated: Removes text that is rotated w.r.t. to the page from + layout mode output. Defaults to True. + debug_path (Path | None): if supplied, must target a directory. + creates the following files with debug information for layout mode + functions if supplied: + - fonts.json: output of self._layout_mode_fonts + - tjs.json: individual text render ops with corresponding transform matrices + - bts.json: text render ops left justified and grouped by BT/ET operators + - bt_groups.json: BT/ET operations grouped by rendered y-coord (aka lines) + Defaults to None. + font_height_weight: multiplier for font height when calculating + blank lines. Defaults to 1. + + Returns: + str: multiline string containing page text in a fixed width format that + closely adheres to the rendered layout in the source pdf. + + """ + fonts = self._layout_mode_fonts() + if debug_path: # pragma: no cover + import json + + debug_path.joinpath("fonts.json").write_text( + json.dumps( + fonts, indent=2, default=lambda x: getattr(x, "to_dict", str)(x) + ), + "utf-8", + ) + + ops = iter( + ContentStream(self["/Contents"].get_object(), self.pdf, "bytes").operations + ) + bt_groups = _layout_mode.text_show_operations( + ops, fonts, strip_rotated, debug_path + ) + + if not bt_groups: + return "" + + ty_groups = _layout_mode.y_coordinate_groups(bt_groups, debug_path) + + char_width = _layout_mode.fixed_char_width(bt_groups, scale_weight) + + return _layout_mode.fixed_width_page(ty_groups, char_width, space_vertically, font_height_weight) + + def extract_text( + self, + *args: Any, + orientations: Union[int, Tuple[int, ...]] = (0, 90, 180, 270), + space_width: float = 200.0, + visitor_operand_before: Optional[Callable[[Any, Any, Any, Any], None]] = None, + visitor_operand_after: Optional[Callable[[Any, Any, Any, Any], None]] = None, + visitor_text: Optional[Callable[[Any, Any, Any, Any, Any], None]] = None, + extraction_mode: Literal["plain", "layout"] = "plain", + **kwargs: Any, + ) -> str: + """ + Locate all text drawing commands, in the order they are provided in the + content stream, and extract the text. + + This works well for some PDF files, but poorly for others, depending on + the generator used. This will be refined in the future. + + Do not rely on the order of text coming out of this function, as it + will change if this function is made more sophisticated. + + Arabic and Hebrew are extracted in the correct order. + If required a custom RTL range of characters can be defined; + see function set_custom_rtl. + + Additionally you can provide visitor methods to get informed on all + operations and all text objects. + For example in some PDF files this can be useful to parse tables. + + Args: + orientations: list of orientations extract_text will look for + default = (0, 90, 180, 270) + note: currently only 0 (up),90 (turned left), 180 (upside down), + 270 (turned right) + Silently ignored in "layout" mode. + space_width: force default space width + if not extracted from font (default: 200) + Silently ignored in "layout" mode. + visitor_operand_before: function to be called before processing an operation. + It has four arguments: operator, operand-arguments, + current transformation matrix and text matrix. + Ignored with a warning in "layout" mode. + visitor_operand_after: function to be called after processing an operation. + It has four arguments: operator, operand-arguments, + current transformation matrix and text matrix. + Ignored with a warning in "layout" mode. + visitor_text: function to be called when extracting some text at some position. + It has five arguments: text, current transformation matrix, + text matrix, font-dictionary and font-size. + The font-dictionary may be None in case of unknown fonts. + If not None it may e.g. contain key "/BaseFont" with value "/Arial,Bold". + Ignored with a warning in "layout" mode. + extraction_mode (Literal["plain", "layout"]): "plain" for legacy functionality, + "layout" for experimental layout mode functionality. + NOTE: orientations, space_width, and visitor_* parameters are NOT respected + in "layout" mode. + + kwargs: + layout_mode_space_vertically (bool): include blank lines inferred from + y distance + font height. Defaults to True. + layout_mode_scale_weight (float): multiplier for string length when calculating + weighted average character width. Defaults to 1.25. + layout_mode_strip_rotated (bool): layout mode does not support rotated text. + Set to False to include rotated text anyway. If rotated text is discovered, + layout will be degraded and a warning will result. Defaults to True. + layout_mode_debug_path (Path | None): if supplied, must target a directory. + creates the following files with debug information for layout mode + functions if supplied: + + - fonts.json: output of self._layout_mode_fonts + - tjs.json: individual text render ops with corresponding transform matrices + - bts.json: text render ops left justified and grouped by BT/ET operators + - bt_groups.json: BT/ET operations grouped by rendered y-coord (aka lines) + layout_mode_font_height_weight (float): multiplier for font height when calculating + blank lines. Defaults to 1. + + Returns: + The extracted text + + """ + if extraction_mode not in ["plain", "layout"]: + raise ValueError(f"Invalid text extraction mode '{extraction_mode}'") + if extraction_mode == "layout": + for visitor in ( + "visitor_operand_before", + "visitor_operand_after", + "visitor_text", + ): + if locals()[visitor]: + logger_warning( + f"Argument {visitor} is ignored in layout mode", + __name__, + ) + return self._layout_mode_text( + space_vertically=kwargs.get("layout_mode_space_vertically", True), + scale_weight=kwargs.get("layout_mode_scale_weight", 1.25), + strip_rotated=kwargs.get("layout_mode_strip_rotated", True), + debug_path=kwargs.get("layout_mode_debug_path"), + font_height_weight=kwargs.get("layout_mode_font_height_weight", 1) + ) + if len(args) >= 1: + if isinstance(args[0], str): + if len(args) >= 3: + if isinstance(args[2], (tuple, int)): + orientations = args[2] + else: + raise TypeError(f"Invalid positional parameter {args[2]}") + if len(args) >= 4: + if isinstance(args[3], (float, int)): + space_width = args[3] + else: + raise TypeError(f"Invalid positional parameter {args[3]}") + elif isinstance(args[0], (tuple, int)): + orientations = args[0] + if len(args) >= 2: + if isinstance(args[1], (float, int)): + space_width = args[1] + else: + raise TypeError(f"Invalid positional parameter {args[1]}") + else: + raise TypeError(f"Invalid positional parameter {args[0]}") + + if isinstance(orientations, int): + orientations = (orientations,) + + return self._extract_text( + self, + self.pdf, + orientations, + space_width, + PG.CONTENTS, + visitor_operand_before, + visitor_operand_after, + visitor_text, + ) + + def extract_xform_text( + self, + xform: EncodedStreamObject, + orientations: Tuple[int, ...] = (0, 90, 270, 360), + space_width: float = 200.0, + visitor_operand_before: Optional[Callable[[Any, Any, Any, Any], None]] = None, + visitor_operand_after: Optional[Callable[[Any, Any, Any, Any], None]] = None, + visitor_text: Optional[Callable[[Any, Any, Any, Any, Any], None]] = None, + ) -> str: + """ + Extract text from an XObject. + + Args: + xform: + orientations: + space_width: force default space width (if not extracted from font (default 200) + visitor_operand_before: + visitor_operand_after: + visitor_text: + + Returns: + The extracted text + + """ + return self._extract_text( + xform, + self.pdf, + orientations, + space_width, + None, + visitor_operand_before, + visitor_operand_after, + visitor_text, + ) + + def _get_fonts(self) -> Tuple[Set[str], Set[str]]: + """ + Get the names of embedded fonts and unembedded fonts. + + Returns: + A tuple (Set of embedded fonts, set of unembedded fonts) + + """ + obj = self.get_object() + assert isinstance(obj, DictionaryObject) + fonts: Set[str] = set() + embedded: Set[str] = set() + fonts, embedded = _get_fonts_walk(obj, fonts, embedded) + unembedded = fonts - embedded + return embedded, unembedded + + mediabox = _create_rectangle_accessor(PG.MEDIABOX, ()) + """A :class:`RectangleObject`, expressed in + default user space units, defining the boundaries of the physical medium on + which the page is intended to be displayed or printed.""" + + cropbox = _create_rectangle_accessor("/CropBox", (PG.MEDIABOX,)) + """ + A :class:`RectangleObject`, expressed in + default user space units, defining the visible region of default user + space. + + When the page is displayed or printed, its contents are to be clipped + (cropped) to this rectangle and then imposed on the output medium in some + implementation-defined manner. Default value: same as + :attr:`mediabox`. + """ + + bleedbox = _create_rectangle_accessor("/BleedBox", ("/CropBox", PG.MEDIABOX)) + """A :class:`RectangleObject`, expressed in + default user space units, defining the region to which the contents of the + page should be clipped when output in a production environment.""" + + trimbox = _create_rectangle_accessor("/TrimBox", ("/CropBox", PG.MEDIABOX)) + """A :class:`RectangleObject`, expressed in + default user space units, defining the intended dimensions of the finished + page after trimming.""" + + artbox = _create_rectangle_accessor("/ArtBox", ("/CropBox", PG.MEDIABOX)) + """A :class:`RectangleObject`, expressed in + default user space units, defining the extent of the page's meaningful + content as intended by the page's creator.""" + + @property + def annotations(self) -> Optional[ArrayObject]: + if "/Annots" not in self: + return None + else: + return cast(ArrayObject, self["/Annots"]) + + @annotations.setter + def annotations(self, value: Optional[ArrayObject]) -> None: + """ + Set the annotations array of the page. + + Typically you do not want to set this value, but append to it. + If you append to it, remember to add the object first to the writer + and only add the indirect object. + """ + if value is None: + del self[NameObject("/Annots")] + else: + self[NameObject("/Annots")] = value + + +class _VirtualList(Sequence[PageObject]): + def __init__( + self, + length_function: Callable[[], int], + get_function: Callable[[int], PageObject], + ) -> None: + self.length_function = length_function + self.get_function = get_function + self.current = -1 + + def __len__(self) -> int: + return self.length_function() + + @overload + def __getitem__(self, index: int) -> PageObject: + ... + + @overload + def __getitem__(self, index: slice) -> Sequence[PageObject]: + ... + + def __getitem__( + self, index: Union[int, slice] + ) -> Union[PageObject, Sequence[PageObject]]: + if isinstance(index, slice): + indices = range(*index.indices(len(self))) + cls = type(self) + return cls(indices.__len__, lambda idx: self[indices[idx]]) + if not isinstance(index, int): + raise TypeError("Sequence indices must be integers") + len_self = len(self) + if index < 0: + # support negative indexes + index = len_self + index + if index < 0 or index >= len_self: + raise IndexError("Sequence index out of range") + return self.get_function(index) + + def __delitem__(self, index: Union[int, slice]) -> None: + if isinstance(index, slice): + r = list(range(*index.indices(len(self)))) + # pages have to be deleted from last to first + r.sort() + r.reverse() + for p in r: + del self[p] # recursive call + return + if not isinstance(index, int): + raise TypeError("Index must be integers") + len_self = len(self) + if index < 0: + # support negative indexes + index = len_self + index + if index < 0 or index >= len_self: + raise IndexError("Index out of range") + ind = self[index].indirect_reference + assert ind is not None + parent: Optional[PdfObject] = cast(DictionaryObject, ind.get_object()).get( + "/Parent", None + ) + first = True + while parent is not None: + parent = cast(DictionaryObject, parent.get_object()) + try: + i = cast(ArrayObject, parent["/Kids"]).index(ind) + del cast(ArrayObject, parent["/Kids"])[i] + first = False + try: + assert ind is not None + del ind.pdf.flattened_pages[index] # case of page in a Reader + except Exception: # pragma: no cover + pass + if "/Count" in parent: + parent[NameObject("/Count")] = NumberObject( + cast(int, parent["/Count"]) - 1 + ) + if len(cast(ArrayObject, parent["/Kids"])) == 0: + # No more objects in this part of this sub tree + ind = parent.indirect_reference + parent = parent.get("/Parent", None) + except ValueError: # from index + if first: + raise PdfReadError(f"Page not found in page tree: {ind}") + break + + def __iter__(self) -> Iterator[PageObject]: + for i in range(len(self)): + yield self[i] + + def __str__(self) -> str: + p = [f"PageObject({i})" for i in range(self.length_function())] + return f"[{', '.join(p)}]" + + +def _get_fonts_walk( + obj: DictionaryObject, + fnt: Set[str], + emb: Set[str], +) -> Tuple[Set[str], Set[str]]: + """ + Get the set of all fonts and all embedded fonts. + + Args: + obj: Page resources dictionary + fnt: font + emb: embedded fonts + + Returns: + A tuple (fnt, emb) + + If there is a key called 'BaseFont', that is a font that is used in the document. + If there is a key called 'FontName' and another key in the same dictionary object + that is called 'FontFilex' (where x is null, 2, or 3), then that fontname is + embedded. + + We create and add to two sets, fnt = fonts used and emb = fonts embedded. + + """ + fontkeys = ("/FontFile", "/FontFile2", "/FontFile3") + + def process_font(f: DictionaryObject) -> None: + nonlocal fnt, emb + f = cast(DictionaryObject, f.get_object()) # to be sure + if "/BaseFont" in f: + fnt.add(cast(str, f["/BaseFont"])) + + if ( + ("/CharProcs" in f) + or ( + "/FontDescriptor" in f + and any( + x in cast(DictionaryObject, f["/FontDescriptor"]) for x in fontkeys + ) + ) + or ( + "/DescendantFonts" in f + and "/FontDescriptor" + in cast( + DictionaryObject, + cast(ArrayObject, f["/DescendantFonts"])[0].get_object(), + ) + and any( + x + in cast( + DictionaryObject, + cast( + DictionaryObject, + cast(ArrayObject, f["/DescendantFonts"])[0].get_object(), + )["/FontDescriptor"], + ) + for x in fontkeys + ) + ) + ): + # the list comprehension ensures there is FontFile + try: + emb.add(cast(str, f["/BaseFont"])) + except KeyError: + emb.add("(" + cast(str, f["/Subtype"]) + ")") + + if "/DR" in obj and "/Font" in cast(DictionaryObject, obj["/DR"]): + for f in cast(DictionaryObject, cast(DictionaryObject, obj["/DR"])["/Font"]): + process_font(f) + if "/Resources" in obj: + if "/Font" in cast(DictionaryObject, obj["/Resources"]): + for f in cast( + DictionaryObject, cast(DictionaryObject, obj["/Resources"])["/Font"] + ).values(): + process_font(f) + if "/XObject" in cast(DictionaryObject, obj["/Resources"]): + for x in cast( + DictionaryObject, cast(DictionaryObject, obj["/Resources"])["/XObject"] + ).values(): + _get_fonts_walk(cast(DictionaryObject, x.get_object()), fnt, emb) + if "/Annots" in obj: + for a in cast(ArrayObject, obj["/Annots"]): + _get_fonts_walk(cast(DictionaryObject, a.get_object()), fnt, emb) + if "/AP" in obj: + if ( + cast(DictionaryObject, cast(DictionaryObject, obj["/AP"])["/N"]).get( + "/Type" + ) + == "/XObject" + ): + _get_fonts_walk( + cast(DictionaryObject, cast(DictionaryObject, obj["/AP"])["/N"]), + fnt, + emb, + ) + else: + for a in cast(DictionaryObject, cast(DictionaryObject, obj["/AP"])["/N"]): + _get_fonts_walk(cast(DictionaryObject, a), fnt, emb) + return fnt, emb # return the sets for each page diff --git a/venv/lib/python3.12/site-packages/pypdf/_page_labels.py b/venv/lib/python3.12/site-packages/pypdf/_page_labels.py new file mode 100644 index 0000000..2d025d6 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_page_labels.py @@ -0,0 +1,289 @@ +""" +Page labels are shown by PDF viewers as "the page number". + +A page has a numeric index, starting at 0. Additionally, the page +has a label. In the most simple case: + + label = index + 1 + +However, the title page and the table of contents might have Roman numerals as +page labels. This makes things more complicated. + +Example 1 +--------- + +>>> reader.root_object["/PageLabels"]["/Nums"] +[0, IndirectObject(18, 0, 139929798197504), + 8, IndirectObject(19, 0, 139929798197504)] +>>> reader.get_object(reader.root_object["/PageLabels"]["/Nums"][1]) +{'/S': '/r'} +>>> reader.get_object(reader.root_object["/PageLabels"]["/Nums"][3]) +{'/S': '/D'} + +Example 2 +--------- +The following is a document with pages labeled +i, ii, iii, iv, 1, 2, 3, A-8, A-9, ... + +1 0 obj + << /Type /Catalog + /PageLabels << /Nums [ + 0 << /S /r >> + 4 << /S /D >> + 7 << /S /D + /P ( A- ) + /St 8 + >> + % A number tree containing + % three page label dictionaries + ] + >> + ... + >> +endobj + + +§12.4.2 PDF Specification 1.7 and 2.0 +===================================== + +Entries in a page label dictionary +---------------------------------- +The /S key: +D Decimal Arabic numerals +R Uppercase Roman numerals +r Lowercase Roman numerals +A Uppercase letters (A to Z for the first 26 pages, + AA to ZZ for the next 26, and so on) +a Lowercase letters (a to z for the first 26 pages, + aa to zz for the next 26, and so on) +""" + +from typing import Iterator, List, Optional, Tuple, cast + +from ._protocols import PdfCommonDocProtocol +from ._utils import logger_warning +from .generic import ( + ArrayObject, + DictionaryObject, + NullObject, + NumberObject, + is_null_or_none, +) + + +def number2uppercase_roman_numeral(num: int) -> str: + roman = [ + (1000, "M"), + (900, "CM"), + (500, "D"), + (400, "CD"), + (100, "C"), + (90, "XC"), + (50, "L"), + (40, "XL"), + (10, "X"), + (9, "IX"), + (5, "V"), + (4, "IV"), + (1, "I"), + ] + + def roman_num(num: int) -> Iterator[str]: + for decimal, roman_repr in roman: + x, _ = divmod(num, decimal) + yield roman_repr * x + num -= decimal * x + if num <= 0: + break + + return "".join(list(roman_num(num))) + + +def number2lowercase_roman_numeral(number: int) -> str: + return number2uppercase_roman_numeral(number).lower() + + +def number2uppercase_letter(number: int) -> str: + if number <= 0: + raise ValueError("Expecting a positive number") + alphabet = [chr(i) for i in range(ord("A"), ord("Z") + 1)] + rep = "" + while number > 0: + remainder = number % 26 + if remainder == 0: + remainder = 26 + rep = alphabet[remainder - 1] + rep + # update + number -= remainder + number = number // 26 + return rep + + +def number2lowercase_letter(number: int) -> str: + return number2uppercase_letter(number).lower() + + +def get_label_from_nums(dictionary_object: DictionaryObject, index: int) -> str: + # [Nums] shall be an array of the form + # [ key_1 value_1 key_2 value_2 ... key_n value_n ] + # where each key_i is an integer and the corresponding + # value_i shall be the object associated with that key. + # The keys shall be sorted in numerical order, + # analogously to the arrangement of keys in a name tree + # as described in 7.9.6, "Name Trees." + nums = cast(ArrayObject, dictionary_object["/Nums"]) + i = 0 + value = None + start_index = 0 + while i < len(nums): + start_index = nums[i] + value = nums[i + 1].get_object() + if i + 2 == len(nums): + break + if nums[i + 2] > index: + break + i += 2 + m = { + None: lambda n: "", + "/D": lambda n: str(n), + "/R": number2uppercase_roman_numeral, + "/r": number2lowercase_roman_numeral, + "/A": number2uppercase_letter, + "/a": number2lowercase_letter, + } + # if /Nums array is not following the specification or if /Nums is empty + if not isinstance(value, dict): + return str(index + 1) # Fallback + start = value.get("/St", 1) + prefix = value.get("/P", "") + return prefix + m[value.get("/S")](index - start_index + start) + + +def index2label(reader: PdfCommonDocProtocol, index: int) -> str: + """ + See 7.9.7 "Number Trees". + + Args: + reader: The PdfReader + index: The index of the page + + Returns: + The label of the page, e.g. "iv" or "4". + + """ + root = cast(DictionaryObject, reader.root_object) + if "/PageLabels" not in root: + return str(index + 1) # Fallback + number_tree = cast(DictionaryObject, root["/PageLabels"].get_object()) + if "/Nums" in number_tree: + return get_label_from_nums(number_tree, index) + if "/Kids" in number_tree and not isinstance(number_tree["/Kids"], NullObject): + # number_tree = {'/Kids': [IndirectObject(7333, 0, 140132998195856), ...]} + # Limit maximum depth. + level = 0 + while level < 100: + kids = cast(List[DictionaryObject], number_tree["/Kids"]) + for kid in kids: + # kid = {'/Limits': [0, 63], '/Nums': [0, {'/P': 'C1'}, ...]} + limits = cast(List[int], kid["/Limits"]) + if limits[0] <= index <= limits[1]: + if not is_null_or_none(kid.get("/Kids", None)): + # Recursive definition. + level += 1 + if level == 100: # pragma: no cover + raise NotImplementedError( + "Too deep nesting is not supported." + ) + number_tree = kid + # Exit the inner `for` loop and continue at the next level with the + # next iteration of the `while` loop. + break + return get_label_from_nums(kid, index) + else: + # When there are no kids, make sure to exit the `while` loop directly + # and continue with the fallback. + break + + logger_warning(f"Could not reliably determine page label for {index}.", __name__) + return str(index + 1) # Fallback if neither /Nums nor /Kids is in the number_tree + + +def nums_insert( + key: NumberObject, + value: DictionaryObject, + nums: ArrayObject, +) -> None: + """ + Insert a key, value pair in a Nums array. + + See 7.9.7 "Number Trees". + + Args: + key: number key of the entry + value: value of the entry + nums: Nums array to modify + + """ + if len(nums) % 2 != 0: + raise ValueError("A nums like array must have an even number of elements") + + i = len(nums) + while i != 0 and key <= nums[i - 2]: + i = i - 2 + + if i < len(nums) and key == nums[i]: + nums[i + 1] = value + else: + nums.insert(i, key) + nums.insert(i + 1, value) + + +def nums_clear_range( + key: NumberObject, + page_index_to: int, + nums: ArrayObject, +) -> None: + """ + Remove all entries in a number tree in a range after an entry. + + See 7.9.7 "Number Trees". + + Args: + key: number key of the entry before the range + page_index_to: The page index of the upper limit of the range + nums: Nums array to modify + + """ + if len(nums) % 2 != 0: + raise ValueError("A nums like array must have an even number of elements") + if page_index_to < key: + raise ValueError("page_index_to must be greater or equal than key") + + i = nums.index(key) + 2 + while i < len(nums) and nums[i] <= page_index_to: + nums.pop(i) + nums.pop(i) + + +def nums_next( + key: NumberObject, + nums: ArrayObject, +) -> Tuple[Optional[NumberObject], Optional[DictionaryObject]]: + """ + Return the (key, value) pair of the entry after the given one. + + See 7.9.7 "Number Trees". + + Args: + key: number key of the entry + nums: Nums array + + """ + if len(nums) % 2 != 0: + raise ValueError("A nums like array must have an even number of elements") + + i = nums.index(key) + 2 + if i < len(nums): + return (nums[i], nums[i + 1]) + else: + return (None, None) diff --git a/venv/lib/python3.12/site-packages/pypdf/_protocols.py b/venv/lib/python3.12/site-packages/pypdf/_protocols.py new file mode 100644 index 0000000..431db1a --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_protocols.py @@ -0,0 +1,86 @@ +"""Helpers for working with PDF types.""" + +from abc import abstractmethod +from pathlib import Path +from typing import IO, Any, Dict, List, Optional, Protocol, Tuple, Union + +from ._utils import StrByteType, StreamType + + +class PdfObjectProtocol(Protocol): + indirect_reference: Any + + def clone( + self, + pdf_dest: Any, + force_duplicate: bool = False, + ignore_fields: Union[Tuple[str, ...], List[str], None] = (), + ) -> Any: + ... # pragma: no cover + + def _reference_clone(self, clone: Any, pdf_dest: Any) -> Any: + ... # pragma: no cover + + def get_object(self) -> Optional["PdfObjectProtocol"]: + ... # pragma: no cover + + def hash_value(self) -> bytes: + ... # pragma: no cover + + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + ... # pragma: no cover + + +class XmpInformationProtocol(PdfObjectProtocol): + pass + + +class PdfCommonDocProtocol(Protocol): + @property + def pdf_header(self) -> str: + ... # pragma: no cover + + @property + def pages(self) -> List[Any]: + ... # pragma: no cover + + @property + def root_object(self) -> PdfObjectProtocol: + ... # pragma: no cover + + def get_object(self, indirect_reference: Any) -> Optional[PdfObjectProtocol]: + ... # pragma: no cover + + @property + def strict(self) -> bool: + ... # pragma: no cover + + +class PdfReaderProtocol(PdfCommonDocProtocol, Protocol): + @property + @abstractmethod + def xref(self) -> Dict[int, Dict[int, Any]]: + ... # pragma: no cover + + @property + @abstractmethod + def trailer(self) -> Dict[str, Any]: + ... # pragma: no cover + + +class PdfWriterProtocol(PdfCommonDocProtocol, Protocol): + _objects: List[Any] + _id_translated: Dict[int, Dict[int, int]] + + incremental: bool + _reader: Any # PdfReader + + @abstractmethod + def write(self, stream: Union[Path, StrByteType]) -> Tuple[bool, IO[Any]]: + ... # pragma: no cover + + @abstractmethod + def _add_object(self, obj: Any) -> Any: + ... # pragma: no cover diff --git a/venv/lib/python3.12/site-packages/pypdf/_reader.py b/venv/lib/python3.12/site-packages/pypdf/_reader.py new file mode 100644 index 0000000..2efb998 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_reader.py @@ -0,0 +1,1273 @@ +# Copyright (c) 2006, Mathieu Fenniak +# Copyright (c) 2007, Ashish Kulkarni +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import os +import re +from io import BytesIO, UnsupportedOperation +from pathlib import Path +from types import TracebackType +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Dict, + Iterable, + List, + Optional, + Set, + Tuple, + Type, + Union, + cast, +) + +from ._doc_common import PdfDocCommon, convert_to_int +from ._encryption import Encryption, PasswordType +from ._utils import ( + StrByteType, + StreamType, + logger_warning, + read_non_whitespace, + read_previous_line, + read_until_whitespace, + skip_over_comment, + skip_over_whitespace, +) +from .constants import TrailerKeys as TK +from .errors import ( + EmptyFileError, + FileNotDecryptedError, + PdfReadError, + PdfStreamError, + WrongPasswordError, +) +from .generic import ( + ArrayObject, + ContentStream, + DecodedStreamObject, + DictionaryObject, + EncodedStreamObject, + IndirectObject, + NameObject, + NullObject, + NumberObject, + PdfObject, + StreamObject, + TextStringObject, + is_null_or_none, + read_object, +) +from .xmp import XmpInformation + +if TYPE_CHECKING: + from ._page import PageObject + + +class PdfReader(PdfDocCommon): + """ + Initialize a PdfReader object. + + This operation can take some time, as the PDF stream's cross-reference + tables are read into memory. + + Args: + stream: A File object or an object that supports the standard read + and seek methods similar to a File object. Could also be a + string representing a path to a PDF file. + strict: Determines whether user should be warned of all + problems and also causes some correctable problems to be fatal. + Defaults to ``False``. + password: Decrypt PDF file at initialization. If the + password is None, the file will not be decrypted. + Defaults to ``None``. + + """ + + def __init__( + self, + stream: Union[StrByteType, Path], + strict: bool = False, + password: Union[None, str, bytes] = None, + ) -> None: + self.strict = strict + self.flattened_pages: Optional[List[PageObject]] = None + + #: Storage of parsed PDF objects. + self.resolved_objects: Dict[Tuple[Any, Any], Optional[PdfObject]] = {} + + self._startxref: int = 0 + self.xref_index = 0 + self.xref: Dict[int, Dict[Any, Any]] = {} + self.xref_free_entry: Dict[int, Dict[Any, Any]] = {} + self.xref_objStm: Dict[int, Tuple[Any, Any]] = {} + self.trailer = DictionaryObject() + + # Map page indirect_reference number to page number + self._page_id2num: Optional[Dict[Any, Any]] = None + + self._validated_root: Optional[DictionaryObject] = None + + self._initialize_stream(stream) + self._known_objects: Set[Tuple[int, int]] = set() + + self._override_encryption = False + self._encryption: Optional[Encryption] = None + if self.is_encrypted: + self._handle_encryption(password) + elif password is not None: + raise PdfReadError("Not an encrypted file") + + def _initialize_stream(self, stream: Union[StrByteType, Path]) -> None: + if hasattr(stream, "mode") and "b" not in stream.mode: + logger_warning( + "PdfReader stream/file object is not in binary mode. " + "It may not be read correctly.", + __name__, + ) + self._stream_opened = False + if isinstance(stream, (str, Path)): + with open(stream, "rb") as fh: + stream = BytesIO(fh.read()) + self._stream_opened = True + self.read(stream) + self.stream = stream + + def _handle_encryption(self, password: Optional[Union[str, bytes]]) -> None: + self._override_encryption = True + # Some documents may not have a /ID, use two empty + # byte strings instead. Solves + # https://github.com/py-pdf/pypdf/issues/608 + id_entry = self.trailer.get(TK.ID) + id1_entry = id_entry[0].get_object().original_bytes if id_entry else b"" + encrypt_entry = cast(DictionaryObject, self.trailer[TK.ENCRYPT].get_object()) + self._encryption = Encryption.read(encrypt_entry, id1_entry) + + # try empty password if no password provided + pwd = password if password is not None else b"" + if ( + self._encryption.verify(pwd) == PasswordType.NOT_DECRYPTED + and password is not None + ): + # raise if password provided + raise WrongPasswordError("Wrong password") + self._override_encryption = False + + def __enter__(self) -> "PdfReader": + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self.close() + + def close(self) -> None: + """Close the stream if opened in __init__ and clear memory.""" + if self._stream_opened: + self.stream.close() + self.flattened_pages = [] + self.resolved_objects = {} + self.trailer = DictionaryObject() + self.xref = {} + self.xref_free_entry = {} + self.xref_objStm = {} + + @property + def root_object(self) -> DictionaryObject: + """Provide access to "/Root". Standardized with PdfWriter.""" + if self._validated_root: + return self._validated_root + root = self.trailer.get(TK.ROOT) + if is_null_or_none(root): + logger_warning('Cannot find "/Root" key in trailer', __name__) + elif ( + cast(DictionaryObject, cast(PdfObject, root).get_object()).get("/Type") + == "/Catalog" + ): + self._validated_root = cast( + DictionaryObject, cast(PdfObject, root).get_object() + ) + else: + logger_warning("Invalid Root object in trailer", __name__) + if self._validated_root is None: + logger_warning('Searching object with "/Catalog" key', __name__) + nb = cast(int, self.trailer.get("/Size", 0)) + for i in range(nb): + try: + o = self.get_object(i + 1) + except Exception: # to be sure to capture all errors + o = None + if isinstance(o, DictionaryObject) and o.get("/Type") == "/Catalog": + self._validated_root = o + logger_warning(f"Root found at {o.indirect_reference!r}", __name__) + break + if self._validated_root is None: + if not is_null_or_none(root) and "/Pages" in cast(DictionaryObject, cast(PdfObject, root).get_object()): + logger_warning( + f"Possible root found at {cast(PdfObject, root).indirect_reference!r}, but missing /Catalog key", + __name__ + ) + self._validated_root = cast( + DictionaryObject, cast(PdfObject, root).get_object() + ) + else: + raise PdfReadError("Cannot find Root object in pdf") + return self._validated_root + + @property + def _info(self) -> Optional[DictionaryObject]: + """ + Provide access to "/Info". Standardized with PdfWriter. + + Returns: + /Info Dictionary; None if the entry does not exist + + """ + info = self.trailer.get(TK.INFO, None) + if is_null_or_none(info): + return None + info = info.get_object() + if not isinstance(info, DictionaryObject): + raise PdfReadError( + "Trailer not found or does not point to document information directory" + ) + return info + + @property + def _ID(self) -> Optional[ArrayObject]: + """ + Provide access to "/ID". Standardized with PdfWriter. + + Returns: + /ID array; None if the entry does not exist + + """ + id = self.trailer.get(TK.ID, None) + return None if is_null_or_none(id) else cast(ArrayObject, id.get_object()) + + @property + def pdf_header(self) -> str: + """ + The first 8 bytes of the file. + + This is typically something like ``'%PDF-1.6'`` and can be used to + detect if the file is actually a PDF file and which version it is. + """ + # TODO: Make this return a bytes object for consistency + # but that needs a deprecation + loc = self.stream.tell() + self.stream.seek(0, 0) + pdf_file_version = self.stream.read(8).decode("utf-8", "backslashreplace") + self.stream.seek(loc, 0) # return to where it was + return pdf_file_version + + @property + def xmp_metadata(self) -> Optional[XmpInformation]: + """XMP (Extensible Metadata Platform) data.""" + try: + self._override_encryption = True + return cast(XmpInformation, self.root_object.xmp_metadata) + finally: + self._override_encryption = False + + def _get_page_number_by_indirect( + self, indirect_reference: Union[None, int, NullObject, IndirectObject] + ) -> Optional[int]: + """ + Retrieve the page number from an indirect reference. + + Args: + indirect_reference: The indirect reference to locate. + + Returns: + Page number or None. + + """ + if self._page_id2num is None: + self._page_id2num = { + x.indirect_reference.idnum: i for i, x in enumerate(self.pages) # type: ignore + } + + if is_null_or_none(indirect_reference): + return None + assert isinstance(indirect_reference, (int, IndirectObject)), "mypy" + if isinstance(indirect_reference, int): + idnum = indirect_reference + else: + idnum = indirect_reference.idnum + assert self._page_id2num is not None, "hint for mypy" + return self._page_id2num.get(idnum, None) + + def _get_object_from_stream( + self, indirect_reference: IndirectObject + ) -> Union[int, PdfObject, str]: + # indirect reference to object in object stream + # read the entire object stream into memory + stmnum, idx = self.xref_objStm[indirect_reference.idnum] + obj_stm: EncodedStreamObject = IndirectObject(stmnum, 0, self).get_object() # type: ignore + # This is an xref to a stream, so its type better be a stream + assert cast(str, obj_stm["/Type"]) == "/ObjStm" + stream_data = BytesIO(obj_stm.get_data()) + for i in range(obj_stm["/N"]): # type: ignore + read_non_whitespace(stream_data) + stream_data.seek(-1, 1) + objnum = NumberObject.read_from_stream(stream_data) + read_non_whitespace(stream_data) + stream_data.seek(-1, 1) + offset = NumberObject.read_from_stream(stream_data) + read_non_whitespace(stream_data) + stream_data.seek(-1, 1) + if objnum != indirect_reference.idnum: + # We're only interested in one object + continue + if self.strict and idx != i: + raise PdfReadError("Object is in wrong index.") + stream_data.seek(int(obj_stm["/First"] + offset), 0) # type: ignore + + # to cope with some case where the 'pointer' is on a white space + read_non_whitespace(stream_data) + stream_data.seek(-1, 1) + + try: + obj = read_object(stream_data, self) + except PdfStreamError as exc: + # Stream object cannot be read. Normally, a critical error, but + # Adobe Reader doesn't complain, so continue (in strict mode?) + logger_warning( + f"Invalid stream (index {i}) within object " + f"{indirect_reference.idnum} {indirect_reference.generation}: " + f"{exc}", + __name__, + ) + + if self.strict: # pragma: no cover + raise PdfReadError( + f"Cannot read object stream: {exc}" + ) # pragma: no cover + # Replace with null. Hopefully it's nothing important. + obj = NullObject() # pragma: no cover + return obj + + if self.strict: # pragma: no cover + raise PdfReadError( + "This is a fatal error in strict mode." + ) # pragma: no cover + return NullObject() # pragma: no cover + + def get_object( + self, indirect_reference: Union[int, IndirectObject] + ) -> Optional[PdfObject]: + if isinstance(indirect_reference, int): + indirect_reference = IndirectObject(indirect_reference, 0, self) + retval = self.cache_get_indirect_object( + indirect_reference.generation, indirect_reference.idnum + ) + if retval is not None: + return retval + if ( + indirect_reference.generation == 0 + and indirect_reference.idnum in self.xref_objStm + ): + retval = self._get_object_from_stream(indirect_reference) # type: ignore + elif ( + indirect_reference.generation in self.xref + and indirect_reference.idnum in self.xref[indirect_reference.generation] + ): + if self.xref_free_entry.get(indirect_reference.generation, {}).get( + indirect_reference.idnum, False + ): + return NullObject() + start = self.xref[indirect_reference.generation][indirect_reference.idnum] + self.stream.seek(start, 0) + try: + idnum, generation = self.read_object_header(self.stream) + if ( + idnum != indirect_reference.idnum + or generation != indirect_reference.generation + ): + raise PdfReadError("Not matching, we parse the file for it") + except Exception: + if hasattr(self.stream, "getbuffer"): + buf = bytes(self.stream.getbuffer()) + else: + p = self.stream.tell() + self.stream.seek(0, 0) + buf = self.stream.read(-1) + self.stream.seek(p, 0) + m = re.search( + rf"\s{indirect_reference.idnum}\s+{indirect_reference.generation}\s+obj".encode(), + buf, + ) + if m is not None: + logger_warning( + f"Object ID {indirect_reference.idnum},{indirect_reference.generation} ref repaired", + __name__, + ) + self.xref[indirect_reference.generation][ + indirect_reference.idnum + ] = (m.start(0) + 1) + self.stream.seek(m.start(0) + 1) + idnum, generation = self.read_object_header(self.stream) + else: + idnum = -1 + generation = -1 # exception will be raised below + if idnum != indirect_reference.idnum and self.xref_index: + # xref table probably had bad indexes due to not being zero-indexed + if self.strict: + raise PdfReadError( + f"Expected object ID ({indirect_reference.idnum} {indirect_reference.generation}) " + f"does not match actual ({idnum} {generation}); " + "xref table not zero-indexed." + ) + # xref table is corrected in non-strict mode + elif idnum != indirect_reference.idnum and self.strict: + # some other problem + raise PdfReadError( + f"Expected object ID ({indirect_reference.idnum} {indirect_reference.generation}) " + f"does not match actual ({idnum} {generation})." + ) + if self.strict: + assert generation == indirect_reference.generation + + current_object = (indirect_reference.idnum, indirect_reference.generation) + if current_object in self._known_objects: + raise PdfReadError(f"Detected loop with self reference for {indirect_reference!r}.") + self._known_objects.add(current_object) + retval = read_object(self.stream, self) # type: ignore + self._known_objects.remove(current_object) + + # override encryption is used for the /Encrypt dictionary + if not self._override_encryption and self._encryption is not None: + # if we don't have the encryption key: + if not self._encryption.is_decrypted(): + raise FileNotDecryptedError("File has not been decrypted") + # otherwise, decrypt here... + retval = cast(PdfObject, retval) + retval = self._encryption.decrypt_object( + retval, indirect_reference.idnum, indirect_reference.generation + ) + else: + if hasattr(self.stream, "getbuffer"): + buf = bytes(self.stream.getbuffer()) + else: + p = self.stream.tell() + self.stream.seek(0, 0) + buf = self.stream.read(-1) + self.stream.seek(p, 0) + m = re.search( + rf"\s{indirect_reference.idnum}\s+{indirect_reference.generation}\s+obj".encode(), + buf, + ) + if m is not None: + logger_warning( + f"Object {indirect_reference.idnum} {indirect_reference.generation} found", + __name__, + ) + if indirect_reference.generation not in self.xref: + self.xref[indirect_reference.generation] = {} + self.xref[indirect_reference.generation][indirect_reference.idnum] = ( + m.start(0) + 1 + ) + self.stream.seek(m.end(0) + 1) + skip_over_whitespace(self.stream) + self.stream.seek(-1, 1) + retval = read_object(self.stream, self) # type: ignore + + # override encryption is used for the /Encrypt dictionary + if not self._override_encryption and self._encryption is not None: + # if we don't have the encryption key: + if not self._encryption.is_decrypted(): + raise FileNotDecryptedError("File has not been decrypted") + # otherwise, decrypt here... + retval = cast(PdfObject, retval) + retval = self._encryption.decrypt_object( + retval, indirect_reference.idnum, indirect_reference.generation + ) + else: + logger_warning( + f"Object {indirect_reference.idnum} {indirect_reference.generation} not defined.", + __name__, + ) + if self.strict: + raise PdfReadError("Could not find object.") + self.cache_indirect_object( + indirect_reference.generation, indirect_reference.idnum, retval + ) + return retval + + def read_object_header(self, stream: StreamType) -> Tuple[int, int]: + # Should never be necessary to read out whitespace, since the + # cross-reference table should put us in the right spot to read the + # object header. In reality some files have stupid cross-reference + # tables that are off by whitespace bytes. + skip_over_comment(stream) + extra = skip_over_whitespace(stream) + stream.seek(-1, 1) + idnum = read_until_whitespace(stream) + extra |= skip_over_whitespace(stream) + stream.seek(-1, 1) + generation = read_until_whitespace(stream) + extra |= skip_over_whitespace(stream) + stream.seek(-1, 1) + + # although it's not used, it might still be necessary to read + _obj = stream.read(3) + + read_non_whitespace(stream) + stream.seek(-1, 1) + if extra and self.strict: + logger_warning( + f"Superfluous whitespace found in object header {idnum} {generation}", # type: ignore + __name__, + ) + return int(idnum), int(generation) + + def cache_get_indirect_object( + self, generation: int, idnum: int + ) -> Optional[PdfObject]: + try: + return self.resolved_objects.get((generation, idnum)) + except RecursionError: + raise PdfReadError("Maximum recursion depth reached.") + + def cache_indirect_object( + self, generation: int, idnum: int, obj: Optional[PdfObject] + ) -> Optional[PdfObject]: + if (generation, idnum) in self.resolved_objects: + msg = f"Overwriting cache for {generation} {idnum}" + if self.strict: + raise PdfReadError(msg) + logger_warning(msg, __name__) + self.resolved_objects[(generation, idnum)] = obj + if obj is not None: + obj.indirect_reference = IndirectObject(idnum, generation, self) + return obj + + def _replace_object(self, indirect: IndirectObject, obj: PdfObject) -> PdfObject: + # function reserved for future development + if indirect.pdf != self: + raise ValueError("Cannot update PdfReader with external object") + if (indirect.generation, indirect.idnum) not in self.resolved_objects: + raise ValueError("Cannot find referenced object") + self.resolved_objects[(indirect.generation, indirect.idnum)] = obj + obj.indirect_reference = indirect + return obj + + def read(self, stream: StreamType) -> None: + """ + Read and process the PDF stream, extracting necessary data. + + Args: + stream: The PDF file stream. + + """ + self._basic_validation(stream) + self._find_eof_marker(stream) + startxref = self._find_startxref_pos(stream) + self._startxref = startxref + + # check and eventually correct the startxref only if not strict + xref_issue_nr = self._get_xref_issues(stream, startxref) + if xref_issue_nr != 0: + if self.strict and xref_issue_nr: + raise PdfReadError("Broken xref table") + logger_warning(f"incorrect startxref pointer({xref_issue_nr})", __name__) + + # read all cross-reference tables and their trailers + self._read_xref_tables_and_trailers(stream, startxref, xref_issue_nr) + + # if not zero-indexed, verify that the table is correct; change it if necessary + if self.xref_index and not self.strict: + loc = stream.tell() + for gen, xref_entry in self.xref.items(): + if gen == 65535: + continue + xref_k = sorted( + xref_entry.keys() + ) # ensure ascending to prevent damage + for id in xref_k: + stream.seek(xref_entry[id], 0) + try: + pid, _pgen = self.read_object_header(stream) + except ValueError: + self._rebuild_xref_table(stream) + break + if pid == id - self.xref_index: + # fixing index item per item is required for revised PDF. + self.xref[gen][pid] = self.xref[gen][id] + del self.xref[gen][id] + # if not, then either it's just plain wrong, or the + # non-zero-index is actually correct + stream.seek(loc, 0) # return to where it was + + # remove wrong objects (not pointing to correct structures) - cf #2326 + if not self.strict: + loc = stream.tell() + for gen, xref_entry in self.xref.items(): + if gen == 65535: + continue + ids = list(xref_entry.keys()) + for id in ids: + stream.seek(xref_entry[id], 0) + try: + self.read_object_header(stream) + except ValueError: + logger_warning( + f"Ignoring wrong pointing object {id} {gen} (offset {xref_entry[id]})", + __name__, + ) + del xref_entry[id] # we can delete the id, we are parsing ids + stream.seek(loc, 0) # return to where it was + + def _basic_validation(self, stream: StreamType) -> None: + """Ensure the stream is valid and not empty.""" + stream.seek(0, os.SEEK_SET) + try: + header_byte = stream.read(5) + except UnicodeDecodeError: + raise UnsupportedOperation("cannot read header") + if header_byte == b"": + raise EmptyFileError("Cannot read an empty file") + elif header_byte != b"%PDF-": + if self.strict: + raise PdfReadError( + f"PDF starts with '{header_byte.decode('utf8')}', " + "but '%PDF-' expected" + ) + else: + logger_warning(f"invalid pdf header: {header_byte}", __name__) + stream.seek(0, os.SEEK_END) + + def _find_eof_marker(self, stream: StreamType) -> None: + """ + Jump to the %%EOF marker. + + According to the specs, the %%EOF marker should be at the very end of + the file. Hence for standard-compliant PDF documents this function will + read only the last part (DEFAULT_BUFFER_SIZE). + """ + HEADER_SIZE = 8 # to parse whole file, Header is e.g. '%PDF-1.6' + line = b"" + first = True + while not line.startswith(b"%%EOF"): + if line != b"" and first: + if any( + line.strip().endswith(tr) for tr in (b"%%EO", b"%%E", b"%%", b"%") + ): + # Consider the file as truncated while + # having enough confidence to carry on. + logger_warning("EOF marker seems truncated", __name__) + break + first = False + if b"startxref" in line: + logger_warning( + "CAUTION: startxref found while searching for %%EOF. " + "The file might be truncated and some data might not be read.", + __name__, + ) + if stream.tell() < HEADER_SIZE: + if self.strict: + raise PdfReadError("EOF marker not found") + else: + logger_warning("EOF marker not found", __name__) + line = read_previous_line(stream) + + def _find_startxref_pos(self, stream: StreamType) -> int: + """ + Find startxref entry - the location of the xref table. + + Args: + stream: + + Returns: + The bytes offset + + """ + line = read_previous_line(stream) + try: + startxref = int(line) + except ValueError: + # 'startxref' may be on the same line as the location + if not line.startswith(b"startxref"): + raise PdfReadError("startxref not found") + startxref = int(line[9:].strip()) + logger_warning("startxref on same line as offset", __name__) + else: + line = read_previous_line(stream) + if not line.startswith(b"startxref"): + raise PdfReadError("startxref not found") + return startxref + + def _read_standard_xref_table(self, stream: StreamType) -> None: + # standard cross-reference table + ref = stream.read(3) + if ref != b"ref": + raise PdfReadError("xref table read error") + read_non_whitespace(stream) + stream.seek(-1, 1) + first_time = True # check if the first time looking at the xref table + while True: + num = cast(int, read_object(stream, self)) + if first_time and num != 0: + self.xref_index = num + if self.strict: + logger_warning( + "Xref table not zero-indexed. ID numbers for objects will be corrected.", + __name__, + ) + # if table not zero indexed, could be due to error from when PDF was created + # which will lead to mismatched indices later on, only warned and corrected if self.strict==True + first_time = False + read_non_whitespace(stream) + stream.seek(-1, 1) + size = cast(int, read_object(stream, self)) + if not isinstance(size, int): + logger_warning( + "Invalid/Truncated xref table. Rebuilding it.", + __name__, + ) + self._rebuild_xref_table(stream) + stream.read() + return + read_non_whitespace(stream) + stream.seek(-1, 1) + cnt = 0 + while cnt < size: + line = stream.read(20) + if not line: + raise PdfReadError("Unexpected empty line in Xref table.") + + # It's very clear in section 3.4.3 of the PDF spec + # that all cross-reference table lines are a fixed + # 20 bytes (as of PDF 1.7). However, some files have + # 21-byte entries (or more) due to the use of \r\n + # (CRLF) EOL's. Detect that case, and adjust the line + # until it does not begin with a \r (CR) or \n (LF). + while line[0] in b"\x0D\x0A": + stream.seek(-20 + 1, 1) + line = stream.read(20) + + # On the other hand, some malformed PDF files + # use a single character EOL without a preceding + # space. Detect that case, and seek the stream + # back one character (0-9 means we've bled into + # the next xref entry, t means we've bled into the + # text "trailer"): + if line[-1] in b"0123456789t": + stream.seek(-1, 1) + + try: + offset_b, generation_b = line[:16].split(b" ") + entry_type_b = line[17:18] + + offset, generation = int(offset_b), int(generation_b) + except Exception: + if hasattr(stream, "getbuffer"): + buf = bytes(stream.getbuffer()) + else: + p = stream.tell() + stream.seek(0, 0) + buf = stream.read(-1) + stream.seek(p) + + f = re.search(rf"{num}\s+(\d+)\s+obj".encode(), buf) + if f is None: + logger_warning( + f"entry {num} in Xref table invalid; object not found", + __name__, + ) + generation = 65535 + offset = -1 + else: + logger_warning( + f"entry {num} in Xref table invalid but object found", + __name__, + ) + generation = int(f.group(1)) + offset = f.start() + + if generation not in self.xref: + self.xref[generation] = {} + self.xref_free_entry[generation] = {} + if num in self.xref[generation]: + # It really seems like we should allow the last + # xref table in the file to override previous + # ones. Since we read the file backwards, assume + # any existing key is already set correctly. + pass + else: + if entry_type_b == b"n": + self.xref[generation][num] = offset + try: + self.xref_free_entry[generation][num] = entry_type_b == b"f" + except Exception: + pass + try: + self.xref_free_entry[65535][num] = entry_type_b == b"f" + except Exception: + pass + cnt += 1 + num += 1 + read_non_whitespace(stream) + stream.seek(-1, 1) + trailer_tag = stream.read(7) + if trailer_tag != b"trailer": + # more xrefs! + stream.seek(-7, 1) + else: + break + + def _read_xref_tables_and_trailers( + self, stream: StreamType, startxref: Optional[int], xref_issue_nr: int + ) -> None: + """Read the cross-reference tables and trailers in the PDF stream.""" + self.xref = {} + self.xref_free_entry = {} + self.xref_objStm = {} + self.trailer = DictionaryObject() + while startxref is not None: + # load the xref table + stream.seek(startxref, 0) + x = stream.read(1) + if x in b"\r\n": + x = stream.read(1) + if x == b"x": + startxref = self._read_xref(stream) + elif xref_issue_nr: + try: + self._rebuild_xref_table(stream) + break + except Exception: + xref_issue_nr = 0 + elif x.isdigit(): + try: + xrefstream = self._read_pdf15_xref_stream(stream) + except Exception as e: + if TK.ROOT in self.trailer: + logger_warning( + f"Previous trailer cannot be read: {e.args}", __name__ + ) + break + raise PdfReadError(f"Trailer cannot be read: {e!s}") + self._process_xref_stream(xrefstream) + if "/Prev" in xrefstream: + startxref = cast(int, xrefstream["/Prev"]) + else: + break + else: + startxref = self._read_xref_other_error(stream, startxref) + + def _process_xref_stream(self, xrefstream: DictionaryObject) -> None: + """Process and handle the xref stream.""" + trailer_keys = TK.ROOT, TK.ENCRYPT, TK.INFO, TK.ID, TK.SIZE + for key in trailer_keys: + if key in xrefstream and key not in self.trailer: + self.trailer[NameObject(key)] = xrefstream.raw_get(key) + if "/XRefStm" in xrefstream: + p = self.stream.tell() + self.stream.seek(cast(int, xrefstream["/XRefStm"]) + 1, 0) + self._read_pdf15_xref_stream(self.stream) + self.stream.seek(p, 0) + + def _read_xref(self, stream: StreamType) -> Optional[int]: + self._read_standard_xref_table(stream) + if stream.read(1) == b"": + return None + stream.seek(-1, 1) + read_non_whitespace(stream) + stream.seek(-1, 1) + new_trailer = cast(Dict[str, Any], read_object(stream, self)) + for key, value in new_trailer.items(): + if key not in self.trailer: + self.trailer[key] = value + if "/XRefStm" in new_trailer: + p = stream.tell() + stream.seek(cast(int, new_trailer["/XRefStm"]) + 1, 0) + try: + self._read_pdf15_xref_stream(stream) + except Exception: + logger_warning( + f"XRef object at {new_trailer['/XRefStm']} can not be read, some object may be missing", + __name__, + ) + stream.seek(p, 0) + if "/Prev" in new_trailer: + return new_trailer["/Prev"] + return None + + def _read_xref_other_error( + self, stream: StreamType, startxref: int + ) -> Optional[int]: + # some PDFs have /Prev=0 in the trailer, instead of no /Prev + if startxref == 0: + if self.strict: + raise PdfReadError( + "/Prev=0 in the trailer (try opening with strict=False)" + ) + logger_warning( + "/Prev=0 in the trailer - assuming there is no previous xref table", + __name__, + ) + return None + # bad xref character at startxref. Let's see if we can find + # the xref table nearby, as we've observed this error with an + # off-by-one before. + stream.seek(-11, 1) + tmp = stream.read(20) + xref_loc = tmp.find(b"xref") + if xref_loc != -1: + startxref -= 10 - xref_loc + return startxref + # No explicit xref table, try finding a cross-reference stream. + stream.seek(startxref, 0) + for look in range(25): # value extended to cope with more linearized files + if stream.read(1).isdigit(): + # This is not a standard PDF, consider adding a warning + startxref += look + return startxref + # no xref table found at specified location + if "/Root" in self.trailer and not self.strict: + # if Root has been already found, just raise warning + logger_warning("Invalid parent xref., rebuild xref", __name__) + try: + self._rebuild_xref_table(stream) + return None + except Exception: + raise PdfReadError("Cannot rebuild xref") + raise PdfReadError("Could not find xref table at specified location") + + def _read_pdf15_xref_stream( + self, stream: StreamType + ) -> Union[ContentStream, EncodedStreamObject, DecodedStreamObject]: + """Read the cross-reference stream for PDF 1.5+.""" + stream.seek(-1, 1) + idnum, generation = self.read_object_header(stream) + xrefstream = cast(ContentStream, read_object(stream, self)) + if cast(str, xrefstream["/Type"]) != "/XRef": + raise PdfReadError(f"Unexpected type {xrefstream['/Type']!r}") + self.cache_indirect_object(generation, idnum, xrefstream) + stream_data = BytesIO(xrefstream.get_data()) + # Index pairs specify the subsections in the dictionary. + # If none, create one subsection that spans everything. + idx_pairs = xrefstream.get("/Index", [0, xrefstream.get("/Size")]) + entry_sizes = cast(Dict[Any, Any], xrefstream.get("/W")) + assert len(entry_sizes) >= 3 + if self.strict and len(entry_sizes) > 3: + raise PdfReadError(f"Too many entry sizes: {entry_sizes}") + + def get_entry(i: int) -> Union[int, Tuple[int, ...]]: + # Reads the correct number of bytes for each entry. See the + # discussion of the W parameter in PDF spec table 17. + if entry_sizes[i] > 0: + d = stream_data.read(entry_sizes[i]) + return convert_to_int(d, entry_sizes[i]) + + # PDF Spec Table 17: A value of zero for an element in the + # W array indicates...the default value shall be used + if i == 0: + return 1 # First value defaults to 1 + return 0 + + def used_before(num: int, generation: Union[int, Tuple[int, ...]]) -> bool: + # We move backwards through the xrefs, don't replace any. + return num in self.xref.get(generation, []) or num in self.xref_objStm # type: ignore + + # Iterate through each subsection + self._read_xref_subsections(idx_pairs, get_entry, used_before) + return xrefstream + + @staticmethod + def _get_xref_issues(stream: StreamType, startxref: int) -> int: + """ + Return an int which indicates an issue. 0 means there is no issue. + + Args: + stream: + startxref: + + Returns: + 0 means no issue, other values represent specific issues. + + """ + if startxref == 0: + return 4 + + stream.seek(startxref - 1, 0) # -1 to check character before + line = stream.read(1) + if line == b"j": + line = stream.read(1) + if line not in b"\r\n \t": + return 1 + line = stream.read(4) + if line != b"xref": + # not a xref so check if it is an XREF object + line = b"" + while line in b"0123456789 \t": + line = stream.read(1) + if line == b"": + return 2 + line += stream.read(2) # 1 char already read, +2 to check "obj" + if line.lower() != b"obj": + return 3 + return 0 + + def _rebuild_xref_table(self, stream: StreamType) -> None: + self.xref = {} + stream.seek(0, 0) + f_ = stream.read(-1) + + for m in re.finditer(rb"[\r\n \t][ \t]*(\d+)[ \t]+(\d+)[ \t]+obj", f_): + idnum = int(m.group(1)) + generation = int(m.group(2)) + if generation not in self.xref: + self.xref[generation] = {} + self.xref[generation][idnum] = m.start(1) + + logger_warning("parsing for Object Streams", __name__) + for g in self.xref: + for i in self.xref[g]: + # get_object in manual + stream.seek(self.xref[g][i], 0) + try: + _ = self.read_object_header(stream) + o = cast(StreamObject, read_object(stream, self)) + if o.get("/Type", "") != "/ObjStm": + continue + strm = BytesIO(o.get_data()) + cpt = 0 + while True: + s = read_until_whitespace(strm) + if not s.isdigit(): + break + _i = int(s) + skip_over_whitespace(strm) + strm.seek(-1, 1) + s = read_until_whitespace(strm) + if not s.isdigit(): # pragma: no cover + break # pragma: no cover + _o = int(s) + self.xref_objStm[_i] = (i, _o) + cpt += 1 + if cpt != o.get("/N"): # pragma: no cover + logger_warning( # pragma: no cover + f"found {cpt} objects within Object({i},{g})" + f" whereas {o.get('/N')} expected", + __name__, + ) + except Exception: # could be multiple causes + pass + + stream.seek(0, 0) + for m in re.finditer(rb"[\r\n \t][ \t]*trailer[\r\n \t]*(<<)", f_): + stream.seek(m.start(1), 0) + new_trailer = cast(Dict[Any, Any], read_object(stream, self)) + # Here, we are parsing the file from start to end, the new data have to erase the existing. + for key, value in list(new_trailer.items()): + self.trailer[key] = value + + def _read_xref_subsections( + self, + idx_pairs: List[int], + get_entry: Callable[[int], Union[int, Tuple[int, ...]]], + used_before: Callable[[int, Union[int, Tuple[int, ...]]], bool], + ) -> None: + """Read and process the subsections of the xref.""" + for start, size in self._pairs(idx_pairs): + # The subsections must increase + for num in range(start, start + size): + # The first entry is the type + xref_type = get_entry(0) + # The rest of the elements depend on the xref_type + if xref_type == 0: + # linked list of free objects + next_free_object = get_entry(1) # noqa: F841 + next_generation = get_entry(2) # noqa: F841 + elif xref_type == 1: + # objects that are in use but are not compressed + byte_offset = get_entry(1) + generation = get_entry(2) + if generation not in self.xref: + self.xref[generation] = {} # type: ignore + if not used_before(num, generation): + self.xref[generation][num] = byte_offset # type: ignore + elif xref_type == 2: + # compressed objects + objstr_num = get_entry(1) + obstr_idx = get_entry(2) + generation = 0 # PDF spec table 18, generation is 0 + if not used_before(num, generation): + self.xref_objStm[num] = (objstr_num, obstr_idx) + elif self.strict: + raise PdfReadError(f"Unknown xref type: {xref_type}") + + def _pairs(self, array: List[int]) -> Iterable[Tuple[int, int]]: + """Iterate over pairs in the array.""" + i = 0 + while i + 1 < len(array): + yield array[i], array[i + 1] + i += 2 + + def decrypt(self, password: Union[str, bytes]) -> PasswordType: + """ + When using an encrypted / secured PDF file with the PDF Standard + encryption handler, this function will allow the file to be decrypted. + It checks the given password against the document's user password and + owner password, and then stores the resulting decryption key if either + password is correct. + + It does not matter which password was matched. Both passwords provide + the correct decryption key that will allow the document to be used with + this library. + + Args: + password: The password to match. + + Returns: + An indicator if the document was decrypted and whether it was the + owner password or the user password. + + """ + if not self._encryption: + raise PdfReadError("Not encrypted file") + # TODO: raise Exception for wrong password + return self._encryption.verify(password) + + @property + def is_encrypted(self) -> bool: + """ + Read-only boolean property showing whether this PDF file is encrypted. + + Note that this property, if true, will remain true even after the + :meth:`decrypt()` method is called. + """ + return TK.ENCRYPT in self.trailer + + def add_form_topname(self, name: str) -> Optional[DictionaryObject]: + """ + Add a top level form that groups all form fields below it. + + Args: + name: text string of the "/T" Attribute of the created object + + Returns: + The created object. ``None`` means no object was created. + + """ + catalog = self.root_object + + if "/AcroForm" not in catalog or not isinstance( + catalog["/AcroForm"], DictionaryObject + ): + return None + acroform = cast(DictionaryObject, catalog[NameObject("/AcroForm")]) + if "/Fields" not in acroform: + # TODO: No error but this may be extended for XFA Forms + return None + + interim = DictionaryObject() + interim[NameObject("/T")] = TextStringObject(name) + interim[NameObject("/Kids")] = acroform[NameObject("/Fields")] + self.cache_indirect_object( + 0, + max(i for (g, i) in self.resolved_objects if g == 0) + 1, + interim, + ) + arr = ArrayObject() + arr.append(interim.indirect_reference) + acroform[NameObject("/Fields")] = arr + for o in cast(ArrayObject, interim["/Kids"]): + obj = o.get_object() + if "/Parent" in obj: + logger_warning( + f"Top Level Form Field {obj.indirect_reference} have a non-expected parent", + __name__, + ) + obj[NameObject("/Parent")] = interim.indirect_reference + return interim + + def rename_form_topname(self, name: str) -> Optional[DictionaryObject]: + """ + Rename top level form field that all form fields below it. + + Args: + name: text string of the "/T" field of the created object + + Returns: + The modified object. ``None`` means no object was modified. + + """ + catalog = self.root_object + + if "/AcroForm" not in catalog or not isinstance( + catalog["/AcroForm"], DictionaryObject + ): + return None + acroform = cast(DictionaryObject, catalog[NameObject("/AcroForm")]) + if "/Fields" not in acroform: + return None + + interim = cast( + DictionaryObject, + cast(ArrayObject, acroform[NameObject("/Fields")])[0].get_object(), + ) + interim[NameObject("/T")] = TextStringObject(name) + return interim + + def _repr_mimebundle_( + self, + include: Union[None, Iterable[str]] = None, + exclude: Union[None, Iterable[str]] = None, + ) -> Dict[str, Any]: + """ + Integration into Jupyter Notebooks. + + This method returns a dictionary that maps a mime-type to its + representation. + + .. seealso:: + + https://ipython.readthedocs.io/en/stable/config/integrating.html + """ + self.stream.seek(0) + pdf_data = self.stream.read() + data = { + "application/pdf": pdf_data, + } + + if include is not None: + # Filter representations based on include list + data = {k: v for k, v in data.items() if k in include} + + if exclude is not None: + # Remove representations based on exclude list + data = {k: v for k, v in data.items() if k not in exclude} + + return data diff --git a/venv/lib/python3.12/site-packages/pypdf/_text_extraction/__init__.py b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/__init__.py new file mode 100644 index 0000000..66be6ff --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/__init__.py @@ -0,0 +1,248 @@ +""" +Code related to text extraction. + +Some parts are still in _page.py. In doubt, they will stay there. +""" + +import math +from typing import Any, Callable, Dict, List, Optional, Tuple, Union + +from ..generic import DictionaryObject, TextStringObject, encode_pdfdocencoding + +CUSTOM_RTL_MIN: int = -1 +CUSTOM_RTL_MAX: int = -1 +CUSTOM_RTL_SPECIAL_CHARS: List[int] = [] +LAYOUT_NEW_BT_GROUP_SPACE_WIDTHS: int = 5 + + +class OrientationNotFoundError(Exception): + pass + + +def set_custom_rtl( + _min: Union[str, int, None] = None, + _max: Union[str, int, None] = None, + specials: Union[str, List[int], None] = None, +) -> Tuple[int, int, List[int]]: + """ + Change the Right-To-Left and special characters custom parameters. + + Args: + _min: The new minimum value for the range of custom characters that + will be written right to left. + If set to ``None``, the value will not be changed. + If set to an integer or string, it will be converted to its ASCII code. + The default value is -1, which sets no additional range to be converted. + _max: The new maximum value for the range of custom characters that will + be written right to left. + If set to ``None``, the value will not be changed. + If set to an integer or string, it will be converted to its ASCII code. + The default value is -1, which sets no additional range to be converted. + specials: The new list of special characters to be inserted in the + current insertion order. + If set to ``None``, the current value will not be changed. + If set to a string, it will be converted to a list of ASCII codes. + The default value is an empty list. + + Returns: + A tuple containing the new values for ``CUSTOM_RTL_MIN``, + ``CUSTOM_RTL_MAX``, and ``CUSTOM_RTL_SPECIAL_CHARS``. + + """ + global CUSTOM_RTL_MIN, CUSTOM_RTL_MAX, CUSTOM_RTL_SPECIAL_CHARS + if isinstance(_min, int): + CUSTOM_RTL_MIN = _min + elif isinstance(_min, str): + CUSTOM_RTL_MIN = ord(_min) + if isinstance(_max, int): + CUSTOM_RTL_MAX = _max + elif isinstance(_max, str): + CUSTOM_RTL_MAX = ord(_max) + if isinstance(specials, str): + CUSTOM_RTL_SPECIAL_CHARS = [ord(x) for x in specials] + elif isinstance(specials, list): + CUSTOM_RTL_SPECIAL_CHARS = specials + return CUSTOM_RTL_MIN, CUSTOM_RTL_MAX, CUSTOM_RTL_SPECIAL_CHARS + + +def mult(m: List[float], n: List[float]) -> List[float]: + return [ + m[0] * n[0] + m[1] * n[2], + m[0] * n[1] + m[1] * n[3], + m[2] * n[0] + m[3] * n[2], + m[2] * n[1] + m[3] * n[3], + m[4] * n[0] + m[5] * n[2] + n[4], + m[4] * n[1] + m[5] * n[3] + n[5], + ] + + +def orient(m: List[float]) -> int: + if m[3] > 1e-6: + return 0 + elif m[3] < -1e-6: + return 180 + elif m[1] > 0: + return 90 + else: + return 270 + + +def crlf_space_check( + text: str, + cmtm_prev: Tuple[List[float], List[float]], + cmtm_matrix: Tuple[List[float], List[float]], + memo_cmtm: Tuple[List[float], List[float]], + cmap: Tuple[ + Union[str, Dict[int, str]], Dict[str, str], str, Optional[DictionaryObject] + ], + orientations: Tuple[int, ...], + output: str, + font_size: float, + visitor_text: Optional[Callable[[Any, Any, Any, Any, Any], None]], + str_widths: float, + spacewidth: float, + str_height: float, +) -> Tuple[str, str, List[float], List[float]]: + cm_prev = cmtm_prev[0] + tm_prev = cmtm_prev[1] + cm_matrix = cmtm_matrix[0] + tm_matrix = cmtm_matrix[1] + memo_cm = memo_cmtm[0] + memo_tm = memo_cmtm[1] + + m_prev = mult(tm_prev, cm_prev) + m = mult(tm_matrix, cm_matrix) + orientation = orient(m) + delta_x = m[4] - m_prev[4] + delta_y = m[5] - m_prev[5] + # Table 108 of the 1.7 reference ("Text positioning operators") + scale_prev_x = math.sqrt(tm_prev[0]**2 + tm_prev[1]**2) + scale_prev_y = math.sqrt(tm_prev[2]**2 + tm_prev[3]**2) + scale_y = math.sqrt(tm_matrix[2]**2 + tm_matrix[3]**2) + cm_prev = m + + if orientation not in orientations: + raise OrientationNotFoundError + if orientation in (0, 180): + moved_height: float = delta_y + moved_width: float = delta_x + elif orientation in (90, 270): + moved_height = delta_x + moved_width = delta_y + try: + if abs(moved_height) > 0.8 * min(str_height * scale_prev_y, font_size * scale_y): + if (output + text)[-1] != "\n": + output += text + "\n" + if visitor_text is not None: + visitor_text( + text + "\n", + memo_cm, + memo_tm, + cmap[3], + font_size, + ) + text = "" + elif ( + (moved_width >= (spacewidth + str_widths) * scale_prev_x) + and (output + text)[-1] != " " + ): + text += " " + except Exception: + pass + tm_prev = tm_matrix.copy() + cm_prev = cm_matrix.copy() + return text, output, cm_prev, tm_prev + + +def get_text_operands( + operands: List[Union[str, TextStringObject]], + cm_matrix: List[float], + tm_matrix: List[float], + cmap: Tuple[ + Union[str, Dict[int, str]], Dict[str, str], str, Optional[DictionaryObject] + ], + orientations: Tuple[int, ...] +) -> Tuple[str, bool]: + t: str = "" + is_str_operands = False + m = mult(tm_matrix, cm_matrix) + orientation = orient(m) + if orientation in orientations and len(operands) > 0: + if isinstance(operands[0], str): + t = operands[0] + is_str_operands = True + else: + t = "" + tt: bytes = ( + encode_pdfdocencoding(operands[0]) + if isinstance(operands[0], str) + else operands[0] + ) + if isinstance(cmap[0], str): + try: + t = tt.decode(cmap[0], "surrogatepass") # apply str encoding + except Exception: + # the data does not match the expectation, + # we use the alternative ; + # text extraction may not be good + t = tt.decode( + "utf-16-be" if cmap[0] == "charmap" else "charmap", + "surrogatepass", + ) # apply str encoding + else: # apply dict encoding + t = "".join( + [cmap[0][x] if x in cmap[0] else bytes((x,)).decode() for x in tt] + ) + return (t, is_str_operands) + + +def get_display_str( + text: str, + cm_matrix: List[float], + tm_matrix: List[float], + cmap: Tuple[ + Union[str, Dict[int, str]], Dict[str, str], str, Optional[DictionaryObject] + ], + text_operands: str, + font_size: float, + rtl_dir: bool, + visitor_text: Optional[Callable[[Any, Any, Any, Any, Any], None]] +) -> Tuple[str, bool]: + # "\u0590 - \u08FF \uFB50 - \uFDFF" + for x in [cmap[1].get(x, x) for x in text_operands]: + # x can be a sequence of bytes ; ex: habibi.pdf + if len(x) == 1: + xx = ord(x) + else: + xx = 1 + # fmt: off + if ( + # cases where the current inserting order is kept + (xx <= 0x2F) # punctuations but... + or 0x3A <= xx <= 0x40 # numbers (x30-39) + or 0x2000 <= xx <= 0x206F # upper punctuations.. + or 0x20A0 <= xx <= 0x21FF # but (numbers) indices/exponents + or xx in CUSTOM_RTL_SPECIAL_CHARS # customized.... + ): + text = x + text if rtl_dir else text + x + elif ( # right-to-left characters set + 0x0590 <= xx <= 0x08FF + or 0xFB1D <= xx <= 0xFDFF + or 0xFE70 <= xx <= 0xFEFF + or CUSTOM_RTL_MIN <= xx <= CUSTOM_RTL_MAX + ): + if not rtl_dir: + rtl_dir = True + if visitor_text is not None: + visitor_text(text, cm_matrix, tm_matrix, cmap[3], font_size) + text = "" + text = x + text + else: # left-to-right + if rtl_dir: + rtl_dir = False + if visitor_text is not None: + visitor_text(text, cm_matrix, tm_matrix, cmap[3], font_size) + text = "" + text = text + x + # fmt: on + return text, rtl_dir diff --git a/venv/lib/python3.12/site-packages/pypdf/_text_extraction/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b2dd35c3fb90563b1296526427351f876324f7eb GIT binary patch literal 9580 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 T_5P2bOhdih4;z6+x9R@?3-wt> literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__init__.py b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__init__.py new file mode 100644 index 0000000..3e27757 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__init__.py @@ -0,0 +1,16 @@ +"""Layout mode text extraction extension for pypdf""" +from ._fixed_width_page import ( + fixed_char_width, + fixed_width_page, + text_show_operations, + y_coordinate_groups, +) +from ._font import Font + +__all__ = [ + "Font", + "fixed_char_width", + "fixed_width_page", + "text_show_operations", + "y_coordinate_groups", +] diff --git a/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..84eb3f6c9be7c11286e7594532ce9f25e832ea87 GIT binary patch literal 518 zcmZutJx?4l5ViLcNKOd~1r@q>3$XIlMJcIBgebQeEo<+t#qQd&eRnKfenHCgbonj$ z1=*CT=n$s_=_9}HbgX)p#U@346MBd|#2yla&)N2v0&rCVjJxo!{ifMdC1VT~imoMn zZPB&>-^miy$V#(Db%M#dmwqnxNg+|@)Tr7BYuQ}%bJogprU%!k{_WB0H_S>W4s}sp z;C2=t&<_UdB{!xqXxEN{ca#B0lm$4_!)ogTre>}9XkOp|-bZ_Ya2rxef0Fn2K}>@s ULHP5W(EYn8c@}(0%>=(Z0Px6}(EtDd literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/_fixed_width_page.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/_fixed_width_page.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..878e4e72b4540a63b5cd415e9927dc5f161ae5e6 GIT binary patch literal 18033 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/_font_widths.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/_font_widths.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..30245d073cab2c5a24bbddaaf7e3821335c525f2 GIT binary patch literal 4725 zcma*pNo-Wf83*w9wegBKU|?X_j13qYOdA`pu?=`%u-i7a!C;nlyQ|%Pcxlt!wlU0l zh%&c~ltVJgNJ$Q(Fv^8P4mm{193$lr^`J;rC5lGMCEN@Xg4*&e+NB>HGRp~f?_p$R+W*Xle%XgfgIIg1{ML#ALLd{dVxSg*G zxE7)osbX%IsNGykRTJikV zsK-!`qgJ7wK&?it!5Sw~Php?asI{nPR2}bJug-Ek=U?NO{!R_J+Vd*Ry^W|B(9?w3 z&FUieUqb(7tlOemx#tSzv|-nF)xkYiG3OfQU&m;t>f-)xzm1)G(A$f3`><9&>Hw~8 z5Ni#g-oPHiXpf*qP)9L;40Rm!Ch7$0q<=TD(-dakLcNVTjd}<5F6s>GJ=FWC4^SUs zttjd&dSa+^xTZMT%CBFNBGt;j3H~kMR|nSuHUC8kuE9}B{`4U{;XJj#?R>0Ih+2eu zR)V`#s$3p@`=t2yc%OR2bwAeGIVt{{2ho4XUk4|}pL-aq9zi{ddJOeAY8C1U)N0hX zPl~_KX{=g{dPXgBPrX{=dd`2YZ=Do=p8q*1{)uYBJ!!`C-#ID%sc*q~zk>cYJoR>b zKXy)vf8ws=y`7k2pA`Q)wR2MZdHt9%fD<){_7Lg~tUHXmJc4HyL3>m!^Sj3IS;x_H z6Q5}UJ(GUhoD~1=-NM*y%$vrHJE(WD;tc9N^xQ}L0rq}~o+#=pY7BJ_>%{Ttl|P?P zN~>B_Vbr~9MWy()EGI>+ei52+67+}@=D&Xuj(U8EJ5~DEAsOSIOb0jr&-|=4f9-qB zZ?)#HV?OWW@67vc7(X%IG{%+j_*37T&+6XysLDM+j^oh@kE-1`nluwwibh>}yJvDV{>ekfbe#5<*dNuWF>en>jmSA{L z(~zbc?mu~VO~aZ-G)3GljE!m<(=@K>ruzaN6PhM9O=-HN>9(e6O?Nci)imSLJ&*2t z^uVKsnxY=fYKm!^(-haFG$l06Yf5Tb(Bx`*q-jyplBQ)%E1FW8Ry94=l-88dlzsI# zzB_d#n$|R}YueECMAN3Gryf1?i0}3X9)0-A<4NvM`LbXA#&2EZ&*%P*>3+`F>i*ep z-SMs`3#e<2Z^+eW<$8`RbyPU|Rlm6T8__w97C$*M#6KVG!{>LnxiLK7}x+}@K zST>^zCO4PoQcJqT%o$B=r04maI=?IJ#+Gy$7USND)N*WPv@TCqOip!;_I6G5MyH2* zrv@kWF6G9vx@bO~T3$?SX1;R1#eoI+aW(GMVst zVr4zN!kbBrM87}a!kbBrM87(vc4f}CRnImZZcjuGS> zBgi>MkaG+>=a_cRG3}gV+BwIxbB<}}9MjG@rk!(4JLi~o&N1zrW7;{#v~!MW=N!|{ zIi{U+Ogrb8cFr;FoMYNK$Fy^fY3Cf%&N-%?b4)wun0C%F?VMxUImfhfj%nu{)6O}j zopVe(=a}8*tL*0-)6O}jopVe(=a_cRG3}gV+BwIxbB<}}9MjG@rk!(4JLi~o&N1zr zW7;{#v~!MW=N!|{Ii{U+Ogrb8cFr-sSI(6eyza~E$=etDxMF*}z{xNEVdRs@XW?Je z=JwV?dYJb)6%Z3*fUl-;Y2mf&LW%by{6`z&ooa0+Z zs(v2%Jn}sJ+uB@x_t!lyj|}oiQO-H^ZB_V1ajvS3S(ZXK?F-kv+$!Ys@=2e)dP TUbN(D+L;yKI92I1|FQXRu-_}s literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/_text_state_manager.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/_text_state_manager.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..616ecb43db3892e6645de1cc22019387c2cdec88 GIT binary patch literal 11742 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 A4FCWD literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/_text_state_params.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/__pycache__/_text_state_params.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5ed39cce345df9e13b2b4256398e3b07927f8d4 GIT binary patch literal 7394 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 F{{@yW^GpB$ literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_fixed_width_page.py b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_fixed_width_page.py new file mode 100644 index 0000000..30e501f --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_fixed_width_page.py @@ -0,0 +1,394 @@ +"""Extract PDF text preserving the layout of the source PDF""" + +from itertools import groupby +from math import ceil +from pathlib import Path +from typing import Any, Dict, Iterator, List, Literal, Optional, Tuple, TypedDict + +from ..._utils import logger_warning +from .. import LAYOUT_NEW_BT_GROUP_SPACE_WIDTHS +from ._font import Font +from ._text_state_manager import TextStateManager +from ._text_state_params import TextStateParams + + +class BTGroup(TypedDict): + """ + Dict describing a line of text rendered within a BT/ET operator pair. + If multiple text show operations render text on the same line, the text + will be combined into a single BTGroup dict. + + Keys: + tx: x coordinate of first character in BTGroup + ty: y coordinate of first character in BTGroup + font_size: nominal font size + font_height: effective font height + text: rendered text + displaced_tx: x coordinate of last character in BTGroup + flip_sort: -1 if page is upside down, else 1 + """ + + tx: float + ty: float + font_size: float + font_height: float + text: str + displaced_tx: float + flip_sort: Literal[-1, 1] + + +def bt_group(tj_op: TextStateParams, rendered_text: str, dispaced_tx: float) -> BTGroup: + """ + BTGroup constructed from a TextStateParams instance, rendered text, and + displaced tx value. + + Args: + tj_op (TextStateParams): TextStateParams instance + rendered_text (str): rendered text + dispaced_tx (float): x coordinate of last character in BTGroup + + """ + return BTGroup( + tx=tj_op.tx, + ty=tj_op.ty, + font_size=tj_op.font_size, + font_height=tj_op.font_height, + text=rendered_text, + displaced_tx=dispaced_tx, + flip_sort=-1 if tj_op.flip_vertical else 1, + ) + + +def recurs_to_target_op( + ops: Iterator[Tuple[List[Any], bytes]], + text_state_mgr: TextStateManager, + end_target: Literal[b"Q", b"ET"], + fonts: Dict[str, Font], + strip_rotated: bool = True, +) -> Tuple[List[BTGroup], List[TextStateParams]]: + """ + Recurse operators between BT/ET and/or q/Q operators managing the transform + stack and capturing text positioning and rendering data. + + Args: + ops: iterator of operators in content stream + text_state_mgr: a TextStateManager instance + end_target: Either b"Q" (ends b"q" op) or b"ET" (ends b"BT" op) + fonts: font dictionary as returned by PageObject._layout_mode_fonts() + + Returns: + tuple: list of BTGroup dicts + list of TextStateParams dataclass instances. + + """ + # 1 entry per line of text rendered within each BT/ET operation. + bt_groups: List[BTGroup] = [] + + # 1 entry per text show operator (Tj/TJ/'/") + tj_ops: List[TextStateParams] = [] + + if end_target == b"Q": + # add new q level. cm's added at this level will be popped at next b'Q' + text_state_mgr.add_q() + + while True: + try: + operands, op = next(ops) + except StopIteration: + return bt_groups, tj_ops + if op == end_target: + if op == b"Q": + text_state_mgr.remove_q() + if op == b"ET": + if not tj_ops: + return bt_groups, tj_ops + _text = "" + bt_idx = 0 # idx of first tj in this bt group + last_displaced_tx = tj_ops[bt_idx].displaced_tx + last_ty = tj_ops[bt_idx].ty + for _idx, _tj in enumerate( + tj_ops + ): # ... build text from new Tj operators + if strip_rotated and _tj.rotated: + continue + if not _tj.font.interpretable: # generates warning + continue + # if the y position of the text is greater than the font height, assume + # the text is on a new line and start a new group + if abs(_tj.ty - last_ty) > _tj.font_height: + if _text.strip(): + bt_groups.append( + bt_group(tj_ops[bt_idx], _text, last_displaced_tx) + ) + bt_idx = _idx + _text = "" + + # if the x position of the text is less than the last x position by + # more than 5 spaces widths, assume the text order should be flipped + # and start a new group + if ( + last_displaced_tx - _tj.tx + > _tj.space_tx * LAYOUT_NEW_BT_GROUP_SPACE_WIDTHS + ): + if _text.strip(): + bt_groups.append( + bt_group(tj_ops[bt_idx], _text, last_displaced_tx) + ) + bt_idx = _idx + last_displaced_tx = _tj.displaced_tx + _text = "" + + # calculate excess x translation based on ending tx of previous Tj. + # multiply by bool (_idx != bt_idx) to ensure spaces aren't double + # applied to the first tj of a BTGroup in fixed_width_page(). + excess_tx = round(_tj.tx - last_displaced_tx, 3) * (_idx != bt_idx) + # space_tx could be 0 if either Tz or font_size was 0 for this _tj. + spaces = int(excess_tx // _tj.space_tx) if _tj.space_tx else 0 + new_text = f'{" " * spaces}{_tj.txt}' + + last_ty = _tj.ty + _text = f"{_text}{new_text}" + last_displaced_tx = _tj.displaced_tx + if _text: + bt_groups.append(bt_group(tj_ops[bt_idx], _text, last_displaced_tx)) + text_state_mgr.reset_tm() + return bt_groups, tj_ops + if op == b"q": + bts, tjs = recurs_to_target_op( + ops, text_state_mgr, b"Q", fonts, strip_rotated + ) + bt_groups.extend(bts) + tj_ops.extend(tjs) + elif op == b"cm": + text_state_mgr.add_cm(*operands) + elif op == b"BT": + bts, tjs = recurs_to_target_op( + ops, text_state_mgr, b"ET", fonts, strip_rotated + ) + bt_groups.extend(bts) + tj_ops.extend(tjs) + elif op == b"Tj": + tj_ops.append(text_state_mgr.text_state_params(operands[0])) + elif op == b"TJ": + _tj = text_state_mgr.text_state_params() + for tj_op in operands[0]: + if isinstance(tj_op, bytes): + _tj = text_state_mgr.text_state_params(tj_op) + tj_ops.append(_tj) + else: + text_state_mgr.add_trm(_tj.displacement_matrix(TD_offset=tj_op)) + elif op == b"'": + text_state_mgr.reset_trm() + text_state_mgr.add_tm([0, -text_state_mgr.TL]) + tj_ops.append(text_state_mgr.text_state_params(operands[0])) + elif op == b'"': + text_state_mgr.reset_trm() + text_state_mgr.set_state_param(b"Tw", operands[0]) + text_state_mgr.set_state_param(b"Tc", operands[1]) + text_state_mgr.add_tm([0, -text_state_mgr.TL]) + tj_ops.append(text_state_mgr.text_state_params(operands[2])) + elif op in (b"Td", b"Tm", b"TD", b"T*"): + text_state_mgr.reset_trm() + if op == b"Tm": + text_state_mgr.reset_tm() + elif op == b"TD": + text_state_mgr.set_state_param(b"TL", -operands[1]) + elif op == b"T*": + operands = [0, -text_state_mgr.TL] + text_state_mgr.add_tm(operands) + elif op == b"Tf": + text_state_mgr.set_font(fonts[operands[0]], operands[1]) + else: # handle Tc, Tw, Tz, TL, and Ts operators + text_state_mgr.set_state_param(op, operands) + + +def y_coordinate_groups( + bt_groups: List[BTGroup], debug_path: Optional[Path] = None +) -> Dict[int, List[BTGroup]]: + """ + Group text operations by rendered y coordinate, i.e. the line number. + + Args: + bt_groups: list of dicts as returned by text_show_operations() + debug_path (Path, optional): Path to a directory for saving debug output. + + Returns: + Dict[int, List[BTGroup]]: dict of lists of text rendered by each BT operator + keyed by y coordinate + + """ + ty_groups = { + ty: sorted(grp, key=lambda x: x["tx"]) + for ty, grp in groupby( + bt_groups, key=lambda bt_grp: int(bt_grp["ty"] * bt_grp["flip_sort"]) + ) + } + # combine groups whose y coordinates differ by less than the effective font height + # (accounts for mixed fonts and other minor oddities) + last_ty = next(iter(ty_groups)) + last_txs = {int(_t["tx"]) for _t in ty_groups[last_ty] if _t["text"].strip()} + for ty in list(ty_groups)[1:]: + fsz = min(ty_groups[_y][0]["font_height"] for _y in (ty, last_ty)) + txs = {int(_t["tx"]) for _t in ty_groups[ty] if _t["text"].strip()} + # prevent merge if both groups are rendering in the same x position. + no_text_overlap = not (txs & last_txs) + offset_less_than_font_height = abs(ty - last_ty) < fsz + if no_text_overlap and offset_less_than_font_height: + ty_groups[last_ty] = sorted( + ty_groups.pop(ty) + ty_groups[last_ty], key=lambda x: x["tx"] + ) + last_txs |= txs + else: + last_ty = ty + last_txs = txs + if debug_path: # pragma: no cover + import json + + debug_path.joinpath("bt_groups.json").write_text( + json.dumps(ty_groups, indent=2, default=str), "utf-8" + ) + return ty_groups + + +def text_show_operations( + ops: Iterator[Tuple[List[Any], bytes]], + fonts: Dict[str, Font], + strip_rotated: bool = True, + debug_path: Optional[Path] = None, +) -> List[BTGroup]: + """ + Extract text from BT/ET operator pairs. + + Args: + ops (Iterator[Tuple[List, bytes]]): iterator of operators in content stream + fonts (Dict[str, Font]): font dictionary + strip_rotated: Removes text if rotated w.r.t. to the page. Defaults to True. + debug_path (Path, optional): Path to a directory for saving debug output. + + Returns: + List[BTGroup]: list of dicts of text rendered by each BT operator + + """ + state_mgr = TextStateManager() # transformation stack manager + debug = bool(debug_path) + bt_groups: List[BTGroup] = [] # BT operator dict + tj_debug: List[TextStateParams] = [] # Tj/TJ operator data (debug only) + try: + warned_rotation = False + warned_uninterpretable_font = False + while True: + operands, op = next(ops) + if op in (b"BT", b"q"): + bts, tjs = recurs_to_target_op( + ops, state_mgr, b"ET" if op == b"BT" else b"Q", fonts, strip_rotated + ) + if not warned_rotation and any(tj.rotated for tj in tjs): + warned_rotation = True + if strip_rotated: + logger_warning( + "Rotated text discovered. Output will be incomplete.", + __name__, + ) + else: + logger_warning( + "Rotated text discovered. Layout will be degraded.", + __name__, + ) + if not warned_uninterpretable_font and any(not tj.font.interpretable for tj in tjs): + warned_uninterpretable_font = True + logger_warning( + "PDF contains an uninterpretable font. Output will be incomplete.", + __name__, + ) + bt_groups.extend(bts) + if debug: # pragma: no cover + tj_debug.extend(tjs) + elif op == b"Tf": + state_mgr.set_font(fonts[operands[0]], operands[1]) + else: # set Tc, Tw, Tz, TL, and Ts if required. ignores all other ops + state_mgr.set_state_param(op, operands) + except StopIteration: + pass + + # left align the data, i.e. decrement all tx values by min(tx) + min_x = min((x["tx"] for x in bt_groups), default=0.0) + bt_groups = [ + dict(ogrp, tx=ogrp["tx"] - min_x, displaced_tx=ogrp["displaced_tx"] - min_x) # type: ignore[misc] + for ogrp in sorted( + bt_groups, key=lambda x: (x["ty"] * x["flip_sort"], -x["tx"]), reverse=True + ) + ] + + if debug_path: # pragma: no cover + import json + + debug_path.joinpath("bts.json").write_text( + json.dumps(bt_groups, indent=2, default=str), "utf-8" + ) + debug_path.joinpath("tjs.json").write_text( + json.dumps( + tj_debug, indent=2, default=lambda x: getattr(x, "to_dict", str)(x) + ), + "utf-8", + ) + return bt_groups + + +def fixed_char_width(bt_groups: List[BTGroup], scale_weight: float = 1.25) -> float: + """ + Calculate average character width weighted by the length of the rendered + text in each sample for conversion to fixed-width layout. + + Args: + bt_groups (List[BTGroup]): List of dicts of text rendered by each + BT operator + + Returns: + float: fixed character width + + """ + char_widths = [] + for _bt in bt_groups: + _len = len(_bt["text"]) * scale_weight + char_widths.append(((_bt["displaced_tx"] - _bt["tx"]) / _len, _len)) + return sum(_w * _l for _w, _l in char_widths) / sum(_l for _, _l in char_widths) + + +def fixed_width_page( + ty_groups: Dict[int, List[BTGroup]], char_width: float, space_vertically: bool, font_height_weight: float +) -> str: + """ + Generate page text from text operations grouped by rendered y coordinate. + + Args: + ty_groups: dict of text show ops as returned by y_coordinate_groups() + char_width: fixed character width + space_vertically: include blank lines inferred from y distance + font height. + font_height_weight: multiplier for font height when calculating blank lines. + + Returns: + str: page text in a fixed width format that closely adheres to the rendered + layout in the source pdf. + + """ + lines: List[str] = [] + last_y_coord = 0 + for y_coord, line_data in ty_groups.items(): + if space_vertically and lines: + fh = line_data[0]["font_height"] + blank_lines = 0 if fh == 0 else ( + int(abs(y_coord - last_y_coord) / (fh * font_height_weight)) - 1 + ) + lines.extend([""] * blank_lines) + line = "" + last_disp = 0.0 + for bt_op in line_data: + offset = int(bt_op["tx"] // char_width) + spaces = (offset - len(line)) * (ceil(last_disp) < int(bt_op["tx"])) + line = f"{line}{' ' * spaces}{bt_op['text']}" + last_disp = bt_op["displaced_tx"] + if line.strip() or lines: + lines.append( + "".join(c if ord(c) < 14 or ord(c) > 31 else " " for c in line) + ) + last_y_coord = y_coord + return "\n".join(ln.rstrip() for ln in lines if space_vertically or ln.strip()) diff --git a/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_font.py b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_font.py new file mode 100644 index 0000000..08946f1 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_font.py @@ -0,0 +1,152 @@ +"""Font constants and classes for "layout" mode text operations""" + +from dataclasses import dataclass, field +from typing import Any, Dict, Sequence, Union, cast + +from ..._codecs import adobe_glyphs +from ...errors import ParseError +from ...generic import IndirectObject +from ._font_widths import STANDARD_WIDTHS + + +@dataclass +class Font: + """ + A font object formatted for use during "layout" mode text extraction + + Attributes: + subtype (str): font subtype + space_width (int | float): width of a space character + encoding (str | Dict[int, str]): font encoding + char_map (dict): character map + font_dictionary (dict): font dictionary + width_map (Dict[str, int]): mapping of characters to widths + interpretable (bool): Default True. If False, the font glyphs cannot + be translated to characters, e.g. Type3 fonts that do not define + a '/ToUnicode' mapping. + + """ + + subtype: str + space_width: Union[int, float] + encoding: Union[str, Dict[int, str]] + char_map: Dict[Any, Any] + font_dictionary: Dict[Any, Any] + width_map: Dict[str, int] = field(default_factory=dict, init=False) + interpretable: bool = True + + def __post_init__(self) -> None: + # Type3 fonts that do not specify a "/ToUnicode" mapping cannot be + # reliably converted into character codes unless all named chars + # in /CharProcs map to a standard adobe glyph. See § 9.10.2 of the + # PDF 1.7 standard. + if self.subtype == "/Type3" and "/ToUnicode" not in self.font_dictionary: + self.interpretable = all( + cname in adobe_glyphs + for cname in self.font_dictionary.get("/CharProcs") or [] + ) + + if not self.interpretable: # save some overhead if font is not interpretable + return + + # TrueType fonts have a /Widths array mapping character codes to widths + if isinstance(self.encoding, dict) and "/Widths" in self.font_dictionary: + first_char = self.font_dictionary.get("/FirstChar", 0) + self.width_map = { + self.encoding.get(idx + first_char, chr(idx + first_char)): width + for idx, width in enumerate(self.font_dictionary["/Widths"]) + } + + # CID fonts have a /W array mapping character codes to widths stashed in /DescendantFonts + if "/DescendantFonts" in self.font_dictionary: + d_font: Dict[Any, Any] + for d_font_idx, d_font in enumerate( + self.font_dictionary["/DescendantFonts"] + ): + while isinstance(d_font, IndirectObject): + d_font = d_font.get_object() + self.font_dictionary["/DescendantFonts"][d_font_idx] = d_font + ord_map = { + ord(_target): _surrogate + for _target, _surrogate in self.char_map.items() + if isinstance(_target, str) + } + # /W width definitions have two valid formats which can be mixed and matched: + # (1) A character start index followed by a list of widths, e.g. + # `45 [500 600 700]` applies widths 500, 600, 700 to characters 45-47. + # (2) A character start index, a character stop index, and a width, e.g. + # `45 65 500` applies width 500 to characters 45-65. + skip_count = 0 + _w = d_font.get("/W", []) + for idx, w_entry in enumerate(_w): + w_entry = w_entry.get_object() + if skip_count: + skip_count -= 1 + continue + if not isinstance(w_entry, (int, float)): # pragma: no cover + # We should never get here due to skip_count above. Add a + # warning and or use reader's "strict" to force an ex??? + continue + # check for format (1): `int [int int int int ...]` + w_next_entry = _w[idx + 1].get_object() + if isinstance(w_next_entry, Sequence): + start_idx, width_list = w_entry, w_next_entry + self.width_map.update( + { + ord_map[_cidx]: _width + for _cidx, _width in zip( + range( + cast(int, start_idx), + cast(int, start_idx) + len(width_list), + 1, + ), + width_list, + ) + if _cidx in ord_map + } + ) + skip_count = 1 + # check for format (2): `int int int` + elif isinstance(w_next_entry, (int, float)) and isinstance( + _w[idx + 2].get_object(), (int, float) + ): + start_idx, stop_idx, const_width = ( + w_entry, + w_next_entry, + _w[idx + 2].get_object(), + ) + self.width_map.update( + { + ord_map[_cidx]: const_width + for _cidx in range( + cast(int, start_idx), cast(int, stop_idx + 1), 1 + ) + if _cidx in ord_map + } + ) + skip_count = 2 + else: + # Note: this doesn't handle the case of out of bounds (reaching the end of the width definitions + # while expecting more elements). This raises an IndexError which is sufficient. + raise ParseError( + f"Invalid font width definition. Next elements: {w_entry}, {w_next_entry}, {_w[idx + 2]}" + ) # pragma: no cover + + if not self.width_map and "/BaseFont" in self.font_dictionary: + for key in STANDARD_WIDTHS: + if self.font_dictionary["/BaseFont"].startswith(f"/{key}"): + self.width_map = STANDARD_WIDTHS[key] + break + + def word_width(self, word: str) -> float: + """Sum of character widths specified in PDF font for the supplied word""" + return sum( + [self.width_map.get(char, self.space_width * 2) for char in word], 0.0 + ) + + @staticmethod + def to_dict(font_instance: "Font") -> Dict[str, Any]: + """Dataclass to dict for json.dumps serialization.""" + return { + k: getattr(font_instance, k) for k in font_instance.__dataclass_fields__ + } diff --git a/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_font_widths.py b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_font_widths.py new file mode 100644 index 0000000..85084ce --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_font_widths.py @@ -0,0 +1,208 @@ +# Widths for the standard 14 fonts as described on page 416 of the PDF 1.7 standard +STANDARD_WIDTHS = { + "Helvetica": { # 4 fonts, includes bold, oblique and boldoblique variants + " ": 278, + "!": 278, + '"': 355, + "#": 556, + "$": 556, + "%": 889, + "&": 667, + "'": 191, + "(": 333, + ")": 333, + "*": 389, + "+": 584, + ",": 278, + "-": 333, + ".": 278, + "/": 278, + "0": 556, + "1": 556, + "2": 556, + "3": 556, + "4": 556, + "5": 556, + "6": 556, + "7": 556, + "8": 556, + "9": 556, + ":": 278, + ";": 278, + "<": 584, + "=": 584, + ">": 584, + "?": 611, + "@": 975, + "A": 667, + "B": 667, + "C": 722, + "D": 722, + "E": 667, + "F": 611, + "G": 778, + "H": 722, + "I": 278, + "J": 500, + "K": 667, + "L": 556, + "M": 833, + "N": 722, + "O": 778, + "P": 667, + "Q": 944, + "R": 667, + "S": 667, + "T": 611, + "U": 278, + "V": 278, + "W": 584, + "X": 556, + "Y": 556, + "Z": 500, + "[": 556, + "\\": 556, + "]": 556, + "^": 278, + "_": 278, + "`": 278, + "a": 278, + "b": 278, + "c": 333, + "d": 556, + "e": 556, + "f": 556, + "g": 556, + "h": 556, + "i": 556, + "j": 556, + "k": 556, + "l": 556, + "m": 556, + "n": 278, + "o": 278, + "p": 556, + "q": 556, + "r": 500, + "s": 556, + "t": 556, + "u": 278, + "v": 500, + "w": 500, + "x": 222, + "y": 222, + "z": 556, + "{": 222, + "|": 833, + "}": 556, + "~": 556, + }, + "Times": { # 4 fonts, includes bold, oblique and boldoblique variants + " ": 250, + "!": 333, + '"': 408, + "#": 500, + "$": 500, + "%": 833, + "&": 778, + "'": 180, + "(": 333, + ")": 333, + "*": 500, + "+": 564, + ",": 250, + "-": 333, + ".": 250, + "/": 564, + "0": 500, + "1": 500, + "2": 500, + "3": 500, + "4": 500, + "5": 500, + "6": 500, + "7": 500, + "8": 500, + "9": 500, + ":": 278, + ";": 278, + "<": 564, + "=": 564, + ">": 564, + "?": 444, + "@": 921, + "A": 722, + "B": 667, + "C": 667, + "D": 722, + "E": 611, + "F": 556, + "G": 722, + "H": 722, + "I": 333, + "J": 389, + "K": 722, + "L": 611, + "M": 889, + "N": 722, + "O": 722, + "P": 556, + "Q": 722, + "R": 667, + "S": 556, + "T": 611, + "U": 722, + "V": 722, + "W": 944, + "X": 722, + "Y": 722, + "Z": 611, + "[": 333, + "\\": 278, + "]": 333, + "^": 469, + "_": 500, + "`": 333, + "a": 444, + "b": 500, + "c": 444, + "d": 500, + "e": 444, + "f": 333, + "g": 500, + "h": 500, + "i": 278, + "j": 278, + "k": 500, + "l": 278, + "m": 722, + "n": 500, + "o": 500, + "p": 500, + "q": 500, + "r": 333, + "s": 389, + "t": 278, + "u": 500, + "v": 444, + "w": 722, + "x": 500, + "y": 444, + "z": 389, + "{": 348, + "|": 220, + "}": 348, + "~": 469, + }, +} + +# 4 fonts, includes bold, oblique and bold oblique variants +STANDARD_WIDTHS[ + "Courier" +] = dict.fromkeys(STANDARD_WIDTHS["Times"], 600) # fixed width +STANDARD_WIDTHS["ZapfDingbats"] = dict.fromkeys(STANDARD_WIDTHS["Times"], 1000) # 1 font +STANDARD_WIDTHS["Symbol"] = dict.fromkeys(STANDARD_WIDTHS["Times"], 500) # 1 font +# add aliases per table H.3 on page 1110 of the PDF 1.7 standard +STANDARD_WIDTHS["CourierNew"] = STANDARD_WIDTHS["Courier"] +STANDARD_WIDTHS["Arial"] = STANDARD_WIDTHS["Helvetica"] +STANDARD_WIDTHS["TimesNewRoman"] = STANDARD_WIDTHS["Times"] diff --git a/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_text_state_manager.py b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_text_state_manager.py new file mode 100644 index 0000000..1af77fb --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_text_state_manager.py @@ -0,0 +1,217 @@ +"""manage the PDF transform stack during "layout" mode text extraction""" + +from collections import ChainMap, Counter +from typing import Any, Dict, List, MutableMapping, Union +from typing import ChainMap as ChainMapType +from typing import Counter as CounterType + +from ...errors import PdfReadError +from .. import mult +from ._font import Font +from ._text_state_params import TextStateParams + +TextStateManagerChainMapType = ChainMapType[Union[int, str], Union[float, bool]] +TextStateManagerDictType = MutableMapping[Union[int, str], Union[float, bool]] + + +class TextStateManager: + """ + Tracks the current text state including cm/tm/trm transformation matrices. + + Attributes: + transform_stack (ChainMap): ChainMap of cm/tm transformation matrices + q_queue (Counter[int]): Counter of q operators + q_depth (List[int]): list of q operator nesting levels + Tc (float): character spacing + Tw (float): word spacing + Tz (int): horizontal scaling + TL (float): leading + Ts (float): text rise + font (Font): font object + font_size (int | float): font size + + """ + + def __init__(self) -> None: + self.transform_stack: TextStateManagerChainMapType = ChainMap( + self.new_transform() + ) + self.q_queue: CounterType[int] = Counter() + self.q_depth = [0] + self.Tc: float = 0.0 + self.Tw: float = 0.0 + self.Tz: float = 100.0 + self.TL: float = 0.0 + self.Ts: float = 0.0 + self.font: Union[Font, None] = None + self.font_size: Union[int, float] = 0 + + def set_state_param(self, op: bytes, value: Union[float, List[Any]]) -> None: + """ + Set a text state parameter. Supports Tc, Tz, Tw, TL, and Ts operators. + + Args: + op: operator read from PDF stream as bytes. No action is taken + for unsupported operators (see supported operators above). + value (float | List[Any]): new parameter value. If a list, + value[0] is used. + + """ + if op not in [b"Tc", b"Tz", b"Tw", b"TL", b"Ts"]: + return + self.__setattr__(op.decode(), value[0] if isinstance(value, list) else value) + + def set_font(self, font: Font, size: float) -> None: + """ + Set the current font and font_size. + + Args: + font (Font): a layout mode Font + size (float): font size + + """ + self.font = font + self.font_size = size + + def text_state_params(self, value: Union[bytes, str] = "") -> TextStateParams: + """ + Create a TextStateParams instance to display a text string. Type[bytes] values + will be decoded implicitly. + + Args: + value (str | bytes): text to associate with the captured state. + + Raises: + PdfReadError: if font not set (no Tf operator in incoming pdf content stream) + + Returns: + TextStateParams: current text state parameters + + """ + if not isinstance(self.font, Font): + raise PdfReadError( + "font not set: is PDF missing a Tf operator?" + ) # pragma: no cover + if isinstance(value, bytes): + try: + if isinstance(self.font.encoding, str): + txt = value.decode(self.font.encoding, "surrogatepass") + else: + txt = "".join( + self.font.encoding[x] + if x in self.font.encoding + else bytes((x,)).decode() + for x in value + ) + except (UnicodeEncodeError, UnicodeDecodeError): + txt = value.decode("utf-8", "replace") + txt = "".join( + self.font.char_map.get(x, x) for x in txt + ) + else: + txt = value + return TextStateParams( + txt, + self.font, + self.font_size, + self.Tc, + self.Tw, + self.Tz, + self.TL, + self.Ts, + self.effective_transform, + ) + + @staticmethod + def raw_transform( + _a: float = 1.0, + _b: float = 0.0, + _c: float = 0.0, + _d: float = 1.0, + _e: float = 0.0, + _f: float = 0.0, + ) -> Dict[int, float]: + """Only a/b/c/d/e/f matrix params""" + return dict(zip(range(6), map(float, (_a, _b, _c, _d, _e, _f)))) + + @staticmethod + def new_transform( + _a: float = 1.0, + _b: float = 0.0, + _c: float = 0.0, + _d: float = 1.0, + _e: float = 0.0, + _f: float = 0.0, + is_text: bool = False, + is_render: bool = False, + ) -> TextStateManagerDictType: + """Standard a/b/c/d/e/f matrix params + 'is_text' and 'is_render' keys""" + result: Any = TextStateManager.raw_transform(_a, _b, _c, _d, _e, _f) + result.update({"is_text": is_text, "is_render": is_render}) + return result + + def reset_tm(self) -> TextStateManagerChainMapType: + """Clear all transforms from chainmap having is_text==True or is_render==True""" + while ( + self.transform_stack.maps[0]["is_text"] + or self.transform_stack.maps[0]["is_render"] + ): + self.transform_stack = self.transform_stack.parents + return self.transform_stack + + def reset_trm(self) -> TextStateManagerChainMapType: + """Clear all transforms from chainmap having is_render==True""" + while self.transform_stack.maps[0]["is_render"]: + self.transform_stack = self.transform_stack.parents + return self.transform_stack + + def remove_q(self) -> TextStateManagerChainMapType: + """Rewind to stack prior state after closing a 'q' with internal 'cm' ops""" + self.transform_stack = self.reset_tm() + self.transform_stack.maps = self.transform_stack.maps[ + self.q_queue.pop(self.q_depth.pop(), 0) : + ] + return self.transform_stack + + def add_q(self) -> None: + """Add another level to q_queue""" + self.q_depth.append(len(self.q_depth)) + + def add_cm(self, *args: Any) -> TextStateManagerChainMapType: + """Concatenate an additional transform matrix""" + self.transform_stack = self.reset_tm() + self.q_queue.update(self.q_depth[-1:]) + self.transform_stack = self.transform_stack.new_child(self.new_transform(*args)) + return self.transform_stack + + def _complete_matrix(self, operands: List[float]) -> List[float]: + """Adds a, b, c, and d to an "e/f only" operand set (e.g Td)""" + if len(operands) == 2: # this is a Td operator or equivalent + operands = [1.0, 0.0, 0.0, 1.0, *operands] + return operands + + def add_tm(self, operands: List[float]) -> TextStateManagerChainMapType: + """Append a text transform matrix""" + self.transform_stack = self.transform_stack.new_child( + self.new_transform( # type: ignore[misc] + *self._complete_matrix(operands), is_text=True # type: ignore[arg-type] + ) + ) + return self.transform_stack + + def add_trm(self, operands: List[float]) -> TextStateManagerChainMapType: + """Append a text rendering transform matrix""" + self.transform_stack = self.transform_stack.new_child( + self.new_transform( # type: ignore[misc] + *self._complete_matrix(operands), is_text=True, is_render=True # type: ignore[arg-type] + ) + ) + return self.transform_stack + + @property + def effective_transform(self) -> List[float]: + """Current effective transform accounting for cm, tm, and trm transforms""" + eff_transform = [*self.transform_stack.maps[0].values()] + for transform in self.transform_stack.maps[1:]: + eff_transform = mult(eff_transform, transform) # type: ignore[arg-type] # dict has int keys 0-5 + return eff_transform diff --git a/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_text_state_params.py b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_text_state_params.py new file mode 100644 index 0000000..843fc06 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_text_extraction/_layout_mode/_text_state_params.py @@ -0,0 +1,129 @@ +"""A dataclass that captures the CTM and Text State for a tj operation""" + +import math +from dataclasses import dataclass, field +from typing import Any, Dict, List, Union + +from .. import mult, orient +from ._font import Font + + +@dataclass +class TextStateParams: + """ + Text state parameters and operator values for a single text value in a + TJ or Tj PDF operation. + + Attributes: + txt (str): the text to be rendered. + font (Font): font object + font_size (int | float): font size + Tc (float): character spacing. Defaults to 0.0. + Tw (float): word spacing. Defaults to 0.0. + Tz (float): horizontal scaling. Defaults to 100.0. + TL (float): leading, vertical displacement between text lines. Defaults to 0.0. + Ts (float): text rise. Used for super/subscripts. Defaults to 0.0. + transform (List[float]): effective transformation matrix. + tx (float): x cood of rendered text, i.e. self.transform[4] + ty (float): y cood of rendered text. May differ from self.transform[5] per self.Ts. + displaced_tx (float): x coord immediately following rendered text + space_tx (float): tx for a space character + font_height (float): effective font height accounting for CTM + flip_vertical (bool): True if y axis has been inverted (i.e. if self.transform[3] < 0.) + rotated (bool): True if the text orientation is rotated with respect to the page. + + """ + + txt: str + font: Font + font_size: Union[int, float] + Tc: float = 0.0 + Tw: float = 0.0 + Tz: float = 100.0 + TL: float = 0.0 + Ts: float = 0.0 + transform: List[float] = field( + default_factory=lambda: [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] + ) + tx: float = field(default=0.0, init=False) + ty: float = field(default=0.0, init=False) + displaced_tx: float = field(default=0.0, init=False) + space_tx: float = field(default=0.0, init=False) + font_height: float = field(default=0.0, init=False) + flip_vertical: bool = field(default=False, init=False) + rotated: bool = field(default=False, init=False) + + def __post_init__(self) -> None: + if orient(self.transform) in (90, 270): + self.transform = mult( + [1.0, -self.transform[1], -self.transform[2], 1.0, 0.0, 0.0], + self.transform, + ) + self.rotated = True + # self.transform[0] AND self.transform[3] < 0 indicates true rotation. + # If only self.transform[3] < 0, the y coords are simply inverted. + if orient(self.transform) == 180 and self.transform[0] < -1e-6: + self.transform = mult([-1.0, 0.0, 0.0, -1.0, 0.0, 0.0], self.transform) + self.rotated = True + self.displaced_tx = self.displaced_transform()[4] + self.tx = self.transform[4] + self.ty = self.render_transform()[5] + self.space_tx = round(self.word_tx(" "), 3) + if self.space_tx < 1e-6: + # if the " " char is assigned 0 width (e.g. for fine tuned spacing + # with TJ int operators a la crazyones.pdf), calculate space_tx as + # a TD_offset of -2 * font.space_width where font.space_width is + # the space_width calculated in _cmap.py. + self.space_tx = round(self.word_tx("", self.font.space_width * -2), 3) + self.font_height = self.font_size * math.sqrt( + self.transform[1] ** 2 + self.transform[3] ** 2 + ) + # flip_vertical handles PDFs generated by Microsoft Word's "publish" command. + self.flip_vertical = self.transform[3] < -1e-6 # inverts y axis + + def font_size_matrix(self) -> List[float]: + """Font size matrix""" + return [ + self.font_size * (self.Tz / 100.0), + 0.0, + 0.0, + self.font_size, + 0.0, + self.Ts, + ] + + def displaced_transform(self) -> List[float]: + """Effective transform matrix after text has been rendered.""" + return mult(self.displacement_matrix(), self.transform) + + def render_transform(self) -> List[float]: + """Effective transform matrix accounting for font size, Tz, and Ts.""" + return mult(self.font_size_matrix(), self.transform) + + def displacement_matrix( + self, word: Union[str, None] = None, TD_offset: float = 0.0 + ) -> List[float]: + """ + Text displacement matrix + + Args: + word (str, optional): Defaults to None in which case self.txt displacement is + returned. + TD_offset (float, optional): translation applied by TD operator. Defaults to 0.0. + + """ + word = word if word is not None else self.txt + return [1.0, 0.0, 0.0, 1.0, self.word_tx(word, TD_offset), 0.0] + + def word_tx(self, word: str, TD_offset: float = 0.0) -> float: + """Horizontal text displacement for any word according this text state""" + return ( + (self.font_size * ((self.font.word_width(word) - TD_offset) / 1000.0)) + + self.Tc + + word.count(" ") * self.Tw + ) * (self.Tz / 100.0) + + @staticmethod + def to_dict(inst: "TextStateParams") -> Dict[str, Any]: + """Dataclass to dict for json.dumps serialization""" + return {k: getattr(inst, k) for k in inst.__dataclass_fields__ if k != "font"} diff --git a/venv/lib/python3.12/site-packages/pypdf/_utils.py b/venv/lib/python3.12/site-packages/pypdf/_utils.py new file mode 100644 index 0000000..48f23e1 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_utils.py @@ -0,0 +1,605 @@ +# Copyright (c) 2006, Mathieu Fenniak +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +"""Utility functions for PDF library.""" +__author__ = "Mathieu Fenniak" +__author_email__ = "biziqe@mathieu.fenniak.net" + +import functools +import logging +import re +import sys +import warnings +from dataclasses import dataclass +from datetime import datetime, timezone +from io import DEFAULT_BUFFER_SIZE +from os import SEEK_CUR +from typing import ( + IO, + Any, + Dict, + List, + Optional, + Pattern, + Tuple, + Union, + overload, +) + +if sys.version_info[:2] >= (3, 10): + # Python 3.10+: https://www.python.org/dev/peps/pep-0484/ + from typing import TypeAlias +else: + from typing_extensions import TypeAlias + +if sys.version_info >= (3, 11): + from typing import Self +else: + from typing_extensions import Self + +from .errors import ( + STREAM_TRUNCATED_PREMATURELY, + DeprecationError, + PdfStreamError, +) + +TransformationMatrixType: TypeAlias = Tuple[ + Tuple[float, float, float], Tuple[float, float, float], Tuple[float, float, float] +] +CompressedTransformationMatrix: TypeAlias = Tuple[ + float, float, float, float, float, float +] + +StreamType = IO[Any] +StrByteType = Union[str, StreamType] + + +def parse_iso8824_date(text: Optional[str]) -> Optional[datetime]: + orgtext = text + if text is None: + return None + if text[0].isdigit(): + text = "D:" + text + if text.endswith(("Z", "z")): + text += "0000" + text = text.replace("z", "+").replace("Z", "+").replace("'", "") + i = max(text.find("+"), text.find("-")) + if i > 0 and i != len(text) - 5: + text += "00" + for f in ( + "D:%Y", + "D:%Y%m", + "D:%Y%m%d", + "D:%Y%m%d%H", + "D:%Y%m%d%H%M", + "D:%Y%m%d%H%M%S", + "D:%Y%m%d%H%M%S%z", + ): + try: + d = datetime.strptime(text, f) # noqa: DTZ007 + except ValueError: + continue + else: + if text.endswith("+0000"): + d = d.replace(tzinfo=timezone.utc) + return d + raise ValueError(f"Can not convert date: {orgtext}") + + +def _get_max_pdf_version_header(header1: str, header2: str) -> str: + versions = ( + "%PDF-1.3", + "%PDF-1.4", + "%PDF-1.5", + "%PDF-1.6", + "%PDF-1.7", + "%PDF-2.0", + ) + pdf_header_indices = [] + if header1 in versions: + pdf_header_indices.append(versions.index(header1)) + if header2 in versions: + pdf_header_indices.append(versions.index(header2)) + if len(pdf_header_indices) == 0: + raise ValueError(f"Neither {header1!r} nor {header2!r} are proper headers") + return versions[max(pdf_header_indices)] + + +WHITESPACES = (b"\x00", b"\t", b"\n", b"\f", b"\r", b" ") +WHITESPACES_AS_BYTES = b"".join(WHITESPACES) +WHITESPACES_AS_REGEXP = b"[" + WHITESPACES_AS_BYTES + b"]" + + +def read_until_whitespace(stream: StreamType, maxchars: Optional[int] = None) -> bytes: + """ + Read non-whitespace characters and return them. + + Stops upon encountering whitespace or when maxchars is reached. + + Args: + stream: The data stream from which was read. + maxchars: The maximum number of bytes returned; by default unlimited. + + Returns: + The data which was read. + + """ + txt = b"" + while True: + tok = stream.read(1) + if tok.isspace() or not tok: + break + txt += tok + if len(txt) == maxchars: + break + return txt + + +def read_non_whitespace(stream: StreamType) -> bytes: + """ + Find and read the next non-whitespace character (ignores whitespace). + + Args: + stream: The data stream from which was read. + + Returns: + The data which was read. + + """ + tok = stream.read(1) + while tok in WHITESPACES: + tok = stream.read(1) + return tok + + +def skip_over_whitespace(stream: StreamType) -> bool: + """ + Similar to read_non_whitespace, but return a boolean if at least one + whitespace character was read. + + Args: + stream: The data stream from which was read. + + Returns: + True if one or more whitespace was skipped, otherwise return False. + + """ + tok = stream.read(1) + cnt = 0 + while tok in WHITESPACES: + cnt += 1 + tok = stream.read(1) + return cnt > 0 + + +def check_if_whitespace_only(value: bytes) -> bool: + """ + Check if the given value consists of whitespace characters only. + + Args: + value: The bytes to check. + + Returns: + True if the value only has whitespace characters, otherwise return False. + + """ + return all(b in WHITESPACES_AS_BYTES for b in value) + + +def skip_over_comment(stream: StreamType) -> None: + tok = stream.read(1) + stream.seek(-1, 1) + if tok == b"%": + while tok not in (b"\n", b"\r"): + tok = stream.read(1) + if tok == b"": + raise PdfStreamError("File ended unexpectedly.") + + +def read_until_regex(stream: StreamType, regex: Pattern[bytes]) -> bytes: + """ + Read until the regular expression pattern matched (ignore the match). + Treats EOF on the underlying stream as the end of the token to be matched. + + Args: + regex: re.Pattern + + Returns: + The read bytes. + + """ + name = b"" + while True: + tok = stream.read(16) + if not tok: + return name + m = regex.search(name + tok) + if m is not None: + stream.seek(m.start() - (len(name) + len(tok)), 1) + name = (name + tok)[: m.start()] + break + name += tok + return name + + +def read_block_backwards(stream: StreamType, to_read: int) -> bytes: + """ + Given a stream at position X, read a block of size to_read ending at position X. + + This changes the stream's position to the beginning of where the block was + read. + + Args: + stream: + to_read: + + Returns: + The data which was read. + + """ + if stream.tell() < to_read: + raise PdfStreamError("Could not read malformed PDF file") + # Seek to the start of the block we want to read. + stream.seek(-to_read, SEEK_CUR) + read = stream.read(to_read) + # Seek to the start of the block we read after reading it. + stream.seek(-to_read, SEEK_CUR) + return read + + +def read_previous_line(stream: StreamType) -> bytes: + """ + Given a byte stream with current position X, return the previous line. + + All characters between the first CR/LF byte found before X + (or, the start of the file, if no such byte is found) and position X + After this call, the stream will be positioned one byte after the + first non-CRLF character found beyond the first CR/LF byte before X, + or, if no such byte is found, at the beginning of the stream. + + Args: + stream: StreamType: + + Returns: + The data which was read. + + """ + line_content = [] + found_crlf = False + if stream.tell() == 0: + raise PdfStreamError(STREAM_TRUNCATED_PREMATURELY) + while True: + to_read = min(DEFAULT_BUFFER_SIZE, stream.tell()) + if to_read == 0: + break + # Read the block. After this, our stream will be one + # beyond the initial position. + block = read_block_backwards(stream, to_read) + idx = len(block) - 1 + if not found_crlf: + # We haven't found our first CR/LF yet. + # Read off characters until we hit one. + while idx >= 0 and block[idx] not in b"\r\n": + idx -= 1 + if idx >= 0: + found_crlf = True + if found_crlf: + # We found our first CR/LF already (on this block or + # a previous one). + # Our combined line is the remainder of the block + # plus any previously read blocks. + line_content.append(block[idx + 1 :]) + # Continue to read off any more CRLF characters. + while idx >= 0 and block[idx] in b"\r\n": + idx -= 1 + else: + # Didn't find CR/LF yet - add this block to our + # previously read blocks and continue. + line_content.append(block) + if idx >= 0: + # We found the next non-CRLF character. + # Set the stream position correctly, then break + stream.seek(idx + 1, SEEK_CUR) + break + # Join all the blocks in the line (which are in reverse order) + return b"".join(line_content[::-1]) + + +def matrix_multiply( + a: TransformationMatrixType, b: TransformationMatrixType +) -> TransformationMatrixType: + return tuple( # type: ignore[return-value] + tuple(sum(float(i) * float(j) for i, j in zip(row, col)) for col in zip(*b)) + for row in a + ) + + +def mark_location(stream: StreamType) -> None: + """Create text file showing current location in context.""" + # Mainly for debugging + radius = 5000 + stream.seek(-radius, 1) + with open("pypdf_pdfLocation.txt", "wb") as output_fh: + output_fh.write(stream.read(radius)) + output_fh.write(b"HERE") + output_fh.write(stream.read(radius)) + stream.seek(-radius, 1) + + +@overload +def ord_(b: str) -> int: + ... + + +@overload +def ord_(b: bytes) -> bytes: + ... + + +@overload +def ord_(b: int) -> int: + ... + + +def ord_(b: Union[int, str, bytes]) -> Union[int, bytes]: + if isinstance(b, str): + return ord(b) + return b + + +def deprecate(msg: str, stacklevel: int = 3) -> None: + warnings.warn(msg, DeprecationWarning, stacklevel=stacklevel) + + +def deprecation(msg: str) -> None: + raise DeprecationError(msg) + + +def deprecate_with_replacement(old_name: str, new_name: str, removed_in: str) -> None: + """Issue a warning that a feature will be removed, but has a replacement.""" + deprecate( + f"{old_name} is deprecated and will be removed in pypdf {removed_in}. Use {new_name} instead.", + 4, + ) + + +def deprecation_with_replacement(old_name: str, new_name: str, removed_in: str) -> None: + """Raise an exception that a feature was already removed, but has a replacement.""" + deprecation( + f"{old_name} is deprecated and was removed in pypdf {removed_in}. Use {new_name} instead." + ) + + +def deprecate_no_replacement(name: str, removed_in: str) -> None: + """Issue a warning that a feature will be removed without replacement.""" + deprecate(f"{name} is deprecated and will be removed in pypdf {removed_in}.", 4) + + +def deprecation_no_replacement(name: str, removed_in: str) -> None: + """Raise an exception that a feature was already removed without replacement.""" + deprecation(f"{name} is deprecated and was removed in pypdf {removed_in}.") + + +def logger_error(msg: str, src: str) -> None: + """ + Use this instead of logger.error directly. + + That allows people to overwrite it more easily. + + See the docs on when to use which: + https://pypdf.readthedocs.io/en/latest/user/suppress-warnings.html + """ + logging.getLogger(src).error(msg) + + +def logger_warning(msg: str, src: str) -> None: + """ + Use this instead of logger.warning directly. + + That allows people to overwrite it more easily. + + ## Exception, warnings.warn, logger_warning + - Exceptions should be used if the user should write code that deals with + an error case, e.g. the PDF being completely broken. + - warnings.warn should be used if the user needs to fix their code, e.g. + DeprecationWarnings + - logger_warning should be used if the user needs to know that an issue was + handled by pypdf, e.g. a non-compliant PDF being read in a way that + pypdf could apply a robustness fix to still read it. This applies mainly + to strict=False mode. + """ + logging.getLogger(src).warning(msg) + + +def rename_kwargs( + func_name: str, kwargs: Dict[str, Any], aliases: Dict[str, str], fail: bool = False +) -> None: + """ + Helper function to deprecate arguments. + + Args: + func_name: Name of the function to be deprecated + kwargs: + aliases: + fail: + + """ + for old_term, new_term in aliases.items(): + if old_term in kwargs: + if fail: + raise DeprecationError( + f"{old_term} is deprecated as an argument. Use {new_term} instead" + ) + if new_term in kwargs: + raise TypeError( + f"{func_name} received both {old_term} and {new_term} as " + f"an argument. {old_term} is deprecated. " + f"Use {new_term} instead." + ) + kwargs[new_term] = kwargs.pop(old_term) + warnings.warn( + message=( + f"{old_term} is deprecated as an argument. Use {new_term} instead" + ), + category=DeprecationWarning, + ) + + +def _human_readable_bytes(bytes: int) -> str: + if bytes < 10**3: + return f"{bytes} Byte" + elif bytes < 10**6: + return f"{bytes / 10**3:.1f} kB" + elif bytes < 10**9: + return f"{bytes / 10**6:.1f} MB" + else: + return f"{bytes / 10**9:.1f} GB" + + +# The following class has been copied from Django: +# https://github.com/django/django/blob/adae619426b6f50046b3daaa744db52989c9d6db/django/utils/functional.py#L51-L65 +# It received some modifications to comply with our own coding standards. +# +# Original license: +# +# --------------------------------------------------------------------------------- +# Copyright (c) Django Software Foundation and individual contributors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of Django nor the names of its contributors may be used +# to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# --------------------------------------------------------------------------------- +class classproperty: # noqa: N801 + """ + Decorator that converts a method with a single cls argument into a property + that can be accessed directly from the class. + """ + + def __init__(self, method=None) -> None: # type: ignore # noqa: ANN001 + self.fget = method + + def __get__(self, instance, cls=None) -> Any: # type: ignore # noqa: ANN001 + return self.fget(cls) + + def getter(self, method) -> Self: # type: ignore # noqa: ANN001 + self.fget = method + return self + + +@dataclass +class File: + from .generic import IndirectObject + + name: str = "" + """ + Filename as identified within the PDF file. + """ + data: bytes = b"" + """ + Data as bytes. + """ + indirect_reference: Optional[IndirectObject] = None + """ + Reference to the object storing the stream. + """ + + def __str__(self) -> str: + return f"{self.__class__.__name__}(name={self.name}, data: {_human_readable_bytes(len(self.data))})" + + def __repr__(self) -> str: + return self.__str__()[:-1] + f", hash: {hash(self.data)})" + + +@functools.total_ordering +class Version: + COMPONENT_PATTERN = re.compile(r"^(\d+)(.*)$") + + def __init__(self, version_str: str) -> None: + self.version_str = version_str + self.components = self._parse_version(version_str) + + def _parse_version(self, version_str: str) -> List[Tuple[int, str]]: + components = version_str.split(".") + parsed_components = [] + for component in components: + match = Version.COMPONENT_PATTERN.match(component) + if not match: + parsed_components.append((0, component)) + continue + integer_prefix = match.group(1) + suffix = match.group(2) + if integer_prefix is None: + integer_prefix = 0 + parsed_components.append((int(integer_prefix), suffix)) + return parsed_components + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Version): + return False + return self.components == other.components + + def __lt__(self, other: Any) -> bool: + if not isinstance(other, Version): + raise ValueError(f"Version cannot be compared against {type(other)}") + + for self_component, other_component in zip(self.components, other.components): + self_value, self_suffix = self_component + other_value, other_suffix = other_component + + if self_value < other_value: + return True + elif self_value > other_value: + return False + + if self_suffix < other_suffix: + return True + elif self_suffix > other_suffix: + return False + + return len(self.components) < len(other.components) diff --git a/venv/lib/python3.12/site-packages/pypdf/_version.py b/venv/lib/python3.12/site-packages/pypdf/_version.py new file mode 100644 index 0000000..fc30498 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_version.py @@ -0,0 +1 @@ +__version__ = "5.4.0" diff --git a/venv/lib/python3.12/site-packages/pypdf/_writer.py b/venv/lib/python3.12/site-packages/pypdf/_writer.py new file mode 100644 index 0000000..0c9a7da --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_writer.py @@ -0,0 +1,3380 @@ +# Copyright (c) 2006, Mathieu Fenniak +# Copyright (c) 2007, Ashish Kulkarni +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import decimal +import enum +import hashlib +import re +import struct +import uuid +from io import BytesIO, FileIO, IOBase +from itertools import compress +from pathlib import Path +from types import TracebackType +from typing import ( + IO, + Any, + Callable, + Dict, + Iterable, + List, + Optional, + Pattern, + Tuple, + Type, + Union, + cast, +) + +from ._cmap import _default_fonts_space_width, build_char_map_from_dict +from ._doc_common import DocumentInformation, PdfDocCommon +from ._encryption import EncryptAlgorithm, Encryption +from ._page import PageObject +from ._page_labels import nums_clear_range, nums_insert, nums_next +from ._reader import PdfReader +from ._utils import ( + StrByteType, + StreamType, + _get_max_pdf_version_header, + deprecate, + deprecate_no_replacement, + deprecation_with_replacement, + logger_warning, +) +from .constants import AnnotationDictionaryAttributes as AA +from .constants import CatalogAttributes as CA +from .constants import ( + CatalogDictionary, + FileSpecificationDictionaryEntries, + GoToActionArguments, + ImageType, + InteractiveFormDictEntries, + OutlineFontFlag, + PageLabelStyle, + TypFitArguments, + UserAccessPermissions, +) +from .constants import Core as CO +from .constants import FieldDictionaryAttributes as FA +from .constants import PageAttributes as PG +from .constants import PagesAttributes as PA +from .constants import TrailerKeys as TK +from .errors import PyPdfError +from .generic import ( + PAGE_FIT, + ArrayObject, + BooleanObject, + ByteStringObject, + ContentStream, + DecodedStreamObject, + Destination, + DictionaryObject, + Fit, + FloatObject, + IndirectObject, + NameObject, + NullObject, + NumberObject, + PdfObject, + RectangleObject, + StreamObject, + TextStringObject, + TreeObject, + ViewerPreferences, + create_string_object, + hex_to_rgb, + is_null_or_none, +) +from .pagerange import PageRange, PageRangeSpec +from .types import ( + AnnotationSubtype, + BorderArrayType, + LayoutType, + OutlineItemType, + OutlineType, + PagemodeType, +) +from .xmp import XmpInformation + +ALL_DOCUMENT_PERMISSIONS = UserAccessPermissions.all() +DEFAULT_FONT_HEIGHT_IN_MULTILINE = 12 + + +class ObjectDeletionFlag(enum.IntFlag): + NONE = 0 + TEXT = enum.auto() + LINKS = enum.auto() + ATTACHMENTS = enum.auto() + OBJECTS_3D = enum.auto() + ALL_ANNOTATIONS = enum.auto() + XOBJECT_IMAGES = enum.auto() + INLINE_IMAGES = enum.auto() + DRAWING_IMAGES = enum.auto() + IMAGES = XOBJECT_IMAGES | INLINE_IMAGES | DRAWING_IMAGES + + +def _rolling_checksum(stream: BytesIO, blocksize: int = 65536) -> str: + hash = hashlib.md5() + for block in iter(lambda: stream.read(blocksize), b""): + hash.update(block) + return hash.hexdigest() + + +class PdfWriter(PdfDocCommon): + """ + Write a PDF file out, given pages produced by another class or through + cloning a PDF file during initialization. + + Typically data is added from a :class:`PdfReader`. + + Args: + clone_from: identical to fileobj (for compatibility) + + incremental: If true, loads the document and set the PdfWriter in incremental mode. + + + When writing incrementally, the original document is written first and new/modified + content is appended. To be used for signed document/forms to keep signature valid. + + full: If true, loads all the objects (always full if incremental = True). + This parameters may allows to load very big PDFs. + + """ + + def __init__( + self, + fileobj: Union[None, PdfReader, StrByteType, Path] = "", + clone_from: Union[None, PdfReader, StrByteType, Path] = None, + incremental: bool = False, + full: bool = False, + ) -> None: + self.incremental = incremental or full + """ + Returns if the PdfWriter object has been started in incremental mode. + """ + + self._objects: List[Optional[PdfObject]] = [] + """ + The indirect objects in the PDF. + For the incremental case, it will be filled with None + in clone_reader_document_root. + """ + + self._original_hash: List[int] = [] + """ + List of hashes after import; used to identify changes. + """ + + self._idnum_hash: Dict[bytes, Tuple[IndirectObject, List[IndirectObject]]] = {} + """ + Maps hash values of indirect objects to the list of IndirectObjects. + This is used for compression. + """ + + self._id_translated: Dict[int, Dict[int, int]] = {} + """List of already translated IDs. + dict[id(pdf)][(idnum, generation)] + """ + + self._info_obj: Optional[PdfObject] + """The PDF files's document information dictionary, + the Info entry in the PDF file's trailer dictionary.""" + + self._ID: Union[ArrayObject, None] = None + """The PDF file identifier, + defined by the ID in the PDF file's trailer dictionary.""" + + if self.incremental: + if isinstance(fileobj, (str, Path)): + with open(fileobj, "rb") as f: + fileobj = BytesIO(f.read(-1)) + if isinstance(fileobj, BytesIO): + fileobj = PdfReader(fileobj) + if not isinstance(fileobj, PdfReader): + raise PyPdfError("Invalid type for incremental mode") + self._reader = fileobj # prev content is in _reader.stream + self._header = fileobj.pdf_header.encode() + self._readonly = True # !!!TODO: to be analysed + else: + self._header = b"%PDF-1.3" + self._info_obj = self._add_object( + DictionaryObject( + {NameObject("/Producer"): create_string_object("pypdf")} + ) + ) + + def _get_clone_from( + fileobj: Union[None, PdfReader, str, Path, IO[Any], BytesIO], + clone_from: Union[None, PdfReader, str, Path, IO[Any], BytesIO], + ) -> Union[None, PdfReader, str, Path, IO[Any], BytesIO]: + if isinstance(fileobj, (str, Path, IO, BytesIO)) and ( + fileobj == "" or clone_from is not None + ): + return clone_from + cloning = True + if isinstance(fileobj, (str, Path)) and ( + not Path(str(fileobj)).exists() + or Path(str(fileobj)).stat().st_size == 0 + ): + cloning = False + if isinstance(fileobj, (IOBase, BytesIO)): + t = fileobj.tell() + if fileobj.seek(0, 2) == 0: + cloning = False + fileobj.seek(t, 0) + if cloning: + clone_from = fileobj + return clone_from + + clone_from = _get_clone_from(fileobj, clone_from) + # to prevent overwriting + self.temp_fileobj = fileobj + self.fileobj = "" + self._with_as_usage = False + self._cloned = False + # The root of our page tree node. + pages = DictionaryObject() + pages.update( + { + NameObject(PA.TYPE): NameObject("/Pages"), + NameObject(PA.COUNT): NumberObject(0), + NameObject(PA.KIDS): ArrayObject(), + } + ) + self.flattened_pages = [] + self._encryption: Optional[Encryption] = None + self._encrypt_entry: Optional[DictionaryObject] = None + + if clone_from is not None: + if not isinstance(clone_from, PdfReader): + clone_from = PdfReader(clone_from) + self.clone_document_from_reader(clone_from) + self._cloned = True + else: + self._pages = self._add_object(pages) + # root object + self._root_object = DictionaryObject() + self._root_object.update( + { + NameObject(PA.TYPE): NameObject(CO.CATALOG), + NameObject(CO.PAGES): self._pages, + } + ) + self._add_object(self._root_object) + if full and not incremental: + self.incremental = False + if isinstance(self._ID, list): + if isinstance(self._ID[0], TextStringObject): + self._ID[0] = ByteStringObject(self._ID[0].get_original_bytes()) + if isinstance(self._ID[1], TextStringObject): + self._ID[1] = ByteStringObject(self._ID[1].get_original_bytes()) + + # for commonality + @property + def is_encrypted(self) -> bool: + """ + Read-only boolean property showing whether this PDF file is encrypted. + + Note that this property, if true, will remain true even after the + :meth:`decrypt()` method is called. + """ + return False + + @property + def root_object(self) -> DictionaryObject: + """ + Provide direct access to PDF Structure. + + Note: + Recommended only for read access. + + """ + return self._root_object + + @property + def _info(self) -> Optional[DictionaryObject]: + """ + Provide access to "/Info". Standardized with PdfReader. + + Returns: + /Info Dictionary; None if the entry does not exist + + """ + return ( + None + if self._info_obj is None + else cast(DictionaryObject, self._info_obj.get_object()) + ) + + @_info.setter + def _info(self, value: Optional[Union[IndirectObject, DictionaryObject]]) -> None: + if value is None: + try: + self._objects[self._info_obj.indirect_reference.idnum - 1] = None # type: ignore + except (KeyError, AttributeError): + pass + self._info_obj = None + else: + if self._info_obj is None: + self._info_obj = self._add_object(DictionaryObject()) + obj = cast(DictionaryObject, self._info_obj.get_object()) + obj.clear() + obj.update(cast(DictionaryObject, value.get_object())) + + @property + def xmp_metadata(self) -> Optional[XmpInformation]: + """XMP (Extensible Metadata Platform) data.""" + return cast(XmpInformation, self.root_object.xmp_metadata) + + @xmp_metadata.setter + def xmp_metadata(self, value: Optional[XmpInformation]) -> None: + """XMP (Extensible Metadata Platform) data.""" + if value is None: + if "/Metadata" in self.root_object: + del self.root_object["/Metadata"] + else: + self.root_object[NameObject("/Metadata")] = value + + return self.root_object.xmp_metadata # type: ignore + + @property + def with_as_usage(self) -> bool: + deprecate_no_replacement("with_as_usage", "6.0") + return self._with_as_usage + + @with_as_usage.setter + def with_as_usage(self, value: bool) -> None: + deprecate_no_replacement("with_as_usage", "6.0") + self._with_as_usage = value + + def __enter__(self) -> "PdfWriter": + """Store how writer is initialized by 'with'.""" + c: bool = self._cloned + t = self.temp_fileobj + self.__init__() # type: ignore + self._cloned = c + self._with_as_usage = True + self.fileobj = t # type: ignore + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc: Optional[BaseException], + traceback: Optional[TracebackType], + ) -> None: + """Write data to the fileobj.""" + if self.fileobj and not self._cloned: + self.write(self.fileobj) + + @property + def pdf_header(self) -> str: + """ + Read/Write property of the PDF header that is written. + + This should be something like ``'%PDF-1.5'``. It is recommended to set + the lowest version that supports all features which are used within the + PDF file. + + Note: `pdf_header` returns a string but accepts bytes or str for writing + """ + return self._header.decode() + + @pdf_header.setter + def pdf_header(self, new_header: Union[str, bytes]) -> None: + if isinstance(new_header, str): + new_header = new_header.encode() + self._header = new_header + + def _add_object(self, obj: PdfObject) -> IndirectObject: + if ( + getattr(obj, "indirect_reference", None) is not None + and obj.indirect_reference.pdf == self # type: ignore + ): + return obj.indirect_reference # type: ignore + # check for /Contents in Pages (/Contents in annotations are strings) + if isinstance(obj, DictionaryObject) and isinstance( + obj.get(PG.CONTENTS, None), (ArrayObject, DictionaryObject) + ): + obj[NameObject(PG.CONTENTS)] = self._add_object(obj[PG.CONTENTS]) + self._objects.append(obj) + obj.indirect_reference = IndirectObject(len(self._objects), 0, self) + return obj.indirect_reference + + def get_object( + self, + indirect_reference: Union[int, IndirectObject], + ) -> PdfObject: + if isinstance(indirect_reference, int): + obj = self._objects[indirect_reference - 1] + elif indirect_reference.pdf != self: + raise ValueError("PDF must be self") + else: + obj = self._objects[indirect_reference.idnum - 1] + assert obj is not None # clarification for mypy + return obj + + def _replace_object( + self, + indirect_reference: Union[int, IndirectObject], + obj: PdfObject, + ) -> PdfObject: + if isinstance(indirect_reference, IndirectObject): + if indirect_reference.pdf != self: + raise ValueError("PDF must be self") + indirect_reference = indirect_reference.idnum + gen = self._objects[indirect_reference - 1].indirect_reference.generation # type: ignore + if ( + getattr(obj, "indirect_reference", None) is not None + and obj.indirect_reference.pdf != self # type: ignore + ): + obj = obj.clone(self) + self._objects[indirect_reference - 1] = obj + obj.indirect_reference = IndirectObject(indirect_reference, gen, self) + + assert isinstance(obj, PdfObject) # clarification for mypy + return obj + + def _add_page( + self, + page: PageObject, + index: int, + excluded_keys: Iterable[str] = (), + ) -> PageObject: + if not isinstance(page, PageObject) or page.get(PA.TYPE, None) != CO.PAGE: + raise ValueError("Invalid page object") + assert self.flattened_pages is not None, "for mypy" + page_org = page + excluded_keys = list(excluded_keys) + excluded_keys += [PA.PARENT, "/StructParents"] + # Acrobat does not accept two indirect references pointing on the same + # page; therefore in order to add multiple copies of the same + # page, we need to create a new dictionary for the page, however the + # objects below (including content) are not duplicated: + try: # delete an already existing page + del self._id_translated[id(page_org.indirect_reference.pdf)][ # type: ignore + page_org.indirect_reference.idnum # type: ignore + ] + except Exception: + pass + page = cast( + "PageObject", page_org.clone(self, False, excluded_keys).get_object() + ) + if page_org.pdf is not None: + other = page_org.pdf.pdf_header + self.pdf_header = _get_max_pdf_version_header(self.pdf_header, other) + node, idx = self._get_page_in_node(index) + page[NameObject(PA.PARENT)] = node.indirect_reference + + if idx >= 0: + cast(ArrayObject, node[PA.KIDS]).insert(idx, page.indirect_reference) + self.flattened_pages.insert(index, page) + else: + cast(ArrayObject, node[PA.KIDS]).append(page.indirect_reference) + self.flattened_pages.append(page) + recurse = 0 + while not is_null_or_none(node): + node = cast(DictionaryObject, node.get_object()) + node[NameObject(PA.COUNT)] = NumberObject(cast(int, node[PA.COUNT]) + 1) + node = node.get(PA.PARENT, None) + recurse += 1 + if recurse > 1000: + raise PyPdfError("Too many recursive calls!") + return page + + def set_need_appearances_writer(self, state: bool = True) -> None: + """ + Sets the "NeedAppearances" flag in the PDF writer. + + The "NeedAppearances" flag indicates whether the appearance dictionary + for form fields should be automatically generated by the PDF viewer or + if the embedded appearance should be used. + + Args: + state: The actual value of the NeedAppearances flag. + + Returns: + None + + """ + # See §12.7.2 and §7.7.2 for more information: + # https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf + try: + # get the AcroForm tree + if CatalogDictionary.ACRO_FORM not in self._root_object: + self._root_object[ + NameObject(CatalogDictionary.ACRO_FORM) + ] = self._add_object(DictionaryObject()) + + need_appearances = NameObject(InteractiveFormDictEntries.NeedAppearances) + cast(DictionaryObject, self._root_object[CatalogDictionary.ACRO_FORM])[ + need_appearances + ] = BooleanObject(state) + except Exception as exc: # pragma: no cover + logger_warning( + f"set_need_appearances_writer({state}) catch : {exc}", __name__ + ) + + def create_viewer_preferences(self) -> ViewerPreferences: + o = ViewerPreferences() + self._root_object[ + NameObject(CatalogDictionary.VIEWER_PREFERENCES) + ] = self._add_object(o) + return o + + def add_page( + self, + page: PageObject, + excluded_keys: Iterable[str] = (), + ) -> PageObject: + """ + Add a page to this PDF file. + + Recommended for advanced usage including the adequate excluded_keys. + + The page is usually acquired from a :class:`PdfReader` + instance. + + Args: + page: The page to add to the document. Should be + an instance of :class:`PageObject` + excluded_keys: + + Returns: + The added PageObject. + + """ + assert self.flattened_pages is not None, "mypy" + return self._add_page(page, len(self.flattened_pages), excluded_keys) + + def insert_page( + self, + page: PageObject, + index: int = 0, + excluded_keys: Iterable[str] = (), + ) -> PageObject: + """ + Insert a page in this PDF file. The page is usually acquired from a + :class:`PdfReader` instance. + + Args: + page: The page to add to the document. + index: Position at which the page will be inserted. + excluded_keys: + + Returns: + The added PageObject. + + """ + assert self.flattened_pages is not None, "mypy" + if index < 0: + index = len(self.flattened_pages) + index + if index < 0: + raise ValueError("Invalid index value") + if index >= len(self.flattened_pages): + return self.add_page(page, excluded_keys) + else: + return self._add_page(page, index, excluded_keys) + + def _get_page_number_by_indirect( + self, indirect_reference: Union[None, int, NullObject, IndirectObject] + ) -> Optional[int]: + """ + Generate _page_id2num. + + Args: + indirect_reference: + + Returns: + The page number or None + + """ + # to provide same function as in PdfReader + if is_null_or_none(indirect_reference): + return None + assert indirect_reference is not None, "mypy" + if isinstance(indirect_reference, int): + indirect_reference = IndirectObject(indirect_reference, 0, self) + obj = indirect_reference.get_object() + if isinstance(obj, PageObject): + return obj.page_number + return None + + def add_blank_page( + self, width: Optional[float] = None, height: Optional[float] = None + ) -> PageObject: + """ + Append a blank page to this PDF file and return it. + + If no page size is specified, use the size of the last page. + + Args: + width: The width of the new page expressed in default user + space units. + height: The height of the new page expressed in default + user space units. + + Returns: + The newly appended page. + + Raises: + PageSizeNotDefinedError: if width and height are not defined + and previous page does not exist. + + """ + page = PageObject.create_blank_page(self, width, height) + return self.add_page(page) + + def insert_blank_page( + self, + width: Optional[Union[float, decimal.Decimal]] = None, + height: Optional[Union[float, decimal.Decimal]] = None, + index: int = 0, + ) -> PageObject: + """ + Insert a blank page to this PDF file and return it. + + If no page size is specified, use the size of the last page. + + Args: + width: The width of the new page expressed in default user + space units. + height: The height of the new page expressed in default + user space units. + index: Position to add the page. + + Returns: + The newly inserted page. + + Raises: + PageSizeNotDefinedError: if width and height are not defined + and previous page does not exist. + + """ + if width is None or (height is None and index < self.get_num_pages()): + oldpage = self.pages[index] + width = oldpage.mediabox.width + height = oldpage.mediabox.height + page = PageObject.create_blank_page(self, width, height) + self.insert_page(page, index) + return page + + @property + def open_destination( + self, + ) -> Union[None, Destination, TextStringObject, ByteStringObject]: + return super().open_destination + + @open_destination.setter + def open_destination(self, dest: Union[None, str, Destination, PageObject]) -> None: + if dest is None: + try: + del self._root_object["/OpenAction"] + except KeyError: + pass + elif isinstance(dest, str): + self._root_object[NameObject("/OpenAction")] = TextStringObject(dest) + elif isinstance(dest, Destination): + self._root_object[NameObject("/OpenAction")] = dest.dest_array + elif isinstance(dest, PageObject): + self._root_object[NameObject("/OpenAction")] = Destination( + "Opening", + dest.indirect_reference + if dest.indirect_reference is not None + else NullObject(), + PAGE_FIT, + ).dest_array + + def add_js(self, javascript: str) -> None: + """ + Add JavaScript which will launch upon opening this PDF. + + Args: + javascript: Your JavaScript. + + >>> output.add_js("this.print({bUI:true,bSilent:false,bShrinkToFit:true});") + # Example: This will launch the print window when the PDF is opened. + + """ + # Names / JavaScript preferred to be able to add multiple scripts + if "/Names" not in self._root_object: + self._root_object[NameObject(CA.NAMES)] = DictionaryObject() + names = cast(DictionaryObject, self._root_object[CA.NAMES]) + if "/JavaScript" not in names: + names[NameObject("/JavaScript")] = DictionaryObject( + {NameObject("/Names"): ArrayObject()} + ) + js_list = cast( + ArrayObject, cast(DictionaryObject, names["/JavaScript"])["/Names"] + ) + + js = DictionaryObject() + js.update( + { + NameObject(PA.TYPE): NameObject("/Action"), + NameObject("/S"): NameObject("/JavaScript"), + NameObject("/JS"): TextStringObject(f"{javascript}"), + } + ) + # We need a name for parameterized JavaScript in the PDF file, + # but it can be anything. + js_list.append(create_string_object(str(uuid.uuid4()))) + js_list.append(self._add_object(js)) + + def add_attachment(self, filename: str, data: Union[str, bytes]) -> None: + """ + Embed a file inside the PDF. + + Reference: + https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf + Section 7.11.3 + + Args: + filename: The filename to display. + data: The data in the file. + + """ + # We need three entries: + # * The file's data + # * The /Filespec entry + # * The file's name, which goes in the Catalog + + # The entry for the file + # Sample: + # 8 0 obj + # << + # /Length 12 + # /Type /EmbeddedFile + # >> + # stream + # Hello world! + # endstream + # endobj + + if isinstance(data, str): + data = data.encode("latin-1") + file_entry = DecodedStreamObject() + file_entry.set_data(data) + file_entry.update({NameObject(PA.TYPE): NameObject("/EmbeddedFile")}) + + # The Filespec entry + # Sample: + # 7 0 obj + # << + # /Type /Filespec + # /F (hello.txt) + # /EF << /F 8 0 R >> + # >> + # endobj + + ef_entry = DictionaryObject() + ef_entry.update({NameObject("/F"): self._add_object(file_entry)}) + + filespec = DictionaryObject() + filespec.update( + { + NameObject(PA.TYPE): NameObject("/Filespec"), + NameObject(FileSpecificationDictionaryEntries.F): create_string_object( + filename + ), # Perhaps also try TextStringObject + NameObject(FileSpecificationDictionaryEntries.EF): ef_entry, + } + ) + + # Then create the entry for the root, as it needs + # a reference to the Filespec + # Sample: + # 1 0 obj + # << + # /Type /Catalog + # /Outlines 2 0 R + # /Pages 3 0 R + # /Names << /EmbeddedFiles << /Names [(hello.txt) 7 0 R] >> >> + # >> + # endobj + + if CA.NAMES not in self._root_object: + self._root_object[NameObject(CA.NAMES)] = self._add_object( + DictionaryObject() + ) + if "/EmbeddedFiles" not in cast(DictionaryObject, self._root_object[CA.NAMES]): + embedded_files_names_dictionary = DictionaryObject( + {NameObject(CA.NAMES): ArrayObject()} + ) + cast(DictionaryObject, self._root_object[CA.NAMES])[ + NameObject("/EmbeddedFiles") + ] = self._add_object(embedded_files_names_dictionary) + else: + embedded_files_names_dictionary = cast( + DictionaryObject, + cast(DictionaryObject, self._root_object[CA.NAMES])["/EmbeddedFiles"], + ) + cast(ArrayObject, embedded_files_names_dictionary[CA.NAMES]).extend( + [create_string_object(filename), filespec] + ) + + def append_pages_from_reader( + self, + reader: PdfReader, + after_page_append: Optional[Callable[[PageObject], None]] = None, + ) -> None: + """ + Copy pages from reader to writer. Includes an optional callback + parameter which is invoked after pages are appended to the writer. + + ``append`` should be preferred. + + Args: + reader: a PdfReader object from which to copy page + annotations to this writer object. The writer's annots + will then be updated. + after_page_append: + Callback function that is invoked after each page is appended to + the writer. Signature includes a reference to the appended page + (delegates to append_pages_from_reader). The single parameter of + the callback is a reference to the page just appended to the + document. + + """ + reader_num_pages = len(reader.pages) + # Copy pages from reader to writer + for reader_page_number in range(reader_num_pages): + reader_page = reader.pages[reader_page_number] + writer_page = self.add_page(reader_page) + # Trigger callback, pass writer page as parameter + if callable(after_page_append): + after_page_append(writer_page) + + def _update_field_annotation( + self, + field: DictionaryObject, + annotation: DictionaryObject, + font_name: str = "", + font_size: float = -1, + ) -> None: + # Calculate rectangle dimensions + _rct = cast(RectangleObject, annotation[AA.Rect]) + rct = RectangleObject((0, 0, abs(_rct[2] - _rct[0]), abs(_rct[3] - _rct[1]))) + + # Extract font information + da = annotation.get_inherited( + AA.DA, + cast(DictionaryObject, self.root_object[CatalogDictionary.ACRO_FORM]).get( + AA.DA, None + ), + ) + if da is None: + da = TextStringObject("/Helv 0 Tf 0 g") + else: + da = da.get_object() + font_properties = da.replace("\n", " ").replace("\r", " ").split(" ") + font_properties = [x for x in font_properties if x != ""] + if font_name: + font_properties[font_properties.index("Tf") - 2] = font_name + else: + font_name = font_properties[font_properties.index("Tf") - 2] + font_height = ( + font_size + if font_size >= 0 + else float(font_properties[font_properties.index("Tf") - 1]) + ) + if font_height == 0: + if field.get(FA.Ff, 0) & FA.FfBits.Multiline: + font_height = DEFAULT_FONT_HEIGHT_IN_MULTILINE + else: + font_height = rct.height - 2 + font_properties[font_properties.index("Tf") - 1] = str(font_height) + da = " ".join(font_properties) + y_offset = rct.height - 1 - font_height + + # Retrieve font information from local DR ... + dr: Any = cast( + DictionaryObject, + cast( + DictionaryObject, + annotation.get_inherited( + "/DR", + cast( + DictionaryObject, self.root_object[CatalogDictionary.ACRO_FORM] + ).get("/DR", DictionaryObject()), + ), + ).get_object(), + ) + dr = dr.get("/Font", DictionaryObject()).get_object() + # _default_fonts_space_width keys is the list of Standard fonts + if font_name not in dr and font_name not in _default_fonts_space_width: + # ...or AcroForm dictionary + dr = cast( + Dict[Any, Any], + cast( + DictionaryObject, self.root_object[CatalogDictionary.ACRO_FORM] + ).get("/DR", {}), + ) + dr = dr.get_object().get("/Font", DictionaryObject()).get_object() + font_res = dr.get(font_name, None) + if not is_null_or_none(font_res): + font_res = cast(DictionaryObject, font_res.get_object()) + font_subtype, _, font_encoding, font_map = build_char_map_from_dict( + 200, font_res + ) + try: # remove width stored in -1 key + del font_map[-1] + except KeyError: + pass + font_full_rev: Dict[str, bytes] + if isinstance(font_encoding, str): + font_full_rev = { + v: k.encode(font_encoding) for k, v in font_map.items() + } + else: + font_full_rev = {v: bytes((k,)) for k, v in font_encoding.items()} + font_encoding_rev = {v: bytes((k,)) for k, v in font_encoding.items()} + for key, value in font_map.items(): + font_full_rev[value] = font_encoding_rev.get(key, key) + else: + logger_warning(f"Font dictionary for {font_name} not found.", __name__) + font_full_rev = {} + + # Retrieve field text and selected values + field_flags = field.get(FA.Ff, 0) + if field.get(FA.FT, "/Tx") == "/Ch" and field_flags & FA.FfBits.Combo == 0: + txt = "\n".join(annotation.get_inherited(FA.Opt, [])) + sel = field.get("/V", []) + if not isinstance(sel, list): + sel = [sel] + else: # /Tx + txt = field.get("/V", "") + sel = [] + # Escape parentheses (PDF 1.7 reference, table 3.2, Literal Strings) + txt = txt.replace("\\", "\\\\").replace("(", r"\(").replace(")", r"\)") + # Generate appearance stream + ap_stream = generate_appearance_stream( + txt, sel, da, font_full_rev, rct, font_height, y_offset + ) + + # Create appearance dictionary + dct = DecodedStreamObject.initialize_from_dictionary( + { + NameObject("/Type"): NameObject("/XObject"), + NameObject("/Subtype"): NameObject("/Form"), + NameObject("/BBox"): rct, + "__streamdata__": ByteStringObject(ap_stream), + "/Length": 0, + } + ) + if AA.AP in annotation: + for k, v in cast(DictionaryObject, annotation[AA.AP]).get("/N", {}).items(): + if k not in {"/BBox", "/Length", "/Subtype", "/Type", "/Filter"}: + dct[k] = v + + # Update Resources with font information if necessary + if font_res is not None: + dct[NameObject("/Resources")] = DictionaryObject( + { + NameObject("/Font"): DictionaryObject( + { + NameObject(font_name): getattr( + font_res, "indirect_reference", font_res + ) + } + ) + } + ) + if AA.AP not in annotation: + annotation[NameObject(AA.AP)] = DictionaryObject( + {NameObject("/N"): self._add_object(dct)} + ) + elif "/N" not in cast(DictionaryObject, annotation[AA.AP]): + cast(DictionaryObject, annotation[NameObject(AA.AP)])[ + NameObject("/N") + ] = self._add_object(dct) + else: # [/AP][/N] exists + n = annotation[AA.AP]["/N"].indirect_reference.idnum # type: ignore + self._objects[n - 1] = dct + dct.indirect_reference = IndirectObject(n, 0, self) + + FFBITS_NUL = FA.FfBits(0) + + def update_page_form_field_values( + self, + page: Union[PageObject, List[PageObject], None], + fields: Dict[str, Union[str, List[str], Tuple[str, str, float]]], + flags: FA.FfBits = FFBITS_NUL, + auto_regenerate: Optional[bool] = True, + ) -> None: + """ + Update the form field values for a given page from a fields dictionary. + + Copy field texts and values from fields to page. + If the field links to a parent object, add the information to the parent. + + Args: + page: `PageObject` - references **PDF writer's page** where the + annotations and field data will be updated. + `List[Pageobject]` - provides list of pages to be processed. + `None` - all pages. + fields: a Python dictionary of: + + * field names (/T) as keys and text values (/V) as value + * field names (/T) as keys and list of text values (/V) for multiple choice list + * field names (/T) as keys and tuple of: + * text values (/V) + * font id (e.g. /F1, the font id must exist) + * font size (0 for autosize) + + flags: A set of flags from :class:`~pypdf.constants.FieldDictionaryAttributes.FfBits`. + + auto_regenerate: Set/unset the need_appearances flag; + the flag is unchanged if auto_regenerate is None. + + """ + if CatalogDictionary.ACRO_FORM not in self._root_object: + raise PyPdfError("No /AcroForm dictionary in PDF of PdfWriter Object") + af = cast(DictionaryObject, self._root_object[CatalogDictionary.ACRO_FORM]) + if InteractiveFormDictEntries.Fields not in af: + raise PyPdfError("No /Fields dictionary in PDF of PdfWriter Object") + if isinstance(auto_regenerate, bool): + self.set_need_appearances_writer(auto_regenerate) + # Iterate through pages, update field values + if page is None: + page = list(self.pages) + if isinstance(page, list): + for p in page: + if PG.ANNOTS in p: # just to prevent warnings + self.update_page_form_field_values(p, fields, flags, None) + return None + if PG.ANNOTS not in page: + logger_warning("No fields to update on this page", __name__) + return + for annotation in page[PG.ANNOTS]: # type: ignore + annotation = cast(DictionaryObject, annotation.get_object()) + if annotation.get("/Subtype", "") != "/Widget": + continue + if "/FT" in annotation and "/T" in annotation: + parent_annotation = annotation + else: + parent_annotation = annotation.get( + PG.PARENT, DictionaryObject() + ).get_object() + + for field, value in fields.items(): + if not ( + self._get_qualified_field_name(parent_annotation) == field + or parent_annotation.get("/T", None) == field + ): + continue + if ( + parent_annotation.get("/FT", None) == "/Ch" + and "/I" in parent_annotation + ): + del parent_annotation["/I"] + if flags: + annotation[NameObject(FA.Ff)] = NumberObject(flags) + if isinstance(value, list): + lst = ArrayObject(TextStringObject(v) for v in value) + parent_annotation[NameObject(FA.V)] = lst + elif isinstance(value, tuple): + annotation[NameObject(FA.V)] = TextStringObject( + value[0], + ) + else: + parent_annotation[NameObject(FA.V)] = TextStringObject(value) + if parent_annotation.get(FA.FT) in ("/Btn"): + # Checkbox button (no /FT found in Radio widgets) + v = NameObject(value) + if v not in annotation[NameObject(AA.AP)][NameObject("/N")]: + v = NameObject("/Off") + # other cases will be updated through the for loop + annotation[NameObject(AA.AS)] = v + annotation[NameObject(FA.V)] = v + elif ( + parent_annotation.get(FA.FT) == "/Tx" + or parent_annotation.get(FA.FT) == "/Ch" + ): + # textbox + if isinstance(value, tuple): + self._update_field_annotation( + parent_annotation, annotation, value[1], value[2] + ) + else: + self._update_field_annotation(parent_annotation, annotation) + elif ( + annotation.get(FA.FT) == "/Sig" + ): # deprecated # not implemented yet + logger_warning("Signature forms not implemented yet", __name__) + + def reattach_fields( + self, page: Optional[PageObject] = None + ) -> List[DictionaryObject]: + """ + Parse annotations within the page looking for orphan fields and + reattach then into the Fields Structure. + + Args: + page: page to analyze. + If none is provided, all pages will be analyzed. + + Returns: + list of reattached fields. + + """ + lst = [] + if page is None: + for p in self.pages: + lst += self.reattach_fields(p) + return lst + + try: + af = cast(DictionaryObject, self._root_object[CatalogDictionary.ACRO_FORM]) + except KeyError: + af = DictionaryObject() + self._root_object[NameObject(CatalogDictionary.ACRO_FORM)] = af + try: + fields = cast(ArrayObject, af[InteractiveFormDictEntries.Fields]) + except KeyError: + fields = ArrayObject() + af[NameObject(InteractiveFormDictEntries.Fields)] = fields + + if "/Annots" not in page: + return lst + annotations = cast(ArrayObject, page["/Annots"]) + for idx, annotation in enumerate(annotations): + is_indirect = isinstance(annotation, IndirectObject) + annotation = cast(DictionaryObject, annotation.get_object()) + if annotation.get("/Subtype", "") == "/Widget" and "/FT" in annotation: + if ( + "indirect_reference" in annotation.__dict__ + and annotation.indirect_reference in fields + ): + continue + if not is_indirect: + annotations[idx] = self._add_object(annotation) + fields.append(annotation.indirect_reference) + lst.append(annotation) + return lst + + def clone_reader_document_root(self, reader: PdfReader) -> None: + """ + Copy the reader document root to the writer and all sub-elements, + including pages, threads, outlines,... For partial insertion, ``append`` + should be considered. + + Args: + reader: PdfReader from which the document root should be copied. + + """ + self._info_obj = None + if self.incremental: + self._objects = [None] * (cast(int, reader.trailer["/Size"]) - 1) + for i in range(len(self._objects)): + o = reader.get_object(i + 1) + if o is not None: + self._objects[i] = o.replicate(self) + else: + self._objects.clear() + self._root_object = reader.root_object.clone(self) + self._pages = self._root_object.raw_get("/Pages") + + assert len(self._objects) <= cast(int, reader.trailer["/Size"]) # for pytest + # must be done here before rewriting + if self.incremental: + self._original_hash = [ + (obj.hash_bin() if obj is not None else 0) for obj in self._objects + ] + self._flatten() + assert self.flattened_pages is not None + for p in self.flattened_pages: + self._replace_object(cast(IndirectObject, p.indirect_reference).idnum, p) + if not self.incremental: + p[NameObject("/Parent")] = self._pages + if not self.incremental: + cast(DictionaryObject, self._pages.get_object())[ + NameObject("/Kids") + ] = ArrayObject([p.indirect_reference for p in self.flattened_pages]) + + def clone_document_from_reader( + self, + reader: PdfReader, + after_page_append: Optional[Callable[[PageObject], None]] = None, + ) -> None: + """ + Create a copy (clone) of a document from a PDF file reader cloning + section '/Root' and '/Info' and '/ID' of the pdf. + + Args: + reader: PDF file reader instance from which the clone + should be created. + after_page_append: + Callback function that is invoked after each page is appended to + the writer. Signature includes a reference to the appended page + (delegates to append_pages_from_reader). The single parameter of + the callback is a reference to the page just appended to the + document. + + """ + self.clone_reader_document_root(reader) + inf = reader._info + if self.incremental: + if inf is not None: + self._info_obj = cast( + IndirectObject, inf.clone(self).indirect_reference + ) + assert isinstance(self._info, DictionaryObject), "for mypy" + self._original_hash[ + self._info_obj.indirect_reference.idnum - 1 + ] = self._info.hash_bin() + elif inf is not None: + self._info_obj = self._add_object( + DictionaryObject(cast(DictionaryObject, inf.get_object())) + ) + # else: _info_obj = None done in clone_reader_document_root() + + try: + self._ID = cast(ArrayObject, reader._ID).clone(self) + except AttributeError: + pass + + if callable(after_page_append): + for page in cast( + ArrayObject, cast(DictionaryObject, self._pages.get_object())["/Kids"] + ): + after_page_append(page.get_object()) + + def _compute_document_identifier(self) -> ByteStringObject: + stream = BytesIO() + self._write_pdf_structure(stream) + stream.seek(0) + return ByteStringObject(_rolling_checksum(stream).encode("utf8")) + + def generate_file_identifiers(self) -> None: + """ + Generate an identifier for the PDF that will be written. + + The only point of this is ensuring uniqueness. Reproducibility is not + required. + When a file is first written, both identifiers shall be set to the same value. + If both identifiers match when a file reference is resolved, it is very + likely that the correct and unchanged file has been found. If only the first + identifier matches, a different version of the correct file has been found. + see §14.4 "File Identifiers". + """ + if self._ID: + id1 = self._ID[0] + id2 = self._compute_document_identifier() + else: + id1 = self._compute_document_identifier() + id2 = id1 + self._ID = ArrayObject((id1, id2)) + + def encrypt( + self, + user_password: str, + owner_password: Optional[str] = None, + use_128bit: bool = True, + permissions_flag: UserAccessPermissions = ALL_DOCUMENT_PERMISSIONS, + *, + algorithm: Optional[str] = None, + ) -> None: + """ + Encrypt this PDF file with the PDF Standard encryption handler. + + Args: + user_password: The password which allows for opening + and reading the PDF file with the restrictions provided. + owner_password: The password which allows for + opening the PDF files without any restrictions. By default, + the owner password is the same as the user password. + use_128bit: flag as to whether to use 128bit + encryption. When false, 40bit encryption will be used. + By default, this flag is on. + permissions_flag: permissions as described in + Table 3.20 of the PDF 1.7 specification. A bit value of 1 means + the permission is granted. + Hence an integer value of -1 will set all flags. + Bit position 3 is for printing, 4 is for modifying content, + 5 and 6 control annotations, 9 for form fields, + 10 for extraction of text and graphics. + algorithm: encrypt algorithm. Values may be one of "RC4-40", "RC4-128", + "AES-128", "AES-256-R5", "AES-256". If it is valid, + `use_128bit` will be ignored. + + """ + if owner_password is None: + owner_password = user_password + + if algorithm is not None: + try: + alg = getattr(EncryptAlgorithm, algorithm.replace("-", "_")) + except AttributeError: + raise ValueError(f"Algorithm '{algorithm}' NOT supported") + else: + alg = EncryptAlgorithm.RC4_128 + if not use_128bit: + alg = EncryptAlgorithm.RC4_40 + self.generate_file_identifiers() + assert self._ID + self._encryption = Encryption.make(alg, permissions_flag, self._ID[0]) + # in case call `encrypt` again + entry = self._encryption.write_entry(user_password, owner_password) + if self._encrypt_entry: + # replace old encrypt_entry + assert self._encrypt_entry.indirect_reference is not None + entry.indirect_reference = self._encrypt_entry.indirect_reference + self._objects[entry.indirect_reference.idnum - 1] = entry + else: + self._add_object(entry) + self._encrypt_entry = entry + + def write_stream(self, stream: StreamType) -> None: + if hasattr(stream, "mode") and "b" not in stream.mode: + logger_warning( + f"File <{stream.name}> to write to is not in binary mode. " + "It may not be written to correctly.", + __name__, + ) + # deprecated to be removed in pypdf 6.0.0 : + # if not self._root: + # self._root = self._add_object(self._root_object) + # self._sweep_indirect_references(self._root) + + if self.incremental: + self._reader.stream.seek(0) + stream.write(self._reader.stream.read(-1)) + if len(self.list_objects_in_increment()) > 0: + self._write_increment(stream) # writes objs, xref stream and startxref + else: + object_positions, free_objects = self._write_pdf_structure(stream) + xref_location = self._write_xref_table( + stream, object_positions, free_objects + ) + self._write_trailer(stream, xref_location) + + def write(self, stream: Union[Path, StrByteType]) -> Tuple[bool, IO[Any]]: + """ + Write the collection of pages added to this object out as a PDF file. + + Args: + stream: An object to write the file to. The object can support + the write method and the tell method, similar to a file object, or + be a file path, just like the fileobj, just named it stream to keep + existing workflow. + + Returns: + A tuple (bool, IO). + + """ + my_file = False + + if stream == "": + raise ValueError(f"Output({stream=}) is empty.") + + if isinstance(stream, (str, Path)): + stream = FileIO(stream, "wb") + my_file = True + + self.write_stream(stream) + + if my_file: + stream.close() + else: + stream.flush() + + return my_file, stream + + def list_objects_in_increment(self) -> List[IndirectObject]: + """ + For analysis or debugging. + Provides the list of new or modified objects that will be written + in the increment. + Deleted objects will not be freed but will become orphans. + + Returns: + List of new or modified IndirectObjects + + """ + original_hash_count = len(self._original_hash) + return [ + cast(IndirectObject, obj).indirect_reference + for i, obj in enumerate(self._objects) + if ( + obj is not None + and ( + i >= original_hash_count + or obj.hash_bin() != self._original_hash[i] + ) + ) + ] + + def _write_increment(self, stream: StreamType) -> None: + object_positions = {} + object_blocks = [] + current_start = -1 + current_stop = -2 + original_hash_count = len(self._original_hash) + for i, obj in enumerate(self._objects): + if obj is not None and ( + i >= original_hash_count + or obj.hash_bin() != self._original_hash[i] + ): + idnum = i + 1 + assert isinstance(obj, PdfObject) # mypy + # first write new/modified object + object_positions[idnum] = stream.tell() + stream.write(f"{idnum} 0 obj\n".encode()) + """ encryption is not operational + if self._encryption and obj != self._encrypt_entry: + obj = self._encryption.encrypt_object(obj, idnum, 0) + """ + obj.write_to_stream(stream) + stream.write(b"\nendobj\n") + + # prepare xref + if idnum != current_stop: + if current_start > 0: + object_blocks.append( + [current_start, current_stop - current_start] + ) + current_start = idnum + current_stop = idnum + 1 + assert current_start > 0, "for pytest only" + object_blocks.append([current_start, current_stop - current_start]) + # write incremented xref + xref_location = stream.tell() + xr_id = len(self._objects) + 1 + stream.write(f"{xr_id} 0 obj".encode()) + init_data = { + NameObject("/Type"): NameObject("/XRef"), + NameObject("/Size"): NumberObject(xr_id + 1), + NameObject("/Root"): self.root_object.indirect_reference, + NameObject("/Filter"): NameObject("/FlateDecode"), + NameObject("/Index"): ArrayObject( + [NumberObject(_it) for _su in object_blocks for _it in _su] + ), + NameObject("/W"): ArrayObject( + [NumberObject(1), NumberObject(4), NumberObject(1)] + ), + "__streamdata__": b"", + } + if self._info is not None and ( + self._info.indirect_reference.idnum - 1 # type: ignore + >= len(self._original_hash) + or cast(IndirectObject, self._info).hash_bin() # kept for future + != self._original_hash[ + self._info.indirect_reference.idnum - 1 # type: ignore + ] + ): + init_data[NameObject(TK.INFO)] = self._info.indirect_reference + init_data[NameObject(TK.PREV)] = NumberObject(self._reader._startxref) + if self._ID: + init_data[NameObject(TK.ID)] = self._ID + xr = StreamObject.initialize_from_dictionary(init_data) + xr.set_data( + b"".join( + [struct.pack(b">BIB", 1, _pos, 0) for _pos in object_positions.values()] + ) + ) + xr.write_to_stream(stream) + stream.write(f"\nstartxref\n{xref_location}\n%%EOF\n".encode()) # eof + + def _write_pdf_structure(self, stream: StreamType) -> Tuple[List[int], List[int]]: + object_positions = [] + free_objects = [] # will contain list of all free entries + stream.write(self.pdf_header.encode() + b"\n") + stream.write(b"%\xE2\xE3\xCF\xD3\n") + + for i, obj in enumerate(self._objects): + if obj is not None: + idnum = i + 1 + object_positions.append(stream.tell()) + stream.write(f"{idnum} 0 obj\n".encode()) + if self._encryption and obj != self._encrypt_entry: + obj = self._encryption.encrypt_object(obj, idnum, 0) + obj.write_to_stream(stream) + stream.write(b"\nendobj\n") + else: + object_positions.append(-1) + free_objects.append(i + 1) + free_objects.append(0) # add 0 to loop in accordance with PDF spec + return object_positions, free_objects + + def _write_xref_table( + self, stream: StreamType, object_positions: List[int], free_objects: List[int] + ) -> int: + xref_location = stream.tell() + stream.write(b"xref\n") + stream.write(f"0 {len(self._objects) + 1}\n".encode()) + stream.write(f"{free_objects[0]:0>10} {65535:0>5} f \n".encode()) + free_idx = 1 + for offset in object_positions: + if offset > 0: + stream.write(f"{offset:0>10} {0:0>5} n \n".encode()) + else: + stream.write(f"{free_objects[free_idx]:0>10} {1:0>5} f \n".encode()) + free_idx += 1 + return xref_location + + def _write_trailer(self, stream: StreamType, xref_location: int) -> None: + """ + Write the PDF trailer to the stream. + + To quote the PDF specification: + [The] trailer [gives] the location of the cross-reference table and + of certain special objects within the body of the file. + """ + stream.write(b"trailer\n") + trailer = DictionaryObject( + { + NameObject(TK.SIZE): NumberObject(len(self._objects) + 1), + NameObject(TK.ROOT): self.root_object.indirect_reference, + } + ) + if self._info is not None: + trailer[NameObject(TK.INFO)] = self._info.indirect_reference + if self._ID is not None: + trailer[NameObject(TK.ID)] = self._ID + if self._encrypt_entry: + trailer[NameObject(TK.ENCRYPT)] = self._encrypt_entry.indirect_reference + trailer.write_to_stream(stream) + stream.write(f"\nstartxref\n{xref_location}\n%%EOF\n".encode()) # eof + + @property + def metadata(self) -> Optional[DocumentInformation]: + """ + Retrieve/set the PDF file's document information dictionary, if it exists. + + Args: + value: dict with the entries to be set. if None : remove the /Info entry from the pdf. + + Note that some PDF files use (XMP) metadata streams instead of document + information dictionaries, and these metadata streams will not be + accessed by this function. + + """ + return super().metadata + + @metadata.setter + def metadata( + self, + value: Optional[Union[DocumentInformation, DictionaryObject, Dict[Any, Any]]], + ) -> None: + if value is None: + self._info = None + else: + if self._info is not None: + self._info.clear() + + self.add_metadata(value) + + def add_metadata(self, infos: Dict[str, Any]) -> None: + """ + Add custom metadata to the output. + + Args: + infos: a Python dictionary where each key is a field + and each value is your new metadata. + + """ + args = {} + if isinstance(infos, PdfObject): + infos = cast(DictionaryObject, infos.get_object()) + for key, value in list(infos.items()): + if isinstance(value, PdfObject): + value = value.get_object() + args[NameObject(key)] = create_string_object(str(value)) + if self._info is None: + self._info = DictionaryObject() + self._info.update(args) + + def compress_identical_objects( + self, + remove_identicals: bool = True, + remove_orphans: bool = True, + ) -> None: + """ + Parse the PDF file and merge objects that have the same hash. + This will make objects common to multiple pages. + Recommended to be used just before writing output. + + Args: + remove_identicals: Remove identical objects. + remove_orphans: Remove unreferenced objects. + + """ + + def replace_in_obj( + obj: PdfObject, crossref: Dict[IndirectObject, IndirectObject] + ) -> None: + if isinstance(obj, DictionaryObject): + key_val = obj.items() + elif isinstance(obj, ArrayObject): + key_val = enumerate(obj) # type: ignore + else: + return + assert isinstance(obj, (DictionaryObject, ArrayObject)) + for k, v in key_val: + if isinstance(v, IndirectObject): + orphans[v.idnum - 1] = False + if v in crossref: + obj[k] = crossref[v] + else: + """the filtering on DictionaryObject and ArrayObject only + will be performed within replace_in_obj""" + replace_in_obj(v, crossref) + + # _idnum_hash :dict[hash]=(1st_ind_obj,[other_indir_objs,...]) + self._idnum_hash = {} + orphans = [True] * len(self._objects) + # look for similar objects + for idx, obj in enumerate(self._objects): + if obj is None: + continue + assert isinstance(obj.indirect_reference, IndirectObject) + h = obj.hash_value() + if remove_identicals and h in self._idnum_hash: + self._idnum_hash[h][1].append(obj.indirect_reference) + self._objects[idx] = None + else: + self._idnum_hash[h] = (obj.indirect_reference, []) + + # generate the dict converting others to 1st + cnv = {v[0]: v[1] for v in self._idnum_hash.values() if len(v[1]) > 0} + cnv_rev: Dict[IndirectObject, IndirectObject] = {} + for k, v in cnv.items(): + cnv_rev.update(zip(v, (k,) * len(v))) + + # replace reference to merged objects + for obj in self._objects: + if isinstance(obj, (DictionaryObject, ArrayObject)): + replace_in_obj(obj, cnv_rev) + + # remove orphans (if applicable) + orphans[self.root_object.indirect_reference.idnum - 1] = False # type: ignore + + orphans[self._info.indirect_reference.idnum - 1] = False # type: ignore + + try: + orphans[self._ID.indirect_reference.idnum - 1] = False # type: ignore + except AttributeError: + pass + for i in compress(range(len(self._objects)), orphans): + self._objects[i] = None + + def _sweep_indirect_references( + self, + root: Union[ + ArrayObject, + BooleanObject, + DictionaryObject, + FloatObject, + IndirectObject, + NameObject, + PdfObject, + NumberObject, + TextStringObject, + NullObject, + ], + ) -> None: # deprecated + """ + Resolving any circular references to Page objects. + + Circular references to Page objects can arise when objects such as + annotations refer to their associated page. If these references are not + properly handled, the PDF file will contain multiple copies of the same + Page object. To address this problem, Page objects store their original + object reference number. This method adds the reference number of any + circularly referenced Page objects to an external reference map. This + ensures that self-referencing trees reference the correct new object + location, rather than copying in a new copy of the Page object. + + Args: + root: The root of the PDF object tree to sweep. + + """ + deprecate( + "_sweep_indirect_references has been removed, please report to dev team if this warning is observed", + ) + + def _resolve_indirect_object( + self, data: IndirectObject + ) -> IndirectObject: # deprecated + """ + Resolves an indirect object to an indirect object in this PDF file. + + If the input indirect object already belongs to this PDF file, it is + returned directly. Otherwise, the object is retrieved from the input + object's PDF file using the object's ID number and generation number. If + the object cannot be found, a warning is logged and a `NullObject` is + returned. + + If the object is not already in this PDF file, it is added to the file's + list of objects and assigned a new ID number and generation number of 0. + The hash value of the object is then added to the `_idnum_hash` + dictionary, with the corresponding `IndirectObject` reference as the + value. + + Args: + data: The `IndirectObject` to resolve. + + Returns: + The resolved `IndirectObject` in this PDF file. + + Raises: + ValueError: If the input stream is closed. + + """ + deprecate( + "_resolve_indirect_object has been removed, please report to dev team if this warning is observed", + ) + return IndirectObject(0, 0, self) + + def get_reference(self, obj: PdfObject) -> IndirectObject: + idnum = self._objects.index(obj) + 1 + ref = IndirectObject(idnum, 0, self) + assert ref.get_object() == obj + return ref + + def get_outline_root(self) -> TreeObject: + if CO.OUTLINES in self._root_object: + # Table 3.25 Entries in the catalog dictionary + outline = cast(TreeObject, self._root_object[CO.OUTLINES]) + if not isinstance(outline, TreeObject): + t = TreeObject(outline) + self._replace_object(outline.indirect_reference.idnum, t) + outline = t + idnum = self._objects.index(outline) + 1 + outline_ref = IndirectObject(idnum, 0, self) + assert outline_ref.get_object() == outline + else: + outline = TreeObject() + outline.update({}) + outline_ref = self._add_object(outline) + self._root_object[NameObject(CO.OUTLINES)] = outline_ref + + return outline + + def get_threads_root(self) -> ArrayObject: + """ + The list of threads. + + See §12.4.3 of the PDF 1.7 or PDF 2.0 specification. + + Returns: + An array (possibly empty) of Dictionaries with ``/F`` and + ``/I`` properties. + + """ + if CO.THREADS in self._root_object: + # Table 3.25 Entries in the catalog dictionary + threads = cast(ArrayObject, self._root_object[CO.THREADS]) + else: + threads = ArrayObject() + self._root_object[NameObject(CO.THREADS)] = threads + return threads + + @property + def threads(self) -> ArrayObject: + """ + Read-only property for the list of threads. + + See §8.3.2 from PDF 1.7 spec. + + Each element is a dictionary with ``/F`` and ``/I`` keys. + """ + return self.get_threads_root() + + def add_outline_item_destination( + self, + page_destination: Union[IndirectObject, PageObject, TreeObject], + parent: Union[None, TreeObject, IndirectObject] = None, + before: Union[None, TreeObject, IndirectObject] = None, + is_open: bool = True, + ) -> IndirectObject: + page_destination = cast(PageObject, page_destination.get_object()) + if isinstance(page_destination, PageObject): + return self.add_outline_item_destination( + Destination( + f"page #{page_destination.page_number}", + cast(IndirectObject, page_destination.indirect_reference), + Fit.fit(), + ) + ) + + if parent is None: + parent = self.get_outline_root() + + page_destination[NameObject("/%is_open%")] = BooleanObject(is_open) + parent = cast(TreeObject, parent.get_object()) + page_destination_ref = self._add_object(page_destination) + if before is not None: + before = before.indirect_reference + parent.insert_child( + page_destination_ref, + before, + self, + page_destination.inc_parent_counter_outline + if is_open + else (lambda x, y: 0), + ) + if "/Count" not in page_destination: + page_destination[NameObject("/Count")] = NumberObject(0) + + return page_destination_ref + + def add_outline_item_dict( + self, + outline_item: OutlineItemType, + parent: Union[None, TreeObject, IndirectObject] = None, + before: Union[None, TreeObject, IndirectObject] = None, + is_open: bool = True, + ) -> IndirectObject: + outline_item_object = TreeObject() + outline_item_object.update(outline_item) + + """code currently unreachable + if "/A" in outline_item: + action = DictionaryObject() + a_dict = cast(DictionaryObject, outline_item["/A"]) + for k, v in list(a_dict.items()): + action[NameObject(str(k))] = v + action_ref = self._add_object(action) + outline_item_object[NameObject("/A")] = action_ref + """ + return self.add_outline_item_destination( + outline_item_object, parent, before, is_open + ) + + def add_outline_item( + self, + title: str, + page_number: Union[None, PageObject, IndirectObject, int], + parent: Union[None, TreeObject, IndirectObject] = None, + before: Union[None, TreeObject, IndirectObject] = None, + color: Optional[Union[Tuple[float, float, float], str]] = None, + bold: bool = False, + italic: bool = False, + fit: Fit = PAGE_FIT, + is_open: bool = True, + ) -> IndirectObject: + """ + Add an outline item (commonly referred to as a "Bookmark") to the PDF file. + + Args: + title: Title to use for this outline item. + page_number: Page number this outline item will point to. + parent: A reference to a parent outline item to create nested + outline items. + before: + color: Color of the outline item's font as a red, green, blue tuple + from 0.0 to 1.0 or as a Hex String (#RRGGBB) + bold: Outline item font is bold + italic: Outline item font is italic + fit: The fit of the destination page. + + Returns: + The added outline item as an indirect object. + + """ + page_ref: Union[None, NullObject, IndirectObject, NumberObject] + if isinstance(italic, Fit): # it means that we are on the old params + if fit is not None and page_number is None: + page_number = fit + return self.add_outline_item( + title, page_number, parent, None, before, color, bold, italic, is_open=is_open + ) + if page_number is None: + action_ref = None + else: + if isinstance(page_number, IndirectObject): + page_ref = page_number + elif isinstance(page_number, PageObject): + page_ref = page_number.indirect_reference + elif isinstance(page_number, int): + try: + page_ref = self.pages[page_number].indirect_reference + except IndexError: + page_ref = NumberObject(page_number) + if page_ref is None: + logger_warning( + f"can not find reference of page {page_number}", + __name__, + ) + page_ref = NullObject() + dest = Destination( + NameObject("/" + title + " outline item"), + page_ref, + fit, + ) + + action_ref = self._add_object( + DictionaryObject( + { + NameObject(GoToActionArguments.D): dest.dest_array, + NameObject(GoToActionArguments.S): NameObject("/GoTo"), + } + ) + ) + outline_item = self._add_object( + _create_outline_item(action_ref, title, color, italic, bold) + ) + + if parent is None: + parent = self.get_outline_root() + return self.add_outline_item_destination(outline_item, parent, before, is_open) + + def add_outline(self) -> None: + raise NotImplementedError( + "This method is not yet implemented. Use :meth:`add_outline_item` instead." + ) + + def add_named_destination_array( + self, title: TextStringObject, destination: Union[IndirectObject, ArrayObject] + ) -> None: + named_dest = self.get_named_dest_root() + i = 0 + while i < len(named_dest): + if title < named_dest[i]: + named_dest.insert(i, destination) + named_dest.insert(i, TextStringObject(title)) + return + else: + i += 2 + named_dest.extend([TextStringObject(title), destination]) + return + + def add_named_destination_object( + self, + page_destination: PdfObject, + ) -> IndirectObject: + page_destination_ref = self._add_object(page_destination.dest_array) # type: ignore + self.add_named_destination_array( + cast("TextStringObject", page_destination["/Title"]), page_destination_ref # type: ignore + ) + + return page_destination_ref + + def add_named_destination( + self, + title: str, + page_number: int, + ) -> IndirectObject: + page_ref = self.get_object(self._pages)[PA.KIDS][page_number] # type: ignore + dest = DictionaryObject() + dest.update( + { + NameObject(GoToActionArguments.D): ArrayObject( + [page_ref, NameObject(TypFitArguments.FIT_H), NumberObject(826)] + ), + NameObject(GoToActionArguments.S): NameObject("/GoTo"), + } + ) + + dest_ref = self._add_object(dest) + if not isinstance(title, TextStringObject): + title = TextStringObject(str(title)) + + self.add_named_destination_array(title, dest_ref) + return dest_ref + + def remove_links(self) -> None: + """Remove links and annotations from this output.""" + for page in self.pages: + self.remove_objects_from_page(page, ObjectDeletionFlag.ALL_ANNOTATIONS) + + def remove_annotations( + self, subtypes: Optional[Union[AnnotationSubtype, Iterable[AnnotationSubtype]]] + ) -> None: + """ + Remove annotations by annotation subtype. + + Args: + subtypes: subtype or list of subtypes to be removed. + Examples are: "/Link", "/FileAttachment", "/Sound", + "/Movie", "/Screen", ... + If you want to remove all annotations, use subtypes=None. + + """ + for page in self.pages: + self._remove_annots_from_page(page, subtypes) + + def _remove_annots_from_page( + self, + page: Union[IndirectObject, PageObject, DictionaryObject], + subtypes: Optional[Iterable[str]], + ) -> None: + page = cast(DictionaryObject, page.get_object()) + if PG.ANNOTS in page: + i = 0 + while i < len(cast(ArrayObject, page[PG.ANNOTS])): + an = cast(ArrayObject, page[PG.ANNOTS])[i] + obj = cast(DictionaryObject, an.get_object()) + if subtypes is None or cast(str, obj["/Subtype"]) in subtypes: + if isinstance(an, IndirectObject): + self._objects[an.idnum - 1] = NullObject() # to reduce PDF size + del page[PG.ANNOTS][i] # type:ignore + else: + i += 1 + + def remove_objects_from_page( + self, + page: Union[PageObject, DictionaryObject], + to_delete: Union[ObjectDeletionFlag, Iterable[ObjectDeletionFlag]], + ) -> None: + """ + Remove objects specified by ``to_delete`` from the given page. + + Args: + page: Page object to clean up. + to_delete: Objects to be deleted; can be a ``ObjectDeletionFlag`` + or a list of ObjectDeletionFlag + + """ + if isinstance(to_delete, (list, tuple)): + for to_d in to_delete: + self.remove_objects_from_page(page, to_d) + return + assert isinstance(to_delete, ObjectDeletionFlag) + + if to_delete & ObjectDeletionFlag.LINKS: + return self._remove_annots_from_page(page, ("/Link",)) + if to_delete & ObjectDeletionFlag.ATTACHMENTS: + return self._remove_annots_from_page( + page, ("/FileAttachment", "/Sound", "/Movie", "/Screen") + ) + if to_delete & ObjectDeletionFlag.OBJECTS_3D: + return self._remove_annots_from_page(page, ("/3D",)) + if to_delete & ObjectDeletionFlag.ALL_ANNOTATIONS: + return self._remove_annots_from_page(page, None) + + jump_operators = [] + if to_delete & ObjectDeletionFlag.DRAWING_IMAGES: + jump_operators = ( + [ + b"w", b"J", b"j", b"M", b"d", b"i", + b"W", b"W*", + b"b", b"b*", b"B", b"B*", b"S", b"s", b"f", b"f*", b"F", b"n", + b"m", b"l", b"c", b"v", b"y", b"h", b"re", + b"sh" + ] + ) + if to_delete & ObjectDeletionFlag.TEXT: + jump_operators = [b"Tj", b"TJ", b"'", b'"'] + + def clean(content: ContentStream, images: List[str], forms: List[str]) -> None: + nonlocal jump_operators, to_delete + i = 0 + while i < len(content.operations): + operands, operator = content.operations[i] + if ( + ( + operator == b"INLINE IMAGE" + and (to_delete & ObjectDeletionFlag.INLINE_IMAGES) + ) + or (operator in jump_operators) + or ( + operator == b"Do" + and (to_delete & ObjectDeletionFlag.XOBJECT_IMAGES) + and (operands[0] in images) + ) + ): + del content.operations[i] + else: + i += 1 + content.get_data() # this ensures ._data is rebuilt from the .operations + + def clean_forms( + elt: DictionaryObject, stack: List[DictionaryObject] + ) -> Tuple[List[str], List[str]]: + nonlocal to_delete + # elt in recursive call is a new ContentStream object, so we have to check the indirect_reference + if (elt in stack) or ( + hasattr(elt, "indirect_reference") + and any( + elt.indirect_reference == getattr(x, "indirect_reference", -1) + for x in stack + ) + ): + # to prevent infinite looping + return [], [] # pragma: no cover + try: + d = cast( + Dict[Any, Any], + cast(DictionaryObject, elt["/Resources"])["/XObject"], + ) + except KeyError: + d = {} + images = [] + forms = [] + for k, v in d.items(): + o = v.get_object() + try: + content: Any = None + if ( + to_delete & ObjectDeletionFlag.XOBJECT_IMAGES + and o["/Subtype"] == "/Image" + ): + content = NullObject() # to delete the image keeping the entry + images.append(k) + if o["/Subtype"] == "/Form": + forms.append(k) + if isinstance(o, ContentStream): + content = o + else: + content = ContentStream(o, self) + content.update( + { + k1: v1 + for k1, v1 in o.items() + if k1 not in ["/Length", "/Filter", "/DecodeParms"] + } + ) + try: + content.indirect_reference = o.indirect_reference + except AttributeError: # pragma: no cover + pass + stack.append(elt) + clean_forms(content, stack) # clean subforms + if content is not None: + if isinstance(v, IndirectObject): + self._objects[v.idnum - 1] = content + else: + # should only occur in a PDF not respecting PDF spec + # where streams must be indirected. + d[k] = self._add_object(content) # pragma: no cover + except (TypeError, KeyError): + pass + for im in images: + del d[im] # for clean-up + if isinstance(elt, StreamObject): # for /Form + if not isinstance(elt, ContentStream): # pragma: no cover + e = ContentStream(elt, self) + e.update(elt.items()) + elt = e + clean(elt, images, forms) # clean the content + return images, forms + + if not isinstance(page, PageObject): + page = PageObject(self, page.indirect_reference) # pragma: no cover + if "/Contents" in page: + content = cast(ContentStream, page.get_contents()) + + images, forms = clean_forms(page, []) + + clean(content, images, forms) + page.replace_contents(content) + + def remove_images( + self, + to_delete: ImageType = ImageType.ALL, + ) -> None: + """ + Remove images from this output. + + Args: + to_delete: The type of images to be deleted + (default = all images types) + + """ + if isinstance(to_delete, bool): + to_delete = ImageType.ALL + + i = ObjectDeletionFlag.NONE + + for image in ("XOBJECT_IMAGES", "INLINE_IMAGES", "DRAWING_IMAGES"): + if to_delete & ImageType[image]: + i |= ObjectDeletionFlag[image] + + for page in self.pages: + self.remove_objects_from_page(page, i) + + def remove_text(self) -> None: + """Remove text from this output.""" + for page in self.pages: + self.remove_objects_from_page(page, ObjectDeletionFlag.TEXT) + + def add_uri( + self, + page_number: int, + uri: str, + rect: RectangleObject, + border: Optional[ArrayObject] = None, + ) -> None: + """ + Add an URI from a rectangular area to the specified page. + + Args: + page_number: index of the page on which to place the URI action. + uri: URI of resource to link to. + rect: :class:`RectangleObject` or + array of four integers specifying the clickable rectangular area + ``[xLL, yLL, xUR, yUR]``, or string in the form + ``"[ xLL yLL xUR yUR ]"``. + border: if provided, an array describing border-drawing + properties. See the PDF spec for details. No border will be + drawn if this argument is omitted. + + """ + page_link = self.get_object(self._pages)[PA.KIDS][page_number] # type: ignore + page_ref = cast(Dict[str, Any], self.get_object(page_link)) + + border_arr: BorderArrayType + if border is not None: + border_arr = [NumberObject(n) for n in border[:3]] + if len(border) == 4: + dash_pattern = ArrayObject([NumberObject(n) for n in border[3]]) + border_arr.append(dash_pattern) + else: + border_arr = [NumberObject(2), NumberObject(2), NumberObject(2)] + + if isinstance(rect, str): + rect = NumberObject(rect) + elif isinstance(rect, RectangleObject): + pass + else: + rect = RectangleObject(rect) + + lnk2 = DictionaryObject() + lnk2.update( + { + NameObject("/S"): NameObject("/URI"), + NameObject("/URI"): TextStringObject(uri), + } + ) + lnk = DictionaryObject() + lnk.update( + { + NameObject(AA.Type): NameObject("/Annot"), + NameObject(AA.Subtype): NameObject("/Link"), + NameObject(AA.P): page_link, + NameObject(AA.Rect): rect, + NameObject("/H"): NameObject("/I"), + NameObject(AA.Border): ArrayObject(border_arr), + NameObject("/A"): lnk2, + } + ) + lnk_ref = self._add_object(lnk) + + if PG.ANNOTS in page_ref: + page_ref[PG.ANNOTS].append(lnk_ref) + else: + page_ref[NameObject(PG.ANNOTS)] = ArrayObject([lnk_ref]) + + _valid_layouts = ( + "/NoLayout", + "/SinglePage", + "/OneColumn", + "/TwoColumnLeft", + "/TwoColumnRight", + "/TwoPageLeft", + "/TwoPageRight", + ) + + def _get_page_layout(self) -> Optional[LayoutType]: + try: + return cast(LayoutType, self._root_object["/PageLayout"]) + except KeyError: + return None + + def _set_page_layout(self, layout: Union[NameObject, LayoutType]) -> None: + """ + Set the page layout. + + Args: + layout: The page layout to be used. + + .. list-table:: Valid ``layout`` arguments + :widths: 50 200 + + * - /NoLayout + - Layout explicitly not specified + * - /SinglePage + - Show one page at a time + * - /OneColumn + - Show one column at a time + * - /TwoColumnLeft + - Show pages in two columns, odd-numbered pages on the left + * - /TwoColumnRight + - Show pages in two columns, odd-numbered pages on the right + * - /TwoPageLeft + - Show two pages at a time, odd-numbered pages on the left + * - /TwoPageRight + - Show two pages at a time, odd-numbered pages on the right + + """ + if not isinstance(layout, NameObject): + if layout not in self._valid_layouts: + logger_warning( + f"Layout should be one of: {'', ''.join(self._valid_layouts)}", + __name__, + ) + layout = NameObject(layout) + self._root_object.update({NameObject("/PageLayout"): layout}) + + def set_page_layout(self, layout: LayoutType) -> None: + """ + Set the page layout. + + Args: + layout: The page layout to be used + + .. list-table:: Valid ``layout`` arguments + :widths: 50 200 + + * - /NoLayout + - Layout explicitly not specified + * - /SinglePage + - Show one page at a time + * - /OneColumn + - Show one column at a time + * - /TwoColumnLeft + - Show pages in two columns, odd-numbered pages on the left + * - /TwoColumnRight + - Show pages in two columns, odd-numbered pages on the right + * - /TwoPageLeft + - Show two pages at a time, odd-numbered pages on the left + * - /TwoPageRight + - Show two pages at a time, odd-numbered pages on the right + + """ + self._set_page_layout(layout) + + @property + def page_layout(self) -> Optional[LayoutType]: + """ + Page layout property. + + .. list-table:: Valid ``layout`` values + :widths: 50 200 + + * - /NoLayout + - Layout explicitly not specified + * - /SinglePage + - Show one page at a time + * - /OneColumn + - Show one column at a time + * - /TwoColumnLeft + - Show pages in two columns, odd-numbered pages on the left + * - /TwoColumnRight + - Show pages in two columns, odd-numbered pages on the right + * - /TwoPageLeft + - Show two pages at a time, odd-numbered pages on the left + * - /TwoPageRight + - Show two pages at a time, odd-numbered pages on the right + """ + return self._get_page_layout() + + @page_layout.setter + def page_layout(self, layout: LayoutType) -> None: + self._set_page_layout(layout) + + _valid_modes = ( + "/UseNone", + "/UseOutlines", + "/UseThumbs", + "/FullScreen", + "/UseOC", + "/UseAttachments", + ) + + def _get_page_mode(self) -> Optional[PagemodeType]: + try: + return cast(PagemodeType, self._root_object["/PageMode"]) + except KeyError: + return None + + @property + def page_mode(self) -> Optional[PagemodeType]: + """ + Page mode property. + + .. list-table:: Valid ``mode`` values + :widths: 50 200 + + * - /UseNone + - Do not show outline or thumbnails panels + * - /UseOutlines + - Show outline (aka bookmarks) panel + * - /UseThumbs + - Show page thumbnails panel + * - /FullScreen + - Fullscreen view + * - /UseOC + - Show Optional Content Group (OCG) panel + * - /UseAttachments + - Show attachments panel + """ + return self._get_page_mode() + + @page_mode.setter + def page_mode(self, mode: PagemodeType) -> None: + if isinstance(mode, NameObject): + mode_name: NameObject = mode + else: + if mode not in self._valid_modes: + logger_warning( + f"Mode should be one of: {', '.join(self._valid_modes)}", __name__ + ) + mode_name = NameObject(mode) + self._root_object.update({NameObject("/PageMode"): mode_name}) + + def add_annotation( + self, + page_number: Union[int, PageObject], + annotation: Dict[str, Any], + ) -> DictionaryObject: + """ + Add a single annotation to the page. + The added annotation must be a new annotation. + It cannot be recycled. + + Args: + page_number: PageObject or page index. + annotation: Annotation to be added (created with annotation). + + Returns: + The inserted object. + This can be used for popup creation, for example. + + """ + page = page_number + if isinstance(page, int): + page = self.pages[page] + elif not isinstance(page, PageObject): + raise TypeError("page: invalid type") + + to_add = cast(DictionaryObject, _pdf_objectify(annotation)) + to_add[NameObject("/P")] = page.indirect_reference + + if page.annotations is None: + page[NameObject("/Annots")] = ArrayObject() + assert page.annotations is not None + + # Internal link annotations need the correct object type for the + # destination + if to_add.get("/Subtype") == "/Link" and "/Dest" in to_add: + tmp = cast(Dict[Any, Any], to_add[NameObject("/Dest")]) + dest = Destination( + NameObject("/LinkName"), + tmp["target_page_index"], + Fit( + fit_type=tmp["fit"], fit_args=dict(tmp)["fit_args"] + ), # I have no clue why this dict-hack is necessary + ) + to_add[NameObject("/Dest")] = dest.dest_array + + page.annotations.append(self._add_object(to_add)) + + if to_add.get("/Subtype") == "/Popup" and NameObject("/Parent") in to_add: + cast(DictionaryObject, to_add["/Parent"].get_object())[ + NameObject("/Popup") + ] = to_add.indirect_reference + + return to_add + + def clean_page(self, page: Union[PageObject, IndirectObject]) -> PageObject: + """ + Perform some clean up in the page. + Currently: convert NameObject named destination to TextStringObject + (required for names/dests list) + + Args: + page: + + Returns: + The cleaned PageObject + + """ + page = cast("PageObject", page.get_object()) + for a in page.get("/Annots", []): + a_obj = a.get_object() + d = a_obj.get("/Dest", None) + act = a_obj.get("/A", None) + if isinstance(d, NameObject): + a_obj[NameObject("/Dest")] = TextStringObject(d) + elif act is not None: + act = act.get_object() + d = act.get("/D", None) + if isinstance(d, NameObject): + act[NameObject("/D")] = TextStringObject(d) + return page + + def _create_stream( + self, fileobj: Union[Path, StrByteType, PdfReader] + ) -> Tuple[IOBase, Optional[Encryption]]: + # If the fileobj parameter is a string, assume it is a path + # and create a file object at that location. If it is a file, + # copy the file's contents into a BytesIO stream object; if + # it is a PdfReader, copy that reader's stream into a + # BytesIO stream. + # If fileobj is none of the above types, it is not modified + encryption_obj = None + stream: IOBase + if isinstance(fileobj, (str, Path)): + with FileIO(fileobj, "rb") as f: + stream = BytesIO(f.read()) + elif isinstance(fileobj, PdfReader): + if fileobj._encryption: + encryption_obj = fileobj._encryption + orig_tell = fileobj.stream.tell() + fileobj.stream.seek(0) + stream = BytesIO(fileobj.stream.read()) + + # reset the stream to its original location + fileobj.stream.seek(orig_tell) + elif hasattr(fileobj, "seek") and hasattr(fileobj, "read"): + fileobj.seek(0) + filecontent = fileobj.read() + stream = BytesIO(filecontent) + else: + raise NotImplementedError( + "Merging requires an object that PdfReader can parse. " + "Typically, that is a Path or a string representing a Path, " + "a file object, or an object implementing .seek and .read. " + "Passing a PdfReader directly works as well." + ) + return stream, encryption_obj + + def append( + self, + fileobj: Union[StrByteType, PdfReader, Path], + outline_item: Union[ + str, None, PageRange, Tuple[int, int], Tuple[int, int, int], List[int] + ] = None, + pages: Union[ + None, + PageRange, + Tuple[int, int], + Tuple[int, int, int], + List[int], + List[PageObject], + ] = None, + import_outline: bool = True, + excluded_fields: Optional[Union[List[str], Tuple[str, ...]]] = None, + ) -> None: + """ + Identical to the :meth:`merge()` method, but assumes you want to + concatenate all pages onto the end of the file instead of specifying a + position. + + Args: + fileobj: A File Object or an object that supports the standard + read and seek methods similar to a File Object. Could also be a + string representing a path to a PDF file. + outline_item: Optionally, you may specify a string to build an + outline (aka 'bookmark') to identify the beginning of the + included file. + pages: Can be a :class:`PageRange` + or a ``(start, stop[, step])`` tuple + or a list of pages to be processed + to merge only the specified range of pages from the source + document into the output document. + import_outline: You may prevent the source document's + outline (collection of outline items, previously referred to as + 'bookmarks') from being imported by specifying this as ``False``. + excluded_fields: Provide the list of fields/keys to be ignored + if ``/Annots`` is part of the list, the annotation will be ignored + if ``/B`` is part of the list, the articles will be ignored + + """ + if excluded_fields is None: + excluded_fields = () + if isinstance(outline_item, (tuple, list, PageRange)): + if isinstance(pages, bool): + if not isinstance(import_outline, bool): + excluded_fields = import_outline + import_outline = pages + pages = outline_item + self.merge( + None, + fileobj, + None, + pages, + import_outline, + excluded_fields, + ) + else: # if isinstance(outline_item,str): + self.merge( + None, + fileobj, + outline_item, + pages, + import_outline, + excluded_fields, + ) + + def merge( + self, + position: Optional[int], + fileobj: Union[Path, StrByteType, PdfReader], + outline_item: Optional[str] = None, + pages: Optional[Union[PageRangeSpec, List[PageObject]]] = None, + import_outline: bool = True, + excluded_fields: Optional[Union[List[str], Tuple[str, ...]]] = (), + ) -> None: + """ + Merge the pages from the given file into the output file at the + specified page number. + + Args: + position: The *page number* to insert this file. File will + be inserted after the given number. + fileobj: A File Object or an object that supports the standard + read and seek methods similar to a File Object. Could also be a + string representing a path to a PDF file. + outline_item: Optionally, you may specify a string to build an outline + (aka 'bookmark') to identify the + beginning of the included file. + pages: can be a :class:`PageRange` + or a ``(start, stop[, step])`` tuple + or a list of pages to be processed + to merge only the specified range of pages from the source + document into the output document. + import_outline: You may prevent the source document's + outline (collection of outline items, previously referred to as + 'bookmarks') from being imported by specifying this as ``False``. + excluded_fields: provide the list of fields/keys to be ignored + if ``/Annots`` is part of the list, the annotation will be ignored + if ``/B`` is part of the list, the articles will be ignored + + Raises: + TypeError: The pages attribute is not configured properly + + """ + if isinstance(fileobj, PdfDocCommon): + reader = fileobj + else: + stream, encryption_obj = self._create_stream(fileobj) + # Create a new PdfReader instance using the stream + # (either file or BytesIO or StringIO) created above + reader = PdfReader(stream, strict=False) # type: ignore[arg-type] + + if excluded_fields is None: + excluded_fields = () + # Find the range of pages to merge. + if pages is None: + pages = list(range(len(reader.pages))) + elif isinstance(pages, PageRange): + pages = list(range(*pages.indices(len(reader.pages)))) + elif isinstance(pages, list): + pass # keep unchanged + elif isinstance(pages, tuple) and len(pages) <= 3: + pages = list(range(*pages)) + elif not isinstance(pages, tuple): + raise TypeError( + '"pages" must be a tuple of (start, stop[, step]) or a list' + ) + + srcpages = {} + for page in pages: + if isinstance(page, PageObject): + pg = page + else: + pg = reader.pages[page] + assert pg.indirect_reference is not None + if position is None: + # numbers in the exclude list identifies that the exclusion is + # only applicable to 1st level of cloning + srcpages[pg.indirect_reference.idnum] = self.add_page( + pg, [*list(excluded_fields), 1, "/B", 1, "/Annots"] # type: ignore + ) + else: + srcpages[pg.indirect_reference.idnum] = self.insert_page( + pg, position, [*list(excluded_fields), 1, "/B", 1, "/Annots"] # type: ignore + ) + position += 1 + srcpages[pg.indirect_reference.idnum].original_page = pg + + reader._named_destinations = ( + reader.named_destinations + ) # need for the outline processing below + + arr: Any + + def _process_named_dests(dest: Any) -> None: + arr = dest.dest_array + if "/Names" in self._root_object and dest["/Title"] in cast( + List[Any], + cast( + DictionaryObject, + cast(DictionaryObject, self._root_object["/Names"])["/Dests"], + )["/Names"], + ): + # already exists: should not duplicate it + pass + elif dest["/Page"] is None or isinstance(dest["/Page"], NullObject): + pass + elif isinstance(dest["/Page"], int): + # the page reference is a page number normally not a PDF Reference + # page numbers as int are normally accepted only in external goto + try: + p = reader.pages[dest["/Page"]] + except IndexError: + return + assert p.indirect_reference is not None + try: + arr[NumberObject(0)] = NumberObject( + srcpages[p.indirect_reference.idnum].page_number + ) + self.add_named_destination_array(dest["/Title"], arr) + except KeyError: + pass + elif dest["/Page"].indirect_reference.idnum in srcpages: + arr[NumberObject(0)] = srcpages[ + dest["/Page"].indirect_reference.idnum + ].indirect_reference + self.add_named_destination_array(dest["/Title"], arr) + + for dest in reader._named_destinations.values(): + _process_named_dests(dest) + + outline_item_typ: TreeObject + if outline_item is not None: + outline_item_typ = cast( + "TreeObject", + self.add_outline_item( + TextStringObject(outline_item), + next(iter(srcpages.values())).indirect_reference, + fit=PAGE_FIT, + ).get_object(), + ) + else: + outline_item_typ = self.get_outline_root() + + _ro = reader.root_object + if import_outline and CO.OUTLINES in _ro: + outline = self._get_filtered_outline( + _ro.get(CO.OUTLINES, None), srcpages, reader + ) + self._insert_filtered_outline( + outline, outline_item_typ, None + ) # TODO: use before parameter + + if "/Annots" not in excluded_fields: + for pag in srcpages.values(): + lst = self._insert_filtered_annotations( + pag.original_page.get("/Annots", ()), pag, srcpages, reader + ) + if len(lst) > 0: + pag[NameObject("/Annots")] = lst + self.clean_page(pag) + + if "/AcroForm" in _ro and _ro["/AcroForm"] is not None: + if "/AcroForm" not in self._root_object: + self._root_object[NameObject("/AcroForm")] = self._add_object( + cast( + DictionaryObject, + reader.root_object["/AcroForm"], + ).clone(self, False, ("/Fields",)) + ) + arr = ArrayObject() + else: + arr = cast( + ArrayObject, + cast(DictionaryObject, self._root_object["/AcroForm"])["/Fields"], + ) + trslat = self._id_translated[id(reader)] + try: + for f in reader.root_object["/AcroForm"]["/Fields"]: # type: ignore + try: + ind = IndirectObject(trslat[f.idnum], 0, self) + if ind not in arr: + arr.append(ind) + except KeyError: + # for trslat[] which mean the field has not be copied + # through the page + pass + except KeyError: # for /Acroform or /Fields are not existing + arr = self._add_object(ArrayObject()) + cast(DictionaryObject, self._root_object["/AcroForm"])[ + NameObject("/Fields") + ] = arr + + if "/B" not in excluded_fields: + self.add_filtered_articles("", srcpages, reader) + + def _add_articles_thread( + self, + thread: DictionaryObject, # thread entry from the reader's array of threads + pages: Dict[int, PageObject], + reader: PdfReader, + ) -> IndirectObject: + """ + Clone the thread with only the applicable articles. + + Args: + thread: + pages: + reader: + + Returns: + The added thread as an indirect reference + + """ + nthread = thread.clone( + self, force_duplicate=True, ignore_fields=("/F",) + ) # use of clone to keep link between reader and writer + self.threads.append(nthread.indirect_reference) + first_article = cast("DictionaryObject", thread["/F"]) + current_article: Optional[DictionaryObject] = first_article + new_article: Optional[DictionaryObject] = None + while current_article is not None: + pag = self._get_cloned_page( + cast("PageObject", current_article["/P"]), pages, reader + ) + if pag is not None: + if new_article is None: + new_article = cast( + "DictionaryObject", + self._add_object(DictionaryObject()).get_object(), + ) + new_first = new_article + nthread[NameObject("/F")] = new_article.indirect_reference + else: + new_article2 = cast( + "DictionaryObject", + self._add_object( + DictionaryObject( + {NameObject("/V"): new_article.indirect_reference} + ) + ).get_object(), + ) + new_article[NameObject("/N")] = new_article2.indirect_reference + new_article = new_article2 + new_article[NameObject("/P")] = pag + new_article[NameObject("/T")] = nthread.indirect_reference + new_article[NameObject("/R")] = current_article["/R"] + pag_obj = cast("PageObject", pag.get_object()) + if "/B" not in pag_obj: + pag_obj[NameObject("/B")] = ArrayObject() + cast("ArrayObject", pag_obj["/B"]).append( + new_article.indirect_reference + ) + current_article = cast("DictionaryObject", current_article["/N"]) + if current_article == first_article: + new_article[NameObject("/N")] = new_first.indirect_reference # type: ignore + new_first[NameObject("/V")] = new_article.indirect_reference # type: ignore + current_article = None + assert nthread.indirect_reference is not None + return nthread.indirect_reference + + def add_filtered_articles( + self, + fltr: Union[ + Pattern[Any], str + ], # thread entry from the reader's array of threads + pages: Dict[int, PageObject], + reader: PdfReader, + ) -> None: + """ + Add articles matching the defined criteria. + + Args: + fltr: + pages: + reader: + + """ + if isinstance(fltr, str): + fltr = re.compile(fltr) + elif not isinstance(fltr, Pattern): + fltr = re.compile("") + for p in pages.values(): + pp = p.original_page + for a in pp.get("/B", ()): + thr = a.get_object().get("/T") + if thr is None: + continue + thr = thr.get_object() + if thr.indirect_reference.idnum not in self._id_translated[ + id(reader) + ] and fltr.search((thr.get("/I", {})).get("/Title", "")): + self._add_articles_thread(thr, pages, reader) + + def _get_cloned_page( + self, + page: Union[None, IndirectObject, PageObject, NullObject], + pages: Dict[int, PageObject], + reader: PdfReader, + ) -> Optional[IndirectObject]: + if isinstance(page, NullObject): + return None + elif isinstance(page, DictionaryObject) and page.get("/Type", "") == "/Page": + _i = page.indirect_reference + elif isinstance(page, IndirectObject): + _i = page + try: + return pages[_i.idnum].indirect_reference # type: ignore + except Exception: + return None + + def _insert_filtered_annotations( + self, + annots: Union[IndirectObject, List[DictionaryObject], None], + page: PageObject, + pages: Dict[int, PageObject], + reader: PdfReader, + ) -> List[Destination]: + outlist = ArrayObject() + if isinstance(annots, IndirectObject): + annots = cast("List[Any]", annots.get_object()) + if annots is None: + return outlist + for an in annots: + ano = cast("DictionaryObject", an.get_object()) + if ( + ano["/Subtype"] != "/Link" + or "/A" not in ano + or cast("DictionaryObject", ano["/A"])["/S"] != "/GoTo" + or "/Dest" in ano + ): + if "/Dest" not in ano: + outlist.append(self._add_object(ano.clone(self))) + else: + d = ano["/Dest"] + if isinstance(d, str): + # it is a named dest + if str(d) in self.get_named_dest_root(): + outlist.append(ano.clone(self).indirect_reference) + else: + d = cast("ArrayObject", d) + p = self._get_cloned_page(d[0], pages, reader) + if p is not None: + anc = ano.clone(self, ignore_fields=("/Dest",)) + anc[NameObject("/Dest")] = ArrayObject([p] + d[1:]) + outlist.append(self._add_object(anc)) + else: + d = cast("DictionaryObject", ano["/A"])["/D"] + if isinstance(d, NullObject): + continue + if isinstance(d, str): + # it is a named dest + if str(d) in self.get_named_dest_root(): + outlist.append(ano.clone(self).indirect_reference) + else: + d = cast("ArrayObject", d) + p = self._get_cloned_page(d[0], pages, reader) + if p is not None: + anc = ano.clone(self, ignore_fields=("/D",)) + cast("DictionaryObject", anc["/A"])[ + NameObject("/D") + ] = ArrayObject([p] + d[1:]) + outlist.append(self._add_object(anc)) + return outlist + + def _get_filtered_outline( + self, + node: Any, + pages: Dict[int, PageObject], + reader: PdfReader, + ) -> List[Destination]: + """ + Extract outline item entries that are part of the specified page set. + + Args: + node: + pages: + reader: + + Returns: + A list of destination objects. + + """ + new_outline = [] + if node is None: + node = NullObject() + node = node.get_object() + if is_null_or_none(node): + node = DictionaryObject() + if node.get("/Type", "") == "/Outlines" or "/Title" not in node: + node = node.get("/First", None) + if node is not None: + node = node.get_object() + new_outline += self._get_filtered_outline(node, pages, reader) + else: + v: Union[None, IndirectObject, NullObject] + while node is not None: + node = node.get_object() + o = cast("Destination", reader._build_outline_item(node)) + v = self._get_cloned_page(cast("PageObject", o["/Page"]), pages, reader) + if v is None: + v = NullObject() + o[NameObject("/Page")] = v + if "/First" in node: + o._filtered_children = self._get_filtered_outline( + node["/First"], pages, reader + ) + else: + o._filtered_children = [] + if ( + not isinstance(o["/Page"], NullObject) + or len(o._filtered_children) > 0 + ): + new_outline.append(o) + node = node.get("/Next", None) + return new_outline + + def _clone_outline(self, dest: Destination) -> TreeObject: + n_ol = TreeObject() + self._add_object(n_ol) + n_ol[NameObject("/Title")] = TextStringObject(dest["/Title"]) + if not isinstance(dest["/Page"], NullObject): + if dest.node is not None and "/A" in dest.node: + n_ol[NameObject("/A")] = dest.node["/A"].clone(self) + else: + n_ol[NameObject("/Dest")] = dest.dest_array + # TODO: /SE + if dest.node is not None: + n_ol[NameObject("/F")] = NumberObject(dest.node.get("/F", 0)) + n_ol[NameObject("/C")] = ArrayObject( + dest.node.get( + "/C", [FloatObject(0.0), FloatObject(0.0), FloatObject(0.0)] + ) + ) + return n_ol + + def _insert_filtered_outline( + self, + outlines: List[Destination], + parent: Union[TreeObject, IndirectObject], + before: Union[None, TreeObject, IndirectObject] = None, + ) -> None: + for dest in outlines: + # TODO: can be improved to keep A and SE entries (ignored for the moment) + # with np=self.add_outline_item_destination(dest,parent,before) + if dest.get("/Type", "") == "/Outlines" or "/Title" not in dest: + np = parent + else: + np = self._clone_outline(dest) + cast(TreeObject, parent.get_object()).insert_child(np, before, self) + self._insert_filtered_outline(dest._filtered_children, np, None) + + def close(self) -> None: + """Implemented for API harmonization.""" + return + + def find_outline_item( + self, + outline_item: Dict[str, Any], + root: Optional[OutlineType] = None, + ) -> Optional[List[int]]: + if root is None: + o = self.get_outline_root() + else: + o = cast("TreeObject", root) + + i = 0 + while o is not None: + if ( + o.indirect_reference == outline_item + or o.get("/Title", None) == outline_item + ): + return [i] + elif "/First" in o: + res = self.find_outline_item( + outline_item, cast(OutlineType, o["/First"]) + ) + if res: + return ([i] if "/Title" in o else []) + res + if "/Next" in o: + i += 1 + o = cast(TreeObject, o["/Next"]) + else: + return None + + def find_bookmark( + self, + outline_item: Dict[str, Any], + root: Optional[OutlineType] = None, + ) -> None: # deprecated + """ + .. deprecated:: 2.9.0 + Use :meth:`find_outline_item` instead. + """ + deprecation_with_replacement("find_bookmark", "find_outline_item", "5.0.0") + + def reset_translation( + self, reader: Union[None, PdfReader, IndirectObject] = None + ) -> None: + """ + Reset the translation table between reader and the writer object. + + Late cloning will create new independent objects. + + Args: + reader: PdfReader or IndirectObject referencing a PdfReader object. + if set to None or omitted, all tables will be reset. + + """ + if reader is None: + self._id_translated = {} + elif isinstance(reader, PdfReader): + try: + del self._id_translated[id(reader)] + except Exception: + pass + elif isinstance(reader, IndirectObject): + try: + del self._id_translated[id(reader.pdf)] + except Exception: + pass + else: + raise Exception("invalid parameter {reader}") + + def set_page_label( + self, + page_index_from: int, + page_index_to: int, + style: Optional[PageLabelStyle] = None, + prefix: Optional[str] = None, + start: Optional[int] = 0, + ) -> None: + """ + Set a page label to a range of pages. + + Page indexes must be given starting from 0. + Labels must have a style, a prefix or both. + If a range is not assigned any page label, a decimal label starting from 1 is applied. + + Args: + page_index_from: page index of the beginning of the range starting from 0 + page_index_to: page index of the beginning of the range starting from 0 + style: The numbering style to be used for the numeric portion of each page label: + + * ``/D`` Decimal Arabic numerals + * ``/R`` Uppercase Roman numerals + * ``/r`` Lowercase Roman numerals + * ``/A`` Uppercase letters (A to Z for the first 26 pages, + AA to ZZ for the next 26, and so on) + * ``/a`` Lowercase letters (a to z for the first 26 pages, + aa to zz for the next 26, and so on) + + prefix: The label prefix for page labels in this range. + start: The value of the numeric portion for the first page label + in the range. + Subsequent pages are numbered sequentially from this value, + which must be greater than or equal to 1. + Default value: 1. + + """ + if style is None and prefix is None: + raise ValueError("At least one of style and prefix must be given") + if page_index_from < 0: + raise ValueError("page_index_from must be greater or equal than 0") + if page_index_to < page_index_from: + raise ValueError( + "page_index_to must be greater or equal than page_index_from" + ) + if page_index_to >= len(self.pages): + raise ValueError("page_index_to exceeds number of pages") + if start is not None and start != 0 and start < 1: + raise ValueError("If given, start must be greater or equal than one") + + self._set_page_label(page_index_from, page_index_to, style, prefix, start) + + def _set_page_label( + self, + page_index_from: int, + page_index_to: int, + style: Optional[PageLabelStyle] = None, + prefix: Optional[str] = None, + start: Optional[int] = 0, + ) -> None: + """ + Set a page label to a range of pages. + + Page indexes must be given starting from 0. + Labels must have a style, a prefix or both. + If a range is not assigned any page label a decimal label starting from 1 is applied. + + Args: + page_index_from: page index of the beginning of the range starting from 0 + page_index_to: page index of the beginning of the range starting from 0 + style: The numbering style to be used for the numeric portion of each page label: + /D Decimal Arabic numerals + /R Uppercase Roman numerals + /r Lowercase Roman numerals + /A Uppercase letters (A to Z for the first 26 pages, + AA to ZZ for the next 26, and so on) + /a Lowercase letters (a to z for the first 26 pages, + aa to zz for the next 26, and so on) + prefix: The label prefix for page labels in this range. + start: The value of the numeric portion for the first page label + in the range. + Subsequent pages are numbered sequentially from this value, + which must be greater than or equal to 1. Default value: 1. + + """ + default_page_label = DictionaryObject() + default_page_label[NameObject("/S")] = NameObject("/D") + + new_page_label = DictionaryObject() + if style is not None: + new_page_label[NameObject("/S")] = NameObject(style) + if prefix is not None: + new_page_label[NameObject("/P")] = TextStringObject(prefix) + if start != 0: + new_page_label[NameObject("/St")] = NumberObject(start) + + if NameObject(CatalogDictionary.PAGE_LABELS) not in self._root_object: + nums = ArrayObject() + nums_insert(NumberObject(0), default_page_label, nums) + page_labels = TreeObject() + page_labels[NameObject("/Nums")] = nums + self._root_object[NameObject(CatalogDictionary.PAGE_LABELS)] = page_labels + + page_labels = cast( + TreeObject, self._root_object[NameObject(CatalogDictionary.PAGE_LABELS)] + ) + nums = cast(ArrayObject, page_labels[NameObject("/Nums")]) + + nums_insert(NumberObject(page_index_from), new_page_label, nums) + nums_clear_range(NumberObject(page_index_from), page_index_to, nums) + next_label_pos, *_ = nums_next(NumberObject(page_index_from), nums) + if next_label_pos != page_index_to + 1 and page_index_to + 1 < len(self.pages): + nums_insert(NumberObject(page_index_to + 1), default_page_label, nums) + + page_labels[NameObject("/Nums")] = nums + self._root_object[NameObject(CatalogDictionary.PAGE_LABELS)] = page_labels + + def _repr_mimebundle_( + self, + include: Union[None, Iterable[str]] = None, + exclude: Union[None, Iterable[str]] = None, + ) -> Dict[str, Any]: + """ + Integration into Jupyter Notebooks. + + This method returns a dictionary that maps a mime-type to its + representation. + + .. seealso:: + + https://ipython.readthedocs.io/en/stable/config/integrating.html + """ + pdf_data = BytesIO() + self.write(pdf_data) + data = { + "application/pdf": pdf_data, + } + + if include is not None: + # Filter representations based on include list + data = {k: v for k, v in data.items() if k in include} + + if exclude is not None: + # Remove representations based on exclude list + data = {k: v for k, v in data.items() if k not in exclude} + + return data + + +def _pdf_objectify(obj: Union[Dict[str, Any], str, float, List[Any]]) -> PdfObject: + if isinstance(obj, PdfObject): + return obj + if isinstance(obj, dict): + to_add = DictionaryObject() + for key, value in obj.items(): + to_add[NameObject(key)] = _pdf_objectify(value) + return to_add + elif isinstance(obj, str): + if obj.startswith("/"): + return NameObject(obj) + else: + return TextStringObject(obj) + elif isinstance(obj, (float, int)): + return FloatObject(obj) + elif isinstance(obj, list): + return ArrayObject(_pdf_objectify(i) for i in obj) + else: + raise NotImplementedError( + f"{type(obj)=} could not be cast to a PdfObject" + ) + + +def _create_outline_item( + action_ref: Union[None, IndirectObject], + title: str, + color: Union[Tuple[float, float, float], str, None], + italic: bool, + bold: bool, +) -> TreeObject: + outline_item = TreeObject() + if action_ref is not None: + outline_item[NameObject("/A")] = action_ref + outline_item.update( + { + NameObject("/Title"): create_string_object(title), + } + ) + if color: + if isinstance(color, str): + color = hex_to_rgb(color) + outline_item.update( + {NameObject("/C"): ArrayObject([FloatObject(c) for c in color])} + ) + if italic or bold: + format_flag = 0 + if italic: + format_flag += OutlineFontFlag.italic + if bold: + format_flag += OutlineFontFlag.bold + outline_item.update({NameObject("/F"): NumberObject(format_flag)}) + return outline_item + + +def generate_appearance_stream( + txt: str, + sel: List[str], + da: str, + font_full_rev: Dict[str, bytes], + rct: RectangleObject, + font_height: float, + y_offset: float, +) -> bytes: + ap_stream = f"q\n/Tx BMC \nq\n1 1 {rct.width - 1} {rct.height - 1} re\nW\nBT\n{da}\n".encode() + for line_number, line in enumerate(txt.replace("\n", "\r").split("\r")): + if line in sel: + # may be improved but cannot find how to get fill working => replaced with lined box + ap_stream += ( + f"1 {y_offset - (line_number * font_height * 1.4) - 1} {rct.width - 2} {font_height + 2} re\n" + f"0.5 0.5 0.5 rg s\n{da}\n" + ).encode() + if line_number == 0: + ap_stream += f"2 {y_offset} Td\n".encode() + else: + # Td is a relative translation + ap_stream += f"0 {- font_height * 1.4} Td\n".encode() + enc_line: List[bytes] = [ + font_full_rev.get(c, c.encode("utf-16-be")) for c in line + ] + if any(len(c) >= 2 for c in enc_line): + ap_stream += b"<" + (b"".join(enc_line)).hex().encode() + b"> Tj\n" + else: + ap_stream += b"(" + b"".join(enc_line) + b") Tj\n" + ap_stream += b"ET\nQ\nEMC\nQ\n" + return ap_stream diff --git a/venv/lib/python3.12/site-packages/pypdf/_xobj_image_helpers.py b/venv/lib/python3.12/site-packages/pypdf/_xobj_image_helpers.py new file mode 100644 index 0000000..c175ae3 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_xobj_image_helpers.py @@ -0,0 +1,379 @@ +"""Code in here is only used by pypdf.filters._xobj_to_image""" + +import sys +from io import BytesIO +from typing import Any, Dict, List, Literal, Tuple, Union, cast + +from ._utils import check_if_whitespace_only, logger_warning +from .constants import ColorSpaces +from .constants import FilterTypes as FT +from .constants import ImageAttributes as IA +from .errors import EmptyImageDataError, PdfReadError +from .generic import ( + ArrayObject, + DecodedStreamObject, + EncodedStreamObject, + IndirectObject, + NullObject, + TextStringObject, +) + +if sys.version_info[:2] >= (3, 10): + from typing import TypeAlias +else: + from typing_extensions import TypeAlias + + +try: + from PIL import Image, UnidentifiedImageError # noqa: F401 +except ImportError: + raise ImportError( + "pillow is required to do image extraction. " + "It can be installed via 'pip install pypdf[image]'" + ) + +mode_str_type: TypeAlias = Literal[ + "", "1", "RGB", "2bits", "4bits", "P", "L", "RGBA", "CMYK" +] + +MAX_IMAGE_MODE_NESTING_DEPTH: int = 10 + + +def _get_imagemode( + color_space: Union[str, List[Any], Any], + color_components: int, + prev_mode: mode_str_type, + depth: int = 0, +) -> Tuple[mode_str_type, bool]: + """ + Returns: + Image mode, not taking into account mask (transparency). + ColorInversion is required (like for some DeviceCMYK). + + """ + if depth > MAX_IMAGE_MODE_NESTING_DEPTH: + raise PdfReadError( + "Color spaces nested too deeply. If required, consider increasing MAX_IMAGE_MODE_NESTING_DEPTH." + ) + if isinstance(color_space, NullObject): + return "", False + if isinstance(color_space, str): + pass + elif not isinstance(color_space, list): + raise PdfReadError( + "Cannot interpret color space", color_space + ) # pragma: no cover + elif color_space[0].startswith("/Cal"): # /CalRGB and /CalGray + color_space = "/Device" + color_space[0][4:] + elif color_space[0] == "/ICCBased": + icc_profile = color_space[1].get_object() + color_components = cast(int, icc_profile["/N"]) + color_space = icc_profile.get("/Alternate", "") + elif color_space[0] == "/Indexed": + color_space = color_space[1].get_object() + mode, invert_color = _get_imagemode( + color_space, color_components, prev_mode, depth + 1 + ) + if mode in ("RGB", "CMYK"): + mode = "P" + return mode, invert_color + elif color_space[0] == "/Separation": + color_space = color_space[2] + if isinstance(color_space, IndirectObject): + color_space = color_space.get_object() + mode, invert_color = _get_imagemode( + color_space, color_components, prev_mode, depth + 1 + ) + return mode, True + elif color_space[0] == "/DeviceN": + original_color_space = color_space + color_components = len(color_space[1]) + color_space = color_space[2] + if isinstance(color_space, IndirectObject): # pragma: no cover + color_space = color_space.get_object() + if color_space == "/DeviceCMYK" and color_components == 1: + if original_color_space[1][0] != "/Black": + logger_warning( + f"Color {original_color_space[1][0]} converted to Gray. Please share PDF with pypdf dev team", + __name__, + ) + return "L", True + mode, invert_color = _get_imagemode( + color_space, color_components, prev_mode, depth + 1 + ) + return mode, invert_color + + mode_map: Dict[str, mode_str_type] = { + "1bit": "1", # must be zeroth position: color_components may index the values + "/DeviceGray": "L", # must be first position: color_components may index the values + "palette": "P", # must be second position: color_components may index the values + "/DeviceRGB": "RGB", # must be third position: color_components may index the values + "/DeviceCMYK": "CMYK", # must be fourth position: color_components may index the values + "2bit": "2bits", + "4bit": "4bits", + } + + mode = ( + mode_map.get(color_space) + or list(mode_map.values())[color_components] + or prev_mode + ) + + return mode, mode == "CMYK" + + +def bits2byte(data: bytes, size: Tuple[int, int], bits: int) -> bytes: + mask = (1 << bits) - 1 + byte_buffer = bytearray(size[0] * size[1]) + data_index = 0 + bit = 8 - bits + for y in range(size[1]): + if bit != 8 - bits: + data_index += 1 + bit = 8 - bits + for x in range(size[0]): + byte_buffer[x + y * size[0]] = (data[data_index] >> bit) & mask + bit -= bits + if bit < 0: + data_index += 1 + bit = 8 - bits + return bytes(byte_buffer) + + +def _extended_image_frombytes( + mode: str, size: Tuple[int, int], data: bytes +) -> Image.Image: + try: + img = Image.frombytes(mode, size, data) + except ValueError as exc: + nb_pix = size[0] * size[1] + data_length = len(data) + if data_length == 0: + raise EmptyImageDataError( + "Data is 0 bytes, cannot process an image from empty data." + ) from exc + if data_length % nb_pix != 0: + raise exc + k = nb_pix * len(mode) / data_length + data = b"".join(bytes((x,) * int(k)) for x in data) + img = Image.frombytes(mode, size, data) + return img + + +def _handle_flate( + size: Tuple[int, int], + data: bytes, + mode: mode_str_type, + color_space: str, + colors: int, + obj_as_text: str, +) -> Tuple[Image.Image, str, str, bool]: + """ + Process image encoded in flateEncode + Returns img, image_format, extension, color inversion + """ + extension = ".png" # mime_type = "image/png" + image_format = "PNG" + lookup: Any + base: Any + hival: Any + if isinstance(color_space, ArrayObject) and color_space[0] == "/Indexed": + color_space, base, hival, lookup = (value.get_object() for value in color_space) + if mode == "2bits": + mode = "P" + data = bits2byte(data, size, 2) + elif mode == "4bits": + mode = "P" + data = bits2byte(data, size, 4) + img = _extended_image_frombytes(mode, size, data) + if color_space == "/Indexed": + if isinstance(lookup, (EncodedStreamObject, DecodedStreamObject)): + lookup = lookup.get_data() + if isinstance(lookup, TextStringObject): + lookup = lookup.original_bytes + if isinstance(lookup, str): + lookup = lookup.encode() + try: + nb, conv, mode = { # type: ignore + "1": (0, "", ""), + "L": (1, "P", "L"), + "P": (0, "", ""), + "RGB": (3, "P", "RGB"), + "CMYK": (4, "P", "CMYK"), + }[_get_imagemode(base, 0, "")[0]] + except KeyError: # pragma: no cover + logger_warning( + f"Base {base} not coded please share the pdf file with pypdf dev team", + __name__, + ) + lookup = None + else: + if img.mode == "1": + # Two values ("high" and "low"). + expected_count = 2 * nb + actual_count = len(lookup) + if actual_count != expected_count: + if actual_count < expected_count: + logger_warning( + f"Not enough lookup values: Expected {expected_count}, got {actual_count}.", + __name__ + ) + lookup += bytes([0] * (expected_count - actual_count)) + elif not check_if_whitespace_only(lookup[expected_count:]): + logger_warning( + f"Too many lookup values: Expected {expected_count}, got {actual_count}.", + __name__ + ) + lookup = lookup[:expected_count] + colors_arr = [lookup[:nb], lookup[nb:]] + arr = b"".join( + b"".join( + colors_arr[1 if img.getpixel((x, y)) > 127 else 0] + for x in range(img.size[0]) + ) + for y in range(img.size[1]) + ) + img = Image.frombytes(mode, img.size, arr) + else: + img = img.convert(conv) + if len(lookup) != (hival + 1) * nb: + logger_warning(f"Invalid Lookup Table in {obj_as_text}", __name__) + lookup = None + elif mode == "L": + # gray lookup does not work : it is converted to a similar RGB lookup + lookup = b"".join([bytes([b, b, b]) for b in lookup]) + mode = "RGB" + # TODO : cf https://github.com/py-pdf/pypdf/pull/2039 + # this is a work around until PIL is able to process CMYK images + elif mode == "CMYK": + _rgb = [] + for _c, _m, _y, _k in ( + lookup[n : n + 4] for n in range(0, 4 * (len(lookup) // 4), 4) + ): + _r = int(255 * (1 - _c / 255) * (1 - _k / 255)) + _g = int(255 * (1 - _m / 255) * (1 - _k / 255)) + _b = int(255 * (1 - _y / 255) * (1 - _k / 255)) + _rgb.append(bytes((_r, _g, _b))) + lookup = b"".join(_rgb) + mode = "RGB" + if lookup is not None: + img.putpalette(lookup, rawmode=mode) + img = img.convert("L" if base == ColorSpaces.DEVICE_GRAY else "RGB") + elif not isinstance(color_space, NullObject) and color_space[0] == "/ICCBased": + # see Table 66 - Additional Entries Specific to an ICC Profile + # Stream Dictionary + mode2 = _get_imagemode(color_space, colors, mode)[0] + if mode != mode2: + img = Image.frombytes(mode2, size, data) # reloaded as mode may have change + if mode == "CMYK": + extension = ".tif" + image_format = "TIFF" + return img, image_format, extension, False + + +def _handle_jpx( + size: Tuple[int, int], + data: bytes, + mode: mode_str_type, + color_space: str, + colors: int, +) -> Tuple[Image.Image, str, str, bool]: + """ + Process image encoded in flateEncode + Returns img, image_format, extension, inversion + """ + extension = ".jp2" # mime_type = "image/x-jp2" + img1 = Image.open(BytesIO(data), formats=("JPEG2000",)) + mode, invert_color = _get_imagemode(color_space, colors, mode) + if mode == "": + mode = cast(mode_str_type, img1.mode) + invert_color = mode in ("CMYK",) + if img1.mode == "RGBA" and mode == "RGB": + mode = "RGBA" + # we need to convert to the good mode + if img1.mode == mode or {img1.mode, mode} == {"L", "P"}: # compare (unordered) sets + # L and P are indexed modes which should not be changed. + img = img1 + elif {img1.mode, mode} == {"RGBA", "CMYK"}: + # RGBA / CMYK are 4bytes encoding where + # the encoding should be corrected + img = Image.frombytes(mode, img1.size, img1.tobytes()) + else: # pragma: no cover + img = img1.convert(mode) + # for CMYK conversion : + # https://stcom/questions/38855022/conversion-from-cmyk-to-rgb-with-pillow-is-different-from-that-of-photoshop + # not implemented for the moment as I need to get properly the ICC + if img.mode == "CMYK": + img = img.convert("RGB") + image_format = "JPEG2000" + return img, image_format, extension, invert_color + + +def _apply_decode( + img: Image.Image, + x_object_obj: Dict[str, Any], + lfilters: FT, + color_space: Union[str, List[Any], Any], + invert_color: bool, +) -> Image.Image: + # CMYK image and other color spaces without decode + # requires reverting scale (cf p243,2§ last sentence) + decode = x_object_obj.get( + IA.DECODE, + ([1.0, 0.0] * len(img.getbands())) + if ( + (img.mode == "CMYK" and lfilters in (FT.DCT_DECODE, FT.JPX_DECODE)) + or (invert_color and img.mode == "L") + ) + else None, + ) + if ( + isinstance(color_space, ArrayObject) + and color_space[0].get_object() == "/Indexed" + ): + decode = None # decode is meaningless if Indexed + if ( + isinstance(color_space, ArrayObject) + and color_space[0].get_object() == "/Separation" + ): + decode = [1.0, 0.0] * len(img.getbands()) + if decode is not None and not all(decode[i] == i % 2 for i in range(len(decode))): + lut: List[int] = [] + for i in range(0, len(decode), 2): + dmin = decode[i] + dmax = decode[i + 1] + lut.extend( + round(255.0 * (j / 255.0 * (dmax - dmin) + dmin)) for j in range(256) + ) + img = img.point(lut) + return img + + +def _get_mode_and_invert_color( + x_object_obj: Dict[str, Any], colors: int, color_space: Union[str, List[Any], Any] +) -> Tuple[mode_str_type, bool]: + if ( + IA.COLOR_SPACE in x_object_obj + and x_object_obj[IA.COLOR_SPACE] == ColorSpaces.DEVICE_RGB + ): + # https://pillow.readthedocs.io/en/stable/handbook/concepts.html#modes + mode: mode_str_type = "RGB" + if x_object_obj.get("/BitsPerComponent", 8) < 8: + mode, invert_color = _get_imagemode( + f"{x_object_obj.get('/BitsPerComponent', 8)}bit", 0, "" + ) + else: + mode, invert_color = _get_imagemode( + color_space, + 2 + if ( + colors == 1 + and ( + not isinstance(color_space, NullObject) + and "Gray" not in color_space + ) + ) + else colors, + "", + ) + return mode, invert_color diff --git a/venv/lib/python3.12/site-packages/pypdf/annotations/__init__.py b/venv/lib/python3.12/site-packages/pypdf/annotations/__init__.py new file mode 100644 index 0000000..44ed1da --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/annotations/__init__.py @@ -0,0 +1,42 @@ +""" +PDF specifies several annotation types which pypdf makes available here. + +The names of the annotations and their attributes do not reflect the names in +the specification in all cases. For example, the PDF standard defines a +'Square' annotation that does not actually need to be square. For this reason, +pypdf calls it 'Rectangle'. + +At their core, all annotation types are DictionaryObjects. That means if pypdf +does not implement a feature, users can easily extend the given functionality. +""" + + +from ._base import NO_FLAGS, AnnotationDictionary +from ._markup_annotations import ( + Ellipse, + FreeText, + Highlight, + Line, + MarkupAnnotation, + Polygon, + PolyLine, + Rectangle, + Text, +) +from ._non_markup_annotations import Link, Popup + +__all__ = [ + "NO_FLAGS", + "AnnotationDictionary", + "Ellipse", + "FreeText", + "Highlight", + "Line", + "Link", + "MarkupAnnotation", + "PolyLine", + "Polygon", + "Popup", + "Rectangle", + "Text", +] diff --git a/venv/lib/python3.12/site-packages/pypdf/annotations/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/annotations/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3ad583a7af6653d09fa5a5582d579d63a84562c5 GIT binary patch literal 1158 zcmZuwyKdA#6dms)yX$0=@DL!X>7qrj7SJN3NFh*=hai=Oux9PM-XZfaGvg4Kd;ujr z9pAzq7>R}o(Et%dqT-G>WGS%ZqdT5E=bU@*_``4*5_~?s`IUca6Y|+F{ywd<;N%$w zZ%IaCk_A~y1hN&kWIJvLe%%%w*^Rq$DPEGjxF`E@Uk>7d4C7EP$IEghUXjCi*yMJ^ zs$7fL5LXtkxi*&hxmmZF)r9d0G)w>aTp%VfGQ?&OHZl8#exL0Rp!5OLz#1iPfCY*nWiX1 z4NL{3t~oO&;41V4XTH+85w0i`f~L%Z9n)=XC>%3c2)NmtYzlFx!%Rjqm~!P!h8s^` zmdwD$KW;FcITXizFV9j}B5_3(0GiZvg38UIxr&={iyoQP>Sj3aK#KX6az{6wpmC;h z0UOwX&87ydG1UfLdAExmoHY`?&@G<&)-qG=OpRRGmc@dh?(J()sVTiChx>)y; zB-3e<)ZJu)mt(y#k;^l*BG1h;>5 NR+n3^d*%wJ{{hApV?O`@ literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/annotations/__pycache__/_base.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/annotations/__pycache__/_base.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..db5066dc54ea37436f2ddd1aa9e451b6e5d58e57 GIT binary patch literal 1488 zcmaJ>&1)n@6o1uU)0t$FY@)L48c9$WN8M>$H>emFqLLNSULhW&U1)o{YGx<)$5`DH zGGUY~1l$E-JqXFcgU3kx1NT zDrLa+@ZR6e?^J-_g)v%2p$tDmWd|rw5}z>NXG{U6QrIVjUGAFIu}8wFl1yEG`<+Khu1_vUQJi{dD~?tI zuUS>Hvh9WJMtzO>X*OYZ!aC!*g*&I;ZTTYAUU zRue5D>M*>50ujcN0^u(aVFh}Gsw0GYxvh=tCCu+aRkyi-v`VskO3Xjvag(zovDR6% zZUwEn)$XRZ;^@`dD_5+fm9ooi&;Q(OvIGNd+OWLi+e$2XWUbxJOxJB;IoI8sI}4fG zC_IL}Bo|R^!GT#jG~jt_Z=?U*>vy!f&Tgq+nSWp|3^5G67^aj#1 z*}QP(gfccGcFdvJg5RcQ?`_=O_`dwZ)&BVxeyaU^uK(hj{i&t<<`O?AtF3!MhxtV} z=mGc-Rnp@rd&d*?&YZKLiemFwEK^l@2|ooDweMkf;_^fF*h^Y zJZ>|db|uQPjm$_`nlk<)$f|jN;xCH}Vd5`&55+bN6-|F*FayTqKq2~D-+uKM;Ag0g z90LQ4@vm>*zA3_syVnL7UfiQ1Yf)s)914Gah$wAW$1~Nd`&>{b8}s8RNxdjdWNTTe zcvv|n1ftpb10Y+GAsyEZ)EP(%$N0K<)4nOkCJq=#M{r+mzM*0WTs_y8r+H literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/annotations/__pycache__/_markup_annotations.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/annotations/__pycache__/_markup_annotations.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..590cdc8864f4cd6799881e60fd3a2194892823d0 GIT binary patch literal 12990 zcmeHNTWlLwdOkyPhQq5U>VC0JSy%cZM!s8ioXD0Od+W%KFGG(!^-{oZ%@!ySpeR6@xhPX@W3=f*UKW(4ba(yK|35>{ z3}xBgqT59ub|n6D=0BG?Gw1)m|8nM^eLgpV<6qzVuhDCrg!~6yln$X-SoxA8W<%~L0VpN1Whr}mcDR`eMn{-{4y5v^d?Vlt4bj8>+C(O{}7T9vAfR;OyBHLT8+tWDKL>sZ;HtWPyW8=&lw zyvfE?Q?x179Bt-^OfL48CT^Z3PI5F7$@j)ue5pA`R7l>4KjY!pUvuwNL(C-&*WBeN6 z*UD{o>_u)nw_TDYBz+XUQZ3%84LHvo5|g&StvO~4IVxLX*v1-P3n z+^vk;3fwjeciRLPZvPIaIT+?Nd*9(BVIEHD3C(dLp{Sa8a!gHR(($CmpB*1d${K$z z4cFh;h9Jsmfa3+(KjdWJNqMlJ{ zB0Z{e;N}&l;U4kyXtLM^Sndn*m6)1|(b1vrK%fasNE|#FJ9?t;g)>^UIazaFVcU1O zir=A%zyPkZ6Jv5;G7(oa;bobs@)b?I4ClnK3>+$}<1{^tBbN?TARJ(25y*!m3+lr} ziBaQ<3Eh-!iZeLt)jOu_S<+8l-%ZGCumDs1l%N{-%5qu$4lWBEQ=Elw%L)eHrWQq# zkgVO(-frPLEbSfd>~#>8*GGjuT-FBt93zf9#rsYfr^ z3avthNSooL@mFHV=O^?NT*a@jD>!lR4>AX`q$(mb4i%4wiO7XaN{%E((+QN6$cq^$ zWaufH8KttKL@vwe%aLSaC^9yoUdW_(cK7UvC<#^GJ{BK-BR(oCP%$QrMB;`ZDiOFb zePetqX5n>@O=xwoQCW=*WyaGIh!IF~QF>??CbSWL%DX_WlEtc~nZBC`W-i@4G`nxE z?~?;_mp(Z(z5D9G<0}I74~T=`c-=A0P4_GXs%{L-^!$x)ntw|1I$v->w^cXsHq8vo z?w)I(ugNv-&3pD;?O*g%T>Y~Zm=GC8QaVa&wXzL39|9ysIf+DV5*M{gHp%`mfT8S= zc_xFrWCJ)8t^r_A*uqXN@FIIJrW#EC(v9nIIIhT{;bdGrhigNrs|0{+6b!AV=>Y}iJFz@Y&k051+jPL8nKDySi$5bc7K zCdOh35ad{FvSIB@?=DsCf`&>95D+;}b|G|4K49Rn0v4G3 zfDsn;zYzz@sBVrWUUo@>?3SFeM-pYPUnP{j%Eo3Xe2XEK`vE!RHjPk{P`bVIdNiJ zXadQVbElzn?)2;D&zDK1GA0ivMkW9>m?#b>697F!NjX%6knto)cAUy_qZiH#R02hx zsl|o3ih>-MBv1-a5|n6IrExT)MyJe}oHkW!1nenj8mm2uf`-)^&)5{)IHEalY`Pzc z6x||Cc;n4DXeSf@K|}u0b3ys{z;6YdH1YxWAu*-@x{xLBLL14MAX)wv_tzX}F$ks> zfNqqa2Ry?&MU6q-P@O>7ku`LtthK$YwaaL2j8fLxFgh@zA5y{gKjb5)L0}%bB1bYHBxzNFCMV(5PYMxqaTK}- z<^#IOE8}Cbu3HQXm?_ku!4EBHC2K|_SjOd|2ap)6Me*@8S1iVGHx^UyEdm01_lk)UzcUj;r8$}6~c6g(P`*CFuyG&|@XMWJM{r1^?( zU|3EjW3k&DJq%R}ir4e{Ye2}RNbuDuX&}EvuyO-fZ6>u%i!~b_`276-ftd~WN&Li^EN_0a|Y3k4^(5J^R_;KGudR8$o_Sn`rURe|;Qld9T61@Z#K z?f*?Bl$Hq)9rJJkWtdk73_MnT3gl7DlkD&Zp%MHElJjFHpqfK+JplpTQ11a0^uo^v zWk38XWZ*Wy_zX-vNg41rHJO3}g6Il9a<=^up0peK=>Lh=%l(@4%BIg11}Vhwm9SfDmB@Y2A* zt^u!#B6w8+c)9OdSMJ7jsZQq?|2*pIg$tN z<;{|d22jE@i^qC^ZQ&VUZQ&VDYXNoRy;$0LOS4l=$X#zd-#YC)2G2AoeuHO@XWS!U zfILUC;?=Ec#X3(|VT^#l%MK|};w6l^m6?OeQa!G1*7ept6~h^JSXRPSYSmBP^AFob z$*}EpnB|mT#b}5fS!4b;ZSPb#pv9EIDZ68^G#1_woyuWIuVCvpNw|7&(iJJ`EIkAb z=yO0O1=P3R(4b5zR(N z>GL>{J<@*$NgueeudsLyt`47hXp0=tjhct{;a$=2SWH?qTx!Djm=srK-M--(G5bcn zSiF`_CK#CN=4tV3Pvv6c=9$LXy}7!r z*N@#d%G1Zb_EhLqyK{Bn@~Xw!jW?pRu9+XtwaoR;?a5W`m=+l?w`uQP_k1>2)juuX zZ|lg3Enj=;mTE(@&H38y2ZZyT;%?X$Bgb;x$3NTrS@mZx<+hz%2!soEthv9nKeuJz z)6==GV>xg8ebM`#=ep&1NQV8Q3~`B&{Om%C6+y!AQHrf)m;tO}%N z(~O$0Zo8G7@A=zIfwxx%SL}SJpM@?1`O3`;-c~TK-sYUAbE*BArSQ(&uKs*@;LE_# z*}nIiW?uSW3s_j@gwV`c7L++;Q4h={XE7KPulb^G=5Bbv-Ed?~R8BSRG8bO0< zSW~NglUP=zgy3a00(xod)Yu-|$0n8a88z>1&f95>XwJv1H9Q2%6BxYF_1=SF$<}*5 z$!*-NBs%2DyixPLnzJ&kyJ4lxU@Tz-U>qh?e1pu)L4bvFq+2^%ev!5bw$dLbtYlTi-f+c=pmK1Nr(bOTS0C z;Noj)SM1K#Al$mLiNW=)1K-wfp52?T-?~&h10-WBzAd=wwYF-VJ(92Q!uwdy1*ZdB z3(y(>s;SIG6nYwb{_pKgF1H^1aTM_~>|Kk>O~73jkQq`N5#Rb)d>%U^`4E1J1O%`c zV6&!f+0(|m?|Xv<9?k&2zN&%~OHYPhY@x$1mb?g^J}mhWIxC>GOn~UniMK6-PBb2P ztYCm^g-(RcVnk+>d5rKz1Qv(!*St|EK^%tJazPVMWs(z2sGDI3Yh(k+XB;S=3=iK1 z=VVP}Q^G?`%h=XNHfEwl;@*IKBlTD?z|j1+xlsZ;3LHcb5IeIS1;-ShwO=$)(3lA^ z5y8~f5*~op{j@%Yhi>+H=Kw?~5_I+(d4rL~6~5^f>k))B)t23NN&PPS%GLQ2p5ay&UM4^Rs6w1BQ}TGE|s z6U-QnVQj*-DsC5X%n&Wj&1Mlx!j2wo$7UT!o&aZ+r8ydq_9^sG{tgI2ntLszEqVOY zSN`hRnZA3T4NJl1+=g@c;LADh%ZoL2)9%IUW=I*kBG>z;`=&1~dTYP(ZdmYc_&7P& z^HJt=Z}%F`7vAmy56wZBUB1V7tmvZtqG>*w4?l0>=I6UleD-R7_sjYAR{*aNlY|l` ziEF_K9S6z~=_$Z7f(?=U1N@ZjKoEFrLBO0~?TyPfw-tCO!(0JDoLCYOL0nK;CO~uq z!Tx0kQqr(ToG;j{w!t2a9dU#?UII8@!Wy>=a^x)Q!?NNMHzG2OaYC-gbiPE*g?UQ0 z{W*9Wc49H5O%s`7E=D(P3e3v{pWzbr0NN1T?_}7ME@F?wW$l+?htEt6<6J>Q?a&eq zL;-zoa|-qdCGJ_vX32FP@-UG3liYw-b{(xi_YJQ=9|5TuS4*azm);iSR7#p@X=m!R z+0OKgOrGKUSg_2{c&nyoZFHaMy_wmBtbv>m={qcuzQck##;lD<-{3%`Z_dW>wGP5l zTOxf2MEagVt)jSG*#!R#jVLNp?tT-cQV3UXHUJ^wEsl$nj z;z~Zn1;P-Xh3U5iOG4U|jvrw?g9`yl%=@uAKS4v%47m6b+UX(FRRTuUyJ1#X@N_JB zyK>>)+`$u{jeZW`u%R{AwtHd2p6S8GKy9wBD;EeaiN3O&wZ&IrQEGHv%(w4HoiE0) z`}18aD7D0}O!-$)`IiI4+ql%x1L5WTU_N~0%Rs*wUG_tCX$eU0K|l(7X^jwF_OIY$ z{-Y;&c!zlV5kICpgRRGu*q$Y^pB7VI!iGq`fS-b)7s82~gttF%)$#uO{;J33sClRd zbZKart@@d-fUTh)ppFMiUPK)ql$Hq)9d+(fCY^y8rZW8EtQ)<&{cV47tDevMF=^V@3MFiMjGtdd>}l> z!ZJM$TiU+&Zbg3ku`jES&vEbnaJKS;AKj}y4j|GByGErX*fJ!+s+Sr%ziQaN(6D{F z|J@%Ts8s*%fs54qfMZ#!Uv3Q^-rN}Wt#wJ(!xi@WSbWrv@8v1J%3oj`Bn9{>2_Slq z6zW=R*!aL#!*_$9@`R+66I+O+wx!_0lAAPcD0r|0@ljoY_1Aa7kf-m0L1~!)(Gdsl zU4}R%d-s3o=QszF$;6l<4^j%Z|C3__F9E(_DM88qGslLG;~Fu~;xd-rL~;emAs~~^ z$dLpcPOkN0=mfTy1j01v5eFnt6afPQ@H>V-g!^I1ng0>p5Bg(#+$@q8@R{LZO1s@Z zMJ5s#K4H24Q2!MF0qQOO177L=1D16E0ZPjRh_20en=)-iF9(kmw8`cEL(y;G_3w39 zbYhc*H5m{m^ASXr0dZo42@y2=G|+0~OF;&%eJS1LIxTc^JEDXZ}GFy3(#>b6o@QO zf)av;3^KjP&rbSEyd%lXxMU_x=tUd=zx`0wPtOL5(q;fe2ddA%KnL^@e(!X~{XbMX zV|_5`g^zA9v{{qg!2Pycy>pp-E34Hb9c!|~BVe*aEG0W!Yds5=?7$bJ2P;qUBCcaY zB<=W)_ToFjj7N>0@fe>uH#;!%+Ctryh2Yi#58Ptz150}D14`%<6muUqQg}OjXgHy0 z_V~~+#e9J#z_(QB`LnsO`60MaHc51ZG$A&wCXxz^UNskd^r=8D0|Eo)K{`ie*bhhy z>-)>-Kx@7ts~f&HRb+}Eg|LWL&-SCRvmCz`G};wE&I4nEqO19h3jN0Dv}(LQS}k_3 zLxvafdkTK+o=C%|u#L#7)E^}V8|-o#>lFPpV|Gcah*`ffhOaKeIMg;I_{k94UZm%- zG=k(366VGs__9@CF18NHUBG)N9@IbVJVbGq0hWj;D?nh!m*bX*`&Xpu8?x&QvgT?;VXO9g1zd-;TtdI>~%AH@7Xv1nuFq>yv?9?j`XR}*Y%z&r`6>+3)udD1UqBn{0Q0kbhytF2WkKdKH-Wh(Z)jC3!Bz<@pq!ccdJ7 zXUdruQUXU5UU8^m-j#CYrIeI+r`&l@%45l$syFXT`SSjh->M60ARkNx^PyD8s*7qk zA4x@kcPWzEmXD^Q9O20*QQU76#Y3Z?IO^j_t+S+FkosDr?bH55;2x?Z1k*op=H#&a z!tvo3esW@L)N~AL)21|DG;#$kt(w9_si;y@IIThb9*pwhH9K6#F24AV1~ z&eJvCH&)6|QnpqLP0&lmDTC#-Y+aJzP46IM>1kVGD3`H3u{8-Q3=NMAo_=XU9yu{# zI!1Cvf-{4!fTOgQRoDF7<8UOL86DKLf{{iOO-mV^nO%Zw%qj!sm#`<4q&S77c!k3s zbtwE*r{bVaDo~NS>c1&xCumRcNEIiQsN3QM;5-&50_U|j7xgI;^($_Ln+nX4DNgac z9Y_IpiAx1fk%ZTDzLe9>kHNBulLe+wW;#ktHN!@lWvL+-(^)F#G=*L=9aA~ObTXJJ zYX`^dDI^_8(32^izX)A)Q)JXAF)f2jfCbN-5B^^Guf7F4|9kE|V%V+Za-d9p*7e+p^y?cE0vwr*Ikx$f7z{j4YX|)#qr6S<+r%9 z#M;Vk7H(;EmK`7Picofbz<=m$(d2*rvoa62L5z_h@{T9NXGw;C%}>az#{gO{WslwC zcl@t|PBQC-R(t$f{p;Z*O-KRy?7(t87`vkqlI9l}l4LzK=RmxmL z*7O@_$eOFw@R4im5$wIhP8sWMTP>b~4GT@Hp(n_mG{f){^qPG)+TO~IQe8gEK%PHDT^7{#o=?Ek??qIO>#$u#^j zJO}?-&&3ul(LTl`Xh-BaW?gy<^d_c@bmsVQ&Nxe1ya!OACtd*NM@Y~UKbyWl<3=Gq zN#jLUxR6t*(icBgFwVv=Qbyxr1&#L24E*1g!1cgPbXWXGo(Jw>8ge1b+BO!^%JmX5%r#ZtXPt7=!r(Zb%qCpGVK{S|fwBVQoFef9D zfsG-m8y}NI*c9|q5uj0$0Slp7W;hO0Kvz1$9W*_!rqvQ1W~{&%!jb7vsm5^gO)*_8 zQcW?%Qc+18lwo{kc-$GpXTlI1P0K5qW80vb2%1ivs#7e63Qs^=hBu+^*qhU32xF9C zJj6;)TdQ!I>8WEn%!ipiC9R(YKsT`2^eZqoS)o&uF{+quS0Lo1OD)lh2H!M6o! zg!c#Ti^TWT`zWsQT)3m!);{08)UkVM{jQ~0U(LaVpI&u1P}kuP)O^GjS@LeI?m2LC z>&<5t4}RHsOfGdEnR^k)N-#3t|Eo8yq;Cf|uWa7=*{gpVymjWw-to`4 zPhYwj{=@j~-to%jlk>i6DE3uo%W`PT!mcku$-A-ch1Wj-BRg;Wbh)!{?!~Vq-#gyR z-n*gLm3@`aw(F@ysnT^|1*!)tq3%yTi~A}&4q?@5l@})}T?esxpc3l3{>I|LO3#s+ zTkr=SI$Ung{SeG?rEBlq=%y=1CA$6kxyANM_x=^AUaUlWK8-D&s3eYH^+F}u{g)m4 zZ?;u-4AflCaAegXb_eE$-i=)us)V;J`?lT>fUUb5cHK?vUFsjLB#y7F?^?)wq+U}i z>-SXS+dlGL^W9(TxiK*JaxFj-{g#2zN_hKiUstUS41E6}Nn+1`|IglW9gqC2NMvN6 z^K%jzIV>eYc(pXh(`4E7$a21*lvLz>viy1}t=3x@o=oOKV%;7QI8&HX3u%L4mQlZL z4&8tp1}*`^Bf~7L!1HAK*N%9Gs;Vr1%(3S{s$;rvlo(5Z?f99=|S+Y&|ectFgicJaQepH#jcy{J`2eA*TN`^5KrLSHsJ0PAgeHv z`oJ>C*~LzJR#PB(EOmtB{VETsp`AF2kUWY%NE-!6B_%6G6scQrQI8@)is-RYL^q^} zUMofPL5k=xg_DJ1sW>(Q*{@hkGpa!zSO7??!_y$RXUC9OptJ$FM)HR+iExKwT|EeE z{aErRt|fnNNdBDl|)@yTSaN65lvYm`D)Q?1WChf_iaf*nthvL*mJdH%frNXmn7M@x>DGQ2Z zL~V^vFtkD8$QcOW7s(~Z8FGTC%6_XA0|*ly&l*!I}rv6QTP ziK|%;LT}b@rxgnIA5jKg22K98G_g zYLw+Neez^lrwq?g{aE4ct0zMp4Hd|j(lP*gDFbgxNVPDZva%-A*U*7{tsWT=@6AX< zj_1;PlUvJb3Uz<@kg6m7QRMKL*C&7>;E{B=9(s;2TtmPsqCXD=asrO~I~n+b41DVp uIDVA?`PN6cVUYITAy3~SJrBhJu7An9`5}St!=wCqF0$l{|C_+qa_}FPrW?lq literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/annotations/_base.py b/venv/lib/python3.12/site-packages/pypdf/annotations/_base.py new file mode 100644 index 0000000..e726006 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/annotations/_base.py @@ -0,0 +1,27 @@ +from abc import ABC + +from ..constants import AnnotationFlag +from ..generic import NameObject, NumberObject +from ..generic._data_structures import DictionaryObject + + +class AnnotationDictionary(DictionaryObject, ABC): + def __init__(self) -> None: + from ..generic._base import NameObject + + # /Rect should not be added here as Polygon and PolyLine can automatically set it + self[NameObject("/Type")] = NameObject("/Annot") + # The flags were NOT added to the constructor on purpose: + # We expect that most users don't want to change the default. + # If they do, they can use the property. The default is 0. + + @property + def flags(self) -> AnnotationFlag: + return self.get(NameObject("/F"), AnnotationFlag(0)) + + @flags.setter + def flags(self, value: AnnotationFlag) -> None: + self[NameObject("/F")] = NumberObject(value) + + +NO_FLAGS = AnnotationFlag(0) diff --git a/venv/lib/python3.12/site-packages/pypdf/annotations/_markup_annotations.py b/venv/lib/python3.12/site-packages/pypdf/annotations/_markup_annotations.py new file mode 100644 index 0000000..17f118f --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/annotations/_markup_annotations.py @@ -0,0 +1,315 @@ +import sys +from abc import ABC +from typing import Any, List, Optional, Tuple, Union + +from .._utils import deprecation_with_replacement +from ..constants import AnnotationFlag +from ..generic import ArrayObject, DictionaryObject +from ..generic._base import ( + BooleanObject, + FloatObject, + NameObject, + NumberObject, + TextStringObject, +) +from ..generic._rectangle import RectangleObject +from ..generic._utils import hex_to_rgb +from ._base import NO_FLAGS, AnnotationDictionary + +if sys.version_info[:2] >= (3, 10): + from typing import TypeAlias +else: + # PEP 613 introduced typing.TypeAlias with Python 3.10 + # For older Python versions, the backport typing_extensions is necessary: + from typing_extensions import TypeAlias + + +Vertex: TypeAlias = Tuple[float, float] + + +def _get_bounding_rectangle(vertices: List[Vertex]) -> RectangleObject: + x_min, y_min = vertices[0][0], vertices[0][1] + x_max, y_max = vertices[0][0], vertices[0][1] + for x, y in vertices: + x_min = min(x_min, x) + y_min = min(y_min, y) + x_max = max(x_max, x) + y_max = max(y_max, y) + rect = RectangleObject((x_min, y_min, x_max, y_max)) + return rect + + +class MarkupAnnotation(AnnotationDictionary, ABC): + """ + Base class for all markup annotations. + + Args: + title_bar: Text to be displayed in the title bar of the annotation; + by convention this is the name of the author + + """ + + def __init__(self, *, title_bar: Optional[str] = None) -> None: + if title_bar is not None: + self[NameObject("/T")] = TextStringObject(title_bar) + + +class Text(MarkupAnnotation): + """ + A text annotation. + + Args: + rect: array of four integers ``[xLL, yLL, xUR, yUR]`` + specifying the clickable rectangular area + text: The text that is added to the document + open: + flags: + + """ + + def __init__( + self, + *, + rect: Union[RectangleObject, Tuple[float, float, float, float]], + text: str, + open: bool = False, + flags: int = NO_FLAGS, + **kwargs: Any, + ) -> None: + super().__init__(**kwargs) + self[NameObject("/Subtype")] = NameObject("/Text") + self[NameObject("/Rect")] = RectangleObject(rect) + self[NameObject("/Contents")] = TextStringObject(text) + self[NameObject("/Open")] = BooleanObject(open) + self[NameObject("/Flags")] = NumberObject(flags) + + +class FreeText(MarkupAnnotation): + """A FreeText annotation""" + + def __init__( + self, + *, + text: str, + rect: Union[RectangleObject, Tuple[float, float, float, float]], + font: str = "Helvetica", + bold: bool = False, + italic: bool = False, + font_size: str = "14pt", + font_color: str = "000000", + border_color: Optional[str] = "000000", + background_color: Optional[str] = "ffffff", + **kwargs: Any, + ) -> None: + super().__init__(**kwargs) + self[NameObject("/Subtype")] = NameObject("/FreeText") + self[NameObject("/Rect")] = RectangleObject(rect) + + # Table 225 of the 1.7 reference ("CSS2 style attributes used in rich text strings") + font_str = "font: " + if italic: + font_str = f"{font_str}italic " + else: + font_str = f"{font_str}normal " + if bold: + font_str = f"{font_str}bold " + else: + font_str = f"{font_str}normal " + font_str = f"{font_str}{font_size} {font}" + font_str = f"{font_str};text-align:left;color:#{font_color}" + + default_appearance_string = "" + if border_color: + for st in hex_to_rgb(border_color): + default_appearance_string = f"{default_appearance_string}{st} " + default_appearance_string = f"{default_appearance_string}rg" + + self.update( + { + NameObject("/Subtype"): NameObject("/FreeText"), + NameObject("/Rect"): RectangleObject(rect), + NameObject("/Contents"): TextStringObject(text), + # font size color + NameObject("/DS"): TextStringObject(font_str), + NameObject("/DA"): TextStringObject(default_appearance_string), + } + ) + if border_color is None: + # Border Style + self[NameObject("/BS")] = DictionaryObject( + { + # width of 0 means no border + NameObject("/W"): NumberObject(0) + } + ) + if background_color is not None: + self[NameObject("/C")] = ArrayObject( + [FloatObject(n) for n in hex_to_rgb(background_color)] + ) + + +class Line(MarkupAnnotation): + def __init__( + self, + p1: Vertex, + p2: Vertex, + rect: Union[RectangleObject, Tuple[float, float, float, float]], + text: str = "", + **kwargs: Any, + ) -> None: + super().__init__(**kwargs) + self.update( + { + NameObject("/Subtype"): NameObject("/Line"), + NameObject("/Rect"): RectangleObject(rect), + NameObject("/L"): ArrayObject( + [ + FloatObject(p1[0]), + FloatObject(p1[1]), + FloatObject(p2[0]), + FloatObject(p2[1]), + ] + ), + NameObject("/LE"): ArrayObject( + [ + NameObject("/None"), + NameObject("/None"), + ] + ), + NameObject("/IC"): ArrayObject( + [ + FloatObject(0.5), + FloatObject(0.5), + FloatObject(0.5), + ] + ), + NameObject("/Contents"): TextStringObject(text), + } + ) + + +class PolyLine(MarkupAnnotation): + def __init__( + self, + vertices: List[Vertex], + **kwargs: Any, + ) -> None: + super().__init__(**kwargs) + if len(vertices) == 0: + raise ValueError("A polygon needs at least 1 vertex with two coordinates") + coord_list = [] + for x, y in vertices: + coord_list.append(NumberObject(x)) + coord_list.append(NumberObject(y)) + self.update( + { + NameObject("/Subtype"): NameObject("/PolyLine"), + NameObject("/Vertices"): ArrayObject(coord_list), + NameObject("/Rect"): RectangleObject(_get_bounding_rectangle(vertices)), + } + ) + + +class Rectangle(MarkupAnnotation): + def __init__( + self, + rect: Union[RectangleObject, Tuple[float, float, float, float]], + *, + interior_color: Optional[str] = None, + **kwargs: Any, + ) -> None: + if "interiour_color" in kwargs: + deprecation_with_replacement("interiour_color", "interior_color", "5.0.0") + interior_color = kwargs["interiour_color"] + del kwargs["interiour_color"] + super().__init__(**kwargs) + self.update( + { + NameObject("/Type"): NameObject("/Annot"), + NameObject("/Subtype"): NameObject("/Square"), + NameObject("/Rect"): RectangleObject(rect), + } + ) + + if interior_color: + self[NameObject("/IC")] = ArrayObject( + [FloatObject(n) for n in hex_to_rgb(interior_color)] + ) + + +class Highlight(MarkupAnnotation): + def __init__( + self, + *, + rect: Union[RectangleObject, Tuple[float, float, float, float]], + quad_points: ArrayObject, + highlight_color: str = "ff0000", + printing: bool = False, + **kwargs: Any, + ) -> None: + super().__init__(**kwargs) + self.update( + { + NameObject("/Subtype"): NameObject("/Highlight"), + NameObject("/Rect"): RectangleObject(rect), + NameObject("/QuadPoints"): quad_points, + NameObject("/C"): ArrayObject( + [FloatObject(n) for n in hex_to_rgb(highlight_color)] + ), + } + ) + if printing: + self.flags = AnnotationFlag.PRINT + + +class Ellipse(MarkupAnnotation): + def __init__( + self, + rect: Union[RectangleObject, Tuple[float, float, float, float]], + *, + interior_color: Optional[str] = None, + **kwargs: Any, + ) -> None: + if "interiour_color" in kwargs: + deprecation_with_replacement("interiour_color", "interior_color", "5.0.0") + interior_color = kwargs["interiour_color"] + del kwargs["interiour_color"] + super().__init__(**kwargs) + + self.update( + { + NameObject("/Type"): NameObject("/Annot"), + NameObject("/Subtype"): NameObject("/Circle"), + NameObject("/Rect"): RectangleObject(rect), + } + ) + + if interior_color: + self[NameObject("/IC")] = ArrayObject( + [FloatObject(n) for n in hex_to_rgb(interior_color)] + ) + + +class Polygon(MarkupAnnotation): + def __init__( + self, + vertices: List[Tuple[float, float]], + **kwargs: Any, + ) -> None: + super().__init__(**kwargs) + if len(vertices) == 0: + raise ValueError("A polygon needs at least 1 vertex with two coordinates") + + coord_list = [] + for x, y in vertices: + coord_list.append(NumberObject(x)) + coord_list.append(NumberObject(y)) + self.update( + { + NameObject("/Type"): NameObject("/Annot"), + NameObject("/Subtype"): NameObject("/Polygon"), + NameObject("/Vertices"): ArrayObject(coord_list), + NameObject("/IT"): NameObject("/PolygonCloud"), + NameObject("/Rect"): RectangleObject(_get_bounding_rectangle(vertices)), + } + ) diff --git a/venv/lib/python3.12/site-packages/pypdf/annotations/_non_markup_annotations.py b/venv/lib/python3.12/site-packages/pypdf/annotations/_non_markup_annotations.py new file mode 100644 index 0000000..921be3d --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/annotations/_non_markup_annotations.py @@ -0,0 +1,106 @@ +from typing import TYPE_CHECKING, Any, Optional, Tuple, Union + +from ..generic._base import ( + BooleanObject, + NameObject, + NumberObject, + TextStringObject, +) +from ..generic._data_structures import ArrayObject, DictionaryObject +from ..generic._fit import DEFAULT_FIT, Fit +from ..generic._rectangle import RectangleObject +from ._base import AnnotationDictionary + + +class Link(AnnotationDictionary): + def __init__( + self, + *, + rect: Union[RectangleObject, Tuple[float, float, float, float]], + border: Optional[ArrayObject] = None, + url: Optional[str] = None, + target_page_index: Optional[int] = None, + fit: Fit = DEFAULT_FIT, + **kwargs: Any, + ) -> None: + super().__init__(**kwargs) + if TYPE_CHECKING: + from ..types import BorderArrayType + + is_external = url is not None + is_internal = target_page_index is not None + if not is_external and not is_internal: + raise ValueError( + "Either 'url' or 'target_page_index' have to be provided. Both were None." + ) + if is_external and is_internal: + raise ValueError( + "Either 'url' or 'target_page_index' have to be provided. " + f"{url=}, {target_page_index=}" + ) + + border_arr: BorderArrayType + if border is not None: + border_arr = [NumberObject(n) for n in border[:3]] + if len(border) == 4: + dash_pattern = ArrayObject([NumberObject(n) for n in border[3]]) + border_arr.append(dash_pattern) + else: + border_arr = [NumberObject(0)] * 3 + + self.update( + { + NameObject("/Type"): NameObject("/Annot"), + NameObject("/Subtype"): NameObject("/Link"), + NameObject("/Rect"): RectangleObject(rect), + NameObject("/Border"): ArrayObject(border_arr), + } + ) + if is_external: + self[NameObject("/A")] = DictionaryObject( + { + NameObject("/S"): NameObject("/URI"), + NameObject("/Type"): NameObject("/Action"), + NameObject("/URI"): TextStringObject(url), + } + ) + if is_internal: + # This needs to be updated later! + dest_deferred = DictionaryObject( + { + "target_page_index": NumberObject(target_page_index), + "fit": NameObject(fit.fit_type), + "fit_args": fit.fit_args, + } + ) + self[NameObject("/Dest")] = dest_deferred + + +class Popup(AnnotationDictionary): + def __init__( + self, + *, + rect: Union[RectangleObject, Tuple[float, float, float, float]], + parent: Optional[DictionaryObject] = None, + open: bool = False, + **kwargs: Any, + ) -> None: + super().__init__(**kwargs) + self.update( + { + NameObject("/Subtype"): NameObject("/Popup"), + NameObject("/Rect"): RectangleObject(rect), + NameObject("/Open"): BooleanObject(open), + } + ) + if parent: + # This needs to be an indirect object + try: + self[NameObject("/Parent")] = parent.indirect_reference + except AttributeError: + from .._utils import logger_warning + + logger_warning( + "Unregistered Parent object : No Parent field set", + __name__, + ) diff --git a/venv/lib/python3.12/site-packages/pypdf/constants.py b/venv/lib/python3.12/site-packages/pypdf/constants.py new file mode 100644 index 0000000..7bf5aae --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/constants.py @@ -0,0 +1,722 @@ +"""Various constants, enums, and flags to aid readability.""" + +from enum import Enum, IntFlag, auto, unique +from typing import Dict, Tuple + + +class StrEnum(str, Enum): # Once we are on Python 3.11+: enum.StrEnum + def __str__(self) -> str: + return str(self.value) + + +class Core: + """Keywords that don't quite belong anywhere else.""" + + OUTLINES = "/Outlines" + THREADS = "/Threads" + PAGE = "/Page" + PAGES = "/Pages" + CATALOG = "/Catalog" + + +class TrailerKeys: + ROOT = "/Root" + ENCRYPT = "/Encrypt" + ID = "/ID" + INFO = "/Info" + SIZE = "/Size" + PREV = "/Prev" + + +class CatalogAttributes: + NAMES = "/Names" + DESTS = "/Dests" + + +class EncryptionDictAttributes: + """ + Additional encryption dictionary entries for the standard security handler. + + Table 3.19, Page 122. + Table 21 of the 2.0 manual. + """ + + R = "/R" # number, required; revision of the standard security handler + O = "/O" # 32-byte string, required # noqa: E741 + U = "/U" # 32-byte string, required + P = "/P" # integer flag, required; permitted operations + ENCRYPT_METADATA = "/EncryptMetadata" # boolean flag, optional + + +class UserAccessPermissions(IntFlag): + """ + Table 3.20 User access permissions. + Table 22 of the 2.0 manual. + """ + + R1 = 1 + R2 = 2 + PRINT = 4 + MODIFY = 8 + EXTRACT = 16 + ADD_OR_MODIFY = 32 + R7 = 64 + R8 = 128 + FILL_FORM_FIELDS = 256 + EXTRACT_TEXT_AND_GRAPHICS = 512 + ASSEMBLE_DOC = 1024 + PRINT_TO_REPRESENTATION = 2048 + R13 = 2**12 + R14 = 2**13 + R15 = 2**14 + R16 = 2**15 + R17 = 2**16 + R18 = 2**17 + R19 = 2**18 + R20 = 2**19 + R21 = 2**20 + R22 = 2**21 + R23 = 2**22 + R24 = 2**23 + R25 = 2**24 + R26 = 2**25 + R27 = 2**26 + R28 = 2**27 + R29 = 2**28 + R30 = 2**29 + R31 = 2**30 + R32 = 2**31 + + @classmethod + def _is_reserved(cls, name: str) -> bool: + """Check if the given name corresponds to a reserved flag entry.""" + return name.startswith("R") and name[1:].isdigit() + + @classmethod + def _is_active(cls, name: str) -> bool: + """Check if the given reserved name defaults to 1 = active.""" + return name not in {"R1", "R2"} + + def to_dict(self) -> Dict[str, bool]: + """Convert the given flag value to a corresponding verbose name mapping.""" + result: Dict[str, bool] = {} + for name, flag in UserAccessPermissions.__members__.items(): + if UserAccessPermissions._is_reserved(name): + continue + result[name.lower()] = (self & flag) == flag + return result + + @classmethod + def from_dict(cls, value: Dict[str, bool]) -> "UserAccessPermissions": + """Convert the verbose name mapping to the corresponding flag value.""" + value_copy = value.copy() + result = cls(0) + for name, flag in cls.__members__.items(): + if cls._is_reserved(name): + # Reserved names have a required value. Use it. + if cls._is_active(name): + result |= flag + continue + is_active = value_copy.pop(name.lower(), False) + if is_active: + result |= flag + if value_copy: + raise ValueError(f"Unknown dictionary keys: {value_copy!r}") + return result + + @classmethod + def all(cls) -> "UserAccessPermissions": + return cls((2**32 - 1) - cls.R1 - cls.R2) + + +class Resources: + """ + Table 3.30 Entries in a resource dictionary. + Table 34 in the 2.0 reference. + """ + + EXT_G_STATE = "/ExtGState" # dictionary, optional + COLOR_SPACE = "/ColorSpace" # dictionary, optional + PATTERN = "/Pattern" # dictionary, optional + SHADING = "/Shading" # dictionary, optional + XOBJECT = "/XObject" # dictionary, optional + FONT = "/Font" # dictionary, optional + PROC_SET = "/ProcSet" # array, optional + PROPERTIES = "/Properties" # dictionary, optional + + +class Ressources: # deprecated + """ + Use :class: `Resources` instead. + + .. deprecated:: 5.0.0 + """ + + +class PagesAttributes: + """§7.7.3.2 of the 1.7 and 2.0 reference.""" + + TYPE = "/Type" # name, required; must be /Pages + PARENT = "/Parent" # dictionary, required; indirect reference to pages object + KIDS = "/Kids" # array, required; List of indirect references + COUNT = "/Count" + # integer, required; the number of leaf nodes (page objects) + # that are descendants of this node within the page tree + + +class PageAttributes: + """§7.7.3.3 of the 1.7 and 2.0 reference.""" + + TYPE = "/Type" # name, required; must be /Page + PARENT = "/Parent" # dictionary, required; a pages object + LAST_MODIFIED = ( + "/LastModified" # date, optional; date and time of last modification + ) + RESOURCES = "/Resources" # dictionary, required if there are any + MEDIABOX = "/MediaBox" # rectangle, required; rectangle specifying page size + CROPBOX = "/CropBox" # rectangle, optional + BLEEDBOX = "/BleedBox" # rectangle, optional + TRIMBOX = "/TrimBox" # rectangle, optional + ARTBOX = "/ArtBox" # rectangle, optional + BOX_COLOR_INFO = "/BoxColorInfo" # dictionary, optional + CONTENTS = "/Contents" # stream or array, optional + ROTATE = "/Rotate" # integer, optional; page rotation in degrees + GROUP = "/Group" # dictionary, optional; page group + THUMB = "/Thumb" # stream, optional; indirect reference to image of the page + B = "/B" # array, optional + DUR = "/Dur" # number, optional + TRANS = "/Trans" # dictionary, optional + ANNOTS = "/Annots" # array, optional; an array of annotations + AA = "/AA" # dictionary, optional + METADATA = "/Metadata" # stream, optional + PIECE_INFO = "/PieceInfo" # dictionary, optional + STRUCT_PARENTS = "/StructParents" # integer, optional + ID = "/ID" # byte string, optional + PZ = "/PZ" # number, optional + SEPARATION_INFO = "/SeparationInfo" # dictionary, optional + TABS = "/Tabs" # name, optional + TEMPLATE_INSTANTIATED = "/TemplateInstantiated" # name, optional + PRES_STEPS = "/PresSteps" # dictionary, optional + USER_UNIT = "/UserUnit" # number, optional + VP = "/VP" # dictionary, optional + AF = "/AF" # array of dictionaries, optional + OUTPUT_INTENTS = "/OutputIntents" # array, optional + D_PART = "/DPart" # dictionary, required, if this page is within the range of a DPart, not permitted otherwise + + +class FileSpecificationDictionaryEntries: + """Table 3.41 Entries in a file specification dictionary.""" + + Type = "/Type" + FS = "/FS" # The name of the file system to be used to interpret this file specification + F = "/F" # A file specification string of the form described in §3.10.1 + UF = "/UF" # A Unicode string of the file as described in §3.10.1 + DOS = "/DOS" + Mac = "/Mac" + Unix = "/Unix" + ID = "/ID" + V = "/V" + EF = "/EF" # dictionary, containing a subset of the keys F, UF, DOS, Mac, and Unix + RF = "/RF" # dictionary, containing arrays of /EmbeddedFile + DESC = "/Desc" # description of the file + Cl = "/Cl" + + +class StreamAttributes: + """ + Table 4.2. + Table 5 in the 2.0 reference. + """ + + LENGTH = "/Length" # integer, required + FILTER = "/Filter" # name or array of names, optional + DECODE_PARMS = "/DecodeParms" # variable, optional -- 'decodeParams is wrong + + +@unique +class FilterTypes(StrEnum): + """§7.4 of the 1.7 and 2.0 references.""" + + ASCII_HEX_DECODE = "/ASCIIHexDecode" # abbreviation: AHx + ASCII_85_DECODE = "/ASCII85Decode" # abbreviation: A85 + LZW_DECODE = "/LZWDecode" # abbreviation: LZW + FLATE_DECODE = "/FlateDecode" # abbreviation: Fl, PDF 1.2 + RUN_LENGTH_DECODE = "/RunLengthDecode" # abbreviation: RL + CCITT_FAX_DECODE = "/CCITTFaxDecode" # abbreviation: CCF + DCT_DECODE = "/DCTDecode" # abbreviation: DCT + JPX_DECODE = "/JPXDecode" + + +class FilterTypeAbbreviations: + """§8.9.7 of the 1.7 and 2.0 references.""" + + AHx = "/AHx" + A85 = "/A85" + LZW = "/LZW" + FL = "/Fl" # FlateDecode + RL = "/RL" + CCF = "/CCF" + DCT = "/DCT" + + +class LzwFilterParameters: + """ + Table 4.4. + Table 8 in the 2.0 reference. + """ + + PREDICTOR = "/Predictor" # integer + COLORS = "/Colors" # integer + BITS_PER_COMPONENT = "/BitsPerComponent" # integer + COLUMNS = "/Columns" # integer + EARLY_CHANGE = "/EarlyChange" # integer + + +class CcittFaxDecodeParameters: + """ + Table 4.5. + Table 11 in the 2.0 reference. + """ + + K = "/K" # integer + END_OF_LINE = "/EndOfLine" # boolean + ENCODED_BYTE_ALIGN = "/EncodedByteAlign" # boolean + COLUMNS = "/Columns" # integer + ROWS = "/Rows" # integer + END_OF_BLOCK = "/EndOfBlock" # boolean + BLACK_IS_1 = "/BlackIs1" # boolean + DAMAGED_ROWS_BEFORE_ERROR = "/DamagedRowsBeforeError" # integer + + +class ImageAttributes: + """§11.6.5 of the 1.7 and 2.0 references.""" + + TYPE = "/Type" # name, required; must be /XObject + SUBTYPE = "/Subtype" # name, required; must be /Image + NAME = "/Name" # name, required + WIDTH = "/Width" # integer, required + HEIGHT = "/Height" # integer, required + BITS_PER_COMPONENT = "/BitsPerComponent" # integer, required + COLOR_SPACE = "/ColorSpace" # name, required + DECODE = "/Decode" # array, optional + INTENT = "/Intent" # string, optional + INTERPOLATE = "/Interpolate" # boolean, optional + IMAGE_MASK = "/ImageMask" # boolean, optional + MASK = "/Mask" # 1-bit image mask stream + S_MASK = "/SMask" # dictionary or name, optional + + +class ColorSpaces: + DEVICE_RGB = "/DeviceRGB" + DEVICE_CMYK = "/DeviceCMYK" + DEVICE_GRAY = "/DeviceGray" + + +class TypArguments: + """Table 8.2 of the PDF 1.7 reference.""" + + LEFT = "/Left" + RIGHT = "/Right" + BOTTOM = "/Bottom" + TOP = "/Top" + + +class TypFitArguments: + """Table 8.2 of the PDF 1.7 reference.""" + + FIT = "/Fit" + FIT_V = "/FitV" + FIT_BV = "/FitBV" + FIT_B = "/FitB" + FIT_H = "/FitH" + FIT_BH = "/FitBH" + FIT_R = "/FitR" + XYZ = "/XYZ" + + +class GoToActionArguments: + S = "/S" # name, required: type of action + D = "/D" # name / byte string /array, required: Destination to jump to + + +class AnnotationDictionaryAttributes: + """Table 8.15 Entries common to all annotation dictionaries.""" + + Type = "/Type" + Subtype = "/Subtype" + Rect = "/Rect" + Contents = "/Contents" + P = "/P" + NM = "/NM" + M = "/M" + F = "/F" + AP = "/AP" + AS = "/AS" + DA = "/DA" + Border = "/Border" + C = "/C" + StructParent = "/StructParent" + OC = "/OC" + + +class InteractiveFormDictEntries: + Fields = "/Fields" + NeedAppearances = "/NeedAppearances" + SigFlags = "/SigFlags" + CO = "/CO" + DR = "/DR" + DA = "/DA" + Q = "/Q" + XFA = "/XFA" + + +class FieldDictionaryAttributes: + """ + Entries common to all field dictionaries (Table 8.69 PDF 1.7 reference) + (*very partially documented here*). + + FFBits provides the constants used for `/Ff` from Table 8.70/8.75/8.77/8.79 + """ + + FT = "/FT" # name, required for terminal fields + Parent = "/Parent" # dictionary, required for children + Kids = "/Kids" # array, sometimes required + T = "/T" # text string, optional + TU = "/TU" # text string, optional + TM = "/TM" # text string, optional + Ff = "/Ff" # integer, optional + V = "/V" # text string or array, optional + DV = "/DV" # text string, optional + AA = "/AA" # dictionary, optional + Opt = "/Opt" # array, optional + + class FfBits(IntFlag): + """ + Ease building /Ff flags + Some entries may be specific to: + + * Text (Tx) (Table 8.75 PDF 1.7 reference) + * Buttons (Btn) (Table 8.77 PDF 1.7 reference) + * Choice (Ch) (Table 8.79 PDF 1.7 reference) + """ + + ReadOnly = 1 << 0 + """common to Tx/Btn/Ch in Table 8.70""" + Required = 1 << 1 + """common to Tx/Btn/Ch in Table 8.70""" + NoExport = 1 << 2 + """common to Tx/Btn/Ch in Table 8.70""" + + Multiline = 1 << 12 + """Tx""" + Password = 1 << 13 + """Tx""" + + NoToggleToOff = 1 << 14 + """Btn""" + Radio = 1 << 15 + """Btn""" + Pushbutton = 1 << 16 + """Btn""" + + Combo = 1 << 17 + """Ch""" + Edit = 1 << 18 + """Ch""" + Sort = 1 << 19 + """Ch""" + + FileSelect = 1 << 20 + """Tx""" + + MultiSelect = 1 << 21 + """Tx""" + + DoNotSpellCheck = 1 << 22 + """Tx/Ch""" + DoNotScroll = 1 << 23 + """Tx""" + Comb = 1 << 24 + """Tx""" + + RadiosInUnison = 1 << 25 + """Btn""" + + RichText = 1 << 25 + """Tx""" + + CommitOnSelChange = 1 << 26 + """Ch""" + + @classmethod + def attributes(cls) -> Tuple[str, ...]: + """ + Get a tuple of all the attributes present in a Field Dictionary. + + This method returns a tuple of all the attribute constants defined in + the FieldDictionaryAttributes class. These attributes correspond to the + entries that are common to all field dictionaries as specified in the + PDF 1.7 reference. + + Returns: + A tuple containing all the attribute constants. + + """ + return ( + cls.TM, + cls.T, + cls.FT, + cls.Parent, + cls.TU, + cls.Ff, + cls.V, + cls.DV, + cls.Kids, + cls.AA, + ) + + @classmethod + def attributes_dict(cls) -> Dict[str, str]: + """ + Get a dictionary of attribute keys and their human-readable names. + + This method returns a dictionary where the keys are the attribute + constants defined in the FieldDictionaryAttributes class and the values + are their corresponding human-readable names. These attributes + correspond to the entries that are common to all field dictionaries as + specified in the PDF 1.7 reference. + + Returns: + A dictionary containing attribute keys and their names. + + """ + return { + cls.FT: "Field Type", + cls.Parent: "Parent", + cls.T: "Field Name", + cls.TU: "Alternate Field Name", + cls.TM: "Mapping Name", + cls.Ff: "Field Flags", + cls.V: "Value", + cls.DV: "Default Value", + } + + +class CheckboxRadioButtonAttributes: + """Table 8.76 Field flags common to all field types.""" + + Opt = "/Opt" # Options, Optional + + @classmethod + def attributes(cls) -> Tuple[str, ...]: + """ + Get a tuple of all the attributes present in a Field Dictionary. + + This method returns a tuple of all the attribute constants defined in + the CheckboxRadioButtonAttributes class. These attributes correspond to + the entries that are common to all field dictionaries as specified in + the PDF 1.7 reference. + + Returns: + A tuple containing all the attribute constants. + + """ + return (cls.Opt,) + + @classmethod + def attributes_dict(cls) -> Dict[str, str]: + """ + Get a dictionary of attribute keys and their human-readable names. + + This method returns a dictionary where the keys are the attribute + constants defined in the CheckboxRadioButtonAttributes class and the + values are their corresponding human-readable names. These attributes + correspond to the entries that are common to all field dictionaries as + specified in the PDF 1.7 reference. + + Returns: + A dictionary containing attribute keys and their names. + + """ + return { + cls.Opt: "Options", + } + + +class FieldFlag(IntFlag): + """Table 8.70 Field flags common to all field types.""" + + READ_ONLY = 1 + REQUIRED = 2 + NO_EXPORT = 4 + + +class DocumentInformationAttributes: + """Table 10.2 Entries in the document information dictionary.""" + + TITLE = "/Title" # text string, optional + AUTHOR = "/Author" # text string, optional + SUBJECT = "/Subject" # text string, optional + KEYWORDS = "/Keywords" # text string, optional + CREATOR = "/Creator" # text string, optional + PRODUCER = "/Producer" # text string, optional + CREATION_DATE = "/CreationDate" # date, optional + MOD_DATE = "/ModDate" # date, optional + TRAPPED = "/Trapped" # name, optional + + +class PageLayouts: + """ + Page 84, PDF 1.4 reference. + Page 115, PDF 2.0 reference. + """ + + SINGLE_PAGE = "/SinglePage" + ONE_COLUMN = "/OneColumn" + TWO_COLUMN_LEFT = "/TwoColumnLeft" + TWO_COLUMN_RIGHT = "/TwoColumnRight" + TWO_PAGE_LEFT = "/TwoPageLeft" # (PDF 1.5) + TWO_PAGE_RIGHT = "/TwoPageRight" # (PDF 1.5) + + +class GraphicsStateParameters: + """Table 58 – Entries in a Graphics State Parameter Dictionary""" + + TYPE = "/Type" # name, optional + LW = "/LW" # number, optional + LC = "/LC" # integer, optional + LJ = "/LJ" # integer, optional + ML = "/ML" # number, optional + D = "/D" # array, optional + RI = "/RI" # name, optional + OP = "/OP" + op = "/op" + OPM = "/OPM" + FONT = "/Font" # array, optional + BG = "/BG" + BG2 = "/BG2" + UCR = "/UCR" + UCR2 = "/UCR2" + TR = "/TR" + TR2 = "/TR2" + HT = "/HT" + FL = "/FL" + SM = "/SM" + SA = "/SA" + BM = "/BM" + S_MASK = "/SMask" # dictionary or name, optional + CA = "/CA" + ca = "/ca" + AIS = "/AIS" + TK = "/TK" + + +class CatalogDictionary: + """§7.7.2 of the 1.7 and 2.0 references.""" + + TYPE = "/Type" # name, required; must be /Catalog + VERSION = "/Version" # name + EXTENSIONS = "/Extensions" # dictionary, optional; ISO 32000-1 + PAGES = "/Pages" # dictionary, required + PAGE_LABELS = "/PageLabels" # number tree, optional + NAMES = "/Names" # dictionary, optional + DESTS = "/Dests" # dictionary, optional + VIEWER_PREFERENCES = "/ViewerPreferences" # dictionary, optional + PAGE_LAYOUT = "/PageLayout" # name, optional + PAGE_MODE = "/PageMode" # name, optional + OUTLINES = "/Outlines" # dictionary, optional + THREADS = "/Threads" # array, optional + OPEN_ACTION = "/OpenAction" # array or dictionary or name, optional + AA = "/AA" # dictionary, optional + URI = "/URI" # dictionary, optional + ACRO_FORM = "/AcroForm" # dictionary, optional + METADATA = "/Metadata" # stream, optional + STRUCT_TREE_ROOT = "/StructTreeRoot" # dictionary, optional + MARK_INFO = "/MarkInfo" # dictionary, optional + LANG = "/Lang" # text string, optional + SPIDER_INFO = "/SpiderInfo" # dictionary, optional + OUTPUT_INTENTS = "/OutputIntents" # array, optional + PIECE_INFO = "/PieceInfo" # dictionary, optional + OC_PROPERTIES = "/OCProperties" # dictionary, optional + PERMS = "/Perms" # dictionary, optional + LEGAL = "/Legal" # dictionary, optional + REQUIREMENTS = "/Requirements" # array, optional + COLLECTION = "/Collection" # dictionary, optional + NEEDS_RENDERING = "/NeedsRendering" # boolean, optional + DSS = "/DSS" # dictionary, optional + AF = "/AF" # array of dictionaries, optional + D_PART_ROOT = "/DPartRoot" # dictionary, optional + + +class OutlineFontFlag(IntFlag): + """A class used as an enumerable flag for formatting an outline font.""" + + italic = 1 + bold = 2 + + +class PageLabelStyle: + """ + Table 8.10 in the 1.7 reference. + Table 161 in the 2.0 reference. + """ + + DECIMAL = "/D" # Decimal Arabic numerals + UPPERCASE_ROMAN = "/R" # Uppercase Roman numerals + LOWERCASE_ROMAN = "/r" # Lowercase Roman numerals + UPPERCASE_LETTER = "/A" # Uppercase letters + LOWERCASE_LETTER = "/a" # Lowercase letters + + +class AnnotationFlag(IntFlag): + """See §12.5.3 "Annotation Flags".""" + + INVISIBLE = 1 + HIDDEN = 2 + PRINT = 4 + NO_ZOOM = 8 + NO_ROTATE = 16 + NO_VIEW = 32 + READ_ONLY = 64 + LOCKED = 128 + TOGGLE_NO_VIEW = 256 + LOCKED_CONTENTS = 512 + + +PDF_KEYS = ( + AnnotationDictionaryAttributes, + CatalogAttributes, + CatalogDictionary, + CcittFaxDecodeParameters, + CheckboxRadioButtonAttributes, + ColorSpaces, + Core, + DocumentInformationAttributes, + EncryptionDictAttributes, + FieldDictionaryAttributes, + FileSpecificationDictionaryEntries, + FilterTypeAbbreviations, + FilterTypes, + GoToActionArguments, + GraphicsStateParameters, + ImageAttributes, + InteractiveFormDictEntries, + LzwFilterParameters, + PageAttributes, + PageLayouts, + PagesAttributes, + Resources, + StreamAttributes, + TrailerKeys, + TypArguments, + TypFitArguments, +) + + +class ImageType(IntFlag): + NONE = 0 + XOBJECT_IMAGES = auto() + INLINE_IMAGES = auto() + DRAWING_IMAGES = auto() + ALL = XOBJECT_IMAGES | INLINE_IMAGES | DRAWING_IMAGES + IMAGES = ALL # for consistency with ObjectDeletionFlag diff --git a/venv/lib/python3.12/site-packages/pypdf/errors.py b/venv/lib/python3.12/site-packages/pypdf/errors.py new file mode 100644 index 0000000..1e73041 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/errors.py @@ -0,0 +1,66 @@ +""" +All errors/exceptions pypdf raises and all of the warnings it uses. + +Please note that broken PDF files might cause other Exceptions. +""" + + +class DeprecationError(Exception): + """Raised when a deprecated feature is used.""" + + +class DependencyError(Exception): + """ + Raised when a required dependency (a library or module that pypdf depends on) + is not available or cannot be imported. + """ + + +class PyPdfError(Exception): + """Base class for all exceptions raised by pypdf.""" + + +class PdfReadError(PyPdfError): + """Raised when there is an issue reading a PDF file.""" + + +class PageSizeNotDefinedError(PyPdfError): + """Raised when the page size of a PDF document is not defined.""" + + +class PdfReadWarning(UserWarning): + """Issued when there is a potential issue reading a PDF file, but it can still be read.""" + + +class PdfStreamError(PdfReadError): + """Raised when there is an issue reading the stream of data in a PDF file.""" + + +class ParseError(PyPdfError): + """ + Raised when there is an issue parsing (analyzing and understanding the + structure and meaning of) a PDF file. + """ + + +class FileNotDecryptedError(PdfReadError): + """ + Raised when a PDF file that has been encrypted + (meaning it requires a password to be accessed) has not been successfully + decrypted. + """ + + +class WrongPasswordError(FileNotDecryptedError): + """Raised when the wrong password is used to try to decrypt an encrypted PDF file.""" + + +class EmptyFileError(PdfReadError): + """Raised when a PDF file is empty or has no content.""" + + +class EmptyImageDataError(PyPdfError): + """Raised when trying to process an image that has no data.""" + + +STREAM_TRUNCATED_PREMATURELY = "Stream has ended unexpectedly" diff --git a/venv/lib/python3.12/site-packages/pypdf/filters.py b/venv/lib/python3.12/site-packages/pypdf/filters.py new file mode 100644 index 0000000..6db2b96 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/filters.py @@ -0,0 +1,836 @@ +# Copyright (c) 2006, Mathieu Fenniak +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + + +""" +Implementation of stream filters for PDF. + +See TABLE H.1 Abbreviations for standard filter names +""" +__author__ = "Mathieu Fenniak" +__author_email__ = "biziqe@mathieu.fenniak.net" + +import math +import struct +import zlib +from base64 import a85decode +from dataclasses import dataclass +from io import BytesIO +from typing import Any, Dict, List, Optional, Tuple, Union, cast + +from ._codecs._codecs import LzwCodec as _LzwCodec +from ._utils import ( + WHITESPACES_AS_BYTES, + deprecate, + deprecate_with_replacement, + deprecation_no_replacement, + logger_warning, +) +from .constants import CcittFaxDecodeParameters as CCITT +from .constants import FilterTypeAbbreviations as FTA +from .constants import FilterTypes as FT +from .constants import ImageAttributes as IA +from .constants import LzwFilterParameters as LZW +from .constants import StreamAttributes as SA +from .errors import DeprecationError, PdfReadError, PdfStreamError +from .generic import ( + ArrayObject, + DictionaryObject, + IndirectObject, + NullObject, +) + + +def decompress(data: bytes) -> bytes: + """ + Decompress the given data using zlib. + + Attempts to decompress the input data using zlib. + If the decompression fails due to a zlib error, it falls back + to using a decompression object with a larger window size. + + Args: + data: The input data to be decompressed. + + Returns: + The decompressed data. + + """ + try: + return zlib.decompress(data) + except zlib.error: + try: + # For larger files, use decompression object to enable buffered reading + return zlib.decompressobj().decompress(data) + except zlib.error: + # If still failing, then try with increased window size + d = zlib.decompressobj(zlib.MAX_WBITS | 32) + result_str = b"" + for b in [data[i : i + 1] for i in range(len(data))]: + try: + result_str += d.decompress(b) + except zlib.error: + pass + return result_str + + +class FlateDecode: + @staticmethod + def decode( + data: bytes, + decode_parms: Optional[DictionaryObject] = None, + **kwargs: Any, + ) -> bytes: + """ + Decode data which is flate-encoded. + + Args: + data: flate-encoded data. + decode_parms: a dictionary of values, understanding the + "/Predictor": key only + + Returns: + The flate-decoded data. + + Raises: + PdfReadError: + + """ + if isinstance(decode_parms, ArrayObject): + raise DeprecationError("decode_parms as ArrayObject is deprecated") + + str_data = decompress(data) + predictor = 1 + + if decode_parms: + try: + predictor = decode_parms.get("/Predictor", 1) + except (AttributeError, TypeError): # Type Error is NullObject + pass # Usually an array with a null object was read + # predictor 1 == no predictor + if predictor != 1: + # /Columns, the number of samples in each row, has a default value of 1; + # §7.4.4.3, ISO 32000. + DEFAULT_BITS_PER_COMPONENT = 8 + try: + columns = cast(int, decode_parms[LZW.COLUMNS].get_object()) # type: ignore + except (TypeError, KeyError): + columns = 1 + try: + colors = cast(int, decode_parms[LZW.COLORS].get_object()) # type: ignore + except (TypeError, KeyError): + colors = 1 + try: + bits_per_component = cast( + int, + decode_parms[LZW.BITS_PER_COMPONENT].get_object(), # type: ignore + ) + except (TypeError, KeyError): + bits_per_component = DEFAULT_BITS_PER_COMPONENT + + # PNG predictor can vary by row and so is the lead byte on each row + rowlength = ( + math.ceil(columns * colors * bits_per_component / 8) + 1 + ) # number of bytes + + # TIFF prediction: + if predictor == 2: + rowlength -= 1 # remove the predictor byte + bpp = rowlength // columns + str_data = bytearray(str_data) + for i in range(len(str_data)): + if i % rowlength >= bpp: + str_data[i] = (str_data[i] + str_data[i - bpp]) % 256 + str_data = bytes(str_data) + # PNG prediction: + elif 10 <= predictor <= 15: + str_data = FlateDecode._decode_png_prediction( + str_data, columns, rowlength + ) + else: + raise PdfReadError(f"Unsupported flatedecode predictor {predictor!r}") + return str_data + + @staticmethod + def _decode_png_prediction(data: bytes, columns: int, rowlength: int) -> bytes: + # PNG prediction can vary from row to row + if len(data) % rowlength != 0: + raise PdfReadError("Image data is not rectangular") + output = [] + prev_rowdata = (0,) * rowlength + bpp = (rowlength - 1) // columns # recomputed locally to not change params + for row in range(0, len(data), rowlength): + rowdata: List[int] = list(data[row : row + rowlength]) + filter_byte = rowdata[0] + + if filter_byte == 0: + # PNG None Predictor + pass + elif filter_byte == 1: + # PNG Sub Predictor + for i in range(bpp + 1, rowlength): + rowdata[i] = (rowdata[i] + rowdata[i - bpp]) % 256 + elif filter_byte == 2: + # PNG Up Predictor + for i in range(1, rowlength): + rowdata[i] = (rowdata[i] + prev_rowdata[i]) % 256 + elif filter_byte == 3: + # PNG Average Predictor + for i in range(1, bpp + 1): + floor = prev_rowdata[i] // 2 + rowdata[i] = (rowdata[i] + floor) % 256 + for i in range(bpp + 1, rowlength): + left = rowdata[i - bpp] + floor = (left + prev_rowdata[i]) // 2 + rowdata[i] = (rowdata[i] + floor) % 256 + elif filter_byte == 4: + # PNG Paeth Predictor + for i in range(1, bpp + 1): + rowdata[i] = (rowdata[i] + prev_rowdata[i]) % 256 + for i in range(bpp + 1, rowlength): + left = rowdata[i - bpp] + up = prev_rowdata[i] + up_left = prev_rowdata[i - bpp] + + p = left + up - up_left + dist_left = abs(p - left) + dist_up = abs(p - up) + dist_up_left = abs(p - up_left) + + if dist_left <= dist_up and dist_left <= dist_up_left: + paeth = left + elif dist_up <= dist_up_left: + paeth = up + else: + paeth = up_left + + rowdata[i] = (rowdata[i] + paeth) % 256 + else: + raise PdfReadError( + f"Unsupported PNG filter {filter_byte!r}" + ) # pragma: no cover + prev_rowdata = tuple(rowdata) + output.extend(rowdata[1:]) + return bytes(output) + + @staticmethod + def encode(data: bytes, level: int = -1) -> bytes: + """ + Compress the input data using zlib. + + Args: + data: The data to be compressed. + level: See https://docs.python.org/3/library/zlib.html#zlib.compress + + Returns: + The compressed data. + + """ + return zlib.compress(data, level) + + +class ASCIIHexDecode: + """ + The ASCIIHexDecode filter decodes data that has been encoded in ASCII + hexadecimal form into a base-7 ASCII format. + """ + + @staticmethod + def decode( + data: Union[str, bytes], + decode_parms: Optional[DictionaryObject] = None, + **kwargs: Any, + ) -> bytes: + """ + Decode an ASCII-Hex encoded data stream. + + Args: + data: a str sequence of hexadecimal-encoded values to be + converted into a base-7 ASCII string + decode_parms: a string conversion in base-7 ASCII, where each of its values + v is such that 0 <= ord(v) <= 127. + + Returns: + A string conversion in base-7 ASCII, where each of its values + v is such that 0 <= ord(v) <= 127. + + Raises: + PdfStreamError: + + """ + # decode_parms is unused here + + if isinstance(data, str): + data = data.encode() + retval = b"" + hex_pair = b"" + index = 0 + while True: + if index >= len(data): + logger_warning( + "missing EOD in ASCIIHexDecode, check if output is OK", __name__ + ) + break # Reached end of string even if no EOD + char = data[index : index + 1] + if char == b">": + break + if char.isspace(): + index += 1 + continue + hex_pair += char + if len(hex_pair) == 2: + retval += bytes((int(hex_pair, base=16),)) + hex_pair = b"" + index += 1 + assert hex_pair == b"" + return retval + + +class RunLengthDecode: + """ + The RunLengthDecode filter decodes data that has been encoded in a + simple byte-oriented format based on run length. + The encoded data is a sequence of runs, where each run consists of + a length byte followed by 1 to 128 bytes of data. If the length byte is + in the range 0 to 127, + the following length + 1 (1 to 128) bytes are copied literally during + decompression. + If length is in the range 129 to 255, the following single byte is to be + copied 257 − length (2 to 128) times during decompression. A length value + of 128 denotes EOD. + """ + + @staticmethod + def decode( + data: bytes, + decode_parms: Optional[DictionaryObject] = None, + **kwargs: Any, + ) -> bytes: + """ + Decode a run length encoded data stream. + + Args: + data: a bytes sequence of length/data + decode_parms: ignored. + + Returns: + A bytes decompressed sequence. + + Raises: + PdfStreamError: + + """ + # decode_parms is unused here + + lst = [] + index = 0 + while True: + if index >= len(data): + logger_warning( + "missing EOD in RunLengthDecode, check if output is OK", __name__ + ) + break # reach End Of String even if no EOD + length = data[index] + index += 1 + if length == 128: + if index < len(data): + raise PdfStreamError("Early EOD in RunLengthDecode") + else: + break + elif length < 128: + length += 1 + lst.append(data[index : (index + length)]) + index += length + else: # >128 + length = 257 - length + lst.append(bytes((data[index],)) * length) + index += 1 + return b"".join(lst) + + +class LZWDecode: + class Decoder: + STOP = 257 + CLEARDICT = 256 + + def __init__(self, data: bytes) -> None: + self.data = data + + def decode(self) -> bytes: + return _LzwCodec().decode(self.data) + + @staticmethod + def _decodeb( + data: bytes, + decode_parms: Optional[DictionaryObject] = None, + **kwargs: Any, + ) -> bytes: + """ + Decode an LZW encoded data stream. + + Args: + data: ``bytes`` or ``str`` text to decode. + decode_parms: a dictionary of parameter values. + + Returns: + decoded data. + + """ + # decode_parms is unused here + return LZWDecode.Decoder(data).decode() + + @staticmethod + def decode( + data: bytes, + decode_parms: Optional[DictionaryObject] = None, + **kwargs: Any, + ) -> str: # deprecated + """ + Decode an LZW encoded data stream. + + Args: + data: ``bytes`` or ``str`` text to decode. + decode_parms: a dictionary of parameter values. + + Returns: + decoded data. + + """ + # decode_parms is unused here + deprecate("LZWDecode.decode will return bytes instead of str in pypdf 6.0.0") + return LZWDecode.Decoder(data).decode().decode("latin-1") + + +class ASCII85Decode: + """Decodes string ASCII85-encoded data into a byte format.""" + + @staticmethod + def decode( + data: Union[str, bytes], + decode_parms: Optional[DictionaryObject] = None, + **kwargs: Any, + ) -> bytes: + """ + Decode an Ascii85 encoded data stream. + + Args: + data: ``bytes`` or ``str`` text to decode. + decode_parms: a dictionary of parameter values. + + Returns: + decoded data. + + """ + if isinstance(data, str): + data = data.encode() + data = data.strip(WHITESPACES_AS_BYTES) + try: + return a85decode(data, adobe=True, ignorechars=WHITESPACES_AS_BYTES) + except ValueError as error: + if error.args[0] == "Ascii85 encoded byte sequences must end with b'~>'": + logger_warning("Ignoring missing Ascii85 end marker.", __name__) + return a85decode(data, adobe=False, ignorechars=WHITESPACES_AS_BYTES) + raise + + +class DCTDecode: + @staticmethod + def decode( + data: bytes, + decode_parms: Optional[DictionaryObject] = None, + **kwargs: Any, + ) -> bytes: + # decode_parms is unused here + return data + + +class JPXDecode: + @staticmethod + def decode( + data: bytes, + decode_parms: Optional[DictionaryObject] = None, + **kwargs: Any, + ) -> bytes: + # decode_parms is unused here + return data + + +@dataclass +class CCITTParameters: + """§7.4.6, optional parameters for the CCITTFaxDecode filter.""" + + K: int = 0 + columns: int = 0 + rows: int = 0 + EndOfBlock: Union[int, None] = None + EndOfLine: Union[int, None] = None + EncodedByteAlign: Union[int, None] = None + DamagedRowsBeforeError: Union[int, None] = None + + @property + def group(self) -> int: + if self.K < 0: + # Pure two-dimensional encoding (Group 4) + CCITTgroup = 4 + else: + # K == 0: Pure one-dimensional encoding (Group 3, 1-D) + # K > 0: Mixed one- and two-dimensional encoding (Group 3, 2-D) + CCITTgroup = 3 + return CCITTgroup + + +def __create_old_class_instance( + K: int = 0, + columns: int = 0, + rows: int = 0 +) -> CCITTParameters: + deprecate_with_replacement("CCITParameters", "CCITTParameters", "6.0.0") + return CCITTParameters(K, columns, rows) + + +# Create an alias for the old class name +CCITParameters = __create_old_class_instance + + +class CCITTFaxDecode: + """ + §7.4.6, CCITTFaxDecode filter (ISO 32000). + + Either Group 3 or Group 4 CCITT facsimile (fax) encoding. + CCITT encoding is bit-oriented, not byte-oriented. + + §7.4.6, optional parameters for the CCITTFaxDecode filter. + """ + + @staticmethod + def _get_parameters( + parameters: Union[None, ArrayObject, DictionaryObject, IndirectObject], + rows: Union[int, IndirectObject], + ) -> CCITTParameters: + # §7.4.6, optional parameters for the CCITTFaxDecode filter + k = 0 + columns = 1728 + if parameters: + parameters_unwrapped = cast( + Union[ArrayObject, DictionaryObject], parameters.get_object() + ) + if isinstance(parameters_unwrapped, ArrayObject): + for decode_parm in parameters_unwrapped: + if CCITT.COLUMNS in decode_parm: + columns = decode_parm[CCITT.COLUMNS].get_object() + if CCITT.K in decode_parm: + k = decode_parm[CCITT.K].get_object() + else: + if CCITT.COLUMNS in parameters_unwrapped: + columns = parameters_unwrapped[CCITT.COLUMNS].get_object() # type: ignore + if CCITT.K in parameters_unwrapped: + k = parameters_unwrapped[CCITT.K].get_object() # type: ignore + + return CCITTParameters(K=k, columns=columns, rows=int(rows)) + + @staticmethod + def decode( + data: bytes, + decode_parms: Optional[DictionaryObject] = None, + height: int = 0, + **kwargs: Any, + ) -> bytes: + # decode_parms is unused here + if isinstance(decode_parms, ArrayObject): # deprecated + deprecation_no_replacement( + "decode_parms being an ArrayObject", removed_in="3.15.5" + ) + params = CCITTFaxDecode._get_parameters(decode_parms, height) + + img_size = len(data) + tiff_header_struct = "<2shlh" + "hhll" * 8 + "h" + tiff_header = struct.pack( + tiff_header_struct, + b"II", # Byte order indication: Little endian + 42, # Version number (always 42) + 8, # Offset to first IFD + 8, # Number of tags in IFD + 256, + 4, + 1, + params.columns, # ImageWidth, LONG, 1, width + 257, + 4, + 1, + params.rows, # ImageLength, LONG, 1, length + 258, + 3, + 1, + 1, # BitsPerSample, SHORT, 1, 1 + 259, + 3, + 1, + params.group, # Compression, SHORT, 1, 4 = CCITT Group 4 fax encoding + 262, + 3, + 1, + 0, # Thresholding, SHORT, 1, 0 = WhiteIsZero + 273, + 4, + 1, + struct.calcsize( + tiff_header_struct + ), # StripOffsets, LONG, 1, length of header + 278, + 4, + 1, + params.rows, # RowsPerStrip, LONG, 1, length + 279, + 4, + 1, + img_size, # StripByteCounts, LONG, 1, size of image + 0, # last IFD + ) + + return tiff_header + data + + +def decode_stream_data(stream: Any) -> bytes: + """ + Decode the stream data based on the specified filters. + + This function decodes the stream data using the filters provided in the + stream. + + Args: + stream: The input stream object containing the data and filters. + + Returns: + The decoded stream data. + + Raises: + NotImplementedError: If an unsupported filter type is encountered. + + """ + filters = stream.get(SA.FILTER, ()) + if isinstance(filters, IndirectObject): + filters = cast(ArrayObject, filters.get_object()) + if not isinstance(filters, ArrayObject): + # We have a single filter instance + filters = (filters,) + decode_parms = stream.get(SA.DECODE_PARMS, ({},) * len(filters)) + if not isinstance(decode_parms, (list, tuple)): + decode_parms = (decode_parms,) + data: bytes = stream._data + # If there is not data to decode we should not try to decode the data. + if not data: + return data + for filter_name, params in zip(filters, decode_parms): + if isinstance(params, NullObject): + params = {} + if filter_name in (FT.ASCII_HEX_DECODE, FTA.AHx): + data = ASCIIHexDecode.decode(data) + elif filter_name in (FT.ASCII_85_DECODE, FTA.A85): + data = ASCII85Decode.decode(data) + elif filter_name in (FT.LZW_DECODE, FTA.LZW): + data = LZWDecode._decodeb(data, params) + elif filter_name in (FT.FLATE_DECODE, FTA.FL): + data = FlateDecode.decode(data, params) + elif filter_name in (FT.RUN_LENGTH_DECODE, FTA.RL): + data = RunLengthDecode.decode(data) + elif filter_name == FT.CCITT_FAX_DECODE: + height = stream.get(IA.HEIGHT, ()) + data = CCITTFaxDecode.decode(data, params, height) + elif filter_name == FT.DCT_DECODE: + data = DCTDecode.decode(data) + elif filter_name == FT.JPX_DECODE: + data = JPXDecode.decode(data) + elif filter_name == "/Crypt": + if "/Name" in params or "/Type" in params: + raise NotImplementedError( + "/Crypt filter with /Name or /Type not supported yet" + ) + else: + raise NotImplementedError(f"Unsupported filter {filter_name}") + return data + + +def _xobj_to_image(x_object_obj: Dict[str, Any]) -> Tuple[Optional[str], bytes, Any]: + """ + Users need to have the pillow package installed. + + It's unclear if pypdf will keep this function here, hence it's private. + It might get removed at any point. + + Args: + x_object_obj: + + Returns: + Tuple[file extension, bytes, PIL.Image.Image] + + """ + from ._xobj_image_helpers import ( + Image, + UnidentifiedImageError, + _apply_decode, + _extended_image_frombytes, + _get_mode_and_invert_color, + _handle_flate, + _handle_jpx, + ) + + def _apply_alpha( + img: Image.Image, + x_object_obj: Dict[str, Any], + obj_as_text: str, + image_format: str, + extension: str, + ) -> Tuple[Image.Image, str, str]: + alpha = None + if IA.S_MASK in x_object_obj: # add alpha channel + alpha = _xobj_to_image(x_object_obj[IA.S_MASK])[2] + if img.size != alpha.size: + logger_warning( + f"image and mask size not matching: {obj_as_text}", __name__ + ) + else: + # TODO : implement mask + if alpha.mode != "L": + alpha = alpha.convert("L") + if img.mode == "P": + img = img.convert("RGB") + elif img.mode == "1": + img = img.convert("L") + img.putalpha(alpha) + if "JPEG" in image_format: + extension = ".jp2" + image_format = "JPEG2000" + else: + extension = ".png" + image_format = "PNG" + return img, extension, image_format + + # for error reporting + obj_as_text = ( + x_object_obj.indirect_reference.__repr__() + if x_object_obj is None # pragma: no cover + else x_object_obj.__repr__() + ) + + # Get size and data + size = (cast(int, x_object_obj[IA.WIDTH]), cast(int, x_object_obj[IA.HEIGHT])) + data = x_object_obj.get_data() # type: ignore + if isinstance(data, str): # pragma: no cover + data = data.encode() + if len(data) % (size[0] * size[1]) == 1 and data[-1] == 0x0A: # ie. '\n' + data = data[:-1] + + # Get color properties + colors = x_object_obj.get("/Colors", 1) + color_space: Any = x_object_obj.get("/ColorSpace", NullObject()).get_object() + if isinstance(color_space, list) and len(color_space) == 1: + color_space = color_space[0].get_object() + + mode, invert_color = _get_mode_and_invert_color(x_object_obj, colors, color_space) + + # Get filters + filters = x_object_obj.get(SA.FILTER, NullObject()).get_object() + lfilters = filters[-1] if isinstance(filters, list) else filters + + extension = None + if lfilters in (FT.FLATE_DECODE, FT.RUN_LENGTH_DECODE): + img, image_format, extension, _ = _handle_flate( + size, + data, + mode, + color_space, + colors, + obj_as_text, + ) + elif lfilters in (FT.LZW_DECODE, FT.ASCII_85_DECODE, FT.CCITT_FAX_DECODE): + # I'm not sure if the following logic is correct. + # There might not be any relationship between the filters and the + # extension + if lfilters in (FT.LZW_DECODE, FT.CCITT_FAX_DECODE): + extension = ".tiff" # mime_type = "image/tiff" + image_format = "TIFF" + else: + extension = ".png" # mime_type = "image/png" + image_format = "PNG" + try: + img = Image.open(BytesIO(data), formats=("TIFF", "PNG")) + except UnidentifiedImageError: + img = _extended_image_frombytes(mode, size, data) + elif lfilters == FT.DCT_DECODE: + img, image_format, extension = Image.open(BytesIO(data)), "JPEG", ".jpg" + # invert_color kept unchanged + elif lfilters == FT.JPX_DECODE: + img, image_format, extension, invert_color = _handle_jpx( + size, data, mode, color_space, colors + ) + elif lfilters == FT.CCITT_FAX_DECODE: + img, image_format, extension, invert_color = ( + Image.open(BytesIO(data), formats=("TIFF",)), + "TIFF", + ".tiff", + False, + ) + elif mode == "CMYK": + img, image_format, extension, invert_color = ( + _extended_image_frombytes(mode, size, data), + "TIFF", + ".tif", + False, + ) + elif mode == "": + raise PdfReadError(f"ColorSpace field not found in {x_object_obj}") + else: + img, image_format, extension, invert_color = ( + _extended_image_frombytes(mode, size, data), + "PNG", + ".png", + False, + ) + + img = _apply_decode(img, x_object_obj, lfilters, color_space, invert_color) + img, extension, image_format = _apply_alpha( + img, x_object_obj, obj_as_text, image_format, extension + ) + + # Save image to bytes + img_byte_arr = BytesIO() + try: + img.save(img_byte_arr, format=image_format) + except OSError: # pragma: no cover # covered with pillow 10.3 + # in case of we convert to RGBA and then to PNG + img1 = img.convert("RGBA") + image_format = "PNG" + extension = ".png" + img_byte_arr = BytesIO() + img1.save(img_byte_arr, format=image_format) + data = img_byte_arr.getvalue() + + try: # temporary try/except until other fixes of images + img = Image.open(BytesIO(data)) + except Exception: + img = None # type: ignore + return extension, data, img diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/__init__.py b/venv/lib/python3.12/site-packages/pypdf/generic/__init__.py new file mode 100644 index 0000000..dc45459 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/generic/__init__.py @@ -0,0 +1,238 @@ +# Copyright (c) 2006, Mathieu Fenniak +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +"""Implementation of generic PDF objects (dictionary, number, string, ...).""" +__author__ = "Mathieu Fenniak" +__author_email__ = "biziqe@mathieu.fenniak.net" + +from typing import List, Optional, Tuple, Union + +from .._utils import ( + deprecation_with_replacement, +) +from ..constants import OutlineFontFlag +from ._base import ( + BooleanObject, + ByteStringObject, + FloatObject, + IndirectObject, + NameObject, + NullObject, + NumberObject, + PdfObject, + TextStringObject, + encode_pdfdocencoding, + is_null_or_none, +) +from ._data_structures import ( + ArrayObject, + ContentStream, + DecodedStreamObject, + Destination, + DictionaryObject, + EncodedStreamObject, + Field, + StreamObject, + TreeObject, + read_object, +) +from ._files import EmbeddedFile +from ._fit import Fit +from ._outline import OutlineItem +from ._rectangle import RectangleObject +from ._utils import ( + create_string_object, + decode_pdfdocencoding, + hex_to_rgb, + read_hex_string_from_stream, + read_string_from_stream, +) +from ._viewerpref import ViewerPreferences + +PAGE_FIT = Fit.fit() + + +class AnnotationBuilder: # deprecated + """ + The AnnotationBuilder is deprecated. + + Instead, use the annotation classes in pypdf.annotations. + + See `adding PDF annotations <../user/adding-pdf-annotations.html>`_ for + its usage combined with PdfWriter. + """ + + from ..generic._rectangle import RectangleObject + + @staticmethod + def text( + rect: Union[RectangleObject, Tuple[float, float, float, float]], + text: str, + open: bool = False, + flags: int = 0, + ) -> None: + deprecation_with_replacement( + "AnnotationBuilder.text", "pypdf.annotations.Text", "5.0.0" + ) + + @staticmethod + def free_text( + text: str, + rect: Union[RectangleObject, Tuple[float, float, float, float]], + font: str = "Helvetica", + bold: bool = False, + italic: bool = False, + font_size: str = "14pt", + font_color: str = "000000", + border_color: Optional[str] = "000000", + background_color: Optional[str] = "ffffff", + ) -> None: + deprecation_with_replacement( + "AnnotationBuilder.free_text", "pypdf.annotations.FreeText", "5.0.0" + ) + + @staticmethod + def popup( + *, + rect: Union[RectangleObject, Tuple[float, float, float, float]], + flags: int = 0, + parent: Optional[DictionaryObject] = None, + open: bool = False, + ) -> None: + deprecation_with_replacement( + "AnnotationBuilder.popup", "pypdf.annotations.Popup", "5.0.0" + ) + + @staticmethod + def line( + p1: Tuple[float, float], + p2: Tuple[float, float], + rect: Union[RectangleObject, Tuple[float, float, float, float]], + text: str = "", + title_bar: Optional[str] = None, + ) -> None: + deprecation_with_replacement( + "AnnotationBuilder.line", "pypdf.annotations.Line", "5.0.0" + ) + + @staticmethod + def polyline( + vertices: List[Tuple[float, float]], + ) -> None: + deprecation_with_replacement( + "AnnotationBuilder.polyline", "pypdf.annotations.PolyLine", "5.0.0" + ) + + @staticmethod + def rectangle( + rect: Union[RectangleObject, Tuple[float, float, float, float]], + interiour_color: Optional[str] = None, + ) -> None: + deprecation_with_replacement( + "AnnotationBuilder.rectangle", "pypdf.annotations.Rectangle", "5.0.0" + ) + + @staticmethod + def highlight( + *, + rect: Union[RectangleObject, Tuple[float, float, float, float]], + quad_points: ArrayObject, + highlight_color: str = "ff0000", + printing: bool = False, + ) -> None: + deprecation_with_replacement( + "AnnotationBuilder.highlight", "pypdf.annotations.Highlight", "5.0.0" + ) + + @staticmethod + def ellipse( + rect: Union[RectangleObject, Tuple[float, float, float, float]], + interiour_color: Optional[str] = None, + ) -> None: + deprecation_with_replacement( + "AnnotationBuilder.ellipse", "pypdf.annotations.Ellipse", "5.0.0" + ) + + @staticmethod + def polygon(vertices: List[Tuple[float, float]]) -> None: + deprecation_with_replacement( + "AnnotationBuilder.polygon", "pypdf.annotations.Polygon", "5.0.0" + ) + + from ._fit import DEFAULT_FIT + + @staticmethod + def link( + rect: Union[RectangleObject, Tuple[float, float, float, float]], + border: Optional[ArrayObject] = None, + url: Optional[str] = None, + target_page_index: Optional[int] = None, + fit: Fit = DEFAULT_FIT, + ) -> None: + deprecation_with_replacement( + "AnnotationBuilder.link", "pypdf.annotations.Link", "5.0.0" + ) + + +__all__ = [ + "PAGE_FIT", + "AnnotationBuilder", + "ArrayObject", + "BooleanObject", + "ByteStringObject", + "ContentStream", + "DecodedStreamObject", + "Destination", + "DictionaryObject", + "EmbeddedFile", + "EncodedStreamObject", + "Field", + "Fit", + "FloatObject", + "IndirectObject", + "NameObject", + "NullObject", + "NumberObject", + "OutlineFontFlag", + "OutlineItem", + "PdfObject", + "RectangleObject", + "StreamObject", + "TextStringObject", + "TreeObject", + "ViewerPreferences", + # Utility functions + "create_string_object", + "decode_pdfdocencoding", + "encode_pdfdocencoding", + "hex_to_rgb", + "is_null_or_none", + "read_hex_string_from_stream", + # Data structures core functions + "read_object", + "read_string_from_stream", +] diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e60e3967ccd968a3720f7ac202decc2adc5e318 GIT binary patch literal 6766 zcmb_hO>7&-6(0WoiXtVE)W24?WQqDAB|FYvlQjMjZKIBCBz9VClWr*PklJ{EnAxQh z>Esp$+M+$)9w@u6ft>o@?2@8FS+1L` zz{j^UJMVq(o0<29t3UVjLbKnsdNEhL6KL=MP7HLOL%2-ibuREvo*(8F>>jcYw(kCqSwc z5>r~A*r)Z2{n~&yprysMmJu^rR?PA-QFTxo5{I;5aabD>N3>CKR2vh=v~h7Que+-b5-$#mz*PV>L!uvfP`*1zlFaP3u0oTGFW7 z7hSEZs;kFWdGzjG^420T-!FWnATf*N54H637$;GKEL<$&fEpo+&(p1|uXw@uHMNG%AN_OpegF9F=30s2sl;Xz#Zk#|GMQ{^TV-;xLOnU@-v}d*PD=Jq4dW znxIkcufMIKw*h&e!&@&6LRO2(emVWA?@-i;HUpND+$Q38uxD=u+t^cX{LAv76T2Jn z(7wCFB0+A3_u-ApBOQ4A0PiU6@3hD9AQrzocGKU+GJsg*LwK|7*=YV6v}GJG^r^lx=`DI?3dr`Gu`2DP%6Arl4VGU zywG$!A-t5&7r-hjIQ@%YVX>n>ziw&jEAL1`#b6wY0tKpWma0@J8`>IF0$IQ^AwX{a zAyX{M^87Itf(^{3Kol947Tb^M-u7FNw{5>sqq-faK>aZ7Afr~D>8s_|IRl<10r)`v zAP>etd`v8?GW?R^+#&lu!#=n?WCJSO>SpFtn-7=bJUZIUbTfj5qYX%gWpkkF&rEEvAO)`~DYDc+RHdKSz@il|N!jqi4?GVl*lm}G;i=$om()Q{YHoY}+!t9+Dti`sb3Q)*cCc20;$}H3 z;#KHq7dc!RPf1a>o1&UgtJgNO-Sk|>jt*|z<%x@uAr6kHy*!=h1Fp5lxVa9)T2Uu? z)YIEDuil;6i`w?qmf>^Uj#!GNQfaNk${1toddheY*p7H+JZL*!g!YbT1MCd=WM@(A zZOaw7H4#I{jQbsn-63Q9&*0ey?mRmYcWfR$&vy7aWtM`cmv(M}K~EXzaJT!Kp>A+! z2Q2-|(6>L}J05lcgF_60GnwH%3y-({YaHYT80J$tyFFL@!pRO!fV~PFY?)%z-CbXH zf0Mw-r;hW0J%#C9EutaJ%z2IL?hY+SDts(Aj}>ARXg@x9nRe~18z8y2MU>fVEZbH_1!1!YmZ6V*Y+651)QDz7Jz1NqxcC53B*B38!UDc0~zz$ zpK#Q96uc07or7a8WJk_Z^*V)QT`CrB|MD|6%MRj3Us_@^JZ{6j#|!p7SF$(Z9gtO|t6^1;P*eNZ{nXK&lxgnUO|1vl|Hq zqK!oVtxLDB{{G}2raw>L4Q$V^>`WK82Z}q1b4?%g-%F&L0r+kPNpF8Mgj$#+`vtAcc5mnjm2d^dp{O=0xakUSP*>(wJ=EyZ4c#kl5@=n-bWE8+5m9itOqpL z8MbB6S(K!+jiWQW_*5gFx;4F(zO}FupJ@7^;a+D$0LK6Y1CN~@7Xy&wdLJ0wI`h%X zPe9-efaku_ z<@Q@U6UTRkPc#WMe(t}IUv7w?J&cmT5!_-yl3Q$yO*ZBWjs9_Gx(`|JeD;%rTO&Kk z>83mLiOj9?FW+tjKRR{$%qK6m2!Jhgz&hLY!kXb}k#GOp5j%YO)VUR`3rIC#+b3)c1Ex2FAnTL2$r`6@bVktAwvU z>t%QqK}{z+A4K9Ff1C|Ygn%}Jkh@hF$yt66S~$T_hz#d_IVTgs-(O-n_~X=Z){rne zCSB*RS>a`T#i1JODKk-E1+bxfmEg6u#27YV#pE^O>+nlXy?ce-fHpjrm_G;6^m#m< z-RFttlBdx#ek0oGFKm`l!iD&kaH}3I1A}z7Ywc!}HwZy|g;+g!C zq`xE}XC8TjFqEK35YPO*Sl=&BeE8fipZnDdH^PsC?|VGaU4rty<(rOqe;VRI{|iWY B*~S0> literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_base.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_base.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3f81cdb24558d487f8dd7d1ad80bbc9787956221 GIT binary patch literal 38704 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_data_structures.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_data_structures.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b40e55398ab81e5f06aea70929a5bbd377136b59 GIT binary patch literal 72306 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≷gA7$SXt-DJB=3C}O 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_fit.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_fit.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6df697900e30e47a5b96ba3b89be547e4c75ce7c GIT binary patch literal 7105 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_outline.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_outline.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a23dcb1e3bf6cf6adf2a189ccc726a55039689a1 GIT binary patch literal 1827 zcmb_c&1)M+6rb5It)!JD$ExFxxRxn)SxU98OGu%{P^!8OD2kyDp@OiicSrI%tCcdl zva>>l7JRTF#rDZQ`p`@9KagYYy~ISpVq1fuhvJ)SyMgA^nO!My0=bmD!<+YJ-sjBk z&2NcB3=sN#^F?`<1K>}pbcyc>=LI6{00S7%0u@+<5EzWXT1wRDRnYB)C8WC~R6K_q*R%r%ordp{*b&YriLe6@ zC_)1inJ6#>gF&ppBF=z_M?#4mBo?F@SP~3=jW0$#C`bJG?Ye83HoEDeO2HSLphmw3 z**f-WL3#I)=L;CQb!_XMHiMi3;Z#4rLK@rwP39-brL_lSK!e$*jT3^P370N=hTFhk z_dE9VVsl`V)tNHTnR~qetg=nE36=qlyWOV(%~$r@%%eVzSgx`;aPKa$=9=76q!aei z(uA)wyrTyGk_A|bUUKe;O|EOP$~XD{nMLTvfZ)*&9C+Q65$T@1w;lq}zuCw8sr(%` zD0Vx5z$0%0gLhd0a6k1u1ZCcIE!2o8a~dYoK{jSh?6?hH$!oz*@EhE>D8N^f7FxEU-@Hq!rB`gsaoS=U2q0iEp;FmS4jvN{{ z6VS_|vRJJk#Vp$l?YWlhpT0b97kD3_OfD`3rfv%7pwN?+0UjFhg`s?HBG;- zm61aZYDP&ZBO75;SJY}ao7tL&`$(F`@TFnRzEwVju5(VvJeNjK`$(vZG)NBaUVYXxw$8T2_@Ov_AP(=&w#1LxVoy-md`lc^r_wvg?c_S& z788f!$bmSrTWX2pU6VU4arl+|Tpa%QY>brZ&_Cjr{v5~2upo=RsH!#rnX39RRjpKw zxQOr15!q&iXe(rB}fWOx6 z&zuJ9)Q!j7WBtkXr(b+`Fm*H7JB}tUcw&Rcx&aDu%okj*X4>U2ub|dl({jQ}LU^hR znu9`krc^_7H98n|o&3F|Hu}P0JsBzmfoY8|#p$re89YH$It0!LVW%vF@CXe21-?82 UBS%2K5C-A3txx^|WC`5=13opGc>n+a literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_rectangle.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_rectangle.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..82855d4b9d3f3cb364ceed53a57c942307afe0b6 GIT binary patch literal 7814 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_viewerpref.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/generic/__pycache__/_viewerpref.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd8b1791543d1e375f7410fdc9be7d835946ae7c GIT binary patch literal 9067 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/_base.py b/venv/lib/python3.12/site-packages/pypdf/generic/_base.py new file mode 100644 index 0000000..aa86383 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/generic/_base.py @@ -0,0 +1,910 @@ +# Copyright (c) 2006, Mathieu Fenniak +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +import binascii +import codecs +import hashlib +import re +import sys +from binascii import unhexlify +from math import log10 +from struct import iter_unpack +from typing import Any, Callable, ClassVar, Dict, Optional, Sequence, Union, cast + +if sys.version_info[:2] >= (3, 10): + from typing import TypeGuard +else: + from typing_extensions import TypeGuard # PEP 647 + +from .._codecs import _pdfdoc_encoding_rev +from .._protocols import PdfObjectProtocol, PdfWriterProtocol +from .._utils import ( + StreamType, + deprecate_no_replacement, + logger_warning, + read_non_whitespace, + read_until_regex, +) +from ..errors import STREAM_TRUNCATED_PREMATURELY, PdfReadError, PdfStreamError + +__author__ = "Mathieu Fenniak" +__author_email__ = "biziqe@mathieu.fenniak.net" + + +class PdfObject(PdfObjectProtocol): + # function for calculating a hash value + hash_func: Callable[..., "hashlib._Hash"] = hashlib.sha1 + indirect_reference: Optional["IndirectObject"] + + def hash_bin(self) -> int: + """ + Used to detect modified object. + + Returns: + Hash considering type and value. + + """ + raise NotImplementedError( + f"{self.__class__.__name__} does not implement .hash_bin() so far" + ) + + def hash_value_data(self) -> bytes: + return f"{self}".encode() + + def hash_value(self) -> bytes: + return ( + f"{self.__class__.__name__}:" + f"{self.hash_func(self.hash_value_data()).hexdigest()}" + ).encode() + + def replicate( + self, + pdf_dest: PdfWriterProtocol, + ) -> "PdfObject": + """ + Clone object into pdf_dest (PdfWriterProtocol which is an interface for PdfWriter) + without ensuring links. This is used in clone_document_from_root with incremental = True. + + Args: + pdf_dest: Target to clone to. + + Returns: + The cloned PdfObject + + """ + return self.clone(pdf_dest) + + def clone( + self, + pdf_dest: PdfWriterProtocol, + force_duplicate: bool = False, + ignore_fields: Optional[Sequence[Union[str, int]]] = (), + ) -> "PdfObject": + """ + Clone object into pdf_dest (PdfWriterProtocol which is an interface for PdfWriter). + + By default, this method will call ``_reference_clone`` (see ``_reference``). + + + Args: + pdf_dest: Target to clone to. + force_duplicate: By default, if the object has already been cloned and referenced, + the copy will be returned; when ``True``, a new copy will be created. + (Default value = ``False``) + ignore_fields: List/tuple of field names (for dictionaries) that will be ignored + during cloning (applies to children duplication as well). If fields are to be + considered for a limited number of levels, you have to add it as integer, for + example ``[1,"/B","/TOTO"]`` means that ``"/B"`` will be ignored at the first + level only but ``"/TOTO"`` on all levels. + + Returns: + The cloned PdfObject + + """ + raise NotImplementedError( + f"{self.__class__.__name__} does not implement .clone so far" + ) + + def _reference_clone( + self, clone: Any, pdf_dest: PdfWriterProtocol, force_duplicate: bool = False + ) -> PdfObjectProtocol: + """ + Reference the object within the _objects of pdf_dest only if + indirect_reference attribute exists (which means the objects was + already identified in xref/xobjstm) if object has been already + referenced do nothing. + + Args: + clone: + pdf_dest: + + Returns: + The clone + + """ + try: + if not force_duplicate and clone.indirect_reference.pdf == pdf_dest: + return clone + except Exception: + pass + # if hasattr(clone, "indirect_reference"): + try: + ind = self.indirect_reference + except AttributeError: + return clone + if ( + pdf_dest.incremental + and ind is not None + and ind.pdf == pdf_dest._reader + and ind.idnum <= len(pdf_dest._objects) + ): + i = ind.idnum + else: + i = len(pdf_dest._objects) + 1 + if ind is not None: + if id(ind.pdf) not in pdf_dest._id_translated: + pdf_dest._id_translated[id(ind.pdf)] = {} + pdf_dest._id_translated[id(ind.pdf)]["PreventGC"] = ind.pdf # type: ignore + if ( + not force_duplicate + and ind.idnum in pdf_dest._id_translated[id(ind.pdf)] + ): + obj = pdf_dest.get_object( + pdf_dest._id_translated[id(ind.pdf)][ind.idnum] + ) + assert obj is not None + return obj + pdf_dest._id_translated[id(ind.pdf)][ind.idnum] = i + try: + pdf_dest._objects[i - 1] = clone + except IndexError: + pdf_dest._objects.append(clone) + i = len(pdf_dest._objects) + clone.indirect_reference = IndirectObject(i, 0, pdf_dest) + return clone + + def get_object(self) -> Optional["PdfObject"]: + """Resolve indirect references.""" + return self + + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + raise NotImplementedError + + +class NullObject(PdfObject): + def clone( + self, + pdf_dest: PdfWriterProtocol, + force_duplicate: bool = False, + ignore_fields: Optional[Sequence[Union[str, int]]] = (), + ) -> "NullObject": + """Clone object into pdf_dest.""" + return cast( + "NullObject", self._reference_clone(NullObject(), pdf_dest, force_duplicate) + ) + + def hash_bin(self) -> int: + """ + Used to detect modified object. + + Returns: + Hash considering type and value. + + """ + return hash((self.__class__,)) + + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) + stream.write(b"null") + + @staticmethod + def read_from_stream(stream: StreamType) -> "NullObject": + nulltxt = stream.read(4) + if nulltxt != b"null": + raise PdfReadError("Could not read Null object") + return NullObject() + + def __repr__(self) -> str: + return "NullObject" + + +class BooleanObject(PdfObject): + def __init__(self, value: Any) -> None: + self.value = value + + def clone( + self, + pdf_dest: PdfWriterProtocol, + force_duplicate: bool = False, + ignore_fields: Optional[Sequence[Union[str, int]]] = (), + ) -> "BooleanObject": + """Clone object into pdf_dest.""" + return cast( + "BooleanObject", + self._reference_clone(BooleanObject(self.value), pdf_dest, force_duplicate), + ) + + def hash_bin(self) -> int: + """ + Used to detect modified object. + + Returns: + Hash considering type and value. + + """ + return hash((self.__class__, self.value)) + + def __eq__(self, o: object, /) -> bool: + if isinstance(o, BooleanObject): + return self.value == o.value + elif isinstance(o, bool): + return self.value == o + else: + return False + + def __repr__(self) -> str: + return "True" if self.value else "False" + + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) + if self.value: + stream.write(b"true") + else: + stream.write(b"false") + + @staticmethod + def read_from_stream(stream: StreamType) -> "BooleanObject": + word = stream.read(4) + if word == b"true": + return BooleanObject(True) + elif word == b"fals": + stream.read(1) + return BooleanObject(False) + else: + raise PdfReadError("Could not read Boolean object") + + +class IndirectObject(PdfObject): + def __init__(self, idnum: int, generation: int, pdf: Any) -> None: # PdfReader + self.idnum = idnum + self.generation = generation + self.pdf = pdf + + def __hash__(self) -> int: + return hash((self.idnum, self.generation, id(self.pdf))) + + def hash_bin(self) -> int: + """ + Used to detect modified object. + + Returns: + Hash considering type and value. + + """ + return hash((self.__class__, self.idnum, self.generation, id(self.pdf))) + + def replicate( + self, + pdf_dest: PdfWriterProtocol, + ) -> "PdfObject": + return IndirectObject(self.idnum, self.generation, pdf_dest) + + def clone( + self, + pdf_dest: PdfWriterProtocol, + force_duplicate: bool = False, + ignore_fields: Optional[Sequence[Union[str, int]]] = (), + ) -> "IndirectObject": + """Clone object into pdf_dest.""" + if self.pdf == pdf_dest and not force_duplicate: + # Already duplicated and no extra duplication required + return self + if id(self.pdf) not in pdf_dest._id_translated: + pdf_dest._id_translated[id(self.pdf)] = {} + + if self.idnum in pdf_dest._id_translated[id(self.pdf)]: + dup = pdf_dest.get_object(pdf_dest._id_translated[id(self.pdf)][self.idnum]) + if force_duplicate: + assert dup is not None + assert dup.indirect_reference is not None + idref = dup.indirect_reference + return IndirectObject(idref.idnum, idref.generation, idref.pdf) + else: + obj = self.get_object() + # case observed : a pointed object can not be found + if obj is None: + # this normally + obj = NullObject() + assert isinstance(self, (IndirectObject,)) + obj.indirect_reference = self + dup = pdf_dest._add_object( + obj.clone(pdf_dest, force_duplicate, ignore_fields) + ) + # asserts added to prevent errors in mypy + assert dup is not None + assert dup.indirect_reference is not None + return dup.indirect_reference + + @property + def indirect_reference(self) -> "IndirectObject": # type: ignore[override] + return self + + def get_object(self) -> Optional["PdfObject"]: + return self.pdf.get_object(self) + + def __deepcopy__(self, memo: Any) -> "IndirectObject": + return IndirectObject(self.idnum, self.generation, self.pdf) + + def _get_object_with_check(self) -> Optional["PdfObject"]: + o = self.get_object() + # the check is done here to not slow down get_object() + if isinstance(o, IndirectObject): + raise PdfStreamError( + f"{self.__repr__()} references an IndirectObject {o.__repr__()}" + ) + return o + + def __getattr__(self, name: str) -> Any: + # Attribute not found in object: look in pointed object + try: + return getattr(self._get_object_with_check(), name) + except AttributeError: + raise AttributeError( + f"No attribute {name} found in IndirectObject or pointed object" + ) + + def __getitem__(self, key: Any) -> Any: + # items should be extracted from pointed Object + return self._get_object_with_check()[key] # type: ignore + + def __contains__(self, key: Any) -> bool: + return key in self._get_object_with_check() # type: ignore + + def __float__(self) -> str: + # in this case we are looking for the pointed data + return self.get_object().__float__() # type: ignore + + def __int__(self) -> int: + # in this case we are looking for the pointed data + return self.get_object().__int__() # type: ignore + + def __str__(self) -> str: + # in this case we are looking for the pointed data + return self.get_object().__str__() + + def __repr__(self) -> str: + return f"IndirectObject({self.idnum!r}, {self.generation!r}, {id(self.pdf)})" + + def __eq__(self, other: object) -> bool: + return ( + other is not None + and isinstance(other, IndirectObject) + and self.idnum == other.idnum + and self.generation == other.generation + and self.pdf is other.pdf + ) + + def __ne__(self, other: object) -> bool: + return not self.__eq__(other) + + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) + stream.write(f"{self.idnum} {self.generation} R".encode()) + + @staticmethod + def read_from_stream(stream: StreamType, pdf: Any) -> "IndirectObject": # PdfReader + idnum = b"" + while True: + tok = stream.read(1) + if not tok: + raise PdfStreamError(STREAM_TRUNCATED_PREMATURELY) + if tok.isspace(): + break + idnum += tok + generation = b"" + while True: + tok = stream.read(1) + if not tok: + raise PdfStreamError(STREAM_TRUNCATED_PREMATURELY) + if tok.isspace(): + if not generation: + continue + break + generation += tok + r = read_non_whitespace(stream) + if r != b"R": + raise PdfReadError( + f"Error reading indirect object reference at byte {hex(stream.tell())}" + ) + return IndirectObject(int(idnum), int(generation), pdf) + + +FLOAT_WRITE_PRECISION = 8 # shall be min 5 digits max, allow user adj + + +class FloatObject(float, PdfObject): + def __new__( + cls, value: Any = "0.0", context: Optional[Any] = None + ) -> "FloatObject": + try: + value = float(value) + return float.__new__(cls, value) + except Exception as e: + # If this isn't a valid decimal (happens in malformed PDFs) + # fallback to 0 + logger_warning( + f"{e} : FloatObject ({value}) invalid; use 0.0 instead", __name__ + ) + return float.__new__(cls, 0.0) + + def clone( + self, + pdf_dest: Any, + force_duplicate: bool = False, + ignore_fields: Optional[Sequence[Union[str, int]]] = (), + ) -> "FloatObject": + """Clone object into pdf_dest.""" + return cast( + "FloatObject", + self._reference_clone(FloatObject(self), pdf_dest, force_duplicate), + ) + + def hash_bin(self) -> int: + """ + Used to detect modified object. + + Returns: + Hash considering type and value. + + """ + return hash((self.__class__, self.as_numeric)) + + def myrepr(self) -> str: + if self == 0: + return "0.0" + nb = FLOAT_WRITE_PRECISION - int(log10(abs(self))) + s = f"{self:.{max(1,nb)}f}".rstrip("0").rstrip(".") + return s + + def __repr__(self) -> str: + return self.myrepr() # repr(float(self)) + + def as_numeric(self) -> float: + return float(self) + + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) + stream.write(self.myrepr().encode("utf8")) + + +class NumberObject(int, PdfObject): + NumberPattern = re.compile(b"[^+-.0-9]") + + def __new__(cls, value: Any) -> "NumberObject": + try: + return int.__new__(cls, int(value)) + except ValueError: + logger_warning(f"NumberObject({value}) invalid; use 0 instead", __name__) + return int.__new__(cls, 0) + + def clone( + self, + pdf_dest: Any, + force_duplicate: bool = False, + ignore_fields: Optional[Sequence[Union[str, int]]] = (), + ) -> "NumberObject": + """Clone object into pdf_dest.""" + return cast( + "NumberObject", + self._reference_clone(NumberObject(self), pdf_dest, force_duplicate), + ) + + def hash_bin(self) -> int: + """ + Used to detect modified object. + + Returns: + Hash considering type and value. + + """ + return hash((self.__class__, self.as_numeric())) + + def as_numeric(self) -> int: + return int(repr(self).encode("utf8")) + + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) + stream.write(repr(self).encode("utf8")) + + @staticmethod + def read_from_stream(stream: StreamType) -> Union["NumberObject", "FloatObject"]: + num = read_until_regex(stream, NumberObject.NumberPattern) + if b"." in num: + return FloatObject(num) + return NumberObject(num) + + +class ByteStringObject(bytes, PdfObject): + """ + Represents a string object where the text encoding could not be determined. + + This occurs quite often, as the PDF spec doesn't provide an alternate way to + represent strings -- for example, the encryption data stored in files (like + /O) is clearly not text, but is still stored in a "String" object. + """ + + def clone( + self, + pdf_dest: Any, + force_duplicate: bool = False, + ignore_fields: Optional[Sequence[Union[str, int]]] = (), + ) -> "ByteStringObject": + """Clone object into pdf_dest.""" + return cast( + "ByteStringObject", + self._reference_clone( + ByteStringObject(bytes(self)), pdf_dest, force_duplicate + ), + ) + + def hash_bin(self) -> int: + """ + Used to detect modified object. + + Returns: + Hash considering type and value. + + """ + return hash((self.__class__, bytes(self))) + + @property + def original_bytes(self) -> bytes: + """For compatibility with TextStringObject.original_bytes.""" + return self + + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) + stream.write(b"<") + stream.write(binascii.hexlify(self)) + stream.write(b">") + + def __str__(self) -> str: + charset_to_try = ["utf-16", *list(NameObject.CHARSETS)] + for enc in charset_to_try: + try: + return self.decode(enc) + except UnicodeDecodeError: + pass + raise PdfReadError("Cannot decode ByteStringObject.") + + +class TextStringObject(str, PdfObject): # noqa: SLOT000 + """ + A string object that has been decoded into a real unicode string. + + If read from a PDF document, this string appeared to match the + PDFDocEncoding, or contained a UTF-16BE BOM mark to cause UTF-16 decoding + to occur. + """ + + autodetect_pdfdocencoding: bool + autodetect_utf16: bool + utf16_bom: bytes + _original_bytes: Optional[bytes] = None + + def __new__(cls, value: Any) -> "TextStringObject": + org = None + if isinstance(value, bytes): + org = value + value = value.decode("charmap") + o = str.__new__(cls, value) + o._original_bytes = org + o.autodetect_utf16 = False + o.autodetect_pdfdocencoding = False + o.utf16_bom = b"" + if o.startswith(("\xfe\xff", "\xff\xfe")): + assert org is not None # for mypy + try: + o = str.__new__(cls, org.decode("utf-16")) + except UnicodeDecodeError as exc: + logger_warning( + f"{exc!s}\ninitial string:{exc.object!r}", + __name__, + ) + o = str.__new__(cls, exc.object[: exc.start].decode("utf-16")) + o._original_bytes = org + o.autodetect_utf16 = True + o.utf16_bom = org[:2] + else: + try: + encode_pdfdocencoding(o) + o.autodetect_pdfdocencoding = True + except UnicodeEncodeError: + o.autodetect_utf16 = True + o.utf16_bom = codecs.BOM_UTF16_BE + return o + + def clone( + self, + pdf_dest: Any, + force_duplicate: bool = False, + ignore_fields: Optional[Sequence[Union[str, int]]] = (), + ) -> "TextStringObject": + """Clone object into pdf_dest.""" + obj = TextStringObject(self) + obj._original_bytes = self._original_bytes + obj.autodetect_pdfdocencoding = self.autodetect_pdfdocencoding + obj.autodetect_utf16 = self.autodetect_utf16 + obj.utf16_bom = self.utf16_bom + return cast( + "TextStringObject", self._reference_clone(obj, pdf_dest, force_duplicate) + ) + + def hash_bin(self) -> int: + """ + Used to detect modified object. + + Returns: + Hash considering type and value. + + """ + return hash((self.__class__, self.original_bytes)) + + @property + def original_bytes(self) -> bytes: + """ + It is occasionally possible that a text string object gets created where + a byte string object was expected due to the autodetection mechanism -- + if that occurs, this "original_bytes" property can be used to + back-calculate what the original encoded bytes were. + """ + if self._original_bytes is not None: + return self._original_bytes + else: + return self.get_original_bytes() + + def get_original_bytes(self) -> bytes: + # We're a text string object, but the library is trying to get our raw + # bytes. This can happen if we auto-detected this string as text, but + # we were wrong. It's pretty common. Return the original bytes that + # would have been used to create this object, based upon the autodetect + # method. + if self.autodetect_utf16: + if self.utf16_bom == codecs.BOM_UTF16_LE: + return codecs.BOM_UTF16_LE + self.encode("utf-16le") + elif self.utf16_bom == codecs.BOM_UTF16_BE: + return codecs.BOM_UTF16_BE + self.encode("utf-16be") + else: + return self.encode("utf-16be") + elif self.autodetect_pdfdocencoding: + return encode_pdfdocencoding(self) + else: + raise Exception("no information about original bytes") # pragma: no cover + + def get_encoded_bytes(self) -> bytes: + # Try to write the string out as a PDFDocEncoding encoded string. It's + # nicer to look at in the PDF file. Sadly, we take a performance hit + # here for trying... + try: + if self._original_bytes is not None: + return self._original_bytes + if self.autodetect_utf16: + raise UnicodeEncodeError("", "forced", -1, -1, "") + bytearr = encode_pdfdocencoding(self) + except UnicodeEncodeError: + if self.utf16_bom == codecs.BOM_UTF16_LE: + bytearr = codecs.BOM_UTF16_LE + self.encode("utf-16le") + elif self.utf16_bom == codecs.BOM_UTF16_BE: + bytearr = codecs.BOM_UTF16_BE + self.encode("utf-16be") + else: + bytearr = self.encode("utf-16be") + return bytearr + + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) + bytearr = self.get_encoded_bytes() + stream.write(b"(") + for c_ in iter_unpack("c", bytearr): + c = cast(bytes, c_[0]) + if not c.isalnum() and c != b" ": + # This: + # stream.write(rf"\{c:0>3o}".encode()) + # gives + # https://github.com/davidhalter/parso/issues/207 + stream.write(b"\\%03o" % ord(c)) + else: + stream.write(c) + stream.write(b")") + + +class NameObject(str, PdfObject): # noqa: SLOT000 + delimiter_pattern = re.compile(rb"\s+|[\(\)<>\[\]{}/%]") + surfix = b"/" + renumber_table: ClassVar[Dict[str, bytes]] = { + "#": b"#23", + "(": b"#28", + ")": b"#29", + "/": b"#2F", + "%": b"#25", + **{chr(i): f"#{i:02X}".encode() for i in range(33)}, + } + + def clone( + self, + pdf_dest: Any, + force_duplicate: bool = False, + ignore_fields: Optional[Sequence[Union[str, int]]] = (), + ) -> "NameObject": + """Clone object into pdf_dest.""" + return cast( + "NameObject", + self._reference_clone(NameObject(self), pdf_dest, force_duplicate), + ) + + def hash_bin(self) -> int: + """ + Used to detect modified object. + + Returns: + Hash considering type and value. + + """ + return hash((self.__class__, self)) + + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) + stream.write(self.renumber()) + + def renumber(self) -> bytes: + out = self[0].encode("utf-8") + if out != b"/": + deprecate_no_replacement( + f"Incorrect first char in NameObject, should start with '/': ({self})", + "6.0.0", + ) + for c in self[1:]: + if c > "~": + for x in c.encode("utf-8"): + out += f"#{x:02X}".encode() + else: + try: + out += self.renumber_table[c] + except KeyError: + out += c.encode("utf-8") + return out + + @staticmethod + def unnumber(sin: bytes) -> bytes: + i = sin.find(b"#", 0) + while i >= 0: + try: + sin = sin[:i] + unhexlify(sin[i + 1 : i + 3]) + sin[i + 3 :] + i = sin.find(b"#", i + 1) + except ValueError: + # if the 2 characters after # can not be converted to hex + # we change nothing and carry on + i = i + 1 + return sin + + CHARSETS = ("utf-8", "gbk", "latin1") + + @staticmethod + def read_from_stream(stream: StreamType, pdf: Any) -> "NameObject": # PdfReader + name = stream.read(1) + if name != NameObject.surfix: + raise PdfReadError("Name read error") + name += read_until_regex(stream, NameObject.delimiter_pattern) + try: + # Name objects should represent irregular characters + # with a '#' followed by the symbol's hex number + name = NameObject.unnumber(name) + for enc in NameObject.CHARSETS: + try: + ret = name.decode(enc) + return NameObject(ret) + except Exception: + pass + raise UnicodeDecodeError("", name, 0, 0, "Code Not Found") + except (UnicodeEncodeError, UnicodeDecodeError) as e: + if not pdf.strict: + logger_warning( + f"Illegal character in NameObject ({name!r}), " + "you may need to adjust NameObject.CHARSETS", + __name__, + ) + return NameObject(name.decode("charmap")) + else: + raise PdfReadError( + f"Illegal character in NameObject ({name!r}). " + "You may need to adjust NameObject.CHARSETS.", + ) from e + + +def encode_pdfdocencoding(unicode_string: str) -> bytes: + try: + return bytes([_pdfdoc_encoding_rev[k] for k in unicode_string]) + except KeyError: + raise UnicodeEncodeError( + "pdfdocencoding", + unicode_string, + -1, + -1, + "does not exist in translation table", + ) + + +def is_null_or_none(x: Any) -> TypeGuard[Union[None, NullObject, IndirectObject]]: + """ + Returns: + True if x is None or NullObject. + + """ + return x is None or ( + isinstance(x, PdfObject) + and (x.get_object() is None or isinstance(x.get_object(), NullObject)) + ) diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/_data_structures.py b/venv/lib/python3.12/site-packages/pypdf/generic/_data_structures.py new file mode 100644 index 0000000..bb14ec3 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/generic/_data_structures.py @@ -0,0 +1,1781 @@ +# Copyright (c) 2006, Mathieu Fenniak +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + + +__author__ = "Mathieu Fenniak" +__author_email__ = "biziqe@mathieu.fenniak.net" + +import logging +import re +import sys +from io import BytesIO +from math import ceil +from typing import ( + Any, + Callable, + Dict, + Iterable, + List, + Optional, + Sequence, + Set, + Tuple, + Union, + cast, +) + +from .._protocols import PdfReaderProtocol, PdfWriterProtocol, XmpInformationProtocol +from .._utils import ( + WHITESPACES, + StreamType, + deprecation_no_replacement, + deprecation_with_replacement, + logger_warning, + read_non_whitespace, + read_until_regex, + read_until_whitespace, + skip_over_comment, +) +from ..constants import ( + CheckboxRadioButtonAttributes, + FieldDictionaryAttributes, + OutlineFontFlag, +) +from ..constants import FilterTypes as FT +from ..constants import StreamAttributes as SA +from ..constants import TypArguments as TA +from ..constants import TypFitArguments as TF +from ..errors import STREAM_TRUNCATED_PREMATURELY, PdfReadError, PdfStreamError +from ._base import ( + BooleanObject, + ByteStringObject, + FloatObject, + IndirectObject, + NameObject, + NullObject, + NumberObject, + PdfObject, + TextStringObject, + is_null_or_none, +) +from ._fit import Fit +from ._image_inline import ( + extract_inline_A85, + extract_inline_AHx, + extract_inline_DCT, + extract_inline_default, + extract_inline_RL, +) +from ._utils import read_hex_string_from_stream, read_string_from_stream + +if sys.version_info >= (3, 11): + from typing import Self +else: + from typing_extensions import Self + +logger = logging.getLogger(__name__) +NumberSigns = b"+-" +IndirectPattern = re.compile(rb"[+-]?(\d+)\s+(\d+)\s+R[^a-zA-Z]") + + +class ArrayObject(List[Any], PdfObject): + def replicate( + self, + pdf_dest: PdfWriterProtocol, + ) -> "ArrayObject": + arr = cast( + "ArrayObject", + self._reference_clone(ArrayObject(), pdf_dest, False), + ) + for data in self: + if hasattr(data, "replicate"): + arr.append(data.replicate(pdf_dest)) + else: + arr.append(data) + return arr + + def clone( + self, + pdf_dest: PdfWriterProtocol, + force_duplicate: bool = False, + ignore_fields: Optional[Sequence[Union[str, int]]] = (), + ) -> "ArrayObject": + """Clone object into pdf_dest.""" + try: + if self.indirect_reference.pdf == pdf_dest and not force_duplicate: # type: ignore + return self + except Exception: + pass + arr = cast( + "ArrayObject", + self._reference_clone(ArrayObject(), pdf_dest, force_duplicate), + ) + for data in self: + if isinstance(data, StreamObject): + dup = data._reference_clone( + data.clone(pdf_dest, force_duplicate, ignore_fields), + pdf_dest, + force_duplicate, + ) + arr.append(dup.indirect_reference) + elif hasattr(data, "clone"): + arr.append(data.clone(pdf_dest, force_duplicate, ignore_fields)) + else: + arr.append(data) + return arr + + def hash_bin(self) -> int: + """ + Used to detect modified object. + + Returns: + Hash considering type and value. + + """ + return hash((self.__class__, tuple(x.hash_bin() for x in self))) + + def items(self) -> Iterable[Any]: + """Emulate DictionaryObject.items for a list (index, object).""" + return enumerate(self) + + def _to_lst(self, lst: Any) -> List[Any]: + # Convert to list, internal + if isinstance(lst, (list, tuple, set)): + pass + elif isinstance(lst, PdfObject): + lst = [lst] + elif isinstance(lst, str): + if lst[0] == "/": + lst = [NameObject(lst)] + else: + lst = [TextStringObject(lst)] + elif isinstance(lst, bytes): + lst = [ByteStringObject(lst)] + else: # for numbers,... + lst = [lst] + return lst + + def __add__(self, lst: Any) -> "ArrayObject": + """ + Allow extension by adding list or add one element only + + Args: + lst: any list, tuples are extended the list. + other types(numbers,...) will be appended. + if str is passed it will be converted into TextStringObject + or NameObject (if starting with "/") + if bytes is passed it will be converted into ByteStringObject + + Returns: + ArrayObject with all elements + + """ + temp = ArrayObject(self) + temp.extend(self._to_lst(lst)) + return temp + + def __iadd__(self, lst: Any) -> Self: + """ + Allow extension by adding list or add one element only + + Args: + lst: any list, tuples are extended the list. + other types(numbers,...) will be appended. + if str is passed it will be converted into TextStringObject + or NameObject (if starting with "/") + if bytes is passed it will be converted into ByteStringObject + + """ + self.extend(self._to_lst(lst)) + return self + + def __isub__(self, lst: Any) -> Self: + """Allow to remove items""" + for x in self._to_lst(lst): + try: + x = self.index(x) + del self[x] + except ValueError: + pass + return self + + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + if encryption_key is not None: # deprecated + deprecation_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) + stream.write(b"[") + for data in self: + stream.write(b" ") + data.write_to_stream(stream) + stream.write(b" ]") + + @staticmethod + def read_from_stream( + stream: StreamType, + pdf: Optional[PdfReaderProtocol], + forced_encoding: Union[None, str, List[str], Dict[int, str]] = None, + ) -> "ArrayObject": + arr = ArrayObject() + tmp = stream.read(1) + if tmp != b"[": + raise PdfReadError("Could not read array") + while True: + # skip leading whitespace + tok = stream.read(1) + while tok.isspace(): + tok = stream.read(1) + if tok == b"": + break + if tok == b"%": + stream.seek(-1, 1) + skip_over_comment(stream) + continue + stream.seek(-1, 1) + # check for array ending + peek_ahead = stream.read(1) + if peek_ahead == b"]": + break + stream.seek(-1, 1) + # read and append obj + arr.append(read_object(stream, pdf, forced_encoding)) + return arr + + +class DictionaryObject(Dict[Any, Any], PdfObject): + def replicate( + self, + pdf_dest: PdfWriterProtocol, + ) -> "DictionaryObject": + d__ = cast( + "DictionaryObject", + self._reference_clone(self.__class__(), pdf_dest, False), + ) + for k, v in self.items(): + d__[k.replicate(pdf_dest)] = ( + v.replicate(pdf_dest) if hasattr(v, "replicate") else v + ) + return d__ + + def clone( + self, + pdf_dest: PdfWriterProtocol, + force_duplicate: bool = False, + ignore_fields: Optional[Sequence[Union[str, int]]] = (), + ) -> "DictionaryObject": + """Clone object into pdf_dest.""" + try: + if self.indirect_reference.pdf == pdf_dest and not force_duplicate: # type: ignore + return self + except Exception: + pass + + visited: Set[Tuple[int, int]] = set() # (idnum, generation) + d__ = cast( + "DictionaryObject", + self._reference_clone(self.__class__(), pdf_dest, force_duplicate), + ) + if ignore_fields is None: + ignore_fields = [] + if len(d__.keys()) == 0: + d__._clone(self, pdf_dest, force_duplicate, ignore_fields, visited) + return d__ + + def _clone( + self, + src: "DictionaryObject", + pdf_dest: PdfWriterProtocol, + force_duplicate: bool, + ignore_fields: Optional[Sequence[Union[str, int]]], + visited: Set[Tuple[int, int]], # (idnum, generation) + ) -> None: + """ + Update the object from src. + + Args: + src: "DictionaryObject": + pdf_dest: + force_duplicate: + ignore_fields: + + """ + # first we remove for the ignore_fields + # that are for a limited number of levels + x = 0 + assert ignore_fields is not None + ignore_fields = list(ignore_fields) + while x < len(ignore_fields): + if isinstance(ignore_fields[x], int): + if cast(int, ignore_fields[x]) <= 0: + del ignore_fields[x] + del ignore_fields[x] + continue + ignore_fields[x] -= 1 # type:ignore + x += 1 + # First check if this is a chain list, we need to loop to prevent recur + if any( + field not in ignore_fields + and field in src + and isinstance(src.raw_get(field), IndirectObject) + and isinstance(src[field], DictionaryObject) + and ( + src.get("/Type", None) is None + or cast(DictionaryObject, src[field]).get("/Type", None) is None + or src.get("/Type", None) + == cast(DictionaryObject, src[field]).get("/Type", None) + ) + for field in ["/Next", "/Prev", "/N", "/V"] + ): + ignore_fields = list(ignore_fields) + for lst in (("/Next", "/Prev"), ("/N", "/V")): + for k in lst: + objs = [] + if ( + k in src + and k not in self + and isinstance(src.raw_get(k), IndirectObject) + and isinstance(src[k], DictionaryObject) + # IF need to go further the idea is to check + # that the types are the same: + and ( + src.get("/Type", None) is None + or cast(DictionaryObject, src[k]).get("/Type", None) is None + or src.get("/Type", None) + == cast(DictionaryObject, src[k]).get("/Type", None) + ) + ): + cur_obj: Optional[DictionaryObject] = cast( + "DictionaryObject", src[k] + ) + prev_obj: Optional[DictionaryObject] = self + while cur_obj is not None: + clon = cast( + "DictionaryObject", + cur_obj._reference_clone( + cur_obj.__class__(), pdf_dest, force_duplicate + ), + ) + # check to see if we've previously processed our item + if clon.indirect_reference is not None: + idnum = clon.indirect_reference.idnum + generation = clon.indirect_reference.generation + if (idnum, generation) in visited: + cur_obj = None + break + visited.add((idnum, generation)) + objs.append((cur_obj, clon)) + assert prev_obj is not None + prev_obj[NameObject(k)] = clon.indirect_reference + prev_obj = clon + try: + if cur_obj == src: + cur_obj = None + else: + cur_obj = cast("DictionaryObject", cur_obj[k]) + except Exception: + cur_obj = None + for s, c in objs: + c._clone( + s, pdf_dest, force_duplicate, ignore_fields, visited + ) + + for k, v in src.items(): + if k not in ignore_fields: + if isinstance(v, StreamObject): + if not hasattr(v, "indirect_reference"): + v.indirect_reference = None + vv = v.clone(pdf_dest, force_duplicate, ignore_fields) + assert vv.indirect_reference is not None + self[k.clone(pdf_dest)] = vv.indirect_reference # type: ignore[attr-defined] + elif k not in self: + self[NameObject(k)] = ( + v.clone(pdf_dest, force_duplicate, ignore_fields) + if hasattr(v, "clone") + else v + ) + + def hash_bin(self) -> int: + """ + Used to detect modified object. + + Returns: + Hash considering type and value. + + """ + return hash( + (self.__class__, tuple(((k, v.hash_bin()) for k, v in self.items()))) + ) + + def raw_get(self, key: Any) -> Any: + return dict.__getitem__(self, key) + + def get_inherited(self, key: str, default: Any = None) -> Any: + """ + Returns the value of a key or from the parent if not found. + If not found returns default. + + Args: + key: string identifying the field to return + + default: default value to return + + Returns: + Current key or inherited one, otherwise default value. + + """ + if key in self: + return self[key] + try: + if "/Parent" not in self: + return default + raise KeyError("Not present") + except KeyError: + return cast("DictionaryObject", self["/Parent"].get_object()).get_inherited( + key, default + ) + + def __setitem__(self, key: Any, value: Any) -> Any: + if not isinstance(key, PdfObject): + raise ValueError("Key must be a PdfObject") + if not isinstance(value, PdfObject): + raise ValueError("Value must be a PdfObject") + return dict.__setitem__(self, key, value) + + def setdefault(self, key: Any, value: Optional[Any] = None) -> Any: + if not isinstance(key, PdfObject): + raise ValueError("Key must be a PdfObject") + if not isinstance(value, PdfObject): + raise ValueError("Value must be a PdfObject") + return dict.setdefault(self, key, value) # type: ignore + + def __getitem__(self, key: Any) -> PdfObject: + return dict.__getitem__(self, key).get_object() + + @property + def xmp_metadata(self) -> Optional[XmpInformationProtocol]: + """ + Retrieve XMP (Extensible Metadata Platform) data relevant to the this + object, if available. + + See Table 347 — Additional entries in a metadata stream dictionary. + + Returns: + Returns a :class:`~pypdf.xmp.XmpInformation` instance + that can be used to access XMP metadata from the document. Can also + return None if no metadata was found on the document root. + + """ + from ..xmp import XmpInformation + + metadata = self.get("/Metadata", None) + if is_null_or_none(metadata): + return None + metadata = metadata.get_object() + + if not isinstance(metadata, XmpInformation): + metadata = XmpInformation(metadata) + self[NameObject("/Metadata")] = metadata + return metadata + + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + if encryption_key is not None: # deprecated + deprecation_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) + stream.write(b"<<\n") + for key, value in list(self.items()): + if len(key) > 2 and key[1] == "%" and key[-1] == "%": + continue + key.write_to_stream(stream, encryption_key) + stream.write(b" ") + value.write_to_stream(stream) + stream.write(b"\n") + stream.write(b">>") + + @staticmethod + def read_from_stream( + stream: StreamType, + pdf: Optional[PdfReaderProtocol], + forced_encoding: Union[None, str, List[str], Dict[int, str]] = None, + ) -> "DictionaryObject": + def get_next_obj_pos( + p: int, p1: int, rem_gens: List[int], pdf: PdfReaderProtocol + ) -> int: + out = p1 + for gen in rem_gens: + loc = pdf.xref[gen] + try: + values = [x for x in loc.values() if p < x <= p1] + if values: + out = min(out, *values) + except ValueError: + pass + return out + + def read_unsized_from_stream( + stream: StreamType, pdf: PdfReaderProtocol + ) -> bytes: + # we are just pointing at beginning of the stream + eon = get_next_obj_pos(stream.tell(), 2**32, list(pdf.xref), pdf) - 1 + curr = stream.tell() + rw = stream.read(eon - stream.tell()) + p = rw.find(b"endstream") + if p < 0: + raise PdfReadError( + f"Unable to find 'endstream' marker for obj starting at {curr}." + ) + stream.seek(curr + p + 9) + return rw[: p - 1] + + tmp = stream.read(2) + if tmp != b"<<": + raise PdfReadError( + f"Dictionary read error at byte {hex(stream.tell())}: " + "stream must begin with '<<'" + ) + data: Dict[Any, Any] = {} + while True: + tok = read_non_whitespace(stream) + if tok == b"\x00": + continue + if tok == b"%": + stream.seek(-1, 1) + skip_over_comment(stream) + continue + if not tok: + raise PdfStreamError(STREAM_TRUNCATED_PREMATURELY) + + if tok == b">": + stream.read(1) + break + stream.seek(-1, 1) + try: + try: + key = read_object(stream, pdf) + if isinstance(key, NullObject): + break + if not isinstance(key, NameObject): + raise PdfReadError( + f"Expecting a NameObject for key but found {key!r}" + ) + except PdfReadError as exc: + if pdf is not None and pdf.strict: + raise + logger_warning(exc.__repr__(), __name__) + continue + tok = read_non_whitespace(stream) + stream.seek(-1, 1) + value = read_object(stream, pdf, forced_encoding) + except Exception as exc: + if pdf is not None and pdf.strict: + raise PdfReadError(exc.__repr__()) + logger_warning(exc.__repr__(), __name__) + retval = DictionaryObject() + retval.update(data) + return retval # return partial data + + if not data.get(key): + data[key] = value + else: + # multiple definitions of key not permitted + msg = ( + f"Multiple definitions in dictionary at byte " + f"{hex(stream.tell())} for key {key}" + ) + if pdf is not None and pdf.strict: + raise PdfReadError(msg) + logger_warning(msg, __name__) + + pos = stream.tell() + s = read_non_whitespace(stream) + if s == b"s" and stream.read(5) == b"tream": + eol = stream.read(1) + # odd PDF file output has spaces after 'stream' keyword but before EOL. + # patch provided by Danial Sandler + while eol == b" ": + eol = stream.read(1) + if eol not in (b"\n", b"\r"): + raise PdfStreamError("Stream data must be followed by a newline") + if eol == b"\r" and stream.read(1) != b"\n": + stream.seek(-1, 1) + # this is a stream object, not a dictionary + if SA.LENGTH not in data: + if pdf is not None and pdf.strict: + raise PdfStreamError("Stream length not defined") + else: + logger_warning( + f"Stream length not defined @pos={stream.tell()}", __name__ + ) + data[NameObject(SA.LENGTH)] = NumberObject(-1) + length = data[SA.LENGTH] + if isinstance(length, IndirectObject): + t = stream.tell() + assert pdf is not None # hint for mypy + length = pdf.get_object(length) + stream.seek(t, 0) + if length is None: # if the PDF is damaged + length = -1 + pstart = stream.tell() + if length > 0: + data["__streamdata__"] = stream.read(length) + else: + data["__streamdata__"] = read_until_regex( + stream, re.compile(b"endstream") + ) + e = read_non_whitespace(stream) + ndstream = stream.read(8) + if (e + ndstream) != b"endstream": + # (sigh) - the odd PDF file has a length that is too long, so + # we need to read backwards to find the "endstream" ending. + # ReportLab (unknown version) generates files with this bug, + # and Python users into PDF files tend to be our audience. + # we need to do this to correct the streamdata and chop off + # an extra character. + pos = stream.tell() + stream.seek(-10, 1) + end = stream.read(9) + if end == b"endstream": + # we found it by looking back one character further. + data["__streamdata__"] = data["__streamdata__"][:-1] + elif pdf is not None and not pdf.strict: + stream.seek(pstart, 0) + data["__streamdata__"] = read_unsized_from_stream(stream, pdf) + pos = stream.tell() + else: + stream.seek(pos, 0) + raise PdfReadError( + "Unable to find 'endstream' marker after stream at byte " + f"{hex(stream.tell())} (nd='{ndstream!r}', end='{end!r}')." + ) + else: + stream.seek(pos, 0) + if "__streamdata__" in data: + return StreamObject.initialize_from_dictionary(data) + else: + retval = DictionaryObject() + retval.update(data) + return retval + + +class TreeObject(DictionaryObject): + def __init__(self, dct: Optional[DictionaryObject] = None) -> None: + DictionaryObject.__init__(self) + if dct: + self.update(dct) + + def has_children(self) -> bool: + return "/First" in self + + def __iter__(self) -> Any: + return self.children() + + def children(self) -> Iterable[Any]: + if not self.has_children(): + return + + child_ref = self[NameObject("/First")] + child = child_ref.get_object() + while True: + yield child + if child == self[NameObject("/Last")]: + return + child_ref = child.get(NameObject("/Next")) # type: ignore + if is_null_or_none(child_ref): + return + child = child_ref.get_object() + + def add_child(self, child: Any, pdf: PdfWriterProtocol) -> None: + self.insert_child(child, None, pdf) + + def inc_parent_counter_default( + self, parent: Union[None, IndirectObject, "TreeObject"], n: int + ) -> None: + if is_null_or_none(parent): + return + assert parent is not None, "mypy" + parent = cast("TreeObject", parent.get_object()) + if "/Count" in parent: + parent[NameObject("/Count")] = NumberObject( + max(0, cast(int, parent[NameObject("/Count")]) + n) + ) + self.inc_parent_counter_default(parent.get("/Parent", None), n) + + def inc_parent_counter_outline( + self, parent: Union[None, IndirectObject, "TreeObject"], n: int + ) -> None: + if is_null_or_none(parent): + return + assert parent is not None, "mypy" + parent = cast("TreeObject", parent.get_object()) + # BooleanObject requires comparison with == not is + opn = parent.get("/%is_open%", True) == True # noqa: E712 + c = cast(int, parent.get("/Count", 0)) + if c < 0: + c = abs(c) + parent[NameObject("/Count")] = NumberObject((c + n) * (1 if opn else -1)) + if not opn: + return + self.inc_parent_counter_outline(parent.get("/Parent", None), n) + + def insert_child( + self, + child: Any, + before: Any, + pdf: PdfWriterProtocol, + inc_parent_counter: Optional[Callable[..., Any]] = None, + ) -> IndirectObject: + if inc_parent_counter is None: + inc_parent_counter = self.inc_parent_counter_default + child_obj = child.get_object() + child = child.indirect_reference # get_reference(child_obj) + + prev: Optional[DictionaryObject] + if "/First" not in self: # no child yet + self[NameObject("/First")] = child + self[NameObject("/Count")] = NumberObject(0) + self[NameObject("/Last")] = child + child_obj[NameObject("/Parent")] = self.indirect_reference + inc_parent_counter(self, child_obj.get("/Count", 1)) + if "/Next" in child_obj: + del child_obj["/Next"] + if "/Prev" in child_obj: + del child_obj["/Prev"] + return child + else: + prev = cast("DictionaryObject", self["/Last"]) + + while prev.indirect_reference != before: + if "/Next" in prev: + prev = cast("TreeObject", prev["/Next"]) + else: # append at the end + prev[NameObject("/Next")] = cast("TreeObject", child) + child_obj[NameObject("/Prev")] = prev.indirect_reference + child_obj[NameObject("/Parent")] = self.indirect_reference + if "/Next" in child_obj: + del child_obj["/Next"] + self[NameObject("/Last")] = child + inc_parent_counter(self, child_obj.get("/Count", 1)) + return child + try: # insert as first or in the middle + assert isinstance(prev["/Prev"], DictionaryObject) + prev["/Prev"][NameObject("/Next")] = child + child_obj[NameObject("/Prev")] = prev["/Prev"] + except Exception: # it means we are inserting in first position + del child_obj["/Next"] + child_obj[NameObject("/Next")] = prev + prev[NameObject("/Prev")] = child + child_obj[NameObject("/Parent")] = self.indirect_reference + inc_parent_counter(self, child_obj.get("/Count", 1)) + return child + + def _remove_node_from_tree( + self, prev: Any, prev_ref: Any, cur: Any, last: Any + ) -> None: + """ + Adjust the pointers of the linked list and tree node count. + + Args: + prev: + prev_ref: + cur: + last: + + """ + next_ref = cur.get(NameObject("/Next"), None) + if prev is None: + if next_ref: + # Removing first tree node + next_obj = next_ref.get_object() + del next_obj[NameObject("/Prev")] + self[NameObject("/First")] = next_ref + self[NameObject("/Count")] = NumberObject( + self[NameObject("/Count")] - 1 # type: ignore + ) + + else: + # Removing only tree node + self[NameObject("/Count")] = NumberObject(0) + del self[NameObject("/First")] + if NameObject("/Last") in self: + del self[NameObject("/Last")] + else: + if next_ref: + # Removing middle tree node + next_obj = next_ref.get_object() + next_obj[NameObject("/Prev")] = prev_ref + prev[NameObject("/Next")] = next_ref + else: + # Removing last tree node + assert cur == last + del prev[NameObject("/Next")] + self[NameObject("/Last")] = prev_ref + self[NameObject("/Count")] = NumberObject(self[NameObject("/Count")] - 1) # type: ignore + + def remove_child(self, child: Any) -> None: + child_obj = child.get_object() + child = child_obj.indirect_reference + + if NameObject("/Parent") not in child_obj: + raise ValueError("Removed child does not appear to be a tree item") + elif child_obj[NameObject("/Parent")] != self: + raise ValueError("Removed child is not a member of this tree") + + found = False + prev_ref = None + prev = None + cur_ref: Optional[Any] = self[NameObject("/First")] + cur: Optional[Dict[str, Any]] = cur_ref.get_object() # type: ignore + last_ref = self[NameObject("/Last")] + last = last_ref.get_object() + while cur is not None: + if cur == child_obj: + self._remove_node_from_tree(prev, prev_ref, cur, last) + found = True + break + + # Go to the next node + prev_ref = cur_ref + prev = cur + if NameObject("/Next") in cur: + cur_ref = cur[NameObject("/Next")] + cur = cur_ref.get_object() + else: + cur_ref = None + cur = None + + if not found: + raise ValueError("Removal couldn't find item in tree") + + _reset_node_tree_relationship(child_obj) + + def remove_from_tree(self) -> None: + """Remove the object from the tree it is in.""" + if NameObject("/Parent") not in self: + raise ValueError("Removed child does not appear to be a tree item") + else: + cast("TreeObject", self["/Parent"]).remove_child(self) + + def empty_tree(self) -> None: + for child in self: + child_obj = child.get_object() + _reset_node_tree_relationship(child_obj) + + if NameObject("/Count") in self: + del self[NameObject("/Count")] + if NameObject("/First") in self: + del self[NameObject("/First")] + if NameObject("/Last") in self: + del self[NameObject("/Last")] + + +def _reset_node_tree_relationship(child_obj: Any) -> None: + """ + Call this after a node has been removed from a tree. + + This resets the nodes attributes in respect to that tree. + + Args: + child_obj: + + """ + del child_obj[NameObject("/Parent")] + if NameObject("/Next") in child_obj: + del child_obj[NameObject("/Next")] + if NameObject("/Prev") in child_obj: + del child_obj[NameObject("/Prev")] + + +class StreamObject(DictionaryObject): + def __init__(self) -> None: + self._data: bytes = b"" + self.decoded_self: Optional[DecodedStreamObject] = None + + def replicate( + self, + pdf_dest: PdfWriterProtocol, + ) -> "StreamObject": + d__ = cast( + "StreamObject", + self._reference_clone(self.__class__(), pdf_dest, False), + ) + d__._data = self._data + try: + decoded_self = self.decoded_self + if decoded_self is None: + self.decoded_self = None + else: + self.decoded_self = cast( + "DecodedStreamObject", decoded_self.replicate(pdf_dest) + ) + except Exception: + pass + for k, v in self.items(): + d__[k.replicate(pdf_dest)] = ( + v.replicate(pdf_dest) if hasattr(v, "replicate") else v + ) + return d__ + + def _clone( + self, + src: DictionaryObject, + pdf_dest: PdfWriterProtocol, + force_duplicate: bool, + ignore_fields: Optional[Sequence[Union[str, int]]], + visited: Set[Tuple[int, int]], + ) -> None: + """ + Update the object from src. + + Args: + src: + pdf_dest: + force_duplicate: + ignore_fields: + + """ + self._data = cast("StreamObject", src)._data + try: + decoded_self = cast("StreamObject", src).decoded_self + if decoded_self is None: + self.decoded_self = None + else: + self.decoded_self = cast( + "DecodedStreamObject", + decoded_self.clone(pdf_dest, force_duplicate, ignore_fields), + ) + except Exception: + pass + super()._clone(src, pdf_dest, force_duplicate, ignore_fields, visited) + + def hash_bin(self) -> int: + """ + Used to detect modified object. + + Returns: + Hash considering type and value. + + """ + # use of _data to prevent errors on non decoded stream such as JBIG2 + return hash((super().hash_bin(), self._data)) + + def get_data(self) -> bytes: + return self._data + + def set_data(self, data: bytes) -> None: + self._data = data + + def hash_value_data(self) -> bytes: + data = super().hash_value_data() + data += self._data + return data + + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + if encryption_key is not None: # deprecated + deprecation_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) + self[NameObject(SA.LENGTH)] = NumberObject(len(self._data)) + DictionaryObject.write_to_stream(self, stream) + del self[SA.LENGTH] + stream.write(b"\nstream\n") + stream.write(self._data) + stream.write(b"\nendstream") + + @staticmethod + def initializeFromDictionary(data: Dict[str, Any]) -> None: + deprecation_with_replacement( + "initializeFromDictionary", "initialize_from_dictionary", "5.0.0" + ) # pragma: no cover + + @staticmethod + def initialize_from_dictionary( + data: Dict[str, Any] + ) -> Union["EncodedStreamObject", "DecodedStreamObject"]: + retval: Union[EncodedStreamObject, DecodedStreamObject] + if SA.FILTER in data: + retval = EncodedStreamObject() + else: + retval = DecodedStreamObject() + retval._data = data["__streamdata__"] + del data["__streamdata__"] + if SA.LENGTH in data: + del data[SA.LENGTH] + retval.update(data) + return retval + + def flate_encode(self, level: int = -1) -> "EncodedStreamObject": + from ..filters import FlateDecode + + if SA.FILTER in self: + f = self[SA.FILTER] + if isinstance(f, ArrayObject): + f = ArrayObject([NameObject(FT.FLATE_DECODE), *f]) + try: + params = ArrayObject( + [NullObject(), *self.get(SA.DECODE_PARMS, ArrayObject())] + ) + except TypeError: + # case of error where the * operator is not working (not an array + params = ArrayObject( + [NullObject(), self.get(SA.DECODE_PARMS, ArrayObject())] + ) + else: + f = ArrayObject([NameObject(FT.FLATE_DECODE), f]) + params = ArrayObject( + [NullObject(), self.get(SA.DECODE_PARMS, NullObject())] + ) + else: + f = NameObject(FT.FLATE_DECODE) + params = None + retval = EncodedStreamObject() + retval.update(self) + retval[NameObject(SA.FILTER)] = f + if params is not None: + retval[NameObject(SA.DECODE_PARMS)] = params + retval._data = FlateDecode.encode(self._data, level) + return retval + + def decode_as_image(self) -> Any: + """ + Try to decode the stream object as an image + + Returns: + a PIL image if proper decoding has been found + Raises: + Exception: (any)during decoding to to invalid object or + errors during decoding will be reported + It is recommended to catch exceptions to prevent + stops in your program. + + """ + from ..filters import _xobj_to_image + + if self.get("/Subtype", "") != "/Image": + try: + msg = f"{self.indirect_reference} does not seem to be an Image" # pragma: no cover + except AttributeError: + msg = f"{self.__repr__()} object does not seem to be an Image" # pragma: no cover + logger_warning(msg, __name__) + extension, byte_stream, img = _xobj_to_image(self) + if extension is None: + return None # pragma: no cover + return img + + +class DecodedStreamObject(StreamObject): + pass + + +class EncodedStreamObject(StreamObject): + def __init__(self) -> None: + self.decoded_self: Optional[DecodedStreamObject] = None + + # This overrides the parent method: + def get_data(self) -> bytes: + from ..filters import decode_stream_data + + if self.decoded_self is not None: + # cached version of decoded object + return self.decoded_self.get_data() + else: + # create decoded object + decoded = DecodedStreamObject() + + decoded.set_data(decode_stream_data(self)) + for key, value in list(self.items()): + if key not in (SA.LENGTH, SA.FILTER, SA.DECODE_PARMS): + decoded[key] = value + self.decoded_self = decoded + return decoded.get_data() + + # This overrides the parent method: + def set_data(self, data: bytes) -> None: + from ..filters import FlateDecode + + if self.get(SA.FILTER, "") in (FT.FLATE_DECODE, [FT.FLATE_DECODE]): + if not isinstance(data, bytes): + raise TypeError("Data must be bytes") + if self.decoded_self is None: + self.get_data() # to create self.decoded_self + assert self.decoded_self is not None, "mypy" + self.decoded_self.set_data(data) + super().set_data(FlateDecode.encode(data)) + else: + raise PdfReadError( + "Streams encoded with a filter different from FlateDecode are not supported" + ) + + +class ContentStream(DecodedStreamObject): + """ + In order to be fast, this data structure can contain either: + + * raw data in ._data + * parsed stream operations in ._operations. + + At any time, ContentStream object can either have both of those fields defined, + or one field defined and the other set to None. + + These fields are "rebuilt" lazily, when accessed: + + * when .get_data() is called, if ._data is None, it is rebuilt from ._operations. + * when .operations is called, if ._operations is None, it is rebuilt from ._data. + + Conversely, these fields can be invalidated: + + * when .set_data() is called, ._operations is set to None. + * when .operations is set, ._data is set to None. + """ + + def __init__( + self, + stream: Any, + pdf: Any, + forced_encoding: Union[None, str, List[str], Dict[int, str]] = None, + ) -> None: + self.pdf = pdf + + # The inner list has two elements: + # Element 0: List + # Element 1: str + self._operations: List[Tuple[Any, bytes]] = [] + + # stream may be a StreamObject or an ArrayObject containing + # multiple StreamObjects to be cat'd together. + if stream is None: + super().set_data(b"") + else: + stream = stream.get_object() + if isinstance(stream, ArrayObject): + data = b"" + for s in stream: + s_resolved = s.get_object() + if isinstance(s_resolved, NullObject): + continue + if not isinstance(s_resolved, StreamObject): + # No need to emit an exception here for now - the PDF structure + # seems to already be broken beforehand in these cases. + logger_warning( + f"Expected StreamObject, got {type(s_resolved).__name__} instead. Data might be wrong.", + __name__ + ) + else: + data += s_resolved.get_data() + if len(data) == 0 or data[-1] != b"\n": + data += b"\n" + super().set_data(bytes(data)) + else: + stream_data = stream.get_data() + assert stream_data is not None + super().set_data(stream_data) + self.forced_encoding = forced_encoding + + def replicate( + self, + pdf_dest: PdfWriterProtocol, + ) -> "ContentStream": + d__ = cast( + "ContentStream", + self._reference_clone(self.__class__(None, None), pdf_dest, False), + ) + d__._data = self._data + try: + decoded_self = self.decoded_self + if decoded_self is None: + self.decoded_self = None + else: + self.decoded_self = cast( + "DecodedStreamObject", decoded_self.replicate(pdf_dest) + ) + except Exception: + pass + for k, v in self.items(): + d__[k.replicate(pdf_dest)] = ( + v.replicate(pdf_dest) if hasattr(v, "replicate") else v + ) + return d__ + d__.set_data(self._data) + d__.pdf = pdf_dest + d__._operations = list(self._operations) + d__.forced_encoding = self.forced_encoding + return d__ + + def clone( + self, + pdf_dest: Any, + force_duplicate: bool = False, + ignore_fields: Optional[Sequence[Union[str, int]]] = (), + ) -> "ContentStream": + """ + Clone object into pdf_dest. + + Args: + pdf_dest: + force_duplicate: + ignore_fields: + + Returns: + The cloned ContentStream + + """ + try: + if self.indirect_reference.pdf == pdf_dest and not force_duplicate: # type: ignore + return self + except Exception: + pass + + visited: Set[Tuple[int, int]] = set() + d__ = cast( + "ContentStream", + self._reference_clone( + self.__class__(None, None), pdf_dest, force_duplicate + ), + ) + if ignore_fields is None: + ignore_fields = [] + d__._clone(self, pdf_dest, force_duplicate, ignore_fields, visited) + return d__ + + def _clone( + self, + src: DictionaryObject, + pdf_dest: PdfWriterProtocol, + force_duplicate: bool, + ignore_fields: Optional[Sequence[Union[str, int]]], + visited: Set[Tuple[int, int]], + ) -> None: + """ + Update the object from src. + + Args: + src: + pdf_dest: + force_duplicate: + ignore_fields: + + """ + src_cs = cast("ContentStream", src) + super().set_data(src_cs._data) + self.pdf = pdf_dest + self._operations = list(src_cs._operations) + self.forced_encoding = src_cs.forced_encoding + # no need to call DictionaryObjection or anything + # like super(DictionaryObject,self)._clone(src, pdf_dest, force_duplicate, ignore_fields, visited) + + def _parse_content_stream(self, stream: StreamType) -> None: + # 7.8.2 Content Streams + stream.seek(0, 0) + operands: List[Union[int, str, PdfObject]] = [] + while True: + peek = read_non_whitespace(stream) + if peek in (b"", 0): + break + stream.seek(-1, 1) + if peek.isalpha() or peek in (b"'", b'"'): + operator = read_until_regex(stream, NameObject.delimiter_pattern) + if operator == b"BI": + # begin inline image - a completely different parsing + # mechanism is required, of course... thanks buddy... + assert operands == [] + ii = self._read_inline_image(stream) + self._operations.append((ii, b"INLINE IMAGE")) + else: + self._operations.append((operands, operator)) + operands = [] + elif peek == b"%": + # If we encounter a comment in the content stream, we have to + # handle it here. Typically, read_object will handle + # encountering a comment -- but read_object assumes that + # following the comment must be the object we're trying to + # read. In this case, it could be an operator instead. + while peek not in (b"\r", b"\n", b""): + peek = stream.read(1) + else: + operands.append(read_object(stream, None, self.forced_encoding)) + + def _read_inline_image(self, stream: StreamType) -> Dict[str, Any]: + # begin reading just after the "BI" - begin image + # first read the dictionary of settings. + settings = DictionaryObject() + while True: + tok = read_non_whitespace(stream) + stream.seek(-1, 1) + if tok == b"I": + # "ID" - begin of image data + break + key = read_object(stream, self.pdf) + tok = read_non_whitespace(stream) + stream.seek(-1, 1) + value = read_object(stream, self.pdf) + settings[key] = value + # left at beginning of ID + tmp = stream.read(3) + assert tmp[:2] == b"ID" + filtr = settings.get("/F", settings.get("/Filter", "not set")) + savpos = stream.tell() + if isinstance(filtr, list): + filtr = filtr[0] # used forencoding + if "AHx" in filtr or "ASCIIHexDecode" in filtr: + data = extract_inline_AHx(stream) + elif "A85" in filtr or "ASCII85Decode" in filtr: + data = extract_inline_A85(stream) + elif "RL" in filtr or "RunLengthDecode" in filtr: + data = extract_inline_RL(stream) + elif "DCT" in filtr or "DCTDecode" in filtr: + data = extract_inline_DCT(stream) + elif filtr == "not set": + cs = settings.get("/CS", "") + if isinstance(cs, list): + cs = cs[0] + if "RGB" in cs: + lcs = 3 + elif "CMYK" in cs: + lcs = 4 + else: + bits = settings.get( + "/BPC", + 8 if cs in {"/I", "/G", "/Indexed", "/DeviceGray"} else -1, + ) + if bits > 0: + lcs = bits / 8.0 + else: + data = extract_inline_default(stream) + lcs = -1 + if lcs > 0: + data = stream.read( + ceil(cast(int, settings["/W"]) * lcs) * cast(int, settings["/H"]) + ) + # Move to the `EI` if possible. + ei = read_non_whitespace(stream) + stream.seek(-1, 1) + else: + data = extract_inline_default(stream) + + ei = stream.read(3) + stream.seek(-1, 1) + if ei[0:2] != b"EI" or ei[2:3] not in WHITESPACES: + # Deal with wrong/missing `EI` tags. Example: Wrong dimensions specified above. + stream.seek(savpos, 0) + data = extract_inline_default(stream) + ei = stream.read(3) + stream.seek(-1, 1) + if ei[0:2] != b"EI" or ei[2:3] not in WHITESPACES: # pragma: no cover + # Check the same condition again. This should never fail as + # edge cases are covered by `extract_inline_default` above, + # but check this ot make sure that we are behind the `EI` afterwards. + raise PdfStreamError( + f"Could not extract inline image, even using fallback. Expected 'EI', got {ei!r}" + ) + return {"settings": settings, "data": data} + + # This overrides the parent method: + def get_data(self) -> bytes: + if not self._data: + new_data = BytesIO() + for operands, operator in self._operations: + if operator == b"INLINE IMAGE": + new_data.write(b"BI") + dict_text = BytesIO() + operands["settings"].write_to_stream(dict_text) + new_data.write(dict_text.getvalue()[2:-2]) + new_data.write(b"ID ") + new_data.write(operands["data"]) + new_data.write(b"EI") + else: + for op in operands: + op.write_to_stream(new_data) + new_data.write(b" ") + new_data.write(operator) + new_data.write(b"\n") + self._data = new_data.getvalue() + return self._data + + # This overrides the parent method: + def set_data(self, data: bytes) -> None: + super().set_data(data) + self._operations = [] + + @property + def operations(self) -> List[Tuple[Any, bytes]]: + if not self._operations and self._data: + self._parse_content_stream(BytesIO(self._data)) + self._data = b"" + return self._operations + + @operations.setter + def operations(self, operations: List[Tuple[Any, bytes]]) -> None: + self._operations = operations + self._data = b"" + + def isolate_graphics_state(self) -> None: + if self._operations: + self._operations.insert(0, ([], b"q")) + self._operations.append(([], b"Q")) + elif self._data: + self._data = b"q\n" + self._data + b"\nQ\n" + + # This overrides the parent method: + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + if not self._data and self._operations: + self.get_data() # this ensures ._data is rebuilt + super().write_to_stream(stream, encryption_key) + + +def read_object( + stream: StreamType, + pdf: Optional[PdfReaderProtocol], + forced_encoding: Union[None, str, List[str], Dict[int, str]] = None, +) -> Union[PdfObject, int, str, ContentStream]: + tok = stream.read(1) + stream.seek(-1, 1) # reset to start + if tok == b"/": + return NameObject.read_from_stream(stream, pdf) + elif tok == b"<": + # hexadecimal string OR dictionary + peek = stream.read(2) + stream.seek(-2, 1) # reset to start + if peek == b"<<": + return DictionaryObject.read_from_stream(stream, pdf, forced_encoding) + else: + return read_hex_string_from_stream(stream, forced_encoding) + elif tok == b"[": + return ArrayObject.read_from_stream(stream, pdf, forced_encoding) + elif tok in (b"t", b"f"): + return BooleanObject.read_from_stream(stream) + elif tok == b"(": + return read_string_from_stream(stream, forced_encoding) + elif tok == b"e" and stream.read(6) == b"endobj": + return NullObject() + elif tok == b"n": + return NullObject.read_from_stream(stream) + elif tok == b"%": + # comment + skip_over_comment(stream) + tok = read_non_whitespace(stream) + stream.seek(-1, 1) + return read_object(stream, pdf, forced_encoding) + elif tok in b"0123456789+-.": + # number object OR indirect reference + peek = stream.read(20) + stream.seek(-len(peek), 1) # reset to start + if IndirectPattern.match(peek) is not None: + assert pdf is not None # hint for mypy + return IndirectObject.read_from_stream(stream, pdf) + else: + return NumberObject.read_from_stream(stream) + else: + pos = stream.tell() + stream.seek(-20, 1) + stream_extract = stream.read(80) + stream.seek(pos) + read_until_whitespace(stream) + raise PdfReadError( + f"Invalid Elementary Object starting with {tok!r} @{pos}: {stream_extract!r}" + ) + + +class Field(TreeObject): + """ + A class representing a field dictionary. + + This class is accessed through + :meth:`get_fields()` + """ + + def __init__(self, data: DictionaryObject) -> None: + DictionaryObject.__init__(self) + field_attributes = ( + FieldDictionaryAttributes.attributes() + + CheckboxRadioButtonAttributes.attributes() + ) + self.indirect_reference = data.indirect_reference + for attr in field_attributes: + try: + self[NameObject(attr)] = data[attr] + except KeyError: + pass + if isinstance(self.get("/V"), EncodedStreamObject): + d = cast(EncodedStreamObject, self[NameObject("/V")]).get_data() + if isinstance(d, bytes): + d_str = d.decode() + elif d is None: + d_str = "" + else: + raise Exception("Should never happen") + self[NameObject("/V")] = TextStringObject(d_str) + + # TABLE 8.69 Entries common to all field dictionaries + @property + def field_type(self) -> Optional[NameObject]: + """Read-only property accessing the type of this field.""" + return self.get(FieldDictionaryAttributes.FT) + + @property + def parent(self) -> Optional[DictionaryObject]: + """Read-only property accessing the parent of this field.""" + return self.get(FieldDictionaryAttributes.Parent) + + @property + def kids(self) -> Optional["ArrayObject"]: + """Read-only property accessing the kids of this field.""" + return self.get(FieldDictionaryAttributes.Kids) + + @property + def name(self) -> Optional[str]: + """Read-only property accessing the name of this field.""" + return self.get(FieldDictionaryAttributes.T) + + @property + def alternate_name(self) -> Optional[str]: + """Read-only property accessing the alternate name of this field.""" + return self.get(FieldDictionaryAttributes.TU) + + @property + def mapping_name(self) -> Optional[str]: + """ + Read-only property accessing the mapping name of this field. + + This name is used by pypdf as a key in the dictionary returned by + :meth:`get_fields()` + """ + return self.get(FieldDictionaryAttributes.TM) + + @property + def flags(self) -> Optional[int]: + """ + Read-only property accessing the field flags, specifying various + characteristics of the field (see Table 8.70 of the PDF 1.7 reference). + """ + return self.get(FieldDictionaryAttributes.Ff) + + @property + def value(self) -> Optional[Any]: + """ + Read-only property accessing the value of this field. + + Format varies based on field type. + """ + return self.get(FieldDictionaryAttributes.V) + + @property + def default_value(self) -> Optional[Any]: + """Read-only property accessing the default value of this field.""" + return self.get(FieldDictionaryAttributes.DV) + + @property + def additional_actions(self) -> Optional[DictionaryObject]: + """ + Read-only property accessing the additional actions dictionary. + + This dictionary defines the field's behavior in response to trigger + events. See Section 8.5.2 of the PDF 1.7 reference. + """ + return self.get(FieldDictionaryAttributes.AA) + + +class Destination(TreeObject): + """ + A class representing a destination within a PDF file. + + See section 12.3.2 of the PDF 2.0 reference. + + Args: + title: Title of this destination. + page: Reference to the page of this destination. Should + be an instance of :class:`IndirectObject`. + fit: How the destination is displayed. + + Raises: + PdfReadError: If destination type is invalid. + + """ + + node: Optional[ + DictionaryObject + ] = None # node provide access to the original Object + + def __init__( + self, + title: str, + page: Union[NumberObject, IndirectObject, NullObject, DictionaryObject], + fit: Fit, + ) -> None: + self._filtered_children: List[Any] = [] # used in PdfWriter + + typ = fit.fit_type + args = fit.fit_args + + DictionaryObject.__init__(self) + self[NameObject("/Title")] = TextStringObject(title) + self[NameObject("/Page")] = page + self[NameObject("/Type")] = typ + + # from table 8.2 of the PDF 1.7 reference. + if typ == "/XYZ": + if len(args) < 1: # left is missing : should never occur + args.append(NumberObject(0.0)) + if len(args) < 2: # top is missing + args.append(NumberObject(0.0)) + if len(args) < 3: # zoom is missing + args.append(NumberObject(0.0)) + ( + self[NameObject(TA.LEFT)], + self[NameObject(TA.TOP)], + self[NameObject("/Zoom")], + ) = args + elif len(args) == 0: + pass + elif typ == TF.FIT_R: + ( + self[NameObject(TA.LEFT)], + self[NameObject(TA.BOTTOM)], + self[NameObject(TA.RIGHT)], + self[NameObject(TA.TOP)], + ) = args + elif typ in [TF.FIT_H, TF.FIT_BH]: + try: # Preferred to be more robust not only to null parameters + (self[NameObject(TA.TOP)],) = args + except Exception: + (self[NameObject(TA.TOP)],) = (NullObject(),) + elif typ in [TF.FIT_V, TF.FIT_BV]: + try: # Preferred to be more robust not only to null parameters + (self[NameObject(TA.LEFT)],) = args + except Exception: + (self[NameObject(TA.LEFT)],) = (NullObject(),) + elif typ in [TF.FIT, TF.FIT_B]: + pass + else: + raise PdfReadError(f"Unknown Destination Type: {typ!r}") + + @property + def dest_array(self) -> "ArrayObject": + return ArrayObject( + [self.raw_get("/Page"), self["/Type"]] + + [ + self[x] + for x in ["/Left", "/Bottom", "/Right", "/Top", "/Zoom"] + if x in self + ] + ) + + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + if encryption_key is not None: # deprecated + deprecation_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) + stream.write(b"<<\n") + key = NameObject("/D") + key.write_to_stream(stream) + stream.write(b" ") + value = self.dest_array + value.write_to_stream(stream) + + key = NameObject("/S") + key.write_to_stream(stream) + stream.write(b" ") + value_s = NameObject("/GoTo") + value_s.write_to_stream(stream) + + stream.write(b"\n") + stream.write(b">>") + + @property + def title(self) -> Optional[str]: + """Read-only property accessing the destination title.""" + return self.get("/Title") + + @property + def page(self) -> Optional[int]: + """Read-only property accessing the destination page number.""" + return self.get("/Page") + + @property + def typ(self) -> Optional[str]: + """Read-only property accessing the destination type.""" + return self.get("/Type") + + @property + def zoom(self) -> Optional[int]: + """Read-only property accessing the zoom factor.""" + return self.get("/Zoom", None) + + @property + def left(self) -> Optional[FloatObject]: + """Read-only property accessing the left horizontal coordinate.""" + return self.get("/Left", None) + + @property + def right(self) -> Optional[FloatObject]: + """Read-only property accessing the right horizontal coordinate.""" + return self.get("/Right", None) + + @property + def top(self) -> Optional[FloatObject]: + """Read-only property accessing the top vertical coordinate.""" + return self.get("/Top", None) + + @property + def bottom(self) -> Optional[FloatObject]: + """Read-only property accessing the bottom vertical coordinate.""" + return self.get("/Bottom", None) + + @property + def color(self) -> Optional["ArrayObject"]: + """Read-only property accessing the color in (R, G, B) with values 0.0-1.0.""" + return self.get( + "/C", ArrayObject([FloatObject(0), FloatObject(0), FloatObject(0)]) + ) + + @property + def font_format(self) -> Optional[OutlineFontFlag]: + """ + Read-only property accessing the font type. + + 1=italic, 2=bold, 3=both + """ + return self.get("/F", 0) + + @property + def outline_count(self) -> Optional[int]: + """ + Read-only property accessing the outline count. + + positive = expanded + negative = collapsed + absolute value = number of visible descendants at all levels + """ + return self.get("/Count", None) diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/_files.py b/venv/lib/python3.12/site-packages/pypdf/generic/_files.py new file mode 100644 index 0000000..0e00799 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/generic/_files.py @@ -0,0 +1,148 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Generator, cast + +from pypdf._utils import parse_iso8824_date +from pypdf.constants import FileSpecificationDictionaryEntries +from pypdf.errors import PdfReadError +from pypdf.generic import ArrayObject, DictionaryObject, StreamObject + +if TYPE_CHECKING: + import datetime + + +class EmbeddedFile: + """ + Container holding the information on an embedded file. + + Attributes are evaluated lazily if possible. + + Further information on embedded files can be found in section 7.11 of the PDF 2.0 specification. + """ + def __init__(self, name: str, pdf_object: DictionaryObject) -> None: + """ + Args: + name: The (primary) name as provided in the name tree. + pdf_object: The corresponding PDF object to allow retrieving further data. + """ + self.name = name + self.pdf_object = pdf_object + + @property + def alternative_name(self) -> str | None: + """Retrieve the alternative name (file specification).""" + for key in [FileSpecificationDictionaryEntries.UF, FileSpecificationDictionaryEntries.F]: + # PDF 2.0 reference, table 43: + # > A PDF reader shall use the value of the UF key, when present, instead of the F key. + if key in self.pdf_object: + return cast(str, self.pdf_object[key].get_object()) + return None + + @property + def description(self) -> str | None: + """Retrieve the description.""" + return self.pdf_object.get(FileSpecificationDictionaryEntries.DESC) + + @property + def associated_file_relationship(self) -> str: + """Retrieve the relationship of the referring document to this embedded file.""" + return self.pdf_object.get("/AFRelationship", "/Unspecified") + + @property + def _embedded_file(self) -> StreamObject: + """Retrieve the actual embedded file stream.""" + if "/EF" not in self.pdf_object: + raise PdfReadError(f"/EF entry not found: {self.pdf_object}") + ef = cast(DictionaryObject, self.pdf_object["/EF"]) + for key in [FileSpecificationDictionaryEntries.UF, FileSpecificationDictionaryEntries.F]: + if key in ef: + return cast(StreamObject, ef[key].get_object()) + raise PdfReadError(f"No /(U)F key found in file dictionary: {ef}") + + @property + def _params(self) -> DictionaryObject: + """Retrieve the file-specific parameters.""" + return self._embedded_file.get("/Params", DictionaryObject()).get_object() + + @property + def subtype(self) -> str | None: + """Retrieve the subtype. This is a MIME media type, prefixed by a slash.""" + return self._embedded_file.get("/Subtype") + + @property + def content(self) -> bytes: + """Retrieve the actual file content.""" + return self._embedded_file.get_data() + + @property + def size(self) -> int | None: + """Retrieve the size of the uncompressed file in bytes.""" + return self._params.get("/Size") + + @property + def creation_date(self) -> datetime.datetime | None: + """Retrieve the file creation datetime.""" + return parse_iso8824_date(self._params.get("/CreationDate")) + + @property + def modification_date(self) -> datetime.datetime | None: + """Retrieve the datetime of the last file modification.""" + return parse_iso8824_date(self._params.get("/ModDate")) + + @property + def checksum(self) -> bytes | None: + """Retrieve the MD5 checksum of the (uncompressed) file.""" + return self._params.get("/CheckSum") + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} name={self.name!r}>" + + @classmethod + def _load_from_names(cls, names: ArrayObject) -> Generator[EmbeddedFile]: + """ + Convert the given name tree into class instances. + + Args: + names: The name tree to load the data from. + + Returns: + Iterable of class instances for the files found. + """ + # This is a name tree of the format [name_1, reference_1, name_2, reference_2, ...] + for i, name in enumerate(names): + if not isinstance(name, str): + # Skip plain strings and retrieve them as `direct_name` by index. + file_dictionary = name.get_object() + direct_name = names[i - 1].get_object() + yield EmbeddedFile(name=direct_name, pdf_object=file_dictionary) + + @classmethod + def _load(cls, catalog: DictionaryObject) -> Generator[EmbeddedFile]: + """ + Load the embedded files for the given document catalog. + + This method and its signature are considered internal API and thus not exposed publicly for now. + + Args: + catalog: The document catalog to load from. + + Returns: + Iterable of class instances for the files found. + """ + try: + container = cast( + DictionaryObject, + cast(DictionaryObject, catalog["/Names"])["/EmbeddedFiles"], + ) + except KeyError: + return + + if "/Kids" in container: + for kid in cast(ArrayObject, container["/Kids"].get_object()): + # There might be further (nested) kids here. + # Wait for an example before evaluating an implementation. + kid = kid.get_object() + if "/Names" in kid: + yield from cls._load_from_names(cast(ArrayObject, kid["/Names"])) + if "/Names" in container: + yield from cls._load_from_names(cast(ArrayObject, container["/Names"])) diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/_fit.py b/venv/lib/python3.12/site-packages/pypdf/generic/_fit.py new file mode 100644 index 0000000..ab3478c --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/generic/_fit.py @@ -0,0 +1,174 @@ +from typing import Any, List, Optional, Tuple, Union + +from ._base import is_null_or_none + + +class Fit: + def __init__( + self, fit_type: str, fit_args: Tuple[Union[None, float, Any], ...] = () + ) -> None: + from ._base import FloatObject, NameObject, NullObject, NumberObject + + self.fit_type = NameObject(fit_type) + self.fit_args: List[Union[NullObject, FloatObject, NumberObject]] = [ + NullObject() if is_null_or_none(a) else FloatObject(a) for a in fit_args + ] + + @classmethod + def xyz( + cls, + left: Optional[float] = None, + top: Optional[float] = None, + zoom: Optional[float] = None, + ) -> "Fit": + """ + Display the page designated by page, with the coordinates (left, top) + positioned at the upper-left corner of the window and the contents + of the page magnified by the factor zoom. + + A null value for any of the parameters left, top, or zoom specifies + that the current value of that parameter is to be retained unchanged. + + A zoom value of 0 has the same meaning as a null value. + + Args: + left: + top: + zoom: + + Returns: + The created fit object. + + """ + return Fit(fit_type="/XYZ", fit_args=(left, top, zoom)) + + @classmethod + def fit(cls) -> "Fit": + """ + Display the page designated by page, with its contents magnified just + enough to fit the entire page within the window both horizontally and + vertically. + + If the required horizontal and vertical magnification factors are + different, use the smaller of the two, centering the page within the + window in the other dimension. + """ + return Fit(fit_type="/Fit") + + @classmethod + def fit_horizontally(cls, top: Optional[float] = None) -> "Fit": + """ + Display the page designated by page, with the vertical coordinate top + positioned at the top edge of the window and the contents of the page + magnified just enough to fit the entire width of the page within the + window. + + A null value for ``top`` specifies that the current value of that + parameter is to be retained unchanged. + + Args: + top: + + Returns: + The created fit object. + + """ + return Fit(fit_type="/FitH", fit_args=(top,)) + + @classmethod + def fit_vertically(cls, left: Optional[float] = None) -> "Fit": + return Fit(fit_type="/FitV", fit_args=(left,)) + + @classmethod + def fit_rectangle( + cls, + left: Optional[float] = None, + bottom: Optional[float] = None, + right: Optional[float] = None, + top: Optional[float] = None, + ) -> "Fit": + """ + Display the page designated by page, with its contents magnified + just enough to fit the rectangle specified by the coordinates + left, bottom, right, and top entirely within the window + both horizontally and vertically. + + If the required horizontal and vertical magnification factors are + different, use the smaller of the two, centering the rectangle within + the window in the other dimension. + + A null value for any of the parameters may result in unpredictable + behavior. + + Args: + left: + bottom: + right: + top: + + Returns: + The created fit object. + + """ + return Fit(fit_type="/FitR", fit_args=(left, bottom, right, top)) + + @classmethod + def fit_box(cls) -> "Fit": + """ + Display the page designated by page, with its contents magnified just + enough to fit its bounding box entirely within the window both + horizontally and vertically. + + If the required horizontal and vertical magnification factors are + different, use the smaller of the two, centering the bounding box + within the window in the other dimension. + """ + return Fit(fit_type="/FitB") + + @classmethod + def fit_box_horizontally(cls, top: Optional[float] = None) -> "Fit": + """ + Display the page designated by page, with the vertical coordinate top + positioned at the top edge of the window and the contents of the page + magnified just enough to fit the entire width of its bounding box + within the window. + + A null value for top specifies that the current value of that parameter + is to be retained unchanged. + + Args: + top: + + Returns: + The created fit object. + + """ + return Fit(fit_type="/FitBH", fit_args=(top,)) + + @classmethod + def fit_box_vertically(cls, left: Optional[float] = None) -> "Fit": + """ + Display the page designated by page, with the horizontal coordinate + left positioned at the left edge of the window and the contents of the + page magnified just enough to fit the entire height of its bounding box + within the window. + + A null value for left specifies that the current value of that + parameter is to be retained unchanged. + + Args: + left: + + Returns: + The created fit object. + + """ + return Fit(fit_type="/FitBV", fit_args=(left,)) + + def __str__(self) -> str: + if not self.fit_args: + return f"Fit({self.fit_type})" + return f"Fit({self.fit_type}, {self.fit_args})" + + +DEFAULT_FIT = Fit.fit() diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/_image_inline.py b/venv/lib/python3.12/site-packages/pypdf/generic/_image_inline.py new file mode 100644 index 0000000..f70819d --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/generic/_image_inline.py @@ -0,0 +1,299 @@ +# Copyright (c) 2024, pypdf contributors +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import logging +from io import BytesIO +from typing import IO + +from .._utils import ( + WHITESPACES, + WHITESPACES_AS_BYTES, + StreamType, + read_non_whitespace, +) +from ..errors import PdfReadError + +logger = logging.getLogger(__name__) + +BUFFER_SIZE = 8192 + + +def extract_inline_AHx(stream: StreamType) -> bytes: + """ + Extract HexEncoded Stream from Inline Image. + the stream will be moved onto the EI + """ + data_out: bytes = b"" + # Read data until delimiter > and EI as backup + # ignoring backup. + while True: + data_buffered = read_non_whitespace(stream) + stream.read(BUFFER_SIZE) + if not data_buffered: + raise PdfReadError("Unexpected end of stream") + pos_tok = data_buffered.find(b">") + if pos_tok >= 0: # found > + data_out += data_buffered[: pos_tok + 1] + stream.seek(-len(data_buffered) + pos_tok + 1, 1) + break + pos_ei = data_buffered.find(b"EI") + if pos_ei >= 0: # found EI + stream.seek(-len(data_buffered) + pos_ei - 1, 1) + c = stream.read(1) + while c in WHITESPACES: + stream.seek(-2, 1) + c = stream.read(1) + pos_ei -= 1 + data_out += data_buffered[:pos_ei] + break + if len(data_buffered) == 2: + data_out += data_buffered + raise PdfReadError("Unexpected end of stream") + # Neither > nor EI found + data_out += data_buffered[:-2] + stream.seek(-2, 1) + + ei_tok = read_non_whitespace(stream) + ei_tok += stream.read(2) + stream.seek(-3, 1) + if ei_tok[:2] != b"EI" or not (ei_tok[2:3] == b"" or ei_tok[2:3] in WHITESPACES): + raise PdfReadError("EI stream not found") + return data_out + + +def extract_inline_A85(stream: StreamType) -> bytes: + """ + Extract A85 Stream from Inline Image. + the stream will be moved onto the EI + """ + data_out: bytes = b"" + # Read data up to delimiter ~> + # see §3.3.2 from PDF ref 1.7 + while True: + data_buffered = read_non_whitespace(stream) + stream.read(BUFFER_SIZE) + if not data_buffered: + raise PdfReadError("Unexpected end of stream") + pos_tok = data_buffered.find(b"~>") + if pos_tok >= 0: # found! + data_out += data_buffered[: pos_tok + 2] + stream.seek(-len(data_buffered) + pos_tok + 2, 1) + break + if len(data_buffered) == 2: # end of buffer + data_out += data_buffered + raise PdfReadError("Unexpected end of stream") + data_out += data_buffered[ + :-2 + ] # back by one char in case of in the middle of ~> + stream.seek(-2, 1) + + ei_tok = read_non_whitespace(stream) + ei_tok += stream.read(2) + stream.seek(-3, 1) + if ei_tok[:2] != b"EI" or not (ei_tok[2:3] == b"" or ei_tok[2:3] in WHITESPACES): + raise PdfReadError("EI stream not found") + return data_out + + +def extract_inline_RL(stream: StreamType) -> bytes: + """ + Extract RL Stream from Inline Image. + the stream will be moved onto the EI + """ + data_out: bytes = b"" + # Read data up to delimiter ~> + # see §3.3.4 from PDF ref 1.7 + while True: + data_buffered = stream.read(BUFFER_SIZE) + if not data_buffered: + raise PdfReadError("Unexpected end of stream") + pos_tok = data_buffered.find(b"\x80") + if pos_tok >= 0: # found + data_out += data_buffered[: pos_tok + 1] + stream.seek(-len(data_buffered) + pos_tok + 1, 1) + break + data_out += data_buffered + + ei_tok = read_non_whitespace(stream) + ei_tok += stream.read(2) + stream.seek(-3, 1) + if ei_tok[:2] != b"EI" or not (ei_tok[2:3] == b"" or ei_tok[2:3] in WHITESPACES): + raise PdfReadError("EI stream not found") + return data_out + + +def extract_inline_DCT(stream: StreamType) -> bytes: + """ + Extract DCT (JPEG) Stream from Inline Image. + the stream will be moved onto the EI + """ + data_out: bytes = b"" + # Read Blocks of data (ID/Size/data) up to ID=FF/D9 + # see https://www.digicamsoft.com/itu/itu-t81-36.html + notfirst = False + while True: + c = stream.read(1) + if notfirst or (c == b"\xff"): + data_out += c + if c != b"\xff": + continue + notfirst = True + c = stream.read(1) + data_out += c + if c == b"\xff": + stream.seek(-1, 1) # pragma: no cover + elif c == b"\x00": # stuffing + pass + elif c == b"\xd9": # end + break + elif c in ( + b"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc9\xca\xcb\xcc\xcd\xce\xcf" + b"\xda\xdb\xdc\xdd\xde\xdf" + b"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xfe" + ): + c = stream.read(2) + data_out += c + sz = c[0] * 256 + c[1] + data_out += stream.read(sz - 2) + # else: pass + + ei_tok = read_non_whitespace(stream) + ei_tok += stream.read(2) + stream.seek(-3, 1) + if ei_tok[:2] != b"EI" or not (ei_tok[2:3] == b"" or ei_tok[2:3] in WHITESPACES): + raise PdfReadError("EI stream not found") + return data_out + + +def extract_inline_default(stream: StreamType) -> bytes: + """ + Legacy method + used by default + """ + stream_out = BytesIO() + # Read the inline image, while checking for EI (End Image) operator. + while True: + data_buffered = stream.read(BUFFER_SIZE) + if not data_buffered: + raise PdfReadError("Unexpected end of stream") + pos_ei = data_buffered.find( + b"E" + ) # we can not look straight for "EI" because it may not have been loaded in the buffer + + if pos_ei == -1: + stream_out.write(data_buffered) + else: + # Write out everything including E (the one from EI to be removed). + stream_out.write(data_buffered[0 : pos_ei + 1]) + sav_pos_ei = stream_out.tell() - 1 + # Seek back in the stream to read the E next. + stream.seek(pos_ei + 1 - len(data_buffered), 1) + saved_pos = stream.tell() + # Check for End Image + tok2 = stream.read(1) # I of "EI" + if tok2 != b"I": + stream.seek(saved_pos, 0) + continue + tok3 = stream.read(1) # possible space after "EI" + if tok3 not in WHITESPACES: + stream.seek(saved_pos, 0) + continue + while tok3 in WHITESPACES: + tok3 = stream.read(1) + if data_buffered[pos_ei - 1 : pos_ei] not in WHITESPACES and tok3 not in { + b"Q", + b"E", + }: # for Q or EMC + stream.seek(saved_pos, 0) + continue + if is_followed_by_binary_data(stream): + # Inline image contains `EI ` sequence usually marking the end of it, but + # is followed by binary data which does not make sense for the actual end. + stream.seek(saved_pos, 0) + continue + # Data contains [\s]EI[\s](Q|EMC): 4 chars are sufficient + # remove E(I) wrongly inserted earlier + stream.seek(saved_pos - 1, 0) + stream_out.truncate(sav_pos_ei) + break + + return stream_out.getvalue() + + +def is_followed_by_binary_data(stream: IO[bytes], length: int = 10) -> bool: + """ + Check if the next bytes of the stream look like binary image data or regular page content. + + This is just some heuristics due to the PDF specification being too imprecise about + inline images containing the `EI` marker which would end an image. Starting with PDF 2.0, + we finally get a mandatory length field, but with (proper) PDF 2.0 support being very limited + everywhere, we should not expect to be able to remove such hacks in the near future - especially + considering legacy documents as well. + + The actual implementation draws some inspiration from + https://github.com/itext/itext-java/blob/9.1.0/kernel/src/main/java/com/itextpdf/kernel/pdf/canvas/parser/util/InlineImageParsingUtils.java + """ + position = stream.tell() + data = stream.read(length) + stream.seek(position) + if not data: + return False + operator_start = None + operator_end = None + + for index, byte in enumerate(data): + if byte < 32 and byte not in WHITESPACES_AS_BYTES: + # This covers all characters not being displayable directly, although omitting whitespace + # to allow for operator detection. + return True + is_whitespace = byte in WHITESPACES_AS_BYTES + if operator_start is None and not is_whitespace: + # Interpret all other non-whitespace characters as the start of an operation. + operator_start = index + if operator_start is not None and is_whitespace: + # A whitespace stops an operation. + # Assume that having an inline image with tons of whitespace is rather unlikely. + operator_end = index + break + + if operator_start is None: + # Inline images should not have tons of whitespaces, which would lead to no operator start. + return False + if operator_end is None: + # We probably are inside an operation. + operator_end = length + operator_length = operator_end - operator_start + operator = data[operator_start:operator_end] + if operator.startswith(b"/") and operator_length > 1: + # Name object. + return False + if operator.replace(b".", b"").isdigit(): + # Graphics operator, for example a move. A number (integer or float). + return False + if operator_length > 3: # noqa: SIM103 + # Usually, the operators inside a content stream should not have more than three characters, + # especially after an inline image. + return True + return False diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/_outline.py b/venv/lib/python3.12/site-packages/pypdf/generic/_outline.py new file mode 100644 index 0000000..d5d4bb1 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/generic/_outline.py @@ -0,0 +1,33 @@ +from typing import Union + +from .._utils import StreamType, deprecation_no_replacement +from ._base import NameObject +from ._data_structures import Destination + + +class OutlineItem(Destination): + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + if encryption_key is not None: # deprecated + deprecation_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) + stream.write(b"<<\n") + for key in [ + NameObject(x) + for x in ["/Title", "/Parent", "/First", "/Last", "/Next", "/Prev"] + if x in self + ]: + key.write_to_stream(stream) + stream.write(b" ") + value = self.raw_get(key) + value.write_to_stream(stream) + stream.write(b"\n") + key = NameObject("/Dest") + key.write_to_stream(stream) + stream.write(b" ") + value = self.dest_array + value.write_to_stream(stream) + stream.write(b"\n") + stream.write(b">>") diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/_rectangle.py b/venv/lib/python3.12/site-packages/pypdf/generic/_rectangle.py new file mode 100644 index 0000000..c1f22ce --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/generic/_rectangle.py @@ -0,0 +1,132 @@ +from typing import Any, Tuple, Union + +from ._base import FloatObject, NumberObject +from ._data_structures import ArrayObject + + +class RectangleObject(ArrayObject): + """ + This class is used to represent *page boxes* in pypdf. + + These boxes include: + + * :attr:`artbox ` + * :attr:`bleedbox ` + * :attr:`cropbox ` + * :attr:`mediabox ` + * :attr:`trimbox ` + """ + + def __init__( + self, arr: Union["RectangleObject", Tuple[float, float, float, float]] + ) -> None: + # must have four points + assert len(arr) == 4 + # automatically convert arr[x] into NumberObject(arr[x]) if necessary + ArrayObject.__init__(self, [self._ensure_is_number(x) for x in arr]) # type: ignore + + def _ensure_is_number(self, value: Any) -> Union[FloatObject, NumberObject]: + if not isinstance(value, (FloatObject, NumberObject)): + value = FloatObject(value) + return value + + def scale(self, sx: float, sy: float) -> "RectangleObject": + return RectangleObject( + ( + float(self.left) * sx, + float(self.bottom) * sy, + float(self.right) * sx, + float(self.top) * sy, + ) + ) + + def __repr__(self) -> str: + return f"RectangleObject({list(self)!r})" + + @property + def left(self) -> FloatObject: + return self[0] + + @left.setter + def left(self, f: float) -> None: + self[0] = FloatObject(f) + + @property + def bottom(self) -> FloatObject: + return self[1] + + @bottom.setter + def bottom(self, f: float) -> None: + self[1] = FloatObject(f) + + @property + def right(self) -> FloatObject: + return self[2] + + @right.setter + def right(self, f: float) -> None: + self[2] = FloatObject(f) + + @property + def top(self) -> FloatObject: + return self[3] + + @top.setter + def top(self, f: float) -> None: + self[3] = FloatObject(f) + + @property + def lower_left(self) -> Tuple[float, float]: + """ + Property to read and modify the lower left coordinate of this box + in (x,y) form. + """ + return self.left, self.bottom + + @lower_left.setter + def lower_left(self, value: Tuple[float, float]) -> None: + self[0], self[1] = (self._ensure_is_number(x) for x in value) + + @property + def lower_right(self) -> Tuple[float, float]: + """ + Property to read and modify the lower right coordinate of this box + in (x,y) form. + """ + return self.right, self.bottom + + @lower_right.setter + def lower_right(self, value: Tuple[float, float]) -> None: + self[2], self[1] = (self._ensure_is_number(x) for x in value) + + @property + def upper_left(self) -> Tuple[float, float]: + """ + Property to read and modify the upper left coordinate of this box + in (x,y) form. + """ + return self.left, self.top + + @upper_left.setter + def upper_left(self, value: Tuple[float, float]) -> None: + self[0], self[3] = (self._ensure_is_number(x) for x in value) + + @property + def upper_right(self) -> Tuple[float, float]: + """ + Property to read and modify the upper right coordinate of this box + in (x,y) form. + """ + return self.right, self.top + + @upper_right.setter + def upper_right(self, value: Tuple[float, float]) -> None: + self[2], self[3] = (self._ensure_is_number(x) for x in value) + + @property + def width(self) -> float: + return self.right - self.left + + @property + def height(self) -> float: + return self.top - self.bottom diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/_utils.py b/venv/lib/python3.12/site-packages/pypdf/generic/_utils.py new file mode 100644 index 0000000..c0a1cf4 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/generic/_utils.py @@ -0,0 +1,209 @@ +import codecs +from typing import Dict, List, Tuple, Union + +from .._codecs import _pdfdoc_encoding +from .._utils import StreamType, logger_warning, read_non_whitespace +from ..errors import STREAM_TRUNCATED_PREMATURELY, PdfStreamError +from ._base import ByteStringObject, TextStringObject + + +def hex_to_rgb(value: str) -> Tuple[float, float, float]: + return tuple(int(value.lstrip("#")[i : i + 2], 16) / 255.0 for i in (0, 2, 4)) # type: ignore + + +def read_hex_string_from_stream( + stream: StreamType, + forced_encoding: Union[None, str, List[str], Dict[int, str]] = None, +) -> Union["TextStringObject", "ByteStringObject"]: + stream.read(1) + arr = [] + x = b"" + while True: + tok = read_non_whitespace(stream) + if not tok: + raise PdfStreamError(STREAM_TRUNCATED_PREMATURELY) + if tok == b">": + break + x += tok + if len(x) == 2: + arr.append(int(x, base=16)) + x = b"" + if len(x) == 1: + x += b"0" + if x != b"": + arr.append(int(x, base=16)) + return create_string_object(bytes(arr), forced_encoding) + + +__ESCAPE_DICT__ = { + b"n": ord(b"\n"), + b"r": ord(b"\r"), + b"t": ord(b"\t"), + b"b": ord(b"\b"), + b"f": ord(b"\f"), + b"(": ord(b"("), + b")": ord(b")"), + b"/": ord(b"/"), + b"\\": ord(b"\\"), + b" ": ord(b" "), + b"%": ord(b"%"), + b"<": ord(b"<"), + b">": ord(b">"), + b"[": ord(b"["), + b"]": ord(b"]"), + b"#": ord(b"#"), + b"_": ord(b"_"), + b"&": ord(b"&"), + b"$": ord(b"$"), +} +__BACKSLASH_CODE__ = 92 + + +def read_string_from_stream( + stream: StreamType, + forced_encoding: Union[None, str, List[str], Dict[int, str]] = None, +) -> Union["TextStringObject", "ByteStringObject"]: + tok = stream.read(1) + parens = 1 + txt = [] + while True: + tok = stream.read(1) + if not tok: + raise PdfStreamError(STREAM_TRUNCATED_PREMATURELY) + if tok == b"(": + parens += 1 + elif tok == b")": + parens -= 1 + if parens == 0: + break + elif tok == b"\\": + tok = stream.read(1) + try: + txt.append(__ESCAPE_DICT__[tok]) + continue + except KeyError: + if b"0" <= tok <= b"7": + # "The number ddd may consist of one, two, or three + # octal digits; high-order overflow shall be ignored. + # Three octal digits shall be used, with leading zeros + # as needed, if the next character of the string is also + # a digit." (PDF reference 7.3.4.2, p 16) + sav = stream.tell() - 1 + for _ in range(2): + ntok = stream.read(1) + if b"0" <= ntok <= b"7": + tok += ntok + else: + stream.seek(-1, 1) # ntok has to be analyzed + break + i = int(tok, base=8) + if i > 255: + txt.append(__BACKSLASH_CODE__) + stream.seek(sav) + else: + txt.append(i) + continue + if tok in b"\n\r": + # This case is hit when a backslash followed by a line + # break occurs. If it's a multi-char EOL, consume the + # second character: + tok = stream.read(1) + if tok not in b"\n\r": + stream.seek(-1, 1) + # Then don't add anything to the actual string, since this + # line break was escaped: + continue + msg = f"Unexpected escaped string: {tok.decode('utf-8', 'ignore')}" + logger_warning(msg, __name__) + txt.append(__BACKSLASH_CODE__) + txt.append(ord(tok)) + return create_string_object(bytes(txt), forced_encoding) + + +def create_string_object( + string: Union[str, bytes], + forced_encoding: Union[None, str, List[str], Dict[int, str]] = None, +) -> Union[TextStringObject, ByteStringObject]: + """ + Create a ByteStringObject or a TextStringObject from a string to represent the string. + + Args: + string: The data being used + forced_encoding: Typically None, or an encoding string + + Returns: + A ByteStringObject + + Raises: + TypeError: If string is not of type str or bytes. + + """ + if isinstance(string, str): + return TextStringObject(string) + elif isinstance(string, bytes): + if isinstance(forced_encoding, (list, dict)): + out = "" + for x in string: + try: + out += forced_encoding[x] + except Exception: + out += bytes((x,)).decode("charmap") + obj = TextStringObject(out) + obj._original_bytes = string + return obj + elif isinstance(forced_encoding, str): + if forced_encoding == "bytes": + return ByteStringObject(string) + obj = TextStringObject(string.decode(forced_encoding)) + obj._original_bytes = string + return obj + else: + try: + if string.startswith((codecs.BOM_UTF16_BE, codecs.BOM_UTF16_LE)): + retval = TextStringObject(string.decode("utf-16")) + retval._original_bytes = string + retval.autodetect_utf16 = True + retval.utf16_bom = string[:2] + return retval + if string.startswith(b"\x00"): + retval = TextStringObject(string.decode("utf-16be")) + retval._original_bytes = string + retval.autodetect_utf16 = True + retval.utf16_bom = codecs.BOM_UTF16_BE + return retval + if string[1:2] == b"\x00": + retval = TextStringObject(string.decode("utf-16le")) + retval._original_bytes = string + retval.autodetect_utf16 = True + retval.utf16_bom = codecs.BOM_UTF16_LE + return retval + + # This is probably a big performance hit here, but we need + # to convert string objects into the text/unicode-aware + # version if possible... and the only way to check if that's + # possible is to try. + # Some strings are strings, some are just byte arrays. + retval = TextStringObject(decode_pdfdocencoding(string)) + retval._original_bytes = string + retval.autodetect_pdfdocencoding = True + return retval + except UnicodeDecodeError: + return ByteStringObject(string) + else: + raise TypeError("create_string_object should have str or unicode arg") + + +def decode_pdfdocencoding(byte_array: bytes) -> str: + retval = "" + for b in byte_array: + c = _pdfdoc_encoding[b] + if c == "\u0000": + raise UnicodeDecodeError( + "pdfdocencoding", + bytearray(b), + -1, + -1, + "does not exist in translation table", + ) + retval += c + return retval diff --git a/venv/lib/python3.12/site-packages/pypdf/generic/_viewerpref.py b/venv/lib/python3.12/site-packages/pypdf/generic/_viewerpref.py new file mode 100644 index 0000000..f5dbd9c --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/generic/_viewerpref.py @@ -0,0 +1,164 @@ +# Copyright (c) 2023, Pubpub-ZZ +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +from typing import ( + Any, + List, + Optional, +) + +from ._base import BooleanObject, NameObject, NumberObject, is_null_or_none +from ._data_structures import ArrayObject, DictionaryObject + +f_obj = BooleanObject(False) + + +class ViewerPreferences(DictionaryObject): + def __init__(self, obj: Optional[DictionaryObject] = None) -> None: + super().__init__(self) + if not is_null_or_none(obj): + self.update(obj.items()) # type: ignore + try: + self.indirect_reference = obj.indirect_reference # type: ignore + except AttributeError: + pass + + def _get_bool(self, key: str, default: Optional[BooleanObject]) -> BooleanObject: + return self.get(key, default) + + def _set_bool(self, key: str, v: bool) -> None: + self[NameObject(key)] = BooleanObject(v is True) + + def _get_name(self, key: str, default: Optional[NameObject]) -> Optional[NameObject]: + return self.get(key, default) + + def _set_name(self, key: str, lst: List[str], v: NameObject) -> None: + if v[0] != "/": + raise ValueError(f"{v} does not start with '/'") + if lst != [] and v not in lst: + raise ValueError(f"{v} is an unacceptable value") + self[NameObject(key)] = NameObject(v) + + def _get_arr(self, key: str, default: Optional[List[Any]]) -> NumberObject: + return self.get(key, None if default is None else ArrayObject(default)) + + def _set_arr(self, key: str, v: Optional[ArrayObject]) -> None: + if v is None: + try: + del self[NameObject(key)] + except KeyError: + pass + return + if not isinstance(v, ArrayObject): + raise ValueError("ArrayObject is expected") + self[NameObject(key)] = v + + def _get_int(self, key: str, default: Optional[NumberObject]) -> NumberObject: + return self.get(key, default) + + def _set_int(self, key: str, v: int) -> None: + self[NameObject(key)] = NumberObject(v) + + @property + def PRINT_SCALING(self) -> NameObject: + return NameObject("/PrintScaling") + + def __new__(cls: Any, value: Any = None) -> "ViewerPreferences": + def _add_prop_bool(key: str, default: Optional[BooleanObject]) -> property: + return property( + lambda self: self._get_bool(key, default), + lambda self, v: self._set_bool(key, v), + None, + f""" + Returns/Modify the status of {key}, Returns {default} if not defined + """, + ) + + def _add_prop_name( + key: str, lst: List[str], default: Optional[NameObject] + ) -> property: + return property( + lambda self: self._get_name(key, default), + lambda self, v: self._set_name(key, lst, v), + None, + f""" + Returns/Modify the status of {key}, Returns {default} if not defined. + Acceptable values: {lst} + """, + ) + + def _add_prop_arr(key: str, default: Optional[ArrayObject]) -> property: + return property( + lambda self: self._get_arr(key, default), + lambda self, v: self._set_arr(key, v), + None, + f""" + Returns/Modify the status of {key}, Returns {default} if not defined + """, + ) + + def _add_prop_int(key: str, default: Optional[int]) -> property: + return property( + lambda self: self._get_int(key, default), + lambda self, v: self._set_int(key, v), + None, + f""" + Returns/Modify the status of {key}, Returns {default} if not defined + """, + ) + + cls.hide_toolbar = _add_prop_bool("/HideToolbar", f_obj) + cls.hide_menubar = _add_prop_bool("/HideMenubar", f_obj) + cls.hide_windowui = _add_prop_bool("/HideWindowUI", f_obj) + cls.fit_window = _add_prop_bool("/FitWindow", f_obj) + cls.center_window = _add_prop_bool("/CenterWindow", f_obj) + cls.display_doctitle = _add_prop_bool("/DisplayDocTitle", f_obj) + + cls.non_fullscreen_pagemode = _add_prop_name( + "/NonFullScreenPageMode", + ["/UseNone", "/UseOutlines", "/UseThumbs", "/UseOC"], + NameObject("/UseNone"), + ) + cls.direction = _add_prop_name( + "/Direction", ["/L2R", "/R2L"], NameObject("/L2R") + ) + cls.view_area = _add_prop_name("/ViewArea", [], None) + cls.view_clip = _add_prop_name("/ViewClip", [], None) + cls.print_area = _add_prop_name("/PrintArea", [], None) + cls.print_clip = _add_prop_name("/PrintClip", [], None) + cls.print_scaling = _add_prop_name("/PrintScaling", [], None) + cls.duplex = _add_prop_name( + "/Duplex", ["/Simplex", "/DuplexFlipShortEdge", "/DuplexFlipLongEdge"], None + ) + cls.pick_tray_by_pdfsize = _add_prop_bool("/PickTrayByPDFSize", None) + cls.print_pagerange = _add_prop_arr("/PrintPageRange", None) + cls.num_copies = _add_prop_int("/NumCopies", None) + + cls.enforce = _add_prop_arr("/Enforce", ArrayObject()) + + return DictionaryObject.__new__(cls) diff --git a/venv/lib/python3.12/site-packages/pypdf/pagerange.py b/venv/lib/python3.12/site-packages/pypdf/pagerange.py new file mode 100644 index 0000000..dac5b92 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/pagerange.py @@ -0,0 +1,197 @@ +""" +Representation and utils for ranges of PDF file pages. + +Copyright (c) 2014, Steve Witham . +All rights reserved. This software is available under a BSD license; +see https://github.com/py-pdf/pypdf/blob/main/LICENSE +""" + +import re +from typing import Any, List, Tuple, Union + +from .errors import ParseError + +_INT_RE = r"(0|-?[1-9]\d*)" # A decimal int, don't allow "-0". +PAGE_RANGE_RE = f"^({_INT_RE}|({_INT_RE}?(:{_INT_RE}?(:{_INT_RE}?)?)))$" +# groups: 12 34 5 6 7 8 + + +class PageRange: + """ + A slice-like representation of a range of page indices. + + For example, page numbers, only starting at zero. + + The syntax is like what you would put between brackets [ ]. + The slice is one of the few Python types that can't be subclassed, + but this class converts to and from slices, and allows similar use. + + - PageRange(str) parses a string representing a page range. + - PageRange(slice) directly "imports" a slice. + - to_slice() gives the equivalent slice. + - str() and repr() allow printing. + - indices(n) is like slice.indices(n). + """ + + def __init__(self, arg: Union[slice, "PageRange", str]) -> None: + """ + Initialize with either a slice -- giving the equivalent page range, + or a PageRange object -- making a copy, + or a string like + "int", "[int]:[int]" or "[int]:[int]:[int]", + where the brackets indicate optional ints. + Remember, page indices start with zero. + Page range expression examples: + + : all pages. -1 last page. + 22 just the 23rd page. :-1 all but the last page. + 0:3 the first three pages. -2 second-to-last page. + :3 the first three pages. -2: last two pages. + 5: from the sixth page onward. -3:-1 third & second to last. + The third, "stride" or "step" number is also recognized. + ::2 0 2 4 ... to the end. 3:0:-1 3 2 1 but not 0. + 1:10:2 1 3 5 7 9 2::-1 2 1 0. + ::-1 all pages in reverse order. + Note the difference between this notation and arguments to slice(): + slice(3) means the first three pages; + PageRange("3") means the range of only the fourth page. + However PageRange(slice(3)) means the first three pages. + """ + if isinstance(arg, slice): + self._slice = arg + return + + if isinstance(arg, PageRange): + self._slice = arg.to_slice() + return + + m = isinstance(arg, str) and re.match(PAGE_RANGE_RE, arg) + if not m: + raise ParseError(arg) + elif m.group(2): + # Special case: just an int means a range of one page. + start = int(m.group(2)) + stop = start + 1 if start != -1 else None + self._slice = slice(start, stop) + else: + self._slice = slice(*[int(g) if g else None for g in m.group(4, 6, 8)]) + + @staticmethod + def valid(input: Any) -> bool: + """ + True if input is a valid initializer for a PageRange. + + Args: + input: A possible PageRange string or a PageRange object. + + Returns: + True, if the ``input`` is a valid PageRange. + + """ + return isinstance(input, (slice, PageRange)) or ( + isinstance(input, str) and bool(re.match(PAGE_RANGE_RE, input)) + ) + + def to_slice(self) -> slice: + """Return the slice equivalent of this page range.""" + return self._slice + + def __str__(self) -> str: + """A string like "1:2:3".""" + s = self._slice + indices: Union[Tuple[int, int], Tuple[int, int, int]] + if s.step is None: + if s.start is not None and s.stop == s.start + 1: + return str(s.start) + + indices = s.start, s.stop + else: + indices = s.start, s.stop, s.step + return ":".join("" if i is None else str(i) for i in indices) + + def __repr__(self) -> str: + """A string like "PageRange('1:2:3')".""" + return "PageRange(" + repr(str(self)) + ")" + + def indices(self, n: int) -> Tuple[int, int, int]: + """ + Assuming a sequence of length n, calculate the start and stop indices, + and the stride length of the PageRange. + + See help(slice.indices). + + Args: + n: the length of the list of pages to choose from. + + Returns: + Arguments for range(). + + """ + return self._slice.indices(n) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, PageRange): + return False + return self._slice == other._slice + + def __add__(self, other: "PageRange") -> "PageRange": + if not isinstance(other, PageRange): + raise TypeError(f"Can't add PageRange and {type(other)}") + if self._slice.step is not None or other._slice.step is not None: + raise ValueError("Can't add PageRange with stride") + a = self._slice.start, self._slice.stop + b = other._slice.start, other._slice.stop + + if a[0] > b[0]: + a, b = b, a + + # Now a[0] is the smallest + if b[0] > a[1]: + # There is a gap between a and b. + raise ValueError("Can't add PageRanges with gap") + return PageRange(slice(a[0], max(a[1], b[1]))) + + +PAGE_RANGE_ALL = PageRange(":") # The range of all pages. + + +def parse_filename_page_ranges( + args: List[Union[str, PageRange, None]] +) -> List[Tuple[str, PageRange]]: + """ + Given a list of filenames and page ranges, return a list of (filename, page_range) pairs. + + Args: + args: A list where the first element is a filename. The other elements are + filenames, page-range expressions, slice objects, or PageRange objects. + A filename not followed by a page range indicates all pages of the file. + + Returns: + A list of (filename, page_range) pairs. + + """ + pairs: List[Tuple[str, PageRange]] = [] + pdf_filename: Union[str, None] = None + did_page_range = False + for arg in [*args, None]: + if PageRange.valid(arg): + if not pdf_filename: + raise ValueError( + "The first argument must be a filename, not a page range." + ) + + assert arg is not None + pairs.append((pdf_filename, PageRange(arg))) + did_page_range = True + else: + # New filename or end of list - use the complete previous file? + if pdf_filename and not did_page_range: + pairs.append((pdf_filename, PAGE_RANGE_ALL)) + + assert not isinstance(arg, PageRange), arg + pdf_filename = arg + did_page_range = False + return pairs + + +PageRangeSpec = Union[str, PageRange, Tuple[int, int], Tuple[int, int, int], List[int]] diff --git a/venv/lib/python3.12/site-packages/pypdf/papersizes.py b/venv/lib/python3.12/site-packages/pypdf/papersizes.py new file mode 100644 index 0000000..ed09f34 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/papersizes.py @@ -0,0 +1,52 @@ +"""Helper to get paper sizes.""" + +from typing import NamedTuple + + +class Dimensions(NamedTuple): + width: int + height: int + + +class PaperSize: + """(width, height) of the paper in portrait mode in pixels at 72 ppi.""" + + # Notes of how to calculate it: + # 1. Get the size of the paper in millimeters + # 2. Convert it to inches (25.4 millimeters is equal to 1 inch) + # 3. Convert it to pixels at 72dpi (1 inch is equal to 72 pixels) + + # All Din-A paper sizes follow this pattern: + # 2 x A(n - 1) = A(n) + # So the height of the next bigger one is the width of the smaller one + # The ratio is always approximately 1:2**0.5 + # Additionally, A0 is defined to have an area of 1 m**2 + # https://en.wikipedia.org/wiki/ISO_216 + # Be aware of rounding issues! + A0 = Dimensions(2384, 3370) # 841mm x 1189mm + A1 = Dimensions(1684, 2384) + A2 = Dimensions(1191, 1684) + A3 = Dimensions(842, 1191) + A4 = Dimensions( + 595, 842 + ) # Printer paper, documents - this is by far the most common + A5 = Dimensions(420, 595) # Paperback books + A6 = Dimensions(298, 420) # Postcards + A7 = Dimensions(210, 298) + A8 = Dimensions(147, 210) + + # Envelopes + C4 = Dimensions(649, 918) + + +_din_a = ( + PaperSize.A0, + PaperSize.A1, + PaperSize.A2, + PaperSize.A3, + PaperSize.A4, + PaperSize.A5, + PaperSize.A6, + PaperSize.A7, + PaperSize.A8, +) diff --git a/venv/lib/python3.12/site-packages/pypdf/py.typed b/venv/lib/python3.12/site-packages/pypdf/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.12/site-packages/pypdf/types.py b/venv/lib/python3.12/site-packages/pypdf/types.py new file mode 100644 index 0000000..e383dc7 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/types.py @@ -0,0 +1,77 @@ +"""Helpers for working with PDF types.""" + +import sys +from typing import List, Literal, Union + +if sys.version_info[:2] >= (3, 10): + # Python 3.10+: https://www.python.org/dev/peps/pep-0484 + from typing import TypeAlias +else: + from typing_extensions import TypeAlias + +from .generic._base import NameObject, NullObject, NumberObject +from .generic._data_structures import ArrayObject, Destination +from .generic._outline import OutlineItem + +BorderArrayType: TypeAlias = List[Union[NameObject, NumberObject, ArrayObject]] +OutlineItemType: TypeAlias = Union[OutlineItem, Destination] +FitType: TypeAlias = Literal[ + "/XYZ", "/Fit", "/FitH", "/FitV", "/FitR", "/FitB", "/FitBH", "/FitBV" +] +# Those go with the FitType: They specify values for the fit +ZoomArgType: TypeAlias = Union[NumberObject, NullObject, float] +ZoomArgsType: TypeAlias = List[ZoomArgType] + +# Recursive types like the following are not yet supported by mypy: +# OutlineType = List[Union[Destination, "OutlineType"]] +# See https://github.com/python/mypy/issues/731 +# Hence use this for the moment: +OutlineType = List[Union[Destination, List[Union[Destination, List[Destination]]]]] + +LayoutType: TypeAlias = Literal[ + "/NoLayout", + "/SinglePage", + "/OneColumn", + "/TwoColumnLeft", + "/TwoColumnRight", + "/TwoPageLeft", + "/TwoPageRight", +] +PagemodeType: TypeAlias = Literal[ + "/UseNone", + "/UseOutlines", + "/UseThumbs", + "/FullScreen", + "/UseOC", + "/UseAttachments", +] +AnnotationSubtype: TypeAlias = Literal[ + "/Text", + "/Link", + "/FreeText", + "/Line", + "/Square", + "/Circle", + "/Polygon", + "/PolyLine", + "/Highlight", + "/Underline", + "/Squiggly", + "/StrikeOut", + "/Caret", + "/Stamp", + "/Ink", + "/Popup", + "/FileAttachment", + "/Sound", + "/Movie", + "/Screen", + "/Widget", + "/PrinterMark", + "/TrapNet", + "/Watermark", + "/3D", + "/Redact", + "/Projection", + "/RichMedia", +] diff --git a/venv/lib/python3.12/site-packages/pypdf/xmp.py b/venv/lib/python3.12/site-packages/pypdf/xmp.py new file mode 100644 index 0000000..099c369 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/xmp.py @@ -0,0 +1,394 @@ +""" +Anything related to Extensible Metadata Platform (XMP) metadata. + +https://en.wikipedia.org/wiki/Extensible_Metadata_Platform +""" + +import datetime +import decimal +import re +from typing import ( + Any, + Callable, + Dict, + Iterator, + List, + Optional, + TypeVar, + Union, +) +from xml.dom.minidom import Document, parseString +from xml.dom.minidom import Element as XmlElement +from xml.parsers.expat import ExpatError + +from ._utils import StreamType, deprecate_no_replacement +from .errors import PdfReadError +from .generic import ContentStream, PdfObject + +RDF_NAMESPACE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#" +DC_NAMESPACE = "http://purl.org/dc/elements/1.1/" +XMP_NAMESPACE = "http://ns.adobe.com/xap/1.0/" +PDF_NAMESPACE = "http://ns.adobe.com/pdf/1.3/" +XMPMM_NAMESPACE = "http://ns.adobe.com/xap/1.0/mm/" + +# What is the PDFX namespace, you might ask? +# It's documented here: https://github.com/adobe/xmp-docs/raw/master/XMPSpecifications/XMPSpecificationPart3.pdf +# This namespace is used to place "custom metadata" +# properties, which are arbitrary metadata properties with no semantic or +# documented meaning. +# +# Elements in the namespace are key/value-style storage, +# where the element name is the key and the content is the value. The keys +# are transformed into valid XML identifiers by substituting an invalid +# identifier character with \u2182 followed by the unicode hex ID of the +# original character. A key like "my car" is therefore "my\u21820020car". +# +# \u2182 is the unicode character \u{ROMAN NUMERAL TEN THOUSAND} +# +# The pdfx namespace should be avoided. +# A custom data schema and sensical XML elements could be used instead, as is +# suggested by Adobe's own documentation on XMP under "Extensibility of +# Schemas". +PDFX_NAMESPACE = "http://ns.adobe.com/pdfx/1.3/" + +iso8601 = re.compile( + """ + (?P[0-9]{4}) + (- + (?P[0-9]{2}) + (- + (?P[0-9]+) + (T + (?P[0-9]{2}): + (?P[0-9]{2}) + (:(?P[0-9]{2}(.[0-9]+)?))? + (?PZ|[-+][0-9]{2}:[0-9]{2}) + )? + )? + )? + """, + re.VERBOSE, +) + + +K = TypeVar("K") + + +def _identity(value: K) -> K: + return value + + +def _converter_date(value: str) -> datetime.datetime: + matches = iso8601.match(value) + if matches is None: + raise ValueError(f"Invalid date format: {value}") + year = int(matches.group("year")) + month = int(matches.group("month") or "1") + day = int(matches.group("day") or "1") + hour = int(matches.group("hour") or "0") + minute = int(matches.group("minute") or "0") + second = decimal.Decimal(matches.group("second") or "0") + seconds_dec = second.to_integral(decimal.ROUND_FLOOR) + milliseconds_dec = (second - seconds_dec) * 1_000_000 + + seconds = int(seconds_dec) + milliseconds = int(milliseconds_dec) + + tzd = matches.group("tzd") or "Z" + dt = datetime.datetime(year, month, day, hour, minute, seconds, milliseconds) + if tzd != "Z": + tzd_hours, tzd_minutes = (int(x) for x in tzd.split(":")) + tzd_hours *= -1 + if tzd_hours < 0: + tzd_minutes *= -1 + dt = dt + datetime.timedelta(hours=tzd_hours, minutes=tzd_minutes) + return dt + + +def _getter_bag( + namespace: str, name: str +) -> Callable[["XmpInformation"], Optional[List[str]]]: + def get(self: "XmpInformation") -> Optional[List[str]]: + cached = self.cache.get(namespace, {}).get(name) + if cached: + return cached + retval = [] + for element in self.get_element("", namespace, name): + bags = element.getElementsByTagNameNS(RDF_NAMESPACE, "Bag") + if len(bags): + for bag in bags: + for item in bag.getElementsByTagNameNS(RDF_NAMESPACE, "li"): + value = self._get_text(item) + retval.append(value) + ns_cache = self.cache.setdefault(namespace, {}) + ns_cache[name] = retval + return retval + + return get + + +def _getter_seq( + namespace: str, name: str, converter: Callable[[Any], Any] = _identity +) -> Callable[["XmpInformation"], Optional[List[Any]]]: + def get(self: "XmpInformation") -> Optional[List[Any]]: + cached = self.cache.get(namespace, {}).get(name) + if cached: + return cached + retval = [] + for element in self.get_element("", namespace, name): + seqs = element.getElementsByTagNameNS(RDF_NAMESPACE, "Seq") + if len(seqs): + for seq in seqs: + for item in seq.getElementsByTagNameNS(RDF_NAMESPACE, "li"): + value = self._get_text(item) + value = converter(value) + retval.append(value) + else: + value = converter(self._get_text(element)) + retval.append(value) + ns_cache = self.cache.setdefault(namespace, {}) + ns_cache[name] = retval + return retval + + return get + + +def _getter_langalt( + namespace: str, name: str +) -> Callable[["XmpInformation"], Optional[Dict[Any, Any]]]: + def get(self: "XmpInformation") -> Optional[Dict[Any, Any]]: + cached = self.cache.get(namespace, {}).get(name) + if cached: + return cached + retval = {} + for element in self.get_element("", namespace, name): + alts = element.getElementsByTagNameNS(RDF_NAMESPACE, "Alt") + if len(alts): + for alt in alts: + for item in alt.getElementsByTagNameNS(RDF_NAMESPACE, "li"): + value = self._get_text(item) + retval[item.getAttribute("xml:lang")] = value + else: + retval["x-default"] = self._get_text(element) + ns_cache = self.cache.setdefault(namespace, {}) + ns_cache[name] = retval + return retval + + return get + + +def _getter_single( + namespace: str, name: str, converter: Callable[[str], Any] = _identity +) -> Callable[["XmpInformation"], Optional[Any]]: + def get(self: "XmpInformation") -> Optional[Any]: + cached = self.cache.get(namespace, {}).get(name) + if cached: + return cached + value = None + for element in self.get_element("", namespace, name): + if element.nodeType == element.ATTRIBUTE_NODE: + value = element.nodeValue + else: + value = self._get_text(element) + break + if value is not None: + value = converter(value) + ns_cache = self.cache.setdefault(namespace, {}) + ns_cache[name] = value + return value + + return get + + +class XmpInformation(PdfObject): + """ + An object that represents Extensible Metadata Platform (XMP) metadata. + Usually accessed by :py:attr:`xmp_metadata()`. + + Raises: + PdfReadError: if XML is invalid + + """ + + def __init__(self, stream: ContentStream) -> None: + self.stream = stream + try: + data = self.stream.get_data() + doc_root: Document = parseString(data) # noqa: S318 + except ExpatError as e: + raise PdfReadError(f"XML in XmpInformation was invalid: {e}") + self.rdf_root: XmlElement = doc_root.getElementsByTagNameNS( + RDF_NAMESPACE, "RDF" + )[0] + self.cache: Dict[Any, Any] = {} + + def write_to_stream( + self, stream: StreamType, encryption_key: Union[None, str, bytes] = None + ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) + self.stream.write_to_stream(stream) + + def get_element(self, about_uri: str, namespace: str, name: str) -> Iterator[Any]: + for desc in self.rdf_root.getElementsByTagNameNS(RDF_NAMESPACE, "Description"): + if desc.getAttributeNS(RDF_NAMESPACE, "about") == about_uri: + attr = desc.getAttributeNodeNS(namespace, name) + if attr is not None: + yield attr + yield from desc.getElementsByTagNameNS(namespace, name) + + def get_nodes_in_namespace(self, about_uri: str, namespace: str) -> Iterator[Any]: + for desc in self.rdf_root.getElementsByTagNameNS(RDF_NAMESPACE, "Description"): + if desc.getAttributeNS(RDF_NAMESPACE, "about") == about_uri: + for i in range(desc.attributes.length): + attr = desc.attributes.item(i) + if attr.namespaceURI == namespace: + yield attr + for child in desc.childNodes: + if child.namespaceURI == namespace: + yield child + + def _get_text(self, element: XmlElement) -> str: + text = "" + for child in element.childNodes: + if child.nodeType == child.TEXT_NODE: + text += child.data + return text + + dc_contributor = property(_getter_bag(DC_NAMESPACE, "contributor")) + """ + Contributors to the resource (other than the authors). + + An unsorted array of names. + """ + + dc_coverage = property(_getter_single(DC_NAMESPACE, "coverage")) + """Text describing the extent or scope of the resource.""" + + dc_creator = property(_getter_seq(DC_NAMESPACE, "creator")) + """A sorted array of names of the authors of the resource, listed in order + of precedence.""" + + dc_date = property(_getter_seq(DC_NAMESPACE, "date", _converter_date)) + """ + A sorted array of dates (datetime.datetime instances) of significance to + the resource. + + The dates and times are in UTC. + """ + + dc_description = property(_getter_langalt(DC_NAMESPACE, "description")) + """A language-keyed dictionary of textual descriptions of the content of the + resource.""" + + dc_format = property(_getter_single(DC_NAMESPACE, "format")) + """The mime-type of the resource.""" + + dc_identifier = property(_getter_single(DC_NAMESPACE, "identifier")) + """Unique identifier of the resource.""" + + dc_language = property(_getter_bag(DC_NAMESPACE, "language")) + """An unordered array specifying the languages used in the resource.""" + + dc_publisher = property(_getter_bag(DC_NAMESPACE, "publisher")) + """An unordered array of publisher names.""" + + dc_relation = property(_getter_bag(DC_NAMESPACE, "relation")) + """An unordered array of text descriptions of relationships to other + documents.""" + + dc_rights = property(_getter_langalt(DC_NAMESPACE, "rights")) + """A language-keyed dictionary of textual descriptions of the rights the + user has to this resource.""" + + dc_source = property(_getter_single(DC_NAMESPACE, "source")) + """Unique identifier of the work from which this resource was derived.""" + + dc_subject = property(_getter_bag(DC_NAMESPACE, "subject")) + """An unordered array of descriptive phrases or keywords that specify the + topic of the content of the resource.""" + + dc_title = property(_getter_langalt(DC_NAMESPACE, "title")) + """A language-keyed dictionary of the title of the resource.""" + + dc_type = property(_getter_bag(DC_NAMESPACE, "type")) + """An unordered array of textual descriptions of the document type.""" + + pdf_keywords = property(_getter_single(PDF_NAMESPACE, "Keywords")) + """An unformatted text string representing document keywords.""" + + pdf_pdfversion = property(_getter_single(PDF_NAMESPACE, "PDFVersion")) + """The PDF file version, for example 1.0 or 1.3.""" + + pdf_producer = property(_getter_single(PDF_NAMESPACE, "Producer")) + """The name of the tool that created the PDF document.""" + + xmp_create_date = property( + _getter_single(XMP_NAMESPACE, "CreateDate", _converter_date) + ) + """ + The date and time the resource was originally created. + + The date and time are returned as a UTC datetime.datetime object. + """ + + xmp_modify_date = property( + _getter_single(XMP_NAMESPACE, "ModifyDate", _converter_date) + ) + """ + The date and time the resource was last modified. + + The date and time are returned as a UTC datetime.datetime object. + """ + + xmp_metadata_date = property( + _getter_single(XMP_NAMESPACE, "MetadataDate", _converter_date) + ) + """ + The date and time that any metadata for this resource was last changed. + + The date and time are returned as a UTC datetime.datetime object. + """ + + xmp_creator_tool = property(_getter_single(XMP_NAMESPACE, "CreatorTool")) + """The name of the first known tool used to create the resource.""" + + xmpmm_document_id = property(_getter_single(XMPMM_NAMESPACE, "DocumentID")) + """The common identifier for all versions and renditions of this resource.""" + + xmpmm_instance_id = property(_getter_single(XMPMM_NAMESPACE, "InstanceID")) + """An identifier for a specific incarnation of a document, updated each + time a file is saved.""" + + @property + def custom_properties(self) -> Dict[Any, Any]: + """ + Retrieve custom metadata properties defined in the undocumented pdfx + metadata schema. + + Returns: + A dictionary of key/value items for custom metadata properties. + + """ + if not hasattr(self, "_custom_properties"): + self._custom_properties = {} + for node in self.get_nodes_in_namespace("", PDFX_NAMESPACE): + key = node.localName + while True: + # see documentation about PDFX_NAMESPACE earlier in file + idx = key.find("\u2182") + if idx == -1: + break + key = ( + key[:idx] + + chr(int(key[idx + 1 : idx + 5], base=16)) + + key[idx + 5 :] + ) + if node.nodeType == node.ATTRIBUTE_NODE: + value = node.nodeValue + else: + value = self._get_text(node) + self._custom_properties[key] = value + return self._custom_properties

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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/__pycache__/constants.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/__pycache__/constants.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a7fbaeb51121f242140e10fdd1fd4d2d3fc54fd3 GIT binary patch literal 22959 zcmeHvdu&@*n&0L7AyK5>vi!QSWn1((q$S(&BaaEiheVqXg{0(|-7Saay^@(wq~=^I zu?Po|7Xj*E2Z*y-G@iEG@pM}xX}aC{qkrsQ#dHc3Xm^3NCj$&~JMDP3TND9`g&ez8 z*J!)_edk_2L{ZL67PHttN=V;5_q*qudmi8So$q|#ckUm%TuuSM|M=ejT>kkhg79DH zrturs6OWFY1mQzL60(A1kc=h6iZN?kF=b6F=B#BJZz@?=Y+2iiJ!>}zMqyTv z%Pt96QStrL^fwz5X)Nwr=X9v#F#PxEV6S$rx&c$)Pz`2^ZK91`H&Mlih zMJwr-b#tr-*#2ft562AvH`v7WbKDSc!%f@($Bh6t+QbcV+!%0snz$j38wYN06E`ed zICdYf`(a@F*eo;3aUyWfG;w1bcL=z{P23)in*i=e6F1IrM}a%m z#O>v{N#MLq+&+#w4%|1IxcwY=0=Q?JxC0#L1J2*X9pt!^z)dxABF9YwcdChdhT~2H zcczIu#Bt97ceZVI4s+}|V9z&mPH@}>;GS>dj&R%yz`fYS9p$)}fcs_>cZ}m+1}@O{ zmPwAC0XEpo>E*Z(aN)L`$K`{vOFky=kq^mxEcVtvjVt({%WvtngU5et>FQq7mE$_Y^}udU#c zFH7Q5DZi|U)ry!eN+OfBYR<1!E2?#^T>SQ$ z>@}+9P_a-|Et$2|l3dWKi(hn}5+04=_CrAyvIcOiQ8LJ;C8K0~2mHEjLjAUMmGM_t znOt3C<$|HD7Gfj%e{_OZQf)rFA-vXjL0k4u_2+59Ye=ARCZ)<$%NzL;nrcwZidPAv5*0SjD$7h(6#pA?`3--mc-6nUUcFW+pYlyj`;}r< zes(oqcs;)?D|oOfE%}>+>RVk`ZMhs?n9J4NdY^nc!j5+;9)JzuXYPU9r$4;#{)OLu z`=0&4BWirYYfxl}1HgRa)!ye2acYe|uPPaOW_ zTD4Rx%gPhGKXZ+UOsQG?^BBe_R(?@xc7HHm&6g_639o|ZCnkS1 z1Z=dtRKX=(tjRPkOn#%wD40{pWJa}x6T#G#`HX6ehE#Jj5lO1%bTk{rK%~NpogF`n zE-(T#Ac_d^j-d6G_uA37F{9n`{`U;r3~61bBHg=Av$B&~I3xG#GZ?5=S@G&x71M3? zCqUG64arJX0ik!!ttAnNW9BTOa5|IjY(6nPBXAJ^3QZoG&u6K3=w?`JDn0Jr)L((H z$Mgw-Bp`9t>Ot+cQ^YSINnA|iOAwuW>X1{EkQLWFTL%_>mKAZS!oU@>NPj@xOrde9hCKrnp>%^seT2(hl2)K~fDV)sR#T3#wsW_2^`ji-$9T5V)pu=%-PF z5uj02h#uY%9vUqc`(~fuaBT$Y_TFt^)O+7Nq|FGG+BPE=An5nV1EI5%csfOmWXn1v zd)6sAvOSVB+bi{CT~cqhPjY45QeW01xwHL}Cp#eZX9uN$?2t5=9hQc&BhqkoR2s>S zNu$|4(pYv}+LPTYjc4~sd$aqcec1!j{_H{NKvt9vW}lJ7>>=ry>|uFAIwT*F4$DWE z%+ka==B9phY}=C~ZBHhV+lv+W=#p^{I)%0DDAuy$$bYOIFCCTy)H&H!@*BwW4awVv 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 TxM6?%0{VR0_CKiWTw?q`e@e@G literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/__pycache__/errors.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/__pycache__/errors.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..30c52185d88dbe1945d5d84140e68298d14d0526 GIT binary patch literal 3300 zcmb7GPj4GV6yLR-#BmZQBx%#60Y)G}jKEe~g!(5fN)xB5)CA)ss%j9c@$T4Oy58N+ ztdp*}IXy%51ojyWIXhv*9>|aqe+ZU{6iv2e#)5;)lLf zBb?fT2|`_qP*C$~Bxo>lM7e9bbwTWav|v7;$&?&M1tYE(Fi@cZsdDczb4h7yo78Lv zY&7k9BOoS)1;hg@oD>IN%V*4f&hQD@lGo`RJf3MxtLTusgr!%KVIr68&TTQDGm|3I zA~J91%1G2AM-BKUB~~;KNR82;#Tl^$Qnm8C&r{vBVYsx(45OPdjHYL`92`#@#*-Fx zqL~T9usqW+o@=MbYNEtIArc&!Lh3aKMWe4do6$E zYC+fm`^2Z_V_IhdCLp2(73sVma;!cn(l8KMtH)Y5b&X>^OMIl5%tB0(<8Z_DTO7gro7JI z#WFMzkGpyQJRm*y|NHtXTo&RrwSaux60^EblTvzlEABo;HkSjB4DS}tx8NqEJ zOOv`#prXYH2SwOggbsGj5RUW65yeuR<1NJz@sT(#m7qlT>^9r=f-P3FT^7;3b&f9a zL6Hd1#Acva!aiv=nH%69!!odxfg!{fkvNLWapFZq9PyEeXQSXgR4u8!e;>mbHG;G7 z5+53q8`#tt8t0EmwFNFm5#*7PK!e0yu0Cfo0MZc-Jyz3&&Ha$tWH@;A}4L?}j}83867#Z9;eG}jeP#7CmJAZgxj zLJQu4ovyfEk8_2H%Dv+epLJo9{z19;;L*9?j92M(^)qvae*oXYe@gK) zh!;s+*Iy=5da9Sz^-nutPlHD)&< zZ-(Ca3f~O*R@OUT<69Zt(Ar95ZA?#}Jm_ig=*{VRMgMI%k7^aU=(bvO8_jL%Cm-R= Qrv4(WkL2v7vY%@3d?(m+My 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%0Aqp`SWHKxw{UXZq+1O zROGf>PCu_n98tl=sac>Y(dLOk-d=W>0^LjKpU2IEpdW%G3kRq1H-kV?NI$^;jGRU| zf}Zx*_U#eRi&==AFavPhFi-5XpbpJ4Y9Q#bkpvb?v>0J@42oUJiiGHxXtzn^3TBk_ z_Y80mr1a*=ww3=51?heB5&Y#M@rW8}bwwj}Cqcxz3nsb~2zTj5!n~V2e?m?PIUD4Z zlEWxi89_u7dBW@B-VO2RJW)D9AEZBq6c%srC-NoU<6*cEoC)%wvCZ}|9*RLq6?WS{ z+vgFtkKQ7`KOpBHlk-R9+#%=t%$5Fo z?&vyqG|3(PkKFFh)OwZruQ_sxI92Dz+}@A5?H_Z^A9L*=b1na#>rQgrpQ&{!^%D+G z#!;iHq3av*TAhDFug|(wFRN8M9&_Y=c1gQWRr;8N^BJ!?q}uYBgY#KbwOiG#dd!jg z*`#WV%K4as^Vw0AQRN0jRJlJZl_3~?sV$$W-KxqA2M2aJYD^Bl zRZH4n&S>y{1cNFa-dKp1q6~!qpXy7Vm+E$#C?2x9{He`yGGW^3#&U>9dK0XOnwIp0WTo7XKYh C^Eg}p literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/__pycache__/pagerange.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/__pycache__/pagerange.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cece6c62d817209270f10d19414d789a7b6ed0ae GIT binary patch literal 9142 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/__pycache__/types.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/__pycache__/types.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..54f9048968762304c1ea745dceae0b277adcb3db GIT binary patch literal 1861 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/_cmap.py b/venv/lib/python3.12/site-packages/pypdf/_cmap.py new file mode 100644 index 0000000..f460bc8 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_cmap.py @@ -0,0 +1,544 @@ +import binascii +from binascii import unhexlify +from math import ceil +from typing import Any, Dict, List, Tuple, Union, cast + +from ._codecs import adobe_glyphs, charset_encoding +from ._utils import logger_error, logger_warning +from .generic import ( + DecodedStreamObject, + DictionaryObject, + StreamObject, + is_null_or_none, +) + + +# code freely inspired from @twiggy ; see #711 +def build_char_map( + font_name: str, space_width: float, obj: DictionaryObject +) -> Tuple[str, float, Union[str, Dict[int, str]], Dict[Any, Any], DictionaryObject]: + """ + Determine information about a font. + + Args: + font_name: font name as a string + space_width: default space width if no data is found. + obj: XObject or Page where you can find a /Resource dictionary + + Returns: + Font sub-type, space_width criteria (50% of width), encoding, map character-map, font-dictionary. + The font-dictionary itself is suitable for the curious. + + """ + ft: DictionaryObject = obj["/Resources"]["/Font"][font_name] # type: ignore + font_subtype, font_halfspace, font_encoding, font_map = build_char_map_from_dict( + space_width, ft + ) + return font_subtype, font_halfspace, font_encoding, font_map, ft + + +def build_char_map_from_dict( + space_width: float, ft: DictionaryObject +) -> Tuple[str, float, Union[str, Dict[int, str]], Dict[Any, Any]]: + """ + Determine information about a font. + + Args: + space_width: default space with if no data found + (normally half the width of a character). + ft: Font Dictionary + + Returns: + Font sub-type, space_width criteria(50% of width), encoding, map character-map. + The font-dictionary itself is suitable for the curious. + + """ + font_type = cast(str, ft["/Subtype"].get_object()) + encoding, map_dict = get_encoding(ft) + + space_key_char = get_actual_str_key(" ", encoding, map_dict) + font_width_map = build_font_width_map(ft, space_width * 2.0) + half_space_width = compute_space_width(font_width_map, space_key_char) / 2.0 + + return ( + font_type, + half_space_width, + encoding, + # https://github.com/python/mypy/issues/4374 + map_dict + ) + + +# used when missing data, e.g. font def missing +unknown_char_map: Tuple[str, float, Union[str, Dict[int, str]], Dict[Any, Any]] = ( + "Unknown", + 9999, + dict.fromkeys(range(256), "�"), + {}, +) + + +_predefined_cmap: Dict[str, str] = { + "/Identity-H": "utf-16-be", + "/Identity-V": "utf-16-be", + "/GB-EUC-H": "gbk", + "/GB-EUC-V": "gbk", + "/GBpc-EUC-H": "gb2312", + "/GBpc-EUC-V": "gb2312", + "/GBK-EUC-H": "gbk", + "/GBK-EUC-V": "gbk", + "/GBK2K-H": "gb18030", + "/GBK2K-V": "gb18030", + "/ETen-B5-H": "cp950", + "/ETen-B5-V": "cp950", + "/ETenms-B5-H": "cp950", + "/ETenms-B5-V": "cp950", + "/UniCNS-UTF16-H": "utf-16-be", + "/UniCNS-UTF16-V": "utf-16-be", + "/UniGB-UTF16-H": "gb18030", + "/UniGB-UTF16-V": "gb18030", + # UCS2 in code +} + +# manually extracted from http://mirrors.ctan.org/fonts/adobe/afm/Adobe-Core35_AFMs-229.tar.gz +_default_fonts_space_width: Dict[str, int] = { + "/Courier": 600, + "/Courier-Bold": 600, + "/Courier-BoldOblique": 600, + "/Courier-Oblique": 600, + "/Helvetica": 278, + "/Helvetica-Bold": 278, + "/Helvetica-BoldOblique": 278, + "/Helvetica-Oblique": 278, + "/Helvetica-Narrow": 228, + "/Helvetica-NarrowBold": 228, + "/Helvetica-NarrowBoldOblique": 228, + "/Helvetica-NarrowOblique": 228, + "/Times-Roman": 250, + "/Times-Bold": 250, + "/Times-BoldItalic": 250, + "/Times-Italic": 250, + "/Symbol": 250, + "/ZapfDingbats": 278, +} + + +def get_encoding( + ft: DictionaryObject +) -> Tuple[Union[str, Dict[int, str]], Dict[Any, Any]]: + encoding = _parse_encoding(ft) + map_dict, int_entry = _parse_to_unicode(ft) + + # Apply rule from PDF ref 1.7 §5.9.1, 1st bullet: + # if cmap not empty encoding should be discarded + # (here transformed into identity for those characters) + # If encoding is a string it is expected to be an identity translation. + if isinstance(encoding, dict): + for x in int_entry: + if x <= 255: + encoding[x] = chr(x) + + return encoding, map_dict + + +def _parse_encoding( + ft: DictionaryObject +) -> Union[str, Dict[int, str]]: + encoding: Union[str, List[str], Dict[int, str]] = [] + if "/Encoding" not in ft: + if "/BaseFont" in ft and cast(str, ft["/BaseFont"]) in charset_encoding: + encoding = dict( + zip(range(256), charset_encoding[cast(str, ft["/BaseFont"])]) + ) + else: + encoding = "charmap" + return encoding + enc: Union(str, DictionaryObject) = ft["/Encoding"].get_object() # type: ignore + if isinstance(enc, str): + try: + # already done : enc = NameObject.unnumber(enc.encode()).decode() + # for #xx decoding + if enc in charset_encoding: + encoding = charset_encoding[enc].copy() + elif enc in _predefined_cmap: + encoding = _predefined_cmap[enc] + elif "-UCS2-" in enc: + encoding = "utf-16-be" + else: + raise Exception("not found") + except Exception: + logger_error(f"Advanced encoding {enc} not implemented yet", __name__) + encoding = enc + elif isinstance(enc, DictionaryObject) and "/BaseEncoding" in enc: + try: + encoding = charset_encoding[cast(str, enc["/BaseEncoding"])].copy() + except Exception: + logger_error( + f"Advanced encoding {encoding} not implemented yet", + __name__, + ) + encoding = charset_encoding["/StandardEncoding"].copy() + else: + encoding = charset_encoding["/StandardEncoding"].copy() + if "/Differences" in enc: + x: int = 0 + o: Union[int, str] + for o in cast(DictionaryObject, cast(DictionaryObject, enc)["/Differences"]): + if isinstance(o, int): + x = o + else: # isinstance(o,str): + try: + if x < len(encoding): + encoding[x] = adobe_glyphs[o] # type: ignore + except Exception: + encoding[x] = o # type: ignore + x += 1 + if isinstance(encoding, list): + encoding = dict(zip(range(256), encoding)) + return encoding + + +def _parse_to_unicode( + ft: DictionaryObject +) -> Tuple[Dict[Any, Any], List[int]]: + # will store all translation code + # and map_dict[-1] we will have the number of bytes to convert + map_dict: Dict[Any, Any] = {} + + # will provide the list of cmap keys as int to correct encoding + int_entry: List[int] = [] + + if "/ToUnicode" not in ft: + if ft.get("/Subtype", "") == "/Type1": + return _type1_alternative(ft, map_dict, int_entry) + else: + return {}, [] + process_rg: bool = False + process_char: bool = False + multiline_rg: Union[ + None, Tuple[int, int] + ] = None # tuple = (current_char, remaining size) ; cf #1285 for example of file + cm = prepare_cm(ft) + for line in cm.split(b"\n"): + process_rg, process_char, multiline_rg = process_cm_line( + line.strip(b" \t"), + process_rg, + process_char, + multiline_rg, + map_dict, + int_entry, + ) + + return map_dict, int_entry + + +def get_actual_str_key( + value_char: str, encoding: Union[str, Dict[int, str]], map_dict: Dict[Any, Any] +) -> str: + key_dict = {} + if isinstance(encoding, dict): + key_dict = {value: chr(key) for key, value in encoding.items() if value == value_char} + else: + key_dict = {value: key for key, value in map_dict.items() if value == value_char} + key_char = key_dict.get(value_char, value_char) + return key_char + + +def prepare_cm(ft: DictionaryObject) -> bytes: + tu = ft["/ToUnicode"] + cm: bytes + if isinstance(tu, StreamObject): + cm = cast(DecodedStreamObject, ft["/ToUnicode"]).get_data() + else: # if (tu is None) or cast(str, tu).startswith("/Identity"): + # the full range 0000-FFFF will be processed + cm = b"beginbfrange\n<0000> <0001> <0000>\nendbfrange" + if isinstance(cm, str): + cm = cm.encode() + # we need to prepare cm before due to missing return line in pdf printed + # to pdf from word + cm = ( + cm.strip() + .replace(b"beginbfchar", b"\nbeginbfchar\n") + .replace(b"endbfchar", b"\nendbfchar\n") + .replace(b"beginbfrange", b"\nbeginbfrange\n") + .replace(b"endbfrange", b"\nendbfrange\n") + .replace(b"<<", b"\n{\n") # text between << and >> not used but + .replace(b">>", b"\n}\n") # some solution to find it back + ) + ll = cm.split(b"<") + for i in range(len(ll)): + j = ll[i].find(b">") + if j >= 0: + if j == 0: + # string is empty: stash a placeholder here (see below) + # see https://github.com/py-pdf/pypdf/issues/1111 + content = b"." + else: + content = ll[i][:j].replace(b" ", b"") + ll[i] = content + b" " + ll[i][j + 1 :] + cm = ( + (b" ".join(ll)) + .replace(b"[", b" [ ") + .replace(b"]", b" ]\n ") + .replace(b"\r", b"\n") + ) + return cm + + +def process_cm_line( + line: bytes, + process_rg: bool, + process_char: bool, + multiline_rg: Union[None, Tuple[int, int]], + map_dict: Dict[Any, Any], + int_entry: List[int], +) -> Tuple[bool, bool, Union[None, Tuple[int, int]]]: + if line == b"" or line[0] == 37: # 37 = % + return process_rg, process_char, multiline_rg + line = line.replace(b"\t", b" ") + if b"beginbfrange" in line: + process_rg = True + elif b"endbfrange" in line: + process_rg = False + elif b"beginbfchar" in line: + process_char = True + elif b"endbfchar" in line: + process_char = False + elif process_rg: + try: + multiline_rg = parse_bfrange(line, map_dict, int_entry, multiline_rg) + except binascii.Error as error: + logger_warning(f"Skipping broken line {line!r}: {error}", __name__) + elif process_char: + parse_bfchar(line, map_dict, int_entry) + return process_rg, process_char, multiline_rg + + +def parse_bfrange( + line: bytes, + map_dict: Dict[Any, Any], + int_entry: List[int], + multiline_rg: Union[None, Tuple[int, int]], +) -> Union[None, Tuple[int, int]]: + lst = [x for x in line.split(b" ") if x] + closure_found = False + if multiline_rg is not None: + fmt = b"%%0%dX" % (map_dict[-1] * 2) + a = multiline_rg[0] # a, b not in the current line + b = multiline_rg[1] + for sq in lst[0:]: + if sq == b"]": + closure_found = True + break + map_dict[ + unhexlify(fmt % a).decode( + "charmap" if map_dict[-1] == 1 else "utf-16-be", + "surrogatepass", + ) + ] = unhexlify(sq).decode("utf-16-be", "surrogatepass") + int_entry.append(a) + a += 1 + else: + a = int(lst[0], 16) + b = int(lst[1], 16) + nbi = max(len(lst[0]), len(lst[1])) + map_dict[-1] = ceil(nbi / 2) + fmt = b"%%0%dX" % (map_dict[-1] * 2) + if lst[2] == b"[": + for sq in lst[3:]: + if sq == b"]": + closure_found = True + break + map_dict[ + unhexlify(fmt % a).decode( + "charmap" if map_dict[-1] == 1 else "utf-16-be", + "surrogatepass", + ) + ] = unhexlify(sq).decode("utf-16-be", "surrogatepass") + int_entry.append(a) + a += 1 + else: # case without list + c = int(lst[2], 16) + fmt2 = b"%%0%dX" % max(4, len(lst[2])) + closure_found = True + while a <= b: + map_dict[ + unhexlify(fmt % a).decode( + "charmap" if map_dict[-1] == 1 else "utf-16-be", + "surrogatepass", + ) + ] = unhexlify(fmt2 % c).decode("utf-16-be", "surrogatepass") + int_entry.append(a) + a += 1 + c += 1 + return None if closure_found else (a, b) + + +def parse_bfchar(line: bytes, map_dict: Dict[Any, Any], int_entry: List[int]) -> None: + lst = [x for x in line.split(b" ") if x] + map_dict[-1] = len(lst[0]) // 2 + while len(lst) > 1: + map_to = "" + # placeholder (see above) means empty string + if lst[1] != b".": + map_to = unhexlify(lst[1]).decode( + "charmap" if len(lst[1]) < 4 else "utf-16-be", "surrogatepass" + ) # join is here as some cases where the code was split + map_dict[ + unhexlify(lst[0]).decode( + "charmap" if map_dict[-1] == 1 else "utf-16-be", "surrogatepass" + ) + ] = map_to + int_entry.append(int(lst[0], 16)) + lst = lst[2:] + + +def build_font_width_map( + ft: DictionaryObject, default_font_width: float +) -> Dict[Any, float]: + font_width_map: Dict[Any, float] = {} + st: int = 0 + en: int = 0 + try: + default_font_width = _default_fonts_space_width[cast(str, ft["/BaseFont"].get_object())] * 2.0 + except KeyError: + pass + if "/DescendantFonts" in ft: # ft["/Subtype"].startswith("/CIDFontType"): + # §9.7.4.3 of the 1.7 reference ("Glyph Metrics in CIDFonts") + # Widths for a CIDFont are defined using the DW and W entries. + # DW2 and W2 are for vertical use. Vertical type is not implemented. + ft1 = ft["/DescendantFonts"][0].get_object() # type: ignore + if "/DW" in ft1: + font_width_map["default"] = cast(float, ft1["/DW"].get_object()) + else: + font_width_map["default"] = default_font_width + if "/W" in ft1: + w = ft1["/W"].get_object() + else: + w = [] + while len(w) > 0: + st = w[0] if isinstance(w[0], int) else w[0].get_object() + second = w[1].get_object() + if isinstance(second, int): + # C_first C_last same_W + en = second + width = w[2].get_object() + if not isinstance(width, (int, float)): + logger_warning(f"Expected numeric value for width, got {width}. Ignoring it.", __name__) + w = w[3:] + continue + for c_code in range(st, en + 1): + font_width_map[chr(c_code)] = width + w = w[3:] + elif isinstance(second, list): + # Starting_C [W1 W2 ... Wn] + c_code = st + for ww in second: + width = ww.get_object() + font_width_map[chr(c_code)] = width + c_code += 1 + w = w[2:] + else: + logger_warning( + "unknown widths : \n" + (ft1["/W"]).__repr__(), + __name__, + ) + break + elif "/Widths" in ft: + w = ft["/Widths"].get_object() + if "/FontDescriptor" in ft and "/MissingWidth" in cast( + DictionaryObject, ft["/FontDescriptor"] + ): + font_width_map["default"] = ft["/FontDescriptor"]["/MissingWidth"].get_object() # type: ignore + else: + # will consider width of char as avg(width) + m = 0 + cpt = 0 + for xx in w: + xx = xx.get_object() + if xx > 0: + m += xx + cpt += 1 + font_width_map["default"] = m / max(1, cpt) + st = cast(int, ft["/FirstChar"]) + en = cast(int, ft["/LastChar"]) + for c_code in range(st, en + 1): + try: + width = w[c_code - st].get_object() + font_width_map[chr(c_code)] = width + except (IndexError, KeyError): + # The PDF structure is invalid. The array is too small + # for the specified font width. + pass + if is_null_or_none(font_width_map.get("default")): + font_width_map["default"] = default_font_width if default_font_width else 0.0 + return font_width_map + + +def compute_space_width( + font_width_map: Dict[Any, float], space_char: str +) -> float: + try: + sp_width = font_width_map[space_char] + if sp_width == 0: + raise ValueError("Zero width") + except (KeyError, ValueError): + sp_width = ( + font_width_map["default"] / 2.0 + ) # if using default we consider space will be only half size + + return sp_width + + +def compute_font_width( + font_width_map: Dict[Any, float], + char: str +) -> float: + char_width: float = 0.0 + try: + char_width = font_width_map[char] + except KeyError: + char_width = ( + font_width_map["default"] + ) + + return char_width + + +def _type1_alternative( + ft: DictionaryObject, + map_dict: Dict[Any, Any], + int_entry: List[int], +) -> Tuple[Dict[Any, Any], List[int]]: + if "/FontDescriptor" not in ft: + return map_dict, int_entry + ft_desc = cast(DictionaryObject, ft["/FontDescriptor"]).get("/FontFile") + if is_null_or_none(ft_desc): + return map_dict, int_entry + assert ft_desc is not None, "mypy" + txt = ft_desc.get_object().get_data() + txt = txt.split(b"eexec\n")[0] # only clear part + txt = txt.split(b"/Encoding")[1] # to get the encoding part + lines = txt.replace(b"\r", b"\n").split(b"\n") + for li in lines: + if li.startswith(b"dup"): + words = [_w for _w in li.split(b" ") if _w != b""] + if len(words) > 3 and words[3] != b"put": + continue + try: + i = int(words[1]) + except ValueError: # pragma: no cover + continue + try: + v = adobe_glyphs[words[2].decode()] + except KeyError: + if words[2].startswith(b"/uni"): + try: + v = chr(int(words[2][4:], 16)) + except ValueError: # pragma: no cover + continue + else: + continue + map_dict[chr(i)] = v + int_entry.append(i) + return map_dict, int_entry diff --git a/venv/lib/python3.12/site-packages/pypdf/_codecs/__init__.py b/venv/lib/python3.12/site-packages/pypdf/_codecs/__init__.py new file mode 100644 index 0000000..540bcc4 --- /dev/null +++ b/venv/lib/python3.12/site-packages/pypdf/_codecs/__init__.py @@ -0,0 +1,61 @@ +from typing import Dict, List + +from .adobe_glyphs import adobe_glyphs +from .pdfdoc import _pdfdoc_encoding +from .std import _std_encoding +from .symbol import _symbol_encoding +from .zapfding import _zapfding_encoding + + +def fill_from_encoding(enc: str) -> List[str]: + lst: List[str] = [] + for x in range(256): + try: + lst += (bytes((x,)).decode(enc),) + except Exception: + lst += (chr(x),) + return lst + + +def rev_encoding(enc: List[str]) -> Dict[str, int]: + rev: Dict[str, int] = {} + for i in range(256): + char = enc[i] + if char == "\u0000": + continue + assert char not in rev, f"{char} at {i} already at {rev[char]}" + rev[char] = i + return rev + + +_win_encoding = fill_from_encoding("cp1252") +_mac_encoding = fill_from_encoding("mac_roman") + + +_win_encoding_rev: Dict[str, int] = rev_encoding(_win_encoding) +_mac_encoding_rev: Dict[str, int] = rev_encoding(_mac_encoding) +_symbol_encoding_rev: Dict[str, int] = rev_encoding(_symbol_encoding) +_zapfding_encoding_rev: Dict[str, int] = rev_encoding(_zapfding_encoding) +_pdfdoc_encoding_rev: Dict[str, int] = rev_encoding(_pdfdoc_encoding) + + +charset_encoding: Dict[str, List[str]] = { + "/StandardEncoding": _std_encoding, + "/WinAnsiEncoding": _win_encoding, + "/MacRomanEncoding": _mac_encoding, + "/PDFDocEncoding": _pdfdoc_encoding, + "/Symbol": _symbol_encoding, + "/ZapfDingbats": _zapfding_encoding, +} + +__all__ = [ + "_mac_encoding", + "_pdfdoc_encoding", + "_pdfdoc_encoding_rev", + "_std_encoding", + "_symbol_encoding", + "_win_encoding", + "_zapfding_encoding", + "adobe_glyphs", + "charset_encoding", +] diff --git a/venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce60f94f023fff34fd4ed0e4919ef33cf3719f83 GIT binary patch literal 2231 zcmZ`)O>7%Q6rR~1|HO9u6X%zvHI19pg?35PqM}xs54_Hu7A>lKX9GI|TCNX0pn$0?lWQXEDqr}8;I&!>2s z7ji;gOo=ux=3IGq%5C$moG0&1d2QaE>&W|3KHxpXuX+hb{QYoDMo>FG5>f%sZfU@V ziJx?4xGlR6>_HBZfa<>w@vxN&*>b>?!ZJChPX+Hgo#MJ#HV(B?n?F9sCH)T`$OzehRq_i`%9ea zFZCpPAAyV#oFyc+v}p;iYliuVB_@F_zoHgqh@8!pin9jDA-Sk#)IwS&db*%$dKPp6 z*)Y}ZijZuS@-v0pc3niCSBe?7!_itiII&!mn3t)Z-l_x(1;P74Jp9(b0JRgAlcquM`hiNo~Om?!p;)q5t z^XqME%G}O<7tzw`E9feJ5naIvZt4+&7!#r;Qbo@aOPnd0#IRf{flLw0J8?Blil$c3 zEj~R<6Fl{SXN%7nriHH>Ec{q3wvm!%3wa`GSzTjT>3jj00=+;BSxO8;nj`w0l+$LU zV#%B>=wpXQ4@-t-l7mGheM!j@0}N0iNoI$p4M~ zWsPePAPcD3-McXUYamh?`#ALk3F6=)ZgISKu;~weHc=g|#&5s&b98t$I$Sdv(HH7n z2Uq|Kp>VJap=BDu~zI~?h%Bp|Y&G8lw$_*n3Cw;o-DEDpO z>5%wC5Ci>J^*vy>t3L=cWnAXj6u67N5bwj6tq*aTV|vyVO9wVzLPDIPogi;uG%v&yGdAy!DLG0MwZx&23MIQ_F8xV;#;xmMdKxJ$&@A<;^Q;8OpEdR#?8G=}urWyFplH=5}M- zs_4#6wzWO~?d2`>j^V(x3DP4t2hSq2+<=5emcK@HH?y#Z zw&6LEFQ}Jux^whJvdlVt7Esc76O);R?;hd_omjF__zm!hibaJREbxNYO>aK XXR`ACYGjz*kb4s8@Nplw?cDtXYlTIV literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/_codecs.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/_codecs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fcee131857bc58b32d6d8b8335cc3fad65d4b42d GIT binary patch literal 9812 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 L9jsEZ!MC literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/adobe_glyphs.cpython-312.pyc b/venv/lib/python3.12/site-packages/pypdf/_codecs/__pycache__/adobe_glyphs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..808f013cc1f2acc74a671b1c8018ed3d21c4b45f GIT binary patch literal 691154 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�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