aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/PyPDF2
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/PyPDF2')
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/__init__.py41
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_cmap.py413
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_codecs/__init__.py63
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_codecs/adobe_glyphs.py13437
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_codecs/pdfdoc.py264
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_codecs/std.py258
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_codecs/symbol.py260
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_codecs/zapfding.py261
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_encryption.py895
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_merger.py821
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_page.py2114
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_protocols.py62
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_reader.py1977
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_security.py252
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_utils.py471
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_version.py1
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/_writer.py2822
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/constants.py461
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/errors.py54
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/filters.py645
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/generic/__init__.py144
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/generic/_annotations.py275
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/generic/_base.py648
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/generic/_data_structures.py1382
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/generic/_fit.py129
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/generic/_outline.py35
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/generic/_rectangle.py265
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/generic/_utils.py172
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/pagerange.py173
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/papersizes.py48
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/py.typed0
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/types.py52
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/xmp.py525
33 files changed, 29420 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/__init__.py b/.venv/lib/python3.12/site-packages/PyPDF2/__init__.py
new file mode 100644
index 00000000..4154ee64
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/__init__.py
@@ -0,0 +1,41 @@
+"""
+PyPDF2 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. PyPDF2 can retrieve
+text and metadata from PDFs as well.
+
+You can read the full docs at https://pypdf2.readthedocs.io/.
+"""
+
+import warnings
+
+from ._encryption import PasswordType
+from ._merger import PdfFileMerger, PdfMerger
+from ._page import PageObject, Transformation
+from ._reader import DocumentInformation, PdfFileReader, PdfReader
+from ._version import __version__
+from ._writer import PdfFileWriter, PdfWriter
+from .pagerange import PageRange, parse_filename_page_ranges
+from .papersizes import PaperSize
+
+warnings.warn(
+ message="PyPDF2 is deprecated. Please move to the pypdf library instead.",
+ category=DeprecationWarning,
+)
+
+__all__ = [
+ "__version__",
+ "PageRange",
+ "PaperSize",
+ "DocumentInformation",
+ "parse_filename_page_ranges",
+ "PdfFileMerger", # will be removed in PyPDF2 3.0.0; use PdfMerger instead
+ "PdfFileReader", # will be removed in PyPDF2 3.0.0; use PdfReader instead
+ "PdfFileWriter", # will be removed in PyPDF2 3.0.0; use PdfWriter instead
+ "PdfMerger",
+ "PdfReader",
+ "PdfWriter",
+ "Transformation",
+ "PageObject",
+ "PasswordType",
+]
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/_cmap.py b/.venv/lib/python3.12/site-packages/PyPDF2/_cmap.py
new file mode 100644
index 00000000..db082a82
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_cmap.py
@@ -0,0 +1,413 @@
+import warnings
+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_warning
+from .errors import PdfReadWarning
+from .generic import DecodedStreamObject, DictionaryObject, StreamObject
+
+
+# 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, DictionaryObject
+]: # font_type,space_width /2, encoding, cmap
+ """Determine information about a font.
+
+ This function returns a tuple consisting of:
+ font sub-type, space_width/2, 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_type: str = cast(str, ft["/Subtype"])
+
+ space_code = 32
+ encoding, space_code = parse_encoding(ft, space_code)
+ map_dict, space_code, int_entry = parse_to_unicode(ft, space_code)
+
+ # encoding can be either a string for decode (on 1,2 or a variable number of bytes) of a char table (for 1 byte only for me)
+ # if empty string, it means it is than encoding field is not present and we have to select the good encoding from cmap input data
+ if encoding == "":
+ if -1 not in map_dict or map_dict[-1] == 1:
+ # I have not been able to find any rule for no /Encoding nor /ToUnicode
+ # One example shows /Symbol,bold I consider 8 bits encoding default
+ encoding = "charmap"
+ else:
+ encoding = "utf-16-be"
+ # 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 an str it is expected to be a identity translation
+ elif isinstance(encoding, dict):
+ for x in int_entry:
+ if x <= 255:
+ encoding[x] = chr(x)
+ try:
+ # override space_width with new params
+ space_width = _default_fonts_space_width[cast(str, ft["/BaseFont"])]
+ except Exception:
+ pass
+ # I conside the space_code is available on one byte
+ if isinstance(space_code, str):
+ try: # one byte
+ sp = space_code.encode("charmap")[0]
+ except Exception:
+ sp = space_code.encode("utf-16-be")
+ sp = sp[0] + 256 * sp[1]
+ else:
+ sp = space_code
+ sp_width = compute_space_width(ft, sp, space_width)
+
+ return (
+ font_type,
+ float(sp_width / 2),
+ encoding,
+ # https://github.com/python/mypy/issues/4374
+ map_dict,
+ ft,
+ )
+
+
+# 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(zip(range(256), ["�"] * 256)),
+ {},
+)
+
+
+_predefined_cmap: Dict[str, str] = {
+ "/Identity-H": "utf-16-be",
+ "/Identity-V": "utf-16-be",
+ "/GB-EUC-H": "gbk", # TBC
+ "/GB-EUC-V": "gbk", # TBC
+ "/GBpc-EUC-H": "gb2312", # TBC
+ "/GBpc-EUC-V": "gb2312", # TBC
+}
+
+
+# manually extracted from http://mirrors.ctan.org/fonts/adobe/afm/Adobe-Core35_AFMs-229.tar.gz
+_default_fonts_space_width: Dict[str, int] = {
+ "/Courrier": 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 parse_encoding(
+ ft: DictionaryObject, space_code: int
+) -> Tuple[Union[str, Dict[int, str]], int]:
+ encoding: Union[str, List[str], Dict[int, str]] = []
+ if "/Encoding" not in ft:
+ try:
+ 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, _default_fonts_space_width[cast(str, ft["/BaseFont"])]
+ except Exception:
+ if cast(str, ft["/Subtype"]) == "/Type1":
+ return "charmap", space_code
+ else:
+ return "", space_code
+ enc: Union(str, DictionaryObject) = ft["/Encoding"].get_object() # type: ignore
+ if isinstance(enc, str):
+ try:
+ # allready 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]
+ else:
+ raise Exception("not found")
+ except Exception:
+ warnings.warn(
+ f"Advanced encoding {enc} not implemented yet",
+ PdfReadWarning,
+ )
+ encoding = enc
+ elif isinstance(enc, DictionaryObject) and "/BaseEncoding" in enc:
+ try:
+ encoding = charset_encoding[cast(str, enc["/BaseEncoding"])].copy()
+ except Exception:
+ warnings.warn(
+ f"Advanced encoding {encoding} not implemented yet",
+ PdfReadWarning,
+ )
+ encoding = charset_encoding["/StandardCoding"].copy()
+ else:
+ encoding = charset_encoding["/StandardCoding"].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:
+ encoding[x] = adobe_glyphs[o] # type: ignore
+ except Exception:
+ encoding[x] = o # type: ignore
+ if o == " ":
+ space_code = x
+ x += 1
+ if isinstance(encoding, list):
+ encoding = dict(zip(range(256), encoding))
+ return encoding, space_code
+
+
+def parse_to_unicode(
+ ft: DictionaryObject, space_code: int
+) -> Tuple[Dict[Any, Any], int, 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:
+ return {}, space_code, []
+ 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 l in cm.split(b"\n"):
+ process_rg, process_char, multiline_rg = process_cm_line(
+ l.strip(b" "), process_rg, process_char, multiline_rg, map_dict, int_entry
+ )
+
+ for a, value in map_dict.items():
+ if value == " ":
+ space_code = a
+ return map_dict, space_code, int_entry
+
+
+def prepare_cm(ft: DictionaryObject) -> bytes:
+ tu = ft["/ToUnicode"]
+ cm: bytes
+ if isinstance(tu, StreamObject):
+ cm = cast(DecodedStreamObject, ft["/ToUnicode"]).get_data()
+ elif isinstance(tu, str) and tu.startswith("/Identity"):
+ cm = b"beginbfrange\n<0000> <0001> <0000>\nendbfrange" # the full range 0000-FFFF will be processed
+ 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/PyPDF2/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(
+ l: 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 l in (b"", b" ") or l[0] == 37: # 37 = %
+ return process_rg, process_char, multiline_rg
+ if b"beginbfrange" in l:
+ process_rg = True
+ elif b"endbfrange" in l:
+ process_rg = False
+ elif b"beginbfchar" in l:
+ process_char = True
+ elif b"endbfchar" in l:
+ process_char = False
+ elif process_rg:
+ multiline_rg = parse_bfrange(l, map_dict, int_entry, multiline_rg)
+ elif process_char:
+ parse_bfchar(l, map_dict, int_entry)
+ return process_rg, process_char, multiline_rg
+
+
+def parse_bfrange(
+ l: 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 l.split(b" ") if x]
+ closure_found = False
+ nbi = max(len(lst[0]), len(lst[1]))
+ map_dict[-1] = ceil(nbi / 2)
+ fmt = b"%%0%dX" % (map_dict[-1] * 2)
+ if multiline_rg is not None:
+ a = multiline_rg[0] # a, b not in the current line
+ b = multiline_rg[1]
+ for sq in lst[1:]:
+ 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)
+ 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(l: bytes, map_dict: Dict[Any, Any], int_entry: List[int]) -> None:
+ lst = [x for x in l.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 compute_space_width(
+ ft: DictionaryObject, space_code: int, space_width: float
+) -> float:
+ sp_width: float = space_width * 2 # default value
+ w = []
+ w1 = {}
+ st: int = 0
+ if "/DescendantFonts" in ft: # ft["/Subtype"].startswith("/CIDFontType"):
+ ft1 = ft["/DescendantFonts"][0].get_object() # type: ignore
+ try:
+ w1[-1] = cast(float, ft1["/DW"])
+ except Exception:
+ w1[-1] = 1000.0
+ if "/W" in ft1:
+ w = list(ft1["/W"])
+ else:
+ w = []
+ while len(w) > 0:
+ st = w[0]
+ second = w[1]
+ if isinstance(second, int):
+ for x in range(st, second):
+ w1[x] = w[2]
+ w = w[3:]
+ elif isinstance(second, list):
+ for y in second:
+ w1[st] = y
+ st += 1
+ w = w[2:]
+ else:
+ logger_warning(
+ "unknown widths : \n" + (ft1["/W"]).__repr__(),
+ __name__,
+ )
+ break
+ try:
+ sp_width = w1[space_code]
+ except Exception:
+ sp_width = (
+ w1[-1] / 2.0
+ ) # if using default we consider space will be only half size
+ elif "/Widths" in ft:
+ w = list(ft["/Widths"]) # type: ignore
+ try:
+ st = cast(int, ft["/FirstChar"])
+ en: int = cast(int, ft["/LastChar"])
+ if st > space_code or en < space_code:
+ raise Exception("Not in range")
+ if w[space_code - st] == 0:
+ raise Exception("null width")
+ sp_width = w[space_code - st]
+ except Exception:
+ if "/FontDescriptor" in ft and "/MissingWidth" in cast(
+ DictionaryObject, ft["/FontDescriptor"]
+ ):
+ sp_width = ft["/FontDescriptor"]["/MissingWidth"] # type: ignore
+ else:
+ # will consider width of char as avg(width)/2
+ m = 0
+ cpt = 0
+ for x in w:
+ if x > 0:
+ m += x
+ cpt += 1
+ sp_width = m / max(1, cpt) / 2
+ return sp_width
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/_codecs/__init__.py b/.venv/lib/python3.12/site-packages/PyPDF2/_codecs/__init__.py
new file mode 100644
index 00000000..7e056181
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_codecs/__init__.py
@@ -0,0 +1,63 @@
+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, (
+ str(char) + " at " + str(i) + " already at " + str(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]] = {
+ "/StandardCoding": _std_encoding,
+ "/WinAnsiEncoding": _win_encoding,
+ "/MacRomanEncoding": _mac_encoding,
+ "/PDFDocEncoding": _pdfdoc_encoding,
+ "/Symbol": _symbol_encoding,
+ "/ZapfDingbats": _zapfding_encoding,
+}
+
+__all__ = [
+ "adobe_glyphs",
+ "_std_encoding",
+ "_symbol_encoding",
+ "_zapfding_encoding",
+ "_pdfdoc_encoding",
+ "_pdfdoc_encoding_rev",
+ "_win_encoding",
+ "_mac_encoding",
+ "charset_encoding",
+]
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/_codecs/adobe_glyphs.py b/.venv/lib/python3.12/site-packages/PyPDF2/_codecs/adobe_glyphs.py
new file mode 100644
index 00000000..6d8f7fbd
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_codecs/adobe_glyphs.py
@@ -0,0 +1,13437 @@
+# 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 = {
+ "/.notdef": "\u0000",
+ "/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",
+}
+
+
+def _complete() -> None:
+ global adobe_glyphs
+ 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/PyPDF2/_codecs/pdfdoc.py b/.venv/lib/python3.12/site-packages/PyPDF2/_codecs/pdfdoc.py
new file mode 100644
index 00000000..306357a5
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_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/PyPDF2/_codecs/std.py b/.venv/lib/python3.12/site-packages/PyPDF2/_codecs/std.py
new file mode 100644
index 00000000..a6057ff3
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_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/PyPDF2/_codecs/symbol.py b/.venv/lib/python3.12/site-packages/PyPDF2/_codecs/symbol.py
new file mode 100644
index 00000000..4c0d680f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_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/PyPDF2/_codecs/zapfding.py b/.venv/lib/python3.12/site-packages/PyPDF2/_codecs/zapfding.py
new file mode 100644
index 00000000..9b6cdbcc
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_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/PyPDF2/_encryption.py b/.venv/lib/python3.12/site-packages/PyPDF2/_encryption.py
new file mode 100644
index 00000000..5c80e600
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_encryption.py
@@ -0,0 +1,895 @@
+# 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 random
+import struct
+from enum import IntEnum
+from typing import Any, Dict, Optional, Tuple, Union, cast
+
+from ._utils import logger_warning
+from .errors import DependencyError
+from .generic import (
+ ArrayObject,
+ ByteStringObject,
+ DictionaryObject,
+ PdfObject,
+ StreamObject,
+ TextStringObject,
+ create_string_object,
+)
+
+
+class CryptBase:
+ def encrypt(self, data: bytes) -> bytes: # pragma: no cover
+ return data
+
+ def decrypt(self, data: bytes) -> bytes: # pragma: no cover
+ return data
+
+
+class CryptIdentity(CryptBase):
+ pass
+
+
+try:
+ from Crypto.Cipher import AES, ARC4 # type: ignore[import]
+ from Crypto.Util.Padding import pad # type: ignore[import]
+
+ 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 = bytes(bytearray(random.randint(0, 255) for _ in range(16)))
+ p = 16 - len(data) % 16
+ data += bytes(bytearray(p for _ in range(p)))
+ 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:]
+ aes = AES.new(self.key, AES.MODE_CBC, iv)
+ if len(data) % 16:
+ data = pad(data, 16)
+ d = aes.decrypt(data)
+ if len(d) == 0:
+ return d
+ else:
+ 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)
+
+except ImportError:
+
+ class CryptRC4(CryptBase): # type: ignore
+ def __init__(self, key: bytes) -> None:
+ self.S = list(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 = list(self.S)
+ out = list(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(bytearray(out))
+
+ def decrypt(self, data: bytes) -> bytes:
+ return self.encrypt(data)
+
+ class CryptAES(CryptBase): # type: ignore
+ def __init__(self, key: bytes) -> None:
+ pass
+
+ def encrypt(self, data: bytes) -> bytes:
+ raise DependencyError("PyCryptodome is required for AES algorithm")
+
+ def decrypt(self, data: bytes) -> bytes:
+ raise DependencyError("PyCryptodome is required for AES algorithm")
+
+ 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("PyCryptodome is required for AES algorithm")
+
+ def AES_ECB_decrypt(key: bytes, data: bytes) -> bytes:
+ raise DependencyError("PyCryptodome is required for AES algorithm")
+
+ def AES_CBC_encrypt(key: bytes, iv: bytes, data: bytes) -> bytes:
+ raise DependencyError("PyCryptodome is required for AES algorithm")
+
+ def AES_CBC_decrypt(key: bytes, iv: bytes, data: bytes) -> bytes:
+ raise DependencyError("PyCryptodome is required for AES algorithm")
+
+
+class CryptFilter:
+ def __init__(
+ self, stmCrypt: CryptBase, strCrypt: CryptBase, efCrypt: CryptBase
+ ) -> None:
+ self.stmCrypt = stmCrypt
+ self.strCrypt = strCrypt
+ self.efCrypt = efCrypt
+
+ def encrypt_object(self, obj: PdfObject) -> PdfObject:
+ # TODO
+ return NotImplemented
+
+ def decrypt_object(self, obj: PdfObject) -> PdfObject:
+ if isinstance(obj, (ByteStringObject, TextStringObject)):
+ data = self.strCrypt.decrypt(obj.original_bytes)
+ obj = create_string_object(data)
+ elif isinstance(obj, StreamObject):
+ obj._data = self.stmCrypt.decrypt(obj._data)
+ elif isinstance(obj, DictionaryObject):
+ for dictkey, value in list(obj.items()):
+ obj[dictkey] = self.decrypt_object(value)
+ elif isinstance(obj, ArrayObject):
+ for i in range(len(obj)):
+ obj[i] = self.decrypt_object(obj[i])
+ return obj
+
+
+_PADDING = bytes(
+ [
+ 0x28,
+ 0xBF,
+ 0x4E,
+ 0x5E,
+ 0x4E,
+ 0x75,
+ 0x8A,
+ 0x41,
+ 0x64,
+ 0x00,
+ 0x4E,
+ 0x56,
+ 0xFF,
+ 0xFA,
+ 0x01,
+ 0x08,
+ 0x2E,
+ 0x2E,
+ 0x00,
+ 0xB6,
+ 0xD0,
+ 0x68,
+ 0x3E,
+ 0x80,
+ 0x2F,
+ 0x0C,
+ 0xA9,
+ 0xFE,
+ 0x64,
+ 0x53,
+ 0x69,
+ 0x7A,
+ ]
+)
+
+
+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.
+ """
+ a = _padding(password)
+ u_hash = hashlib.md5(a)
+ u_hash.update(o_entry)
+ u_hash.update(struct.pack("<I", P))
+ u_hash.update(id1_entry)
+ if rev >= 4 and metadata_encrypted is False:
+ 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.
+ """
+ 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()
+
+ rc4_key = o_hash_digest[: key_size // 8]
+ return rc4_key
+
+ @staticmethod
+ def compute_O_value(rc4_key: bytes, user_password: bytes, rev: int) -> bytes:
+ """See :func:`compute_O_value_key`."""
+ a = _padding(user_password)
+ rc4_enc = RC4_encrypt(rc4_key, a)
+ if rev >= 3:
+ for i in range(1, 20):
+ key = bytes(bytearray(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.
+ """
+ if rev <= 2:
+ value = RC4_encrypt(key, _PADDING)
+ return value
+
+ """
+ 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(bytearray(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.
+ """
+ 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.
+ """
+ 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(bytearray(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.
+ """
+ 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])
+ key = AES_CBC_decrypt(tmp_key, iv, oe_value)
+ return key
+
+ @staticmethod
+ def verify_user_password(
+ R: int, password: bytes, u_value: bytes, ue_value: bytes
+ ) -> bytes:
+ """See :func:`verify_owner_password`."""
+ 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:
+ # from 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`."""
+ b8 = b"T" if metadata_encrypted else b"F"
+ p1 = struct.pack("<I", p) + b"\xff\xff\xff\xff" + b8 + b"adb"
+ p2 = AES_ECB_decrypt(key, perms)
+ return p1 == p2[:12]
+
+ @staticmethod
+ def generate_values(
+ user_password: bytes,
+ owner_password: bytes,
+ key: bytes,
+ p: int,
+ metadata_encrypted: bool,
+ ) -> Dict[Any, Any]:
+ u_value, ue_value = AlgV5.compute_U_value(user_password, key)
+ o_value, oe_value = AlgV5.compute_O_value(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(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.
+ """
+ random_bytes = bytes(random.randrange(0, 256) for _ in range(16))
+ val_salt = random_bytes[:8]
+ key_salt = random_bytes[8:]
+ u_value = hashlib.sha256(password + val_salt).digest() + val_salt + key_salt
+
+ tmp_key = hashlib.sha256(password + key_salt).digest()
+ 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(
+ 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.
+ """
+ random_bytes = bytes(random.randrange(0, 256) for _ in range(16))
+ val_salt = random_bytes[:8]
+ key_salt = random_bytes[8:]
+ o_value = (
+ hashlib.sha256(password + val_salt + u_value).digest() + val_salt + key_salt
+ )
+
+ tmp_key = hashlib.sha256(password + key_salt + u_value).digest()
+ 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.
+ """
+ b8 = b"T" if metadata_encrypted else b"F"
+ rr = bytes(random.randrange(0, 256) for _ in range(4))
+ data = struct.pack("<I", p) + b"\xff\xff\xff\xff" + b8 + b"adb" + rr
+ perms = AES_ECB_encrypt(key, data)
+ return perms
+
+
+class PasswordType(IntEnum):
+ NOT_DECRYPTED = 0
+ USER_PASSWORD = 1
+ OWNER_PASSWORD = 2
+
+
+class Encryption:
+ def __init__(
+ self,
+ algV: int,
+ algR: int,
+ entry: DictionaryObject,
+ first_id_entry: bytes,
+ StmF: str,
+ StrF: str,
+ EFF: str,
+ ) -> None:
+ # See TABLE 3.18 Entries common to all encryption dictionaries
+ self.algV = algV
+ self.algR = algR
+ self.entry = entry
+ self.key_size = entry.get("/Length", 40)
+ self.id1_entry = first_id_entry
+ self.StmF = StmF
+ self.StrF = StrF
+ self.EFF = EFF
+
+ # 1 => owner password
+ # 2 => user password
+ self._password_type = PasswordType.NOT_DECRYPTED
+ self._key: Optional[bytes] = None
+
+ def is_decrypted(self) -> bool:
+ return self._password_type != PasswordType.NOT_DECRYPTED
+
+ def decrypt_object(self, obj: PdfObject, idnum: int, generation: int) -> PdfObject:
+ """
+ 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("<i", idnum)[:3]
+ pack2 = struct.pack("<i", generation)[:2]
+
+ assert self._key
+ key = self._key
+ n = 5 if self.algV == 1 else self.key_size // 8
+ key_data = key[:n] + pack1 + pack2
+ key_hash = hashlib.md5(key_data)
+ rc4_key = key_hash.digest()[: min(n + 5, 16)]
+ # for AES-128
+ key_hash.update(b"sAlT")
+ aes128_key = key_hash.digest()[: min(n + 5, 16)]
+
+ # for AES-256
+ aes256_key = key
+
+ stmCrypt = self._get_crypt(self.StmF, rc4_key, aes128_key, aes256_key)
+ StrCrypt = self._get_crypt(self.StrF, rc4_key, aes128_key, aes256_key)
+ efCrypt = self._get_crypt(self.EFF, rc4_key, aes128_key, aes256_key)
+
+ cf = CryptFilter(stmCrypt, StrCrypt, efCrypt)
+ return cf.decrypt_object(obj)
+
+ @staticmethod
+ def _get_crypt(
+ method: str, rc4_key: bytes, aes128_key: bytes, aes256_key: bytes
+ ) -> CryptBase:
+ if method == "/AESV3":
+ return CryptAES(aes256_key)
+ if method == "/AESV2":
+ return CryptAES(aes128_key)
+ elif method == "/Identity":
+ return CryptIdentity()
+ else:
+ return CryptRC4(rc4_key)
+
+ def verify(self, password: Union[bytes, str]) -> PasswordType:
+ if isinstance(password, str):
+ try:
+ pwd = password.encode("latin-1")
+ except Exception: # noqa
+ pwd = password.encode("utf-8")
+ else:
+ pwd = password
+
+ key, rc = self.verify_v4(pwd) if self.algV <= 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]:
+ R = cast(int, self.entry["/R"])
+ P = cast(int, self.entry["/P"])
+ P = (P + 0x100000000) % 0x100000000 # maybe < 0
+ # make type(metadata_encrypted) == bool
+ em = self.entry.get("/EncryptMetadata")
+ metadata_encrypted = em.value if em else True
+ o_entry = cast(ByteStringObject, self.entry["/O"].get_object()).original_bytes
+ u_entry = cast(ByteStringObject, self.entry["/U"].get_object()).original_bytes
+
+ # verify owner password first
+ key = AlgV4.verify_owner_password(
+ password,
+ R,
+ self.key_size,
+ o_entry,
+ u_entry,
+ P,
+ self.id1_entry,
+ metadata_encrypted,
+ )
+ if key:
+ return key, PasswordType.OWNER_PASSWORD
+ key = AlgV4.verify_user_password(
+ password,
+ R,
+ self.key_size,
+ o_entry,
+ u_entry,
+ P,
+ self.id1_entry,
+ metadata_encrypted,
+ )
+ 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
+ o_entry = cast(ByteStringObject, self.entry["/O"].get_object()).original_bytes
+ u_entry = cast(ByteStringObject, self.entry["/U"].get_object()).original_bytes
+ oe_entry = cast(ByteStringObject, self.entry["/OE"].get_object()).original_bytes
+ ue_entry = cast(ByteStringObject, self.entry["/UE"].get_object()).original_bytes
+
+ # verify owner password first
+ key = AlgV5.verify_owner_password(
+ self.algR, password, o_entry, oe_entry, u_entry
+ )
+ rc = PasswordType.OWNER_PASSWORD
+ if not key:
+ key = AlgV5.verify_user_password(self.algR, password, u_entry, ue_entry)
+ rc = PasswordType.USER_PASSWORD
+ if not key:
+ return b"", PasswordType.NOT_DECRYPTED
+
+ # verify Perms
+ perms = cast(ByteStringObject, self.entry["/Perms"].get_object()).original_bytes
+ P = cast(int, self.entry["/P"])
+ P = (P + 0x100000000) % 0x100000000 # maybe < 0
+ metadata_encrypted = self.entry.get("/EncryptMetadata", True)
+ if not AlgV5.verify_perms(key, perms, P, metadata_encrypted):
+ logger_warning("ignore '/Perms' verify failed", __name__)
+ return key, rc
+
+ @staticmethod
+ def read(encryption_entry: DictionaryObject, first_id_entry: bytes) -> "Encryption":
+ filter = encryption_entry.get("/Filter")
+ if filter != "/Standard":
+ raise NotImplementedError(
+ "only Standard PDF encryption handler is available"
+ )
+ if "/SubFilter" in encryption_entry:
+ raise NotImplementedError("/SubFilter NOT supported")
+
+ StmF = "/V2"
+ StrF = "/V2"
+ EFF = "/V2"
+
+ V = encryption_entry.get("/V", 0)
+ if V not in (1, 2, 3, 4, 5):
+ raise NotImplementedError(f"Encryption V={V} NOT supported")
+ if V >= 4:
+ filters = encryption_entry["/CF"]
+
+ StmF = encryption_entry.get("/StmF", "/Identity")
+ StrF = encryption_entry.get("/StrF", "/Identity")
+ EFF = encryption_entry.get("/EFF", StmF)
+
+ if StmF != "/Identity":
+ StmF = filters[StmF]["/CFM"] # type: ignore
+ if StrF != "/Identity":
+ StrF = filters[StrF]["/CFM"] # type: ignore
+ if EFF != "/Identity":
+ EFF = filters[EFF]["/CFM"] # type: ignore
+
+ allowed_methods = ("/Identity", "/V2", "/AESV2", "/AESV3")
+ if StmF not in allowed_methods:
+ raise NotImplementedError("StmF Method {StmF} NOT supported!")
+ if StrF not in allowed_methods:
+ raise NotImplementedError(f"StrF Method {StrF} NOT supported!")
+ if EFF not in allowed_methods:
+ raise NotImplementedError(f"EFF Method {EFF} NOT supported!")
+
+ R = cast(int, encryption_entry["/R"])
+ return Encryption(V, R, encryption_entry, first_id_entry, StmF, StrF, EFF)
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/_merger.py b/.venv/lib/python3.12/site-packages/PyPDF2/_merger.py
new file mode 100644
index 00000000..4d7a659d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_merger.py
@@ -0,0 +1,821 @@
+# 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 warnings
+from io import BytesIO, FileIO, IOBase
+from pathlib import Path
+from types import TracebackType
+from typing import (
+ Any,
+ Dict,
+ Iterable,
+ List,
+ Optional,
+ Tuple,
+ Type,
+ Union,
+ cast,
+)
+
+from ._encryption import Encryption
+from ._page import PageObject
+from ._reader import PdfReader
+from ._utils import (
+ StrByteType,
+ deprecation_bookmark,
+ deprecation_with_replacement,
+ str_,
+)
+from ._writer import PdfWriter
+from .constants import GoToActionArguments
+from .constants import PagesAttributes as PA
+from .constants import TypArguments, TypFitArguments
+from .generic import (
+ PAGE_FIT,
+ ArrayObject,
+ Destination,
+ DictionaryObject,
+ Fit,
+ FloatObject,
+ IndirectObject,
+ NameObject,
+ NullObject,
+ NumberObject,
+ OutlineItem,
+ TextStringObject,
+ TreeObject,
+)
+from .pagerange import PageRange, PageRangeSpec
+from .types import FitType, LayoutType, OutlineType, PagemodeType, ZoomArgType
+
+ERR_CLOSED_WRITER = "close() was called and thus the writer cannot be used anymore"
+
+
+class _MergedPage:
+ """Collect necessary information on each page that is being merged."""
+
+ def __init__(self, pagedata: PageObject, src: PdfReader, id: int) -> None:
+ self.src = src
+ self.pagedata = pagedata
+ self.out_pagedata = None
+ self.id = id
+
+
+class PdfMerger:
+ """
+ Initialize a ``PdfMerger`` object.
+
+ ``PdfMerger`` merges multiple PDFs into a single PDF.
+ It can concatenate, slice, insert, or any combination of the above.
+
+ See the functions :meth:`merge()<merge>` (or :meth:`append()<append>`)
+ and :meth:`write()<write>` for usage information.
+
+ :param bool strict: Determines whether user should be warned of all
+ problems and also causes some correctable problems to be fatal.
+ Defaults to ``False``.
+ :param fileobj: Output file. Can be a filename or any kind of
+ file-like object.
+ """
+
+ @deprecation_bookmark(bookmarks="outline")
+ def __init__(
+ self, strict: bool = False, fileobj: Union[Path, StrByteType] = ""
+ ) -> None:
+ self.inputs: List[Tuple[Any, PdfReader]] = []
+ self.pages: List[Any] = []
+ self.output: Optional[PdfWriter] = PdfWriter()
+ self.outline: OutlineType = []
+ self.named_dests: List[Any] = []
+ self.id_count = 0
+ self.fileobj = fileobj
+ self.strict = strict
+
+ def __enter__(self) -> "PdfMerger":
+ # There is nothing to do.
+ return self
+
+ def __exit__(
+ self,
+ exc_type: Optional[Type[BaseException]],
+ exc: Optional[BaseException],
+ traceback: Optional[TracebackType],
+ ) -> None:
+ """Write to the fileobj and close the merger."""
+ if self.fileobj:
+ self.write(self.fileobj)
+ self.close()
+
+ @deprecation_bookmark(bookmark="outline_item", import_bookmarks="import_outline")
+ def merge(
+ self,
+ page_number: Optional[int] = None,
+ fileobj: Union[Path, StrByteType, PdfReader] = None,
+ outline_item: Optional[str] = None,
+ pages: Optional[PageRangeSpec] = None,
+ import_outline: bool = True,
+ position: Optional[int] = None, # deprecated
+ ) -> None:
+ """
+ Merge the pages from the given file into the output file at the
+ specified page number.
+
+ :param int page_number: The *page number* to insert this file. File will
+ be inserted after the given number.
+
+ :param 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.
+
+ :param str outline_item: Optionally, you may specify an outline item
+ (previously referred to as a 'bookmark') to be applied at the
+ beginning of the included file by supplying the text of the outline item.
+
+ :param pages: can be a :class:`PageRange<PyPDF2.pagerange.PageRange>`
+ or a ``(start, stop[, step])`` tuple
+ to merge only the specified range of pages from the source
+ document into the output document.
+ Can also be a list of pages to merge.
+
+ :param bool 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``.
+ """
+ if position is not None: # deprecated
+ if page_number is None:
+ page_number = position
+ old_term = "position"
+ new_term = "page_number"
+ warnings.warn(
+ (
+ f"{old_term} is deprecated as an argument and will be "
+ f"removed in PyPDF2=4.0.0. Use {new_term} instead"
+ ),
+ DeprecationWarning,
+ )
+ else:
+ raise ValueError(
+ "The argument position of merge is deprecated. Use page_number only."
+ )
+
+ if page_number is None: # deprecated
+ # The paremter is only marked as Optional as long as
+ # position is not fully deprecated
+ raise ValueError("page_number may not be None")
+ if fileobj is None: # deprecated
+ # The argument is only Optional due to the deprecated position
+ # argument
+ raise ValueError("fileobj may not be None")
+
+ 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=self.strict) # type: ignore[arg-type]
+ self.inputs.append((stream, reader))
+ if encryption_obj is not None:
+ reader._encryption = encryption_obj
+
+ # Find the range of pages to merge.
+ if pages is None:
+ pages = (0, len(reader.pages))
+ elif isinstance(pages, PageRange):
+ pages = pages.indices(len(reader.pages))
+ elif isinstance(pages, list):
+ pass
+ elif not isinstance(pages, tuple):
+ raise TypeError('"pages" must be a tuple of (start, stop[, step])')
+
+ srcpages = []
+
+ outline = []
+ if import_outline:
+ outline = reader.outline
+ outline = self._trim_outline(reader, outline, pages)
+
+ if outline_item:
+ outline_item_typ = OutlineItem(
+ TextStringObject(outline_item),
+ NumberObject(self.id_count),
+ Fit.fit(),
+ )
+ self.outline += [outline_item_typ, outline] # type: ignore
+ else:
+ self.outline += outline
+
+ dests = reader.named_destinations
+ trimmed_dests = self._trim_dests(reader, dests, pages)
+ self.named_dests += trimmed_dests
+
+ # Gather all the pages that are going to be merged
+ for i in range(*pages):
+ page = reader.pages[i]
+
+ id = self.id_count
+ self.id_count += 1
+
+ mp = _MergedPage(page, reader, id)
+
+ srcpages.append(mp)
+
+ self._associate_dests_to_pages(srcpages)
+ self._associate_outline_items_to_pages(srcpages)
+
+ # Slice to insert the pages at the specified page_number
+ self.pages[page_number:page_number] = srcpages
+
+ 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)):
+ stream = FileIO(fileobj, "rb")
+ 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(
+ "PdfMerger.merge 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
+
+ @deprecation_bookmark(bookmark="outline_item", import_bookmarks="import_outline")
+ def append(
+ self,
+ fileobj: Union[StrByteType, PdfReader, Path],
+ outline_item: Optional[str] = None,
+ pages: Union[
+ None, PageRange, Tuple[int, int], Tuple[int, int, int], List[int]
+ ] = None,
+ import_outline: bool = True,
+ ) -> None:
+ """
+ Identical to the :meth:`merge()<merge>` method, but assumes you want to
+ concatenate all pages onto the end of the file instead of specifying a
+ position.
+
+ :param 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.
+
+ :param str outline_item: Optionally, you may specify an outline item
+ (previously referred to as a 'bookmark') to be applied at the
+ beginning of the included file by supplying the text of the outline item.
+
+ :param pages: can be a :class:`PageRange<PyPDF2.pagerange.PageRange>`
+ or a ``(start, stop[, step])`` tuple
+ to merge only the specified range of pages from the source
+ document into the output document.
+ Can also be a list of pages to append.
+
+ :param bool 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``.
+ """
+ self.merge(len(self.pages), fileobj, outline_item, pages, import_outline)
+
+ def write(self, fileobj: Union[Path, StrByteType]) -> None:
+ """
+ Write all data that has been merged to the given output file.
+
+ :param fileobj: Output file. Can be a filename or any kind of
+ file-like object.
+ """
+ if self.output is None:
+ raise RuntimeError(ERR_CLOSED_WRITER)
+
+ # Add pages to the PdfWriter
+ # The commented out line below was replaced with the two lines below it
+ # to allow PdfMerger to work with PyPdf 1.13
+ for page in self.pages:
+ self.output.add_page(page.pagedata)
+ pages_obj = cast(Dict[str, Any], self.output._pages.get_object())
+ page.out_pagedata = self.output.get_reference(
+ pages_obj[PA.KIDS][-1].get_object()
+ )
+ # idnum = self.output._objects.index(self.output._pages.get_object()[PA.KIDS][-1].get_object()) + 1
+ # page.out_pagedata = IndirectObject(idnum, 0, self.output)
+
+ # Once all pages are added, create outline items to point at those pages
+ self._write_dests()
+ self._write_outline()
+
+ # Write the output to the file
+ my_file, ret_fileobj = self.output.write(fileobj)
+
+ if my_file:
+ ret_fileobj.close()
+
+ def close(self) -> None:
+ """Shut all file descriptors (input and output) and clear all memory usage."""
+ self.pages = []
+ for fo, _reader in self.inputs:
+ fo.close()
+
+ self.inputs = []
+ self.output = None
+
+ def add_metadata(self, infos: Dict[str, Any]) -> None:
+ """
+ Add custom metadata to the output.
+
+ :param dict infos: a Python dictionary where each key is a field
+ and each value is your new metadata.
+ Example: ``{u'/Title': u'My title'}``
+ """
+ if self.output is None:
+ raise RuntimeError(ERR_CLOSED_WRITER)
+ self.output.add_metadata(infos)
+
+ def addMetadata(self, infos: Dict[str, Any]) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_metadata` instead.
+ """
+ deprecation_with_replacement("addMetadata", "add_metadata")
+ self.add_metadata(infos)
+
+ def setPageLayout(self, layout: LayoutType) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`set_page_layout` instead.
+ """
+ deprecation_with_replacement("setPageLayout", "set_page_layout")
+ self.set_page_layout(layout)
+
+ def set_page_layout(self, layout: LayoutType) -> None:
+ """
+ Set the page layout.
+
+ :param str 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 self.output is None:
+ raise RuntimeError(ERR_CLOSED_WRITER)
+ self.output._set_page_layout(layout)
+
+ def setPageMode(self, mode: PagemodeType) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`set_page_mode` instead.
+ """
+ deprecation_with_replacement("setPageMode", "set_page_mode", "3.0.0")
+ self.set_page_mode(mode)
+
+ def set_page_mode(self, mode: PagemodeType) -> None:
+ """
+ Set the page mode.
+
+ :param str mode: The page mode to use.
+
+ .. list-table:: Valid ``mode`` arguments
+ :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
+ """
+ if self.output is None:
+ raise RuntimeError(ERR_CLOSED_WRITER)
+ self.output.set_page_mode(mode)
+
+ def _trim_dests(
+ self,
+ pdf: PdfReader,
+ dests: Dict[str, Dict[str, Any]],
+ pages: Union[Tuple[int, int], Tuple[int, int, int], List[int]],
+ ) -> List[Dict[str, Any]]:
+ """Remove named destinations that are not a part of the specified page set."""
+ new_dests = []
+ lst = pages if isinstance(pages, list) else list(range(*pages))
+ for key, obj in dests.items():
+ for j in lst:
+ if pdf.pages[j].get_object() == obj["/Page"].get_object():
+ obj[NameObject("/Page")] = obj["/Page"].get_object()
+ assert str_(key) == str_(obj["/Title"])
+ new_dests.append(obj)
+ break
+ return new_dests
+
+ def _trim_outline(
+ self,
+ pdf: PdfReader,
+ outline: OutlineType,
+ pages: Union[Tuple[int, int], Tuple[int, int, int], List[int]],
+ ) -> OutlineType:
+ """Remove outline item entries that are not a part of the specified page set."""
+ new_outline = []
+ prev_header_added = True
+ lst = pages if isinstance(pages, list) else list(range(*pages))
+ for i, outline_item in enumerate(outline):
+ if isinstance(outline_item, list):
+ sub = self._trim_outline(pdf, outline_item, lst) # type: ignore
+ if sub:
+ if not prev_header_added:
+ new_outline.append(outline[i - 1])
+ new_outline.append(sub) # type: ignore
+ else:
+ prev_header_added = False
+ for j in lst:
+ if outline_item["/Page"] is None:
+ continue
+ if pdf.pages[j].get_object() == outline_item["/Page"].get_object():
+ outline_item[NameObject("/Page")] = outline_item[
+ "/Page"
+ ].get_object()
+ new_outline.append(outline_item)
+ prev_header_added = True
+ break
+ return new_outline
+
+ def _write_dests(self) -> None:
+ if self.output is None:
+ raise RuntimeError(ERR_CLOSED_WRITER)
+ for named_dest in self.named_dests:
+ pageno = None
+ if "/Page" in named_dest:
+ for pageno, page in enumerate(self.pages): # noqa: B007
+ if page.id == named_dest["/Page"]:
+ named_dest[NameObject("/Page")] = page.out_pagedata
+ break
+
+ if pageno is not None:
+ self.output.add_named_destination_object(named_dest)
+
+ @deprecation_bookmark(bookmarks="outline")
+ def _write_outline(
+ self,
+ outline: Optional[Iterable[OutlineItem]] = None,
+ parent: Optional[TreeObject] = None,
+ ) -> None:
+ if self.output is None:
+ raise RuntimeError(ERR_CLOSED_WRITER)
+ if outline is None:
+ outline = self.outline # type: ignore
+ assert outline is not None, "hint for mypy" # TODO: is that true?
+
+ last_added = None
+ for outline_item in outline:
+ if isinstance(outline_item, list):
+ self._write_outline(outline_item, last_added)
+ continue
+
+ page_no = None
+ if "/Page" in outline_item:
+ for page_no, page in enumerate(self.pages): # noqa: B007
+ if page.id == outline_item["/Page"]:
+ self._write_outline_item_on_page(outline_item, page)
+ break
+ if page_no is not None:
+ del outline_item["/Page"], outline_item["/Type"]
+ last_added = self.output.add_outline_item_dict(outline_item, parent)
+
+ @deprecation_bookmark(bookmark="outline_item")
+ def _write_outline_item_on_page(
+ self, outline_item: Union[OutlineItem, Destination], page: _MergedPage
+ ) -> None:
+ oi_type = cast(str, outline_item["/Type"])
+ args = [NumberObject(page.id), NameObject(oi_type)]
+ fit2arg_keys: Dict[str, Tuple[str, ...]] = {
+ TypFitArguments.FIT_H: (TypArguments.TOP,),
+ TypFitArguments.FIT_BH: (TypArguments.TOP,),
+ TypFitArguments.FIT_V: (TypArguments.LEFT,),
+ TypFitArguments.FIT_BV: (TypArguments.LEFT,),
+ TypFitArguments.XYZ: (TypArguments.LEFT, TypArguments.TOP, "/Zoom"),
+ TypFitArguments.FIT_R: (
+ TypArguments.LEFT,
+ TypArguments.BOTTOM,
+ TypArguments.RIGHT,
+ TypArguments.TOP,
+ ),
+ }
+ for arg_key in fit2arg_keys.get(oi_type, tuple()):
+ if arg_key in outline_item and not isinstance(
+ outline_item[arg_key], NullObject
+ ):
+ args.append(FloatObject(outline_item[arg_key]))
+ else:
+ args.append(FloatObject(0))
+ del outline_item[arg_key]
+
+ outline_item[NameObject("/A")] = DictionaryObject(
+ {
+ NameObject(GoToActionArguments.S): NameObject("/GoTo"),
+ NameObject(GoToActionArguments.D): ArrayObject(args),
+ }
+ )
+
+ def _associate_dests_to_pages(self, pages: List[_MergedPage]) -> None:
+ for named_dest in self.named_dests:
+ pageno = None
+ np = named_dest["/Page"]
+
+ if isinstance(np, NumberObject):
+ continue
+
+ for page in pages:
+ if np.get_object() == page.pagedata.get_object():
+ pageno = page.id
+
+ if pageno is None:
+ raise ValueError(
+ f"Unresolved named destination '{named_dest['/Title']}'"
+ )
+ named_dest[NameObject("/Page")] = NumberObject(pageno)
+
+ @deprecation_bookmark(bookmarks="outline")
+ def _associate_outline_items_to_pages(
+ self, pages: List[_MergedPage], outline: Optional[Iterable[OutlineItem]] = None
+ ) -> None:
+ if outline is None:
+ outline = self.outline # type: ignore # TODO: self.bookmarks can be None!
+ assert outline is not None, "hint for mypy"
+ for outline_item in outline:
+ if isinstance(outline_item, list):
+ self._associate_outline_items_to_pages(pages, outline_item)
+ continue
+
+ pageno = None
+ outline_item_page = outline_item["/Page"]
+
+ if isinstance(outline_item_page, NumberObject):
+ continue
+
+ for p in pages:
+ if outline_item_page.get_object() == p.pagedata.get_object():
+ pageno = p.id
+
+ if pageno is not None:
+ outline_item[NameObject("/Page")] = NumberObject(pageno)
+
+ @deprecation_bookmark(bookmark="outline_item")
+ def find_outline_item(
+ self,
+ outline_item: Dict[str, Any],
+ root: Optional[OutlineType] = None,
+ ) -> Optional[List[int]]:
+ if root is None:
+ root = self.outline
+
+ for i, oi_enum in enumerate(root):
+ if isinstance(oi_enum, list):
+ # oi_enum is still an inner node
+ # (OutlineType, if recursive types were supported by mypy)
+ res = self.find_outline_item(outline_item, oi_enum) # type: ignore
+ if res:
+ return [i] + res
+ elif (
+ oi_enum == outline_item
+ or cast(Dict[Any, Any], oi_enum["/Title"]) == outline_item
+ ):
+ # we found a leaf node
+ return [i]
+
+ return None
+
+ @deprecation_bookmark(bookmark="outline_item")
+ def find_bookmark(
+ self,
+ outline_item: Dict[str, Any],
+ root: Optional[OutlineType] = None,
+ ) -> Optional[List[int]]: # pragma: no cover
+ """
+ .. deprecated:: 2.9.0
+ Use :meth:`find_outline_item` instead.
+ """
+ return self.find_outline_item(outline_item, root)
+
+ def add_outline_item(
+ self,
+ title: str,
+ page_number: Optional[int] = None,
+ parent: Union[None, TreeObject, IndirectObject] = None,
+ color: Optional[Tuple[float, float, float]] = None,
+ bold: bool = False,
+ italic: bool = False,
+ fit: Fit = PAGE_FIT,
+ pagenum: Optional[int] = None, # deprecated
+ ) -> IndirectObject:
+ """
+ Add an outline item (commonly referred to as a "Bookmark") to this PDF file.
+
+ :param str title: Title to use for this outline item.
+ :param int page_number: Page number this outline item will point to.
+ :param parent: A reference to a parent outline item to create nested
+ outline items.
+ :param tuple color: Color of the outline item's font as a red, green, blue tuple
+ from 0.0 to 1.0
+ :param bool bold: Outline item font is bold
+ :param bool italic: Outline item font is italic
+ :param Fit fit: The fit of the destination page.
+ """
+ if page_number is not None and pagenum is not None:
+ raise ValueError(
+ "The argument pagenum of add_outline_item is deprecated. Use page_number only."
+ )
+ if pagenum is not None:
+ old_term = "pagenum"
+ new_term = "page_number"
+ warnings.warn(
+ (
+ f"{old_term} is deprecated as an argument and will be "
+ f"removed in PyPDF2==4.0.0. Use {new_term} instead"
+ ),
+ DeprecationWarning,
+ )
+ page_number = pagenum
+ if page_number is None:
+ raise ValueError("page_number may not be None")
+ writer = self.output
+ if writer is None:
+ raise RuntimeError(ERR_CLOSED_WRITER)
+ return writer.add_outline_item(
+ title,
+ page_number,
+ parent,
+ None,
+ color,
+ bold,
+ italic,
+ fit,
+ )
+
+ def addBookmark(
+ self,
+ title: str,
+ pagenum: int, # deprecated, but the whole method is deprecated
+ parent: Union[None, TreeObject, IndirectObject] = None,
+ color: Optional[Tuple[float, float, float]] = None,
+ bold: bool = False,
+ italic: bool = False,
+ fit: FitType = "/Fit",
+ *args: ZoomArgType,
+ ) -> IndirectObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+ Use :meth:`add_outline_item` instead.
+ """
+ deprecation_with_replacement("addBookmark", "add_outline_item", "3.0.0")
+ return self.add_outline_item(
+ title,
+ pagenum,
+ parent,
+ color,
+ bold,
+ italic,
+ Fit(fit_type=fit, fit_args=args),
+ )
+
+ def add_bookmark(
+ self,
+ title: str,
+ pagenum: int, # deprecated, but the whole method is deprecated already
+ parent: Union[None, TreeObject, IndirectObject] = None,
+ color: Optional[Tuple[float, float, float]] = None,
+ bold: bool = False,
+ italic: bool = False,
+ fit: FitType = "/Fit",
+ *args: ZoomArgType,
+ ) -> IndirectObject: # pragma: no cover
+ """
+ .. deprecated:: 2.9.0
+ Use :meth:`add_outline_item` instead.
+ """
+ deprecation_with_replacement("addBookmark", "add_outline_item", "3.0.0")
+ return self.add_outline_item(
+ title,
+ pagenum,
+ parent,
+ color,
+ bold,
+ italic,
+ Fit(fit_type=fit, fit_args=args),
+ )
+
+ def addNamedDestination(self, title: str, pagenum: int) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+ Use :meth:`add_named_destination` instead.
+ """
+ deprecation_with_replacement(
+ "addNamedDestination", "add_named_destination", "3.0.0"
+ )
+ return self.add_named_destination(title, pagenum)
+
+ def add_named_destination(
+ self,
+ title: str,
+ page_number: Optional[int] = None,
+ pagenum: Optional[int] = None,
+ ) -> None:
+ """
+ Add a destination to the output.
+
+ :param str title: Title to use
+ :param int page_number: Page number this destination points at.
+ """
+ if page_number is not None and pagenum is not None:
+ raise ValueError(
+ "The argument pagenum of add_named_destination is deprecated. Use page_number only."
+ )
+ if pagenum is not None:
+ old_term = "pagenum"
+ new_term = "page_number"
+ warnings.warn(
+ (
+ f"{old_term} is deprecated as an argument and will be "
+ f"removed in PyPDF2==4.0.0. Use {new_term} instead"
+ ),
+ DeprecationWarning,
+ )
+ page_number = pagenum
+ if page_number is None:
+ raise ValueError("page_number may not be None")
+ dest = Destination(
+ TextStringObject(title),
+ NumberObject(page_number),
+ Fit.fit_horizontally(top=826),
+ )
+ self.named_dests.append(dest)
+
+
+class PdfFileMerger(PdfMerger): # pragma: no cover
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
+ deprecation_with_replacement("PdfFileMerger", "PdfMerger", "3.0.0")
+
+ if "strict" not in kwargs and len(args) < 1:
+ kwargs["strict"] = True # maintain the default
+ super().__init__(*args, **kwargs)
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/_page.py b/.venv/lib/python3.12/site-packages/PyPDF2/_page.py
new file mode 100644
index 00000000..ed385bb3
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_page.py
@@ -0,0 +1,2114 @@
+# Copyright (c) 2006, Mathieu Fenniak
+# Copyright (c) 2007, Ashish Kulkarni <kulkarni.ashish@gmail.com>
+#
+# 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
+import uuid
+import warnings
+from decimal import Decimal
+from typing import (
+ Any,
+ Callable,
+ Dict,
+ Iterable,
+ Iterator,
+ List,
+ Optional,
+ Set,
+ Tuple,
+ Union,
+ cast,
+)
+
+from ._cmap import build_char_map, unknown_char_map
+from ._protocols import PdfReaderProtocol
+from ._utils import (
+ CompressedTransformationMatrix,
+ File,
+ TransformationMatrixType,
+ deprecation_no_replacement,
+ deprecation_with_replacement,
+ 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 Ressources as RES
+from .errors import PageSizeNotDefinedError
+from .filters import _xobj_to_image
+from .generic import (
+ ArrayObject,
+ ContentStream,
+ DictionaryObject,
+ EncodedStreamObject,
+ FloatObject,
+ IndirectObject,
+ NameObject,
+ NullObject,
+ NumberObject,
+ RectangleObject,
+ encode_pdfdocencoding,
+)
+
+CUSTOM_RTL_MIN: int = -1
+CUSTOM_RTL_MAX: int = -1
+CUSTOM_RTL_SPECIAL_CHARS: List[int] = []
+
+
+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 _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 retval is None:
+ 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 getRectangle(
+ self: Any, name: str, defaults: Iterable[str]
+) -> RectangleObject: # pragma: no cover
+ deprecation_no_replacement("getRectangle", "3.0.0")
+ return _get_rectangle(self, name, defaults)
+
+
+def _set_rectangle(self: Any, name: str, value: Union[RectangleObject, float]) -> None:
+ name = NameObject(name)
+ self[name] = value
+
+
+def setRectangle(
+ self: Any, name: str, value: Union[RectangleObject, float]
+) -> None: # pragma: no cover
+ deprecation_no_replacement("setRectangle", "3.0.0")
+ _set_rectangle(self, name, value)
+
+
+def _delete_rectangle(self: Any, name: str) -> None:
+ del self[name]
+
+
+def deleteRectangle(self: Any, name: str) -> None: # pragma: no cover
+ deprecation_no_replacement("deleteRectangle", "3.0.0")
+ 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),
+ )
+
+
+def createRectangleAccessor(
+ name: str, fallback: Iterable[str]
+) -> property: # pragma: no cover
+ deprecation_no_replacement("createRectangleAccessor", "3.0.0")
+ return _create_rectangle_accessor(name, fallback)
+
+
+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 PyPDF2 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)):
+ 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 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})"
+
+ def apply_on(
+ self, pt: Union[Tuple[Decimal, Decimal], Tuple[float, float], List[float]]
+ ) -> 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')
+ """
+ pt1 = (
+ float(pt[0]) * self.ctm[0] + float(pt[1]) * self.ctm[2] + self.ctm[4],
+ float(pt[0]) * self.ctm[1] + float(pt[1]) * self.ctm[3] + self.ctm[5],
+ )
+ return list(pt1) if isinstance(pt, list) else pt1
+
+
+class PageObject(DictionaryObject):
+ """
+ PageObject represents a single page within a PDF file.
+
+ Typically this object will be created by accessing the
+ :meth:`get_page()<PyPDF2.PdfReader.get_page>` method of the
+ :class:`PdfReader<PyPDF2.PdfReader>` class, but it is
+ also possible to create an empty page with the
+ :meth:`create_blank_page()<PyPDF2._page.PageObject.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[PdfReaderProtocol] = None,
+ indirect_reference: Optional[IndirectObject] = None,
+ indirect_ref: Optional[IndirectObject] = None, # deprecated
+ ) -> None:
+
+ DictionaryObject.__init__(self)
+ self.pdf: Optional[PdfReaderProtocol] = pdf
+ if indirect_ref is not None: # deprecated
+ warnings.warn(
+ (
+ "indirect_ref is deprecated and will be removed in "
+ "PyPDF2 4.0.0. Use indirect_reference instead of indirect_ref."
+ ),
+ DeprecationWarning,
+ )
+ if indirect_reference is not None:
+ raise ValueError("Use indirect_reference instead of indirect_ref.")
+ indirect_reference = indirect_ref
+ self.indirect_reference = indirect_reference
+
+ @property
+ def indirect_ref(self) -> Optional[IndirectObject]: # deprecated
+ warnings.warn(
+ (
+ "indirect_ref is deprecated and will be removed in PyPDF2 4.0.0"
+ "Use indirect_reference instead of indirect_ref."
+ ),
+ DeprecationWarning,
+ )
+ return self.indirect_reference
+
+ @indirect_ref.setter
+ def indirect_ref(self, value: Optional[IndirectObject]) -> None: # deprecated
+ self.indirect_reference = value
+
+ 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[Any] = None, # PdfReader
+ 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 belongs to
+ 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
+
+ @staticmethod
+ def createBlankPage(
+ pdf: Optional[Any] = None, # PdfReader
+ width: Union[float, Decimal, None] = None,
+ height: Union[float, Decimal, None] = None,
+ ) -> "PageObject": # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`create_blank_page` instead.
+ """
+ deprecation_with_replacement("createBlankPage", "create_blank_page", "3.0.0")
+ return PageObject.create_blank_page(pdf, width, height)
+
+ @property
+ def images(self) -> List[File]:
+ """
+ Get a list of all images of the page.
+
+ This requires pillow. You can install it via 'pip install PyPDF2[image]'.
+
+ For the moment, this does NOT include inline images. They will be added
+ in future.
+ """
+ images_extracted: List[File] = []
+ if RES.XOBJECT not in self[PG.RESOURCES]: # type: ignore
+ return images_extracted
+
+ x_object = self[PG.RESOURCES][RES.XOBJECT].get_object() # type: ignore
+ for obj in x_object:
+ if x_object[obj][IA.SUBTYPE] == "/Image":
+ extension, byte_stream = _xobj_to_image(x_object[obj])
+ if extension is not None:
+ filename = f"{obj[1:]}{extension}"
+ images_extracted.append(File(name=filename, data=byte_stream))
+ return images_extracted
+
+ @property
+ def rotation(self) -> int:
+ """
+ The VISUAL rotation of the page.
+
+ This number has to be a multiple of 90 degrees: 0,90,180,270
+ This property does not affect "/Contents"
+ """
+ return int(self.get(PG.ROTATE, 0))
+
+ @rotation.setter
+ def rotation(self, r: Union[int, 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's 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.
+ """
+ if angle % 90 != 0:
+ raise ValueError("Rotation angle must be a multiple of 90")
+ rotate_obj = self.get(PG.ROTATE, 0)
+ current_angle = (
+ rotate_obj if isinstance(rotate_obj, int) else rotate_obj.get_object()
+ )
+ self[NameObject(PG.ROTATE)] = NumberObject(current_angle + angle)
+ return self
+
+ def rotate_clockwise(self, angle: int) -> "PageObject": # pragma: no cover
+ deprecation_with_replacement("rotate_clockwise", "rotate", "3.0.0")
+ return self.rotate(angle)
+
+ def rotateClockwise(self, angle: int) -> "PageObject": # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`rotate_clockwise` instead.
+ """
+ deprecation_with_replacement("rotateClockwise", "rotate", "3.0.0")
+ return self.rotate(angle)
+
+ def rotateCounterClockwise(self, angle: int) -> "PageObject": # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`rotate_clockwise` with a negative argument instead.
+ """
+ deprecation_with_replacement("rotateCounterClockwise", "rotate", "3.0.0")
+ return self.rotate(-angle)
+
+ @staticmethod
+ def _merge_resources(
+ res1: DictionaryObject, res2: DictionaryObject, resource: Any
+ ) -> Tuple[Dict[str, Any], Dict[str, Any]]:
+ new_res = DictionaryObject()
+ new_res.update(res1.get(resource, DictionaryObject()).get_object())
+ page2res = cast(
+ DictionaryObject, res2.get(resource, DictionaryObject()).get_object()
+ )
+ rename_res = {}
+ for key in list(page2res.keys()):
+ if key in new_res and new_res.raw_get(key) != page2res.raw_get(key):
+ newname = NameObject(key + str(uuid.uuid4()))
+ rename_res[key] = newname
+ new_res[newname] = page2res[key]
+ elif key not in new_res:
+ new_res[key] = page2res.raw_get(key)
+ return new_res, rename_res
+
+ @staticmethod
+ def _content_stream_rename(
+ stream: ContentStream, rename: Dict[Any, Any], pdf: Any # PdfReader
+ ) -> ContentStream:
+ if not rename:
+ return stream
+ stream = ContentStream(stream, pdf)
+ for operands, _operator in stream.operations:
+ if isinstance(operands, list):
+ for i in range(len(operands)):
+ op = operands[i]
+ if isinstance(op, NameObject):
+ operands[i] = rename.get(op, op)
+ elif isinstance(operands, dict):
+ for i in operands:
+ op = operands[i]
+ if isinstance(op, NameObject):
+ operands[i] = rename.get(op, op)
+ else:
+ raise KeyError(f"type of operands is {type(operands)}")
+ return stream
+
+ @staticmethod
+ def _push_pop_gs(contents: Any, pdf: Any) -> ContentStream: # PdfReader
+ # adds a graphics state "push" and "pop" to the beginning and end
+ # of a content stream. This isolates it from changes such as
+ # transformation matricies.
+ stream = ContentStream(contents, pdf)
+ stream.operations.insert(0, ([], "q"))
+ stream.operations.append(([], "Q"))
+ return stream
+
+ @staticmethod
+ def _add_transformation_matrix(
+ contents: Any, pdf: Any, ctm: CompressedTransformationMatrix
+ ) -> ContentStream: # PdfReader
+ # adds transformation matrix at the beginning of the given
+ # contents stream.
+ a, b, c, d, e, f = ctm
+ contents = ContentStream(contents, pdf)
+ contents.operations.insert(
+ 0,
+ [
+ [
+ FloatObject(a),
+ FloatObject(b),
+ FloatObject(c),
+ FloatObject(d),
+ FloatObject(e),
+ FloatObject(f),
+ ],
+ " cm",
+ ],
+ )
+ return contents
+
+ def get_contents(self) -> Optional[ContentStream]:
+ """
+ Access the page contents.
+
+ :return: the ``/Contents`` object, or ``None`` if it doesn't exist.
+ ``/Contents`` is optional, as described in PDF Reference 7.7.3.3
+ """
+ if PG.CONTENTS in self:
+ return self[PG.CONTENTS].get_object() # type: ignore
+ else:
+ return None
+
+ def getContents(self) -> Optional[ContentStream]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`get_contents` instead.
+ """
+ deprecation_with_replacement("getContents", "get_contents", "3.0.0")
+ return self.get_contents()
+
+ def merge_page(self, page2: "PageObject", expand: bool = False) -> 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<PageObject>`.
+ expand: If true, the current page dimensions will be
+ expanded to accommodate the dimensions of the page to be merged.
+ """
+ self._merge_page(page2, expand=expand)
+
+ def mergePage(self, page2: "PageObject") -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`merge_page` instead.
+ """
+ deprecation_with_replacement("mergePage", "merge_page", "3.0.0")
+ return self.merge_page(page2)
+
+ def _merge_page(
+ self,
+ page2: "PageObject",
+ page2transformation: Optional[Callable[[Any], ContentStream]] = None,
+ ctm: Optional[CompressedTransformationMatrix] = None,
+ 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.
+
+ 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):
+ for ref in annots:
+ new_annots.append(ref)
+
+ for res in (
+ RES.EXT_G_STATE,
+ RES.FONT,
+ RES.XOBJECT,
+ RES.COLOR_SPACE,
+ RES.PATTERN,
+ RES.SHADING,
+ RES.PROPERTIES,
+ ):
+ new, newrename = PageObject._merge_resources(
+ original_resources, page2resources, res
+ )
+ if new:
+ new_resources[NameObject(res)] = new
+ rename.update(newrename)
+
+ # Combine /ProcSet sets.
+ new_resources[NameObject(RES.PROC_SET)] = ArrayObject(
+ frozenset(
+ original_resources.get(RES.PROC_SET, ArrayObject()).get_object()
+ ).union(
+ frozenset(page2resources.get(RES.PROC_SET, ArrayObject()).get_object())
+ )
+ )
+
+ new_content_array = ArrayObject()
+
+ original_content = self.get_contents()
+ if original_content is not None:
+ new_content_array.append(
+ PageObject._push_pop_gs(original_content, self.pdf)
+ )
+
+ page2content = page2.get_contents()
+ if page2content is not None:
+ page2content = ContentStream(page2content, self.pdf)
+ rect = page2.trimbox
+ page2content.operations.insert(
+ 0,
+ (
+ map(
+ FloatObject,
+ [
+ rect.left,
+ rect.bottom,
+ rect.width,
+ rect.height,
+ ],
+ ),
+ "re",
+ ),
+ )
+ page2content.operations.insert(1, ([], "W"))
+ page2content.operations.insert(2, ([], "n"))
+ if page2transformation is not None:
+ page2content = page2transformation(page2content)
+ page2content = PageObject._content_stream_rename(
+ page2content, rename, self.pdf
+ )
+ page2content = PageObject._push_pop_gs(page2content, self.pdf)
+ new_content_array.append(page2content)
+
+ # if expanding the page to fit a new page, calculate the new media box size
+ if expand:
+ self._expand_mediabox(page2, ctm)
+
+ self[NameObject(PG.CONTENTS)] = ContentStream(new_content_array, self.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 mergeTransformedPage(
+ self,
+ page2: "PageObject",
+ ctm: Union[CompressedTransformationMatrix, Transformation],
+ expand: bool = False,
+ ) -> None: # pragma: no cover
+ """
+ mergeTransformedPage is similar to merge_page, but a transformation
+ matrix is applied to the merged stream.
+
+ :param PageObject page2: The page to be merged into this one. Should be
+ an instance of :class:`PageObject<PageObject>`.
+ :param tuple ctm: a 6-element tuple containing the operands of the
+ transformation matrix
+ :param bool expand: Whether the page should be expanded to fit the dimensions
+ of the page to be merged.
+
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_transformation` and :meth:`merge_page` instead.
+ """
+ deprecation_with_replacement(
+ "page.mergeTransformedPage(page2, ctm)",
+ "page2.add_transformation(ctm); page.merge_page(page2)",
+ "3.0.0",
+ )
+ if isinstance(ctm, Transformation):
+ ctm = ctm.ctm
+ ctm = cast(CompressedTransformationMatrix, ctm)
+ self._merge_page(
+ page2,
+ lambda page2Content: PageObject._add_transformation_matrix(
+ page2Content, page2.pdf, ctm # type: ignore[arg-type]
+ ),
+ ctm,
+ expand,
+ )
+
+ def mergeScaledPage(
+ self, page2: "PageObject", scale: float, expand: bool = False
+ ) -> None: # pragma: no cover
+ """
+ mergeScaledPage is similar to merge_page, but the stream to be merged
+ is scaled by applying a transformation matrix.
+
+ :param PageObject page2: The page to be merged into this one. Should be
+ an instance of :class:`PageObject<PageObject>`.
+ :param float scale: The scaling factor
+ :param bool expand: Whether the page should be expanded to fit the
+ dimensions of the page to be merged.
+
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_transformation` and :meth:`merge_page` instead.
+ """
+ deprecation_with_replacement(
+ "page.mergeScaledPage(page2, scale, expand)",
+ "page2.add_transformation(Transformation().scale(scale)); page.merge_page(page2, expand)",
+ "3.0.0",
+ )
+ op = Transformation().scale(scale, scale)
+ self.mergeTransformedPage(page2, op, expand)
+
+ def mergeRotatedPage(
+ self, page2: "PageObject", rotation: float, expand: bool = False
+ ) -> None: # pragma: no cover
+ """
+ mergeRotatedPage is similar to merge_page, but the stream to be merged
+ is rotated by applying a transformation matrix.
+
+ :param PageObject page2: the page to be merged into this one. Should be
+ an instance of :class:`PageObject<PageObject>`.
+ :param float rotation: The angle of the rotation, in degrees
+ :param bool expand: Whether the page should be expanded to fit the
+ dimensions of the page to be merged.
+
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_transformation` and :meth:`merge_page` instead.
+ """
+ deprecation_with_replacement(
+ "page.mergeRotatedPage(page2, rotation, expand)",
+ "page2.add_transformation(Transformation().rotate(rotation)); page.merge_page(page2, expand)",
+ "3.0.0",
+ )
+ op = Transformation().rotate(rotation)
+ self.mergeTransformedPage(page2, op, expand)
+
+ def mergeTranslatedPage(
+ self, page2: "PageObject", tx: float, ty: float, expand: bool = False
+ ) -> None: # pragma: no cover
+ """
+ mergeTranslatedPage is similar to merge_page, but the stream to be
+ merged is translated by applying a transformation matrix.
+
+ :param PageObject page2: the page to be merged into this one. Should be
+ an instance of :class:`PageObject<PageObject>`.
+ :param float tx: The translation on X axis
+ :param float ty: The translation on Y axis
+ :param bool expand: Whether the page should be expanded to fit the
+ dimensions of the page to be merged.
+
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_transformation` and :meth:`merge_page` instead.
+ """
+ deprecation_with_replacement(
+ "page.mergeTranslatedPage(page2, tx, ty, expand)",
+ "page2.add_transformation(Transformation().translate(tx, ty)); page.merge_page(page2, expand)",
+ "3.0.0",
+ )
+ op = Transformation().translate(tx, ty)
+ self.mergeTransformedPage(page2, op, expand)
+
+ def mergeRotatedTranslatedPage(
+ self,
+ page2: "PageObject",
+ rotation: float,
+ tx: float,
+ ty: float,
+ expand: bool = False,
+ ) -> None: # pragma: no cover
+ """
+ mergeRotatedTranslatedPage is similar to merge_page, but the stream to
+ be merged is rotated and translated by applying a transformation matrix.
+
+ :param PageObject page2: the page to be merged into this one. Should be
+ an instance of :class:`PageObject<PageObject>`.
+ :param float tx: The translation on X axis
+ :param float ty: The translation on Y axis
+ :param float rotation: The angle of the rotation, in degrees
+ :param bool expand: Whether the page should be expanded to fit the
+ dimensions of the page to be merged.
+
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_transformation` and :meth:`merge_page` instead.
+ """
+ deprecation_with_replacement(
+ "page.mergeRotatedTranslatedPage(page2, rotation, tx, ty, expand)",
+ "page2.add_transformation(Transformation().rotate(rotation).translate(tx, ty)); page.merge_page(page2, expand)",
+ "3.0.0",
+ )
+ op = Transformation().translate(-tx, -ty).rotate(rotation).translate(tx, ty)
+ return self.mergeTransformedPage(page2, op, expand)
+
+ def mergeRotatedScaledPage(
+ self, page2: "PageObject", rotation: float, scale: float, expand: bool = False
+ ) -> None: # pragma: no cover
+ """
+ mergeRotatedScaledPage is similar to merge_page, but the stream to be
+ merged is rotated and scaled by applying a transformation matrix.
+
+ :param PageObject page2: the page to be merged into this one. Should be
+ an instance of :class:`PageObject<PageObject>`.
+ :param float rotation: The angle of the rotation, in degrees
+ :param float scale: The scaling factor
+ :param bool expand: Whether the page should be expanded to fit the
+ dimensions of the page to be merged.
+
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_transformation` and :meth:`merge_page` instead.
+ """
+ deprecation_with_replacement(
+ "page.mergeRotatedScaledPage(page2, rotation, scale, expand)",
+ "page2.add_transformation(Transformation().rotate(rotation).scale(scale)); page.merge_page(page2, expand)",
+ "3.0.0",
+ )
+ op = Transformation().rotate(rotation).scale(scale, scale)
+ self.mergeTransformedPage(page2, op, expand)
+
+ def mergeScaledTranslatedPage(
+ self,
+ page2: "PageObject",
+ scale: float,
+ tx: float,
+ ty: float,
+ expand: bool = False,
+ ) -> None: # pragma: no cover
+ """
+ mergeScaledTranslatedPage is similar to merge_page, but the stream to be
+ merged is translated and scaled by applying a transformation matrix.
+
+ :param PageObject page2: the page to be merged into this one. Should be
+ an instance of :class:`PageObject<PageObject>`.
+ :param float scale: The scaling factor
+ :param float tx: The translation on X axis
+ :param float ty: The translation on Y axis
+ :param bool expand: Whether the page should be expanded to fit the
+ dimensions of the page to be merged.
+
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_transformation` and :meth:`merge_page` instead.
+ """
+ deprecation_with_replacement(
+ "page.mergeScaledTranslatedPage(page2, scale, tx, ty, expand)",
+ "page2.add_transformation(Transformation().scale(scale).translate(tx, ty)); page.merge_page(page2, expand)",
+ "3.0.0",
+ )
+ op = Transformation().scale(scale, scale).translate(tx, ty)
+ return self.mergeTransformedPage(page2, op, expand)
+
+ def mergeRotatedScaledTranslatedPage(
+ self,
+ page2: "PageObject",
+ rotation: float,
+ scale: float,
+ tx: float,
+ ty: float,
+ expand: bool = False,
+ ) -> None: # pragma: no cover
+ """
+ mergeRotatedScaledTranslatedPage is similar to merge_page, but the
+ stream to be merged is translated, rotated and scaled by applying a
+ transformation matrix.
+
+ :param PageObject page2: the page to be merged into this one. Should be
+ an instance of :class:`PageObject<PageObject>`.
+ :param float tx: The translation on X axis
+ :param float ty: The translation on Y axis
+ :param float rotation: The angle of the rotation, in degrees
+ :param float scale: The scaling factor
+ :param bool expand: Whether the page should be expanded to fit the
+ dimensions of the page to be merged.
+
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_transformation` and :meth:`merge_page` instead.
+ """
+ deprecation_with_replacement(
+ "page.mergeRotatedScaledTranslatedPage(page2, rotation, tx, ty, expand)",
+ "page2.add_transformation(Transformation().rotate(rotation).scale(scale)); page.merge_page(page2, expand)",
+ "3.0.0",
+ )
+ op = Transformation().rotate(rotation).scale(scale, scale).translate(tx, ty)
+ self.mergeTransformedPage(page2, op, 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<PyPDF2.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 = PageObject._push_pop_gs(content, self.pdf)
+ self[NameObject(PG.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))
+ lowerleft = (min(corners[0], lowerleft[0]), min(corners[1], lowerleft[1]))
+ upperright = (
+ max(corners[2], upperright[0]),
+ max(corners[3], upperright[1]),
+ )
+
+ self.mediabox.lower_left = lowerleft
+ self.mediabox.upper_right = upperright
+
+ def addTransformation(
+ self, ctm: CompressedTransformationMatrix
+ ) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_transformation` instead.
+ """
+ deprecation_with_replacement("addTransformation", "add_transformation", "3.0.0")
+ self.add_transformation(ctm)
+
+ 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 scaleBy(self, factor: float) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`scale_by` instead.
+ """
+ deprecation_with_replacement("scaleBy", "scale_by", "3.0.0")
+ 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 scaleTo(self, width: float, height: float) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`scale_to` instead.
+ """
+ deprecation_with_replacement("scaleTo", "scale_to", "3.0.0")
+ self.scale_to(width, height)
+
+ def compress_content_streams(self) -> 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:
+ if not isinstance(content, ContentStream):
+ content = ContentStream(content, self.pdf)
+ self[NameObject(PG.CONTENTS)] = content.flate_encode()
+
+ def compressContentStreams(self) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`compress_content_streams` instead.
+ """
+ deprecation_with_replacement(
+ "compressContentStreams", "compress_content_streams", "3.0.0"
+ )
+ self.compress_content_streams()
+
+ 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 _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 allow to reuse the function on 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 we will have no /Resources will be available => an exception wil be raised
+ resources_dict = cast(DictionaryObject, objr[PG.RESOURCES])
+ except Exception:
+ return "" # no resources means no text is possible (no font) we consider the file as not damaged, no need to check for TJ or Tj
+ 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,dictionary-object of 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: # it means no content can be extracted(certainly empty page)
+ return ""
+ # Note: 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]
+ cm_stack = []
+ tm_matrix: 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,
+ ] # will store cm_matrix * tm_matrix
+ char_scale = 1.0
+ space_scale = 1.0
+ _space_width: float = 500.0 # will be set correctly at first Tf
+ TL = 0.0
+ font_size = 12.0 # init just in case of
+
+ 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 current_spacewidth() -> float:
+ # return space_scale * _space_width * char_scale
+ return _space_width / 1000.0
+
+ def process_operation(operator: bytes, operands: List) -> None:
+ nonlocal cm_matrix, cm_stack, tm_matrix, tm_prev, output, text, char_scale, space_scale, _space_width, TL, font_size, cmap, orientations, rtl_dir, visitor_text
+ global CUSTOM_RTL_MIN, CUSTOM_RTL_MAX, CUSTOM_RTL_SPECIAL_CHARS
+
+ check_crlf_space: bool = False
+ # Table 5.4 page 405
+ if operator == b"BT":
+ tm_matrix = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0]
+ # tm_prev = tm_matrix
+ output += text
+ if visitor_text is not None:
+ visitor_text(text, cm_matrix, tm_matrix, cmap[3], font_size)
+ # based
+ # if output != "" and output[-1]!="\n":
+ # output += "\n"
+ text = ""
+ return None
+ elif operator == b"ET":
+ output += text
+ if visitor_text is not None:
+ visitor_text(text, cm_matrix, tm_matrix, cmap[3], font_size)
+ text = ""
+ # table 4.7 "Graphics state operators", page 219
+ # cm_matrix calculation is a reserved for the moment
+ 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]
+ # rtl_dir = False
+ elif operator == b"cm":
+ output += text
+ if visitor_text is not None:
+ visitor_text(text, cm_matrix, tm_matrix, cmap[3], font_size)
+ text = ""
+ cm_matrix = mult(
+ [
+ float(operands[0]),
+ float(operands[1]),
+ float(operands[2]),
+ float(operands[3]),
+ float(operands[4]),
+ float(operands[5]),
+ ],
+ cm_matrix,
+ )
+ # rtl_dir = False
+ # Table 5.2 page 398
+ elif operator == b"Tz":
+ char_scale = float(operands[0]) / 100.0
+ elif operator == b"Tw":
+ space_scale = 1.0 + float(operands[0])
+ elif operator == b"TL":
+ TL = float(operands[0])
+ elif operator == b"Tf":
+ if text != "":
+ output += text # .translate(cmap)
+ if visitor_text is not None:
+ visitor_text(text, cm_matrix, tm_matrix, cmap[3], font_size)
+ text = ""
+ # rtl_dir = False
+ try:
+ # charMapTuple: font_type, float(sp_width / 2), encoding, map_dict, font-dictionary
+ charMapTuple = cmaps[operands[0]]
+ _space_width = charMapTuple[1]
+ # current cmap: encoding, map_dict, font resource name (internal name, not the real font-name),
+ # font-dictionary. The font-dictionary describes the font.
+ cmap = (
+ charMapTuple[2],
+ charMapTuple[3],
+ operands[0],
+ charMapTuple[4],
+ )
+ except KeyError: # font not found
+ _space_width = unknown_char_map[1]
+ cmap = (
+ unknown_char_map[2],
+ unknown_char_map[3],
+ "???" + operands[0],
+ None,
+ )
+ 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[0..5] = 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]
+ elif operator == b"Tm":
+ check_crlf_space = True
+ tm_matrix = [
+ float(operands[0]),
+ float(operands[1]),
+ float(operands[2]),
+ float(operands[3]),
+ float(operands[4]),
+ float(operands[5]),
+ ]
+ elif operator == b"T*":
+ check_crlf_space = True
+ tm_matrix[5] -= TL
+
+ elif operator == b"Tj":
+ check_crlf_space = True
+ m = mult(tm_matrix, cm_matrix)
+ orientation = orient(m)
+ if orientation in orientations:
+ if isinstance(operands[0], str):
+ text += operands[0]
+ else:
+ t: str = ""
+ 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
+ ]
+ )
+ # "\u0590 - \u08FF \uFB50 - \uFDFF"
+ for x in "".join(
+ [cmap[1][x] if x in cmap[1] else x for x in t]
+ ):
+ xx = ord(x)
+ # fmt: off
+ if ( # cases where the current inserting order is kept (punctuation,...)
+ (xx <= 0x2F) # punctuations but...
+ or (0x3A <= xx and xx <= 0x40) # numbers (x30-39)
+ or (0x2000 <= xx and xx <= 0x206F) # upper punctuations..
+ or (0x20A0 <= xx and 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 and xx <= 0x08FF)
+ or (0xFB1D <= xx and xx <= 0xFDFF)
+ or (0xFE70 <= xx and xx <= 0xFEFF)
+ or (CUSTOM_RTL_MIN <= xx and xx <= CUSTOM_RTL_MAX)
+ ):
+ # print("<",xx,x)
+ if not rtl_dir:
+ rtl_dir = True
+ # print("RTL",text,"*")
+ output += text
+ 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
+ # print(">",xx,x,end="")
+ if rtl_dir:
+ rtl_dir = False
+ # print("LTR",text,"*")
+ output += text
+ if visitor_text is not None:
+ visitor_text(text, cm_matrix, tm_matrix, cmap[3], font_size)
+ text = ""
+ text = text + x
+ # fmt: on
+ else:
+ return None
+ if check_crlf_space:
+ m = mult(tm_matrix, cm_matrix)
+ orientation = orient(m)
+ delta_x = m[4] - tm_prev[4]
+ delta_y = m[5] - tm_prev[5]
+ k = math.sqrt(abs(m[0] * m[3]) + abs(m[1] * m[2]))
+ f = font_size * k
+ tm_prev = m
+ if orientation not in orientations:
+ return None
+ try:
+ if orientation == 0:
+ if delta_y < -0.8 * f:
+ if (output + text)[-1] != "\n":
+ output += text + "\n"
+ if visitor_text is not None:
+ visitor_text(
+ text + "\n",
+ cm_matrix,
+ tm_matrix,
+ cmap[3],
+ font_size,
+ )
+ text = ""
+ elif (
+ abs(delta_y) < f * 0.3
+ and abs(delta_x) > current_spacewidth() * f * 15
+ ):
+ if (output + text)[-1] != " ":
+ text += " "
+ elif orientation == 180:
+ if delta_y > 0.8 * f:
+ if (output + text)[-1] != "\n":
+ output += text + "\n"
+ if visitor_text is not None:
+ visitor_text(
+ text + "\n",
+ cm_matrix,
+ tm_matrix,
+ cmap[3],
+ font_size,
+ )
+ text = ""
+ elif (
+ abs(delta_y) < f * 0.3
+ and abs(delta_x) > current_spacewidth() * f * 15
+ ):
+ if (output + text)[-1] != " ":
+ text += " "
+ elif orientation == 90:
+ if delta_x > 0.8 * f:
+ if (output + text)[-1] != "\n":
+ output += text + "\n"
+ if visitor_text is not None:
+ visitor_text(
+ text + "\n",
+ cm_matrix,
+ tm_matrix,
+ cmap[3],
+ font_size,
+ )
+ text = ""
+ elif (
+ abs(delta_x) < f * 0.3
+ and abs(delta_y) > current_spacewidth() * f * 15
+ ):
+ if (output + text)[-1] != " ":
+ text += " "
+ elif orientation == 270:
+ if delta_x < -0.8 * f:
+ if (output + text)[-1] != "\n":
+ output += text + "\n"
+ if visitor_text is not None:
+ visitor_text(
+ text + "\n",
+ cm_matrix,
+ tm_matrix,
+ cmap[3],
+ font_size,
+ )
+ text = ""
+ elif (
+ abs(delta_x) < f * 0.3
+ and abs(delta_y) > current_spacewidth() * f * 15
+ ):
+ if (output + text)[-1] != " ":
+ text += " "
+ except Exception:
+ pass
+
+ 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 defined in 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"TD":
+ process_operation(b"TL", [-operands[1]])
+ process_operation(b"Td", operands)
+ elif operator == b"TJ":
+ for op in operands[0]:
+ if isinstance(op, (str, bytes)):
+ process_operation(b"Tj", [op])
+ if isinstance(op, (int, float, NumberObject, FloatObject)):
+ if (
+ (abs(float(op)) >= _space_width)
+ and (len(text) > 0)
+ and (text[-1] != " ")
+ ):
+ process_operation(b"Tj", [" "])
+ elif operator == b"Do":
+ output += text
+ if visitor_text is not None:
+ visitor_text(text, cm_matrix, tm_matrix, cmap[3], font_size)
+ try:
+ if output[-1] != "\n":
+ output += "\n"
+ if visitor_text is not None:
+ visitor_text("\n", cm_matrix, tm_matrix, cmap[3], font_size)
+ except IndexError:
+ pass
+ try:
+ xobj = resources_dict["/XObject"]
+ if xobj[operands[0]]["/Subtype"] != "/Image": # type: ignore
+ # output += text
+ 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, cm_matrix, tm_matrix, cmap[3], font_size)
+ except Exception:
+ logger_warning(
+ f" impossible to decode XFormObject {operands[0]}",
+ __name__,
+ )
+ finally:
+ text = ""
+ 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 of
+ if text != "" and visitor_text is not None:
+ visitor_text(text, cm_matrix, tm_matrix, cmap[3], font_size)
+ return output
+
+ def extract_text(
+ self,
+ *args: Any,
+ Tj_sep: str = None,
+ TJ_sep: str = None,
+ 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,
+ ) -> 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, Hebrew,... are extracted in the good order.
+ If required an custom RTL range of characters can be defined; see function set_custom_rtl
+
+ Additionally you can provide visitor-methods to get informed on all operands and all text-objects.
+ For example in some PDF files this can be useful to parse tables.
+
+ Args:
+ Tj_sep: Deprecated. Kept for compatibility until PyPDF2 4.0.0
+ TJ_sep: Deprecated. Kept for compatibility until PyPDF2 4.0.0
+ orientations: list of orientations text_extraction will look for
+ default = (0, 90, 180, 270)
+ note: currently only 0(Up),90(turned Left), 180(upside Down),
+ 270 (turned Right)
+ space_width: force default space width
+ if not extracted from font (default: 200)
+ visitor_operand_before: function to be called before processing an operand.
+ It has four arguments: operand, operand-arguments,
+ current transformation matrix and text matrix.
+ visitor_operand_after: function to be called after processing an operand.
+ It has four arguments: operand, operand-arguments,
+ current transformation matrix and text matrix.
+ 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".
+
+ Returns:
+ The extracted text
+ """
+ if len(args) >= 1:
+ if isinstance(args[0], str):
+ Tj_sep = args[0]
+ if len(args) >= 2:
+ if isinstance(args[1], str):
+ TJ_sep = args[1]
+ else:
+ raise TypeError(f"Invalid positional parameter {args[1]}")
+ 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 Tj_sep is not None or TJ_sep is not None:
+ warnings.warn(
+ "parameters Tj_Sep, TJ_sep depreciated, and will be removed in PyPDF2 4.0.0.",
+ DeprecationWarning,
+ )
+
+ 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:
+ space_width: force default space width (if not extracted from font (default 200)
+
+ Returns:
+ The extracted text
+ """
+ return self._extract_text(
+ xform,
+ self.pdf,
+ orientations,
+ space_width,
+ None,
+ visitor_operand_before,
+ visitor_operand_after,
+ visitor_text,
+ )
+
+ def extractText(
+ self, Tj_sep: str = "", TJ_sep: str = ""
+ ) -> str: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`extract_text` instead.
+ """
+ deprecation_with_replacement("extractText", "extract_text", "3.0.0")
+ return self.extract_text()
+
+ def _get_fonts(self) -> Tuple[Set[str], Set[str]]:
+ """
+ Get the names of embedded fonts and unembedded fonts.
+
+ :return: (Set of embedded fonts, set of unembedded fonts)
+ """
+ obj = self.get_object()
+ assert isinstance(obj, DictionaryObject)
+ fonts, embedded = _get_fonts_walk(cast(DictionaryObject, obj[PG.RESOURCES]))
+ unembedded = fonts - embedded
+ return embedded, unembedded
+
+ mediabox = _create_rectangle_accessor(PG.MEDIABOX, ())
+ """
+ A :class:`RectangleObject<PyPDF2.generic.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.
+ """
+
+ @property
+ def mediaBox(self) -> RectangleObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`mediabox` instead.
+ """
+ deprecation_with_replacement("mediaBox", "mediabox", "3.0.0")
+ return self.mediabox
+
+ @mediaBox.setter
+ def mediaBox(self, value: RectangleObject) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`mediabox` instead.
+ """
+ deprecation_with_replacement("mediaBox", "mediabox", "3.0.0")
+ self.mediabox = value
+
+ cropbox = _create_rectangle_accessor("/CropBox", (PG.MEDIABOX,))
+ """
+ A :class:`RectangleObject<PyPDF2.generic.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<mediabox>`.
+ """
+
+ @property
+ def cropBox(self) -> RectangleObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`cropbox` instead.
+ """
+ deprecation_with_replacement("cropBox", "cropbox", "3.0.0")
+ return self.cropbox
+
+ @cropBox.setter
+ def cropBox(self, value: RectangleObject) -> None: # pragma: no cover
+ deprecation_with_replacement("cropBox", "cropbox", "3.0.0")
+ self.cropbox = value
+
+ bleedbox = _create_rectangle_accessor("/BleedBox", ("/CropBox", PG.MEDIABOX))
+ """
+ A :class:`RectangleObject<PyPDF2.generic.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.
+ """
+
+ @property
+ def bleedBox(self) -> RectangleObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`bleedbox` instead.
+ """
+ deprecation_with_replacement("bleedBox", "bleedbox", "3.0.0")
+ return self.bleedbox
+
+ @bleedBox.setter
+ def bleedBox(self, value: RectangleObject) -> None: # pragma: no cover
+ deprecation_with_replacement("bleedBox", "bleedbox", "3.0.0")
+ self.bleedbox = value
+
+ trimbox = _create_rectangle_accessor("/TrimBox", ("/CropBox", PG.MEDIABOX))
+ """
+ A :class:`RectangleObject<PyPDF2.generic.RectangleObject>`, expressed in default user space units,
+ defining the intended dimensions of the finished page after trimming.
+ """
+
+ @property
+ def trimBox(self) -> RectangleObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`trimbox` instead.
+ """
+ deprecation_with_replacement("trimBox", "trimbox", "3.0.0")
+ return self.trimbox
+
+ @trimBox.setter
+ def trimBox(self, value: RectangleObject) -> None: # pragma: no cover
+ deprecation_with_replacement("trimBox", "trimbox", "3.0.0")
+ self.trimbox = value
+
+ artbox = _create_rectangle_accessor("/ArtBox", ("/CropBox", PG.MEDIABOX))
+ """
+ A :class:`RectangleObject<PyPDF2.generic.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 artBox(self) -> RectangleObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`artbox` instead.
+ """
+ deprecation_with_replacement("artBox", "artbox", "3.0.0")
+ return self.artbox
+
+ @artBox.setter
+ def artBox(self, value: RectangleObject) -> None: # pragma: no cover
+ deprecation_with_replacement("artBox", "artbox", "3.0.0")
+ self.artbox = value
+
+ @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 don't want to set this value, but append to it.
+ If you append to it, don't forget 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:
+ 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()
+
+ def __getitem__(self, index: int) -> PageObject:
+ if isinstance(index, slice):
+ indices = range(*index.indices(len(self)))
+ cls = type(self)
+ return cls(indices.__len__, lambda idx: self[indices[idx]]) # type: ignore
+ 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 __iter__(self) -> Iterator[PageObject]:
+ for i in range(len(self)):
+ yield self[i]
+
+
+def _get_fonts_walk(
+ obj: DictionaryObject,
+ fnt: Optional[Set[str]] = None,
+ emb: Optional[Set[str]] = None,
+) -> Tuple[Set[str], Set[str]]:
+ """
+ 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.
+ """
+ if fnt is None:
+ fnt = set()
+ if emb is None:
+ emb = set()
+ if not hasattr(obj, "keys"):
+ return set(), set()
+ fontkeys = ("/FontFile", "/FontFile2", "/FontFile3")
+ if "/BaseFont" in obj:
+ fnt.add(cast(str, obj["/BaseFont"]))
+ if "/FontName" in obj:
+ if [x for x in fontkeys if x in obj]: # test to see if there is FontFile
+ emb.add(cast(str, obj["/FontName"]))
+
+ for key in obj.keys():
+ _get_fonts_walk(cast(DictionaryObject, obj[key]), fnt, emb)
+
+ return fnt, emb # return the sets for each page
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/_protocols.py b/.venv/lib/python3.12/site-packages/PyPDF2/_protocols.py
new file mode 100644
index 00000000..89c80f9a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_protocols.py
@@ -0,0 +1,62 @@
+"""Helpers for working with PDF types."""
+
+from pathlib import Path
+from typing import IO, Any, Dict, List, Optional, Tuple, Union
+
+try:
+ # Python 3.8+: https://peps.python.org/pep-0586
+ from typing import Protocol # type: ignore[attr-defined]
+except ImportError:
+ from typing_extensions import Protocol # type: ignore[misc]
+
+from ._utils import StrByteType
+
+
+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:
+ ...
+
+ def _reference_clone(self, clone: Any, pdf_dest: Any) -> Any:
+ ...
+
+ def get_object(self) -> Optional["PdfObjectProtocol"]:
+ ...
+
+
+class PdfReaderProtocol(Protocol): # pragma: no cover
+ @property
+ def pdf_header(self) -> str:
+ ...
+
+ @property
+ def strict(self) -> bool:
+ ...
+
+ @property
+ def xref(self) -> Dict[int, Dict[int, Any]]:
+ ...
+
+ @property
+ def pages(self) -> List[Any]:
+ ...
+
+ def get_object(self, indirect_reference: Any) -> Optional[PdfObjectProtocol]:
+ ...
+
+
+class PdfWriterProtocol(Protocol): # pragma: no cover
+ _objects: List[Any]
+ _id_translated: Dict[int, Dict[int, int]]
+
+ def get_object(self, indirect_reference: Any) -> Optional[PdfObjectProtocol]:
+ ...
+
+ def write(self, stream: Union[Path, StrByteType]) -> Tuple[bool, IO]:
+ ...
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/_reader.py b/.venv/lib/python3.12/site-packages/PyPDF2/_reader.py
new file mode 100644
index 00000000..0a914476
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_reader.py
@@ -0,0 +1,1977 @@
+# Copyright (c) 2006, Mathieu Fenniak
+# Copyright (c) 2007, Ashish Kulkarni <kulkarni.ashish@gmail.com>
+#
+# 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
+import struct
+import zlib
+from datetime import datetime
+from io import BytesIO
+from pathlib import Path
+from typing import (
+ Any,
+ Callable,
+ Dict,
+ Iterable,
+ List,
+ Optional,
+ Tuple,
+ Union,
+ cast,
+)
+
+from ._encryption import Encryption, PasswordType
+from ._page import PageObject, _VirtualList
+from ._utils import (
+ StrByteType,
+ StreamType,
+ b_,
+ deprecate_no_replacement,
+ deprecation_no_replacement,
+ deprecation_with_replacement,
+ logger_warning,
+ read_non_whitespace,
+ read_previous_line,
+ read_until_whitespace,
+ skip_over_comment,
+ skip_over_whitespace,
+)
+from .constants import CatalogAttributes as CA
+from .constants import CatalogDictionary as CD
+from .constants import CheckboxRadioButtonAttributes
+from .constants import Core as CO
+from .constants import DocumentInformationAttributes as DI
+from .constants import FieldDictionaryAttributes, GoToActionArguments
+from .constants import PageAttributes as PG
+from .constants import PagesAttributes as PA
+from .constants import TrailerKeys as TK
+from .errors import (
+ EmptyFileError,
+ FileNotDecryptedError,
+ PdfReadError,
+ PdfStreamError,
+ WrongPasswordError,
+)
+from .generic import (
+ ArrayObject,
+ ContentStream,
+ DecodedStreamObject,
+ Destination,
+ DictionaryObject,
+ EncodedStreamObject,
+ Field,
+ Fit,
+ FloatObject,
+ IndirectObject,
+ NameObject,
+ NullObject,
+ NumberObject,
+ PdfObject,
+ TextStringObject,
+ TreeObject,
+ read_object,
+)
+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]
+
+
+def convertToInt(
+ d: bytes, size: int
+) -> Union[int, Tuple[Any, ...]]: # pragma: no cover
+ deprecation_with_replacement("convertToInt", "convert_to_int")
+ return convert_to_int(d, size)
+
+
+class DocumentInformation(DictionaryObject):
+ """
+ A class representing the basic document metadata provided in a PDF File.
+ This class is accessible through :py:class:`PdfReader.metadata<PyPDF2.PdfReader.metadata>`.
+
+ All text properties of the document metadata have
+ *two* properties, eg. 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 PyPDF2 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
+ return None
+
+ def getText(self, key: str) -> Optional[str]: # pragma: no cover
+ """
+ The text value of the specified key or None.
+
+ .. deprecated:: 1.28.0
+
+ Use the attributes (e.g. :py:attr:`title` / :py:attr:`author`).
+ """
+ deprecation_no_replacement("getText", "3.0.0")
+ return self._get_text(key)
+
+ @property
+ def title(self) -> Optional[str]:
+ """
+ Read-only property accessing the document's **title**.
+
+ Returns a unicode string (``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 unicode string (``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 unicode string (``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 unicode string
+ (``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, OSX Quartz) that converted
+ it to PDF. Returns a unicode string (``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**.
+ """
+ text = self._get_text(DI.CREATION_DATE)
+ if text is None:
+ return None
+ return datetime.strptime(text.replace("'", ""), "D:%Y%m%d%H%M%S%z")
+
+ @property
+ def creation_date_raw(self) -> Optional[str]:
+ """
+ The "raw" version of creation date; can return a ``ByteStringObject``.
+
+ Typically in the format D:YYYYMMDDhhmmss[+-]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.
+ """
+ text = self._get_text(DI.MOD_DATE)
+ if text is None:
+ return None
+ return datetime.strptime(text.replace("'", ""), "D:%Y%m%d%H%M%S%z")
+
+ @property
+ def modification_date_raw(self) -> Optional[str]:
+ """
+ The "raw" version of modification date; can return a ``ByteStringObject``.
+
+ Typically in the format D:YYYYMMDDhhmmss[+-]hh'mm where the suffix is the
+ offset from UTC.
+ """
+ return self.get(DI.MOD_DATE)
+
+
+class PdfReader:
+ """
+ Initialize a PdfReader object.
+
+ This operation can take some time, as the PDF stream's cross-reference
+ tables are read into memory.
+
+ :param 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.
+ :param bool strict: Determines whether user should be warned of all
+ problems and also causes some correctable problems to be fatal.
+ Defaults to ``False``.
+ :param None/str/bytes 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
+ self.resolved_objects: Dict[Tuple[Any, Any], Optional[PdfObject]] = {}
+ self.xref_index = 0
+ self._page_id2num: Optional[
+ Dict[Any, Any]
+ ] = None # map page indirect_reference number to Page Number
+ if hasattr(stream, "mode") and "b" not in stream.mode: # type: ignore
+ logger_warning(
+ "PdfReader stream/file object is not in binary mode. "
+ "It may not be read correctly.",
+ __name__,
+ )
+ if isinstance(stream, (str, Path)):
+ with open(stream, "rb") as fh:
+ stream = BytesIO(fh.read())
+ self.read(stream)
+ self.stream = stream
+
+ self._override_encryption = False
+ self._encryption: Optional[Encryption] = None
+ if self.is_encrypted:
+ self._override_encryption = True
+ # Some documents may not have a /ID, use two empty
+ # byte strings instead. Solves
+ # https://github.com/mstamy2/PyPDF2/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
+ else:
+ if password is not None:
+ raise PdfReadError("Not encrypted file")
+
+ @property
+ def pdf_header(self) -> str:
+ # 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")
+ self.stream.seek(loc, 0) # return to where it was
+ return pdf_file_version
+
+ @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 docinfo
+ dictionaries, and these metadata streams will not be accessed by this
+ function.
+
+ :return: the document information of this PDF file
+ """
+ if TK.INFO not in self.trailer:
+ return None
+ obj = self.trailer[TK.INFO]
+ retval = DocumentInformation()
+ if isinstance(obj, type(None)):
+ raise PdfReadError(
+ "trailer not found or does not point to document information directory"
+ )
+ retval.update(obj) # type: ignore
+ return retval
+
+ def getDocumentInfo(self) -> Optional[DocumentInformation]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use the attribute :py:attr:`metadata` instead.
+ """
+ deprecation_with_replacement("getDocumentInfo", "metadata", "3.0.0")
+ return self.metadata
+
+ @property
+ def documentInfo(self) -> Optional[DocumentInformation]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use the attribute :py:attr:`metadata` instead.
+ """
+ deprecation_with_replacement("documentInfo", "metadata", "3.0.0")
+ return self.metadata
+
+ @property
+ def xmp_metadata(self) -> Optional[XmpInformation]:
+ """
+ XMP (Extensible Metadata Platform) data
+
+ :return: a :class:`XmpInformation<xmp.XmpInformation>`
+ instance that can be used to access XMP metadata from the document.
+ or ``None`` if no metadata was found on the document root.
+ """
+ try:
+ self._override_encryption = True
+ return self.trailer[TK.ROOT].xmp_metadata # type: ignore
+ finally:
+ self._override_encryption = False
+
+ def getXmpMetadata(self) -> Optional[XmpInformation]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use the attribute :py:attr:`xmp_metadata` instead.
+ """
+ deprecation_with_replacement("getXmpMetadata", "xmp_metadata", "3.0.0")
+ return self.xmp_metadata
+
+ @property
+ def xmpMetadata(self) -> Optional[XmpInformation]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use the attribute :py:attr:`xmp_metadata` instead.
+ """
+ deprecation_with_replacement("xmpMetadata", "xmp_metadata", "3.0.0")
+ return self.xmp_metadata
+
+ def _get_num_pages(self) -> int:
+ """
+ Calculate the number of pages in this PDF file.
+
+ :return: number of pages
+ :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.trailer[TK.ROOT]["/Pages"]["/Count"] # type: ignore
+ else:
+ if self.flattened_pages is None:
+ self._flatten()
+ return len(self.flattened_pages) # type: ignore
+
+ def getNumPages(self) -> int: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :code:`len(reader.pages)` instead.
+ """
+ deprecation_with_replacement("reader.getNumPages", "len(reader.pages)", "3.0.0")
+ return self._get_num_pages()
+
+ @property
+ def numPages(self) -> int: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :code:`len(reader.pages)` instead.
+ """
+ deprecation_with_replacement("reader.numPages", "len(reader.pages)", "3.0.0")
+ return self._get_num_pages()
+
+ def getPage(self, pageNumber: int) -> PageObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :code:`reader.pages[page_number]` instead.
+ """
+ deprecation_with_replacement(
+ "reader.getPage(pageNumber)", "reader.pages[page_number]", "3.0.0"
+ )
+ return self._get_page(pageNumber)
+
+ def _get_page(self, page_number: int) -> PageObject:
+ """
+ Retrieve a page by number from this PDF file.
+
+ :param int page_number: The page number to retrieve
+ (pages begin at zero)
+ :return: a :class:`PageObject<PyPDF2._page.PageObject>` instance.
+ """
+ # ensure that we're not trying to access an encrypted PDF
+ # assert not self.trailer.has_key(TK.ENCRYPT)
+ if self.flattened_pages is None:
+ self._flatten()
+ assert self.flattened_pages is not None, "hint for mypy"
+ return self.flattened_pages[page_number]
+
+ @property
+ def namedDestinations(self) -> Dict[str, Any]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`named_destinations` instead.
+ """
+ deprecation_with_replacement("namedDestinations", "named_destinations", "3.0.0")
+ return self.named_destinations
+
+ @property
+ def named_destinations(self) -> Dict[str, Any]:
+ """
+ A read-only dictionary which maps names to
+ :class:`Destinations<PyPDF2.generic.Destination>`
+ """
+ return self._get_named_destinations()
+
+ # A select group of relevant field attributes. For the complete list,
+ # see section 8.6.2 of the PDF 1.7 reference.
+
+ def get_fields(
+ self,
+ tree: Optional[TreeObject] = None,
+ retval: Optional[Dict[Any, Any]] = None,
+ fileobj: Optional[Any] = None,
+ ) -> Optional[Dict[str, Any]]:
+ """
+ Extract field data if this PDF contains interactive form fields.
+
+ The *tree* and *retval* parameters are for recursive use.
+
+ :param fileobj: A file object (usually a text file) to write
+ a report to on all interactive form fields found.
+ :return: A dictionary where each key is a field name, and each
+ value is a :class:`Field<PyPDF2.generic.Field>` object. By
+ default, the mapping name is used for keys.
+ ``None`` if form data could not be located.
+ """
+ field_attributes = FieldDictionaryAttributes.attributes_dict()
+ field_attributes.update(CheckboxRadioButtonAttributes.attributes_dict())
+ if retval is None:
+ retval = {}
+ catalog = cast(DictionaryObject, self.trailer[TK.ROOT])
+ # 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
+ self._check_kids(tree, retval, fileobj)
+ for attr in field_attributes:
+ if attr in tree:
+ # Tree is a field
+ self._build_field(tree, retval, fileobj, field_attributes)
+ break
+
+ 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)
+
+ return retval
+
+ def getFields(
+ self,
+ tree: Optional[TreeObject] = None,
+ retval: Optional[Dict[Any, Any]] = None,
+ fileobj: Optional[Any] = None,
+ ) -> Optional[Dict[str, Any]]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`get_fields` instead.
+ """
+ deprecation_with_replacement("getFields", "get_fields", "3.0.0")
+ return self.get_fields(tree, retval, fileobj)
+
+ def _build_field(
+ self,
+ field: Union[TreeObject, DictionaryObject],
+ retval: Dict[Any, Any],
+ fileobj: Any,
+ field_attributes: Any,
+ ) -> None:
+ self._check_kids(field, retval, fileobj)
+ try:
+ key = field["/TM"]
+ except KeyError:
+ try:
+ key = field["/T"]
+ except KeyError:
+ # Ignore no-name field for now
+ return
+ if fileobj:
+ self._write_field(fileobj, field, field_attributes)
+ fileobj.write("\n")
+ retval[key] = Field(field)
+
+ def _check_kids(
+ self, tree: Union[TreeObject, DictionaryObject], retval: Any, fileobj: Any
+ ) -> None:
+ if PA.KIDS in tree:
+ # recurse down the tree
+ for kid in tree[PA.KIDS]: # type: ignore
+ self.get_fields(kid.get_object(), retval, fileobj)
+
+ def _write_field(self, fileobj: Any, field: Any, field_attributes: Any) -> None:
+ field_attributes_tuple = FieldDictionaryAttributes.attributes()
+ field_attributes_tuple = (
+ field_attributes_tuple + CheckboxRadioButtonAttributes.attributes()
+ )
+
+ for attr in field_attributes_tuple:
+ if attr in (
+ FieldDictionaryAttributes.Kids,
+ FieldDictionaryAttributes.AA,
+ ):
+ continue
+ attr_name = field_attributes[attr]
+ try:
+ if attr == FieldDictionaryAttributes.FT:
+ # Make the field type value more clear
+ types = {
+ "/Btn": "Button",
+ "/Tx": "Text",
+ "/Ch": "Choice",
+ "/Sig": "Signature",
+ }
+ if field[attr] in types:
+ fileobj.write(attr_name + ": " + types[field[attr]] + "\n")
+ elif attr == FieldDictionaryAttributes.Parent:
+ # Let's just write the name of the parent
+ try:
+ name = field[attr][FieldDictionaryAttributes.TM]
+ except KeyError:
+ name = field[attr][FieldDictionaryAttributes.T]
+ fileobj.write(attr_name + ": " + name + "\n")
+ else:
+ fileobj.write(attr_name + ": " + str(field[attr]) + "\n")
+ except KeyError:
+ # Field attribute is N/A or unknown, so don't write anything
+ pass
+
+ def get_form_text_fields(self) -> Dict[str, Any]:
+ """
+ Retrieve form fields from the document with textual data.
+
+ 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, ...
+ """
+ # Retrieve document form fields
+ formfields = self.get_fields()
+ if formfields is None:
+ return {}
+ return {
+ formfields[field]["/T"]: formfields[field].get("/V")
+ for field in formfields
+ if formfields[field].get("/FT") == "/Tx"
+ }
+
+ def getFormTextFields(self) -> Dict[str, Any]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`get_form_text_fields` instead.
+ """
+ deprecation_with_replacement(
+ "getFormTextFields", "get_form_text_fields", "3.0.0"
+ )
+ return self.get_form_text_fields()
+
+ 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.
+
+ :return: a dictionary which maps names to
+ :class:`Destinations<PyPDF2.generic.Destination>`.
+ """
+ if retval is None:
+ retval = {}
+ catalog = cast(DictionaryObject, self.trailer[TK.ROOT])
+
+ # 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)
+ # TABLE 3.33 Entries in a name tree node dictionary (PDF 1.7 specs)
+ elif CA.NAMES in tree: # KIDS and NAMES are exclusives (PDF 1.7 specs p 162)
+ names = cast(DictionaryObject, tree[CA.NAMES])
+ for i in range(0, len(names), 2):
+ key = cast(str, names[i].get_object())
+ value = names[i + 1].get_object()
+ if isinstance(value, DictionaryObject) and "/D" in value:
+ value = value["/D"]
+ 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 PDF1.1
+ for k__, v__ in tree.items():
+ val = v__.get_object()
+ dest = self._build_destination(k__, val)
+ if dest is not None:
+ retval[k__] = dest
+ return retval
+
+ def getNamedDestinations(
+ self,
+ tree: Union[TreeObject, None] = None,
+ retval: Optional[Any] = None,
+ ) -> Dict[str, Any]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`named_destinations` instead.
+ """
+ deprecation_with_replacement(
+ "getNamedDestinations", "named_destinations", "3.0.0"
+ )
+ return self._get_named_destinations(tree, retval)
+
+ @property
+ def outline(self) -> OutlineType:
+ """
+ Read-only property for the outline (i.e., a collection of 'outline items'
+ which are also known as 'bookmarks') present in the document.
+
+ :return: a nested list of :class:`Destinations<PyPDF2.generic.Destination>`.
+ """
+ return self._get_outline()
+
+ @property
+ def outlines(self) -> OutlineType: # pragma: no cover
+ """
+ .. deprecated:: 2.9.0
+
+ Use :py:attr:`outline` instead.
+ """
+ deprecation_with_replacement("outlines", "outline", "3.0.0")
+ return self.outline
+
+ def _get_outline(
+ self, node: Optional[DictionaryObject] = None, outline: Optional[Any] = None
+ ) -> OutlineType:
+ if outline is None:
+ outline = []
+ catalog = cast(DictionaryObject, self.trailer[TK.ROOT])
+
+ # get the outline dictionary and named destinations
+ if CO.OUTLINES in catalog:
+ lines = cast(DictionaryObject, catalog[CO.OUTLINES])
+
+ if isinstance(lines, NullObject):
+ return outline
+
+ # TABLE 8.3 Entries in the outline dictionary
+ if lines is not None and "/First" in lines:
+ node = cast(DictionaryObject, lines["/First"])
+ self._namedDests = 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
+
+ def getOutlines(
+ self, node: Optional[DictionaryObject] = None, outline: Optional[Any] = None
+ ) -> OutlineType: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`outline` instead.
+ """
+ deprecation_with_replacement("getOutlines", "outline", "3.0.0")
+ return self._get_outline(node, outline)
+
+ @property
+ def threads(self) -> Optional[ArrayObject]:
+ """
+ Read-only property for the list of threads see §8.3.2 from PDF 1.7 spec
+
+ :return: an Array of Dictionnaries with "/F" and "/I" properties
+ or None if no articles.
+ """
+ catalog = cast(DictionaryObject, self.trailer[TK.ROOT])
+ if CO.THREADS in catalog:
+ return cast("ArrayObject", catalog[CO.THREADS])
+ else:
+ return None
+
+ def _get_page_number_by_indirect(
+ self, indirect_reference: Union[None, int, NullObject, IndirectObject]
+ ) -> int:
+ """Generate _page_id2num"""
+ if self._page_id2num is None:
+ self._page_id2num = {
+ x.indirect_reference.idnum: i for i, x in enumerate(self.pages) # type: ignore
+ }
+
+ if indirect_reference is None or isinstance(indirect_reference, NullObject):
+ return -1
+ if isinstance(indirect_reference, int):
+ idnum = indirect_reference
+ else:
+ idnum = indirect_reference.idnum
+ assert self._page_id2num is not None, "hint for mypy"
+ ret = self._page_id2num.get(idnum, -1)
+ return ret
+
+ def get_page_number(self, page: PageObject) -> int:
+ """
+ Retrieve page number of a given PageObject
+
+ :param PageObject page: The page to get page number. Should be
+ an instance of :class:`PageObject<PyPDF2._page.PageObject>`
+ :return: the page number or -1 if page not found
+ """
+ return self._get_page_number_by_indirect(page.indirect_reference)
+
+ def getPageNumber(self, page: PageObject) -> int: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`get_page_number` instead.
+ """
+ deprecation_with_replacement("getPageNumber", "get_page_number", "3.0.0")
+ return self.get_page_number(page)
+
+ def get_destination_page_number(self, destination: Destination) -> int:
+ """
+ Retrieve page number of a given Destination object.
+
+ :param Destination destination: The destination to get page number.
+ :return: the page number or -1 if page not found
+ """
+ return self._get_page_number_by_indirect(destination.page)
+
+ def getDestinationPageNumber(
+ self, destination: Destination
+ ) -> int: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`get_destination_page_number` instead.
+ """
+ deprecation_with_replacement(
+ "getDestinationPageNumber", "get_destination_page_number", "3.0.0"
+ )
+ return self.get_destination_page_number(destination)
+
+ 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[0:2] # type: ignore
+ array = array[2:]
+ 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()) # type: ignore
+
+ def _build_outline_item(self, node: DictionaryObject) -> Optional[Destination]:
+ dest, title, outline_item = None, None, None
+
+ # title required for valid outline
+ # PDF Reference 1.7: TABLE 8.4 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 = "" # type: ignore
+
+ 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._namedDests[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) # type: ignore
+
+ # 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
+ # 1=italic, 2=bold, 3=both
+ outline_item[NameObject("/F")] = node["/F"]
+ if "/Count" in node:
+ # absolute value = num. visible children
+ # positive = open/unfolded, negative = closed/folded
+ outline_item[NameObject("/Count")] = node["/Count"]
+ outline_item.node = node
+ return outline_item
+
+ @property
+ def pages(self) -> List[PageObject]:
+ """Read-only property that emulates a list of :py:class:`Page<PyPDF2._page.Page>` objects."""
+ return _VirtualList(self._get_num_pages, self._get_page) # type: ignore
+
+ @property
+ def page_layout(self) -> Optional[str]:
+ """
+ Get the page layout.
+
+ :return: 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
+ """
+ trailer = cast(DictionaryObject, self.trailer[TK.ROOT])
+ if CD.PAGE_LAYOUT in trailer:
+ return cast(NameObject, trailer[CD.PAGE_LAYOUT])
+ return None
+
+ def getPageLayout(self) -> Optional[str]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`page_layout` instead.
+ """
+ deprecation_with_replacement("getPageLayout", "page_layout", "3.0.0")
+ return self.page_layout
+
+ @property
+ def pageLayout(self) -> Optional[str]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`page_layout` instead.
+ """
+ deprecation_with_replacement("pageLayout", "page_layout", "3.0.0")
+ return self.page_layout
+
+ @property
+ def page_mode(self) -> Optional[PagemodeType]:
+ """
+ Get the page mode.
+
+ :return: 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.trailer[TK.ROOT]["/PageMode"] # type: ignore
+ except KeyError:
+ return None
+
+ def getPageMode(self) -> Optional[PagemodeType]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`page_mode` instead.
+ """
+ deprecation_with_replacement("getPageMode", "page_mode", "3.0.0")
+ return self.page_mode
+
+ @property
+ def pageMode(self) -> Optional[PagemodeType]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`page_mode` instead.
+ """
+ deprecation_with_replacement("pageMode", "page_mode", "3.0.0")
+ return self.page_mode
+
+ def _flatten(
+ self,
+ pages: Union[None, DictionaryObject, PageObject] = None,
+ inherit: Optional[Dict[str, Any]] = None,
+ indirect_reference: Optional[IndirectObject] = None,
+ ) -> None:
+ 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.trailer[TK.ROOT].get_object()
+ pages = catalog["/Pages"].get_object() # type: ignore
+ self.flattened_pages = []
+
+ t = "/Pages"
+ if PA.TYPE in pages:
+ t = pages[PA.TYPE] # type: ignore
+
+ if t == "/Pages":
+ for attr in inheritable_page_attributes:
+ if attr in pages:
+ inherit[attr] = pages[attr]
+ for page in pages[PA.KIDS]: # type: ignore
+ addt = {}
+ if isinstance(page, IndirectObject):
+ addt["indirect_reference"] = page
+ self._flatten(page.get_object(), inherit, **addt)
+ 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)
+ page_obj.update(pages)
+
+ # TODO: Could flattened_pages be None at this point?
+ self.flattened_pages.append(page_obj) # type: ignore
+
+ 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"
+ # /N is the number of indirect objects in the stream
+ assert idx < obj_stm["/N"]
+ stream_data = BytesIO(b_(obj_stm.get_data())) # type: ignore
+ 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:
+ raise PdfReadError(f"Can't read object stream: {exc}")
+ # Replace with null. Hopefully it's nothing important.
+ obj = NullObject()
+ return obj
+
+ if self.strict:
+ raise PdfReadError("This is a fatal error in strict mode.")
+ return NullObject()
+
+ def _get_indirect_object(self, num: int, gen: int) -> Optional[PdfObject]:
+ """
+ used to ease development
+ equivalent to generic.IndirectObject(num,gen,self).get_object()
+ """
+ return IndirectObject(num, gen, self).get_object()
+
+ 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)
+ except Exception:
+ if hasattr(self.stream, "getbuffer"):
+ buf = bytes(self.stream.getbuffer()) # type: ignore
+ 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 # 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} "
+ f"{indirect_reference.generation}) does not match actual "
+ f"({idnum} {generation})."
+ )
+ if self.strict:
+ assert generation == indirect_reference.generation
+ 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:
+ if hasattr(self.stream, "getbuffer"):
+ buf = bytes(self.stream.getbuffer()) # type: ignore
+ 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 getObject(
+ self, indirectReference: IndirectObject
+ ) -> Optional[PdfObject]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`get_object` instead.
+ """
+ deprecation_with_replacement("getObject", "get_object", "3.0.0")
+ return self.get_object(indirectReference)
+
+ 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.
+ extra = False
+ 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) # noqa: F841
+
+ 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 readObjectHeader(
+ self, stream: StreamType
+ ) -> Tuple[int, int]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`read_object_header` instead.
+ """
+ deprecation_with_replacement("readObjectHeader", "read_object_header", "3.0.0")
+ return self.read_object_header(stream)
+
+ def cache_get_indirect_object(
+ self, generation: int, idnum: int
+ ) -> Optional[PdfObject]:
+ return self.resolved_objects.get((generation, idnum))
+
+ def cacheGetIndirectObject(
+ self, generation: int, idnum: int
+ ) -> Optional[PdfObject]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`cache_get_indirect_object` instead.
+ """
+ deprecation_with_replacement(
+ "cacheGetIndirectObject", "cache_get_indirect_object", "3.0.0"
+ )
+ return self.cache_get_indirect_object(generation, idnum)
+
+ 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 cacheIndirectObject(
+ self, generation: int, idnum: int, obj: Optional[PdfObject]
+ ) -> Optional[PdfObject]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`cache_indirect_object` instead.
+ """
+ deprecation_with_replacement("cacheIndirectObject", "cache_indirect_object")
+ return self.cache_indirect_object(generation, idnum, obj)
+
+ def read(self, stream: StreamType) -> None:
+ self._basic_validation(stream)
+ self._find_eof_marker(stream)
+ startxref = self._find_startxref_pos(stream)
+
+ # check and eventually correct the startxref only in 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()
+ ) # must ensure ascendant to prevent damange
+ for id in xref_k:
+ stream.seek(xref_entry[id], 0)
+ try:
+ pid, _pgen = self.read_object_header(stream)
+ except ValueError:
+ 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
+
+ def _basic_validation(self, stream: StreamType) -> None:
+ # start at the end:
+ stream.seek(0, os.SEEK_END)
+ if not stream.tell():
+ raise EmptyFileError("Cannot read an empty file")
+ if self.strict:
+ stream.seek(0, os.SEEK_SET)
+ header_byte = stream.read(5)
+ if header_byte != b"%PDF-":
+ raise PdfReadError(
+ f"PDF starts with '{header_byte.decode('utf8')}', "
+ "but '%PDF-' expected"
+ )
+ stream.seek(0, os.SEEK_END)
+
+ def _find_eof_marker(self, stream: StreamType) -> None:
+ last_mb = 8 # to parse whole file
+ line = b""
+ while line[:5] != b"%%EOF":
+ if stream.tell() < last_mb:
+ raise PdfReadError("EOF marker not found")
+ line = read_previous_line(stream)
+
+ def _find_startxref_pos(self, stream: StreamType) -> int:
+ """Find startxref entry - the location of the xref table"""
+ 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 line[:9] != 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(4)
+ if ref[:3] != b"ref":
+ raise PdfReadError("xref table read error")
+ read_non_whitespace(stream)
+ stream.seek(-1, 1)
+ firsttime = True # check if the first time looking at the xref table
+ while True:
+ num = cast(int, read_object(stream, self))
+ if firsttime 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
+ firsttime = False
+ read_non_whitespace(stream)
+ stream.seek(-1, 1)
+ size = cast(int, read_object(stream, self))
+ read_non_whitespace(stream)
+ stream.seek(-1, 1)
+ cnt = 0
+ while cnt < size:
+ line = stream.read(20)
+
+ # 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 something wrong occured
+ if hasattr(stream, "getbuffer"):
+ buf = bytes(stream.getbuffer()) # type: ignore
+ else:
+ p = stream.tell()
+ stream.seek(0, 0)
+ buf = stream.read(-1)
+ stream.seek(p)
+
+ f = re.search(f"{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:
+ 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)
+ trailertag = stream.read(7)
+ if trailertag != 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:
+ 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()
+ 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 can not be read {e.args}",
+ __name__,
+ )
+ break
+ else:
+ raise PdfReadError(f"trailer can not be read {e.args}")
+ trailer_keys = TK.ROOT, TK.ENCRYPT, TK.INFO, TK.ID
+ 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 = stream.tell()
+ stream.seek(cast(int, xrefstream["/XRefStm"]) + 1, 0)
+ self._read_pdf15_xref_stream(stream)
+ stream.seek(p, 0)
+ if "/Prev" in xrefstream:
+ startxref = cast(int, xrefstream["/Prev"])
+ else:
+ break
+ else:
+ startxref = self._read_xref_other_error(stream, startxref)
+
+ def _read_xref(self, stream: StreamType) -> Optional[int]:
+ self._read_standard_xref_table(stream)
+ 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:
+ startxref = new_trailer["/Prev"]
+ return startxref
+ else:
+ 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(5):
+ 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("can not rebuild xref")
+ raise PdfReadError("Could not find xref table at specified location")
+
+ def _read_pdf15_xref_stream(
+ self, stream: StreamType
+ ) -> Union[ContentStream, EncodedStreamObject, DecodedStreamObject]:
+ # PDF 1.5+ Cross-Reference Stream
+ stream.seek(-1, 1)
+ idnum, generation = self.read_object_header(stream)
+ xrefstream = cast(ContentStream, read_object(stream, self))
+ assert cast(str, xrefstream["/Type"]) == "/XRef"
+ self.cache_indirect_object(generation, idnum, xrefstream)
+ stream_data = BytesIO(b_(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
+ else:
+ 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."""
+ stream.seek(startxref - 1, 0) # -1 to check character before
+ line = stream.read(1)
+ if line not in b"\r\n \t":
+ return 1
+ line = stream.read(4)
+ if line != b"xref":
+ # not an 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
+ # while stream.read(1) in b" \t\r\n":
+ # pass
+ # line = stream.read(256) # check that it is xref obj
+ # if b"/xref" not in line.lower():
+ # return 4
+ 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)
+ 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:
+ last_end = 0
+ for start, size in self._pairs(idx_pairs):
+ # The subsections must increase
+ assert start >= last_end
+ last_end = start + size
+ 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]]:
+ i = 0
+ while True:
+ yield array[i], array[i + 1]
+ i += 2
+ if (i + 1) >= len(array):
+ break
+
+ def read_next_end_line(
+ self, stream: StreamType, limit_offset: int = 0
+ ) -> bytes: # pragma: no cover
+ """.. deprecated:: 2.1.0"""
+ deprecate_no_replacement("read_next_end_line", removed_in="4.0.0")
+ line_parts = []
+ while True:
+ # Prevent infinite loops in malformed PDFs
+ if stream.tell() == 0 or stream.tell() == limit_offset:
+ raise PdfReadError("Could not read malformed PDF file")
+ x = stream.read(1)
+ if stream.tell() < 2:
+ raise PdfReadError("EOL marker not found")
+ stream.seek(-2, 1)
+ if x in (b"\n", b"\r"): # \n = LF; \r = CR
+ crlf = False
+ while x in (b"\n", b"\r"):
+ x = stream.read(1)
+ if x in (b"\n", b"\r"): # account for CR+LF
+ stream.seek(-1, 1)
+ crlf = True
+ if stream.tell() < 2:
+ raise PdfReadError("EOL marker not found")
+ stream.seek(-2, 1)
+ stream.seek(
+ 2 if crlf else 1, 1
+ ) # if using CR+LF, go back 2 bytes, else 1
+ break
+ else:
+ line_parts.append(x)
+ line_parts.reverse()
+ return b"".join(line_parts)
+
+ def readNextEndLine(
+ self, stream: StreamType, limit_offset: int = 0
+ ) -> bytes: # pragma: no cover
+ """.. deprecated:: 1.28.0"""
+ deprecation_no_replacement("readNextEndLine", "3.0.0")
+ return self.read_next_end_line(stream, limit_offset)
+
+ 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.
+
+ :param str password: The password to match.
+ :return: `PasswordType`.
+ """
+ if not self._encryption:
+ raise PdfReadError("Not encrypted file")
+ # TODO: raise Exception for wrong password
+ return self._encryption.verify(password)
+
+ def decode_permissions(self, permissions_code: int) -> Dict[str, bool]:
+ # Takes the permissions as an integer, returns the allowed access
+ permissions = {}
+ permissions["print"] = permissions_code & (1 << 3 - 1) != 0 # bit 3
+ permissions["modify"] = permissions_code & (1 << 4 - 1) != 0 # bit 4
+ permissions["copy"] = permissions_code & (1 << 5 - 1) != 0 # bit 5
+ permissions["annotations"] = permissions_code & (1 << 6 - 1) != 0 # bit 6
+ permissions["forms"] = permissions_code & (1 << 9 - 1) != 0 # bit 9
+ permissions["accessability"] = permissions_code & (1 << 10 - 1) != 0 # bit 10
+ permissions["assemble"] = permissions_code & (1 << 11 - 1) != 0 # bit 11
+ permissions["print_high_quality"] = (
+ permissions_code & (1 << 12 - 1) != 0
+ ) # bit 12
+ return permissions
+
+ @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()<PyPDF2.PdfReader.decrypt>` method is called.
+ """
+ return TK.ENCRYPT in self.trailer
+
+ def getIsEncrypted(self) -> bool: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`is_encrypted` instead.
+ """
+ deprecation_with_replacement("getIsEncrypted", "is_encrypted", "3.0.0")
+ return self.is_encrypted
+
+ @property
+ def isEncrypted(self) -> bool: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`is_encrypted` instead.
+ """
+ deprecation_with_replacement("isEncrypted", "is_encrypted", "3.0.0")
+ return self.is_encrypted
+
+ @property
+ def xfa(self) -> Optional[Dict[str, Any]]:
+ tree: Optional[TreeObject] = None
+ retval: Dict[str, Any] = {}
+ catalog = cast(DictionaryObject, self.trailer[TK.ROOT])
+
+ 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
+
+
+class PdfFileReader(PdfReader): # pragma: no cover
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
+ deprecation_with_replacement("PdfFileReader", "PdfReader", "3.0.0")
+ if "strict" not in kwargs and len(args) < 2:
+ kwargs["strict"] = True # maintain the default
+ super().__init__(*args, **kwargs)
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/_security.py b/.venv/lib/python3.12/site-packages/PyPDF2/_security.py
new file mode 100644
index 00000000..47e5c373
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_security.py
@@ -0,0 +1,252 @@
+# Copyright (c) 2006, Mathieu Fenniak
+# Copyright (c) 2007, Ashish Kulkarni <kulkarni.ashish@gmail.com>
+#
+# 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.
+
+"""Anything related to encryption / decryption."""
+
+import struct
+from hashlib import md5
+from typing import Tuple, Union
+
+from ._utils import b_, ord_, str_
+from .generic import ByteStringObject
+
+try:
+ from typing import Literal # type: ignore[attr-defined]
+except ImportError:
+ # PEP 586 introduced typing.Literal with Python 3.8
+ # For older Python versions, the backport typing_extensions is necessary:
+ from typing_extensions import Literal # type: ignore[misc]
+
+# ref: pdf1.8 spec section 3.5.2 algorithm 3.2
+_encryption_padding = (
+ b"\x28\xbf\x4e\x5e\x4e\x75\x8a\x41\x64\x00\x4e\x56"
+ b"\xff\xfa\x01\x08\x2e\x2e\x00\xb6\xd0\x68\x3e\x80\x2f\x0c"
+ b"\xa9\xfe\x64\x53\x69\x7a"
+)
+
+
+def _alg32(
+ password: str,
+ rev: Literal[2, 3, 4],
+ keylen: int,
+ owner_entry: ByteStringObject,
+ p_entry: int,
+ id1_entry: ByteStringObject,
+ metadata_encrypt: bool = True,
+) -> bytes:
+ """
+ Implementation of algorithm 3.2 of the PDF standard security handler.
+
+ See section 3.5.2 of the PDF 1.6 reference.
+ """
+ # 1. 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 padding string
+ # (_encryption_padding).
+ password_bytes = b_((str_(password) + str_(_encryption_padding))[:32])
+ # 2. Initialize the MD5 hash function and pass the result of step 1 as
+ # input to this function.
+ m = md5(password_bytes)
+ # 3. Pass the value of the encryption dictionary's /O entry to the MD5 hash
+ # function.
+ m.update(owner_entry.original_bytes)
+ # 4. Treat the value of the /P entry as an unsigned 4-byte integer and pass
+ # these bytes to the MD5 hash function, low-order byte first.
+ p_entry_bytes = struct.pack("<i", p_entry)
+ m.update(p_entry_bytes)
+ # 5. Pass the first element of the file's file identifier array to the MD5
+ # hash function.
+ m.update(id1_entry.original_bytes)
+ # 6. (Revision 3 or greater) If document metadata is not being encrypted,
+ # pass 4 bytes with the value 0xFFFFFFFF to the MD5 hash function.
+ if rev >= 3 and not metadata_encrypt:
+ m.update(b"\xff\xff\xff\xff")
+ # 7. Finish the hash.
+ md5_hash = m.digest()
+ # 8. (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.
+ if rev >= 3:
+ for _ in range(50):
+ md5_hash = md5(md5_hash[:keylen]).digest()
+ # 9. Set the encryption key to the first n bytes of the output from the
+ # final MD5 hash, where n is always 5 for revision 2 but, for revision 3 or
+ # greater, depends on the value of the encryption dictionary's /Length
+ # entry.
+ return md5_hash[:keylen]
+
+
+def _alg33(
+ owner_password: str, user_password: str, rev: Literal[2, 3, 4], keylen: int
+) -> bytes:
+ """
+ Implementation of algorithm 3.3 of the PDF standard security handler,
+ section 3.5.2 of the PDF 1.6 reference.
+ """
+ # steps 1 - 4
+ key = _alg33_1(owner_password, rev, keylen)
+ # 5. Pad or truncate the user password string as described in step 1 of
+ # algorithm 3.2.
+ user_password_bytes = b_((user_password + str_(_encryption_padding))[:32])
+ # 6. Encrypt the result of step 5, using an RC4 encryption function with
+ # the encryption key obtained in step 4.
+ val = RC4_encrypt(key, user_password_bytes)
+ # 7. (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 4 and performing
+ # an XOR operation between that byte and the single-byte value of the
+ # iteration counter (from 1 to 19).
+ if rev >= 3:
+ for i in range(1, 20):
+ new_key = ""
+ for key_char in key:
+ new_key += chr(ord_(key_char) ^ i)
+ val = RC4_encrypt(new_key, val)
+ # 8. Store the output from the final invocation of the RC4 as the value of
+ # the /O entry in the encryption dictionary.
+ return val
+
+
+def _alg33_1(password: str, rev: Literal[2, 3, 4], keylen: int) -> bytes:
+ """Steps 1-4 of algorithm 3.3"""
+ # 1. Pad or truncate the owner password string as described in step 1 of
+ # algorithm 3.2. If there is no owner password, use the user password
+ # instead.
+ password_bytes = b_((password + str_(_encryption_padding))[:32])
+ # 2. Initialize the MD5 hash function and pass the result of step 1 as
+ # input to this function.
+ m = md5(password_bytes)
+ # 3. (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.
+ md5_hash = m.digest()
+ if rev >= 3:
+ for _ in range(50):
+ md5_hash = md5(md5_hash).digest()
+ # 4. Create an RC4 encryption key using the first n bytes of the output
+ # from the final MD5 hash, where n is always 5 for revision 2 but, for
+ # revision 3 or greater, depends on the value of the encryption
+ # dictionary's /Length entry.
+ key = md5_hash[:keylen]
+ return key
+
+
+def _alg34(
+ password: str,
+ owner_entry: ByteStringObject,
+ p_entry: int,
+ id1_entry: ByteStringObject,
+) -> Tuple[bytes, bytes]:
+ """
+ Implementation of algorithm 3.4 of the PDF standard security handler.
+
+ See section 3.5.2 of the PDF 1.6 reference.
+ """
+ # 1. Create an encryption key based on the user password string, as
+ # described in algorithm 3.2.
+ rev: Literal[2] = 2
+ keylen = 5
+ key = _alg32(password, rev, keylen, owner_entry, p_entry, id1_entry)
+ # 2. Encrypt the 32-byte padding string shown in step 1 of algorithm 3.2,
+ # using an RC4 encryption function with the encryption key from the
+ # preceding step.
+ U = RC4_encrypt(key, _encryption_padding)
+ # 3. Store the result of step 2 as the value of the /U entry in the
+ # encryption dictionary.
+ return U, key
+
+
+def _alg35(
+ password: str,
+ rev: Literal[2, 3, 4],
+ keylen: int,
+ owner_entry: ByteStringObject,
+ p_entry: int,
+ id1_entry: ByteStringObject,
+ metadata_encrypt: bool,
+) -> Tuple[bytes, bytes]:
+ """
+ Implementation of algorithm 3.4 of the PDF standard security handler.
+
+ See section 3.5.2 of the PDF 1.6 reference.
+ """
+ # 1. Create an encryption key based on the user password string, as
+ # described in Algorithm 3.2.
+ key = _alg32(password, rev, keylen, owner_entry, p_entry, id1_entry)
+ # 2. Initialize the MD5 hash function and pass the 32-byte padding string
+ # shown in step 1 of Algorithm 3.2 as input to this function.
+ m = md5()
+ m.update(_encryption_padding)
+ # 3. 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 3.13 on
+ # page 73) to the hash function and finish the hash. (See implementation
+ # note 25 in Appendix H.)
+ m.update(id1_entry.original_bytes)
+ md5_hash = m.digest()
+ # 4. Encrypt the 16-byte result of the hash, using an RC4 encryption
+ # function with the encryption key from step 1.
+ val = RC4_encrypt(key, md5_hash)
+ # 5. 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 2) and performing an XOR
+ # operation between that byte and the single-byte value of the iteration
+ # counter (from 1 to 19).
+ for i in range(1, 20):
+ new_key = b""
+ for k in key:
+ new_key += b_(chr(ord_(k) ^ i))
+ val = RC4_encrypt(new_key, val)
+ # 6. 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.
+ # (implementer note: I don't know what "arbitrary padding" is supposed to
+ # mean, so I have used null bytes. This seems to match a few other
+ # people's implementations)
+ return val + (b"\x00" * 16), key
+
+
+def RC4_encrypt(key: Union[str, bytes], plaintext: bytes) -> bytes: # TODO
+ S = list(range(256))
+ j = 0
+ for i in range(256):
+ j = (j + S[i] + ord_(key[i % len(key)])) % 256
+ S[i], S[j] = S[j], S[i]
+ i, j = 0, 0
+ retval = []
+ for plaintext_char in plaintext:
+ i = (i + 1) % 256
+ j = (j + S[i]) % 256
+ S[i], S[j] = S[j], S[i]
+ t = S[(S[i] + S[j]) % 256]
+ retval.append(b_(chr(ord_(plaintext_char) ^ t)))
+ return b"".join(retval)
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/_utils.py b/.venv/lib/python3.12/site-packages/PyPDF2/_utils.py
new file mode 100644
index 00000000..b6f090b8
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_utils.py
@@ -0,0 +1,471 @@
+# 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 warnings
+from codecs import getencoder
+from dataclasses import dataclass
+from io import DEFAULT_BUFFER_SIZE
+from os import SEEK_CUR
+from typing import (
+ IO,
+ Any,
+ Callable,
+ Dict,
+ Optional,
+ Pattern,
+ Tuple,
+ Union,
+ overload,
+)
+
+try:
+ # Python 3.10+: https://www.python.org/dev/peps/pep-0484/
+ from typing import TypeAlias # type: ignore[attr-defined]
+except ImportError:
+ from typing_extensions import TypeAlias
+
+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
+StrByteType = Union[str, StreamType]
+
+DEPR_MSG_NO_REPLACEMENT = "{} is deprecated and will be removed in PyPDF2 {}."
+DEPR_MSG_NO_REPLACEMENT_HAPPENED = "{} is deprecated and was removed in PyPDF2 {}."
+DEPR_MSG = "{} is deprecated and will be removed in PyPDF2 3.0.0. Use {} instead."
+DEPR_MSG_HAPPENED = "{} is deprecated and was removed in PyPDF2 {}. Use {} instead."
+
+
+def _get_max_pdf_version_header(header1: bytes, header2: bytes) -> bytes:
+ versions = (
+ b"%PDF-1.3",
+ b"%PDF-1.4",
+ b"%PDF-1.5",
+ b"%PDF-1.6",
+ b"%PDF-1.7",
+ b"%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)]
+
+
+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.
+ """
+ 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)."""
+ 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 more than
+ one whitespace character was read.
+ """
+ tok = WHITESPACES[0]
+ cnt = 0
+ while tok in WHITESPACES:
+ tok = stream.read(1)
+ cnt += 1
+ return cnt > 1
+
+
+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)
+
+
+def read_until_regex(
+ stream: StreamType, regex: Pattern[bytes], ignore_eof: bool = False
+) -> bytes:
+ """
+ Read until the regular expression pattern matched (ignore the match).
+
+ :raises PdfStreamError: on premature end-of-file
+ :param bool ignore_eof: If true, ignore end-of-line and return immediately
+ :param regex: re.Pattern
+ """
+ name = b""
+ while True:
+ tok = stream.read(16)
+ if not tok:
+ if ignore_eof:
+ return name
+ raise PdfStreamError(STREAM_TRUNCATED_PREMATURELY)
+ m = regex.search(tok)
+ if m is not None:
+ name += tok[: m.start()]
+ stream.seek(m.start() - len(tok), 1)
+ 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.
+ """
+ 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.
+ """
+ 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("PyPDF2_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)
+
+
+B_CACHE: Dict[Union[str, bytes], bytes] = {}
+
+
+def b_(s: Union[str, bytes]) -> bytes:
+ bc = B_CACHE
+ if s in bc:
+ return bc[s]
+ if isinstance(s, bytes):
+ return s
+ try:
+ r = s.encode("latin-1")
+ if len(s) < 2:
+ bc[s] = r
+ return r
+ except Exception:
+ r = s.encode("utf-8")
+ if len(s) < 2:
+ bc[s] = r
+ return r
+
+
+@overload
+def str_(b: str) -> str:
+ ...
+
+
+@overload
+def str_(b: bytes) -> str:
+ ...
+
+
+def str_(b: Union[str, bytes]) -> str:
+ if isinstance(b, bytes):
+ return b.decode("latin-1")
+ else:
+ return b
+
+
+@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 hexencode(b: bytes) -> bytes:
+
+ coder = getencoder("hex_codec")
+ coded = coder(b) # type: ignore
+ return coded[0]
+
+
+def hex_str(num: int) -> str:
+ return hex(num).replace("L", "")
+
+
+WHITESPACES = (b" ", b"\n", b"\r", b"\t", b"\x00")
+
+
+def paeth_predictor(left: int, up: int, up_left: int) -> int:
+ 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:
+ return left
+ elif dist_up <= dist_up_left:
+ return up
+ else:
+ return up_left
+
+
+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 = "3.0.0"
+) -> None:
+ """
+ Raise an exception that a feature will be removed, but has a replacement.
+ """
+ deprecate(DEPR_MSG.format(old_name, new_name, removed_in), 4)
+
+
+def deprecation_with_replacement(
+ old_name: str, new_name: str, removed_in: str = "3.0.0"
+) -> None:
+ """
+ Raise an exception that a feature was already removed, but has a replacement.
+ """
+ deprecation(DEPR_MSG_HAPPENED.format(old_name, removed_in, new_name))
+
+
+def deprecate_no_replacement(name: str, removed_in: str = "3.0.0") -> None:
+ """
+ Raise an exception that a feature will be removed without replacement.
+ """
+ deprecate(DEPR_MSG_NO_REPLACEMENT.format(name, removed_in), 4)
+
+
+def deprecation_no_replacement(name: str, removed_in: str = "3.0.0") -> None:
+ """
+ Raise an exception that a feature was already removed without replacement.
+ """
+ deprecation(DEPR_MSG_NO_REPLACEMENT_HAPPENED.format(name, removed_in))
+
+
+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 PyPDF2, e.g. a non-compliant PDF being read in a way that
+ PyPDF2 could apply a robustness fix to still read it. This applies mainly
+ to strict=False mode.
+ """
+ logging.getLogger(src).warning(msg)
+
+
+def deprecation_bookmark(**aliases: str) -> Callable:
+ """
+ Decorator for deprecated term "bookmark"
+ To be used for methods and function arguments
+ outline_item = a bookmark
+ outline = a collection of outline items
+ """
+
+ def decoration(func: Callable): # type: ignore
+ @functools.wraps(func)
+ def wrapper(*args, **kwargs): # type: ignore
+ rename_kwargs(func.__name__, kwargs, aliases, fail=True)
+ return func(*args, **kwargs)
+
+ return wrapper
+
+ return decoration
+
+
+def rename_kwargs( # type: ignore
+ func_name: str, kwargs: Dict[str, Any], aliases: Dict[str, str], fail: bool = False
+):
+ """
+ Helper function to deprecate arguments.
+ """
+
+ 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 an argument. "
+ f"{old_term} is deprecated. 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"
+
+
+@dataclass
+class File:
+ name: str
+ data: bytes
+
+ def __str__(self) -> str:
+ return f"File(name={self.name}, data: {_human_readable_bytes(len(self.data))})"
+
+ def __repr__(self) -> str:
+ return f"File(name={self.name}, data: {_human_readable_bytes(len(self.data))}, hash: {hash(self.data)})"
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/_version.py b/.venv/lib/python3.12/site-packages/PyPDF2/_version.py
new file mode 100644
index 00000000..05527687
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_version.py
@@ -0,0 +1 @@
+__version__ = "3.0.1"
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/_writer.py b/.venv/lib/python3.12/site-packages/PyPDF2/_writer.py
new file mode 100644
index 00000000..b2e92cdb
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/_writer.py
@@ -0,0 +1,2822 @@
+# Copyright (c) 2006, Mathieu Fenniak
+# Copyright (c) 2007, Ashish Kulkarni <kulkarni.ashish@gmail.com>
+#
+# 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 codecs
+import collections
+import decimal
+import logging
+import random
+import re
+import struct
+import time
+import uuid
+import warnings
+from hashlib import md5
+from io import BytesIO, FileIO, IOBase
+from pathlib import Path
+from types import TracebackType
+from typing import (
+ IO,
+ Any,
+ Callable,
+ Deque,
+ Dict,
+ Iterable,
+ List,
+ Optional,
+ Pattern,
+ Tuple,
+ Type,
+ Union,
+ cast,
+)
+
+from ._encryption import Encryption
+from ._page import PageObject, _VirtualList
+from ._reader import PdfReader
+from ._security import _alg33, _alg34, _alg35
+from ._utils import (
+ StrByteType,
+ StreamType,
+ _get_max_pdf_version_header,
+ b_,
+ deprecate_with_replacement,
+ deprecation_bookmark,
+ deprecation_with_replacement,
+ logger_warning,
+)
+from .constants import AnnotationDictionaryAttributes
+from .constants import CatalogAttributes as CA
+from .constants import CatalogDictionary
+from .constants import Core as CO
+from .constants import EncryptionDictAttributes as ED
+from .constants import (
+ FieldDictionaryAttributes,
+ FieldFlag,
+ FileSpecificationDictionaryEntries,
+ GoToActionArguments,
+ InteractiveFormDictEntries,
+)
+from .constants import PageAttributes as PG
+from .constants import PagesAttributes as PA
+from .constants import StreamAttributes as SA
+from .constants import TrailerKeys as TK
+from .constants import TypFitArguments, UserAccessPermissions
+from .generic import (
+ PAGE_FIT,
+ AnnotationBuilder,
+ ArrayObject,
+ BooleanObject,
+ ByteStringObject,
+ ContentStream,
+ DecodedStreamObject,
+ Destination,
+ DictionaryObject,
+ Fit,
+ FloatObject,
+ IndirectObject,
+ NameObject,
+ NullObject,
+ NumberObject,
+ PdfObject,
+ RectangleObject,
+ StreamObject,
+ TextStringObject,
+ TreeObject,
+ create_string_object,
+ hex_to_rgb,
+)
+from .pagerange import PageRange, PageRangeSpec
+from .types import (
+ BorderArrayType,
+ FitType,
+ LayoutType,
+ OutlineItemType,
+ OutlineType,
+ PagemodeType,
+ ZoomArgType,
+)
+
+logger = logging.getLogger(__name__)
+
+
+OPTIONAL_READ_WRITE_FIELD = FieldFlag(0)
+ALL_DOCUMENT_PERMISSIONS = UserAccessPermissions((2**31 - 1) - 3)
+
+
+class PdfWriter:
+ """
+ This class supports writing PDF files out, given pages produced by another
+ class (typically :class:`PdfReader<PyPDF2.PdfReader>`).
+ """
+
+ def __init__(self, fileobj: StrByteType = "") -> None:
+ self._header = b"%PDF-1.3"
+ self._objects: List[PdfObject] = [] # array of indirect objects
+ self._idnum_hash: Dict[bytes, IndirectObject] = {}
+ self._id_translated: Dict[int, Dict[int, int]] = {}
+
+ # 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._pages = self._add_object(pages)
+
+ # info object
+ info = DictionaryObject()
+ info.update(
+ {
+ NameObject("/Producer"): create_string_object(
+ codecs.BOM_UTF16_BE + "PyPDF2".encode("utf-16be")
+ )
+ }
+ )
+ self._info = self._add_object(info)
+
+ # root object
+ self._root_object = DictionaryObject()
+ self._root_object.update(
+ {
+ NameObject(PA.TYPE): NameObject(CO.CATALOG),
+ NameObject(CO.PAGES): self._pages,
+ }
+ )
+ self._root = self._add_object(self._root_object)
+ self.fileobj = fileobj
+ self.with_as_usage = False
+
+ def __enter__(self) -> "PdfWriter":
+ """Store that writer is initialized by 'with'."""
+ self.with_as_usage = True
+ 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:
+ self.write(self.fileobj)
+
+ @property
+ def pdf_header(self) -> bytes:
+ """
+ Header of the PDF document that is written.
+
+ This should be something like b'%PDF-1.5'. It is recommended to set the
+ lowest version that supports all features which are used within the
+ PDF file.
+ """
+ return self._header
+
+ @pdf_header.setter
+ def pdf_header(self, new_header: bytes) -> None:
+ self._header = new_header
+
+ def _add_object(self, obj: PdfObject) -> IndirectObject:
+ if hasattr(obj, "indirect_reference") and obj.indirect_reference.pdf == self: # type: ignore
+ return obj.indirect_reference # type: ignore
+ self._objects.append(obj)
+ obj.indirect_reference = IndirectObject(len(self._objects), 0, self)
+ return obj.indirect_reference
+
+ def get_object(
+ self,
+ indirect_reference: Union[None, int, IndirectObject] = None,
+ ido: Optional[IndirectObject] = None,
+ ) -> PdfObject:
+ if ido is not None: # deprecated
+ if indirect_reference is not None:
+ raise ValueError(
+ "Please only set 'indirect_reference'. The 'ido' argument is deprecated."
+ )
+ else:
+ indirect_reference = ido
+ warnings.warn(
+ "The parameter 'ido' is depreciated and will be removed in PyPDF2 4.0.0.",
+ DeprecationWarning,
+ )
+ assert (
+ indirect_reference is not None
+ ) # the None value is only there to keep the deprecated name
+ if isinstance(indirect_reference, int):
+ return self._objects[indirect_reference - 1]
+ if indirect_reference.pdf != self:
+ raise ValueError("pdf must be self")
+ return self._objects[indirect_reference.idnum - 1] # type: ignore
+
+ def getObject(
+ self, ido: Union[int, IndirectObject]
+ ) -> PdfObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`get_object` instead.
+ """
+ deprecation_with_replacement("getObject", "get_object", "3.0.0")
+ return self.get_object(ido)
+
+ def _add_page(
+ self,
+ page: PageObject,
+ action: Callable[[Any, IndirectObject], None],
+ excluded_keys: Iterable[str] = (),
+ ) -> PageObject:
+ assert cast(str, page[PA.TYPE]) == CO.PAGE
+ page_org = page
+ excluded_keys = list(excluded_keys)
+ excluded_keys += [PA.PARENT, "/StructParents"]
+ # acrobat does not accept to have two indirect ref pointing on the same page;
+ # therefore in order to add easily multiple copies of the same page, we need to create a new
+ # dictionary for the page, however the objects below (including content) is 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))
+ # page_ind = self._add_object(page)
+ if page_org.pdf is not None:
+ other = page_org.pdf.pdf_header
+ if isinstance(other, str):
+ other = other.encode() # type: ignore
+ self.pdf_header = _get_max_pdf_version_header(self.pdf_header, other) # type: ignore
+ page[NameObject(PA.PARENT)] = self._pages
+ pages = cast(DictionaryObject, self.get_object(self._pages))
+ assert page.indirect_reference is not None
+ action(pages[PA.KIDS], page.indirect_reference)
+ page_count = cast(int, pages[PA.COUNT])
+ pages[NameObject(PA.COUNT)] = NumberObject(page_count + 1)
+ return page
+
+ def set_need_appearances_writer(self) -> None:
+ # See 12.7.2 and 7.7.2 for more information:
+ # http://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/PDF32000_2008.pdf
+ try:
+ catalog = self._root_object
+ # get the AcroForm tree
+ if CatalogDictionary.ACRO_FORM not in catalog:
+ self._root_object.update(
+ {
+ NameObject(CatalogDictionary.ACRO_FORM): IndirectObject(
+ len(self._objects), 0, self
+ )
+ }
+ )
+
+ need_appearances = NameObject(InteractiveFormDictEntries.NeedAppearances)
+ self._root_object[CatalogDictionary.ACRO_FORM][need_appearances] = BooleanObject(True) # type: ignore
+ except Exception as exc:
+ logger.error("set_need_appearances_writer() catch : ", repr(exc))
+
+ 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<PyPDF2.PdfReader>`
+ instance.
+
+ :param PageObject page: The page to add to the document. Should be
+ an instance of :class:`PageObject<PyPDF2._page.PageObject>`
+ """
+ return self._add_page(page, list.append, excluded_keys)
+
+ def addPage(
+ self,
+ page: PageObject,
+ excluded_keys: Iterable[str] = (),
+ ) -> PageObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_page` instead.
+ """
+ deprecation_with_replacement("addPage", "add_page", "3.0.0")
+ return self.add_page(page, 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<PyPDF2.PdfReader>` instance.
+
+ :param PageObject page: The page to add to the document.
+ :param int index: Position at which the page will be inserted.
+ """
+ return self._add_page(page, lambda l, p: l.insert(index, p))
+
+ def insertPage(
+ self,
+ page: PageObject,
+ index: int = 0,
+ excluded_keys: Iterable[str] = (),
+ ) -> PageObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`insert_page` instead.
+ """
+ deprecation_with_replacement("insertPage", "insert_page", "3.0.0")
+ return self.insert_page(page, index, excluded_keys)
+
+ def get_page(
+ self, page_number: Optional[int] = None, pageNumber: Optional[int] = None
+ ) -> PageObject:
+ """
+ Retrieve a page by number from this PDF file.
+
+ :param int page_number: The page number to retrieve
+ (pages begin at zero)
+ :return: the page at the index given by *page_number*
+ """
+ if pageNumber is not None: # pragma: no cover
+ if page_number is not None:
+ raise ValueError("Please only use the page_number parameter")
+ deprecate_with_replacement(
+ "get_page(pageNumber)", "get_page(page_number)", "4.0.0"
+ )
+ page_number = pageNumber
+ if page_number is None and pageNumber is None: # pragma: no cover
+ raise ValueError("Please specify the page_number")
+ pages = cast(Dict[str, Any], self.get_object(self._pages))
+ # TODO: crude hack
+ return cast(PageObject, pages[PA.KIDS][page_number].get_object())
+
+ def getPage(self, pageNumber: int) -> PageObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :code:`writer.pages[page_number]` instead.
+ """
+ deprecation_with_replacement("getPage", "writer.pages[page_number]", "3.0.0")
+ return self.get_page(pageNumber)
+
+ def _get_num_pages(self) -> int:
+ pages = cast(Dict[str, Any], self.get_object(self._pages))
+ return int(pages[NameObject("/Count")])
+
+ def getNumPages(self) -> int: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :code:`len(writer.pages)` instead.
+ """
+ deprecation_with_replacement("getNumPages", "len(writer.pages)", "3.0.0")
+ return self._get_num_pages()
+
+ @property
+ def pages(self) -> List[PageObject]:
+ """Property that emulates a list of :class:`PageObject<PyPDF2._page.PageObject>`."""
+ return _VirtualList(self._get_num_pages, self.get_page) # type: ignore
+
+ def add_blank_page(
+ self, width: Optional[float] = None, height: Optional[float] = None
+ ) -> PageObject:
+ """
+ Append a blank page to this PDF file and returns it. If no page size
+ is specified, use the size of the last page.
+
+ :param float width: The width of the new page expressed in default user
+ space units.
+ :param float height: The height of the new page expressed in default
+ user space units.
+ :return: 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)
+ self.add_page(page)
+ return page
+
+ def addBlankPage(
+ self, width: Optional[float] = None, height: Optional[float] = None
+ ) -> PageObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_blank_page` instead.
+ """
+ deprecation_with_replacement("addBlankPage", "add_blank_page", "3.0.0")
+ return self.add_blank_page(width, height)
+
+ def insert_blank_page(
+ self,
+ width: Optional[decimal.Decimal] = None,
+ height: Optional[decimal.Decimal] = None,
+ index: int = 0,
+ ) -> PageObject:
+ """
+ Insert a blank page to this PDF file and returns it. If no page size
+ is specified, use the size of the last page.
+
+ :param float width: The width of the new page expressed in default user
+ space units.
+ :param float height: The height of the new page expressed in default
+ user space units.
+ :param int index: Position to add the page.
+ :return: the newly appended 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 (self._get_num_pages() - 1) >= index:
+ 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
+
+ def insertBlankPage(
+ self,
+ width: Optional[decimal.Decimal] = None,
+ height: Optional[decimal.Decimal] = None,
+ index: int = 0,
+ ) -> PageObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`insertBlankPage` instead.
+ """
+ deprecation_with_replacement("insertBlankPage", "insert_blank_page", "3.0.0")
+ return self.insert_blank_page(width, height, index)
+
+ @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 is not set.
+
+ :param destination:.
+ the property can be set to a Destination, a Page or an string(NamedDest) or
+ None (to remove "/OpenAction")
+
+ (value stored in "/OpenAction" entry in the Pdf Catalog)
+ """
+ if "/OpenAction" not in self._root_object:
+ return None
+ oa = self._root_object["/OpenAction"]
+ if isinstance(oa, (str, bytes)):
+ return create_string_object(str(oa))
+ elif isinstance(oa, ArrayObject):
+ try:
+ page, typ = oa[0:2] # type: ignore
+ array = oa[2:]
+ 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:
+ 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.
+
+ :param str 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 prefered 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()}
+ )
+ # cast(DictionaryObject, names[NameObject("/JavaScript")])[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 addJS(self, javascript: str) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_js` instead.
+ """
+ deprecation_with_replacement("addJS", "add_js", "3.0.0")
+ return self.add_js(javascript)
+
+ def add_attachment(self, filename: str, data: Union[str, bytes]) -> None:
+ """
+ Embed a file inside the PDF.
+
+ :param str filename: The filename to display.
+ :param str data: The data in the file.
+
+ Reference:
+ https://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf
+ Section 7.11.3
+ """
+ # 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
+
+ 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 >>
+ # >>
+
+ ef_entry = DictionaryObject()
+ ef_entry.update({NameObject("/F"): 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
+
+ embedded_files_names_dictionary = DictionaryObject()
+ embedded_files_names_dictionary.update(
+ {
+ NameObject(CA.NAMES): ArrayObject(
+ [create_string_object(filename), filespec]
+ )
+ }
+ )
+
+ embedded_files_dictionary = DictionaryObject()
+ embedded_files_dictionary.update(
+ {NameObject("/EmbeddedFiles"): embedded_files_names_dictionary}
+ )
+ # Update the root
+ self._root_object.update({NameObject(CA.NAMES): embedded_files_dictionary})
+
+ def addAttachment(
+ self, fname: str, fdata: Union[str, bytes]
+ ) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_attachment` instead.
+ """
+ deprecation_with_replacement("addAttachment", "add_attachment", "3.0.0")
+ return self.add_attachment(fname, fdata)
+
+ 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.
+
+ :param PdfReader reader: a PdfReader object from which to copy page
+ annotations to this writer object. The writer's annots
+ will then be updated
+ :param Callable[[PageObject], None] 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.
+ """
+ # Get page count from writer and reader
+ 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 appendPagesFromReader(
+ self,
+ reader: PdfReader,
+ after_page_append: Optional[Callable[[PageObject], None]] = None,
+ ) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`append_pages_from_reader` instead.
+ """
+ deprecation_with_replacement(
+ "appendPagesFromReader", "append_pages_from_reader", "3.0.0"
+ )
+ self.append_pages_from_reader(reader, after_page_append)
+
+ def update_page_form_field_values(
+ self,
+ page: PageObject,
+ fields: Dict[str, Any],
+ flags: FieldFlag = OPTIONAL_READ_WRITE_FIELD,
+ ) -> 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.
+
+ :param PageObject page: Page reference from PDF writer where the
+ annotations and field data will be updated.
+ :param dict fields: a Python dictionary of field names (/T) and text
+ values (/V)
+ :param int flags: An integer (0 to 7). The first bit sets ReadOnly, the
+ second bit sets Required, the third bit sets NoExport. See
+ PDF Reference Table 8.70 for details.
+ """
+ self.set_need_appearances_writer()
+ # Iterate through pages, update field values
+ if PG.ANNOTS not in page:
+ logger_warning("No fields to update on this page", __name__)
+ return
+ for j in range(len(page[PG.ANNOTS])): # type: ignore
+ writer_annot = page[PG.ANNOTS][j].get_object() # type: ignore
+ # retrieve parent field values, if present
+ writer_parent_annot = {} # fallback if it's not there
+ if PG.PARENT in writer_annot:
+ writer_parent_annot = writer_annot[PG.PARENT]
+ for field in fields:
+ if writer_annot.get(FieldDictionaryAttributes.T) == field:
+ if writer_annot.get(FieldDictionaryAttributes.FT) == "/Btn":
+ writer_annot.update(
+ {
+ NameObject(
+ AnnotationDictionaryAttributes.AS
+ ): NameObject(fields[field])
+ }
+ )
+ writer_annot.update(
+ {
+ NameObject(FieldDictionaryAttributes.V): TextStringObject(
+ fields[field]
+ )
+ }
+ )
+ if flags:
+ writer_annot.update(
+ {
+ NameObject(FieldDictionaryAttributes.Ff): NumberObject(
+ flags
+ )
+ }
+ )
+ elif writer_parent_annot.get(FieldDictionaryAttributes.T) == field:
+ writer_parent_annot.update(
+ {
+ NameObject(FieldDictionaryAttributes.V): TextStringObject(
+ fields[field]
+ )
+ }
+ )
+
+ def updatePageFormFieldValues(
+ self,
+ page: PageObject,
+ fields: Dict[str, Any],
+ flags: FieldFlag = OPTIONAL_READ_WRITE_FIELD,
+ ) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`update_page_form_field_values` instead.
+ """
+ deprecation_with_replacement(
+ "updatePageFormFieldValues", "update_page_form_field_values", "3.0.0"
+ )
+ return self.update_page_form_field_values(page, fields, flags)
+
+ def clone_reader_document_root(self, reader: PdfReader) -> None:
+ """
+ Copy the reader document root to the writer.
+
+ :param reader: PdfReader from the document root should be copied.
+ """
+ self._root_object = cast(DictionaryObject, reader.trailer[TK.ROOT])
+
+ def cloneReaderDocumentRoot(self, reader: PdfReader) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`clone_reader_document_root` instead.
+ """
+ deprecation_with_replacement(
+ "cloneReaderDocumentRoot", "clone_reader_document_root", "3.0.0"
+ )
+ self.clone_reader_document_root(reader)
+
+ 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
+
+ :param reader: PDF file reader instance from which the clone
+ should be created.
+ :param Callable[[PageObject], None] 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.
+ """
+ # TODO : ppZZ may be limited because we do not copy all info...
+ self.clone_reader_document_root(reader)
+ self.append_pages_from_reader(reader, after_page_append)
+
+ def cloneDocumentFromReader(
+ self,
+ reader: PdfReader,
+ after_page_append: Optional[Callable[[PageObject], None]] = None,
+ ) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`clone_document_from_reader` instead.
+ """
+ deprecation_with_replacement(
+ "cloneDocumentFromReader", "clone_document_from_reader", "3.0.0"
+ )
+ self.clone_document_from_reader(reader, after_page_append)
+
+ def encrypt(
+ self,
+ user_password: Optional[str] = None,
+ owner_password: Optional[str] = None,
+ use_128bit: bool = True,
+ permissions_flag: UserAccessPermissions = ALL_DOCUMENT_PERMISSIONS,
+ user_pwd: Optional[str] = None, # deprecated
+ owner_pwd: Optional[str] = None, # deprecated
+ ) -> None:
+ """
+ Encrypt this PDF file with the PDF Standard encryption handler.
+
+ :param str user_password: The "user password", which allows for opening
+ and reading the PDF file with the restrictions provided.
+ :param str owner_password: The "owner password", which allows for
+ opening the PDF files without any restrictions. By default,
+ the owner password is the same as the user password.
+ :param bool use_128bit: flag as to whether to use 128bit
+ encryption. When false, 40bit encryption will be used. By default,
+ this flag is on.
+ :param unsigned int permissions_flag: permissions as described in
+ TABLE 3.20 of the PDF 1.7 specification. A bit value of 1 means the
+ permission is grantend. 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.
+ """
+ if user_pwd is not None:
+ if user_password is not None:
+ raise ValueError(
+ "Please only set 'user_password'. "
+ "The 'user_pwd' argument is deprecated."
+ )
+ else:
+ warnings.warn(
+ "Please use 'user_password' instead of 'user_pwd'. "
+ "The 'user_pwd' argument is deprecated and "
+ "will be removed in PyPDF2 4.0.0."
+ )
+ user_password = user_pwd
+ if user_password is None: # deprecated
+ # user_password is only Optional for due to the deprecated user_pwd
+ raise ValueError("user_password may not be None")
+
+ if owner_pwd is not None: # deprecated
+ if owner_password is not None:
+ raise ValueError(
+ "The argument owner_pwd of encrypt is deprecated. Use owner_password only."
+ )
+ else:
+ old_term = "owner_pwd"
+ new_term = "owner_password"
+ warnings.warn(
+ message=(
+ f"{old_term} is deprecated as an argument and will be "
+ f"removed in PyPDF2 4.0.0. Use {new_term} instead"
+ ),
+ category=DeprecationWarning,
+ )
+ owner_password = owner_pwd
+
+ if owner_password is None:
+ owner_password = user_password
+ if use_128bit:
+ V = 2
+ rev = 3
+ keylen = int(128 / 8)
+ else:
+ V = 1
+ rev = 2
+ keylen = int(40 / 8)
+ P = permissions_flag
+ O = ByteStringObject(_alg33(owner_password, user_password, rev, keylen)) # type: ignore[arg-type]
+ ID_1 = ByteStringObject(md5((repr(time.time())).encode("utf8")).digest())
+ ID_2 = ByteStringObject(md5((repr(random.random())).encode("utf8")).digest())
+ self._ID = ArrayObject((ID_1, ID_2))
+ if rev == 2:
+ U, key = _alg34(user_password, O, P, ID_1)
+ else:
+ assert rev == 3
+ U, key = _alg35(user_password, rev, keylen, O, P, ID_1, False) # type: ignore[arg-type]
+ encrypt = DictionaryObject()
+ encrypt[NameObject(SA.FILTER)] = NameObject("/Standard")
+ encrypt[NameObject("/V")] = NumberObject(V)
+ if V == 2:
+ encrypt[NameObject(SA.LENGTH)] = NumberObject(keylen * 8)
+ encrypt[NameObject(ED.R)] = NumberObject(rev)
+ encrypt[NameObject(ED.O)] = ByteStringObject(O)
+ encrypt[NameObject(ED.U)] = ByteStringObject(U)
+ encrypt[NameObject(ED.P)] = NumberObject(P)
+ self._encrypt = self._add_object(encrypt)
+ self._encrypt_key = key
+
+ 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. " # type: ignore
+ "It may not be written to correctly.",
+ __name__,
+ )
+
+ if not self._root:
+ self._root = self._add_object(self._root_object)
+
+ # PDF objects sometimes have circular references to their /Page objects
+ # inside their object tree (for example, annotations). Those will be
+ # indirect references to objects that we've recreated in this PDF. To
+ # address this problem, PageObject's store their original object
+ # reference number, and we add it to the external reference map before
+ # we sweep for indirect references. This forces self-page-referencing
+ # trees to reference the correct new object location, rather than
+ # copying in a new copy of the page object.
+ self._sweep_indirect_references(self._root)
+
+ object_positions = self._write_header(stream)
+ xref_location = self._write_xref_table(stream, object_positions)
+ self._write_trailer(stream)
+ stream.write(b_(f"\nstartxref\n{xref_location}\n%%EOF\n")) # eof
+
+ def write(self, stream: Union[Path, StrByteType]) -> Tuple[bool, IO]:
+ """
+ Write the collection of pages added to this object out as a PDF file.
+
+ :param 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.
+ """
+ my_file = False
+
+ if stream == "":
+ raise ValueError(f"Output(stream={stream}) is empty.")
+
+ if isinstance(stream, (str, Path)):
+ stream = FileIO(stream, "wb")
+ self.with_as_usage = True #
+ my_file = True
+
+ self.write_stream(stream)
+
+ if self.with_as_usage:
+ stream.close()
+
+ return my_file, stream
+
+ def _write_header(self, stream: StreamType) -> List[int]:
+ object_positions = []
+ stream.write(self.pdf_header + b"\n")
+ stream.write(b"%\xE2\xE3\xCF\xD3\n")
+ for i, obj in enumerate(self._objects):
+ obj = self._objects[i]
+ # If the obj is None we can't write anything
+ if obj is not None:
+ idnum = i + 1
+ object_positions.append(stream.tell())
+ stream.write(b_(str(idnum)) + b" 0 obj\n")
+ key = None
+ if hasattr(self, "_encrypt") and idnum != self._encrypt.idnum:
+ pack1 = struct.pack("<i", i + 1)[:3]
+ pack2 = struct.pack("<i", 0)[:2]
+ key = self._encrypt_key + pack1 + pack2
+ assert len(key) == (len(self._encrypt_key) + 5)
+ md5_hash = md5(key).digest()
+ key = md5_hash[: min(16, len(self._encrypt_key) + 5)]
+ obj.write_to_stream(stream, key)
+ stream.write(b"\nendobj\n")
+ return object_positions
+
+ def _write_xref_table(self, stream: StreamType, object_positions: List[int]) -> int:
+ xref_location = stream.tell()
+ stream.write(b"xref\n")
+ stream.write(b_(f"0 {len(self._objects) + 1}\n"))
+ stream.write(b_(f"{0:0>10} {65535:0>5} f \n"))
+ for offset in object_positions:
+ stream.write(b_(f"{offset:0>10} {0:0>5} n \n"))
+ return xref_location
+
+ def _write_trailer(self, stream: StreamType) -> None:
+ stream.write(b"trailer\n")
+ trailer = DictionaryObject()
+ trailer.update(
+ {
+ NameObject(TK.SIZE): NumberObject(len(self._objects) + 1),
+ NameObject(TK.ROOT): self._root,
+ NameObject(TK.INFO): self._info,
+ }
+ )
+ if hasattr(self, "_ID"):
+ trailer[NameObject(TK.ID)] = self._ID
+ if hasattr(self, "_encrypt"):
+ trailer[NameObject(TK.ENCRYPT)] = self._encrypt
+ trailer.write_to_stream(stream, None)
+
+ def add_metadata(self, infos: Dict[str, Any]) -> None:
+ """
+ Add custom metadata to the output.
+
+ :param dict infos: a Python dictionary where each key is a field
+ and each value is your new metadata.
+ """
+ args = {}
+ for key, value in list(infos.items()):
+ args[NameObject(key)] = create_string_object(value)
+ self.get_object(self._info).update(args) # type: ignore
+
+ def addMetadata(self, infos: Dict[str, Any]) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_metadata` instead.
+ """
+ deprecation_with_replacement("addMetadata", "add_metadata", "3.0.0")
+ self.add_metadata(infos)
+
+ def _sweep_indirect_references(
+ self,
+ root: Union[
+ ArrayObject,
+ BooleanObject,
+ DictionaryObject,
+ FloatObject,
+ IndirectObject,
+ NameObject,
+ PdfObject,
+ NumberObject,
+ TextStringObject,
+ NullObject,
+ ],
+ ) -> None:
+ stack: Deque[
+ Tuple[
+ Any,
+ Optional[Any],
+ Any,
+ List[PdfObject],
+ ]
+ ] = collections.deque()
+ discovered = []
+ parent = None
+ grant_parents: List[PdfObject] = []
+ key_or_id = None
+
+ # Start from root
+ stack.append((root, parent, key_or_id, grant_parents))
+
+ while len(stack):
+ data, parent, key_or_id, grant_parents = stack.pop()
+
+ # Build stack for a processing depth-first
+ if isinstance(data, (ArrayObject, DictionaryObject)):
+ for key, value in data.items():
+ stack.append(
+ (
+ value,
+ data,
+ key,
+ grant_parents + [parent] if parent is not None else [],
+ )
+ )
+ elif isinstance(data, IndirectObject):
+ if data.pdf != self:
+ data = self._resolve_indirect_object(data)
+
+ if str(data) not in discovered:
+ discovered.append(str(data))
+ stack.append((data.get_object(), None, None, []))
+
+ # Check if data has a parent and if it is a dict or an array update the value
+ if isinstance(parent, (DictionaryObject, ArrayObject)):
+ if isinstance(data, StreamObject):
+ # a dictionary value is a stream. streams must be indirect
+ # objects, so we need to change this value.
+ data = self._resolve_indirect_object(self._add_object(data))
+
+ update_hashes = []
+
+ # Data changed and thus the hash value changed
+ if parent[key_or_id] != data:
+ update_hashes = [parent.hash_value()] + [
+ grant_parent.hash_value() for grant_parent in grant_parents
+ ]
+ parent[key_or_id] = data
+
+ # Update old hash value to new hash value
+ for old_hash in update_hashes:
+ indirect_reference = self._idnum_hash.pop(old_hash, None)
+
+ if indirect_reference is not None:
+ indirect_reference_obj = indirect_reference.get_object()
+
+ if indirect_reference_obj is not None:
+ self._idnum_hash[
+ indirect_reference_obj.hash_value()
+ ] = indirect_reference
+
+ def _resolve_indirect_object(self, data: IndirectObject) -> IndirectObject:
+ """
+ Resolves indirect object to this pdf indirect objects.
+
+ If it is a new object then it is added to self._objects
+ and new idnum is given and generation is always 0.
+ """
+ if hasattr(data.pdf, "stream") and data.pdf.stream.closed:
+ raise ValueError(f"I/O operation on closed file: {data.pdf.stream.name}")
+
+ if data.pdf == self:
+ return data
+
+ # Get real object indirect object
+ real_obj = data.pdf.get_object(data)
+
+ if real_obj is None:
+ logger_warning(
+ f"Unable to resolve [{data.__class__.__name__}: {data}], "
+ "returning NullObject instead",
+ __name__,
+ )
+ real_obj = NullObject()
+
+ hash_value = real_obj.hash_value()
+
+ # Check if object is handled
+ if hash_value in self._idnum_hash:
+ return self._idnum_hash[hash_value]
+
+ if data.pdf == self:
+ self._idnum_hash[hash_value] = IndirectObject(data.idnum, 0, self)
+ # This is new object in this pdf
+ else:
+ self._idnum_hash[hash_value] = self._add_object(real_obj)
+
+ return self._idnum_hash[hash_value]
+
+ 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 getReference(self, obj: PdfObject) -> IndirectObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`get_reference` instead.
+ """
+ deprecation_with_replacement("getReference", "get_reference", "3.0.0")
+ return self.get_reference(obj)
+
+ 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])
+ 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 §8.3.2 from PDF 1.7 spec
+
+ :return: 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
+
+ :return: an Array (possibly empty) of Dictionaries with "/F" and "/I" properties
+ """
+ return self.get_threads_root()
+
+ def getOutlineRoot(self) -> TreeObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`get_outline_root` instead.
+ """
+ deprecation_with_replacement("getOutlineRoot", "get_outline_root", "3.0.0")
+ return self.get_outline_root()
+
+ def get_named_dest_root(self) -> 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:
+ # TABLE 3.33 Entries in a name tree node dictionary
+ nd = cast(ArrayObject, dests[CA.NAMES])
+ else:
+ nd = ArrayObject()
+ dests[NameObject(CA.NAMES)] = nd
+ else:
+ dests = DictionaryObject()
+ dests_ref = self._add_object(dests)
+ names[NameObject(CA.DESTS)] = dests_ref
+ nd = ArrayObject()
+ dests[NameObject(CA.NAMES)] = nd
+
+ else:
+ 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
+ nd = ArrayObject()
+ dests[NameObject(CA.NAMES)] = nd
+
+ return nd
+
+ def getNamedDestRoot(self) -> ArrayObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`get_named_dest_root` instead.
+ """
+ deprecation_with_replacement("getNamedDestRoot", "get_named_dest_root", "3.0.0")
+ return self.get_named_dest_root()
+
+ def add_outline_item_destination(
+ self,
+ page_destination: Union[None, PageObject, TreeObject] = None,
+ parent: Union[None, TreeObject, IndirectObject] = None,
+ before: Union[None, TreeObject, IndirectObject] = None,
+ dest: Union[None, PageObject, TreeObject] = None, # deprecated
+ ) -> IndirectObject:
+ if page_destination is not None and dest is not None: # deprecated
+ raise ValueError(
+ "The argument dest of add_outline_item_destination is deprecated. Use page_destination only."
+ )
+ if dest is not None: # deprecated
+ old_term = "dest"
+ new_term = "page_destination"
+ warnings.warn(
+ message=(
+ f"{old_term} is deprecated as an argument and will be "
+ f"removed in PyPDF2 4.0.0. Use {new_term} instead"
+ ),
+ category=DeprecationWarning,
+ )
+ page_destination = dest
+ if page_destination is None: # deprecated
+ # argument is only Optional due to deprecated argument.
+ raise ValueError("page_destination may not be None")
+
+ if parent is None:
+ parent = self.get_outline_root()
+
+ 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)
+
+ return page_destination_ref
+
+ def add_bookmark_destination(
+ self,
+ dest: Union[PageObject, TreeObject],
+ parent: Union[None, TreeObject, IndirectObject] = None,
+ ) -> IndirectObject: # pragma: no cover
+ """
+ .. deprecated:: 2.9.0
+
+ Use :meth:`add_outline_item_destination` instead.
+ """
+ deprecation_with_replacement(
+ "add_bookmark_destination", "add_outline_item_destination", "3.0.0"
+ )
+ return self.add_outline_item_destination(dest, parent)
+
+ def addBookmarkDestination(
+ self, dest: PageObject, parent: Optional[TreeObject] = None
+ ) -> IndirectObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_outline_item_destination` instead.
+ """
+ deprecation_with_replacement(
+ "addBookmarkDestination", "add_outline_item_destination", "3.0.0"
+ )
+ return self.add_outline_item_destination(dest, parent)
+
+ @deprecation_bookmark(bookmark="outline_item")
+ def add_outline_item_dict(
+ self,
+ outline_item: OutlineItemType,
+ parent: Union[None, TreeObject, IndirectObject] = None,
+ before: Union[None, TreeObject, IndirectObject] = None,
+ ) -> IndirectObject:
+ outline_item_object = TreeObject()
+ for k, v in list(outline_item.items()):
+ outline_item_object[NameObject(str(k))] = v
+ outline_item_object.update(outline_item)
+
+ 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)
+
+ @deprecation_bookmark(bookmark="outline_item")
+ def add_bookmark_dict(
+ self, outline_item: OutlineItemType, parent: Optional[TreeObject] = None
+ ) -> IndirectObject: # pragma: no cover
+ """
+ .. deprecated:: 2.9.0
+
+ Use :meth:`add_outline_item_dict` instead.
+ """
+ deprecation_with_replacement(
+ "add_bookmark_dict", "add_outline_item_dict", "3.0.0"
+ )
+ return self.add_outline_item_dict(outline_item, parent)
+
+ @deprecation_bookmark(bookmark="outline_item")
+ def addBookmarkDict(
+ self, outline_item: OutlineItemType, parent: Optional[TreeObject] = None
+ ) -> IndirectObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_outline_item_dict` instead.
+ """
+ deprecation_with_replacement(
+ "addBookmarkDict", "add_outline_item_dict", "3.0.0"
+ )
+ return self.add_outline_item_dict(outline_item, parent)
+
+ 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,
+ pagenum: Optional[int] = None, # deprecated
+ ) -> IndirectObject:
+ """
+ Add an outline item (commonly referred to as a "Bookmark") to this PDF file.
+
+ :param str title: Title to use for this outline item.
+ :param int page_number: Page number this outline item will point to.
+ :param parent: A reference to a parent outline item to create nested
+ outline items.
+ :param parent: A reference to a parent outline item to create nested
+ outline items.
+ :param tuple 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)
+ :param bool bold: Outline item font is bold
+ :param bool italic: Outline item font is italic
+ :param Fit fit: The fit of the destination page.
+ """
+ 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 # type: ignore
+ return self.add_outline_item(
+ title, page_number, parent, None, before, color, bold, italic # type: ignore
+ )
+ if page_number is not None and pagenum is not None:
+ raise ValueError(
+ "The argument pagenum of add_outline_item is deprecated. Use page_number only."
+ )
+ 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 = _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)
+
+ def add_bookmark(
+ self,
+ title: str,
+ pagenum: int, # deprecated, but the whole method is deprecated
+ parent: Union[None, TreeObject, IndirectObject] = None,
+ color: Optional[Tuple[float, float, float]] = None,
+ bold: bool = False,
+ italic: bool = False,
+ fit: FitType = "/Fit",
+ *args: ZoomArgType,
+ ) -> IndirectObject: # pragma: no cover
+ """
+ .. deprecated:: 2.9.0
+
+ Use :meth:`add_outline_item` instead.
+ """
+ deprecation_with_replacement("add_bookmark", "add_outline_item", "3.0.0")
+ return self.add_outline_item(
+ title,
+ pagenum,
+ parent,
+ color, # type: ignore
+ bold, # type: ignore
+ italic,
+ Fit(fit_type=fit, fit_args=args), # type: ignore
+ )
+
+ def addBookmark(
+ self,
+ title: str,
+ pagenum: int,
+ parent: Union[None, TreeObject, IndirectObject] = None,
+ color: Optional[Tuple[float, float, float]] = None,
+ bold: bool = False,
+ italic: bool = False,
+ fit: FitType = "/Fit",
+ *args: ZoomArgType,
+ ) -> IndirectObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_outline_item` instead.
+ """
+ deprecation_with_replacement("addBookmark", "add_outline_item", "3.0.0")
+ return self.add_outline_item(
+ title,
+ pagenum,
+ parent,
+ None,
+ color,
+ bold,
+ italic,
+ Fit(fit_type=fit, fit_args=args),
+ )
+
+ 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:
+ nd = self.get_named_dest_root()
+ i = 0
+ while i < len(nd):
+ if title < nd[i]:
+ nd.insert(i, destination)
+ nd.insert(i, TextStringObject(title))
+ return
+ else:
+ i += 2
+ nd.extend([TextStringObject(title), destination])
+ return
+
+ def add_named_destination_object(
+ self,
+ page_destination: Optional[PdfObject] = None,
+ dest: Optional[PdfObject] = None,
+ ) -> IndirectObject:
+ if page_destination is not None and dest is not None:
+ raise ValueError(
+ "The argument dest of add_named_destination_object is deprecated. Use page_destination only."
+ )
+ if dest is not None: # deprecated
+ old_term = "dest"
+ new_term = "page_destination"
+ warnings.warn(
+ message=(
+ f"{old_term} is deprecated as an argument and will be "
+ f"removed in PyPDF2 4.0.0. Use {new_term} instead"
+ ),
+ category=DeprecationWarning,
+ )
+ page_destination = dest
+ if page_destination is None: # deprecated
+ raise ValueError("page_destination may not be None")
+
+ 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 addNamedDestinationObject(
+ self, dest: Destination
+ ) -> IndirectObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_named_destination_object` instead.
+ """
+ deprecation_with_replacement(
+ "addNamedDestinationObject", "add_named_destination_object", "3.0.0"
+ )
+ return self.add_named_destination_object(dest)
+
+ def add_named_destination(
+ self,
+ title: str,
+ page_number: Optional[int] = None,
+ pagenum: Optional[int] = None, # deprecated
+ ) -> IndirectObject:
+ if page_number is not None and pagenum is not None:
+ raise ValueError(
+ "The argument pagenum of add_outline_item is deprecated. Use page_number only."
+ )
+ if pagenum is not None:
+ old_term = "pagenum"
+ new_term = "page_number"
+ warnings.warn(
+ message=(
+ f"{old_term} is deprecated as an argument and will be "
+ f"removed in PyPDF2 4.0.0. Use {new_term} instead"
+ ),
+ category=DeprecationWarning,
+ )
+ page_number = pagenum
+ if page_number is None:
+ raise ValueError("page_number may not be None")
+ 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)
+ nd = self.get_named_dest_root()
+ if not isinstance(title, TextStringObject):
+ title = TextStringObject(str(title))
+ nd.extend([title, dest_ref])
+ return dest_ref
+
+ def addNamedDestination(
+ self, title: str, pagenum: int
+ ) -> IndirectObject: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_named_destination` instead.
+ """
+ deprecation_with_replacement(
+ "addNamedDestination", "add_named_destination", "3.0.0"
+ )
+ return self.add_named_destination(title, pagenum)
+
+ def remove_links(self) -> None:
+ """Remove links and annotations from this output."""
+ pg_dict = cast(DictionaryObject, self.get_object(self._pages))
+ pages = cast(ArrayObject, pg_dict[PA.KIDS])
+ for page in pages:
+ page_ref = cast(DictionaryObject, self.get_object(page))
+ if PG.ANNOTS in page_ref:
+ del page_ref[PG.ANNOTS]
+
+ def removeLinks(self) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`remove_links` instead.
+ """
+ deprecation_with_replacement("removeLinks", "remove_links", "3.0.0")
+ return self.remove_links()
+
+ def remove_images(self, ignore_byte_string_object: bool = False) -> None:
+ """
+ Remove images from this output.
+
+ :param bool ignore_byte_string_object: optional parameter
+ to ignore ByteString Objects.
+ """
+ pg_dict = cast(DictionaryObject, self.get_object(self._pages))
+ pages = cast(ArrayObject, pg_dict[PA.KIDS])
+ jump_operators = (
+ b"cm",
+ b"w",
+ b"J",
+ b"j",
+ b"M",
+ b"d",
+ b"ri",
+ b"i",
+ b"gs",
+ b"W",
+ b"b",
+ b"s",
+ b"S",
+ b"f",
+ b"F",
+ b"n",
+ b"m",
+ b"l",
+ b"c",
+ b"v",
+ b"y",
+ b"h",
+ b"B",
+ b"Do",
+ b"sh",
+ )
+ for page in pages:
+ page_ref = cast(DictionaryObject, self.get_object(page))
+ content = page_ref["/Contents"].get_object()
+ if not isinstance(content, ContentStream):
+ content = ContentStream(content, page_ref)
+
+ _operations = []
+ seq_graphics = False
+ for operands, operator in content.operations:
+ if operator in [b"Tj", b"'"]:
+ text = operands[0]
+ if ignore_byte_string_object and not isinstance(
+ text, TextStringObject
+ ):
+ operands[0] = TextStringObject()
+ elif operator == b'"':
+ text = operands[2]
+ if ignore_byte_string_object and not isinstance(
+ text, TextStringObject
+ ):
+ operands[2] = TextStringObject()
+ elif operator == b"TJ":
+ for i in range(len(operands[0])):
+ if ignore_byte_string_object and not isinstance(
+ operands[0][i], TextStringObject
+ ):
+ operands[0][i] = TextStringObject()
+
+ if operator == b"q":
+ seq_graphics = True
+ if operator == b"Q":
+ seq_graphics = False
+ if seq_graphics and operator in jump_operators:
+ continue
+ if operator == b"re":
+ continue
+ _operations.append((operands, operator))
+
+ content.operations = _operations
+ page_ref.__setitem__(NameObject("/Contents"), content)
+
+ def removeImages(
+ self, ignoreByteStringObject: bool = False
+ ) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`remove_images` instead.
+ """
+ deprecation_with_replacement("removeImages", "remove_images", "3.0.0")
+ return self.remove_images(ignoreByteStringObject)
+
+ def remove_text(self, ignore_byte_string_object: bool = False) -> None:
+ """
+ Remove text from this output.
+
+ :param bool ignore_byte_string_object: optional parameter
+ to ignore ByteString Objects.
+ """
+ pg_dict = cast(DictionaryObject, self.get_object(self._pages))
+ pages = cast(List[IndirectObject], pg_dict[PA.KIDS])
+ for page in pages:
+ page_ref = cast(PageObject, self.get_object(page))
+ content = page_ref["/Contents"].get_object()
+ if not isinstance(content, ContentStream):
+ content = ContentStream(content, page_ref)
+ for operands, operator in content.operations:
+ if operator in [b"Tj", b"'"]:
+ text = operands[0]
+ if not ignore_byte_string_object:
+ if isinstance(text, TextStringObject):
+ operands[0] = TextStringObject()
+ else:
+ if isinstance(text, (TextStringObject, ByteStringObject)):
+ operands[0] = TextStringObject()
+ elif operator == b'"':
+ text = operands[2]
+ if not ignore_byte_string_object:
+ if isinstance(text, TextStringObject):
+ operands[2] = TextStringObject()
+ else:
+ if isinstance(text, (TextStringObject, ByteStringObject)):
+ operands[2] = TextStringObject()
+ elif operator == b"TJ":
+ for i in range(len(operands[0])):
+ if not ignore_byte_string_object:
+ if isinstance(operands[0][i], TextStringObject):
+ operands[0][i] = TextStringObject()
+ else:
+ if isinstance(
+ operands[0][i], (TextStringObject, ByteStringObject)
+ ):
+ operands[0][i] = TextStringObject()
+
+ page_ref.__setitem__(NameObject("/Contents"), content)
+
+ def removeText(
+ self, ignoreByteStringObject: bool = False
+ ) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`remove_text` instead.
+ """
+ deprecation_with_replacement("removeText", "remove_text", "3.0.0")
+ return self.remove_text(ignoreByteStringObject)
+
+ def add_uri(
+ self,
+ page_number: int,
+ uri: str,
+ rect: RectangleObject,
+ border: Optional[ArrayObject] = None,
+ pagenum: Optional[int] = None,
+ ) -> None:
+ """
+ Add an URI from a rectangular area to the specified page.
+ This uses the basic structure of :meth:`add_link`
+
+ :param int page_number: index of the page on which to place the URI action.
+ :param str uri: URI of resource to link to.
+ :param Tuple[int, int, int, int] rect: :class:`RectangleObject<PyPDF2.generic.RectangleObject>` or array of four
+ integers specifying the clickable rectangular area
+ ``[xLL, yLL, xUR, yUR]``, or string in the form ``"[ xLL yLL xUR yUR ]"``.
+ :param ArrayObject 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.
+ """
+ if pagenum is not None:
+ warnings.warn(
+ "The 'pagenum' argument of add_uri is deprecated and will be "
+ "removed in PyPDF2 4.0.0. Use 'page_number' instead.",
+ category=DeprecationWarning,
+ )
+ page_number = pagenum
+ 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 = [NameObject(n) for n in border[:3]]
+ if len(border) == 4:
+ dash_pattern = ArrayObject([NameObject(n) for n in border[3]])
+ border_arr.append(dash_pattern)
+ else:
+ border_arr = [NumberObject(2)] * 3
+
+ if isinstance(rect, str):
+ rect = NameObject(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(AnnotationDictionaryAttributes.Type): NameObject(PG.ANNOTS),
+ NameObject(AnnotationDictionaryAttributes.Subtype): NameObject("/Link"),
+ NameObject(AnnotationDictionaryAttributes.P): page_link,
+ NameObject(AnnotationDictionaryAttributes.Rect): rect,
+ NameObject("/H"): NameObject("/I"),
+ NameObject(AnnotationDictionaryAttributes.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])
+
+ def addURI(
+ self,
+ pagenum: int, # deprecated, but method is deprecated already
+ uri: str,
+ rect: RectangleObject,
+ border: Optional[ArrayObject] = None,
+ ) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_uri` instead.
+ """
+ deprecation_with_replacement("addURI", "add_uri", "3.0.0")
+ return self.add_uri(pagenum, uri, rect, border)
+
+ def add_link(
+ self,
+ pagenum: int, # deprecated, but method is deprecated already
+ page_destination: int,
+ rect: RectangleObject,
+ border: Optional[ArrayObject] = None,
+ fit: FitType = "/Fit",
+ *args: ZoomArgType,
+ ) -> None:
+ deprecation_with_replacement(
+ "add_link", "add_annotation(AnnotationBuilder.link(...))"
+ )
+
+ if isinstance(rect, str):
+ rect = rect.strip()[1:-1]
+ rect = RectangleObject(
+ [float(num) for num in rect.split(" ") if len(num) > 0]
+ )
+ elif isinstance(rect, RectangleObject):
+ pass
+ else:
+ rect = RectangleObject(rect)
+
+ annotation = AnnotationBuilder.link(
+ rect=rect,
+ border=border,
+ target_page_index=page_destination,
+ fit=Fit(fit_type=fit, fit_args=args),
+ )
+ return self.add_annotation(page_number=pagenum, annotation=annotation)
+
+ def addLink(
+ self,
+ pagenum: int, # deprecated, but method is deprecated already
+ page_destination: int,
+ rect: RectangleObject,
+ border: Optional[ArrayObject] = None,
+ fit: FitType = "/Fit",
+ *args: ZoomArgType,
+ ) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`add_link` instead.
+ """
+ deprecate_with_replacement(
+ "addLink", "add_annotation(AnnotationBuilder.link(...))", "4.0.0"
+ )
+ return self.add_link(pagenum, page_destination, rect, border, fit, *args)
+
+ _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 getPageLayout(self) -> Optional[LayoutType]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`page_layout` instead.
+ """
+ deprecation_with_replacement("getPageLayout", "page_layout", "3.0.0")
+ return self._get_page_layout()
+
+ def _set_page_layout(self, layout: Union[NameObject, LayoutType]) -> None:
+ """
+ Set the page layout.
+
+ :param str 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.
+
+ :param str 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)
+
+ def setPageLayout(self, layout: LayoutType) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`page_layout` instead.
+ """
+ deprecation_with_replacement(
+ "writer.setPageLayout(val)", "writer.page_layout = val", "3.0.0"
+ )
+ return 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)
+
+ @property
+ def pageLayout(self) -> Optional[LayoutType]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`page_layout` instead.
+ """
+ deprecation_with_replacement("pageLayout", "page_layout", "3.0.0")
+ return self.page_layout
+
+ @pageLayout.setter
+ def pageLayout(self, layout: LayoutType) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`page_layout` instead.
+ """
+ deprecation_with_replacement("pageLayout", "page_layout", "3.0.0")
+ self.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
+
+ def getPageMode(self) -> Optional[PagemodeType]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`page_mode` instead.
+ """
+ deprecation_with_replacement("getPageMode", "page_mode", "3.0.0")
+ return self._get_page_mode()
+
+ def set_page_mode(self, mode: PagemodeType) -> None:
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`page_mode` instead.
+ """
+ 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 setPageMode(self, mode: PagemodeType) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`page_mode` instead.
+ """
+ deprecation_with_replacement(
+ "writer.setPageMode(val)", "writer.page_mode = val", "3.0.0"
+ )
+ self.set_page_mode(mode)
+
+ @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:
+ self.set_page_mode(mode)
+
+ @property
+ def pageMode(self) -> Optional[PagemodeType]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`page_mode` instead.
+ """
+ deprecation_with_replacement("pageMode", "page_mode", "3.0.0")
+ return self.page_mode
+
+ @pageMode.setter
+ def pageMode(self, mode: PagemodeType) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :py:attr:`page_mode` instead.
+ """
+ deprecation_with_replacement("pageMode", "page_mode", "3.0.0")
+ self.page_mode = mode
+
+ def add_annotation(self, page_number: int, annotation: Dict[str, Any]) -> None:
+ to_add = cast(DictionaryObject, _pdf_objectify(annotation))
+ to_add[NameObject("/P")] = self.get_object(self._pages)["/Kids"][page_number] # type: ignore
+ page = self.pages[page_number]
+ 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 NameObject("/Dest") in to_add:
+ tmp = cast(dict, 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
+
+ ind_obj = self._add_object(to_add)
+
+ page.annotations.append(ind_obj)
+
+ def clean_page(self, page: Union[PageObject, IndirectObject]) -> PageObject:
+ """
+ Perform some clean up in the page.
+ Currently: convert NameObject nameddestination to TextStringObject (required for names/dests list)
+ """
+ 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(
+ "PdfMerger.merge 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]
+ ] = None,
+ import_outline: bool = True,
+ excluded_fields: Optional[Union[List[str], Tuple[str, ...]]] = None,
+ ) -> None:
+ """
+ Identical to the :meth:`merge()<merge>` method, but assumes you want to
+ concatenate all pages onto the end of the file instead of specifying a
+ position.
+
+ :param 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.
+
+ :param str outline_item: Optionally, you may specify a string to build an outline
+ (aka 'bookmark') to identify the
+ beginning of the included file.
+
+ :param pages: can be a :class:`PageRange<PyPDF2.pagerange.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.
+
+ :param bool 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``.
+
+ :param List 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
+ )
+
+ @deprecation_bookmark(bookmark="outline_item", import_bookmarks="import_outline")
+ def merge(
+ self,
+ position: Optional[int],
+ fileobj: Union[Path, StrByteType, PdfReader],
+ outline_item: Optional[str] = None,
+ pages: Optional[PageRangeSpec] = 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.
+
+ :param int position: The *page number* to insert this file. File will
+ be inserted after the given number.
+
+ :param 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.
+
+ :param str outline_item: Optionally, you may specify a string to build an outline
+ (aka 'bookmark') to identify the
+ beginning of the included file.
+
+ :param pages: can be a :class:`PageRange<PyPDF2.pagerange.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.
+
+ :param bool 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``.
+
+ :param List 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 isinstance(fileobj, PdfReader):
+ 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(0, 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 i in pages:
+ pg = reader.pages[i]
+ assert pg.indirect_reference is not None
+ if position is None:
+ srcpages[pg.indirect_reference.idnum] = self.add_page(
+ pg, list(excluded_fields) + ["/B", "/Annots"] # type: ignore
+ )
+ else:
+ srcpages[pg.indirect_reference.idnum] = self.insert_page(
+ pg, position, list(excluded_fields) + ["/B", "/Annots"] # type: ignore
+ )
+ position += 1
+ srcpages[pg.indirect_reference.idnum].original_page = pg
+
+ reader._namedDests = (
+ reader.named_destinations
+ ) # need for the outline processing below
+ for dest in reader._namedDests.values():
+ arr = dest.dest_array
+ # try:
+ if isinstance(dest["/Page"], NullObject):
+ pass # self.add_named_destination_array(dest["/Title"],arr)
+ 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)
+ # except Exception as e:
+ # logger_warning(f"can not insert {dest} : {e.msg}",__name__)
+
+ outline_item_typ: TreeObject
+ if outline_item is not None:
+ outline_item_typ = cast(
+ "TreeObject",
+ self.add_outline_item(
+ TextStringObject(outline_item),
+ list(srcpages.values())[0].indirect_reference,
+ fit=PAGE_FIT,
+ ).get_object(),
+ )
+ else:
+ outline_item_typ = self.get_outline_root()
+
+ _ro = cast("DictionaryObject", reader.trailer[TK.ROOT])
+ 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 "/B" not in excluded_fields:
+ self.add_filtered_articles("", srcpages, reader)
+
+ return
+
+ 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
+
+ """
+ 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, str], # thread entry from the reader's array of threads
+ pages: Dict[int, PageObject],
+ reader: PdfReader,
+ ) -> None:
+ """
+ Add articles matching the defined criteria
+ """
+ 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()["/T"]
+ if thr.indirect_reference.idnum not in self._id_translated[
+ id(reader)
+ ] and fltr.search(thr["/I"]["/Title"]):
+ self._add_articles_thread(thr, pages, reader)
+
+ def _get_cloned_page(
+ self,
+ page: Union[None, int, IndirectObject, PageObject, NullObject],
+ pages: Dict[int, PageObject],
+ reader: PdfReader,
+ ) -> Optional[IndirectObject]:
+ if isinstance(page, NullObject):
+ return None
+ if isinstance(page, int):
+ _i = reader.pages[page].indirect_reference
+ # elif isinstance(page, PageObject):
+ # _i = page.indirect_reference
+ 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]],
+ page: PageObject,
+ pages: Dict[int, PageObject],
+ reader: PdfReader,
+ ) -> List[Destination]:
+ outlist = ArrayObject()
+ if isinstance(annots, IndirectObject):
+ annots = cast("List", annots.get_object())
+ 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(ano.clone(self).indirect_reference)
+ 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(anc.indirect_reference)
+ else:
+ d = cast("DictionaryObject", ano["/A"])["/D"]
+ 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",))
+ anc = cast("DictionaryObject", anc)
+ cast("DictionaryObject", anc["/A"])[
+ NameObject("/D")
+ ] = ArrayObject([p] + d[1:])
+ outlist.append(anc.indirect_reference)
+ 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."""
+ new_outline = []
+ node = node.get_object()
+ 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.childs = self._get_filtered_outline(node["/First"], pages, reader)
+ else:
+ o.childs = []
+ if not isinstance(o["/Page"], NullObject) or len(o.childs) > 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)
+ # elif "/D" in dest.node:
+ # n_ol[NameObject("/Dest")] = dest.node["/D"].clone(self)
+ # elif "/Dest" in dest.node:
+ # n_ol[NameObject("/Dest")] = dest.node["/Dest"].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)
+ # 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.childs, np, None)
+
+ def close(self) -> None:
+ """To match the functions from Merger"""
+ return
+
+ # @deprecation_bookmark(bookmark="outline_item")
+ 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]
+ else:
+ if "/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
+
+ @deprecation_bookmark(bookmark="outline_item")
+ def find_bookmark(
+ self,
+ outline_item: Dict[str, Any],
+ root: Optional[OutlineType] = None,
+ ) -> Optional[List[int]]: # pragma: no cover
+ """
+ .. deprecated:: 2.9.0
+ Use :meth:`find_outline_item` instead.
+ """
+ return self.find_outline_item(outline_item, root)
+
+ 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
+
+ :param reader: PdfReader or IndirectObject refering 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 _pdf_objectify(obj: Union[Dict[str, Any], str, int, List[Any]]) -> PdfObject:
+ if isinstance(obj, PdfObject):
+ return obj
+ if isinstance(obj, dict):
+ to_add = DictionaryObject()
+ for key, value in obj.items():
+ name_key = NameObject(key)
+ casted_value = _pdf_objectify(value)
+ to_add[name_key] = casted_value
+ return to_add
+ elif isinstance(obj, list):
+ arr = ArrayObject()
+ for el in obj:
+ arr.append(_pdf_objectify(el))
+ return arr
+ elif isinstance(obj, str):
+ if obj.startswith("/"):
+ return NameObject(obj)
+ else:
+ return TextStringObject(obj)
+ elif isinstance(obj, (int, float)):
+ return FloatObject(obj)
+ else:
+ raise NotImplementedError(
+ f"type(obj)={type(obj)} could not be casted to 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)
+ prec = decimal.Decimal("1.00000")
+ outline_item.update(
+ {
+ NameObject("/C"): ArrayObject(
+ [FloatObject(decimal.Decimal(c).quantize(prec)) for c in color]
+ )
+ }
+ )
+ if italic or bold:
+ format_flag = 0
+ if italic:
+ format_flag += 1
+ if bold:
+ format_flag += 2
+ outline_item.update({NameObject("/F"): NumberObject(format_flag)})
+ return outline_item
+
+
+class PdfFileWriter(PdfWriter): # pragma: no cover
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
+ deprecation_with_replacement("PdfFileWriter", "PdfWriter", "3.0.0")
+ super().__init__(*args, **kwargs)
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/constants.py b/.venv/lib/python3.12/site-packages/PyPDF2/constants.py
new file mode 100644
index 00000000..a2f8c49e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/constants.py
@@ -0,0 +1,461 @@
+"""
+See Portable Document Format Reference Manual, 1993. ISBN 0-201-62628-4.
+
+See https://ia802202.us.archive.org/8/items/pdfy-0vt8s-egqFwDl7L2/PDF%20Reference%201.0.pdf
+
+PDF Reference, third edition, Version 1.4, 2001. ISBN 0-201-75839-3.
+
+PDF Reference, sixth edition, Version 1.7, 2006.
+"""
+
+from enum import IntFlag
+from typing import Dict, Tuple
+
+
+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"
+
+
+class CatalogAttributes:
+ NAMES = "/Names"
+ DESTS = "/Dests"
+
+
+class EncryptionDictAttributes:
+ """
+ Additional encryption dictionary entries for the standard security handler.
+
+ TABLE 3.19, Page 122
+ """
+
+ R = "/R" # number, required; revision of the standard security handler
+ O = "/O" # 32-byte string, required
+ 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"""
+
+ 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
+
+
+class Ressources:
+ """TABLE 3.30 Entries in a resource dictionary."""
+
+ 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 PagesAttributes:
+ """Page Attributes, Table 6.2, Page 52."""
+
+ TYPE = "/Type" # name, required; must be /Pages
+ KIDS = "/Kids" # array, required; List of indirect references
+ COUNT = "/Count" # integer, required; the number of all nodes und this node
+ PARENT = "/Parent" # dictionary, required; indirect reference to pages object
+
+
+class PageAttributes:
+ """TABLE 3.27 Entries in a page object."""
+
+ 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; rectangle
+ BLEEDBOX = "/BleedBox" # rectangle, optional; rectangle
+ TRIMBOX = "/TrimBox" # rectangle, optional; rectangle
+ ARTBOX = "/ArtBox" # rectangle, optional; rectangle
+ 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
+ TABS = "/Tabs" # name, optional
+ TEMPLATE_INSTANTIATED = "/TemplateInstantiated" # name, optional
+ PRES_STEPS = "/PresSteps" # dictionary, optional
+ USER_UNIT = "/UserUnit" # number, optional
+ VP = "/VP" # dictionary, optional
+
+
+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 Section 3.10.1
+ EF = "/EF" # dictionary, containing a subset of the keys F , UF , DOS , Mac , and Unix
+
+
+class StreamAttributes:
+ """Table 4.2."""
+
+ LENGTH = "/Length" # integer, required
+ FILTER = "/Filter" # name or array of names, optional
+ DECODE_PARMS = "/DecodeParms" # variable, optional -- 'decodeParams is wrong
+
+
+class FilterTypes:
+ """
+ Table 4.3 of the 1.4 Manual.
+
+ Page 354 of the 1.7 Manual
+ """
+
+ 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
+
+
+class FilterTypeAbbreviations:
+ """Table 4.44 of the 1.7 Manual (page 353ff)."""
+
+ AHx = "/AHx"
+ A85 = "/A85"
+ LZW = "/LZW"
+ FL = "/Fl" # FlateDecode
+ RL = "/RL"
+ CCF = "/CCF"
+ DCT = "/DCT"
+
+
+class LzwFilterParameters:
+ """Table 4.4."""
+
+ PREDICTOR = "/Predictor" # integer
+ COLUMNS = "/Columns" # integer
+ COLORS = "/Colors" # integer
+ BITS_PER_COMPONENT = "/BitsPerComponent" # integer
+ EARLY_CHANGE = "/EarlyChange" # integer
+
+
+class CcittFaxDecodeParameters:
+ """Table 4.5."""
+
+ 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:
+ """Table 6.20."""
+
+ 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
+ INTERPOLATE = "/Interpolate" # boolean, optional
+ IMAGE_MASK = "/ImageMask" # boolean, 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"
+ 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:
+ """TABLE 8.69 Entries common to all field dictionaries (PDF 1.7 reference)."""
+
+ 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, optional
+ DV = "/DV" # text string, optional
+ AA = "/AA" # dictionary, optional
+
+ @classmethod
+ def attributes(cls) -> Tuple[str, ...]:
+ 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]:
+ 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, ...]:
+ return (cls.Opt,)
+
+ @classmethod
+ def attributes_dict(cls) -> Dict[str, str]:
+ 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."""
+
+ SINGLE_PAGE = "/SinglePage"
+ ONE_COLUMN = "/OneColumn"
+ TWO_COLUMN_LEFT = "/TwoColumnLeft"
+ TWO_COLUMN_RIGHT = "/TwoColumnRight"
+
+
+class GraphicsStateParameters:
+ """Table 4.8 of the 1.7 reference."""
+
+ TYPE = "/Type" # name, optional
+ LW = "/LW" # number, optional
+ # TODO: Many more!
+ FONT = "/Font" # array, optional
+ S_MASK = "/SMask" # dictionary or name, optional
+
+
+class CatalogDictionary:
+ """Table 3.25 in the 1.7 reference."""
+
+ TYPE = "/Type" # name, required; must be /Catalog
+ VERSION = "/Version" # name
+ 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
+
+
+class OutlineFontFlag(IntFlag):
+ """
+ A class used as an enumerable flag for formatting an outline font
+ """
+
+ italic = 1
+ bold = 2
+
+
+PDF_KEYS = (
+ AnnotationDictionaryAttributes,
+ CatalogAttributes,
+ CatalogDictionary,
+ CcittFaxDecodeParameters,
+ CheckboxRadioButtonAttributes,
+ ColorSpaces,
+ Core,
+ DocumentInformationAttributes,
+ EncryptionDictAttributes,
+ FieldDictionaryAttributes,
+ FilterTypeAbbreviations,
+ FilterTypes,
+ GoToActionArguments,
+ GraphicsStateParameters,
+ ImageAttributes,
+ FileSpecificationDictionaryEntries,
+ LzwFilterParameters,
+ PageAttributes,
+ PageLayouts,
+ PagesAttributes,
+ Ressources,
+ StreamAttributes,
+ TrailerKeys,
+ TypArguments,
+ TypFitArguments,
+)
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/errors.py b/.venv/lib/python3.12/site-packages/PyPDF2/errors.py
new file mode 100644
index 00000000..a84b0569
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/errors.py
@@ -0,0 +1,54 @@
+"""
+All errors/exceptions PyPDF2 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."""
+
+ pass
+
+
+class DependencyError(Exception):
+ pass
+
+
+class PyPdfError(Exception):
+ pass
+
+
+class PdfReadError(PyPdfError):
+ pass
+
+
+class PageSizeNotDefinedError(PyPdfError):
+ pass
+
+
+class PdfReadWarning(UserWarning):
+ pass
+
+
+class PdfStreamError(PdfReadError):
+ pass
+
+
+class ParseError(Exception):
+ pass
+
+
+class FileNotDecryptedError(PdfReadError):
+ pass
+
+
+class WrongPasswordError(FileNotDecryptedError):
+ pass
+
+
+class EmptyFileError(PdfReadError):
+ pass
+
+
+STREAM_TRUNCATED_PREMATURELY = "Stream has ended unexpectedly"
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/filters.py b/.venv/lib/python3.12/site-packages/PyPDF2/filters.py
new file mode 100644
index 00000000..11f6a21b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/filters.py
@@ -0,0 +1,645 @@
+# 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 io import BytesIO
+from typing import Any, Dict, Optional, Tuple, Union, cast
+
+from .generic import ArrayObject, DictionaryObject, IndirectObject, NameObject
+
+try:
+ from typing import Literal # type: ignore[attr-defined]
+except ImportError:
+ # PEP 586 introduced typing.Literal with Python 3.8
+ # For older Python versions, the backport typing_extensions is necessary:
+ from typing_extensions import Literal # type: ignore[misc]
+
+from ._utils import b_, deprecate_with_replacement, ord_, paeth_predictor
+from .constants import CcittFaxDecodeParameters as CCITT
+from .constants import ColorSpaces
+from .constants import FilterTypeAbbreviations as FTA
+from .constants import FilterTypes as FT
+from .constants import GraphicsStateParameters as G
+from .constants import ImageAttributes as IA
+from .constants import LzwFilterParameters as LZW
+from .constants import StreamAttributes as SA
+from .errors import PdfReadError, PdfStreamError
+
+
+def decompress(data: bytes) -> bytes:
+ try:
+ return zlib.decompress(data)
+ except zlib.error:
+ 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: Union[None, ArrayObject, DictionaryObject] = None,
+ **kwargs: Any,
+ ) -> bytes:
+ """
+ Decode data which is flate-encoded.
+
+ :param data: flate-encoded data.
+ :param decode_parms: a dictionary of values, understanding the
+ "/Predictor":<int> key only
+ :return: the flate-decoded data.
+
+ :raises PdfReadError:
+ """
+ if "decodeParms" in kwargs: # pragma: no cover
+ deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
+ decode_parms = kwargs["decodeParms"]
+ str_data = decompress(data)
+ predictor = 1
+
+ if decode_parms:
+ try:
+ if isinstance(decode_parms, ArrayObject):
+ for decode_parm in decode_parms:
+ if "/Predictor" in decode_parm:
+ predictor = decode_parm["/Predictor"]
+ else:
+ 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:
+ # The /Columns param. has 1 as the default value; see ISO 32000,
+ # §7.4.4.3 LZWDecode and FlateDecode Parameters, Table 8
+ DEFAULT_BITS_PER_COMPONENT = 8
+ if isinstance(decode_parms, ArrayObject):
+ columns = 1
+ bits_per_component = DEFAULT_BITS_PER_COMPONENT
+ for decode_parm in decode_parms:
+ if "/Columns" in decode_parm:
+ columns = decode_parm["/Columns"]
+ if LZW.BITS_PER_COMPONENT in decode_parm:
+ bits_per_component = decode_parm[LZW.BITS_PER_COMPONENT]
+ else:
+ columns = (
+ 1 if decode_parms is None else decode_parms.get(LZW.COLUMNS, 1)
+ )
+ bits_per_component = (
+ decode_parms.get(LZW.BITS_PER_COMPONENT, DEFAULT_BITS_PER_COMPONENT)
+ if decode_parms
+ else DEFAULT_BITS_PER_COMPONENT
+ )
+
+ # PNG predictor can vary by row and so is the lead byte on each row
+ rowlength = (
+ math.ceil(columns * bits_per_component / 8) + 1
+ ) # number of bytes
+
+ # PNG prediction:
+ if 10 <= predictor <= 15:
+ str_data = FlateDecode._decode_png_prediction(str_data, columns, rowlength) # type: ignore
+ else:
+ # unsupported predictor
+ raise PdfReadError(f"Unsupported flatedecode predictor {predictor!r}")
+ return str_data
+
+ @staticmethod
+ def _decode_png_prediction(data: str, columns: int, rowlength: int) -> bytes:
+ output = BytesIO()
+ # PNG prediction can vary from row to row
+ if len(data) % rowlength != 0:
+ raise PdfReadError("Image data is not rectangular")
+ prev_rowdata = (0,) * rowlength
+ for row in range(len(data) // rowlength):
+ rowdata = [
+ ord_(x) for x in data[(row * rowlength) : ((row + 1) * rowlength)]
+ ]
+ filter_byte = rowdata[0]
+
+ if filter_byte == 0:
+ pass
+ elif filter_byte == 1:
+ for i in range(2, rowlength):
+ rowdata[i] = (rowdata[i] + rowdata[i - 1]) % 256
+ elif filter_byte == 2:
+ for i in range(1, rowlength):
+ rowdata[i] = (rowdata[i] + prev_rowdata[i]) % 256
+ elif filter_byte == 3:
+ for i in range(1, rowlength):
+ left = rowdata[i - 1] if i > 1 else 0
+ floor = math.floor(left + prev_rowdata[i]) / 2
+ rowdata[i] = (rowdata[i] + int(floor)) % 256
+ elif filter_byte == 4:
+ for i in range(1, rowlength):
+ left = rowdata[i - 1] if i > 1 else 0
+ up = prev_rowdata[i]
+ up_left = prev_rowdata[i - 1] if i > 1 else 0
+ paeth = paeth_predictor(left, up, up_left)
+ rowdata[i] = (rowdata[i] + paeth) % 256
+ else:
+ # unsupported PNG filter
+ raise PdfReadError(f"Unsupported PNG filter {filter_byte!r}")
+ prev_rowdata = tuple(rowdata)
+ output.write(bytearray(rowdata[1:]))
+ return output.getvalue()
+
+ @staticmethod
+ def encode(data: bytes) -> bytes:
+ return zlib.compress(data)
+
+
+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: str,
+ decode_parms: Union[None, ArrayObject, DictionaryObject] = None, # noqa: F841
+ **kwargs: Any,
+ ) -> str:
+ """
+ :param data: a str sequence of hexadecimal-encoded values to be
+ converted into a base-7 ASCII string
+ :param decode_parms:
+ :return: a string conversion in base-7 ASCII, where each of its values
+ v is such that 0 <= ord(v) <= 127.
+
+ :raises PdfStreamError:
+ """
+ if "decodeParms" in kwargs: # pragma: no cover
+ deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
+ decode_parms = kwargs["decodeParms"] # noqa: F841
+ retval = ""
+ hex_pair = ""
+ index = 0
+ while True:
+ if index >= len(data):
+ raise PdfStreamError("Unexpected EOD in ASCIIHexDecode")
+ char = data[index]
+ if char == ">":
+ break
+ elif char.isspace():
+ index += 1
+ continue
+ hex_pair += char
+ if len(hex_pair) == 2:
+ retval += chr(int(hex_pair, base=16))
+ hex_pair = ""
+ index += 1
+ assert hex_pair == ""
+ return retval
+
+
+class LZWDecode:
+ """Taken from:
+ http://www.java2s.com/Open-Source/Java-Document/PDF/PDF-Renderer/com/sun/pdfview/decode/LZWDecode.java.htm
+ """
+
+ class Decoder:
+ def __init__(self, data: bytes) -> None:
+ self.STOP = 257
+ self.CLEARDICT = 256
+ self.data = data
+ self.bytepos = 0
+ self.bitpos = 0
+ self.dict = [""] * 4096
+ for i in range(256):
+ self.dict[i] = chr(i)
+ self.reset_dict()
+
+ def reset_dict(self) -> None:
+ self.dictlen = 258
+ self.bitspercode = 9
+
+ def next_code(self) -> int:
+ fillbits = self.bitspercode
+ value = 0
+ while fillbits > 0:
+ if self.bytepos >= len(self.data):
+ return -1
+ nextbits = ord_(self.data[self.bytepos])
+ bitsfromhere = 8 - self.bitpos
+ bitsfromhere = min(bitsfromhere, fillbits)
+ value |= (
+ (nextbits >> (8 - self.bitpos - bitsfromhere))
+ & (0xFF >> (8 - bitsfromhere))
+ ) << (fillbits - bitsfromhere)
+ fillbits -= bitsfromhere
+ self.bitpos += bitsfromhere
+ if self.bitpos >= 8:
+ self.bitpos = 0
+ self.bytepos = self.bytepos + 1
+ return value
+
+ def decode(self) -> str:
+ """
+ TIFF 6.0 specification explains in sufficient details the steps to
+ implement the LZW encode() and decode() algorithms.
+
+ algorithm derived from:
+ http://www.rasip.fer.hr/research/compress/algorithms/fund/lz/lzw.html
+ and the PDFReference
+
+ :raises PdfReadError: If the stop code is missing
+ """
+ cW = self.CLEARDICT
+ baos = ""
+ while True:
+ pW = cW
+ cW = self.next_code()
+ if cW == -1:
+ raise PdfReadError("Missed the stop code in LZWDecode!")
+ if cW == self.STOP:
+ break
+ elif cW == self.CLEARDICT:
+ self.reset_dict()
+ elif pW == self.CLEARDICT:
+ baos += self.dict[cW]
+ else:
+ if cW < self.dictlen:
+ baos += self.dict[cW]
+ p = self.dict[pW] + self.dict[cW][0]
+ self.dict[self.dictlen] = p
+ self.dictlen += 1
+ else:
+ p = self.dict[pW] + self.dict[pW][0]
+ baos += p
+ self.dict[self.dictlen] = p
+ self.dictlen += 1
+ if (
+ self.dictlen >= (1 << self.bitspercode) - 1
+ and self.bitspercode < 12
+ ):
+ self.bitspercode += 1
+ return baos
+
+ @staticmethod
+ def decode(
+ data: bytes,
+ decode_parms: Union[None, ArrayObject, DictionaryObject] = None,
+ **kwargs: Any,
+ ) -> str:
+ """
+ :param data: ``bytes`` or ``str`` text to decode.
+ :param decode_parms: a dictionary of parameter values.
+ :return: decoded data.
+ """
+ if "decodeParms" in kwargs: # pragma: no cover
+ deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
+ decode_parms = kwargs["decodeParms"] # noqa: F841
+ return LZWDecode.Decoder(data).decode()
+
+
+class ASCII85Decode:
+ """Decodes string ASCII85-encoded data into a byte format."""
+
+ @staticmethod
+ def decode(
+ data: Union[str, bytes],
+ decode_parms: Union[None, ArrayObject, DictionaryObject] = None,
+ **kwargs: Any,
+ ) -> bytes:
+ if "decodeParms" in kwargs: # pragma: no cover
+ deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
+ decode_parms = kwargs["decodeParms"] # noqa: F841
+ if isinstance(data, str):
+ data = data.encode("ascii")
+ group_index = b = 0
+ out = bytearray()
+ for char in data:
+ if ord("!") <= char and char <= ord("u"):
+ group_index += 1
+ b = b * 85 + (char - 33)
+ if group_index == 5:
+ out += struct.pack(b">L", b)
+ group_index = b = 0
+ elif char == ord("z"):
+ assert group_index == 0
+ out += b"\0\0\0\0"
+ elif char == ord("~"):
+ if group_index:
+ for _ in range(5 - group_index):
+ b = b * 85 + 84
+ out += struct.pack(b">L", b)[: group_index - 1]
+ break
+ return bytes(out)
+
+
+class DCTDecode:
+ @staticmethod
+ def decode(
+ data: bytes,
+ decode_parms: Union[None, ArrayObject, DictionaryObject] = None,
+ **kwargs: Any,
+ ) -> bytes:
+ if "decodeParms" in kwargs: # pragma: no cover
+ deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
+ decode_parms = kwargs["decodeParms"] # noqa: F841
+ return data
+
+
+class JPXDecode:
+ @staticmethod
+ def decode(
+ data: bytes,
+ decode_parms: Union[None, ArrayObject, DictionaryObject] = None,
+ **kwargs: Any,
+ ) -> bytes:
+ if "decodeParms" in kwargs: # pragma: no cover
+ deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
+ decode_parms = kwargs["decodeParms"] # noqa: F841
+ return data
+
+
+class CCITParameters:
+ """TABLE 3.9 Optional parameters for the CCITTFaxDecode filter."""
+
+ def __init__(self, K: int = 0, columns: int = 0, rows: int = 0) -> None:
+ self.K = K
+ self.EndOfBlock = None
+ self.EndOfLine = None
+ self.EncodedByteAlign = None
+ self.columns = columns # width
+ self.rows = rows # height
+ self.DamagedRowsBeforeError = None
+
+ @property
+ def group(self) -> int:
+ if self.K < 0:
+ 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
+
+
+class CCITTFaxDecode:
+ """
+ See 3.3.5 CCITTFaxDecode Filter (PDF 1.7 Standard).
+
+ Either Group 3 or Group 4 CCITT facsimile (fax) encoding.
+ CCITT encoding is bit-oriented, not byte-oriented.
+
+ See: TABLE 3.9 Optional parameters for the CCITTFaxDecode filter
+ """
+
+ @staticmethod
+ def _get_parameters(
+ parameters: Union[None, ArrayObject, DictionaryObject], rows: int
+ ) -> CCITParameters:
+ # TABLE 3.9 Optional parameters for the CCITTFaxDecode filter
+ k = 0
+ columns = 1728
+ if parameters:
+ if isinstance(parameters, ArrayObject):
+ for decode_parm in parameters:
+ if CCITT.COLUMNS in decode_parm:
+ columns = decode_parm[CCITT.COLUMNS]
+ if CCITT.K in decode_parm:
+ k = decode_parm[CCITT.K]
+ else:
+ if CCITT.COLUMNS in parameters:
+ columns = parameters[CCITT.COLUMNS] # type: ignore
+ if CCITT.K in parameters:
+ k = parameters[CCITT.K] # type: ignore
+
+ return CCITParameters(k, columns, rows)
+
+ @staticmethod
+ def decode(
+ data: bytes,
+ decode_parms: Union[None, ArrayObject, DictionaryObject] = None,
+ height: int = 0,
+ **kwargs: Any,
+ ) -> bytes:
+ if "decodeParms" in kwargs: # pragma: no cover
+ deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
+ decode_parms = kwargs["decodeParms"]
+ parms = 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,
+ parms.columns, # ImageWidth, LONG, 1, width
+ 257,
+ 4,
+ 1,
+ parms.rows, # ImageLength, LONG, 1, length
+ 258,
+ 3,
+ 1,
+ 1, # BitsPerSample, SHORT, 1, 1
+ 259,
+ 3,
+ 1,
+ parms.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,
+ parms.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) -> Union[str, bytes]: # utils.StreamObject
+ filters = stream.get(SA.FILTER, ())
+ if isinstance(filters, IndirectObject):
+ filters = cast(ArrayObject, filters.get_object())
+ if len(filters) and not isinstance(filters[0], NameObject):
+ # we have a single filter instance
+ filters = (filters,)
+ data: bytes = stream._data
+ # If there is not data to decode we should not try to decode the data.
+ if data:
+ for filter_type in filters:
+ if filter_type in (FT.FLATE_DECODE, FTA.FL):
+ data = FlateDecode.decode(data, stream.get(SA.DECODE_PARMS))
+ elif filter_type in (FT.ASCII_HEX_DECODE, FTA.AHx):
+ data = ASCIIHexDecode.decode(data) # type: ignore
+ elif filter_type in (FT.LZW_DECODE, FTA.LZW):
+ data = LZWDecode.decode(data, stream.get(SA.DECODE_PARMS)) # type: ignore
+ elif filter_type in (FT.ASCII_85_DECODE, FTA.A85):
+ data = ASCII85Decode.decode(data)
+ elif filter_type == FT.DCT_DECODE:
+ data = DCTDecode.decode(data)
+ elif filter_type == "/JPXDecode":
+ data = JPXDecode.decode(data)
+ elif filter_type == FT.CCITT_FAX_DECODE:
+ height = stream.get(IA.HEIGHT, ())
+ data = CCITTFaxDecode.decode(data, stream.get(SA.DECODE_PARMS), height)
+ elif filter_type == "/Crypt":
+ decode_parms = stream.get(SA.DECODE_PARMS, {})
+ if "/Name" not in decode_parms and "/Type" not in decode_parms:
+ pass
+ else:
+ raise NotImplementedError(
+ "/Crypt filter with /Name or /Type not supported yet"
+ )
+ else:
+ # Unsupported filter
+ raise NotImplementedError(f"unsupported filter {filter_type}")
+ return data
+
+
+def decodeStreamData(stream: Any) -> Union[str, bytes]: # pragma: no cover
+ deprecate_with_replacement("decodeStreamData", "decode_stream_data", "4.0.0")
+ return decode_stream_data(stream)
+
+
+def _xobj_to_image(x_object_obj: Dict[str, Any]) -> Tuple[Optional[str], bytes]:
+ """
+ Users need to have the pillow package installed.
+
+ It's unclear if PyPDF2 will keep this function here, hence it's private.
+ It might get removed at any point.
+
+ :return: Tuple[file extension, bytes]
+ """
+ try:
+ from PIL import Image
+ except ImportError:
+ raise ImportError(
+ "pillow is required to do image extraction. "
+ "It can be installed via 'pip install PyPDF2[image]'"
+ )
+
+ size = (x_object_obj[IA.WIDTH], x_object_obj[IA.HEIGHT])
+ data = x_object_obj.get_data() # type: ignore
+ 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: Literal["RGB", "P"] = "RGB"
+ else:
+ mode = "P"
+ extension = None
+ if SA.FILTER in x_object_obj:
+ if x_object_obj[SA.FILTER] == FT.FLATE_DECODE:
+ extension = ".png" # mime_type = "image/png"
+ color_space = None
+ if "/ColorSpace" in x_object_obj:
+ color_space = x_object_obj["/ColorSpace"].get_object()
+ if (
+ isinstance(color_space, ArrayObject)
+ and color_space[0] == "/Indexed"
+ ):
+ color_space, base, hival, lookup = (
+ value.get_object() for value in color_space
+ )
+
+ img = Image.frombytes(mode, size, data)
+ if color_space == "/Indexed":
+ from .generic import ByteStringObject
+
+ if isinstance(lookup, ByteStringObject):
+ if base == ColorSpaces.DEVICE_GRAY and len(lookup) == hival + 1:
+ lookup = b"".join(
+ [lookup[i : i + 1] * 3 for i in range(len(lookup))]
+ )
+ img.putpalette(lookup)
+ else:
+ img.putpalette(lookup.get_data())
+ img = img.convert("L" if base == ColorSpaces.DEVICE_GRAY else "RGB")
+ if G.S_MASK in x_object_obj: # add alpha channel
+ alpha = Image.frombytes("L", size, x_object_obj[G.S_MASK].get_data())
+ img.putalpha(alpha)
+ img_byte_arr = BytesIO()
+ img.save(img_byte_arr, format="PNG")
+ data = img_byte_arr.getvalue()
+ elif x_object_obj[SA.FILTER] 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 x_object_obj[SA.FILTER] in [[FT.LZW_DECODE], [FT.CCITT_FAX_DECODE]]:
+ extension = ".tiff" # mime_type = "image/tiff"
+ else:
+ extension = ".png" # mime_type = "image/png"
+ data = b_(data)
+ elif x_object_obj[SA.FILTER] == FT.DCT_DECODE:
+ extension = ".jpg" # mime_type = "image/jpeg"
+ elif x_object_obj[SA.FILTER] == "/JPXDecode":
+ extension = ".jp2" # mime_type = "image/x-jp2"
+ elif x_object_obj[SA.FILTER] == FT.CCITT_FAX_DECODE:
+ extension = ".tiff" # mime_type = "image/tiff"
+ else:
+ extension = ".png" # mime_type = "image/png"
+ img = Image.frombytes(mode, size, data)
+ img_byte_arr = BytesIO()
+ img.save(img_byte_arr, format="PNG")
+ data = img_byte_arr.getvalue()
+
+ return extension, data
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/generic/__init__.py b/.venv/lib/python3.12/site-packages/PyPDF2/generic/__init__.py
new file mode 100644
index 00000000..5f0b16dd
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/generic/__init__.py
@@ -0,0 +1,144 @@
+# 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 Dict, List, Union
+
+from .._utils import StreamType, deprecate_with_replacement
+from ..constants import OutlineFontFlag
+from ._annotations import AnnotationBuilder
+from ._base import (
+ BooleanObject,
+ ByteStringObject,
+ FloatObject,
+ IndirectObject,
+ NameObject,
+ NullObject,
+ NumberObject,
+ PdfObject,
+ TextStringObject,
+ encode_pdfdocencoding,
+)
+from ._data_structures import (
+ ArrayObject,
+ ContentStream,
+ DecodedStreamObject,
+ Destination,
+ DictionaryObject,
+ EncodedStreamObject,
+ Field,
+ StreamObject,
+ TreeObject,
+ read_object,
+)
+from ._fit import Fit
+from ._outline import Bookmark, 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,
+)
+
+
+def readHexStringFromStream(
+ stream: StreamType,
+) -> Union["TextStringObject", "ByteStringObject"]: # pragma: no cover
+ deprecate_with_replacement(
+ "readHexStringFromStream", "read_hex_string_from_stream", "4.0.0"
+ )
+ return read_hex_string_from_stream(stream)
+
+
+def readStringFromStream(
+ stream: StreamType,
+ forced_encoding: Union[None, str, List[str], Dict[int, str]] = None,
+) -> Union["TextStringObject", "ByteStringObject"]: # pragma: no cover
+ deprecate_with_replacement(
+ "readStringFromStream", "read_string_from_stream", "4.0.0"
+ )
+ return read_string_from_stream(stream, forced_encoding)
+
+
+def createStringObject(
+ string: Union[str, bytes],
+ forced_encoding: Union[None, str, List[str], Dict[int, str]] = None,
+) -> Union[TextStringObject, ByteStringObject]: # pragma: no cover
+ deprecate_with_replacement("createStringObject", "create_string_object", "4.0.0")
+ return create_string_object(string, forced_encoding)
+
+
+PAGE_FIT = Fit.fit()
+
+
+__all__ = [
+ # Base types
+ "BooleanObject",
+ "FloatObject",
+ "NumberObject",
+ "NameObject",
+ "IndirectObject",
+ "NullObject",
+ "PdfObject",
+ "TextStringObject",
+ "ByteStringObject",
+ # Annotations
+ "AnnotationBuilder",
+ # Fit
+ "Fit",
+ "PAGE_FIT",
+ # Data structures
+ "ArrayObject",
+ "DictionaryObject",
+ "TreeObject",
+ "StreamObject",
+ "DecodedStreamObject",
+ "EncodedStreamObject",
+ "ContentStream",
+ "RectangleObject",
+ "Field",
+ "Destination",
+ # --- More specific stuff
+ # Outline
+ "OutlineItem",
+ "OutlineFontFlag",
+ "Bookmark",
+ # Data structures core functions
+ "read_object",
+ # Utility functions
+ "create_string_object",
+ "encode_pdfdocencoding",
+ "decode_pdfdocencoding",
+ "hex_to_rgb",
+ "read_hex_string_from_stream",
+ "read_string_from_stream",
+]
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/generic/_annotations.py b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_annotations.py
new file mode 100644
index 00000000..bb46dd90
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_annotations.py
@@ -0,0 +1,275 @@
+from typing import Optional, Tuple, Union
+
+from ._base import (
+ BooleanObject,
+ FloatObject,
+ NameObject,
+ NumberObject,
+ TextStringObject,
+)
+from ._data_structures import ArrayObject, DictionaryObject
+from ._fit import DEFAULT_FIT, Fit
+from ._rectangle import RectangleObject
+from ._utils import hex_to_rgb
+
+
+class AnnotationBuilder:
+ """
+ The AnnotationBuilder creates dictionaries representing PDF annotations.
+
+ Those dictionaries can be modified before they are added to a PdfWriter
+ instance via `writer.add_annotation`.
+
+ See `adding PDF annotations <../user/adding-pdf-annotations.html>`_ for
+ it's usage combined with PdfWriter.
+ """
+
+ from ..types import FitType, ZoomArgType
+
+ @staticmethod
+ def text(
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ text: str,
+ open: bool = False,
+ flags: int = 0,
+ ) -> DictionaryObject:
+ """
+ Add text annotation.
+
+ :param Tuple[int, int, int, int] rect:
+ or array of four integers specifying the clickable rectangular area
+ ``[xLL, yLL, xUR, yUR]``
+ :param bool open:
+ :param int flags:
+ """
+ # TABLE 8.23 Additional entries specific to a text annotation
+ text_obj = DictionaryObject(
+ {
+ NameObject("/Type"): NameObject("/Annot"),
+ NameObject("/Subtype"): NameObject("/Text"),
+ NameObject("/Rect"): RectangleObject(rect),
+ NameObject("/Contents"): TextStringObject(text),
+ NameObject("/Open"): BooleanObject(open),
+ NameObject("/Flags"): NumberObject(flags),
+ }
+ )
+ return text_obj
+
+ @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: str = "000000",
+ background_color: str = "ffffff",
+ ) -> DictionaryObject:
+ """
+ Add text in a rectangle to a page.
+
+ :param str text: Text to be added
+ :param RectangleObject rect: or array of four integers
+ specifying the clickable rectangular area ``[xLL, yLL, xUR, yUR]``
+ :param str font: Name of the Font, e.g. 'Helvetica'
+ :param bool bold: Print the text in bold
+ :param bool italic: Print the text in italic
+ :param str font_size: How big the text will be, e.g. '14pt'
+ :param str font_color: Hex-string for the color
+ :param str border_color: Hex-string for the border color
+ :param str background_color: Hex-string for the background of the annotation
+ """
+ font_str = "font: "
+ if bold is True:
+ font_str = font_str + "bold "
+ if italic is True:
+ font_str = font_str + "italic "
+ font_str = font_str + font + " " + font_size
+ font_str = font_str + ";text-align:left;color:#" + font_color
+
+ bg_color_str = ""
+ for st in hex_to_rgb(border_color):
+ bg_color_str = bg_color_str + str(st) + " "
+ bg_color_str = bg_color_str + "rg"
+
+ free_text = DictionaryObject()
+ free_text.update(
+ {
+ NameObject("/Type"): NameObject("/Annot"),
+ NameObject("/Subtype"): NameObject("/FreeText"),
+ NameObject("/Rect"): RectangleObject(rect),
+ NameObject("/Contents"): TextStringObject(text),
+ # font size color
+ NameObject("/DS"): TextStringObject(font_str),
+ # border color
+ NameObject("/DA"): TextStringObject(bg_color_str),
+ # background color
+ NameObject("/C"): ArrayObject(
+ [FloatObject(n) for n in hex_to_rgb(background_color)]
+ ),
+ }
+ )
+ return free_text
+
+ @staticmethod
+ def line(
+ p1: Tuple[float, float],
+ p2: Tuple[float, float],
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ text: str = "",
+ title_bar: str = "",
+ ) -> DictionaryObject:
+ """
+ Draw a line on the PDF.
+
+ :param Tuple[float, float] p1: First point
+ :param Tuple[float, float] p2: Second point
+ :param RectangleObject rect: or array of four
+ integers specifying the clickable rectangular area
+ ``[xLL, yLL, xUR, yUR]``
+ :param str text: Text to be displayed as the line annotation
+ :param str title_bar: Text to be displayed in the title bar of the
+ annotation; by convention this is the name of the author
+ """
+ line_obj = DictionaryObject(
+ {
+ NameObject("/Type"): NameObject("/Annot"),
+ NameObject("/Subtype"): NameObject("/Line"),
+ NameObject("/Rect"): RectangleObject(rect),
+ NameObject("/T"): TextStringObject(title_bar),
+ 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),
+ }
+ )
+ return line_obj
+
+ @staticmethod
+ def rectangle(
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ interiour_color: Optional[str] = None,
+ ) -> DictionaryObject:
+ """
+ Draw a rectangle on the PDF.
+
+ :param RectangleObject rect: or array of four
+ integers specifying the clickable rectangular area
+ ``[xLL, yLL, xUR, yUR]``
+ """
+ square_obj = DictionaryObject(
+ {
+ NameObject("/Type"): NameObject("/Annot"),
+ NameObject("/Subtype"): NameObject("/Square"),
+ NameObject("/Rect"): RectangleObject(rect),
+ }
+ )
+
+ if interiour_color:
+ square_obj[NameObject("/IC")] = ArrayObject(
+ [FloatObject(n) for n in hex_to_rgb(interiour_color)]
+ )
+
+ return square_obj
+
+ @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,
+ ) -> DictionaryObject:
+ """
+ Add a link to the document.
+
+ The link can either be an external link or an internal link.
+
+ An external link requires the URL parameter.
+ An internal link requires the target_page_index, fit, and fit args.
+
+
+ :param RectangleObject rect: or array of four
+ integers specifying the clickable rectangular area
+ ``[xLL, yLL, xUR, yUR]``
+ :param 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.
+ - horizontal corner radius,
+ - vertical corner radius, and
+ - border width
+ - Optionally: Dash
+ :param str url: Link to a website (if you want to make an external link)
+ :param int target_page_index: index of the page to which the link should go
+ (if you want to make an internal link)
+ :param Fit fit: Page fit or 'zoom' option.
+ """
+ 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(
+ f"Either 'url' or 'target_page_index' have to be provided. url={url}, target_page_index={target_page_index}"
+ )
+
+ border_arr: BorderArrayType
+ if border is not None:
+ border_arr = [NameObject(n) for n in border[:3]]
+ if len(border) == 4:
+ dash_pattern = ArrayObject([NameObject(n) for n in border[3]])
+ border_arr.append(dash_pattern)
+ else:
+ border_arr = [NumberObject(0)] * 3
+
+ link_obj = DictionaryObject(
+ {
+ NameObject("/Type"): NameObject("/Annot"),
+ NameObject("/Subtype"): NameObject("/Link"),
+ NameObject("/Rect"): RectangleObject(rect),
+ NameObject("/Border"): ArrayObject(border_arr),
+ }
+ )
+ if is_external:
+ link_obj[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,
+ }
+ )
+ link_obj[NameObject("/Dest")] = dest_deferred
+ return link_obj
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/generic/_base.py b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_base.py
new file mode 100644
index 00000000..00b9c17b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_base.py
@@ -0,0 +1,648 @@
+# 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 codecs
+import decimal
+import hashlib
+import re
+from binascii import unhexlify
+from typing import Any, Callable, List, Optional, Tuple, Union, cast
+
+from .._codecs import _pdfdoc_encoding_rev
+from .._protocols import PdfObjectProtocol, PdfWriterProtocol
+from .._utils import (
+ StreamType,
+ b_,
+ deprecation_with_replacement,
+ hex_str,
+ hexencode,
+ logger_warning,
+ read_non_whitespace,
+ read_until_regex,
+ str_,
+)
+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_value_data(self) -> bytes:
+ return ("%s" % self).encode()
+
+ def hash_value(self) -> bytes:
+ return (
+ "%s:%s"
+ % (
+ self.__class__.__name__,
+ self.hash_func(self.hash_value_data()).hexdigest(),
+ )
+ ).encode()
+
+ def clone(
+ self,
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool = False,
+ ignore_fields: Union[Tuple[str, ...], List[str], None] = (),
+ ) -> "PdfObject":
+ """
+ clone object into pdf_dest (PdfWriterProtocol which is an interface for PdfWriter)
+ force_duplicate: in standard if the object has been already cloned and reference,
+ the copy is returned; when force_duplicate == True, a new copy is always performed
+ ignore_fields : list/tuple of Fields names (for dictionaries that will be ignored during cloning (apply also to childs duplication)
+ in standard, clone function call _reference_clone (see _reference)
+ """
+ raise Exception("clone PdfObject")
+
+ def _reference_clone(
+ self, clone: Any, pdf_dest: PdfWriterProtocol
+ ) -> 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
+ """
+ try:
+ if clone.indirect_reference.pdf == pdf_dest:
+ return clone
+ except Exception:
+ pass
+ if hasattr(self, "indirect_reference"):
+ ind = self.indirect_reference
+ 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)] = {}
+ if 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
+ pdf_dest._objects.append(clone)
+ clone.indirect_reference = IndirectObject(i, 0, pdf_dest)
+ return clone
+
+ def get_object(self) -> Optional["PdfObject"]:
+ """Resolve indirect references."""
+ return self
+
+ def getObject(self) -> Optional["PdfObject"]: # pragma: no cover
+ deprecation_with_replacement("getObject", "get_object", "3.0.0")
+ return self.get_object()
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None:
+ raise NotImplementedError
+
+
+class NullObject(PdfObject):
+ def clone(
+ self,
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool = False,
+ ignore_fields: Union[Tuple[str, ...], List[str], None] = (),
+ ) -> "NullObject":
+ """clone object into pdf_dest"""
+ return cast("NullObject", self._reference_clone(NullObject(), pdf_dest))
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None:
+ 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 writeToStream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None: # pragma: no cover
+ deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0")
+ self.write_to_stream(stream, encryption_key)
+
+ def __repr__(self) -> str:
+ return "NullObject"
+
+ @staticmethod
+ def readFromStream(stream: StreamType) -> "NullObject": # pragma: no cover
+ deprecation_with_replacement("readFromStream", "read_from_stream", "3.0.0")
+ return NullObject.read_from_stream(stream)
+
+
+class BooleanObject(PdfObject):
+ def __init__(self, value: Any) -> None:
+ self.value = value
+
+ def clone(
+ self,
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool = False,
+ ignore_fields: Union[Tuple[str, ...], List[str], None] = (),
+ ) -> "BooleanObject":
+ """clone object into pdf_dest"""
+ return cast(
+ "BooleanObject", self._reference_clone(BooleanObject(self.value), pdf_dest)
+ )
+
+ 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:
+ if self.value:
+ stream.write(b"true")
+ else:
+ stream.write(b"false")
+
+ def writeToStream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None: # pragma: no cover
+ deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0")
+ self.write_to_stream(stream, encryption_key)
+
+ @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")
+
+ @staticmethod
+ def readFromStream(stream: StreamType) -> "BooleanObject": # pragma: no cover
+ deprecation_with_replacement("readFromStream", "read_from_stream", "3.0.0")
+ return BooleanObject.read_from_stream(stream)
+
+
+class IndirectObject(PdfObject):
+ def __init__(self, idnum: int, generation: int, pdf: Any) -> None: # PdfReader
+ self.idnum = idnum
+ self.generation = generation
+ self.pdf = pdf
+
+ def clone(
+ self,
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool = False,
+ ignore_fields: Union[Tuple[str, ...], List[str], None] = (),
+ ) -> "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 not force_duplicate and self.idnum in pdf_dest._id_translated[id(self.pdf)]:
+ dup = pdf_dest.get_object(pdf_dest._id_translated[id(self.pdf)][self.idnum])
+ else:
+ obj = self.get_object()
+ assert obj is not None
+ dup = obj.clone(pdf_dest, force_duplicate, ignore_fields)
+ 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"]:
+ obj = self.pdf.get_object(self)
+ if obj is None:
+ return None
+ return obj.get_object()
+
+ def __repr__(self) -> str:
+ return f"IndirectObject({self.idnum!r}, {self.generation!r}, {id(self.pdf)})"
+
+ def __eq__(self, other: Any) -> 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: Any) -> bool:
+ return not self.__eq__(other)
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None:
+ stream.write(b_(f"{self.idnum} {self.generation} R"))
+
+ def writeToStream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None: # pragma: no cover
+ deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0")
+ self.write_to_stream(stream, encryption_key)
+
+ @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_str(stream.tell())}"
+ )
+ return IndirectObject(int(idnum), int(generation), pdf)
+
+ @staticmethod
+ def readFromStream(
+ stream: StreamType, pdf: Any # PdfReader
+ ) -> "IndirectObject": # pragma: no cover
+ deprecation_with_replacement("readFromStream", "read_from_stream", "3.0.0")
+ return IndirectObject.read_from_stream(stream, pdf)
+
+
+class FloatObject(decimal.Decimal, PdfObject):
+ def __new__(
+ cls, value: Union[str, Any] = "0", context: Optional[Any] = None
+ ) -> "FloatObject":
+ try:
+ return decimal.Decimal.__new__(cls, str_(value), context)
+ except Exception:
+ # If this isn't a valid decimal (happens in malformed PDFs)
+ # fallback to 0
+ logger_warning(f"FloatObject ({value}) invalid; use 0.0 instead", __name__)
+ return decimal.Decimal.__new__(cls, "0.0")
+
+ def clone(
+ self,
+ pdf_dest: Any,
+ force_duplicate: bool = False,
+ ignore_fields: Union[Tuple[str, ...], List[str], None] = (),
+ ) -> "FloatObject":
+ """clone object into pdf_dest"""
+ return cast("FloatObject", self._reference_clone(FloatObject(self), pdf_dest))
+
+ def __repr__(self) -> str:
+ if self == self.to_integral():
+ # If this is an integer, format it with no decimal place.
+ return str(self.quantize(decimal.Decimal(1)))
+ else:
+ # Otherwise, format it with a decimal place, taking care to
+ # remove any extraneous trailing zeros.
+ return f"{self:f}".rstrip("0")
+
+ def as_numeric(self) -> float:
+ return float(repr(self).encode("utf8"))
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None:
+ stream.write(repr(self).encode("utf8"))
+
+ def writeToStream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None: # pragma: no cover
+ deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0")
+ self.write_to_stream(stream, encryption_key)
+
+
+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: Union[Tuple[str, ...], List[str], None] = (),
+ ) -> "NumberObject":
+ """clone object into pdf_dest"""
+ return cast("NumberObject", self._reference_clone(NumberObject(self), pdf_dest))
+
+ 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:
+ stream.write(repr(self).encode("utf8"))
+
+ def writeToStream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None: # pragma: no cover
+ deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0")
+ self.write_to_stream(stream, encryption_key)
+
+ @staticmethod
+ def read_from_stream(stream: StreamType) -> Union["NumberObject", "FloatObject"]:
+ num = read_until_regex(stream, NumberObject.NumberPattern)
+ if num.find(b".") != -1:
+ return FloatObject(num)
+ return NumberObject(num)
+
+ @staticmethod
+ def readFromStream(
+ stream: StreamType,
+ ) -> Union["NumberObject", "FloatObject"]: # pragma: no cover
+ deprecation_with_replacement("readFromStream", "read_from_stream", "3.0.0")
+ return NumberObject.read_from_stream(stream)
+
+
+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: Union[Tuple[str, ...], List[str], None] = (),
+ ) -> "ByteStringObject":
+ """clone object into pdf_dest"""
+ return cast(
+ "ByteStringObject",
+ self._reference_clone(ByteStringObject(bytes(self)), pdf_dest),
+ )
+
+ @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:
+ bytearr = self
+ if encryption_key:
+ from .._security import RC4_encrypt
+
+ bytearr = RC4_encrypt(encryption_key, bytearr) # type: ignore
+ stream.write(b"<")
+ stream.write(hexencode(bytearr))
+ stream.write(b">")
+
+ def writeToStream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None: # pragma: no cover
+ deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0")
+ self.write_to_stream(stream, encryption_key)
+
+
+class TextStringObject(str, PdfObject):
+ """
+ Represents 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.
+ """
+
+ def clone(
+ self,
+ pdf_dest: Any,
+ force_duplicate: bool = False,
+ ignore_fields: Union[Tuple[str, ...], List[str], None] = (),
+ ) -> "TextStringObject":
+ """clone object into pdf_dest"""
+ obj = TextStringObject(self)
+ obj.autodetect_pdfdocencoding = self.autodetect_pdfdocencoding
+ obj.autodetect_utf16 = self.autodetect_utf16
+ return cast("TextStringObject", self._reference_clone(obj, pdf_dest))
+
+ autodetect_pdfdocencoding = False
+ autodetect_utf16 = False
+
+ @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.
+ """
+ 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:
+ return codecs.BOM_UTF16_BE + self.encode("utf-16be")
+ elif self.autodetect_pdfdocencoding:
+ return encode_pdfdocencoding(self)
+ else:
+ raise Exception("no information about original bytes")
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None:
+ # 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:
+ bytearr = encode_pdfdocencoding(self)
+ except UnicodeEncodeError:
+ bytearr = codecs.BOM_UTF16_BE + self.encode("utf-16be")
+ if encryption_key:
+ from .._security import RC4_encrypt
+
+ bytearr = RC4_encrypt(encryption_key, bytearr)
+ obj = ByteStringObject(bytearr)
+ obj.write_to_stream(stream, None)
+ else:
+ stream.write(b"(")
+ for c in bytearr:
+ if not chr(c).isalnum() and c != b" ":
+ # This:
+ # stream.write(b_(rf"\{c:0>3o}"))
+ # gives
+ # https://github.com/davidhalter/parso/issues/207
+ stream.write(b_("\\%03o" % c))
+ else:
+ stream.write(b_(chr(c)))
+ stream.write(b")")
+
+ def writeToStream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None: # pragma: no cover
+ deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0")
+ self.write_to_stream(stream, encryption_key)
+
+
+class NameObject(str, PdfObject):
+ delimiter_pattern = re.compile(rb"\s+|[\(\)<>\[\]{}/%]")
+ surfix = b"/"
+ renumber_table = {
+ "#": b"#23",
+ "(": b"#28",
+ ")": b"#29",
+ "/": b"#2F",
+ **{chr(i): f"#{i:02X}".encode() for i in range(33)},
+ }
+
+ def clone(
+ self,
+ pdf_dest: Any,
+ force_duplicate: bool = False,
+ ignore_fields: Union[Tuple[str, ...], List[str], None] = (),
+ ) -> "NameObject":
+ """clone object into pdf_dest"""
+ return cast("NameObject", self._reference_clone(NameObject(self), pdf_dest))
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None:
+ stream.write(self.renumber()) # b_(renumber(self)))
+
+ def writeToStream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None: # pragma: no cover
+ deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0")
+ self.write_to_stream(stream, encryption_key)
+
+ def renumber(self) -> bytes:
+ out = self[0].encode("utf-8")
+ if out != b"/":
+ logger_warning(f"Incorrect first char in NameObject:({self})", __name__)
+ 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 hexa
+ # we change nothing and carry on
+ i = i + 1
+ return sin
+
+ @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, ignore_eof=True)
+ try:
+ # Name objects should represent irregular characters
+ # with a '#' followed by the symbol's hex number
+ name = NameObject.unnumber(name)
+ for enc in ("utf-8", "gbk"):
+ 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 Name Object ({repr(name)})", __name__
+ )
+ return NameObject(name.decode("charmap"))
+ else:
+ raise PdfReadError(
+ f"Illegal character in Name Object ({repr(name)})"
+ ) from e
+
+ @staticmethod
+ def readFromStream(
+ stream: StreamType, pdf: Any # PdfReader
+ ) -> "NameObject": # pragma: no cover
+ deprecation_with_replacement("readFromStream", "read_from_stream", "3.0.0")
+ return NameObject.read_from_stream(stream, pdf)
+
+
+def encode_pdfdocencoding(unicode_string: str) -> bytes:
+ retval = b""
+ for c in unicode_string:
+ try:
+ retval += b_(chr(_pdfdoc_encoding_rev[c]))
+ except KeyError:
+ raise UnicodeEncodeError(
+ "pdfdocencoding", c, -1, -1, "does not exist in translation table"
+ )
+ return retval
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/generic/_data_structures.py b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_data_structures.py
new file mode 100644
index 00000000..19f5be9f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_data_structures.py
@@ -0,0 +1,1382 @@
+# 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
+from io import BytesIO
+from typing import Any, Dict, Iterable, List, Optional, Tuple, Union, cast
+
+from .._protocols import PdfWriterProtocol
+from .._utils import (
+ WHITESPACES,
+ StreamType,
+ b_,
+ deprecate_with_replacement,
+ deprecation_with_replacement,
+ hex_str,
+ logger_warning,
+ read_non_whitespace,
+ read_until_regex,
+ skip_over_comment,
+)
+from ..constants import (
+ CheckboxRadioButtonAttributes,
+ FieldDictionaryAttributes,
+)
+from ..constants import FilterTypes as FT
+from ..constants import OutlineFontFlag
+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,
+ FloatObject,
+ IndirectObject,
+ NameObject,
+ NullObject,
+ NumberObject,
+ PdfObject,
+ TextStringObject,
+)
+from ._fit import Fit
+from ._utils import read_hex_string_from_stream, read_string_from_stream
+
+logger = logging.getLogger(__name__)
+NumberSigns = b"+-"
+IndirectPattern = re.compile(rb"[+-]?(\d+)\s+(\d+)\s+R[^a-zA-Z]")
+
+
+class ArrayObject(list, PdfObject):
+ def clone(
+ self,
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool = False,
+ ignore_fields: Union[Tuple[str, ...], List[str], None] = (),
+ ) -> "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))
+ for data in self:
+ if isinstance(data, StreamObject):
+ # if not hasattr(data, "indirect_reference"):
+ # data.indirect_reference = None
+ dup = data._reference_clone(
+ data.clone(pdf_dest, force_duplicate, ignore_fields), pdf_dest
+ )
+ arr.append(dup.indirect_reference)
+ elif hasattr(data, "clone"):
+ arr.append(data.clone(pdf_dest, force_duplicate, ignore_fields))
+ else:
+ arr.append(data)
+ return cast("ArrayObject", arr)
+
+ def items(self) -> Iterable[Any]:
+ """
+ Emulate DictionaryObject.items for a list
+ (index, object)
+ """
+ return enumerate(self)
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None:
+ stream.write(b"[")
+ for data in self:
+ stream.write(b" ")
+ data.write_to_stream(stream, encryption_key)
+ stream.write(b" ]")
+
+ def writeToStream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None: # pragma: no cover
+ deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0")
+ self.write_to_stream(stream, encryption_key)
+
+ @staticmethod
+ def read_from_stream(
+ stream: StreamType,
+ pdf: Any,
+ forced_encoding: Union[None, str, List[str], Dict[int, str]] = None,
+ ) -> "ArrayObject": # PdfReader
+ 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)
+ stream.seek(-1, 1)
+ # check for array ending
+ peekahead = stream.read(1)
+ if peekahead == b"]":
+ break
+ stream.seek(-1, 1)
+ # read and append obj
+ arr.append(read_object(stream, pdf, forced_encoding))
+ return arr
+
+ @staticmethod
+ def readFromStream(
+ stream: StreamType, pdf: Any # PdfReader
+ ) -> "ArrayObject": # pragma: no cover
+ deprecation_with_replacement("readFromStream", "read_from_stream", "3.0.0")
+ return ArrayObject.read_from_stream(stream, pdf)
+
+
+class DictionaryObject(dict, PdfObject):
+ def clone(
+ self,
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool = False,
+ ignore_fields: Union[Tuple[str, ...], List[str], None] = (),
+ ) -> "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
+
+ d__ = cast(
+ "DictionaryObject", self._reference_clone(self.__class__(), pdf_dest)
+ )
+ if ignore_fields is None:
+ ignore_fields = []
+ if len(d__.keys()) == 0:
+ d__._clone(self, pdf_dest, force_duplicate, ignore_fields)
+ return d__
+
+ def _clone(
+ self,
+ src: "DictionaryObject",
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool,
+ ignore_fields: Union[Tuple[str, ...], List[str]],
+ ) -> None:
+ """update the object from src"""
+ # First check if this is a chain list, we need to loop to prevent recur
+ if (
+ ("/Next" not in ignore_fields and "/Next" in src)
+ or ("/Prev" not in ignore_fields and "/Prev" in src)
+ ) or (
+ ("/N" not in ignore_fields and "/N" in src)
+ or ("/V" not in ignore_fields and "/V" in src)
+ ):
+ 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)
+ ):
+ 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),
+ )
+ 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 + [k])
+
+ 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]
+ else:
+ if k not in self:
+ self[NameObject(k)] = (
+ v.clone(pdf_dest, force_duplicate, ignore_fields)
+ if hasattr(v, "clone")
+ else v
+ )
+
+ def raw_get(self, key: Any) -> Any:
+ return dict.__getitem__(self, key)
+
+ def __setitem__(self, key: Any, value: Any) -> Any:
+ if not isinstance(key, PdfObject):
+ raise ValueError("key must be PdfObject")
+ if not isinstance(value, PdfObject):
+ raise ValueError("value must be 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 PdfObject")
+ if not isinstance(value, PdfObject):
+ raise ValueError("value must be 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[PdfObject]:
+ """
+ Retrieve XMP (Extensible Metadata Platform) data relevant to the
+ this object, if available.
+
+ Stability: Added in v1.12, will exist for all future v1.x releases.
+ @return Returns a {@link #xmp.XmpInformation XmlInformation} 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 metadata is None:
+ return None
+ metadata = metadata.get_object()
+
+ if not isinstance(metadata, XmpInformation):
+ metadata = XmpInformation(metadata)
+ self[NameObject("/Metadata")] = metadata
+ return metadata
+
+ def getXmpMetadata(
+ self,
+ ) -> Optional[PdfObject]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.3
+
+ Use :meth:`xmp_metadata` instead.
+ """
+ deprecation_with_replacement("getXmpMetadata", "xmp_metadata", "3.0.0")
+ return self.xmp_metadata
+
+ @property
+ def xmpMetadata(self) -> Optional[PdfObject]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.3
+
+ Use :meth:`xmp_metadata` instead.
+ """
+ deprecation_with_replacement("xmpMetadata", "xmp_metadata", "3.0.0")
+ return self.xmp_metadata
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None:
+ stream.write(b"<<\n")
+ for key, value in list(self.items()):
+ key.write_to_stream(stream, encryption_key)
+ stream.write(b" ")
+ value.write_to_stream(stream, encryption_key)
+ stream.write(b"\n")
+ stream.write(b">>")
+
+ def writeToStream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None: # pragma: no cover
+ deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0")
+ self.write_to_stream(stream, encryption_key)
+
+ @staticmethod
+ def read_from_stream(
+ stream: StreamType,
+ pdf: Any, # PdfReader
+ 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: Any
+ ) -> int: # PdfReader
+ l = pdf.xref[rem_gens[0]]
+ for o in l:
+ if p1 > l[o] and p < l[o]:
+ p1 = l[o]
+ if len(rem_gens) == 1:
+ return p1
+ else:
+ return get_next_obj_pos(p, p1, rem_gens[1:], pdf)
+
+ def read_unsized_from_steam(stream: StreamType, pdf: Any) -> bytes: # PdfReader
+ # 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_str(stream.tell())}: "
+ "stream must begin with '<<'"
+ )
+ data: Dict[Any, Any] = {}
+ while True:
+ tok = read_non_whitespace(stream)
+ if tok == b"\x00":
+ continue
+ elif 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:
+ key = read_object(stream, pdf)
+ 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_str(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":
+ # read \n after
+ if stream.read(1) != b"\n":
+ stream.seek(-1, 1)
+ # this is a stream object, not a dictionary
+ if SA.LENGTH not in data:
+ raise PdfStreamError("Stream length not defined")
+ length = data[SA.LENGTH]
+ if isinstance(length, IndirectObject):
+ t = stream.tell()
+ length = pdf.get_object(length)
+ stream.seek(t, 0)
+ pstart = stream.tell()
+ data["__streamdata__"] = stream.read(length)
+ 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 not pdf.strict:
+ stream.seek(pstart, 0)
+ data["__streamdata__"] = read_unsized_from_steam(stream, pdf)
+ pos = stream.tell()
+ else:
+ stream.seek(pos, 0)
+ raise PdfReadError(
+ "Unable to find 'endstream' marker after stream at byte "
+ f"{hex_str(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
+
+ @staticmethod
+ def readFromStream(
+ stream: StreamType, pdf: Any # PdfReader
+ ) -> "DictionaryObject": # pragma: no cover
+ deprecation_with_replacement("readFromStream", "read_from_stream", "3.0.0")
+ return DictionaryObject.read_from_stream(stream, pdf)
+
+
+class TreeObject(DictionaryObject):
+ def __init__(self) -> None:
+ DictionaryObject.__init__(self)
+
+ def hasChildren(self) -> bool: # pragma: no cover
+ deprecate_with_replacement("hasChildren", "has_children", "4.0.0")
+ return self.has_children()
+
+ 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 child_ref is None:
+ return
+ child = child_ref.get_object()
+
+ def addChild(self, child: Any, pdf: Any) -> None: # pragma: no cover
+ deprecation_with_replacement("addChild", "add_child", "3.0.0")
+ self.add_child(child, pdf)
+
+ def add_child(self, child: Any, pdf: PdfWriterProtocol) -> None:
+ self.insert_child(child, None, pdf)
+
+ def insert_child(self, child: Any, before: Any, pdf: PdfWriterProtocol) -> None:
+ def inc_parent_counter(
+ parent: Union[None, IndirectObject, TreeObject], n: int
+ ) -> None:
+ if parent is None:
+ return
+ parent = cast("TreeObject", parent.get_object())
+ if "/Count" in parent:
+ parent[NameObject("/Count")] = NumberObject(
+ cast(int, parent[NameObject("/Count")]) + n
+ )
+ inc_parent_counter(parent.get("/Parent", None), n)
+
+ child_obj = child.get_object()
+ child = child.indirect_reference # get_reference(child_obj)
+ # assert isinstance(child, IndirectObject)
+
+ 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
+ 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
+ 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))
+
+ def removeChild(self, child: Any) -> None: # pragma: no cover
+ deprecation_with_replacement("removeChild", "remove_child", "3.0.0")
+ self.remove_child(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."""
+ 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
+ assert self[NameObject("/Count")] == 1
+ del self[NameObject("/Count")]
+ 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 emptyTree(self) -> None: # pragma: no cover
+ deprecate_with_replacement("emptyTree", "empty_tree", "4.0.0")
+ self.empty_tree()
+
+ 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.
+ """
+ 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: Optional[str] = None
+ self.decoded_self: Optional["DecodedStreamObject"] = None
+
+ def _clone(
+ self,
+ src: DictionaryObject,
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool,
+ ignore_fields: Union[Tuple[str, ...], List[str]],
+ ) -> None:
+ """update the object from src"""
+ 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 = decoded_self.clone(pdf_dest, True, ignore_fields) # type: ignore[assignment]
+ except Exception:
+ pass
+ super()._clone(src, pdf_dest, force_duplicate, ignore_fields)
+ return
+
+ def hash_value_data(self) -> bytes:
+ data = super().hash_value_data()
+ data += b_(self._data)
+ return data
+
+ @property
+ def decodedSelf(self) -> Optional["DecodedStreamObject"]: # pragma: no cover
+ deprecation_with_replacement("decodedSelf", "decoded_self", "3.0.0")
+ return self.decoded_self
+
+ @decodedSelf.setter
+ def decodedSelf(self, value: "DecodedStreamObject") -> None: # pragma: no cover
+ deprecation_with_replacement("decodedSelf", "decoded_self", "3.0.0")
+ self.decoded_self = value
+
+ @property
+ def _data(self) -> Any:
+ return self.__data
+
+ @_data.setter
+ def _data(self, value: Any) -> None:
+ self.__data = value
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None:
+ self[NameObject(SA.LENGTH)] = NumberObject(len(self._data))
+ DictionaryObject.write_to_stream(self, stream, encryption_key)
+ del self[SA.LENGTH]
+ stream.write(b"\nstream\n")
+ data = self._data
+ if encryption_key:
+ from .._security import RC4_encrypt
+
+ data = RC4_encrypt(encryption_key, data)
+ stream.write(data)
+ stream.write(b"\nendstream")
+
+ @staticmethod
+ def initializeFromDictionary(
+ data: Dict[str, Any]
+ ) -> Union["EncodedStreamObject", "DecodedStreamObject"]: # pragma: no cover
+ return StreamObject.initialize_from_dictionary(data)
+
+ @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__"]
+ del data[SA.LENGTH]
+ retval.update(data)
+ return retval
+
+ def flateEncode(self) -> "EncodedStreamObject": # pragma: no cover
+ deprecation_with_replacement("flateEncode", "flate_encode", "3.0.0")
+ return self.flate_encode()
+
+ def flate_encode(self) -> "EncodedStreamObject":
+ from ..filters import FlateDecode
+
+ if SA.FILTER in self:
+ f = self[SA.FILTER]
+ if isinstance(f, ArrayObject):
+ f.insert(0, NameObject(FT.FLATE_DECODE))
+ else:
+ newf = ArrayObject()
+ newf.append(NameObject("/FlateDecode"))
+ newf.append(f)
+ f = newf
+ else:
+ f = NameObject("/FlateDecode")
+ retval = EncodedStreamObject()
+ retval[NameObject(SA.FILTER)] = f
+ retval._data = FlateDecode.encode(self._data)
+ return retval
+
+
+class DecodedStreamObject(StreamObject):
+ def get_data(self) -> Any:
+ return self._data
+
+ def set_data(self, data: Any) -> Any:
+ self._data = data
+
+ def getData(self) -> Any: # pragma: no cover
+ deprecation_with_replacement("getData", "get_data", "3.0.0")
+ return self._data
+
+ def setData(self, data: Any) -> None: # pragma: no cover
+ deprecation_with_replacement("setData", "set_data", "3.0.0")
+ self.set_data(data)
+
+
+class EncodedStreamObject(StreamObject):
+ def __init__(self) -> None:
+ self.decoded_self: Optional["DecodedStreamObject"] = None
+
+ @property
+ def decodedSelf(self) -> Optional["DecodedStreamObject"]: # pragma: no cover
+ deprecation_with_replacement("decodedSelf", "decoded_self", "3.0.0")
+ return self.decoded_self
+
+ @decodedSelf.setter
+ def decodedSelf(self, value: DecodedStreamObject) -> None: # pragma: no cover
+ deprecation_with_replacement("decodedSelf", "decoded_self", "3.0.0")
+ self.decoded_self = value
+
+ def get_data(self) -> Union[None, str, 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._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._data
+
+ def getData(self) -> Union[None, str, bytes]: # pragma: no cover
+ deprecation_with_replacement("getData", "get_data", "3.0.0")
+ return self.get_data()
+
+ def set_data(self, data: Any) -> None: # pragma: no cover
+ raise PdfReadError("Creating EncodedStreamObject is not currently supported")
+
+ def setData(self, data: Any) -> None: # pragma: no cover
+ deprecation_with_replacement("setData", "set_data", "3.0.0")
+ return self.set_data(data)
+
+
+class ContentStream(DecodedStreamObject):
+ 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:
+ # [0] : List
+ # [1] : str
+ self.operations: List[Tuple[Any, Any]] = []
+
+ # stream may be a StreamObject or an ArrayObject containing
+ # multiple StreamObjects to be cat'd together.
+ if stream is not None:
+ stream = stream.get_object()
+ if isinstance(stream, ArrayObject):
+ data = b""
+ for s in stream:
+ data += b_(s.get_object().get_data())
+ if len(data) == 0 or data[-1] != b"\n":
+ data += b"\n"
+ stream_bytes = BytesIO(data)
+ else:
+ stream_data = stream.get_data()
+ assert stream_data is not None
+ stream_data_bytes = b_(stream_data)
+ stream_bytes = BytesIO(stream_data_bytes)
+ self.forced_encoding = forced_encoding
+ self.__parse_content_stream(stream_bytes)
+
+ def clone(
+ self,
+ pdf_dest: Any,
+ force_duplicate: bool = False,
+ ignore_fields: Union[Tuple[str, ...], List[str], None] = (),
+ ) -> "ContentStream":
+ """clone object into pdf_dest"""
+ try:
+ if self.indirect_reference.pdf == pdf_dest and not force_duplicate: # type: ignore
+ return self
+ except Exception:
+ pass
+
+ d__ = cast(
+ "ContentStream", self._reference_clone(self.__class__(None, None), pdf_dest)
+ )
+ if ignore_fields is None:
+ ignore_fields = []
+ d__._clone(self, pdf_dest, force_duplicate, ignore_fields)
+ return d__
+
+ def _clone(
+ self,
+ src: DictionaryObject,
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool,
+ ignore_fields: Union[Tuple[str, ...], List[str]],
+ ) -> None:
+ """update the object from src"""
+ self.pdf = pdf_dest
+ self.operations = list(cast("ContentStream", src).operations)
+ self.forced_encoding = cast("ContentStream", src).forced_encoding
+ # no need to call DictionaryObjection or any
+ # super(DictionaryObject,self)._clone(src, pdf_dest, force_duplicate, ignore_fields)
+ return
+
+ def __parse_content_stream(self, stream: StreamType) -> None:
+ stream.seek(0, 0)
+ operands: List[Union[int, str, PdfObject]] = []
+ while True:
+ peek = read_non_whitespace(stream)
+ if peek == b"" or peek == 0:
+ break
+ stream.seek(-1, 1)
+ if peek.isalpha() or peek in (b"'", b'"'):
+ operator = read_until_regex(stream, NameObject.delimiter_pattern, True)
+ 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"):
+ 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"
+ data = BytesIO()
+ # Read the inline image, while checking for EI (End Image) operator.
+ while True:
+ # Read 8 kB at a time and check if the chunk contains the E operator.
+ buf = stream.read(8192)
+ # We have reached the end of the stream, but haven't found the EI operator.
+ if not buf:
+ raise PdfReadError("Unexpected end of stream")
+ loc = buf.find(b"E")
+
+ if loc == -1:
+ data.write(buf)
+ else:
+ # Write out everything before the E.
+ data.write(buf[0:loc])
+
+ # Seek back in the stream to read the E next.
+ stream.seek(loc - len(buf), 1)
+ tok = stream.read(1)
+ # Check for End Image
+ tok2 = stream.read(1)
+ if tok2 == b"I" and buf[loc - 1 : loc] in WHITESPACES:
+ # Data can contain [\s]EI, so check for the separator \s; 4 chars suffisent Q operator not required.
+ tok3 = stream.read(1)
+ info = tok + tok2
+ # We need to find at least one whitespace after.
+ has_q_whitespace = False
+ while tok3 in WHITESPACES:
+ has_q_whitespace = True
+ info += tok3
+ tok3 = stream.read(1)
+ if has_q_whitespace:
+ stream.seek(-1, 1)
+ break
+ else:
+ stream.seek(-1, 1)
+ data.write(info)
+ else:
+ stream.seek(-1, 1)
+ data.write(tok)
+ return {"settings": settings, "data": data.getvalue()}
+
+ @property
+ def _data(self) -> bytes:
+ newdata = BytesIO()
+ for operands, operator in self.operations:
+ if operator == b"INLINE IMAGE":
+ newdata.write(b"BI")
+ dicttext = BytesIO()
+ operands["settings"].write_to_stream(dicttext, None)
+ newdata.write(dicttext.getvalue()[2:-2])
+ newdata.write(b"ID ")
+ newdata.write(operands["data"])
+ newdata.write(b"EI")
+ else:
+ for op in operands:
+ op.write_to_stream(newdata, None)
+ newdata.write(b" ")
+ newdata.write(b_(operator))
+ newdata.write(b"\n")
+ return newdata.getvalue()
+
+ @_data.setter
+ def _data(self, value: Union[str, bytes]) -> None:
+ self.__parse_content_stream(BytesIO(b_(value)))
+
+
+def read_object(
+ stream: StreamType,
+ pdf: Any, # PdfReader
+ 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 == b"t" or tok == 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":
+ stream.seek(-6, 1)
+ return NullObject()
+ elif tok == b"n":
+ return NullObject.read_from_stream(stream)
+ elif tok == b"%":
+ # comment
+ while tok not in (b"\r", b"\n"):
+ tok = stream.read(1)
+ # Prevents an infinite loop by raising an error if the stream is at
+ # the EOF
+ if len(tok) <= 0:
+ raise PdfStreamError("File ended unexpectedly.")
+ 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:
+ return IndirectObject.read_from_stream(stream, pdf)
+ else:
+ return NumberObject.read_from_stream(stream)
+ else:
+ stream.seek(-20, 1)
+ raise PdfReadError(
+ f"Invalid Elementary Object starting with {tok!r} @{stream.tell()}: {stream.read(80).__repr__()}"
+ )
+
+
+class Field(TreeObject):
+ """
+ A class representing a field dictionary.
+
+ This class is accessed through
+ :meth:`get_fields()<PyPDF2.PdfReader.get_fields>`
+ """
+
+ def __init__(self, data: Dict[str, Any]) -> None:
+ DictionaryObject.__init__(self)
+ field_attributes = (
+ FieldDictionaryAttributes.attributes()
+ + CheckboxRadioButtonAttributes.attributes()
+ )
+ for attr in field_attributes:
+ try:
+ self[NameObject(attr)] = data[attr]
+ except KeyError:
+ pass
+
+ # 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 fieldType(self) -> Optional[NameObject]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.3
+
+ Use :py:attr:`field_type` instead.
+ """
+ deprecation_with_replacement("fieldType", "field_type", "3.0.0")
+ return self.field_type
+
+ @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 altName(self) -> Optional[str]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.3
+
+ Use :py:attr:`alternate_name` instead.
+ """
+ deprecation_with_replacement("altName", "alternate_name", "3.0.0")
+ return self.alternate_name
+
+ @property
+ def mapping_name(self) -> Optional[str]:
+ """
+ Read-only property accessing the mapping name of this field. This
+ name is used by PyPDF2 as a key in the dictionary returned by
+ :meth:`get_fields()<PyPDF2.PdfReader.get_fields>`
+ """
+ return self.get(FieldDictionaryAttributes.TM)
+
+ @property
+ def mappingName(self) -> Optional[str]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.3
+
+ Use :py:attr:`mapping_name` instead.
+ """
+ deprecation_with_replacement("mappingName", "mapping_name", "3.0.0")
+ return self.mapping_name
+
+ @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 defaultValue(self) -> Optional[Any]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.3
+
+ Use :py:attr:`default_value` instead.
+ """
+ deprecation_with_replacement("defaultValue", "default_value", "3.0.0")
+ return self.default_value
+
+ @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)
+
+ @property
+ def additionalActions(self) -> Optional[DictionaryObject]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.3
+
+ Use :py:attr:`additional_actions` instead.
+ """
+ deprecation_with_replacement("additionalActions", "additional_actions", "3.0.0")
+ return self.additional_actions
+
+
+class Destination(TreeObject):
+ """
+ A class representing a destination within a PDF file.
+ See section 8.2.1 of the PDF 1.6 reference.
+
+ :param str title: Title of this destination.
+ :param IndirectObject page: Reference to the page of this destination. Should
+ be an instance of :class:`IndirectObject<PyPDF2.generic.IndirectObject>`.
+ :param Fit fit: How the destination is displayed.
+ :raises PdfReadError: If destination type is invalid.
+
+
+ """
+
+ node: Optional[
+ DictionaryObject
+ ] = None # node provide access to the original Object
+ childs: List[Any] = [] # used in PdfWriter
+
+ def __init__(
+ self,
+ title: str,
+ page: Union[NumberObject, IndirectObject, NullObject, DictionaryObject],
+ fit: Fit,
+ ) -> None:
+ 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":
+ (
+ self[NameObject(TA.LEFT)],
+ self[NameObject(TA.TOP)],
+ self[NameObject("/Zoom")],
+ ) = args
+ 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: # Prefered 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: # Prefered 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 getDestArray(self) -> "ArrayObject": # pragma: no cover
+ """
+ .. deprecated:: 1.28.3
+
+ Use :py:attr:`dest_array` instead.
+ """
+ deprecation_with_replacement("getDestArray", "dest_array", "3.0.0")
+ return self.dest_array
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None:
+ stream.write(b"<<\n")
+ key = NameObject("/D")
+ key.write_to_stream(stream, encryption_key)
+ stream.write(b" ")
+ value = self.dest_array
+ value.write_to_stream(stream, encryption_key)
+
+ key = NameObject("/S")
+ key.write_to_stream(stream, encryption_key)
+ stream.write(b" ")
+ value_s = NameObject("/GoTo")
+ value_s.write_to_stream(stream, encryption_key)
+
+ 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 descendents at all levels
+ """
+ return self.get("/Count", None)
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/generic/_fit.py b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_fit.py
new file mode 100644
index 00000000..b0e7aaa9
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_fit.py
@@ -0,0 +1,129 @@
+from typing import Any, Optional, Tuple, Union
+
+
+class Fit:
+ def __init__(
+ self, fit_type: str, fit_args: Tuple[Union[None, float, Any], ...] = tuple()
+ ):
+ from ._base import FloatObject, NameObject, NullObject
+
+ self.fit_type = NameObject(fit_type)
+ self.fit_args = [
+ NullObject() if a is None or isinstance(a, NullObject) 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.
+ """
+ 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.
+ """
+ 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.
+ """
+ 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.
+ """
+ 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.
+ """
+ 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/PyPDF2/generic/_outline.py b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_outline.py
new file mode 100644
index 00000000..c2e72c0a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_outline.py
@@ -0,0 +1,35 @@
+from typing import Any, Union
+
+from .._utils import StreamType, deprecation_with_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:
+ 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, encryption_key)
+ stream.write(b" ")
+ value = self.raw_get(key)
+ value.write_to_stream(stream, encryption_key)
+ stream.write(b"\n")
+ key = NameObject("/Dest")
+ key.write_to_stream(stream, encryption_key)
+ stream.write(b" ")
+ value = self.dest_array
+ value.write_to_stream(stream, encryption_key)
+ stream.write(b"\n")
+ stream.write(b">>")
+
+
+class Bookmark(OutlineItem): # pragma: no cover
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
+ deprecation_with_replacement("Bookmark", "OutlineItem", "3.0.0")
+ super().__init__(*args, **kwargs)
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/generic/_rectangle.py b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_rectangle.py
new file mode 100644
index 00000000..3f41bfd5
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_rectangle.py
@@ -0,0 +1,265 @@
+import decimal
+from typing import Any, List, Tuple, Union
+
+from .._utils import deprecation_no_replacement, deprecation_with_replacement
+from ._base import FloatObject, NumberObject
+from ._data_structures import ArrayObject
+
+
+class RectangleObject(ArrayObject):
+ """
+ This class is used to represent *page boxes* in PyPDF2. These boxes include:
+ * :attr:`artbox <PyPDF2._page.PageObject.artbox>`
+ * :attr:`bleedbox <PyPDF2._page.PageObject.bleedbox>`
+ * :attr:`cropbox <PyPDF2._page.PageObject.cropbox>`
+ * :attr:`mediabox <PyPDF2._page.PageObject.mediabox>`
+ * :attr:`trimbox <PyPDF2._page.PageObject.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, (NumberObject, FloatObject)):
+ 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 ensureIsNumber(
+ self, value: Any
+ ) -> Union[FloatObject, NumberObject]: # pragma: no cover
+ deprecation_no_replacement("ensureIsNumber", "3.0.0")
+ return self._ensure_is_number(value)
+
+ def __repr__(self) -> str:
+ return f"RectangleObject({repr(list(self))})"
+
+ @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)
+
+ def getLowerLeft_x(self) -> FloatObject: # pragma: no cover
+ deprecation_with_replacement("getLowerLeft_x", "left", "3.0.0")
+ return self.left
+
+ def getLowerLeft_y(self) -> FloatObject: # pragma: no cover
+ deprecation_with_replacement("getLowerLeft_y", "bottom", "3.0.0")
+ return self.bottom
+
+ def getUpperRight_x(self) -> FloatObject: # pragma: no cover
+ deprecation_with_replacement("getUpperRight_x", "right", "3.0.0")
+ return self.right
+
+ def getUpperRight_y(self) -> FloatObject: # pragma: no cover
+ deprecation_with_replacement("getUpperRight_y", "top", "3.0.0")
+ return self.top
+
+ def getUpperLeft_x(self) -> FloatObject: # pragma: no cover
+ deprecation_with_replacement("getUpperLeft_x", "left", "3.0.0")
+ return self.left
+
+ def getUpperLeft_y(self) -> FloatObject: # pragma: no cover
+ deprecation_with_replacement("getUpperLeft_y", "top", "3.0.0")
+ return self.top
+
+ def getLowerRight_x(self) -> FloatObject: # pragma: no cover
+ deprecation_with_replacement("getLowerRight_x", "right", "3.0.0")
+ return self.right
+
+ def getLowerRight_y(self) -> FloatObject: # pragma: no cover
+ deprecation_with_replacement("getLowerRight_y", "bottom", "3.0.0")
+ return self.bottom
+
+ @property
+ def lower_left(self) -> Tuple[decimal.Decimal, decimal.Decimal]:
+ """
+ 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: List[Any]) -> None:
+ self[0], self[1] = (self._ensure_is_number(x) for x in value)
+
+ @property
+ def lower_right(self) -> Tuple[decimal.Decimal, decimal.Decimal]:
+ """
+ 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: List[Any]) -> None:
+ self[2], self[1] = (self._ensure_is_number(x) for x in value)
+
+ @property
+ def upper_left(self) -> Tuple[decimal.Decimal, decimal.Decimal]:
+ """
+ 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: List[Any]) -> None:
+ self[0], self[3] = (self._ensure_is_number(x) for x in value)
+
+ @property
+ def upper_right(self) -> Tuple[decimal.Decimal, decimal.Decimal]:
+ """
+ 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: List[Any]) -> None:
+ self[2], self[3] = (self._ensure_is_number(x) for x in value)
+
+ def getLowerLeft(
+ self,
+ ) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover
+ deprecation_with_replacement("getLowerLeft", "lower_left", "3.0.0")
+ return self.lower_left
+
+ def getLowerRight(
+ self,
+ ) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover
+ deprecation_with_replacement("getLowerRight", "lower_right", "3.0.0")
+ return self.lower_right
+
+ def getUpperLeft(
+ self,
+ ) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover
+ deprecation_with_replacement("getUpperLeft", "upper_left", "3.0.0")
+ return self.upper_left
+
+ def getUpperRight(
+ self,
+ ) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover
+ deprecation_with_replacement("getUpperRight", "upper_right", "3.0.0")
+ return self.upper_right
+
+ def setLowerLeft(self, value: Tuple[float, float]) -> None: # pragma: no cover
+ deprecation_with_replacement("setLowerLeft", "lower_left", "3.0.0")
+ self.lower_left = value # type: ignore
+
+ def setLowerRight(self, value: Tuple[float, float]) -> None: # pragma: no cover
+ deprecation_with_replacement("setLowerRight", "lower_right", "3.0.0")
+ self[2], self[1] = (self._ensure_is_number(x) for x in value)
+
+ def setUpperLeft(self, value: Tuple[float, float]) -> None: # pragma: no cover
+ deprecation_with_replacement("setUpperLeft", "upper_left", "3.0.0")
+ self[0], self[3] = (self._ensure_is_number(x) for x in value)
+
+ def setUpperRight(self, value: Tuple[float, float]) -> None: # pragma: no cover
+ deprecation_with_replacement("setUpperRight", "upper_right", "3.0.0")
+ self[2], self[3] = (self._ensure_is_number(x) for x in value)
+
+ @property
+ def width(self) -> decimal.Decimal:
+ return self.right - self.left
+
+ def getWidth(self) -> decimal.Decimal: # pragma: no cover
+ deprecation_with_replacement("getWidth", "width", "3.0.0")
+ return self.width
+
+ @property
+ def height(self) -> decimal.Decimal:
+ return self.top - self.bottom
+
+ def getHeight(self) -> decimal.Decimal: # pragma: no cover
+ deprecation_with_replacement("getHeight", "height", "3.0.0")
+ return self.height
+
+ @property
+ def lowerLeft(self) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover
+ deprecation_with_replacement("lowerLeft", "lower_left", "3.0.0")
+ return self.lower_left
+
+ @lowerLeft.setter
+ def lowerLeft(
+ self, value: Tuple[decimal.Decimal, decimal.Decimal]
+ ) -> None: # pragma: no cover
+ deprecation_with_replacement("lowerLeft", "lower_left", "3.0.0")
+ self.lower_left = value
+
+ @property
+ def lowerRight(self) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover
+ deprecation_with_replacement("lowerRight", "lower_right", "3.0.0")
+ return self.lower_right
+
+ @lowerRight.setter
+ def lowerRight(
+ self, value: Tuple[decimal.Decimal, decimal.Decimal]
+ ) -> None: # pragma: no cover
+ deprecation_with_replacement("lowerRight", "lower_right", "3.0.0")
+ self.lower_right = value
+
+ @property
+ def upperLeft(self) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover
+ deprecation_with_replacement("upperLeft", "upper_left", "3.0.0")
+ return self.upper_left
+
+ @upperLeft.setter
+ def upperLeft(
+ self, value: Tuple[decimal.Decimal, decimal.Decimal]
+ ) -> None: # pragma: no cover
+ deprecation_with_replacement("upperLeft", "upper_left", "3.0.0")
+ self.upper_left = value
+
+ @property
+ def upperRight(self) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover
+ deprecation_with_replacement("upperRight", "upper_right", "3.0.0")
+ return self.upper_right
+
+ @upperRight.setter
+ def upperRight(
+ self, value: Tuple[decimal.Decimal, decimal.Decimal]
+ ) -> None: # pragma: no cover
+ deprecation_with_replacement("upperRight", "upper_right", "3.0.0")
+ self.upper_right = value
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/generic/_utils.py b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_utils.py
new file mode 100644
index 00000000..2f8debdc
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_utils.py
@@ -0,0 +1,172 @@
+import codecs
+from typing import Dict, List, Tuple, Union
+
+from .._codecs import _pdfdoc_encoding
+from .._utils import StreamType, b_, 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)
+ txt = ""
+ 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:
+ txt += chr(int(x, base=16))
+ x = b""
+ if len(x) == 1:
+ x += b"0"
+ if len(x) == 2:
+ txt += chr(int(x, base=16))
+ return create_string_object(b_(txt), forced_encoding)
+
+
+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)
+ escape_dict = {
+ b"n": b"\n",
+ b"r": b"\r",
+ b"t": b"\t",
+ b"b": b"\b",
+ b"f": b"\f",
+ b"c": rb"\c",
+ b"(": b"(",
+ b")": b")",
+ b"/": b"/",
+ b"\\": b"\\",
+ b" ": b" ",
+ b"%": b"%",
+ b"<": b"<",
+ b">": b">",
+ b"[": b"[",
+ b"]": b"]",
+ b"#": b"#",
+ b"_": b"_",
+ b"&": b"&",
+ b"$": b"$",
+ }
+ try:
+ tok = escape_dict[tok]
+ except KeyError:
+ if b"0" <= tok and 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)
+ for _ in range(2):
+ ntok = stream.read(1)
+ if b"0" <= ntok and ntok <= b"7":
+ tok += ntok
+ else:
+ stream.seek(-1, 1) # ntok has to be analysed
+ break
+ tok = b_(chr(int(tok, base=8)))
+ elif 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:
+ tok = b""
+ else:
+ msg = rf"Unexpected escaped string: {tok.decode('utf8')}"
+ logger_warning(msg, __name__)
+ txt.append(tok)
+ return create_string_object(b"".join(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.
+
+ :param Union[str, bytes] string: A string
+
+ :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")
+ return TextStringObject(out)
+ elif isinstance(forced_encoding, str):
+ if forced_encoding == "bytes":
+ return ByteStringObject(string)
+ return TextStringObject(string.decode(forced_encoding))
+ else:
+ try:
+ if string.startswith(codecs.BOM_UTF16_BE):
+ retval = TextStringObject(string.decode("utf-16"))
+ retval.autodetect_utf16 = True
+ return retval
+ else:
+ # 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.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/PyPDF2/pagerange.py b/.venv/lib/python3.12/site-packages/PyPDF2/pagerange.py
new file mode 100644
index 00000000..f009adc1
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/pagerange.py
@@ -0,0 +1,173 @@
+"""
+Representation and utils for ranges of PDF file pages.
+
+Copyright (c) 2014, Steve Witham <switham_github@mac-guyver.com>.
+All rights reserved. This software is available under a BSD license;
+see https://github.com/py-pdf/PyPDF2/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 = "^({int}|({int}?(:{int}?(:{int}?)?)))$".format(int=_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."""
+ 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]:
+ """
+ n is the length of the list of pages to choose from.
+
+ Returns arguments for range(). See help(slice.indices).
+ """
+ return self._slice.indices(n)
+
+ def __eq__(self, other: Any) -> 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.
+
+ First arg must be a filename; other ags are filenames, page-range
+ expressions, slice objects, or PageRange objects.
+ A filename not followed by a page range indicates all pages of the file.
+ """
+ pairs: List[Tuple[str, PageRange]] = []
+ pdf_filename = 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."
+ )
+
+ pairs.append((pdf_filename, PageRange(arg)))
+ did_page_range = True
+ else:
+ # New filename or end of list--do all of the previous file?
+ if pdf_filename and not did_page_range:
+ pairs.append((pdf_filename, PAGE_RANGE_ALL))
+
+ 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/PyPDF2/papersizes.py b/.venv/lib/python3.12/site-packages/PyPDF2/papersizes.py
new file mode 100644
index 00000000..51aa2de5
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/papersizes.py
@@ -0,0 +1,48 @@
+"""Helper to get paper sizes."""
+
+from collections import namedtuple
+
+Dimensions = namedtuple("Dimensions", ["width", "height"])
+
+
+class PaperSize:
+ """(width, height) of the paper in portrait mode in pixels at 72 ppi."""
+
+ # Notes how to calculate it:
+ # 1. Get the size of the paper in mm
+ # 2. Convert it to inches (25.4 millimeters are equal to 1 inches)
+ # 3. Convert it to pixels ad 72dpi (1 inch is equal to 72 pixels)
+
+ # All Din-A paper sizes follow this pattern:
+ # 2xA(n-1) = A(n)
+ # So the height of the next bigger one is the width of the smaller one
+ # The ratio is always approximately the ratio 1:2**0.5
+ # Additionally, A0 is defined to have an area of 1 m**2
+ # 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) # Post cards
+ 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/PyPDF2/py.typed b/.venv/lib/python3.12/site-packages/PyPDF2/py.typed
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/py.typed
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/types.py b/.venv/lib/python3.12/site-packages/PyPDF2/types.py
new file mode 100644
index 00000000..92cba6fe
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/types.py
@@ -0,0 +1,52 @@
+"""Helpers for working with PDF types."""
+
+from typing import List, Union
+
+try:
+ # Python 3.8+: https://peps.python.org/pep-0586
+ from typing import Literal # type: ignore[attr-defined]
+except ImportError:
+ from typing_extensions import Literal # type: ignore[misc]
+
+try:
+ # Python 3.10+: https://www.python.org/dev/peps/pep-0484/
+ from typing import TypeAlias # type: ignore[attr-defined]
+except ImportError:
+ 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[
+ "/Fit", "/XYZ", "/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",
+]
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/xmp.py b/.venv/lib/python3.12/site-packages/PyPDF2/xmp.py
new file mode 100644
index 00000000..de432823
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/xmp.py
@@ -0,0 +1,525 @@
+"""
+Anything related to XMP metadata.
+
+See 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,
+ cast,
+)
+from xml.dom.minidom import Document
+from xml.dom.minidom import Element as XmlElement
+from xml.dom.minidom import parseString
+from xml.parsers.expat import ExpatError
+
+from ._utils import (
+ StreamType,
+ deprecate_with_replacement,
+ deprecation_with_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? I might ask that too. It's
+# a completely undocumented namespace 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, in case you're wondering, is the unicode character
+# \u{ROMAN NUMERAL TEN THOUSAND}, a straightforward and obvious choice for
+# escaping characters.
+#
+# Intentional users of the pdfx namespace should be shot on sight. 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").
+#
+# Information presented here on the /pdfx/ schema is a result of limited
+# reverse engineering, and does not constitute a full specification.
+PDFX_NAMESPACE = "http://ns.adobe.com/pdfx/1.3/"
+
+iso8601 = re.compile(
+ """
+ (?P<year>[0-9]{4})
+ (-
+ (?P<month>[0-9]{2})
+ (-
+ (?P<day>[0-9]+)
+ (T
+ (?P<hour>[0-9]{2}):
+ (?P<minute>[0-9]{2})
+ (:(?P<second>[0-9]{2}(.[0-9]+)?))?
+ (?P<tzd>Z|[-+][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) * 1000000
+
+ 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 Adobe XMP metadata.
+ Usually accessed by :py:attr:`xmp_metadata()<PyPDF2.PdfReader.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)
+ 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] = {}
+
+ @property
+ def rdfRoot(self) -> XmlElement: # pragma: no cover
+ deprecate_with_replacement("rdfRoot", "rdf_root", "4.0.0")
+ return self.rdf_root
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None:
+ self.stream.write_to_stream(stream, encryption_key)
+
+ def writeToStream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes]
+ ) -> None: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`write_to_stream` instead.
+ """
+ deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0")
+ self.write_to_stream(stream, encryption_key)
+
+ 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 getElement(
+ self, aboutUri: str, namespace: str, name: str
+ ) -> Iterator[Any]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`get_element` instead.
+ """
+ deprecation_with_replacement("getElement", "get_element", "3.0.0")
+ return self.get_element(aboutUri, 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 getNodesInNamespace(
+ self, aboutUri: str, namespace: str
+ ) -> Iterator[Any]: # pragma: no cover
+ """
+ .. deprecated:: 1.28.0
+
+ Use :meth:`get_nodes_in_namespace` instead.
+ """
+ deprecation_with_replacement(
+ "getNodesInNamespace", "get_nodes_in_namespace", "3.0.0"
+ )
+ return self.get_nodes_in_namespace(aboutUri, namespace)
+
+ 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 keywrods 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, 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.
+ """
+
+ @property
+ def xmp_createDate(self) -> datetime.datetime: # pragma: no cover
+ deprecate_with_replacement("xmp_createDate", "xmp_create_date", "4.0.0")
+ return self.xmp_create_date
+
+ @xmp_createDate.setter
+ def xmp_createDate(self, value: datetime.datetime) -> None: # pragma: no cover
+ deprecate_with_replacement("xmp_createDate", "xmp_create_date", "4.0.0")
+ self.xmp_create_date = value
+
+ 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.
+ """
+
+ @property
+ def xmp_modifyDate(self) -> datetime.datetime: # pragma: no cover
+ deprecate_with_replacement("xmp_modifyDate", "xmp_modify_date", "4.0.0")
+ return self.xmp_modify_date
+
+ @xmp_modifyDate.setter
+ def xmp_modifyDate(self, value: datetime.datetime) -> None: # pragma: no cover
+ deprecate_with_replacement("xmp_modifyDate", "xmp_modify_date", "4.0.0")
+ self.xmp_modify_date = value
+
+ 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.
+ """
+
+ @property
+ def xmp_metadataDate(self) -> datetime.datetime: # pragma: no cover
+ deprecate_with_replacement("xmp_metadataDate", "xmp_metadata_date", "4.0.0")
+ return self.xmp_metadata_date
+
+ @xmp_metadataDate.setter
+ def xmp_metadataDate(self, value: datetime.datetime) -> None: # pragma: no cover
+ deprecate_with_replacement("xmp_metadataDate", "xmp_metadata_date", "4.0.0")
+ self.xmp_metadata_date = value
+
+ xmp_creator_tool = property(_getter_single(XMP_NAMESPACE, "CreatorTool"))
+ """The name of the first known tool used to create the resource."""
+
+ @property
+ def xmp_creatorTool(self) -> str: # pragma: no cover
+ deprecation_with_replacement("xmp_creatorTool", "xmp_creator_tool", "3.0.0")
+ return self.xmp_creator_tool
+
+ @xmp_creatorTool.setter
+ def xmp_creatorTool(self, value: str) -> None: # pragma: no cover
+ deprecation_with_replacement("xmp_creatorTool", "xmp_creator_tool", "3.0.0")
+ self.xmp_creator_tool = value
+
+ xmpmm_document_id = property(_getter_single(XMPMM_NAMESPACE, "DocumentID"))
+ """
+ The common identifier for all versions and renditions of this resource.
+ """
+
+ @property
+ def xmpmm_documentId(self) -> str: # pragma: no cover
+ deprecation_with_replacement("xmpmm_documentId", "xmpmm_document_id", "3.0.0")
+ return self.xmpmm_document_id
+
+ @xmpmm_documentId.setter
+ def xmpmm_documentId(self, value: str) -> None: # pragma: no cover
+ deprecation_with_replacement("xmpmm_documentId", "xmpmm_document_id", "3.0.0")
+ self.xmpmm_document_id = value
+
+ 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 xmpmm_instanceId(self) -> str: # pragma: no cover
+ deprecation_with_replacement("xmpmm_instanceId", "xmpmm_instance_id", "3.0.0")
+ return cast(str, self.xmpmm_instance_id)
+
+ @xmpmm_instanceId.setter
+ def xmpmm_instanceId(self, value: str) -> None: # pragma: no cover
+ deprecation_with_replacement("xmpmm_instanceId", "xmpmm_instance_id", "3.0.0")
+ self.xmpmm_instance_id = value
+
+ @property
+ def custom_properties(self) -> Dict[Any, Any]:
+ """
+ Retrieve custom metadata properties defined in the undocumented pdfx
+ metadata schema.
+
+ :return: 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