back to Reference (Gold) summary
Reference (Gold): pypdf
Pytest Summary for test tests
status | count |
---|---|
passed | 910 |
skipped | 1 |
xfailed | 3 |
xpassed | 1 |
total | 915 |
collected | 915 |
Failed pytests:
test_reader.py::test_get_images[imagemagick-lzw.pdf-expected_images3]
test_reader.py::test_get_images[imagemagick-lzw.pdf-expected_images3]
[gw0] linux -- Python 3.12.6 /testbed/.venv/bin/python3
test_reader.py::test_get_images[imagemagick-ASCII85Decode.pdf-expected_images4]
test_reader.py::test_get_images[imagemagick-ASCII85Decode.pdf-expected_images4]
[gw0] linux -- Python 3.12.6 /testbed/.venv/bin/python3
test_text_extraction.py::test_issue_2336
test_text_extraction.py::test_issue_2336
[gw4] linux -- Python 3.12.6 /testbed/.venv/bin/python3
test_page.py::test_text_extraction_issue_1091
test_page.py::test_text_extraction_issue_1091
[gw3] linux -- Python 3.12.6 /testbed/.venv/bin/python3
Patch diff
diff --git a/pypdf/_cmap.py b/pypdf/_cmap.py
index 77c2f842..9a2d10a6 100644
--- a/pypdf/_cmap.py
+++ b/pypdf/_cmap.py
@@ -1,14 +1,22 @@
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 b_, logger_error, logger_warning
-from .generic import DecodedStreamObject, DictionaryObject, IndirectObject, NullObject, StreamObject
+from .generic import (
+ DecodedStreamObject,
+ DictionaryObject,
+ IndirectObject,
+ NullObject,
+ StreamObject,
+)
-def build_char_map(font_name: str, space_width: float, obj: DictionaryObject
- ) ->Tuple[str, float, Union[str, Dict[int, str]], Dict[Any, Any],
- DictionaryObject]:
+# code freely inspired from @twiggy ; see #711
+def build_char_map(
+ font_name: str, space_width: float, obj: DictionaryObject
+) -> Tuple[str, float, Union[str, Dict[int, str]], Dict[Any, Any], DictionaryObject]:
"""
Determine information about a font.
@@ -21,11 +29,16 @@ def build_char_map(font_name: str, space_width: float, obj: DictionaryObject
Font sub-type, space_width criteria (50% of width), encoding, map character-map, font-dictionary.
The font-dictionary itself is suitable for the curious.
"""
- pass
+ ft: DictionaryObject = obj["/Resources"]["/Font"][font_name] # type: ignore
+ font_subtype, font_halfspace, font_encoding, font_map = build_char_map_from_dict(
+ space_width, ft
+ )
+ return font_subtype, font_halfspace, font_encoding, font_map, ft
-def build_char_map_from_dict(space_width: float, ft: DictionaryObject) ->Tuple[
- str, float, Union[str, Dict[int, str]], Dict[Any, Any]]:
+def build_char_map_from_dict(
+ space_width: float, ft: DictionaryObject
+) -> Tuple[str, float, Union[str, Dict[int, str]], Dict[Any, Any]]:
"""
Determine information about a font.
@@ -38,23 +51,470 @@ def build_char_map_from_dict(space_width: float, ft: DictionaryObject) ->Tuple[
Font sub-type, space_width criteria(50% of width), encoding, map character-map.
The font-dictionary itself is suitable for the curious.
"""
- pass
-
-
-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', '/GB-EUC-V': 'gbk',
- '/GBpc-EUC-H': 'gb2312', '/GBpc-EUC-V': 'gb2312', '/GBK-EUC-H': 'gbk',
- '/GBK-EUC-V': 'gbk', '/GBK2K-H': 'gb18030', '/GBK2K-V': 'gb18030',
- '/ETen-B5-H': 'cp950', '/ETen-B5-V': 'cp950', '/ETenms-B5-H': 'cp950',
- '/ETenms-B5-V': 'cp950', '/UniCNS-UTF16-H': 'utf-16-be',
- '/UniCNS-UTF16-V': 'utf-16-be'}
-_default_fonts_space_width: Dict[str, int] = {'/Courier': 600,
- '/Courier-Bold': 600, '/Courier-BoldOblique': 600, '/Courier-Oblique':
- 600, '/Helvetica': 278, '/Helvetica-Bold': 278,
- '/Helvetica-BoldOblique': 278, '/Helvetica-Oblique': 278,
- '/Helvetica-Narrow': 228, '/Helvetica-NarrowBold': 228,
- '/Helvetica-NarrowBoldOblique': 228, '/Helvetica-NarrowOblique': 228,
- '/Times-Roman': 250, '/Times-Bold': 250, '/Times-BoldItalic': 250,
- '/Times-Italic': 250, '/Symbol': 250, '/ZapfDingbats': 278}
+ 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 consider 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,
+ )
+
+
+# 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",
+ "/GB-EUC-V": "gbk",
+ "/GBpc-EUC-H": "gb2312",
+ "/GBpc-EUC-V": "gb2312",
+ "/GBK-EUC-H": "gbk",
+ "/GBK-EUC-V": "gbk",
+ "/GBK2K-H": "gb18030",
+ "/GBK2K-V": "gb18030",
+ "/ETen-B5-H": "cp950",
+ "/ETen-B5-V": "cp950",
+ "/ETenms-B5-H": "cp950",
+ "/ETenms-B5-V": "cp950",
+ "/UniCNS-UTF16-H": "utf-16-be",
+ "/UniCNS-UTF16-V": "utf-16-be",
+ # UCS2 in code
+}
+
+# manually extracted from http://mirrors.ctan.org/fonts/adobe/afm/Adobe-Core35_AFMs-229.tar.gz
+_default_fonts_space_width: Dict[str, int] = {
+ "/Courier": 600,
+ "/Courier-Bold": 600,
+ "/Courier-BoldOblique": 600,
+ "/Courier-Oblique": 600,
+ "/Helvetica": 278,
+ "/Helvetica-Bold": 278,
+ "/Helvetica-BoldOblique": 278,
+ "/Helvetica-Oblique": 278,
+ "/Helvetica-Narrow": 228,
+ "/Helvetica-NarrowBold": 228,
+ "/Helvetica-NarrowBoldOblique": 228,
+ "/Helvetica-NarrowOblique": 228,
+ "/Times-Roman": 250,
+ "/Times-Bold": 250,
+ "/Times-BoldItalic": 250,
+ "/Times-Italic": 250,
+ "/Symbol": 250,
+ "/ZapfDingbats": 278,
+}
+
+
+def 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:
+ # already done : enc = NameObject.unnumber(enc.encode()).decode()
+ # for #xx decoding
+ if enc in charset_encoding:
+ encoding = charset_encoding[enc].copy()
+ elif enc in _predefined_cmap:
+ encoding = _predefined_cmap[enc]
+ elif "-UCS2-" in enc:
+ encoding = "utf-16-be"
+ else:
+ raise Exception("not found")
+ except Exception:
+ logger_error(f"Advanced encoding {enc} not implemented yet", __name__)
+ encoding = enc
+ elif isinstance(enc, DictionaryObject) and "/BaseEncoding" in enc:
+ try:
+ encoding = charset_encoding[cast(str, enc["/BaseEncoding"])].copy()
+ except Exception:
+ logger_error(
+ f"Advanced encoding {encoding} not implemented yet",
+ __name__,
+ )
+ encoding = charset_encoding["/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:
+ if ft.get("/Subtype", "") == "/Type1":
+ return type1_alternative(ft, map_dict, space_code, int_entry)
+ else:
+ 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 line in cm.split(b"\n"):
+ process_rg, process_char, multiline_rg = process_cm_line(
+ line.strip(b" \t"),
+ process_rg,
+ process_char,
+ multiline_rg,
+ map_dict,
+ int_entry,
+ )
+
+ 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 = b_(cast(DecodedStreamObject, ft["/ToUnicode"]).get_data())
+ elif isinstance(tu, str) and tu.startswith("/Identity"):
+ # the full range 0000-FFFF will be processed
+ cm = b"beginbfrange\n<0000> <0001> <0000>\nendbfrange"
+ if isinstance(cm, str):
+ cm = cm.encode()
+ # we need to prepare cm before due to missing return line in pdf printed
+ # to pdf from word
+ cm = (
+ cm.strip()
+ .replace(b"beginbfchar", b"\nbeginbfchar\n")
+ .replace(b"endbfchar", b"\nendbfchar\n")
+ .replace(b"beginbfrange", b"\nbeginbfrange\n")
+ .replace(b"endbfrange", b"\nendbfrange\n")
+ .replace(b"<<", b"\n{\n") # text between << and >> not used but
+ .replace(b">>", b"\n}\n") # some solution to find it back
+ )
+ ll = cm.split(b"<")
+ for i in range(len(ll)):
+ j = ll[i].find(b">")
+ if j >= 0:
+ if j == 0:
+ # string is empty: stash a placeholder here (see below)
+ # see https://github.com/py-pdf/pypdf/issues/1111
+ content = b"."
+ else:
+ content = ll[i][:j].replace(b" ", b"")
+ ll[i] = content + b" " + ll[i][j + 1 :]
+ cm = (
+ (b" ".join(ll))
+ .replace(b"[", b" [ ")
+ .replace(b"]", b" ]\n ")
+ .replace(b"\r", b"\n")
+ )
+ return cm
+
+
+def process_cm_line(
+ line: bytes,
+ process_rg: bool,
+ process_char: bool,
+ multiline_rg: Union[None, Tuple[int, int]],
+ map_dict: Dict[Any, Any],
+ int_entry: List[int],
+) -> Tuple[bool, bool, Union[None, Tuple[int, int]]]:
+ if line == b"" or line[0] == 37: # 37 = %
+ return process_rg, process_char, multiline_rg
+ line = line.replace(b"\t", b" ")
+ if b"beginbfrange" in line:
+ process_rg = True
+ elif b"endbfrange" in line:
+ process_rg = False
+ elif b"beginbfchar" in line:
+ process_char = True
+ elif b"endbfchar" in line:
+ process_char = False
+ elif process_rg:
+ multiline_rg = parse_bfrange(line, map_dict, int_entry, multiline_rg)
+ elif process_char:
+ parse_bfchar(line, map_dict, int_entry)
+ return process_rg, process_char, multiline_rg
+
+
+def parse_bfrange(
+ line: bytes,
+ map_dict: Dict[Any, Any],
+ int_entry: List[int],
+ multiline_rg: Union[None, Tuple[int, int]],
+) -> Union[None, Tuple[int, int]]:
+ lst = [x for x in line.split(b" ") if x]
+ closure_found = False
+ if multiline_rg is not None:
+ fmt = b"%%0%dX" % (map_dict[-1] * 2)
+ a = multiline_rg[0] # a, b not in the current line
+ b = multiline_rg[1]
+ for sq in lst[0:]:
+ if sq == b"]":
+ closure_found = True
+ break
+ map_dict[
+ unhexlify(fmt % a).decode(
+ "charmap" if map_dict[-1] == 1 else "utf-16-be",
+ "surrogatepass",
+ )
+ ] = unhexlify(sq).decode("utf-16-be", "surrogatepass")
+ int_entry.append(a)
+ a += 1
+ else:
+ a = int(lst[0], 16)
+ b = int(lst[1], 16)
+ nbi = max(len(lst[0]), len(lst[1]))
+ map_dict[-1] = ceil(nbi / 2)
+ fmt = b"%%0%dX" % (map_dict[-1] * 2)
+ if lst[2] == b"[":
+ for sq in lst[3:]:
+ if sq == b"]":
+ closure_found = True
+ break
+ map_dict[
+ unhexlify(fmt % a).decode(
+ "charmap" if map_dict[-1] == 1 else "utf-16-be",
+ "surrogatepass",
+ )
+ ] = unhexlify(sq).decode("utf-16-be", "surrogatepass")
+ int_entry.append(a)
+ a += 1
+ else: # case without list
+ c = int(lst[2], 16)
+ fmt2 = b"%%0%dX" % max(4, len(lst[2]))
+ closure_found = True
+ while a <= b:
+ map_dict[
+ unhexlify(fmt % a).decode(
+ "charmap" if map_dict[-1] == 1 else "utf-16-be",
+ "surrogatepass",
+ )
+ ] = unhexlify(fmt2 % c).decode("utf-16-be", "surrogatepass")
+ int_entry.append(a)
+ a += 1
+ c += 1
+ return None if closure_found else (a, b)
+
+
+def parse_bfchar(line: bytes, map_dict: Dict[Any, Any], int_entry: List[int]) -> None:
+ lst = [x for x in line.split(b" ") if x]
+ map_dict[-1] = len(lst[0]) // 2
+ while len(lst) > 1:
+ map_to = ""
+ # placeholder (see above) means empty string
+ if lst[1] != b".":
+ map_to = unhexlify(lst[1]).decode(
+ "charmap" if len(lst[1]) < 4 else "utf-16-be", "surrogatepass"
+ ) # join is here as some cases where the code was split
+ map_dict[
+ unhexlify(lst[0]).decode(
+ "charmap" if map_dict[-1] == 1 else "utf-16-be", "surrogatepass"
+ )
+ ] = map_to
+ int_entry.append(int(lst[0], 16))
+ lst = lst[2:]
+
+
+def compute_space_width(
+ ft: DictionaryObject, space_code: int, space_width: float
+) -> float:
+ sp_width: float = space_width * 2.0 # 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] if isinstance(w[0], int) else w[0].get_object()
+ second = w[1].get_object()
+ 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
+
+ if isinstance(sp_width, IndirectObject):
+ # According to
+ # 'Table 122 - Entries common to all font descriptors (continued)'
+ # the MissingWidth should be a number, but according to #2286 it can
+ # be an indirect object
+ obj = sp_width.get_object()
+ if obj is None or isinstance(obj, NullObject):
+ return 0.0
+ return obj # type: ignore
+
+ return sp_width
+
+
+def type1_alternative(
+ ft: DictionaryObject,
+ map_dict: Dict[Any, Any],
+ space_code: int,
+ int_entry: List[int],
+) -> Tuple[Dict[Any, Any], int, List[int]]:
+ if "/FontDescriptor" not in ft:
+ return map_dict, space_code, int_entry
+ ft_desc = cast(DictionaryObject, ft["/FontDescriptor"]).get("/FontFile")
+ if ft_desc is None:
+ return map_dict, space_code, int_entry
+ txt = ft_desc.get_object().get_data()
+ txt = txt.split(b"eexec\n")[0] # only clear part
+ txt = txt.split(b"/Encoding")[1] # to get the encoding part
+ lines = txt.replace(b"\r", b"\n").split(b"\n")
+ for li in lines:
+ if li.startswith(b"dup"):
+ words = [_w for _w in li.split(b" ") if _w != b""]
+ if len(words) > 3 and words[3] != b"put":
+ continue
+ try:
+ i = int(words[1])
+ except ValueError: # pragma: no cover
+ continue
+ try:
+ v = adobe_glyphs[words[2].decode()]
+ except KeyError:
+ if words[2].startswith(b"/uni"):
+ try:
+ v = chr(int(words[2][4:], 16))
+ except ValueError: # pragma: no cover
+ continue
+ else:
+ continue
+ if words[2].decode() == b" ":
+ space_code = i
+ map_dict[chr(i)] = v
+ int_entry.append(i)
+ return map_dict, space_code, int_entry
diff --git a/pypdf/_codecs/adobe_glyphs.py b/pypdf/_codecs/adobe_glyphs.py
index 5a8b986c..19e2a99c 100644
--- a/pypdf/_codecs/adobe_glyphs.py
+++ b/pypdf/_codecs/adobe_glyphs.py
@@ -1,4972 +1,13970 @@
-adobe_glyphs = {'/A': 'A', '/AA': 'Ꜳ', '/AE': 'Æ', '/AEacute': 'Ǽ',
- '/AEmacron': 'Ǣ', '/AEsmall': '\uf7e6', '/AO': 'Ꜵ', '/AU': 'Ꜷ', '/AV':
- 'Ꜹ', '/AVhorizontalbar': 'Ꜻ', '/AY': 'Ꜽ', '/Aacute': 'Á',
- '/Aacutesmall': '\uf7e1', '/Abreve': 'Ă', '/Abreveacute': 'Ắ',
- '/Abrevecyr': 'Ӑ', '/Abrevecyrillic': 'Ӑ', '/Abrevedotbelow': 'Ặ',
- '/Abrevegrave': 'Ằ', '/Abrevehoi': 'Ẳ', '/Abrevehookabove': 'Ẳ',
- '/Abrevetilde': 'Ẵ', '/Acaron': 'Ǎ', '/Acircle': 'Ⓐ', '/Acircleblack':
- 'ἕ0', '/Acircumflex': 'Â', '/Acircumflexacute': 'Ấ',
- '/Acircumflexdotbelow': 'Ậ', '/Acircumflexgrave': 'Ầ',
- '/Acircumflexhoi': 'Ẩ', '/Acircumflexhookabove': 'Ẩ',
- '/Acircumflexsmall': '\uf7e2', '/Acircumflextilde': 'Ẫ', '/Acute':
- '\uf6c9', '/Acutesmall': '\uf7b4', '/Acyr': 'А', '/Acyrillic': 'А',
- '/Adblgrave': 'Ȁ', '/Adieresis': 'Ä', '/Adieresiscyr': 'Ӓ',
- '/Adieresiscyrillic': 'Ӓ', '/Adieresismacron': 'Ǟ', '/Adieresissmall':
- '\uf7e4', '/Adot': 'Ȧ', '/Adotbelow': 'Ạ', '/Adotmacron': 'Ǡ',
- '/Agrave': 'À', '/Agravedbl': 'Ȁ', '/Agravesmall': '\uf7e0', '/Ahoi':
- 'Ả', '/Ahookabove': 'Ả', '/Aiecyr': 'Ӕ', '/Aiecyrillic': 'Ӕ',
- '/Ainvertedbreve': 'Ȃ', '/Akbar': 'ﷳ', '/Alayhe': 'ﷷ', '/Allah': 'ﷲ',
- '/Alpha': 'Α', '/Alphaacute': 'Ά', '/Alphaasper': 'Ἁ',
- '/Alphaasperacute': 'Ἅ', '/Alphaasperacuteiotasub': 'ᾍ',
- '/Alphaaspergrave': 'Ἃ', '/Alphaaspergraveiotasub': 'ᾋ',
- '/Alphaasperiotasub': 'ᾉ', '/Alphaaspertilde': 'Ἇ',
- '/Alphaaspertildeiotasub': 'ᾏ', '/Alphabreve': 'Ᾰ', '/Alphagrave': 'Ὰ',
- '/Alphaiotasub': 'ᾼ', '/Alphalenis': 'Ἀ', '/Alphalenisacute': 'Ἄ',
- '/Alphalenisacuteiotasub': 'ᾌ', '/Alphalenisgrave': 'Ἂ',
- '/Alphalenisgraveiotasub': 'ᾊ', '/Alphalenisiotasub': 'ᾈ',
- '/Alphalenistilde': 'Ἆ', '/Alphalenistildeiotasub': 'ᾎ', '/Alphatonos':
- 'Ά', '/Alphawithmacron': 'Ᾱ', '/Amacron': 'Ā', '/Amonospace': 'A',
- '/Aogonek': 'Ą', '/Aparens': 'ἑ0', '/Aring': 'Å', '/Aringacute': 'Ǻ',
- '/Aringbelow': 'Ḁ', '/Aringsmall': '\uf7e5', '/Asmall': '\uf761',
- '/Asquare': 'ἓ0', '/Asquareblack': '\u1f170', '/Astroke': 'Ⱥ',
- '/Atilde': 'Ã', '/Atildesmall': '\uf7e3', '/Aturned': 'Ɐ', '/Ayahend':
- '\u06dd', '/Aybarmenian': 'Ա', '/B': 'B', '/Bcircle': 'Ⓑ',
- '/Bcircleblack': 'ἕ1', '/Bdot': 'Ḃ', '/Bdotaccent': 'Ḃ', '/Bdotbelow':
- 'Ḅ', '/Becyr': 'Б', '/Becyrillic': 'Б', '/Benarmenian': 'Բ', '/Beta':
- 'Β', '/Bflourish': 'Ꞗ', '/Bhook': 'Ɓ', '/BismillahArRahmanArRaheem':
- '﷽', '/Blinebelow': 'Ḇ', '/Bmonospace': 'B', '/Bparens': 'ἑ1',
- '/Brevesmall': '\uf6f4', '/Bscript': 'ℬ', '/Bsmall': '\uf762',
- '/Bsquare': 'ἓ1', '/Bsquareblack': '\u1f171', '/Bstroke': 'Ƀ',
- '/Btopbar': 'Ƃ', '/C': 'C', '/CDcircle': 'ἒD', '/Caarmenian': 'Ծ',
- '/Cacute': 'Ć', '/Caron': '\uf6ca', '/Caronsmall': '\uf6f5', '/Cbar':
- 'Ꞓ', '/Ccaron': 'Č', '/Ccedilla': 'Ç', '/Ccedillaacute': 'Ḉ',
- '/Ccedillasmall': '\uf7e7', '/Ccircle': 'Ⓒ', '/Ccircleblack': 'ἕ2',
- '/Ccircumflex': 'Ĉ', '/Cdblstruck': 'ℂ', '/Cdot': 'Ċ', '/Cdotaccent':
- 'Ċ', '/Cdotreversed': 'Ꜿ', '/Cedillasmall': '\uf7b8', '/Cfraktur': 'ℭ',
- '/Chaarmenian': 'Չ', '/Cheabkhasiancyrillic': 'Ҽ', '/Cheabkhcyr': 'Ҽ',
- '/Cheabkhtailcyr': 'Ҿ', '/Checyr': 'Ч', '/Checyrillic': 'Ч',
- '/Chedescenderabkhasiancyrillic': 'Ҿ', '/Chedescendercyrillic': 'Ҷ',
- '/Chedieresiscyr': 'Ӵ', '/Chedieresiscyrillic': 'Ӵ', '/Cheharmenian':
- 'Ճ', '/Chekhakascyr': 'Ӌ', '/Chekhakassiancyrillic': 'Ӌ', '/Chetailcyr':
- 'Ҷ', '/Chevertcyr': 'Ҹ', '/Cheverticalstrokecyrillic': 'Ҹ', '/Chi': 'Χ',
- '/Chook': 'Ƈ', '/Circumflexsmall': '\uf6f6', '/Citaliccircle': 'ἒB',
- '/Cmonospace': 'C', '/Coarmenian': 'Ց', '/Con': 'Ꝯ', '/Cparens': 'ἑ2',
- '/Csmall': '\uf763', '/Csquare': 'ἓ2', '/Csquareblack': '\u1f172',
- '/Cstretched': 'ʗ', '/Cstroke': 'Ȼ', '/Cuatrillo': 'Ꜭ',
- '/Cuatrillocomma': 'Ꜯ', '/D': 'D', '/DZ': 'DZ', '/DZcaron': 'DŽ',
- '/Daarmenian': 'Դ', '/Dafrican': 'Ɖ', '/Dcaron': 'Ď', '/Dcedilla': 'Ḑ',
- '/Dchecyr': 'Ԭ', '/Dcircle': 'Ⓓ', '/Dcircleblack': 'ἕ3',
- '/Dcircumflexbelow': 'Ḓ', '/Dcroat': 'Đ', '/Ddblstruckitalic': 'ⅅ',
- '/Ddot': 'Ḋ', '/Ddotaccent': 'Ḋ', '/Ddotbelow': 'Ḍ', '/Decyr': 'Д',
- '/Decyrillic': 'Д', '/Deicoptic': 'Ϯ', '/Dekomicyr': 'Ԁ', '/Delta': '∆',
- '/Deltagreek': 'Δ', '/Dhook': 'Ɗ', '/Dieresis': '\uf6cb',
- '/DieresisAcute': '\uf6cc', '/DieresisGrave': '\uf6cd',
- '/Dieresissmall': '\uf7a8', '/Digamma': 'Ϝ', '/Digammagreek': 'Ϝ',
- '/Digammapamphylian': 'Ͷ', '/Dinsular': 'Ꝺ', '/Djecyr': 'Ђ',
- '/Djecyrillic': 'Ђ', '/Djekomicyr': 'Ԃ', '/Dlinebelow': 'Ḏ',
- '/Dmonospace': 'D', '/Dotaccentsmall': '\uf6f7', '/Dparens': 'ἑ3',
- '/Dslash': 'Đ', '/Dsmall': '\uf764', '/Dsquare': 'ἓ3', '/Dsquareblack':
- '\u1f173', '/Dtopbar': 'Ƌ', '/Dz': 'Dz', '/Dzcaron': 'Dž',
- '/Dzeabkhasiancyrillic': 'Ӡ', '/Dzeabkhcyr': 'Ӡ', '/Dzecyr': 'Ѕ',
- '/Dzecyrillic': 'Ѕ', '/Dzhecyr': 'Џ', '/Dzhecyrillic': 'Џ',
- '/Dzjekomicyr': 'Ԇ', '/Dzzhecyr': 'Ԫ', '/E': 'E', '/Eacute': 'É',
- '/Eacutesmall': '\uf7e9', '/Ebreve': 'Ĕ', '/Ecaron': 'Ě', '/Ecedilla':
- 'Ȩ', '/Ecedillabreve': 'Ḝ', '/Echarmenian': 'Ե', '/Ecircle': 'Ⓔ',
- '/Ecircleblack': 'ἕ4', '/Ecircumflex': 'Ê', '/Ecircumflexacute': 'Ế',
- '/Ecircumflexbelow': 'Ḙ', '/Ecircumflexdotbelow': 'Ệ',
- '/Ecircumflexgrave': 'Ề', '/Ecircumflexhoi': 'Ể',
- '/Ecircumflexhookabove': 'Ể', '/Ecircumflexsmall': '\uf7ea',
- '/Ecircumflextilde': 'Ễ', '/Ecyrillic': 'Є', '/Edblgrave': 'Ȅ',
- '/Edieresis': 'Ë', '/Edieresissmall': '\uf7eb', '/Edot': 'Ė',
- '/Edotaccent': 'Ė', '/Edotbelow': 'Ẹ', '/Efcyr': 'Ф', '/Efcyrillic':
- 'Ф', '/Egrave': 'È', '/Egravedbl': 'Ȅ', '/Egravesmall': '\uf7e8',
- '/Egyptain': 'Ꜥ', '/Egyptalef': 'Ꜣ', '/Eharmenian': 'Է', '/Ehoi': 'Ẻ',
- '/Ehookabove': 'Ẻ', '/Eightroman': 'Ⅷ', '/Einvertedbreve': 'Ȇ',
- '/Eiotifiedcyr': 'Ѥ', '/Eiotifiedcyrillic': 'Ѥ', '/Elcyr': 'Л',
- '/Elcyrillic': 'Л', '/Elevenroman': 'Ⅺ', '/Elhookcyr': 'Ԓ',
- '/Elmiddlehookcyr': 'Ԡ', '/Elsharptailcyr': 'Ӆ', '/Eltailcyr': 'Ԯ',
- '/Emacron': 'Ē', '/Emacronacute': 'Ḗ', '/Emacrongrave': 'Ḕ', '/Emcyr':
- 'М', '/Emcyrillic': 'М', '/Emonospace': 'E', '/Emsharptailcyr': 'Ӎ',
- '/Encyr': 'Н', '/Encyrillic': 'Н', '/Endescendercyrillic': 'Ң', '/Eng':
- 'Ŋ', '/Engecyr': 'Ҥ', '/Enghecyrillic': 'Ҥ', '/Enhookcyr': 'Ӈ',
- '/Enhookcyrillic': 'Ӈ', '/Enhookleftcyr': 'Ԩ', '/Enmiddlehookcyr': 'Ԣ',
- '/Ensharptailcyr': 'Ӊ', '/Entailcyr': 'Ң', '/Eogonek': 'Ę', '/Eopen':
- 'Ɛ', '/Eparens': 'ἑ4', '/Epsilon': 'Ε', '/Epsilonacute': 'Έ',
- '/Epsilonasper': 'Ἑ', '/Epsilonasperacute': 'Ἕ', '/Epsilonaspergrave':
- 'Ἓ', '/Epsilongrave': 'Ὲ', '/Epsilonlenis': 'Ἐ', '/Epsilonlenisacute':
- 'Ἔ', '/Epsilonlenisgrave': 'Ἒ', '/Epsilontonos': 'Έ', '/Ercyr': 'Р',
- '/Ercyrillic': 'Р', '/Ereversed': 'Ǝ', '/Ereversedcyr': 'Э',
- '/Ereversedcyrillic': 'Э', '/Ereverseddieresiscyr': 'Ӭ',
- '/Ereversedopen': 'Ɜ', '/Ertickcyr': 'Ҏ', '/Escript': 'ℰ', '/Escyr':
- 'С', '/Escyrillic': 'С', '/Esdescendercyrillic': 'Ҫ', '/Esh': 'Ʃ',
- '/Esmall': '\uf765', '/Esmallturned': 'ⱻ', '/Esquare': 'ἓ4',
- '/Esquareblack': '\u1f174', '/Estailcyr': 'Ҫ', '/Estroke': 'Ɇ', '/Et':
- 'Ꝫ', '/Eta': 'Η', '/Etaacute': 'Ή', '/Etaasper': 'Ἡ', '/Etaasperacute':
- 'Ἥ', '/Etaasperacuteiotasub': 'ᾝ', '/Etaaspergrave': 'Ἣ',
- '/Etaaspergraveiotasub': 'ᾛ', '/Etaasperiotasub': 'ᾙ', '/Etaaspertilde':
- 'Ἧ', '/Etaaspertildeiotasub': 'ᾟ', '/Etagrave': 'Ὴ', '/Etaiotasub': 'ῌ',
- '/Etalenis': 'Ἠ', '/Etalenisacute': 'Ἤ', '/Etalenisacuteiotasub': 'ᾜ',
- '/Etalenisgrave': 'Ἢ', '/Etalenisgraveiotasub': 'ᾚ', '/Etalenisiotasub':
- 'ᾘ', '/Etalenistilde': 'Ἦ', '/Etalenistildeiotasub': 'ᾞ', '/Etarmenian':
- 'Ը', '/Etatonos': 'Ή', '/Eth': 'Ð', '/Ethsmall': '\uf7f0', '/Etilde':
- 'Ẽ', '/Etildebelow': 'Ḛ', '/Eukrcyr': 'Є', '/Euro': '€', '/Ezh': 'Ʒ',
- '/Ezhcaron': 'Ǯ', '/Ezhreversed': 'Ƹ', '/F': 'F', '/Fcircle': 'Ⓕ',
- '/Fcircleblack': 'ἕ5', '/Fdot': 'Ḟ', '/Fdotaccent': 'Ḟ', '/Feharmenian':
- 'Ֆ', '/Feicoptic': 'Ϥ', '/Fhook': 'Ƒ', '/Finsular': 'Ꝼ', '/Fitacyr':
- 'Ѳ', '/Fitacyrillic': 'Ѳ', '/Fiveroman': 'Ⅴ', '/Fmonospace': 'F',
- '/Fourroman': 'Ⅳ', '/Fparens': 'ἑ5', '/Fscript': 'ℱ', '/Fsmall':
- '\uf766', '/Fsquare': 'ἓ5', '/Fsquareblack': '\u1f175', '/Fstroke': 'Ꞙ',
- '/Fturned': 'Ⅎ', '/G': 'G', '/GBsquare': '㎇', '/Gacute': 'Ǵ', '/Gamma':
- 'Γ', '/Gammaafrican': 'Ɣ', '/Gammadblstruck': 'ℾ', '/Gangiacoptic': 'Ϫ',
- '/Gbreve': 'Ğ', '/Gcaron': 'Ǧ', '/Gcedilla': 'Ģ', '/Gcircle': 'Ⓖ',
- '/Gcircleblack': 'ἕ6', '/Gcircumflex': 'Ĝ', '/Gcommaaccent': 'Ģ',
- '/Gdot': 'Ġ', '/Gdotaccent': 'Ġ', '/Gecyr': 'Г', '/Gecyrillic': 'Г',
- '/Gehookcyr': 'Ҕ', '/Gehookstrokecyr': 'Ӻ', '/Germandbls': 'ẞ',
- '/Gestrokecyr': 'Ғ', '/Getailcyr': 'Ӷ', '/Geupcyr': 'Ґ',
- '/Ghadarmenian': 'Ղ', '/Ghemiddlehookcyrillic': 'Ҕ',
- '/Ghestrokecyrillic': 'Ғ', '/Gheupturncyrillic': 'Ґ', '/Ghook': 'Ɠ',
- '/Ghooksmall': 'ʛ', '/Gimarmenian': 'Գ', '/Ginsular': 'Ᵹ',
- '/Ginsularturned': 'Ꝿ', '/Gjecyr': 'Ѓ', '/Gjecyrillic': 'Ѓ',
- '/Glottalstop': 'Ɂ', '/Gmacron': 'Ḡ', '/Gmonospace': 'G',
- '/Gobliquestroke': 'Ꞡ', '/Gparens': 'ἑ6', '/Grave': '\uf6ce',
- '/Gravesmall': '\uf760', '/Gsmall': '\uf767', '/Gsmallhook': 'ʛ',
- '/Gsquare': 'ἓ6', '/Gsquareblack': '\u1f176', '/Gstroke': 'Ǥ',
- '/Gturnedsans': '⅁', '/H': 'H', '/H18533': '●', '/H18543': '▪',
- '/H18551': '▫', '/H22073': '□', '/HPsquare': '㏋', '/HVsquare': 'ἔA',
- '/Haabkhasiancyrillic': 'Ҩ', '/Haabkhcyr': 'Ҩ', '/Hacyr': 'Х',
- '/Hadescendercyrillic': 'Ҳ', '/Hahookcyr': 'Ӽ', '/Hardcyr': 'Ъ',
- '/Hardsigncyrillic': 'Ъ', '/Hastrokecyr': 'Ӿ', '/Hbar': 'Ħ',
- '/Hbrevebelow': 'Ḫ', '/Hcaron': 'Ȟ', '/Hcedilla': 'Ḩ', '/Hcircle': 'Ⓗ',
- '/Hcircleblack': 'ἕ7', '/Hcircumflex': 'Ĥ', '/Hdblstruck': 'ℍ',
- '/Hdescender': 'Ⱨ', '/Hdieresis': 'Ḧ', '/Hdot': 'Ḣ', '/Hdotaccent': 'Ḣ',
- '/Hdotbelow': 'Ḥ', '/Heng': 'Ꜧ', '/Heta': 'Ͱ', '/Hfraktur': 'ℌ',
- '/Hgfullwidth': '㋌', '/Hhalf': 'Ⱶ', '/Hhook': 'Ɦ', '/Hmonospace': 'H',
- '/Hoarmenian': 'Հ', '/HonAA': 'ؑ', '/HonRA': 'ؒ', '/HonSAW': 'ؐ',
- '/Horicoptic': 'Ϩ', '/Hparens': 'ἑ7', '/Hscript': 'ℋ', '/Hsmall':
- '\uf768', '/Hsquare': 'ἓ7', '/Hsquareblack': '\u1f177', '/Hstrokemod':
- 'ꟸ', '/Hturned': 'Ɥ', '/Hungarumlaut': '\uf6cf', '/Hungarumlautsmall':
- '\uf6f8', '/Hwair': 'Ƕ', '/Hzsquare': '㎐', '/I': 'I', '/IAcyrillic':
- 'Я', '/ICsquareblack': 'ἘB', '/IJ': 'IJ', '/IUcyrillic': 'Ю', '/Iacute':
- 'Í', '/Iacutesmall': '\uf7ed', '/Ibreve': 'Ĭ', '/Icaron': 'Ǐ',
- '/Icircle': 'Ⓘ', '/Icircleblack': 'ἕ8', '/Icircumflex': 'Î',
- '/Icircumflexsmall': '\uf7ee', '/Icyr': 'И', '/Icyrillic': 'І',
- '/Idblgrave': 'Ȉ', '/Idieresis': 'Ï', '/Idieresisacute': 'Ḯ',
- '/Idieresiscyr': 'Ӥ', '/Idieresiscyrillic': 'Ӥ', '/Idieresissmall':
- '\uf7ef', '/Idot': 'İ', '/Idotaccent': 'İ', '/Idotbelow': 'Ị',
- '/Iebrevecyr': 'Ӗ', '/Iebrevecyrillic': 'Ӗ', '/Iecyr': 'Е',
- '/Iecyrillic': 'Е', '/Iegravecyr': 'Ѐ', '/Ifraktur': 'ℑ', '/Igrave':
- 'Ì', '/Igravecyr': 'Ѝ', '/Igravedbl': 'Ȉ', '/Igravesmall': '\uf7ec',
- '/Ihoi': 'Ỉ', '/Ihookabove': 'Ỉ', '/Iicyrillic': 'И', '/Iinvertedbreve':
- 'Ȋ', '/Iishortcyrillic': 'Й', '/Imacron': 'Ī', '/Imacroncyr': 'Ӣ',
- '/Imacroncyrillic': 'Ӣ', '/Imonospace': 'I', '/Iniarmenian': 'Ի',
- '/Iocyr': 'Ё', '/Iocyrillic': 'Ё', '/Iogonek': 'Į', '/Iota': 'Ι',
- '/Iotaacute': 'Ί', '/Iotaafrican': 'Ɩ', '/Iotaasper': 'Ἱ',
- '/Iotaasperacute': 'Ἵ', '/Iotaaspergrave': 'Ἳ', '/Iotaaspertilde': 'Ἷ',
- '/Iotabreve': 'Ῐ', '/Iotadieresis': 'Ϊ', '/Iotagrave': 'Ὶ',
- '/Iotalenis': 'Ἰ', '/Iotalenisacute': 'Ἴ', '/Iotalenisgrave': 'Ἲ',
- '/Iotalenistilde': 'Ἶ', '/Iotatonos': 'Ί', '/Iotawithmacron': 'Ῑ',
- '/Iparens': 'ἑ8', '/Is': 'Ꝭ', '/Iscript': 'ℐ', '/Ishortcyr': 'Й',
- '/Ishortsharptailcyr': 'Ҋ', '/Ismall': '\uf769', '/Isquare': 'ἓ8',
- '/Isquareblack': '\u1f178', '/Istroke': 'Ɨ', '/Itilde': 'Ĩ',
- '/Itildebelow': 'Ḭ', '/Iukrcyr': 'І', '/Izhitsacyr': 'Ѵ',
- '/Izhitsacyrillic': 'Ѵ', '/Izhitsadblgravecyrillic': 'Ѷ',
- '/Izhitsagravedblcyr': 'Ѷ', '/J': 'J', '/Jaarmenian': 'Ձ',
- '/Jallajalalouhou': 'ﷻ', '/Jcircle': 'Ⓙ', '/Jcircleblack': 'ἕ9',
- '/Jcircumflex': 'Ĵ', '/Jcrossed-tail': 'Ʝ', '/Jecyr': 'Ј',
- '/Jecyrillic': 'Ј', '/Jheharmenian': 'Ջ', '/Jmonospace': 'J',
- '/Jparens': 'ἑ9', '/Jsmall': '\uf76a', '/Jsquare': 'ἓ9',
- '/Jsquareblack': '\u1f179', '/Jstroke': 'Ɉ', '/K': 'K', '/KBsquare':
- '㎅', '/KKsquare': '㏍', '/KORONIS': '᾽', '/Kaaleutcyr': 'Ԟ',
- '/Kabashkcyr': 'Ҡ', '/Kabashkircyrillic': 'Ҡ', '/Kacute': 'Ḱ', '/Kacyr':
- 'К', '/Kacyrillic': 'К', '/Kadescendercyrillic': 'Қ', '/Kahookcyr': 'Ӄ',
- '/Kahookcyrillic': 'Ӄ', '/Kaisymbol': 'Ϗ', '/Kappa': 'Κ',
- '/Kastrokecyr': 'Ҟ', '/Kastrokecyrillic': 'Ҟ', '/Katailcyr': 'Қ',
- '/Kaverticalstrokecyr': 'Ҝ', '/Kaverticalstrokecyrillic': 'Ҝ',
- '/Kcaron': 'Ǩ', '/Kcedilla': 'Ķ', '/Kcircle': 'Ⓚ', '/Kcircleblack':
- 'ἕA', '/Kcommaaccent': 'Ķ', '/Kdescender': 'Ⱪ', '/Kdiagonalstroke': 'Ꝃ',
- '/Kdotbelow': 'Ḳ', '/Keharmenian': 'Ք', '/Kenarmenian': 'Կ',
- '/Khacyrillic': 'Х', '/Kheicoptic': 'Ϧ', '/Khook': 'Ƙ', '/Kjecyr': 'Ќ',
- '/Kjecyrillic': 'Ќ', '/Klinebelow': 'Ḵ', '/Kmonospace': 'K',
- '/Kobliquestroke': 'Ꞣ', '/Koppa': 'Ϟ', '/Koppaarchaic': 'Ϙ',
- '/Koppacyr': 'Ҁ', '/Koppacyrillic': 'Ҁ', '/Koppagreek': 'Ϟ', '/Kparens':
- 'ἑA', '/Ksicyr': 'Ѯ', '/Ksicyrillic': 'Ѯ', '/Ksmall': '\uf76b',
- '/Ksquare': 'ἓA', '/Ksquareblack': '\u1f17A', '/Kstroke': 'Ꝁ',
- '/Kstrokediagonalstroke': 'Ꝅ', '/Kturned': 'Ʞ', '/L': 'L', '/LJ': 'LJ',
- '/LL': '\uf6bf', '/LLwelsh': 'Ỻ', '/LTDfullwidth': '㋏', '/Lacute': 'Ĺ',
- '/Lambda': 'Λ', '/Lbar': 'Ƚ', '/Lbelt': 'Ɬ', '/Lbroken': 'Ꝇ', '/Lcaron':
- 'Ľ', '/Lcedilla': 'Ļ', '/Lcircle': 'Ⓛ', '/Lcircleblack': 'ἕB',
- '/Lcircumflexbelow': 'Ḽ', '/Lcommaaccent': 'Ļ', '/Ldblbar': 'Ⱡ',
- '/Ldot': 'Ŀ', '/Ldotaccent': 'Ŀ', '/Ldotbelow': 'Ḷ', '/Ldotbelowmacron':
- 'Ḹ', '/Lhacyr': 'Ԕ', '/Liwnarmenian': 'Լ', '/Lj': 'Lj', '/Ljecyr': 'Љ',
- '/Ljecyrillic': 'Љ', '/Ljekomicyr': 'Ԉ', '/Llinebelow': 'Ḻ',
- '/Lmacrondot': 'Ḹ', '/Lmiddletilde': 'Ɫ', '/Lmonospace': 'L',
- '/Lparens': 'ἑB', '/Lreversedsans': '⅃', '/Lscript': 'ℒ', '/Lslash':
- 'Ł', '/Lslashsmall': '\uf6f9', '/Lsmall': '\uf76c', '/Lsquare': 'ἓB',
- '/Lsquareblack': '\u1f17B', '/Lstroke': 'Ꝉ', '/Lturned': 'Ꞁ',
- '/Lturnedsans': '⅂', '/M': 'M', '/MBsquare': '㎆', '/MVsquare': 'ἔB',
- '/Macron': '\uf6d0', '/Macronsmall': '\uf7af', '/Macute': 'Ḿ',
- '/Mcircle': 'Ⓜ', '/Mcircleblack': 'ἕC', '/Mdot': 'Ṁ', '/Mdotaccent':
- 'Ṁ', '/Mdotbelow': 'Ṃ', '/Menarmenian': 'Մ', '/Mhook': 'Ɱ',
- '/Mmonospace': 'M', '/Mohammad': 'ﷴ', '/Mparens': 'ἑC', '/Mscript': 'ℳ',
- '/Msmall': '\uf76d', '/Msquare': 'ἓC', '/Msquareblack': '\u1f17C',
- '/Mturned': 'Ɯ', '/Mturnedsmall': 'ꟺ', '/Mu': 'Μ', '/N': 'N', '/NJ':
- 'NJ', '/Nacute': 'Ń', '/Ncaron': 'Ň', '/Ncedilla': 'Ņ', '/Ncircle': 'Ⓝ',
- '/Ncircleblack': 'ἕD', '/Ncircumflexbelow': 'Ṋ', '/Ncommaaccent': 'Ņ',
- '/Ndblstruck': 'ℕ', '/Ndescender': 'Ꞑ', '/Ndot': 'Ṅ', '/Ndotaccent':
- 'Ṅ', '/Ndotbelow': 'Ṇ', '/Ngrave': 'Ǹ', '/Nhookleft': 'Ɲ', '/Nineroman':
- 'Ⅸ', '/Nj': 'Nj', '/Njecyr': 'Њ', '/Njecyrillic': 'Њ', '/Njekomicyr':
- 'Ԋ', '/Nlinebelow': 'Ṉ', '/Nlongrightleg': 'Ƞ', '/Nmonospace': 'N',
- '/Nobliquestroke': 'Ꞥ', '/Nowarmenian': 'Ն', '/Nparens': 'ἑD',
- '/Nsmall': '\uf76e', '/Nsquare': 'ἓD', '/Nsquareblack': '\u1f17D',
- '/Ntilde': 'Ñ', '/Ntildesmall': '\uf7f1', '/Nu': 'Ν', '/O': 'O', '/OE':
- 'Œ', '/OEsmall': '\uf6fa', '/OO': 'Ꝏ', '/Oacute': 'Ó', '/Oacutesmall':
- '\uf7f3', '/Obar': 'Ɵ', '/Obarcyr': 'Ө', '/Obardieresiscyr': 'Ӫ',
- '/Obarredcyrillic': 'Ө', '/Obarreddieresiscyrillic': 'Ӫ', '/Obreve':
- 'Ŏ', '/Ocaron': 'Ǒ', '/Ocenteredtilde': 'Ɵ', '/Ocircle': 'Ⓞ',
- '/Ocircleblack': 'ἕE', '/Ocircumflex': 'Ô', '/Ocircumflexacute': 'Ố',
- '/Ocircumflexdotbelow': 'Ộ', '/Ocircumflexgrave': 'Ồ',
- '/Ocircumflexhoi': 'Ổ', '/Ocircumflexhookabove': 'Ổ',
- '/Ocircumflexsmall': '\uf7f4', '/Ocircumflextilde': 'Ỗ', '/Ocyr': 'О',
- '/Ocyrillic': 'О', '/Odblacute': 'Ő', '/Odblgrave': 'Ȍ', '/Odieresis':
- 'Ö', '/Odieresiscyr': 'Ӧ', '/Odieresiscyrillic': 'Ӧ',
- '/Odieresismacron': 'Ȫ', '/Odieresissmall': '\uf7f6', '/Odot': 'Ȯ',
- '/Odotbelow': 'Ọ', '/Odotmacron': 'Ȱ', '/Ogoneksmall': '\uf6fb',
- '/Ograve': 'Ò', '/Ogravedbl': 'Ȍ', '/Ogravesmall': '\uf7f2',
- '/Oharmenian': 'Օ', '/Ohm': 'Ω', '/Ohoi': 'Ỏ', '/Ohookabove': 'Ỏ',
- '/Ohorn': 'Ơ', '/Ohornacute': 'Ớ', '/Ohorndotbelow': 'Ợ', '/Ohorngrave':
- 'Ờ', '/Ohornhoi': 'Ở', '/Ohornhookabove': 'Ở', '/Ohorntilde': 'Ỡ',
- '/Ohungarumlaut': 'Ő', '/Oi': 'Ƣ', '/Oinvertedbreve': 'Ȏ', '/Oloop':
- 'Ꝍ', '/Omacron': 'Ō', '/Omacronacute': 'Ṓ', '/Omacrongrave': 'Ṑ',
- '/Omega': 'Ω', '/Omegaacute': 'Ώ', '/Omegaasper': 'Ὡ',
- '/Omegaasperacute': 'Ὥ', '/Omegaasperacuteiotasub': 'ᾭ',
- '/Omegaaspergrave': 'Ὣ', '/Omegaaspergraveiotasub': 'ᾫ',
- '/Omegaasperiotasub': 'ᾩ', '/Omegaaspertilde': 'Ὧ',
- '/Omegaaspertildeiotasub': 'ᾯ', '/Omegacyr': 'Ѡ', '/Omegacyrillic': 'Ѡ',
- '/Omegagrave': 'Ὼ', '/Omegagreek': 'Ω', '/Omegaiotasub': 'ῼ',
- '/Omegalenis': 'Ὠ', '/Omegalenisacute': 'Ὤ', '/Omegalenisacuteiotasub':
- 'ᾬ', '/Omegalenisgrave': 'Ὢ', '/Omegalenisgraveiotasub': 'ᾪ',
- '/Omegalenisiotasub': 'ᾨ', '/Omegalenistilde': 'Ὦ',
- '/Omegalenistildeiotasub': 'ᾮ', '/Omegaroundcyr': 'Ѻ',
- '/Omegaroundcyrillic': 'Ѻ', '/Omegatitlocyr': 'Ѽ',
- '/Omegatitlocyrillic': 'Ѽ', '/Omegatonos': 'Ώ', '/Omicron': 'Ο',
- '/Omicronacute': 'Ό', '/Omicronasper': 'Ὁ', '/Omicronasperacute': 'Ὅ',
- '/Omicronaspergrave': 'Ὃ', '/Omicrongrave': 'Ὸ', '/Omicronlenis': 'Ὀ',
- '/Omicronlenisacute': 'Ὄ', '/Omicronlenisgrave': 'Ὂ', '/Omicrontonos':
- 'Ό', '/Omonospace': 'O', '/Oneroman': 'Ⅰ', '/Oogonek': 'Ǫ',
- '/Oogonekmacron': 'Ǭ', '/Oopen': 'Ɔ', '/Oparens': 'ἑE', '/Oslash': 'Ø',
- '/Oslashacute': 'Ǿ', '/Oslashsmall': '\uf7f8', '/Osmall': '\uf76f',
- '/Osquare': 'ἓE', '/Osquareblack': '\u1f17E', '/Ostroke': 'Ꝋ',
- '/Ostrokeacute': 'Ǿ', '/Otcyr': 'Ѿ', '/Otcyrillic': 'Ѿ', '/Otilde': 'Õ',
- '/Otildeacute': 'Ṍ', '/Otildedieresis': 'Ṏ', '/Otildemacron': 'Ȭ',
- '/Otildesmall': '\uf7f5', '/Ou': 'Ȣ', '/P': 'P', '/PAsquareblack': 'ἘC',
- '/PPVsquare': 'ἔE', '/Pacute': 'Ṕ', '/Palochkacyr': 'Ӏ', '/Pcircle':
- 'Ⓟ', '/Pcircleblack': 'ἕF', '/Pcrosssquareblack': 'ἘA', '/Pdblstruck':
- 'ℙ', '/Pdot': 'Ṗ', '/Pdotaccent': 'Ṗ', '/Pecyr': 'П', '/Pecyrillic':
- 'П', '/Peharmenian': 'Պ', '/Pehookcyr': 'Ҧ', '/Pemiddlehookcyrillic':
- 'Ҧ', '/Petailcyr': 'Ԥ', '/Pflourish': 'Ꝓ', '/Phi': 'Φ', '/Phook': 'Ƥ',
- '/Pi': 'Π', '/Pidblstruck': 'ℿ', '/Piwrarmenian': 'Փ', '/Pmonospace':
- 'P', '/Pparens': 'ἑF', '/Psi': 'Ψ', '/Psicyr': 'Ѱ', '/Psicyrillic': 'Ѱ',
- '/Psmall': '\uf770', '/Psquare': 'ἓF', '/Psquareblack': '\u1f17F',
- '/Pstroke': 'Ᵽ', '/Pstrokedescender': 'Ꝑ', '/Ptail': 'Ꝕ', '/Q': 'Q',
- '/Qacyr': 'Ԛ', '/QalaUsedAsKoranicStopSign': 'ﷱ', '/Qcircle': 'Ⓠ',
- '/Qcircleblack': '\u1f160', '/Qdblstruck': 'ℚ', '/Qdiagonalstroke': 'Ꝙ',
- '/Qmonospace': 'Q', '/Qparens': 'ἒ0', '/Qrotated': '℺', '/Qsmall':
- '\uf771', '/Qsmallhooktail': 'Ɋ', '/Qsquare': 'ἔ0', '/Qsquareblack':
- 'Ἐ0', '/Qstrokedescender': 'Ꝗ', '/R': 'R', '/Raarmenian': 'Ռ',
- '/Racute': 'Ŕ', '/Rasoul': 'ﷶ', '/Rcaron': 'Ř', '/Rcedilla': 'Ŗ',
- '/Rcircle': 'Ⓡ', '/Rcircleblack': '\u1f161', '/Rcommaaccent': 'Ŗ',
- '/Rdblgrave': 'Ȑ', '/Rdblstruck': 'ℝ', '/Rdot': 'Ṙ', '/Rdotaccent': 'Ṙ',
- '/Rdotbelow': 'Ṛ', '/Rdotbelowmacron': 'Ṝ', '/Reharmenian': 'Ր',
- '/Reverseddottedsigmalunatesymbol': 'Ͽ', '/Reversedzecyr': 'Ԑ',
- '/Rfraktur': 'ℜ', '/Rgravedbl': 'Ȑ', '/Rhacyr': 'Ԗ', '/Rho': 'Ρ',
- '/Rhoasper': 'Ῥ', '/Ringsmall': '\uf6fc', '/Rinsular': 'Ꞃ',
- '/Rinvertedbreve': 'Ȓ', '/Rinvertedsmall': 'ʁ', '/Ritaliccircle': 'ἒC',
- '/Rlinebelow': 'Ṟ', '/Rmacrondot': 'Ṝ', '/Rmonospace': 'R',
- '/Robliquestroke': 'Ꞧ', '/Rparens': 'ἒ1', '/Rrotunda': 'Ꝛ', '/Rscript':
- 'ℛ', '/Rsmall': '\uf772', '/Rsmallinverted': 'ʁ',
- '/Rsmallinvertedsuperior': 'ʶ', '/Rsquare': 'ἔ1', '/Rsquareblack': 'Ἐ1',
- '/Rstroke': 'Ɍ', '/Rsupinvertedmod': 'ʶ', '/Rtail': 'Ɽ',
- '/RubElHizbstart': '۞', '/Rumrotunda': 'Ꝝ', '/Rumsmall': 'ꝶ', '/S': 'S',
- '/SAsquareblack': 'ἘD', '/SDsquare': 'ἔC', '/SF010000': '┌',
- '/SF020000': '└', '/SF030000': '┐', '/SF040000': '┘', '/SF050000': '┼',
- '/SF060000': '┬', '/SF070000': '┴', '/SF080000': '├', '/SF090000': '┤',
- '/SF100000': '─', '/SF110000': '│', '/SF190000': '╡', '/SF200000': '╢',
- '/SF210000': '╖', '/SF220000': '╕', '/SF230000': '╣', '/SF240000': '║',
- '/SF250000': '╗', '/SF260000': '╝', '/SF270000': '╜', '/SF280000': '╛',
- '/SF360000': '╞', '/SF370000': '╟', '/SF380000': '╚', '/SF390000': '╔',
- '/SF400000': '╩', '/SF410000': '╦', '/SF420000': '╠', '/SF430000': '═',
- '/SF440000': '╬', '/SF450000': '╧', '/SF460000': '╨', '/SF470000': '╤',
- '/SF480000': '╥', '/SF490000': '╙', '/SF500000': '╘', '/SF510000': '╒',
- '/SF520000': '╓', '/SF530000': '╫', '/SF540000': '╪', '/SSsquare': 'ἔD',
- '/Sacute': 'Ś', '/Sacutedotaccent': 'Ṥ', '/Safha': '\u0603', '/Sajdah':
- '۩', '/Salam': 'ﷵ', '/Salla': 'ﷹ', '/SallaUsedAsKoranicStopSign': 'ﷰ',
- '/SallallahouAlayheWasallam': 'ﷺ', '/Saltillo': 'Ꞌ', '/Sampi': 'Ϡ',
- '/Sampiarchaic': 'Ͳ', '/Sampigreek': 'Ϡ', '/San': 'Ϻ', '/Sanah':
- '\u0601', '/Scaron': 'Š', '/Scarondot': 'Ṧ', '/Scarondotaccent': 'Ṧ',
- '/Scaronsmall': '\uf6fd', '/Scedilla': 'Ş', '/Schwa': 'Ə', '/Schwacyr':
- 'Ә', '/Schwacyrillic': 'Ә', '/Schwadieresiscyr': 'Ӛ',
- '/Schwadieresiscyrillic': 'Ӛ', '/Scircle': 'Ⓢ', '/Scircleblack':
- '\u1f162', '/Scircumflex': 'Ŝ', '/Scommaaccent': 'Ș', '/Scriptg': 'Ɡ',
- '/Sdot': 'Ṡ', '/Sdotaccent': 'Ṡ', '/Sdotbelow': 'Ṣ',
- '/Sdotbelowdotabove': 'Ṩ', '/Sdotbelowdotaccent': 'Ṩ', '/Seharmenian':
- 'Ս', '/Semisoftcyr': 'Ҍ', '/Sevenroman': 'Ⅶ', '/Shaarmenian': 'Շ',
- '/Shacyr': 'Ш', '/Shacyrillic': 'Ш', '/Shchacyr': 'Щ', '/Shchacyrillic':
- 'Щ', '/Sheicoptic': 'Ϣ', '/SheneGerishin:hb': '֞', '/Shhacyr': 'Һ',
- '/Shhacyrillic': 'Һ', '/Shhatailcyr': 'Ԧ', '/Shimacoptic': 'Ϭ', '/Sho':
- 'Ϸ', '/Sigma': 'Σ', '/Sigmalunatesymbol': 'Ϲ',
- '/Sigmalunatesymboldotted': 'Ͼ', '/Sigmareversedlunatesymbol': 'Ͻ',
- '/Sinsular': 'Ꞅ', '/Sixroman': 'Ⅵ', '/Sjekomicyr': 'Ԍ', '/Smonospace':
- 'S', '/Sobliquestroke': 'Ꞩ', '/Softcyr': 'Ь', '/Softsigncyrillic': 'Ь',
- '/Sparens': 'ἒ2', '/Sshell': 'ἒA', '/Ssmall': '\uf773', '/Ssquare':
- 'ἔ2', '/Ssquareblack': 'Ἐ2', '/Sswashtail': 'Ȿ', '/Stigma': 'Ϛ',
- '/Stigmagreek': 'Ϛ', '/T': 'T', '/Tau': 'Τ', '/Tbar': 'Ŧ', '/Tcaron':
- 'Ť', '/Tcedilla': 'Ţ', '/Tcircle': 'Ⓣ', '/Tcircleblack': '\u1f163',
- '/Tcircumflexbelow': 'Ṱ', '/Tcommaaccent': 'Ţ', '/Tdot': 'Ṫ',
- '/Tdotaccent': 'Ṫ', '/Tdotbelow': 'Ṭ', '/Tecyr': 'Т', '/Tecyrillic':
- 'Т', '/Tedescendercyrillic': 'Ҭ', '/Tenroman': 'Ⅹ', '/Tetailcyr': 'Ҭ',
- '/Tetsecyr': 'Ҵ', '/Tetsecyrillic': 'Ҵ', '/Theta': 'Θ', '/Thetasymbol':
- 'ϴ', '/Thook': 'Ƭ', '/Thorn': 'Þ', '/Thornsmall': '\uf7fe',
- '/Thornstroke': 'Ꝥ', '/Thornstrokedescender': 'Ꝧ', '/Threeroman': 'Ⅲ',
- '/Tildesmall': '\uf6fe', '/Tinsular': 'Ꞇ', '/Tiwnarmenian': 'Տ',
- '/Tjekomicyr': 'Ԏ', '/Tlinebelow': 'Ṯ', '/Tmonospace': 'T',
- '/Toarmenian': 'Թ', '/Tonefive': 'Ƽ', '/Tonesix': 'Ƅ', '/Tonetwo': 'Ƨ',
- '/Tparens': 'ἒ3', '/Tresillo': 'Ꜫ', '/Tretroflexhook': 'Ʈ', '/Tsecyr':
- 'Ц', '/Tsecyrillic': 'Ц', '/Tshecyr': 'Ћ', '/Tshecyrillic': 'Ћ',
- '/Tsmall': '\uf774', '/Tsquare': 'ἔ3', '/Tsquareblack': 'Ἐ3',
- '/Tturned': 'Ʇ', '/Twelveroman': 'Ⅻ', '/Twithdiagonalstroke': 'Ⱦ',
- '/Tworoman': 'Ⅱ', '/Tz': 'Ꜩ', '/U': 'U', '/Uacute': 'Ú',
- '/Uacutedblcyr': 'Ӳ', '/Uacutesmall': '\uf7fa', '/Ubar': 'Ʉ', '/Ubreve':
- 'Ŭ', '/Ucaron': 'Ǔ', '/Ucircle': 'Ⓤ', '/Ucircleblack': '\u1f164',
- '/Ucircumflex': 'Û', '/Ucircumflexbelow': 'Ṷ', '/Ucircumflexsmall':
- '\uf7fb', '/Ucyr': 'У', '/Ucyrillic': 'У', '/Udblacute': 'Ű',
- '/Udblgrave': 'Ȕ', '/Udieresis': 'Ü', '/Udieresisacute': 'Ǘ',
- '/Udieresisbelow': 'Ṳ', '/Udieresiscaron': 'Ǚ', '/Udieresiscyr': 'Ӱ',
- '/Udieresiscyrillic': 'Ӱ', '/Udieresisgrave': 'Ǜ', '/Udieresismacron':
- 'Ǖ', '/Udieresissmall': '\uf7fc', '/Udotbelow': 'Ụ', '/Ugrave': 'Ù',
- '/Ugravedbl': 'Ȕ', '/Ugravesmall': '\uf7f9', '/Uhoi': 'Ủ',
- '/Uhookabove': 'Ủ', '/Uhorn': 'Ư', '/Uhornacute': 'Ứ', '/Uhorndotbelow':
- 'Ự', '/Uhorngrave': 'Ừ', '/Uhornhoi': 'Ử', '/Uhornhookabove': 'Ử',
- '/Uhorntilde': 'Ữ', '/Uhungarumlaut': 'Ű', '/Uhungarumlautcyrillic':
- 'Ӳ', '/Uinvertedbreve': 'Ȗ', '/Ukcyr': 'Ѹ', '/Ukcyrillic': 'Ѹ',
- '/Umacron': 'Ū', '/Umacroncyr': 'Ӯ', '/Umacroncyrillic': 'Ӯ',
- '/Umacrondieresis': 'Ṻ', '/Umonospace': 'U', '/Uogonek': 'Ų',
- '/Uparens': 'ἒ4', '/Upsilon': 'Υ', '/Upsilon1': 'ϒ', '/Upsilonacute':
- 'Ύ', '/Upsilonacutehooksymbol': 'ϓ', '/Upsilonacutehooksymbolgreek':
- 'ϓ', '/Upsilonadieresishooksymbol': 'ϔ', '/Upsilonafrican': 'Ʊ',
- '/Upsilonasper': 'Ὑ', '/Upsilonasperacute': 'Ὕ', '/Upsilonaspergrave':
- 'Ὓ', '/Upsilonaspertilde': 'Ὗ', '/Upsilonbreve': 'Ῠ',
- '/Upsilondieresis': 'Ϋ', '/Upsilondieresishooksymbolgreek': 'ϔ',
- '/Upsilongrave': 'Ὺ', '/Upsilonhooksymbol': 'ϒ', '/Upsilontonos': 'Ύ',
- '/Upsilonwithmacron': 'Ῡ', '/Uring': 'Ů', '/Ushortcyr': 'Ў',
- '/Ushortcyrillic': 'Ў', '/Usmall': '\uf775', '/Usquare': 'ἔ4',
- '/Usquareblack': 'Ἐ4', '/Ustraightcyr': 'Ү', '/Ustraightcyrillic': 'Ү',
- '/Ustraightstrokecyr': 'Ұ', '/Ustraightstrokecyrillic': 'Ұ', '/Utilde':
- 'Ũ', '/Utildeacute': 'Ṹ', '/Utildebelow': 'Ṵ', '/V': 'V', '/Vcircle':
- 'Ⓥ', '/Vcircleblack': '\u1f165', '/Vdiagonalstroke': 'Ꝟ', '/Vdotbelow':
- 'Ṿ', '/Vecyr': 'В', '/Vecyrillic': 'В', '/Vend': 'Ꝩ', '/Vewarmenian':
- 'Վ', '/Vhook': 'Ʋ', '/Visigothicz': 'Ꝣ', '/Vmod': 'ⱽ', '/Vmonospace':
- 'V', '/Voarmenian': 'Ո', '/Volapukae': 'Ꞛ', '/Volapukoe': 'Ꞝ',
- '/Volapukue': 'Ꞟ', '/Vparens': 'ἒ5', '/Vsmall': '\uf776', '/Vsquare':
- 'ἔ5', '/Vsquareblack': 'Ἐ5', '/Vtilde': 'Ṽ', '/Vturned': 'Ʌ', '/Vwelsh':
- 'Ỽ', '/Vy': 'Ꝡ', '/W': 'W', '/WZcircle': 'ἒE', '/Wacute': 'Ẃ',
- '/Wasallam': 'ﷸ', '/Wcircle': 'Ⓦ', '/Wcircleblack': '\u1f166',
- '/Wcircumflex': 'Ŵ', '/Wdieresis': 'Ẅ', '/Wdot': 'Ẇ', '/Wdotaccent':
- 'Ẇ', '/Wdotbelow': 'Ẉ', '/Wecyr': 'Ԝ', '/Wgrave': 'Ẁ', '/Whook': 'Ⱳ',
- '/Wmonospace': 'W', '/Wparens': 'ἒ6', '/Wsmall': '\uf777', '/Wsquare':
- 'ἔ6', '/Wsquareblack': 'Ἐ6', '/Wynn': 'Ƿ', '/X': 'X', '/Xatailcyr': 'Ҳ',
- '/Xcircle': 'Ⓧ', '/Xcircleblack': '\u1f167', '/Xdieresis': 'Ẍ', '/Xdot':
- 'Ẋ', '/Xdotaccent': 'Ẋ', '/Xeharmenian': 'Խ', '/Xi': 'Ξ', '/Xmonospace':
- 'X', '/Xparens': 'ἒ7', '/Xsmall': '\uf778', '/Xsquare': 'ἔ7',
- '/Xsquareblack': 'Ἐ7', '/Y': 'Y', '/Yacute': 'Ý', '/Yacutesmall':
- '\uf7fd', '/Yacyr': 'Я', '/Yaecyr': 'Ԙ', '/Yatcyr': 'Ѣ', '/Yatcyrillic':
- 'Ѣ', '/Ycircle': 'Ⓨ', '/Ycircleblack': '\u1f168', '/Ycircumflex': 'Ŷ',
- '/Ydieresis': 'Ÿ', '/Ydieresissmall': '\uf7ff', '/Ydot': 'Ẏ',
- '/Ydotaccent': 'Ẏ', '/Ydotbelow': 'Ỵ', '/Yericyrillic': 'Ы',
- '/Yerudieresiscyrillic': 'Ӹ', '/Ygrave': 'Ỳ', '/Yhoi': 'Ỷ', '/Yhook':
- 'Ƴ', '/Yhookabove': 'Ỷ', '/Yiarmenian': 'Յ', '/Yicyrillic': 'Ї',
- '/Yiwnarmenian': 'Ւ', '/Ylongcyr': 'Ы', '/Ylongdieresiscyr': 'Ӹ',
- '/Yloop': 'Ỿ', '/Ymacron': 'Ȳ', '/Ymonospace': 'Y', '/Yogh': 'Ȝ',
- '/Yot': 'Ϳ', '/Yparens': 'ἒ8', '/Ysmall': '\uf779', '/Ysquare': 'ἔ8',
- '/Ysquareblack': 'Ἐ8', '/Ystroke': 'Ɏ', '/Ytilde': 'Ỹ', '/Yturnedsans':
- '⅄', '/Yucyr': 'Ю', '/Yukrcyr': 'Ї', '/Yusbigcyr': 'Ѫ',
- '/Yusbigcyrillic': 'Ѫ', '/Yusbigiotifiedcyr': 'Ѭ',
- '/Yusbigiotifiedcyrillic': 'Ѭ', '/Yuslittlecyr': 'Ѧ',
- '/Yuslittlecyrillic': 'Ѧ', '/Yuslittleiotifiedcyr': 'Ѩ',
- '/Yuslittleiotifiedcyrillic': 'Ѩ', '/Z': 'Z', '/Zaarmenian': 'Զ',
- '/Zacute': 'Ź', '/Zcaron': 'Ž', '/Zcaronsmall': '\uf6ff', '/Zcircle':
- 'Ⓩ', '/Zcircleblack': '\u1f169', '/Zcircumflex': 'Ẑ', '/Zdblstruck':
- 'ℤ', '/Zdescender': 'Ⱬ', '/Zdot': 'Ż', '/Zdotaccent': 'Ż', '/Zdotbelow':
- 'Ẓ', '/Zecyr': 'З', '/Zecyrillic': 'З', '/Zedescendercyrillic': 'Ҙ',
- '/Zedieresiscyr': 'Ӟ', '/Zedieresiscyrillic': 'Ӟ', '/Zeta': 'Ζ',
- '/Zetailcyr': 'Ҙ', '/Zfraktur': 'ℨ', '/Zhearmenian': 'Ժ',
- '/Zhebrevecyr': 'Ӂ', '/Zhebrevecyrillic': 'Ӂ', '/Zhecyr': 'Ж',
- '/Zhecyrillic': 'Ж', '/Zhedescendercyrillic': 'Җ', '/Zhedieresiscyr':
- 'Ӝ', '/Zhedieresiscyrillic': 'Ӝ', '/Zhetailcyr': 'Җ', '/Zhook': 'Ȥ',
- '/Zjekomicyr': 'Ԅ', '/Zlinebelow': 'Ẕ', '/Zmonospace': 'Z', '/Zparens':
- 'ἒ9', '/Zsmall': '\uf77a', '/Zsquare': 'ἔ9', '/Zsquareblack': 'Ἐ9',
- '/Zstroke': 'Ƶ', '/Zswashtail': 'Ɀ', '/a': 'a', '/a.inferior': 'ₐ',
- '/aHonRAA': 'ؓ', '/aa': 'ꜳ', '/aabengali': 'আ', '/aacute': 'á',
- '/aadeva': 'आ', '/aagujarati': 'આ', '/aagurmukhi': 'ਆ',
- '/aamatragurmukhi': 'ਾ', '/aarusquare': '㌃', '/aavowelsignbengali': 'া',
- '/aavowelsigndeva': 'ा', '/aavowelsigngujarati': 'ા',
- '/abbreviationmarkarmenian': '՟', '/abbreviationsigndeva': '॰',
- '/abengali': 'অ', '/abopomofo': 'ㄚ', '/abreve': 'ă', '/abreveacute':
- 'ắ', '/abrevecyr': 'ӑ', '/abrevecyrillic': 'ӑ', '/abrevedotbelow': 'ặ',
- '/abrevegrave': 'ằ', '/abrevehoi': 'ẳ', '/abrevehookabove': 'ẳ',
- '/abrevetilde': 'ẵ', '/absquareblack': 'ἘE', '/acaron': 'ǎ',
- '/accountof': '℀', '/accurrent': '⏦', '/acircle': 'ⓐ',
- '/acirclekatakana': '㋐', '/acircumflex': 'â', '/acircumflexacute': 'ấ',
- '/acircumflexdotbelow': 'ậ', '/acircumflexgrave': 'ầ',
- '/acircumflexhoi': 'ẩ', '/acircumflexhookabove': 'ẩ',
- '/acircumflextilde': 'ẫ', '/activatearabicformshaping': '\u206d',
- '/activatesymmetricswapping': '\u206b', '/acute': '´', '/acutebelowcmb':
- '̗', '/acutecmb': '́', '/acutecomb': '́', '/acutedblmiddlemod': '˶',
- '/acutedeva': '॔', '/acutelowmod': 'ˏ', '/acutemod': 'ˊ',
- '/acutetonecmb': '́', '/acyr': 'а', '/acyrillic': 'а', '/adblgrave':
- 'ȁ', '/addakgurmukhi': 'ੱ', '/addressedsubject': '℁', '/adegadegpada':
- '꧋', '/adegpada': '꧊', '/adeva': 'अ', '/adieresis': 'ä',
- '/adieresiscyr': 'ӓ', '/adieresiscyrillic': 'ӓ', '/adieresismacron':
- 'ǟ', '/adishakti': '☬', '/admissionTickets': 'ἹF', '/adot': 'ȧ',
- '/adotbelow': 'ạ', '/adotmacron': 'ǡ', '/ae': 'æ', '/aeacute': 'ǽ',
- '/aekorean': 'ㅐ', '/aemacron': 'ǣ', '/aerialTramway': 'Ὢ1', '/afghani':
- '؋', '/afii00208': '―', '/afii08941': '₤', '/afii10017': 'А',
- '/afii10018': 'Б', '/afii10019': 'В', '/afii10020': 'Г', '/afii10021':
- 'Д', '/afii10022': 'Е', '/afii10023': 'Ё', '/afii10024': 'Ж',
- '/afii10025': 'З', '/afii10026': 'И', '/afii10027': 'Й', '/afii10028':
- 'К', '/afii10029': 'Л', '/afii10030': 'М', '/afii10031': 'Н',
- '/afii10032': 'О', '/afii10033': 'П', '/afii10034': 'Р', '/afii10035':
- 'С', '/afii10036': 'Т', '/afii10037': 'У', '/afii10038': 'Ф',
- '/afii10039': 'Х', '/afii10040': 'Ц', '/afii10041': 'Ч', '/afii10042':
- 'Ш', '/afii10043': 'Щ', '/afii10044': 'Ъ', '/afii10045': 'Ы',
- '/afii10046': 'Ь', '/afii10047': 'Э', '/afii10048': 'Ю', '/afii10049':
- 'Я', '/afii10050': 'Ґ', '/afii10051': 'Ђ', '/afii10052': 'Ѓ',
- '/afii10053': 'Є', '/afii10054': 'Ѕ', '/afii10055': 'І', '/afii10056':
- 'Ї', '/afii10057': 'Ј', '/afii10058': 'Љ', '/afii10059': 'Њ',
- '/afii10060': 'Ћ', '/afii10061': 'Ќ', '/afii10062': 'Ў', '/afii10063':
- '\uf6c4', '/afii10064': '\uf6c5', '/afii10065': 'а', '/afii10066': 'б',
- '/afii10067': 'в', '/afii10068': 'г', '/afii10069': 'д', '/afii10070':
- 'е', '/afii10071': 'ё', '/afii10072': 'ж', '/afii10073': 'з',
- '/afii10074': 'и', '/afii10075': 'й', '/afii10076': 'к', '/afii10077':
- 'л', '/afii10078': 'м', '/afii10079': 'н', '/afii10080': 'о',
- '/afii10081': 'п', '/afii10082': 'р', '/afii10083': 'с', '/afii10084':
- 'т', '/afii10085': 'у', '/afii10086': 'ф', '/afii10087': 'х',
- '/afii10088': 'ц', '/afii10089': 'ч', '/afii10090': 'ш', '/afii10091':
- 'щ', '/afii10092': 'ъ', '/afii10093': 'ы', '/afii10094': 'ь',
- '/afii10095': 'э', '/afii10096': 'ю', '/afii10097': 'я', '/afii10098':
- 'ґ', '/afii10099': 'ђ', '/afii10100': 'ѓ', '/afii10101': 'є',
- '/afii10102': 'ѕ', '/afii10103': 'і', '/afii10104': 'ї', '/afii10105':
- 'ј', '/afii10106': 'љ', '/afii10107': 'њ', '/afii10108': 'ћ',
- '/afii10109': 'ќ', '/afii10110': 'ў', '/afii10145': 'Џ', '/afii10146':
- 'Ѣ', '/afii10147': 'Ѳ', '/afii10148': 'Ѵ', '/afii10192': '\uf6c6',
- '/afii10193': 'џ', '/afii10194': 'ѣ', '/afii10195': 'ѳ', '/afii10196':
- 'ѵ', '/afii10831': '\uf6c7', '/afii10832': '\uf6c8', '/afii10846': 'ә',
- '/afii299': '\u200e', '/afii300': '\u200f', '/afii301': '\u200d',
- '/afii57381': '٪', '/afii57388': '،', '/afii57392': '٠', '/afii57393':
- '١', '/afii57394': '٢', '/afii57395': '٣', '/afii57396': '٤',
- '/afii57397': '٥', '/afii57398': '٦', '/afii57399': '٧', '/afii57400':
- '٨', '/afii57401': '٩', '/afii57403': '؛', '/afii57407': '؟',
- '/afii57409': 'ء', '/afii57410': 'آ', '/afii57411': 'أ', '/afii57412':
- 'ؤ', '/afii57413': 'إ', '/afii57414': 'ئ', '/afii57415': 'ا',
- '/afii57416': 'ب', '/afii57417': 'ة', '/afii57418': 'ت', '/afii57419':
- 'ث', '/afii57420': 'ج', '/afii57421': 'ح', '/afii57422': 'خ',
- '/afii57423': 'د', '/afii57424': 'ذ', '/afii57425': 'ر', '/afii57426':
- 'ز', '/afii57427': 'س', '/afii57428': 'ش', '/afii57429': 'ص',
- '/afii57430': 'ض', '/afii57431': 'ط', '/afii57432': 'ظ', '/afii57433':
- 'ع', '/afii57434': 'غ', '/afii57440': 'ـ', '/afii57441': 'ف',
- '/afii57442': 'ق', '/afii57443': 'ك', '/afii57444': 'ل', '/afii57445':
- 'م', '/afii57446': 'ن', '/afii57448': 'و', '/afii57449': 'ى',
- '/afii57450': 'ي', '/afii57451': 'ً', '/afii57452': 'ٌ', '/afii57453':
- 'ٍ', '/afii57454': 'َ', '/afii57455': 'ُ', '/afii57456': 'ِ',
- '/afii57457': 'ّ', '/afii57458': 'ْ', '/afii57470': 'ه', '/afii57505':
- 'ڤ', '/afii57506': 'پ', '/afii57507': 'چ', '/afii57508': 'ژ',
- '/afii57509': 'گ', '/afii57511': 'ٹ', '/afii57512': 'ڈ', '/afii57513':
- 'ڑ', '/afii57514': 'ں', '/afii57519': 'ے', '/afii57534': 'ە',
- '/afii57636': '₪', '/afii57645': '־', '/afii57658': '׃', '/afii57664':
- 'א', '/afii57665': 'ב', '/afii57666': 'ג', '/afii57667': 'ד',
- '/afii57668': 'ה', '/afii57669': 'ו', '/afii57670': 'ז', '/afii57671':
- 'ח', '/afii57672': 'ט', '/afii57673': 'י', '/afii57674': 'ך',
- '/afii57675': 'כ', '/afii57676': 'ל', '/afii57677': 'ם', '/afii57678':
- 'מ', '/afii57679': 'ן', '/afii57680': 'נ', '/afii57681': 'ס',
- '/afii57682': 'ע', '/afii57683': 'ף', '/afii57684': 'פ', '/afii57685':
- 'ץ', '/afii57686': 'צ', '/afii57687': 'ק', '/afii57688': 'ר',
- '/afii57689': 'ש', '/afii57690': 'ת', '/afii57694': 'שׁ', '/afii57695':
- 'שׂ', '/afii57700': 'וֹ', '/afii57705': 'ײַ', '/afii57716': 'װ',
- '/afii57717': 'ױ', '/afii57718': 'ײ', '/afii57723': 'וּ', '/afii57793':
- 'ִ', '/afii57794': 'ֵ', '/afii57795': 'ֶ', '/afii57796': 'ֻ',
- '/afii57797': 'ָ', '/afii57798': 'ַ', '/afii57799': 'ְ', '/afii57800':
- 'ֲ', '/afii57801': 'ֱ', '/afii57802': 'ֳ', '/afii57803': 'ׂ',
- '/afii57804': 'ׁ', '/afii57806': 'ֹ', '/afii57807': 'ּ', '/afii57839':
- 'ֽ', '/afii57841': 'ֿ', '/afii57842': '׀', '/afii57929': 'ʼ',
- '/afii61248': '℅', '/afii61289': 'ℓ', '/afii61352': '№', '/afii61573':
- '\u202c', '/afii61574': '\u202d', '/afii61575': '\u202e', '/afii61664':
- '\u200c', '/afii63167': '٭', '/afii64937': 'ʽ', '/agrave': 'à',
- '/agravedbl': 'ȁ', '/agujarati': 'અ', '/agurmukhi': 'ਅ', '/ahiragana':
- 'あ', '/ahoi': 'ả', '/ahookabove': 'ả', '/aibengali': 'ঐ', '/aibopomofo':
- 'ㄞ', '/aideva': 'ऐ', '/aiecyr': 'ӕ', '/aiecyrillic': 'ӕ', '/aigujarati':
- 'ઐ', '/aigurmukhi': 'ਐ', '/aimatragurmukhi': 'ੈ', '/ain.fina': 'ﻊ',
- '/ain.init': 'ﻋ', '/ain.init_alefmaksura.fina': 'ﳷ',
- '/ain.init_jeem.fina': 'ﰩ', '/ain.init_jeem.medi': 'ﲺ',
- '/ain.init_jeem.medi_meem.medi': 'ﷄ', '/ain.init_meem.fina': 'ﰪ',
- '/ain.init_meem.medi': 'ﲻ', '/ain.init_meem.medi_meem.medi': 'ﵷ',
- '/ain.init_yeh.fina': 'ﳸ', '/ain.isol': 'ﻉ', '/ain.medi': 'ﻌ',
- '/ain.medi_alefmaksura.fina': 'ﴓ', '/ain.medi_jeem.medi_meem.fina': 'ﵵ',
- '/ain.medi_meem.medi_alefmaksura.fina': 'ﵸ',
- '/ain.medi_meem.medi_meem.fina': 'ﵶ', '/ain.medi_meem.medi_yeh.fina':
- 'ﶶ', '/ain.medi_yeh.fina': 'ﴔ', '/ainThreeDotsDownAbove': 'ݞ',
- '/ainTwoDotsAbove': 'ݝ', '/ainTwoDotsVerticallyAbove': 'ݟ',
- '/ainarabic': 'ع', '/ainfinalarabic': 'ﻊ', '/aininitialarabic': 'ﻋ',
- '/ainmedialarabic': 'ﻌ', '/ainthreedotsabove': 'ڠ', '/ainvertedbreve':
- 'ȃ', '/airplaneArriving': 'ὮC', '/airplaneDeparture': 'ὮB',
- '/aivowelsignbengali': 'ৈ', '/aivowelsigndeva': 'ै',
- '/aivowelsigngujarati': 'ૈ', '/akatakana': 'ア', '/akatakanahalfwidth':
- 'ア', '/akorean': 'ㅏ', '/aktieselskab': '⅍', '/alarmclock': '⏰', '/alef':
- 'א', '/alef.fina': 'ﺎ', '/alef.init_fathatan.fina': 'ﴽ', '/alef.isol':
- 'ﺍ', '/alef.medi_fathatan.fina': 'ﴼ', '/alef:hb': 'א',
- '/alefDigitThreeAbove': 'ݴ', '/alefDigitTwoAbove': 'ݳ',
- '/alefLamYehabove': 'ؖ', '/alefabove': 'ٰ', '/alefarabic': 'ا',
- '/alefdageshhebrew': 'אּ', '/aleffinalarabic': 'ﺎ', '/alefhamza': 'أ',
- '/alefhamza.fina': 'ﺄ', '/alefhamza.isol': 'ﺃ', '/alefhamzaabovearabic':
- 'أ', '/alefhamzaabovefinalarabic': 'ﺄ', '/alefhamzabelow': 'إ',
- '/alefhamzabelow.fina': 'ﺈ', '/alefhamzabelow.isol': 'ﺇ',
- '/alefhamzabelowarabic': 'إ', '/alefhamzabelowfinalarabic': 'ﺈ',
- '/alefhebrew': 'א', '/alefhighhamza': 'ٵ', '/aleflamedhebrew': 'ﭏ',
- '/alefmadda': 'آ', '/alefmadda.fina': 'ﺂ', '/alefmadda.isol': 'ﺁ',
- '/alefmaddaabovearabic': 'آ', '/alefmaddaabovefinalarabic': 'ﺂ',
- '/alefmaksura': 'ى', '/alefmaksura.fina': 'ﻰ',
- '/alefmaksura.init_superscriptalef.fina': 'ﱝ', '/alefmaksura.isol': 'ﻯ',
- '/alefmaksura.medi_superscriptalef.fina': 'ﲐ', '/alefmaksuraarabic':
- 'ى', '/alefmaksurafinalarabic': 'ﻰ', '/alefmaksurainitialarabic': 'ﻳ',
- '/alefmaksuramedialarabic': 'ﻴ', '/alefpatahhebrew': 'אַ',
- '/alefqamatshebrew': 'אָ', '/alefwasla': 'ٱ', '/alefwasla.fina': 'ﭑ',
- '/alefwasla.isol': 'ﭐ', '/alefwavyhamza': 'ٲ', '/alefwavyhamzabelow':
- 'ٳ', '/alefwide:hb': 'ﬡ', '/alefwithmapiq:hb': 'אּ', '/alefwithpatah:hb':
- 'אַ', '/alefwithqamats:hb': 'אָ', '/alembic': '⚗', '/aleph': 'ℵ',
- '/alienMonster': '\u1f47E', '/allaroundprofile': '⌮', '/allequal': '≌',
- '/allianceideographiccircled': '㊯', '/allianceideographicparen': '㈿',
- '/almostequalorequal': '≊', '/alpha': 'α', '/alphaacute': 'ά',
- '/alphaacuteiotasub': 'ᾴ', '/alphaasper': 'ἁ', '/alphaasperacute': 'ἅ',
- '/alphaasperacuteiotasub': 'ᾅ', '/alphaaspergrave': 'ἃ',
- '/alphaaspergraveiotasub': 'ᾃ', '/alphaasperiotasub': 'ᾁ',
- '/alphaaspertilde': 'ἇ', '/alphaaspertildeiotasub': 'ᾇ', '/alphabreve':
- 'ᾰ', '/alphafunc': '⍺', '/alphagrave': 'ὰ', '/alphagraveiotasub': 'ᾲ',
- '/alphaiotasub': 'ᾳ', '/alphalenis': 'ἀ', '/alphalenisacute': 'ἄ',
- '/alphalenisacuteiotasub': 'ᾄ', '/alphalenisgrave': 'ἂ',
- '/alphalenisgraveiotasub': 'ᾂ', '/alphalenisiotasub': 'ᾀ',
- '/alphalenistilde': 'ἆ', '/alphalenistildeiotasub': 'ᾆ', '/alphatilde':
- 'ᾶ', '/alphatildeiotasub': 'ᾷ', '/alphatonos': 'ά', '/alphaturned': 'ɒ',
- '/alphaunderlinefunc': '⍶', '/alphawithmacron': 'ᾱ',
- '/alternateonewayleftwaytraffic': '⛕', '/alternative': '⎇', '/amacron':
- 'ā', '/ambulance': 'Ὡ1', '/americanFootball': 'Ἴ8', '/amfullwidth': '㏂',
- '/amonospace': 'a', '/amountofcheck': '⑇', '/ampersand': '&',
- '/ampersandSindhi': '۽', '/ampersandmonospace': '&', '/ampersandsmall':
- '\uf726', '/ampersandturned': '⅋', '/amphora': 'ἿA', '/amsquare': '㏂',
- '/anbopomofo': 'ㄢ', '/anchor': '⚓', '/ancoradown': '⸔', '/ancoraup':
- '⸕', '/andappada': '꧃', '/angbopomofo': 'ㄤ', '/anger': 'Ὂ2',
- '/angkhankhuthai': '๚', '/angle': '∠', '/anglearcright': '⊾',
- '/anglebracketleft': '〈', '/anglebracketleftvertical': '︿',
- '/anglebracketright': '〉', '/anglebracketrightvertical': '﹀',
- '/angledottedright': '⸖', '/angleleft': '〈',
- '/anglemarkerdottedsubstitutionright': '⸁',
- '/anglemarkersubstitutionright': '⸀', '/angleright': '〉',
- '/anglezigzagarrowdownright': '⍼', '/angryFace': 'ὢ0', '/angstrom': 'Å',
- '/anguishedFace': 'ὢ7', '/ankh': '☥', '/anoteleia': '·', '/anpeasquare':
- '㌂', '/ant': 'ὁC', '/antennaBars': '\u1f4f6',
- '/anticlockwiseDownwardsAndUpwardsOpenCircleArrows': 'ὐ4',
- '/anudattadeva': '॒', '/anusvarabengali': 'ং', '/anusvaradeva': 'ं',
- '/anusvaragujarati': 'ં', '/ao': 'ꜵ', '/aogonek': 'ą',
- '/aovermfullwidth': '㏟', '/apaatosquare': '㌀', '/aparen': '⒜',
- '/aparenthesized': '⒜', '/apostrophearmenian': '՚', '/apostrophedblmod':
- 'ˮ', '/apostrophemod': 'ʼ', '/apple': '\uf8ff', '/approaches': '≐',
- '/approacheslimit': '≐', '/approxequal': '≈', '/approxequalorimage':
- '≒', '/approximatelybutnotactuallyequal': '≆', '/approximatelyequal':
- '≅', '/approximatelyequalorimage': '≒', '/apriltelegraph': '㋃',
- '/aquarius': '♒', '/ar:ae': 'ە', '/ar:ain': 'ع', '/ar:alef': 'ا',
- '/ar:comma': '،', '/ar:cuberoot': '؆', '/ar:decimalseparator': '٫',
- '/ar:e': 'ې', '/ar:eight': '٨', '/ar:feh': 'ف', '/ar:five': '٥',
- '/ar:four': '٤', '/ar:fourthroot': '؇', '/ar:kaf': 'ك', '/ar:ng': 'ڭ',
- '/ar:nine': '٩', '/ar:numbersign': '\u0600', '/ar:oe': 'ۆ', '/ar:one':
- '١', '/ar:peh': 'پ', '/ar:percent': '٪', '/ar:perthousand': '؊',
- '/ar:question': '؟', '/ar:reh': 'ر', '/ar:semicolon': '؛', '/ar:seven':
- '٧', '/ar:shadda': 'ّ', '/ar:six': '٦', '/ar:sukun': 'ْ', '/ar:three':
- '٣', '/ar:two': '٢', '/ar:u': 'ۇ', '/ar:ve': 'ۋ', '/ar:yu': 'ۈ',
- '/ar:zero': '٠', '/araeaekorean': 'ㆎ', '/araeakorean': 'ㆍ', '/arc': '⌒',
- '/archaicmepigraphic': 'ꟿ', '/aries': '♈', '/arighthalfring': 'ẚ',
- '/aring': 'å', '/aringacute': 'ǻ', '/aringbelow': 'ḁ', '/armn:Ayb': 'Ա',
- '/armn:Ben': 'Բ', '/armn:Ca': 'Ծ', '/armn:Cha': 'Չ', '/armn:Cheh': 'Ճ',
- '/armn:Co': 'Ց', '/armn:DRAMSIGN': '֏', '/armn:Da': 'Դ', '/armn:Ech':
- 'Ե', '/armn:Eh': 'Է', '/armn:Et': 'Ը', '/armn:Feh': 'Ֆ', '/armn:Ghad':
- 'Ղ', '/armn:Gim': 'Գ', '/armn:Ho': 'Հ', '/armn:Ini': 'Ի', '/armn:Ja':
- 'Ձ', '/armn:Jheh': 'Ջ', '/armn:Keh': 'Ք', '/armn:Ken': 'Կ',
- '/armn:Liwn': 'Լ', '/armn:Men': 'Մ', '/armn:Now': 'Ն', '/armn:Oh': 'Օ',
- '/armn:Peh': 'Պ', '/armn:Piwr': 'Փ', '/armn:Ra': 'Ռ', '/armn:Reh': 'Ր',
- '/armn:Seh': 'Ս', '/armn:Sha': 'Շ', '/armn:Tiwn': 'Տ', '/armn:To': 'Թ',
- '/armn:Vew': 'Վ', '/armn:Vo': 'Ո', '/armn:Xeh': 'Խ', '/armn:Yi': 'Յ',
- '/armn:Yiwn': 'Ւ', '/armn:Za': 'Զ', '/armn:Zhe': 'Ժ',
- '/armn:abbreviationmark': '՟', '/armn:apostrophe': '՚', '/armn:ayb':
- 'ա', '/armn:ben': 'բ', '/armn:ca': 'ծ', '/armn:cha': 'չ', '/armn:cheh':
- 'ճ', '/armn:co': 'ց', '/armn:comma': '՝', '/armn:da': 'դ', '/armn:ech':
- 'ե', '/armn:ech_yiwn': 'և', '/armn:eh': 'է', '/armn:emphasismark': '՛',
- '/armn:et': 'ը', '/armn:exclam': '՜', '/armn:feh': 'ֆ', '/armn:ghad':
- 'ղ', '/armn:gim': 'գ', '/armn:ho': 'հ', '/armn:hyphen': '֊',
- '/armn:ini': 'ի', '/armn:ja': 'ձ', '/armn:jheh': 'ջ', '/armn:keh': 'ք',
- '/armn:ken': 'կ', '/armn:leftfacingeternitysign': '֎', '/armn:liwn':
- 'լ', '/armn:men': 'մ', '/armn:men_ech': 'ﬔ', '/armn:men_ini': 'ﬕ',
- '/armn:men_now': 'ﬓ', '/armn:men_xeh': 'ﬗ', '/armn:now': 'ն',
- '/armn:oh': 'օ', '/armn:peh': 'պ', '/armn:period': '։', '/armn:piwr':
- 'փ', '/armn:question': '՞', '/armn:ra': 'ռ', '/armn:reh': 'ր',
- '/armn:rightfacingeternitysign': '֍', '/armn:ringhalfleft': 'ՙ',
- '/armn:seh': 'ս', '/armn:sha': 'շ', '/armn:tiwn': 'տ', '/armn:to': 'թ',
- '/armn:vew': 'վ', '/armn:vew_now': 'ﬖ', '/armn:vo': 'ո', '/armn:xeh':
- 'խ', '/armn:yi': 'յ', '/armn:yiwn': 'ւ', '/armn:za': 'զ', '/armn:zhe':
- 'ժ', '/arrowNE': '↗', '/arrowNW': '↖', '/arrowSE': '↘', '/arrowSW': '↙',
- '/arrowanticlockwiseopencircle': '↺', '/arrowanticlockwisesemicircle':
- '↶', '/arrowboth': '↔', '/arrowclockwiseopencircle': '↻',
- '/arrowclockwisesemicircle': '↷', '/arrowdashdown': '⇣',
- '/arrowdashleft': '⇠', '/arrowdashright': '⇢', '/arrowdashup': '⇡',
- '/arrowdblboth': '⇔', '/arrowdbldown': '⇓', '/arrowdblleft': '⇐',
- '/arrowdblright': '⇒', '/arrowdblup': '⇑', '/arrowdown': '↓',
- '/arrowdowndashed': '⇣', '/arrowdownfrombar': '↧', '/arrowdownleft':
- '↙', '/arrowdownright': '↘', '/arrowdowntwoheaded': '↡',
- '/arrowdownwhite': '⇩', '/arrowdownzigzag': '↯', '/arrowheaddown': '⌄',
- '/arrowheaddownlowmod': '˯', '/arrowheaddownmod': '˅',
- '/arrowheadleftlowmod': '˱', '/arrowheadleftmod': '˂',
- '/arrowheadrightlowmod': '˲', '/arrowheadrightmod': '˃',
- '/arrowheadtwobarsuphorizontal': '⌤', '/arrowheadup': '⌃',
- '/arrowheaduplowmod': '˰', '/arrowheadupmod': '˄', '/arrowhorizex':
- '\uf8e7', '/arrowleft': '←', '/arrowleftdashed': '⇠', '/arrowleftdbl':
- '⇐', '/arrowleftdblstroke': '⇍', '/arrowleftdowncorner': '↵',
- '/arrowleftdowntip': '↲', '/arrowleftfrombar': '↤', '/arrowlefthook':
- '↩', '/arrowleftloop': '↫', '/arrowleftlowmod': '˿',
- '/arrowleftoverright': '⇆', '/arrowleftoverrighttobar': '↹',
- '/arrowleftright': '↔', '/arrowleftrightstroke': '↮',
- '/arrowleftrightwave': '↭', '/arrowleftsquiggle': '⇜',
- '/arrowleftstroke': '↚', '/arrowlefttail': '↢', '/arrowlefttobar': '⇤',
- '/arrowlefttwoheaded': '↞', '/arrowleftuptip': '↰', '/arrowleftwave':
- '↜', '/arrowleftwhite': '⇦', '/arrowlongNWtobar': '↸', '/arrowright':
- '→', '/arrowrightdashed': '⇢', '/arrowrightdblstroke': '⇏',
- '/arrowrightdowncorner': '↴', '/arrowrightdowntip': '↳',
- '/arrowrightfrombar': '↦', '/arrowrightheavy': '➞', '/arrowrighthook':
- '↪', '/arrowrightloop': '↬', '/arrowrightoverleft': '⇄',
- '/arrowrightsmallcircle': '⇴', '/arrowrightsquiggle': '⇝',
- '/arrowrightstroke': '↛', '/arrowrighttail': '↣', '/arrowrighttobar':
- '⇥', '/arrowrighttwoheaded': '↠', '/arrowrightwave': '↝',
- '/arrowrightwhite': '⇨', '/arrowspaireddown': '⇊', '/arrowspairedleft':
- '⇇', '/arrowspairedright': '⇉', '/arrowspairedup': '⇈', '/arrowtableft':
- '⇤', '/arrowtabright': '⇥', '/arrowup': '↑', '/arrowupdashed': '⇡',
- '/arrowupdn': '↕', '/arrowupdnbse': '↨', '/arrowupdown': '↕',
- '/arrowupdownbase': '↨', '/arrowupdownwithbase': '↨', '/arrowupfrombar':
- '↥', '/arrowupleft': '↖', '/arrowupleftofdown': '⇅', '/arrowupright':
- '↗', '/arrowuprighttip': '↱', '/arrowuptwoheaded': '↟', '/arrowupwhite':
- '⇧', '/arrowvertex': '\uf8e6', '/articulatedLorry': 'ὩB',
- '/artistPalette': 'Ἲ8', '/aruhuasquare': '㌁', '/asciicircum': '^',
- '/asciicircummonospace': '^', '/asciitilde': '~',
- '/asciitildemonospace': '~', '/ascript': 'ɑ', '/ascriptturned': 'ɒ',
- '/asmallhiragana': 'ぁ', '/asmallkatakana': 'ァ',
- '/asmallkatakanahalfwidth': 'ァ', '/asper': '῾', '/asperacute': '῞',
- '/aspergrave': '῝', '/aspertilde': '῟', '/assertion': '⊦', '/asterisk':
- '*', '/asteriskaltonearabic': '٭', '/asteriskarabic': '٭',
- '/asteriskmath': '∗', '/asteriskmonospace': '*', '/asterisksmall': '﹡',
- '/asterism': '⁂', '/astonishedFace': 'ὣ2', '/astroke': 'ⱥ',
- '/astronomicaluranus': '⛢', '/asuperior': '\uf6e9',
- '/asympticallyequal': '≃', '/asymptoticallyequal': '≃', '/at': '@',
- '/athleticShoe': 'ὅF', '/atilde': 'ã', '/atmonospace': '@',
- '/atnachHafukh:hb': '֢', '/atom': '⚛', '/atsmall': '﹫',
- '/attentionideographiccircled': '㊟', '/aturned': 'ɐ', '/au': 'ꜷ',
- '/aubengali': 'ঔ', '/aubergine': 'ἴ6', '/aubopomofo': 'ㄠ', '/audeva':
- 'औ', '/aufullwidth': '㍳', '/augujarati': 'ઔ', '/augurmukhi': 'ਔ',
- '/augusttelegraph': '㋇', '/aulengthmarkbengali': 'ৗ',
- '/aumatragurmukhi': 'ੌ', '/austral': '₳', '/automatedTellerMachine':
- 'Ἶ7', '/automobile': 'Ὡ7', '/auvowelsignbengali': 'ৌ',
- '/auvowelsigndeva': 'ौ', '/auvowelsigngujarati': 'ૌ', '/av': 'ꜹ',
- '/avagrahadeva': 'ऽ', '/avhorizontalbar': 'ꜻ', '/ay': 'ꜽ',
- '/aybarmenian': 'ա', '/ayin': 'ע', '/ayin:hb': 'ע', '/ayinalt:hb': 'ﬠ',
- '/ayinaltonehebrew': 'ﬠ', '/ayinhebrew': 'ע', '/azla:hb': '֜', '/b':
- 'b', '/baarerusquare': '㌭', '/babengali': 'ব', '/babyAngel': '\u1f47C',
- '/babyBottle': 'ἷC', '/babyChick': 'ὂ4', '/backLeftwardsArrowAbove':
- 'ὑ9', '/backOfEnvelope': '\u1f582', '/backslash': '\\',
- '/backslashbarfunc': '⍀', '/backslashdbl': '⑊', '/backslashmonospace':
- '\', '/bactrianCamel': 'ὂB', '/badeva': 'ब',
- '/badmintonRacquetAndShuttlecock': 'Ἷ8', '/bagdelimitersshapeleft': '⟅',
- '/bagdelimitersshaperight': '⟆', '/baggageClaim': 'Ὤ4', '/bagujarati':
- 'બ', '/bagurmukhi': 'ਬ', '/bahiragana': 'ば', '/bahtthai': '฿',
- '/bakatakana': 'バ', '/balloon': 'Ἰ8', '/ballotBoldScriptX': 'Ὗ6',
- '/ballotBoxBallot': 'Ὗ3', '/ballotBoxBoldCheck': 'Ὗ9',
- '/ballotBoxBoldScriptX': 'Ὗ7', '/ballotBoxScriptX': 'Ὗ5',
- '/ballotScriptX': 'Ὗ4', '/bamurda': 'ꦨ', '/banana': 'ἴC', '/bank': 'Ἶ6',
- '/banknoteDollarSign': 'Ὃ5', '/banknoteEuroSign': 'Ὃ6',
- '/banknotePoundSign': 'Ὃ7', '/banknoteYenSign': 'Ὃ4', '/bar': '|',
- '/barChart': 'ὌA', '/barberPole': 'Ὀ8', '/barfullwidth': '㍴',
- '/barmonospace': '|', '/barquillverticalleft': '⸠',
- '/barquillverticalright': '⸡', '/baseball': '⚾', '/basketballAndHoop':
- 'Ἴ0', '/bath': 'Ὤ0', '/bathtub': 'Ὤ1', '/battery': 'ὐB', '/bbopomofo':
- 'ㄅ', '/bcircle': 'ⓑ', '/bdot': 'ḃ', '/bdotaccent': 'ḃ', '/bdotbelow':
- 'ḅ', '/beachUmbrella': 'Ἵ6', '/beamedAscendingMusicalNotes': 'ἹC',
- '/beamedDescendingMusicalNotes': 'ἹD', '/beamedeighthnotes': '♫',
- '/beamedsixteenthnotes': '♬', '/beamfunc': '⌶', '/bearFace': 'ὃB',
- '/beatingHeart': 'Ὁ3', '/because': '∵', '/becyr': 'б', '/becyrillic':
- 'б', '/bed': 'ὬF', '/beeh': 'ٻ', '/beeh.fina': 'ﭓ', '/beeh.init': 'ﭔ',
- '/beeh.isol': 'ﭒ', '/beeh.medi': 'ﭕ', '/beerMug': 'ἷA', '/beetasquare':
- '㌼', '/beh': 'ب', '/beh.fina': 'ﺐ', '/beh.init': 'ﺑ',
- '/beh.init_alefmaksura.fina': 'ﰉ', '/beh.init_hah.fina': 'ﰆ',
- '/beh.init_hah.medi': 'ﲝ', '/beh.init_heh.medi': 'ﲠ',
- '/beh.init_jeem.fina': 'ﰅ', '/beh.init_jeem.medi': 'ﲜ',
- '/beh.init_khah.fina': 'ﰇ', '/beh.init_khah.medi': 'ﲞ',
- '/beh.init_meem.fina': 'ﰈ', '/beh.init_meem.medi': 'ﲟ',
- '/beh.init_yeh.fina': 'ﰊ', '/beh.isol': 'ﺏ', '/beh.medi': 'ﺒ',
- '/beh.medi_alefmaksura.fina': 'ﱮ', '/beh.medi_hah.medi_yeh.fina': 'ﷂ',
- '/beh.medi_heh.medi': 'ﳢ', '/beh.medi_khah.medi_yeh.fina': 'ﶞ',
- '/beh.medi_meem.fina': 'ﱬ', '/beh.medi_meem.medi': 'ﳡ',
- '/beh.medi_noon.fina': 'ﱭ', '/beh.medi_reh.fina': 'ﱪ',
- '/beh.medi_yeh.fina': 'ﱯ', '/beh.medi_zain.fina': 'ﱫ',
- '/behDotBelowThreeDotsAbove': 'ݑ', '/behInvertedSmallVBelow': 'ݕ',
- '/behSmallV': 'ݖ', '/behThreeDotsHorizontallyBelow': 'ݐ',
- '/behThreeDotsUpBelow': 'ݒ', '/behThreeDotsUpBelowTwoDotsAbove': 'ݓ',
- '/behTwoDotsBelowDotAbove': 'ݔ', '/beharabic': 'ب', '/beheh': 'ڀ',
- '/beheh.fina': 'ﭛ', '/beheh.init': 'ﭜ', '/beheh.isol': 'ﭚ',
- '/beheh.medi': 'ﭝ', '/behfinalarabic': 'ﺐ', '/behinitialarabic': 'ﺑ',
- '/behiragana': 'べ', '/behmedialarabic': 'ﺒ', '/behmeeminitialarabic':
- 'ﲟ', '/behmeemisolatedarabic': 'ﰈ', '/behnoonfinalarabic': 'ﱭ',
- '/bekatakana': 'ベ', '/bellCancellationStroke': 'ὑ5', '/bellhopBell':
- 'ὬE', '/beltbuckle': '⑄', '/benarmenian': 'բ', '/beng:a': 'অ',
- '/beng:aa': 'আ', '/beng:aasign': 'া', '/beng:abbreviationsign': '৽',
- '/beng:ai': 'ঐ', '/beng:aisign': 'ৈ', '/beng:anji': 'ঀ',
- '/beng:anusvara': 'ং', '/beng:au': 'ঔ', '/beng:aulengthmark': 'ৗ',
- '/beng:ausign': 'ৌ', '/beng:avagraha': 'ঽ', '/beng:ba': 'ব',
- '/beng:bha': 'ভ', '/beng:ca': 'চ', '/beng:candrabindu': 'ঁ',
- '/beng:cha': 'ছ', '/beng:currencyoneless': '৸', '/beng:da': 'দ',
- '/beng:dda': 'ড', '/beng:ddha': 'ঢ', '/beng:dha': 'ধ', '/beng:e': 'এ',
- '/beng:eight': '৮', '/beng:esign': 'ে', '/beng:five': '৫', '/beng:four':
- '৪', '/beng:fourcurrencynumerator': '৷', '/beng:ga': 'গ',
- '/beng:gandamark': '৻', '/beng:gha': 'ঘ', '/beng:ha': 'হ', '/beng:i':
- 'ই', '/beng:ii': 'ঈ', '/beng:iisign': 'ী', '/beng:isign': 'ি',
- '/beng:isshar': '৺', '/beng:ja': 'জ', '/beng:jha': 'ঝ', '/beng:ka': 'ক',
- '/beng:kha': 'খ', '/beng:khandata': 'ৎ', '/beng:la': 'ল',
- '/beng:llvocal': 'ৡ', '/beng:llvocalsign': 'ৣ', '/beng:lvocal': 'ঌ',
- '/beng:lvocalsign': 'ৢ', '/beng:ma': 'ম', '/beng:na': 'ন', '/beng:nga':
- 'ঙ', '/beng:nine': '৯', '/beng:nna': 'ণ', '/beng:nukta': '়',
- '/beng:nya': 'ঞ', '/beng:o': 'ও', '/beng:one': '১',
- '/beng:onecurrencynumerator': '৴', '/beng:osign': 'ো', '/beng:pa': 'প',
- '/beng:pha': 'ফ', '/beng:ra': 'র', '/beng:ralowdiagonal': 'ৱ',
- '/beng:ramiddiagonal': 'ৰ', '/beng:rha': 'ঢ়', '/beng:rra': 'ড়',
- '/beng:rrvocal': 'ৠ', '/beng:rrvocalsign': 'ৄ', '/beng:rupee': '৳',
- '/beng:rupeemark': '৲', '/beng:rvocal': 'ঋ', '/beng:rvocalsign': 'ৃ',
- '/beng:sa': 'স', '/beng:seven': '৭', '/beng:sha': 'শ', '/beng:six': '৬',
- '/beng:sixteencurrencydenominator': '৹', '/beng:ssa': 'ষ', '/beng:ta':
- 'ত', '/beng:tha': 'থ', '/beng:three': '৩',
- '/beng:threecurrencynumerator': '৶', '/beng:tta': 'ট', '/beng:ttha':
- 'ঠ', '/beng:two': '২', '/beng:twocurrencynumerator': '৵', '/beng:u':
- 'উ', '/beng:usign': 'ু', '/beng:uu': 'ঊ', '/beng:uusign': 'ূ',
- '/beng:vedicanusvara': 'ৼ', '/beng:virama': '্', '/beng:visarga': 'ঃ',
- '/beng:ya': 'য', '/beng:yya': 'য়', '/beng:zero': '০', '/bentoBox': 'ἷ1',
- '/benzenering': '⌬', '/benzeneringcircle': '⏣', '/bet': 'ב', '/bet:hb':
- 'ב', '/beta': 'β', '/betasymbol': 'ϐ', '/betasymbolgreek': 'ϐ',
- '/betdagesh': 'בּ', '/betdageshhebrew': 'בּ', '/bethebrew': 'ב',
- '/betrafehebrew': 'בֿ', '/between': '≬', '/betwithdagesh:hb': 'בּ',
- '/betwithrafe:hb': 'בֿ', '/bflourish': 'ꞗ', '/bhabengali': 'ভ',
- '/bhadeva': 'भ', '/bhagujarati': 'ભ', '/bhagurmukhi': 'ਭ', '/bhook':
- 'ɓ', '/bicycle': 'Ὣ2', '/bicyclist': 'Ὣ4', '/bihiragana': 'び',
- '/bikatakana': 'ビ', '/bikini': 'ὅ9', '/bilabialclick': 'ʘ',
- '/billiards': 'Ἳ1', '/bindigurmukhi': 'ਂ', '/biohazard': '☣', '/bird':
- 'ὂ6', '/birthdayCake': 'Ἰ2', '/birusquare': '㌱', '/bishopblack': '♝',
- '/bishopwhite': '♗', '/bitcoin': '₿', '/blackDownPointingBackhandIndex':
- '\u1f5a3', '/blackDroplet': 'ἲ2', '/blackFolder': 'ὛF',
- '/blackHardShellFloppyDisk': '\u1f5aA', '/blackHeart': '\u1f5a4',
- '/blackLeftPointingBackhandIndex': 'ὙC', '/blackPennant': 'Ἷ2',
- '/blackPushpin': '\u1f588', '/blackRightPointingBackhandIndex': 'ὙD',
- '/blackRosette': 'Ἷ6', '/blackSkullAndCrossbones': 'ὗ1',
- '/blackSquareButton': 'ὓ2', '/blackTouchtoneTelephone': 'ὗF',
- '/blackUpPointingBackhandIndex': '\u1f5a2', '/blackcircle': '●',
- '/blackcircleforrecord': '⏺', '/blackdiamond': '◆',
- '/blackdownpointingtriangle': '▼', '/blackforstopsquare': '⏹',
- '/blackleftpointingpointer': '◄', '/blackleftpointingtriangle': '◀',
- '/blacklenticularbracketleft': '【',
- '/blacklenticularbracketleftvertical': '︻',
- '/blacklenticularbracketright': '】',
- '/blacklenticularbracketrightvertical': '︼', '/blacklowerlefttriangle':
- '◣', '/blacklowerrighttriangle': '◢',
- '/blackmediumpointingtriangledown': '⏷',
- '/blackmediumpointingtriangleleft': '⏴',
- '/blackmediumpointingtriangleright': '⏵',
- '/blackmediumpointingtriangleup': '⏶',
- '/blackpointingdoubletrianglebarverticalleft': '⏮',
- '/blackpointingdoubletrianglebarverticalright': '⏭',
- '/blackpointingdoubletriangledown': '⏬',
- '/blackpointingdoubletriangleleft': '⏪',
- '/blackpointingdoubletriangleright': '⏩',
- '/blackpointingdoubletriangleup': '⏫',
- '/blackpointingtriangledoublebarverticalright': '⏯', '/blackrectangle':
- '▬', '/blackrightpointingpointer': '►', '/blackrightpointingtriangle':
- '▶', '/blacksmallsquare': '▪', '/blacksmilingface': '☻', '/blacksquare':
- '■', '/blackstar': '★', '/blackupperlefttriangle': '◤',
- '/blackupperrighttriangle': '◥', '/blackuppointingsmalltriangle': '▴',
- '/blackuppointingtriangle': '▲', '/blackwardsbulletleft': '⁌',
- '/blackwardsbulletright': '⁍', '/blank': '␣', '/blinebelow': 'ḇ',
- '/block': '█', '/blossom': 'ἳC', '/blowfish': 'ὂ1', '/blueBook': 'Ὅ8',
- '/blueHeart': 'Ὁ9', '/bmonospace': 'b', '/boar': 'ὁ7', '/board': '⌨',
- '/bobaimaithai': 'บ', '/bohiragana': 'ぼ', '/bokatakana': 'ボ', '/bomb':
- 'Ὂ3', '/book': 'ὖE', '/bookmark': 'ὑ6', '/bookmarkTabs': 'Ὅ1', '/books':
- 'ὍA', '/bopo:a': 'ㄚ', '/bopo:ai': 'ㄞ', '/bopo:an': 'ㄢ', '/bopo:ang':
- 'ㄤ', '/bopo:au': 'ㄠ', '/bopo:b': 'ㄅ', '/bopo:c': 'ㄘ', '/bopo:ch': 'ㄔ',
- '/bopo:d': 'ㄉ', '/bopo:e': 'ㄜ', '/bopo:eh': 'ㄝ', '/bopo:ei': 'ㄟ',
- '/bopo:en': 'ㄣ', '/bopo:eng': 'ㄥ', '/bopo:er': 'ㄦ', '/bopo:f': 'ㄈ',
- '/bopo:g': 'ㄍ', '/bopo:gn': 'ㄬ', '/bopo:h': 'ㄏ', '/bopo:i': 'ㄧ',
- '/bopo:ih': 'ㄭ', '/bopo:iu': 'ㄩ', '/bopo:j': 'ㄐ', '/bopo:k': 'ㄎ',
- '/bopo:l': 'ㄌ', '/bopo:m': 'ㄇ', '/bopo:n': 'ㄋ', '/bopo:ng': 'ㄫ',
- '/bopo:o': 'ㄛ', '/bopo:ou': 'ㄡ', '/bopo:owithdotabove': 'ㄮ', '/bopo:p':
- 'ㄆ', '/bopo:q': 'ㄑ', '/bopo:r': 'ㄖ', '/bopo:s': 'ㄙ', '/bopo:sh': 'ㄕ',
- '/bopo:t': 'ㄊ', '/bopo:u': 'ㄨ', '/bopo:v': 'ㄪ', '/bopo:x': 'ㄒ',
- '/bopo:z': 'ㄗ', '/bopo:zh': 'ㄓ', '/borutosquare': '㌾',
- '/bottlePoppingCork': 'ἷE', '/bouquet': 'Ὁ0', '/bouquetOfFlowers': 'Ἱ5',
- '/bowAndArrow': 'Ἷ9', '/bowlOfHygieia': 'ὔF', '/bowling': 'Ἳ3',
- '/boxlineverticalleft': '⎸', '/boxlineverticalright': '⎹', '/boy':
- '\u1f466', '/boys': 'Ὤ9', '/bparen': '⒝', '/bparenthesized': '⒝',
- '/bqfullwidth': '㏃', '/bqsquare': '㏃', '/braceex': '\uf8f4',
- '/braceleft': '{', '/braceleftbt': '\uf8f3', '/braceleftmid': '\uf8f2',
- '/braceleftmonospace': '{', '/braceleftsmall': '﹛', '/bracelefttp':
- '\uf8f1', '/braceleftvertical': '︷', '/braceright': '}',
- '/bracerightbt': '\uf8fe', '/bracerightmid': '\uf8fd',
- '/bracerightmonospace': '}', '/bracerightsmall': '﹜', '/bracerighttp':
- '\uf8fc', '/bracerightvertical': '︸', '/bracketangledblleft': '⟪',
- '/bracketangledblright': '⟫', '/bracketangleleft': '⟨',
- '/bracketangleright': '⟩', '/bracketbottomcurly': '⏟',
- '/bracketbottomsquare': '⎵', '/bracketcornerupleftsquare': '⎡',
- '/bracketcorneruprightsquare': '⎤', '/bracketdottedsubstitutionleft':
- '⸄', '/bracketdottedsubstitutionright': '⸅', '/bracketextensioncurly':
- '⎪', '/bracketextensionleftsquare': '⎢', '/bracketextensionrightsquare':
- '⎥', '/brackethalfbottomleft': '⸤', '/brackethalfbottomright': '⸥',
- '/brackethalftopleft': '⸢', '/brackethalftopright': '⸣',
- '/brackethookupleftcurly': '⎧', '/brackethookuprightcurly': '⎫',
- '/bracketleft': '[', '/bracketleftbt': '\uf8f0', '/bracketleftex':
- '\uf8ef', '/bracketleftmonospace': '[', '/bracketleftsquarequill': '⁅',
- '/bracketlefttp': '\uf8ee', '/bracketlowercornerleftsquare': '⎣',
- '/bracketlowercornerrightsquare': '⎦', '/bracketlowerhookleftcurly':
- '⎩', '/bracketlowerhookrightcurly': '⎭', '/bracketmiddlepieceleftcurly':
- '⎨', '/bracketmiddlepiecerightcurly': '⎬',
- '/bracketoverbrackettopbottomsquare': '⎶', '/bracketparaphraselowleft':
- '⸜', '/bracketparaphraselowright': '⸝', '/bracketraisedleft': '⸌',
- '/bracketraisedright': '⸍', '/bracketright': ']', '/bracketrightbt':
- '\uf8fb', '/bracketrightex': '\uf8fa', '/bracketrightmonospace': ']',
- '/bracketrightsquarequill': '⁆', '/bracketrighttp': '\uf8f9',
- '/bracketsectionupleftlowerrightcurly': '⎰',
- '/bracketsectionuprightlowerleftcurly': '⎱', '/bracketshellbottom': '⏡',
- '/bracketshelltop': '⏠', '/bracketshellwhiteleft': '⟬',
- '/bracketshellwhiteright': '⟭', '/bracketsubstitutionleft': '⸂',
- '/bracketsubstitutionright': '⸃', '/brackettopcurly': '⏞',
- '/brackettopsquare': '⎴', '/brackettranspositionleft': '⸉',
- '/brackettranspositionright': '⸊', '/bracketwhitesquareleft': '⟦',
- '/bracketwhitesquareright': '⟧', '/branchbankidentification': '⑆',
- '/bread': 'ἵE', '/breve': '˘', '/brevebelowcmb': '̮', '/brevecmb': '̆',
- '/breveinvertedbelowcmb': '̯', '/breveinvertedcmb': '̑',
- '/breveinverteddoublecmb': '͡', '/brevemetrical': '⏑', '/brideVeil':
- '\u1f470', '/bridgeAtNight': 'ἰ9', '/bridgebelowcmb': '̪',
- '/bridgeinvertedbelowcmb': '̺', '/briefcase': 'ὋC', '/brll:blank': '⠀',
- '/brokenHeart': 'Ὁ4', '/brokenbar': '¦', '/brokencirclenorthwestarrow':
- '⎋', '/bstroke': 'ƀ', '/bsuperior': '\uf6ea', '/btopbar': 'ƃ', '/bug':
- 'ὁB', '/buhiragana': 'ぶ', '/buildingConstruction': 'Ἵ7', '/bukatakana':
- 'ブ', '/bullet': '•', '/bulletinverse': '◘', '/bulletoperator': '∙',
- '/bullhorn': 'ὖB', '/bullhornSoundWaves': 'ὖC', '/bullseye': '◎',
- '/burrito': 'ἲF', '/bus': 'ὨC', '/busStop': 'ὨF', '/bussyerusquare':
- '㌴', '/bustInSilhouette': '\u1f464', '/bustsInSilhouette': '\u1f465',
- '/c': 'c', '/caarmenian': 'ծ', '/cabengali': 'চ', '/cactus': 'ἳ5',
- '/cacute': 'ć', '/cadauna': '℆', '/cadeva': 'च', '/caduceus': '☤',
- '/cagujarati': 'ચ', '/cagurmukhi': 'ਚ', '/cakraconsonant': 'ꦿ',
- '/calendar': 'Ὄ5', '/calfullwidth': '㎈', '/callideographicparen': '㈺',
- '/calsquare': '㎈', '/camera': '\u1f4f7', '/cameraFlash': '\u1f4f8',
- '/camping': 'Ἵ5', '/camurda': 'ꦖ', '/cancellationX': 'Ὕ9', '/cancer':
- '♋', '/candle': 'ὖF', '/candrabindubengali': 'ঁ', '/candrabinducmb':
- '̐', '/candrabindudeva': 'ँ', '/candrabindugujarati': 'ઁ', '/candy':
- 'ἶC', '/canoe': 'Ὧ6', '/capitulum': '⸿', '/capricorn': '♑', '/capslock':
- '⇪', '/cardFileBox': '\u1f5c3', '/cardIndex': 'Ὄ7',
- '/cardIndexDividers': '\u1f5c2', '/careof': '℅', '/caret': '‸',
- '/caretinsertionpoint': '⁁', '/carettildedownfunc': '⍱',
- '/carettildeupfunc': '⍲', '/caron': 'ˇ', '/caronbelowcmb': '̬',
- '/caroncmb': '̌', '/carouselHorse': 'Ἲ0', '/carpStreamer': 'ἸF',
- '/carriagereturn': '↵', '/carsliding': '⛐', '/castle': '⛫', '/cat':
- 'ὀ8', '/catFace': 'ὃ1', '/catFaceWithTearsOfJoy': 'ὣ9',
- '/catFaceWithWrySmile': 'ὣC', '/caution': '☡', '/cbar': 'ꞓ',
- '/cbopomofo': 'ㄘ', '/ccaron': 'č', '/ccedilla': 'ç', '/ccedillaacute':
- 'ḉ', '/ccfullwidth': '㏄', '/ccircle': 'ⓒ', '/ccircumflex': 'ĉ',
- '/ccurl': 'ɕ', '/cdfullwidth': '㏅', '/cdot': 'ċ', '/cdotaccent': 'ċ',
- '/cdotreversed': 'ꜿ', '/cdsquare': '㏅', '/cecak': 'ꦁ', '/cecaktelu':
- '꦳', '/cedi': '₵', '/cedilla': '¸', '/cedillacmb': '̧', '/ceilingleft':
- '⌈', '/ceilingright': '⌉', '/celticCross': 'ὔ8', '/cent': '¢',
- '/centigrade': '℃', '/centinferior': '\uf6df', '/centmonospace': '¢',
- '/centoldstyle': '\uf7a2', '/centreddotwhitediamond': '⟐',
- '/centreideographiccircled': '㊥', '/centreline': '℄',
- '/centrelineverticalsquarewhite': '⎅', '/centsuperior': '\uf6e0',
- '/ceres': '⚳', '/chaarmenian': 'չ', '/chabengali': 'ছ', '/chadeva': 'छ',
- '/chagujarati': 'છ', '/chagurmukhi': 'ਛ', '/chains': '⛓', '/chair': '⑁',
- '/chamkocircle': '㉼', '/charactertie': '⁀', '/chartDownwardsTrend':
- 'Ὄ9', '/chartUpwardsTrend': 'Ὄ8', '/chartUpwardsTrendAndYenSign': 'Ὃ9',
- '/chbopomofo': 'ㄔ', '/cheabkhasiancyrillic': 'ҽ', '/cheabkhcyr': 'ҽ',
- '/cheabkhtailcyr': 'ҿ', '/checkbox': '☐', '/checkboxchecked': '☑',
- '/checkboxx': '☒', '/checkmark': '✓', '/checyr': 'ч', '/checyrillic':
- 'ч', '/chedescenderabkhasiancyrillic': 'ҿ', '/chedescendercyrillic':
- 'ҷ', '/chedieresiscyr': 'ӵ', '/chedieresiscyrillic': 'ӵ',
- '/cheeringMegaphone': '\u1f4e3', '/cheharmenian': 'ճ', '/chekhakascyr':
- 'ӌ', '/chekhakassiancyrillic': 'ӌ', '/chequeredFlag': 'Ἴ1', '/cherries':
- 'ἵ2', '/cherryBlossom': 'ἳ8', '/chestnut': 'ἳ0', '/chetailcyr': 'ҷ',
- '/chevertcyr': 'ҹ', '/cheverticalstrokecyrillic': 'ҹ', '/chi': 'χ',
- '/chicken': 'ὁ4', '/chieuchacirclekorean': '㉷', '/chieuchaparenkorean':
- '㈗', '/chieuchcirclekorean': '㉩', '/chieuchkorean': 'ㅊ',
- '/chieuchparenkorean': '㈉', '/childrenCrossing': 'Ὣ8', '/chipmunk':
- 'ὃF', '/chirho': '☧', '/chiron': '⚷', '/chochangthai': 'ช',
- '/chochanthai': 'จ', '/chochingthai': 'ฉ', '/chochoethai': 'ฌ',
- '/chocolateBar': 'ἶB', '/chook': 'ƈ', '/christmasTree': 'Ἰ4', '/church':
- '⛪', '/cieucacirclekorean': '㉶', '/cieucaparenkorean': '㈖',
- '/cieuccirclekorean': '㉨', '/cieuckorean': 'ㅈ', '/cieucparenkorean':
- '㈈', '/cieucuparenkorean': '㈜', '/cinema': 'Ἲ6', '/circle': '○',
- '/circleallbutupperquadrantleftblack': '◕', '/circlebackslashfunc': '⍉',
- '/circleblack': '●', '/circledCrossPommee': 'ὔ0',
- '/circledInformationSource': 'Ὤ8', '/circledasteriskoperator': '⊛',
- '/circledbarnotchhorizontal': '⎉', '/circledcrossinglanes': '⛒',
- '/circleddash': '⊝', '/circleddivisionslash': '⊘',
- '/circleddotoperator': '⊙', '/circledequals': '⊜',
- '/circlediaeresisfunc': '⍥', '/circledminus': '⊖', '/circledot': '⊙',
- '/circledotrightwhite': '⚆', '/circledotted': '◌',
- '/circledringoperator': '⊚', '/circledtriangledown': '⎊',
- '/circlehalfleftblack': '◐', '/circlehalfrightblack': '◑',
- '/circleinversewhite': '◙', '/circlejotfunc': '⌾',
- '/circlelowerhalfblack': '◒', '/circlelowerquadrantleftwhite': '◵',
- '/circlelowerquadrantrightwhite': '◶', '/circlemultiply': '⊗',
- '/circleot': '⊙', '/circleplus': '⊕', '/circlepostalmark': '〶',
- '/circlestarfunc': '⍟', '/circlestilefunc': '⌽',
- '/circlestroketwodotsaboveheavy': '⛣', '/circletwodotsblackwhite': '⚉',
- '/circletwodotswhite': '⚇', '/circleunderlinefunc': '⍜',
- '/circleupperhalfblack': '◓', '/circleupperquadrantleftwhite': '◴',
- '/circleupperquadrantrightblack': '◔', '/circleupperquadrantrightwhite':
- '◷', '/circleverticalfill': '◍', '/circlewhite': '○',
- '/circlewhitedotrightblack': '⚈', '/circlewithlefthalfblack': '◐',
- '/circlewithrighthalfblack': '◑', '/circumflex': 'ˆ',
- '/circumflexbelowcmb': '̭', '/circumflexcmb': '̂', '/circumflexlow':
- 'ꞈ', '/circusTent': 'ἺA', '/cityscape': 'Ἵ9', '/cityscapeAtDusk': 'ἰ6',
- '/cjk:ideographiccomma': '、', '/cjk:tortoiseshellbracketleft': '〔',
- '/cjk:tortoiseshellbracketright': '〕', '/clamshellMobilePhone':
- '\u1f581', '/clapperBoard': 'ἺC', '/clappingHandsSign': 'ὄF',
- '/classicalBuilding': 'ἽB', '/clear': '⌧', '/clearscreen': '⎚',
- '/clickalveolar': 'ǂ', '/clickbilabial': 'ʘ', '/clickdental': 'ǀ',
- '/clicklateral': 'ǁ', '/clickretroflex': 'ǃ', '/clinkingBeerMugs': 'ἷB',
- '/clipboard': 'ὌB', '/clockFaceEight-thirty': 'ὖ3',
- '/clockFaceEightOclock': 'ὕ7', '/clockFaceEleven-thirty': 'ὖ6',
- '/clockFaceElevenOclock': 'ὕA', '/clockFaceFive-thirty': 'ὖ0',
- '/clockFaceFiveOclock': 'ὕ4', '/clockFaceFour-thirty': 'ὕF',
- '/clockFaceFourOclock': 'ὕ3', '/clockFaceNine-thirty': 'ὖ4',
- '/clockFaceNineOclock': 'ὕ8', '/clockFaceOne-thirty': 'ὕC',
- '/clockFaceOneOclock': 'ὕ0', '/clockFaceSeven-thirty': 'ὖ2',
- '/clockFaceSevenOclock': 'ὕ6', '/clockFaceSix-thirty': 'ὖ1',
- '/clockFaceSixOclock': 'ὕ5', '/clockFaceTen-thirty': 'ὖ5',
- '/clockFaceTenOclock': 'ὕ9', '/clockFaceThree-thirty': 'ὕE',
- '/clockFaceThreeOclock': 'ὕ2', '/clockFaceTwelve-thirty': 'ὖ7',
- '/clockFaceTwelveOclock': 'ὕB', '/clockFaceTwo-thirty': 'ὕD',
- '/clockFaceTwoOclock': 'ὕ1',
- '/clockwiseDownwardsAndUpwardsOpenCircleArrows': 'ὐ3',
- '/clockwiseRightAndLeftSemicircleArrows': 'Ὕ8',
- '/clockwiseRightwardsAndLeftwardsOpenCircleArrows': 'ὐ1',
- '/clockwiseRightwardsAndLeftwardsOpenCircleArrowsCircledOneOverlay':
- 'ὐ2', '/closedBook': 'Ὅ5', '/closedLockKey': 'ὑ0',
- '/closedMailboxLoweredFlag': '\u1f4eA', '/closedMailboxRaisedFlag':
- '\u1f4eB', '/closedUmbrella': 'ἰ2', '/closedentryleft': '⛜', '/closeup':
- '⁐', '/cloud': '☁', '/cloudLightning': 'ἲ9', '/cloudRain': 'ἲ7',
- '/cloudSnow': 'ἲ8', '/cloudTornado': 'ἲA', '/clsquare': 'Ἑ1', '/club':
- '♣', '/clubblack': '♣', '/clubsuitblack': '♣', '/clubsuitwhite': '♧',
- '/clubwhite': '♧', '/cm2fullwidth': '㎠', '/cm3fullwidth': '㎤', '/cmb:a':
- 'ͣ', '/cmb:aaboveflat': 'ᷓ', '/cmb:aboveogonek': '᷎', '/cmb:acute': '́',
- '/cmb:acutebelow': '̗', '/cmb:acutegraveacute': '᷉', '/cmb:acutemacron':
- '᷇', '/cmb:acutetone': '́', '/cmb:adieresis': 'ᷲ', '/cmb:ae': 'ᷔ',
- '/cmb:almostequalabove': '͌', '/cmb:almostequaltobelow': '᷽',
- '/cmb:alpha': 'ᷧ', '/cmb:ao': 'ᷕ', '/cmb:arrowheadleftbelow': '͔',
- '/cmb:arrowheadrightabove': '͐', '/cmb:arrowheadrightarrowheadupbelow':
- '͖', '/cmb:arrowheadrightbelow': '͕', '/cmb:arrowleftrightbelow': '͍',
- '/cmb:arrowrightdoublebelow': '͢', '/cmb:arrowupbelow': '͎',
- '/cmb:asteriskbelow': '͙', '/cmb:av': 'ᷖ', '/cmb:b': 'ᷨ',
- '/cmb:belowbreve': '̮', '/cmb:beta': 'ᷩ', '/cmb:breve': '̆',
- '/cmb:brevemacron': '᷋', '/cmb:bridgeabove': '͆', '/cmb:bridgebelow':
- '̪', '/cmb:c': 'ͨ', '/cmb:candrabindu': '̐', '/cmb:caron': '̌',
- '/cmb:caronbelow': '̬', '/cmb:ccedilla': 'ᷗ', '/cmb:cedilla': '̧',
- '/cmb:circumflex': '̂', '/cmb:circumflexbelow': '̭',
- '/cmb:commaaccentbelow': '̦', '/cmb:commaturnedabove': '̒', '/cmb:d':
- 'ͩ', '/cmb:dblarchinvertedbelow': '̫', '/cmb:dbloverline': '̿',
- '/cmb:dblverticallineabove': '̎', '/cmb:dblverticallinebelow': '͈',
- '/cmb:deletionmark': '᷻', '/cmb:dialytikatonos': '̈́', '/cmb:dieresis':
- '̈', '/cmb:dieresisbelow': '̤', '/cmb:dotaboveleft': '᷸',
- '/cmb:dotaccent': '̇', '/cmb:dotbelowcomb': '̣', '/cmb:dotrightabove':
- '͘', '/cmb:dottedacute': '᷁', '/cmb:dottedgrave': '᷀',
- '/cmb:doubleabovecircumflex': '᷍', '/cmb:doublebelowbreve': '͜',
- '/cmb:doublebreve': '͝', '/cmb:doubleinvertedbelowbreve': '᷼',
- '/cmb:doubleringbelow': '͚', '/cmb:downtackbelow': '̞', '/cmb:e': 'ͤ',
- '/cmb:equalbelow': '͇', '/cmb:esh': 'ᷯ', '/cmb:eth': 'ᷙ', '/cmb:f': 'ᷫ',
- '/cmb:fermata': '͒', '/cmb:g': 'ᷚ', '/cmb:graphemejoiner': '͏',
- '/cmb:grave': '̀', '/cmb:graveacutegrave': '᷈', '/cmb:gravebelow': '̖',
- '/cmb:gravedouble': '̏', '/cmb:gravemacron': '᷅', '/cmb:gravetone': '̀',
- '/cmb:gsmall': 'ᷛ', '/cmb:h': 'ͪ', '/cmb:halfleftringabove': '͑',
- '/cmb:halfleftringbelow': '̜', '/cmb:halfrightringabove': '͗',
- '/cmb:halfrightringbelow': '̹', '/cmb:homotheticabove': '͋',
- '/cmb:hookabove': '̉', '/cmb:horn': '̛', '/cmb:hungarumlaut': '̋',
- '/cmb:i': 'ͥ', '/cmb:insulard': 'ᷘ', '/cmb:invertedbelowbreve': '̯',
- '/cmb:invertedbreve': '̑', '/cmb:invertedbridgebelow': '̺',
- '/cmb:inverteddoublebreve': '͡', '/cmb:iotasub': 'ͅ', '/cmb:isbelow':
- '᷐', '/cmb:k': 'ᷜ', '/cmb:kavykaaboveleft': '᷷',
- '/cmb:kavykaaboveright': '᷶', '/cmb:koronis': '̓', '/cmb:l': 'ᷝ',
- '/cmb:leftangleabove': '̚', '/cmb:leftanglebelow': '͉',
- '/cmb:leftarrowheadabove': '᷾', '/cmb:lefttackbelow': '̘',
- '/cmb:lineverticalabove': '̍', '/cmb:lineverticalbelow': '̩',
- '/cmb:longs': 'ᷥ', '/cmb:lowline': '̲', '/cmb:lowlinedouble': '̳',
- '/cmb:lsmall': 'ᷞ', '/cmb:lwithdoublemiddletilde': 'ᷬ', '/cmb:m': 'ͫ',
- '/cmb:macron': '̄', '/cmb:macronacute': '᷄', '/cmb:macronbelow': '̱',
- '/cmb:macronbreve': '᷌', '/cmb:macrondouble': '͞',
- '/cmb:macrondoublebelow': '͟', '/cmb:macrongrave': '᷆',
- '/cmb:minusbelow': '̠', '/cmb:msmall': 'ᷟ', '/cmb:n': 'ᷠ',
- '/cmb:nottildeabove': '͊', '/cmb:nsmall': 'ᷡ', '/cmb:o': 'ͦ',
- '/cmb:odieresis': 'ᷳ', '/cmb:ogonek': '̨', '/cmb:overlaystrokelong':
- '̶', '/cmb:overlaystrokeshort': '̵', '/cmb:overline': '̅',
- '/cmb:owithlightcentralizationstroke': 'ᷭ', '/cmb:p': 'ᷮ',
- '/cmb:palatalizedhookbelow': '̡', '/cmb:perispomeni': '͂',
- '/cmb:plusbelow': '̟', '/cmb:r': 'ͬ', '/cmb:rbelow': '᷊',
- '/cmb:retroflexhookbelow': '̢', '/cmb:reversedcommaabove': '̔',
- '/cmb:rightarrowheadanddownarrowheadbelow': '᷿', '/cmb:righttackbelow':
- '̙', '/cmb:ringabove': '̊', '/cmb:ringbelow': '̥', '/cmb:rrotunda': 'ᷣ',
- '/cmb:rsmall': 'ᷢ', '/cmb:s': 'ᷤ', '/cmb:schwa': 'ᷪ',
- '/cmb:seagullbelow': '̼', '/cmb:snakebelow': '᷂',
- '/cmb:soliduslongoverlay': '̸', '/cmb:solidusshortoverlay': '̷',
- '/cmb:squarebelow': '̻', '/cmb:suspensionmark': '᷃', '/cmb:t': 'ͭ',
- '/cmb:tilde': '̃', '/cmb:tildebelow': '̰', '/cmb:tildedouble': '͠',
- '/cmb:tildeoverlay': '̴', '/cmb:tildevertical': '̾', '/cmb:turnedabove':
- '̓', '/cmb:turnedcommaabove': '̕', '/cmb:u': 'ͧ', '/cmb:udieresis': 'ᷴ',
- '/cmb:uptackabove': '᷵', '/cmb:uptackbelow': '̝', '/cmb:urabove': '᷑',
- '/cmb:usabove': '᷒', '/cmb:uwithlightcentralizationstroke': 'ᷰ',
- '/cmb:v': 'ͮ', '/cmb:w': 'ᷱ', '/cmb:wideinvertedbridgebelow': '᷹',
- '/cmb:x': 'ͯ', '/cmb:xabove': '̽', '/cmb:xbelow': '͓', '/cmb:z': 'ᷦ',
- '/cmb:zigzagabove': '͛', '/cmb:zigzagbelow': '᷏', '/cmcubedsquare': '㎤',
- '/cmfullwidth': '㎝', '/cmonospace': 'c', '/cmsquaredsquare': '㎠',
- '/cntr:acknowledge': '␆', '/cntr:backspace': '␈', '/cntr:bell': '␇',
- '/cntr:blank': '␢', '/cntr:cancel': '␘', '/cntr:carriagereturn': '␍',
- '/cntr:datalinkescape': '␐', '/cntr:delete': '␡', '/cntr:deleteformtwo':
- '␥', '/cntr:devicecontrolfour': '␔', '/cntr:devicecontrolone': '␑',
- '/cntr:devicecontrolthree': '␓', '/cntr:devicecontroltwo': '␒',
- '/cntr:endofmedium': '␙', '/cntr:endoftext': '␃',
- '/cntr:endoftransmission': '␄', '/cntr:endoftransmissionblock': '␗',
- '/cntr:enquiry': '␅', '/cntr:escape': '␛', '/cntr:fileseparator': '␜',
- '/cntr:formfeed': '␌', '/cntr:groupseparator': '␝',
- '/cntr:horizontaltab': '␉', '/cntr:linefeed': '␊',
- '/cntr:negativeacknowledge': '␕', '/cntr:newline': '', '/cntr:null':
- '␀', '/cntr:openbox': '␣', '/cntr:recordseparator': '␞',
- '/cntr:shiftin': '␏', '/cntr:shiftout': '␎', '/cntr:space': '␠',
- '/cntr:startofheading': '␁', '/cntr:startoftext': '␂',
- '/cntr:substitute': '␚', '/cntr:substituteformtwo': '␦',
- '/cntr:synchronousidle': '␖', '/cntr:unitseparator': '␟',
- '/cntr:verticaltab': '␋', '/coarmenian': 'ց', '/cocktailGlass': 'ἷ8',
- '/coffin': '⚰', '/cofullwidth': '㏇', '/collision': 'Ὂ5', '/colon': ':',
- '/colonequals': '≔', '/colonmod': '꞉', '/colonmonetary': '₡',
- '/colonmonospace': ':', '/colonraisedmod': '˸', '/colonsign': '₡',
- '/colonsmall': '﹕', '/colontriangularhalfmod': 'ˑ',
- '/colontriangularmod': 'ː', '/comet': '☄', '/comma': ',',
- '/commaabovecmb': '̓', '/commaaboverightcmb': '̕', '/commaaccent':
- '\uf6c3', '/commaarabic': '،', '/commaarmenian': '՝', '/commabarfunc':
- '⍪', '/commainferior': '\uf6e1', '/commamonospace': ',', '/commaraised':
- '⸴', '/commareversed': '⹁', '/commareversedabovecmb': '̔',
- '/commareversedmod': 'ʽ', '/commasmall': '﹐', '/commasuperior':
- '\uf6e2', '/commaturnedabovecmb': '̒', '/commaturnedmod': 'ʻ',
- '/commercialat': '﹫', '/commercialminussign': '⁒', '/compass': '☼',
- '/complement': '∁', '/composition': '⎄', '/compression': 'ὝC', '/con':
- 'ꝯ', '/confettiBall': 'ἸA', '/confoundedFace': 'ὡ6', '/confusedFace':
- 'ὡ5', '/congratulationideographiccircled': '㊗',
- '/congratulationideographicparen': '㈷', '/congruent': '≅',
- '/conicaltaper': '⌲', '/conjunction': '☌', '/consquareupblack': '⛾',
- '/constructionSign': 'Ὢ7', '/constructionWorker': '\u1f477',
- '/containsasmembersmall': '∍', '/containsasnormalsubgroorequalup': '⊵',
- '/containsasnormalsubgroup': '⊳', '/containslonghorizontalstroke': '⋺',
- '/containsoverbar': '⋽', '/containsoverbarsmall': '⋾',
- '/containssmallverticalbarhorizontalstroke': '⋼',
- '/containsverticalbarhorizontalstroke': '⋻', '/continuousunderline':
- '⎁', '/contourintegral': '∮', '/control': '⌃', '/controlACK': '\x06',
- '/controlBEL': '\x07', '/controlBS': '\x08', '/controlCAN': '\x18',
- '/controlCR': '\r', '/controlDC1': '\x11', '/controlDC2': '\x12',
- '/controlDC3': '\x13', '/controlDC4': '\x14', '/controlDEL': '\x7f',
- '/controlDLE': '\x10', '/controlEM': '\x19', '/controlENQ': '\x05',
- '/controlEOT': '\x04', '/controlESC': '\x1b', '/controlETB': '\x17',
- '/controlETX': '\x03', '/controlFF': '\x0c', '/controlFS': '\x1c',
- '/controlGS': '\x1d', '/controlHT': '\t', '/controlKnobs': 'ἹB',
- '/controlLF': '\n', '/controlNAK': '\x15', '/controlRS': '\x1e',
- '/controlSI': '\x0f', '/controlSO': '\x0e', '/controlSOT': '\x02',
- '/controlSTX': '\x01', '/controlSUB': '\x1a', '/controlSYN': '\x16',
- '/controlUS': '\x1f', '/controlVT': '\x0b', '/convavediamondwhite': '⟡',
- '/convenienceStore': 'ἾA', '/cookedRice': 'ἵA', '/cookie': 'ἶA',
- '/cooking': 'ἷ3', '/coolsquare': 'Ἑ2', '/coproductarray': '∐',
- '/copyideographiccircled': '㊢', '/copyright': '©', '/copyrightsans':
- '\uf8e9', '/copyrightserif': '\uf6d9', '/cornerbottomleft': '⌞',
- '/cornerbottomright': '⌟', '/cornerbracketleft': '「',
- '/cornerbracketlefthalfwidth': '「', '/cornerbracketleftvertical': '﹁',
- '/cornerbracketright': '」', '/cornerbracketrighthalfwidth': '」',
- '/cornerbracketrightvertical': '﹂', '/cornerdotupleft': '⟔',
- '/cornertopleft': '⌜', '/cornertopright': '⌝', '/coroniseditorial': '⸎',
- '/corporationsquare': '㍿', '/correctideographiccircled': '㊣',
- '/corresponds': '≘', '/cosquare': '㏇', '/couchAndLamp': 'ὬB',
- '/counterbore': '⌴', '/countersink': '⌵', '/coupleHeart': 'Ὁ1',
- '/coverkgfullwidth': '㏆', '/coverkgsquare': '㏆', '/cow': 'ὀ4',
- '/cowFace': 'ὂE', '/cpalatalhook': 'ꞔ', '/cparen': '⒞',
- '/cparenthesized': '⒞', '/creditCard': 'Ὃ3', '/crescentMoon': 'ἱ9',
- '/creversed': 'ↄ', '/cricketBatAndBall': 'ἼF', '/crocodile': 'ὀA',
- '/cropbottomleft': '⌍', '/cropbottomright': '⌌', '/croptopleft': '⌏',
- '/croptopright': '⌎', '/crossPommee': 'ὔ2',
- '/crossPommeeHalf-circleBelow': 'ὔ1', '/crossedFlags': 'ἸC',
- '/crossedswords': '⚔', '/crossinglanes': '⛌', '/crossmod': '˟',
- '/crossofjerusalem': '☩', '/crossoflorraine': '☨',
- '/crossonshieldblack': '⛨', '/crown': 'ὅ1', '/crrn:rupee': '₨',
- '/cruzeiro': '₢', '/cryingCatFace': 'ὣF', '/cryingFace': 'ὢ2',
- '/crystalBall': 'ὒE', '/cstretched': 'ʗ', '/cstroke': 'ȼ', '/cuatrillo':
- 'ꜭ', '/cuatrillocomma': 'ꜯ', '/curlyand': '⋏', '/curlylogicaland': '⋏',
- '/curlylogicalor': '⋎', '/curlyor': '⋎', '/currency': '¤',
- '/currencyExchange': 'Ὃ1', '/curryAndRice': 'ἵB', '/custard': 'ἶE',
- '/customeraccountnumber': '⑉', '/customs': 'Ὤ3', '/cyclone': 'ἰ0',
- '/cylindricity': '⌭', '/cyrBreve': '\uf6d1', '/cyrFlex': '\uf6d2',
- '/cyrbreve': '\uf6d4', '/cyrflex': '\uf6d5', '/d': 'd', '/daarmenian':
- 'դ', '/daasusquare': '㌤', '/dabengali': 'দ', '/dad': 'ض', '/dad.fina':
- 'ﺾ', '/dad.init': 'ﺿ', '/dad.init_alefmaksura.fina': 'ﴇ',
- '/dad.init_hah.fina': 'ﰣ', '/dad.init_hah.medi': 'ﲵ',
- '/dad.init_jeem.fina': 'ﰢ', '/dad.init_jeem.medi': 'ﲴ',
- '/dad.init_khah.fina': 'ﰤ', '/dad.init_khah.medi': 'ﲶ',
- '/dad.init_khah.medi_meem.medi': 'ﵰ', '/dad.init_meem.fina': 'ﰥ',
- '/dad.init_meem.medi': 'ﲷ', '/dad.init_reh.fina': 'ﴐ',
- '/dad.init_yeh.fina': 'ﴈ', '/dad.isol': 'ﺽ', '/dad.medi': 'ﻀ',
- '/dad.medi_alefmaksura.fina': 'ﴣ',
- '/dad.medi_hah.medi_alefmaksura.fina': 'ﵮ',
- '/dad.medi_hah.medi_yeh.fina': 'ﶫ', '/dad.medi_khah.medi_meem.fina':
- 'ﵯ', '/dad.medi_reh.fina': 'ﴬ', '/dad.medi_yeh.fina': 'ﴤ', '/dadarabic':
- 'ض', '/daddotbelow': 'ۻ', '/dadeva': 'द', '/dadfinalarabic': 'ﺾ',
- '/dadinitialarabic': 'ﺿ', '/dadmedialarabic': 'ﻀ', '/dafullwidth': '㍲',
- '/dagesh': 'ּ', '/dagesh:hb': 'ּ', '/dageshhebrew': 'ּ', '/dagger': '†',
- '/daggerKnife': '\u1f5e1', '/daggerdbl': '‡', '/daggerwithguardleft':
- '⸶', '/daggerwithguardright': '⸷', '/dagujarati': 'દ', '/dagurmukhi':
- 'ਦ', '/dahal': 'ڌ', '/dahal.fina': 'ﮅ', '/dahal.isol': 'ﮄ',
- '/dahiragana': 'だ', '/dakatakana': 'ダ', '/dal': 'د', '/dal.fina': 'ﺪ',
- '/dal.isol': 'ﺩ', '/dalInvertedSmallVBelow': 'ݚ',
- '/dalTwoDotsVerticallyBelowSmallTah': 'ݙ', '/dalarabic': 'د',
- '/daldotbelow': 'ڊ', '/daldotbelowtahsmall': 'ڋ',
- '/daldownthreedotsabove': 'ڏ', '/dalet': 'ד', '/dalet:hb': 'ד',
- '/daletdagesh': 'דּ', '/daletdageshhebrew': 'דּ', '/dalethatafpatah': 'ד',
- '/dalethatafpatahhebrew': 'ד', '/dalethatafsegol': 'ד',
- '/dalethatafsegolhebrew': 'ד', '/dalethebrew': 'ד', '/dalethiriq': 'ד',
- '/dalethiriqhebrew': 'ד', '/daletholam': 'ד', '/daletholamhebrew': 'ד',
- '/daletpatah': 'ד', '/daletpatahhebrew': 'ד', '/daletqamats': 'ד',
- '/daletqamatshebrew': 'ד', '/daletqubuts': 'ד', '/daletqubutshebrew':
- 'ד', '/daletsegol': 'ד', '/daletsegolhebrew': 'ד', '/daletsheva': 'ד',
- '/daletshevahebrew': 'ד', '/dalettsere': 'ד', '/dalettserehebrew': 'ד',
- '/daletwide:hb': 'ﬢ', '/daletwithdagesh:hb': 'דּ', '/dalfinalarabic':
- 'ﺪ', '/dalfourdotsabove': 'ڐ', '/dalinvertedV': 'ۮ', '/dalring': 'ډ',
- '/damahaprana': 'ꦣ', '/damma': 'ُ', '/dammaIsol': 'ﹸ', '/dammaMedi':
- 'ﹹ', '/dammaarabic': 'ُ', '/dammalowarabic': 'ُ', '/dammareversed': 'ٝ',
- '/dammasmall': 'ؙ', '/dammatan': 'ٌ', '/dammatanIsol': 'ﹲ',
- '/dammatanaltonearabic': 'ٌ', '/dammatanarabic': 'ٌ', '/dancer': 'Ὀ3',
- '/danda': '।', '/dango': 'ἶ1', '/darga:hb': '֧', '/dargahebrew': '֧',
- '/dargalefthebrew': '֧', '/darkShade': '▓', '/darkSunglasses': 'ὗ6',
- '/dashwithupturnleft': '⹃', '/dasiacmbcyr': '҅',
- '/dasiapneumatacyrilliccmb': '҅', '/dateseparator': '؍',
- '/dayeighteentelegraph': '㏱', '/dayeighttelegraph': '㏧',
- '/dayeleventelegraph': '㏪', '/dayfifteentelegraph': '㏮',
- '/dayfivetelegraph': '㏤', '/dayfourteentelegraph': '㏭',
- '/dayfourtelegraph': '㏣', '/daynineteentelegraph': '㏲',
- '/dayninetelegraph': '㏨', '/dayonetelegraph': '㏠',
- '/dayseventeentelegraph': '㏰', '/dayseventelegraph': '㏦',
- '/daysixteentelegraph': '㏯', '/daysixtelegraph': '㏥',
- '/daytentelegraph': '㏩', '/daythirteentelegraph': '㏬',
- '/daythirtyonetelegraph': '㏾', '/daythirtytelegraph': '㏽',
- '/daythreetelegraph': '㏢', '/daytwelvetelegraph': '㏫',
- '/daytwentyeighttelegraph': '㏻', '/daytwentyfivetelegraph': '㏸',
- '/daytwentyfourtelegraph': '㏷', '/daytwentyninetelegraph': '㏼',
- '/daytwentyonetelegraph': '㏴', '/daytwentyseventelegraph': '㏺',
- '/daytwentysixtelegraph': '㏹', '/daytwentytelegraph': '㏳',
- '/daytwentythreetelegraph': '㏶', '/daytwentytwotelegraph': '㏵',
- '/daytwotelegraph': '㏡', '/dbdigraph': 'ȸ', '/dbfullwidth': '㏈',
- '/dblGrave': '\uf6d3', '/dblanglebracketleft': '《',
- '/dblanglebracketleftvertical': '︽', '/dblanglebracketright': '》',
- '/dblanglebracketrightvertical': '︾', '/dblarchinvertedbelowcmb': '̫',
- '/dblarrowNE': '⇗', '/dblarrowNW': '⇖', '/dblarrowSE': '⇘',
- '/dblarrowSW': '⇙', '/dblarrowdown': '⇓', '/dblarrowleft': '⇔',
- '/dblarrowleftright': '⇔', '/dblarrowleftrightstroke': '⇎',
- '/dblarrowleftstroke': '⇍', '/dblarrowright': '⇒',
- '/dblarrowrightstroke': '⇏', '/dblarrowup': '⇑', '/dblarrowupdown': '⇕',
- '/dbldanda': '॥', '/dbldnhorz': '╦', '/dbldnleft': '╗', '/dbldnright':
- '╔', '/dblgrave': '\uf6d6', '/dblgravecmb': '̏', '/dblhorz': '═',
- '/dblintegral': '∬', '/dbllowline': '‗', '/dbllowlinecmb': '̳',
- '/dbloverlinecmb': '̿', '/dblprimemod': 'ʺ', '/dblstrokearrowdown': '⇟',
- '/dblstrokearrowup': '⇞', '/dbluphorz': '╩', '/dblupleft': '╝',
- '/dblupright': '╚', '/dblvert': '║', '/dblverthorz': '╬',
- '/dblverticalbar': '‖', '/dblverticallineabovecmb': '̎', '/dblvertleft':
- '╣', '/dblvertright': '╠', '/dbopomofo': 'ㄉ', '/dbsquare': '㏈',
- '/dcaron': 'ď', '/dcedilla': 'ḑ', '/dchecyr': 'ԭ', '/dcircle': 'ⓓ',
- '/dcircumflexbelow': 'ḓ', '/dcroat': 'đ', '/dcurl': 'ȡ', '/ddabengali':
- 'ড', '/ddadeva': 'ड', '/ddagujarati': 'ડ', '/ddagurmukhi': 'ਡ',
- '/ddahal': 'ڍ', '/ddahal.fina': 'ﮃ', '/ddahal.isol': 'ﮂ', '/ddal': 'ڈ',
- '/ddal.fina': 'ﮉ', '/ddal.isol': 'ﮈ', '/ddalarabic': 'ڈ',
- '/ddalfinalarabic': 'ﮉ', '/ddamahaprana': 'ꦞ', '/ddblstruckitalic': 'ⅆ',
- '/dddhadeva': 'ड़', '/ddhabengali': 'ঢ', '/ddhadeva': 'ढ',
- '/ddhagujarati': 'ઢ', '/ddhagurmukhi': 'ਢ', '/ddot': 'ḋ', '/ddotaccent':
- 'ḋ', '/ddotbelow': 'ḍ', '/decembertelegraph': '㋋', '/deciduousTree':
- 'ἳ3', '/decimalexponent': '⏨', '/decimalseparatorarabic': '٫',
- '/decimalseparatorpersian': '٫', '/decreaseFontSize': 'ὝB', '/decyr':
- 'д', '/decyrillic': 'д', '/degree': '°', '/degreecelsius': '℃',
- '/degreefahrenheit': '℉', '/dehi:hb': '֭', '/dehihebrew': '֭',
- '/dehiragana': 'で', '/deicoptic': 'ϯ', '/dekatakana': 'デ', '/dekomicyr':
- 'ԁ', '/deldiaeresisfunc': '⍢', '/deleteleft': '⌫', '/deleteright': '⌦',
- '/deliveryTruck': 'ὩA', '/delstilefunc': '⍒', '/delta': 'δ',
- '/deltaequal': '≜', '/deltastilefunc': '⍋', '/deltaturned': 'ƍ',
- '/deltaunderlinefunc': '⍙', '/deltildefunc': '⍫',
- '/denominatorminusonenumeratorbengali': '৸',
- '/dentistrybottomverticalleft': '⏌', '/dentistrybottomverticalright':
- '⎿', '/dentistrycircledownhorizontal': '⏁',
- '/dentistrycircleuphorizontal': '⏂', '/dentistrycirclevertical': '⏀',
- '/dentistrydownhorizontal': '⏉', '/dentistrytopverticalleft': '⏋',
- '/dentistrytopverticalright': '⎾', '/dentistrytriangledownhorizontal':
- '⏄', '/dentistrytriangleuphorizontal': '⏅',
- '/dentistrytrianglevertical': '⏃', '/dentistryuphorizontal': '⏊',
- '/dentistrywavedownhorizontal': '⏇', '/dentistrywaveuphorizontal': '⏈',
- '/dentistrywavevertical': '⏆', '/departmentStore': 'ἾC',
- '/derelictHouseBuilding': 'ἽA', '/desert': 'ἽC', '/desertIsland': 'ἽD',
- '/desisquare': '㌥', '/desktopComputer': '\u1f5a5', '/desktopWindow':
- 'Ὕ4', '/deva:a': 'अ', '/deva:aa': 'आ', '/deva:aasign': 'ा',
- '/deva:abbreviation': '॰', '/deva:acandra': 'ॲ', '/deva:acute': '॔',
- '/deva:ai': 'ऐ', '/deva:aisign': 'ै', '/deva:anudatta': '॒',
- '/deva:anusvara': 'ं', '/deva:ashort': 'ऄ', '/deva:au': 'औ',
- '/deva:ausign': 'ौ', '/deva:avagraha': 'ऽ', '/deva:aw': 'ॵ',
- '/deva:awsign': 'ॏ', '/deva:ba': 'ब', '/deva:bba': 'ॿ', '/deva:bha':
- 'भ', '/deva:ca': 'च', '/deva:candrabindu': 'ँ',
- '/deva:candrabinduinverted': 'ऀ', '/deva:cha': 'छ', '/deva:da': 'द',
- '/deva:danda': '।', '/deva:dbldanda': '॥', '/deva:dda': 'ड',
- '/deva:ddda': 'ॾ', '/deva:dddha': 'ड़', '/deva:ddha': 'ढ', '/deva:dha':
- 'ध', '/deva:dothigh': 'ॱ', '/deva:e': 'ए', '/deva:ecandra': 'ऍ',
- '/deva:eight': '८', '/deva:eshort': 'ऎ', '/deva:esign': 'े',
- '/deva:esigncandra': 'ॅ', '/deva:esignprishthamatra': 'ॎ',
- '/deva:esignshort': 'ॆ', '/deva:fa': 'फ़', '/deva:five': '५',
- '/deva:four': '४', '/deva:ga': 'ग', '/deva:gga': 'ॻ', '/deva:gha': 'घ',
- '/deva:ghha': 'ग़', '/deva:glottalstop': 'ॽ', '/deva:grave': '॓',
- '/deva:ha': 'ह', '/deva:i': 'इ', '/deva:ii': 'ई', '/deva:iisign': 'ी',
- '/deva:isign': 'ि', '/deva:ja': 'ज', '/deva:jha': 'झ', '/deva:jja': 'ॼ',
- '/deva:ka': 'क', '/deva:kha': 'ख', '/deva:khha': 'ख़', '/deva:la': 'ल',
- '/deva:lla': 'ळ', '/deva:llla': 'ऴ', '/deva:llvocal': 'ॡ',
- '/deva:llvocalsign': 'ॣ', '/deva:lvocal': 'ऌ', '/deva:lvocalsign': 'ॢ',
- '/deva:ma': 'म', '/deva:marwaridda': 'ॸ', '/deva:na': 'न', '/deva:nga':
- 'ङ', '/deva:nine': '९', '/deva:nna': 'ण', '/deva:nnna': 'ऩ',
- '/deva:nukta': '़', '/deva:nya': 'ञ', '/deva:o': 'ओ', '/deva:ocandra':
- 'ऑ', '/deva:oe': 'ॳ', '/deva:oesign': 'ऺ', '/deva:om': 'ॐ', '/deva:one':
- '१', '/deva:ooe': 'ॴ', '/deva:ooesign': 'ऻ', '/deva:oshort': 'ऒ',
- '/deva:osign': 'ो', '/deva:osigncandra': 'ॉ', '/deva:osignshort': 'ॊ',
- '/deva:pa': 'प', '/deva:pha': 'फ', '/deva:qa': 'क़', '/deva:ra': 'र',
- '/deva:rha': 'ढ़', '/deva:rra': 'ऱ', '/deva:rrvocal': 'ॠ',
- '/deva:rrvocalsign': 'ॄ', '/deva:rvocal': 'ऋ', '/deva:rvocalsign': 'ृ',
- '/deva:sa': 'स', '/deva:seven': '७', '/deva:sha': 'श',
- '/deva:signelongcandra': 'ॕ', '/deva:six': '६', '/deva:ssa': 'ष',
- '/deva:ta': 'त', '/deva:tha': 'थ', '/deva:three': '३', '/deva:tta': 'ट',
- '/deva:ttha': 'ठ', '/deva:two': '२', '/deva:u': 'उ', '/deva:udatta':
- '॑', '/deva:ue': 'ॶ', '/deva:uesign': 'ॖ', '/deva:usign': 'ु',
- '/deva:uu': 'ऊ', '/deva:uue': 'ॷ', '/deva:uuesign': 'ॗ', '/deva:uusign':
- 'ू', '/deva:va': 'व', '/deva:virama': '्', '/deva:visarga': 'ः',
- '/deva:ya': 'य', '/deva:yaheavy': 'ॺ', '/deva:yya': 'य़', '/deva:za':
- 'ज़', '/deva:zero': '०', '/deva:zha': 'ॹ', '/dezh': 'ʤ', '/dfemaledbl':
- '⚢', '/dhabengali': 'ধ', '/dhadeva': 'ध', '/dhagujarati': 'ધ',
- '/dhagurmukhi': 'ਧ', '/dhook': 'ɗ', '/diaeresisgreaterfunc': '⍩',
- '/dialytikatonos': '΅', '/dialytikatonoscmb': '̈́', '/diametersign': '⌀',
- '/diamond': '♦', '/diamondShapeADotInside': 'Ὂ0',
- '/diamondinsquarewhite': '⛋', '/diamondoperator': '⋄',
- '/diamondsuitwhite': '♢', '/diamondunderlinefunc': '⍚',
- '/diamondwhitewithdiamondsmallblack': '◈', '/diefive': '⚄', '/diefour':
- '⚃', '/dieone': '⚀', '/dieresis': '¨', '/dieresisacute': '\uf6d7',
- '/dieresisbelowcmb': '̤', '/dieresiscmb': '̈', '/dieresisgrave':
- '\uf6d8', '/dieresistilde': '῁', '/dieresistonos': '΅',
- '/dieselLocomotive': 'Ὧ2', '/diesix': '⚅', '/diethree': '⚂', '/dietwo':
- '⚁', '/differencebetween': '≏', '/digamma': 'ϝ', '/digammapamphylian':
- 'ͷ', '/digramgreateryang': '⚌', '/digramgreateryin': '⚏',
- '/digramlesseryang': '⚎', '/digramlesseryin': '⚍', '/dihiragana': 'ぢ',
- '/dikatakana': 'ヂ', '/dimensionorigin': '⌱',
- '/dingbatSAns-serifzerocircle': 'ἐB',
- '/dingbatSAns-serifzerocircleblack': 'ἐC', '/dinsular': 'ꝺ',
- '/directHit': 'ἺF', '/directcurrentformtwo': '⎓', '/dirgamurevowel':
- 'ꦻ', '/disabledcar': '⛍', '/disappointedButRelievedFace': 'ὢ5',
- '/disappointedFace': 'ὡE', '/discontinuousunderline': '⎂', '/dittomark':
- '〃', '/divide': '÷', '/divides': '∣', '/divisionslash': '∕',
- '/divisiontimes': '⋇', '/divorce': '⚮', '/dizzy': 'ὊB', '/dizzyFace':
- 'ὣ5', '/djecyr': 'ђ', '/djecyrillic': 'ђ', '/djekomicyr': 'ԃ',
- '/dkshade': '▓', '/dlfullwidth': '㎗', '/dlinebelow': 'ḏ',
- '/dlogicalorsquare': '⟏', '/dlogicalsquare': '⟎', '/dlsquare': '㎗',
- '/dm2fullwidth': '㍸', '/dm3fullwidth': '㍹', '/dmacron': 'đ',
- '/dmaledbl': '⚣', '/dmfullwidth': '㍷', '/dmonospace': 'd', '/dnblock':
- '▄', '/dndblhorzsng': '╥', '/dndblleftsng': '╖', '/dndblrightsng': '╓',
- '/dngb:airplane': '✈', '/dngb:arrowfeatheredblackNE': '➶',
- '/dngb:arrowfeatheredblackSE': '➴', '/dngb:arrowfeatheredblackheavyNE':
- '➹', '/dngb:arrowfeatheredblackheavySE': '➷',
- '/dngb:arrowheadrightblack': '➤',
- '/dngb:arrowheadrightthreeDbottomlight': '➣',
- '/dngb:arrowheadrightthreeDtoplight': '➢', '/dngb:arrowheavyNE': '➚',
- '/dngb:arrowheavySE': '➘', '/dngb:arrowrightbacktiltedshadowedwhite':
- '➫', '/dngb:arrowrightblack': '➡', '/dngb:arrowrightcircledwhiteheavy':
- '➲', '/dngb:arrowrightcurvedownblackheavy': '➥',
- '/dngb:arrowrightcurveupblackheavy': '➦',
- '/dngb:arrowrightfeatheredblack': '➵',
- '/dngb:arrowrightfeatheredblackheavy': '➸',
- '/dngb:arrowrightfeatheredwhite': '➳',
- '/dngb:arrowrightfronttiltedshadowedwhite': '➬',
- '/dngb:arrowrightheavy': '➙', '/dngb:arrowrightleftshadedwhite': '➪',
- '/dngb:arrowrightoutlinedopen': '➾', '/dngb:arrowrightpointed': '➛',
- '/dngb:arrowrightpointedblackheavy': '➨',
- '/dngb:arrowrightrightshadedwhite': '➩', '/dngb:arrowrightroundheavy':
- '➜', '/dngb:arrowrightsquatblack': '➧', '/dngb:arrowrighttriangle': '➝',
- '/dngb:arrowrighttriangledashed': '➟',
- '/dngb:arrowrighttriangledashedheavy': '➠',
- '/dngb:arrowrighttriangleheavy': '➞', '/dngb:arrowrightwedge': '➼',
- '/dngb:arrowrightwedgeheavy': '➽', '/dngb:arrowrightwideheavy': '➔',
- '/dngb:arrowshadowrightlowerwhiteheavy': '➭',
- '/dngb:arrowshadowrightnotchedlowerwhite': '➯',
- '/dngb:arrowshadowrightnotchedupperwhite': '➱',
- '/dngb:arrowshadowrightupperwhiteheavy': '➮',
- '/dngb:arrowteardropright': '➺', '/dngb:arrowteardroprightheavy': '➻',
- '/dngb:asteriskballoon': '❉', '/dngb:asteriskballoonfour': '✣',
- '/dngb:asteriskballoonheavyfour': '✤', '/dngb:asteriskcentreopen': '✲',
- '/dngb:asteriskclubfour': '✥', '/dngb:asteriskheavy': '✱',
- '/dngb:asteriskpointedsixteen': '✺', '/dngb:asteriskteardrop': '✻',
- '/dngb:asteriskteardropcentreopen': '✼', '/dngb:asteriskteardropfour':
- '✢', '/dngb:asteriskteardropheavy': '✽',
- '/dngb:asteriskteardroppinwheelheavy': '❃',
- '/dngb:asteriskteardroppropellereight': '❊',
- '/dngb:asteriskteardroppropellerheavyeight': '❋', '/dngb:ballotx': '✗',
- '/dngb:ballotxheavy': '✘', '/dngb:bracketleftpointedangleheavyornament':
- '❰', '/dngb:bracketleftpointedanglemediumornament': '❬',
- '/dngb:bracketrightpointedangleheavyornament': '❱',
- '/dngb:bracketrightpointedanglemediumornament': '❭',
- '/dngb:bracketshellleftlightornament': '❲',
- '/dngb:bracketshellrightlightornament': '❳', '/dngb:check': '✓',
- '/dngb:checkheavy': '✔', '/dngb:checkwhiteheavy': '✅',
- '/dngb:chevronsnowflakeheavy': '❆', '/dngb:circleshadowedwhite': '❍',
- '/dngb:commaheavydoubleornament': '❞',
- '/dngb:commaheavydoubleturnedornament': '❝', '/dngb:commaheavyornament':
- '❜', '/dngb:commaheavyturnedornament': '❛',
- '/dngb:compasstarpointedblackeight': '✷',
- '/dngb:compasstarpointedblackheavyeight': '✸', '/dngb:cross': '❌',
- '/dngb:crosscentreopen': '✛', '/dngb:crosscentreopenheavy': '✜',
- '/dngb:curlybracketleftmediumornament': '❴',
- '/dngb:curlybracketrightmediumornament': '❵', '/dngb:curlyloop': '➰',
- '/dngb:curlyloopdouble': '➿', '/dngb:curvedstemparagraphsignornament':
- '❡', '/dngb:diamondminusxblackwhite': '❖', '/dngb:divisionsignheavy':
- '➗', '/dngb:eightnegativecircled': '❽', '/dngb:eightsanscircled': '➇',
- '/dngb:eightsansnegativecircled': '➑', '/dngb:envelope': '✉',
- '/dngb:exclamationheavy': '❗', '/dngb:exclamationheavyornament': '❢',
- '/dngb:exclamationwhiteornament': '❕', '/dngb:fivenegativecircled': '❺',
- '/dngb:fivesanscircled': '➄', '/dngb:fivesansnegativecircled': '➎',
- '/dngb:floralheart': '❦', '/dngb:floralheartbulletrotated': '❧',
- '/dngb:floretteblack': '✿', '/dngb:floretteoutlinedpetalledblackeight':
- '❁', '/dngb:florettepetalledblackwhitesix': '✾', '/dngb:florettewhite':
- '❀', '/dngb:fournegativecircled': '❹', '/dngb:foursanscircled': '➃',
- '/dngb:foursansnegativecircled': '➍', '/dngb:greekcrossheavy': '✚',
- '/dngb:greekcrossoutlined': '✙', '/dngb:heartblackheavy': '❤',
- '/dngb:heartbulletrotatedblackheavy': '❥',
- '/dngb:heartexclamationheavyornament': '❣', '/dngb:hvictory': '✌',
- '/dngb:hwriting': '✍', '/dngb:latincross': '✝',
- '/dngb:latincrossoutlined': '✟', '/dngb:latincrossshadowedwhite': '✞',
- '/dngb:lowcommaheavydoubleornament': '❠', '/dngb:lowcommaheavyornament':
- '❟', '/dngb:maltesecross': '✠', '/dngb:minussignheavy': '➖',
- '/dngb:multiplicationx': '✕', '/dngb:multiplicationxheavy': '✖',
- '/dngb:nibblack': '✒', '/dngb:nibwhite': '✑',
- '/dngb:ninenegativecircled': '❾', '/dngb:ninesanscircled': '➈',
- '/dngb:ninesansnegativecircled': '➒', '/dngb:onenegativecircled': '❶',
- '/dngb:onesanscircled': '➀', '/dngb:onesansnegativecircled': '➊',
- '/dngb:parenthesisleftflattenedmediumornament': '❪',
- '/dngb:parenthesisleftmediumornament': '❨',
- '/dngb:parenthesisrightflattenedmediumornament': '❫',
- '/dngb:parenthesisrightmediumornament': '❩', '/dngb:pencil': '✏',
- '/dngb:pencillowerright': '✎', '/dngb:pencilupperright': '✐',
- '/dngb:plussignheavy': '➕', '/dngb:questionblackornament': '❓',
- '/dngb:questionwhiteornament': '❔',
- '/dngb:quotationleftpointedangleheavyornament': '❮',
- '/dngb:quotationrightpointedangleheavyornament': '❯',
- '/dngb:raisedfist': '✊', '/dngb:raisedh': '✋',
- '/dngb:safetyscissorsblack': '✀', '/dngb:scissorsblack': '✂',
- '/dngb:scissorslowerblade': '✃', '/dngb:scissorsupperblade': '✁',
- '/dngb:scissorswhite': '✄', '/dngb:sevennegativecircled': '❼',
- '/dngb:sevensanscircled': '➆', '/dngb:sevensansnegativecircled': '➐',
- '/dngb:sixnegativecircled': '❻', '/dngb:sixsanscircled': '➅',
- '/dngb:sixsansnegativecircled': '➏', '/dngb:snowflake': '❄',
- '/dngb:snowflaketight': '❅', '/dngb:sparkle': '❇', '/dngb:sparkleheavy':
- '❈', '/dngb:sparkles': '✨', '/dngb:spokedasteriskeight': '✳',
- '/dngb:squaredcrossnegative': '❎',
- '/dngb:squarelowerrightshadowedwhite': '❑',
- '/dngb:squareshadowlowerrightwhite': '❏',
- '/dngb:squareshadowupperrightwhite': '❐',
- '/dngb:squareupperrightshadowedwhite': '❒',
- '/dngb:starcentreblackwhite': '✬', '/dngb:starcentreopenblack': '✫',
- '/dngb:starcentreopenpointedcircledeight': '❂',
- '/dngb:starcircledwhite': '✪', '/dngb:starofdavid': '✡',
- '/dngb:staroutlinedblack': '✭', '/dngb:staroutlinedblackheavy': '✮',
- '/dngb:staroutlinedstresswhite': '✩', '/dngb:starpinwheel': '✯',
- '/dngb:starpointedblackeight': '✴', '/dngb:starpointedblackfour': '✦',
- '/dngb:starpointedblacksix': '✶', '/dngb:starpointedblacktwelve': '✹',
- '/dngb:starpointedpinwheeleight': '✵', '/dngb:starpointedwhitefour':
- '✧', '/dngb:starshadowedwhite': '✰', '/dngb:tapedrive': '✇',
- '/dngb:telephonelocationsign': '✆', '/dngb:tennegativecircled': '❿',
- '/dngb:tensanscircled': '➉', '/dngb:tensansnegativecircled': '➓',
- '/dngb:threenegativecircled': '❸', '/dngb:threesanscircled': '➂',
- '/dngb:threesansnegativecircled': '➌', '/dngb:twonegativecircled': '❷',
- '/dngb:twosanscircled': '➁', '/dngb:twosansnegativecircled': '➋',
- '/dngb:verticalbarheavy': '❚', '/dngb:verticalbarlight': '❘',
- '/dngb:verticalbarmedium': '❙', '/dnheavyhorzlight': '┰',
- '/dnheavyleftlight': '┒', '/dnheavyleftuplight': '┧',
- '/dnheavyrightlight': '┎', '/dnheavyrightuplight': '┟',
- '/dnheavyuphorzlight': '╁', '/dnlighthorzheavy': '┯',
- '/dnlightleftheavy': '┑', '/dnlightleftupheavy': '┩',
- '/dnlightrightheavy': '┍', '/dnlightrightupheavy': '┡',
- '/dnlightuphorzheavy': '╇', '/dnsnghorzdbl': '╤', '/dnsngleftdbl': '╕',
- '/dnsngrightdbl': '╒', '/doNotLitter': 'ὪF', '/dochadathai': 'ฎ',
- '/document': '\u1f5cE', '/documentPicture': 'ὛB', '/documentText': 'Ὓ9',
- '/documentTextAndPicture': 'ὛA', '/dodekthai': 'ด',
- '/doesnotcontainasnormalsubgroorequalup': '⋭',
- '/doesnotcontainasnormalsubgroup': '⋫', '/doesnotdivide': '∤',
- '/doesnotforce': '⊮', '/doesnotprecede': '⊀', '/doesnotprecedeorequal':
- '⋠', '/doesnotprove': '⊬', '/doesnotsucceed': '⊁',
- '/doesnotsucceedorequal': '⋡', '/dog': 'ὁ5', '/dogFace': 'ὃ6',
- '/dohiragana': 'ど', '/dokatakana': 'ド', '/dollar': '$',
- '/dollarinferior': '\uf6e3', '/dollarmonospace': '$', '/dollaroldstyle':
- '\uf724', '/dollarsmall': '﹩', '/dollarsuperior': '\uf6e4', '/dolphin':
- 'ὂC', '/dominohorizontal_00_00': 'ἃ1', '/dominohorizontal_00_01': 'ἃ2',
- '/dominohorizontal_00_02': 'ἃ3', '/dominohorizontal_00_03': 'ἃ4',
- '/dominohorizontal_00_04': 'ἃ5', '/dominohorizontal_00_05': 'ἃ6',
- '/dominohorizontal_00_06': 'ἃ7', '/dominohorizontal_01_00': 'ἃ8',
- '/dominohorizontal_01_01': 'ἃ9', '/dominohorizontal_01_02': 'ἃA',
- '/dominohorizontal_01_03': 'ἃB', '/dominohorizontal_01_04': 'ἃC',
- '/dominohorizontal_01_05': 'ἃD', '/dominohorizontal_01_06': 'ἃE',
- '/dominohorizontal_02_00': 'ἃF', '/dominohorizontal_02_01': 'ἄ0',
- '/dominohorizontal_02_02': 'ἄ1', '/dominohorizontal_02_03': 'ἄ2',
- '/dominohorizontal_02_04': 'ἄ3', '/dominohorizontal_02_05': 'ἄ4',
- '/dominohorizontal_02_06': 'ἄ5', '/dominohorizontal_03_00': 'ἄ6',
- '/dominohorizontal_03_01': 'ἄ7', '/dominohorizontal_03_02': 'ἄ8',
- '/dominohorizontal_03_03': 'ἄ9', '/dominohorizontal_03_04': 'ἄA',
- '/dominohorizontal_03_05': 'ἄB', '/dominohorizontal_03_06': 'ἄC',
- '/dominohorizontal_04_00': 'ἄD', '/dominohorizontal_04_01': 'ἄE',
- '/dominohorizontal_04_02': 'ἄF', '/dominohorizontal_04_03': 'ἅ0',
- '/dominohorizontal_04_04': 'ἅ1', '/dominohorizontal_04_05': 'ἅ2',
- '/dominohorizontal_04_06': 'ἅ3', '/dominohorizontal_05_00': 'ἅ4',
- '/dominohorizontal_05_01': 'ἅ5', '/dominohorizontal_05_02': 'ἅ6',
- '/dominohorizontal_05_03': 'ἅ7', '/dominohorizontal_05_04': 'ἅ8',
- '/dominohorizontal_05_05': 'ἅ9', '/dominohorizontal_05_06': 'ἅA',
- '/dominohorizontal_06_00': 'ἅB', '/dominohorizontal_06_01': 'ἅC',
- '/dominohorizontal_06_02': 'ἅD', '/dominohorizontal_06_03': 'ἅE',
- '/dominohorizontal_06_04': 'ἅF', '/dominohorizontal_06_05': 'ἆ0',
- '/dominohorizontal_06_06': 'ἆ1', '/dominohorizontalback': 'ἃ0',
- '/dominovertical_00_00': 'ἆ3', '/dominovertical_00_01': 'ἆ4',
- '/dominovertical_00_02': 'ἆ5', '/dominovertical_00_03': 'ἆ6',
- '/dominovertical_00_04': 'ἆ7', '/dominovertical_00_05': 'ἆ8',
- '/dominovertical_00_06': 'ἆ9', '/dominovertical_01_00': 'ἆA',
- '/dominovertical_01_01': 'ἆB', '/dominovertical_01_02': 'ἆC',
- '/dominovertical_01_03': 'ἆD', '/dominovertical_01_04': 'ἆE',
- '/dominovertical_01_05': 'ἆF', '/dominovertical_01_06': 'ἇ0',
- '/dominovertical_02_00': 'ἇ1', '/dominovertical_02_01': 'ἇ2',
- '/dominovertical_02_02': 'ἇ3', '/dominovertical_02_03': 'ἇ4',
- '/dominovertical_02_04': 'ἇ5', '/dominovertical_02_05': 'ἇ6',
- '/dominovertical_02_06': 'ἇ7', '/dominovertical_03_00': 'ἇ8',
- '/dominovertical_03_01': 'ἇ9', '/dominovertical_03_02': 'ἇA',
- '/dominovertical_03_03': 'ἇB', '/dominovertical_03_04': 'ἇC',
- '/dominovertical_03_05': 'ἇD', '/dominovertical_03_06': 'ἇE',
- '/dominovertical_04_00': 'ἇF', '/dominovertical_04_01': 'Ἀ0',
- '/dominovertical_04_02': 'Ἀ1', '/dominovertical_04_03': 'Ἀ2',
- '/dominovertical_04_04': 'Ἀ3', '/dominovertical_04_05': 'Ἀ4',
- '/dominovertical_04_06': 'Ἀ5', '/dominovertical_05_00': 'Ἀ6',
- '/dominovertical_05_01': 'Ἀ7', '/dominovertical_05_02': 'Ἀ8',
- '/dominovertical_05_03': 'Ἀ9', '/dominovertical_05_04': 'ἈA',
- '/dominovertical_05_05': 'ἈB', '/dominovertical_05_06': 'ἈC',
- '/dominovertical_06_00': 'ἈD', '/dominovertical_06_01': 'ἈE',
- '/dominovertical_06_02': 'ἈF', '/dominovertical_06_03': 'Ἁ0',
- '/dominovertical_06_04': 'Ἁ1', '/dominovertical_06_05': 'Ἁ2',
- '/dominovertical_06_06': 'Ἁ3', '/dominoverticalback': 'ἆ2', '/dong':
- '₫', '/door': 'ὪA', '/dorusquare': '㌦', '/dot': '⟑', '/dotaccent': '˙',
- '/dotaccentcmb': '̇', '/dotbelowcmb': '̣', '/dotbelowcomb': '̣',
- '/dotkatakana': '・', '/dotlessbeh': 'ٮ', '/dotlessfeh': 'ڡ',
- '/dotlessi': 'ı', '/dotlessj': '\uf6be', '/dotlessjstroke': 'ɟ',
- '/dotlessjstrokehook': 'ʄ', '/dotlesskhahabove': 'ۡ', '/dotlessqaf':
- 'ٯ', '/dotlower:hb': 'ׅ', '/dotmath': '⋅', '/dotminus': '∸', '/dotplus':
- '∔', '/dotraised': '⸳', '/dots1': '⠁', '/dots12': '⠃', '/dots123': '⠇',
- '/dots1234': '⠏', '/dots12345': '⠟', '/dots123456': '⠿', '/dots1234567':
- '⡿', '/dots12345678': '⣿', '/dots1234568': '⢿', '/dots123457': '⡟',
- '/dots1234578': '⣟', '/dots123458': '⢟', '/dots12346': '⠯',
- '/dots123467': '⡯', '/dots1234678': '⣯', '/dots123468': '⢯',
- '/dots12347': '⡏', '/dots123478': '⣏', '/dots12348': '⢏', '/dots1235':
- '⠗', '/dots12356': '⠷', '/dots123567': '⡷', '/dots1235678': '⣷',
- '/dots123568': '⢷', '/dots12357': '⡗', '/dots123578': '⣗', '/dots12358':
- '⢗', '/dots1236': '⠧', '/dots12367': '⡧', '/dots123678': '⣧',
- '/dots12368': '⢧', '/dots1237': '⡇', '/dots12378': '⣇', '/dots1238':
- '⢇', '/dots124': '⠋', '/dots1245': '⠛', '/dots12456': '⠻',
- '/dots124567': '⡻', '/dots1245678': '⣻', '/dots124568': '⢻',
- '/dots12457': '⡛', '/dots124578': '⣛', '/dots12458': '⢛', '/dots1246':
- '⠫', '/dots12467': '⡫', '/dots124678': '⣫', '/dots12468': '⢫',
- '/dots1247': '⡋', '/dots12478': '⣋', '/dots1248': '⢋', '/dots125': '⠓',
- '/dots1256': '⠳', '/dots12567': '⡳', '/dots125678': '⣳', '/dots12568':
- '⢳', '/dots1257': '⡓', '/dots12578': '⣓', '/dots1258': '⢓', '/dots126':
- '⠣', '/dots1267': '⡣', '/dots12678': '⣣', '/dots1268': '⢣', '/dots127':
- '⡃', '/dots1278': '⣃', '/dots128': '⢃', '/dots13': '⠅', '/dots134': '⠍',
- '/dots1345': '⠝', '/dots13456': '⠽', '/dots134567': '⡽', '/dots1345678':
- '⣽', '/dots134568': '⢽', '/dots13457': '⡝', '/dots134578': '⣝',
- '/dots13458': '⢝', '/dots1346': '⠭', '/dots13467': '⡭', '/dots134678':
- '⣭', '/dots13468': '⢭', '/dots1347': '⡍', '/dots13478': '⣍',
- '/dots1348': '⢍', '/dots135': '⠕', '/dots1356': '⠵', '/dots13567': '⡵',
- '/dots135678': '⣵', '/dots13568': '⢵', '/dots1357': '⡕', '/dots13578':
- '⣕', '/dots1358': '⢕', '/dots136': '⠥', '/dots1367': '⡥', '/dots13678':
- '⣥', '/dots1368': '⢥', '/dots137': '⡅', '/dots1378': '⣅', '/dots138':
- '⢅', '/dots14': '⠉', '/dots145': '⠙', '/dots1456': '⠹', '/dots14567':
- '⡹', '/dots145678': '⣹', '/dots14568': '⢹', '/dots1457': '⡙',
- '/dots14578': '⣙', '/dots1458': '⢙', '/dots146': '⠩', '/dots1467': '⡩',
- '/dots14678': '⣩', '/dots1468': '⢩', '/dots147': '⡉', '/dots1478': '⣉',
- '/dots148': '⢉', '/dots15': '⠑', '/dots156': '⠱', '/dots1567': '⡱',
- '/dots15678': '⣱', '/dots1568': '⢱', '/dots157': '⡑', '/dots1578': '⣑',
- '/dots158': '⢑', '/dots16': '⠡', '/dots167': '⡡', '/dots1678': '⣡',
- '/dots168': '⢡', '/dots17': '⡁', '/dots178': '⣁', '/dots18': '⢁',
- '/dots2': '⠂', '/dots23': '⠆', '/dots234': '⠎', '/dots2345': '⠞',
- '/dots23456': '⠾', '/dots234567': '⡾', '/dots2345678': '⣾',
- '/dots234568': '⢾', '/dots23457': '⡞', '/dots234578': '⣞', '/dots23458':
- '⢞', '/dots2346': '⠮', '/dots23467': '⡮', '/dots234678': '⣮',
- '/dots23468': '⢮', '/dots2347': '⡎', '/dots23478': '⣎', '/dots2348':
- '⢎', '/dots235': '⠖', '/dots2356': '⠶', '/dots23567': '⡶',
- '/dots235678': '⣶', '/dots23568': '⢶', '/dots2357': '⡖', '/dots23578':
- '⣖', '/dots2358': '⢖', '/dots236': '⠦', '/dots2367': '⡦', '/dots23678':
- '⣦', '/dots2368': '⢦', '/dots237': '⡆', '/dots2378': '⣆', '/dots238':
- '⢆', '/dots24': '⠊', '/dots245': '⠚', '/dots2456': '⠺', '/dots24567':
- '⡺', '/dots245678': '⣺', '/dots24568': '⢺', '/dots2457': '⡚',
- '/dots24578': '⣚', '/dots2458': '⢚', '/dots246': '⠪', '/dots2467': '⡪',
- '/dots24678': '⣪', '/dots2468': '⢪', '/dots247': '⡊', '/dots2478': '⣊',
- '/dots248': '⢊', '/dots25': '⠒', '/dots256': '⠲', '/dots2567': '⡲',
- '/dots25678': '⣲', '/dots2568': '⢲', '/dots257': '⡒', '/dots2578': '⣒',
- '/dots258': '⢒', '/dots26': '⠢', '/dots267': '⡢', '/dots2678': '⣢',
- '/dots268': '⢢', '/dots27': '⡂', '/dots278': '⣂', '/dots28': '⢂',
- '/dots3': '⠄', '/dots34': '⠌', '/dots345': '⠜', '/dots3456': '⠼',
- '/dots34567': '⡼', '/dots345678': '⣼', '/dots34568': '⢼', '/dots3457':
- '⡜', '/dots34578': '⣜', '/dots3458': '⢜', '/dots346': '⠬', '/dots3467':
- '⡬', '/dots34678': '⣬', '/dots3468': '⢬', '/dots347': '⡌', '/dots3478':
- '⣌', '/dots348': '⢌', '/dots35': '⠔', '/dots356': '⠴', '/dots3567': '⡴',
- '/dots35678': '⣴', '/dots3568': '⢴', '/dots357': '⡔', '/dots3578': '⣔',
- '/dots358': '⢔', '/dots36': '⠤', '/dots367': '⡤', '/dots3678': '⣤',
- '/dots368': '⢤', '/dots37': '⡄', '/dots378': '⣄', '/dots38': '⢄',
- '/dots4': '⠈', '/dots45': '⠘', '/dots456': '⠸', '/dots4567': '⡸',
- '/dots45678': '⣸', '/dots4568': '⢸', '/dots457': '⡘', '/dots4578': '⣘',
- '/dots458': '⢘', '/dots46': '⠨', '/dots467': '⡨', '/dots4678': '⣨',
- '/dots468': '⢨', '/dots47': '⡈', '/dots478': '⣈', '/dots48': '⢈',
- '/dots5': '⠐', '/dots56': '⠰', '/dots567': '⡰', '/dots5678': '⣰',
- '/dots568': '⢰', '/dots57': '⡐', '/dots578': '⣐', '/dots58': '⢐',
- '/dots6': '⠠', '/dots67': '⡠', '/dots678': '⣠', '/dots68': '⢠',
- '/dots7': '⡀', '/dots78': '⣀', '/dots8': '⢀', '/dotsquarefour': '⸬',
- '/dottedcircle': '◌', '/dottedcross': '⁜', '/dotupper:hb': 'ׄ',
- '/doublebarvertical': '⏸', '/doubleyodpatah': 'ײַ',
- '/doubleyodpatahhebrew': 'ײַ', '/doughnut': 'ἶ9', '/doveOfPeace': 'ὔA',
- '/downtackbelowcmb': '̞', '/downtackmod': '˕',
- '/downwarrowleftofuparrow': '⇵', '/dparen': '⒟', '/dparenthesized': '⒟',
- '/drachma': '₯', '/dragon': 'ὀ9', '/dragonFace': 'ὃ2',
- '/draughtskingblack': '⛃', '/draughtskingwhite': '⛁',
- '/draughtsmanblack': '⛂', '/draughtsmanwhite': '⛀', '/dress': 'ὅ7',
- '/driveslow': '⛚', '/dromedaryCamel': 'ὂA', '/droplet': 'Ὂ7',
- '/dsquare': 'Ἒ5', '/dsuperior': '\uf6eb', '/dtail': 'ɖ', '/dtopbar':
- 'ƌ', '/duhiragana': 'づ', '/dukatakana': 'ヅ', '/dul': 'ڎ', '/dul.fina':
- 'ﮇ', '/dul.isol': 'ﮆ', '/dum': 'ꝱ', '/dvd': 'Ὄ0', '/dyeh': 'ڄ',
- '/dyeh.fina': 'ﭳ', '/dyeh.init': 'ﭴ', '/dyeh.isol': 'ﭲ', '/dyeh.medi':
- 'ﭵ', '/dz': 'dz', '/dzaltone': 'ʣ', '/dzcaron': 'dž', '/dzcurl': 'ʥ',
- '/dzeabkhasiancyrillic': 'ӡ', '/dzeabkhcyr': 'ӡ', '/dzecyr': 'ѕ',
- '/dzecyrillic': 'ѕ', '/dzed': 'ʣ', '/dzedcurl': 'ʥ', '/dzhecyr': 'џ',
- '/dzhecyrillic': 'џ', '/dzjekomicyr': 'ԇ', '/dzzhecyr': 'ԫ', '/e': 'e',
- '/e-mail': '\u1f4e7', '/e.fina': 'ﯥ', '/e.inferior': 'ₑ', '/e.init':
- 'ﯦ', '/e.isol': 'ﯤ', '/e.medi': 'ﯧ', '/eVfullwidth': '㋎', '/eacute':
- 'é', '/earOfMaize': 'ἳD', '/earOfRice': 'ἳE', '/earth': '♁',
- '/earthGlobeAmericas': 'ἰE', '/earthGlobeAsiaAustralia': 'ἰF',
- '/earthGlobeEuropeAfrica': 'ἰD', '/earthground': '⏚',
- '/earthideographiccircled': '㊏', '/earthideographicparen': '㈯',
- '/eastsyriaccross': '♱', '/ebengali': 'এ', '/ebopomofo': 'ㄜ', '/ebreve':
- 'ĕ', '/ecandradeva': 'ऍ', '/ecandragujarati': 'ઍ',
- '/ecandravowelsigndeva': 'ॅ', '/ecandravowelsigngujarati': 'ૅ',
- '/ecaron': 'ě', '/ecedilla': 'ȩ', '/ecedillabreve': 'ḝ', '/echarmenian':
- 'ե', '/echyiwnarmenian': 'և', '/ecircle': 'ⓔ', '/ecirclekatakana': '㋓',
- '/ecircumflex': 'ê', '/ecircumflexacute': 'ế', '/ecircumflexbelow': 'ḙ',
- '/ecircumflexdotbelow': 'ệ', '/ecircumflexgrave': 'ề',
- '/ecircumflexhoi': 'ể', '/ecircumflexhookabove': 'ể',
- '/ecircumflextilde': 'ễ', '/ecyrillic': 'є', '/edblgrave': 'ȅ',
- '/edblstruckitalic': 'ⅇ', '/edeva': 'ए', '/edieresis': 'ë', '/edot':
- 'ė', '/edotaccent': 'ė', '/edotbelow': 'ẹ', '/eegurmukhi': 'ਏ',
- '/eekaasquare': '㌈', '/eematragurmukhi': 'ੇ', '/efcyr': 'ф',
- '/efcyrillic': 'ф', '/egrave': 'è', '/egravedbl': 'ȅ', '/egujarati':
- 'એ', '/egyptain': 'ꜥ', '/egyptalef': 'ꜣ', '/eharmenian': 'է',
- '/ehbopomofo': 'ㄝ', '/ehiragana': 'え', '/ehoi': 'ẻ', '/ehookabove': 'ẻ',
- '/eibopomofo': 'ㄟ', '/eight': '8', '/eight.inferior': '₈',
- '/eight.roman': 'Ⅷ', '/eight.romansmall': 'ⅷ', '/eight.superior': '⁸',
- '/eightarabic': '٨', '/eightbengali': '৮', '/eightcircle': '⑧',
- '/eightcircledbl': '⓼', '/eightcircleinversesansserif': '➑',
- '/eightcomma': 'ἐ9', '/eightdeva': '८', '/eighteencircle': '⑱',
- '/eighteencircleblack': '⓲', '/eighteenparen': '⒅',
- '/eighteenparenthesized': '⒅', '/eighteenperiod': '⒙', '/eightfar': '۸',
- '/eightgujarati': '૮', '/eightgurmukhi': '੮', '/eighthackarabic': '٨',
- '/eighthangzhou': '〨', '/eighthnote': '♪', '/eighthnotebeamed': '♫',
- '/eightideographiccircled': '㊇', '/eightideographicparen': '㈧',
- '/eightinferior': '₈', '/eightksquare': 'ἙF', '/eightmonospace': '8',
- '/eightoldstyle': '\uf738', '/eightparen': '⑻', '/eightparenthesized':
- '⑻', '/eightperiod': '⒏', '/eightpersian': '۸', '/eightroman': 'ⅷ',
- '/eightsuperior': '⁸', '/eightthai': '๘', '/eightycirclesquare': '㉏',
- '/einvertedbreve': 'ȇ', '/eiotifiedcyr': 'ѥ', '/eiotifiedcyrillic': 'ѥ',
- '/eject': '⏏', '/ekatakana': 'エ', '/ekatakanahalfwidth': 'エ',
- '/ekonkargurmukhi': 'ੴ', '/ekorean': 'ㅔ', '/elcyr': 'л', '/elcyrillic':
- 'л', '/electricLightBulb': 'Ὂ1', '/electricPlug': 'ὐC',
- '/electricTorch': 'ὒ6', '/electricalintersection': '⏧',
- '/electricarrow': '⌁', '/element': '∈', '/elementdotabove': '⋵',
- '/elementlonghorizontalstroke': '⋲', '/elementopeningup': '⟒',
- '/elementoverbar': '⋶', '/elementoverbarsmall': '⋷', '/elementsmall':
- '∊', '/elementsmallverticalbarhorizontalstroke': '⋴',
- '/elementtwoshorizontalstroke': '⋹', '/elementunderbar': '⋸',
- '/elementverticalbarhorizontalstroke': '⋳', '/elephant': 'ὁ8',
- '/eleven.roman': 'Ⅺ', '/eleven.romansmall': 'ⅺ', '/elevencircle': '⑪',
- '/elevencircleblack': '⓫', '/elevenparen': '⑾', '/elevenparenthesized':
- '⑾', '/elevenperiod': '⒒', '/elevenroman': 'ⅺ', '/elhookcyr': 'ԓ',
- '/ellipsis': '…', '/ellipsisdiagonaldownright': '⋱',
- '/ellipsisdiagonalupright': '⋰', '/ellipsismidhorizontal': '⋯',
- '/ellipsisvertical': '⋮', '/elmiddlehookcyr': 'ԡ', '/elsharptailcyr':
- 'ӆ', '/eltailcyr': 'ԯ', '/emacron': 'ē', '/emacronacute': 'ḗ',
- '/emacrongrave': 'ḕ', '/emcyr': 'м', '/emcyrillic': 'м', '/emdash': '—',
- '/emdashdbl': '⸺', '/emdashtpl': '⸻', '/emdashvertical': '︱',
- '/emojiModifierFitzpatrickType-1-2': 'ἿB',
- '/emojiModifierFitzpatrickType-3': 'ἿC',
- '/emojiModifierFitzpatrickType-4': 'ἿD',
- '/emojiModifierFitzpatrickType-5': 'ἿE',
- '/emojiModifierFitzpatrickType-6': 'ἿF', '/emonospace': 'e',
- '/emphasis': '⎃', '/emphasismarkarmenian': '՛', '/emptyDocument':
- '\u1f5cB', '/emptyNote': '\u1f5c5', '/emptyNotePad': '\u1f5c7',
- '/emptyNotePage': '\u1f5c6', '/emptyPage': '\u1f5cC', '/emptyPages':
- '\u1f5cD', '/emptyset': '∅', '/emquad': '\u2001', '/emsharptailcyr':
- 'ӎ', '/emspace': '\u2003', '/enbopomofo': 'ㄣ', '/encyr': 'н',
- '/encyrillic': 'н', '/endLeftwardsArrowAbove': 'ὑA', '/endash': '–',
- '/endashvertical': '︲', '/endescendercyrillic': 'ң', '/endpro': '∎',
- '/eng': 'ŋ', '/engbopomofo': 'ㄥ', '/engecyr': 'ҥ', '/enghecyrillic':
- 'ҥ', '/enhookcyr': 'ӈ', '/enhookcyrillic': 'ӈ', '/enhookleftcyr': 'ԩ',
- '/enmiddlehookcyr': 'ԣ', '/enotch': 'ⱸ', '/enquad': '\u2000',
- '/ensharptailcyr': 'ӊ', '/enspace': '\u2002', '/entailcyr': 'ң',
- '/enter': '⎆', '/enterpriseideographiccircled': '㊭',
- '/enterpriseideographicparen': '㈽', '/envelopeDownwardsArrowAbove':
- '\u1f4e9', '/envelopeLightning': '\u1f584', '/eogonek': 'ę',
- '/eokorean': 'ㅓ', '/eopen': 'ɛ', '/eopenclosed': 'ʚ', '/eopenreversed':
- 'ɜ', '/eopenreversedclosed': 'ɞ', '/eopenreversedhook': 'ɝ', '/eparen':
- '⒠', '/eparenthesized': '⒠', '/epsilon': 'ε', '/epsilonacute': 'έ',
- '/epsilonasper': 'ἑ', '/epsilonasperacute': 'ἕ', '/epsilonaspergrave':
- 'ἓ', '/epsilongrave': 'ὲ', '/epsilonlenis': 'ἐ', '/epsilonlenisacute':
- 'ἔ', '/epsilonlenisgrave': 'ἒ', '/epsilonlunatesymbol': 'ϵ',
- '/epsilonreversedlunatesymbol': '϶', '/epsilontonos': 'έ',
- '/epsilonunderlinefunc': '⍷', '/equal': '=', '/equal.inferior': '₌',
- '/equal.superior': '⁼', '/equalandparallel': '⋕', '/equalbydefinition':
- '≝', '/equalmonospace': '=', '/equalorgreater': '⋝', '/equalorless':
- '⋜', '/equalorprecedes': '⋞', '/equalorsucceeds': '⋟', '/equalscolon':
- '≕', '/equalsmall': '﹦', '/equalsuperior': '⁼', '/equiangular': '≚',
- '/equivalence': '≡', '/equivalent': '≍', '/eranameheiseisquare': '㍻',
- '/eranamemeizisquare': '㍾', '/eranamesyouwasquare': '㍼',
- '/eranametaisyousquare': '㍽', '/eraseleft': '⌫', '/eraseright': '⌦',
- '/erbopomofo': 'ㄦ', '/ercyr': 'р', '/ercyrillic': 'р', '/ereversed':
- 'ɘ', '/ereversedcyr': 'э', '/ereversedcyrillic': 'э',
- '/ereverseddieresiscyr': 'ӭ', '/ergfullwidth': '㋍', '/ertickcyr': 'ҏ',
- '/escript': 'ℯ', '/escyr': 'с', '/escyrillic': 'с',
- '/esdescendercyrillic': 'ҫ', '/esh': 'ʃ', '/eshcurl': 'ʆ',
- '/eshortdeva': 'ऎ', '/eshortvowelsigndeva': 'ॆ', '/eshreversedloop':
- 'ƪ', '/eshsquatreversed': 'ʅ', '/esmallhiragana': 'ぇ',
- '/esmallkatakana': 'ェ', '/esmallkatakanahalfwidth': 'ェ', '/estailcyr':
- 'ҫ', '/estimated': '℮', '/estimates': '≙', '/estroke': 'ɇ',
- '/esukuudosquare': '㌇', '/esuperior': '\uf6ec', '/et': 'ꝫ', '/eta': 'η',
- '/etaacute': 'ή', '/etaacuteiotasub': 'ῄ', '/etaasper': 'ἡ',
- '/etaasperacute': 'ἥ', '/etaasperacuteiotasub': 'ᾕ', '/etaaspergrave':
- 'ἣ', '/etaaspergraveiotasub': 'ᾓ', '/etaasperiotasub': 'ᾑ',
- '/etaaspertilde': 'ἧ', '/etaaspertildeiotasub': 'ᾗ', '/etagrave': 'ὴ',
- '/etagraveiotasub': 'ῂ', '/etaiotasub': 'ῃ', '/etalenis': 'ἠ',
- '/etalenisacute': 'ἤ', '/etalenisacuteiotasub': 'ᾔ', '/etalenisgrave':
- 'ἢ', '/etalenisgraveiotasub': 'ᾒ', '/etalenisiotasub': 'ᾐ',
- '/etalenistilde': 'ἦ', '/etalenistildeiotasub': 'ᾖ', '/etarmenian': 'ը',
- '/etatilde': 'ῆ', '/etatildeiotasub': 'ῇ', '/etatonos': 'ή', '/eth':
- 'ð', '/ethi:aaglottal': 'ኣ', '/ethi:aglottal': 'አ', '/ethi:ba': 'በ',
- '/ethi:baa': 'ባ', '/ethi:be': 'ብ', '/ethi:bee': 'ቤ', '/ethi:bi': 'ቢ',
- '/ethi:bo': 'ቦ', '/ethi:bu': 'ቡ', '/ethi:bwa': 'ቧ', '/ethi:ca': 'ቸ',
- '/ethi:caa': 'ቻ', '/ethi:ce': 'ች', '/ethi:cee': 'ቼ', '/ethi:cha': 'ጨ',
- '/ethi:chaa': 'ጫ', '/ethi:che': 'ጭ', '/ethi:chee': 'ጬ', '/ethi:chi':
- 'ጪ', '/ethi:cho': 'ጮ', '/ethi:chu': 'ጩ', '/ethi:chwa': 'ጯ', '/ethi:ci':
- 'ቺ', '/ethi:co': 'ቾ', '/ethi:colon': '፥', '/ethi:comma': '፣',
- '/ethi:cu': 'ቹ', '/ethi:cwa': 'ቿ', '/ethi:da': 'ደ', '/ethi:daa': 'ዳ',
- '/ethi:dda': 'ዸ', '/ethi:ddaa': 'ዻ', '/ethi:dde': 'ዽ', '/ethi:ddee':
- 'ዼ', '/ethi:ddi': 'ዺ', '/ethi:ddo': 'ዾ', '/ethi:ddu': 'ዹ', '/ethi:ddwa':
- 'ዿ', '/ethi:de': 'ድ', '/ethi:dee': 'ዴ', '/ethi:di': 'ዲ', '/ethi:do':
- 'ዶ', '/ethi:du': 'ዱ', '/ethi:dwa': 'ዷ', '/ethi:eeglottal': 'ኤ',
- '/ethi:eglottal': 'እ', '/ethi:eight': '፰', '/ethi:eighty': '፹',
- '/ethi:fa': 'ፈ', '/ethi:faa': 'ፋ', '/ethi:fe': 'ፍ', '/ethi:fee': 'ፌ',
- '/ethi:fi': 'ፊ', '/ethi:fifty': '፶', '/ethi:five': '፭', '/ethi:fo': 'ፎ',
- '/ethi:forty': '፵', '/ethi:four': '፬', '/ethi:fu': 'ፉ',
- '/ethi:fullstop': '።', '/ethi:fwa': 'ፏ', '/ethi:fya': 'ፚ', '/ethi:ga':
- 'ገ', '/ethi:gaa': 'ጋ', '/ethi:ge': 'ግ', '/ethi:gee': 'ጌ',
- '/ethi:geminationandvowellengthmarkcmb': '፝', '/ethi:geminationmarkcmb':
- '፟', '/ethi:gga': 'ጘ', '/ethi:ggaa': 'ጛ', '/ethi:gge': 'ጝ',
- '/ethi:ggee': 'ጜ', '/ethi:ggi': 'ጚ', '/ethi:ggo': 'ጞ', '/ethi:ggu': 'ጙ',
- '/ethi:ggwaa': 'ጟ', '/ethi:gi': 'ጊ', '/ethi:go': 'ጎ', '/ethi:goa': 'ጏ',
- '/ethi:gu': 'ጉ', '/ethi:gwa': 'ጐ', '/ethi:gwaa': 'ጓ', '/ethi:gwe': 'ጕ',
- '/ethi:gwee': 'ጔ', '/ethi:gwi': 'ጒ', '/ethi:ha': 'ሀ', '/ethi:haa': 'ሃ',
- '/ethi:he': 'ህ', '/ethi:hee': 'ሄ', '/ethi:hha': 'ሐ', '/ethi:hhaa': 'ሓ',
- '/ethi:hhe': 'ሕ', '/ethi:hhee': 'ሔ', '/ethi:hhi': 'ሒ', '/ethi:hho': 'ሖ',
- '/ethi:hhu': 'ሑ', '/ethi:hhwa': 'ሗ', '/ethi:hi': 'ሂ', '/ethi:ho': 'ሆ',
- '/ethi:hoa': 'ሇ', '/ethi:hu': 'ሁ', '/ethi:hundred': '፻',
- '/ethi:iglottal': 'ኢ', '/ethi:ja': 'ጀ', '/ethi:jaa': 'ጃ', '/ethi:je':
- 'ጅ', '/ethi:jee': 'ጄ', '/ethi:ji': 'ጂ', '/ethi:jo': 'ጆ', '/ethi:ju':
- 'ጁ', '/ethi:jwa': 'ጇ', '/ethi:ka': 'ከ', '/ethi:kaa': 'ካ', '/ethi:ke':
- 'ክ', '/ethi:kee': 'ኬ', '/ethi:ki': 'ኪ', '/ethi:ko': 'ኮ', '/ethi:koa':
- 'ኯ', '/ethi:ku': 'ኩ', '/ethi:kwa': 'ኰ', '/ethi:kwaa': 'ኳ', '/ethi:kwe':
- 'ኵ', '/ethi:kwee': 'ኴ', '/ethi:kwi': 'ኲ', '/ethi:kxa': 'ኸ',
- '/ethi:kxaa': 'ኻ', '/ethi:kxe': 'ኽ', '/ethi:kxee': 'ኼ', '/ethi:kxi':
- 'ኺ', '/ethi:kxo': 'ኾ', '/ethi:kxu': 'ኹ', '/ethi:kxwa': 'ዀ',
- '/ethi:kxwaa': 'ዃ', '/ethi:kxwe': 'ዅ', '/ethi:kxwee': 'ዄ', '/ethi:kxwi':
- 'ዂ', '/ethi:la': 'ለ', '/ethi:laa': 'ላ', '/ethi:le': 'ል', '/ethi:lee':
- 'ሌ', '/ethi:li': 'ሊ', '/ethi:lo': 'ሎ', '/ethi:lu': 'ሉ', '/ethi:lwa':
- 'ሏ', '/ethi:ma': 'መ', '/ethi:maa': 'ማ', '/ethi:me': 'ም', '/ethi:mee':
- 'ሜ', '/ethi:mi': 'ሚ', '/ethi:mo': 'ሞ', '/ethi:mu': 'ሙ', '/ethi:mwa':
- 'ሟ', '/ethi:mya': 'ፙ', '/ethi:na': 'ነ', '/ethi:naa': 'ና', '/ethi:ne':
- 'ን', '/ethi:nee': 'ኔ', '/ethi:ni': 'ኒ', '/ethi:nine': '፱',
- '/ethi:ninety': '፺', '/ethi:no': 'ኖ', '/ethi:nu': 'ኑ', '/ethi:nwa': 'ኗ',
- '/ethi:nya': 'ኘ', '/ethi:nyaa': 'ኛ', '/ethi:nye': 'ኝ', '/ethi:nyee':
- 'ኜ', '/ethi:nyi': 'ኚ', '/ethi:nyo': 'ኞ', '/ethi:nyu': 'ኙ', '/ethi:nywa':
- 'ኟ', '/ethi:oglottal': 'ኦ', '/ethi:one': '፩', '/ethi:pa': 'ፐ',
- '/ethi:paa': 'ፓ', '/ethi:paragraphseparator': '፨', '/ethi:pe': 'ፕ',
- '/ethi:pee': 'ፔ', '/ethi:pha': 'ጰ', '/ethi:phaa': 'ጳ',
- '/ethi:pharyngeala': 'ዐ', '/ethi:pharyngealaa': 'ዓ',
- '/ethi:pharyngeale': 'ዕ', '/ethi:pharyngealee': 'ዔ',
- '/ethi:pharyngeali': 'ዒ', '/ethi:pharyngealo': 'ዖ', '/ethi:pharyngealu':
- 'ዑ', '/ethi:phe': 'ጵ', '/ethi:phee': 'ጴ', '/ethi:phi': 'ጲ', '/ethi:pho':
- 'ጶ', '/ethi:phu': 'ጱ', '/ethi:phwa': 'ጷ', '/ethi:pi': 'ፒ', '/ethi:po':
- 'ፖ', '/ethi:prefacecolon': '፦', '/ethi:pu': 'ፑ', '/ethi:pwa': 'ፗ',
- '/ethi:qa': 'ቀ', '/ethi:qaa': 'ቃ', '/ethi:qe': 'ቅ', '/ethi:qee': 'ቄ',
- '/ethi:qha': 'ቐ', '/ethi:qhaa': 'ቓ', '/ethi:qhe': 'ቕ', '/ethi:qhee':
- 'ቔ', '/ethi:qhi': 'ቒ', '/ethi:qho': 'ቖ', '/ethi:qhu': 'ቑ', '/ethi:qhwa':
- 'ቘ', '/ethi:qhwaa': 'ቛ', '/ethi:qhwe': 'ቝ', '/ethi:qhwee': 'ቜ',
- '/ethi:qhwi': 'ቚ', '/ethi:qi': 'ቂ', '/ethi:qo': 'ቆ', '/ethi:qoa': 'ቇ',
- '/ethi:qu': 'ቁ', '/ethi:questionmark': '፧', '/ethi:qwa': 'ቈ',
- '/ethi:qwaa': 'ቋ', '/ethi:qwe': 'ቍ', '/ethi:qwee': 'ቌ', '/ethi:qwi':
- 'ቊ', '/ethi:ra': 'ረ', '/ethi:raa': 'ራ', '/ethi:re': 'ር', '/ethi:ree':
- 'ሬ', '/ethi:ri': 'ሪ', '/ethi:ro': 'ሮ', '/ethi:ru': 'ሩ', '/ethi:rwa':
- 'ሯ', '/ethi:rya': 'ፘ', '/ethi:sa': 'ሰ', '/ethi:saa': 'ሳ', '/ethi:se':
- 'ስ', '/ethi:sectionmark': '፠', '/ethi:see': 'ሴ', '/ethi:semicolon': '፤',
- '/ethi:seven': '፯', '/ethi:seventy': '፸', '/ethi:sha': 'ሸ',
- '/ethi:shaa': 'ሻ', '/ethi:she': 'ሽ', '/ethi:shee': 'ሼ', '/ethi:shi':
- 'ሺ', '/ethi:sho': 'ሾ', '/ethi:shu': 'ሹ', '/ethi:shwa': 'ሿ', '/ethi:si':
- 'ሲ', '/ethi:six': '፮', '/ethi:sixty': '፷', '/ethi:so': 'ሶ', '/ethi:su':
- 'ሱ', '/ethi:swa': 'ሷ', '/ethi:sza': 'ሠ', '/ethi:szaa': 'ሣ', '/ethi:sze':
- 'ሥ', '/ethi:szee': 'ሤ', '/ethi:szi': 'ሢ', '/ethi:szo': 'ሦ', '/ethi:szu':
- 'ሡ', '/ethi:szwa': 'ሧ', '/ethi:ta': 'ተ', '/ethi:taa': 'ታ', '/ethi:te':
- 'ት', '/ethi:tee': 'ቴ', '/ethi:ten': '፲', '/ethi:tenthousand': '፼',
- '/ethi:tha': 'ጠ', '/ethi:thaa': 'ጣ', '/ethi:the': 'ጥ', '/ethi:thee':
- 'ጤ', '/ethi:thi': 'ጢ', '/ethi:thirty': '፴', '/ethi:tho': 'ጦ',
- '/ethi:three': '፫', '/ethi:thu': 'ጡ', '/ethi:thwa': 'ጧ', '/ethi:ti':
- 'ቲ', '/ethi:to': 'ቶ', '/ethi:tsa': 'ጸ', '/ethi:tsaa': 'ጻ', '/ethi:tse':
- 'ጽ', '/ethi:tsee': 'ጼ', '/ethi:tsi': 'ጺ', '/ethi:tso': 'ጾ', '/ethi:tsu':
- 'ጹ', '/ethi:tswa': 'ጿ', '/ethi:tu': 'ቱ', '/ethi:twa': 'ቷ',
- '/ethi:twenty': '፳', '/ethi:two': '፪', '/ethi:tza': 'ፀ', '/ethi:tzaa':
- 'ፃ', '/ethi:tze': 'ፅ', '/ethi:tzee': 'ፄ', '/ethi:tzi': 'ፂ', '/ethi:tzo':
- 'ፆ', '/ethi:tzoa': 'ፇ', '/ethi:tzu': 'ፁ', '/ethi:uglottal': 'ኡ',
- '/ethi:va': 'ቨ', '/ethi:vaa': 'ቫ', '/ethi:ve': 'ቭ', '/ethi:vee': 'ቬ',
- '/ethi:vi': 'ቪ', '/ethi:vo': 'ቮ', '/ethi:vowellengthmarkcmb': '፞',
- '/ethi:vu': 'ቩ', '/ethi:vwa': 'ቯ', '/ethi:wa': 'ወ', '/ethi:waa': 'ዋ',
- '/ethi:waglottal': 'ኧ', '/ethi:we': 'ው', '/ethi:wee': 'ዌ', '/ethi:wi':
- 'ዊ', '/ethi:wo': 'ዎ', '/ethi:woa': 'ዏ', '/ethi:wordspace': '፡',
- '/ethi:wu': 'ዉ', '/ethi:xa': 'ኀ', '/ethi:xaa': 'ኃ', '/ethi:xe': 'ኅ',
- '/ethi:xee': 'ኄ', '/ethi:xi': 'ኂ', '/ethi:xo': 'ኆ', '/ethi:xoa': 'ኇ',
- '/ethi:xu': 'ኁ', '/ethi:xwa': 'ኈ', '/ethi:xwaa': 'ኋ', '/ethi:xwe': 'ኍ',
- '/ethi:xwee': 'ኌ', '/ethi:xwi': 'ኊ', '/ethi:ya': 'የ', '/ethi:yaa': 'ያ',
- '/ethi:ye': 'ይ', '/ethi:yee': 'ዬ', '/ethi:yi': 'ዪ', '/ethi:yo': 'ዮ',
- '/ethi:yoa': 'ዯ', '/ethi:yu': 'ዩ', '/ethi:za': 'ዘ', '/ethi:zaa': 'ዛ',
- '/ethi:ze': 'ዝ', '/ethi:zee': 'ዜ', '/ethi:zha': 'ዠ', '/ethi:zhaa': 'ዣ',
- '/ethi:zhe': 'ዥ', '/ethi:zhee': 'ዤ', '/ethi:zhi': 'ዢ', '/ethi:zho': 'ዦ',
- '/ethi:zhu': 'ዡ', '/ethi:zhwa': 'ዧ', '/ethi:zi': 'ዚ', '/ethi:zo': 'ዞ',
- '/ethi:zu': 'ዙ', '/ethi:zwa': 'ዟ', '/etilde': 'ẽ', '/etildebelow': 'ḛ',
- '/etnahta:hb': '֑', '/etnahtafoukhhebrew': '֑',
- '/etnahtafoukhlefthebrew': '֑', '/etnahtahebrew': '֑',
- '/etnahtalefthebrew': '֑', '/eturned': 'ǝ', '/eukorean': 'ㅡ',
- '/eukrcyr': 'є', '/euler': 'ℇ', '/euro': '€', '/euroarchaic': '₠',
- '/europeanCastle': 'Ἷ0', '/europeanPostOffice': 'Ἶ4', '/evergreenTree':
- 'ἳ2', '/evowelsignbengali': 'ে', '/evowelsigndeva': 'े',
- '/evowelsigngujarati': 'ે', '/excellentideographiccircled': '㊝',
- '/excess': '∹', '/exclam': '!', '/exclamarmenian': '՜',
- '/exclamationquestion': '⁉', '/exclamdbl': '‼', '/exclamdown': '¡',
- '/exclamdownsmall': '\uf7a1', '/exclammonospace': '!', '/exclamsmall':
- '\uf721', '/existential': '∃', '/expressionlessFace': 'ὡ1',
- '/extraterrestrialAlien': '\u1f47D', '/eye': 'ὄ1', '/eyeglasses': 'ὅ3',
- '/eyes': 'ὄ0', '/ezh': 'ʒ', '/ezhcaron': 'ǯ', '/ezhcurl': 'ʓ',
- '/ezhreversed': 'ƹ', '/ezhtail': 'ƺ', '/f': 'f', '/f_f': 'ff', '/f_f_i':
- 'ffi', '/f_f_l': 'ffl', '/faceMassage': 'Ὀ6', '/faceSavouringDeliciousFood':
- 'ὠB', '/faceScreamingInFear': 'ὣ1', '/faceThrowingAKiss': 'ὡ8',
- '/faceWithColdSweat': 'ὡ3', '/faceWithLookOfTriumph': 'ὢ4',
- '/faceWithMedicalMask': 'ὣ7', '/faceWithNoGoodGesture': 'ὤ5',
- '/faceWithOkGesture': 'ὤ6', '/faceWithOpenMouth': 'ὢE',
- '/faceWithOpenMouthAndColdSweat': 'ὣ0', '/faceWithRollingEyes': 'ὤ4',
- '/faceWithStuckOutTongue': 'ὡB',
- '/faceWithStuckOutTongueAndTightlyClosedEyes': 'ὡD',
- '/faceWithStuckOutTongueAndWinkingEye': 'ὡC', '/faceWithTearsOfJoy':
- 'ὠ2', '/faceWithoutMouth': 'ὣ6', '/facsimile': '℻', '/factory': 'ἾD',
- '/fadeva': 'फ़', '/fagurmukhi': 'ਫ਼', '/fahrenheit': '℉', '/fallenLeaf':
- 'ἴ2', '/fallingdiagonal': '⟍',
- '/fallingdiagonalincircleinsquareblackwhite': '⛞', '/family': '\u1f46A',
- '/farsi': '☫', '/farsiYehDigitFourBelow': 'ݷ',
- '/farsiYehDigitThreeAbove': 'ݶ', '/farsiYehDigitTwoAbove': 'ݵ',
- '/fatha': 'َ', '/fathaIsol': 'ﹶ', '/fathaMedi': 'ﹷ', '/fathaarabic':
- 'َ', '/fathalowarabic': 'َ', '/fathasmall': 'ؘ', '/fathatan': 'ً',
- '/fathatanIsol': 'ﹰ', '/fathatanarabic': 'ً', '/fathatwodotsdots': 'ٞ',
- '/fatherChristmas': 'Ἰ5', '/faxIcon': 'Ὓ7', '/faxMachine': '\u1f4e0',
- '/fbopomofo': 'ㄈ', '/fcircle': 'ⓕ', '/fdot': 'ḟ', '/fdotaccent': 'ḟ',
- '/fearfulFace': 'ὢ8', '/februarytelegraph': '㋁', '/feh.fina': 'ﻒ',
- '/feh.init': 'ﻓ', '/feh.init_alefmaksura.fina': 'ﰱ',
- '/feh.init_hah.fina': 'ﰮ', '/feh.init_hah.medi': 'ﲿ',
- '/feh.init_jeem.fina': 'ﰭ', '/feh.init_jeem.medi': 'ﲾ',
- '/feh.init_khah.fina': 'ﰯ', '/feh.init_khah.medi': 'ﳀ',
- '/feh.init_khah.medi_meem.medi': 'ﵽ', '/feh.init_meem.fina': 'ﰰ',
- '/feh.init_meem.medi': 'ﳁ', '/feh.init_yeh.fina': 'ﰲ', '/feh.isol': 'ﻑ',
- '/feh.medi': 'ﻔ', '/feh.medi_alefmaksura.fina': 'ﱼ',
- '/feh.medi_khah.medi_meem.fina': 'ﵼ', '/feh.medi_meem.medi_yeh.fina':
- 'ﷁ', '/feh.medi_yeh.fina': 'ﱽ', '/fehThreeDotsUpBelow': 'ݡ',
- '/fehTwoDotsBelow': 'ݠ', '/feharabic': 'ف', '/feharmenian': 'ֆ',
- '/fehdotbelow': 'ڣ', '/fehdotbelowright': 'ڢ', '/fehfinalarabic': 'ﻒ',
- '/fehinitialarabic': 'ﻓ', '/fehmedialarabic': 'ﻔ', '/fehthreedotsbelow':
- 'ڥ', '/feicoptic': 'ϥ', '/female': '♀', '/femaleideographiccircled':
- '㊛', '/feng': 'ʩ', '/ferrisWheel': 'Ἲ1', '/ferry': '⛴',
- '/festivalideographicparen': '㉀', '/ff': 'ff', '/ffi': 'ffi', '/ffl': 'ffl',
- '/fhook': 'ƒ', '/fi': 'fi', '/fieldHockeyStickAndBall': 'Ἵ1',
- '/fifteencircle': '⑮', '/fifteencircleblack': '⓯', '/fifteenparen': '⒂',
- '/fifteenparenthesized': '⒂', '/fifteenperiod': '⒖', '/fifty.roman':
- 'Ⅼ', '/fifty.romansmall': 'ⅼ', '/fiftycircle': '㊿',
- '/fiftycirclesquare': '㉌', '/fiftyearlyform.roman': 'ↆ',
- '/fiftythousand.roman': 'ↇ', '/figuredash': '‒', '/figurespace':
- '\u2007', '/fileCabinet': '\u1f5c4', '/fileFolder': 'Ὄ1', '/filledbox':
- '■', '/filledrect': '▬', '/filledstopabove': '۬', '/filmFrames': 'ἹE',
- '/filmProjector': '\u1f4fD', '/finalkaf': 'ך', '/finalkaf:hb': 'ך',
- '/finalkafdagesh': 'ךּ', '/finalkafdageshhebrew': 'ךּ', '/finalkafhebrew':
- 'ך', '/finalkafqamats': 'ך', '/finalkafqamatshebrew': 'ך',
- '/finalkafsheva': 'ך', '/finalkafshevahebrew': 'ך',
- '/finalkafwithdagesh:hb': 'ךּ', '/finalmem': 'ם', '/finalmem:hb': 'ם',
- '/finalmemhebrew': 'ם', '/finalmemwide:hb': 'ﬦ', '/finalnun': 'ן',
- '/finalnun:hb': 'ן', '/finalnunhebrew': 'ן', '/finalpe': 'ף',
- '/finalpe:hb': 'ף', '/finalpehebrew': 'ף', '/finalpewithdagesh:hb': 'ףּ',
- '/finalsigma': 'ς', '/finaltsadi': 'ץ', '/finaltsadi:hb': 'ץ',
- '/finaltsadihebrew': 'ץ', '/financialideographiccircled': '㊖',
- '/financialideographicparen': '㈶', '/finsular': 'ꝼ', '/fire': 'ὒ5',
- '/fireEngine': 'Ὡ2', '/fireideographiccircled': '㊋',
- '/fireideographicparen': '㈫', '/fireworkSparkler': 'Ἰ7', '/fireworks':
- 'Ἰ6', '/firstQuarterMoon': 'ἱ3', '/firstQuarterMoonFace': 'ἱB',
- '/firstquartermoon': '☽', '/firststrongisolate': '\u2068',
- '/firsttonechinese': 'ˉ', '/fish': 'ὁF', '/fishCakeSwirlDesign': 'ἶ5',
- '/fisheye': '◉', '/fishingPoleAndFish': 'Ἲ3', '/fistedHandSign': 'ὄA',
- '/fitacyr': 'ѳ', '/fitacyrillic': 'ѳ', '/five': '5', '/five.inferior':
- '₅', '/five.roman': 'Ⅴ', '/five.romansmall': 'ⅴ', '/five.superior': '⁵',
- '/fivearabic': '٥', '/fivebengali': '৫', '/fivecircle': '⑤',
- '/fivecircledbl': '⓹', '/fivecircleinversesansserif': '➎', '/fivecomma':
- 'ἐ6', '/fivedeva': '५', '/fivedot': '⸭', '/fivedotpunctuation': '⁙',
- '/fiveeighths': '⅝', '/fivefar': '۵', '/fivegujarati': '૫',
- '/fivegurmukhi': '੫', '/fivehackarabic': '٥', '/fivehangzhou': '〥',
- '/fivehundred.roman': 'Ⅾ', '/fivehundred.romansmall': 'ⅾ',
- '/fiveideographiccircled': '㊄', '/fiveideographicparen': '㈤',
- '/fiveinferior': '₅', '/fivemonospace': '5', '/fiveoldstyle': '\uf735',
- '/fiveparen': '⑸', '/fiveparenthesized': '⑸', '/fiveperiod': '⒌',
- '/fivepersian': '۵', '/fivepointedstar': '٭', '/fivepointonesquare':
- 'Ἒ0', '/fiveroman': 'ⅴ', '/fivesixths': '⅚', '/fivesuperior': '⁵',
- '/fivethai': '๕', '/fivethousand.roman': 'ↁ', '/fl': 'fl', '/flagblack':
- '⚑', '/flaghorizontalmiddlestripeblackwhite': '⛿', '/flaginhole': '⛳',
- '/flagwhite': '⚐', '/flatness': '⏥', '/fleurdelis': '⚜',
- '/flexedBiceps': 'ὊA', '/floorleft': '⌊', '/floorright': '⌋',
- '/floppyDisk': 'ὋE', '/floralheartbulletreversedrotated': '☙',
- '/florin': 'ƒ', '/flower': '⚘', '/flowerPlayingCards': 'Ἳ4',
- '/flowerpunctuationmark': '⁕', '/flushedFace': 'ὣ3', '/flyingEnvelope':
- '\u1f585', '/flyingSaucer': 'Ὧ8', '/fmfullwidth': '㎙', '/fmonospace':
- 'f', '/fmsquare': '㎙', '/fofanthai': 'ฟ', '/fofathai': 'ฝ', '/fog':
- 'ἲB', '/foggy': 'ἰ1', '/folder': '\u1f5c0', '/fongmanthai': '๏',
- '/footnote': '\u0602', '/footprints': '\u1f463', '/footsquare': '⏍',
- '/forall': '∀', '/forces': '⊩', '/fork': '⑂', '/forkKnife': 'ἷ4',
- '/forkKnifePlate': 'ἷD', '/forsamaritan': '⅏', '/fortycircle': '㊵',
- '/fortycirclesquare': '㉋', '/fortyeightcircle': '㊽', '/fortyfivecircle':
- '㊺', '/fortyfourcircle': '㊹', '/fortyninecircle': '㊾',
- '/fortyonecircle': '㊶', '/fortysevencircle': '㊼', '/fortysixcircle':
- '㊻', '/fortythreecircle': '㊸', '/fortytwocircle': '㊷', '/fountain': '⛲',
- '/four': '4', '/four.inferior': '₄', '/four.roman': 'Ⅳ',
- '/four.romansmall': 'ⅳ', '/four.superior': '⁴', '/fourLeafClover': 'ἴ0',
- '/fourarabic': '٤', '/fourbengali': '৪', '/fourcircle': '④',
- '/fourcircledbl': '⓸', '/fourcircleinversesansserif': '➍', '/fourcomma':
- 'ἐ5', '/fourdeva': '४', '/fourdotmark': '⁛', '/fourdotpunctuation': '⁘',
- '/fourfar': '۴', '/fourfifths': '⅘', '/fourgujarati': '૪',
- '/fourgurmukhi': '੪', '/fourhackarabic': '٤', '/fourhangzhou': '〤',
- '/fourideographiccircled': '㊃', '/fourideographicparen': '㈣',
- '/fourinferior': '₄', '/fourksquare': 'ἙE', '/fourmonospace': '4',
- '/fournumeratorbengali': '৷', '/fouroldstyle': '\uf734', '/fourparen':
- '⑷', '/fourparenthesized': '⑷', '/fourperemspace': '\u2005',
- '/fourperiod': '⒋', '/fourpersian': '۴', '/fourroman': 'ⅳ',
- '/foursuperior': '⁴', '/fourteencircle': '⑭', '/fourteencircleblack':
- '⓮', '/fourteenparen': '⒁', '/fourteenparenthesized': '⒁',
- '/fourteenperiod': '⒕', '/fourthai': '๔', '/fourthtonechinese': 'ˋ',
- '/fparen': '⒡', '/fparenthesized': '⒡', '/fraction': '⁄', '/frameAnX':
- 'ὛE', '/framePicture': 'ὛC', '/frameTiles': 'ὛD', '/franc': '₣',
- '/freesquare': 'Ἑ3', '/frenchFries': 'ἵF', '/freversedepigraphic': 'ꟻ',
- '/friedShrimp': 'ἶ4', '/frogFace': 'ὃ8', '/front-facingBabyChick': 'ὂ5',
- '/frown': '⌢', '/frowningFaceWithOpenMouth': 'ὢ6', '/frowningfacewhite':
- '☹', '/fstroke': 'ꞙ', '/fturned': 'ⅎ', '/fuelpump': '⛽', '/fullBlock':
- '█', '/fullMoon': 'ἱ5', '/fullMoonFace': 'ἱD', '/functionapplication':
- '\u2061', '/funeralurn': '⚱', '/fuse': '⏛', '/fwd:A': 'A', '/fwd:B':
- 'B', '/fwd:C': 'C', '/fwd:D': 'D', '/fwd:E': 'E', '/fwd:F': 'F',
- '/fwd:G': 'G', '/fwd:H': 'H', '/fwd:I': 'I', '/fwd:J': 'J', '/fwd:K':
- 'K', '/fwd:L': 'L', '/fwd:M': 'M', '/fwd:N': 'N', '/fwd:O': 'O',
- '/fwd:P': 'P', '/fwd:Q': 'Q', '/fwd:R': 'R', '/fwd:S': 'S', '/fwd:T':
- 'T', '/fwd:U': 'U', '/fwd:V': 'V', '/fwd:W': 'W', '/fwd:X': 'X',
- '/fwd:Y': 'Y', '/fwd:Z': 'Z', '/fwd:a': 'a', '/fwd:ampersand': '&',
- '/fwd:asciicircum': '^', '/fwd:asciitilde': '~', '/fwd:asterisk': '*',
- '/fwd:at': '@', '/fwd:b': 'b', '/fwd:backslash': '\', '/fwd:bar': '|',
- '/fwd:braceleft': '{', '/fwd:braceright': '}', '/fwd:bracketleft': '[',
- '/fwd:bracketright': ']', '/fwd:brokenbar': '¦', '/fwd:c': 'c',
- '/fwd:centsign': '¢', '/fwd:colon': ':', '/fwd:comma': ',', '/fwd:d':
- 'd', '/fwd:dollar': '$', '/fwd:e': 'e', '/fwd:eight': '8', '/fwd:equal':
- '=', '/fwd:exclam': '!', '/fwd:f': 'f', '/fwd:five': '5', '/fwd:four':
- '4', '/fwd:g': 'g', '/fwd:grave': '`', '/fwd:greater': '>', '/fwd:h':
- 'h', '/fwd:hyphen': '-', '/fwd:i': 'i', '/fwd:j': 'j', '/fwd:k': 'k',
- '/fwd:l': 'l', '/fwd:leftwhiteparenthesis': '⦅', '/fwd:less': '<',
- '/fwd:m': 'm', '/fwd:macron': ' ̄', '/fwd:n': 'n', '/fwd:nine': '9',
- '/fwd:notsign': '¬', '/fwd:numbersign': '#', '/fwd:o': 'o', '/fwd:one':
- '1', '/fwd:p': 'p', '/fwd:parenthesisleft': '(',
- '/fwd:parenthesisright': ')', '/fwd:percent': '%', '/fwd:period': '.',
- '/fwd:plus': '+', '/fwd:poundsign': '£', '/fwd:q': 'q', '/fwd:question':
- '?', '/fwd:quotedbl': '"', '/fwd:quotesingle': ''', '/fwd:r': 'r',
- '/fwd:rightwhiteparenthesis': '⦆', '/fwd:s': 's', '/fwd:semicolon': ';',
- '/fwd:seven': '7', '/fwd:six': '6', '/fwd:slash': '/', '/fwd:t': 't',
- '/fwd:three': '3', '/fwd:two': '2', '/fwd:u': 'u', '/fwd:underscore':
- '_', '/fwd:v': 'v', '/fwd:w': 'w', '/fwd:wonsign': '₩', '/fwd:x': 'x',
- '/fwd:y': 'y', '/fwd:yensign': '¥', '/fwd:z': 'z', '/fwd:zero': '0',
- '/g': 'g', '/gabengali': 'গ', '/gacute': 'ǵ', '/gadeva': 'ग', '/gaf':
- 'گ', '/gaf.fina': 'ﮓ', '/gaf.init': 'ﮔ', '/gaf.isol': 'ﮒ', '/gaf.medi':
- 'ﮕ', '/gafarabic': 'گ', '/gaffinalarabic': 'ﮓ', '/gafinitialarabic':
- 'ﮔ', '/gafmedialarabic': 'ﮕ', '/gafring': 'ڰ', '/gafthreedotsabove':
- 'ڴ', '/gaftwodotsbelow': 'ڲ', '/gagujarati': 'ગ', '/gagurmukhi': 'ਗ',
- '/gahiragana': 'が', '/gakatakana': 'ガ', '/galsquare': '㏿', '/gameDie':
- 'Ἳ2', '/gamma': 'γ', '/gammadblstruck': 'ℽ', '/gammalatinsmall': 'ɣ',
- '/gammasuperior': 'ˠ', '/gammasupmod': 'ˠ', '/gamurda': 'ꦓ',
- '/gangiacoptic': 'ϫ', '/ganmasquare': '㌏', '/garonsquare': '㌎',
- '/gbfullwidth': '㎇', '/gbopomofo': 'ㄍ', '/gbreve': 'ğ', '/gcaron': 'ǧ',
- '/gcedilla': 'ģ', '/gcircle': 'ⓖ', '/gcircumflex': 'ĝ', '/gcommaaccent':
- 'ģ', '/gdot': 'ġ', '/gdotaccent': 'ġ', '/gear': '⚙', '/gearhles': '⛮',
- '/gearouthub': '⛭', '/gecyr': 'г', '/gecyrillic': 'г', '/gehiragana':
- 'げ', '/gehookcyr': 'ҕ', '/gehookstrokecyr': 'ӻ', '/gekatakana': 'ゲ',
- '/gemStone': 'ὈE', '/gemini': '♊', '/geometricallyequal': '≑',
- '/geometricallyequivalent': '≎', '/geometricproportion': '∺',
- '/geresh:hb': '׳', '/gereshMuqdam:hb': '֝', '/gereshaccenthebrew': '֜',
- '/gereshhebrew': '׳', '/gereshmuqdamhebrew': '֝', '/germandbls': 'ß',
- '/germanpenny': '₰', '/gershayim:hb': '״', '/gershayimaccenthebrew':
- '֞', '/gershayimhebrew': '״', '/gestrokecyr': 'ғ', '/getailcyr': 'ӷ',
- '/getamark': '〓', '/geupcyr': 'ґ', '/ghabengali': 'ঘ', '/ghadarmenian':
- 'ղ', '/ghadeva': 'घ', '/ghagujarati': 'ઘ', '/ghagurmukhi': 'ਘ',
- '/ghain': 'غ', '/ghain.fina': 'ﻎ', '/ghain.init': 'ﻏ',
- '/ghain.init_alefmaksura.fina': 'ﳹ', '/ghain.init_jeem.fina': 'ﰫ',
- '/ghain.init_jeem.medi': 'ﲼ', '/ghain.init_meem.fina': 'ﰬ',
- '/ghain.init_meem.medi': 'ﲽ', '/ghain.init_yeh.fina': 'ﳺ',
- '/ghain.isol': 'ﻍ', '/ghain.medi': 'ﻐ', '/ghain.medi_alefmaksura.fina':
- 'ﴕ', '/ghain.medi_meem.medi_alefmaksura.fina': 'ﵻ',
- '/ghain.medi_meem.medi_meem.fina': 'ﵹ',
- '/ghain.medi_meem.medi_yeh.fina': 'ﵺ', '/ghain.medi_yeh.fina': 'ﴖ',
- '/ghainarabic': 'غ', '/ghaindotbelow': 'ۼ', '/ghainfinalarabic': 'ﻎ',
- '/ghaininitialarabic': 'ﻏ', '/ghainmedialarabic': 'ﻐ',
- '/ghemiddlehookcyrillic': 'ҕ', '/ghestrokecyrillic': 'ғ',
- '/gheupturncyrillic': 'ґ', '/ghhadeva': 'ग़', '/ghhagurmukhi': 'ਗ਼',
- '/ghook': 'ɠ', '/ghost': '\u1f47B', '/ghzfullwidth': '㎓', '/ghzsquare':
- '㎓', '/gigasquare': '㌐', '/gihiragana': 'ぎ', '/gikatakana': 'ギ',
- '/gimarmenian': 'գ', '/gimel': 'ג', '/gimel:hb': 'ג', '/gimeldagesh':
- 'גּ', '/gimeldageshhebrew': 'גּ', '/gimelhebrew': 'ג',
- '/gimelwithdagesh:hb': 'גּ', '/giniisquare': '㌑', '/ginsularturned': 'ꝿ',
- '/girl': '\u1f467', '/girls': 'ὬA', '/girudaasquare': '㌓', '/gjecyr':
- 'ѓ', '/gjecyrillic': 'ѓ', '/globeMeridians': 'ἱ0',
- '/glottalinvertedstroke': 'ƾ', '/glottalstop': 'ʔ',
- '/glottalstopinverted': 'ʖ', '/glottalstopmod': 'ˀ',
- '/glottalstopreversed': 'ʕ', '/glottalstopreversedmod': 'ˁ',
- '/glottalstopreversedsuperior': 'ˤ', '/glottalstopstroke': 'ʡ',
- '/glottalstopstrokereversed': 'ʢ', '/glottalstopsupreversedmod': 'ˤ',
- '/glowingStar': 'ἱF', '/gmacron': 'ḡ', '/gmonospace': 'g',
- '/gmtr:diamondblack': '◆', '/gmtr:diamondwhite': '◇', '/gnrl:hyphen':
- '‐', '/goat': 'ὁ0', '/gobliquestroke': 'ꞡ', '/gohiragana': 'ご',
- '/gokatakana': 'ゴ', '/golfer': 'ἼC', '/gpafullwidth': '㎬', '/gparen':
- '⒢', '/gparenthesized': '⒢', '/gpasquare': '㎬', '/gr:acute': '´',
- '/gr:grave': '`', '/gr:question': ';', '/gr:tilde': '῀', '/gradient':
- '∇', '/graduationCap': 'Ἱ3', '/grapes': 'ἴ7', '/grave': '`',
- '/gravebelowcmb': '̖', '/gravecmb': '̀', '/gravecomb': '̀',
- '/gravedblmiddlemod': '˵', '/gravedeva': '॓', '/gravelowmod': 'ˎ',
- '/gravemiddlemod': '˴', '/gravemod': 'ˋ', '/gravemonospace': '`',
- '/gravetonecmb': '̀', '/greater': '>', '/greaterbutnotequal': '≩',
- '/greaterbutnotequivalent': '⋧', '/greaterdot': '⋗', '/greaterequal':
- '≥', '/greaterequalorless': '⋛', '/greatermonospace': '>',
- '/greaterorequivalent': '≳', '/greaterorless': '≷', '/greateroverequal':
- '≧', '/greatersmall': '﹥', '/greenApple': 'ἴF', '/greenBook': 'Ὅ7',
- '/greenHeart': 'ὉA', '/grimacingFace': 'ὢC',
- '/grinningCatFaceWithSmilingEyes': 'ὣ8', '/grinningFace': 'ὠ0',
- '/grinningFaceWithSmilingEyes': 'ὠ1', '/growingHeart': 'Ὁ7', '/gscript':
- 'ɡ', '/gstroke': 'ǥ', '/guarani': '₲', '/guardsman': 'Ὀ2', '/gueh': 'ڳ',
- '/gueh.fina': 'ﮗ', '/gueh.init': 'ﮘ', '/gueh.isol': 'ﮖ', '/gueh.medi':
- 'ﮙ', '/guhiragana': 'ぐ', '/guillemetleft': '«', '/guillemetright': '»',
- '/guillemotleft': '«', '/guillemotright': '»', '/guilsinglleft': '‹',
- '/guilsinglright': '›', '/guitar': 'Ἳ8', '/gujr:a': 'અ', '/gujr:aa':
- 'આ', '/gujr:aasign': 'ા', '/gujr:abbreviation': '૰', '/gujr:ai': 'ઐ',
- '/gujr:aisign': 'ૈ', '/gujr:anusvara': 'ં', '/gujr:au': 'ઔ',
- '/gujr:ausign': 'ૌ', '/gujr:avagraha': 'ઽ', '/gujr:ba': 'બ',
- '/gujr:bha': 'ભ', '/gujr:binducandra': 'ઁ', '/gujr:ca': 'ચ',
- '/gujr:cha': 'છ', '/gujr:circlenuktaabove': '૾', '/gujr:da': 'દ',
- '/gujr:dda': 'ડ', '/gujr:ddha': 'ઢ', '/gujr:dha': 'ધ', '/gujr:e': 'એ',
- '/gujr:ecandra': 'ઍ', '/gujr:eight': '૮', '/gujr:esign': 'ે',
- '/gujr:esigncandra': 'ૅ', '/gujr:five': '૫', '/gujr:four': '૪',
- '/gujr:ga': 'ગ', '/gujr:gha': 'ઘ', '/gujr:ha': 'હ', '/gujr:i': 'ઇ',
- '/gujr:ii': 'ઈ', '/gujr:iisign': 'ી', '/gujr:isign': 'િ', '/gujr:ja':
- 'જ', '/gujr:jha': 'ઝ', '/gujr:ka': 'ક', '/gujr:kha': 'ખ', '/gujr:la':
- 'લ', '/gujr:lla': 'ળ', '/gujr:llvocal': 'ૡ', '/gujr:llvocalsign': 'ૣ',
- '/gujr:lvocal': 'ઌ', '/gujr:lvocalsign': 'ૢ', '/gujr:ma': 'મ',
- '/gujr:maddah': 'ૼ', '/gujr:na': 'ન', '/gujr:nga': 'ઙ', '/gujr:nine':
- '૯', '/gujr:nna': 'ણ', '/gujr:nukta': '઼', '/gujr:nya': 'ઞ', '/gujr:o':
- 'ઓ', '/gujr:ocandra': 'ઑ', '/gujr:om': 'ૐ', '/gujr:one': '૧',
- '/gujr:osign': 'ો', '/gujr:osigncandra': 'ૉ', '/gujr:pa': 'પ',
- '/gujr:pha': 'ફ', '/gujr:ra': 'ર', '/gujr:rrvocal': 'ૠ',
- '/gujr:rrvocalsign': 'ૄ', '/gujr:rupee': '૱', '/gujr:rvocal': 'ઋ',
- '/gujr:rvocalsign': 'ૃ', '/gujr:sa': 'સ', '/gujr:seven': '૭',
- '/gujr:sha': 'શ', '/gujr:shadda': 'ૻ', '/gujr:six': '૬', '/gujr:ssa':
- 'ષ', '/gujr:sukun': 'ૺ', '/gujr:ta': 'ત', '/gujr:tha': 'થ',
- '/gujr:three': '૩', '/gujr:three-dotnuktaabove': '૽', '/gujr:tta': 'ટ',
- '/gujr:ttha': 'ઠ', '/gujr:two': '૨', '/gujr:two-circlenuktaabove': '૿',
- '/gujr:u': 'ઉ', '/gujr:usign': 'ુ', '/gujr:uu': 'ઊ', '/gujr:uusign':
- 'ૂ', '/gujr:va': 'વ', '/gujr:virama': '્', '/gujr:visarga': 'ઃ',
- '/gujr:ya': 'ય', '/gujr:zero': '૦', '/gujr:zha': 'ૹ', '/gukatakana':
- 'グ', '/guramusquare': '㌘', '/guramutonsquare': '㌙', '/guru:a': 'ਅ',
- '/guru:aa': 'ਆ', '/guru:aasign': 'ਾ', '/guru:adakbindisign': 'ਁ',
- '/guru:addak': 'ੱ', '/guru:ai': 'ਐ', '/guru:aisign': 'ੈ', '/guru:au':
- 'ਔ', '/guru:ausign': 'ੌ', '/guru:ba': 'ਬ', '/guru:bha': 'ਭ',
- '/guru:bindisign': 'ਂ', '/guru:ca': 'ਚ', '/guru:cha': 'ਛ', '/guru:da':
- 'ਦ', '/guru:dda': 'ਡ', '/guru:ddha': 'ਢ', '/guru:dha': 'ਧ', '/guru:ee':
- 'ਏ', '/guru:eesign': 'ੇ', '/guru:eight': '੮', '/guru:ekonkar': 'ੴ',
- '/guru:fa': 'ਫ਼', '/guru:five': '੫', '/guru:four': '੪', '/guru:ga': 'ਗ',
- '/guru:gha': 'ਘ', '/guru:ghha': 'ਗ਼', '/guru:ha': 'ਹ', '/guru:i': 'ਇ',
- '/guru:ii': 'ਈ', '/guru:iisign': 'ੀ', '/guru:iri': 'ੲ', '/guru:isign':
- 'ਿ', '/guru:ja': 'ਜ', '/guru:jha': 'ਝ', '/guru:ka': 'ਕ', '/guru:kha':
- 'ਖ', '/guru:khha': 'ਖ਼', '/guru:la': 'ਲ', '/guru:lla': 'ਲ਼', '/guru:ma':
- 'ਮ', '/guru:na': 'ਨ', '/guru:nga': 'ਙ', '/guru:nine': '੯', '/guru:nna':
- 'ਣ', '/guru:nukta': '਼', '/guru:nya': 'ਞ', '/guru:one': '੧', '/guru:oo':
- 'ਓ', '/guru:oosign': 'ੋ', '/guru:pa': 'ਪ', '/guru:pha': 'ਫ', '/guru:ra':
- 'ਰ', '/guru:rra': 'ੜ', '/guru:sa': 'ਸ', '/guru:seven': '੭', '/guru:sha':
- 'ਸ਼', '/guru:six': '੬', '/guru:ta': 'ਤ', '/guru:tha': 'ਥ', '/guru:three':
- '੩', '/guru:tippi': 'ੰ', '/guru:tta': 'ਟ', '/guru:ttha': 'ਠ',
- '/guru:two': '੨', '/guru:u': 'ਉ', '/guru:udaatsign': 'ੑ', '/guru:ura':
- 'ੳ', '/guru:usign': 'ੁ', '/guru:uu': 'ਊ', '/guru:uusign': 'ੂ',
- '/guru:va': 'ਵ', '/guru:virama': '੍', '/guru:visarga': 'ਃ', '/guru:ya':
- 'ਯ', '/guru:yakashsign': 'ੵ', '/guru:za': 'ਜ਼', '/guru:zero': '੦',
- '/gyfullwidth': '㏉', '/gysquare': '㏉', '/h': 'h', '/h.inferior': 'ₕ',
- '/haabkhasiancyrillic': 'ҩ', '/haabkhcyr': 'ҩ', '/haaltonearabic': 'ہ',
- '/habengali': 'হ', '/hacirclekatakana': '㋩', '/hacyr': 'х',
- '/hadescendercyrillic': 'ҳ', '/hadeva': 'ह', '/hafullwidth': '㏊',
- '/hagujarati': 'હ', '/hagurmukhi': 'ਹ', '/hah': 'ح', '/hah.fina': 'ﺢ',
- '/hah.init': 'ﺣ', '/hah.init_alefmaksura.fina': 'ﳿ',
- '/hah.init_jeem.fina': 'ﰗ', '/hah.init_jeem.medi': 'ﲩ',
- '/hah.init_meem.fina': 'ﰘ', '/hah.init_meem.medi': 'ﲪ',
- '/hah.init_yeh.fina': 'ﴀ', '/hah.isol': 'ﺡ', '/hah.medi': 'ﺤ',
- '/hah.medi_alefmaksura.fina': 'ﴛ', '/hah.medi_jeem.medi_yeh.fina': 'ﶿ',
- '/hah.medi_meem.medi_alefmaksura.fina': 'ﵛ',
- '/hah.medi_meem.medi_yeh.fina': 'ﵚ', '/hah.medi_yeh.fina': 'ﴜ',
- '/hahDigitFourBelow': 'ݼ', '/hahSmallTahAbove': 'ݲ',
- '/hahSmallTahBelow': 'ݮ', '/hahSmallTahTwoDots': 'ݯ',
- '/hahThreeDotsUpBelow': 'ݘ', '/hahTwoDotsAbove': 'ݗ', '/haharabic': 'ح',
- '/hahfinalarabic': 'ﺢ', '/hahhamza': 'ځ', '/hahinitialarabic': 'ﺣ',
- '/hahiragana': 'は', '/hahmedialarabic': 'ﺤ', '/hahookcyr': 'ӽ',
- '/hahthreedotsabove': 'څ', '/hahtwodotsvertical': 'ڂ', '/haircut': 'Ὀ7',
- '/hairspace': '\u200a', '/haitusquare': '㌪', '/hakatakana': 'ハ',
- '/hakatakanahalfwidth': 'ハ', '/halantgurmukhi': '੍',
- '/halfcircleleftblack': '◖', '/halfcirclerightblack': '◗', '/hamburger':
- 'ἵ4', '/hammer': 'ὒ8', '/hammerAndWrench': 'Ὦ0', '/hammerpick': '⚒',
- '/hammersickle': '☭', '/hamsterFace': 'ὃ9', '/hamza': 'ء', '/hamzaIsol':
- 'ﺀ', '/hamzaabove': 'ٔ', '/hamzaarabic': 'ء', '/hamzabelow': 'ٕ',
- '/hamzadammaarabic': 'ء', '/hamzadammatanarabic': 'ء',
- '/hamzafathaarabic': 'ء', '/hamzafathatanarabic': 'ء',
- '/hamzalowarabic': 'ء', '/hamzalowkasraarabic': 'ء',
- '/hamzalowkasratanarabic': 'ء', '/hamzasukunarabic': 'ء', '/handbag':
- 'ὅC', '/handtailfishhookturned': 'ʯ', '/hangulchieuchaparen': '㈗',
- '/hangulchieuchparen': '㈉', '/hangulcieucaparen': '㈖',
- '/hangulcieucparen': '㈈', '/hangulcieucuparen': '㈜',
- '/hanguldottonemarkdbl': '〯', '/hangulfiller': 'ㅤ',
- '/hangulhieuhaparen': '㈛', '/hangulhieuhparen': '㈍',
- '/hangulieungaparen': '㈕', '/hangulieungparen': '㈇',
- '/hangulkhieukhaparen': '㈘', '/hangulkhieukhparen': '㈊',
- '/hangulkiyeokaparen': '㈎', '/hangulkiyeokparen': '㈀',
- '/hangulmieumaparen': '㈒', '/hangulmieumparen': '㈄',
- '/hangulnieunaparen': '㈏', '/hangulnieunparen': '㈁',
- '/hangulphieuphaparen': '㈚', '/hangulphieuphparen': '㈌',
- '/hangulpieupaparen': '㈓', '/hangulpieupparen': '㈅',
- '/hangulrieulaparen': '㈑', '/hangulrieulparen': '㈃',
- '/hangulsingledottonemark': '〮', '/hangulsiosaparen': '㈔',
- '/hangulsiosparen': '㈆', '/hangulthieuthaparen': '㈙',
- '/hangulthieuthparen': '㈋', '/hangultikeutaparen': '㈐',
- '/hangultikeutparen': '㈂', '/happyPersonRaisingOneHand': 'ὤB',
- '/hardDisk': 'Ὓ4', '/hardcyr': 'ъ', '/hardsigncyrillic': 'ъ',
- '/harpoondownbarbleft': '⇃', '/harpoondownbarbright': '⇂',
- '/harpoonleftbarbdown': '↽', '/harpoonleftbarbup': '↼',
- '/harpoonrightbarbdown': '⇁', '/harpoonrightbarbup': '⇀',
- '/harpoonupbarbleft': '↿', '/harpoonupbarbright': '↾', '/hasquare': '㏊',
- '/hastrokecyr': 'ӿ', '/hatafPatah:hb': 'ֲ', '/hatafQamats:hb': 'ֳ',
- '/hatafSegol:hb': 'ֱ', '/hatafpatah': 'ֲ', '/hatafpatah16': 'ֲ',
- '/hatafpatah23': 'ֲ', '/hatafpatah2f': 'ֲ', '/hatafpatahhebrew': 'ֲ',
- '/hatafpatahnarrowhebrew': 'ֲ', '/hatafpatahquarterhebrew': 'ֲ',
- '/hatafpatahwidehebrew': 'ֲ', '/hatafqamats': 'ֳ', '/hatafqamats1b':
- 'ֳ', '/hatafqamats28': 'ֳ', '/hatafqamats34': 'ֳ', '/hatafqamatshebrew':
- 'ֳ', '/hatafqamatsnarrowhebrew': 'ֳ', '/hatafqamatsquarterhebrew': 'ֳ',
- '/hatafqamatswidehebrew': 'ֳ', '/hatafsegol': 'ֱ', '/hatafsegol17': 'ֱ',
- '/hatafsegol24': 'ֱ', '/hatafsegol30': 'ֱ', '/hatafsegolhebrew': 'ֱ',
- '/hatafsegolnarrowhebrew': 'ֱ', '/hatafsegolquarterhebrew': 'ֱ',
- '/hatafsegolwidehebrew': 'ֱ', '/hatchingChick': 'ὂ3',
- '/haveideographiccircled': '㊒', '/haveideographicparen': '㈲', '/hbar':
- 'ħ', '/hbopomofo': 'ㄏ', '/hbrevebelow': 'ḫ', '/hcaron': 'ȟ',
- '/hcedilla': 'ḩ', '/hcircle': 'ⓗ', '/hcircumflex': 'ĥ', '/hcsquare':
- 'Ἒ6', '/hdescender': 'ⱨ', '/hdieresis': 'ḧ', '/hdot': 'ḣ',
- '/hdotaccent': 'ḣ', '/hdotbelow': 'ḥ', '/hdrsquare': 'Ἒ7', '/he': 'ה',
- '/he:hb': 'ה', '/headphone': 'Ἲ7', '/headstonegraveyard': '⛼',
- '/hearNoEvilMonkey': 'ὤ9', '/heart': '♥', '/heartArrow': 'Ὁ8',
- '/heartDecoration': 'ὉF', '/heartRibbon': 'ὉD', '/heartTipOnTheLeft':
- 'Ἱ4', '/heartblack': '♥', '/heartsuitblack': '♥', '/heartsuitwhite':
- '♡', '/heartwhite': '♡', '/heavyDollarSign': 'Ὃ2', '/heavyLatinCross':
- 'ὔ7', '/heavydbldashhorz': '╍', '/heavydbldashvert': '╏', '/heavydn':
- '╻', '/heavydnhorz': '┳', '/heavydnleft': '┓', '/heavydnright': '┏',
- '/heavyhorz': '━', '/heavyleft': '╸', '/heavyleftlightright': '╾',
- '/heavyquaddashhorz': '┉', '/heavyquaddashvert': '┋', '/heavyright':
- '╺', '/heavytrpldashhorz': '┅', '/heavytrpldashvert': '┇', '/heavyup':
- '╹', '/heavyuphorz': '┻', '/heavyupleft': '┛', '/heavyuplightdn': '╿',
- '/heavyupright': '┗', '/heavyvert': '┃', '/heavyverthorz': '╋',
- '/heavyvertleft': '┫', '/heavyvertright': '┣', '/hecirclekatakana': '㋬',
- '/hedagesh': 'הּ', '/hedageshhebrew': 'הּ', '/hedinterlacedpentagramleft':
- '⛦', '/hedinterlacedpentagramright': '⛥', '/heh': 'ه', '/heh.fina': 'ﻪ',
- '/heh.init': 'ﻫ', '/heh.init_alefmaksura.fina': 'ﱓ',
- '/heh.init_jeem.fina': 'ﱑ', '/heh.init_jeem.medi': 'ﳗ',
- '/heh.init_meem.fina': 'ﱒ', '/heh.init_meem.medi': 'ﳘ',
- '/heh.init_meem.medi_jeem.medi': 'ﶓ', '/heh.init_meem.medi_meem.medi':
- 'ﶔ', '/heh.init_superscriptalef.medi': 'ﳙ', '/heh.init_yeh.fina': 'ﱔ',
- '/heh.isol': 'ﻩ', '/heh.medi': 'ﻬ', '/hehaltonearabic': 'ہ',
- '/heharabic': 'ه', '/hehdoachashmee': 'ھ', '/hehdoachashmee.fina': 'ﮫ',
- '/hehdoachashmee.init': 'ﮬ', '/hehdoachashmee.isol': 'ﮪ',
- '/hehdoachashmee.medi': 'ﮭ', '/hehebrew': 'ה', '/hehfinalaltonearabic':
- 'ﮧ', '/hehfinalalttwoarabic': 'ﻪ', '/hehfinalarabic': 'ﻪ', '/hehgoal':
- 'ہ', '/hehgoal.fina': 'ﮧ', '/hehgoal.init': 'ﮨ', '/hehgoal.isol': 'ﮦ',
- '/hehgoal.medi': 'ﮩ', '/hehgoalhamza': 'ۂ', '/hehhamzaabovefinalarabic':
- 'ﮥ', '/hehhamzaaboveisolatedarabic': 'ﮤ', '/hehinitialaltonearabic':
- 'ﮨ', '/hehinitialarabic': 'ﻫ', '/hehinvertedV': 'ۿ', '/hehiragana': 'へ',
- '/hehmedialaltonearabic': 'ﮩ', '/hehmedialarabic': 'ﻬ', '/hehyeh': 'ۀ',
- '/hehyeh.fina': 'ﮥ', '/hehyeh.isol': 'ﮤ', '/heiseierasquare': '㍻',
- '/hekatakana': 'ヘ', '/hekatakanahalfwidth': 'ヘ', '/hekutaarusquare':
- '㌶', '/helicopter': 'Ὠ1', '/helm': '⎈', '/helmetcrosswhite': '⛑',
- '/heng': 'ꜧ', '/henghook': 'ɧ', '/herb': 'ἳF',
- '/hermitianconjugatematrix': '⊹', '/herutusquare': '㌹', '/het': 'ח',
- '/het:hb': 'ח', '/heta': 'ͱ', '/hethebrew': 'ח', '/hewide:hb': 'ﬣ',
- '/hewithmapiq:hb': 'הּ', '/hfishhookturned': 'ʮ', '/hhalf': 'ⱶ',
- '/hhook': 'ɦ', '/hhooksuperior': 'ʱ', '/hhooksupmod': 'ʱ',
- '/hi-ressquare': 'Ἒ8', '/hibiscus': 'ἳA', '/hicirclekatakana': '㋪',
- '/hieuhacirclekorean': '㉻', '/hieuhaparenkorean': '㈛',
- '/hieuhcirclekorean': '㉭', '/hieuhkorean': 'ㅎ', '/hieuhparenkorean':
- '㈍', '/high-heeledShoe': '\u1f460', '/highBrightness': 'ὐ6',
- '/highSpeedTrain': 'Ὠ4', '/highSpeedTrainWithBulletNose': 'Ὠ5',
- '/highhamza': 'ٴ', '/highideographiccircled': '㊤', '/highvoltage': '⚡',
- '/hihiragana': 'ひ', '/hikatakana': 'ヒ', '/hikatakanahalfwidth': 'ヒ',
- '/hira:a': 'あ', '/hira:asmall': 'ぁ', '/hira:ba': 'ば', '/hira:be': 'べ',
- '/hira:bi': 'び', '/hira:bo': 'ぼ', '/hira:bu': 'ぶ', '/hira:da': 'だ',
- '/hira:de': 'で', '/hira:di': 'ぢ', '/hira:digraphyori': 'ゟ', '/hira:do':
- 'ど', '/hira:du': 'づ', '/hira:e': 'え', '/hira:esmall': 'ぇ', '/hira:ga':
- 'が', '/hira:ge': 'げ', '/hira:gi': 'ぎ', '/hira:go': 'ご', '/hira:gu': 'ぐ',
- '/hira:ha': 'は', '/hira:he': 'へ', '/hira:hi': 'ひ', '/hira:ho': 'ほ',
- '/hira:hu': 'ふ', '/hira:i': 'い', '/hira:ismall': 'ぃ',
- '/hira:iterationhiragana': 'ゝ', '/hira:ka': 'か', '/hira:kasmall': 'ゕ',
- '/hira:ke': 'け', '/hira:kesmall': 'ゖ', '/hira:ki': 'き', '/hira:ko': 'こ',
- '/hira:ku': 'く', '/hira:ma': 'ま', '/hira:me': 'め', '/hira:mi': 'み',
- '/hira:mo': 'も', '/hira:mu': 'む', '/hira:n': 'ん', '/hira:na': 'な',
- '/hira:ne': 'ね', '/hira:ni': 'に', '/hira:no': 'の', '/hira:nu': 'ぬ',
- '/hira:o': 'お', '/hira:osmall': 'ぉ', '/hira:pa': 'ぱ', '/hira:pe': 'ぺ',
- '/hira:pi': 'ぴ', '/hira:po': 'ぽ', '/hira:pu': 'ぷ', '/hira:ra': 'ら',
- '/hira:re': 'れ', '/hira:ri': 'り', '/hira:ro': 'ろ', '/hira:ru': 'る',
- '/hira:sa': 'さ', '/hira:se': 'せ', '/hira:semivoicedmarkkana': '゜',
- '/hira:semivoicedmarkkanacmb': '゚', '/hira:si': 'し', '/hira:so': 'そ',
- '/hira:su': 'す', '/hira:ta': 'た', '/hira:te': 'て', '/hira:ti': 'ち',
- '/hira:to': 'と', '/hira:tu': 'つ', '/hira:tusmall': 'っ', '/hira:u': 'う',
- '/hira:usmall': 'ぅ', '/hira:voicediterationhiragana': 'ゞ',
- '/hira:voicedmarkkana': '゛', '/hira:voicedmarkkanacmb': '゙', '/hira:vu':
- 'ゔ', '/hira:wa': 'わ', '/hira:wasmall': 'ゎ', '/hira:we': 'ゑ', '/hira:wi':
- 'ゐ', '/hira:wo': 'を', '/hira:ya': 'や', '/hira:yasmall': 'ゃ', '/hira:yo':
- 'よ', '/hira:yosmall': 'ょ', '/hira:yu': 'ゆ', '/hira:yusmall': 'ゅ',
- '/hira:za': 'ざ', '/hira:ze': 'ぜ', '/hira:zi': 'じ', '/hira:zo': 'ぞ',
- '/hira:zu': 'ず', '/hiriq': 'ִ', '/hiriq14': 'ִ', '/hiriq21': 'ִ',
- '/hiriq2d': 'ִ', '/hiriq:hb': 'ִ', '/hiriqhebrew': 'ִ',
- '/hiriqnarrowhebrew': 'ִ', '/hiriqquarterhebrew': 'ִ',
- '/hiriqwidehebrew': 'ִ', '/historicsite': '⛬', '/hlinebelow': 'ẖ',
- '/hmonospace': 'h', '/hoarmenian': 'հ', '/hocho': 'ὒA',
- '/hocirclekatakana': '㋭', '/hohipthai': 'ห', '/hohiragana': 'ほ',
- '/hokatakana': 'ホ', '/hokatakanahalfwidth': 'ホ', '/holam': 'ֹ',
- '/holam19': 'ֹ', '/holam26': 'ֹ', '/holam32': 'ֹ', '/holam:hb': 'ֹ',
- '/holamHaser:hb': 'ֺ', '/holamhebrew': 'ֹ', '/holamnarrowhebrew': 'ֹ',
- '/holamquarterhebrew': 'ֹ', '/holamwidehebrew': 'ֹ', '/hole': 'ὗ3',
- '/homotic': '∻', '/honeyPot': 'ἶF', '/honeybee': 'ὁD', '/honokhukthai':
- 'ฮ', '/honsquare': '㌿', '/hook': '⑀', '/hookabovecomb': '̉', '/hookcmb':
- '̉', '/hookpalatalizedbelowcmb': '̡', '/hookretroflexbelowcmb': '̢',
- '/hoonsquare': '㍂', '/hoorusquare': '㍁', '/horicoptic': 'ϩ',
- '/horizontalTrafficLight': 'Ὢ5', '/horizontalbar': '―',
- '/horizontalbarwhitearrowonpedestalup': '⇬', '/horizontalmalestroke':
- '⚩', '/horncmb': '̛', '/horse': 'ὀE', '/horseFace': 'ὃ4',
- '/horseRacing': 'Ἴ7', '/hospital': 'Ἶ5', '/hotDog': 'ἲD', '/hotPepper':
- 'ἳ6', '/hotbeverage': '☕', '/hotel': 'Ἶ8', '/hotsprings': '♨',
- '/hourglass': '⌛', '/hourglassflowings': '⏳', '/house': '⌂',
- '/houseBuilding': 'Ἶ0', '/houseBuildings': 'Ἵ8', '/houseGarden': 'Ἶ1',
- '/hpafullwidth': '㍱', '/hpalatalhook': 'ꞕ', '/hparen': '⒣',
- '/hparenthesized': '⒣', '/hpfullwidth': '㏋', '/hryvnia': '₴',
- '/hsuperior': 'ʰ', '/hsupmod': 'ʰ', '/hturned': 'ɥ',
- '/htypeopencircuit': '⎏', '/huaraddosquare': '㌲', '/hucirclekatakana':
- '㋫', '/huhiragana': 'ふ', '/huiitosquare': '㌳', '/hukatakana': 'フ',
- '/hukatakanahalfwidth': 'フ', '/hundredPoints': 'ὊF',
- '/hundredthousandscmbcyr': '҈', '/hungarumlaut': '˝',
- '/hungarumlautcmb': '̋', '/huransquare': '㌵', '/hushedFace': 'ὢF',
- '/hv': 'ƕ', '/hwd:a': 'ᅡ', '/hwd:ae': 'ᅢ', '/hwd:blacksquare': '■',
- '/hwd:chieuch': 'ᄎ', '/hwd:cieuc': 'ᄌ', '/hwd:downwardsarrow': '↓',
- '/hwd:e': 'ᅦ', '/hwd:eo': 'ᅥ', '/hwd:eu': 'ᅳ',
- '/hwd:formslightvertical': '│', '/hwd:hangulfiller': 'ᅠ', '/hwd:hieuh':
- 'ᄒ', '/hwd:i': 'ᅵ', '/hwd:ideographiccomma': '、',
- '/hwd:ideographicfullstop': '。', '/hwd:ieung': 'ᄋ', '/hwd:kata:a': 'ア',
- '/hwd:kata:asmall': 'ァ', '/hwd:kata:e': 'エ', '/hwd:kata:esmall': 'ェ',
- '/hwd:kata:ha': 'ハ', '/hwd:kata:he': 'ヘ', '/hwd:kata:hi': 'ヒ',
- '/hwd:kata:ho': 'ホ', '/hwd:kata:hu': 'フ', '/hwd:kata:i': 'イ',
- '/hwd:kata:ismall': 'ィ', '/hwd:kata:ka': 'カ', '/hwd:kata:ke': 'ケ',
- '/hwd:kata:ki': 'キ', '/hwd:kata:ko': 'コ', '/hwd:kata:ku': 'ク',
- '/hwd:kata:ma': 'マ', '/hwd:kata:me': 'メ', '/hwd:kata:mi': 'ミ',
- '/hwd:kata:middledot': '・', '/hwd:kata:mo': 'モ', '/hwd:kata:mu': 'ム',
- '/hwd:kata:n': 'ン', '/hwd:kata:na': 'ナ', '/hwd:kata:ne': 'ネ',
- '/hwd:kata:ni': 'ニ', '/hwd:kata:no': 'ノ', '/hwd:kata:nu': 'ヌ',
- '/hwd:kata:o': 'オ', '/hwd:kata:osmall': 'ォ', '/hwd:kata:prolongedkana':
- 'ー', '/hwd:kata:ra': 'ラ', '/hwd:kata:re': 'レ', '/hwd:kata:ri': 'リ',
- '/hwd:kata:ro': 'ロ', '/hwd:kata:ru': 'ル', '/hwd:kata:sa': 'サ',
- '/hwd:kata:se': 'セ', '/hwd:kata:semi-voiced': '゚', '/hwd:kata:si': 'シ',
- '/hwd:kata:so': 'ソ', '/hwd:kata:su': 'ス', '/hwd:kata:ta': 'タ',
- '/hwd:kata:te': 'テ', '/hwd:kata:ti': 'チ', '/hwd:kata:to': 'ト',
- '/hwd:kata:tu': 'ツ', '/hwd:kata:tusmall': 'ッ', '/hwd:kata:u': 'ウ',
- '/hwd:kata:usmall': 'ゥ', '/hwd:kata:voiced': '゙', '/hwd:kata:wa': 'ワ',
- '/hwd:kata:wo': 'ヲ', '/hwd:kata:ya': 'ヤ', '/hwd:kata:yasmall': 'ャ',
- '/hwd:kata:yo': 'ヨ', '/hwd:kata:yosmall': 'ョ', '/hwd:kata:yu': 'ユ',
- '/hwd:kata:yusmall': 'ュ', '/hwd:khieukh': 'ᄏ', '/hwd:kiyeok': 'ᄀ',
- '/hwd:kiyeoksios': 'ᆪ', '/hwd:leftcornerbracket': '「',
- '/hwd:leftwardsarrow': '←', '/hwd:mieum': 'ᄆ', '/hwd:nieun': 'ᄂ',
- '/hwd:nieuncieuc': 'ᆬ', '/hwd:nieunhieuh': 'ᆭ', '/hwd:o': 'ᅩ',
- '/hwd:oe': 'ᅬ', '/hwd:phieuph': 'ᄑ', '/hwd:pieup': 'ᄇ',
- '/hwd:pieupsios': 'ᄡ', '/hwd:rieul': 'ᄅ', '/hwd:rieulhieuh': 'ᄚ',
- '/hwd:rieulkiyeok': 'ᆰ', '/hwd:rieulmieum': 'ᆱ', '/hwd:rieulphieuph':
- 'ᆵ', '/hwd:rieulpieup': 'ᆲ', '/hwd:rieulsios': 'ᆳ', '/hwd:rieulthieuth':
- 'ᆴ', '/hwd:rightcornerbracket': '」', '/hwd:rightwardsarrow': '→',
- '/hwd:sios': 'ᄉ', '/hwd:ssangcieuc': 'ᄍ', '/hwd:ssangkiyeok': 'ᄁ',
- '/hwd:ssangpieup': 'ᄈ', '/hwd:ssangsios': 'ᄊ', '/hwd:ssangtikeut': 'ᄄ',
- '/hwd:thieuth': 'ᄐ', '/hwd:tikeut': 'ᄃ', '/hwd:u': 'ᅮ',
- '/hwd:upwardsarrow': '↑', '/hwd:wa': 'ᅪ', '/hwd:wae': 'ᅫ', '/hwd:we':
- 'ᅰ', '/hwd:weo': 'ᅯ', '/hwd:whitecircle': '○', '/hwd:wi': 'ᅱ',
- '/hwd:ya': 'ᅣ', '/hwd:yae': 'ᅤ', '/hwd:ye': 'ᅨ', '/hwd:yeo': 'ᅧ',
- '/hwd:yi': 'ᅴ', '/hwd:yo': 'ᅭ', '/hwd:yu': 'ᅲ', '/hyphen': '-',
- '/hyphenationpoint': '‧', '/hyphenbullet': '⁃', '/hyphendbl': '⹀',
- '/hyphendbloblique': '⸗', '/hyphendieresis': '⸚', '/hypheninferior':
- '\uf6e5', '/hyphenminus': '-', '/hyphenmonospace': '-', '/hyphensmall':
- '﹣', '/hyphensoft': '\xad', '/hyphensuperior': '\uf6e6', '/hyphentwo':
- '‐', '/hypodiastole': '⸒', '/hysteresis': '⎎', '/hzfullwidth': '㎐',
- '/i': 'i', '/i.superior': 'ⁱ', '/iacute': 'í', '/iacyrillic': 'я',
- '/iaepigraphic': 'ꟾ', '/ibengali': 'ই', '/ibopomofo': 'ㄧ', '/ibreve':
- 'ĭ', '/icaron': 'ǐ', '/iceCream': 'ἶ8', '/iceHockeyStickAndPuck': 'Ἵ2',
- '/iceskate': '⛸', '/icircle': 'ⓘ', '/icirclekatakana': '㋑',
- '/icircumflex': 'î', '/icyr': 'и', '/icyrillic': 'і', '/idblgrave': 'ȉ',
- '/idblstruckitalic': 'ⅈ', '/ideographearthcircle': '㊏',
- '/ideographfirecircle': '㊋', '/ideographicallianceparen': '㈿',
- '/ideographiccallparen': '㈺', '/ideographiccentrecircle': '㊥',
- '/ideographicclose': '〆', '/ideographiccomma': '、',
- '/ideographiccommaleft': '、', '/ideographiccongratulationparen': '㈷',
- '/ideographiccorrectcircle': '㊣', '/ideographicdepartingtonemark': '〬',
- '/ideographicearthparen': '㈯', '/ideographicenteringtonemark': '〭',
- '/ideographicenterpriseparen': '㈽', '/ideographicexcellentcircle': '㊝',
- '/ideographicfestivalparen': '㉀', '/ideographicfinancialcircle': '㊖',
- '/ideographicfinancialparen': '㈶', '/ideographicfireparen': '㈫',
- '/ideographichalffillspace': '〿', '/ideographichaveparen': '㈲',
- '/ideographichighcircle': '㊤', '/ideographiciterationmark': '々',
- '/ideographiclaborcircle': '㊘', '/ideographiclaborparen': '㈸',
- '/ideographicleftcircle': '㊧', '/ideographicleveltonemark': '〪',
- '/ideographiclowcircle': '㊦', '/ideographicmedicinecircle': '㊩',
- '/ideographicmetalparen': '㈮', '/ideographicmoonparen': '㈪',
- '/ideographicnameparen': '㈴', '/ideographicperiod': '。',
- '/ideographicprintcircle': '㊞', '/ideographicreachparen': '㉃',
- '/ideographicrepresentparen': '㈹', '/ideographicresourceparen': '㈾',
- '/ideographicrightcircle': '㊨', '/ideographicrisingtonemark': '〫',
- '/ideographicsecretcircle': '㊙', '/ideographicselfparen': '㉂',
- '/ideographicsocietyparen': '㈳', '/ideographicspace': '\u3000',
- '/ideographicspecialparen': '㈵', '/ideographicstockparen': '㈱',
- '/ideographicstudyparen': '㈻', '/ideographicsunparen': '㈰',
- '/ideographicsuperviseparen': '㈼',
- '/ideographictelegraphlinefeedseparatorsymbol': '〷',
- '/ideographictelegraphsymbolforhoureight': '㍠',
- '/ideographictelegraphsymbolforhoureighteen': '㍪',
- '/ideographictelegraphsymbolforhoureleven': '㍣',
- '/ideographictelegraphsymbolforhourfifteen': '㍧',
- '/ideographictelegraphsymbolforhourfive': '㍝',
- '/ideographictelegraphsymbolforhourfour': '㍜',
- '/ideographictelegraphsymbolforhourfourteen': '㍦',
- '/ideographictelegraphsymbolforhournine': '㍡',
- '/ideographictelegraphsymbolforhournineteen': '㍫',
- '/ideographictelegraphsymbolforhourone': '㍙',
- '/ideographictelegraphsymbolforhourseven': '㍟',
- '/ideographictelegraphsymbolforhourseventeen': '㍩',
- '/ideographictelegraphsymbolforhoursix': '㍞',
- '/ideographictelegraphsymbolforhoursixteen': '㍨',
- '/ideographictelegraphsymbolforhourten': '㍢',
- '/ideographictelegraphsymbolforhourthirteen': '㍥',
- '/ideographictelegraphsymbolforhourthree': '㍛',
- '/ideographictelegraphsymbolforhourtwelve': '㍤',
- '/ideographictelegraphsymbolforhourtwenty': '㍬',
- '/ideographictelegraphsymbolforhourtwentyfour': '㍰',
- '/ideographictelegraphsymbolforhourtwentyone': '㍭',
- '/ideographictelegraphsymbolforhourtwentythree': '㍯',
- '/ideographictelegraphsymbolforhourtwentytwo': '㍮',
- '/ideographictelegraphsymbolforhourtwo': '㍚',
- '/ideographictelegraphsymbolforhourzero': '㍘',
- '/ideographicvariationindicator': '〾', '/ideographicwaterparen': '㈬',
- '/ideographicwoodparen': '㈭', '/ideographiczero': '〇',
- '/ideographmetalcircle': '㊎', '/ideographmooncircle': '㊊',
- '/ideographnamecircle': '㊔', '/ideographsuncircle': '㊐',
- '/ideographwatercircle': '㊌', '/ideographwoodcircle': '㊍', '/ideva':
- 'इ', '/idieresis': 'ï', '/idieresisacute': 'ḯ', '/idieresiscyr': 'ӥ',
- '/idieresiscyrillic': 'ӥ', '/idotbelow': 'ị', '/idsquare': 'Ἑ4',
- '/iebrevecyr': 'ӗ', '/iebrevecyrillic': 'ӗ', '/iecyr': 'е',
- '/iecyrillic': 'е', '/iegravecyr': 'ѐ', '/iepigraphicsideways': 'ꟷ',
- '/ieungacirclekorean': '㉵', '/ieungaparenkorean': '㈕',
- '/ieungcirclekorean': '㉧', '/ieungkorean': 'ㅇ', '/ieungparenkorean':
- '㈇', '/ieungucirclekorean': '㉾', '/igrave': 'ì', '/igravecyr': 'ѝ',
- '/igravedbl': 'ȉ', '/igujarati': 'ઇ', '/igurmukhi': 'ਇ', '/ihiragana':
- 'い', '/ihoi': 'ỉ', '/ihookabove': 'ỉ', '/iibengali': 'ঈ', '/iicyrillic':
- 'и', '/iideva': 'ई', '/iigujarati': 'ઈ', '/iigurmukhi': 'ਈ',
- '/iimatragurmukhi': 'ੀ', '/iinvertedbreve': 'ȋ', '/iishortcyrillic':
- 'й', '/iivowelsignbengali': 'ী', '/iivowelsigndeva': 'ी',
- '/iivowelsigngujarati': 'ી', '/ij': 'ij', '/ikatakana': 'イ',
- '/ikatakanahalfwidth': 'イ', '/ikawi': 'ꦅ', '/ikorean': 'ㅣ', '/ilde':
- '˜', '/iluy:hb': '֬', '/iluyhebrew': '֬', '/imacron': 'ī',
- '/imacroncyr': 'ӣ', '/imacroncyrillic': 'ӣ', '/image': '⊷',
- '/imageorapproximatelyequal': '≓', '/imatragurmukhi': 'ਿ',
- '/imonospace': 'i', '/imp': '\u1f47F', '/inboxTray': '\u1f4e5',
- '/incomingEnvelope': '\u1f4e8', '/increaseFontSize': 'ὝA', '/increment':
- '∆', '/indianrupee': '₹', '/infinity': '∞', '/information': 'ℹ',
- '/infullwidth': '㏌', '/inhibitarabicformshaping': '\u206c',
- '/inhibitsymmetricswapping': '\u206a', '/iniarmenian': 'ի',
- '/iningusquare': '㌄', '/inmationDeskPerson': 'Ὀ1',
- '/inputLatinCapitalLetters': 'ὒ0', '/inputLatinLetters': 'ὒ4',
- '/inputLatinSmallLetters': 'ὒ1', '/inputNumbers': 'ὒ2', '/inputS': 'ὒ3',
- '/insertion': '⎀', '/integral': '∫', '/integralbottom': '⌡',
- '/integralbt': '⌡', '/integralclockwise': '∱', '/integralcontour': '∮',
- '/integralcontouranticlockwise': '∳', '/integralcontourclockwise': '∲',
- '/integraldbl': '∬', '/integralex': '\uf8f5', '/integralextension': '⎮',
- '/integralsurface': '∯', '/integraltop': '⌠', '/integraltp': '⌠',
- '/integraltpl': '∭', '/integralvolume': '∰', '/intercalate': '⊺',
- '/interlinearanchor': '\ufff9', '/interlinearseparator': '\ufffa',
- '/interlinearterminator': '\ufffb', '/interlockedfemalemale': '⚤',
- '/interrobang': '‽', '/interrobanginverted': '⸘', '/intersection': '∩',
- '/intersectionarray': '⋂', '/intersectiondbl': '⋒', '/intisquare': '㌅',
- '/invbullet': '◘', '/invcircle': '◙', '/inverteddamma': 'ٗ',
- '/invertedfork': '⑃', '/invertedpentagram': '⛧', '/invertedundertie':
- '⁔', '/invisibleplus': '\u2064', '/invisibleseparator': '\u2063',
- '/invisibletimes': '\u2062', '/invsmileface': '☻', '/iocyr': 'ё',
- '/iocyrillic': 'ё', '/iogonek': 'į', '/iota': 'ι', '/iotaacute': 'ί',
- '/iotaadscript': 'ι', '/iotaasper': 'ἱ', '/iotaasperacute': 'ἵ',
- '/iotaaspergrave': 'ἳ', '/iotaaspertilde': 'ἷ', '/iotabreve': 'ῐ',
- '/iotadieresis': 'ϊ', '/iotadieresisacute': 'ΐ', '/iotadieresisgrave':
- 'ῒ', '/iotadieresistilde': 'ῗ', '/iotadieresistonos': 'ΐ', '/iotafunc':
- '⍳', '/iotagrave': 'ὶ', '/iotalatin': 'ɩ', '/iotalenis': 'ἰ',
- '/iotalenisacute': 'ἴ', '/iotalenisgrave': 'ἲ', '/iotalenistilde': 'ἶ',
- '/iotasub': 'ͺ', '/iotatilde': 'ῖ', '/iotatonos': 'ί', '/iotaturned':
- '℩', '/iotaunderlinefunc': '⍸', '/iotawithmacron': 'ῑ', '/ipa:Ismall':
- 'ɪ', '/ipa:alpha': 'ɑ', '/ipa:ereversed': 'ɘ', '/ipa:esh': 'ʃ',
- '/ipa:gamma': 'ɣ', '/ipa:glottalstop': 'ʔ', '/ipa:gscript': 'ɡ',
- '/ipa:iota': 'ɩ', '/ipa:phi': 'ɸ', '/ipa:rtail': 'ɽ', '/ipa:schwa': 'ə',
- '/ipa:upsilon': 'ʊ', '/iparen': '⒤', '/iparenthesized': '⒤',
- '/irigurmukhi': 'ੲ', '/is': 'ꝭ', '/isen-isenpada': '꧟', '/ishortcyr':
- 'й', '/ishortsharptailcyr': 'ҋ', '/ismallhiragana': 'ぃ',
- '/ismallkatakana': 'ィ', '/ismallkatakanahalfwidth': 'ィ',
- '/issharbengali': '৺', '/istroke': 'ɨ', '/isuperior': '\uf6ed',
- '/itemideographiccircled': '㊠', '/iterationhiragana': 'ゝ',
- '/iterationkatakana': 'ヽ', '/itilde': 'ĩ', '/itildebelow': 'ḭ',
- '/iubopomofo': 'ㄩ', '/iucyrillic': 'ю', '/iufullwidth': '㍺', '/iukrcyr':
- 'і', '/ivowelsignbengali': 'ি', '/ivowelsigndeva': 'ि',
- '/ivowelsigngujarati': 'િ', '/izakayaLantern': 'ἾE', '/izhitsacyr': 'ѵ',
- '/izhitsacyrillic': 'ѵ', '/izhitsadblgravecyrillic': 'ѷ',
- '/izhitsagravedblcyr': 'ѷ', '/j': 'j', '/j.inferior': 'ⱼ',
- '/jaarmenian': 'ձ', '/jabengali': 'জ', '/jackOLantern': 'Ἰ3', '/jadeva':
- 'ज', '/jagujarati': 'જ', '/jagurmukhi': 'ਜ', '/jamahaprana': 'ꦙ',
- '/januarytelegraph': '㋀', '/japaneseBeginner': 'ὓ0', '/japaneseCastle':
- 'ἾF', '/japaneseDolls': 'ἸE', '/japaneseGoblin': '\u1f47A',
- '/japaneseOgre': '\u1f479', '/japanesePostOffice': 'Ἶ3',
- '/japanesebank': '⛻', '/java:a': 'ꦄ', '/java:ai': 'ꦍ', '/java:ba': 'ꦧ',
- '/java:ca': 'ꦕ', '/java:da': 'ꦢ', '/java:dda': 'ꦝ', '/java:e': 'ꦌ',
- '/java:eight': '꧘', '/java:five': '꧕', '/java:four': '꧔', '/java:ga':
- 'ꦒ', '/java:ha': 'ꦲ', '/java:i': 'ꦆ', '/java:ii': 'ꦇ', '/java:ja': 'ꦗ',
- '/java:ka': 'ꦏ', '/java:la': 'ꦭ', '/java:ma': 'ꦩ', '/java:na': 'ꦤ',
- '/java:nga': 'ꦔ', '/java:nine': '꧙', '/java:nya': 'ꦚ', '/java:o': 'ꦎ',
- '/java:one': '꧑', '/java:pa': 'ꦥ', '/java:ra': 'ꦫ', '/java:sa': 'ꦱ',
- '/java:seven': '꧗', '/java:six': '꧖', '/java:ta': 'ꦠ', '/java:three':
- '꧓', '/java:tta': 'ꦛ', '/java:two': '꧒', '/java:u': 'ꦈ', '/java:wa':
- 'ꦮ', '/java:ya': 'ꦪ', '/java:zero': '꧐', '/jbopomofo': 'ㄐ', '/jcaron':
- 'ǰ', '/jcircle': 'ⓙ', '/jcircumflex': 'ĵ', '/jcrossedtail': 'ʝ',
- '/jdblstruckitalic': 'ⅉ', '/jdotlessstroke': 'ɟ', '/jeans': 'ὅ6',
- '/jecyr': 'ј', '/jecyrillic': 'ј', '/jeem': 'ج', '/jeem.fina': 'ﺞ',
- '/jeem.init': 'ﺟ', '/jeem.init_alefmaksura.fina': 'ﴁ',
- '/jeem.init_hah.fina': 'ﰕ', '/jeem.init_hah.medi': 'ﲧ',
- '/jeem.init_meem.fina': 'ﰖ', '/jeem.init_meem.medi': 'ﲨ',
- '/jeem.init_meem.medi_hah.medi': 'ﵙ', '/jeem.init_yeh.fina': 'ﴂ',
- '/jeem.isol': 'ﺝ', '/jeem.medi': 'ﺠ', '/jeem.medi_alefmaksura.fina':
- 'ﴝ', '/jeem.medi_hah.medi_alefmaksura.fina': 'ﶦ',
- '/jeem.medi_hah.medi_yeh.fina': 'ﶾ',
- '/jeem.medi_meem.medi_alefmaksura.fina': 'ﶧ',
- '/jeem.medi_meem.medi_hah.fina': 'ﵘ', '/jeem.medi_meem.medi_yeh.fina':
- 'ﶥ', '/jeem.medi_yeh.fina': 'ﴞ', '/jeemabove': 'ۚ', '/jeemarabic': 'ج',
- '/jeemfinalarabic': 'ﺞ', '/jeeminitialarabic': 'ﺟ', '/jeemmedialarabic':
- 'ﺠ', '/jeh': 'ژ', '/jeh.fina': 'ﮋ', '/jeh.isol': 'ﮊ', '/jeharabic': 'ژ',
- '/jehfinalarabic': 'ﮋ', '/jhabengali': 'ঝ', '/jhadeva': 'झ',
- '/jhagujarati': 'ઝ', '/jhagurmukhi': 'ਝ', '/jheharmenian': 'ջ', '/jis':
- '〄', '/jiterup': '♃', '/jmonospace': 'j', '/jotdiaeresisfunc': '⍤',
- '/jotunderlinefunc': '⍛', '/joystick': 'ὗ9', '/jparen': '⒥',
- '/jparenthesized': '⒥', '/jstroke': 'ɉ', '/jsuperior': 'ʲ', '/jsupmod':
- 'ʲ', '/jueuicircle': '㉽', '/julytelegraph': '㋆', '/junetelegraph': '㋅',
- '/juno': '⚵', '/k': 'k', '/k.inferior': 'ₖ', '/kaaba': 'ὔB',
- '/kaaleutcyr': 'ԟ', '/kabashkcyr': 'ҡ', '/kabashkircyrillic': 'ҡ',
- '/kabengali': 'ক', '/kacirclekatakana': '㋕', '/kacute': 'ḱ', '/kacyr':
- 'к', '/kacyrillic': 'к', '/kadescendercyrillic': 'қ', '/kadeva': 'क',
- '/kaf': 'כ', '/kaf.fina': 'ﻚ', '/kaf.init': 'ﻛ', '/kaf.init_alef.fina':
- 'ﰷ', '/kaf.init_alefmaksura.fina': 'ﰽ', '/kaf.init_hah.fina': 'ﰹ',
- '/kaf.init_hah.medi': 'ﳅ', '/kaf.init_jeem.fina': 'ﰸ',
- '/kaf.init_jeem.medi': 'ﳄ', '/kaf.init_khah.fina': 'ﰺ',
- '/kaf.init_khah.medi': 'ﳆ', '/kaf.init_lam.fina': 'ﰻ',
- '/kaf.init_lam.medi': 'ﳇ', '/kaf.init_meem.fina': 'ﰼ',
- '/kaf.init_meem.medi': 'ﳈ', '/kaf.init_meem.medi_meem.medi': 'ﷃ',
- '/kaf.init_yeh.fina': 'ﰾ', '/kaf.isol': 'ﻙ', '/kaf.medi': 'ﻜ',
- '/kaf.medi_alef.fina': 'ﲀ', '/kaf.medi_alefmaksura.fina': 'ﲃ',
- '/kaf.medi_lam.fina': 'ﲁ', '/kaf.medi_lam.medi': 'ﳫ',
- '/kaf.medi_meem.fina': 'ﲂ', '/kaf.medi_meem.medi': 'ﳬ',
- '/kaf.medi_meem.medi_meem.fina': 'ﶻ', '/kaf.medi_meem.medi_yeh.fina':
- 'ﶷ', '/kaf.medi_yeh.fina': 'ﲄ', '/kaf:hb': 'כ', '/kafTwoDotsAbove': 'ݿ',
- '/kafarabic': 'ك', '/kafdagesh': 'כּ', '/kafdageshhebrew': 'כּ',
- '/kafdotabove': 'ڬ', '/kaffinalarabic': 'ﻚ', '/kafhebrew': 'כ',
- '/kafinitialarabic': 'ﻛ', '/kafmedialarabic': 'ﻜ', '/kafrafehebrew':
- 'כֿ', '/kafring': 'ګ', '/kafswash': 'ڪ', '/kafthreedotsbelow': 'ڮ',
- '/kafullwidth': '㎄', '/kafwide:hb': 'ﬤ', '/kafwithdagesh:hb': 'כּ',
- '/kafwithrafe:hb': 'כֿ', '/kagujarati': 'ક', '/kagurmukhi': 'ਕ',
- '/kahiragana': 'か', '/kahookcyr': 'ӄ', '/kahookcyrillic': 'ӄ',
- '/kairisquare': '㌋', '/kaisymbol': 'ϗ', '/kakatakana': 'カ',
- '/kakatakanahalfwidth': 'カ', '/kamurda': 'ꦑ', '/kappa': 'κ',
- '/kappa.math': 'ϰ', '/kappasymbolgreek': 'ϰ', '/kapyeounmieumkorean':
- 'ㅱ', '/kapyeounphieuphkorean': 'ㆄ', '/kapyeounpieupkorean': 'ㅸ',
- '/kapyeounssangpieupkorean': 'ㅹ', '/karattosquare': '㌌',
- '/karoriisquare': '㌍', '/kasasak': 'ꦐ', '/kashida': 'ـ', '/kashidaFina':
- 'ﹳ', '/kashidaautoarabic': 'ـ', '/kashidaautonosidebearingarabic': 'ـ',
- '/kashmiriyeh': 'ؠ', '/kasmallkatakana': 'ヵ', '/kasquare': '㎄',
- '/kasra': 'ِ', '/kasraIsol': 'ﹺ', '/kasraMedi': 'ﹻ', '/kasraarabic':
- 'ِ', '/kasrasmall': 'ؚ', '/kasratan': 'ٍ', '/kasratanIsol': 'ﹴ',
- '/kasratanarabic': 'ٍ', '/kastrokecyr': 'ҟ', '/kastrokecyrillic': 'ҟ',
- '/kata:a': 'ア', '/kata:asmall': 'ァ', '/kata:ba': 'バ', '/kata:be': 'ベ',
- '/kata:bi': 'ビ', '/kata:bo': 'ボ', '/kata:bu': 'ブ', '/kata:da': 'ダ',
- '/kata:de': 'デ', '/kata:di': 'ヂ', '/kata:digraphkoto': 'ヿ', '/kata:do':
- 'ド', '/kata:doublehyphenkana': '゠', '/kata:du': 'ヅ', '/kata:e': 'エ',
- '/kata:esmall': 'ェ', '/kata:ga': 'ガ', '/kata:ge': 'ゲ', '/kata:gi': 'ギ',
- '/kata:go': 'ゴ', '/kata:gu': 'グ', '/kata:ha': 'ハ', '/kata:he': 'ヘ',
- '/kata:hi': 'ヒ', '/kata:ho': 'ホ', '/kata:hu': 'フ', '/kata:i': 'イ',
- '/kata:ismall': 'ィ', '/kata:iteration': 'ヽ', '/kata:ka': 'カ',
- '/kata:kasmall': 'ヵ', '/kata:ke': 'ケ', '/kata:kesmall': 'ヶ', '/kata:ki':
- 'キ', '/kata:ko': 'コ', '/kata:ku': 'ク', '/kata:ma': 'マ', '/kata:me': 'メ',
- '/kata:mi': 'ミ', '/kata:middledot': '・', '/kata:mo': 'モ', '/kata:mu':
- 'ム', '/kata:n': 'ン', '/kata:na': 'ナ', '/kata:ne': 'ネ', '/kata:ni': 'ニ',
- '/kata:no': 'ノ', '/kata:nu': 'ヌ', '/kata:o': 'オ', '/kata:osmall': 'ォ',
- '/kata:pa': 'パ', '/kata:pe': 'ペ', '/kata:pi': 'ピ', '/kata:po': 'ポ',
- '/kata:prolongedkana': 'ー', '/kata:pu': 'プ', '/kata:ra': 'ラ',
- '/kata:re': 'レ', '/kata:ri': 'リ', '/kata:ro': 'ロ', '/kata:ru': 'ル',
- '/kata:sa': 'サ', '/kata:se': 'セ', '/kata:si': 'シ', '/kata:so': 'ソ',
- '/kata:su': 'ス', '/kata:ta': 'タ', '/kata:te': 'テ', '/kata:ti': 'チ',
- '/kata:to': 'ト', '/kata:tu': 'ツ', '/kata:tusmall': 'ッ', '/kata:u': 'ウ',
- '/kata:usmall': 'ゥ', '/kata:va': 'ヷ', '/kata:ve': 'ヹ', '/kata:vi': 'ヸ',
- '/kata:vo': 'ヺ', '/kata:voicediteration': 'ヾ', '/kata:vu': 'ヴ',
- '/kata:wa': 'ワ', '/kata:wasmall': 'ヮ', '/kata:we': 'ヱ', '/kata:wi': 'ヰ',
- '/kata:wo': 'ヲ', '/kata:ya': 'ヤ', '/kata:yasmall': 'ャ', '/kata:yo': 'ヨ',
- '/kata:yosmall': 'ョ', '/kata:yu': 'ユ', '/kata:yusmall': 'ュ', '/kata:za':
- 'ザ', '/kata:ze': 'ゼ', '/kata:zi': 'ジ', '/kata:zo': 'ゾ', '/kata:zu': 'ズ',
- '/katahiraprolongmarkhalfwidth': 'ー', '/katailcyr': 'қ',
- '/kaverticalstrokecyr': 'ҝ', '/kaverticalstrokecyrillic': 'ҝ',
- '/kavykainvertedlow': '⹅', '/kavykalow': '⹇', '/kavykawithdotlow': '⹈',
- '/kavykawithkavykaaboveinvertedlow': '⹆', '/kbfullwidth': '㎅',
- '/kbopomofo': 'ㄎ', '/kcalfullwidth': '㎉', '/kcalsquare': '㎉', '/kcaron':
- 'ǩ', '/kcedilla': 'ķ', '/kcircle': 'ⓚ', '/kcommaaccent': 'ķ',
- '/kdescender': 'ⱪ', '/kdiagonalstroke': 'ꝃ', '/kdotbelow': 'ḳ',
- '/kecirclekatakana': '㋘', '/keesusquare': '㌜', '/keharmenian': 'ք',
- '/keheh': 'ک', '/keheh.fina': 'ﮏ', '/keheh.init': 'ﮐ', '/keheh.isol':
- 'ﮎ', '/keheh.medi': 'ﮑ', '/kehehDotAbove': 'ݢ', '/kehehThreeDotsAbove':
- 'ݣ', '/kehehThreeDotsUpBelow': 'ݤ', '/kehehthreedotsbelow': 'ؼ',
- '/kehehtwodotsabove': 'ػ', '/kehiragana': 'け', '/kekatakana': 'ケ',
- '/kekatakanahalfwidth': 'ケ', '/kelvin': 'K', '/kenarmenian': 'կ',
- '/keretconsonant': 'ꦽ', '/kesmallkatakana': 'ヶ', '/key': 'ὑ1',
- '/keyboardAndMouse': '\u1f5a6', '/keycapTen': 'ὑF', '/kgfullwidth': '㎏',
- '/kgreenlandic': 'ĸ', '/khabengali': 'খ', '/khacyrillic': 'х',
- '/khadeva': 'ख', '/khagujarati': 'ખ', '/khagurmukhi': 'ਖ', '/khah': 'خ',
- '/khah.fina': 'ﺦ', '/khah.init': 'ﺧ', '/khah.init_alefmaksura.fina':
- 'ﴃ', '/khah.init_hah.fina': 'ﰚ', '/khah.init_jeem.fina': 'ﰙ',
- '/khah.init_jeem.medi': 'ﲫ', '/khah.init_meem.fina': 'ﰛ',
- '/khah.init_meem.medi': 'ﲬ', '/khah.init_yeh.fina': 'ﴄ', '/khah.isol':
- 'ﺥ', '/khah.medi': 'ﺨ', '/khah.medi_alefmaksura.fina': 'ﴟ',
- '/khah.medi_yeh.fina': 'ﴠ', '/khaharabic': 'خ', '/khahfinalarabic': 'ﺦ',
- '/khahinitialarabic': 'ﺧ', '/khahmedialarabic': 'ﺨ', '/kheicoptic': 'ϧ',
- '/khhadeva': 'ख़', '/khhagurmukhi': 'ਖ਼', '/khieukhacirclekorean': '㉸',
- '/khieukhaparenkorean': '㈘', '/khieukhcirclekorean': '㉪',
- '/khieukhkorean': 'ㅋ', '/khieukhparenkorean': '㈊', '/khokhaithai': 'ข',
- '/khokhonthai': 'ฅ', '/khokhuatthai': 'ฃ', '/khokhwaithai': 'ค',
- '/khomutthai': '๛', '/khook': 'ƙ', '/khorakhangthai': 'ฆ',
- '/khzfullwidth': '㎑', '/khzsquare': '㎑', '/kicirclekatakana': '㋖',
- '/kihiragana': 'き', '/kikatakana': 'キ', '/kikatakanahalfwidth': 'キ',
- '/kimono': 'ὅ8', '/kindergartenideographiccircled': '㉅', '/kingblack':
- '♚', '/kingwhite': '♔', '/kip': '₭', '/kiroguramusquare': '㌕',
- '/kiromeetorusquare': '㌖', '/kirosquare': '㌔', '/kirowattosquare': '㌗',
- '/kiss': 'ὈF', '/kissMark': 'ὈB', '/kissingCatFaceWithClosedEyes': 'ὣD',
- '/kissingFace': 'ὡ7', '/kissingFaceWithClosedEyes': 'ὡA',
- '/kissingFaceWithSmilingEyes': 'ὡ9', '/kiyeokacirclekorean': '㉮',
- '/kiyeokaparenkorean': '㈎', '/kiyeokcirclekorean': '㉠', '/kiyeokkorean':
- 'ㄱ', '/kiyeokparenkorean': '㈀', '/kiyeoksioskorean': 'ㄳ', '/kjecyr':
- 'ќ', '/kjecyrillic': 'ќ', '/kkfullwidth': '㏍', '/klfullwidth': '㎘',
- '/klinebelow': 'ḵ', '/klsquare': '㎘', '/km2fullwidth': '㎢',
- '/km3fullwidth': '㎦', '/kmcapitalfullwidth': '㏎', '/kmcubedsquare': '㎦',
- '/kmfullwidth': '㎞', '/kmonospace': 'k', '/kmsquaredsquare': '㎢',
- '/knda:a': 'ಅ', '/knda:aa': 'ಆ', '/knda:aasign': 'ಾ', '/knda:ai': 'ಐ',
- '/knda:ailength': 'ೖ', '/knda:aisign': 'ೈ', '/knda:anusvara': 'ಂ',
- '/knda:au': 'ಔ', '/knda:ausign': 'ೌ', '/knda:avagraha': 'ಽ', '/knda:ba':
- 'ಬ', '/knda:bha': 'ಭ', '/knda:ca': 'ಚ', '/knda:cha': 'ಛ', '/knda:da':
- 'ದ', '/knda:dda': 'ಡ', '/knda:ddha': 'ಢ', '/knda:dha': 'ಧ', '/knda:e':
- 'ಎ', '/knda:ee': 'ಏ', '/knda:eesign': 'ೇ', '/knda:eight': '೮',
- '/knda:esign': 'ೆ', '/knda:fa': 'ೞ', '/knda:five': '೫', '/knda:four':
- '೪', '/knda:ga': 'ಗ', '/knda:gha': 'ಘ', '/knda:ha': 'ಹ', '/knda:i': 'ಇ',
- '/knda:ii': 'ಈ', '/knda:iisign': 'ೀ', '/knda:isign': 'ಿ', '/knda:ja':
- 'ಜ', '/knda:jha': 'ಝ', '/knda:jihvamuliya': 'ೱ', '/knda:ka': 'ಕ',
- '/knda:kha': 'ಖ', '/knda:la': 'ಲ', '/knda:length': 'ೕ', '/knda:lla':
- 'ಳ', '/knda:llvocal': 'ೡ', '/knda:llvocalsign': 'ೣ', '/knda:lvocal':
- 'ಌ', '/knda:lvocalsign': 'ೢ', '/knda:ma': 'ಮ', '/knda:na': 'ನ',
- '/knda:nga': 'ಙ', '/knda:nine': '೯', '/knda:nna': 'ಣ', '/knda:nukta':
- '಼', '/knda:nya': 'ಞ', '/knda:o': 'ಒ', '/knda:one': '೧', '/knda:oo':
- 'ಓ', '/knda:oosign': 'ೋ', '/knda:osign': 'ೊ', '/knda:pa': 'ಪ',
- '/knda:pha': 'ಫ', '/knda:ra': 'ರ', '/knda:rra': 'ಱ', '/knda:rrvocal':
- 'ೠ', '/knda:rrvocalsign': 'ೄ', '/knda:rvocal': 'ಋ', '/knda:rvocalsign':
- 'ೃ', '/knda:sa': 'ಸ', '/knda:seven': '೭', '/knda:sha': 'ಶ',
- '/knda:signcandrabindu': 'ಁ', '/knda:signspacingcandrabindu': 'ಀ',
- '/knda:six': '೬', '/knda:ssa': 'ಷ', '/knda:ta': 'ತ', '/knda:tha': 'ಥ',
- '/knda:three': '೩', '/knda:tta': 'ಟ', '/knda:ttha': 'ಠ', '/knda:two':
- '೨', '/knda:u': 'ಉ', '/knda:upadhmaniya': 'ೲ', '/knda:usign': 'ು',
- '/knda:uu': 'ಊ', '/knda:uusign': 'ೂ', '/knda:va': 'ವ', '/knda:virama':
- '್', '/knda:visarga': 'ಃ', '/knda:ya': 'ಯ', '/knda:zero': '೦',
- '/knightblack': '♞', '/knightwhite': '♘', '/ko:a': 'ㅏ', '/ko:ae': 'ㅐ',
- '/ko:aejungseong': 'ᅢ', '/ko:aeujungseong': 'ᆣ', '/ko:ajungseong': 'ᅡ',
- '/ko:aojungseong': 'ᅶ', '/ko:araea': 'ㆍ', '/ko:araeae': 'ㆎ',
- '/ko:araeaeojungseong': 'ᆟ', '/ko:araeaijungseong': 'ᆡ',
- '/ko:araeajungseong': 'ᆞ', '/ko:araeaujungseong': 'ᆠ',
- '/ko:aujungseong': 'ᅷ', '/ko:ceongchieumchieuchchoseong': 'ᅕ',
- '/ko:ceongchieumcieucchoseong': 'ᅐ', '/ko:ceongchieumsioschoseong': 'ᄾ',
- '/ko:ceongchieumssangcieucchoseong': 'ᅑ',
- '/ko:ceongchieumssangsioschoseong': 'ᄿ', '/ko:chieuch': 'ㅊ',
- '/ko:chieuchchoseong': 'ᄎ', '/ko:chieuchhieuhchoseong': 'ᅓ',
- '/ko:chieuchjongseong': 'ᆾ', '/ko:chieuchkhieukhchoseong': 'ᅒ',
- '/ko:chitueumchieuchchoseong': 'ᅔ', '/ko:chitueumcieucchoseong': 'ᅎ',
- '/ko:chitueumsioschoseong': 'ᄼ', '/ko:chitueumssangcieucchoseong': 'ᅏ',
- '/ko:chitueumssangsioschoseong': 'ᄽ', '/ko:cieuc': 'ㅈ',
- '/ko:cieucchoseong': 'ᄌ', '/ko:cieucieungchoseong': 'ᅍ',
- '/ko:cieucjongseong': 'ᆽ', '/ko:e': 'ㅔ', '/ko:ejungseong': 'ᅦ',
- '/ko:eo': 'ㅓ', '/ko:eo_eujungseong': 'ᅼ', '/ko:eojungseong': 'ᅥ',
- '/ko:eoojungseong': 'ᅺ', '/ko:eoujungseong': 'ᅻ', '/ko:eu': 'ㅡ',
- '/ko:eueujungseong': 'ᆖ', '/ko:eujungseong': 'ᅳ', '/ko:euujungseong':
- 'ᆕ', '/ko:filler': 'ㅤ', '/ko:fillerchoseong': 'ᅟ',
- '/ko:fillerjungseong': 'ᅠ', '/ko:hieuh': 'ㅎ', '/ko:hieuhchoseong': 'ᄒ',
- '/ko:hieuhjongseong': 'ᇂ', '/ko:hieuhmieumjongseong': 'ᇷ',
- '/ko:hieuhnieunjongseong': 'ᇵ', '/ko:hieuhpieupjongseong': 'ᇸ',
- '/ko:hieuhrieuljongseong': 'ᇶ', '/ko:i': 'ㅣ', '/ko:iajungseong': 'ᆘ',
- '/ko:iaraeajungseong': 'ᆝ', '/ko:ieujungseong': 'ᆜ', '/ko:ieung': 'ㅇ',
- '/ko:ieungchieuchchoseong': 'ᅉ', '/ko:ieungchoseong': 'ᄋ',
- '/ko:ieungcieucchoseong': 'ᅈ', '/ko:ieungjongseong': 'ᆼ',
- '/ko:ieungkhieukhjongseong': 'ᇯ', '/ko:ieungkiyeokchoseong': 'ᅁ',
- '/ko:ieungkiyeokjongseong': 'ᇬ', '/ko:ieungmieumchoseong': 'ᅃ',
- '/ko:ieungpansioschoseong': 'ᅆ', '/ko:ieungphieuphchoseong': 'ᅋ',
- '/ko:ieungpieupchoseong': 'ᅄ', '/ko:ieungsioschoseong': 'ᅅ',
- '/ko:ieungssangkiyeokjongseong': 'ᇭ', '/ko:ieungthieuthchoseong': 'ᅊ',
- '/ko:ieungtikeutchoseong': 'ᅂ', '/ko:ijungseong': 'ᅵ',
- '/ko:iojungseong': 'ᆚ', '/ko:iujungseong': 'ᆛ', '/ko:iyajungseong': 'ᆙ',
- '/ko:kapyeounmieum': 'ㅱ', '/ko:kapyeounmieumchoseong': 'ᄝ',
- '/ko:kapyeounmieumjongseong': 'ᇢ', '/ko:kapyeounphieuph': 'ㆄ',
- '/ko:kapyeounphieuphchoseong': 'ᅗ', '/ko:kapyeounphieuphjongseong': 'ᇴ',
- '/ko:kapyeounpieup': 'ㅸ', '/ko:kapyeounpieupchoseong': 'ᄫ',
- '/ko:kapyeounpieupjongseong': 'ᇦ', '/ko:kapyeounrieulchoseong': 'ᄛ',
- '/ko:kapyeounssangpieup': 'ㅹ', '/ko:kapyeounssangpieupchoseong': 'ᄬ',
- '/ko:khieukh': 'ㅋ', '/ko:khieukhchoseong': 'ᄏ', '/ko:khieukhjongseong':
- 'ᆿ', '/ko:kiyeok': 'ㄱ', '/ko:kiyeokchieuchjongseong': 'ᇼ',
- '/ko:kiyeokchoseong': 'ᄀ', '/ko:kiyeokhieuhjongseong': 'ᇾ',
- '/ko:kiyeokjongseong': 'ᆨ', '/ko:kiyeokkhieukhjongseong': 'ᇽ',
- '/ko:kiyeoknieunjongseong': 'ᇺ', '/ko:kiyeokpieupjongseong': 'ᇻ',
- '/ko:kiyeokrieuljongseong': 'ᇃ', '/ko:kiyeoksios': 'ㄳ',
- '/ko:kiyeoksiosjongseong': 'ᆪ', '/ko:kiyeoksioskiyeokjongseong': 'ᇄ',
- '/ko:kiyeoktikeutchoseong': 'ᅚ', '/ko:mieum': 'ㅁ',
- '/ko:mieumchieuchjongseong': 'ᇠ', '/ko:mieumchoseong': 'ᄆ',
- '/ko:mieumhieuhjongseong': 'ᇡ', '/ko:mieumjongseong': 'ᆷ',
- '/ko:mieumkiyeokjongseong': 'ᇚ', '/ko:mieumpansios': 'ㅰ',
- '/ko:mieumpansiosjongseong': 'ᇟ', '/ko:mieumpieup': 'ㅮ',
- '/ko:mieumpieupchoseong': 'ᄜ', '/ko:mieumpieupjongseong': 'ᇜ',
- '/ko:mieumrieuljongseong': 'ᇛ', '/ko:mieumsios': 'ㅯ',
- '/ko:mieumsiosjongseong': 'ᇝ', '/ko:mieumssangsiosjongseong': 'ᇞ',
- '/ko:nieun': 'ㄴ', '/ko:nieunchoseong': 'ᄂ', '/ko:nieuncieuc': 'ㄵ',
- '/ko:nieuncieucchoseong': 'ᅜ', '/ko:nieuncieucjongseong': 'ᆬ',
- '/ko:nieunhieuh': 'ㄶ', '/ko:nieunhieuhchoseong': 'ᅝ',
- '/ko:nieunhieuhjongseong': 'ᆭ', '/ko:nieunjongseong': 'ᆫ',
- '/ko:nieunkiyeokchoseong': 'ᄓ', '/ko:nieunkiyeokjongseong': 'ᇅ',
- '/ko:nieunpansios': 'ㅨ', '/ko:nieunpansiosjongseong': 'ᇈ',
- '/ko:nieunpieupchoseong': 'ᄖ', '/ko:nieunsios': 'ㅧ',
- '/ko:nieunsioschoseong': 'ᅛ', '/ko:nieunsiosjongseong': 'ᇇ',
- '/ko:nieunthieuthjongseong': 'ᇉ', '/ko:nieuntikeut': 'ㅦ',
- '/ko:nieuntikeutchoseong': 'ᄕ', '/ko:nieuntikeutjongseong': 'ᇆ',
- '/ko:o': 'ㅗ', '/ko:o_ejungseong': 'ᆀ', '/ko:o_eojungseong': 'ᅿ',
- '/ko:oe': 'ㅚ', '/ko:oejungseong': 'ᅬ', '/ko:ojungseong': 'ᅩ',
- '/ko:oojungseong': 'ᆂ', '/ko:oujungseong': 'ᆃ', '/ko:oyaejungseong':
- 'ᆧ', '/ko:oyajungseong': 'ᆦ', '/ko:oyejungseong': 'ᆁ', '/ko:pansios':
- 'ㅿ', '/ko:pansioschoseong': 'ᅀ', '/ko:pansiosjongseong': 'ᇫ',
- '/ko:phieuph': 'ㅍ', '/ko:phieuphchoseong': 'ᄑ', '/ko:phieuphjongseong':
- 'ᇁ', '/ko:phieuphpieupchoseong': 'ᅖ', '/ko:phieuphpieupjongseong': 'ᇳ',
- '/ko:pieup': 'ㅂ', '/ko:pieupchieuchchoseong': 'ᄨ', '/ko:pieupchoseong':
- 'ᄇ', '/ko:pieupcieuc': 'ㅶ', '/ko:pieupcieucchoseong': 'ᄧ',
- '/ko:pieuphieuhjongseong': 'ᇥ', '/ko:pieupjongseong': 'ᆸ',
- '/ko:pieupkiyeok': 'ㅲ', '/ko:pieupkiyeokchoseong': 'ᄞ',
- '/ko:pieupnieunchoseong': 'ᄟ', '/ko:pieupphieuphchoseong': 'ᄪ',
- '/ko:pieupphieuphjongseong': 'ᇤ', '/ko:pieuprieuljongseong': 'ᇣ',
- '/ko:pieupsios': 'ㅄ', '/ko:pieupsioschoseong': 'ᄡ',
- '/ko:pieupsioscieucchoseong': 'ᄦ', '/ko:pieupsiosjongseong': 'ᆹ',
- '/ko:pieupsioskiyeok': 'ㅴ', '/ko:pieupsioskiyeokchoseong': 'ᄢ',
- '/ko:pieupsiospieupchoseong': 'ᄤ', '/ko:pieupsiostikeut': 'ㅵ',
- '/ko:pieupsiostikeutchoseong': 'ᄣ', '/ko:pieupssangsioschoseong': 'ᄥ',
- '/ko:pieupthieuth': 'ㅷ', '/ko:pieupthieuthchoseong': 'ᄩ',
- '/ko:pieuptikeut': 'ㅳ', '/ko:pieuptikeutchoseong': 'ᄠ', '/ko:rieul':
- 'ㄹ', '/ko:rieulchoseong': 'ᄅ', '/ko:rieulhieuh': 'ㅀ',
- '/ko:rieulhieuhchoseong': 'ᄚ', '/ko:rieulhieuhjongseong': 'ᆶ',
- '/ko:rieuljongseong': 'ᆯ', '/ko:rieulkapyeounpieupjongseong': 'ᇕ',
- '/ko:rieulkhieukhjongseong': 'ᇘ', '/ko:rieulkiyeok': 'ㄺ',
- '/ko:rieulkiyeokjongseong': 'ᆰ', '/ko:rieulkiyeoksios': 'ㅩ',
- '/ko:rieulkiyeoksiosjongseong': 'ᇌ', '/ko:rieulmieum': 'ㄻ',
- '/ko:rieulmieumjongseong': 'ᆱ', '/ko:rieulmieumkiyeokjongseong': 'ᇑ',
- '/ko:rieulmieumsiosjongseong': 'ᇒ', '/ko:rieulnieunchoseong': 'ᄘ',
- '/ko:rieulnieunjongseong': 'ᇍ', '/ko:rieulpansios': 'ㅬ',
- '/ko:rieulpansiosjongseong': 'ᇗ', '/ko:rieulphieuph': 'ㄿ',
- '/ko:rieulphieuphjongseong': 'ᆵ', '/ko:rieulpieup': 'ㄼ',
- '/ko:rieulpieuphieuhjongseong': 'ᇔ', '/ko:rieulpieupjongseong': 'ᆲ',
- '/ko:rieulpieupsios': 'ㅫ', '/ko:rieulpieupsiosjongseong': 'ᇓ',
- '/ko:rieulsios': 'ㄽ', '/ko:rieulsiosjongseong': 'ᆳ',
- '/ko:rieulssangsiosjongseong': 'ᇖ', '/ko:rieulthieuth': 'ㄾ',
- '/ko:rieulthieuthjongseong': 'ᆴ', '/ko:rieultikeut': 'ㅪ',
- '/ko:rieultikeuthieuhjongseong': 'ᇏ', '/ko:rieultikeutjongseong': 'ᇎ',
- '/ko:rieulyeorinhieuh': 'ㅭ', '/ko:rieulyeorinhieuhjongseong': 'ᇙ',
- '/ko:sios': 'ㅅ', '/ko:sioschieuchchoseong': 'ᄷ', '/ko:sioschoseong':
- 'ᄉ', '/ko:sioscieuc': 'ㅾ', '/ko:sioscieucchoseong': 'ᄶ',
- '/ko:sioshieuhchoseong': 'ᄻ', '/ko:siosieungchoseong': 'ᄵ',
- '/ko:siosjongseong': 'ᆺ', '/ko:sioskhieukhchoseong': 'ᄸ',
- '/ko:sioskiyeok': 'ㅺ', '/ko:sioskiyeokchoseong': 'ᄭ',
- '/ko:sioskiyeokjongseong': 'ᇧ', '/ko:siosmieumchoseong': 'ᄱ',
- '/ko:siosnieun': 'ㅻ', '/ko:siosnieunchoseong': 'ᄮ',
- '/ko:siosphieuphchoseong': 'ᄺ', '/ko:siospieup': 'ㅽ',
- '/ko:siospieupchoseong': 'ᄲ', '/ko:siospieupjongseong': 'ᇪ',
- '/ko:siospieupkiyeokchoseong': 'ᄳ', '/ko:siosrieulchoseong': 'ᄰ',
- '/ko:siosrieuljongseong': 'ᇩ', '/ko:siosssangsioschoseong': 'ᄴ',
- '/ko:siosthieuthchoseong': 'ᄹ', '/ko:siostikeut': 'ㅼ',
- '/ko:siostikeutchoseong': 'ᄯ', '/ko:siostikeutjongseong': 'ᇨ',
- '/ko:ssangaraeajungseong': 'ᆢ', '/ko:ssangcieuc': 'ㅉ',
- '/ko:ssangcieucchoseong': 'ᄍ', '/ko:ssanghieuh': 'ㆅ',
- '/ko:ssanghieuhchoseong': 'ᅘ', '/ko:ssangieung': 'ㆀ',
- '/ko:ssangieungchoseong': 'ᅇ', '/ko:ssangieungjongseong': 'ᇮ',
- '/ko:ssangkiyeok': 'ㄲ', '/ko:ssangkiyeokchoseong': 'ᄁ',
- '/ko:ssangkiyeokjongseong': 'ᆩ', '/ko:ssangnieun': 'ㅥ',
- '/ko:ssangnieunchoseong': 'ᄔ', '/ko:ssangnieunjongseong': 'ᇿ',
- '/ko:ssangpieup': 'ㅃ', '/ko:ssangpieupchoseong': 'ᄈ',
- '/ko:ssangrieulchoseong': 'ᄙ', '/ko:ssangrieuljongseong': 'ᇐ',
- '/ko:ssangsios': 'ㅆ', '/ko:ssangsioschoseong': 'ᄊ',
- '/ko:ssangsiosjongseong': 'ᆻ', '/ko:ssangtikeut': 'ㄸ',
- '/ko:ssangtikeutchoseong': 'ᄄ', '/ko:thieuth': 'ㅌ',
- '/ko:thieuthchoseong': 'ᄐ', '/ko:thieuthjongseong': 'ᇀ', '/ko:tikeut':
- 'ㄷ', '/ko:tikeutchoseong': 'ᄃ', '/ko:tikeutjongseong': 'ᆮ',
- '/ko:tikeutkiyeokchoseong': 'ᄗ', '/ko:tikeutkiyeokjongseong': 'ᇊ',
- '/ko:tikeutrieulchoseong': 'ᅞ', '/ko:tikeutrieuljongseong': 'ᇋ',
- '/ko:u': 'ㅜ', '/ko:uaejungseong': 'ᆊ', '/ko:uajungseong': 'ᆉ',
- '/ko:ueo_eujungseong': 'ᆋ', '/ko:ujungseong': 'ᅮ', '/ko:uujungseong':
- 'ᆍ', '/ko:uyejungseong': 'ᆌ', '/ko:wa': 'ㅘ', '/ko:wae': 'ㅙ',
- '/ko:waejungseong': 'ᅫ', '/ko:wajungseong': 'ᅪ', '/ko:we': 'ㅞ',
- '/ko:wejungseong': 'ᅰ', '/ko:weo': 'ㅝ', '/ko:weojungseong': 'ᅯ',
- '/ko:wi': 'ㅟ', '/ko:wijungseong': 'ᅱ', '/ko:ya': 'ㅑ', '/ko:yae': 'ㅒ',
- '/ko:yaejungseong': 'ᅤ', '/ko:yajungseong': 'ᅣ', '/ko:yaojungseong':
- 'ᅸ', '/ko:yaujungseong': 'ᆤ', '/ko:yayojungseong': 'ᅹ', '/ko:ye': 'ㅖ',
- '/ko:yejungseong': 'ᅨ', '/ko:yeo': 'ㅕ', '/ko:yeojungseong': 'ᅧ',
- '/ko:yeoojungseong': 'ᅽ', '/ko:yeorinhieuh': 'ㆆ',
- '/ko:yeorinhieuhchoseong': 'ᅙ', '/ko:yeorinhieuhjongseong': 'ᇹ',
- '/ko:yeoujungseong': 'ᅾ', '/ko:yeoyajungseong': 'ᆥ', '/ko:yesieung':
- 'ㆁ', '/ko:yesieungchoseong': 'ᅌ', '/ko:yesieungjongseong': 'ᇰ',
- '/ko:yesieungpansios': 'ㆃ', '/ko:yesieungpansiosjongseong': 'ᇲ',
- '/ko:yesieungsios': 'ㆂ', '/ko:yesieungsiosjongseong': 'ᇱ', '/ko:yi':
- 'ㅢ', '/ko:yijungseong': 'ᅴ', '/ko:yiujungseong': 'ᆗ', '/ko:yo': 'ㅛ',
- '/ko:yoi': 'ㆉ', '/ko:yoijungseong': 'ᆈ', '/ko:yojungseong': 'ᅭ',
- '/ko:yoojungseong': 'ᆇ', '/ko:yoya': 'ㆇ', '/ko:yoyae': 'ㆈ',
- '/ko:yoyaejungseong': 'ᆅ', '/ko:yoyajungseong': 'ᆄ',
- '/ko:yoyeojungseong': 'ᆆ', '/ko:yu': 'ㅠ', '/ko:yuajungseong': 'ᆎ',
- '/ko:yuejungseong': 'ᆐ', '/ko:yueojungseong': 'ᆏ', '/ko:yui': 'ㆌ',
- '/ko:yuijungseong': 'ᆔ', '/ko:yujungseong': 'ᅲ', '/ko:yuujungseong':
- 'ᆓ', '/ko:yuye': 'ㆋ', '/ko:yuyejungseong': 'ᆒ', '/ko:yuyeo': 'ㆊ',
- '/ko:yuyeojungseong': 'ᆑ', '/koala': 'ὂ8', '/kobliquestroke': 'ꞣ',
- '/kocirclekatakana': '㋙', '/kohiragana': 'こ', '/kohmfullwidth': '㏀',
- '/kohmsquare': '㏀', '/kokaithai': 'ก', '/kokatakana': 'コ',
- '/kokatakanahalfwidth': 'コ', '/kooposquare': '㌞', '/koppa': 'ϟ',
- '/koppaarchaic': 'ϙ', '/koppacyr': 'ҁ', '/koppacyrillic': 'ҁ',
- '/koreanstandardsymbol': '㉿', '/koroniscmb': '̓', '/korunasquare': '㌝',
- '/kotoideographiccircled': '㉇', '/kpafullwidth': '㎪', '/kparen': '⒦',
- '/kparenthesized': '⒦', '/kpasquare': '㎪', '/kra': 'ĸ', '/ksicyr': 'ѯ',
- '/ksicyrillic': 'ѯ', '/kstroke': 'ꝁ', '/kstrokediagonalstroke': 'ꝅ',
- '/ktfullwidth': '㏏', '/ktsquare': '㏏', '/kturned': 'ʞ',
- '/kucirclekatakana': '㋗', '/kuhiragana': 'く', '/kukatakana': 'ク',
- '/kukatakanahalfwidth': 'ク', '/kuroonesquare': '㌛', '/kuruzeirosquare':
- '㌚', '/kvfullwidth': '㎸', '/kvsquare': '㎸', '/kwfullwidth': '㎾',
- '/kwsquare': '㎾', '/kyuriisquare': '㌒', '/l': 'l', '/l.inferior': 'ₗ',
- '/label': 'Ἷ7', '/labengali': 'ল', '/laborideographiccircled': '㊘',
- '/laborideographicparen': '㈸', '/lacute': 'ĺ', '/ladeva': 'ल',
- '/ladyBeetle': 'ὁE', '/lagujarati': 'લ', '/lagurmukhi': 'ਲ',
- '/lakkhangyaothai': 'ๅ', '/lam': 'ل', '/lam.fina': 'ﻞ', '/lam.init':
- 'ﻟ', '/lam.init_alef.fina': 'ﻻ', '/lam.init_alef.medi_hamzaabove.fina':
- 'ﻷ', '/lam.init_alef.medi_hamzabelow.fina': 'ﻹ',
- '/lam.init_alef.medi_maddaabove.fina': 'ﻵ',
- '/lam.init_alefmaksura.fina': 'ﱃ', '/lam.init_hah.fina': 'ﱀ',
- '/lam.init_hah.medi': 'ﳊ', '/lam.init_hah.medi_meem.medi': 'ﶵ',
- '/lam.init_heh.medi': 'ﳍ', '/lam.init_jeem.fina': 'ﰿ',
- '/lam.init_jeem.medi': 'ﳉ', '/lam.init_jeem.medi_jeem.medi': 'ﶃ',
- '/lam.init_jeem.medi_meem.medi': 'ﶺ', '/lam.init_khah.fina': 'ﱁ',
- '/lam.init_khah.medi': 'ﳋ', '/lam.init_khah.medi_meem.medi': 'ﶆ',
- '/lam.init_meem.fina': 'ﱂ', '/lam.init_meem.medi': 'ﳌ',
- '/lam.init_meem.medi_hah.medi': 'ﶈ', '/lam.init_yeh.fina': 'ﱄ',
- '/lam.isol': 'ﻝ', '/lam.medi': 'ﻠ', '/lam.medi_alef.fina': 'ﻼ',
- '/lam.medi_alef.medi_hamzaabove.fina': 'ﻸ',
- '/lam.medi_alef.medi_hamzabelow.fina': 'ﻺ',
- '/lam.medi_alef.medi_maddaabove.fina': 'ﻶ',
- '/lam.medi_alefmaksura.fina': 'ﲆ',
- '/lam.medi_hah.medi_alefmaksura.fina': 'ﶂ',
- '/lam.medi_hah.medi_meem.fina': 'ﶀ', '/lam.medi_hah.medi_yeh.fina': 'ﶁ',
- '/lam.medi_jeem.medi_jeem.fina': 'ﶄ', '/lam.medi_jeem.medi_meem.fina':
- 'ﶼ', '/lam.medi_jeem.medi_yeh.fina': 'ﶬ',
- '/lam.medi_khah.medi_meem.fina': 'ﶅ', '/lam.medi_meem.fina': 'ﲅ',
- '/lam.medi_meem.medi': 'ﳭ', '/lam.medi_meem.medi_hah.fina': 'ﶇ',
- '/lam.medi_meem.medi_yeh.fina': 'ﶭ', '/lam.medi_yeh.fina': 'ﲇ',
- '/lamBar': 'ݪ', '/lamVabove': 'ڵ', '/lamalefabove': 'ۙ',
- '/lamaleffinalarabic': 'ﻼ', '/lamalefhamzaabovefinalarabic': 'ﻸ',
- '/lamalefhamzaaboveisolatedarabic': 'ﻷ',
- '/lamalefhamzabelowfinalarabic': 'ﻺ',
- '/lamalefhamzabelowisolatedarabic': 'ﻹ', '/lamalefisolatedarabic': 'ﻻ',
- '/lamalefmaddaabovefinalarabic': 'ﻶ',
- '/lamalefmaddaaboveisolatedarabic': 'ﻵ', '/lamarabic': 'ل', '/lambda':
- 'λ', '/lambdastroke': 'ƛ', '/lamdotabove': 'ڶ', '/lamed': 'ל',
- '/lamed:hb': 'ל', '/lameddagesh': 'לּ', '/lameddageshhebrew': 'לּ',
- '/lamedhebrew': 'ל', '/lamedholam': 'ל', '/lamedholamdagesh': 'ל',
- '/lamedholamdageshhebrew': 'ל', '/lamedholamhebrew': 'ל',
- '/lamedwide:hb': 'ﬥ', '/lamedwithdagesh:hb': 'לּ', '/lamfinalarabic':
- 'ﻞ', '/lamhahinitialarabic': 'ﳊ', '/laminitialarabic': 'ﻟ',
- '/lamjeeminitialarabic': 'ﳉ', '/lamkhahinitialarabic': 'ﳋ',
- '/lamlamhehisolatedarabic': 'ﷲ', '/lammedialarabic': 'ﻠ',
- '/lammeemhahinitialarabic': 'ﶈ', '/lammeeminitialarabic': 'ﳌ',
- '/lammeemjeeminitialarabic': 'ﻟ', '/lammeemkhahinitialarabic': 'ﻟ',
- '/lamthreedotsabove': 'ڷ', '/lamthreedotsbelow': 'ڸ',
- '/lanemergeleftblack': '⛘', '/lanemergeleftwhite': '⛙',
- '/largeBlueCircle': 'ὓ5', '/largeBlueDiamond': 'ὓ7',
- '/largeOrangeDiamond': 'ὓ6', '/largeRedCircle': 'ὓ4', '/largecircle':
- '◯', '/largetackdown': '⟙', '/largetackup': '⟘', '/lari': '₾',
- '/lastQuarterMoon': 'ἱ7', '/lastQuarterMoonFace': 'ἱC',
- '/lastquartermoon': '☾', '/layar': 'ꦂ', '/lazysinverted': '∾', '/lbar':
- 'ƚ', '/lbbar': '℔', '/lbelt': 'ɬ', '/lbeltretroflex': 'ꞎ', '/lbopomofo':
- 'ㄌ', '/lbroken': 'ꝇ', '/lcaron': 'ľ', '/lcedilla': 'ļ', '/lcircle': 'ⓛ',
- '/lcircumflexbelow': 'ḽ', '/lcommaaccent': 'ļ', '/lcurl': 'ȴ',
- '/ldblbar': 'ⱡ', '/ldot': 'ŀ', '/ldotaccent': 'ŀ', '/ldotbelow': 'ḷ',
- '/ldotbelowmacron': 'ḹ', '/leafFlutteringInWind': 'ἴ3', '/ledger': 'Ὅ2',
- '/left-pointingMagnifyingGlass': 'ὐD', '/leftAngerBubble': '\u1f5eE',
- '/leftFiveEighthsBlock': '▋', '/leftHalfBlock': '▌',
- '/leftHandTelephoneReceiver': 'ὗB', '/leftLuggage': 'Ὤ5',
- '/leftOneEighthBlock': '▏', '/leftOneQuarterBlock': '▎',
- '/leftSevenEighthsBlock': '▉', '/leftSpeechBubble': '\u1f5e8',
- '/leftThoughtBubble': '\u1f5eC', '/leftThreeEighthsBlock': '▍',
- '/leftThreeQuartersBlock': '▊', '/leftWritingHand': '\u1f58E',
- '/leftangleabovecmb': '̚', '/leftarrowoverrightarrow': '⇆',
- '/leftdnheavyrightuplight': '╅', '/leftharpoonoverrightharpoon': '⇋',
- '/leftheavyrightdnlight': '┭', '/leftheavyrightuplight': '┵',
- '/leftheavyrightvertlight': '┽', '/leftideographiccircled': '㊧',
- '/leftlightrightdnheavy': '┲', '/leftlightrightupheavy': '┺',
- '/leftlightrightvertheavy': '╊', '/lefttackbelowcmb': '̘',
- '/lefttorightembed': '\u202a', '/lefttorightisolate': '\u2066',
- '/lefttorightmark': '\u200e', '/lefttorightoverride': '\u202d',
- '/leftupheavyrightdnlight': '╃', '/lemon': 'ἴB', '/lenis': '᾿',
- '/lenisacute': '῎', '/lenisgrave': '῍', '/lenistilde': '῏', '/leo': '♌',
- '/leopard': 'ὀ6', '/less': '<', '/lessbutnotequal': '≨',
- '/lessbutnotequivalent': '⋦', '/lessdot': '⋖', '/lessequal': '≤',
- '/lessequalorgreater': '⋚', '/lessmonospace': '<', '/lessorequivalent':
- '≲', '/lessorgreater': '≶', '/lessoverequal': '≦', '/lesssmall': '﹤',
- '/levelSlider': 'ἹA', '/lezh': 'ɮ', '/lfblock': '▌', '/lhacyr': 'ԕ',
- '/lhookretroflex': 'ɭ', '/libra': '♎', '/ligaturealeflamed:hb': 'ﭏ',
- '/ligatureoemod': 'ꟹ', '/lightCheckMark': 'Ὗ8', '/lightRail': 'Ὠ8',
- '/lightShade': '░', '/lightarcdnleft': '╮', '/lightarcdnright': '╭',
- '/lightarcupleft': '╯', '/lightarcupright': '╰', '/lightdbldashhorz':
- '╌', '/lightdbldashvert': '╎', '/lightdiagcross': '╳',
- '/lightdiagupleftdnright': '╲', '/lightdiaguprightdnleft': '╱',
- '/lightdn': '╷', '/lightdnhorz': '┬', '/lightdnleft': '┐',
- '/lightdnright': '┌', '/lighthorz': '─', '/lightleft': '╴',
- '/lightleftheavyright': '╼', '/lightning': '☇', '/lightningMood': 'Ὗ2',
- '/lightningMoodBubble': 'Ὗ1', '/lightquaddashhorz': '┈',
- '/lightquaddashvert': '┊', '/lightright': '╶', '/lighttrpldashhorz':
- '┄', '/lighttrpldashvert': '┆', '/lightup': '╵', '/lightupheavydn': '╽',
- '/lightuphorz': '┴', '/lightupleft': '┘', '/lightupright': '└',
- '/lightvert': '│', '/lightverthorz': '┼', '/lightvertleft': '┤',
- '/lightvertright': '├', '/lineextensionhorizontal': '⎯',
- '/lineextensionvertical': '⏐', '/linemiddledotvertical': '⍿',
- '/lineseparator': '\u2028', '/lingsapada': '꧈', '/link': 'ὑ7',
- '/linkedPaperclips': '\u1f587', '/lips': '\u1f5e2', '/lipstick': 'Ὀ4',
- '/lira': '₤', '/litre': 'ℓ', '/livretournois': '₶', '/liwnarmenian':
- 'լ', '/lj': 'lj', '/ljecyr': 'љ', '/ljecyrillic': 'љ', '/ljekomicyr':
- 'ԉ', '/ll': '\uf6c0', '/lladeva': 'ळ', '/llagujarati': 'ળ',
- '/llinebelow': 'ḻ', '/llladeva': 'ऴ', '/llvocalicbengali': 'ৡ',
- '/llvocalicdeva': 'ॡ', '/llvocalicvowelsignbengali': 'ৣ',
- '/llvocalicvowelsigndeva': 'ॣ', '/llwelsh': 'ỻ', '/lmacrondot': 'ḹ',
- '/lmfullwidth': '㏐', '/lmiddletilde': 'ɫ', '/lmonospace': 'l',
- '/lmsquare': '㏐', '/lnfullwidth': '㏑', '/lochulathai': 'ฬ', '/lock':
- 'ὑ2', '/lockInkPen': 'ὐF', '/logfullwidth': '㏒', '/logicaland': '∧',
- '/logicalandarray': '⋀', '/logicalnot': '¬', '/logicalnotreversed': '⌐',
- '/logicalor': '∨', '/logicalorarray': '⋁', '/lolingthai': 'ล',
- '/lollipop': 'ἶD', '/longdivision': '⟌', '/longovershortmetrical': '⏒',
- '/longovertwoshortsmetrical': '⏔', '/longs': 'ſ', '/longs_t': 'ſt',
- '/longsdot': 'ẛ', '/longswithdiagonalstroke': 'ẜ',
- '/longswithhighstroke': 'ẝ', '/longtackleft': '⟞', '/longtackright':
- '⟝', '/losslesssquare': 'Ἒ9', '/loudlyCryingFace': 'ὢD', '/loveHotel':
- 'Ἶ9', '/loveLetter': 'ὈC', '/lowBrightness': 'ὐ5', '/lowasterisk': '⁎',
- '/lowerFiveEighthsBlock': '▅', '/lowerHalfBlock': '▄',
- '/lowerLeftBallpointPen': '\u1f58A', '/lowerLeftCrayon': '\u1f58D',
- '/lowerLeftFountainPen': '\u1f58B', '/lowerLeftPaintbrush': '\u1f58C',
- '/lowerLeftPencil': '\u1f589', '/lowerOneEighthBlock': '▁',
- '/lowerOneQuarterBlock': '▂', '/lowerRightShadowedWhiteCircle': 'ὓE',
- '/lowerSevenEighthsBlock': '▇', '/lowerThreeEighthsBlock': '▃',
- '/lowerThreeQuartersBlock': '▆', '/lowercornerdotright': '⟓',
- '/lowerhalfcircle': '◡', '/lowerhalfcircleinversewhite': '◛',
- '/lowerquadrantcirculararcleft': '◟', '/lowerquadrantcirculararcright':
- '◞', '/lowertriangleleft': '◺', '/lowertriangleleftblack': '◣',
- '/lowertriangleright': '◿', '/lowertrianglerightblack': '◢',
- '/lowideographiccircled': '㊦', '/lowlinecenterline': '﹎', '/lowlinecmb':
- '̲', '/lowlinedashed': '﹍', '/lownumeralsign': '͵', '/lowquotedblprime':
- '〟', '/lozenge': '◊', '/lozengedividedbyrulehorizontal': '⟠',
- '/lozengesquare': '⌑', '/lparen': '⒧', '/lparenthesized': '⒧',
- '/lretroflex': 'ɭ', '/ls': 'ʪ', '/lslash': 'ł', '/lsquare': 'ℓ',
- '/lstroke': 'ꝉ', '/lsuperior': '\uf6ee', '/lsupmod': 'ˡ', '/lt:Alpha':
- 'Ɑ', '/lt:Alphaturned': 'Ɒ', '/lt:Beta': 'Ꞵ', '/lt:Chi': 'Ꭓ',
- '/lt:Gamma': 'Ɣ', '/lt:Iota': 'Ɩ', '/lt:Omega': 'Ꞷ', '/lt:Upsilon': 'Ʊ',
- '/lt:beta': 'ꞵ', '/lt:delta': 'ẟ', '/lt:omega': 'ꞷ', '/ltshade': '░',
- '/lttr:bet': 'ℶ', '/lttr:dalet': 'ℸ', '/lttr:gimel': 'ℷ',
- '/lttr:gscript': 'ℊ', '/lturned': 'ꞁ', '/ltypeopencircuit': '⎐',
- '/luhurpada': '꧅', '/lum': 'ꝲ', '/lungsipada': '꧉', '/luthai': 'ฦ',
- '/lvocalicbengali': 'ঌ', '/lvocalicdeva': 'ऌ',
- '/lvocalicvowelsignbengali': 'ৢ', '/lvocalicvowelsigndeva': 'ॢ',
- '/lxfullwidth': '㏓', '/lxsquare': '㏓', '/lzed': 'ʫ', '/m': 'm',
- '/m.inferior': 'ₘ', '/m2fullwidth': '㎡', '/m3fullwidth': '㎥',
- '/mabengali': 'ম', '/macirclekatakana': '㋮', '/macron': '¯',
- '/macronbelowcmb': '̱', '/macroncmb': '̄', '/macronlowmod': 'ˍ',
- '/macronmod': 'ˉ', '/macronmonospace': ' ̄', '/macute': 'ḿ', '/madda':
- 'ٓ', '/maddaabove': 'ۤ', '/madeva': 'म', '/madyapada': '꧄',
- '/mafullwidth': '㎃', '/magujarati': 'મ', '/magurmukhi': 'ਮ',
- '/mahapakhhebrew': '֤', '/mahapakhlefthebrew': '֤', '/mahhasquare': '㍅',
- '/mahiragana': 'ま', '/mahpach:hb': '֤', '/maichattawalowleftthai':
- '\uf895', '/maichattawalowrightthai': '\uf894', '/maichattawathai': '๋',
- '/maichattawaupperleftthai': '\uf893', '/maieklowleftthai': '\uf88c',
- '/maieklowrightthai': '\uf88b', '/maiekthai': '่',
- '/maiekupperleftthai': '\uf88a', '/maihanakatleftthai': '\uf884',
- '/maihanakatthai': 'ั', '/maikurosquare': '㍃', '/mairusquare': '㍄',
- '/maitaikhuleftthai': '\uf889', '/maitaikhuthai': '็',
- '/maitholowleftthai': '\uf88f', '/maitholowrightthai': '\uf88e',
- '/maithothai': '้', '/maithoupperleftthai': '\uf88d',
- '/maitrilowleftthai': '\uf892', '/maitrilowrightthai': '\uf891',
- '/maitrithai': '๊', '/maitriupperleftthai': '\uf890', '/maiyamokthai':
- 'ๆ', '/makatakana': 'マ', '/makatakanahalfwidth': 'マ', '/male': '♂',
- '/malefemale': '⚥', '/maleideographiccircled': '㊚', '/malestroke': '⚦',
- '/malestrokemalefemale': '⚧', '/man': '\u1f468',
- '/manAndWomanHoldingHands': '\u1f46B', '/manDancing': 'ὗA',
- '/manGuaPiMao': '\u1f472', '/manInBusinessSuitLevitating': 'ὗ4',
- '/manTurban': '\u1f473', '/manat': '₼', '/mansShoe': 'ὅE',
- '/mansyonsquare': '㍇', '/mantelpieceClock': 'ὗ0', '/mapleLeaf': 'ἴ1',
- '/maplighthouse': '⛯', '/maqaf:hb': '־', '/maqafhebrew': '־',
- '/marchtelegraph': '㋂', '/mark': '\u061c',
- '/markerdottedraisedinterpolation': '⸇', '/markerdottedtransposition':
- '⸈', '/markerraisedinterpolation': '⸆', '/marknoonghunna': '٘',
- '/marksChapter': 'ὔ5', '/marriage': '⚭', '/mars': '♂', '/marukusquare':
- '㍆', '/masoraCircle:hb': '֯', '/masoracirclehebrew': '֯', '/masquare':
- '㎃', '/masumark': '〼', '/math:bowtie': '⋈', '/math:cuberoot': '∛',
- '/math:fourthroot': '∜', '/maximize': 'Ὕ6', '/maytelegraph': '㋄',
- '/mbfullwidth': '㎆', '/mbopomofo': 'ㄇ', '/mbsmallfullwidth': '㏔',
- '/mbsquare': '㏔', '/mcircle': 'ⓜ', '/mcubedsquare': '㎥', '/mdot': 'ṁ',
- '/mdotaccent': 'ṁ', '/mdotbelow': 'ṃ', '/measuredangle': '∡',
- '/measuredby': '≞', '/meatOnBone': 'ἵ6', '/mecirclekatakana': '㋱',
- '/medicineideographiccircled': '㊩', '/mediumShade': '▒',
- '/mediumcircleblack': '⚫', '/mediumcirclewhite': '⚪',
- '/mediummathematicalspace': '\u205f', '/mediumsmallcirclewhite': '⚬',
- '/meem': 'م', '/meem.fina': 'ﻢ', '/meem.init': 'ﻣ',
- '/meem.init_alefmaksura.fina': 'ﱉ', '/meem.init_hah.fina': 'ﱆ',
- '/meem.init_hah.medi': 'ﳏ', '/meem.init_hah.medi_jeem.medi': 'ﶉ',
- '/meem.init_hah.medi_meem.medi': 'ﶊ', '/meem.init_jeem.fina': 'ﱅ',
- '/meem.init_jeem.medi': 'ﳎ', '/meem.init_jeem.medi_hah.medi': 'ﶌ',
- '/meem.init_jeem.medi_khah.medi': 'ﶒ', '/meem.init_jeem.medi_meem.medi':
- 'ﶍ', '/meem.init_khah.fina': 'ﱇ', '/meem.init_khah.medi': 'ﳐ',
- '/meem.init_khah.medi_jeem.medi': 'ﶎ', '/meem.init_khah.medi_meem.medi':
- 'ﶏ', '/meem.init_meem.fina': 'ﱈ', '/meem.init_meem.medi': 'ﳑ',
- '/meem.init_yeh.fina': 'ﱊ', '/meem.isol': 'ﻡ', '/meem.medi': 'ﻤ',
- '/meem.medi_alef.fina': 'ﲈ', '/meem.medi_hah.medi_yeh.fina': 'ﶋ',
- '/meem.medi_jeem.medi_yeh.fina': 'ﷀ', '/meem.medi_khah.medi_yeh.fina':
- 'ﶹ', '/meem.medi_meem.fina': 'ﲉ', '/meem.medi_meem.medi_yeh.fina': 'ﶱ',
- '/meemDotAbove': 'ݥ', '/meemDotBelow': 'ݦ', '/meemabove': 'ۢ',
- '/meemabove.init': 'ۘ', '/meemarabic': 'م', '/meembelow': 'ۭ',
- '/meemfinalarabic': 'ﻢ', '/meeminitialarabic': 'ﻣ', '/meemmedialarabic':
- 'ﻤ', '/meemmeeminitialarabic': 'ﳑ', '/meemmeemisolatedarabic': 'ﱈ',
- '/meetorusquare': '㍍', '/megasquare': '㍋', '/megatonsquare': '㍌',
- '/mehiragana': 'め', '/meizierasquare': '㍾', '/mekatakana': 'メ',
- '/mekatakanahalfwidth': 'メ', '/melon': 'ἴ8', '/mem': 'מ', '/mem:hb':
- 'מ', '/memdagesh': 'מּ', '/memdageshhebrew': 'מּ', '/memhebrew': 'מ',
- '/memo': 'ὍD', '/memwithdagesh:hb': 'מּ', '/menarmenian': 'մ',
- '/menorahNineBranches': 'ὔE', '/menpostSindhi': '۾', '/mens': 'Ὣ9',
- '/mepigraphicinverted': 'ꟽ', '/mercha:hb': '֥', '/merchaKefulah:hb':
- '֦', '/mercury': '☿', '/merkhahebrew': '֥', '/merkhakefulahebrew': '֦',
- '/merkhakefulalefthebrew': '֦', '/merkhalefthebrew': '֥',
- '/metalideographiccircled': '㊎', '/metalideographicparen': '㈮',
- '/meteg:hb': 'ֽ', '/metro': 'Ὠ7', '/mgfullwidth': '㎎', '/mhook': 'ɱ',
- '/mhzfullwidth': '㎒', '/mhzsquare': '㎒', '/micirclekatakana': '㋯',
- '/microphone': 'Ἲ4', '/microscope': 'ὒC', '/middledotkatakanahalfwidth':
- '・', '/middot': '·', '/mieumacirclekorean': '㉲', '/mieumaparenkorean':
- '㈒', '/mieumcirclekorean': '㉤', '/mieumkorean': 'ㅁ',
- '/mieumpansioskorean': 'ㅰ', '/mieumparenkorean': '㈄',
- '/mieumpieupkorean': 'ㅮ', '/mieumsioskorean': 'ㅯ', '/mihiragana': 'み',
- '/mikatakana': 'ミ', '/mikatakanahalfwidth': 'ミ', '/mikuronsquare': '㍈',
- '/milfullwidth': '㏕', '/militaryMedal': 'Ἱ6', '/milkyWay': 'ἰC',
- '/mill': '₥', '/millionscmbcyr': '҉', '/millisecond': '‴',
- '/millisecondreversed': '‷', '/minibus': 'Ὡ0', '/minidisc': 'ὋD',
- '/minimize': 'Ὕ5', '/minus': '−', '/minus.inferior': '₋',
- '/minus.superior': '⁻', '/minusbelowcmb': '̠', '/minuscircle': '⊖',
- '/minusmod': '˗', '/minusplus': '∓', '/minussignmod': '˗',
- '/minustilde': '≂', '/minute': '′', '/minutereversed': '‵',
- '/miribaarusquare': '㍊', '/mirisquare': '㍉', '/misc:baby': '\u1f476',
- '/misc:bell': 'ὑ4', '/misc:dash': 'Ὂ8', '/misc:decimalseparator': '⎖',
- '/misc:diamondblack': '♦', '/misc:diamondwhite': '♢', '/misc:ear': 'ὄ2',
- '/misc:om': 'ὔ9', '/misc:ring': 'ὈD', '/misra': '؏', '/mlfullwidth':
- '㎖', '/mlonglegturned': 'ɰ', '/mlsquare': '㎖', '/mlym:a': 'അ',
- '/mlym:aa': 'ആ', '/mlym:aasign': 'ാ', '/mlym:ai': 'ഐ', '/mlym:aisign':
- 'ൈ', '/mlym:anusvarasign': 'ം', '/mlym:archaicii': 'ൟ', '/mlym:au': 'ഔ',
- '/mlym:aulength': 'ൗ', '/mlym:ausign': 'ൌ', '/mlym:avagrahasign': 'ഽ',
- '/mlym:ba': 'ബ', '/mlym:bha': 'ഭ', '/mlym:ca': 'ച',
- '/mlym:candrabindusign': 'ഁ', '/mlym:cha': 'ഛ',
- '/mlym:circularviramasign': '഼', '/mlym:combininganusvaraabovesign':
- 'ഀ', '/mlym:da': 'ദ', '/mlym:date': '൹', '/mlym:dda': 'ഡ', '/mlym:ddha':
- 'ഢ', '/mlym:dha': 'ധ', '/mlym:dotreph': 'ൎ', '/mlym:e': 'എ', '/mlym:ee':
- 'ഏ', '/mlym:eesign': 'േ', '/mlym:eight': '൮', '/mlym:esign': 'െ',
- '/mlym:five': '൫', '/mlym:four': '൪', '/mlym:ga': 'ഗ', '/mlym:gha': 'ഘ',
- '/mlym:ha': 'ഹ', '/mlym:i': 'ഇ', '/mlym:ii': 'ഈ', '/mlym:iisign': 'ീ',
- '/mlym:isign': 'ി', '/mlym:ja': 'ജ', '/mlym:jha': 'ഝ', '/mlym:ka': 'ക',
- '/mlym:kchillu': 'ൿ', '/mlym:kha': 'ഖ', '/mlym:la': 'ല',
- '/mlym:lchillu': 'ൽ', '/mlym:lla': 'ള', '/mlym:llchillu': 'ൾ',
- '/mlym:llla': 'ഴ', '/mlym:lllchillu': 'ൖ', '/mlym:llvocal': 'ൡ',
- '/mlym:llvocalsign': 'ൣ', '/mlym:lvocal': 'ഌ', '/mlym:lvocalsign': 'ൢ',
- '/mlym:ma': 'മ', '/mlym:mchillu': 'ൔ', '/mlym:na': 'ന', '/mlym:nchillu':
- 'ൻ', '/mlym:nga': 'ങ', '/mlym:nine': '൯', '/mlym:nna': 'ണ',
- '/mlym:nnchillu': 'ൺ', '/mlym:nnna': 'ഩ', '/mlym:nya': 'ഞ', '/mlym:o':
- 'ഒ', '/mlym:one': '൧', '/mlym:oneeighth': '൷', '/mlym:onefifth': '൞',
- '/mlym:onefortieth': '൙', '/mlym:onehalf': '൴', '/mlym:onehundred': '൱',
- '/mlym:oneone-hundred-and-sixtieth': '൘', '/mlym:onequarter': '൳',
- '/mlym:onesixteenth': '൶', '/mlym:onetenth': '൜', '/mlym:onethousand':
- '൲', '/mlym:onetwentieth': '൛', '/mlym:oo': 'ഓ', '/mlym:oosign': 'ോ',
- '/mlym:osign': 'ൊ', '/mlym:pa': 'പ', '/mlym:parasign': '൏', '/mlym:pha':
- 'ഫ', '/mlym:ra': 'ര', '/mlym:rra': 'റ', '/mlym:rrchillu': 'ർ',
- '/mlym:rrvocal': 'ൠ', '/mlym:rrvocalsign': 'ൄ', '/mlym:rvocal': 'ഋ',
- '/mlym:rvocalsign': 'ൃ', '/mlym:sa': 'സ', '/mlym:seven': '൭',
- '/mlym:sha': 'ശ', '/mlym:six': '൬', '/mlym:ssa': 'ഷ', '/mlym:ta': 'ത',
- '/mlym:ten': '൰', '/mlym:tha': 'ഥ', '/mlym:three': '൩',
- '/mlym:threeeightieths': '൚', '/mlym:threequarters': '൵',
- '/mlym:threesixteenths': '൸', '/mlym:threetwentieths': '൝', '/mlym:tta':
- 'ട', '/mlym:ttha': 'ഠ', '/mlym:ttta': 'ഺ', '/mlym:two': '൨', '/mlym:u':
- 'ഉ', '/mlym:usign': 'ു', '/mlym:uu': 'ഊ', '/mlym:uusign': 'ൂ',
- '/mlym:va': 'വ', '/mlym:verticalbarviramasign': '഻', '/mlym:viramasign':
- '്', '/mlym:visargasign': 'ഃ', '/mlym:ya': 'യ', '/mlym:ychillu': 'ൕ',
- '/mlym:zero': '൦', '/mm2fullwidth': '㎟', '/mm3fullwidth': '㎣',
- '/mmcubedsquare': '㎣', '/mmfullwidth': '㎜', '/mmonospace': 'm',
- '/mmsquaredsquare': '㎟', '/mobilePhone': '\u1f4f1', '/mobilePhoneOff':
- '\u1f4f4', '/mobilePhoneRightwardsArrowAtLeft': '\u1f4f2',
- '/mocirclekatakana': '㋲', '/models': '⊧', '/mohiragana': 'も',
- '/mohmfullwidth': '㏁', '/mohmsquare': '㏁', '/mokatakana': 'モ',
- '/mokatakanahalfwidth': 'モ', '/molfullwidth': '㏖', '/molsquare': '㏖',
- '/momathai': 'ม', '/moneyBag': 'Ὃ0', '/moneyWings': 'Ὃ8', '/mong:a':
- 'ᠠ', '/mong:aaligali': 'ᢇ', '/mong:ahaligali': 'ᢗ', '/mong:ang': 'ᠩ',
- '/mong:angsibe': 'ᡢ', '/mong:angtodo': 'ᡊ', '/mong:anusvaraonealigali':
- 'ᢀ', '/mong:ba': 'ᠪ', '/mong:baludaaligali': 'ᢅ',
- '/mong:baludaaligalithree': 'ᢆ', '/mong:batodo': 'ᡋ',
- '/mong:bhamanchualigali': 'ᢨ', '/mong:birga': '᠀', '/mong:caaligali':
- 'ᢋ', '/mong:camanchualigali': 'ᢜ', '/mong:cha': 'ᠴ', '/mong:chasibe':
- 'ᡱ', '/mong:chatodo': 'ᡒ', '/mong:chi': 'ᡂ', '/mong:colon': '᠄',
- '/mong:comma': '᠂', '/mong:commamanchu': '᠈', '/mong:cyamanchualigali':
- 'ᢣ', '/mong:da': 'ᠳ', '/mong:daaligali': 'ᢑ', '/mong:dagalgaaligali':
- 'ᢩ', '/mong:damarualigali': 'ᢂ', '/mong:dasibe': 'ᡩ', '/mong:datodo':
- 'ᡑ', '/mong:ddaaligali': 'ᢎ', '/mong:ddhamanchualigali': 'ᢟ',
- '/mong:dhamanchualigali': 'ᢡ', '/mong:dzatodo': 'ᡜ', '/mong:e': 'ᠡ',
- '/mong:ee': 'ᠧ', '/mong:eight': '᠘', '/mong:ellipsis': '᠁',
- '/mong:esibe': 'ᡝ', '/mong:etodo': 'ᡄ', '/mong:fa': 'ᠹ',
- '/mong:famanchu': 'ᡶ', '/mong:fasibe': 'ᡫ', '/mong:five': '᠕',
- '/mong:four': '᠔', '/mong:fourdots': '᠅',
- '/mong:freevariationselectorone': '᠋',
- '/mong:freevariationselectorthree': '᠍',
- '/mong:freevariationselectortwo': '᠌', '/mong:ga': 'ᠭ', '/mong:gaasibe':
- 'ᡬ', '/mong:gaatodo': 'ᡘ', '/mong:gasibe': 'ᡤ', '/mong:gatodo': 'ᡎ',
- '/mong:ghamanchualigali': 'ᢚ', '/mong:haa': 'ᠾ', '/mong:haasibe': 'ᡭ',
- '/mong:haatodo': 'ᡙ', '/mong:hasibe': 'ᡥ', '/mong:i': 'ᠢ',
- '/mong:ialigali': 'ᢈ', '/mong:imanchu': 'ᡳ', '/mong:isibe': 'ᡞ',
- '/mong:itodo': 'ᡅ', '/mong:iysibe': 'ᡟ', '/mong:ja': 'ᠵ',
- '/mong:jasibe': 'ᡪ', '/mong:jatodo': 'ᡓ', '/mong:jhamanchualigali': 'ᢝ',
- '/mong:jiatodo': 'ᡚ', '/mong:ka': 'ᠺ', '/mong:kaaligali': 'ᢉ',
- '/mong:kamanchu': 'ᡴ', '/mong:kasibe': 'ᡣ', '/mong:katodo': 'ᡗ',
- '/mong:kha': 'ᠻ', '/mong:la': 'ᠯ', '/mong:lha': 'ᡀ',
- '/mong:lhamanchualigali': 'ᢪ', '/mong:longvowelsigntodo': 'ᡃ',
- '/mong:ma': 'ᠮ', '/mong:matodo': 'ᡏ', '/mong:na': 'ᠨ',
- '/mong:ngaaligali': 'ᢊ', '/mong:ngamanchualigali': 'ᢛ', '/mong:niatodo':
- 'ᡛ', '/mong:nine': '᠙', '/mong:nirugu': '᠊', '/mong:nnaaligali': 'ᢏ',
- '/mong:o': 'ᠣ', '/mong:oe': 'ᠥ', '/mong:oetodo': 'ᡈ', '/mong:one': '᠑',
- '/mong:otodo': 'ᡆ', '/mong:pa': 'ᠫ', '/mong:paaligali': 'ᢒ',
- '/mong:pasibe': 'ᡦ', '/mong:patodo': 'ᡌ', '/mong:period': '᠃',
- '/mong:periodmanchu': '᠉', '/mong:phaaligali': 'ᢓ', '/mong:qa': 'ᠬ',
- '/mong:qatodo': 'ᡍ', '/mong:ra': 'ᠷ', '/mong:raasibe': 'ᡰ',
- '/mong:ramanchu': 'ᡵ', '/mong:sa': 'ᠰ', '/mong:seven': '᠗', '/mong:sha':
- 'ᠱ', '/mong:shasibe': 'ᡧ', '/mong:six': '᠖', '/mong:softhyphentodo':
- '᠆', '/mong:ssaaligali': 'ᢔ', '/mong:ssamanchualigali': 'ᢢ',
- '/mong:syllableboundarymarkersibe': '᠇', '/mong:ta': 'ᠲ',
- '/mong:taaligali': 'ᢐ', '/mong:tamanchualigali': 'ᢠ', '/mong:tasibe':
- 'ᡨ', '/mong:tatodo': 'ᡐ', '/mong:tatodoaligali': 'ᢘ', '/mong:three':
- '᠓', '/mong:tsa': 'ᠼ', '/mong:tsasibe': 'ᡮ', '/mong:tsatodo': 'ᡔ',
- '/mong:ttaaligali': 'ᢌ', '/mong:ttamanchualigali': 'ᢞ',
- '/mong:tthaaligali': 'ᢍ', '/mong:two': '᠒', '/mong:u': 'ᠤ',
- '/mong:ualigalihalf': 'ᢦ', '/mong:ubadamaaligali': 'ᢃ',
- '/mong:ubadamaaligaliinverted': 'ᢄ', '/mong:ue': 'ᠦ', '/mong:uesibe':
- 'ᡠ', '/mong:uetodo': 'ᡉ', '/mong:usibe': 'ᡡ', '/mong:utodo': 'ᡇ',
- '/mong:visargaonealigali': 'ᢁ', '/mong:vowelseparator': '\u180e',
- '/mong:wa': 'ᠸ', '/mong:watodo': 'ᡖ', '/mong:ya': 'ᠶ',
- '/mong:yaaligalihalf': 'ᢧ', '/mong:yatodo': 'ᡕ', '/mong:za': 'ᠽ',
- '/mong:zaaligali': 'ᢖ', '/mong:zamanchualigali': 'ᢥ', '/mong:zasibe':
- 'ᡯ', '/mong:zero': '᠐', '/mong:zhaaligali': 'ᢕ', '/mong:zhamanchu': 'ᡷ',
- '/mong:zhamanchualigali': 'ᢤ', '/mong:zhasibe': 'ᡲ',
- '/mong:zhatodoaligali': 'ᢙ', '/mong:zhi': 'ᡁ', '/mong:zra': 'ᠿ',
- '/monkey': 'ὁ2', '/monkeyFace': 'ὃ5', '/monogramyang': '⚊',
- '/monogramyin': '⚋', '/monorail': 'ὩD', '/monostable': '⎍',
- '/moodBubble': 'Ὗ0', '/moonViewingCeremony': 'Ἱ1',
- '/moonideographiccircled': '㊊', '/moonideographicparen': '㈪',
- '/moonlilithblack': '⚸', '/mosque': 'ὔC', '/motorBoat': 'Ὦ5',
- '/motorScooter': 'Ὧ5', '/motorway': 'Ὦ3', '/mountFuji': 'ὟB',
- '/mountain': '⛰', '/mountainBicyclist': 'Ὣ5', '/mountainCableway': 'Ὢ0',
- '/mountainRailway': 'ὩE', '/mouse': 'ὀ1', '/mouseFace': 'ὂD', '/mouth':
- 'ὄ4', '/movers2fullwidth': '㎨', '/moversfullwidth': '㎧',
- '/moverssquare': '㎧', '/moverssquaredsquare': '㎨', '/movieCamera': 'Ἲ5',
- '/moyai': 'ὟF', '/mpafullwidth': '㎫', '/mparen': '⒨', '/mparenthesized':
- '⒨', '/mpasquare': '㎫', '/msfullwidth': '㎳', '/mssquare': '㎳',
- '/msuperior': '\uf6ef', '/mturned': 'ɯ', '/mu': 'µ', '/mu.math': 'µ',
- '/mu1': 'µ', '/muafullwidth': '㎂', '/muasquare': '㎂', '/muchgreater':
- '≫', '/muchless': '≪', '/mucirclekatakana': '㋰', '/muffullwidth': '㎌',
- '/mufsquare': '㎌', '/mugfullwidth': '㎍', '/mugreek': 'μ', '/mugsquare':
- '㎍', '/muhiragana': 'む', '/mukatakana': 'ム', '/mukatakanahalfwidth':
- 'ム', '/mulfullwidth': '㎕', '/mulsquare': '㎕', '/multimap': '⊸',
- '/multimapleft': '⟜', '/multipleMusicalNotes': 'Ἳ6', '/multiply': '×',
- '/multiset': '⊌', '/multisetmultiplication': '⊍', '/multisetunion': '⊎',
- '/mum': 'ꝳ', '/mumfullwidth': '㎛', '/mumsquare': '㎛', '/munach:hb': '֣',
- '/munahhebrew': '֣', '/munahlefthebrew': '֣', '/musfullwidth': '㎲',
- '/mushroom': 'ἴ4', '/musicalKeyboard': 'Ἳ9', '/musicalKeyboardJacks':
- 'Ἱ8', '/musicalNote': 'Ἳ5', '/musicalScore': 'ἻC', '/musicalnote': '♪',
- '/musicalnotedbl': '♫', '/musicflat': '♭', '/musicflatsign': '♭',
- '/musicnatural': '♮', '/musicsharp': '♯', '/musicsharpsign': '♯',
- '/mussquare': '㎲', '/muvfullwidth': '㎶', '/muvsquare': '㎶',
- '/muwfullwidth': '㎼', '/muwsquare': '㎼', '/mvfullwidth': '㎷',
- '/mvmegafullwidth': '㎹', '/mvmegasquare': '㎹', '/mvsquare': '㎷',
- '/mwfullwidth': '㎽', '/mwmegafullwidth': '㎿', '/mwmegasquare': '㎿',
- '/mwsquare': '㎽', '/n': 'n', '/n.inferior': 'ₙ', '/n.superior': 'ⁿ',
- '/nabengali': 'ন', '/nabla': '∇', '/nacirclekatakana': '㋤', '/nacute':
- 'ń', '/nadeva': 'न', '/nafullwidth': '㎁', '/nagujarati': 'ન',
- '/nagurmukhi': 'ਨ', '/nahiragana': 'な', '/nailPolish': 'Ὀ5', '/naira':
- '₦', '/nakatakana': 'ナ', '/nakatakanahalfwidth': 'ナ', '/nameBadge':
- 'ὍB', '/nameideographiccircled': '㊔', '/nameideographicparen': '㈴',
- '/namurda': 'ꦟ', '/nand': '⊼', '/nanosquare': '㌨', '/napostrophe': 'ʼn',
- '/narrownobreakspace': '\u202f', '/nasquare': '㎁', '/nationalPark':
- 'ἽE', '/nationaldigitshapes': '\u206e', '/nbopomofo': 'ㄋ', '/nbspace':
- '\xa0', '/ncaron': 'ň', '/ncedilla': 'ņ', '/ncircle': 'ⓝ',
- '/ncircumflexbelow': 'ṋ', '/ncommaaccent': 'ņ', '/ncurl': 'ȵ',
- '/ndescender': 'ꞑ', '/ndot': 'ṅ', '/ndotaccent': 'ṅ', '/ndotbelow': 'ṇ',
- '/necirclekatakana': '㋧', '/necktie': 'ὅ4',
- '/negatedturnstiledblverticalbarright': '⊯', '/nehiragana': 'ね',
- '/neirapproximatelynoractuallyequal': '≇', '/neirasersetnorequalup':
- '⊉', '/neirasubsetnorequal': '⊈', '/neirgreaternorequal': '≱',
- '/neirgreaternorequivalent': '≵', '/neirgreaternorless': '≹',
- '/neirlessnorequal': '≰', '/neirlessnorequivalent': '≴',
- '/neirlessnorgreater': '≸', '/nekatakana': 'ネ', '/nekatakanahalfwidth':
- 'ネ', '/neptune': '♆', '/neuter': '⚲', '/neutralFace': 'ὡ0', '/newMoon':
- 'ἱ1', '/newMoonFace': 'ἱA', '/newsheqel': '₪', '/newsheqelsign': '₪',
- '/newspaper': '\u1f4f0', '/newsquare': 'Ἑ5', '/nextpage': '⎘',
- '/nffullwidth': '㎋', '/nfsquare': '㎋', '/ng.fina': 'ﯔ', '/ng.init': 'ﯕ',
- '/ng.isol': 'ﯓ', '/ng.medi': 'ﯖ', '/ngabengali': 'ঙ', '/ngadeva': 'ङ',
- '/ngagujarati': 'ઙ', '/ngagurmukhi': 'ਙ', '/ngalelet': 'ꦊ',
- '/ngaleletraswadi': 'ꦋ', '/ngoeh': 'ڱ', '/ngoeh.fina': 'ﮛ',
- '/ngoeh.init': 'ﮜ', '/ngoeh.isol': 'ﮚ', '/ngoeh.medi': 'ﮝ',
- '/ngonguthai': 'ง', '/ngrave': 'ǹ', '/ngsquare': 'Ἑ6', '/nhiragana':
- 'ん', '/nhookleft': 'ɲ', '/nhookretroflex': 'ɳ', '/nicirclekatakana':
- '㋥', '/nieunacirclekorean': '㉯', '/nieunaparenkorean': '㈏',
- '/nieuncieuckorean': 'ㄵ', '/nieuncirclekorean': '㉡',
- '/nieunhieuhkorean': 'ㄶ', '/nieunkorean': 'ㄴ', '/nieunpansioskorean':
- 'ㅨ', '/nieunparenkorean': '㈁', '/nieunsioskorean': 'ㅧ',
- '/nieuntikeutkorean': 'ㅦ', '/nightStars': 'ἰ3',
- '/nightideographiccircled': '㊰', '/nihiragana': 'に', '/nikatakana': 'ニ',
- '/nikatakanahalfwidth': 'ニ', '/nikhahitleftthai': '\uf899',
- '/nikhahitthai': 'ํ', '/nine': '9', '/nine.inferior': '₉',
- '/nine.roman': 'Ⅸ', '/nine.romansmall': 'ⅸ', '/nine.superior': '⁹',
- '/ninearabic': '٩', '/ninebengali': '৯', '/ninecircle': '⑨',
- '/ninecircledbl': '⓽', '/ninecircleinversesansserif': '➒', '/ninecomma':
- 'ἐA', '/ninedeva': '९', '/ninefar': '۹', '/ninegujarati': '૯',
- '/ninegurmukhi': '੯', '/ninehackarabic': '٩', '/ninehangzhou': '〩',
- '/nineideographiccircled': '㊈', '/nineideographicparen': '㈨',
- '/nineinferior': '₉', '/ninemonospace': '9', '/nineoldstyle': '\uf739',
- '/nineparen': '⑼', '/nineparenthesized': '⑼', '/nineperiod': '⒐',
- '/ninepersian': '۹', '/nineroman': 'ⅸ', '/ninesuperior': '⁹',
- '/nineteencircle': '⑲', '/nineteencircleblack': '⓳', '/nineteenparen':
- '⒆', '/nineteenparenthesized': '⒆', '/nineteenperiod': '⒚', '/ninethai':
- '๙', '/nj': 'nj', '/njecyr': 'њ', '/njecyrillic': 'њ', '/njekomicyr':
- 'ԋ', '/nkatakana': 'ン', '/nkatakanahalfwidth': 'ン', '/nlegrightlong':
- 'ƞ', '/nlinebelow': 'ṉ', '/nlongrightleg': 'ƞ', '/nmbr:oneeighth': '⅛',
- '/nmbr:onefifth': '⅕', '/nmbr:onetenth': '⅒', '/nmfullwidth': '㎚',
- '/nmonospace': 'n', '/nmsquare': '㎚', '/nnabengali': 'ণ', '/nnadeva':
- 'ण', '/nnagujarati': 'ણ', '/nnagurmukhi': 'ਣ', '/nnnadeva': 'ऩ',
- '/noBicycles': 'Ὣ3', '/noEntrySign': 'ὪB', '/noMobilePhones': '\u1f4f5',
- '/noOneUnderEighteen': 'ὑE', '/noPedestrians': 'Ὣ7', '/noPiracy': 'ὗ2',
- '/noSmoking': 'ὪD', '/nobliquestroke': 'ꞥ', '/nocirclekatakana': '㋨',
- '/nodeascending': '☊', '/nodedescending': '☋', '/noentry': '⛔',
- '/nohiragana': 'の', '/nokatakana': 'ノ', '/nokatakanahalfwidth': 'ノ',
- '/nominaldigitshapes': '\u206f', '/nonPotableWater': 'Ὣ1',
- '/nonbreakinghyphen': '‑', '/nonbreakingspace': '\xa0', '/nonenthai':
- 'ณ', '/nonuthai': 'น', '/noon': 'ن', '/noon.fina': 'ﻦ', '/noon.init':
- 'ﻧ', '/noon.init_alefmaksura.fina': 'ﱏ', '/noon.init_hah.fina': 'ﱌ',
- '/noon.init_hah.medi': 'ﳓ', '/noon.init_hah.medi_meem.medi': 'ﶕ',
- '/noon.init_heh.medi': 'ﳖ', '/noon.init_jeem.fina': 'ﱋ',
- '/noon.init_jeem.medi': 'ﳒ', '/noon.init_jeem.medi_hah.medi': 'ﶸ',
- '/noon.init_jeem.medi_meem.medi': 'ﶘ', '/noon.init_khah.fina': 'ﱍ',
- '/noon.init_khah.medi': 'ﳔ', '/noon.init_meem.fina': 'ﱎ',
- '/noon.init_meem.medi': 'ﳕ', '/noon.init_yeh.fina': 'ﱐ', '/noon.isol':
- 'ﻥ', '/noon.medi': 'ﻨ', '/noon.medi_alefmaksura.fina': 'ﲎ',
- '/noon.medi_hah.medi_alefmaksura.fina': 'ﶖ',
- '/noon.medi_hah.medi_yeh.fina': 'ﶳ', '/noon.medi_heh.medi': 'ﳯ',
- '/noon.medi_jeem.medi_alefmaksura.fina': 'ﶙ',
- '/noon.medi_jeem.medi_hah.fina': 'ﶽ', '/noon.medi_jeem.medi_meem.fina':
- 'ﶗ', '/noon.medi_jeem.medi_yeh.fina': 'ﷇ', '/noon.medi_meem.fina': 'ﲌ',
- '/noon.medi_meem.medi': 'ﳮ', '/noon.medi_meem.medi_alefmaksura.fina':
- 'ﶛ', '/noon.medi_meem.medi_yeh.fina': 'ﶚ', '/noon.medi_noon.fina': 'ﲍ',
- '/noon.medi_reh.fina': 'ﲊ', '/noon.medi_yeh.fina': 'ﲏ',
- '/noon.medi_zain.fina': 'ﲋ', '/noonSmallTah': 'ݨ', '/noonSmallV': 'ݩ',
- '/noonTwoDotsBelow': 'ݧ', '/noonabove': 'ۨ', '/noonarabic': 'ن',
- '/noondotbelow': 'ڹ', '/noonfinalarabic': 'ﻦ', '/noonghunna': 'ں',
- '/noonghunna.fina': 'ﮟ', '/noonghunna.isol': 'ﮞ', '/noonghunnaarabic':
- 'ں', '/noonghunnafinalarabic': 'ﮟ', '/noonhehinitialarabic': 'ﻧ',
- '/nooninitialarabic': 'ﻧ', '/noonjeeminitialarabic': 'ﳒ',
- '/noonjeemisolatedarabic': 'ﱋ', '/noonmedialarabic': 'ﻨ',
- '/noonmeeminitialarabic': 'ﳕ', '/noonmeemisolatedarabic': 'ﱎ',
- '/noonnoonfinalarabic': 'ﲍ', '/noonring': 'ڼ', '/noonthreedotsabove':
- 'ڽ', '/nor': '⊽', '/nordicmark': '₻',
- '/normalfacrsemidirectproductleft': '⋉',
- '/normalfacrsemidirectproductright': '⋊', '/normalsubgroorequalup': '⊴',
- '/normalsubgroup': '⊲', '/northeastPointingAirplane': 'ὮA', '/nose':
- 'ὄ3', '/notalmostequal': '≉', '/notasersetup': '⊅',
- '/notasympticallyequal': '≄', '/notcheckmark': '⍻',
- '/notchedLeftSemicircleThreeDots': 'ὔ3',
- '/notchedRightSemicircleThreeDots': 'ὔ4', '/notcontains': '∌', '/note':
- '\u1f5c8', '/notePad': '\u1f5cA', '/notePage': '\u1f5c9', '/notebook':
- 'Ὅ3', '/notebookDecorativeCover': 'Ὅ4', '/notelement': '∉',
- '/notelementof': '∉', '/notequal': '≠', '/notequivalent': '≭',
- '/notexistential': '∄', '/notgreater': '≯', '/notgreaternorequal': '≱',
- '/notgreaternorless': '≹', '/notidentical': '≢', '/notless': '≮',
- '/notlessnorequal': '≰', '/notnormalsubgroorequalup': '⋬',
- '/notnormalsubgroup': '⋪', '/notparallel': '∦', '/notprecedes': '⊀',
- '/notsignturned': '⌙', '/notsquareimageorequal': '⋢',
- '/notsquareoriginalorequal': '⋣', '/notsubset': '⊄', '/notsucceeds':
- '⊁', '/notsuperset': '⊅', '/nottilde': '≁', '/nottosquare': '㌩',
- '/nottrue': '⊭', '/novembertelegraph': '㋊', '/nowarmenian': 'ն',
- '/nparen': '⒩', '/nparenthesized': '⒩', '/nretroflex': 'ɳ',
- '/nsfullwidth': '㎱', '/nssquare': '㎱', '/nsuperior': 'ⁿ', '/ntilde':
- 'ñ', '/nu': 'ν', '/nucirclekatakana': '㋦', '/nuhiragana': 'ぬ',
- '/nukatakana': 'ヌ', '/nukatakanahalfwidth': 'ヌ', '/nuktabengali': '়',
- '/nuktadeva': '़', '/nuktagujarati': '઼', '/nuktagurmukhi': '਼', '/num':
- 'ꝴ', '/numbermarkabove': '\u0605', '/numbersign': '#',
- '/numbersignmonospace': '#', '/numbersignsmall': '﹟', '/numeralsign':
- 'ʹ', '/numeralsigngreek': 'ʹ', '/numeralsignlowergreek': '͵', '/numero':
- '№', '/nun': 'נ', '/nun:hb': 'נ', '/nunHafukha:hb': '׆', '/nundagesh':
- 'נּ', '/nundageshhebrew': 'נּ', '/nunhebrew': 'נ', '/nunwithdagesh:hb':
- 'נּ', '/nutAndBolt': 'ὒ9', '/nvfullwidth': '㎵', '/nvsquare': '㎵',
- '/nwfullwidth': '㎻', '/nwsquare': '㎻', '/nyabengali': 'ঞ', '/nyadeva':
- 'ञ', '/nyagujarati': 'ઞ', '/nyagurmukhi': 'ਞ', '/nyamurda': 'ꦘ',
- '/nyeh': 'ڃ', '/nyeh.fina': 'ﭷ', '/nyeh.init': 'ﭸ', '/nyeh.isol': 'ﭶ',
- '/nyeh.medi': 'ﭹ', '/o': 'o', '/o.inferior': 'ₒ', '/oacute': 'ó',
- '/oangthai': 'อ', '/obarcyr': 'ө', '/obardieresiscyr': 'ӫ', '/obarred':
- 'ɵ', '/obarredcyrillic': 'ө', '/obarreddieresiscyrillic': 'ӫ',
- '/obelosdotted': '⸓', '/obengali': 'ও', '/obopomofo': 'ㄛ', '/obreve':
- 'ŏ', '/observereye': '⏿', '/ocandradeva': 'ऑ', '/ocandragujarati': 'ઑ',
- '/ocandravowelsigndeva': 'ॉ', '/ocandravowelsigngujarati': 'ૉ',
- '/ocaron': 'ǒ', '/ocircle': 'ⓞ', '/ocirclekatakana': '㋔',
- '/ocircumflex': 'ô', '/ocircumflexacute': 'ố', '/ocircumflexdotbelow':
- 'ộ', '/ocircumflexgrave': 'ồ', '/ocircumflexhoi': 'ổ',
- '/ocircumflexhookabove': 'ổ', '/ocircumflextilde': 'ỗ', '/ocr:bowtie':
- '⑅', '/ocr:dash': '⑈', '/octagonalSign': 'Ὥ1', '/octobertelegraph': '㋉',
- '/octopus': 'ὁ9', '/ocyr': 'о', '/ocyrillic': 'о', '/odblacute': 'ő',
- '/odblgrave': 'ȍ', '/oden': 'ἶ2', '/odeva': 'ओ', '/odieresis': 'ö',
- '/odieresiscyr': 'ӧ', '/odieresiscyrillic': 'ӧ', '/odieresismacron':
- 'ȫ', '/odot': 'ȯ', '/odotbelow': 'ọ', '/odotmacron': 'ȱ', '/oe': 'œ',
- '/oe.fina': 'ﯚ', '/oe.isol': 'ﯙ', '/oekirghiz': 'ۅ', '/oekirghiz.fina':
- 'ﯡ', '/oekirghiz.isol': 'ﯠ', '/oekorean': 'ㅚ', '/officeBuilding': 'Ἶ2',
- '/ogonek': '˛', '/ogonekcmb': '̨', '/ograve': 'ò', '/ogravedbl': 'ȍ',
- '/ogujarati': 'ઓ', '/oharmenian': 'օ', '/ohiragana': 'お', '/ohm': 'Ω',
- '/ohminverted': '℧', '/ohoi': 'ỏ', '/ohookabove': 'ỏ', '/ohorn': 'ơ',
- '/ohornacute': 'ớ', '/ohorndotbelow': 'ợ', '/ohorngrave': 'ờ',
- '/ohornhoi': 'ở', '/ohornhookabove': 'ở', '/ohorntilde': 'ỡ',
- '/ohungarumlaut': 'ő', '/ohuparen': '㈞', '/oi': 'ƣ', '/oilDrum': 'Ὦ2',
- '/oinvertedbreve': 'ȏ', '/ojeonparen': '㈝', '/okHandSign': 'ὄC',
- '/okatakana': 'オ', '/okatakanahalfwidth': 'オ', '/okorean': 'ㅗ',
- '/oksquare': 'Ἑ7', '/oldKey': 'ὝD', '/oldPersonalComputer': 'Ὓ3',
- '/olderMan': '\u1f474', '/olderWoman': '\u1f475', '/ole:hb': '֫',
- '/olehebrew': '֫', '/oloop': 'ꝍ', '/olowringinside': 'ⱺ', '/omacron':
- 'ō', '/omacronacute': 'ṓ', '/omacrongrave': 'ṑ', '/omdeva': 'ॐ',
- '/omega': 'ω', '/omega1': 'ϖ', '/omegaacute': 'ώ', '/omegaacuteiotasub':
- 'ῴ', '/omegaasper': 'ὡ', '/omegaasperacute': 'ὥ',
- '/omegaasperacuteiotasub': 'ᾥ', '/omegaaspergrave': 'ὣ',
- '/omegaaspergraveiotasub': 'ᾣ', '/omegaasperiotasub': 'ᾡ',
- '/omegaaspertilde': 'ὧ', '/omegaaspertildeiotasub': 'ᾧ', '/omegaclosed':
- 'ɷ', '/omegacyr': 'ѡ', '/omegacyrillic': 'ѡ', '/omegafunc': '⍵',
- '/omegagrave': 'ὼ', '/omegagraveiotasub': 'ῲ', '/omegaiotasub': 'ῳ',
- '/omegalatinclosed': 'ɷ', '/omegalenis': 'ὠ', '/omegalenisacute': 'ὤ',
- '/omegalenisacuteiotasub': 'ᾤ', '/omegalenisgrave': 'ὢ',
- '/omegalenisgraveiotasub': 'ᾢ', '/omegalenisiotasub': 'ᾠ',
- '/omegalenistilde': 'ὦ', '/omegalenistildeiotasub': 'ᾦ',
- '/omegaroundcyr': 'ѻ', '/omegaroundcyrillic': 'ѻ', '/omegatilde': 'ῶ',
- '/omegatildeiotasub': 'ῷ', '/omegatitlocyr': 'ѽ', '/omegatitlocyrillic':
- 'ѽ', '/omegatonos': 'ώ', '/omegaunderlinefunc': '⍹', '/omgujarati': 'ૐ',
- '/omicron': 'ο', '/omicronacute': 'ό', '/omicronasper': 'ὁ',
- '/omicronasperacute': 'ὅ', '/omicronaspergrave': 'ὃ', '/omicrongrave':
- 'ὸ', '/omicronlenis': 'ὀ', '/omicronlenisacute': 'ὄ',
- '/omicronlenisgrave': 'ὂ', '/omicrontonos': 'ό', '/omonospace': 'o',
- '/onExclamationMarkLeftRightArrowAbove': 'ὑB', '/oncomingAutomobile':
- 'Ὡ8', '/oncomingBus': 'ὨD', '/oncomingFireEngine': 'Ὧ1',
- '/oncomingPoliceCar': 'Ὡ4', '/oncomingTaxi': 'Ὡ6', '/one': '1',
- '/one.inferior': '₁', '/one.roman': 'Ⅰ', '/one.romansmall': 'ⅰ',
- '/oneButtonMouse': '\u1f5aF', '/onearabic': '١', '/onebengali': '১',
- '/onecircle': '①', '/onecircledbl': '⓵', '/onecircleinversesansserif':
- '➊', '/onecomma': 'ἐ2', '/onedeva': '१', '/onedotenleader': '․',
- '/onedotovertwodots': '⸫', '/oneeighth': '⅛', '/onefar': '۱',
- '/onefitted': '\uf6dc', '/onefraction': '⅟', '/onegujarati': '૧',
- '/onegurmukhi': '੧', '/onehackarabic': '١', '/onehalf': '½',
- '/onehangzhou': '〡', '/onehundred.roman': 'Ⅽ', '/onehundred.romansmall':
- 'ⅽ', '/onehundredthousand.roman': 'ↈ', '/onehundredtwentypsquare': 'Ἒ4',
- '/oneideographiccircled': '㊀', '/oneideographicparen': '㈠',
- '/oneinferior': '₁', '/onemonospace': '1', '/oneninth': '⅑',
- '/onenumeratorbengali': '৴', '/oneoldstyle': '\uf731', '/oneparen': '⑴',
- '/oneparenthesized': '⑴', '/oneperiod': '⒈', '/onepersian': '۱',
- '/onequarter': '¼', '/oneroman': 'ⅰ', '/oneseventh': '⅐', '/onesixth':
- '⅙', '/onesuperior': '¹', '/onethai': '๑', '/onethird': '⅓',
- '/onethousand.roman': 'Ⅿ', '/onethousand.romansmall': 'ⅿ',
- '/onethousandcd.roman': 'ↀ', '/onsusquare': '㌉', '/oo': 'ꝏ', '/oogonek':
- 'ǫ', '/oogonekmacron': 'ǭ', '/oogurmukhi': 'ਓ', '/oomatragurmukhi': 'ੋ',
- '/oomusquare': '㌊', '/oopen': 'ɔ', '/oparen': '⒪', '/oparenthesized':
- '⒪', '/openBook': 'Ὅ6', '/openFileFolder': 'Ὄ2', '/openFolder':
- '\u1f5c1', '/openHandsSign': 'ὅ0', '/openLock': 'ὑ3',
- '/openMailboxLoweredFlag': '\u1f4eD', '/openMailboxRaisedFlag':
- '\u1f4eC', '/openbullet': '◦', '/openheadarrowleft': '⇽',
- '/openheadarrowleftright': '⇿', '/openheadarrowright': '⇾',
- '/opensubset': '⟃', '/opensuperset': '⟄', '/ophiuchus': '⛎',
- '/opposition': '☍', '/opticalDisc': 'ὋF', '/opticalDiscIcon': 'Ὓ8',
- '/option': '⌥', '/orangeBook': 'Ὅ9', '/ordfeminine': 'ª',
- '/ordmasculine': 'º', '/ordotinside': '⟇', '/original': '⊶',
- '/ornateleftparenthesis': '﴾', '/ornaterightparenthesis': '﴿',
- '/orthodoxcross': '☦', '/orthogonal': '∟', '/orya:a': 'ଅ', '/orya:aa':
- 'ଆ', '/orya:aasign': 'ା', '/orya:ai': 'ଐ', '/orya:ailengthmark': 'ୖ',
- '/orya:aisign': 'ୈ', '/orya:anusvara': 'ଂ', '/orya:au': 'ଔ',
- '/orya:aulengthmark': 'ୗ', '/orya:ausign': 'ୌ', '/orya:avagraha': 'ଽ',
- '/orya:ba': 'ବ', '/orya:bha': 'ଭ', '/orya:ca': 'ଚ', '/orya:candrabindu':
- 'ଁ', '/orya:cha': 'ଛ', '/orya:da': 'ଦ', '/orya:dda': 'ଡ', '/orya:ddha':
- 'ଢ', '/orya:dha': 'ଧ', '/orya:e': 'ଏ', '/orya:eight': '୮',
- '/orya:esign': 'େ', '/orya:five': '୫', '/orya:four': '୪',
- '/orya:fractiononeeighth': '୶', '/orya:fractiononehalf': '୳',
- '/orya:fractiononequarter': '୲', '/orya:fractiononesixteenth': '୵',
- '/orya:fractionthreequarters': '୴', '/orya:fractionthreesixteenths':
- '୷', '/orya:ga': 'ଗ', '/orya:gha': 'ଘ', '/orya:ha': 'ହ', '/orya:i': 'ଇ',
- '/orya:ii': 'ଈ', '/orya:iisign': 'ୀ', '/orya:isign': 'ି',
- '/orya:isshar': '୰', '/orya:ja': 'ଜ', '/orya:jha': 'ଝ', '/orya:ka': 'କ',
- '/orya:kha': 'ଖ', '/orya:la': 'ଲ', '/orya:lla': 'ଳ', '/orya:llvocal':
- 'ୡ', '/orya:llvocalsign': 'ୣ', '/orya:lvocal': 'ଌ', '/orya:lvocalsign':
- 'ୢ', '/orya:ma': 'ମ', '/orya:na': 'ନ', '/orya:nga': 'ଙ', '/orya:nine':
- '୯', '/orya:nna': 'ଣ', '/orya:nukta': '଼', '/orya:nya': 'ଞ', '/orya:o':
- 'ଓ', '/orya:one': '୧', '/orya:osign': 'ୋ', '/orya:pa': 'ପ', '/orya:pha':
- 'ଫ', '/orya:ra': 'ର', '/orya:rha': 'ଢ଼', '/orya:rra': 'ଡ଼',
- '/orya:rrvocal': 'ୠ', '/orya:rrvocalsign': 'ୄ', '/orya:rvocal': 'ଋ',
- '/orya:rvocalsign': 'ୃ', '/orya:sa': 'ସ', '/orya:seven': '୭',
- '/orya:sha': 'ଶ', '/orya:six': '୬', '/orya:ssa': 'ଷ', '/orya:ta': 'ତ',
- '/orya:tha': 'ଥ', '/orya:three': '୩', '/orya:tta': 'ଟ', '/orya:ttha':
- 'ଠ', '/orya:two': '୨', '/orya:u': 'ଉ', '/orya:usign': 'ୁ', '/orya:uu':
- 'ଊ', '/orya:uusign': 'ୂ', '/orya:va': 'ଵ', '/orya:virama': '୍',
- '/orya:visarga': 'ଃ', '/orya:wa': 'ୱ', '/orya:ya': 'ଯ', '/orya:yya':
- 'ୟ', '/orya:zero': '୦', '/oscript': 'ℴ', '/oshortdeva': 'ऒ',
- '/oshortvowelsigndeva': 'ॊ', '/oslash': 'ø', '/oslashacute': 'ǿ',
- '/osmallhiragana': 'ぉ', '/osmallkatakana': 'ォ',
- '/osmallkatakanahalfwidth': 'ォ', '/ostroke': 'ꝋ', '/ostrokeacute': 'ǿ',
- '/osuperior': '\uf6f0', '/otcyr': 'ѿ', '/otcyrillic': 'ѿ', '/otilde':
- 'õ', '/otildeacute': 'ṍ', '/otildedieresis': 'ṏ', '/otildemacron': 'ȭ',
- '/ou': 'ȣ', '/oubopomofo': 'ㄡ', '/ounce': '℥', '/outboxTray': '\u1f4e4',
- '/outerjoinfull': '⟗', '/outerjoinleft': '⟕', '/outerjoinright': '⟖',
- '/outputpassiveup': '⎒', '/overlap': 'Ὕ7', '/overline': '‾',
- '/overlinecenterline': '﹊', '/overlinecmb': '̅', '/overlinedashed': '﹉',
- '/overlinedblwavy': '﹌', '/overlinewavy': '﹋', '/overscore': '¯',
- '/ovfullwidth': '㍵', '/ovowelsignbengali': 'ো', '/ovowelsigndeva': 'ो',
- '/ovowelsigngujarati': 'ો', '/ox': 'ὀ2', '/p': 'p', '/p.inferior': 'ₚ',
- '/paampsfullwidth': '㎀', '/paampssquare': '㎀', '/paasentosquare': '㌫',
- '/paatusquare': '㌬', '/pabengali': 'প', '/pacerek': 'ꦉ', '/package':
- '\u1f4e6', '/pacute': 'ṕ', '/padeva': 'प', '/pafullwidth': '㎩', '/page':
- '\u1f5cF', '/pageCircledText': 'ὝF', '/pageCurl': 'Ὄ3', '/pageFacingUp':
- 'Ὄ4', '/pagedown': '⇟', '/pager': 'ὍF', '/pages': 'Ὕ0', '/pageup': '⇞',
- '/pagoda': 'Ὥ4', '/pagujarati': 'પ', '/pagurmukhi': 'ਪ', '/pahiragana':
- 'ぱ', '/paiyannoithai': 'ฯ', '/pakatakana': 'パ',
- '/palatalizationcyrilliccmb': '҄', '/palatcmbcyr': '҄', '/pallas': '⚴',
- '/palmTree': 'ἳ4', '/palmbranch': '⸙', '/palochkacyr': 'ӏ',
- '/palochkacyrillic': 'Ӏ', '/pamurda': 'ꦦ', '/pandaFace': 'ὃC',
- '/pangkatpada': '꧇', '/pangkon': '꧀', '/pangrangkep': 'ꧏ',
- '/pansioskorean': 'ㅿ', '/panyangga': 'ꦀ', '/paperclip': 'ὌE',
- '/paragraph': '¶', '/paragraphos': '⸏', '/paragraphosforked': '⸐',
- '/paragraphosforkedreversed': '⸑', '/paragraphseparator': '\u2029',
- '/parallel': '∥', '/parallelogramblack': '▰', '/parallelogramwhite':
- '▱', '/parenbottom': '⏝', '/parendblleft': '⸨', '/parendblright': '⸩',
- '/parenextensionleft': '⎜', '/parenextensionright': '⎟',
- '/parenflatleft': '⟮', '/parenflatright': '⟯', '/parenhookupleft': '⎛',
- '/parenhookupright': '⎞', '/parenleft': '(', '/parenleft.inferior': '₍',
- '/parenleft.superior': '⁽', '/parenleftaltonearabic': '﴾',
- '/parenleftbt': '\uf8ed', '/parenleftex': '\uf8ec',
- '/parenleftinferior': '₍', '/parenleftmonospace': '(',
- '/parenleftsmall': '﹙', '/parenleftsuperior': '⁽', '/parenlefttp':
- '\uf8eb', '/parenleftvertical': '︵', '/parenlowerhookleft': '⎝',
- '/parenlowerhookright': '⎠', '/parenright': ')', '/parenright.inferior':
- '₎', '/parenright.superior': '⁾', '/parenrightaltonearabic': '﴿',
- '/parenrightbt': '\uf8f8', '/parenrightex': '\uf8f7',
- '/parenrightinferior': '₎', '/parenrightmonospace': ')',
- '/parenrightsmall': '﹚', '/parenrightsuperior': '⁾', '/parenrighttp':
- '\uf8f6', '/parenrightvertical': '︶', '/parentop': '⏜',
- '/partalternationmark': '〽', '/partialdiff': '∂', '/partnership': '㉐',
- '/partyPopper': 'Ἰ9', '/paseq:hb': '׀', '/paseqhebrew': '׀',
- '/pashta:hb': '֙', '/pashtahebrew': '֙', '/pasquare': '㎩',
- '/passengerShip': 'Ὧ3', '/passivedown': '⎑', '/passportControl': 'Ὤ2',
- '/patah': 'ַ', '/patah11': 'ַ', '/patah1d': 'ַ', '/patah2a': 'ַ',
- '/patah:hb': 'ַ', '/patahhebrew': 'ַ', '/patahnarrowhebrew': 'ַ',
- '/patahquarterhebrew': 'ַ', '/patahwidehebrew': 'ַ', '/pawPrints': 'ὃE',
- '/pawnblack': '♟', '/pawnwhite': '♙', '/pazer:hb': '֡', '/pazerhebrew':
- '֡', '/pbopomofo': 'ㄆ', '/pcfullwidth': '㍶', '/pcircle': 'ⓟ', '/pdot':
- 'ṗ', '/pdotaccent': 'ṗ', '/pe': 'פ', '/pe:hb': 'פ', '/peace': '☮',
- '/peach': 'ἵ1', '/pear': 'ἵ0', '/pecyr': 'п', '/pecyrillic': 'п',
- '/pedagesh': 'פּ', '/pedageshhebrew': 'פּ', '/pedestrian': 'Ὣ6',
- '/peezisquare': '㌻', '/pefinaldageshhebrew': 'ףּ', '/peh.fina': 'ﭗ',
- '/peh.init': 'ﭘ', '/peh.isol': 'ﭖ', '/peh.medi': 'ﭙ', '/peharabic': 'پ',
- '/peharmenian': 'պ', '/pehebrew': 'פ', '/peheh': 'ڦ', '/peheh.fina':
- 'ﭯ', '/peheh.init': 'ﭰ', '/peheh.isol': 'ﭮ', '/peheh.medi': 'ﭱ',
- '/pehfinalarabic': 'ﭗ', '/pehinitialarabic': 'ﭘ', '/pehiragana': 'ぺ',
- '/pehmedialarabic': 'ﭙ', '/pehookcyr': 'ҧ', '/pekatakana': 'ペ',
- '/pemiddlehookcyrillic': 'ҧ', '/penOverStampedEnvelope': '\u1f586',
- '/pengkalconsonant': 'ꦾ', '/penguin': 'ὂ7', '/penihisquare': '㌸',
- '/pensiveFace': 'ὡ4', '/pensusquare': '㌺', '/pentagram': '⛤',
- '/pentasememetrical': '⏙', '/pepetvowel': 'ꦼ', '/per': '⅌',
- '/perafehebrew': 'פֿ', '/percent': '%', '/percentarabic': '٪',
- '/percentmonospace': '%', '/percentsmall': '﹪', '/percussivebidental':
- 'ʭ', '/percussivebilabial': 'ʬ', '/performingArts': 'ἺD', '/period':
- '.', '/periodarmenian': '։', '/periodcentered': '·', '/periodhalfwidth':
- '。', '/periodinferior': '\uf6e7', '/periodmonospace': '.',
- '/periodsmall': '﹒', '/periodsuperior': '\uf6e8', '/periodurdu': '۔',
- '/perispomenigreekcmb': '͂', '/permanentpaper': '♾', '/permille': '؉',
- '/perpendicular': '⊥', '/perseveringFace': 'ὢ3', '/personBlondHair':
- '\u1f471', '/personBowingDeeply': 'ὤ7', '/personFrowning': 'ὤD',
- '/personRaisingBothHandsInCelebration': 'ὤC', '/personWithFoldedHands':
- 'ὤF', '/personWithPoutingFace': 'ὤE', '/personalComputer': 'ὋB',
- '/personball': '⛹', '/perspective': '⌆', '/pertenthousandsign': '‱',
- '/perthousand': '‰', '/peseta': '₧', '/peso': '₱', '/pesosquare': '㌷',
- '/petailcyr': 'ԥ', '/pewithdagesh:hb': 'פּ', '/pewithrafe:hb': 'פֿ',
- '/pffullwidth': '㎊', '/pflourish': 'ꝓ', '/pfsquare': '㎊', '/phabengali':
- 'ফ', '/phadeva': 'फ', '/phagujarati': 'ફ', '/phagurmukhi': 'ਫ',
- '/pharyngealvoicedfricative': 'ʕ', '/phfullwidth': '㏗', '/phi': 'φ',
- '/phi.math': 'ϕ', '/phi1': 'ϕ', '/phieuphacirclekorean': '㉺',
- '/phieuphaparenkorean': '㈚', '/phieuphcirclekorean': '㉬',
- '/phieuphkorean': 'ㅍ', '/phieuphparenkorean': '㈌', '/philatin': 'ɸ',
- '/phinthuthai': 'ฺ', '/phisymbolgreek': 'ϕ', '/phitailless': 'ⱷ',
- '/phon:AEsmall': 'ᴁ', '/phon:Aemod': 'ᴭ', '/phon:Amod': 'ᴬ',
- '/phon:Asmall': 'ᴀ', '/phon:Bbarmod': 'ᴯ', '/phon:Bbarsmall': 'ᴃ',
- '/phon:Bmod': 'ᴮ', '/phon:Csmall': 'ᴄ', '/phon:Dmod': 'ᴰ',
- '/phon:Dsmall': 'ᴅ', '/phon:ENcyrmod': 'ᵸ', '/phon:Elsmallcyr': 'ᴫ',
- '/phon:Emod': 'ᴱ', '/phon:Ereversedmod': 'ᴲ', '/phon:Esmall': 'ᴇ',
- '/phon:Ethsmall': 'ᴆ', '/phon:Ezhsmall': 'ᴣ', '/phon:Gmod': 'ᴳ',
- '/phon:Hmod': 'ᴴ', '/phon:Imod': 'ᴵ', '/phon:Ismallmod': 'ᶦ',
- '/phon:Ismallstroke': 'ᵻ', '/phon:Istrokesmallmod': 'ᶧ', '/phon:Jmod':
- 'ᴶ', '/phon:Jsmall': 'ᴊ', '/phon:Kmod': 'ᴷ', '/phon:Ksmall': 'ᴋ',
- '/phon:Lmod': 'ᴸ', '/phon:Lsmallmod': 'ᶫ', '/phon:Lsmallstroke': 'ᴌ',
- '/phon:Mmod': 'ᴹ', '/phon:Msmall': 'ᴍ', '/phon:Nmod': 'ᴺ',
- '/phon:Nreversedmod': 'ᴻ', '/phon:Nsmallmod': 'ᶰ',
- '/phon:Nsmallreversed': 'ᴎ', '/phon:OUsmall': 'ᴕ', '/phon:Omod': 'ᴼ',
- '/phon:Oopensmall': 'ᴐ', '/phon:Osmall': 'ᴏ', '/phon:Oumod': 'ᴽ',
- '/phon:Pmod': 'ᴾ', '/phon:Psmall': 'ᴘ', '/phon:Rmod': 'ᴿ',
- '/phon:Rsmallreversed': 'ᴙ', '/phon:Rsmallturned': 'ᴚ', '/phon:Tmod':
- 'ᵀ', '/phon:Tsmall': 'ᴛ', '/phon:Umod': 'ᵁ', '/phon:Usmall': 'ᴜ',
- '/phon:Usmallmod': 'ᶸ', '/phon:Usmallstroke': 'ᵾ', '/phon:Vsmall': 'ᴠ',
- '/phon:Wmod': 'ᵂ', '/phon:Wsmall': 'ᴡ', '/phon:Zsmall': 'ᴢ',
- '/phon:aeturned': 'ᴂ', '/phon:aeturnedmod': 'ᵆ', '/phon:ain': 'ᴥ',
- '/phon:ainmod': 'ᵜ', '/phon:alphamod': 'ᵅ', '/phon:alpharetroflexhook':
- 'ᶐ', '/phon:alphaturnedmod': 'ᶛ', '/phon:amod': 'ᵃ',
- '/phon:aretroflexhook': 'ᶏ', '/phon:aturnedmod': 'ᵄ', '/phon:betamod':
- 'ᵝ', '/phon:bmiddletilde': 'ᵬ', '/phon:bmod': 'ᵇ', '/phon:bpalatalhook':
- 'ᶀ', '/phon:ccurlmod': 'ᶝ', '/phon:chimod': 'ᵡ', '/phon:cmod': 'ᶜ',
- '/phon:deltamod': 'ᵟ', '/phon:dhooktail': 'ᶑ', '/phon:dmiddletilde':
- 'ᵭ', '/phon:dmod': 'ᵈ', '/phon:dotlessjstrokemod': 'ᶡ',
- '/phon:dpalatalhook': 'ᶁ', '/phon:emod': 'ᵉ', '/phon:engmod': 'ᵑ',
- '/phon:eopenmod': 'ᵋ', '/phon:eopenretroflexhook': 'ᶓ',
- '/phon:eopenreversedmod': 'ᶟ', '/phon:eopenreversedretroflexhook': 'ᶔ',
- '/phon:eopenturned': 'ᴈ', '/phon:eopenturnedmod': 'ᵌ',
- '/phon:eretroflexhook': 'ᶒ', '/phon:eshmod': 'ᶴ',
- '/phon:eshpalatalhook': 'ᶋ', '/phon:eshretroflexhook': 'ᶘ',
- '/phon:ethmod': 'ᶞ', '/phon:ezhmod': 'ᶾ', '/phon:ezhretroflexhook': 'ᶚ',
- '/phon:fmiddletilde': 'ᵮ', '/phon:fmod': 'ᶠ', '/phon:fpalatalhook': 'ᶂ',
- '/phon:ginsular': 'ᵹ', '/phon:gmod': 'ᵍ', '/phon:gpalatalhook': 'ᶃ',
- '/phon:gr:Gammasmall': 'ᴦ', '/phon:gr:Lambdasmall': 'ᴧ',
- '/phon:gr:Pismall': 'ᴨ', '/phon:gr:Psismall': 'ᴪ', '/phon:gr:RsmallHO':
- 'ᴩ', '/phon:gr:betasubscript': 'ᵦ', '/phon:gr:chisubscript': 'ᵪ',
- '/phon:gr:gammamod': 'ᵞ', '/phon:gr:gammasubscript': 'ᵧ',
- '/phon:gr:phimod': 'ᵠ', '/phon:gr:phisubscript': 'ᵩ',
- '/phon:gr:rhosubscript': 'ᵨ', '/phon:gscriptmod': 'ᶢ', '/phon:gturned':
- 'ᵷ', '/phon:hturnedmod': 'ᶣ', '/phon:iotamod': 'ᶥ', '/phon:iotastroke':
- 'ᵼ', '/phon:iretroflexhook': 'ᶖ', '/phon:istrokemod': 'ᶤ',
- '/phon:isubscript': 'ᵢ', '/phon:iturned': 'ᴉ', '/phon:iturnedmod': 'ᵎ',
- '/phon:jcrossedtailmod': 'ᶨ', '/phon:kmod': 'ᵏ', '/phon:kpalatalhook':
- 'ᶄ', '/phon:lpalatalhook': 'ᶅ', '/phon:lpalatalhookmod': 'ᶪ',
- '/phon:lretroflexhookmod': 'ᶩ', '/phon:mhookmod': 'ᶬ',
- '/phon:mlonglegturnedmod': 'ᶭ', '/phon:mmiddletilde': 'ᵯ', '/phon:mmod':
- 'ᵐ', '/phon:mpalatalhook': 'ᶆ', '/phon:mturnedmod': 'ᵚ',
- '/phon:mturnedsideways': 'ᴟ', '/phon:nlefthookmod': 'ᶮ',
- '/phon:nmiddletilde': 'ᵰ', '/phon:npalatalhook': 'ᶇ',
- '/phon:nretroflexhookmod': 'ᶯ', '/phon:obarmod': 'ᶱ',
- '/phon:obottomhalf': 'ᴗ', '/phon:obottomhalfmod': 'ᵕ', '/phon:oeturned':
- 'ᴔ', '/phon:omod': 'ᵒ', '/phon:oopenmod': 'ᵓ',
- '/phon:oopenretroflexhook': 'ᶗ', '/phon:oopensideways': 'ᴒ',
- '/phon:osideways': 'ᴑ', '/phon:ostrokesideways': 'ᴓ', '/phon:otophalf':
- 'ᴖ', '/phon:otophalfmod': 'ᵔ', '/phon:phimod': 'ᶲ',
- '/phon:pmiddletilde': 'ᵱ', '/phon:pmod': 'ᵖ', '/phon:ppalatalhook': 'ᶈ',
- '/phon:pstroke': 'ᵽ', '/phon:rfishmiddletilde': 'ᵳ',
- '/phon:rmiddletilde': 'ᵲ', '/phon:rpalatalhook': 'ᶉ',
- '/phon:rsubscript': 'ᵣ', '/phon:schwamod': 'ᵊ',
- '/phon:schwaretroflexhook': 'ᶕ', '/phon:shookmod': 'ᶳ',
- '/phon:smiddletilde': 'ᵴ', '/phon:spalatalhook': 'ᶊ',
- '/phon:spirantvoicedlaryngeal': 'ᴤ', '/phon:thetamod': 'ᶿ',
- '/phon:thstrike': 'ᵺ', '/phon:tmiddletilde': 'ᵵ', '/phon:tmod': 'ᵗ',
- '/phon:tpalatalhookmod': 'ᶵ', '/phon:ubarmod': 'ᶶ', '/phon:ue': 'ᵫ',
- '/phon:umod': 'ᵘ', '/phon:upsilonmod': 'ᶷ', '/phon:upsilonstroke': 'ᵿ',
- '/phon:uretroflexhook': 'ᶙ', '/phon:usideways': 'ᴝ',
- '/phon:usidewaysdieresised': 'ᴞ', '/phon:usidewaysmod': 'ᵙ',
- '/phon:usubscript': 'ᵤ', '/phon:vhookmod': 'ᶹ', '/phon:vmod': 'ᵛ',
- '/phon:vpalatalhook': 'ᶌ', '/phon:vsubscript': 'ᵥ', '/phon:vturnedmod':
- 'ᶺ', '/phon:xpalatalhook': 'ᶍ', '/phon:zcurlmod': 'ᶽ',
- '/phon:zmiddletilde': 'ᵶ', '/phon:zmod': 'ᶻ', '/phon:zpalatalhook': 'ᶎ',
- '/phon:zretroflexhookmod': 'ᶼ', '/phook': 'ƥ', '/phophanthai': 'พ',
- '/phophungthai': 'ผ', '/phosamphaothai': 'ภ', '/pi': 'π', '/pi.math':
- 'ϖ', '/piasutorusquare': '㌮', '/pick': '⛏', '/pidblstruck': 'ℼ',
- '/pieupacirclekorean': '㉳', '/pieupaparenkorean': '㈓',
- '/pieupcieuckorean': 'ㅶ', '/pieupcirclekorean': '㉥',
- '/pieupkiyeokkorean': 'ㅲ', '/pieupkorean': 'ㅂ', '/pieupparenkorean':
- '㈅', '/pieupsioskiyeokkorean': 'ㅴ', '/pieupsioskorean': 'ㅄ',
- '/pieupsiostikeutkorean': 'ㅵ', '/pieupthieuthkorean': 'ㅷ',
- '/pieuptikeutkorean': 'ㅳ', '/pig': 'ὁ6', '/pigFace': 'ὃ7', '/pigNose':
- 'ὃD', '/pihiragana': 'ぴ', '/pikatakana': 'ピ', '/pikosquare': '㌰',
- '/pikurusquare': '㌯', '/pilcrowsignreversed': '⁋', '/pileOfPoo': 'Ὂ9',
- '/pill': 'ὈA', '/pineDecoration': 'ἸD', '/pineapple': 'ἴD', '/pisces':
- '♓', '/piselehpada': '꧌', '/pistol': 'ὒB', '/pisymbolgreek': 'ϖ',
- '/pitchfork': '⋔', '/piwrarmenian': 'փ', '/placeOfWorship': 'Ὥ0',
- '/placeofinterestsign': '⌘', '/planck': 'ℎ', '/plancktwopi': 'ℏ',
- '/plus': '+', '/plus.inferior': '₊', '/plus.superior': '⁺',
- '/plusbelowcmb': '̟', '/pluscircle': '⊕', '/plusminus': '±', '/plusmod':
- '˖', '/plusmonospace': '+', '/plussignalt:hb': '﬩', '/plussignmod': '˖',
- '/plussmall': '﹢', '/plussuperior': '⁺', '/pluto': '♇', '/pmfullwidth':
- '㏘', '/pmonospace': 'p', '/pmsquare': '㏘', '/pocketCalculator':
- '\u1f5a9', '/poeticverse': '؎', '/pohiragana': 'ぽ', '/pointerleftblack':
- '◄', '/pointerleftwhite': '◅', '/pointerrightblack': '►',
- '/pointerrightwhite': '▻', '/pointingindexdownwhite': '☟',
- '/pointingindexleftblack': '☚', '/pointingindexleftwhite': '☜',
- '/pointingindexrightblack': '☛', '/pointingindexrightwhite': '☞',
- '/pointingindexupwhite': '☝', '/pointingtriangledownheavywhite': '⛛',
- '/pointosquare': '㌽', '/pointring': '⸰', '/pokatakana': 'ポ',
- '/pokrytiecmbcyr': '҇', '/policeCar': 'Ὡ3', '/policeCarsRevolvingLight':
- 'Ὢ8', '/policeOfficer': '\u1f46E', '/pondosquare': '㍀', '/poodle': 'ὂ9',
- '/popcorn': 'ἷF', '/popdirectionalformatting': '\u202c',
- '/popdirectionalisolate': '\u2069', '/poplathai': 'ป',
- '/portableStereo': '\u1f4fE', '/positionindicator': '⌖', '/postalHorn':
- '\u1f4eF', '/postalmark': '〒', '/postalmarkface': '〠', '/postbox':
- '\u1f4eE', '/potOfFood': 'ἷ2', '/potableWater': 'Ὣ0', '/pouch': 'ὅD',
- '/poultryLeg': 'ἵ7', '/poutingCatFace': 'ὣE', '/poutingFace': 'ὢ1',
- '/power': '⏻', '/poweron': '⏽', '/poweronoff': '⏼', '/powersleep': '⏾',
- '/pparen': '⒫', '/pparenthesized': '⒫', '/ppmfullwidth': '㏙',
- '/prayerBeads': '\u1f4fF', '/precedes': '≺',
- '/precedesbutnotequivalent': '⋨', '/precedesorequal': '≼',
- '/precedesorequivalent': '≾', '/precedesunderrelation': '⊰',
- '/prescription': '℞', '/preversedepigraphic': 'ꟼ', '/previouspage': '⎗',
- '/prfullwidth': '㏚', '/primedblmod': 'ʺ', '/primemod': 'ʹ',
- '/primereversed': '‵', '/princess': '\u1f478', '/printer': '\u1f5a8',
- '/printerIcon': 'Ὓ6', '/printideographiccircled': '㊞', '/printscreen':
- '⎙', '/product': '∏', '/prohibitedSign': 'Ὤ7', '/projective': '⌅',
- '/prolongedkana': 'ー', '/propellor': '⌘', '/propersubset': '⊂',
- '/propersuperset': '⊃', '/propertyline': '⅊', '/proportion': '∷',
- '/proportional': '∝', '/psfullwidth': '㎰', '/psi': 'ψ', '/psicyr': 'ѱ',
- '/psicyrillic': 'ѱ', '/psilicmbcyr': '҆', '/psilipneumatacyrilliccmb':
- '҆', '/pssquare': '㎰', '/pstrokedescender': 'ꝑ', '/ptail': 'ꝕ',
- '/publicAddressLoudspeaker': '\u1f4e2', '/puhiragana': 'ぷ',
- '/pukatakana': 'プ', '/punctuationspace': '\u2008', '/purpleHeart': 'ὉC',
- '/purse': 'ὅB', '/pushpin': 'ὌC', '/putLitterInItsPlace': 'ὪE',
- '/pvfullwidth': '㎴', '/pvsquare': '㎴', '/pwfullwidth': '㎺', '/pwsquare':
- '㎺', '/q': 'q', '/qacyr': 'ԛ', '/qadeva': 'क़', '/qadma:hb': '֨',
- '/qadmahebrew': '֨', '/qaf': 'ق', '/qaf.fina': 'ﻖ', '/qaf.init': 'ﻗ',
- '/qaf.init_alefmaksura.fina': 'ﰵ', '/qaf.init_hah.fina': 'ﰳ',
- '/qaf.init_hah.medi': 'ﳂ', '/qaf.init_meem.fina': 'ﰴ',
- '/qaf.init_meem.medi': 'ﳃ', '/qaf.init_meem.medi_hah.medi': 'ﶴ',
- '/qaf.init_yeh.fina': 'ﰶ', '/qaf.isol': 'ﻕ', '/qaf.medi': 'ﻘ',
- '/qaf.medi_alefmaksura.fina': 'ﱾ', '/qaf.medi_meem.medi_hah.fina': 'ﵾ',
- '/qaf.medi_meem.medi_meem.fina': 'ﵿ', '/qaf.medi_meem.medi_yeh.fina':
- 'ﶲ', '/qaf.medi_yeh.fina': 'ﱿ', '/qaf_lam_alefmaksuraabove': 'ۗ',
- '/qafarabic': 'ق', '/qafdotabove': 'ڧ', '/qaffinalarabic': 'ﻖ',
- '/qafinitialarabic': 'ﻗ', '/qafmedialarabic': 'ﻘ', '/qafthreedotsabove':
- 'ڨ', '/qamats': 'ָ', '/qamats10': 'ָ', '/qamats1a': 'ָ', '/qamats1c':
- 'ָ', '/qamats27': 'ָ', '/qamats29': 'ָ', '/qamats33': 'ָ', '/qamats:hb':
- 'ָ', '/qamatsQatan:hb': 'ׇ', '/qamatsde': 'ָ', '/qamatshebrew': 'ָ',
- '/qamatsnarrowhebrew': 'ָ', '/qamatsqatanhebrew': 'ָ',
- '/qamatsqatannarrowhebrew': 'ָ', '/qamatsqatanquarterhebrew': 'ָ',
- '/qamatsqatanwidehebrew': 'ָ', '/qamatsquarterhebrew': 'ָ',
- '/qamatswidehebrew': 'ָ', '/qarneFarah:hb': '֟', '/qarneyparahebrew':
- '֟', '/qbopomofo': 'ㄑ', '/qcircle': 'ⓠ', '/qdiagonalstroke': 'ꝙ',
- '/qhook': 'ʠ', '/qhooktail': 'ɋ', '/qmonospace': 'q', '/qof': 'ק',
- '/qof:hb': 'ק', '/qofdagesh': 'קּ', '/qofdageshhebrew': 'קּ',
- '/qofhatafpatah': 'ק', '/qofhatafpatahhebrew': 'ק', '/qofhatafsegol':
- 'ק', '/qofhatafsegolhebrew': 'ק', '/qofhebrew': 'ק', '/qofhiriq': 'ק',
- '/qofhiriqhebrew': 'ק', '/qofholam': 'ק', '/qofholamhebrew': 'ק',
- '/qofpatah': 'ק', '/qofpatahhebrew': 'ק', '/qofqamats': 'ק',
- '/qofqamatshebrew': 'ק', '/qofqubuts': 'ק', '/qofqubutshebrew': 'ק',
- '/qofsegol': 'ק', '/qofsegolhebrew': 'ק', '/qofsheva': 'ק',
- '/qofshevahebrew': 'ק', '/qoftsere': 'ק', '/qoftserehebrew': 'ק',
- '/qofwithdagesh:hb': 'קּ', '/qparen': '⒬', '/qparenthesized': '⒬',
- '/qpdigraph': 'ȹ', '/qstrokedescender': 'ꝗ', '/quadarrowdownfunc': '⍗',
- '/quadarrowleftfunc': '⍇', '/quadarrowrightfunc': '⍈',
- '/quadarrowupfunc': '⍐', '/quadbackslashfunc': '⍂',
- '/quadcaretdownfunc': '⍌', '/quadcaretupfunc': '⍓', '/quadcirclefunc':
- '⌼', '/quadcolonfunc': '⍠', '/quaddelfunc': '⍔', '/quaddeltafunc': '⍍',
- '/quaddiamondfunc': '⌺', '/quaddividefunc': '⌹', '/quadequalfunc': '⌸',
- '/quadfunc': '⎕', '/quadgreaterfunc': '⍄', '/quadjotfunc': '⌻',
- '/quadlessfunc': '⍃', '/quadnotequalfunc': '⍯', '/quadquestionfunc':
- '⍰', '/quadrantLowerLeft': '▖', '/quadrantLowerRight': '▗',
- '/quadrantUpperLeft': '▘',
- '/quadrantUpperLeftAndLowerLeftAndLowerRight': '▙',
- '/quadrantUpperLeftAndLowerRight': '▚',
- '/quadrantUpperLeftAndUpperRightAndLowerLeft': '▛',
- '/quadrantUpperLeftAndUpperRightAndLowerRight': '▜',
- '/quadrantUpperRight': '▝', '/quadrantUpperRightAndLowerLeft': '▞',
- '/quadrantUpperRightAndLowerLeftAndLowerRight': '▟', '/quadrupleminute':
- '⁗', '/quadslashfunc': '⍁', '/quarternote': '♩', '/qubuts': 'ֻ',
- '/qubuts18': 'ֻ', '/qubuts25': 'ֻ', '/qubuts31': 'ֻ', '/qubuts:hb': 'ֻ',
- '/qubutshebrew': 'ֻ', '/qubutsnarrowhebrew': 'ֻ',
- '/qubutsquarterhebrew': 'ֻ', '/qubutswidehebrew': 'ֻ', '/queenblack':
- '♛', '/queenwhite': '♕', '/question': '?', '/questionarabic': '؟',
- '/questionarmenian': '՞', '/questiondbl': '⁇', '/questiondown': '¿',
- '/questiondownsmall': '\uf7bf', '/questionedequal': '≟',
- '/questionexclamationmark': '⁈', '/questiongreek': ';',
- '/questionideographiccircled': '㉄', '/questionmonospace': '?',
- '/questionreversed': '⸮', '/questionsmall': '\uf73f', '/quincunx': '⚻',
- '/quotedbl': '"', '/quotedblbase': '„', '/quotedblleft': '“',
- '/quotedbllowreversed': '⹂', '/quotedblmonospace': '"',
- '/quotedblprime': '〞', '/quotedblprimereversed': '〝',
- '/quotedblreversed': '‟', '/quotedblright': '”', '/quoteleft': '‘',
- '/quoteleftreversed': '‛', '/quotequadfunc': '⍞', '/quotereversed': '‛',
- '/quoteright': '’', '/quoterightn': 'ʼn', '/quotesinglbase': '‚',
- '/quotesingle': "'", '/quotesinglemonospace': ''',
- '/quoteunderlinefunc': '⍘', '/r': 'r', '/raagung': 'ꦬ', '/raarmenian':
- 'ռ', '/rabbit': 'ὀ7', '/rabbitFace': 'ὃ0', '/rabengali': 'র',
- '/racingCar': 'ἼE', '/racingMotorcycle': 'ἼD', '/racirclekatakana': '㋶',
- '/racute': 'ŕ', '/radeva': 'र', '/radfullwidth': '㎭', '/radical': '√',
- '/radicalbottom': '⎷', '/radicalex': '\uf8e5', '/radio': '\u1f4fB',
- '/radioButton': 'ὑ8', '/radioactive': '☢', '/radovers2fullwidth': '㎯',
- '/radoversfullwidth': '㎮', '/radoverssquare': '㎮',
- '/radoverssquaredsquare': '㎯', '/radsquare': '㎭', '/rafe': 'ֿ',
- '/rafe:hb': 'ֿ', '/rafehebrew': 'ֿ', '/ragujarati': 'ર', '/ragurmukhi':
- 'ਰ', '/rahiragana': 'ら', '/railwayCar': 'Ὠ3', '/railwayTrack': 'Ὦ4',
- '/rain': '⛆', '/rainbow': 'ἰ8', '/raisedHandFingersSplayed': 'Ὑ0',
- '/raisedHandPartBetweenMiddleAndRingFingers': 'Ὑ6', '/raisedmcsign':
- '\u1f16A', '/raisedmdsign': '\u1f16B', '/rakatakana': 'ラ',
- '/rakatakanahalfwidth': 'ラ', '/ralowerdiagonalbengali': 'ৱ', '/ram':
- 'ὀF', '/ramiddlediagonalbengali': 'ৰ', '/ramshorn': 'ɤ', '/rat': 'ὀ0',
- '/ratio': '∶', '/ray': '؈', '/rbopomofo': 'ㄖ', '/rcaron': 'ř',
- '/rcedilla': 'ŗ', '/rcircle': 'ⓡ', '/rcommaaccent': 'ŗ', '/rdblgrave':
- 'ȑ', '/rdot': 'ṙ', '/rdotaccent': 'ṙ', '/rdotbelow': 'ṛ',
- '/rdotbelowmacron': 'ṝ', '/reachideographicparen': '㉃',
- '/recirclekatakana': '㋹', '/recreationalVehicle': 'Ὡ9',
- '/rectangleblack': '▬', '/rectangleverticalblack': '▮',
- '/rectangleverticalwhite': '▯', '/rectanglewhite': '▭',
- '/recycledpaper': '♼', '/recyclefiveplastics': '♷',
- '/recyclefourplastics': '♶', '/recyclegeneric': '♺',
- '/recycleoneplastics': '♳', '/recyclepartiallypaper': '♽',
- '/recyclesevenplastics': '♹', '/recyclesixplastics': '♸',
- '/recyclethreeplastics': '♵', '/recycletwoplastics': '♴',
- '/recycleuniversal': '♲', '/recycleuniversalblack': '♻', '/redApple':
- 'ἴE', '/redTriangleDOwn': 'ὓB', '/redTriangleUp': 'ὓA',
- '/referencemark': '※', '/reflexsubset': '⊆', '/reflexsuperset': '⊇',
- '/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': '®',
- '/registersans': '\uf8e8', '/registerserif': '\uf6da', '/reh.fina': 'ﺮ',
- '/reh.init_superscriptalef.fina': 'ﱜ', '/reh.isol': 'ﺭ',
- '/rehHamzaAbove': 'ݬ', '/rehSmallTahTwoDots': 'ݱ', '/rehStroke': 'ݛ',
- '/rehTwoDotsVerticallyAbove': 'ݫ', '/rehVabove': 'ڒ', '/rehVbelow': 'ڕ',
- '/reharabic': 'ر', '/reharmenian': 'ր', '/rehdotbelow': 'ڔ',
- '/rehdotbelowdotabove': 'ږ', '/rehfinalarabic': 'ﺮ',
- '/rehfourdotsabove': 'ڙ', '/rehinvertedV': 'ۯ', '/rehiragana': 'れ',
- '/rehring': 'ړ', '/rehtwodotsabove': 'ڗ', '/rehyehaleflamarabic': 'ر',
- '/rekatakana': 'レ', '/rekatakanahalfwidth': 'レ', '/relievedFace': 'ὠC',
- '/religionideographiccircled': '㊪', '/reminderRibbon': 'Ἱ7',
- '/remusquare': '㍕', '/rentogensquare': '㍖', '/replacementchar': '�',
- '/replacementcharobj': '', '/representideographicparen': '㈹',
- '/rerengganleft': '꧁', '/rerengganright': '꧂', '/resh': 'ר', '/resh:hb':
- 'ר', '/reshdageshhebrew': 'רּ', '/reshhatafpatah': 'ר',
- '/reshhatafpatahhebrew': 'ר', '/reshhatafsegol': 'ר',
- '/reshhatafsegolhebrew': 'ר', '/reshhebrew': 'ר', '/reshhiriq': 'ר',
- '/reshhiriqhebrew': 'ר', '/reshholam': 'ר', '/reshholamhebrew': 'ר',
- '/reshpatah': 'ר', '/reshpatahhebrew': 'ר', '/reshqamats': 'ר',
- '/reshqamatshebrew': 'ר', '/reshqubuts': 'ר', '/reshqubutshebrew': 'ר',
- '/reshsegol': 'ר', '/reshsegolhebrew': 'ר', '/reshsheva': 'ר',
- '/reshshevahebrew': 'ר', '/reshtsere': 'ר', '/reshtserehebrew': 'ר',
- '/reshwide:hb': 'ﬧ', '/reshwithdagesh:hb': 'רּ',
- '/resourceideographiccircled': '㊮', '/resourceideographicparen': '㈾',
- '/response': '℟', '/restideographiccircled': '㊡',
- '/restideographicparen': '㉁', '/restrictedentryoneleft': '⛠',
- '/restrictedentrytwoleft': '⛡', '/restroom': 'ὫB', '/return': '⏎',
- '/reversedHandMiddleFingerExtended': 'Ὑ5',
- '/reversedRaisedHandFingersSplayed': 'Ὑ1', '/reversedThumbsDownSign':
- 'Ὑ3', '/reversedThumbsUpSign': 'Ὑ2', '/reversedVictoryHand': 'Ὑ4',
- '/reversedonehundred.roman': 'Ↄ', '/reversedtilde': '∽',
- '/reversedzecyr': 'ԑ', '/revia:hb': '֗', '/reviahebrew': '֗',
- '/reviamugrashhebrew': '֗', '/revlogicalnot': '⌐', '/revolvingHearts':
- 'ὉE', '/rfishhook': 'ɾ', '/rfishhookreversed': 'ɿ', '/rgravedbl': 'ȑ',
- '/rhabengali': 'ঢ়', '/rhacyr': 'ԗ', '/rhadeva': 'ढ़', '/rho': 'ρ',
- '/rhoasper': 'ῥ', '/rhofunc': '⍴', '/rholenis': 'ῤ', '/rhook': 'ɽ',
- '/rhookturned': 'ɻ', '/rhookturnedsuperior': 'ʵ', '/rhookturnedsupmod':
- 'ʵ', '/rhostrokesymbol': 'ϼ', '/rhosymbol': 'ϱ', '/rhosymbolgreek': 'ϱ',
- '/rhotichookmod': '˞', '/rial': '﷼', '/ribbon': 'Ἰ0', '/riceBall': 'ἵ9',
- '/riceCracker': 'ἵ8', '/ricirclekatakana': '㋷', '/rieulacirclekorean':
- '㉱', '/rieulaparenkorean': '㈑', '/rieulcirclekorean': '㉣',
- '/rieulhieuhkorean': 'ㅀ', '/rieulkiyeokkorean': 'ㄺ',
- '/rieulkiyeoksioskorean': 'ㅩ', '/rieulkorean': 'ㄹ', '/rieulmieumkorean':
- 'ㄻ', '/rieulpansioskorean': 'ㅬ', '/rieulparenkorean': '㈃',
- '/rieulphieuphkorean': 'ㄿ', '/rieulpieupkorean': 'ㄼ',
- '/rieulpieupsioskorean': 'ㅫ', '/rieulsioskorean': 'ㄽ',
- '/rieulthieuthkorean': 'ㄾ', '/rieultikeutkorean': 'ㅪ',
- '/rieulyeorinhieuhkorean': 'ㅭ', '/right-pointingMagnifyingGlass': 'ὐE',
- '/rightAngerBubble': '\u1f5eF', '/rightHalfBlock': '▐',
- '/rightHandTelephoneReceiver': 'ὗD', '/rightOneEighthBlock': '▕',
- '/rightSpeaker': 'ὖ8', '/rightSpeakerOneSoundWave': 'ὖ9',
- '/rightSpeakerThreeSoundWaves': 'ὖA', '/rightSpeechBubble': '\u1f5e9',
- '/rightThoughtBubble': '\u1f5eD', '/rightangle': '∟',
- '/rightarrowoverleftarrow': '⇄', '/rightdnheavyleftuplight': '╆',
- '/rightharpoonoverleftharpoon': '⇌', '/rightheavyleftdnlight': '┮',
- '/rightheavyleftuplight': '┶', '/rightheavyleftvertlight': '┾',
- '/rightideographiccircled': '㊨', '/rightlightleftdnheavy': '┱',
- '/rightlightleftupheavy': '┹', '/rightlightleftvertheavy': '╉',
- '/righttackbelowcmb': '̙', '/righttoleftembed': '\u202b',
- '/righttoleftisolate': '\u2067', '/righttoleftmark': '\u200f',
- '/righttoleftoverride': '\u202e', '/righttriangle': '⊿',
- '/rightupheavyleftdnlight': '╄', '/rihiragana': 'り', '/rikatakana': 'リ',
- '/rikatakanahalfwidth': 'リ', '/ring': '˚', '/ringbelowcmb': '̥',
- '/ringcmb': '̊', '/ringequal': '≗', '/ringhalfleft': 'ʿ',
- '/ringhalfleftarmenian': 'ՙ', '/ringhalfleftbelowcmb': '̜',
- '/ringhalfleftcentered': '˓', '/ringhalfleftcentredmod': '˓',
- '/ringhalfleftmod': 'ʿ', '/ringhalfright': 'ʾ',
- '/ringhalfrightbelowcmb': '̹', '/ringhalfrightcentered': '˒',
- '/ringhalfrightcentredmod': '˒', '/ringhalfrightmod': 'ʾ',
- '/ringinequal': '≖', '/ringingBell': 'ὖD', '/ringlowmod': '˳',
- '/ringoperator': '∘', '/rinsular': 'ꞃ', '/rinvertedbreve': 'ȓ',
- '/rirasquare': '㍒', '/risingdiagonal': '⟋', '/rittorusquare': '㍑',
- '/rlinebelow': 'ṟ', '/rlongleg': 'ɼ', '/rlonglegturned': 'ɺ',
- '/rmacrondot': 'ṝ', '/rmonospace': 'r', '/rnoon': 'ڻ', '/rnoon.fina':
- 'ﮡ', '/rnoon.init': 'ﮢ', '/rnoon.isol': 'ﮠ', '/rnoon.medi': 'ﮣ',
- '/roastedSweetPotato': 'ἶ0', '/robliquestroke': 'ꞧ',
- '/rocirclekatakana': '㋺', '/rocket': 'Ὠ0', '/rohiragana': 'ろ',
- '/rokatakana': 'ロ', '/rokatakanahalfwidth': 'ロ', '/rolled-upNewspaper':
- 'ὝE', '/rollerCoaster': 'Ἲ2', '/rookblack': '♜', '/rookwhite': '♖',
- '/rooster': 'ὁ3', '/roruathai': 'ร', '/rose': 'ἳ9', '/rosette': 'Ἷ5',
- '/roundPushpin': 'ὌD', '/roundedzeroabove': '۟', '/rowboat': 'Ὢ3',
- '/rparen': '⒭', '/rparenthesized': '⒭', '/rrabengali': 'ড়', '/rradeva':
- 'ऱ', '/rragurmukhi': 'ੜ', '/rreh': 'ڑ', '/rreh.fina': 'ﮍ', '/rreh.isol':
- 'ﮌ', '/rreharabic': 'ڑ', '/rrehfinalarabic': 'ﮍ', '/rrotunda': 'ꝛ',
- '/rrvocalicbengali': 'ৠ', '/rrvocalicdeva': 'ॠ', '/rrvocalicgujarati':
- 'ૠ', '/rrvocalicvowelsignbengali': 'ৄ', '/rrvocalicvowelsigndeva': 'ॄ',
- '/rrvocalicvowelsigngujarati': 'ૄ', '/rstroke': 'ɍ', '/rsuperior':
- '\uf6f1', '/rsupmod': 'ʳ', '/rtailturned': 'ⱹ', '/rtblock': '▐',
- '/rturned': 'ɹ', '/rturnedsuperior': 'ʴ', '/rturnedsupmod': 'ʴ',
- '/ruble': '₽', '/rucirclekatakana': '㋸', '/rugbyFootball': 'Ἴ9',
- '/ruhiragana': 'る', '/rukatakana': 'ル', '/rukatakanahalfwidth': 'ル',
- '/rum': 'ꝵ', '/rumrotunda': 'ꝝ', '/runner': 'Ἴ3', '/runningShirtSash':
- 'ἻD', '/rupeemarkbengali': '৲', '/rupeesignbengali': '৳', '/rupiah':
- '\uf6dd', '/rupiisquare': '㍓', '/ruthai': 'ฤ', '/ruuburusquare': '㍔',
- '/rvocalicbengali': 'ঋ', '/rvocalicdeva': 'ऋ', '/rvocalicgujarati': 'ઋ',
- '/rvocalicvowelsignbengali': 'ৃ', '/rvocalicvowelsigndeva': 'ृ',
- '/rvocalicvowelsigngujarati': 'ૃ', '/s': 's', '/s.inferior': 'ₛ',
- '/s_t': 'st', '/sabengali': 'স', '/sacirclekatakana': '㋚', '/sacute':
- 'ś', '/sacutedotaccent': 'ṥ', '/sad': 'ص', '/sad.fina': 'ﺺ',
- '/sad.init': 'ﺻ', '/sad.init_alefmaksura.fina': 'ﴅ',
- '/sad.init_hah.fina': 'ﰠ', '/sad.init_hah.medi': 'ﲱ',
- '/sad.init_hah.medi_hah.medi': 'ﵥ', '/sad.init_khah.medi': 'ﲲ',
- '/sad.init_meem.fina': 'ﰡ', '/sad.init_meem.medi': 'ﲳ',
- '/sad.init_meem.medi_meem.medi': 'ﷅ', '/sad.init_reh.fina': 'ﴏ',
- '/sad.init_yeh.fina': 'ﴆ', '/sad.isol': 'ﺹ', '/sad.medi': 'ﺼ',
- '/sad.medi_alefmaksura.fina': 'ﴡ', '/sad.medi_hah.medi_hah.fina': 'ﵤ',
- '/sad.medi_hah.medi_yeh.fina': 'ﶩ', '/sad.medi_meem.medi_meem.fina':
- 'ﵦ', '/sad.medi_reh.fina': 'ﴫ', '/sad.medi_yeh.fina': 'ﴢ',
- '/sad_lam_alefmaksuraabove': 'ۖ', '/sadarabic': 'ص', '/sadeva': 'स',
- '/sadfinalarabic': 'ﺺ', '/sadinitialarabic': 'ﺻ', '/sadmedialarabic':
- 'ﺼ', '/sadthreedotsabove': 'ڞ', '/sadtwodotsbelow': 'ڝ', '/sagittarius':
- '♐', '/sagujarati': 'સ', '/sagurmukhi': 'ਸ', '/sahiragana': 'さ',
- '/saikurusquare': '㌟', '/sailboat': '⛵', '/sakatakana': 'サ',
- '/sakatakanahalfwidth': 'サ', '/sakeBottleAndCup': 'ἷ6',
- '/sallallahoualayhewasallamarabic': 'ﷺ', '/saltillo': 'ꞌ', '/saltire':
- '☓', '/samahaprana': 'ꦰ', '/samekh': 'ס', '/samekh:hb': 'ס',
- '/samekhdagesh': 'סּ', '/samekhdageshhebrew': 'סּ', '/samekhhebrew': 'ס',
- '/samekhwithdagesh:hb': 'סּ', '/sampi': 'ϡ', '/sampiarchaic': 'ͳ',
- '/samurda': 'ꦯ', '/samvat': '\u0604', '/san': 'ϻ', '/santiimusquare':
- '㌠', '/saraaathai': 'า', '/saraaethai': 'แ', '/saraaimaimalaithai': 'ไ',
- '/saraaimaimuanthai': 'ใ', '/saraamthai': 'ำ', '/saraathai': 'ะ',
- '/saraethai': 'เ', '/saraiileftthai': '\uf886', '/saraiithai': 'ี',
- '/saraileftthai': '\uf885', '/saraithai': 'ิ', '/saraothai': 'โ',
- '/saraueeleftthai': '\uf888', '/saraueethai': 'ื', '/saraueleftthai':
- '\uf887', '/sarauethai': 'ึ', '/sarauthai': 'ุ', '/sarauuthai': 'ู',
- '/satellite': 'Ὧ0', '/satelliteAntenna': '\u1f4e1', '/saturn': '♄',
- '/saxophone': 'Ἳ7', '/sbopomofo': 'ㄙ', '/scales': '⚖',
- '/scanninehorizontal': '⎽', '/scanonehorizontal': '⎺',
- '/scansevenhorizontal': '⎼', '/scanthreehorizontal': '⎻', '/scaron':
- 'š', '/scarondot': 'ṧ', '/scarondotaccent': 'ṧ', '/scedilla': 'ş',
- '/school': 'ἾB', '/schoolSatchel': 'Ἱ2', '/schoolideographiccircled':
- '㉆', '/schwa': 'ə', '/schwa.inferior': 'ₔ', '/schwacyr': 'ә',
- '/schwacyrillic': 'ә', '/schwadieresiscyr': 'ӛ',
- '/schwadieresiscyrillic': 'ӛ', '/schwahook': 'ɚ', '/scircle': 'ⓢ',
- '/scircumflex': 'ŝ', '/scommaaccent': 'ș', '/scooter': 'Ὧ4',
- '/scorpius': '♏', '/screen': 'Ὓ5', '/scroll': 'ὍC', '/scruple': '℈',
- '/sdot': 'ṡ', '/sdotaccent': 'ṡ', '/sdotbelow': 'ṣ',
- '/sdotbelowdotabove': 'ṩ', '/sdotbelowdotaccent': 'ṩ',
- '/seagullbelowcmb': '̼', '/seat': 'ὋA', '/secirclekatakana': '㋝',
- '/second': '″', '/secondreversed': '‶', '/secondscreensquare': 'ἙC',
- '/secondtonechinese': 'ˊ', '/secretideographiccircled': '㊙', '/section':
- '§', '/sectionsignhalftop': '⸹', '/sector': '⌔', '/seeNoEvilMonkey':
- 'ὤ8', '/seedling': 'ἳ1', '/seen': 'س', '/seen.fina': 'ﺲ', '/seen.init':
- 'ﺳ', '/seen.init_alefmaksura.fina': 'ﳻ', '/seen.init_hah.fina': 'ﰝ',
- '/seen.init_hah.medi': 'ﲮ', '/seen.init_hah.medi_jeem.medi': 'ﵜ',
- '/seen.init_heh.medi': 'ﴱ', '/seen.init_jeem.fina': 'ﰜ',
- '/seen.init_jeem.medi': 'ﲭ', '/seen.init_jeem.medi_hah.medi': 'ﵝ',
- '/seen.init_khah.fina': 'ﰞ', '/seen.init_khah.medi': 'ﲯ',
- '/seen.init_meem.fina': 'ﰟ', '/seen.init_meem.medi': 'ﲰ',
- '/seen.init_meem.medi_hah.medi': 'ﵠ', '/seen.init_meem.medi_jeem.medi':
- 'ﵡ', '/seen.init_meem.medi_meem.medi': 'ﵣ', '/seen.init_reh.fina': 'ﴎ',
- '/seen.init_yeh.fina': 'ﳼ', '/seen.isol': 'ﺱ', '/seen.medi': 'ﺴ',
- '/seen.medi_alefmaksura.fina': 'ﴗ', '/seen.medi_hah.medi': 'ﴵ',
- '/seen.medi_heh.medi': 'ﳨ', '/seen.medi_jeem.medi': 'ﴴ',
- '/seen.medi_jeem.medi_alefmaksura.fina': 'ﵞ', '/seen.medi_khah.medi':
- 'ﴶ', '/seen.medi_khah.medi_alefmaksura.fina': 'ﶨ',
- '/seen.medi_khah.medi_yeh.fina': 'ﷆ', '/seen.medi_meem.medi': 'ﳧ',
- '/seen.medi_meem.medi_hah.fina': 'ﵟ', '/seen.medi_meem.medi_meem.fina':
- 'ﵢ', '/seen.medi_reh.fina': 'ﴪ', '/seen.medi_yeh.fina': 'ﴘ',
- '/seenDigitFourAbove': 'ݽ', '/seenFourDotsAbove': 'ݜ', '/seenInvertedV':
- 'ݾ', '/seenSmallTahTwoDots': 'ݰ', '/seenTwoDotsVerticallyAbove': 'ݭ',
- '/seenabove': 'ۜ', '/seenarabic': 'س', '/seendotbelowdotabove': 'ښ',
- '/seenfinalarabic': 'ﺲ', '/seeninitialarabic': 'ﺳ', '/seenlow': 'ۣ',
- '/seenmedialarabic': 'ﺴ', '/seenthreedotsbelow': 'ڛ',
- '/seenthreedotsbelowthreedotsabove': 'ڜ', '/segment': '⌓', '/segol':
- 'ֶ', '/segol13': 'ֶ', '/segol1f': 'ֶ', '/segol2c': 'ֶ', '/segol:hb':
- 'ֶ', '/segolhebrew': 'ֶ', '/segolnarrowhebrew': 'ֶ',
- '/segolquarterhebrew': 'ֶ', '/segolta:hb': '֒', '/segoltahebrew': '֒',
- '/segolwidehebrew': 'ֶ', '/seharmenian': 'ս', '/sehiragana': 'せ',
- '/sekatakana': 'セ', '/sekatakanahalfwidth': 'セ',
- '/selfideographicparen': '㉂', '/semicolon': ';', '/semicolonarabic':
- '؛', '/semicolonmonospace': ';', '/semicolonreversed': '⁏',
- '/semicolonsmall': '﹔', '/semicolonunderlinefunc': '⍮',
- '/semidirectproductleft': '⋋', '/semidirectproductright': '⋌',
- '/semisextile': '⚺', '/semisoftcyr': 'ҍ', '/semivoicedmarkkana': '゜',
- '/semivoicedmarkkanahalfwidth': '゚', '/sentisquare': '㌢',
- '/sentosquare': '㌣', '/septembertelegraph': '㋈', '/sersetdblup': '⋑',
- '/sersetnotequalup': '⊋', '/servicemark': '℠', '/sesamedot': '﹅',
- '/sesquiquadrate': '⚼', '/setminus': '∖', '/seven': '7',
- '/seven.inferior': '₇', '/seven.roman': 'Ⅶ', '/seven.romansmall': 'ⅶ',
- '/seven.superior': '⁷', '/sevenarabic': '٧', '/sevenbengali': '৭',
- '/sevencircle': '⑦', '/sevencircledbl': '⓻',
- '/sevencircleinversesansserif': '➐', '/sevencomma': 'ἐ8', '/sevendeva':
- '७', '/seveneighths': '⅞', '/sevenfar': '۷', '/sevengujarati': '૭',
- '/sevengurmukhi': '੭', '/sevenhackarabic': '٧', '/sevenhangzhou': '〧',
- '/sevenideographiccircled': '㊆', '/sevenideographicparen': '㈦',
- '/seveninferior': '₇', '/sevenmonospace': '7', '/sevenoldstyle':
- '\uf737', '/sevenparen': '⑺', '/sevenparenthesized': '⑺',
- '/sevenperiod': '⒎', '/sevenpersian': '۷', '/sevenpointonesquare': 'Ἒ1',
- '/sevenroman': 'ⅶ', '/sevensuperior': '⁷', '/seventeencircle': '⑰',
- '/seventeencircleblack': '⓱', '/seventeenparen': '⒄',
- '/seventeenparenthesized': '⒄', '/seventeenperiod': '⒘', '/seventhai':
- '๗', '/seventycirclesquare': '㉎', '/sextile': '⚹', '/sfthyphen': '\xad',
- '/shaarmenian': 'շ', '/shabengali': 'শ', '/shacyr': 'ш', '/shacyrillic':
- 'ш', '/shaddaAlefIsol': 'ﱣ', '/shaddaDammaIsol': 'ﱡ',
- '/shaddaDammaMedi': 'ﳳ', '/shaddaDammatanIsol': 'ﱞ', '/shaddaFathaIsol':
- 'ﱠ', '/shaddaFathaMedi': 'ﳲ', '/shaddaIsol': 'ﹼ', '/shaddaKasraIsol':
- 'ﱢ', '/shaddaKasraMedi': 'ﳴ', '/shaddaKasratanIsol': 'ﱟ', '/shaddaMedi':
- 'ﹽ', '/shaddaarabic': 'ّ', '/shaddadammaarabic': 'ﱡ',
- '/shaddadammatanarabic': 'ﱞ', '/shaddafathaarabic': 'ﱠ',
- '/shaddafathatanarabic': 'ّ', '/shaddakasraarabic': 'ﱢ',
- '/shaddakasratanarabic': 'ﱟ', '/shade': '▒', '/shadedark': '▓',
- '/shadelight': '░', '/shademedium': '▒', '/shadeva': 'श',
- '/shagujarati': 'શ', '/shagurmukhi': 'ਸ਼', '/shalshelet:hb': '֓',
- '/shalshelethebrew': '֓', '/shamrock': '☘', '/shavedIce': 'ἶ7',
- '/shbopomofo': 'ㄕ', '/shchacyr': 'щ', '/shchacyrillic': 'щ', '/sheen':
- 'ش', '/sheen.fina': 'ﺶ', '/sheen.init': 'ﺷ',
- '/sheen.init_alefmaksura.fina': 'ﳽ', '/sheen.init_hah.fina': 'ﴊ',
- '/sheen.init_hah.medi': 'ﴮ', '/sheen.init_hah.medi_meem.medi': 'ﵨ',
- '/sheen.init_heh.medi': 'ﴲ', '/sheen.init_jeem.fina': 'ﴉ',
- '/sheen.init_jeem.medi': 'ﴭ', '/sheen.init_khah.fina': 'ﴋ',
- '/sheen.init_khah.medi': 'ﴯ', '/sheen.init_meem.fina': 'ﴌ',
- '/sheen.init_meem.medi': 'ﴰ', '/sheen.init_meem.medi_khah.medi': 'ﵫ',
- '/sheen.init_meem.medi_meem.medi': 'ﵭ', '/sheen.init_reh.fina': 'ﴍ',
- '/sheen.init_yeh.fina': 'ﳾ', '/sheen.isol': 'ﺵ', '/sheen.medi': 'ﺸ',
- '/sheen.medi_alefmaksura.fina': 'ﴙ', '/sheen.medi_hah.fina': 'ﴦ',
- '/sheen.medi_hah.medi': 'ﴸ', '/sheen.medi_hah.medi_meem.fina': 'ﵧ',
- '/sheen.medi_hah.medi_yeh.fina': 'ﶪ', '/sheen.medi_heh.medi': 'ﳪ',
- '/sheen.medi_jeem.fina': 'ﴥ', '/sheen.medi_jeem.medi': 'ﴷ',
- '/sheen.medi_jeem.medi_yeh.fina': 'ﵩ', '/sheen.medi_khah.fina': 'ﴧ',
- '/sheen.medi_khah.medi': 'ﴹ', '/sheen.medi_meem.fina': 'ﴨ',
- '/sheen.medi_meem.medi': 'ﳩ', '/sheen.medi_meem.medi_khah.fina': 'ﵪ',
- '/sheen.medi_meem.medi_meem.fina': 'ﵬ', '/sheen.medi_reh.fina': 'ﴩ',
- '/sheen.medi_yeh.fina': 'ﴚ', '/sheenarabic': 'ش', '/sheendotbelow': 'ۺ',
- '/sheenfinalarabic': 'ﺶ', '/sheeninitialarabic': 'ﺷ',
- '/sheenmedialarabic': 'ﺸ', '/sheep': 'ὁ1', '/sheicoptic': 'ϣ',
- '/shelfmod': '˽', '/shelfopenmod': '˾', '/sheqel': '₪', '/sheqelhebrew':
- '₪', '/sheva': 'ְ', '/sheva115': 'ְ', '/sheva15': 'ְ', '/sheva22': 'ְ',
- '/sheva2e': 'ְ', '/sheva:hb': 'ְ', '/shevahebrew': 'ְ',
- '/shevanarrowhebrew': 'ְ', '/shevaquarterhebrew': 'ְ',
- '/shevawidehebrew': 'ְ', '/shhacyr': 'һ', '/shhacyrillic': 'һ',
- '/shhatailcyr': 'ԧ', '/shield': 'Ὦ1', '/shimacoptic': 'ϭ', '/shin': 'ש',
- '/shin:hb': 'ש', '/shinDot:hb': 'ׁ', '/shindagesh': 'שּ',
- '/shindageshhebrew': 'שּ', '/shindageshshindot': 'שּׁ',
- '/shindageshshindothebrew': 'שּׁ', '/shindageshsindot': 'שּׂ',
- '/shindageshsindothebrew': 'שּׂ', '/shindothebrew': 'ׁ', '/shinhebrew':
- 'ש', '/shinshindot': 'שׁ', '/shinshindothebrew': 'שׁ', '/shinsindot': 'שׂ',
- '/shinsindothebrew': 'שׂ', '/shintoshrine': '⛩', '/shinwithdagesh:hb':
- 'שּ', '/shinwithdageshandshinDot:hb': 'שּׁ', '/shinwithdageshandsinDot:hb':
- 'שּׂ', '/shinwithshinDot:hb': 'שׁ', '/shinwithsinDot:hb': 'שׂ', '/ship':
- 'Ὢ2', '/sho': 'ϸ', '/shoejotupfunc': '⍝', '/shoestiledownfunc': '⍦',
- '/shoestileleftfunc': '⍧', '/shogipieceblack': '☗', '/shogipiecewhite':
- '☖', '/shook': 'ʂ', '/shootingStar': 'ἲ0', '/shoppingBags': 'ὬD',
- '/shoppingTrolley': 'Ὥ2', '/shortcake': 'ἷ0', '/shortequalsmod': '꞊',
- '/shortoverlongmetrical': '⏓', '/shoulderedopenbox': '⍽', '/shower':
- 'ὫF', '/shvsquare': 'ἚA', '/sicirclekatakana': '㋛',
- '/sidewaysBlackDownPointingIndex': '\u1f5a1',
- '/sidewaysBlackLeftPointingIndex': 'ὙA',
- '/sidewaysBlackRightPointingIndex': 'ὙB',
- '/sidewaysBlackUpPointingIndex': '\u1f5a0',
- '/sidewaysWhiteDownPointingIndex': 'ὙF',
- '/sidewaysWhiteLeftPointingIndex': 'Ὑ8',
- '/sidewaysWhiteRightPointingIndex': 'Ὑ9',
- '/sidewaysWhiteUpPointingIndex': 'ὙE', '/sigma': 'σ', '/sigma1': 'ς',
- '/sigmafinal': 'ς', '/sigmalunatedottedreversedsymbol': 'ͽ',
- '/sigmalunatedottedsymbol': 'ͼ', '/sigmalunatereversedsymbol': 'ͻ',
- '/sigmalunatesymbol': 'ϲ', '/sigmalunatesymbolgreek': 'ϲ',
- '/sihiragana': 'し', '/sikatakana': 'シ', '/sikatakanahalfwidth': 'シ',
- '/silhouetteOfJapan': 'ὟE', '/siluqhebrew': 'ֽ', '/siluqlefthebrew':
- 'ֽ', '/similar': '∼', '/sinDot:hb': 'ׂ', '/sindothebrew': 'ׂ',
- '/sinewave': '∿', '/sinh:a': 'අ', '/sinh:aa': 'ආ', '/sinh:aae': 'ඈ',
- '/sinh:aaesign': 'ෑ', '/sinh:aasign': 'ා', '/sinh:ae': 'ඇ',
- '/sinh:aesign': 'ැ', '/sinh:ai': 'ඓ', '/sinh:aisign': 'ෛ',
- '/sinh:anusvara': 'ං', '/sinh:au': 'ඖ', '/sinh:ausign': 'ෞ', '/sinh:ba':
- 'බ', '/sinh:bha': 'භ', '/sinh:ca': 'ච', '/sinh:cha': 'ඡ', '/sinh:da':
- 'ද', '/sinh:dda': 'ඩ', '/sinh:ddha': 'ඪ', '/sinh:dha': 'ධ', '/sinh:e':
- 'එ', '/sinh:ee': 'ඒ', '/sinh:eesign': 'ේ', '/sinh:esign': 'ෙ',
- '/sinh:fa': 'ෆ', '/sinh:ga': 'ග', '/sinh:gha': 'ඝ', '/sinh:ha': 'හ',
- '/sinh:i': 'ඉ', '/sinh:ii': 'ඊ', '/sinh:iisign': 'ී', '/sinh:isign':
- 'ි', '/sinh:ja': 'ජ', '/sinh:jha': 'ඣ', '/sinh:jnya': 'ඥ', '/sinh:ka':
- 'ක', '/sinh:kha': 'ඛ', '/sinh:kunddaliya': '෴', '/sinh:la': 'ල',
- '/sinh:litheight': '෮', '/sinh:lithfive': '෫', '/sinh:lithfour': '෪',
- '/sinh:lithnine': '෯', '/sinh:lithone': '෧', '/sinh:lithseven': '෭',
- '/sinh:lithsix': '෬', '/sinh:liththree': '෩', '/sinh:lithtwo': '෨',
- '/sinh:lithzero': '෦', '/sinh:lla': 'ළ', '/sinh:llvocal': 'ඐ',
- '/sinh:llvocalsign': 'ෳ', '/sinh:lvocal': 'ඏ', '/sinh:lvocalsign': 'ෟ',
- '/sinh:ma': 'ම', '/sinh:mba': 'ඹ', '/sinh:na': 'න', '/sinh:nda': 'ඳ',
- '/sinh:nga': 'ඞ', '/sinh:nna': 'ණ', '/sinh:nndda': 'ඬ', '/sinh:nnga':
- 'ඟ', '/sinh:nya': 'ඤ', '/sinh:nyja': 'ඦ', '/sinh:o': 'ඔ', '/sinh:oo':
- 'ඕ', '/sinh:oosign': 'ෝ', '/sinh:osign': 'ො', '/sinh:pa': 'ප',
- '/sinh:pha': 'ඵ', '/sinh:ra': 'ර', '/sinh:rrvocal': 'ඎ',
- '/sinh:rrvocalsign': 'ෲ', '/sinh:rvocal': 'ඍ', '/sinh:rvocalsign': 'ෘ',
- '/sinh:sa': 'ස', '/sinh:sha': 'ශ', '/sinh:ssa': 'ෂ', '/sinh:ta': 'ත',
- '/sinh:tha': 'ථ', '/sinh:tta': 'ට', '/sinh:ttha': 'ඨ', '/sinh:u': 'උ',
- '/sinh:usign': 'ු', '/sinh:uu': 'ඌ', '/sinh:uusign': 'ූ', '/sinh:va':
- 'ව', '/sinh:virama': '්', '/sinh:visarga': 'ඃ', '/sinh:ya': 'ය',
- '/sinologicaldot': 'ꞏ', '/sinsular': 'ꞅ', '/siosacirclekorean': '㉴',
- '/siosaparenkorean': '㈔', '/sioscieuckorean': 'ㅾ', '/sioscirclekorean':
- '㉦', '/sioskiyeokkorean': 'ㅺ', '/sioskorean': 'ㅅ', '/siosnieunkorean':
- 'ㅻ', '/siosparenkorean': '㈆', '/siospieupkorean': 'ㅽ',
- '/siostikeutkorean': 'ㅼ', '/siringusquare': '㌡', '/six': '6',
- '/six.inferior': '₆', '/six.roman': 'Ⅵ', '/six.romansmall': 'ⅵ',
- '/six.superior': '⁶', '/sixPointedStarMiddleDot': 'ὒF', '/sixarabic':
- '٦', '/sixbengali': '৬', '/sixcircle': '⑥', '/sixcircledbl': '⓺',
- '/sixcircleinversesansserif': '➏', '/sixcomma': 'ἐ7', '/sixdeva': '६',
- '/sixdotsvertical': '⸽', '/sixfar': '۶', '/sixgujarati': '૬',
- '/sixgurmukhi': '੬', '/sixhackarabic': '٦', '/sixhangzhou': '〦',
- '/sixideographiccircled': '㊅', '/sixideographicparen': '㈥',
- '/sixinferior': '₆', '/sixlateform.roman': 'ↅ', '/sixmonospace': '6',
- '/sixoldstyle': '\uf736', '/sixparen': '⑹', '/sixparenthesized': '⑹',
- '/sixperemspace': '\u2006', '/sixperiod': '⒍', '/sixpersian': '۶',
- '/sixroman': 'ⅵ', '/sixsuperior': '⁶', '/sixteencircle': '⑯',
- '/sixteencircleblack': '⓰', '/sixteencurrencydenominatorbengali': '৹',
- '/sixteenparen': '⒃', '/sixteenparenthesized': '⒃', '/sixteenperiod':
- '⒗', '/sixthai': '๖', '/sixtycirclesquare': '㉍', '/sixtypsquare': 'Ἒ3',
- '/sjekomicyr': 'ԍ', '/skiAndSkiBoot': 'ἻF', '/skier': '⛷', '/skull':
- 'Ὀ0', '/skullcrossbones': '☠', '/slash': '/', '/slashbarfunc': '⌿',
- '/slashmonospace': '/', '/sled': 'Ὧ7', '/sleeping': 'Ὂ4',
- '/sleepingAccommodation': 'ὬC', '/sleepingFace': 'ὣ4', '/sleepyFace':
- 'ὢA', '/sleuthOrSpy': 'ὗ5', '/sliceOfPizza': 'ἵ5',
- '/slightlyFrowningFace': 'ὤ1', '/slightlySmilingFace': 'ὤ2', '/slong':
- 'ſ', '/slongdotaccent': 'ẛ', '/slope': '⌳', '/slotMachine': 'Ἳ0',
- '/smallAirplane': 'Ὦ9', '/smallBlueDiamond': 'ὓ9',
- '/smallOrangeDiamond': 'ὓ8', '/smallRedTriangleDOwn': 'ὓD',
- '/smallRedTriangleUp': 'ὓC', '/smile': '⌣', '/smileface': '☺',
- '/smilingCatFaceWithHeartShapedEyes': 'ὣB',
- '/smilingCatFaceWithOpenMouth': 'ὣA', '/smilingFaceWithHalo': 'ὠ7',
- '/smilingFaceWithHeartShapedEyes': 'ὠD', '/smilingFaceWithHorns': 'ὠ8',
- '/smilingFaceWithOpenMouth': 'ὠ3',
- '/smilingFaceWithOpenMouthAndColdSweat': 'ὠ5',
- '/smilingFaceWithOpenMouthAndSmilingEyes': 'ὠ4',
- '/smilingFaceWithOpenMouthAndTightlyClosedEyes': 'ὠ6',
- '/smilingFaceWithSmilingEyes': 'ὠA', '/smilingFaceWithSunglasses': 'ὠE',
- '/smilingfaceblack': '☻', '/smilingfacewhite': '☺', '/smirkingFace':
- 'ὠF', '/smll:ampersand': '﹠', '/smll:asterisk': '﹡', '/smll:backslash':
- '﹨', '/smll:braceleft': '﹛', '/smll:braceright': '﹜', '/smll:colon':
- '﹕', '/smll:comma': '﹐', '/smll:dollar': '﹩', '/smll:emdash': '﹘',
- '/smll:equal': '﹦', '/smll:exclam': '﹗', '/smll:greater': '﹥',
- '/smll:hyphen': '﹣', '/smll:ideographiccomma': '﹑', '/smll:less': '﹤',
- '/smll:numbersign': '﹟', '/smll:parenthesisleft': '﹙',
- '/smll:parenthesisright': '﹚', '/smll:percent': '﹪', '/smll:period':
- '﹒', '/smll:plus': '﹢', '/smll:question': '﹖', '/smll:semicolon': '﹔',
- '/smll:tortoiseshellbracketleft': '﹝',
- '/smll:tortoiseshellbracketright': '﹞', '/smoking': 'ὪC', '/smonospace':
- 's', '/snail': 'ὀC', '/snake': 'ὀD', '/snowboarder': 'Ἴ2',
- '/snowcappedMountain': 'Ἵ4', '/snowman': '☃', '/snowmanblack': '⛇',
- '/snowmanoutsnow': '⛄', '/sobliquestroke': 'ꞩ', '/soccerball': '⚽',
- '/societyideographiccircled': '㊓', '/societyideographicparen': '㈳',
- '/socirclekatakana': '㋞', '/sofPasuq:hb': '׃', '/sofpasuqhebrew': '׃',
- '/softIceCream': 'ἶ6', '/softShellFloppyDisk': '\u1f5aC', '/softcyr':
- 'ь', '/softhyphen': '\xad', '/softsigncyrillic': 'ь',
- '/softwarefunction': '⎔', '/sohiragana': 'そ', '/sokatakana': 'ソ',
- '/sokatakanahalfwidth': 'ソ', '/soliduslongoverlaycmb': '̸',
- '/solidusshortoverlaycmb': '̷', '/solidussubsetreversepreceding': '⟈',
- '/solidussupersetpreceding': '⟉', '/soonRightwardsArrowAbove': 'ὑC',
- '/sorusithai': 'ษ', '/sosalathai': 'ศ', '/sosothai': 'ซ', '/sossquare':
- 'Ἑ8', '/sosuathai': 'ส', '/soundcopyright': '℗', '/space': ' ',
- '/spacehackarabic': ' ', '/spade': '♠', '/spadeblack': '♠',
- '/spadesuitblack': '♠', '/spadesuitwhite': '♤', '/spadewhite': '♤',
- '/spaghetti': 'ἵD', '/sparen': '⒮', '/sparenthesized': '⒮',
- '/sparklingHeart': 'Ὁ6', '/speakNoEvilMonkey': 'ὤA', '/speaker': 'ὐ8',
- '/speakerCancellationStroke': 'ὐ7', '/speakerOneSoundWave': 'ὐ9',
- '/speakerThreeSoundWaves': 'ὐA', '/speakingHeadInSilhouette': '\u1f5e3',
- '/specialideographiccircled': '㊕', '/specialideographicparen': '㈵',
- '/speechBalloon': 'ὊC', '/speedboat': 'Ὢ4', '/spesmilo': '₷',
- '/sphericalangle': '∢', '/spider': 'ὗ7', '/spiderWeb': 'ὗ8',
- '/spiralCalendarPad': 'Ὕ3', '/spiralNotePad': 'Ὕ2', '/spiralShell':
- 'ὁA', '/splashingSweat': 'Ὂ6', '/sportsMedal': 'Ἴ5', '/spoutingWhale':
- 'ὃ3', '/sppl:tildevertical': 'ⸯ', '/squarebelowcmb': '̻',
- '/squareblack': '■', '/squarebracketleftvertical': '﹇',
- '/squarebracketrightvertical': '﹈', '/squarecap': '⊓', '/squarecc': '㏄',
- '/squarecm': '㎝', '/squarecup': '⊔', '/squareddotoperator': '⊡',
- '/squarediagonalcrosshatchfill': '▩', '/squaredj': 'Ἑ0', '/squaredkey':
- '⚿', '/squaredminus': '⊟', '/squaredplus': '⊞', '/squaredsaltire': '⛝',
- '/squaredtimes': '⊠', '/squarefourcorners': '⛶', '/squarehalfleftblack':
- '◧', '/squarehalfrightblack': '◨', '/squarehorizontalfill': '▤',
- '/squareimage': '⊏', '/squareimageorequal': '⊑',
- '/squareimageornotequal': '⋤', '/squarekg': '㎏', '/squarekm': '㎞',
- '/squarekmcapital': '㏎', '/squareln': '㏑', '/squarelog': '㏒',
- '/squarelowerdiagonalhalfrightblack': '◪', '/squaremediumblack': '◼',
- '/squaremediumwhite': '◻', '/squaremg': '㎎', '/squaremil': '㏕',
- '/squaremm': '㎜', '/squaremsquared': '㎡', '/squareoriginal': '⊐',
- '/squareoriginalorequal': '⊒', '/squareoriginalornotequal': '⋥',
- '/squareorthogonalcrosshatchfill': '▦', '/squareraised': '⸋',
- '/squaresmallblack': '▪', '/squaresmallmediumblack': '◾',
- '/squaresmallmediumwhite': '◽', '/squaresmallwhite': '▫',
- '/squareupperdiagonalhalfleftblack': '◩',
- '/squareupperlefttolowerrightfill': '▧',
- '/squareupperrighttolowerleftfill': '▨', '/squareverticalfill': '▥',
- '/squarewhite': '□', '/squarewhitebisectinglinevertical': '◫',
- '/squarewhitelowerquadrantleft': '◱', '/squarewhitelowerquadrantright':
- '◲', '/squarewhiteround': '▢', '/squarewhiteupperquadrantleft': '◰',
- '/squarewhiteupperquadrantright': '◳', '/squarewhitewithsmallblack':
- '▣', '/squarewhitewithsquaresmallblack': '▣', '/squishquadfunc': '⌷',
- '/srfullwidth': '㏛', '/srsquare': '㏛', '/ssabengali': 'ষ', '/ssadeva':
- 'ष', '/ssagujarati': 'ષ', '/ssangcieuckorean': 'ㅉ', '/ssanghieuhkorean':
- 'ㆅ', '/ssangieungkorean': 'ㆀ', '/ssangkiyeokkorean': 'ㄲ',
- '/ssangnieunkorean': 'ㅥ', '/ssangpieupkorean': 'ㅃ', '/ssangsioskorean':
- 'ㅆ', '/ssangtikeutkorean': 'ㄸ', '/ssuperior': '\uf6f2', '/ssupmod': 'ˢ',
- '/sswashtail': 'ȿ', '/stackedcommadbl': '⹉', '/stadium': 'ἽF',
- '/staffofaesculapius': '⚕', '/staffofhermes': '⚚', '/stampedEnvelope':
- '\u1f583', '/star': '⋆', '/starblack': '★', '/starcrescent': '☪',
- '/stardiaeresisfunc': '⍣', '/starequals': '≛', '/staroperator': '⋆',
- '/staroutlinedwhite': '⚝', '/starwhite': '☆', '/station': 'Ὠ9',
- '/statueOfLiberty': 'ὟD', '/steamLocomotive': 'Ὠ2', '/steamingBowl':
- 'ἵC', '/stenographicfullstop': '⸼', '/sterling': '£',
- '/sterlingmonospace': '£', '/stigma': 'ϛ', '/stiletildefunc': '⍭',
- '/stockChart': '\u1f5e0', '/stockideographiccircled': '㊑',
- '/stockideographicparen': '㈱', '/stopabove': '۫', '/stopbelow': '۪',
- '/straightRuler': 'ὌF', '/straightness': '⏤', '/strawberry': 'ἵ3',
- '/stresslowtonemod': '꜡', '/stresstonemod': '꜠', '/strictlyequivalent':
- '≣', '/strokelongoverlaycmb': '̶', '/strokeshortoverlaycmb': '̵',
- '/studioMicrophone': 'Ἱ9', '/studyideographiccircled': '㊫',
- '/studyideographicparen': '㈻', '/stupa': 'Ὥ3', '/subscriptalef': 'ٖ',
- '/subset': '⊂', '/subsetdbl': '⋐', '/subsetnotequal': '⊊',
- '/subsetorequal': '⊆', '/succeeds': '≻', '/succeedsbutnotequivalent':
- '⋩', '/succeedsorequal': '≽', '/succeedsorequivalent': '≿',
- '/succeedsunderrelation': '⊱', '/suchthat': '∋', '/sucirclekatakana':
- '㋜', '/suhiragana': 'す', '/suitableideographiccircled': '㊜',
- '/sukatakana': 'ス', '/sukatakanahalfwidth': 'ス', '/sukumendutvowel':
- 'ꦹ', '/sukunIsol': 'ﹾ', '/sukunMedi': 'ﹿ', '/sukunarabic': 'ْ',
- '/sukuvowel': 'ꦸ', '/summation': '∑', '/summationbottom': '⎳',
- '/summationdblstruck': '⅀', '/summationtop': '⎲', '/sun': '☼',
- '/sunFace': 'ἱE', '/sunbehindcloud': '⛅', '/sunflower': 'ἳB',
- '/sunideographiccircled': '㊐', '/sunideographicparen': '㈰',
- '/sunraysblack': '☀', '/sunrayswhite': '☼', '/sunrise': 'ἰ5',
- '/sunriseOverMountains': 'ἰ4', '/sunsetOverBuildings': 'ἰ7',
- '/superset': '⊃', '/supersetnotequal': '⊋', '/supersetorequal': '⊇',
- '/superviseideographiccircled': '㊬', '/superviseideographicparen': '㈼',
- '/surfer': 'Ἴ4', '/sushi': 'ἶ3', '/suspensionRailway': 'ὩF',
- '/suspensiondbl': '⹄', '/svfullwidth': '㏜', '/svsquare': '㏜',
- '/swatchtop': '⏱', '/swimmer': 'ἼA', '/swungdash': '⁓',
- '/symbolabovethreedotsabove': '﮶', '/symbolbelowthreedotsabove': '﮷',
- '/symboldotabove': '﮲', '/symboldotbelow': '﮳',
- '/symboldoubleverticalbarbelow': '﮼', '/symbolfourdotsabove': '﮺',
- '/symbolfourdotsbelow': '﮻', '/symbolpointingabovedownthreedotsabove':
- '﮸', '/symbolpointingbelowdownthreedotsabove': '﮹', '/symbolring': '﮿',
- '/symboltahabovesmall': '﯀', '/symboltahbelowsmall': '﯁',
- '/symboltwodotsabove': '﮴', '/symboltwodotsbelow': '﮵',
- '/symboltwodotsverticallyabove': '﮽', '/symboltwodotsverticallybelow':
- '﮾', '/symmetry': '⌯', '/synagogue': 'ὔD', '/syouwaerasquare': '㍼',
- '/syringe': 'Ὀ9', '/t': 't', '/t-shirt': 'ὅ5', '/t.inferior': 'ₜ',
- '/tabengali': 'ত', '/tableTennisPaddleAndBall': 'Ἵ3',
- '/tacirclekatakana': '㋟', '/tackcircleaboveup': '⟟',
- '/tackdiaeresisupfunc': '⍡', '/tackdown': '⊤', '/tackdownmod': '˕',
- '/tackjotdownfunc': '⍎', '/tackjotupfunc': '⍕', '/tackleft': '⊣',
- '/tackleftright': '⟛', '/tackoverbarupfunc': '⍑', '/tackright': '⊢',
- '/tackunderlinedownfunc': '⍊', '/tackup': '⊥', '/tackupmod': '˔',
- '/taco': 'ἲE', '/tadeva': 'त', '/tagujarati': 'ત', '/tagurmukhi': 'ਤ',
- '/tah': 'ط', '/tah.fina': 'ﻂ', '/tah.init': 'ﻃ',
- '/tah.init_alefmaksura.fina': 'ﳵ', '/tah.init_hah.fina': 'ﰦ',
- '/tah.init_hah.medi': 'ﲸ', '/tah.init_meem.fina': 'ﰧ',
- '/tah.init_meem.medi': 'ﴳ', '/tah.init_meem.medi_hah.medi': 'ﵲ',
- '/tah.init_meem.medi_meem.medi': 'ﵳ', '/tah.init_yeh.fina': 'ﳶ',
- '/tah.isol': 'ﻁ', '/tah.medi': 'ﻄ', '/tah.medi_alefmaksura.fina': 'ﴑ',
- '/tah.medi_meem.medi': 'ﴺ', '/tah.medi_meem.medi_hah.fina': 'ﵱ',
- '/tah.medi_meem.medi_yeh.fina': 'ﵴ', '/tah.medi_yeh.fina': 'ﴒ',
- '/tahabove': 'ؕ', '/taharabic': 'ط', '/tahfinalarabic': 'ﻂ',
- '/tahinitialarabic': 'ﻃ', '/tahiragana': 'た', '/tahmedialarabic': 'ﻄ',
- '/tahthreedotsabove': 'ڟ', '/taisyouerasquare': '㍽', '/takatakana': 'タ',
- '/takatakanahalfwidth': 'タ', '/takhallus': 'ؔ', '/talingvowel': 'ꦺ',
- '/taml:a': 'அ', '/taml:aa': 'ஆ', '/taml:aasign': 'ா', '/taml:ai': 'ஐ',
- '/taml:aisign': 'ை', '/taml:anusvarasign': 'ஂ', '/taml:asabovesign':
- '௸', '/taml:au': 'ஔ', '/taml:aulengthmark': 'ௗ', '/taml:ausign': 'ௌ',
- '/taml:ca': 'ச', '/taml:creditsign': '௷', '/taml:daysign': '௳',
- '/taml:debitsign': '௶', '/taml:e': 'எ', '/taml:ee': 'ஏ', '/taml:eesign':
- 'ே', '/taml:eight': '௮', '/taml:esign': 'ெ', '/taml:five': '௫',
- '/taml:four': '௪', '/taml:ha': 'ஹ', '/taml:i': 'இ', '/taml:ii': 'ஈ',
- '/taml:iisign': 'ீ', '/taml:isign': 'ி', '/taml:ja': 'ஜ', '/taml:ka':
- 'க', '/taml:la': 'ல', '/taml:lla': 'ள', '/taml:llla': 'ழ', '/taml:ma':
- 'ம', '/taml:monthsign': '௴', '/taml:na': 'ந', '/taml:nga': 'ங',
- '/taml:nine': '௯', '/taml:nna': 'ண', '/taml:nnna': 'ன', '/taml:nya':
- 'ஞ', '/taml:o': 'ஒ', '/taml:om': 'ௐ', '/taml:one': '௧',
- '/taml:onehundred': '௱', '/taml:onethousand': '௲', '/taml:oo': 'ஓ',
- '/taml:oosign': 'ோ', '/taml:osign': 'ொ', '/taml:pa': 'ப', '/taml:ra':
- 'ர', '/taml:rra': 'ற', '/taml:rupeesign': '௹', '/taml:sa': 'ஸ',
- '/taml:seven': '௭', '/taml:sha': 'ஶ', '/taml:sign': '௺', '/taml:six':
- '௬', '/taml:ssa': 'ஷ', '/taml:ta': 'த', '/taml:ten': '௰', '/taml:three':
- '௩', '/taml:tta': 'ட', '/taml:two': '௨', '/taml:u': 'உ', '/taml:usign':
- 'ு', '/taml:uu': 'ஊ', '/taml:uusign': 'ூ', '/taml:va': 'வ',
- '/taml:viramasign': '்', '/taml:visargasign': 'ஃ', '/taml:ya': 'ய',
- '/taml:yearsign': '௵', '/taml:zero': '௦', '/tamurda': 'ꦡ',
- '/tanabataTree': 'ἸB', '/tangerine': 'ἴA', '/tapeCartridge': '\u1f5aD',
- '/tarungvowel': 'ꦴ', '/tatweelFathatanAbove': 'ﹱ', '/tatweelarabic':
- 'ـ', '/tau': 'τ', '/taurus': '♉', '/tav': 'ת', '/tav:hb': 'ת',
- '/tavdages': 'תּ', '/tavdagesh': 'תּ', '/tavdageshhebrew': 'תּ',
- '/tavhebrew': 'ת', '/tavwide:hb': 'ﬨ', '/tavwithdagesh:hb': 'תּ',
- '/taxi': 'Ὡ5', '/tbar': 'ŧ', '/tbopomofo': 'ㄊ', '/tcaron': 'ť',
- '/tccurl': 'ʨ', '/tcedilla': 'ţ', '/tcheh': 'چ', '/tcheh.fina': 'ﭻ',
- '/tcheh.init': 'ﭼ', '/tcheh.isol': 'ﭺ', '/tcheh.medi': 'ﭽ',
- '/tcheharabic': 'چ', '/tchehdotabove': 'ڿ', '/tcheheh': 'ڇ',
- '/tcheheh.fina': 'ﭿ', '/tcheheh.init': 'ﮀ', '/tcheheh.isol': 'ﭾ',
- '/tcheheh.medi': 'ﮁ', '/tchehfinalarabic': 'ﭻ', '/tchehinitialarabic':
- 'ﭼ', '/tchehmedialarabic': 'ﭽ', '/tchehmeeminitialarabic': 'ﭼ',
- '/tcircle': 'ⓣ', '/tcircumflexbelow': 'ṱ', '/tcommaaccent': 'ţ',
- '/tcurl': 'ȶ', '/tdieresis': 'ẗ', '/tdot': 'ṫ', '/tdotaccent': 'ṫ',
- '/tdotbelow': 'ṭ', '/teacupOutHandle': 'ἷ5', '/tear-offCalendar': 'Ὄ6',
- '/tecirclekatakana': '㋢', '/tecyr': 'т', '/tecyrillic': 'т',
- '/tedescendercyrillic': 'ҭ', '/teh': 'ت', '/teh.fina': 'ﺖ', '/teh.init':
- 'ﺗ', '/teh.init_alefmaksura.fina': 'ﰏ', '/teh.init_hah.fina': 'ﰌ',
- '/teh.init_hah.medi': 'ﲢ', '/teh.init_hah.medi_jeem.medi': 'ﵒ',
- '/teh.init_hah.medi_meem.medi': 'ﵓ', '/teh.init_heh.medi': 'ﲥ',
- '/teh.init_jeem.fina': 'ﰋ', '/teh.init_jeem.medi': 'ﲡ',
- '/teh.init_jeem.medi_meem.medi': 'ﵐ', '/teh.init_khah.fina': 'ﰍ',
- '/teh.init_khah.medi': 'ﲣ', '/teh.init_khah.medi_meem.medi': 'ﵔ',
- '/teh.init_meem.fina': 'ﰎ', '/teh.init_meem.medi': 'ﲤ',
- '/teh.init_meem.medi_hah.medi': 'ﵖ', '/teh.init_meem.medi_jeem.medi':
- 'ﵕ', '/teh.init_meem.medi_khah.medi': 'ﵗ', '/teh.init_yeh.fina': 'ﰐ',
- '/teh.isol': 'ﺕ', '/teh.medi': 'ﺘ', '/teh.medi_alefmaksura.fina': 'ﱴ',
- '/teh.medi_hah.medi_jeem.fina': 'ﵑ', '/teh.medi_heh.medi': 'ﳤ',
- '/teh.medi_jeem.medi_alefmaksura.fina': 'ﶠ',
- '/teh.medi_jeem.medi_yeh.fina': 'ﶟ',
- '/teh.medi_khah.medi_alefmaksura.fina': 'ﶢ',
- '/teh.medi_khah.medi_yeh.fina': 'ﶡ', '/teh.medi_meem.fina': 'ﱲ',
- '/teh.medi_meem.medi': 'ﳣ', '/teh.medi_meem.medi_alefmaksura.fina': 'ﶤ',
- '/teh.medi_meem.medi_yeh.fina': 'ﶣ', '/teh.medi_noon.fina': 'ﱳ',
- '/teh.medi_reh.fina': 'ﱰ', '/teh.medi_yeh.fina': 'ﱵ',
- '/teh.medi_zain.fina': 'ﱱ', '/teharabic': 'ت', '/tehdownthreedotsabove':
- 'ٽ', '/teheh': 'ٿ', '/teheh.fina': 'ﭣ', '/teheh.init': 'ﭤ',
- '/teheh.isol': 'ﭢ', '/teheh.medi': 'ﭥ', '/tehfinalarabic': 'ﺖ',
- '/tehhahinitialarabic': 'ﲢ', '/tehhahisolatedarabic': 'ﰌ',
- '/tehinitialarabic': 'ﺗ', '/tehiragana': 'て', '/tehjeeminitialarabic':
- 'ﲡ', '/tehjeemisolatedarabic': 'ﰋ', '/tehmarbuta': 'ة',
- '/tehmarbuta.fina': 'ﺔ', '/tehmarbuta.isol': 'ﺓ', '/tehmarbutaarabic':
- 'ة', '/tehmarbutafinalarabic': 'ﺔ', '/tehmarbutagoal': 'ۃ',
- '/tehmedialarabic': 'ﺘ', '/tehmeeminitialarabic': 'ﲤ',
- '/tehmeemisolatedarabic': 'ﰎ', '/tehnoonfinalarabic': 'ﱳ', '/tehring':
- 'ټ', '/tekatakana': 'テ', '/tekatakanahalfwidth': 'テ', '/telephone': '℡',
- '/telephoneOnTopOfModem': '\u1f580', '/telephoneReceiver': 'ὍE',
- '/telephoneReceiverPage': 'ὗC', '/telephoneblack': '☎',
- '/telephonerecorder': '⌕', '/telephonewhite': '☏', '/telescope': 'ὒD',
- '/television': '\u1f4fA', '/telishaGedolah:hb': '֠',
- '/telishaQetannah:hb': '֩', '/telishagedolahebrew': '֠',
- '/telishaqetanahebrew': '֩', '/telu:a': 'అ', '/telu:aa': 'ఆ',
- '/telu:aasign': 'ా', '/telu:ai': 'ఐ', '/telu:ailengthmark': 'ౖ',
- '/telu:aisign': 'ై', '/telu:anusvarasign': 'ం', '/telu:au': 'ఔ',
- '/telu:ausign': 'ౌ', '/telu:avagrahasign': 'ఽ', '/telu:ba': 'బ',
- '/telu:bha': 'భ', '/telu:bindusigncandra': 'ఁ', '/telu:ca': 'చ',
- '/telu:cha': 'ఛ', '/telu:combiningbinduabovesigncandra': 'ఀ',
- '/telu:da': 'ద', '/telu:dda': 'డ', '/telu:ddha': 'ఢ', '/telu:dha': 'ధ',
- '/telu:dza': 'ౙ', '/telu:e': 'ఎ', '/telu:ee': 'ఏ', '/telu:eesign': 'ే',
- '/telu:eight': '౮', '/telu:esign': 'ె', '/telu:five': '౫', '/telu:four':
- '౪', '/telu:fractiononeforevenpowersoffour': '౼',
- '/telu:fractiononeforoddpowersoffour': '౹',
- '/telu:fractionthreeforevenpowersoffour': '౾',
- '/telu:fractionthreeforoddpowersoffour': '౻',
- '/telu:fractiontwoforevenpowersoffour': '౽',
- '/telu:fractiontwoforoddpowersoffour': '౺',
- '/telu:fractionzeroforoddpowersoffour': '౸', '/telu:ga': 'గ',
- '/telu:gha': 'ఘ', '/telu:ha': 'హ', '/telu:i': 'ఇ', '/telu:ii': 'ఈ',
- '/telu:iisign': 'ీ', '/telu:isign': 'ి', '/telu:ja': 'జ', '/telu:jha':
- 'ఝ', '/telu:ka': 'క', '/telu:kha': 'ఖ', '/telu:la': 'ల',
- '/telu:lengthmark': 'ౕ', '/telu:lla': 'ళ', '/telu:llla': 'ఴ',
- '/telu:llsignvocal': 'ౣ', '/telu:llvocal': 'ౡ', '/telu:lsignvocal': 'ౢ',
- '/telu:lvocal': 'ఌ', '/telu:ma': 'మ', '/telu:na': 'న', '/telu:nga': 'ఙ',
- '/telu:nine': '౯', '/telu:nna': 'ణ', '/telu:nya': 'ఞ', '/telu:o': 'ఒ',
- '/telu:one': '౧', '/telu:oo': 'ఓ', '/telu:oosign': 'ో', '/telu:osign':
- 'ొ', '/telu:pa': 'ప', '/telu:pha': 'ఫ', '/telu:ra': 'ర', '/telu:rra':
- 'ఱ', '/telu:rrra': 'ౚ', '/telu:rrsignvocal': 'ౄ', '/telu:rrvocal': 'ౠ',
- '/telu:rsignvocal': 'ృ', '/telu:rvocal': 'ఋ', '/telu:sa': 'స',
- '/telu:seven': '౭', '/telu:sha': 'శ', '/telu:six': '౬', '/telu:ssa':
- 'ష', '/telu:ta': 'త', '/telu:tha': 'థ', '/telu:three': '౩', '/telu:tsa':
- 'ౘ', '/telu:tta': 'ట', '/telu:ttha': 'ఠ', '/telu:tuumusign': '౿',
- '/telu:two': '౨', '/telu:u': 'ఉ', '/telu:usign': 'ు', '/telu:uu': 'ఊ',
- '/telu:uusign': 'ూ', '/telu:va': 'వ', '/telu:viramasign': '్',
- '/telu:visargasign': 'ః', '/telu:ya': 'య', '/telu:zero': '౦',
- '/ten.roman': 'Ⅹ', '/ten.romansmall': 'ⅹ', '/tencircle': '⑩',
- '/tencircledbl': '⓾', '/tencirclesquare': '㉈', '/tenge': '₸',
- '/tenhangzhou': '〸', '/tenideographiccircled': '㊉',
- '/tenideographicparen': '㈩', '/tennisRacquetAndBall': 'ἻE', '/tenparen':
- '⑽', '/tenparenthesized': '⑽', '/tenperiod': '⒑', '/tenroman': 'ⅹ',
- '/tent': '⛺', '/tenthousand.roman': 'ↂ', '/tesh': 'ʧ', '/tet': 'ט',
- '/tet:hb': 'ט', '/tetailcyr': 'ҭ', '/tetdagesh': 'טּ',
- '/tetdageshhebrew': 'טּ', '/tethebrew': 'ט', '/tetrasememetrical': '⏘',
- '/tetsecyr': 'ҵ', '/tetsecyrillic': 'ҵ', '/tetwithdagesh:hb': 'טּ',
- '/tevir:hb': '֛', '/tevirhebrew': '֛', '/tevirlefthebrew': '֛',
- '/thabengali': 'থ', '/thadeva': 'थ', '/thagujarati': 'થ',
- '/thagurmukhi': 'ਥ', '/thai:angkhankhu': '๚', '/thai:baht': '฿',
- '/thai:bobaimai': 'บ', '/thai:chochan': 'จ', '/thai:chochang': 'ช',
- '/thai:choching': 'ฉ', '/thai:chochoe': 'ฌ', '/thai:dochada': 'ฎ',
- '/thai:dodek': 'ด', '/thai:eight': '๘', '/thai:five': '๕', '/thai:fofa':
- 'ฝ', '/thai:fofan': 'ฟ', '/thai:fongman': '๏', '/thai:four': '๔',
- '/thai:hohip': 'ห', '/thai:honokhuk': 'ฮ', '/thai:khokhai': 'ข',
- '/thai:khokhon': 'ฅ', '/thai:khokhuat': 'ฃ', '/thai:khokhwai': 'ค',
- '/thai:khomut': '๛', '/thai:khorakhang': 'ฆ', '/thai:kokai': 'ก',
- '/thai:lakkhangyao': 'ๅ', '/thai:lochula': 'ฬ', '/thai:loling': 'ล',
- '/thai:lu': 'ฦ', '/thai:maichattawa': '๋', '/thai:maiek': '่',
- '/thai:maihan-akat': 'ั', '/thai:maitaikhu': '็', '/thai:maitho': '้',
- '/thai:maitri': '๊', '/thai:maiyamok': 'ๆ', '/thai:moma': 'ม',
- '/thai:ngongu': 'ง', '/thai:nikhahit': 'ํ', '/thai:nine': '๙',
- '/thai:nonen': 'ณ', '/thai:nonu': 'น', '/thai:oang': 'อ', '/thai:one':
- '๑', '/thai:paiyannoi': 'ฯ', '/thai:phinthu': 'ฺ', '/thai:phophan': 'พ',
- '/thai:phophung': 'ผ', '/thai:phosamphao': 'ภ', '/thai:popla': 'ป',
- '/thai:rorua': 'ร', '/thai:ru': 'ฤ', '/thai:saraa': 'ะ', '/thai:saraaa':
- 'า', '/thai:saraae': 'แ', '/thai:saraaimaimalai': 'ไ',
- '/thai:saraaimaimuan': 'ใ', '/thai:saraam': 'ำ', '/thai:sarae': 'เ',
- '/thai:sarai': 'ิ', '/thai:saraii': 'ี', '/thai:sarao': 'โ',
- '/thai:sarau': 'ุ', '/thai:saraue': 'ึ', '/thai:sarauee': 'ื',
- '/thai:sarauu': 'ู', '/thai:seven': '๗', '/thai:six': '๖',
- '/thai:sorusi': 'ษ', '/thai:sosala': 'ศ', '/thai:soso': 'ซ',
- '/thai:sosua': 'ส', '/thai:thanthakhat': '์', '/thai:thonangmontho':
- 'ฑ', '/thai:thophuthao': 'ฒ', '/thai:thothahan': 'ท', '/thai:thothan':
- 'ฐ', '/thai:thothong': 'ธ', '/thai:thothung': 'ถ', '/thai:three': '๓',
- '/thai:topatak': 'ฏ', '/thai:totao': 'ต', '/thai:two': '๒',
- '/thai:wowaen': 'ว', '/thai:yamakkan': '๎', '/thai:yoyak': 'ย',
- '/thai:yoying': 'ญ', '/thai:zero': '๐', '/thal': 'ذ', '/thal.fina': 'ﺬ',
- '/thal.init_superscriptalef.fina': 'ﱛ', '/thal.isol': 'ﺫ',
- '/thalarabic': 'ذ', '/thalfinalarabic': 'ﺬ', '/thanthakhatlowleftthai':
- '\uf898', '/thanthakhatlowrightthai': '\uf897', '/thanthakhatthai': '์',
- '/thanthakhatupperleftthai': '\uf896', '/theh': 'ث', '/theh.fina': 'ﺚ',
- '/theh.init': 'ﺛ', '/theh.init_alefmaksura.fina': 'ﰓ',
- '/theh.init_jeem.fina': 'ﰑ', '/theh.init_meem.fina': 'ﰒ',
- '/theh.init_meem.medi': 'ﲦ', '/theh.init_yeh.fina': 'ﰔ', '/theh.isol':
- 'ﺙ', '/theh.medi': 'ﺜ', '/theh.medi_alefmaksura.fina': 'ﱺ',
- '/theh.medi_heh.medi': 'ﳦ', '/theh.medi_meem.fina': 'ﱸ',
- '/theh.medi_meem.medi': 'ﳥ', '/theh.medi_noon.fina': 'ﱹ',
- '/theh.medi_reh.fina': 'ﱶ', '/theh.medi_yeh.fina': 'ﱻ',
- '/theh.medi_zain.fina': 'ﱷ', '/theharabic': 'ث', '/thehfinalarabic':
- 'ﺚ', '/thehinitialarabic': 'ﺛ', '/thehmedialarabic': 'ﺜ',
- '/thereexists': '∃', '/therefore': '∴', '/thermometer': 'ἲ1', '/theta':
- 'θ', '/theta.math': 'ϑ', '/theta1': 'ϑ', '/thetasymbolgreek': 'ϑ',
- '/thieuthacirclekorean': '㉹', '/thieuthaparenkorean': '㈙',
- '/thieuthcirclekorean': '㉫', '/thieuthkorean': 'ㅌ',
- '/thieuthparenkorean': '㈋', '/thinspace': '\u2009', '/thirteencircle':
- '⑬', '/thirteencircleblack': '⓭', '/thirteenparen': '⒀',
- '/thirteenparenthesized': '⒀', '/thirteenperiod': '⒔', '/thirtycircle':
- '㉚', '/thirtycirclesquare': '㉊', '/thirtyeightcircle': '㊳',
- '/thirtyfivecircle': '㉟', '/thirtyfourcircle': '㉞', '/thirtyhangzhou':
- '〺', '/thirtyninecircle': '㊴', '/thirtyonecircle': '㉛',
- '/thirtysevencircle': '㊲', '/thirtysixcircle': '㊱',
- '/thirtythreecircle': '㉝', '/thirtytwocircle': '㉜',
- '/thonangmonthothai': 'ฑ', '/thook': 'ƭ', '/thophuthaothai': 'ฒ',
- '/thorn': 'þ', '/thornstroke': 'ꝥ', '/thornstrokedescender': 'ꝧ',
- '/thothahanthai': 'ท', '/thothanthai': 'ฐ', '/thothongthai': 'ธ',
- '/thothungthai': 'ถ', '/thoughtBalloon': 'ὊD', '/thousandcyrillic': '҂',
- '/thousandscyr': '҂', '/thousandsseparator': '٬',
- '/thousandsseparatorarabic': '٬', '/thousandsseparatorpersian': '٬',
- '/three': '3', '/three.inferior': '₃', '/three.roman': 'Ⅲ',
- '/three.romansmall': 'ⅲ', '/threeButtonMouse': 'Ὓ1',
- '/threeNetworkedComputers': '\u1f5a7', '/threeRaysAbove': '\u1f5e4',
- '/threeRaysBelow': '\u1f5e5', '/threeRaysLeft': '\u1f5e6',
- '/threeRaysRight': '\u1f5e7', '/threeSpeechBubbles': '\u1f5eB',
- '/threearabic': '٣', '/threebengali': '৩', '/threecircle': '③',
- '/threecircledbl': '⓷', '/threecircleinversesansserif': '➌',
- '/threecomma': 'ἐ4', '/threedeva': '३', '/threedimensionalangle': '⟀',
- '/threedotpunctuation': '⁖', '/threedotsaboveabove': 'ۛ',
- '/threedsquare': 'ἙB', '/threeeighths': '⅜', '/threefar': '۳',
- '/threefifths': '⅗', '/threegujarati': '૩', '/threegurmukhi': '੩',
- '/threehackarabic': '٣', '/threehangzhou': '〣',
- '/threeideographiccircled': '㊂', '/threeideographicparen': '㈢',
- '/threeinferior': '₃', '/threelinesconvergingleft': '⚟',
- '/threelinesconvergingright': '⚞', '/threemonospace': '3',
- '/threenumeratorbengali': '৶', '/threeoldstyle': '\uf733',
- '/threeparen': '⑶', '/threeparenthesized': '⑶', '/threeperemspace':
- '\u2004', '/threeperiod': '⒊', '/threepersian': '۳', '/threequarters':
- '¾', '/threequartersemdash': '\uf6de', '/threerightarrows': '⇶',
- '/threeroman': 'ⅲ', '/threesuperior': '³', '/threethai': '๓',
- '/thumbsDownSign': 'ὄE', '/thumbsUpSign': 'ὄD', '/thundercloudrain':
- '⛈', '/thunderstorm': '☈', '/thzfullwidth': '㎔', '/thzsquare': '㎔',
- '/tibt:AA': 'འ', '/tibt:a': 'ཨ', '/tibt:aavowelsign': 'ཱ',
- '/tibt:angkhanggyasmark': '༽', '/tibt:angkhanggyonmark': '༼',
- '/tibt:astrologicalkhyudpasign': '༘',
- '/tibt:astrologicalsdongtshugssign': '༙',
- '/tibt:astrologicalsgragcancharrtagssign': '༗', '/tibt:asubjoined': 'ྸ',
- '/tibt:ba': 'བ', '/tibt:basubjoined': 'ྦ', '/tibt:bha': 'བྷ',
- '/tibt:bhasubjoined': 'ྦྷ', '/tibt:bkashogyigmgomark': '༊',
- '/tibt:brdarnyingyigmgomdunmainitialmark': '࿓',
- '/tibt:brdarnyingyigmgosgabmaclosingmark': '࿔', '/tibt:bsdusrtagsmark':
- '༴', '/tibt:bskashoggimgorgyanmark': '࿐', '/tibt:bskuryigmgomark': '༉',
- '/tibt:ca': 'ཅ', '/tibt:cangteucantillationsign': '࿂',
- '/tibt:caretdzudrtagsbzhimigcanmark': '༶',
- '/tibt:caretdzudrtagsmelongcanmark': '༓',
- '/tibt:caretyigmgophurshadmamark': '༆', '/tibt:casubjoined': 'ྕ',
- '/tibt:cha': 'ཆ', '/tibt:chadrtagslogotypesign': '༕',
- '/tibt:chasubjoined': 'ྖ', '/tibt:chemgomark': '༸', '/tibt:da': 'ད',
- '/tibt:dasubjoined': 'ྡ', '/tibt:dda': 'ཌ', '/tibt:ddasubjoined': 'ྜ',
- '/tibt:ddha': 'ཌྷ', '/tibt:ddhasubjoined': 'ྜྷ',
- '/tibt:delimitertshegbstarmark': '༌', '/tibt:dha': 'དྷ',
- '/tibt:dhasubjoined': 'ྡྷ', '/tibt:drilbusymbol': '࿄', '/tibt:dza': 'ཛ',
- '/tibt:dzasubjoined': 'ྫ', '/tibt:dzha': 'ཛྷ', '/tibt:dzhasubjoined':
- 'ྫྷ', '/tibt:eevowelsign': 'ཻ', '/tibt:eight': '༨', '/tibt:evowelsign':
- 'ེ', '/tibt:five': '༥', '/tibt:four': '༤', '/tibt:ga': 'ག',
- '/tibt:gasubjoined': 'ྒ', '/tibt:gha': 'གྷ', '/tibt:ghasubjoined': 'ྒྷ',
- '/tibt:grucanrgyingssign': 'ྊ', '/tibt:grumedrgyingssign': 'ྋ',
- '/tibt:gtertshegmark': '༔', '/tibt:gteryigmgotruncatedamark': '༁',
- '/tibt:gteryigmgoumgtertshegmamark': '༃',
- '/tibt:gteryigmgoumrnambcadmamark': '༂', '/tibt:gugrtagsgyasmark': '༻',
- '/tibt:gugrtagsgyonmark': '༺', '/tibt:ha': 'ཧ', '/tibt:halantamark':
- '྄', '/tibt:halfeight': '༱', '/tibt:halffive': '༮', '/tibt:halffour':
- '༭', '/tibt:halfnine': '༲', '/tibt:halfone': '༪', '/tibt:halfseven':
- '༰', '/tibt:halfsix': '༯', '/tibt:halfthree': '༬', '/tibt:halftwo': '༫',
- '/tibt:halfzero': '༳', '/tibt:hasubjoined': 'ྷ',
- '/tibt:heavybeatcantillationsign': '࿀', '/tibt:iivowelsign': 'ཱི',
- '/tibt:intersyllabictshegmark': '་', '/tibt:invertedmchucansign': 'ྌ',
- '/tibt:invertedmchucansubjoinedsign': 'ྏ', '/tibt:ivowelsign': 'ི',
- '/tibt:ja': 'ཇ', '/tibt:jasubjoined': 'ྗ', '/tibt:ka': 'ཀ',
- '/tibt:kasubjoined': 'ྐ', '/tibt:kha': 'ཁ', '/tibt:khasubjoined': 'ྑ',
- '/tibt:kka': 'ཫ', '/tibt:kssa': 'ཀྵ', '/tibt:kssasubjoined': 'ྐྵ',
- '/tibt:kurukha': '྾', '/tibt:kurukhabzhimigcan': '྿', '/tibt:la': 'ལ',
- '/tibt:lasubjoined': 'ླ', '/tibt:lcetsacansign': 'ྈ',
- '/tibt:lcetsacansubjoinedsign': 'ྍ', '/tibt:lcirtagssign': '྆',
- '/tibt:leadingmchanrtagsmark': '࿙', '/tibt:lhagrtagslogotypesign': '༖',
- '/tibt:lightbeatcantillationsign': '࿁', '/tibt:llvocalicvowelsign': 'ཹ',
- '/tibt:lvocalicvowelsign': 'ླྀ', '/tibt:ma': 'མ', '/tibt:martshessign':
- '༿', '/tibt:masubjoined': 'ྨ', '/tibt:mchucansign': 'ྉ',
- '/tibt:mchucansubjoinedsign': 'ྎ', '/tibt:mnyamyiggimgorgyanmark': '࿑',
- '/tibt:na': 'ན', '/tibt:nasubjoined': 'ྣ', '/tibt:nga': 'ང',
- '/tibt:ngasbzungnyizlamark': '༵', '/tibt:ngasbzungsgorrtagsmark': '༷',
- '/tibt:ngasubjoined': 'ྔ', '/tibt:nine': '༩', '/tibt:nna': 'ཎ',
- '/tibt:nnasubjoined': 'ྞ', '/tibt:norbubzhikhyilsymbol': '࿌',
- '/tibt:norbugsumkhyilsymbol': '࿋', '/tibt:norbunyiskhyilsymbol': '࿊',
- '/tibt:norbusymbol': '࿉', '/tibt:nya': 'ཉ', '/tibt:nyasubjoined': 'ྙ',
- '/tibt:nyisshadmark': '༎', '/tibt:nyistshegmark': '࿒',
- '/tibt:nyistshegshadmark': '༐', '/tibt:nyizlanaadasign': 'ྂ',
- '/tibt:omsyllable': 'ༀ', '/tibt:one': '༡', '/tibt:oovowelsign': 'ཽ',
- '/tibt:ovowelsign': 'ོ', '/tibt:pa': 'པ', '/tibt:padmagdansymbol': '࿆',
- '/tibt:palutamark': '྅', '/tibt:pasubjoined': 'ྤ', '/tibt:pha': 'ཕ',
- '/tibt:phasubjoined': 'ྥ', '/tibt:phurpasymbol': '࿈', '/tibt:ra': 'ར',
- '/tibt:rafixed': 'ཪ', '/tibt:rasubjoined': 'ྲ',
- '/tibt:rasubjoinedfixed': 'ྼ', '/tibt:rdeldkargcigsign': '༚',
- '/tibt:rdeldkargnyissign': '༛', '/tibt:rdeldkargsumsign': '༜',
- '/tibt:rdeldkarrdelnagsign': '༟', '/tibt:rdelnaggcigsign': '༝',
- '/tibt:rdelnaggnyissign': '༞', '/tibt:rdelnaggsumsign': '࿏',
- '/tibt:rdelnagrdeldkarsign': '࿎', '/tibt:rdorjergyagramsymbol': '࿇',
- '/tibt:rdorjesymbol': '࿅', '/tibt:reversediivowelsign': 'ཱྀ',
- '/tibt:reversedivowelsign': 'ྀ', '/tibt:rgyagramshadmark': '༒',
- '/tibt:rinchenspungsshadmark': '༑', '/tibt:rjessungarosign': 'ཾ',
- '/tibt:rnambcadsign': 'ཿ', '/tibt:rra': 'ཬ', '/tibt:rrvocalicvowelsign':
- 'ཷ', '/tibt:rvocalicvowelsign': 'ྲྀ', '/tibt:sa': 'ས',
- '/tibt:sasubjoined': 'ྶ', '/tibt:sbrulshadmark': '༈',
- '/tibt:sbubchalcantillationsign': '࿃', '/tibt:seven': '༧', '/tibt:sha':
- 'ཤ', '/tibt:shadmark': '།', '/tibt:shasubjoined': 'ྴ', '/tibt:six': '༦',
- '/tibt:snaldansign': 'ྃ', '/tibt:ssa': 'ཥ', '/tibt:ssasubjoined': 'ྵ',
- '/tibt:subjoinedAA': 'ྰ', '/tibt:svastileft': '࿖',
- '/tibt:svastileftdot': '࿘', '/tibt:svastiright': '࿕',
- '/tibt:svastirightdot': '࿗', '/tibt:ta': 'ཏ', '/tibt:tasubjoined': 'ྟ',
- '/tibt:tha': 'ཐ', '/tibt:thasubjoined': 'ྠ', '/tibt:three': '༣',
- '/tibt:trailingmchanrtagsmark': '࿚', '/tibt:tsa': 'ཙ',
- '/tibt:tsaphrumark': '༹', '/tibt:tsasubjoined': 'ྩ', '/tibt:tsha': 'ཚ',
- '/tibt:tshasubjoined': 'ྪ', '/tibt:tshegshadmark': '༏', '/tibt:tta':
- 'ཊ', '/tibt:ttasubjoined': 'ྚ', '/tibt:ttha': 'ཋ',
- '/tibt:tthasubjoined': 'ྛ', '/tibt:two': '༢', '/tibt:uuvowelsign': 'ཱུ',
- '/tibt:uvowelsign': 'ུ', '/tibt:wa': 'ཝ', '/tibt:wasubjoined': 'ྭ',
- '/tibt:wasubjoinedfixed': 'ྺ', '/tibt:ya': 'ཡ', '/tibt:yangrtagssign':
- '྇', '/tibt:yartshessign': '༾', '/tibt:yasubjoined': 'ྱ',
- '/tibt:yasubjoinedfixed': 'ྻ', '/tibt:yigmgomdunmainitialmark': '༄',
- '/tibt:yigmgosgabmaclosingmark': '༅', '/tibt:yigmgotshegshadmamark':
- '༇', '/tibt:za': 'ཟ', '/tibt:zasubjoined': 'ྯ', '/tibt:zero': '༠',
- '/tibt:zha': 'ཞ', '/tibt:zhasubjoined': 'ྮ', '/ticirclekatakana': '㋠',
- '/tickconvavediamondleftwhite': '⟢', '/tickconvavediamondrightwhite':
- '⟣', '/ticket': 'ἺB', '/tickleftwhitesquare': '⟤',
- '/tickrightwhitesquare': '⟥', '/tifcha:hb': '֖', '/tiger': 'ὀ5',
- '/tigerFace': 'ὂF', '/tihiragana': 'ち', '/tikatakana': 'チ',
- '/tikatakanahalfwidth': 'チ', '/tikeutacirclekorean': '㉰',
- '/tikeutaparenkorean': '㈐', '/tikeutcirclekorean': '㉢', '/tikeutkorean':
- 'ㄷ', '/tikeutparenkorean': '㈂', '/tilde': '˜', '/tildebelowcmb': '̰',
- '/tildecmb': '̃', '/tildecomb': '̃', '/tildediaeresisfunc': '⍨',
- '/tildedotaccent': '⸞', '/tildedotbelow': '⸟', '/tildedoublecmb': '͠',
- '/tildeequalsreversed': '⋍', '/tildelowmod': '˷', '/tildeoperator': '∼',
- '/tildeoverlaycmb': '̴', '/tildereversed': '∽', '/tildering': '⸛',
- '/tildetpl': '≋', '/tildeverticalcmb': '̾', '/timerclock': '⏲',
- '/timescircle': '⊗', '/tinsular': 'ꞇ', '/tipehahebrew': '֖',
- '/tipehalefthebrew': '֖', '/tippigurmukhi': 'ੰ', '/tiredFace': 'ὢB',
- '/tironiansignet': '⁊', '/tirtatumetespada': '꧞', '/titlocmbcyr': '҃',
- '/titlocyrilliccmb': '҃', '/tiwnarmenian': 'տ', '/tjekomicyr': 'ԏ',
- '/tlinebelow': 'ṯ', '/tmonospace': 't', '/toarmenian': 'թ',
- '/tocirclekatakana': '㋣', '/tocornerarrowNW': '⇱', '/tocornerarrowSE':
- '⇲', '/tohiragana': 'と', '/toilet': 'ὫD', '/tokatakana': 'ト',
- '/tokatakanahalfwidth': 'ト', '/tokyoTower': 'ὟC', '/tolongvowel': 'ꦵ',
- '/tomato': 'ἴ5', '/tonebarextrahighmod': '˥', '/tonebarextralowmod':
- '˩', '/tonebarhighmod': '˦', '/tonebarlowmod': '˨', '/tonebarmidmod':
- '˧', '/tonefive': 'ƽ', '/tonehighbeginmod': '˹', '/tonehighendmod': '˺',
- '/tonelowbeginmod': '˻', '/tonelowendmod': '˼', '/tonesix': 'ƅ',
- '/tonetwo': 'ƨ', '/tongue': 'ὄ5', '/tonos': '΄', '/tonsquare': '㌧',
- '/topHat': 'Ἲ9', '/topUpwardsArrowAbove': 'ὑD', '/topatakthai': 'ฏ',
- '/tortoiseshellbracketleft': '〔', '/tortoiseshellbracketleftsmall': '﹝',
- '/tortoiseshellbracketleftvertical': '︹', '/tortoiseshellbracketright':
- '〕', '/tortoiseshellbracketrightsmall': '﹞',
- '/tortoiseshellbracketrightvertical': '︺', '/totalrunout': '⌰',
- '/totaothai': 'ต', '/tpalatalhook': 'ƫ', '/tparen': '⒯',
- '/tparenthesized': '⒯', '/trackball': 'Ὓ2', '/tractor': 'ὩC',
- '/trademark': '™', '/trademarksans': '\uf8ea', '/trademarkserif':
- '\uf6db', '/train': 'Ὠ6', '/tram': 'ὨA', '/tramCar': 'ὨB',
- '/trapeziumwhite': '⏢', '/tresillo': 'ꜫ', '/tretroflex': 'ʈ',
- '/tretroflexhook': 'ʈ', '/triagdn': '▼', '/triaglf': '◄', '/triagrt':
- '►', '/triagup': '▲', '/triangleWithRoundedCorners': 'Ὤ6',
- '/triangledotupwhite': '◬', '/triangledownblack': '▼',
- '/triangledownsmallblack': '▾', '/triangledownsmallwhite': '▿',
- '/triangledownwhite': '▽', '/trianglehalfupleftblack': '◭',
- '/trianglehalfuprightblack': '◮', '/triangleleftblack': '◀',
- '/triangleleftsmallblack': '◂', '/triangleleftsmallwhite': '◃',
- '/triangleleftwhite': '◁', '/triangleright': '⊿', '/trianglerightblack':
- '▶', '/trianglerightsmallblack': '▸', '/trianglerightsmallwhite': '▹',
- '/trianglerightwhite': '▷', '/triangleupblack': '▲',
- '/triangleupsmallblack': '▴', '/triangleupsmallwhite': '▵',
- '/triangleupwhite': '△', '/triangularFlagOnPost': 'Ὢ9',
- '/triangularRuler': 'Ὅ0', '/triangularbullet': '‣', '/tricolon': '⁝',
- '/tricontainingtriwhiteanglesmall': '⟁', '/tridentEmblem': 'ὓ1',
- '/trigramearth': '☷', '/trigramfire': '☲', '/trigramheaven': '☰',
- '/trigramlake': '☱', '/trigrammountain': '☶', '/trigramthunder': '☳',
- '/trigramwater': '☵', '/trigramwind': '☴', '/triplearrowleft': '⇚',
- '/triplearrowright': '⇛', '/tripledot': '؞', '/trisememetrical': '⏗',
- '/trns:baby': 'ὫC', '/trolleybus': 'ὨE', '/trophy': 'Ἴ6',
- '/tropicalDrink': 'ἷ9', '/tropicalFish': 'ὂ0', '/truckblack': '⛟',
- '/true': '⊨', '/trumpet': 'ἻA', '/ts': 'ʦ', '/tsadi': 'צ', '/tsadi:hb':
- 'צ', '/tsadidagesh': 'צּ', '/tsadidageshhebrew': 'צּ', '/tsadihebrew':
- 'צ', '/tsadiwithdagesh:hb': 'צּ', '/tsecyr': 'ц', '/tsecyrillic': 'ц',
- '/tsere': 'ֵ', '/tsere12': 'ֵ', '/tsere1e': 'ֵ', '/tsere2b': 'ֵ',
- '/tsere:hb': 'ֵ', '/tserehebrew': 'ֵ', '/tserenarrowhebrew': 'ֵ',
- '/tserequarterhebrew': 'ֵ', '/tserewidehebrew': 'ֵ', '/tshecyr': 'ћ',
- '/tshecyrillic': 'ћ', '/tsinnorit:hb': '֮', '/tstroke': 'ⱦ',
- '/tsuperior': '\uf6f3', '/ttabengali': 'ট', '/ttadeva': 'ट',
- '/ttagujarati': 'ટ', '/ttagurmukhi': 'ਟ', '/ttamahaprana': 'ꦜ', '/tteh':
- 'ٹ', '/tteh.fina': 'ﭧ', '/tteh.init': 'ﭨ', '/tteh.isol': 'ﭦ',
- '/tteh.medi': 'ﭩ', '/tteharabic': 'ٹ', '/tteheh': 'ٺ', '/tteheh.fina':
- 'ﭟ', '/tteheh.init': 'ﭠ', '/tteheh.isol': 'ﭞ', '/tteheh.medi': 'ﭡ',
- '/ttehfinalarabic': 'ﭧ', '/ttehinitialarabic': 'ﭨ', '/ttehmedialarabic':
- 'ﭩ', '/tthabengali': 'ঠ', '/tthadeva': 'ठ', '/tthagujarati': 'ઠ',
- '/tthagurmukhi': 'ਠ', '/tturned': 'ʇ', '/tucirclekatakana': '㋡',
- '/tugrik': '₮', '/tuhiragana': 'つ', '/tukatakana': 'ツ',
- '/tukatakanahalfwidth': 'ツ', '/tulip': 'ἳ7', '/tum': 'ꝷ',
- '/turkishlira': '₺', '/turnedOkHandSign': '\u1f58F', '/turnedcomma':
- '⸲', '/turneddagger': '⸸', '/turneddigitthree': '↋', '/turneddigittwo':
- '↊', '/turnedpiselehpada': '꧍', '/turnedsemicolon': '⸵',
- '/turnedshogipieceblack': '⛊', '/turnedshogipiecewhite': '⛉',
- '/turnstiledblverticalbarright': '⊫', '/turnstileleftrightdbl': '⟚',
- '/turnstiletplverticalbarright': '⊪', '/turtle': 'ὂ2',
- '/tusmallhiragana': 'っ', '/tusmallkatakana': 'ッ',
- '/tusmallkatakanahalfwidth': 'ッ', '/twelve.roman': 'Ⅻ',
- '/twelve.romansmall': 'ⅻ', '/twelvecircle': '⑫', '/twelvecircleblack':
- '⓬', '/twelveparen': '⑿', '/twelveparenthesized': '⑿', '/twelveperiod':
- '⒓', '/twelveroman': 'ⅻ', '/twenty-twopointtwosquare': 'Ἒ2',
- '/twentycircle': '⑳', '/twentycircleblack': '⓴', '/twentycirclesquare':
- '㉉', '/twentyeightcircle': '㉘', '/twentyfivecircle': '㉕',
- '/twentyfourcircle': '㉔', '/twentyhangzhou': '卄', '/twentyninecircle':
- '㉙', '/twentyonecircle': '㉑', '/twentyparen': '⒇',
- '/twentyparenthesized': '⒇', '/twentyperiod': '⒛', '/twentysevencircle':
- '㉗', '/twentysixcircle': '㉖', '/twentythreecircle': '㉓',
- '/twentytwocircle': '㉒', '/twistedRightwardsArrows': 'ὐ0', '/two': '2',
- '/two.inferior': '₂', '/two.roman': 'Ⅱ', '/two.romansmall': 'ⅱ',
- '/twoButtonMouse': 'Ὓ0', '/twoHearts': 'Ὁ5', '/twoMenHoldingHands':
- '\u1f46C', '/twoSpeechBubbles': '\u1f5eA', '/twoWomenHoldingHands':
- '\u1f46D', '/twoarabic': '٢', '/twoasterisksalignedvertically': '⁑',
- '/twobengali': '২', '/twocircle': '②', '/twocircledbl': '⓶',
- '/twocircleinversesansserif': '➋', '/twocomma': 'ἐ3', '/twodeva': '२',
- '/twodotenleader': '‥', '/twodotleader': '‥', '/twodotleadervertical':
- '︰', '/twodotpunctuation': '⁚', '/twodotsoveronedot': '⸪', '/twofar':
- '۲', '/twofifths': '⅖', '/twogujarati': '૨', '/twogurmukhi': '੨',
- '/twohackarabic': '٢', '/twohangzhou': '〢', '/twoideographiccircled':
- '㊁', '/twoideographicparen': '㈡', '/twoinferior': '₂', '/twoksquare':
- 'ἙD', '/twomonospace': '2', '/twonumeratorbengali': '৵', '/twooldstyle':
- '\uf732', '/twoparen': '⑵', '/twoparenthesized': '⑵', '/twoperiod': '⒉',
- '/twopersian': '۲', '/tworoman': 'ⅱ', '/twoshortsjoinedmetrical': '⏖',
- '/twoshortsoverlongmetrical': '⏕', '/twostroke': 'ƻ', '/twosuperior':
- '²', '/twothai': '๒', '/twothirds': '⅔', '/twowayleftwaytrafficblack':
- '⛖', '/twowayleftwaytrafficwhite': '⛗', '/tz': 'ꜩ', '/u': 'u',
- '/u.fina': 'ﯘ', '/u.isol': 'ﯗ', '/uacute': 'ú', '/uacutedblcyr': 'ӳ',
- '/ubar': 'ʉ', '/ubengali': 'উ', '/ubopomofo': 'ㄨ', '/ubracketleft': '⸦',
- '/ubracketright': '⸧', '/ubreve': 'ŭ', '/ucaron': 'ǔ', '/ucircle': 'ⓤ',
- '/ucirclekatakana': '㋒', '/ucircumflex': 'û', '/ucircumflexbelow': 'ṷ',
- '/ucyr': 'у', '/ucyrillic': 'у', '/udattadeva': '॑', '/udblacute': 'ű',
- '/udblgrave': 'ȕ', '/udeva': 'उ', '/udieresis': 'ü', '/udieresisacute':
- 'ǘ', '/udieresisbelow': 'ṳ', '/udieresiscaron': 'ǚ', '/udieresiscyr':
- 'ӱ', '/udieresiscyrillic': 'ӱ', '/udieresisgrave': 'ǜ',
- '/udieresismacron': 'ǖ', '/udotbelow': 'ụ', '/ugrave': 'ù',
- '/ugravedbl': 'ȕ', '/ugujarati': 'ઉ', '/ugurmukhi': 'ਉ', '/uhamza': 'ٷ',
- '/uhamza.isol': 'ﯝ', '/uhdsquare': 'ἚB', '/uhiragana': 'う', '/uhoi':
- 'ủ', '/uhookabove': 'ủ', '/uhorn': 'ư', '/uhornacute': 'ứ',
- '/uhorndotbelow': 'ự', '/uhorngrave': 'ừ', '/uhornhoi': 'ử',
- '/uhornhookabove': 'ử', '/uhorntilde': 'ữ', '/uhungarumlaut': 'ű',
- '/uhungarumlautcyrillic': 'ӳ', '/uighurkazakhkirghizalefmaksura.init':
- 'ﯨ', '/uighurkazakhkirghizalefmaksura.medi': 'ﯩ',
- '/uighurkirghizyeh.init_hamzaabove.medi_alefmaksura.fina': 'ﯹ',
- '/uighurkirghizyeh.init_hamzaabove.medi_alefmaksura.medi': 'ﯻ',
- '/uighurkirghizyeh.medi_hamzaabove.medi_alefmaksura.fina': 'ﯺ',
- '/uinvertedbreve': 'ȗ', '/ukatakana': 'ウ', '/ukatakanahalfwidth': 'ウ',
- '/ukcyr': 'ѹ', '/ukcyrillic': 'ѹ', '/ukorean': 'ㅜ', '/um': 'ꝸ',
- '/umacron': 'ū', '/umacroncyr': 'ӯ', '/umacroncyrillic': 'ӯ',
- '/umacrondieresis': 'ṻ', '/umatragurmukhi': 'ੁ', '/umbrella': '☂',
- '/umbrellaonground': '⛱', '/umbrellaraindrops': '☔', '/umonospace': 'u',
- '/unamusedFace': 'ὡ2', '/unaspiratedmod': '˭', '/underscore': '_',
- '/underscorecenterline': '﹎', '/underscoredashed': '﹍',
- '/underscoredbl': '‗', '/underscoremonospace': '_',
- '/underscorevertical': '︳', '/underscorewavy': '﹏',
- '/underscorewavyvertical': '︴', '/undertie': '‿', '/undo': '⎌',
- '/union': '∪', '/unionarray': '⋃', '/uniondbl': '⋓', '/universal': '∀',
- '/unmarriedpartnership': '⚯', '/uogonek': 'ų', '/uonsquare': '㌆',
- '/upPointingAirplane': 'Ὦ7', '/upPointingMilitaryAirplane': 'Ὦ6',
- '/upPointingSmallAirplane': 'Ὦ8', '/uparen': '⒰', '/uparenthesized':
- '⒰', '/uparrowleftofdownarrow': '⇅', '/upblock': '▀', '/updblhorzsng':
- '╨', '/updblleftsng': '╜', '/updblrightsng': '╙', '/upheavydnhorzlight':
- '╀', '/upheavyhorzlight': '┸', '/upheavyleftdnlight': '┦',
- '/upheavyleftlight': '┚', '/upheavyrightdnlight': '┞',
- '/upheavyrightlight': '┖', '/uplightdnhorzheavy': '╈',
- '/uplighthorzheavy': '┷', '/uplightleftdnheavy': '┪',
- '/uplightleftheavy': '┙', '/uplightrightdnheavy': '┢',
- '/uplightrightheavy': '┕', '/upperHalfBlock': '▀',
- '/upperOneEighthBlock': '▔', '/upperRightShadowedWhiteCircle': 'ὓF',
- '/upperdothebrew': 'ׄ', '/upperhalfcircle': '◠',
- '/upperhalfcircleinversewhite': '◚', '/upperquadrantcirculararcleft':
- '◜', '/upperquadrantcirculararcright': '◝', '/uppertriangleleft': '◸',
- '/uppertriangleleftblack': '◤', '/uppertriangleright': '◹',
- '/uppertrianglerightblack': '◥', '/upsideDownFace': 'ὤ3', '/upsilon':
- 'υ', '/upsilonacute': 'ύ', '/upsilonasper': 'ὑ', '/upsilonasperacute':
- 'ὕ', '/upsilonaspergrave': 'ὓ', '/upsilonaspertilde': 'ὗ',
- '/upsilonbreve': 'ῠ', '/upsilondieresis': 'ϋ', '/upsilondieresisacute':
- 'ΰ', '/upsilondieresisgrave': 'ῢ', '/upsilondieresistilde': 'ῧ',
- '/upsilondieresistonos': 'ΰ', '/upsilongrave': 'ὺ', '/upsilonlatin':
- 'ʊ', '/upsilonlenis': 'ὐ', '/upsilonlenisacute': 'ὔ',
- '/upsilonlenisgrave': 'ὒ', '/upsilonlenistilde': 'ὖ', '/upsilontilde':
- 'ῦ', '/upsilontonos': 'ύ', '/upsilonwithmacron': 'ῡ', '/upsnghorzdbl':
- '╧', '/upsngleftdbl': '╛', '/upsngrightdbl': '╘', '/uptackbelowcmb':
- '̝', '/uptackmod': '˔', '/upwithexclamationmarksquare': 'Ἑ9',
- '/uragurmukhi': 'ੳ', '/uranus': '♅', '/uring': 'ů', '/ushortcyr': 'ў',
- '/ushortcyrillic': 'ў', '/usmallhiragana': 'ぅ', '/usmallkatakana': 'ゥ',
- '/usmallkatakanahalfwidth': 'ゥ', '/usmod': 'ꝰ', '/ustraightcyr': 'ү',
- '/ustraightcyrillic': 'ү', '/ustraightstrokecyr': 'ұ',
- '/ustraightstrokecyrillic': 'ұ', '/utilde': 'ũ', '/utildeacute': 'ṹ',
- '/utildebelow': 'ṵ', '/uubengali': 'ঊ', '/uudeva': 'ऊ', '/uugujarati':
- 'ઊ', '/uugurmukhi': 'ਊ', '/uumatragurmukhi': 'ੂ', '/uuvowelsignbengali':
- 'ূ', '/uuvowelsigndeva': 'ू', '/uuvowelsigngujarati': 'ૂ',
- '/uvowelsignbengali': 'ু', '/uvowelsigndeva': 'ु',
- '/uvowelsigngujarati': 'ુ', '/v': 'v', '/vadeva': 'व', '/vagujarati':
- 'વ', '/vagurmukhi': 'ਵ', '/vakatakana': 'ヷ', '/vanedownfunc': '⍖',
- '/vaneleftfunc': '⍅', '/vanerightfunc': '⍆', '/vaneupfunc': '⍏',
- '/varikajudeospanish:hb': 'ﬞ', '/vav': 'ו', '/vav:hb': 'ו',
- '/vav_vav:hb': 'װ', '/vav_yod:hb': 'ױ', '/vavdagesh': 'וּ',
- '/vavdagesh65': 'וּ', '/vavdageshhebrew': 'וּ', '/vavhebrew': 'ו',
- '/vavholam': 'וֹ', '/vavholamhebrew': 'וֹ', '/vavvavhebrew': 'װ',
- '/vavwithdagesh:hb': 'וּ', '/vavwithholam:hb': 'וֹ', '/vavyodhebrew': 'ױ',
- '/vcircle': 'ⓥ', '/vcurl': 'ⱴ', '/vdiagonalstroke': 'ꝟ', '/vdotbelow':
- 'ṿ', '/ve.fina': 'ﯟ', '/ve.isol': 'ﯞ', '/ve:abovetonecandra': '᳴',
- '/ve:anusvaraantargomukhasign': 'ᳩ', '/ve:anusvarabahirgomukhasign':
- 'ᳪ', '/ve:anusvarasignlong': 'ᳯ', '/ve:anusvaraubhayatomukhasign': 'ᳱ',
- '/ve:anusvaravamagomukhasign': 'ᳫ',
- '/ve:anusvaravamagomukhawithtailsign': 'ᳬ', '/ve:ardhavisargasign': 'ᳲ',
- '/ve:atharvaindependentsvaritatone': '᳡', '/ve:atikramasign': '᳷',
- '/ve:belowtonecandra': '᳘', '/ve:dotbelowtone': '᳝',
- '/ve:hexiformanusvarasignlong': 'ᳮ', '/ve:jihvamuliyasign': 'ᳵ',
- '/ve:karshanatone': '᳐', '/ve:kathakaanudattatone': '᳜',
- '/ve:nihshvasasign': '᳓', '/ve:prenkhatone': '᳒',
- '/ve:rigkashmiriindependentsvaritatone': '᳠', '/ve:ringabovetone': '᳸',
- '/ve:ringabovetonedbl': '᳹', '/ve:rotatedardhavisargasign': 'ᳳ',
- '/ve:rthanganusvarasignlong': 'ᳰ', '/ve:sharatone': '᳑',
- '/ve:svaritatonedbl': '᳚', '/ve:svaritatonetpl': '᳛',
- '/ve:threedotsbelowtone': '᳟', '/ve:tiryaksign': '᳭',
- '/ve:twodotsbelowtone': '᳞', '/ve:upadhmaniyasign': 'ᳶ',
- '/ve:visargaanudattasign': '᳥', '/ve:visargaanudattasignreversed': '᳦',
- '/ve:visargaanudattawithtailsign': '᳨', '/ve:visargasvaritasign': '᳢',
- '/ve:visargaudattasign': '᳣', '/ve:visargaudattasignreversed': '᳤',
- '/ve:visargaudattawithtailsign': '᳧',
- '/ve:yajuraggravatedindependentsvaritatone': '᳕',
- '/ve:yajurindependentsvaritatone': '᳖',
- '/ve:yajurkathakaindependentsvaritaschroedertone': '᳙',
- '/ve:yajurkathakaindependentsvaritatone': '᳗',
- '/ve:yajurmidlinesvaritasign': '᳔', '/vecyr': 'в', '/vecyrillic': 'в',
- '/veh': 'ڤ', '/veh.fina': 'ﭫ', '/veh.init': 'ﭬ', '/veh.isol': 'ﭪ',
- '/veh.medi': 'ﭭ', '/veharabic': 'ڤ', '/vehfinalarabic': 'ﭫ',
- '/vehinitialarabic': 'ﭬ', '/vehmedialarabic': 'ﭭ', '/vekatakana': 'ヹ',
- '/vend': 'ꝩ', '/venus': '♀', '/versicle': '℣', '/vert:bracketwhiteleft':
- '︗', '/vert:brakcetwhiteright': '︘', '/vert:colon': '︓', '/vert:comma':
- '︐', '/vert:ellipsishor': '︙', '/vert:exclam': '︕',
- '/vert:ideographiccomma': '︑', '/vert:ideographicfullstop': '︒',
- '/vert:question': '︖', '/vert:semicolon': '︔', '/vertdblhorzsng': '╫',
- '/vertdblleftsng': '╢', '/vertdblrightsng': '╟', '/vertheavyhorzlight':
- '╂', '/vertheavyleftlight': '┨', '/vertheavyrightlight': '┠',
- '/verticalTrafficLight': 'Ὢ6', '/verticalbar': '|', '/verticalbardbl':
- '‖', '/verticalbarhorizontalstroke': '⟊',
- '/verticalbarwhitearrowonpedestalup': '⇭', '/verticalfourdots': '⁞',
- '/verticalideographiciterationmark': '〻', '/verticalkanarepeatmark':
- '〱', '/verticalkanarepeatmarklowerhalf': '〵',
- '/verticalkanarepeatmarkupperhalf': '〳',
- '/verticalkanarepeatwithvoicedsoundmark': '〲',
- '/verticalkanarepeatwithvoicedsoundmarkupperhalf': '〴',
- '/verticallineabovecmb': '̍', '/verticallinebelowcmb': '̩',
- '/verticallinelowmod': 'ˌ', '/verticallinemod': 'ˈ',
- '/verticalmalestroke': '⚨', '/verticalsdbltrokearrowleft': '⇺',
- '/verticalsdbltrokearrowleftright': '⇼', '/verticalsdbltrokearrowright':
- '⇻', '/verticalstrokearrowleft': '⇷', '/verticalstrokearrowleftright':
- '⇹', '/verticalstrokearrowright': '⇸', '/vertlighthorzheavy': '┿',
- '/vertlightleftheavy': '┥', '/vertlightrightheavy': '┝',
- '/vertsnghorzdbl': '╪', '/vertsngleftdbl': '╡', '/vertsngrightdbl': '╞',
- '/verymuchgreater': '⋙', '/verymuchless': '⋘', '/vesta': '⚶',
- '/vewarmenian': 'վ', '/vhook': 'ʋ', '/vibrationMode': '\u1f4f3',
- '/videoCamera': '\u1f4f9', '/videoGame': 'ἺE', '/videocassette':
- '\u1f4fC', '/viewdatasquare': '⌗', '/vikatakana': 'ヸ', '/violin': 'ἻB',
- '/viramabengali': '্', '/viramadeva': '्', '/viramagujarati': '્',
- '/virgo': '♍', '/visargabengali': 'ঃ', '/visargadeva': 'ः',
- '/visargagujarati': 'ઃ', '/visigothicz': 'ꝣ', '/vmonospace': 'v',
- '/voarmenian': 'ո', '/vodsquare': 'ἚC', '/voicediterationhiragana': 'ゞ',
- '/voicediterationkatakana': 'ヾ', '/voicedmarkkana': '゛',
- '/voicedmarkkanahalfwidth': '゙', '/voicingmod': 'ˬ', '/vokatakana': 'ヺ',
- '/volapukae': 'ꞛ', '/volapukoe': 'ꞝ', '/volapukue': 'ꞟ', '/volcano':
- 'ἰB', '/volleyball': 'Ἵ0', '/vovermfullwidth': '㏞', '/vowelVabove': 'ٚ',
- '/voweldotbelow': 'ٜ', '/vowelinvertedVabove': 'ٛ', '/vparen': '⒱',
- '/vparenthesized': '⒱', '/vrighthook': 'ⱱ', '/vssquare': 'ἙA',
- '/vtilde': 'ṽ', '/vturned': 'ʌ', '/vuhiragana': 'ゔ', '/vukatakana': 'ヴ',
- '/vwelsh': 'ỽ', '/vy': 'ꝡ', '/w': 'w', '/wacirclekatakana': '㋻',
- '/wacute': 'ẃ', '/waekorean': 'ㅙ', '/wahiragana': 'わ', '/wakatakana':
- 'ワ', '/wakatakanahalfwidth': 'ワ', '/wakorean': 'ㅘ',
- '/waningCrescentMoon': 'ἱ8', '/waningGibbousMoon': 'ἱ6', '/warning':
- '⚠', '/wasmallhiragana': 'ゎ', '/wasmallkatakana': 'ヮ', '/wastebasket':
- 'Ὕ1', '/watch': '⌚', '/waterBuffalo': 'ὀ3', '/waterCloset': 'ὫE',
- '/waterWave': 'ἰA', '/waterideographiccircled': '㊌',
- '/waterideographicparen': '㈬', '/watermelon': 'ἴ9', '/wattosquare': '㍗',
- '/wavedash': '〜', '/wavingBlackFlag': 'Ἷ4', '/wavingHandSign': 'ὄB',
- '/wavingWhiteFlag': 'Ἷ3', '/wavydash': '〰', '/wavyhamzabelow': 'ٟ',
- '/wavyline': '⌇', '/wavyunderscorevertical': '︴', '/waw': 'و',
- '/waw.fina': 'ﻮ', '/waw.isol': 'ﻭ', '/wawDigitThreeAbove': 'ݹ',
- '/wawDigitTwoAbove': 'ݸ', '/wawarabic': 'و', '/wawdotabove': 'ۏ',
- '/wawfinalarabic': 'ﻮ', '/wawhamza': 'ؤ', '/wawhamza.fina': 'ﺆ',
- '/wawhamza.isol': 'ﺅ', '/wawhamzaabovearabic': 'ؤ',
- '/wawhamzaabovefinalarabic': 'ﺆ', '/wawhighhamza': 'ٶ', '/wawring': 'ۄ',
- '/wawsmall': 'ۥ', '/wawtwodotsabove': 'ۊ', '/waxingCrescentMoon': 'ἱ2',
- '/waxingGibbousMoon': 'ἱ4', '/wbfullwidth': '㏝', '/wbsquare': '㏝',
- '/wcircle': 'ⓦ', '/wcircumflex': 'ŵ', '/wcsquare': 'ἔF',
- '/wcsquareblack': 'ἘF', '/wdieresis': 'ẅ', '/wdot': 'ẇ', '/wdotaccent':
- 'ẇ', '/wdotbelow': 'ẉ', '/wearyCatFace': 'ὤ0', '/wearyFace': 'ὢ9',
- '/wecirclekatakana': '㋽', '/wecyr': 'ԝ', '/wedding': 'Ὁ2',
- '/wehiragana': 'ゑ', '/weierstrass': '℘', '/weightLifter': 'ἼB',
- '/wekatakana': 'ヱ', '/wekorean': 'ㅞ', '/weokorean': 'ㅝ',
- '/westsyriaccross': '♰', '/wgrave': 'ẁ', '/whale': 'ὀB', '/wheelchair':
- '♿', '/wheelofdharma': '☸', '/whiteDownPointingBackhandIndex': 'ὄ7',
- '/whiteDownPointingLeftHandIndex': 'Ὑ7', '/whiteFlower': 'ὊE',
- '/whiteHardShellFloppyDisk': '\u1f5aB', '/whiteLatinCross': 'ὔ6',
- '/whiteLeftPointingBackhandIndex': 'ὄ8', '/whitePennant': 'Ἷ1',
- '/whiteRightPointingBackhandIndex': 'ὄ9', '/whiteSquareButton': 'ὓ3',
- '/whiteSun': 'ἲ3', '/whiteSunBehindCloud': 'ἲ5',
- '/whiteSunBehindCloudRain': 'ἲ6', '/whiteSunSmallCloud': 'ἲ4',
- '/whiteTouchtoneTelephone': 'ὗE', '/whiteUpPointingBackhandIndex': 'ὄ6',
- '/whitearrowdown': '⇩', '/whitearrowfromwallright': '⇰',
- '/whitearrowleft': '⇦', '/whitearrowonpedestalup': '⇫',
- '/whitearrowright': '⇨', '/whitearrowup': '⇧', '/whitearrowupdown': '⇳',
- '/whitearrowupfrombar': '⇪', '/whitebullet': '◦', '/whitecircle': '○',
- '/whitecircleinverse': '◙', '/whitecornerbracketleft': '『',
- '/whitecornerbracketleftvertical': '﹃', '/whitecornerbracketright': '』',
- '/whitecornerbracketrightvertical': '﹄', '/whitedblarrowonpedestalup':
- '⇯', '/whitedblarrowup': '⇮', '/whitediamond': '◇',
- '/whitediamondcontainingblacksmalldiamond': '◈',
- '/whitedownpointingsmalltriangle': '▿', '/whitedownpointingtriangle':
- '▽', '/whiteleftpointingsmalltriangle': '◃',
- '/whiteleftpointingtriangle': '◁', '/whitelenticularbracketleft': '〖',
- '/whitelenticularbracketright': '〗', '/whiterightpointingsmalltriangle':
- '▹', '/whiterightpointingtriangle': '▷', '/whitesesamedot': '﹆',
- '/whitesmallsquare': '▫', '/whitesmilingface': '☺', '/whitesquare': '□',
- '/whitesquarebracketleft': '〚', '/whitesquarebracketright': '〛',
- '/whitestar': '☆', '/whitetelephone': '☏',
- '/whitetortoiseshellbracketleft': '〘',
- '/whitetortoiseshellbracketright': '〙', '/whiteuppointingsmalltriangle':
- '▵', '/whiteuppointingtriangle': '△', '/whook': 'ⱳ',
- '/wicirclekatakana': '㋼', '/wigglylinevertical': '⸾', '/wignyan': 'ꦃ',
- '/wihiragana': 'ゐ', '/wikatakana': 'ヰ', '/wikorean': 'ㅟ',
- '/windBlowingFace': 'ἲC', '/windChime': 'Ἱ0', '/windupada': '꧆',
- '/wineGlass': 'ἷ7', '/winkingFace': 'ὠ9', '/wiredKeyboard': '\u1f5aE',
- '/wmonospace': 'w', '/wocirclekatakana': '㋾', '/wohiragana': 'を',
- '/wokatakana': 'ヲ', '/wokatakanahalfwidth': 'ヲ', '/wolfFace': 'ὃA',
- '/woman': '\u1f469', '/womanBunnyEars': '\u1f46F', '/womansBoots':
- '\u1f462', '/womansClothes': 'ὅA', '/womansHat': 'ὅ2', '/womansSandal':
- '\u1f461', '/womens': 'ὫA', '/won': '₩', '/wonmonospace': '₩',
- '/woodideographiccircled': '㊍', '/woodideographicparen': '㈭',
- '/wordjoiner': '\u2060', '/wordseparatormiddledot': '⸱', '/worldMap':
- 'ὟA', '/worriedFace': 'ὡF', '/wowaenthai': 'ว', '/wparen': '⒲',
- '/wparenthesized': '⒲', '/wrappedPresent': 'Ἰ1', '/wreathproduct': '≀',
- '/wrench': 'ὒ7', '/wring': 'ẘ', '/wsuperior': 'ʷ', '/wsupmod': 'ʷ',
- '/wturned': 'ʍ', '/wulumelikvowel': 'ꦷ', '/wuluvowel': 'ꦶ', '/wynn':
- 'ƿ', '/x': 'x', '/x.inferior': 'ₓ', '/xabovecmb': '̽', '/xatailcyr':
- 'ҳ', '/xbopomofo': 'ㄒ', '/xcircle': 'ⓧ', '/xdieresis': 'ẍ', '/xdot':
- 'ẋ', '/xdotaccent': 'ẋ', '/xeharmenian': 'խ', '/xi': 'ξ', '/xmonospace':
- 'x', '/xor': '⊻', '/xparen': '⒳', '/xparenthesized': '⒳', '/xsuperior':
- 'ˣ', '/xsupmod': 'ˣ', '/y': 'y', '/yaadosquare': '㍎', '/yaarusquare':
- '㍏', '/yabengali': 'য', '/yacirclekatakana': '㋳', '/yacute': 'ý',
- '/yacyr': 'я', '/yadeva': 'य', '/yaecyr': 'ԙ', '/yaekorean': 'ㅒ',
- '/yagujarati': 'ય', '/yagurmukhi': 'ਯ', '/yahiragana': 'や',
- '/yakatakana': 'ヤ', '/yakatakanahalfwidth': 'ヤ', '/yakorean': 'ㅑ',
- '/yamakkanthai': '๎', '/yangtonemod': '˫', '/yasmallhiragana': 'ゃ',
- '/yasmallkatakana': 'ャ', '/yasmallkatakanahalfwidth': 'ャ', '/yatcyr':
- 'ѣ', '/yatcyrillic': 'ѣ', '/ycircle': 'ⓨ', '/ycircumflex': 'ŷ',
- '/ydieresis': 'ÿ', '/ydot': 'ẏ', '/ydotaccent': 'ẏ', '/ydotbelow': 'ỵ',
- '/yeh': 'ي', '/yeh.fina': 'ﻲ', '/yeh.init': 'ﻳ',
- '/yeh.init_alefmaksura.fina': 'ﱙ', '/yeh.init_hah.fina': 'ﱖ',
- '/yeh.init_hah.medi': 'ﳛ', '/yeh.init_hamzaabove.medi_ae.fina': 'ﯬ',
- '/yeh.init_hamzaabove.medi_alef.fina': 'ﯪ',
- '/yeh.init_hamzaabove.medi_alefmaksura.fina': 'ﰃ',
- '/yeh.init_hamzaabove.medi_e.fina': 'ﯶ',
- '/yeh.init_hamzaabove.medi_e.medi': 'ﯸ',
- '/yeh.init_hamzaabove.medi_hah.fina': 'ﰁ',
- '/yeh.init_hamzaabove.medi_hah.medi': 'ﲘ',
- '/yeh.init_hamzaabove.medi_heh.medi': 'ﲛ',
- '/yeh.init_hamzaabove.medi_jeem.fina': 'ﰀ',
- '/yeh.init_hamzaabove.medi_jeem.medi': 'ﲗ',
- '/yeh.init_hamzaabove.medi_khah.medi': 'ﲙ',
- '/yeh.init_hamzaabove.medi_meem.fina': 'ﰂ',
- '/yeh.init_hamzaabove.medi_meem.medi': 'ﲚ',
- '/yeh.init_hamzaabove.medi_oe.fina': 'ﯲ',
- '/yeh.init_hamzaabove.medi_u.fina': 'ﯰ',
- '/yeh.init_hamzaabove.medi_waw.fina': 'ﯮ',
- '/yeh.init_hamzaabove.medi_yeh.fina': 'ﰄ',
- '/yeh.init_hamzaabove.medi_yu.fina': 'ﯴ', '/yeh.init_heh.medi': 'ﳞ',
- '/yeh.init_jeem.fina': 'ﱕ', '/yeh.init_jeem.medi': 'ﳚ',
- '/yeh.init_khah.fina': 'ﱗ', '/yeh.init_khah.medi': 'ﳜ',
- '/yeh.init_meem.fina': 'ﱘ', '/yeh.init_meem.medi': 'ﳝ',
- '/yeh.init_meem.medi_meem.medi': 'ﶝ', '/yeh.init_yeh.fina': 'ﱚ',
- '/yeh.isol': 'ﻱ', '/yeh.medi': 'ﻴ', '/yeh.medi_alefmaksura.fina': 'ﲕ',
- '/yeh.medi_hah.medi_yeh.fina': 'ﶮ', '/yeh.medi_hamzaabove.medi_ae.fina':
- 'ﯭ', '/yeh.medi_hamzaabove.medi_alef.fina': 'ﯫ',
- '/yeh.medi_hamzaabove.medi_alefmaksura.fina': 'ﱨ',
- '/yeh.medi_hamzaabove.medi_e.fina': 'ﯷ',
- '/yeh.medi_hamzaabove.medi_heh.medi': 'ﳠ',
- '/yeh.medi_hamzaabove.medi_meem.fina': 'ﱦ',
- '/yeh.medi_hamzaabove.medi_meem.medi': 'ﳟ',
- '/yeh.medi_hamzaabove.medi_noon.fina': 'ﱧ',
- '/yeh.medi_hamzaabove.medi_oe.fina': 'ﯳ',
- '/yeh.medi_hamzaabove.medi_reh.fina': 'ﱤ',
- '/yeh.medi_hamzaabove.medi_u.fina': 'ﯱ',
- '/yeh.medi_hamzaabove.medi_waw.fina': 'ﯯ',
- '/yeh.medi_hamzaabove.medi_yeh.fina': 'ﱩ',
- '/yeh.medi_hamzaabove.medi_yu.fina': 'ﯵ',
- '/yeh.medi_hamzaabove.medi_zain.fina': 'ﱥ', '/yeh.medi_heh.medi': 'ﳱ',
- '/yeh.medi_jeem.medi_yeh.fina': 'ﶯ', '/yeh.medi_meem.fina': 'ﲓ',
- '/yeh.medi_meem.medi': 'ﳰ', '/yeh.medi_meem.medi_meem.fina': 'ﶜ',
- '/yeh.medi_meem.medi_yeh.fina': 'ﶰ', '/yeh.medi_noon.fina': 'ﲔ',
- '/yeh.medi_reh.fina': 'ﲑ', '/yeh.medi_yeh.fina': 'ﲖ',
- '/yeh.medi_zain.fina': 'ﲒ', '/yehBarreeDigitThreeAbove': 'ݻ',
- '/yehBarreeDigitTwoAbove': 'ݺ', '/yehVabove': 'ێ', '/yehabove': 'ۧ',
- '/yeharabic': 'ي', '/yehbarree': 'ے', '/yehbarree.fina': 'ﮯ',
- '/yehbarree.isol': 'ﮮ', '/yehbarreearabic': 'ے',
- '/yehbarreefinalarabic': 'ﮯ', '/yehbarreehamza': 'ۓ',
- '/yehbarreehamza.fina': 'ﮱ', '/yehbarreehamza.isol': 'ﮰ', '/yehfarsi':
- 'ی', '/yehfarsi.fina': 'ﯽ', '/yehfarsi.init': 'ﯾ', '/yehfarsi.isol':
- 'ﯼ', '/yehfarsi.medi': 'ﯿ', '/yehfarsiinvertedV': 'ؽ',
- '/yehfarsithreedotsabove': 'ؿ', '/yehfarsitwodotsabove': 'ؾ',
- '/yehfinalarabic': 'ﻲ', '/yehhamza': 'ئ', '/yehhamza.fina': 'ﺊ',
- '/yehhamza.init': 'ﺋ', '/yehhamza.isol': 'ﺉ', '/yehhamza.medi': 'ﺌ',
- '/yehhamzaabovearabic': 'ئ', '/yehhamzaabovefinalarabic': 'ﺊ',
- '/yehhamzaaboveinitialarabic': 'ﺋ', '/yehhamzaabovemedialarabic': 'ﺌ',
- '/yehhighhamza': 'ٸ', '/yehinitialarabic': 'ﻳ', '/yehmedialarabic': 'ﻴ',
- '/yehmeeminitialarabic': 'ﳝ', '/yehmeemisolatedarabic': 'ﱘ',
- '/yehnoonfinalarabic': 'ﲔ', '/yehsmall': 'ۦ', '/yehtail': 'ۍ',
- '/yehthreedotsbelow': 'ۑ', '/yehthreedotsbelowarabic': 'ۑ', '/yekorean':
- 'ㅖ', '/yellowHeart': 'ὉB', '/yen': '¥', '/yenmonospace': '¥',
- '/yeokorean': 'ㅕ', '/yeorinhieuhkorean': 'ㆆ', '/yerachBenYomo:hb': '֪',
- '/yerahbenyomohebrew': '֪', '/yerahbenyomolefthebrew': '֪',
- '/yericyrillic': 'ы', '/yerudieresiscyrillic': 'ӹ', '/yesieungkorean':
- 'ㆁ', '/yesieungpansioskorean': 'ㆃ', '/yesieungsioskorean': 'ㆂ',
- '/yetiv:hb': '֚', '/yetivhebrew': '֚', '/ygrave': 'ỳ', '/yhoi': 'ỷ',
- '/yhook': 'ƴ', '/yhookabove': 'ỷ', '/yiarmenian': 'յ', '/yicyrillic':
- 'ї', '/yikorean': 'ㅢ', '/yintonemod': '˪', '/yinyang': '☯',
- '/yiwnarmenian': 'ւ', '/ylongcyr': 'ы', '/ylongdieresiscyr': 'ӹ',
- '/yloop': 'ỿ', '/ymacron': 'ȳ', '/ymonospace': 'y', '/yocirclekatakana':
- '㋵', '/yod': 'י', '/yod:hb': 'י', '/yod_yod:hb': 'ײ',
- '/yod_yod_patah:hb': 'ײַ', '/yoddagesh': 'יּ', '/yoddageshhebrew': 'יּ',
- '/yodhebrew': 'י', '/yodwithdagesh:hb': 'יּ', '/yodwithhiriq:hb': 'יִ',
- '/yodyodhebrew': 'ײ', '/yodyodpatahhebrew': 'ײַ', '/yogh': 'ȝ',
- '/yohiragana': 'よ', '/yoikorean': 'ㆉ', '/yokatakana': 'ヨ',
- '/yokatakanahalfwidth': 'ヨ', '/yokorean': 'ㅛ', '/yosmallhiragana': 'ょ',
- '/yosmallkatakana': 'ョ', '/yosmallkatakanahalfwidth': 'ョ', '/yot': 'ϳ',
- '/yotgreek': 'ϳ', '/yoyaekorean': 'ㆈ', '/yoyakorean': 'ㆇ', '/yoyakthai':
- 'ย', '/yoyingthai': 'ญ', '/yparen': '⒴', '/yparenthesized': '⒴',
- '/ypogegrammeni': 'ͺ', '/ypogegrammenigreekcmb': 'ͅ', '/yr': 'Ʀ',
- '/yring': 'ẙ', '/ystroke': 'ɏ', '/ysuperior': 'ʸ', '/ysupmod': 'ʸ',
- '/ytilde': 'ỹ', '/yturned': 'ʎ', '/yu.fina': 'ﯜ', '/yu.isol': 'ﯛ',
- '/yuansquare': '㍐', '/yucirclekatakana': '㋴', '/yucyr': 'ю',
- '/yuhiragana': 'ゆ', '/yuikorean': 'ㆌ', '/yukatakana': 'ユ',
- '/yukatakanahalfwidth': 'ユ', '/yukirghiz': 'ۉ', '/yukirghiz.fina': 'ﯣ',
- '/yukirghiz.isol': 'ﯢ', '/yukorean': 'ㅠ', '/yukrcyr': 'ї', '/yusbigcyr':
- 'ѫ', '/yusbigcyrillic': 'ѫ', '/yusbigiotifiedcyr': 'ѭ',
- '/yusbigiotifiedcyrillic': 'ѭ', '/yuslittlecyr': 'ѧ',
- '/yuslittlecyrillic': 'ѧ', '/yuslittleiotifiedcyr': 'ѩ',
- '/yuslittleiotifiedcyrillic': 'ѩ', '/yusmallhiragana': 'ゅ',
- '/yusmallkatakana': 'ュ', '/yusmallkatakanahalfwidth': 'ュ',
- '/yuyekorean': 'ㆋ', '/yuyeokorean': 'ㆊ', '/yyabengali': 'য়', '/yyadeva':
- 'य़', '/z': 'z', '/zaarmenian': 'զ', '/zacute': 'ź', '/zadeva': 'ज़',
- '/zagurmukhi': 'ਜ਼', '/zah': 'ظ', '/zah.fina': 'ﻆ', '/zah.init': 'ﻇ',
- '/zah.init_meem.fina': 'ﰨ', '/zah.init_meem.medi': 'ﲹ', '/zah.isol':
- 'ﻅ', '/zah.medi': 'ﻈ', '/zah.medi_meem.medi': 'ﴻ', '/zaharabic': 'ظ',
- '/zahfinalarabic': 'ﻆ', '/zahinitialarabic': 'ﻇ', '/zahiragana': 'ざ',
- '/zahmedialarabic': 'ﻈ', '/zain': 'ز', '/zain.fina': 'ﺰ', '/zain.isol':
- 'ﺯ', '/zainabove': 'ؗ', '/zainarabic': 'ز', '/zainfinalarabic': 'ﺰ',
- '/zakatakana': 'ザ', '/zaqefGadol:hb': '֕', '/zaqefQatan:hb': '֔',
- '/zaqefgadolhebrew': '֕', '/zaqefqatanhebrew': '֔', '/zarqa:hb': '֘',
- '/zarqahebrew': '֘', '/zayin': 'ז', '/zayin:hb': 'ז', '/zayindagesh':
- 'זּ', '/zayindageshhebrew': 'זּ', '/zayinhebrew': 'ז',
- '/zayinwithdagesh:hb': 'זּ', '/zbopomofo': 'ㄗ', '/zcaron': 'ž',
- '/zcircle': 'ⓩ', '/zcircumflex': 'ẑ', '/zcurl': 'ʑ', '/zdescender': 'ⱬ',
- '/zdot': 'ż', '/zdotaccent': 'ż', '/zdotbelow': 'ẓ', '/zecyr': 'з',
- '/zecyrillic': 'з', '/zedescendercyrillic': 'ҙ', '/zedieresiscyr': 'ӟ',
- '/zedieresiscyrillic': 'ӟ', '/zehiragana': 'ぜ', '/zekatakana': 'ゼ',
- '/zero': '0', '/zero.inferior': '₀', '/zero.superior': '⁰',
- '/zeroarabic': '٠', '/zerobengali': '০', '/zerocircle': '⓪',
- '/zerocircleblack': '⓿', '/zerocomma': 'ἐ1', '/zerodeva': '०',
- '/zerofar': '۰', '/zerofullstop': 'ἐ0', '/zerogujarati': '૦',
- '/zerogurmukhi': '੦', '/zerohackarabic': '٠', '/zeroinferior': '₀',
- '/zeromonospace': '0', '/zerooldstyle': '\uf730', '/zeropersian': '۰',
- '/zerosquareabove': '۠', '/zerosuperior': '⁰', '/zerothai': '๐',
- '/zerothirds': '↉', '/zerowidthjoiner': '\ufeff',
- '/zerowidthnobreakspace': '\ufeff', '/zerowidthnonjoiner': '\u200c',
- '/zerowidthspace': '\u200b', '/zeta': 'ζ', '/zetailcyr': 'ҙ',
- '/zhbopomofo': 'ㄓ', '/zhearmenian': 'ժ', '/zhebrevecyr': 'ӂ',
- '/zhebrevecyrillic': 'ӂ', '/zhecyr': 'ж', '/zhecyrillic': 'ж',
- '/zhedescendercyrillic': 'җ', '/zhedieresiscyr': 'ӝ',
- '/zhedieresiscyrillic': 'ӝ', '/zhetailcyr': 'җ', '/zhook': 'ȥ',
- '/zihiragana': 'じ', '/zikatakana': 'ジ', '/zildefunc': '⍬',
- '/zinorhebrew': '֮', '/zjekomicyr': 'ԅ', '/zlinebelow': 'ẕ',
- '/zmonospace': 'z', '/znotationbagmembership': '⋿', '/zohiragana': 'ぞ',
- '/zokatakana': 'ゾ', '/zparen': '⒵', '/zparenthesized': '⒵',
- '/zretroflex': 'ʐ', '/zretroflexhook': 'ʐ', '/zstroke': 'ƶ',
- '/zswashtail': 'ɀ', '/zuhiragana': 'ず', '/zukatakana': 'ズ', '/zwarakay':
- 'ٙ', '/angbracketleftBig': '⣨', '/angbracketleftBigg': '⟨',
- '/angbracketleftbig': '⟨', '/angbracketleftbigg': '⟨',
- '/angbracketrightBig': '⟩', '/angbracketrightBigg': '⟩',
- '/angbracketrightbig': '⟩', '/angbracketrightbigg': '⟩', '/arrowbt':
- '↓', '/arrowdblbt': '⇓', '/arrowdbltp': '⇑', '/arrowhookleft': '↪',
- '/arrowhookright': '↩', '/arrowtp': '↑', '/arrowvertexdbl': '\ued12',
- '/backslashBig': '\\', '/backslashBigg': '\\', '/backslashbig': '\\',
- '/backslashbigg': '\\', '/bracehtipdownleft': '\ued17',
- '/bracehtipdownright': '\ued18', '/bracehtipupleft': '\ued19',
- '/bracehtipupright': '\ued1a', '/braceleftBig': '{', '/braceleftBigg':
- '{', '/braceleftbig': '{', '/braceleftbigg': '{', '/bracerightBig': '}',
- '/bracerightBigg': '}', '/bracerightbig': '}', '/bracerightbigg': '}',
- '/bracketleftBig': '[', '/bracketleftBigg': '[', '/bracketleftbig': '[',
- '/bracketleftbigg': '[', '/bracketrightBig': ']', '/bracketrightBigg':
- ']', '/bracketrightbig': ']', '/bracketrightbigg': ']',
- '/ceilingleftBig': '⌈', '/ceilingleftBigg': '⌈', '/ceilingleftbig': '⌈',
- '/ceilingleftbigg': '⌈', '/ceilingrightBig': '⌉', '/ceilingrightBigg':
- '⌉', '/ceilingrightbig': '⌉', '/ceilingrightbigg': '⌉',
- '/circledotdisplay': '⨀', '/circledottext': '⨀',
- '/circlemultiplydisplay': '⨂', '/circlemultiplytext': '⨂',
- '/circleplusdisplay': '⨁', '/circleplustext': '⨁',
- '/contintegraldisplay': '∮', '/contintegraltext': '∮',
- '/coproductdisplay': '∐', '/coproducttext': '∐', '/floorleftBig': '⌊',
- '/floorleftBigg': '⌊', '/floorleftbig': '⌊', '/floorleftbigg': '⌊',
- '/floorrightBig': '⌋', '/floorrightBigg': '⌋', '/floorrightbig': '⌋',
- '/floorrightbigg': '⌋', '/hatwide': 'ˆ', '/hatwider': 'ˆ', '/hatwidest':
- 'ˆ', '/integraldisplay': '∫', '/integraltext': '∫',
- '/intersectiondisplay': '⋂', '/intersectiontext': '⋂',
- '/logicalanddisplay': '⋀', '/logicalandtext': '⋀', '/logicalordisplay':
- '⋁', '/logicalortext': '⋁', '/mapsto': '↦', '/parenleftBig': '(',
- '/parenleftBigg': '(', '/parenleftbig': '(', '/parenleftbigg': '(',
- '/parenrightBig': ')', '/parenrightBigg': ')', '/parenrightbig': ')',
- '/parenrightbigg': ')', '/productdisplay': '∏', '/producttext': '∏',
- '/radicalBig': '√', '/radicalBigg': '√', '/radicalbig': '√',
- '/radicalbigg': '√', '/radicalbt': '√', '/radicaltp': '\ued6a',
- '/radicalvertex': '\ued6b', '/slashBig': '/', '/slashBigg': '/',
- '/slashbig': '/', '/slashbigg': '/', '/summationdisplay': '∑',
- '/summationtext': '∑', '/tie': '⁀', '/tildewide': '˜', '/tildewider':
- '˜', '/tildewidest': '˜', '/uniondisplay': '⋃', '/unionmultidisplay':
- '⨄', '/unionmultitext': '⨄', '/unionsqdisplay': '⨆', '/unionsqtext':
- '⨆', '/uniontext': '⋃', '/vextenddouble': '\ued79', '/vextendsingle':
- '⏐', '/a1': '◁', '/a2': '⊴', '/a3': '▷', '/a4': '⊵', '/a40': '˂',
- '/a41': '˃', '/a42': '⌃', '/a43': '⌄', '/a48': '℧', '/a49': '⋈', '/a50':
- '□', '/a51': '◇', '/a58': '⁓', '/a59': '↝', '/a60': '⊏', '/a61': '⊐',
- '/d0': '↙', '/d1': '↙', '/d2': '↙', '/d3': '↙', '/d4': '↙', '/d5': '↙',
- '/d6': '↙', '/d7': '↓', '/d8': '↓', '/d9': '↓', '/d10': '↓', '/d11':
- '↓', '/d12': '↓', '/d13': '↓', '/d14': '↓', '/d15': '↓', '/d16': '↓',
- '/d17': '↓', '/d18': '↓', '/d19': '↓', '/d20': '↓', '/d21': '↓', '/d22':
- '↓', '/d23': '↓', '/d24': '↘', '/d25': '↘', '/d26': '↘', '/d27': '↘',
- '/d28': '↘', '/d29': '↘', '/d30': '↘', '/d31': '↘', '/d32': '↘', '/d33':
- '↘', '/d34': '↘', '/d35': '↘', '/d36': '↘', '/d37': '↘', '/d38': '↘',
- '/d39': '→', '/d40': '→', '/d41': '→', '/d42': '→', '/d43': '→', '/d44':
- '→', '/d45': '→', '/d46': '→', '/d47': '→', '/d48': '→', '/d49': '→',
- '/d50': '→', '/d51': '→', '/d52': '→', '/d53': '→', '/d54': '→', '/d55':
- '→', '/d56': '↗', '/d57': '↗', '/d58': '↗', '/d59': '↗', '/d60': '↗',
- '/d61': '↗', '/d62': '↗', '/d63': '↗', '/d64': '↗', '/d65': '↗', '/d66':
- '↗', '/d67': '↗', '/d68': '↗', '/d69': '↗', '/d70': '↗', '/d71': '↑',
- '/d72': '↑', '/d73': '↑', '/d74': '↑', '/d75': '↑', '/d76': '↑', '/d77':
- '↑', '/d78': '↑', '/d79': '↑', '/d80': '↑', '/d81': '↑', '/d82': '↑',
- '/d83': '↑', '/d84': '↑', '/d85': '↑', '/d86': '↑', '/d87': '↑', '/d88':
- '↖', '/d89': '↖', '/d90': '↖', '/d91': '↖', '/d92': '↖', '/d93': '↖',
- '/d94': '↖', '/d95': '↖', '/d96': '↖', '/d97': '↖', '/d98': '↖', '/d99':
- '↖', '/d100': '↖', '/d101': '↖', '/d102': '↖', '/d103': '←', '/d104':
- '←', '/d105': '←', '/d106': '←', '/d107': '←', '/d108': '←', '/d109':
- '←', '/d110': '←', '/d111': '←', '/d112': '←', '/d113': '←', '/d114':
- '←', '/d115': '←', '/d116': '←', '/d117': '←', '/d118': '←', '/d119':
- '←', '/d120': '↙', '/d121': '↙', '/d122': '↙', '/d123': '↙', '/d124':
- '↙', '/d125': '↙', '/d126': '↙', '/d127': '↙', '/Ifractur': 'ℑ',
- '/FFsmall': '\uf766', '/FFIsmall': '\uf766', '/FFLsmall': '\uf766',
- '/FIsmall': '\uf766', '/FLsmall': '\uf766', '/Germandblssmall':
- '\uf773', '/Ng': 'Ŋ', '/Rfractur': 'ℜ', '/SS': 'S', '/SSsmall':
- '\uf773', '/altselector': '\ud802', '/angbracketleft': '⟨',
- '/angbracketright': '⟩', '/arrowbothv': '↕', '/arrowdblbothv': '⇕',
- '/arrowleftbothalf': '↽', '/arrowlefttophalf': '↼', '/arrownortheast':
- '↗', '/arrownorthwest': '↖', '/arrowrightbothalf': '⇁',
- '/arrowrighttophalf': '⇀', '/arrowsoutheast': '↘', '/arrowsouthwest':
- '↙', '/ascendercompwordmark': '\ud80a', '/asteriskcentered': '∗',
- '/bardbl': '∥', '/capitalcompwordmark': '\ud809', '/circlecopyrt': '⃝',
- '/circledivide': '⊘', '/circleminus': '⊖', '/coproduct': '⨿', '/ct':
- 'c', '/cwm': '\u200c', '/dblbracketleft': '⟦', '/dblbracketright': '⟧',
- '/diamondmath': '⋄', '/emptyslot': '\ud801', '/epsilon1': 'ϵ',
- '/epsiloninv': '϶', '/equivasymptotic': '≍', '/flat': '♭', '/follows':
- '≻', '/followsequal': '⪰', '/followsorcurly': '≽', '/greatermuch': '≫',
- '/interrobangdown': '⸘', '/intersectionsq': '⊓', '/latticetop': '⊤',
- '/lessmuch': '≪', '/longdbls': 'ſ', '/longsh': 'ſ', '/longsi': 'ſ',
- '/longsl': 'ſ', '/longst': 'ſt', '/lscript': 'ℓ', '/natural': '♮',
- '/negationslash': '̸', '/ng': 'ŋ', '/owner': '∋', '/pertenthousand':
- '‱', '/pi1': 'ϖ', '/precedesequal': '⪯', '/precedesorcurly': '≼',
- '/prime': '′', '/rho1': 'ϱ', '/ringfitted': '\ud80d', '/sharp': '♯',
- '/similarequal': '≃', '/slurabove': '⌢', '/slurbelow': '⌣', '/st': 'st',
- '/subsetsqequal': '⊑', '/supersetsqequal': '⊒', '/triangle': '△',
- '/triangleinv': '▽', '/triangleleft': '◁', '/turnstileleft': '⊢',
- '/turnstileright': '⊣', '/twelveudash': '\ud80c', '/unionmulti': '⊎',
- '/unionsq': '⊔', '/vector': '⃗', '/visualspace': '␣', '/Dbar': 'Đ',
- '/compwordmark': '\u200c', '/dbar': 'đ', '/rangedash': '–',
- '/hyphenchar': '-', '/punctdash': '—', '/visiblespace': '␣', '/Yen':
- '¥', '/anticlockwise': '⟲', '/arrowparrleftright': '⇆',
- '/arrowparrrightleft': '⇄', '/arrowtailleft': '↢', '/arrowtailright':
- '↣', '/arrowtripleleft': '⇚', '/arrowtripleright': '⇛', '/check': '✓',
- '/circleR': '®', '/circleS': 'Ⓢ', '/circleasterisk': '⊛',
- '/circleequal': '⊜', '/circlering': '⊚', '/clockwise': '⟳',
- '/curlyleft': '↫', '/curlyright': '↬', '/dblarrowdwn': '⇊',
- '/dblarrowheadleft': '↞', '/dblarrowheadright': '↠', '/defines': '≜',
- '/diamondsolid': '♦', '/difference': '≏', '/downfall': '⋎',
- '/equaldotleftright': '≒', '/equaldotrightleft': '≓', '/equalorfollows':
- '⋟', '/equalsdots': '≑', '/followsorequal': '≿', '/forcesbar': '⊪',
- '/geomequivalent': '≎', '/greaterdbleqlless': '⪌', '/greaterdblequal':
- '≧', '/greaterlessequal': '⋛', '/greaterorapproxeql': '⪆',
- '/greaterorequalslant': '⩾', '/greaterorsimilar': '≳',
- '/harpoondownleft': '⇃', '/harpoondownright': '⇂', '/harpoonleftright':
- '⇌', '/harpoonrightleft': '⇋', '/harpoonupleft': '↿', '/harpoonupright':
- '↾', '/intercal': '⊺', '/lessdbleqlgreater': '⪋', '/lessdblequal': '≦',
- '/lessequalgreater': '⋚', '/lessorapproxeql': '⪅', '/lessorequalslant':
- '⩽', '/lessorsimilar': '≲', '/maltesecross': '✠', '/multiopenleft': '⋋',
- '/multiopenright': '⋌', '/orunderscore': '⊻', '/perpcorrespond': '⩞',
- '/primereverse': '‵', '/revasymptequal': '⋍', '/revsimilar': '∽',
- '/rightanglene': '⌝', '/rightanglenw': '⌜', '/rightanglese': '⌟',
- '/rightanglesw': '⌞', '/satisfies': '⊨', '/shiftleft': '↰',
- '/shiftright': '↱', '/square': '□', '/squaredot': '⊡', '/squareminus':
- '⊟', '/squaremultiply': '⊠', '/squareplus': '⊞', '/squaresolid': '■',
- '/squiggleleftright': '↭', '/squiggleright': '⇝', '/subsetdblequal':
- '⫅', '/supersetdbl': '⋑', '/supersetdblequal': '⫆', '/triangledownsld':
- '▼', '/triangleleftequal': '⊴', '/triangleleftsld': '◀',
- '/trianglerightequal': '⊵', '/trianglerightsld': '▶', '/trianglesolid':
- '▲', '/uprise': '⋏', '/Finv': 'Ⅎ', '/Gmir': '⅁', '/Omegainv': '℧',
- '/approxorequal': '≊', '/archleftdown': '↶', '/archrightdown': '↷',
- '/beth': 'ℶ', '/daleth': 'ℸ', '/dividemultiply': '⋇', '/downslope': '⧹',
- '/equalorsimilar': '≂', '/follownotdbleqv': '⪺', '/follownotslnteql':
- '⪶', '/followornoteqvlnt': '⋩', '/greaternotdblequal': '⪊',
- '/greaternotequal': '⪈', '/greaterornotdbleql': '≩',
- '/greaterornotequal': '≩', '/integerdivide': '∖', '/lessnotdblequal':
- '⪉', '/lessnotequal': '⪇', '/lessornotdbleql': '≨', '/lessornotequal':
- '≨', '/multicloseleft': '⋉', '/multicloseright': '⋊', '/notapproxequal':
- '≇', '/notarrowboth': '↮', '/notarrowleft': '↚', '/notarrowright': '↛',
- '/notbar': '∤', '/notdblarrowboth': '⇎', '/notdblarrowleft': '⇍',
- '/notdblarrowright': '⇏', '/notfollows': '⊁', '/notfollowsoreql': '⪰',
- '/notforces': '⊮', '/notforcesextra': '⊯', '/notgreaterdblequal': '≧',
- '/notgreaterequal': '≱', '/notgreaterorslnteql': '⩾',
- '/notlessdblequal': '≦', '/notlessequal': '≰', '/notlessorslnteql': '⩽',
- '/notprecedesoreql': '⪯', '/notsatisfies': '⊭', '/notsimilar': '≁',
- '/notsubseteql': '⊈', '/notsubsetordbleql': '⫅', '/notsubsetoreql': '⊊',
- '/notsuperseteql': '⊉', '/notsupersetordbleql': '⫆',
- '/notsupersetoreql': '⊋', '/nottriangeqlleft': '⋬',
- '/nottriangeqlright': '⋭', '/nottriangleleft': '⋪', '/nottriangleright':
- '⋫', '/notturnstile': '⊬', '/planckover2pi': 'ℏ', '/planckover2pi1':
- 'ℏ', '/precedenotdbleqv': '⪹', '/precedenotslnteql': '⪵',
- '/precedeornoteqvlnt': '⋨', '/subsetnoteql': '⊊', '/subsetornotdbleql':
- '⫋', '/supersetnoteql': '⊋', '/supersetornotdbleql': '⫌', '/upslope': '⧸'}
+# https://raw.githubusercontent.com/adobe-type-tools/agl-aglfn/master/glyphlist.txt
+
+# converted manually to python
+# Extended with data from GlyphNameFormatter:
+# https://github.com/LettError/glyphNameFormatter
+
+# -----------------------------------------------------------
+# Copyright 2002-2019 Adobe (http://www.adobe.com/).
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the
+# following conditions are met:
+#
+# Redistributions of source code must retain the above
+# copyright notice, this list of conditions and the following
+# disclaimer.
+#
+# Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials
+# provided with the distribution.
+#
+# Neither the name of Adobe nor the names of its contributors
+# may be used to endorse or promote products derived from this
+# software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# -----------------------------------------------------------
+# Name: Adobe Glyph List
+# Table version: 2.0
+# Date: September 20, 2002
+# URL: https://github.com/adobe-type-tools/agl-aglfn
+#
+# Format: two semicolon-delimited fields:
+# (1) glyph name--upper/lowercase letters and digits
+# (2) Unicode scalar value--four uppercase hexadecimal digits
+#
+adobe_glyphs = {
+ "/A": "\u0041",
+ "/AA": "\uA732",
+ "/AE": "\u00C6",
+ "/AEacute": "\u01FC",
+ "/AEmacron": "\u01E2",
+ "/AEsmall": "\uF7E6",
+ "/AO": "\uA734",
+ "/AU": "\uA736",
+ "/AV": "\uA738",
+ "/AVhorizontalbar": "\uA73A",
+ "/AY": "\uA73C",
+ "/Aacute": "\u00C1",
+ "/Aacutesmall": "\uF7E1",
+ "/Abreve": "\u0102",
+ "/Abreveacute": "\u1EAE",
+ "/Abrevecyr": "\u04D0",
+ "/Abrevecyrillic": "\u04D0",
+ "/Abrevedotbelow": "\u1EB6",
+ "/Abrevegrave": "\u1EB0",
+ "/Abrevehoi": "\u1EB2",
+ "/Abrevehookabove": "\u1EB2",
+ "/Abrevetilde": "\u1EB4",
+ "/Acaron": "\u01CD",
+ "/Acircle": "\u24B6",
+ "/Acircleblack": "\u1F150",
+ "/Acircumflex": "\u00C2",
+ "/Acircumflexacute": "\u1EA4",
+ "/Acircumflexdotbelow": "\u1EAC",
+ "/Acircumflexgrave": "\u1EA6",
+ "/Acircumflexhoi": "\u1EA8",
+ "/Acircumflexhookabove": "\u1EA8",
+ "/Acircumflexsmall": "\uF7E2",
+ "/Acircumflextilde": "\u1EAA",
+ "/Acute": "\uF6C9",
+ "/Acutesmall": "\uF7B4",
+ "/Acyr": "\u0410",
+ "/Acyrillic": "\u0410",
+ "/Adblgrave": "\u0200",
+ "/Adieresis": "\u00C4",
+ "/Adieresiscyr": "\u04D2",
+ "/Adieresiscyrillic": "\u04D2",
+ "/Adieresismacron": "\u01DE",
+ "/Adieresissmall": "\uF7E4",
+ "/Adot": "\u0226",
+ "/Adotbelow": "\u1EA0",
+ "/Adotmacron": "\u01E0",
+ "/Agrave": "\u00C0",
+ "/Agravedbl": "\u0200",
+ "/Agravesmall": "\uF7E0",
+ "/Ahoi": "\u1EA2",
+ "/Ahookabove": "\u1EA2",
+ "/Aiecyr": "\u04D4",
+ "/Aiecyrillic": "\u04D4",
+ "/Ainvertedbreve": "\u0202",
+ "/Akbar": "\uFDF3",
+ "/Alayhe": "\uFDF7",
+ "/Allah": "\uFDF2",
+ "/Alpha": "\u0391",
+ "/Alphaacute": "\u1FBB",
+ "/Alphaasper": "\u1F09",
+ "/Alphaasperacute": "\u1F0D",
+ "/Alphaasperacuteiotasub": "\u1F8D",
+ "/Alphaaspergrave": "\u1F0B",
+ "/Alphaaspergraveiotasub": "\u1F8B",
+ "/Alphaasperiotasub": "\u1F89",
+ "/Alphaaspertilde": "\u1F0F",
+ "/Alphaaspertildeiotasub": "\u1F8F",
+ "/Alphabreve": "\u1FB8",
+ "/Alphagrave": "\u1FBA",
+ "/Alphaiotasub": "\u1FBC",
+ "/Alphalenis": "\u1F08",
+ "/Alphalenisacute": "\u1F0C",
+ "/Alphalenisacuteiotasub": "\u1F8C",
+ "/Alphalenisgrave": "\u1F0A",
+ "/Alphalenisgraveiotasub": "\u1F8A",
+ "/Alphalenisiotasub": "\u1F88",
+ "/Alphalenistilde": "\u1F0E",
+ "/Alphalenistildeiotasub": "\u1F8E",
+ "/Alphatonos": "\u0386",
+ "/Alphawithmacron": "\u1FB9",
+ "/Amacron": "\u0100",
+ "/Amonospace": "\uFF21",
+ "/Aogonek": "\u0104",
+ "/Aparens": "\u1F110",
+ "/Aring": "\u00C5",
+ "/Aringacute": "\u01FA",
+ "/Aringbelow": "\u1E00",
+ "/Aringsmall": "\uF7E5",
+ "/Asmall": "\uF761",
+ "/Asquare": "\u1F130",
+ "/Asquareblack": "\u1F170",
+ "/Astroke": "\u023A",
+ "/Atilde": "\u00C3",
+ "/Atildesmall": "\uF7E3",
+ "/Aturned": "\u2C6F",
+ "/Ayahend": "\u06DD",
+ "/Aybarmenian": "\u0531",
+ "/B": "\u0042",
+ "/Bcircle": "\u24B7",
+ "/Bcircleblack": "\u1F151",
+ "/Bdot": "\u1E02",
+ "/Bdotaccent": "\u1E02",
+ "/Bdotbelow": "\u1E04",
+ "/Becyr": "\u0411",
+ "/Becyrillic": "\u0411",
+ "/Benarmenian": "\u0532",
+ "/Beta": "\u0392",
+ "/Bflourish": "\uA796",
+ "/Bhook": "\u0181",
+ "/BismillahArRahmanArRaheem": "\uFDFD",
+ "/Blinebelow": "\u1E06",
+ "/Bmonospace": "\uFF22",
+ "/Bparens": "\u1F111",
+ "/Brevesmall": "\uF6F4",
+ "/Bscript": "\u212C",
+ "/Bsmall": "\uF762",
+ "/Bsquare": "\u1F131",
+ "/Bsquareblack": "\u1F171",
+ "/Bstroke": "\u0243",
+ "/Btopbar": "\u0182",
+ "/C": "\u0043",
+ "/CDcircle": "\u1F12D",
+ "/Caarmenian": "\u053E",
+ "/Cacute": "\u0106",
+ "/Caron": "\uF6CA",
+ "/Caronsmall": "\uF6F5",
+ "/Cbar": "\uA792",
+ "/Ccaron": "\u010C",
+ "/Ccedilla": "\u00C7",
+ "/Ccedillaacute": "\u1E08",
+ "/Ccedillasmall": "\uF7E7",
+ "/Ccircle": "\u24B8",
+ "/Ccircleblack": "\u1F152",
+ "/Ccircumflex": "\u0108",
+ "/Cdblstruck": "\u2102",
+ "/Cdot": "\u010A",
+ "/Cdotaccent": "\u010A",
+ "/Cdotreversed": "\uA73E",
+ "/Cedillasmall": "\uF7B8",
+ "/Cfraktur": "\u212D",
+ "/Chaarmenian": "\u0549",
+ "/Cheabkhasiancyrillic": "\u04BC",
+ "/Cheabkhcyr": "\u04BC",
+ "/Cheabkhtailcyr": "\u04BE",
+ "/Checyr": "\u0427",
+ "/Checyrillic": "\u0427",
+ "/Chedescenderabkhasiancyrillic": "\u04BE",
+ "/Chedescendercyrillic": "\u04B6",
+ "/Chedieresiscyr": "\u04F4",
+ "/Chedieresiscyrillic": "\u04F4",
+ "/Cheharmenian": "\u0543",
+ "/Chekhakascyr": "\u04CB",
+ "/Chekhakassiancyrillic": "\u04CB",
+ "/Chetailcyr": "\u04B6",
+ "/Chevertcyr": "\u04B8",
+ "/Cheverticalstrokecyrillic": "\u04B8",
+ "/Chi": "\u03A7",
+ "/Chook": "\u0187",
+ "/Circumflexsmall": "\uF6F6",
+ "/Citaliccircle": "\u1F12B",
+ "/Cmonospace": "\uFF23",
+ "/Coarmenian": "\u0551",
+ "/Con": "\uA76E",
+ "/Cparens": "\u1F112",
+ "/Csmall": "\uF763",
+ "/Csquare": "\u1F132",
+ "/Csquareblack": "\u1F172",
+ "/Cstretched": "\u0297",
+ "/Cstroke": "\u023B",
+ "/Cuatrillo": "\uA72C",
+ "/Cuatrillocomma": "\uA72E",
+ "/D": "\u0044",
+ "/DZ": "\u01F1",
+ "/DZcaron": "\u01C4",
+ "/Daarmenian": "\u0534",
+ "/Dafrican": "\u0189",
+ "/Dcaron": "\u010E",
+ "/Dcedilla": "\u1E10",
+ "/Dchecyr": "\u052C",
+ "/Dcircle": "\u24B9",
+ "/Dcircleblack": "\u1F153",
+ "/Dcircumflexbelow": "\u1E12",
+ "/Dcroat": "\u0110",
+ "/Ddblstruckitalic": "\u2145",
+ "/Ddot": "\u1E0A",
+ "/Ddotaccent": "\u1E0A",
+ "/Ddotbelow": "\u1E0C",
+ "/Decyr": "\u0414",
+ "/Decyrillic": "\u0414",
+ "/Deicoptic": "\u03EE",
+ "/Dekomicyr": "\u0500",
+ "/Delta": "\u2206",
+ "/Deltagreek": "\u0394",
+ "/Dhook": "\u018A",
+ "/Dieresis": "\uF6CB",
+ "/DieresisAcute": "\uF6CC",
+ "/DieresisGrave": "\uF6CD",
+ "/Dieresissmall": "\uF7A8",
+ "/Digamma": "\u03DC",
+ "/Digammagreek": "\u03DC",
+ "/Digammapamphylian": "\u0376",
+ "/Dinsular": "\uA779",
+ "/Djecyr": "\u0402",
+ "/Djecyrillic": "\u0402",
+ "/Djekomicyr": "\u0502",
+ "/Dlinebelow": "\u1E0E",
+ "/Dmonospace": "\uFF24",
+ "/Dotaccentsmall": "\uF6F7",
+ "/Dparens": "\u1F113",
+ "/Dslash": "\u0110",
+ "/Dsmall": "\uF764",
+ "/Dsquare": "\u1F133",
+ "/Dsquareblack": "\u1F173",
+ "/Dtopbar": "\u018B",
+ "/Dz": "\u01F2",
+ "/Dzcaron": "\u01C5",
+ "/Dzeabkhasiancyrillic": "\u04E0",
+ "/Dzeabkhcyr": "\u04E0",
+ "/Dzecyr": "\u0405",
+ "/Dzecyrillic": "\u0405",
+ "/Dzhecyr": "\u040F",
+ "/Dzhecyrillic": "\u040F",
+ "/Dzjekomicyr": "\u0506",
+ "/Dzzhecyr": "\u052A",
+ "/E": "\u0045",
+ "/Eacute": "\u00C9",
+ "/Eacutesmall": "\uF7E9",
+ "/Ebreve": "\u0114",
+ "/Ecaron": "\u011A",
+ "/Ecedilla": "\u0228",
+ "/Ecedillabreve": "\u1E1C",
+ "/Echarmenian": "\u0535",
+ "/Ecircle": "\u24BA",
+ "/Ecircleblack": "\u1F154",
+ "/Ecircumflex": "\u00CA",
+ "/Ecircumflexacute": "\u1EBE",
+ "/Ecircumflexbelow": "\u1E18",
+ "/Ecircumflexdotbelow": "\u1EC6",
+ "/Ecircumflexgrave": "\u1EC0",
+ "/Ecircumflexhoi": "\u1EC2",
+ "/Ecircumflexhookabove": "\u1EC2",
+ "/Ecircumflexsmall": "\uF7EA",
+ "/Ecircumflextilde": "\u1EC4",
+ "/Ecyrillic": "\u0404",
+ "/Edblgrave": "\u0204",
+ "/Edieresis": "\u00CB",
+ "/Edieresissmall": "\uF7EB",
+ "/Edot": "\u0116",
+ "/Edotaccent": "\u0116",
+ "/Edotbelow": "\u1EB8",
+ "/Efcyr": "\u0424",
+ "/Efcyrillic": "\u0424",
+ "/Egrave": "\u00C8",
+ "/Egravedbl": "\u0204",
+ "/Egravesmall": "\uF7E8",
+ "/Egyptain": "\uA724",
+ "/Egyptalef": "\uA722",
+ "/Eharmenian": "\u0537",
+ "/Ehoi": "\u1EBA",
+ "/Ehookabove": "\u1EBA",
+ "/Eightroman": "\u2167",
+ "/Einvertedbreve": "\u0206",
+ "/Eiotifiedcyr": "\u0464",
+ "/Eiotifiedcyrillic": "\u0464",
+ "/Elcyr": "\u041B",
+ "/Elcyrillic": "\u041B",
+ "/Elevenroman": "\u216A",
+ "/Elhookcyr": "\u0512",
+ "/Elmiddlehookcyr": "\u0520",
+ "/Elsharptailcyr": "\u04C5",
+ "/Eltailcyr": "\u052E",
+ "/Emacron": "\u0112",
+ "/Emacronacute": "\u1E16",
+ "/Emacrongrave": "\u1E14",
+ "/Emcyr": "\u041C",
+ "/Emcyrillic": "\u041C",
+ "/Emonospace": "\uFF25",
+ "/Emsharptailcyr": "\u04CD",
+ "/Encyr": "\u041D",
+ "/Encyrillic": "\u041D",
+ "/Endescendercyrillic": "\u04A2",
+ "/Eng": "\u014A",
+ "/Engecyr": "\u04A4",
+ "/Enghecyrillic": "\u04A4",
+ "/Enhookcyr": "\u04C7",
+ "/Enhookcyrillic": "\u04C7",
+ "/Enhookleftcyr": "\u0528",
+ "/Enmiddlehookcyr": "\u0522",
+ "/Ensharptailcyr": "\u04C9",
+ "/Entailcyr": "\u04A2",
+ "/Eogonek": "\u0118",
+ "/Eopen": "\u0190",
+ "/Eparens": "\u1F114",
+ "/Epsilon": "\u0395",
+ "/Epsilonacute": "\u1FC9",
+ "/Epsilonasper": "\u1F19",
+ "/Epsilonasperacute": "\u1F1D",
+ "/Epsilonaspergrave": "\u1F1B",
+ "/Epsilongrave": "\u1FC8",
+ "/Epsilonlenis": "\u1F18",
+ "/Epsilonlenisacute": "\u1F1C",
+ "/Epsilonlenisgrave": "\u1F1A",
+ "/Epsilontonos": "\u0388",
+ "/Ercyr": "\u0420",
+ "/Ercyrillic": "\u0420",
+ "/Ereversed": "\u018E",
+ "/Ereversedcyr": "\u042D",
+ "/Ereversedcyrillic": "\u042D",
+ "/Ereverseddieresiscyr": "\u04EC",
+ "/Ereversedopen": "\uA7AB",
+ "/Ertickcyr": "\u048E",
+ "/Escript": "\u2130",
+ "/Escyr": "\u0421",
+ "/Escyrillic": "\u0421",
+ "/Esdescendercyrillic": "\u04AA",
+ "/Esh": "\u01A9",
+ "/Esmall": "\uF765",
+ "/Esmallturned": "\u2C7B",
+ "/Esquare": "\u1F134",
+ "/Esquareblack": "\u1F174",
+ "/Estailcyr": "\u04AA",
+ "/Estroke": "\u0246",
+ "/Et": "\uA76A",
+ "/Eta": "\u0397",
+ "/Etaacute": "\u1FCB",
+ "/Etaasper": "\u1F29",
+ "/Etaasperacute": "\u1F2D",
+ "/Etaasperacuteiotasub": "\u1F9D",
+ "/Etaaspergrave": "\u1F2B",
+ "/Etaaspergraveiotasub": "\u1F9B",
+ "/Etaasperiotasub": "\u1F99",
+ "/Etaaspertilde": "\u1F2F",
+ "/Etaaspertildeiotasub": "\u1F9F",
+ "/Etagrave": "\u1FCA",
+ "/Etaiotasub": "\u1FCC",
+ "/Etalenis": "\u1F28",
+ "/Etalenisacute": "\u1F2C",
+ "/Etalenisacuteiotasub": "\u1F9C",
+ "/Etalenisgrave": "\u1F2A",
+ "/Etalenisgraveiotasub": "\u1F9A",
+ "/Etalenisiotasub": "\u1F98",
+ "/Etalenistilde": "\u1F2E",
+ "/Etalenistildeiotasub": "\u1F9E",
+ "/Etarmenian": "\u0538",
+ "/Etatonos": "\u0389",
+ "/Eth": "\u00D0",
+ "/Ethsmall": "\uF7F0",
+ "/Etilde": "\u1EBC",
+ "/Etildebelow": "\u1E1A",
+ "/Eukrcyr": "\u0404",
+ "/Euro": "\u20AC",
+ "/Ezh": "\u01B7",
+ "/Ezhcaron": "\u01EE",
+ "/Ezhreversed": "\u01B8",
+ "/F": "\u0046",
+ "/Fcircle": "\u24BB",
+ "/Fcircleblack": "\u1F155",
+ "/Fdot": "\u1E1E",
+ "/Fdotaccent": "\u1E1E",
+ "/Feharmenian": "\u0556",
+ "/Feicoptic": "\u03E4",
+ "/Fhook": "\u0191",
+ "/Finsular": "\uA77B",
+ "/Fitacyr": "\u0472",
+ "/Fitacyrillic": "\u0472",
+ "/Fiveroman": "\u2164",
+ "/Fmonospace": "\uFF26",
+ "/Fourroman": "\u2163",
+ "/Fparens": "\u1F115",
+ "/Fscript": "\u2131",
+ "/Fsmall": "\uF766",
+ "/Fsquare": "\u1F135",
+ "/Fsquareblack": "\u1F175",
+ "/Fstroke": "\uA798",
+ "/Fturned": "\u2132",
+ "/G": "\u0047",
+ "/GBsquare": "\u3387",
+ "/Gacute": "\u01F4",
+ "/Gamma": "\u0393",
+ "/Gammaafrican": "\u0194",
+ "/Gammadblstruck": "\u213E",
+ "/Gangiacoptic": "\u03EA",
+ "/Gbreve": "\u011E",
+ "/Gcaron": "\u01E6",
+ "/Gcedilla": "\u0122",
+ "/Gcircle": "\u24BC",
+ "/Gcircleblack": "\u1F156",
+ "/Gcircumflex": "\u011C",
+ "/Gcommaaccent": "\u0122",
+ "/Gdot": "\u0120",
+ "/Gdotaccent": "\u0120",
+ "/Gecyr": "\u0413",
+ "/Gecyrillic": "\u0413",
+ "/Gehookcyr": "\u0494",
+ "/Gehookstrokecyr": "\u04FA",
+ "/Germandbls": "\u1E9E",
+ "/Gestrokecyr": "\u0492",
+ "/Getailcyr": "\u04F6",
+ "/Geupcyr": "\u0490",
+ "/Ghadarmenian": "\u0542",
+ "/Ghemiddlehookcyrillic": "\u0494",
+ "/Ghestrokecyrillic": "\u0492",
+ "/Gheupturncyrillic": "\u0490",
+ "/Ghook": "\u0193",
+ "/Ghooksmall": "\u029B",
+ "/Gimarmenian": "\u0533",
+ "/Ginsular": "\uA77D",
+ "/Ginsularturned": "\uA77E",
+ "/Gjecyr": "\u0403",
+ "/Gjecyrillic": "\u0403",
+ "/Glottalstop": "\u0241",
+ "/Gmacron": "\u1E20",
+ "/Gmonospace": "\uFF27",
+ "/Gobliquestroke": "\uA7A0",
+ "/Gparens": "\u1F116",
+ "/Grave": "\uF6CE",
+ "/Gravesmall": "\uF760",
+ "/Gsmall": "\uF767",
+ "/Gsmallhook": "\u029B",
+ "/Gsquare": "\u1F136",
+ "/Gsquareblack": "\u1F176",
+ "/Gstroke": "\u01E4",
+ "/Gturnedsans": "\u2141",
+ "/H": "\u0048",
+ "/H18533": "\u25CF",
+ "/H18543": "\u25AA",
+ "/H18551": "\u25AB",
+ "/H22073": "\u25A1",
+ "/HPsquare": "\u33CB",
+ "/HVsquare": "\u1F14A",
+ "/Haabkhasiancyrillic": "\u04A8",
+ "/Haabkhcyr": "\u04A8",
+ "/Hacyr": "\u0425",
+ "/Hadescendercyrillic": "\u04B2",
+ "/Hahookcyr": "\u04FC",
+ "/Hardcyr": "\u042A",
+ "/Hardsigncyrillic": "\u042A",
+ "/Hastrokecyr": "\u04FE",
+ "/Hbar": "\u0126",
+ "/Hbrevebelow": "\u1E2A",
+ "/Hcaron": "\u021E",
+ "/Hcedilla": "\u1E28",
+ "/Hcircle": "\u24BD",
+ "/Hcircleblack": "\u1F157",
+ "/Hcircumflex": "\u0124",
+ "/Hdblstruck": "\u210D",
+ "/Hdescender": "\u2C67",
+ "/Hdieresis": "\u1E26",
+ "/Hdot": "\u1E22",
+ "/Hdotaccent": "\u1E22",
+ "/Hdotbelow": "\u1E24",
+ "/Heng": "\uA726",
+ "/Heta": "\u0370",
+ "/Hfraktur": "\u210C",
+ "/Hgfullwidth": "\u32CC",
+ "/Hhalf": "\u2C75",
+ "/Hhook": "\uA7AA",
+ "/Hmonospace": "\uFF28",
+ "/Hoarmenian": "\u0540",
+ "/HonAA": "\u0611",
+ "/HonRA": "\u0612",
+ "/HonSAW": "\u0610",
+ "/Horicoptic": "\u03E8",
+ "/Hparens": "\u1F117",
+ "/Hscript": "\u210B",
+ "/Hsmall": "\uF768",
+ "/Hsquare": "\u1F137",
+ "/Hsquareblack": "\u1F177",
+ "/Hstrokemod": "\uA7F8",
+ "/Hturned": "\uA78D",
+ "/Hungarumlaut": "\uF6CF",
+ "/Hungarumlautsmall": "\uF6F8",
+ "/Hwair": "\u01F6",
+ "/Hzsquare": "\u3390",
+ "/I": "\u0049",
+ "/IAcyrillic": "\u042F",
+ "/ICsquareblack": "\u1F18B",
+ "/IJ": "\u0132",
+ "/IUcyrillic": "\u042E",
+ "/Iacute": "\u00CD",
+ "/Iacutesmall": "\uF7ED",
+ "/Ibreve": "\u012C",
+ "/Icaron": "\u01CF",
+ "/Icircle": "\u24BE",
+ "/Icircleblack": "\u1F158",
+ "/Icircumflex": "\u00CE",
+ "/Icircumflexsmall": "\uF7EE",
+ "/Icyr": "\u0418",
+ "/Icyrillic": "\u0406",
+ "/Idblgrave": "\u0208",
+ "/Idieresis": "\u00CF",
+ "/Idieresisacute": "\u1E2E",
+ "/Idieresiscyr": "\u04E4",
+ "/Idieresiscyrillic": "\u04E4",
+ "/Idieresissmall": "\uF7EF",
+ "/Idot": "\u0130",
+ "/Idotaccent": "\u0130",
+ "/Idotbelow": "\u1ECA",
+ "/Iebrevecyr": "\u04D6",
+ "/Iebrevecyrillic": "\u04D6",
+ "/Iecyr": "\u0415",
+ "/Iecyrillic": "\u0415",
+ "/Iegravecyr": "\u0400",
+ "/Ifraktur": "\u2111",
+ "/Igrave": "\u00CC",
+ "/Igravecyr": "\u040D",
+ "/Igravedbl": "\u0208",
+ "/Igravesmall": "\uF7EC",
+ "/Ihoi": "\u1EC8",
+ "/Ihookabove": "\u1EC8",
+ "/Iicyrillic": "\u0418",
+ "/Iinvertedbreve": "\u020A",
+ "/Iishortcyrillic": "\u0419",
+ "/Imacron": "\u012A",
+ "/Imacroncyr": "\u04E2",
+ "/Imacroncyrillic": "\u04E2",
+ "/Imonospace": "\uFF29",
+ "/Iniarmenian": "\u053B",
+ "/Iocyr": "\u0401",
+ "/Iocyrillic": "\u0401",
+ "/Iogonek": "\u012E",
+ "/Iota": "\u0399",
+ "/Iotaacute": "\u1FDB",
+ "/Iotaafrican": "\u0196",
+ "/Iotaasper": "\u1F39",
+ "/Iotaasperacute": "\u1F3D",
+ "/Iotaaspergrave": "\u1F3B",
+ "/Iotaaspertilde": "\u1F3F",
+ "/Iotabreve": "\u1FD8",
+ "/Iotadieresis": "\u03AA",
+ "/Iotagrave": "\u1FDA",
+ "/Iotalenis": "\u1F38",
+ "/Iotalenisacute": "\u1F3C",
+ "/Iotalenisgrave": "\u1F3A",
+ "/Iotalenistilde": "\u1F3E",
+ "/Iotatonos": "\u038A",
+ "/Iotawithmacron": "\u1FD9",
+ "/Iparens": "\u1F118",
+ "/Is": "\uA76C",
+ "/Iscript": "\u2110",
+ "/Ishortcyr": "\u0419",
+ "/Ishortsharptailcyr": "\u048A",
+ "/Ismall": "\uF769",
+ "/Isquare": "\u1F138",
+ "/Isquareblack": "\u1F178",
+ "/Istroke": "\u0197",
+ "/Itilde": "\u0128",
+ "/Itildebelow": "\u1E2C",
+ "/Iukrcyr": "\u0406",
+ "/Izhitsacyr": "\u0474",
+ "/Izhitsacyrillic": "\u0474",
+ "/Izhitsadblgravecyrillic": "\u0476",
+ "/Izhitsagravedblcyr": "\u0476",
+ "/J": "\u004A",
+ "/Jaarmenian": "\u0541",
+ "/Jallajalalouhou": "\uFDFB",
+ "/Jcircle": "\u24BF",
+ "/Jcircleblack": "\u1F159",
+ "/Jcircumflex": "\u0134",
+ "/Jcrossed-tail": "\uA7B2",
+ "/Jecyr": "\u0408",
+ "/Jecyrillic": "\u0408",
+ "/Jheharmenian": "\u054B",
+ "/Jmonospace": "\uFF2A",
+ "/Jparens": "\u1F119",
+ "/Jsmall": "\uF76A",
+ "/Jsquare": "\u1F139",
+ "/Jsquareblack": "\u1F179",
+ "/Jstroke": "\u0248",
+ "/K": "\u004B",
+ "/KBsquare": "\u3385",
+ "/KKsquare": "\u33CD",
+ "/KORONIS": "\u1FBD",
+ "/Kaaleutcyr": "\u051E",
+ "/Kabashkcyr": "\u04A0",
+ "/Kabashkircyrillic": "\u04A0",
+ "/Kacute": "\u1E30",
+ "/Kacyr": "\u041A",
+ "/Kacyrillic": "\u041A",
+ "/Kadescendercyrillic": "\u049A",
+ "/Kahookcyr": "\u04C3",
+ "/Kahookcyrillic": "\u04C3",
+ "/Kaisymbol": "\u03CF",
+ "/Kappa": "\u039A",
+ "/Kastrokecyr": "\u049E",
+ "/Kastrokecyrillic": "\u049E",
+ "/Katailcyr": "\u049A",
+ "/Kaverticalstrokecyr": "\u049C",
+ "/Kaverticalstrokecyrillic": "\u049C",
+ "/Kcaron": "\u01E8",
+ "/Kcedilla": "\u0136",
+ "/Kcircle": "\u24C0",
+ "/Kcircleblack": "\u1F15A",
+ "/Kcommaaccent": "\u0136",
+ "/Kdescender": "\u2C69",
+ "/Kdiagonalstroke": "\uA742",
+ "/Kdotbelow": "\u1E32",
+ "/Keharmenian": "\u0554",
+ "/Kenarmenian": "\u053F",
+ "/Khacyrillic": "\u0425",
+ "/Kheicoptic": "\u03E6",
+ "/Khook": "\u0198",
+ "/Kjecyr": "\u040C",
+ "/Kjecyrillic": "\u040C",
+ "/Klinebelow": "\u1E34",
+ "/Kmonospace": "\uFF2B",
+ "/Kobliquestroke": "\uA7A2",
+ "/Koppa": "\u03DE",
+ "/Koppaarchaic": "\u03D8",
+ "/Koppacyr": "\u0480",
+ "/Koppacyrillic": "\u0480",
+ "/Koppagreek": "\u03DE",
+ "/Kparens": "\u1F11A",
+ "/Ksicyr": "\u046E",
+ "/Ksicyrillic": "\u046E",
+ "/Ksmall": "\uF76B",
+ "/Ksquare": "\u1F13A",
+ "/Ksquareblack": "\u1F17A",
+ "/Kstroke": "\uA740",
+ "/Kstrokediagonalstroke": "\uA744",
+ "/Kturned": "\uA7B0",
+ "/L": "\u004C",
+ "/LJ": "\u01C7",
+ "/LL": "\uF6BF",
+ "/LLwelsh": "\u1EFA",
+ "/LTDfullwidth": "\u32CF",
+ "/Lacute": "\u0139",
+ "/Lambda": "\u039B",
+ "/Lbar": "\u023D",
+ "/Lbelt": "\uA7AD",
+ "/Lbroken": "\uA746",
+ "/Lcaron": "\u013D",
+ "/Lcedilla": "\u013B",
+ "/Lcircle": "\u24C1",
+ "/Lcircleblack": "\u1F15B",
+ "/Lcircumflexbelow": "\u1E3C",
+ "/Lcommaaccent": "\u013B",
+ "/Ldblbar": "\u2C60",
+ "/Ldot": "\u013F",
+ "/Ldotaccent": "\u013F",
+ "/Ldotbelow": "\u1E36",
+ "/Ldotbelowmacron": "\u1E38",
+ "/Lhacyr": "\u0514",
+ "/Liwnarmenian": "\u053C",
+ "/Lj": "\u01C8",
+ "/Ljecyr": "\u0409",
+ "/Ljecyrillic": "\u0409",
+ "/Ljekomicyr": "\u0508",
+ "/Llinebelow": "\u1E3A",
+ "/Lmacrondot": "\u1E38",
+ "/Lmiddletilde": "\u2C62",
+ "/Lmonospace": "\uFF2C",
+ "/Lparens": "\u1F11B",
+ "/Lreversedsans": "\u2143",
+ "/Lscript": "\u2112",
+ "/Lslash": "\u0141",
+ "/Lslashsmall": "\uF6F9",
+ "/Lsmall": "\uF76C",
+ "/Lsquare": "\u1F13B",
+ "/Lsquareblack": "\u1F17B",
+ "/Lstroke": "\uA748",
+ "/Lturned": "\uA780",
+ "/Lturnedsans": "\u2142",
+ "/M": "\u004D",
+ "/MBsquare": "\u3386",
+ "/MVsquare": "\u1F14B",
+ "/Macron": "\uF6D0",
+ "/Macronsmall": "\uF7AF",
+ "/Macute": "\u1E3E",
+ "/Mcircle": "\u24C2",
+ "/Mcircleblack": "\u1F15C",
+ "/Mdot": "\u1E40",
+ "/Mdotaccent": "\u1E40",
+ "/Mdotbelow": "\u1E42",
+ "/Menarmenian": "\u0544",
+ "/Mhook": "\u2C6E",
+ "/Mmonospace": "\uFF2D",
+ "/Mohammad": "\uFDF4",
+ "/Mparens": "\u1F11C",
+ "/Mscript": "\u2133",
+ "/Msmall": "\uF76D",
+ "/Msquare": "\u1F13C",
+ "/Msquareblack": "\u1F17C",
+ "/Mturned": "\u019C",
+ "/Mturnedsmall": "\uA7FA",
+ "/Mu": "\u039C",
+ "/N": "\u004E",
+ "/NJ": "\u01CA",
+ "/Nacute": "\u0143",
+ "/Ncaron": "\u0147",
+ "/Ncedilla": "\u0145",
+ "/Ncircle": "\u24C3",
+ "/Ncircleblack": "\u1F15D",
+ "/Ncircumflexbelow": "\u1E4A",
+ "/Ncommaaccent": "\u0145",
+ "/Ndblstruck": "\u2115",
+ "/Ndescender": "\uA790",
+ "/Ndot": "\u1E44",
+ "/Ndotaccent": "\u1E44",
+ "/Ndotbelow": "\u1E46",
+ "/Ngrave": "\u01F8",
+ "/Nhookleft": "\u019D",
+ "/Nineroman": "\u2168",
+ "/Nj": "\u01CB",
+ "/Njecyr": "\u040A",
+ "/Njecyrillic": "\u040A",
+ "/Njekomicyr": "\u050A",
+ "/Nlinebelow": "\u1E48",
+ "/Nlongrightleg": "\u0220",
+ "/Nmonospace": "\uFF2E",
+ "/Nobliquestroke": "\uA7A4",
+ "/Nowarmenian": "\u0546",
+ "/Nparens": "\u1F11D",
+ "/Nsmall": "\uF76E",
+ "/Nsquare": "\u1F13D",
+ "/Nsquareblack": "\u1F17D",
+ "/Ntilde": "\u00D1",
+ "/Ntildesmall": "\uF7F1",
+ "/Nu": "\u039D",
+ "/O": "\u004F",
+ "/OE": "\u0152",
+ "/OEsmall": "\uF6FA",
+ "/OO": "\uA74E",
+ "/Oacute": "\u00D3",
+ "/Oacutesmall": "\uF7F3",
+ "/Obar": "\u019F",
+ "/Obarcyr": "\u04E8",
+ "/Obardieresiscyr": "\u04EA",
+ "/Obarredcyrillic": "\u04E8",
+ "/Obarreddieresiscyrillic": "\u04EA",
+ "/Obreve": "\u014E",
+ "/Ocaron": "\u01D1",
+ "/Ocenteredtilde": "\u019F",
+ "/Ocircle": "\u24C4",
+ "/Ocircleblack": "\u1F15E",
+ "/Ocircumflex": "\u00D4",
+ "/Ocircumflexacute": "\u1ED0",
+ "/Ocircumflexdotbelow": "\u1ED8",
+ "/Ocircumflexgrave": "\u1ED2",
+ "/Ocircumflexhoi": "\u1ED4",
+ "/Ocircumflexhookabove": "\u1ED4",
+ "/Ocircumflexsmall": "\uF7F4",
+ "/Ocircumflextilde": "\u1ED6",
+ "/Ocyr": "\u041E",
+ "/Ocyrillic": "\u041E",
+ "/Odblacute": "\u0150",
+ "/Odblgrave": "\u020C",
+ "/Odieresis": "\u00D6",
+ "/Odieresiscyr": "\u04E6",
+ "/Odieresiscyrillic": "\u04E6",
+ "/Odieresismacron": "\u022A",
+ "/Odieresissmall": "\uF7F6",
+ "/Odot": "\u022E",
+ "/Odotbelow": "\u1ECC",
+ "/Odotmacron": "\u0230",
+ "/Ogoneksmall": "\uF6FB",
+ "/Ograve": "\u00D2",
+ "/Ogravedbl": "\u020C",
+ "/Ogravesmall": "\uF7F2",
+ "/Oharmenian": "\u0555",
+ "/Ohm": "\u2126",
+ "/Ohoi": "\u1ECE",
+ "/Ohookabove": "\u1ECE",
+ "/Ohorn": "\u01A0",
+ "/Ohornacute": "\u1EDA",
+ "/Ohorndotbelow": "\u1EE2",
+ "/Ohorngrave": "\u1EDC",
+ "/Ohornhoi": "\u1EDE",
+ "/Ohornhookabove": "\u1EDE",
+ "/Ohorntilde": "\u1EE0",
+ "/Ohungarumlaut": "\u0150",
+ "/Oi": "\u01A2",
+ "/Oinvertedbreve": "\u020E",
+ "/Oloop": "\uA74C",
+ "/Omacron": "\u014C",
+ "/Omacronacute": "\u1E52",
+ "/Omacrongrave": "\u1E50",
+ "/Omega": "\u2126",
+ "/Omegaacute": "\u1FFB",
+ "/Omegaasper": "\u1F69",
+ "/Omegaasperacute": "\u1F6D",
+ "/Omegaasperacuteiotasub": "\u1FAD",
+ "/Omegaaspergrave": "\u1F6B",
+ "/Omegaaspergraveiotasub": "\u1FAB",
+ "/Omegaasperiotasub": "\u1FA9",
+ "/Omegaaspertilde": "\u1F6F",
+ "/Omegaaspertildeiotasub": "\u1FAF",
+ "/Omegacyr": "\u0460",
+ "/Omegacyrillic": "\u0460",
+ "/Omegagrave": "\u1FFA",
+ "/Omegagreek": "\u03A9",
+ "/Omegaiotasub": "\u1FFC",
+ "/Omegalenis": "\u1F68",
+ "/Omegalenisacute": "\u1F6C",
+ "/Omegalenisacuteiotasub": "\u1FAC",
+ "/Omegalenisgrave": "\u1F6A",
+ "/Omegalenisgraveiotasub": "\u1FAA",
+ "/Omegalenisiotasub": "\u1FA8",
+ "/Omegalenistilde": "\u1F6E",
+ "/Omegalenistildeiotasub": "\u1FAE",
+ "/Omegaroundcyr": "\u047A",
+ "/Omegaroundcyrillic": "\u047A",
+ "/Omegatitlocyr": "\u047C",
+ "/Omegatitlocyrillic": "\u047C",
+ "/Omegatonos": "\u038F",
+ "/Omicron": "\u039F",
+ "/Omicronacute": "\u1FF9",
+ "/Omicronasper": "\u1F49",
+ "/Omicronasperacute": "\u1F4D",
+ "/Omicronaspergrave": "\u1F4B",
+ "/Omicrongrave": "\u1FF8",
+ "/Omicronlenis": "\u1F48",
+ "/Omicronlenisacute": "\u1F4C",
+ "/Omicronlenisgrave": "\u1F4A",
+ "/Omicrontonos": "\u038C",
+ "/Omonospace": "\uFF2F",
+ "/Oneroman": "\u2160",
+ "/Oogonek": "\u01EA",
+ "/Oogonekmacron": "\u01EC",
+ "/Oopen": "\u0186",
+ "/Oparens": "\u1F11E",
+ "/Oslash": "\u00D8",
+ "/Oslashacute": "\u01FE",
+ "/Oslashsmall": "\uF7F8",
+ "/Osmall": "\uF76F",
+ "/Osquare": "\u1F13E",
+ "/Osquareblack": "\u1F17E",
+ "/Ostroke": "\uA74A",
+ "/Ostrokeacute": "\u01FE",
+ "/Otcyr": "\u047E",
+ "/Otcyrillic": "\u047E",
+ "/Otilde": "\u00D5",
+ "/Otildeacute": "\u1E4C",
+ "/Otildedieresis": "\u1E4E",
+ "/Otildemacron": "\u022C",
+ "/Otildesmall": "\uF7F5",
+ "/Ou": "\u0222",
+ "/P": "\u0050",
+ "/PAsquareblack": "\u1F18C",
+ "/PPVsquare": "\u1F14E",
+ "/Pacute": "\u1E54",
+ "/Palochkacyr": "\u04C0",
+ "/Pcircle": "\u24C5",
+ "/Pcircleblack": "\u1F15F",
+ "/Pcrosssquareblack": "\u1F18A",
+ "/Pdblstruck": "\u2119",
+ "/Pdot": "\u1E56",
+ "/Pdotaccent": "\u1E56",
+ "/Pecyr": "\u041F",
+ "/Pecyrillic": "\u041F",
+ "/Peharmenian": "\u054A",
+ "/Pehookcyr": "\u04A6",
+ "/Pemiddlehookcyrillic": "\u04A6",
+ "/Petailcyr": "\u0524",
+ "/Pflourish": "\uA752",
+ "/Phi": "\u03A6",
+ "/Phook": "\u01A4",
+ "/Pi": "\u03A0",
+ "/Pidblstruck": "\u213F",
+ "/Piwrarmenian": "\u0553",
+ "/Pmonospace": "\uFF30",
+ "/Pparens": "\u1F11F",
+ "/Psi": "\u03A8",
+ "/Psicyr": "\u0470",
+ "/Psicyrillic": "\u0470",
+ "/Psmall": "\uF770",
+ "/Psquare": "\u1F13F",
+ "/Psquareblack": "\u1F17F",
+ "/Pstroke": "\u2C63",
+ "/Pstrokedescender": "\uA750",
+ "/Ptail": "\uA754",
+ "/Q": "\u0051",
+ "/Qacyr": "\u051A",
+ "/QalaUsedAsKoranicStopSign": "\uFDF1",
+ "/Qcircle": "\u24C6",
+ "/Qcircleblack": "\u1F160",
+ "/Qdblstruck": "\u211A",
+ "/Qdiagonalstroke": "\uA758",
+ "/Qmonospace": "\uFF31",
+ "/Qparens": "\u1F120",
+ "/Qrotated": "\u213A",
+ "/Qsmall": "\uF771",
+ "/Qsmallhooktail": "\u024A",
+ "/Qsquare": "\u1F140",
+ "/Qsquareblack": "\u1F180",
+ "/Qstrokedescender": "\uA756",
+ "/R": "\u0052",
+ "/Raarmenian": "\u054C",
+ "/Racute": "\u0154",
+ "/Rasoul": "\uFDF6",
+ "/Rcaron": "\u0158",
+ "/Rcedilla": "\u0156",
+ "/Rcircle": "\u24C7",
+ "/Rcircleblack": "\u1F161",
+ "/Rcommaaccent": "\u0156",
+ "/Rdblgrave": "\u0210",
+ "/Rdblstruck": "\u211D",
+ "/Rdot": "\u1E58",
+ "/Rdotaccent": "\u1E58",
+ "/Rdotbelow": "\u1E5A",
+ "/Rdotbelowmacron": "\u1E5C",
+ "/Reharmenian": "\u0550",
+ "/Reverseddottedsigmalunatesymbol": "\u03FF",
+ "/Reversedzecyr": "\u0510",
+ "/Rfraktur": "\u211C",
+ "/Rgravedbl": "\u0210",
+ "/Rhacyr": "\u0516",
+ "/Rho": "\u03A1",
+ "/Rhoasper": "\u1FEC",
+ "/Ringsmall": "\uF6FC",
+ "/Rinsular": "\uA782",
+ "/Rinvertedbreve": "\u0212",
+ "/Rinvertedsmall": "\u0281",
+ "/Ritaliccircle": "\u1F12C",
+ "/Rlinebelow": "\u1E5E",
+ "/Rmacrondot": "\u1E5C",
+ "/Rmonospace": "\uFF32",
+ "/Robliquestroke": "\uA7A6",
+ "/Rparens": "\u1F121",
+ "/Rrotunda": "\uA75A",
+ "/Rscript": "\u211B",
+ "/Rsmall": "\uF772",
+ "/Rsmallinverted": "\u0281",
+ "/Rsmallinvertedsuperior": "\u02B6",
+ "/Rsquare": "\u1F141",
+ "/Rsquareblack": "\u1F181",
+ "/Rstroke": "\u024C",
+ "/Rsupinvertedmod": "\u02B6",
+ "/Rtail": "\u2C64",
+ "/RubElHizbstart": "\u06DE",
+ "/Rumrotunda": "\uA75C",
+ "/Rumsmall": "\uA776",
+ "/S": "\u0053",
+ "/SAsquareblack": "\u1F18D",
+ "/SDsquare": "\u1F14C",
+ "/SF010000": "\u250C",
+ "/SF020000": "\u2514",
+ "/SF030000": "\u2510",
+ "/SF040000": "\u2518",
+ "/SF050000": "\u253C",
+ "/SF060000": "\u252C",
+ "/SF070000": "\u2534",
+ "/SF080000": "\u251C",
+ "/SF090000": "\u2524",
+ "/SF100000": "\u2500",
+ "/SF110000": "\u2502",
+ "/SF190000": "\u2561",
+ "/SF200000": "\u2562",
+ "/SF210000": "\u2556",
+ "/SF220000": "\u2555",
+ "/SF230000": "\u2563",
+ "/SF240000": "\u2551",
+ "/SF250000": "\u2557",
+ "/SF260000": "\u255D",
+ "/SF270000": "\u255C",
+ "/SF280000": "\u255B",
+ "/SF360000": "\u255E",
+ "/SF370000": "\u255F",
+ "/SF380000": "\u255A",
+ "/SF390000": "\u2554",
+ "/SF400000": "\u2569",
+ "/SF410000": "\u2566",
+ "/SF420000": "\u2560",
+ "/SF430000": "\u2550",
+ "/SF440000": "\u256C",
+ "/SF450000": "\u2567",
+ "/SF460000": "\u2568",
+ "/SF470000": "\u2564",
+ "/SF480000": "\u2565",
+ "/SF490000": "\u2559",
+ "/SF500000": "\u2558",
+ "/SF510000": "\u2552",
+ "/SF520000": "\u2553",
+ "/SF530000": "\u256B",
+ "/SF540000": "\u256A",
+ "/SSsquare": "\u1F14D",
+ "/Sacute": "\u015A",
+ "/Sacutedotaccent": "\u1E64",
+ "/Safha": "\u0603",
+ "/Sajdah": "\u06E9",
+ "/Salam": "\uFDF5",
+ "/Salla": "\uFDF9",
+ "/SallaUsedAsKoranicStopSign": "\uFDF0",
+ "/SallallahouAlayheWasallam": "\uFDFA",
+ "/Saltillo": "\uA78B",
+ "/Sampi": "\u03E0",
+ "/Sampiarchaic": "\u0372",
+ "/Sampigreek": "\u03E0",
+ "/San": "\u03FA",
+ "/Sanah": "\u0601",
+ "/Scaron": "\u0160",
+ "/Scarondot": "\u1E66",
+ "/Scarondotaccent": "\u1E66",
+ "/Scaronsmall": "\uF6FD",
+ "/Scedilla": "\u015E",
+ "/Schwa": "\u018F",
+ "/Schwacyr": "\u04D8",
+ "/Schwacyrillic": "\u04D8",
+ "/Schwadieresiscyr": "\u04DA",
+ "/Schwadieresiscyrillic": "\u04DA",
+ "/Scircle": "\u24C8",
+ "/Scircleblack": "\u1F162",
+ "/Scircumflex": "\u015C",
+ "/Scommaaccent": "\u0218",
+ "/Scriptg": "\uA7AC",
+ "/Sdot": "\u1E60",
+ "/Sdotaccent": "\u1E60",
+ "/Sdotbelow": "\u1E62",
+ "/Sdotbelowdotabove": "\u1E68",
+ "/Sdotbelowdotaccent": "\u1E68",
+ "/Seharmenian": "\u054D",
+ "/Semisoftcyr": "\u048C",
+ "/Sevenroman": "\u2166",
+ "/Shaarmenian": "\u0547",
+ "/Shacyr": "\u0428",
+ "/Shacyrillic": "\u0428",
+ "/Shchacyr": "\u0429",
+ "/Shchacyrillic": "\u0429",
+ "/Sheicoptic": "\u03E2",
+ "/SheneGerishin:hb": "\u059E",
+ "/Shhacyr": "\u04BA",
+ "/Shhacyrillic": "\u04BA",
+ "/Shhatailcyr": "\u0526",
+ "/Shimacoptic": "\u03EC",
+ "/Sho": "\u03F7",
+ "/Sigma": "\u03A3",
+ "/Sigmalunatesymbol": "\u03F9",
+ "/Sigmalunatesymboldotted": "\u03FE",
+ "/Sigmareversedlunatesymbol": "\u03FD",
+ "/Sinsular": "\uA784",
+ "/Sixroman": "\u2165",
+ "/Sjekomicyr": "\u050C",
+ "/Smonospace": "\uFF33",
+ "/Sobliquestroke": "\uA7A8",
+ "/Softcyr": "\u042C",
+ "/Softsigncyrillic": "\u042C",
+ "/Sparens": "\u1F122",
+ "/Sshell": "\u1F12A",
+ "/Ssmall": "\uF773",
+ "/Ssquare": "\u1F142",
+ "/Ssquareblack": "\u1F182",
+ "/Sswashtail": "\u2C7E",
+ "/Stigma": "\u03DA",
+ "/Stigmagreek": "\u03DA",
+ "/T": "\u0054",
+ "/Tau": "\u03A4",
+ "/Tbar": "\u0166",
+ "/Tcaron": "\u0164",
+ "/Tcedilla": "\u0162",
+ "/Tcircle": "\u24C9",
+ "/Tcircleblack": "\u1F163",
+ "/Tcircumflexbelow": "\u1E70",
+ "/Tcommaaccent": "\u0162",
+ "/Tdot": "\u1E6A",
+ "/Tdotaccent": "\u1E6A",
+ "/Tdotbelow": "\u1E6C",
+ "/Tecyr": "\u0422",
+ "/Tecyrillic": "\u0422",
+ "/Tedescendercyrillic": "\u04AC",
+ "/Tenroman": "\u2169",
+ "/Tetailcyr": "\u04AC",
+ "/Tetsecyr": "\u04B4",
+ "/Tetsecyrillic": "\u04B4",
+ "/Theta": "\u0398",
+ "/Thetasymbol": "\u03F4",
+ "/Thook": "\u01AC",
+ "/Thorn": "\u00DE",
+ "/Thornsmall": "\uF7FE",
+ "/Thornstroke": "\uA764",
+ "/Thornstrokedescender": "\uA766",
+ "/Threeroman": "\u2162",
+ "/Tildesmall": "\uF6FE",
+ "/Tinsular": "\uA786",
+ "/Tiwnarmenian": "\u054F",
+ "/Tjekomicyr": "\u050E",
+ "/Tlinebelow": "\u1E6E",
+ "/Tmonospace": "\uFF34",
+ "/Toarmenian": "\u0539",
+ "/Tonefive": "\u01BC",
+ "/Tonesix": "\u0184",
+ "/Tonetwo": "\u01A7",
+ "/Tparens": "\u1F123",
+ "/Tresillo": "\uA72A",
+ "/Tretroflexhook": "\u01AE",
+ "/Tsecyr": "\u0426",
+ "/Tsecyrillic": "\u0426",
+ "/Tshecyr": "\u040B",
+ "/Tshecyrillic": "\u040B",
+ "/Tsmall": "\uF774",
+ "/Tsquare": "\u1F143",
+ "/Tsquareblack": "\u1F183",
+ "/Tturned": "\uA7B1",
+ "/Twelveroman": "\u216B",
+ "/Twithdiagonalstroke": "\u023E",
+ "/Tworoman": "\u2161",
+ "/Tz": "\uA728",
+ "/U": "\u0055",
+ "/Uacute": "\u00DA",
+ "/Uacutedblcyr": "\u04F2",
+ "/Uacutesmall": "\uF7FA",
+ "/Ubar": "\u0244",
+ "/Ubreve": "\u016C",
+ "/Ucaron": "\u01D3",
+ "/Ucircle": "\u24CA",
+ "/Ucircleblack": "\u1F164",
+ "/Ucircumflex": "\u00DB",
+ "/Ucircumflexbelow": "\u1E76",
+ "/Ucircumflexsmall": "\uF7FB",
+ "/Ucyr": "\u0423",
+ "/Ucyrillic": "\u0423",
+ "/Udblacute": "\u0170",
+ "/Udblgrave": "\u0214",
+ "/Udieresis": "\u00DC",
+ "/Udieresisacute": "\u01D7",
+ "/Udieresisbelow": "\u1E72",
+ "/Udieresiscaron": "\u01D9",
+ "/Udieresiscyr": "\u04F0",
+ "/Udieresiscyrillic": "\u04F0",
+ "/Udieresisgrave": "\u01DB",
+ "/Udieresismacron": "\u01D5",
+ "/Udieresissmall": "\uF7FC",
+ "/Udotbelow": "\u1EE4",
+ "/Ugrave": "\u00D9",
+ "/Ugravedbl": "\u0214",
+ "/Ugravesmall": "\uF7F9",
+ "/Uhoi": "\u1EE6",
+ "/Uhookabove": "\u1EE6",
+ "/Uhorn": "\u01AF",
+ "/Uhornacute": "\u1EE8",
+ "/Uhorndotbelow": "\u1EF0",
+ "/Uhorngrave": "\u1EEA",
+ "/Uhornhoi": "\u1EEC",
+ "/Uhornhookabove": "\u1EEC",
+ "/Uhorntilde": "\u1EEE",
+ "/Uhungarumlaut": "\u0170",
+ "/Uhungarumlautcyrillic": "\u04F2",
+ "/Uinvertedbreve": "\u0216",
+ "/Ukcyr": "\u0478",
+ "/Ukcyrillic": "\u0478",
+ "/Umacron": "\u016A",
+ "/Umacroncyr": "\u04EE",
+ "/Umacroncyrillic": "\u04EE",
+ "/Umacrondieresis": "\u1E7A",
+ "/Umonospace": "\uFF35",
+ "/Uogonek": "\u0172",
+ "/Uparens": "\u1F124",
+ "/Upsilon": "\u03A5",
+ "/Upsilon1": "\u03D2",
+ "/Upsilonacute": "\u1FEB",
+ "/Upsilonacutehooksymbol": "\u03D3",
+ "/Upsilonacutehooksymbolgreek": "\u03D3",
+ "/Upsilonadieresishooksymbol": "\u03D4",
+ "/Upsilonafrican": "\u01B1",
+ "/Upsilonasper": "\u1F59",
+ "/Upsilonasperacute": "\u1F5D",
+ "/Upsilonaspergrave": "\u1F5B",
+ "/Upsilonaspertilde": "\u1F5F",
+ "/Upsilonbreve": "\u1FE8",
+ "/Upsilondieresis": "\u03AB",
+ "/Upsilondieresishooksymbolgreek": "\u03D4",
+ "/Upsilongrave": "\u1FEA",
+ "/Upsilonhooksymbol": "\u03D2",
+ "/Upsilontonos": "\u038E",
+ "/Upsilonwithmacron": "\u1FE9",
+ "/Uring": "\u016E",
+ "/Ushortcyr": "\u040E",
+ "/Ushortcyrillic": "\u040E",
+ "/Usmall": "\uF775",
+ "/Usquare": "\u1F144",
+ "/Usquareblack": "\u1F184",
+ "/Ustraightcyr": "\u04AE",
+ "/Ustraightcyrillic": "\u04AE",
+ "/Ustraightstrokecyr": "\u04B0",
+ "/Ustraightstrokecyrillic": "\u04B0",
+ "/Utilde": "\u0168",
+ "/Utildeacute": "\u1E78",
+ "/Utildebelow": "\u1E74",
+ "/V": "\u0056",
+ "/Vcircle": "\u24CB",
+ "/Vcircleblack": "\u1F165",
+ "/Vdiagonalstroke": "\uA75E",
+ "/Vdotbelow": "\u1E7E",
+ "/Vecyr": "\u0412",
+ "/Vecyrillic": "\u0412",
+ "/Vend": "\uA768",
+ "/Vewarmenian": "\u054E",
+ "/Vhook": "\u01B2",
+ "/Visigothicz": "\uA762",
+ "/Vmod": "\u2C7D",
+ "/Vmonospace": "\uFF36",
+ "/Voarmenian": "\u0548",
+ "/Volapukae": "\uA79A",
+ "/Volapukoe": "\uA79C",
+ "/Volapukue": "\uA79E",
+ "/Vparens": "\u1F125",
+ "/Vsmall": "\uF776",
+ "/Vsquare": "\u1F145",
+ "/Vsquareblack": "\u1F185",
+ "/Vtilde": "\u1E7C",
+ "/Vturned": "\u0245",
+ "/Vwelsh": "\u1EFC",
+ "/Vy": "\uA760",
+ "/W": "\u0057",
+ "/WZcircle": "\u1F12E",
+ "/Wacute": "\u1E82",
+ "/Wasallam": "\uFDF8",
+ "/Wcircle": "\u24CC",
+ "/Wcircleblack": "\u1F166",
+ "/Wcircumflex": "\u0174",
+ "/Wdieresis": "\u1E84",
+ "/Wdot": "\u1E86",
+ "/Wdotaccent": "\u1E86",
+ "/Wdotbelow": "\u1E88",
+ "/Wecyr": "\u051C",
+ "/Wgrave": "\u1E80",
+ "/Whook": "\u2C72",
+ "/Wmonospace": "\uFF37",
+ "/Wparens": "\u1F126",
+ "/Wsmall": "\uF777",
+ "/Wsquare": "\u1F146",
+ "/Wsquareblack": "\u1F186",
+ "/Wynn": "\u01F7",
+ "/X": "\u0058",
+ "/Xatailcyr": "\u04B2",
+ "/Xcircle": "\u24CD",
+ "/Xcircleblack": "\u1F167",
+ "/Xdieresis": "\u1E8C",
+ "/Xdot": "\u1E8A",
+ "/Xdotaccent": "\u1E8A",
+ "/Xeharmenian": "\u053D",
+ "/Xi": "\u039E",
+ "/Xmonospace": "\uFF38",
+ "/Xparens": "\u1F127",
+ "/Xsmall": "\uF778",
+ "/Xsquare": "\u1F147",
+ "/Xsquareblack": "\u1F187",
+ "/Y": "\u0059",
+ "/Yacute": "\u00DD",
+ "/Yacutesmall": "\uF7FD",
+ "/Yacyr": "\u042F",
+ "/Yaecyr": "\u0518",
+ "/Yatcyr": "\u0462",
+ "/Yatcyrillic": "\u0462",
+ "/Ycircle": "\u24CE",
+ "/Ycircleblack": "\u1F168",
+ "/Ycircumflex": "\u0176",
+ "/Ydieresis": "\u0178",
+ "/Ydieresissmall": "\uF7FF",
+ "/Ydot": "\u1E8E",
+ "/Ydotaccent": "\u1E8E",
+ "/Ydotbelow": "\u1EF4",
+ "/Yericyrillic": "\u042B",
+ "/Yerudieresiscyrillic": "\u04F8",
+ "/Ygrave": "\u1EF2",
+ "/Yhoi": "\u1EF6",
+ "/Yhook": "\u01B3",
+ "/Yhookabove": "\u1EF6",
+ "/Yiarmenian": "\u0545",
+ "/Yicyrillic": "\u0407",
+ "/Yiwnarmenian": "\u0552",
+ "/Ylongcyr": "\u042B",
+ "/Ylongdieresiscyr": "\u04F8",
+ "/Yloop": "\u1EFE",
+ "/Ymacron": "\u0232",
+ "/Ymonospace": "\uFF39",
+ "/Yogh": "\u021C",
+ "/Yot": "\u037F",
+ "/Yparens": "\u1F128",
+ "/Ysmall": "\uF779",
+ "/Ysquare": "\u1F148",
+ "/Ysquareblack": "\u1F188",
+ "/Ystroke": "\u024E",
+ "/Ytilde": "\u1EF8",
+ "/Yturnedsans": "\u2144",
+ "/Yucyr": "\u042E",
+ "/Yukrcyr": "\u0407",
+ "/Yusbigcyr": "\u046A",
+ "/Yusbigcyrillic": "\u046A",
+ "/Yusbigiotifiedcyr": "\u046C",
+ "/Yusbigiotifiedcyrillic": "\u046C",
+ "/Yuslittlecyr": "\u0466",
+ "/Yuslittlecyrillic": "\u0466",
+ "/Yuslittleiotifiedcyr": "\u0468",
+ "/Yuslittleiotifiedcyrillic": "\u0468",
+ "/Z": "\u005A",
+ "/Zaarmenian": "\u0536",
+ "/Zacute": "\u0179",
+ "/Zcaron": "\u017D",
+ "/Zcaronsmall": "\uF6FF",
+ "/Zcircle": "\u24CF",
+ "/Zcircleblack": "\u1F169",
+ "/Zcircumflex": "\u1E90",
+ "/Zdblstruck": "\u2124",
+ "/Zdescender": "\u2C6B",
+ "/Zdot": "\u017B",
+ "/Zdotaccent": "\u017B",
+ "/Zdotbelow": "\u1E92",
+ "/Zecyr": "\u0417",
+ "/Zecyrillic": "\u0417",
+ "/Zedescendercyrillic": "\u0498",
+ "/Zedieresiscyr": "\u04DE",
+ "/Zedieresiscyrillic": "\u04DE",
+ "/Zeta": "\u0396",
+ "/Zetailcyr": "\u0498",
+ "/Zfraktur": "\u2128",
+ "/Zhearmenian": "\u053A",
+ "/Zhebrevecyr": "\u04C1",
+ "/Zhebrevecyrillic": "\u04C1",
+ "/Zhecyr": "\u0416",
+ "/Zhecyrillic": "\u0416",
+ "/Zhedescendercyrillic": "\u0496",
+ "/Zhedieresiscyr": "\u04DC",
+ "/Zhedieresiscyrillic": "\u04DC",
+ "/Zhetailcyr": "\u0496",
+ "/Zhook": "\u0224",
+ "/Zjekomicyr": "\u0504",
+ "/Zlinebelow": "\u1E94",
+ "/Zmonospace": "\uFF3A",
+ "/Zparens": "\u1F129",
+ "/Zsmall": "\uF77A",
+ "/Zsquare": "\u1F149",
+ "/Zsquareblack": "\u1F189",
+ "/Zstroke": "\u01B5",
+ "/Zswashtail": "\u2C7F",
+ "/a": "\u0061",
+ "/a.inferior": "\u2090",
+ "/aHonRAA": "\u0613",
+ "/aa": "\uA733",
+ "/aabengali": "\u0986",
+ "/aacute": "\u00E1",
+ "/aadeva": "\u0906",
+ "/aagujarati": "\u0A86",
+ "/aagurmukhi": "\u0A06",
+ "/aamatragurmukhi": "\u0A3E",
+ "/aarusquare": "\u3303",
+ "/aavowelsignbengali": "\u09BE",
+ "/aavowelsigndeva": "\u093E",
+ "/aavowelsigngujarati": "\u0ABE",
+ "/abbreviationmarkarmenian": "\u055F",
+ "/abbreviationsigndeva": "\u0970",
+ "/abengali": "\u0985",
+ "/abopomofo": "\u311A",
+ "/abreve": "\u0103",
+ "/abreveacute": "\u1EAF",
+ "/abrevecyr": "\u04D1",
+ "/abrevecyrillic": "\u04D1",
+ "/abrevedotbelow": "\u1EB7",
+ "/abrevegrave": "\u1EB1",
+ "/abrevehoi": "\u1EB3",
+ "/abrevehookabove": "\u1EB3",
+ "/abrevetilde": "\u1EB5",
+ "/absquareblack": "\u1F18E",
+ "/acaron": "\u01CE",
+ "/accountof": "\u2100",
+ "/accurrent": "\u23E6",
+ "/acircle": "\u24D0",
+ "/acirclekatakana": "\u32D0",
+ "/acircumflex": "\u00E2",
+ "/acircumflexacute": "\u1EA5",
+ "/acircumflexdotbelow": "\u1EAD",
+ "/acircumflexgrave": "\u1EA7",
+ "/acircumflexhoi": "\u1EA9",
+ "/acircumflexhookabove": "\u1EA9",
+ "/acircumflextilde": "\u1EAB",
+ "/activatearabicformshaping": "\u206D",
+ "/activatesymmetricswapping": "\u206B",
+ "/acute": "\u00B4",
+ "/acutebelowcmb": "\u0317",
+ "/acutecmb": "\u0301",
+ "/acutecomb": "\u0301",
+ "/acutedblmiddlemod": "\u02F6",
+ "/acutedeva": "\u0954",
+ "/acutelowmod": "\u02CF",
+ "/acutemod": "\u02CA",
+ "/acutetonecmb": "\u0341",
+ "/acyr": "\u0430",
+ "/acyrillic": "\u0430",
+ "/adblgrave": "\u0201",
+ "/addakgurmukhi": "\u0A71",
+ "/addressedsubject": "\u2101",
+ "/adegadegpada": "\uA9CB",
+ "/adegpada": "\uA9CA",
+ "/adeva": "\u0905",
+ "/adieresis": "\u00E4",
+ "/adieresiscyr": "\u04D3",
+ "/adieresiscyrillic": "\u04D3",
+ "/adieresismacron": "\u01DF",
+ "/adishakti": "\u262C",
+ "/admissionTickets": "\u1F39F",
+ "/adot": "\u0227",
+ "/adotbelow": "\u1EA1",
+ "/adotmacron": "\u01E1",
+ "/ae": "\u00E6",
+ "/aeacute": "\u01FD",
+ "/aekorean": "\u3150",
+ "/aemacron": "\u01E3",
+ "/aerialTramway": "\u1F6A1",
+ "/afghani": "\u060B",
+ "/afii00208": "\u2015",
+ "/afii08941": "\u20A4",
+ "/afii10017": "\u0410",
+ "/afii10018": "\u0411",
+ "/afii10019": "\u0412",
+ "/afii10020": "\u0413",
+ "/afii10021": "\u0414",
+ "/afii10022": "\u0415",
+ "/afii10023": "\u0401",
+ "/afii10024": "\u0416",
+ "/afii10025": "\u0417",
+ "/afii10026": "\u0418",
+ "/afii10027": "\u0419",
+ "/afii10028": "\u041A",
+ "/afii10029": "\u041B",
+ "/afii10030": "\u041C",
+ "/afii10031": "\u041D",
+ "/afii10032": "\u041E",
+ "/afii10033": "\u041F",
+ "/afii10034": "\u0420",
+ "/afii10035": "\u0421",
+ "/afii10036": "\u0422",
+ "/afii10037": "\u0423",
+ "/afii10038": "\u0424",
+ "/afii10039": "\u0425",
+ "/afii10040": "\u0426",
+ "/afii10041": "\u0427",
+ "/afii10042": "\u0428",
+ "/afii10043": "\u0429",
+ "/afii10044": "\u042A",
+ "/afii10045": "\u042B",
+ "/afii10046": "\u042C",
+ "/afii10047": "\u042D",
+ "/afii10048": "\u042E",
+ "/afii10049": "\u042F",
+ "/afii10050": "\u0490",
+ "/afii10051": "\u0402",
+ "/afii10052": "\u0403",
+ "/afii10053": "\u0404",
+ "/afii10054": "\u0405",
+ "/afii10055": "\u0406",
+ "/afii10056": "\u0407",
+ "/afii10057": "\u0408",
+ "/afii10058": "\u0409",
+ "/afii10059": "\u040A",
+ "/afii10060": "\u040B",
+ "/afii10061": "\u040C",
+ "/afii10062": "\u040E",
+ "/afii10063": "\uF6C4",
+ "/afii10064": "\uF6C5",
+ "/afii10065": "\u0430",
+ "/afii10066": "\u0431",
+ "/afii10067": "\u0432",
+ "/afii10068": "\u0433",
+ "/afii10069": "\u0434",
+ "/afii10070": "\u0435",
+ "/afii10071": "\u0451",
+ "/afii10072": "\u0436",
+ "/afii10073": "\u0437",
+ "/afii10074": "\u0438",
+ "/afii10075": "\u0439",
+ "/afii10076": "\u043A",
+ "/afii10077": "\u043B",
+ "/afii10078": "\u043C",
+ "/afii10079": "\u043D",
+ "/afii10080": "\u043E",
+ "/afii10081": "\u043F",
+ "/afii10082": "\u0440",
+ "/afii10083": "\u0441",
+ "/afii10084": "\u0442",
+ "/afii10085": "\u0443",
+ "/afii10086": "\u0444",
+ "/afii10087": "\u0445",
+ "/afii10088": "\u0446",
+ "/afii10089": "\u0447",
+ "/afii10090": "\u0448",
+ "/afii10091": "\u0449",
+ "/afii10092": "\u044A",
+ "/afii10093": "\u044B",
+ "/afii10094": "\u044C",
+ "/afii10095": "\u044D",
+ "/afii10096": "\u044E",
+ "/afii10097": "\u044F",
+ "/afii10098": "\u0491",
+ "/afii10099": "\u0452",
+ "/afii10100": "\u0453",
+ "/afii10101": "\u0454",
+ "/afii10102": "\u0455",
+ "/afii10103": "\u0456",
+ "/afii10104": "\u0457",
+ "/afii10105": "\u0458",
+ "/afii10106": "\u0459",
+ "/afii10107": "\u045A",
+ "/afii10108": "\u045B",
+ "/afii10109": "\u045C",
+ "/afii10110": "\u045E",
+ "/afii10145": "\u040F",
+ "/afii10146": "\u0462",
+ "/afii10147": "\u0472",
+ "/afii10148": "\u0474",
+ "/afii10192": "\uF6C6",
+ "/afii10193": "\u045F",
+ "/afii10194": "\u0463",
+ "/afii10195": "\u0473",
+ "/afii10196": "\u0475",
+ "/afii10831": "\uF6C7",
+ "/afii10832": "\uF6C8",
+ "/afii10846": "\u04D9",
+ "/afii299": "\u200E",
+ "/afii300": "\u200F",
+ "/afii301": "\u200D",
+ "/afii57381": "\u066A",
+ "/afii57388": "\u060C",
+ "/afii57392": "\u0660",
+ "/afii57393": "\u0661",
+ "/afii57394": "\u0662",
+ "/afii57395": "\u0663",
+ "/afii57396": "\u0664",
+ "/afii57397": "\u0665",
+ "/afii57398": "\u0666",
+ "/afii57399": "\u0667",
+ "/afii57400": "\u0668",
+ "/afii57401": "\u0669",
+ "/afii57403": "\u061B",
+ "/afii57407": "\u061F",
+ "/afii57409": "\u0621",
+ "/afii57410": "\u0622",
+ "/afii57411": "\u0623",
+ "/afii57412": "\u0624",
+ "/afii57413": "\u0625",
+ "/afii57414": "\u0626",
+ "/afii57415": "\u0627",
+ "/afii57416": "\u0628",
+ "/afii57417": "\u0629",
+ "/afii57418": "\u062A",
+ "/afii57419": "\u062B",
+ "/afii57420": "\u062C",
+ "/afii57421": "\u062D",
+ "/afii57422": "\u062E",
+ "/afii57423": "\u062F",
+ "/afii57424": "\u0630",
+ "/afii57425": "\u0631",
+ "/afii57426": "\u0632",
+ "/afii57427": "\u0633",
+ "/afii57428": "\u0634",
+ "/afii57429": "\u0635",
+ "/afii57430": "\u0636",
+ "/afii57431": "\u0637",
+ "/afii57432": "\u0638",
+ "/afii57433": "\u0639",
+ "/afii57434": "\u063A",
+ "/afii57440": "\u0640",
+ "/afii57441": "\u0641",
+ "/afii57442": "\u0642",
+ "/afii57443": "\u0643",
+ "/afii57444": "\u0644",
+ "/afii57445": "\u0645",
+ "/afii57446": "\u0646",
+ "/afii57448": "\u0648",
+ "/afii57449": "\u0649",
+ "/afii57450": "\u064A",
+ "/afii57451": "\u064B",
+ "/afii57452": "\u064C",
+ "/afii57453": "\u064D",
+ "/afii57454": "\u064E",
+ "/afii57455": "\u064F",
+ "/afii57456": "\u0650",
+ "/afii57457": "\u0651",
+ "/afii57458": "\u0652",
+ "/afii57470": "\u0647",
+ "/afii57505": "\u06A4",
+ "/afii57506": "\u067E",
+ "/afii57507": "\u0686",
+ "/afii57508": "\u0698",
+ "/afii57509": "\u06AF",
+ "/afii57511": "\u0679",
+ "/afii57512": "\u0688",
+ "/afii57513": "\u0691",
+ "/afii57514": "\u06BA",
+ "/afii57519": "\u06D2",
+ "/afii57534": "\u06D5",
+ "/afii57636": "\u20AA",
+ "/afii57645": "\u05BE",
+ "/afii57658": "\u05C3",
+ "/afii57664": "\u05D0",
+ "/afii57665": "\u05D1",
+ "/afii57666": "\u05D2",
+ "/afii57667": "\u05D3",
+ "/afii57668": "\u05D4",
+ "/afii57669": "\u05D5",
+ "/afii57670": "\u05D6",
+ "/afii57671": "\u05D7",
+ "/afii57672": "\u05D8",
+ "/afii57673": "\u05D9",
+ "/afii57674": "\u05DA",
+ "/afii57675": "\u05DB",
+ "/afii57676": "\u05DC",
+ "/afii57677": "\u05DD",
+ "/afii57678": "\u05DE",
+ "/afii57679": "\u05DF",
+ "/afii57680": "\u05E0",
+ "/afii57681": "\u05E1",
+ "/afii57682": "\u05E2",
+ "/afii57683": "\u05E3",
+ "/afii57684": "\u05E4",
+ "/afii57685": "\u05E5",
+ "/afii57686": "\u05E6",
+ "/afii57687": "\u05E7",
+ "/afii57688": "\u05E8",
+ "/afii57689": "\u05E9",
+ "/afii57690": "\u05EA",
+ "/afii57694": "\uFB2A",
+ "/afii57695": "\uFB2B",
+ "/afii57700": "\uFB4B",
+ "/afii57705": "\uFB1F",
+ "/afii57716": "\u05F0",
+ "/afii57717": "\u05F1",
+ "/afii57718": "\u05F2",
+ "/afii57723": "\uFB35",
+ "/afii57793": "\u05B4",
+ "/afii57794": "\u05B5",
+ "/afii57795": "\u05B6",
+ "/afii57796": "\u05BB",
+ "/afii57797": "\u05B8",
+ "/afii57798": "\u05B7",
+ "/afii57799": "\u05B0",
+ "/afii57800": "\u05B2",
+ "/afii57801": "\u05B1",
+ "/afii57802": "\u05B3",
+ "/afii57803": "\u05C2",
+ "/afii57804": "\u05C1",
+ "/afii57806": "\u05B9",
+ "/afii57807": "\u05BC",
+ "/afii57839": "\u05BD",
+ "/afii57841": "\u05BF",
+ "/afii57842": "\u05C0",
+ "/afii57929": "\u02BC",
+ "/afii61248": "\u2105",
+ "/afii61289": "\u2113",
+ "/afii61352": "\u2116",
+ "/afii61573": "\u202C",
+ "/afii61574": "\u202D",
+ "/afii61575": "\u202E",
+ "/afii61664": "\u200C",
+ "/afii63167": "\u066D",
+ "/afii64937": "\u02BD",
+ "/agrave": "\u00E0",
+ "/agravedbl": "\u0201",
+ "/agujarati": "\u0A85",
+ "/agurmukhi": "\u0A05",
+ "/ahiragana": "\u3042",
+ "/ahoi": "\u1EA3",
+ "/ahookabove": "\u1EA3",
+ "/aibengali": "\u0990",
+ "/aibopomofo": "\u311E",
+ "/aideva": "\u0910",
+ "/aiecyr": "\u04D5",
+ "/aiecyrillic": "\u04D5",
+ "/aigujarati": "\u0A90",
+ "/aigurmukhi": "\u0A10",
+ "/aimatragurmukhi": "\u0A48",
+ "/ain.fina": "\uFECA",
+ "/ain.init": "\uFECB",
+ "/ain.init_alefmaksura.fina": "\uFCF7",
+ "/ain.init_jeem.fina": "\uFC29",
+ "/ain.init_jeem.medi": "\uFCBA",
+ "/ain.init_jeem.medi_meem.medi": "\uFDC4",
+ "/ain.init_meem.fina": "\uFC2A",
+ "/ain.init_meem.medi": "\uFCBB",
+ "/ain.init_meem.medi_meem.medi": "\uFD77",
+ "/ain.init_yeh.fina": "\uFCF8",
+ "/ain.isol": "\uFEC9",
+ "/ain.medi": "\uFECC",
+ "/ain.medi_alefmaksura.fina": "\uFD13",
+ "/ain.medi_jeem.medi_meem.fina": "\uFD75",
+ "/ain.medi_meem.medi_alefmaksura.fina": "\uFD78",
+ "/ain.medi_meem.medi_meem.fina": "\uFD76",
+ "/ain.medi_meem.medi_yeh.fina": "\uFDB6",
+ "/ain.medi_yeh.fina": "\uFD14",
+ "/ainThreeDotsDownAbove": "\u075E",
+ "/ainTwoDotsAbove": "\u075D",
+ "/ainTwoDotsVerticallyAbove": "\u075F",
+ "/ainarabic": "\u0639",
+ "/ainfinalarabic": "\uFECA",
+ "/aininitialarabic": "\uFECB",
+ "/ainmedialarabic": "\uFECC",
+ "/ainthreedotsabove": "\u06A0",
+ "/ainvertedbreve": "\u0203",
+ "/airplaneArriving": "\u1F6EC",
+ "/airplaneDeparture": "\u1F6EB",
+ "/aivowelsignbengali": "\u09C8",
+ "/aivowelsigndeva": "\u0948",
+ "/aivowelsigngujarati": "\u0AC8",
+ "/akatakana": "\u30A2",
+ "/akatakanahalfwidth": "\uFF71",
+ "/akorean": "\u314F",
+ "/aktieselskab": "\u214D",
+ "/alarmclock": "\u23F0",
+ "/alef": "\u05D0",
+ "/alef.fina": "\uFE8E",
+ "/alef.init_fathatan.fina": "\uFD3D",
+ "/alef.isol": "\uFE8D",
+ "/alef.medi_fathatan.fina": "\uFD3C",
+ "/alef:hb": "\u05D0",
+ "/alefDigitThreeAbove": "\u0774",
+ "/alefDigitTwoAbove": "\u0773",
+ "/alefLamYehabove": "\u0616",
+ "/alefabove": "\u0670",
+ "/alefarabic": "\u0627",
+ "/alefdageshhebrew": "\uFB30",
+ "/aleffinalarabic": "\uFE8E",
+ "/alefhamza": "\u0623",
+ "/alefhamza.fina": "\uFE84",
+ "/alefhamza.isol": "\uFE83",
+ "/alefhamzaabovearabic": "\u0623",
+ "/alefhamzaabovefinalarabic": "\uFE84",
+ "/alefhamzabelow": "\u0625",
+ "/alefhamzabelow.fina": "\uFE88",
+ "/alefhamzabelow.isol": "\uFE87",
+ "/alefhamzabelowarabic": "\u0625",
+ "/alefhamzabelowfinalarabic": "\uFE88",
+ "/alefhebrew": "\u05D0",
+ "/alefhighhamza": "\u0675",
+ "/aleflamedhebrew": "\uFB4F",
+ "/alefmadda": "\u0622",
+ "/alefmadda.fina": "\uFE82",
+ "/alefmadda.isol": "\uFE81",
+ "/alefmaddaabovearabic": "\u0622",
+ "/alefmaddaabovefinalarabic": "\uFE82",
+ "/alefmaksura": "\u0649",
+ "/alefmaksura.fina": "\uFEF0",
+ "/alefmaksura.init_superscriptalef.fina": "\uFC5D",
+ "/alefmaksura.isol": "\uFEEF",
+ "/alefmaksura.medi_superscriptalef.fina": "\uFC90",
+ "/alefmaksuraarabic": "\u0649",
+ "/alefmaksurafinalarabic": "\uFEF0",
+ "/alefmaksurainitialarabic": "\uFEF3",
+ "/alefmaksuramedialarabic": "\uFEF4",
+ "/alefpatahhebrew": "\uFB2E",
+ "/alefqamatshebrew": "\uFB2F",
+ "/alefwasla": "\u0671",
+ "/alefwasla.fina": "\uFB51",
+ "/alefwasla.isol": "\uFB50",
+ "/alefwavyhamza": "\u0672",
+ "/alefwavyhamzabelow": "\u0673",
+ "/alefwide:hb": "\uFB21",
+ "/alefwithmapiq:hb": "\uFB30",
+ "/alefwithpatah:hb": "\uFB2E",
+ "/alefwithqamats:hb": "\uFB2F",
+ "/alembic": "\u2697",
+ "/aleph": "\u2135",
+ "/alienMonster": "\u1F47E",
+ "/allaroundprofile": "\u232E",
+ "/allequal": "\u224C",
+ "/allianceideographiccircled": "\u32AF",
+ "/allianceideographicparen": "\u323F",
+ "/almostequalorequal": "\u224A",
+ "/alpha": "\u03B1",
+ "/alphaacute": "\u1F71",
+ "/alphaacuteiotasub": "\u1FB4",
+ "/alphaasper": "\u1F01",
+ "/alphaasperacute": "\u1F05",
+ "/alphaasperacuteiotasub": "\u1F85",
+ "/alphaaspergrave": "\u1F03",
+ "/alphaaspergraveiotasub": "\u1F83",
+ "/alphaasperiotasub": "\u1F81",
+ "/alphaaspertilde": "\u1F07",
+ "/alphaaspertildeiotasub": "\u1F87",
+ "/alphabreve": "\u1FB0",
+ "/alphafunc": "\u237A",
+ "/alphagrave": "\u1F70",
+ "/alphagraveiotasub": "\u1FB2",
+ "/alphaiotasub": "\u1FB3",
+ "/alphalenis": "\u1F00",
+ "/alphalenisacute": "\u1F04",
+ "/alphalenisacuteiotasub": "\u1F84",
+ "/alphalenisgrave": "\u1F02",
+ "/alphalenisgraveiotasub": "\u1F82",
+ "/alphalenisiotasub": "\u1F80",
+ "/alphalenistilde": "\u1F06",
+ "/alphalenistildeiotasub": "\u1F86",
+ "/alphatilde": "\u1FB6",
+ "/alphatildeiotasub": "\u1FB7",
+ "/alphatonos": "\u03AC",
+ "/alphaturned": "\u0252",
+ "/alphaunderlinefunc": "\u2376",
+ "/alphawithmacron": "\u1FB1",
+ "/alternateonewayleftwaytraffic": "\u26D5",
+ "/alternative": "\u2387",
+ "/amacron": "\u0101",
+ "/ambulance": "\u1F691",
+ "/americanFootball": "\u1F3C8",
+ "/amfullwidth": "\u33C2",
+ "/amonospace": "\uFF41",
+ "/amountofcheck": "\u2447",
+ "/ampersand": "\u0026",
+ "/ampersandSindhi": "\u06FD",
+ "/ampersandmonospace": "\uFF06",
+ "/ampersandsmall": "\uF726",
+ "/ampersandturned": "\u214B",
+ "/amphora": "\u1F3FA",
+ "/amsquare": "\u33C2",
+ "/anbopomofo": "\u3122",
+ "/anchor": "\u2693",
+ "/ancoradown": "\u2E14",
+ "/ancoraup": "\u2E15",
+ "/andappada": "\uA9C3",
+ "/angbopomofo": "\u3124",
+ "/anger": "\u1F4A2",
+ "/angkhankhuthai": "\u0E5A",
+ "/angle": "\u2220",
+ "/anglearcright": "\u22BE",
+ "/anglebracketleft": "\u3008",
+ "/anglebracketleftvertical": "\uFE3F",
+ "/anglebracketright": "\u3009",
+ "/anglebracketrightvertical": "\uFE40",
+ "/angledottedright": "\u2E16",
+ "/angleleft": "\u2329",
+ "/anglemarkerdottedsubstitutionright": "\u2E01",
+ "/anglemarkersubstitutionright": "\u2E00",
+ "/angleright": "\u232A",
+ "/anglezigzagarrowdownright": "\u237C",
+ "/angryFace": "\u1F620",
+ "/angstrom": "\u212B",
+ "/anguishedFace": "\u1F627",
+ "/ankh": "\u2625",
+ "/anoteleia": "\u0387",
+ "/anpeasquare": "\u3302",
+ "/ant": "\u1F41C",
+ "/antennaBars": "\u1F4F6",
+ "/anticlockwiseDownwardsAndUpwardsOpenCircleArrows": "\u1F504",
+ "/anudattadeva": "\u0952",
+ "/anusvarabengali": "\u0982",
+ "/anusvaradeva": "\u0902",
+ "/anusvaragujarati": "\u0A82",
+ "/ao": "\uA735",
+ "/aogonek": "\u0105",
+ "/aovermfullwidth": "\u33DF",
+ "/apaatosquare": "\u3300",
+ "/aparen": "\u249C",
+ "/aparenthesized": "\u249C",
+ "/apostrophearmenian": "\u055A",
+ "/apostrophedblmod": "\u02EE",
+ "/apostrophemod": "\u02BC",
+ "/apple": "\uF8FF",
+ "/approaches": "\u2250",
+ "/approacheslimit": "\u2250",
+ "/approxequal": "\u2248",
+ "/approxequalorimage": "\u2252",
+ "/approximatelybutnotactuallyequal": "\u2246",
+ "/approximatelyequal": "\u2245",
+ "/approximatelyequalorimage": "\u2252",
+ "/apriltelegraph": "\u32C3",
+ "/aquarius": "\u2652",
+ "/ar:ae": "\u06D5",
+ "/ar:ain": "\u0639",
+ "/ar:alef": "\u0627",
+ "/ar:comma": "\u060C",
+ "/ar:cuberoot": "\u0606",
+ "/ar:decimalseparator": "\u066B",
+ "/ar:e": "\u06D0",
+ "/ar:eight": "\u0668",
+ "/ar:feh": "\u0641",
+ "/ar:five": "\u0665",
+ "/ar:four": "\u0664",
+ "/ar:fourthroot": "\u0607",
+ "/ar:kaf": "\u0643",
+ "/ar:ng": "\u06AD",
+ "/ar:nine": "\u0669",
+ "/ar:numbersign": "\u0600",
+ "/ar:oe": "\u06C6",
+ "/ar:one": "\u0661",
+ "/ar:peh": "\u067E",
+ "/ar:percent": "\u066A",
+ "/ar:perthousand": "\u060A",
+ "/ar:question": "\u061F",
+ "/ar:reh": "\u0631",
+ "/ar:semicolon": "\u061B",
+ "/ar:seven": "\u0667",
+ "/ar:shadda": "\u0651",
+ "/ar:six": "\u0666",
+ "/ar:sukun": "\u0652",
+ "/ar:three": "\u0663",
+ "/ar:two": "\u0662",
+ "/ar:u": "\u06C7",
+ "/ar:ve": "\u06CB",
+ "/ar:yu": "\u06C8",
+ "/ar:zero": "\u0660",
+ "/araeaekorean": "\u318E",
+ "/araeakorean": "\u318D",
+ "/arc": "\u2312",
+ "/archaicmepigraphic": "\uA7FF",
+ "/aries": "\u2648",
+ "/arighthalfring": "\u1E9A",
+ "/aring": "\u00E5",
+ "/aringacute": "\u01FB",
+ "/aringbelow": "\u1E01",
+ "/armn:Ayb": "\u0531",
+ "/armn:Ben": "\u0532",
+ "/armn:Ca": "\u053E",
+ "/armn:Cha": "\u0549",
+ "/armn:Cheh": "\u0543",
+ "/armn:Co": "\u0551",
+ "/armn:DRAMSIGN": "\u058F",
+ "/armn:Da": "\u0534",
+ "/armn:Ech": "\u0535",
+ "/armn:Eh": "\u0537",
+ "/armn:Et": "\u0538",
+ "/armn:Feh": "\u0556",
+ "/armn:Ghad": "\u0542",
+ "/armn:Gim": "\u0533",
+ "/armn:Ho": "\u0540",
+ "/armn:Ini": "\u053B",
+ "/armn:Ja": "\u0541",
+ "/armn:Jheh": "\u054B",
+ "/armn:Keh": "\u0554",
+ "/armn:Ken": "\u053F",
+ "/armn:Liwn": "\u053C",
+ "/armn:Men": "\u0544",
+ "/armn:Now": "\u0546",
+ "/armn:Oh": "\u0555",
+ "/armn:Peh": "\u054A",
+ "/armn:Piwr": "\u0553",
+ "/armn:Ra": "\u054C",
+ "/armn:Reh": "\u0550",
+ "/armn:Seh": "\u054D",
+ "/armn:Sha": "\u0547",
+ "/armn:Tiwn": "\u054F",
+ "/armn:To": "\u0539",
+ "/armn:Vew": "\u054E",
+ "/armn:Vo": "\u0548",
+ "/armn:Xeh": "\u053D",
+ "/armn:Yi": "\u0545",
+ "/armn:Yiwn": "\u0552",
+ "/armn:Za": "\u0536",
+ "/armn:Zhe": "\u053A",
+ "/armn:abbreviationmark": "\u055F",
+ "/armn:apostrophe": "\u055A",
+ "/armn:ayb": "\u0561",
+ "/armn:ben": "\u0562",
+ "/armn:ca": "\u056E",
+ "/armn:cha": "\u0579",
+ "/armn:cheh": "\u0573",
+ "/armn:co": "\u0581",
+ "/armn:comma": "\u055D",
+ "/armn:da": "\u0564",
+ "/armn:ech": "\u0565",
+ "/armn:ech_yiwn": "\u0587",
+ "/armn:eh": "\u0567",
+ "/armn:emphasismark": "\u055B",
+ "/armn:et": "\u0568",
+ "/armn:exclam": "\u055C",
+ "/armn:feh": "\u0586",
+ "/armn:ghad": "\u0572",
+ "/armn:gim": "\u0563",
+ "/armn:ho": "\u0570",
+ "/armn:hyphen": "\u058A",
+ "/armn:ini": "\u056B",
+ "/armn:ja": "\u0571",
+ "/armn:jheh": "\u057B",
+ "/armn:keh": "\u0584",
+ "/armn:ken": "\u056F",
+ "/armn:leftfacingeternitysign": "\u058E",
+ "/armn:liwn": "\u056C",
+ "/armn:men": "\u0574",
+ "/armn:men_ech": "\uFB14",
+ "/armn:men_ini": "\uFB15",
+ "/armn:men_now": "\uFB13",
+ "/armn:men_xeh": "\uFB17",
+ "/armn:now": "\u0576",
+ "/armn:oh": "\u0585",
+ "/armn:peh": "\u057A",
+ "/armn:period": "\u0589",
+ "/armn:piwr": "\u0583",
+ "/armn:question": "\u055E",
+ "/armn:ra": "\u057C",
+ "/armn:reh": "\u0580",
+ "/armn:rightfacingeternitysign": "\u058D",
+ "/armn:ringhalfleft": "\u0559",
+ "/armn:seh": "\u057D",
+ "/armn:sha": "\u0577",
+ "/armn:tiwn": "\u057F",
+ "/armn:to": "\u0569",
+ "/armn:vew": "\u057E",
+ "/armn:vew_now": "\uFB16",
+ "/armn:vo": "\u0578",
+ "/armn:xeh": "\u056D",
+ "/armn:yi": "\u0575",
+ "/armn:yiwn": "\u0582",
+ "/armn:za": "\u0566",
+ "/armn:zhe": "\u056A",
+ "/arrowNE": "\u2197",
+ "/arrowNW": "\u2196",
+ "/arrowSE": "\u2198",
+ "/arrowSW": "\u2199",
+ "/arrowanticlockwiseopencircle": "\u21BA",
+ "/arrowanticlockwisesemicircle": "\u21B6",
+ "/arrowboth": "\u2194",
+ "/arrowclockwiseopencircle": "\u21BB",
+ "/arrowclockwisesemicircle": "\u21B7",
+ "/arrowdashdown": "\u21E3",
+ "/arrowdashleft": "\u21E0",
+ "/arrowdashright": "\u21E2",
+ "/arrowdashup": "\u21E1",
+ "/arrowdblboth": "\u21D4",
+ "/arrowdbldown": "\u21D3",
+ "/arrowdblleft": "\u21D0",
+ "/arrowdblright": "\u21D2",
+ "/arrowdblup": "\u21D1",
+ "/arrowdown": "\u2193",
+ "/arrowdowndashed": "\u21E3",
+ "/arrowdownfrombar": "\u21A7",
+ "/arrowdownleft": "\u2199",
+ "/arrowdownright": "\u2198",
+ "/arrowdowntwoheaded": "\u21A1",
+ "/arrowdownwhite": "\u21E9",
+ "/arrowdownzigzag": "\u21AF",
+ "/arrowheaddown": "\u2304",
+ "/arrowheaddownlowmod": "\u02EF",
+ "/arrowheaddownmod": "\u02C5",
+ "/arrowheadleftlowmod": "\u02F1",
+ "/arrowheadleftmod": "\u02C2",
+ "/arrowheadrightlowmod": "\u02F2",
+ "/arrowheadrightmod": "\u02C3",
+ "/arrowheadtwobarsuphorizontal": "\u2324",
+ "/arrowheadup": "\u2303",
+ "/arrowheaduplowmod": "\u02F0",
+ "/arrowheadupmod": "\u02C4",
+ "/arrowhorizex": "\uF8E7",
+ "/arrowleft": "\u2190",
+ "/arrowleftdashed": "\u21E0",
+ "/arrowleftdbl": "\u21D0",
+ "/arrowleftdblstroke": "\u21CD",
+ "/arrowleftdowncorner": "\u21B5",
+ "/arrowleftdowntip": "\u21B2",
+ "/arrowleftfrombar": "\u21A4",
+ "/arrowlefthook": "\u21A9",
+ "/arrowleftloop": "\u21AB",
+ "/arrowleftlowmod": "\u02FF",
+ "/arrowleftoverright": "\u21C6",
+ "/arrowleftoverrighttobar": "\u21B9",
+ "/arrowleftright": "\u2194",
+ "/arrowleftrightstroke": "\u21AE",
+ "/arrowleftrightwave": "\u21AD",
+ "/arrowleftsquiggle": "\u21DC",
+ "/arrowleftstroke": "\u219A",
+ "/arrowlefttail": "\u21A2",
+ "/arrowlefttobar": "\u21E4",
+ "/arrowlefttwoheaded": "\u219E",
+ "/arrowleftuptip": "\u21B0",
+ "/arrowleftwave": "\u219C",
+ "/arrowleftwhite": "\u21E6",
+ "/arrowlongNWtobar": "\u21B8",
+ "/arrowright": "\u2192",
+ "/arrowrightdashed": "\u21E2",
+ "/arrowrightdblstroke": "\u21CF",
+ "/arrowrightdowncorner": "\u21B4",
+ "/arrowrightdowntip": "\u21B3",
+ "/arrowrightfrombar": "\u21A6",
+ "/arrowrightheavy": "\u279E",
+ "/arrowrighthook": "\u21AA",
+ "/arrowrightloop": "\u21AC",
+ "/arrowrightoverleft": "\u21C4",
+ "/arrowrightsmallcircle": "\u21F4",
+ "/arrowrightsquiggle": "\u21DD",
+ "/arrowrightstroke": "\u219B",
+ "/arrowrighttail": "\u21A3",
+ "/arrowrighttobar": "\u21E5",
+ "/arrowrighttwoheaded": "\u21A0",
+ "/arrowrightwave": "\u219D",
+ "/arrowrightwhite": "\u21E8",
+ "/arrowspaireddown": "\u21CA",
+ "/arrowspairedleft": "\u21C7",
+ "/arrowspairedright": "\u21C9",
+ "/arrowspairedup": "\u21C8",
+ "/arrowtableft": "\u21E4",
+ "/arrowtabright": "\u21E5",
+ "/arrowup": "\u2191",
+ "/arrowupdashed": "\u21E1",
+ "/arrowupdn": "\u2195",
+ "/arrowupdnbse": "\u21A8",
+ "/arrowupdown": "\u2195",
+ "/arrowupdownbase": "\u21A8",
+ "/arrowupdownwithbase": "\u21A8",
+ "/arrowupfrombar": "\u21A5",
+ "/arrowupleft": "\u2196",
+ "/arrowupleftofdown": "\u21C5",
+ "/arrowupright": "\u2197",
+ "/arrowuprighttip": "\u21B1",
+ "/arrowuptwoheaded": "\u219F",
+ "/arrowupwhite": "\u21E7",
+ "/arrowvertex": "\uF8E6",
+ "/articulatedLorry": "\u1F69B",
+ "/artistPalette": "\u1F3A8",
+ "/aruhuasquare": "\u3301",
+ "/asciicircum": "\u005E",
+ "/asciicircummonospace": "\uFF3E",
+ "/asciitilde": "\u007E",
+ "/asciitildemonospace": "\uFF5E",
+ "/ascript": "\u0251",
+ "/ascriptturned": "\u0252",
+ "/asmallhiragana": "\u3041",
+ "/asmallkatakana": "\u30A1",
+ "/asmallkatakanahalfwidth": "\uFF67",
+ "/asper": "\u1FFE",
+ "/asperacute": "\u1FDE",
+ "/aspergrave": "\u1FDD",
+ "/aspertilde": "\u1FDF",
+ "/assertion": "\u22A6",
+ "/asterisk": "\u002A",
+ "/asteriskaltonearabic": "\u066D",
+ "/asteriskarabic": "\u066D",
+ "/asteriskmath": "\u2217",
+ "/asteriskmonospace": "\uFF0A",
+ "/asterisksmall": "\uFE61",
+ "/asterism": "\u2042",
+ "/astonishedFace": "\u1F632",
+ "/astroke": "\u2C65",
+ "/astronomicaluranus": "\u26E2",
+ "/asuperior": "\uF6E9",
+ "/asympticallyequal": "\u2243",
+ "/asymptoticallyequal": "\u2243",
+ "/at": "\u0040",
+ "/athleticShoe": "\u1F45F",
+ "/atilde": "\u00E3",
+ "/atmonospace": "\uFF20",
+ "/atnachHafukh:hb": "\u05A2",
+ "/atom": "\u269B",
+ "/atsmall": "\uFE6B",
+ "/attentionideographiccircled": "\u329F",
+ "/aturned": "\u0250",
+ "/au": "\uA737",
+ "/aubengali": "\u0994",
+ "/aubergine": "\u1F346",
+ "/aubopomofo": "\u3120",
+ "/audeva": "\u0914",
+ "/aufullwidth": "\u3373",
+ "/augujarati": "\u0A94",
+ "/augurmukhi": "\u0A14",
+ "/augusttelegraph": "\u32C7",
+ "/aulengthmarkbengali": "\u09D7",
+ "/aumatragurmukhi": "\u0A4C",
+ "/austral": "\u20B3",
+ "/automatedTellerMachine": "\u1F3E7",
+ "/automobile": "\u1F697",
+ "/auvowelsignbengali": "\u09CC",
+ "/auvowelsigndeva": "\u094C",
+ "/auvowelsigngujarati": "\u0ACC",
+ "/av": "\uA739",
+ "/avagrahadeva": "\u093D",
+ "/avhorizontalbar": "\uA73B",
+ "/ay": "\uA73D",
+ "/aybarmenian": "\u0561",
+ "/ayin": "\u05E2",
+ "/ayin:hb": "\u05E2",
+ "/ayinalt:hb": "\uFB20",
+ "/ayinaltonehebrew": "\uFB20",
+ "/ayinhebrew": "\u05E2",
+ "/azla:hb": "\u059C",
+ "/b": "\u0062",
+ "/baarerusquare": "\u332D",
+ "/babengali": "\u09AC",
+ "/babyAngel": "\u1F47C",
+ "/babyBottle": "\u1F37C",
+ "/babyChick": "\u1F424",
+ "/backLeftwardsArrowAbove": "\u1F519",
+ "/backOfEnvelope": "\u1F582",
+ "/backslash": "\u005C",
+ "/backslashbarfunc": "\u2340",
+ "/backslashdbl": "\u244A",
+ "/backslashmonospace": "\uFF3C",
+ "/bactrianCamel": "\u1F42B",
+ "/badeva": "\u092C",
+ "/badmintonRacquetAndShuttlecock": "\u1F3F8",
+ "/bagdelimitersshapeleft": "\u27C5",
+ "/bagdelimitersshaperight": "\u27C6",
+ "/baggageClaim": "\u1F6C4",
+ "/bagujarati": "\u0AAC",
+ "/bagurmukhi": "\u0A2C",
+ "/bahiragana": "\u3070",
+ "/bahtthai": "\u0E3F",
+ "/bakatakana": "\u30D0",
+ "/balloon": "\u1F388",
+ "/ballotBoldScriptX": "\u1F5F6",
+ "/ballotBoxBallot": "\u1F5F3",
+ "/ballotBoxBoldCheck": "\u1F5F9",
+ "/ballotBoxBoldScriptX": "\u1F5F7",
+ "/ballotBoxScriptX": "\u1F5F5",
+ "/ballotScriptX": "\u1F5F4",
+ "/bamurda": "\uA9A8",
+ "/banana": "\u1F34C",
+ "/bank": "\u1F3E6",
+ "/banknoteDollarSign": "\u1F4B5",
+ "/banknoteEuroSign": "\u1F4B6",
+ "/banknotePoundSign": "\u1F4B7",
+ "/banknoteYenSign": "\u1F4B4",
+ "/bar": "\u007C",
+ "/barChart": "\u1F4CA",
+ "/barberPole": "\u1F488",
+ "/barfullwidth": "\u3374",
+ "/barmonospace": "\uFF5C",
+ "/barquillverticalleft": "\u2E20",
+ "/barquillverticalright": "\u2E21",
+ "/baseball": "\u26BE",
+ "/basketballAndHoop": "\u1F3C0",
+ "/bath": "\u1F6C0",
+ "/bathtub": "\u1F6C1",
+ "/battery": "\u1F50B",
+ "/bbopomofo": "\u3105",
+ "/bcircle": "\u24D1",
+ "/bdot": "\u1E03",
+ "/bdotaccent": "\u1E03",
+ "/bdotbelow": "\u1E05",
+ "/beachUmbrella": "\u1F3D6",
+ "/beamedAscendingMusicalNotes": "\u1F39C",
+ "/beamedDescendingMusicalNotes": "\u1F39D",
+ "/beamedeighthnotes": "\u266B",
+ "/beamedsixteenthnotes": "\u266C",
+ "/beamfunc": "\u2336",
+ "/bearFace": "\u1F43B",
+ "/beatingHeart": "\u1F493",
+ "/because": "\u2235",
+ "/becyr": "\u0431",
+ "/becyrillic": "\u0431",
+ "/bed": "\u1F6CF",
+ "/beeh": "\u067B",
+ "/beeh.fina": "\uFB53",
+ "/beeh.init": "\uFB54",
+ "/beeh.isol": "\uFB52",
+ "/beeh.medi": "\uFB55",
+ "/beerMug": "\u1F37A",
+ "/beetasquare": "\u333C",
+ "/beh": "\u0628",
+ "/beh.fina": "\uFE90",
+ "/beh.init": "\uFE91",
+ "/beh.init_alefmaksura.fina": "\uFC09",
+ "/beh.init_hah.fina": "\uFC06",
+ "/beh.init_hah.medi": "\uFC9D",
+ "/beh.init_heh.medi": "\uFCA0",
+ "/beh.init_jeem.fina": "\uFC05",
+ "/beh.init_jeem.medi": "\uFC9C",
+ "/beh.init_khah.fina": "\uFC07",
+ "/beh.init_khah.medi": "\uFC9E",
+ "/beh.init_meem.fina": "\uFC08",
+ "/beh.init_meem.medi": "\uFC9F",
+ "/beh.init_yeh.fina": "\uFC0A",
+ "/beh.isol": "\uFE8F",
+ "/beh.medi": "\uFE92",
+ "/beh.medi_alefmaksura.fina": "\uFC6E",
+ "/beh.medi_hah.medi_yeh.fina": "\uFDC2",
+ "/beh.medi_heh.medi": "\uFCE2",
+ "/beh.medi_khah.medi_yeh.fina": "\uFD9E",
+ "/beh.medi_meem.fina": "\uFC6C",
+ "/beh.medi_meem.medi": "\uFCE1",
+ "/beh.medi_noon.fina": "\uFC6D",
+ "/beh.medi_reh.fina": "\uFC6A",
+ "/beh.medi_yeh.fina": "\uFC6F",
+ "/beh.medi_zain.fina": "\uFC6B",
+ "/behDotBelowThreeDotsAbove": "\u0751",
+ "/behInvertedSmallVBelow": "\u0755",
+ "/behSmallV": "\u0756",
+ "/behThreeDotsHorizontallyBelow": "\u0750",
+ "/behThreeDotsUpBelow": "\u0752",
+ "/behThreeDotsUpBelowTwoDotsAbove": "\u0753",
+ "/behTwoDotsBelowDotAbove": "\u0754",
+ "/beharabic": "\u0628",
+ "/beheh": "\u0680",
+ "/beheh.fina": "\uFB5B",
+ "/beheh.init": "\uFB5C",
+ "/beheh.isol": "\uFB5A",
+ "/beheh.medi": "\uFB5D",
+ "/behfinalarabic": "\uFE90",
+ "/behinitialarabic": "\uFE91",
+ "/behiragana": "\u3079",
+ "/behmedialarabic": "\uFE92",
+ "/behmeeminitialarabic": "\uFC9F",
+ "/behmeemisolatedarabic": "\uFC08",
+ "/behnoonfinalarabic": "\uFC6D",
+ "/bekatakana": "\u30D9",
+ "/bellCancellationStroke": "\u1F515",
+ "/bellhopBell": "\u1F6CE",
+ "/beltbuckle": "\u2444",
+ "/benarmenian": "\u0562",
+ "/beng:a": "\u0985",
+ "/beng:aa": "\u0986",
+ "/beng:aasign": "\u09BE",
+ "/beng:abbreviationsign": "\u09FD",
+ "/beng:ai": "\u0990",
+ "/beng:aisign": "\u09C8",
+ "/beng:anji": "\u0980",
+ "/beng:anusvara": "\u0982",
+ "/beng:au": "\u0994",
+ "/beng:aulengthmark": "\u09D7",
+ "/beng:ausign": "\u09CC",
+ "/beng:avagraha": "\u09BD",
+ "/beng:ba": "\u09AC",
+ "/beng:bha": "\u09AD",
+ "/beng:ca": "\u099A",
+ "/beng:candrabindu": "\u0981",
+ "/beng:cha": "\u099B",
+ "/beng:currencyoneless": "\u09F8",
+ "/beng:da": "\u09A6",
+ "/beng:dda": "\u09A1",
+ "/beng:ddha": "\u09A2",
+ "/beng:dha": "\u09A7",
+ "/beng:e": "\u098F",
+ "/beng:eight": "\u09EE",
+ "/beng:esign": "\u09C7",
+ "/beng:five": "\u09EB",
+ "/beng:four": "\u09EA",
+ "/beng:fourcurrencynumerator": "\u09F7",
+ "/beng:ga": "\u0997",
+ "/beng:gandamark": "\u09FB",
+ "/beng:gha": "\u0998",
+ "/beng:ha": "\u09B9",
+ "/beng:i": "\u0987",
+ "/beng:ii": "\u0988",
+ "/beng:iisign": "\u09C0",
+ "/beng:isign": "\u09BF",
+ "/beng:isshar": "\u09FA",
+ "/beng:ja": "\u099C",
+ "/beng:jha": "\u099D",
+ "/beng:ka": "\u0995",
+ "/beng:kha": "\u0996",
+ "/beng:khandata": "\u09CE",
+ "/beng:la": "\u09B2",
+ "/beng:llvocal": "\u09E1",
+ "/beng:llvocalsign": "\u09E3",
+ "/beng:lvocal": "\u098C",
+ "/beng:lvocalsign": "\u09E2",
+ "/beng:ma": "\u09AE",
+ "/beng:na": "\u09A8",
+ "/beng:nga": "\u0999",
+ "/beng:nine": "\u09EF",
+ "/beng:nna": "\u09A3",
+ "/beng:nukta": "\u09BC",
+ "/beng:nya": "\u099E",
+ "/beng:o": "\u0993",
+ "/beng:one": "\u09E7",
+ "/beng:onecurrencynumerator": "\u09F4",
+ "/beng:osign": "\u09CB",
+ "/beng:pa": "\u09AA",
+ "/beng:pha": "\u09AB",
+ "/beng:ra": "\u09B0",
+ "/beng:ralowdiagonal": "\u09F1",
+ "/beng:ramiddiagonal": "\u09F0",
+ "/beng:rha": "\u09DD",
+ "/beng:rra": "\u09DC",
+ "/beng:rrvocal": "\u09E0",
+ "/beng:rrvocalsign": "\u09C4",
+ "/beng:rupee": "\u09F3",
+ "/beng:rupeemark": "\u09F2",
+ "/beng:rvocal": "\u098B",
+ "/beng:rvocalsign": "\u09C3",
+ "/beng:sa": "\u09B8",
+ "/beng:seven": "\u09ED",
+ "/beng:sha": "\u09B6",
+ "/beng:six": "\u09EC",
+ "/beng:sixteencurrencydenominator": "\u09F9",
+ "/beng:ssa": "\u09B7",
+ "/beng:ta": "\u09A4",
+ "/beng:tha": "\u09A5",
+ "/beng:three": "\u09E9",
+ "/beng:threecurrencynumerator": "\u09F6",
+ "/beng:tta": "\u099F",
+ "/beng:ttha": "\u09A0",
+ "/beng:two": "\u09E8",
+ "/beng:twocurrencynumerator": "\u09F5",
+ "/beng:u": "\u0989",
+ "/beng:usign": "\u09C1",
+ "/beng:uu": "\u098A",
+ "/beng:uusign": "\u09C2",
+ "/beng:vedicanusvara": "\u09FC",
+ "/beng:virama": "\u09CD",
+ "/beng:visarga": "\u0983",
+ "/beng:ya": "\u09AF",
+ "/beng:yya": "\u09DF",
+ "/beng:zero": "\u09E6",
+ "/bentoBox": "\u1F371",
+ "/benzenering": "\u232C",
+ "/benzeneringcircle": "\u23E3",
+ "/bet": "\u05D1",
+ "/bet:hb": "\u05D1",
+ "/beta": "\u03B2",
+ "/betasymbol": "\u03D0",
+ "/betasymbolgreek": "\u03D0",
+ "/betdagesh": "\uFB31",
+ "/betdageshhebrew": "\uFB31",
+ "/bethebrew": "\u05D1",
+ "/betrafehebrew": "\uFB4C",
+ "/between": "\u226C",
+ "/betwithdagesh:hb": "\uFB31",
+ "/betwithrafe:hb": "\uFB4C",
+ "/bflourish": "\uA797",
+ "/bhabengali": "\u09AD",
+ "/bhadeva": "\u092D",
+ "/bhagujarati": "\u0AAD",
+ "/bhagurmukhi": "\u0A2D",
+ "/bhook": "\u0253",
+ "/bicycle": "\u1F6B2",
+ "/bicyclist": "\u1F6B4",
+ "/bihiragana": "\u3073",
+ "/bikatakana": "\u30D3",
+ "/bikini": "\u1F459",
+ "/bilabialclick": "\u0298",
+ "/billiards": "\u1F3B1",
+ "/bindigurmukhi": "\u0A02",
+ "/biohazard": "\u2623",
+ "/bird": "\u1F426",
+ "/birthdayCake": "\u1F382",
+ "/birusquare": "\u3331",
+ "/bishopblack": "\u265D",
+ "/bishopwhite": "\u2657",
+ "/bitcoin": "\u20BF",
+ "/blackDownPointingBackhandIndex": "\u1F5A3",
+ "/blackDroplet": "\u1F322",
+ "/blackFolder": "\u1F5BF",
+ "/blackHardShellFloppyDisk": "\u1F5AA",
+ "/blackHeart": "\u1F5A4",
+ "/blackLeftPointingBackhandIndex": "\u1F59C",
+ "/blackPennant": "\u1F3F2",
+ "/blackPushpin": "\u1F588",
+ "/blackRightPointingBackhandIndex": "\u1F59D",
+ "/blackRosette": "\u1F3F6",
+ "/blackSkullAndCrossbones": "\u1F571",
+ "/blackSquareButton": "\u1F532",
+ "/blackTouchtoneTelephone": "\u1F57F",
+ "/blackUpPointingBackhandIndex": "\u1F5A2",
+ "/blackcircle": "\u25CF",
+ "/blackcircleforrecord": "\u23FA",
+ "/blackdiamond": "\u25C6",
+ "/blackdownpointingtriangle": "\u25BC",
+ "/blackforstopsquare": "\u23F9",
+ "/blackleftpointingpointer": "\u25C4",
+ "/blackleftpointingtriangle": "\u25C0",
+ "/blacklenticularbracketleft": "\u3010",
+ "/blacklenticularbracketleftvertical": "\uFE3B",
+ "/blacklenticularbracketright": "\u3011",
+ "/blacklenticularbracketrightvertical": "\uFE3C",
+ "/blacklowerlefttriangle": "\u25E3",
+ "/blacklowerrighttriangle": "\u25E2",
+ "/blackmediumpointingtriangledown": "\u23F7",
+ "/blackmediumpointingtriangleleft": "\u23F4",
+ "/blackmediumpointingtriangleright": "\u23F5",
+ "/blackmediumpointingtriangleup": "\u23F6",
+ "/blackpointingdoubletrianglebarverticalleft": "\u23EE",
+ "/blackpointingdoubletrianglebarverticalright": "\u23ED",
+ "/blackpointingdoubletriangledown": "\u23EC",
+ "/blackpointingdoubletriangleleft": "\u23EA",
+ "/blackpointingdoubletriangleright": "\u23E9",
+ "/blackpointingdoubletriangleup": "\u23EB",
+ "/blackpointingtriangledoublebarverticalright": "\u23EF",
+ "/blackrectangle": "\u25AC",
+ "/blackrightpointingpointer": "\u25BA",
+ "/blackrightpointingtriangle": "\u25B6",
+ "/blacksmallsquare": "\u25AA",
+ "/blacksmilingface": "\u263B",
+ "/blacksquare": "\u25A0",
+ "/blackstar": "\u2605",
+ "/blackupperlefttriangle": "\u25E4",
+ "/blackupperrighttriangle": "\u25E5",
+ "/blackuppointingsmalltriangle": "\u25B4",
+ "/blackuppointingtriangle": "\u25B2",
+ "/blackwardsbulletleft": "\u204C",
+ "/blackwardsbulletright": "\u204D",
+ "/blank": "\u2423",
+ "/blinebelow": "\u1E07",
+ "/block": "\u2588",
+ "/blossom": "\u1F33C",
+ "/blowfish": "\u1F421",
+ "/blueBook": "\u1F4D8",
+ "/blueHeart": "\u1F499",
+ "/bmonospace": "\uFF42",
+ "/boar": "\u1F417",
+ "/board": "\u2328",
+ "/bobaimaithai": "\u0E1A",
+ "/bohiragana": "\u307C",
+ "/bokatakana": "\u30DC",
+ "/bomb": "\u1F4A3",
+ "/book": "\u1F56E",
+ "/bookmark": "\u1F516",
+ "/bookmarkTabs": "\u1F4D1",
+ "/books": "\u1F4DA",
+ "/bopo:a": "\u311A",
+ "/bopo:ai": "\u311E",
+ "/bopo:an": "\u3122",
+ "/bopo:ang": "\u3124",
+ "/bopo:au": "\u3120",
+ "/bopo:b": "\u3105",
+ "/bopo:c": "\u3118",
+ "/bopo:ch": "\u3114",
+ "/bopo:d": "\u3109",
+ "/bopo:e": "\u311C",
+ "/bopo:eh": "\u311D",
+ "/bopo:ei": "\u311F",
+ "/bopo:en": "\u3123",
+ "/bopo:eng": "\u3125",
+ "/bopo:er": "\u3126",
+ "/bopo:f": "\u3108",
+ "/bopo:g": "\u310D",
+ "/bopo:gn": "\u312C",
+ "/bopo:h": "\u310F",
+ "/bopo:i": "\u3127",
+ "/bopo:ih": "\u312D",
+ "/bopo:iu": "\u3129",
+ "/bopo:j": "\u3110",
+ "/bopo:k": "\u310E",
+ "/bopo:l": "\u310C",
+ "/bopo:m": "\u3107",
+ "/bopo:n": "\u310B",
+ "/bopo:ng": "\u312B",
+ "/bopo:o": "\u311B",
+ "/bopo:ou": "\u3121",
+ "/bopo:owithdotabove": "\u312E",
+ "/bopo:p": "\u3106",
+ "/bopo:q": "\u3111",
+ "/bopo:r": "\u3116",
+ "/bopo:s": "\u3119",
+ "/bopo:sh": "\u3115",
+ "/bopo:t": "\u310A",
+ "/bopo:u": "\u3128",
+ "/bopo:v": "\u312A",
+ "/bopo:x": "\u3112",
+ "/bopo:z": "\u3117",
+ "/bopo:zh": "\u3113",
+ "/borutosquare": "\u333E",
+ "/bottlePoppingCork": "\u1F37E",
+ "/bouquet": "\u1F490",
+ "/bouquetOfFlowers": "\u1F395",
+ "/bowAndArrow": "\u1F3F9",
+ "/bowlOfHygieia": "\u1F54F",
+ "/bowling": "\u1F3B3",
+ "/boxlineverticalleft": "\u23B8",
+ "/boxlineverticalright": "\u23B9",
+ "/boy": "\u1F466",
+ "/boys": "\u1F6C9",
+ "/bparen": "\u249D",
+ "/bparenthesized": "\u249D",
+ "/bqfullwidth": "\u33C3",
+ "/bqsquare": "\u33C3",
+ "/braceex": "\uF8F4",
+ "/braceleft": "\u007B",
+ "/braceleftbt": "\uF8F3",
+ "/braceleftmid": "\uF8F2",
+ "/braceleftmonospace": "\uFF5B",
+ "/braceleftsmall": "\uFE5B",
+ "/bracelefttp": "\uF8F1",
+ "/braceleftvertical": "\uFE37",
+ "/braceright": "\u007D",
+ "/bracerightbt": "\uF8FE",
+ "/bracerightmid": "\uF8FD",
+ "/bracerightmonospace": "\uFF5D",
+ "/bracerightsmall": "\uFE5C",
+ "/bracerighttp": "\uF8FC",
+ "/bracerightvertical": "\uFE38",
+ "/bracketangledblleft": "\u27EA",
+ "/bracketangledblright": "\u27EB",
+ "/bracketangleleft": "\u27E8",
+ "/bracketangleright": "\u27E9",
+ "/bracketbottomcurly": "\u23DF",
+ "/bracketbottomsquare": "\u23B5",
+ "/bracketcornerupleftsquare": "\u23A1",
+ "/bracketcorneruprightsquare": "\u23A4",
+ "/bracketdottedsubstitutionleft": "\u2E04",
+ "/bracketdottedsubstitutionright": "\u2E05",
+ "/bracketextensioncurly": "\u23AA",
+ "/bracketextensionleftsquare": "\u23A2",
+ "/bracketextensionrightsquare": "\u23A5",
+ "/brackethalfbottomleft": "\u2E24",
+ "/brackethalfbottomright": "\u2E25",
+ "/brackethalftopleft": "\u2E22",
+ "/brackethalftopright": "\u2E23",
+ "/brackethookupleftcurly": "\u23A7",
+ "/brackethookuprightcurly": "\u23AB",
+ "/bracketleft": "\u005B",
+ "/bracketleftbt": "\uF8F0",
+ "/bracketleftex": "\uF8EF",
+ "/bracketleftmonospace": "\uFF3B",
+ "/bracketleftsquarequill": "\u2045",
+ "/bracketlefttp": "\uF8EE",
+ "/bracketlowercornerleftsquare": "\u23A3",
+ "/bracketlowercornerrightsquare": "\u23A6",
+ "/bracketlowerhookleftcurly": "\u23A9",
+ "/bracketlowerhookrightcurly": "\u23AD",
+ "/bracketmiddlepieceleftcurly": "\u23A8",
+ "/bracketmiddlepiecerightcurly": "\u23AC",
+ "/bracketoverbrackettopbottomsquare": "\u23B6",
+ "/bracketparaphraselowleft": "\u2E1C",
+ "/bracketparaphraselowright": "\u2E1D",
+ "/bracketraisedleft": "\u2E0C",
+ "/bracketraisedright": "\u2E0D",
+ "/bracketright": "\u005D",
+ "/bracketrightbt": "\uF8FB",
+ "/bracketrightex": "\uF8FA",
+ "/bracketrightmonospace": "\uFF3D",
+ "/bracketrightsquarequill": "\u2046",
+ "/bracketrighttp": "\uF8F9",
+ "/bracketsectionupleftlowerrightcurly": "\u23B0",
+ "/bracketsectionuprightlowerleftcurly": "\u23B1",
+ "/bracketshellbottom": "\u23E1",
+ "/bracketshelltop": "\u23E0",
+ "/bracketshellwhiteleft": "\u27EC",
+ "/bracketshellwhiteright": "\u27ED",
+ "/bracketsubstitutionleft": "\u2E02",
+ "/bracketsubstitutionright": "\u2E03",
+ "/brackettopcurly": "\u23DE",
+ "/brackettopsquare": "\u23B4",
+ "/brackettranspositionleft": "\u2E09",
+ "/brackettranspositionright": "\u2E0A",
+ "/bracketwhitesquareleft": "\u27E6",
+ "/bracketwhitesquareright": "\u27E7",
+ "/branchbankidentification": "\u2446",
+ "/bread": "\u1F35E",
+ "/breve": "\u02D8",
+ "/brevebelowcmb": "\u032E",
+ "/brevecmb": "\u0306",
+ "/breveinvertedbelowcmb": "\u032F",
+ "/breveinvertedcmb": "\u0311",
+ "/breveinverteddoublecmb": "\u0361",
+ "/brevemetrical": "\u23D1",
+ "/brideVeil": "\u1F470",
+ "/bridgeAtNight": "\u1F309",
+ "/bridgebelowcmb": "\u032A",
+ "/bridgeinvertedbelowcmb": "\u033A",
+ "/briefcase": "\u1F4BC",
+ "/brll:blank": "\u2800",
+ "/brokenHeart": "\u1F494",
+ "/brokenbar": "\u00A6",
+ "/brokencirclenorthwestarrow": "\u238B",
+ "/bstroke": "\u0180",
+ "/bsuperior": "\uF6EA",
+ "/btopbar": "\u0183",
+ "/bug": "\u1F41B",
+ "/buhiragana": "\u3076",
+ "/buildingConstruction": "\u1F3D7",
+ "/bukatakana": "\u30D6",
+ "/bullet": "\u2022",
+ "/bulletinverse": "\u25D8",
+ "/bulletoperator": "\u2219",
+ "/bullhorn": "\u1F56B",
+ "/bullhornSoundWaves": "\u1F56C",
+ "/bullseye": "\u25CE",
+ "/burrito": "\u1F32F",
+ "/bus": "\u1F68C",
+ "/busStop": "\u1F68F",
+ "/bussyerusquare": "\u3334",
+ "/bustInSilhouette": "\u1F464",
+ "/bustsInSilhouette": "\u1F465",
+ "/c": "\u0063",
+ "/caarmenian": "\u056E",
+ "/cabengali": "\u099A",
+ "/cactus": "\u1F335",
+ "/cacute": "\u0107",
+ "/cadauna": "\u2106",
+ "/cadeva": "\u091A",
+ "/caduceus": "\u2624",
+ "/cagujarati": "\u0A9A",
+ "/cagurmukhi": "\u0A1A",
+ "/cakraconsonant": "\uA9BF",
+ "/calendar": "\u1F4C5",
+ "/calfullwidth": "\u3388",
+ "/callideographicparen": "\u323A",
+ "/calsquare": "\u3388",
+ "/camera": "\u1F4F7",
+ "/cameraFlash": "\u1F4F8",
+ "/camping": "\u1F3D5",
+ "/camurda": "\uA996",
+ "/cancellationX": "\u1F5D9",
+ "/cancer": "\u264B",
+ "/candle": "\u1F56F",
+ "/candrabindubengali": "\u0981",
+ "/candrabinducmb": "\u0310",
+ "/candrabindudeva": "\u0901",
+ "/candrabindugujarati": "\u0A81",
+ "/candy": "\u1F36C",
+ "/canoe": "\u1F6F6",
+ "/capitulum": "\u2E3F",
+ "/capricorn": "\u2651",
+ "/capslock": "\u21EA",
+ "/cardFileBox": "\u1F5C3",
+ "/cardIndex": "\u1F4C7",
+ "/cardIndexDividers": "\u1F5C2",
+ "/careof": "\u2105",
+ "/caret": "\u2038",
+ "/caretinsertionpoint": "\u2041",
+ "/carettildedownfunc": "\u2371",
+ "/carettildeupfunc": "\u2372",
+ "/caron": "\u02C7",
+ "/caronbelowcmb": "\u032C",
+ "/caroncmb": "\u030C",
+ "/carouselHorse": "\u1F3A0",
+ "/carpStreamer": "\u1F38F",
+ "/carriagereturn": "\u21B5",
+ "/carsliding": "\u26D0",
+ "/castle": "\u26EB",
+ "/cat": "\u1F408",
+ "/catFace": "\u1F431",
+ "/catFaceWithTearsOfJoy": "\u1F639",
+ "/catFaceWithWrySmile": "\u1F63C",
+ "/caution": "\u2621",
+ "/cbar": "\uA793",
+ "/cbopomofo": "\u3118",
+ "/ccaron": "\u010D",
+ "/ccedilla": "\u00E7",
+ "/ccedillaacute": "\u1E09",
+ "/ccfullwidth": "\u33C4",
+ "/ccircle": "\u24D2",
+ "/ccircumflex": "\u0109",
+ "/ccurl": "\u0255",
+ "/cdfullwidth": "\u33C5",
+ "/cdot": "\u010B",
+ "/cdotaccent": "\u010B",
+ "/cdotreversed": "\uA73F",
+ "/cdsquare": "\u33C5",
+ "/cecak": "\uA981",
+ "/cecaktelu": "\uA9B3",
+ "/cedi": "\u20B5",
+ "/cedilla": "\u00B8",
+ "/cedillacmb": "\u0327",
+ "/ceilingleft": "\u2308",
+ "/ceilingright": "\u2309",
+ "/celticCross": "\u1F548",
+ "/cent": "\u00A2",
+ "/centigrade": "\u2103",
+ "/centinferior": "\uF6DF",
+ "/centmonospace": "\uFFE0",
+ "/centoldstyle": "\uF7A2",
+ "/centreddotwhitediamond": "\u27D0",
+ "/centreideographiccircled": "\u32A5",
+ "/centreline": "\u2104",
+ "/centrelineverticalsquarewhite": "\u2385",
+ "/centsuperior": "\uF6E0",
+ "/ceres": "\u26B3",
+ "/chaarmenian": "\u0579",
+ "/chabengali": "\u099B",
+ "/chadeva": "\u091B",
+ "/chagujarati": "\u0A9B",
+ "/chagurmukhi": "\u0A1B",
+ "/chains": "\u26D3",
+ "/chair": "\u2441",
+ "/chamkocircle": "\u327C",
+ "/charactertie": "\u2040",
+ "/chartDownwardsTrend": "\u1F4C9",
+ "/chartUpwardsTrend": "\u1F4C8",
+ "/chartUpwardsTrendAndYenSign": "\u1F4B9",
+ "/chbopomofo": "\u3114",
+ "/cheabkhasiancyrillic": "\u04BD",
+ "/cheabkhcyr": "\u04BD",
+ "/cheabkhtailcyr": "\u04BF",
+ "/checkbox": "\u2610",
+ "/checkboxchecked": "\u2611",
+ "/checkboxx": "\u2612",
+ "/checkmark": "\u2713",
+ "/checyr": "\u0447",
+ "/checyrillic": "\u0447",
+ "/chedescenderabkhasiancyrillic": "\u04BF",
+ "/chedescendercyrillic": "\u04B7",
+ "/chedieresiscyr": "\u04F5",
+ "/chedieresiscyrillic": "\u04F5",
+ "/cheeringMegaphone": "\u1F4E3",
+ "/cheharmenian": "\u0573",
+ "/chekhakascyr": "\u04CC",
+ "/chekhakassiancyrillic": "\u04CC",
+ "/chequeredFlag": "\u1F3C1",
+ "/cherries": "\u1F352",
+ "/cherryBlossom": "\u1F338",
+ "/chestnut": "\u1F330",
+ "/chetailcyr": "\u04B7",
+ "/chevertcyr": "\u04B9",
+ "/cheverticalstrokecyrillic": "\u04B9",
+ "/chi": "\u03C7",
+ "/chicken": "\u1F414",
+ "/chieuchacirclekorean": "\u3277",
+ "/chieuchaparenkorean": "\u3217",
+ "/chieuchcirclekorean": "\u3269",
+ "/chieuchkorean": "\u314A",
+ "/chieuchparenkorean": "\u3209",
+ "/childrenCrossing": "\u1F6B8",
+ "/chipmunk": "\u1F43F",
+ "/chirho": "\u2627",
+ "/chiron": "\u26B7",
+ "/chochangthai": "\u0E0A",
+ "/chochanthai": "\u0E08",
+ "/chochingthai": "\u0E09",
+ "/chochoethai": "\u0E0C",
+ "/chocolateBar": "\u1F36B",
+ "/chook": "\u0188",
+ "/christmasTree": "\u1F384",
+ "/church": "\u26EA",
+ "/cieucacirclekorean": "\u3276",
+ "/cieucaparenkorean": "\u3216",
+ "/cieuccirclekorean": "\u3268",
+ "/cieuckorean": "\u3148",
+ "/cieucparenkorean": "\u3208",
+ "/cieucuparenkorean": "\u321C",
+ "/cinema": "\u1F3A6",
+ "/circle": "\u25CB",
+ "/circleallbutupperquadrantleftblack": "\u25D5",
+ "/circlebackslashfunc": "\u2349",
+ "/circleblack": "\u25CF",
+ "/circledCrossPommee": "\u1F540",
+ "/circledInformationSource": "\u1F6C8",
+ "/circledasteriskoperator": "\u229B",
+ "/circledbarnotchhorizontal": "\u2389",
+ "/circledcrossinglanes": "\u26D2",
+ "/circleddash": "\u229D",
+ "/circleddivisionslash": "\u2298",
+ "/circleddotoperator": "\u2299",
+ "/circledequals": "\u229C",
+ "/circlediaeresisfunc": "\u2365",
+ "/circledminus": "\u2296",
+ "/circledot": "\u2299",
+ "/circledotrightwhite": "\u2686",
+ "/circledotted": "\u25CC",
+ "/circledringoperator": "\u229A",
+ "/circledtriangledown": "\u238A",
+ "/circlehalfleftblack": "\u25D0",
+ "/circlehalfrightblack": "\u25D1",
+ "/circleinversewhite": "\u25D9",
+ "/circlejotfunc": "\u233E",
+ "/circlelowerhalfblack": "\u25D2",
+ "/circlelowerquadrantleftwhite": "\u25F5",
+ "/circlelowerquadrantrightwhite": "\u25F6",
+ "/circlemultiply": "\u2297",
+ "/circleot": "\u2299",
+ "/circleplus": "\u2295",
+ "/circlepostalmark": "\u3036",
+ "/circlestarfunc": "\u235F",
+ "/circlestilefunc": "\u233D",
+ "/circlestroketwodotsaboveheavy": "\u26E3",
+ "/circletwodotsblackwhite": "\u2689",
+ "/circletwodotswhite": "\u2687",
+ "/circleunderlinefunc": "\u235C",
+ "/circleupperhalfblack": "\u25D3",
+ "/circleupperquadrantleftwhite": "\u25F4",
+ "/circleupperquadrantrightblack": "\u25D4",
+ "/circleupperquadrantrightwhite": "\u25F7",
+ "/circleverticalfill": "\u25CD",
+ "/circlewhite": "\u25CB",
+ "/circlewhitedotrightblack": "\u2688",
+ "/circlewithlefthalfblack": "\u25D0",
+ "/circlewithrighthalfblack": "\u25D1",
+ "/circumflex": "\u02C6",
+ "/circumflexbelowcmb": "\u032D",
+ "/circumflexcmb": "\u0302",
+ "/circumflexlow": "\uA788",
+ "/circusTent": "\u1F3AA",
+ "/cityscape": "\u1F3D9",
+ "/cityscapeAtDusk": "\u1F306",
+ "/cjk:ideographiccomma": "\u3001",
+ "/cjk:tortoiseshellbracketleft": "\u3014",
+ "/cjk:tortoiseshellbracketright": "\u3015",
+ "/clamshellMobilePhone": "\u1F581",
+ "/clapperBoard": "\u1F3AC",
+ "/clappingHandsSign": "\u1F44F",
+ "/classicalBuilding": "\u1F3DB",
+ "/clear": "\u2327",
+ "/clearscreen": "\u239A",
+ "/clickalveolar": "\u01C2",
+ "/clickbilabial": "\u0298",
+ "/clickdental": "\u01C0",
+ "/clicklateral": "\u01C1",
+ "/clickretroflex": "\u01C3",
+ "/clinkingBeerMugs": "\u1F37B",
+ "/clipboard": "\u1F4CB",
+ "/clockFaceEight-thirty": "\u1F563",
+ "/clockFaceEightOclock": "\u1F557",
+ "/clockFaceEleven-thirty": "\u1F566",
+ "/clockFaceElevenOclock": "\u1F55A",
+ "/clockFaceFive-thirty": "\u1F560",
+ "/clockFaceFiveOclock": "\u1F554",
+ "/clockFaceFour-thirty": "\u1F55F",
+ "/clockFaceFourOclock": "\u1F553",
+ "/clockFaceNine-thirty": "\u1F564",
+ "/clockFaceNineOclock": "\u1F558",
+ "/clockFaceOne-thirty": "\u1F55C",
+ "/clockFaceOneOclock": "\u1F550",
+ "/clockFaceSeven-thirty": "\u1F562",
+ "/clockFaceSevenOclock": "\u1F556",
+ "/clockFaceSix-thirty": "\u1F561",
+ "/clockFaceSixOclock": "\u1F555",
+ "/clockFaceTen-thirty": "\u1F565",
+ "/clockFaceTenOclock": "\u1F559",
+ "/clockFaceThree-thirty": "\u1F55E",
+ "/clockFaceThreeOclock": "\u1F552",
+ "/clockFaceTwelve-thirty": "\u1F567",
+ "/clockFaceTwelveOclock": "\u1F55B",
+ "/clockFaceTwo-thirty": "\u1F55D",
+ "/clockFaceTwoOclock": "\u1F551",
+ "/clockwiseDownwardsAndUpwardsOpenCircleArrows": "\u1F503",
+ "/clockwiseRightAndLeftSemicircleArrows": "\u1F5D8",
+ "/clockwiseRightwardsAndLeftwardsOpenCircleArrows": "\u1F501",
+ "/clockwiseRightwardsAndLeftwardsOpenCircleArrowsCircledOneOverlay": "\u1F502",
+ "/closedBook": "\u1F4D5",
+ "/closedLockKey": "\u1F510",
+ "/closedMailboxLoweredFlag": "\u1F4EA",
+ "/closedMailboxRaisedFlag": "\u1F4EB",
+ "/closedUmbrella": "\u1F302",
+ "/closedentryleft": "\u26DC",
+ "/closeup": "\u2050",
+ "/cloud": "\u2601",
+ "/cloudLightning": "\u1F329",
+ "/cloudRain": "\u1F327",
+ "/cloudSnow": "\u1F328",
+ "/cloudTornado": "\u1F32A",
+ "/clsquare": "\u1F191",
+ "/club": "\u2663",
+ "/clubblack": "\u2663",
+ "/clubsuitblack": "\u2663",
+ "/clubsuitwhite": "\u2667",
+ "/clubwhite": "\u2667",
+ "/cm2fullwidth": "\u33A0",
+ "/cm3fullwidth": "\u33A4",
+ "/cmb:a": "\u0363",
+ "/cmb:aaboveflat": "\u1DD3",
+ "/cmb:aboveogonek": "\u1DCE",
+ "/cmb:acute": "\u0301",
+ "/cmb:acutebelow": "\u0317",
+ "/cmb:acutegraveacute": "\u1DC9",
+ "/cmb:acutemacron": "\u1DC7",
+ "/cmb:acutetone": "\u0341",
+ "/cmb:adieresis": "\u1DF2",
+ "/cmb:ae": "\u1DD4",
+ "/cmb:almostequalabove": "\u034C",
+ "/cmb:almostequaltobelow": "\u1DFD",
+ "/cmb:alpha": "\u1DE7",
+ "/cmb:ao": "\u1DD5",
+ "/cmb:arrowheadleftbelow": "\u0354",
+ "/cmb:arrowheadrightabove": "\u0350",
+ "/cmb:arrowheadrightarrowheadupbelow": "\u0356",
+ "/cmb:arrowheadrightbelow": "\u0355",
+ "/cmb:arrowleftrightbelow": "\u034D",
+ "/cmb:arrowrightdoublebelow": "\u0362",
+ "/cmb:arrowupbelow": "\u034E",
+ "/cmb:asteriskbelow": "\u0359",
+ "/cmb:av": "\u1DD6",
+ "/cmb:b": "\u1DE8",
+ "/cmb:belowbreve": "\u032E",
+ "/cmb:beta": "\u1DE9",
+ "/cmb:breve": "\u0306",
+ "/cmb:brevemacron": "\u1DCB",
+ "/cmb:bridgeabove": "\u0346",
+ "/cmb:bridgebelow": "\u032A",
+ "/cmb:c": "\u0368",
+ "/cmb:candrabindu": "\u0310",
+ "/cmb:caron": "\u030C",
+ "/cmb:caronbelow": "\u032C",
+ "/cmb:ccedilla": "\u1DD7",
+ "/cmb:cedilla": "\u0327",
+ "/cmb:circumflex": "\u0302",
+ "/cmb:circumflexbelow": "\u032D",
+ "/cmb:commaaccentbelow": "\u0326",
+ "/cmb:commaturnedabove": "\u0312",
+ "/cmb:d": "\u0369",
+ "/cmb:dblarchinvertedbelow": "\u032B",
+ "/cmb:dbloverline": "\u033F",
+ "/cmb:dblverticallineabove": "\u030E",
+ "/cmb:dblverticallinebelow": "\u0348",
+ "/cmb:deletionmark": "\u1DFB",
+ "/cmb:dialytikatonos": "\u0344",
+ "/cmb:dieresis": "\u0308",
+ "/cmb:dieresisbelow": "\u0324",
+ "/cmb:dotaboveleft": "\u1DF8",
+ "/cmb:dotaccent": "\u0307",
+ "/cmb:dotbelowcomb": "\u0323",
+ "/cmb:dotrightabove": "\u0358",
+ "/cmb:dottedacute": "\u1DC1",
+ "/cmb:dottedgrave": "\u1DC0",
+ "/cmb:doubleabovecircumflex": "\u1DCD",
+ "/cmb:doublebelowbreve": "\u035C",
+ "/cmb:doublebreve": "\u035D",
+ "/cmb:doubleinvertedbelowbreve": "\u1DFC",
+ "/cmb:doubleringbelow": "\u035A",
+ "/cmb:downtackbelow": "\u031E",
+ "/cmb:e": "\u0364",
+ "/cmb:equalbelow": "\u0347",
+ "/cmb:esh": "\u1DEF",
+ "/cmb:eth": "\u1DD9",
+ "/cmb:f": "\u1DEB",
+ "/cmb:fermata": "\u0352",
+ "/cmb:g": "\u1DDA",
+ "/cmb:graphemejoiner": "\u034F",
+ "/cmb:grave": "\u0300",
+ "/cmb:graveacutegrave": "\u1DC8",
+ "/cmb:gravebelow": "\u0316",
+ "/cmb:gravedouble": "\u030F",
+ "/cmb:gravemacron": "\u1DC5",
+ "/cmb:gravetone": "\u0340",
+ "/cmb:gsmall": "\u1DDB",
+ "/cmb:h": "\u036A",
+ "/cmb:halfleftringabove": "\u0351",
+ "/cmb:halfleftringbelow": "\u031C",
+ "/cmb:halfrightringabove": "\u0357",
+ "/cmb:halfrightringbelow": "\u0339",
+ "/cmb:homotheticabove": "\u034B",
+ "/cmb:hookabove": "\u0309",
+ "/cmb:horn": "\u031B",
+ "/cmb:hungarumlaut": "\u030B",
+ "/cmb:i": "\u0365",
+ "/cmb:insulard": "\u1DD8",
+ "/cmb:invertedbelowbreve": "\u032F",
+ "/cmb:invertedbreve": "\u0311",
+ "/cmb:invertedbridgebelow": "\u033A",
+ "/cmb:inverteddoublebreve": "\u0361",
+ "/cmb:iotasub": "\u0345",
+ "/cmb:isbelow": "\u1DD0",
+ "/cmb:k": "\u1DDC",
+ "/cmb:kavykaaboveleft": "\u1DF7",
+ "/cmb:kavykaaboveright": "\u1DF6",
+ "/cmb:koronis": "\u0343",
+ "/cmb:l": "\u1DDD",
+ "/cmb:leftangleabove": "\u031A",
+ "/cmb:leftanglebelow": "\u0349",
+ "/cmb:leftarrowheadabove": "\u1DFE",
+ "/cmb:lefttackbelow": "\u0318",
+ "/cmb:lineverticalabove": "\u030D",
+ "/cmb:lineverticalbelow": "\u0329",
+ "/cmb:longs": "\u1DE5",
+ "/cmb:lowline": "\u0332",
+ "/cmb:lowlinedouble": "\u0333",
+ "/cmb:lsmall": "\u1DDE",
+ "/cmb:lwithdoublemiddletilde": "\u1DEC",
+ "/cmb:m": "\u036B",
+ "/cmb:macron": "\u0304",
+ "/cmb:macronacute": "\u1DC4",
+ "/cmb:macronbelow": "\u0331",
+ "/cmb:macronbreve": "\u1DCC",
+ "/cmb:macrondouble": "\u035E",
+ "/cmb:macrondoublebelow": "\u035F",
+ "/cmb:macrongrave": "\u1DC6",
+ "/cmb:minusbelow": "\u0320",
+ "/cmb:msmall": "\u1DDF",
+ "/cmb:n": "\u1DE0",
+ "/cmb:nottildeabove": "\u034A",
+ "/cmb:nsmall": "\u1DE1",
+ "/cmb:o": "\u0366",
+ "/cmb:odieresis": "\u1DF3",
+ "/cmb:ogonek": "\u0328",
+ "/cmb:overlaystrokelong": "\u0336",
+ "/cmb:overlaystrokeshort": "\u0335",
+ "/cmb:overline": "\u0305",
+ "/cmb:owithlightcentralizationstroke": "\u1DED",
+ "/cmb:p": "\u1DEE",
+ "/cmb:palatalizedhookbelow": "\u0321",
+ "/cmb:perispomeni": "\u0342",
+ "/cmb:plusbelow": "\u031F",
+ "/cmb:r": "\u036C",
+ "/cmb:rbelow": "\u1DCA",
+ "/cmb:retroflexhookbelow": "\u0322",
+ "/cmb:reversedcommaabove": "\u0314",
+ "/cmb:rightarrowheadanddownarrowheadbelow": "\u1DFF",
+ "/cmb:righttackbelow": "\u0319",
+ "/cmb:ringabove": "\u030A",
+ "/cmb:ringbelow": "\u0325",
+ "/cmb:rrotunda": "\u1DE3",
+ "/cmb:rsmall": "\u1DE2",
+ "/cmb:s": "\u1DE4",
+ "/cmb:schwa": "\u1DEA",
+ "/cmb:seagullbelow": "\u033C",
+ "/cmb:snakebelow": "\u1DC2",
+ "/cmb:soliduslongoverlay": "\u0338",
+ "/cmb:solidusshortoverlay": "\u0337",
+ "/cmb:squarebelow": "\u033B",
+ "/cmb:suspensionmark": "\u1DC3",
+ "/cmb:t": "\u036D",
+ "/cmb:tilde": "\u0303",
+ "/cmb:tildebelow": "\u0330",
+ "/cmb:tildedouble": "\u0360",
+ "/cmb:tildeoverlay": "\u0334",
+ "/cmb:tildevertical": "\u033E",
+ "/cmb:turnedabove": "\u0313",
+ "/cmb:turnedcommaabove": "\u0315",
+ "/cmb:u": "\u0367",
+ "/cmb:udieresis": "\u1DF4",
+ "/cmb:uptackabove": "\u1DF5",
+ "/cmb:uptackbelow": "\u031D",
+ "/cmb:urabove": "\u1DD1",
+ "/cmb:usabove": "\u1DD2",
+ "/cmb:uwithlightcentralizationstroke": "\u1DF0",
+ "/cmb:v": "\u036E",
+ "/cmb:w": "\u1DF1",
+ "/cmb:wideinvertedbridgebelow": "\u1DF9",
+ "/cmb:x": "\u036F",
+ "/cmb:xabove": "\u033D",
+ "/cmb:xbelow": "\u0353",
+ "/cmb:z": "\u1DE6",
+ "/cmb:zigzagabove": "\u035B",
+ "/cmb:zigzagbelow": "\u1DCF",
+ "/cmcubedsquare": "\u33A4",
+ "/cmfullwidth": "\u339D",
+ "/cmonospace": "\uFF43",
+ "/cmsquaredsquare": "\u33A0",
+ "/cntr:acknowledge": "\u2406",
+ "/cntr:backspace": "\u2408",
+ "/cntr:bell": "\u2407",
+ "/cntr:blank": "\u2422",
+ "/cntr:cancel": "\u2418",
+ "/cntr:carriagereturn": "\u240D",
+ "/cntr:datalinkescape": "\u2410",
+ "/cntr:delete": "\u2421",
+ "/cntr:deleteformtwo": "\u2425",
+ "/cntr:devicecontrolfour": "\u2414",
+ "/cntr:devicecontrolone": "\u2411",
+ "/cntr:devicecontrolthree": "\u2413",
+ "/cntr:devicecontroltwo": "\u2412",
+ "/cntr:endofmedium": "\u2419",
+ "/cntr:endoftext": "\u2403",
+ "/cntr:endoftransmission": "\u2404",
+ "/cntr:endoftransmissionblock": "\u2417",
+ "/cntr:enquiry": "\u2405",
+ "/cntr:escape": "\u241B",
+ "/cntr:fileseparator": "\u241C",
+ "/cntr:formfeed": "\u240C",
+ "/cntr:groupseparator": "\u241D",
+ "/cntr:horizontaltab": "\u2409",
+ "/cntr:linefeed": "\u240A",
+ "/cntr:negativeacknowledge": "\u2415",
+ "/cntr:newline": "\u2424",
+ "/cntr:null": "\u2400",
+ "/cntr:openbox": "\u2423",
+ "/cntr:recordseparator": "\u241E",
+ "/cntr:shiftin": "\u240F",
+ "/cntr:shiftout": "\u240E",
+ "/cntr:space": "\u2420",
+ "/cntr:startofheading": "\u2401",
+ "/cntr:startoftext": "\u2402",
+ "/cntr:substitute": "\u241A",
+ "/cntr:substituteformtwo": "\u2426",
+ "/cntr:synchronousidle": "\u2416",
+ "/cntr:unitseparator": "\u241F",
+ "/cntr:verticaltab": "\u240B",
+ "/coarmenian": "\u0581",
+ "/cocktailGlass": "\u1F378",
+ "/coffin": "\u26B0",
+ "/cofullwidth": "\u33C7",
+ "/collision": "\u1F4A5",
+ "/colon": "\u003A",
+ "/colonequals": "\u2254",
+ "/colonmod": "\uA789",
+ "/colonmonetary": "\u20A1",
+ "/colonmonospace": "\uFF1A",
+ "/colonraisedmod": "\u02F8",
+ "/colonsign": "\u20A1",
+ "/colonsmall": "\uFE55",
+ "/colontriangularhalfmod": "\u02D1",
+ "/colontriangularmod": "\u02D0",
+ "/comet": "\u2604",
+ "/comma": "\u002C",
+ "/commaabovecmb": "\u0313",
+ "/commaaboverightcmb": "\u0315",
+ "/commaaccent": "\uF6C3",
+ "/commaarabic": "\u060C",
+ "/commaarmenian": "\u055D",
+ "/commabarfunc": "\u236A",
+ "/commainferior": "\uF6E1",
+ "/commamonospace": "\uFF0C",
+ "/commaraised": "\u2E34",
+ "/commareversed": "\u2E41",
+ "/commareversedabovecmb": "\u0314",
+ "/commareversedmod": "\u02BD",
+ "/commasmall": "\uFE50",
+ "/commasuperior": "\uF6E2",
+ "/commaturnedabovecmb": "\u0312",
+ "/commaturnedmod": "\u02BB",
+ "/commercialat": "\uFE6B",
+ "/commercialminussign": "\u2052",
+ "/compass": "\u263C",
+ "/complement": "\u2201",
+ "/composition": "\u2384",
+ "/compression": "\u1F5DC",
+ "/con": "\uA76F",
+ "/confettiBall": "\u1F38A",
+ "/confoundedFace": "\u1F616",
+ "/confusedFace": "\u1F615",
+ "/congratulationideographiccircled": "\u3297",
+ "/congratulationideographicparen": "\u3237",
+ "/congruent": "\u2245",
+ "/conicaltaper": "\u2332",
+ "/conjunction": "\u260C",
+ "/consquareupblack": "\u26FE",
+ "/constructionSign": "\u1F6A7",
+ "/constructionWorker": "\u1F477",
+ "/containsasmembersmall": "\u220D",
+ "/containsasnormalsubgroorequalup": "\u22B5",
+ "/containsasnormalsubgroup": "\u22B3",
+ "/containslonghorizontalstroke": "\u22FA",
+ "/containsoverbar": "\u22FD",
+ "/containsoverbarsmall": "\u22FE",
+ "/containssmallverticalbarhorizontalstroke": "\u22FC",
+ "/containsverticalbarhorizontalstroke": "\u22FB",
+ "/continuousunderline": "\u2381",
+ "/contourintegral": "\u222E",
+ "/control": "\u2303",
+ "/controlACK": "\u0006",
+ "/controlBEL": "\u0007",
+ "/controlBS": "\u0008",
+ "/controlCAN": "\u0018",
+ "/controlCR": "\u000D",
+ "/controlDC1": "\u0011",
+ "/controlDC2": "\u0012",
+ "/controlDC3": "\u0013",
+ "/controlDC4": "\u0014",
+ "/controlDEL": "\u007F",
+ "/controlDLE": "\u0010",
+ "/controlEM": "\u0019",
+ "/controlENQ": "\u0005",
+ "/controlEOT": "\u0004",
+ "/controlESC": "\u001B",
+ "/controlETB": "\u0017",
+ "/controlETX": "\u0003",
+ "/controlFF": "\u000C",
+ "/controlFS": "\u001C",
+ "/controlGS": "\u001D",
+ "/controlHT": "\u0009",
+ "/controlKnobs": "\u1F39B",
+ "/controlLF": "\u000A",
+ "/controlNAK": "\u0015",
+ "/controlRS": "\u001E",
+ "/controlSI": "\u000F",
+ "/controlSO": "\u000E",
+ "/controlSOT": "\u0002",
+ "/controlSTX": "\u0001",
+ "/controlSUB": "\u001A",
+ "/controlSYN": "\u0016",
+ "/controlUS": "\u001F",
+ "/controlVT": "\u000B",
+ "/convavediamondwhite": "\u27E1",
+ "/convenienceStore": "\u1F3EA",
+ "/cookedRice": "\u1F35A",
+ "/cookie": "\u1F36A",
+ "/cooking": "\u1F373",
+ "/coolsquare": "\u1F192",
+ "/coproductarray": "\u2210",
+ "/copyideographiccircled": "\u32A2",
+ "/copyright": "\u00A9",
+ "/copyrightsans": "\uF8E9",
+ "/copyrightserif": "\uF6D9",
+ "/cornerbottomleft": "\u231E",
+ "/cornerbottomright": "\u231F",
+ "/cornerbracketleft": "\u300C",
+ "/cornerbracketlefthalfwidth": "\uFF62",
+ "/cornerbracketleftvertical": "\uFE41",
+ "/cornerbracketright": "\u300D",
+ "/cornerbracketrighthalfwidth": "\uFF63",
+ "/cornerbracketrightvertical": "\uFE42",
+ "/cornerdotupleft": "\u27D4",
+ "/cornertopleft": "\u231C",
+ "/cornertopright": "\u231D",
+ "/coroniseditorial": "\u2E0E",
+ "/corporationsquare": "\u337F",
+ "/correctideographiccircled": "\u32A3",
+ "/corresponds": "\u2258",
+ "/cosquare": "\u33C7",
+ "/couchAndLamp": "\u1F6CB",
+ "/counterbore": "\u2334",
+ "/countersink": "\u2335",
+ "/coupleHeart": "\u1F491",
+ "/coverkgfullwidth": "\u33C6",
+ "/coverkgsquare": "\u33C6",
+ "/cow": "\u1F404",
+ "/cowFace": "\u1F42E",
+ "/cpalatalhook": "\uA794",
+ "/cparen": "\u249E",
+ "/cparenthesized": "\u249E",
+ "/creditCard": "\u1F4B3",
+ "/crescentMoon": "\u1F319",
+ "/creversed": "\u2184",
+ "/cricketBatAndBall": "\u1F3CF",
+ "/crocodile": "\u1F40A",
+ "/cropbottomleft": "\u230D",
+ "/cropbottomright": "\u230C",
+ "/croptopleft": "\u230F",
+ "/croptopright": "\u230E",
+ "/crossPommee": "\u1F542",
+ "/crossPommeeHalf-circleBelow": "\u1F541",
+ "/crossedFlags": "\u1F38C",
+ "/crossedswords": "\u2694",
+ "/crossinglanes": "\u26CC",
+ "/crossmod": "\u02DF",
+ "/crossofjerusalem": "\u2629",
+ "/crossoflorraine": "\u2628",
+ "/crossonshieldblack": "\u26E8",
+ "/crown": "\u1F451",
+ "/crrn:rupee": "\u20A8",
+ "/cruzeiro": "\u20A2",
+ "/cryingCatFace": "\u1F63F",
+ "/cryingFace": "\u1F622",
+ "/crystalBall": "\u1F52E",
+ "/cstretched": "\u0297",
+ "/cstroke": "\u023C",
+ "/cuatrillo": "\uA72D",
+ "/cuatrillocomma": "\uA72F",
+ "/curlyand": "\u22CF",
+ "/curlylogicaland": "\u22CF",
+ "/curlylogicalor": "\u22CE",
+ "/curlyor": "\u22CE",
+ "/currency": "\u00A4",
+ "/currencyExchange": "\u1F4B1",
+ "/curryAndRice": "\u1F35B",
+ "/custard": "\u1F36E",
+ "/customeraccountnumber": "\u2449",
+ "/customs": "\u1F6C3",
+ "/cyclone": "\u1F300",
+ "/cylindricity": "\u232D",
+ "/cyrBreve": "\uF6D1",
+ "/cyrFlex": "\uF6D2",
+ "/cyrbreve": "\uF6D4",
+ "/cyrflex": "\uF6D5",
+ "/d": "\u0064",
+ "/daarmenian": "\u0564",
+ "/daasusquare": "\u3324",
+ "/dabengali": "\u09A6",
+ "/dad": "\u0636",
+ "/dad.fina": "\uFEBE",
+ "/dad.init": "\uFEBF",
+ "/dad.init_alefmaksura.fina": "\uFD07",
+ "/dad.init_hah.fina": "\uFC23",
+ "/dad.init_hah.medi": "\uFCB5",
+ "/dad.init_jeem.fina": "\uFC22",
+ "/dad.init_jeem.medi": "\uFCB4",
+ "/dad.init_khah.fina": "\uFC24",
+ "/dad.init_khah.medi": "\uFCB6",
+ "/dad.init_khah.medi_meem.medi": "\uFD70",
+ "/dad.init_meem.fina": "\uFC25",
+ "/dad.init_meem.medi": "\uFCB7",
+ "/dad.init_reh.fina": "\uFD10",
+ "/dad.init_yeh.fina": "\uFD08",
+ "/dad.isol": "\uFEBD",
+ "/dad.medi": "\uFEC0",
+ "/dad.medi_alefmaksura.fina": "\uFD23",
+ "/dad.medi_hah.medi_alefmaksura.fina": "\uFD6E",
+ "/dad.medi_hah.medi_yeh.fina": "\uFDAB",
+ "/dad.medi_khah.medi_meem.fina": "\uFD6F",
+ "/dad.medi_reh.fina": "\uFD2C",
+ "/dad.medi_yeh.fina": "\uFD24",
+ "/dadarabic": "\u0636",
+ "/daddotbelow": "\u06FB",
+ "/dadeva": "\u0926",
+ "/dadfinalarabic": "\uFEBE",
+ "/dadinitialarabic": "\uFEBF",
+ "/dadmedialarabic": "\uFEC0",
+ "/dafullwidth": "\u3372",
+ "/dagesh": "\u05BC",
+ "/dagesh:hb": "\u05BC",
+ "/dageshhebrew": "\u05BC",
+ "/dagger": "\u2020",
+ "/daggerKnife": "\u1F5E1",
+ "/daggerdbl": "\u2021",
+ "/daggerwithguardleft": "\u2E36",
+ "/daggerwithguardright": "\u2E37",
+ "/dagujarati": "\u0AA6",
+ "/dagurmukhi": "\u0A26",
+ "/dahal": "\u068C",
+ "/dahal.fina": "\uFB85",
+ "/dahal.isol": "\uFB84",
+ "/dahiragana": "\u3060",
+ "/dakatakana": "\u30C0",
+ "/dal": "\u062F",
+ "/dal.fina": "\uFEAA",
+ "/dal.isol": "\uFEA9",
+ "/dalInvertedSmallVBelow": "\u075A",
+ "/dalTwoDotsVerticallyBelowSmallTah": "\u0759",
+ "/dalarabic": "\u062F",
+ "/daldotbelow": "\u068A",
+ "/daldotbelowtahsmall": "\u068B",
+ "/daldownthreedotsabove": "\u068F",
+ "/dalet": "\u05D3",
+ "/dalet:hb": "\u05D3",
+ "/daletdagesh": "\uFB33",
+ "/daletdageshhebrew": "\uFB33",
+ "/dalethatafpatah": "\u05D3",
+ "/dalethatafpatahhebrew": "\u05D3",
+ "/dalethatafsegol": "\u05D3",
+ "/dalethatafsegolhebrew": "\u05D3",
+ "/dalethebrew": "\u05D3",
+ "/dalethiriq": "\u05D3",
+ "/dalethiriqhebrew": "\u05D3",
+ "/daletholam": "\u05D3",
+ "/daletholamhebrew": "\u05D3",
+ "/daletpatah": "\u05D3",
+ "/daletpatahhebrew": "\u05D3",
+ "/daletqamats": "\u05D3",
+ "/daletqamatshebrew": "\u05D3",
+ "/daletqubuts": "\u05D3",
+ "/daletqubutshebrew": "\u05D3",
+ "/daletsegol": "\u05D3",
+ "/daletsegolhebrew": "\u05D3",
+ "/daletsheva": "\u05D3",
+ "/daletshevahebrew": "\u05D3",
+ "/dalettsere": "\u05D3",
+ "/dalettserehebrew": "\u05D3",
+ "/daletwide:hb": "\uFB22",
+ "/daletwithdagesh:hb": "\uFB33",
+ "/dalfinalarabic": "\uFEAA",
+ "/dalfourdotsabove": "\u0690",
+ "/dalinvertedV": "\u06EE",
+ "/dalring": "\u0689",
+ "/damahaprana": "\uA9A3",
+ "/damma": "\u064F",
+ "/dammaIsol": "\uFE78",
+ "/dammaMedi": "\uFE79",
+ "/dammaarabic": "\u064F",
+ "/dammalowarabic": "\u064F",
+ "/dammareversed": "\u065D",
+ "/dammasmall": "\u0619",
+ "/dammatan": "\u064C",
+ "/dammatanIsol": "\uFE72",
+ "/dammatanaltonearabic": "\u064C",
+ "/dammatanarabic": "\u064C",
+ "/dancer": "\u1F483",
+ "/danda": "\u0964",
+ "/dango": "\u1F361",
+ "/darga:hb": "\u05A7",
+ "/dargahebrew": "\u05A7",
+ "/dargalefthebrew": "\u05A7",
+ "/darkShade": "\u2593",
+ "/darkSunglasses": "\u1F576",
+ "/dashwithupturnleft": "\u2E43",
+ "/dasiacmbcyr": "\u0485",
+ "/dasiapneumatacyrilliccmb": "\u0485",
+ "/dateseparator": "\u060D",
+ "/dayeighteentelegraph": "\u33F1",
+ "/dayeighttelegraph": "\u33E7",
+ "/dayeleventelegraph": "\u33EA",
+ "/dayfifteentelegraph": "\u33EE",
+ "/dayfivetelegraph": "\u33E4",
+ "/dayfourteentelegraph": "\u33ED",
+ "/dayfourtelegraph": "\u33E3",
+ "/daynineteentelegraph": "\u33F2",
+ "/dayninetelegraph": "\u33E8",
+ "/dayonetelegraph": "\u33E0",
+ "/dayseventeentelegraph": "\u33F0",
+ "/dayseventelegraph": "\u33E6",
+ "/daysixteentelegraph": "\u33EF",
+ "/daysixtelegraph": "\u33E5",
+ "/daytentelegraph": "\u33E9",
+ "/daythirteentelegraph": "\u33EC",
+ "/daythirtyonetelegraph": "\u33FE",
+ "/daythirtytelegraph": "\u33FD",
+ "/daythreetelegraph": "\u33E2",
+ "/daytwelvetelegraph": "\u33EB",
+ "/daytwentyeighttelegraph": "\u33FB",
+ "/daytwentyfivetelegraph": "\u33F8",
+ "/daytwentyfourtelegraph": "\u33F7",
+ "/daytwentyninetelegraph": "\u33FC",
+ "/daytwentyonetelegraph": "\u33F4",
+ "/daytwentyseventelegraph": "\u33FA",
+ "/daytwentysixtelegraph": "\u33F9",
+ "/daytwentytelegraph": "\u33F3",
+ "/daytwentythreetelegraph": "\u33F6",
+ "/daytwentytwotelegraph": "\u33F5",
+ "/daytwotelegraph": "\u33E1",
+ "/dbdigraph": "\u0238",
+ "/dbfullwidth": "\u33C8",
+ "/dblGrave": "\uF6D3",
+ "/dblanglebracketleft": "\u300A",
+ "/dblanglebracketleftvertical": "\uFE3D",
+ "/dblanglebracketright": "\u300B",
+ "/dblanglebracketrightvertical": "\uFE3E",
+ "/dblarchinvertedbelowcmb": "\u032B",
+ "/dblarrowNE": "\u21D7",
+ "/dblarrowNW": "\u21D6",
+ "/dblarrowSE": "\u21D8",
+ "/dblarrowSW": "\u21D9",
+ "/dblarrowdown": "\u21D3",
+ "/dblarrowleft": "\u21D4",
+ "/dblarrowleftright": "\u21D4",
+ "/dblarrowleftrightstroke": "\u21CE",
+ "/dblarrowleftstroke": "\u21CD",
+ "/dblarrowright": "\u21D2",
+ "/dblarrowrightstroke": "\u21CF",
+ "/dblarrowup": "\u21D1",
+ "/dblarrowupdown": "\u21D5",
+ "/dbldanda": "\u0965",
+ "/dbldnhorz": "\u2566",
+ "/dbldnleft": "\u2557",
+ "/dbldnright": "\u2554",
+ "/dblgrave": "\uF6D6",
+ "/dblgravecmb": "\u030F",
+ "/dblhorz": "\u2550",
+ "/dblintegral": "\u222C",
+ "/dbllowline": "\u2017",
+ "/dbllowlinecmb": "\u0333",
+ "/dbloverlinecmb": "\u033F",
+ "/dblprimemod": "\u02BA",
+ "/dblstrokearrowdown": "\u21DF",
+ "/dblstrokearrowup": "\u21DE",
+ "/dbluphorz": "\u2569",
+ "/dblupleft": "\u255D",
+ "/dblupright": "\u255A",
+ "/dblvert": "\u2551",
+ "/dblverthorz": "\u256C",
+ "/dblverticalbar": "\u2016",
+ "/dblverticallineabovecmb": "\u030E",
+ "/dblvertleft": "\u2563",
+ "/dblvertright": "\u2560",
+ "/dbopomofo": "\u3109",
+ "/dbsquare": "\u33C8",
+ "/dcaron": "\u010F",
+ "/dcedilla": "\u1E11",
+ "/dchecyr": "\u052D",
+ "/dcircle": "\u24D3",
+ "/dcircumflexbelow": "\u1E13",
+ "/dcroat": "\u0111",
+ "/dcurl": "\u0221",
+ "/ddabengali": "\u09A1",
+ "/ddadeva": "\u0921",
+ "/ddagujarati": "\u0AA1",
+ "/ddagurmukhi": "\u0A21",
+ "/ddahal": "\u068D",
+ "/ddahal.fina": "\uFB83",
+ "/ddahal.isol": "\uFB82",
+ "/ddal": "\u0688",
+ "/ddal.fina": "\uFB89",
+ "/ddal.isol": "\uFB88",
+ "/ddalarabic": "\u0688",
+ "/ddalfinalarabic": "\uFB89",
+ "/ddamahaprana": "\uA99E",
+ "/ddblstruckitalic": "\u2146",
+ "/dddhadeva": "\u095C",
+ "/ddhabengali": "\u09A2",
+ "/ddhadeva": "\u0922",
+ "/ddhagujarati": "\u0AA2",
+ "/ddhagurmukhi": "\u0A22",
+ "/ddot": "\u1E0B",
+ "/ddotaccent": "\u1E0B",
+ "/ddotbelow": "\u1E0D",
+ "/decembertelegraph": "\u32CB",
+ "/deciduousTree": "\u1F333",
+ "/decimalexponent": "\u23E8",
+ "/decimalseparatorarabic": "\u066B",
+ "/decimalseparatorpersian": "\u066B",
+ "/decreaseFontSize": "\u1F5DB",
+ "/decyr": "\u0434",
+ "/decyrillic": "\u0434",
+ "/degree": "\u00B0",
+ "/degreecelsius": "\u2103",
+ "/degreefahrenheit": "\u2109",
+ "/dehi:hb": "\u05AD",
+ "/dehihebrew": "\u05AD",
+ "/dehiragana": "\u3067",
+ "/deicoptic": "\u03EF",
+ "/dekatakana": "\u30C7",
+ "/dekomicyr": "\u0501",
+ "/deldiaeresisfunc": "\u2362",
+ "/deleteleft": "\u232B",
+ "/deleteright": "\u2326",
+ "/deliveryTruck": "\u1F69A",
+ "/delstilefunc": "\u2352",
+ "/delta": "\u03B4",
+ "/deltaequal": "\u225C",
+ "/deltastilefunc": "\u234B",
+ "/deltaturned": "\u018D",
+ "/deltaunderlinefunc": "\u2359",
+ "/deltildefunc": "\u236B",
+ "/denominatorminusonenumeratorbengali": "\u09F8",
+ "/dentistrybottomverticalleft": "\u23CC",
+ "/dentistrybottomverticalright": "\u23BF",
+ "/dentistrycircledownhorizontal": "\u23C1",
+ "/dentistrycircleuphorizontal": "\u23C2",
+ "/dentistrycirclevertical": "\u23C0",
+ "/dentistrydownhorizontal": "\u23C9",
+ "/dentistrytopverticalleft": "\u23CB",
+ "/dentistrytopverticalright": "\u23BE",
+ "/dentistrytriangledownhorizontal": "\u23C4",
+ "/dentistrytriangleuphorizontal": "\u23C5",
+ "/dentistrytrianglevertical": "\u23C3",
+ "/dentistryuphorizontal": "\u23CA",
+ "/dentistrywavedownhorizontal": "\u23C7",
+ "/dentistrywaveuphorizontal": "\u23C8",
+ "/dentistrywavevertical": "\u23C6",
+ "/departmentStore": "\u1F3EC",
+ "/derelictHouseBuilding": "\u1F3DA",
+ "/desert": "\u1F3DC",
+ "/desertIsland": "\u1F3DD",
+ "/desisquare": "\u3325",
+ "/desktopComputer": "\u1F5A5",
+ "/desktopWindow": "\u1F5D4",
+ "/deva:a": "\u0905",
+ "/deva:aa": "\u0906",
+ "/deva:aasign": "\u093E",
+ "/deva:abbreviation": "\u0970",
+ "/deva:acandra": "\u0972",
+ "/deva:acute": "\u0954",
+ "/deva:ai": "\u0910",
+ "/deva:aisign": "\u0948",
+ "/deva:anudatta": "\u0952",
+ "/deva:anusvara": "\u0902",
+ "/deva:ashort": "\u0904",
+ "/deva:au": "\u0914",
+ "/deva:ausign": "\u094C",
+ "/deva:avagraha": "\u093D",
+ "/deva:aw": "\u0975",
+ "/deva:awsign": "\u094F",
+ "/deva:ba": "\u092C",
+ "/deva:bba": "\u097F",
+ "/deva:bha": "\u092D",
+ "/deva:ca": "\u091A",
+ "/deva:candrabindu": "\u0901",
+ "/deva:candrabinduinverted": "\u0900",
+ "/deva:cha": "\u091B",
+ "/deva:da": "\u0926",
+ "/deva:danda": "\u0964",
+ "/deva:dbldanda": "\u0965",
+ "/deva:dda": "\u0921",
+ "/deva:ddda": "\u097E",
+ "/deva:dddha": "\u095C",
+ "/deva:ddha": "\u0922",
+ "/deva:dha": "\u0927",
+ "/deva:dothigh": "\u0971",
+ "/deva:e": "\u090F",
+ "/deva:ecandra": "\u090D",
+ "/deva:eight": "\u096E",
+ "/deva:eshort": "\u090E",
+ "/deva:esign": "\u0947",
+ "/deva:esigncandra": "\u0945",
+ "/deva:esignprishthamatra": "\u094E",
+ "/deva:esignshort": "\u0946",
+ "/deva:fa": "\u095E",
+ "/deva:five": "\u096B",
+ "/deva:four": "\u096A",
+ "/deva:ga": "\u0917",
+ "/deva:gga": "\u097B",
+ "/deva:gha": "\u0918",
+ "/deva:ghha": "\u095A",
+ "/deva:glottalstop": "\u097D",
+ "/deva:grave": "\u0953",
+ "/deva:ha": "\u0939",
+ "/deva:i": "\u0907",
+ "/deva:ii": "\u0908",
+ "/deva:iisign": "\u0940",
+ "/deva:isign": "\u093F",
+ "/deva:ja": "\u091C",
+ "/deva:jha": "\u091D",
+ "/deva:jja": "\u097C",
+ "/deva:ka": "\u0915",
+ "/deva:kha": "\u0916",
+ "/deva:khha": "\u0959",
+ "/deva:la": "\u0932",
+ "/deva:lla": "\u0933",
+ "/deva:llla": "\u0934",
+ "/deva:llvocal": "\u0961",
+ "/deva:llvocalsign": "\u0963",
+ "/deva:lvocal": "\u090C",
+ "/deva:lvocalsign": "\u0962",
+ "/deva:ma": "\u092E",
+ "/deva:marwaridda": "\u0978",
+ "/deva:na": "\u0928",
+ "/deva:nga": "\u0919",
+ "/deva:nine": "\u096F",
+ "/deva:nna": "\u0923",
+ "/deva:nnna": "\u0929",
+ "/deva:nukta": "\u093C",
+ "/deva:nya": "\u091E",
+ "/deva:o": "\u0913",
+ "/deva:ocandra": "\u0911",
+ "/deva:oe": "\u0973",
+ "/deva:oesign": "\u093A",
+ "/deva:om": "\u0950",
+ "/deva:one": "\u0967",
+ "/deva:ooe": "\u0974",
+ "/deva:ooesign": "\u093B",
+ "/deva:oshort": "\u0912",
+ "/deva:osign": "\u094B",
+ "/deva:osigncandra": "\u0949",
+ "/deva:osignshort": "\u094A",
+ "/deva:pa": "\u092A",
+ "/deva:pha": "\u092B",
+ "/deva:qa": "\u0958",
+ "/deva:ra": "\u0930",
+ "/deva:rha": "\u095D",
+ "/deva:rra": "\u0931",
+ "/deva:rrvocal": "\u0960",
+ "/deva:rrvocalsign": "\u0944",
+ "/deva:rvocal": "\u090B",
+ "/deva:rvocalsign": "\u0943",
+ "/deva:sa": "\u0938",
+ "/deva:seven": "\u096D",
+ "/deva:sha": "\u0936",
+ "/deva:signelongcandra": "\u0955",
+ "/deva:six": "\u096C",
+ "/deva:ssa": "\u0937",
+ "/deva:ta": "\u0924",
+ "/deva:tha": "\u0925",
+ "/deva:three": "\u0969",
+ "/deva:tta": "\u091F",
+ "/deva:ttha": "\u0920",
+ "/deva:two": "\u0968",
+ "/deva:u": "\u0909",
+ "/deva:udatta": "\u0951",
+ "/deva:ue": "\u0976",
+ "/deva:uesign": "\u0956",
+ "/deva:usign": "\u0941",
+ "/deva:uu": "\u090A",
+ "/deva:uue": "\u0977",
+ "/deva:uuesign": "\u0957",
+ "/deva:uusign": "\u0942",
+ "/deva:va": "\u0935",
+ "/deva:virama": "\u094D",
+ "/deva:visarga": "\u0903",
+ "/deva:ya": "\u092F",
+ "/deva:yaheavy": "\u097A",
+ "/deva:yya": "\u095F",
+ "/deva:za": "\u095B",
+ "/deva:zero": "\u0966",
+ "/deva:zha": "\u0979",
+ "/dezh": "\u02A4",
+ "/dfemaledbl": "\u26A2",
+ "/dhabengali": "\u09A7",
+ "/dhadeva": "\u0927",
+ "/dhagujarati": "\u0AA7",
+ "/dhagurmukhi": "\u0A27",
+ "/dhook": "\u0257",
+ "/diaeresisgreaterfunc": "\u2369",
+ "/dialytikatonos": "\u0385",
+ "/dialytikatonoscmb": "\u0344",
+ "/diametersign": "\u2300",
+ "/diamond": "\u2666",
+ "/diamondShapeADotInside": "\u1F4A0",
+ "/diamondinsquarewhite": "\u26CB",
+ "/diamondoperator": "\u22C4",
+ "/diamondsuitwhite": "\u2662",
+ "/diamondunderlinefunc": "\u235A",
+ "/diamondwhitewithdiamondsmallblack": "\u25C8",
+ "/diefive": "\u2684",
+ "/diefour": "\u2683",
+ "/dieone": "\u2680",
+ "/dieresis": "\u00A8",
+ "/dieresisacute": "\uF6D7",
+ "/dieresisbelowcmb": "\u0324",
+ "/dieresiscmb": "\u0308",
+ "/dieresisgrave": "\uF6D8",
+ "/dieresistilde": "\u1FC1",
+ "/dieresistonos": "\u0385",
+ "/dieselLocomotive": "\u1F6F2",
+ "/diesix": "\u2685",
+ "/diethree": "\u2682",
+ "/dietwo": "\u2681",
+ "/differencebetween": "\u224F",
+ "/digamma": "\u03DD",
+ "/digammapamphylian": "\u0377",
+ "/digramgreateryang": "\u268C",
+ "/digramgreateryin": "\u268F",
+ "/digramlesseryang": "\u268E",
+ "/digramlesseryin": "\u268D",
+ "/dihiragana": "\u3062",
+ "/dikatakana": "\u30C2",
+ "/dimensionorigin": "\u2331",
+ "/dingbatSAns-serifzerocircle": "\u1F10B",
+ "/dingbatSAns-serifzerocircleblack": "\u1F10C",
+ "/dinsular": "\uA77A",
+ "/directHit": "\u1F3AF",
+ "/directcurrentformtwo": "\u2393",
+ "/dirgamurevowel": "\uA9BB",
+ "/disabledcar": "\u26CD",
+ "/disappointedButRelievedFace": "\u1F625",
+ "/disappointedFace": "\u1F61E",
+ "/discontinuousunderline": "\u2382",
+ "/dittomark": "\u3003",
+ "/divide": "\u00F7",
+ "/divides": "\u2223",
+ "/divisionslash": "\u2215",
+ "/divisiontimes": "\u22C7",
+ "/divorce": "\u26AE",
+ "/dizzy": "\u1F4AB",
+ "/dizzyFace": "\u1F635",
+ "/djecyr": "\u0452",
+ "/djecyrillic": "\u0452",
+ "/djekomicyr": "\u0503",
+ "/dkshade": "\u2593",
+ "/dlfullwidth": "\u3397",
+ "/dlinebelow": "\u1E0F",
+ "/dlogicalorsquare": "\u27CF",
+ "/dlogicalsquare": "\u27CE",
+ "/dlsquare": "\u3397",
+ "/dm2fullwidth": "\u3378",
+ "/dm3fullwidth": "\u3379",
+ "/dmacron": "\u0111",
+ "/dmaledbl": "\u26A3",
+ "/dmfullwidth": "\u3377",
+ "/dmonospace": "\uFF44",
+ "/dnblock": "\u2584",
+ "/dndblhorzsng": "\u2565",
+ "/dndblleftsng": "\u2556",
+ "/dndblrightsng": "\u2553",
+ "/dngb:airplane": "\u2708",
+ "/dngb:arrowfeatheredblackNE": "\u27B6",
+ "/dngb:arrowfeatheredblackSE": "\u27B4",
+ "/dngb:arrowfeatheredblackheavyNE": "\u27B9",
+ "/dngb:arrowfeatheredblackheavySE": "\u27B7",
+ "/dngb:arrowheadrightblack": "\u27A4",
+ "/dngb:arrowheadrightthreeDbottomlight": "\u27A3",
+ "/dngb:arrowheadrightthreeDtoplight": "\u27A2",
+ "/dngb:arrowheavyNE": "\u279A",
+ "/dngb:arrowheavySE": "\u2798",
+ "/dngb:arrowrightbacktiltedshadowedwhite": "\u27AB",
+ "/dngb:arrowrightblack": "\u27A1",
+ "/dngb:arrowrightcircledwhiteheavy": "\u27B2",
+ "/dngb:arrowrightcurvedownblackheavy": "\u27A5",
+ "/dngb:arrowrightcurveupblackheavy": "\u27A6",
+ "/dngb:arrowrightfeatheredblack": "\u27B5",
+ "/dngb:arrowrightfeatheredblackheavy": "\u27B8",
+ "/dngb:arrowrightfeatheredwhite": "\u27B3",
+ "/dngb:arrowrightfronttiltedshadowedwhite": "\u27AC",
+ "/dngb:arrowrightheavy": "\u2799",
+ "/dngb:arrowrightleftshadedwhite": "\u27AA",
+ "/dngb:arrowrightoutlinedopen": "\u27BE",
+ "/dngb:arrowrightpointed": "\u279B",
+ "/dngb:arrowrightpointedblackheavy": "\u27A8",
+ "/dngb:arrowrightrightshadedwhite": "\u27A9",
+ "/dngb:arrowrightroundheavy": "\u279C",
+ "/dngb:arrowrightsquatblack": "\u27A7",
+ "/dngb:arrowrighttriangle": "\u279D",
+ "/dngb:arrowrighttriangledashed": "\u279F",
+ "/dngb:arrowrighttriangledashedheavy": "\u27A0",
+ "/dngb:arrowrighttriangleheavy": "\u279E",
+ "/dngb:arrowrightwedge": "\u27BC",
+ "/dngb:arrowrightwedgeheavy": "\u27BD",
+ "/dngb:arrowrightwideheavy": "\u2794",
+ "/dngb:arrowshadowrightlowerwhiteheavy": "\u27AD",
+ "/dngb:arrowshadowrightnotchedlowerwhite": "\u27AF",
+ "/dngb:arrowshadowrightnotchedupperwhite": "\u27B1",
+ "/dngb:arrowshadowrightupperwhiteheavy": "\u27AE",
+ "/dngb:arrowteardropright": "\u27BA",
+ "/dngb:arrowteardroprightheavy": "\u27BB",
+ "/dngb:asteriskballoon": "\u2749",
+ "/dngb:asteriskballoonfour": "\u2723",
+ "/dngb:asteriskballoonheavyfour": "\u2724",
+ "/dngb:asteriskcentreopen": "\u2732",
+ "/dngb:asteriskclubfour": "\u2725",
+ "/dngb:asteriskheavy": "\u2731",
+ "/dngb:asteriskpointedsixteen": "\u273A",
+ "/dngb:asteriskteardrop": "\u273B",
+ "/dngb:asteriskteardropcentreopen": "\u273C",
+ "/dngb:asteriskteardropfour": "\u2722",
+ "/dngb:asteriskteardropheavy": "\u273D",
+ "/dngb:asteriskteardroppinwheelheavy": "\u2743",
+ "/dngb:asteriskteardroppropellereight": "\u274A",
+ "/dngb:asteriskteardroppropellerheavyeight": "\u274B",
+ "/dngb:ballotx": "\u2717",
+ "/dngb:ballotxheavy": "\u2718",
+ "/dngb:bracketleftpointedangleheavyornament": "\u2770",
+ "/dngb:bracketleftpointedanglemediumornament": "\u276C",
+ "/dngb:bracketrightpointedangleheavyornament": "\u2771",
+ "/dngb:bracketrightpointedanglemediumornament": "\u276D",
+ "/dngb:bracketshellleftlightornament": "\u2772",
+ "/dngb:bracketshellrightlightornament": "\u2773",
+ "/dngb:check": "\u2713",
+ "/dngb:checkheavy": "\u2714",
+ "/dngb:checkwhiteheavy": "\u2705",
+ "/dngb:chevronsnowflakeheavy": "\u2746",
+ "/dngb:circleshadowedwhite": "\u274D",
+ "/dngb:commaheavydoubleornament": "\u275E",
+ "/dngb:commaheavydoubleturnedornament": "\u275D",
+ "/dngb:commaheavyornament": "\u275C",
+ "/dngb:commaheavyturnedornament": "\u275B",
+ "/dngb:compasstarpointedblackeight": "\u2737",
+ "/dngb:compasstarpointedblackheavyeight": "\u2738",
+ "/dngb:cross": "\u274C",
+ "/dngb:crosscentreopen": "\u271B",
+ "/dngb:crosscentreopenheavy": "\u271C",
+ "/dngb:curlybracketleftmediumornament": "\u2774",
+ "/dngb:curlybracketrightmediumornament": "\u2775",
+ "/dngb:curlyloop": "\u27B0",
+ "/dngb:curlyloopdouble": "\u27BF",
+ "/dngb:curvedstemparagraphsignornament": "\u2761",
+ "/dngb:diamondminusxblackwhite": "\u2756",
+ "/dngb:divisionsignheavy": "\u2797",
+ "/dngb:eightnegativecircled": "\u277D",
+ "/dngb:eightsanscircled": "\u2787",
+ "/dngb:eightsansnegativecircled": "\u2791",
+ "/dngb:envelope": "\u2709",
+ "/dngb:exclamationheavy": "\u2757",
+ "/dngb:exclamationheavyornament": "\u2762",
+ "/dngb:exclamationwhiteornament": "\u2755",
+ "/dngb:fivenegativecircled": "\u277A",
+ "/dngb:fivesanscircled": "\u2784",
+ "/dngb:fivesansnegativecircled": "\u278E",
+ "/dngb:floralheart": "\u2766",
+ "/dngb:floralheartbulletrotated": "\u2767",
+ "/dngb:floretteblack": "\u273F",
+ "/dngb:floretteoutlinedpetalledblackeight": "\u2741",
+ "/dngb:florettepetalledblackwhitesix": "\u273E",
+ "/dngb:florettewhite": "\u2740",
+ "/dngb:fournegativecircled": "\u2779",
+ "/dngb:foursanscircled": "\u2783",
+ "/dngb:foursansnegativecircled": "\u278D",
+ "/dngb:greekcrossheavy": "\u271A",
+ "/dngb:greekcrossoutlined": "\u2719",
+ "/dngb:heartblackheavy": "\u2764",
+ "/dngb:heartbulletrotatedblackheavy": "\u2765",
+ "/dngb:heartexclamationheavyornament": "\u2763",
+ "/dngb:hvictory": "\u270C",
+ "/dngb:hwriting": "\u270D",
+ "/dngb:latincross": "\u271D",
+ "/dngb:latincrossoutlined": "\u271F",
+ "/dngb:latincrossshadowedwhite": "\u271E",
+ "/dngb:lowcommaheavydoubleornament": "\u2760",
+ "/dngb:lowcommaheavyornament": "\u275F",
+ "/dngb:maltesecross": "\u2720",
+ "/dngb:minussignheavy": "\u2796",
+ "/dngb:multiplicationx": "\u2715",
+ "/dngb:multiplicationxheavy": "\u2716",
+ "/dngb:nibblack": "\u2712",
+ "/dngb:nibwhite": "\u2711",
+ "/dngb:ninenegativecircled": "\u277E",
+ "/dngb:ninesanscircled": "\u2788",
+ "/dngb:ninesansnegativecircled": "\u2792",
+ "/dngb:onenegativecircled": "\u2776",
+ "/dngb:onesanscircled": "\u2780",
+ "/dngb:onesansnegativecircled": "\u278A",
+ "/dngb:parenthesisleftflattenedmediumornament": "\u276A",
+ "/dngb:parenthesisleftmediumornament": "\u2768",
+ "/dngb:parenthesisrightflattenedmediumornament": "\u276B",
+ "/dngb:parenthesisrightmediumornament": "\u2769",
+ "/dngb:pencil": "\u270F",
+ "/dngb:pencillowerright": "\u270E",
+ "/dngb:pencilupperright": "\u2710",
+ "/dngb:plussignheavy": "\u2795",
+ "/dngb:questionblackornament": "\u2753",
+ "/dngb:questionwhiteornament": "\u2754",
+ "/dngb:quotationleftpointedangleheavyornament": "\u276E",
+ "/dngb:quotationrightpointedangleheavyornament": "\u276F",
+ "/dngb:raisedfist": "\u270A",
+ "/dngb:raisedh": "\u270B",
+ "/dngb:safetyscissorsblack": "\u2700",
+ "/dngb:scissorsblack": "\u2702",
+ "/dngb:scissorslowerblade": "\u2703",
+ "/dngb:scissorsupperblade": "\u2701",
+ "/dngb:scissorswhite": "\u2704",
+ "/dngb:sevennegativecircled": "\u277C",
+ "/dngb:sevensanscircled": "\u2786",
+ "/dngb:sevensansnegativecircled": "\u2790",
+ "/dngb:sixnegativecircled": "\u277B",
+ "/dngb:sixsanscircled": "\u2785",
+ "/dngb:sixsansnegativecircled": "\u278F",
+ "/dngb:snowflake": "\u2744",
+ "/dngb:snowflaketight": "\u2745",
+ "/dngb:sparkle": "\u2747",
+ "/dngb:sparkleheavy": "\u2748",
+ "/dngb:sparkles": "\u2728",
+ "/dngb:spokedasteriskeight": "\u2733",
+ "/dngb:squaredcrossnegative": "\u274E",
+ "/dngb:squarelowerrightshadowedwhite": "\u2751",
+ "/dngb:squareshadowlowerrightwhite": "\u274F",
+ "/dngb:squareshadowupperrightwhite": "\u2750",
+ "/dngb:squareupperrightshadowedwhite": "\u2752",
+ "/dngb:starcentreblackwhite": "\u272C",
+ "/dngb:starcentreopenblack": "\u272B",
+ "/dngb:starcentreopenpointedcircledeight": "\u2742",
+ "/dngb:starcircledwhite": "\u272A",
+ "/dngb:starofdavid": "\u2721",
+ "/dngb:staroutlinedblack": "\u272D",
+ "/dngb:staroutlinedblackheavy": "\u272E",
+ "/dngb:staroutlinedstresswhite": "\u2729",
+ "/dngb:starpinwheel": "\u272F",
+ "/dngb:starpointedblackeight": "\u2734",
+ "/dngb:starpointedblackfour": "\u2726",
+ "/dngb:starpointedblacksix": "\u2736",
+ "/dngb:starpointedblacktwelve": "\u2739",
+ "/dngb:starpointedpinwheeleight": "\u2735",
+ "/dngb:starpointedwhitefour": "\u2727",
+ "/dngb:starshadowedwhite": "\u2730",
+ "/dngb:tapedrive": "\u2707",
+ "/dngb:telephonelocationsign": "\u2706",
+ "/dngb:tennegativecircled": "\u277F",
+ "/dngb:tensanscircled": "\u2789",
+ "/dngb:tensansnegativecircled": "\u2793",
+ "/dngb:threenegativecircled": "\u2778",
+ "/dngb:threesanscircled": "\u2782",
+ "/dngb:threesansnegativecircled": "\u278C",
+ "/dngb:twonegativecircled": "\u2777",
+ "/dngb:twosanscircled": "\u2781",
+ "/dngb:twosansnegativecircled": "\u278B",
+ "/dngb:verticalbarheavy": "\u275A",
+ "/dngb:verticalbarlight": "\u2758",
+ "/dngb:verticalbarmedium": "\u2759",
+ "/dnheavyhorzlight": "\u2530",
+ "/dnheavyleftlight": "\u2512",
+ "/dnheavyleftuplight": "\u2527",
+ "/dnheavyrightlight": "\u250E",
+ "/dnheavyrightuplight": "\u251F",
+ "/dnheavyuphorzlight": "\u2541",
+ "/dnlighthorzheavy": "\u252F",
+ "/dnlightleftheavy": "\u2511",
+ "/dnlightleftupheavy": "\u2529",
+ "/dnlightrightheavy": "\u250D",
+ "/dnlightrightupheavy": "\u2521",
+ "/dnlightuphorzheavy": "\u2547",
+ "/dnsnghorzdbl": "\u2564",
+ "/dnsngleftdbl": "\u2555",
+ "/dnsngrightdbl": "\u2552",
+ "/doNotLitter": "\u1F6AF",
+ "/dochadathai": "\u0E0E",
+ "/document": "\u1F5CE",
+ "/documentPicture": "\u1F5BB",
+ "/documentText": "\u1F5B9",
+ "/documentTextAndPicture": "\u1F5BA",
+ "/dodekthai": "\u0E14",
+ "/doesnotcontainasnormalsubgroorequalup": "\u22ED",
+ "/doesnotcontainasnormalsubgroup": "\u22EB",
+ "/doesnotdivide": "\u2224",
+ "/doesnotforce": "\u22AE",
+ "/doesnotprecede": "\u2280",
+ "/doesnotprecedeorequal": "\u22E0",
+ "/doesnotprove": "\u22AC",
+ "/doesnotsucceed": "\u2281",
+ "/doesnotsucceedorequal": "\u22E1",
+ "/dog": "\u1F415",
+ "/dogFace": "\u1F436",
+ "/dohiragana": "\u3069",
+ "/dokatakana": "\u30C9",
+ "/dollar": "\u0024",
+ "/dollarinferior": "\uF6E3",
+ "/dollarmonospace": "\uFF04",
+ "/dollaroldstyle": "\uF724",
+ "/dollarsmall": "\uFE69",
+ "/dollarsuperior": "\uF6E4",
+ "/dolphin": "\u1F42C",
+ "/dominohorizontal_00_00": "\u1F031",
+ "/dominohorizontal_00_01": "\u1F032",
+ "/dominohorizontal_00_02": "\u1F033",
+ "/dominohorizontal_00_03": "\u1F034",
+ "/dominohorizontal_00_04": "\u1F035",
+ "/dominohorizontal_00_05": "\u1F036",
+ "/dominohorizontal_00_06": "\u1F037",
+ "/dominohorizontal_01_00": "\u1F038",
+ "/dominohorizontal_01_01": "\u1F039",
+ "/dominohorizontal_01_02": "\u1F03A",
+ "/dominohorizontal_01_03": "\u1F03B",
+ "/dominohorizontal_01_04": "\u1F03C",
+ "/dominohorizontal_01_05": "\u1F03D",
+ "/dominohorizontal_01_06": "\u1F03E",
+ "/dominohorizontal_02_00": "\u1F03F",
+ "/dominohorizontal_02_01": "\u1F040",
+ "/dominohorizontal_02_02": "\u1F041",
+ "/dominohorizontal_02_03": "\u1F042",
+ "/dominohorizontal_02_04": "\u1F043",
+ "/dominohorizontal_02_05": "\u1F044",
+ "/dominohorizontal_02_06": "\u1F045",
+ "/dominohorizontal_03_00": "\u1F046",
+ "/dominohorizontal_03_01": "\u1F047",
+ "/dominohorizontal_03_02": "\u1F048",
+ "/dominohorizontal_03_03": "\u1F049",
+ "/dominohorizontal_03_04": "\u1F04A",
+ "/dominohorizontal_03_05": "\u1F04B",
+ "/dominohorizontal_03_06": "\u1F04C",
+ "/dominohorizontal_04_00": "\u1F04D",
+ "/dominohorizontal_04_01": "\u1F04E",
+ "/dominohorizontal_04_02": "\u1F04F",
+ "/dominohorizontal_04_03": "\u1F050",
+ "/dominohorizontal_04_04": "\u1F051",
+ "/dominohorizontal_04_05": "\u1F052",
+ "/dominohorizontal_04_06": "\u1F053",
+ "/dominohorizontal_05_00": "\u1F054",
+ "/dominohorizontal_05_01": "\u1F055",
+ "/dominohorizontal_05_02": "\u1F056",
+ "/dominohorizontal_05_03": "\u1F057",
+ "/dominohorizontal_05_04": "\u1F058",
+ "/dominohorizontal_05_05": "\u1F059",
+ "/dominohorizontal_05_06": "\u1F05A",
+ "/dominohorizontal_06_00": "\u1F05B",
+ "/dominohorizontal_06_01": "\u1F05C",
+ "/dominohorizontal_06_02": "\u1F05D",
+ "/dominohorizontal_06_03": "\u1F05E",
+ "/dominohorizontal_06_04": "\u1F05F",
+ "/dominohorizontal_06_05": "\u1F060",
+ "/dominohorizontal_06_06": "\u1F061",
+ "/dominohorizontalback": "\u1F030",
+ "/dominovertical_00_00": "\u1F063",
+ "/dominovertical_00_01": "\u1F064",
+ "/dominovertical_00_02": "\u1F065",
+ "/dominovertical_00_03": "\u1F066",
+ "/dominovertical_00_04": "\u1F067",
+ "/dominovertical_00_05": "\u1F068",
+ "/dominovertical_00_06": "\u1F069",
+ "/dominovertical_01_00": "\u1F06A",
+ "/dominovertical_01_01": "\u1F06B",
+ "/dominovertical_01_02": "\u1F06C",
+ "/dominovertical_01_03": "\u1F06D",
+ "/dominovertical_01_04": "\u1F06E",
+ "/dominovertical_01_05": "\u1F06F",
+ "/dominovertical_01_06": "\u1F070",
+ "/dominovertical_02_00": "\u1F071",
+ "/dominovertical_02_01": "\u1F072",
+ "/dominovertical_02_02": "\u1F073",
+ "/dominovertical_02_03": "\u1F074",
+ "/dominovertical_02_04": "\u1F075",
+ "/dominovertical_02_05": "\u1F076",
+ "/dominovertical_02_06": "\u1F077",
+ "/dominovertical_03_00": "\u1F078",
+ "/dominovertical_03_01": "\u1F079",
+ "/dominovertical_03_02": "\u1F07A",
+ "/dominovertical_03_03": "\u1F07B",
+ "/dominovertical_03_04": "\u1F07C",
+ "/dominovertical_03_05": "\u1F07D",
+ "/dominovertical_03_06": "\u1F07E",
+ "/dominovertical_04_00": "\u1F07F",
+ "/dominovertical_04_01": "\u1F080",
+ "/dominovertical_04_02": "\u1F081",
+ "/dominovertical_04_03": "\u1F082",
+ "/dominovertical_04_04": "\u1F083",
+ "/dominovertical_04_05": "\u1F084",
+ "/dominovertical_04_06": "\u1F085",
+ "/dominovertical_05_00": "\u1F086",
+ "/dominovertical_05_01": "\u1F087",
+ "/dominovertical_05_02": "\u1F088",
+ "/dominovertical_05_03": "\u1F089",
+ "/dominovertical_05_04": "\u1F08A",
+ "/dominovertical_05_05": "\u1F08B",
+ "/dominovertical_05_06": "\u1F08C",
+ "/dominovertical_06_00": "\u1F08D",
+ "/dominovertical_06_01": "\u1F08E",
+ "/dominovertical_06_02": "\u1F08F",
+ "/dominovertical_06_03": "\u1F090",
+ "/dominovertical_06_04": "\u1F091",
+ "/dominovertical_06_05": "\u1F092",
+ "/dominovertical_06_06": "\u1F093",
+ "/dominoverticalback": "\u1F062",
+ "/dong": "\u20AB",
+ "/door": "\u1F6AA",
+ "/dorusquare": "\u3326",
+ "/dot": "\u27D1",
+ "/dotaccent": "\u02D9",
+ "/dotaccentcmb": "\u0307",
+ "/dotbelowcmb": "\u0323",
+ "/dotbelowcomb": "\u0323",
+ "/dotkatakana": "\u30FB",
+ "/dotlessbeh": "\u066E",
+ "/dotlessfeh": "\u06A1",
+ "/dotlessi": "\u0131",
+ "/dotlessj": "\uF6BE",
+ "/dotlessjstroke": "\u025F",
+ "/dotlessjstrokehook": "\u0284",
+ "/dotlesskhahabove": "\u06E1",
+ "/dotlessqaf": "\u066F",
+ "/dotlower:hb": "\u05C5",
+ "/dotmath": "\u22C5",
+ "/dotminus": "\u2238",
+ "/dotplus": "\u2214",
+ "/dotraised": "\u2E33",
+ "/dots1": "\u2801",
+ "/dots12": "\u2803",
+ "/dots123": "\u2807",
+ "/dots1234": "\u280F",
+ "/dots12345": "\u281F",
+ "/dots123456": "\u283F",
+ "/dots1234567": "\u287F",
+ "/dots12345678": "\u28FF",
+ "/dots1234568": "\u28BF",
+ "/dots123457": "\u285F",
+ "/dots1234578": "\u28DF",
+ "/dots123458": "\u289F",
+ "/dots12346": "\u282F",
+ "/dots123467": "\u286F",
+ "/dots1234678": "\u28EF",
+ "/dots123468": "\u28AF",
+ "/dots12347": "\u284F",
+ "/dots123478": "\u28CF",
+ "/dots12348": "\u288F",
+ "/dots1235": "\u2817",
+ "/dots12356": "\u2837",
+ "/dots123567": "\u2877",
+ "/dots1235678": "\u28F7",
+ "/dots123568": "\u28B7",
+ "/dots12357": "\u2857",
+ "/dots123578": "\u28D7",
+ "/dots12358": "\u2897",
+ "/dots1236": "\u2827",
+ "/dots12367": "\u2867",
+ "/dots123678": "\u28E7",
+ "/dots12368": "\u28A7",
+ "/dots1237": "\u2847",
+ "/dots12378": "\u28C7",
+ "/dots1238": "\u2887",
+ "/dots124": "\u280B",
+ "/dots1245": "\u281B",
+ "/dots12456": "\u283B",
+ "/dots124567": "\u287B",
+ "/dots1245678": "\u28FB",
+ "/dots124568": "\u28BB",
+ "/dots12457": "\u285B",
+ "/dots124578": "\u28DB",
+ "/dots12458": "\u289B",
+ "/dots1246": "\u282B",
+ "/dots12467": "\u286B",
+ "/dots124678": "\u28EB",
+ "/dots12468": "\u28AB",
+ "/dots1247": "\u284B",
+ "/dots12478": "\u28CB",
+ "/dots1248": "\u288B",
+ "/dots125": "\u2813",
+ "/dots1256": "\u2833",
+ "/dots12567": "\u2873",
+ "/dots125678": "\u28F3",
+ "/dots12568": "\u28B3",
+ "/dots1257": "\u2853",
+ "/dots12578": "\u28D3",
+ "/dots1258": "\u2893",
+ "/dots126": "\u2823",
+ "/dots1267": "\u2863",
+ "/dots12678": "\u28E3",
+ "/dots1268": "\u28A3",
+ "/dots127": "\u2843",
+ "/dots1278": "\u28C3",
+ "/dots128": "\u2883",
+ "/dots13": "\u2805",
+ "/dots134": "\u280D",
+ "/dots1345": "\u281D",
+ "/dots13456": "\u283D",
+ "/dots134567": "\u287D",
+ "/dots1345678": "\u28FD",
+ "/dots134568": "\u28BD",
+ "/dots13457": "\u285D",
+ "/dots134578": "\u28DD",
+ "/dots13458": "\u289D",
+ "/dots1346": "\u282D",
+ "/dots13467": "\u286D",
+ "/dots134678": "\u28ED",
+ "/dots13468": "\u28AD",
+ "/dots1347": "\u284D",
+ "/dots13478": "\u28CD",
+ "/dots1348": "\u288D",
+ "/dots135": "\u2815",
+ "/dots1356": "\u2835",
+ "/dots13567": "\u2875",
+ "/dots135678": "\u28F5",
+ "/dots13568": "\u28B5",
+ "/dots1357": "\u2855",
+ "/dots13578": "\u28D5",
+ "/dots1358": "\u2895",
+ "/dots136": "\u2825",
+ "/dots1367": "\u2865",
+ "/dots13678": "\u28E5",
+ "/dots1368": "\u28A5",
+ "/dots137": "\u2845",
+ "/dots1378": "\u28C5",
+ "/dots138": "\u2885",
+ "/dots14": "\u2809",
+ "/dots145": "\u2819",
+ "/dots1456": "\u2839",
+ "/dots14567": "\u2879",
+ "/dots145678": "\u28F9",
+ "/dots14568": "\u28B9",
+ "/dots1457": "\u2859",
+ "/dots14578": "\u28D9",
+ "/dots1458": "\u2899",
+ "/dots146": "\u2829",
+ "/dots1467": "\u2869",
+ "/dots14678": "\u28E9",
+ "/dots1468": "\u28A9",
+ "/dots147": "\u2849",
+ "/dots1478": "\u28C9",
+ "/dots148": "\u2889",
+ "/dots15": "\u2811",
+ "/dots156": "\u2831",
+ "/dots1567": "\u2871",
+ "/dots15678": "\u28F1",
+ "/dots1568": "\u28B1",
+ "/dots157": "\u2851",
+ "/dots1578": "\u28D1",
+ "/dots158": "\u2891",
+ "/dots16": "\u2821",
+ "/dots167": "\u2861",
+ "/dots1678": "\u28E1",
+ "/dots168": "\u28A1",
+ "/dots17": "\u2841",
+ "/dots178": "\u28C1",
+ "/dots18": "\u2881",
+ "/dots2": "\u2802",
+ "/dots23": "\u2806",
+ "/dots234": "\u280E",
+ "/dots2345": "\u281E",
+ "/dots23456": "\u283E",
+ "/dots234567": "\u287E",
+ "/dots2345678": "\u28FE",
+ "/dots234568": "\u28BE",
+ "/dots23457": "\u285E",
+ "/dots234578": "\u28DE",
+ "/dots23458": "\u289E",
+ "/dots2346": "\u282E",
+ "/dots23467": "\u286E",
+ "/dots234678": "\u28EE",
+ "/dots23468": "\u28AE",
+ "/dots2347": "\u284E",
+ "/dots23478": "\u28CE",
+ "/dots2348": "\u288E",
+ "/dots235": "\u2816",
+ "/dots2356": "\u2836",
+ "/dots23567": "\u2876",
+ "/dots235678": "\u28F6",
+ "/dots23568": "\u28B6",
+ "/dots2357": "\u2856",
+ "/dots23578": "\u28D6",
+ "/dots2358": "\u2896",
+ "/dots236": "\u2826",
+ "/dots2367": "\u2866",
+ "/dots23678": "\u28E6",
+ "/dots2368": "\u28A6",
+ "/dots237": "\u2846",
+ "/dots2378": "\u28C6",
+ "/dots238": "\u2886",
+ "/dots24": "\u280A",
+ "/dots245": "\u281A",
+ "/dots2456": "\u283A",
+ "/dots24567": "\u287A",
+ "/dots245678": "\u28FA",
+ "/dots24568": "\u28BA",
+ "/dots2457": "\u285A",
+ "/dots24578": "\u28DA",
+ "/dots2458": "\u289A",
+ "/dots246": "\u282A",
+ "/dots2467": "\u286A",
+ "/dots24678": "\u28EA",
+ "/dots2468": "\u28AA",
+ "/dots247": "\u284A",
+ "/dots2478": "\u28CA",
+ "/dots248": "\u288A",
+ "/dots25": "\u2812",
+ "/dots256": "\u2832",
+ "/dots2567": "\u2872",
+ "/dots25678": "\u28F2",
+ "/dots2568": "\u28B2",
+ "/dots257": "\u2852",
+ "/dots2578": "\u28D2",
+ "/dots258": "\u2892",
+ "/dots26": "\u2822",
+ "/dots267": "\u2862",
+ "/dots2678": "\u28E2",
+ "/dots268": "\u28A2",
+ "/dots27": "\u2842",
+ "/dots278": "\u28C2",
+ "/dots28": "\u2882",
+ "/dots3": "\u2804",
+ "/dots34": "\u280C",
+ "/dots345": "\u281C",
+ "/dots3456": "\u283C",
+ "/dots34567": "\u287C",
+ "/dots345678": "\u28FC",
+ "/dots34568": "\u28BC",
+ "/dots3457": "\u285C",
+ "/dots34578": "\u28DC",
+ "/dots3458": "\u289C",
+ "/dots346": "\u282C",
+ "/dots3467": "\u286C",
+ "/dots34678": "\u28EC",
+ "/dots3468": "\u28AC",
+ "/dots347": "\u284C",
+ "/dots3478": "\u28CC",
+ "/dots348": "\u288C",
+ "/dots35": "\u2814",
+ "/dots356": "\u2834",
+ "/dots3567": "\u2874",
+ "/dots35678": "\u28F4",
+ "/dots3568": "\u28B4",
+ "/dots357": "\u2854",
+ "/dots3578": "\u28D4",
+ "/dots358": "\u2894",
+ "/dots36": "\u2824",
+ "/dots367": "\u2864",
+ "/dots3678": "\u28E4",
+ "/dots368": "\u28A4",
+ "/dots37": "\u2844",
+ "/dots378": "\u28C4",
+ "/dots38": "\u2884",
+ "/dots4": "\u2808",
+ "/dots45": "\u2818",
+ "/dots456": "\u2838",
+ "/dots4567": "\u2878",
+ "/dots45678": "\u28F8",
+ "/dots4568": "\u28B8",
+ "/dots457": "\u2858",
+ "/dots4578": "\u28D8",
+ "/dots458": "\u2898",
+ "/dots46": "\u2828",
+ "/dots467": "\u2868",
+ "/dots4678": "\u28E8",
+ "/dots468": "\u28A8",
+ "/dots47": "\u2848",
+ "/dots478": "\u28C8",
+ "/dots48": "\u2888",
+ "/dots5": "\u2810",
+ "/dots56": "\u2830",
+ "/dots567": "\u2870",
+ "/dots5678": "\u28F0",
+ "/dots568": "\u28B0",
+ "/dots57": "\u2850",
+ "/dots578": "\u28D0",
+ "/dots58": "\u2890",
+ "/dots6": "\u2820",
+ "/dots67": "\u2860",
+ "/dots678": "\u28E0",
+ "/dots68": "\u28A0",
+ "/dots7": "\u2840",
+ "/dots78": "\u28C0",
+ "/dots8": "\u2880",
+ "/dotsquarefour": "\u2E2C",
+ "/dottedcircle": "\u25CC",
+ "/dottedcross": "\u205C",
+ "/dotupper:hb": "\u05C4",
+ "/doublebarvertical": "\u23F8",
+ "/doubleyodpatah": "\uFB1F",
+ "/doubleyodpatahhebrew": "\uFB1F",
+ "/doughnut": "\u1F369",
+ "/doveOfPeace": "\u1F54A",
+ "/downtackbelowcmb": "\u031E",
+ "/downtackmod": "\u02D5",
+ "/downwarrowleftofuparrow": "\u21F5",
+ "/dparen": "\u249F",
+ "/dparenthesized": "\u249F",
+ "/drachma": "\u20AF",
+ "/dragon": "\u1F409",
+ "/dragonFace": "\u1F432",
+ "/draughtskingblack": "\u26C3",
+ "/draughtskingwhite": "\u26C1",
+ "/draughtsmanblack": "\u26C2",
+ "/draughtsmanwhite": "\u26C0",
+ "/dress": "\u1F457",
+ "/driveslow": "\u26DA",
+ "/dromedaryCamel": "\u1F42A",
+ "/droplet": "\u1F4A7",
+ "/dsquare": "\u1F1A5",
+ "/dsuperior": "\uF6EB",
+ "/dtail": "\u0256",
+ "/dtopbar": "\u018C",
+ "/duhiragana": "\u3065",
+ "/dukatakana": "\u30C5",
+ "/dul": "\u068E",
+ "/dul.fina": "\uFB87",
+ "/dul.isol": "\uFB86",
+ "/dum": "\uA771",
+ "/dvd": "\u1F4C0",
+ "/dyeh": "\u0684",
+ "/dyeh.fina": "\uFB73",
+ "/dyeh.init": "\uFB74",
+ "/dyeh.isol": "\uFB72",
+ "/dyeh.medi": "\uFB75",
+ "/dz": "\u01F3",
+ "/dzaltone": "\u02A3",
+ "/dzcaron": "\u01C6",
+ "/dzcurl": "\u02A5",
+ "/dzeabkhasiancyrillic": "\u04E1",
+ "/dzeabkhcyr": "\u04E1",
+ "/dzecyr": "\u0455",
+ "/dzecyrillic": "\u0455",
+ "/dzed": "\u02A3",
+ "/dzedcurl": "\u02A5",
+ "/dzhecyr": "\u045F",
+ "/dzhecyrillic": "\u045F",
+ "/dzjekomicyr": "\u0507",
+ "/dzzhecyr": "\u052B",
+ "/e": "\u0065",
+ "/e-mail": "\u1F4E7",
+ "/e.fina": "\uFBE5",
+ "/e.inferior": "\u2091",
+ "/e.init": "\uFBE6",
+ "/e.isol": "\uFBE4",
+ "/e.medi": "\uFBE7",
+ "/eVfullwidth": "\u32CE",
+ "/eacute": "\u00E9",
+ "/earOfMaize": "\u1F33D",
+ "/earOfRice": "\u1F33E",
+ "/earth": "\u2641",
+ "/earthGlobeAmericas": "\u1F30E",
+ "/earthGlobeAsiaAustralia": "\u1F30F",
+ "/earthGlobeEuropeAfrica": "\u1F30D",
+ "/earthground": "\u23DA",
+ "/earthideographiccircled": "\u328F",
+ "/earthideographicparen": "\u322F",
+ "/eastsyriaccross": "\u2671",
+ "/ebengali": "\u098F",
+ "/ebopomofo": "\u311C",
+ "/ebreve": "\u0115",
+ "/ecandradeva": "\u090D",
+ "/ecandragujarati": "\u0A8D",
+ "/ecandravowelsigndeva": "\u0945",
+ "/ecandravowelsigngujarati": "\u0AC5",
+ "/ecaron": "\u011B",
+ "/ecedilla": "\u0229",
+ "/ecedillabreve": "\u1E1D",
+ "/echarmenian": "\u0565",
+ "/echyiwnarmenian": "\u0587",
+ "/ecircle": "\u24D4",
+ "/ecirclekatakana": "\u32D3",
+ "/ecircumflex": "\u00EA",
+ "/ecircumflexacute": "\u1EBF",
+ "/ecircumflexbelow": "\u1E19",
+ "/ecircumflexdotbelow": "\u1EC7",
+ "/ecircumflexgrave": "\u1EC1",
+ "/ecircumflexhoi": "\u1EC3",
+ "/ecircumflexhookabove": "\u1EC3",
+ "/ecircumflextilde": "\u1EC5",
+ "/ecyrillic": "\u0454",
+ "/edblgrave": "\u0205",
+ "/edblstruckitalic": "\u2147",
+ "/edeva": "\u090F",
+ "/edieresis": "\u00EB",
+ "/edot": "\u0117",
+ "/edotaccent": "\u0117",
+ "/edotbelow": "\u1EB9",
+ "/eegurmukhi": "\u0A0F",
+ "/eekaasquare": "\u3308",
+ "/eematragurmukhi": "\u0A47",
+ "/efcyr": "\u0444",
+ "/efcyrillic": "\u0444",
+ "/egrave": "\u00E8",
+ "/egravedbl": "\u0205",
+ "/egujarati": "\u0A8F",
+ "/egyptain": "\uA725",
+ "/egyptalef": "\uA723",
+ "/eharmenian": "\u0567",
+ "/ehbopomofo": "\u311D",
+ "/ehiragana": "\u3048",
+ "/ehoi": "\u1EBB",
+ "/ehookabove": "\u1EBB",
+ "/eibopomofo": "\u311F",
+ "/eight": "\u0038",
+ "/eight.inferior": "\u2088",
+ "/eight.roman": "\u2167",
+ "/eight.romansmall": "\u2177",
+ "/eight.superior": "\u2078",
+ "/eightarabic": "\u0668",
+ "/eightbengali": "\u09EE",
+ "/eightcircle": "\u2467",
+ "/eightcircledbl": "\u24FC",
+ "/eightcircleinversesansserif": "\u2791",
+ "/eightcomma": "\u1F109",
+ "/eightdeva": "\u096E",
+ "/eighteencircle": "\u2471",
+ "/eighteencircleblack": "\u24F2",
+ "/eighteenparen": "\u2485",
+ "/eighteenparenthesized": "\u2485",
+ "/eighteenperiod": "\u2499",
+ "/eightfar": "\u06F8",
+ "/eightgujarati": "\u0AEE",
+ "/eightgurmukhi": "\u0A6E",
+ "/eighthackarabic": "\u0668",
+ "/eighthangzhou": "\u3028",
+ "/eighthnote": "\u266A",
+ "/eighthnotebeamed": "\u266B",
+ "/eightideographiccircled": "\u3287",
+ "/eightideographicparen": "\u3227",
+ "/eightinferior": "\u2088",
+ "/eightksquare": "\u1F19F",
+ "/eightmonospace": "\uFF18",
+ "/eightoldstyle": "\uF738",
+ "/eightparen": "\u247B",
+ "/eightparenthesized": "\u247B",
+ "/eightperiod": "\u248F",
+ "/eightpersian": "\u06F8",
+ "/eightroman": "\u2177",
+ "/eightsuperior": "\u2078",
+ "/eightthai": "\u0E58",
+ "/eightycirclesquare": "\u324F",
+ "/einvertedbreve": "\u0207",
+ "/eiotifiedcyr": "\u0465",
+ "/eiotifiedcyrillic": "\u0465",
+ "/eject": "\u23CF",
+ "/ekatakana": "\u30A8",
+ "/ekatakanahalfwidth": "\uFF74",
+ "/ekonkargurmukhi": "\u0A74",
+ "/ekorean": "\u3154",
+ "/elcyr": "\u043B",
+ "/elcyrillic": "\u043B",
+ "/electricLightBulb": "\u1F4A1",
+ "/electricPlug": "\u1F50C",
+ "/electricTorch": "\u1F526",
+ "/electricalintersection": "\u23E7",
+ "/electricarrow": "\u2301",
+ "/element": "\u2208",
+ "/elementdotabove": "\u22F5",
+ "/elementlonghorizontalstroke": "\u22F2",
+ "/elementopeningup": "\u27D2",
+ "/elementoverbar": "\u22F6",
+ "/elementoverbarsmall": "\u22F7",
+ "/elementsmall": "\u220A",
+ "/elementsmallverticalbarhorizontalstroke": "\u22F4",
+ "/elementtwoshorizontalstroke": "\u22F9",
+ "/elementunderbar": "\u22F8",
+ "/elementverticalbarhorizontalstroke": "\u22F3",
+ "/elephant": "\u1F418",
+ "/eleven.roman": "\u216A",
+ "/eleven.romansmall": "\u217A",
+ "/elevencircle": "\u246A",
+ "/elevencircleblack": "\u24EB",
+ "/elevenparen": "\u247E",
+ "/elevenparenthesized": "\u247E",
+ "/elevenperiod": "\u2492",
+ "/elevenroman": "\u217A",
+ "/elhookcyr": "\u0513",
+ "/ellipsis": "\u2026",
+ "/ellipsisdiagonaldownright": "\u22F1",
+ "/ellipsisdiagonalupright": "\u22F0",
+ "/ellipsismidhorizontal": "\u22EF",
+ "/ellipsisvertical": "\u22EE",
+ "/elmiddlehookcyr": "\u0521",
+ "/elsharptailcyr": "\u04C6",
+ "/eltailcyr": "\u052F",
+ "/emacron": "\u0113",
+ "/emacronacute": "\u1E17",
+ "/emacrongrave": "\u1E15",
+ "/emcyr": "\u043C",
+ "/emcyrillic": "\u043C",
+ "/emdash": "\u2014",
+ "/emdashdbl": "\u2E3A",
+ "/emdashtpl": "\u2E3B",
+ "/emdashvertical": "\uFE31",
+ "/emojiModifierFitzpatrickType-1-2": "\u1F3FB",
+ "/emojiModifierFitzpatrickType-3": "\u1F3FC",
+ "/emojiModifierFitzpatrickType-4": "\u1F3FD",
+ "/emojiModifierFitzpatrickType-5": "\u1F3FE",
+ "/emojiModifierFitzpatrickType-6": "\u1F3FF",
+ "/emonospace": "\uFF45",
+ "/emphasis": "\u2383",
+ "/emphasismarkarmenian": "\u055B",
+ "/emptyDocument": "\u1F5CB",
+ "/emptyNote": "\u1F5C5",
+ "/emptyNotePad": "\u1F5C7",
+ "/emptyNotePage": "\u1F5C6",
+ "/emptyPage": "\u1F5CC",
+ "/emptyPages": "\u1F5CD",
+ "/emptyset": "\u2205",
+ "/emquad": "\u2001",
+ "/emsharptailcyr": "\u04CE",
+ "/emspace": "\u2003",
+ "/enbopomofo": "\u3123",
+ "/encyr": "\u043D",
+ "/encyrillic": "\u043D",
+ "/endLeftwardsArrowAbove": "\u1F51A",
+ "/endash": "\u2013",
+ "/endashvertical": "\uFE32",
+ "/endescendercyrillic": "\u04A3",
+ "/endpro": "\u220E",
+ "/eng": "\u014B",
+ "/engbopomofo": "\u3125",
+ "/engecyr": "\u04A5",
+ "/enghecyrillic": "\u04A5",
+ "/enhookcyr": "\u04C8",
+ "/enhookcyrillic": "\u04C8",
+ "/enhookleftcyr": "\u0529",
+ "/enmiddlehookcyr": "\u0523",
+ "/enotch": "\u2C78",
+ "/enquad": "\u2000",
+ "/ensharptailcyr": "\u04CA",
+ "/enspace": "\u2002",
+ "/entailcyr": "\u04A3",
+ "/enter": "\u2386",
+ "/enterpriseideographiccircled": "\u32AD",
+ "/enterpriseideographicparen": "\u323D",
+ "/envelopeDownwardsArrowAbove": "\u1F4E9",
+ "/envelopeLightning": "\u1F584",
+ "/eogonek": "\u0119",
+ "/eokorean": "\u3153",
+ "/eopen": "\u025B",
+ "/eopenclosed": "\u029A",
+ "/eopenreversed": "\u025C",
+ "/eopenreversedclosed": "\u025E",
+ "/eopenreversedhook": "\u025D",
+ "/eparen": "\u24A0",
+ "/eparenthesized": "\u24A0",
+ "/epsilon": "\u03B5",
+ "/epsilonacute": "\u1F73",
+ "/epsilonasper": "\u1F11",
+ "/epsilonasperacute": "\u1F15",
+ "/epsilonaspergrave": "\u1F13",
+ "/epsilongrave": "\u1F72",
+ "/epsilonlenis": "\u1F10",
+ "/epsilonlenisacute": "\u1F14",
+ "/epsilonlenisgrave": "\u1F12",
+ "/epsilonlunatesymbol": "\u03F5",
+ "/epsilonreversedlunatesymbol": "\u03F6",
+ "/epsilontonos": "\u03AD",
+ "/epsilonunderlinefunc": "\u2377",
+ "/equal": "\u003D",
+ "/equal.inferior": "\u208C",
+ "/equal.superior": "\u207C",
+ "/equalandparallel": "\u22D5",
+ "/equalbydefinition": "\u225D",
+ "/equalmonospace": "\uFF1D",
+ "/equalorgreater": "\u22DD",
+ "/equalorless": "\u22DC",
+ "/equalorprecedes": "\u22DE",
+ "/equalorsucceeds": "\u22DF",
+ "/equalscolon": "\u2255",
+ "/equalsmall": "\uFE66",
+ "/equalsuperior": "\u207C",
+ "/equiangular": "\u225A",
+ "/equivalence": "\u2261",
+ "/equivalent": "\u224D",
+ "/eranameheiseisquare": "\u337B",
+ "/eranamemeizisquare": "\u337E",
+ "/eranamesyouwasquare": "\u337C",
+ "/eranametaisyousquare": "\u337D",
+ "/eraseleft": "\u232B",
+ "/eraseright": "\u2326",
+ "/erbopomofo": "\u3126",
+ "/ercyr": "\u0440",
+ "/ercyrillic": "\u0440",
+ "/ereversed": "\u0258",
+ "/ereversedcyr": "\u044D",
+ "/ereversedcyrillic": "\u044D",
+ "/ereverseddieresiscyr": "\u04ED",
+ "/ergfullwidth": "\u32CD",
+ "/ertickcyr": "\u048F",
+ "/escript": "\u212F",
+ "/escyr": "\u0441",
+ "/escyrillic": "\u0441",
+ "/esdescendercyrillic": "\u04AB",
+ "/esh": "\u0283",
+ "/eshcurl": "\u0286",
+ "/eshortdeva": "\u090E",
+ "/eshortvowelsigndeva": "\u0946",
+ "/eshreversedloop": "\u01AA",
+ "/eshsquatreversed": "\u0285",
+ "/esmallhiragana": "\u3047",
+ "/esmallkatakana": "\u30A7",
+ "/esmallkatakanahalfwidth": "\uFF6A",
+ "/estailcyr": "\u04AB",
+ "/estimated": "\u212E",
+ "/estimates": "\u2259",
+ "/estroke": "\u0247",
+ "/esukuudosquare": "\u3307",
+ "/esuperior": "\uF6EC",
+ "/et": "\uA76B",
+ "/eta": "\u03B7",
+ "/etaacute": "\u1F75",
+ "/etaacuteiotasub": "\u1FC4",
+ "/etaasper": "\u1F21",
+ "/etaasperacute": "\u1F25",
+ "/etaasperacuteiotasub": "\u1F95",
+ "/etaaspergrave": "\u1F23",
+ "/etaaspergraveiotasub": "\u1F93",
+ "/etaasperiotasub": "\u1F91",
+ "/etaaspertilde": "\u1F27",
+ "/etaaspertildeiotasub": "\u1F97",
+ "/etagrave": "\u1F74",
+ "/etagraveiotasub": "\u1FC2",
+ "/etaiotasub": "\u1FC3",
+ "/etalenis": "\u1F20",
+ "/etalenisacute": "\u1F24",
+ "/etalenisacuteiotasub": "\u1F94",
+ "/etalenisgrave": "\u1F22",
+ "/etalenisgraveiotasub": "\u1F92",
+ "/etalenisiotasub": "\u1F90",
+ "/etalenistilde": "\u1F26",
+ "/etalenistildeiotasub": "\u1F96",
+ "/etarmenian": "\u0568",
+ "/etatilde": "\u1FC6",
+ "/etatildeiotasub": "\u1FC7",
+ "/etatonos": "\u03AE",
+ "/eth": "\u00F0",
+ "/ethi:aaglottal": "\u12A3",
+ "/ethi:aglottal": "\u12A0",
+ "/ethi:ba": "\u1260",
+ "/ethi:baa": "\u1263",
+ "/ethi:be": "\u1265",
+ "/ethi:bee": "\u1264",
+ "/ethi:bi": "\u1262",
+ "/ethi:bo": "\u1266",
+ "/ethi:bu": "\u1261",
+ "/ethi:bwa": "\u1267",
+ "/ethi:ca": "\u1278",
+ "/ethi:caa": "\u127B",
+ "/ethi:ce": "\u127D",
+ "/ethi:cee": "\u127C",
+ "/ethi:cha": "\u1328",
+ "/ethi:chaa": "\u132B",
+ "/ethi:che": "\u132D",
+ "/ethi:chee": "\u132C",
+ "/ethi:chi": "\u132A",
+ "/ethi:cho": "\u132E",
+ "/ethi:chu": "\u1329",
+ "/ethi:chwa": "\u132F",
+ "/ethi:ci": "\u127A",
+ "/ethi:co": "\u127E",
+ "/ethi:colon": "\u1365",
+ "/ethi:comma": "\u1363",
+ "/ethi:cu": "\u1279",
+ "/ethi:cwa": "\u127F",
+ "/ethi:da": "\u12F0",
+ "/ethi:daa": "\u12F3",
+ "/ethi:dda": "\u12F8",
+ "/ethi:ddaa": "\u12FB",
+ "/ethi:dde": "\u12FD",
+ "/ethi:ddee": "\u12FC",
+ "/ethi:ddi": "\u12FA",
+ "/ethi:ddo": "\u12FE",
+ "/ethi:ddu": "\u12F9",
+ "/ethi:ddwa": "\u12FF",
+ "/ethi:de": "\u12F5",
+ "/ethi:dee": "\u12F4",
+ "/ethi:di": "\u12F2",
+ "/ethi:do": "\u12F6",
+ "/ethi:du": "\u12F1",
+ "/ethi:dwa": "\u12F7",
+ "/ethi:eeglottal": "\u12A4",
+ "/ethi:eglottal": "\u12A5",
+ "/ethi:eight": "\u1370",
+ "/ethi:eighty": "\u1379",
+ "/ethi:fa": "\u1348",
+ "/ethi:faa": "\u134B",
+ "/ethi:fe": "\u134D",
+ "/ethi:fee": "\u134C",
+ "/ethi:fi": "\u134A",
+ "/ethi:fifty": "\u1376",
+ "/ethi:five": "\u136D",
+ "/ethi:fo": "\u134E",
+ "/ethi:forty": "\u1375",
+ "/ethi:four": "\u136C",
+ "/ethi:fu": "\u1349",
+ "/ethi:fullstop": "\u1362",
+ "/ethi:fwa": "\u134F",
+ "/ethi:fya": "\u135A",
+ "/ethi:ga": "\u1308",
+ "/ethi:gaa": "\u130B",
+ "/ethi:ge": "\u130D",
+ "/ethi:gee": "\u130C",
+ "/ethi:geminationandvowellengthmarkcmb": "\u135D",
+ "/ethi:geminationmarkcmb": "\u135F",
+ "/ethi:gga": "\u1318",
+ "/ethi:ggaa": "\u131B",
+ "/ethi:gge": "\u131D",
+ "/ethi:ggee": "\u131C",
+ "/ethi:ggi": "\u131A",
+ "/ethi:ggo": "\u131E",
+ "/ethi:ggu": "\u1319",
+ "/ethi:ggwaa": "\u131F",
+ "/ethi:gi": "\u130A",
+ "/ethi:go": "\u130E",
+ "/ethi:goa": "\u130F",
+ "/ethi:gu": "\u1309",
+ "/ethi:gwa": "\u1310",
+ "/ethi:gwaa": "\u1313",
+ "/ethi:gwe": "\u1315",
+ "/ethi:gwee": "\u1314",
+ "/ethi:gwi": "\u1312",
+ "/ethi:ha": "\u1200",
+ "/ethi:haa": "\u1203",
+ "/ethi:he": "\u1205",
+ "/ethi:hee": "\u1204",
+ "/ethi:hha": "\u1210",
+ "/ethi:hhaa": "\u1213",
+ "/ethi:hhe": "\u1215",
+ "/ethi:hhee": "\u1214",
+ "/ethi:hhi": "\u1212",
+ "/ethi:hho": "\u1216",
+ "/ethi:hhu": "\u1211",
+ "/ethi:hhwa": "\u1217",
+ "/ethi:hi": "\u1202",
+ "/ethi:ho": "\u1206",
+ "/ethi:hoa": "\u1207",
+ "/ethi:hu": "\u1201",
+ "/ethi:hundred": "\u137B",
+ "/ethi:iglottal": "\u12A2",
+ "/ethi:ja": "\u1300",
+ "/ethi:jaa": "\u1303",
+ "/ethi:je": "\u1305",
+ "/ethi:jee": "\u1304",
+ "/ethi:ji": "\u1302",
+ "/ethi:jo": "\u1306",
+ "/ethi:ju": "\u1301",
+ "/ethi:jwa": "\u1307",
+ "/ethi:ka": "\u12A8",
+ "/ethi:kaa": "\u12AB",
+ "/ethi:ke": "\u12AD",
+ "/ethi:kee": "\u12AC",
+ "/ethi:ki": "\u12AA",
+ "/ethi:ko": "\u12AE",
+ "/ethi:koa": "\u12AF",
+ "/ethi:ku": "\u12A9",
+ "/ethi:kwa": "\u12B0",
+ "/ethi:kwaa": "\u12B3",
+ "/ethi:kwe": "\u12B5",
+ "/ethi:kwee": "\u12B4",
+ "/ethi:kwi": "\u12B2",
+ "/ethi:kxa": "\u12B8",
+ "/ethi:kxaa": "\u12BB",
+ "/ethi:kxe": "\u12BD",
+ "/ethi:kxee": "\u12BC",
+ "/ethi:kxi": "\u12BA",
+ "/ethi:kxo": "\u12BE",
+ "/ethi:kxu": "\u12B9",
+ "/ethi:kxwa": "\u12C0",
+ "/ethi:kxwaa": "\u12C3",
+ "/ethi:kxwe": "\u12C5",
+ "/ethi:kxwee": "\u12C4",
+ "/ethi:kxwi": "\u12C2",
+ "/ethi:la": "\u1208",
+ "/ethi:laa": "\u120B",
+ "/ethi:le": "\u120D",
+ "/ethi:lee": "\u120C",
+ "/ethi:li": "\u120A",
+ "/ethi:lo": "\u120E",
+ "/ethi:lu": "\u1209",
+ "/ethi:lwa": "\u120F",
+ "/ethi:ma": "\u1218",
+ "/ethi:maa": "\u121B",
+ "/ethi:me": "\u121D",
+ "/ethi:mee": "\u121C",
+ "/ethi:mi": "\u121A",
+ "/ethi:mo": "\u121E",
+ "/ethi:mu": "\u1219",
+ "/ethi:mwa": "\u121F",
+ "/ethi:mya": "\u1359",
+ "/ethi:na": "\u1290",
+ "/ethi:naa": "\u1293",
+ "/ethi:ne": "\u1295",
+ "/ethi:nee": "\u1294",
+ "/ethi:ni": "\u1292",
+ "/ethi:nine": "\u1371",
+ "/ethi:ninety": "\u137A",
+ "/ethi:no": "\u1296",
+ "/ethi:nu": "\u1291",
+ "/ethi:nwa": "\u1297",
+ "/ethi:nya": "\u1298",
+ "/ethi:nyaa": "\u129B",
+ "/ethi:nye": "\u129D",
+ "/ethi:nyee": "\u129C",
+ "/ethi:nyi": "\u129A",
+ "/ethi:nyo": "\u129E",
+ "/ethi:nyu": "\u1299",
+ "/ethi:nywa": "\u129F",
+ "/ethi:oglottal": "\u12A6",
+ "/ethi:one": "\u1369",
+ "/ethi:pa": "\u1350",
+ "/ethi:paa": "\u1353",
+ "/ethi:paragraphseparator": "\u1368",
+ "/ethi:pe": "\u1355",
+ "/ethi:pee": "\u1354",
+ "/ethi:pha": "\u1330",
+ "/ethi:phaa": "\u1333",
+ "/ethi:pharyngeala": "\u12D0",
+ "/ethi:pharyngealaa": "\u12D3",
+ "/ethi:pharyngeale": "\u12D5",
+ "/ethi:pharyngealee": "\u12D4",
+ "/ethi:pharyngeali": "\u12D2",
+ "/ethi:pharyngealo": "\u12D6",
+ "/ethi:pharyngealu": "\u12D1",
+ "/ethi:phe": "\u1335",
+ "/ethi:phee": "\u1334",
+ "/ethi:phi": "\u1332",
+ "/ethi:pho": "\u1336",
+ "/ethi:phu": "\u1331",
+ "/ethi:phwa": "\u1337",
+ "/ethi:pi": "\u1352",
+ "/ethi:po": "\u1356",
+ "/ethi:prefacecolon": "\u1366",
+ "/ethi:pu": "\u1351",
+ "/ethi:pwa": "\u1357",
+ "/ethi:qa": "\u1240",
+ "/ethi:qaa": "\u1243",
+ "/ethi:qe": "\u1245",
+ "/ethi:qee": "\u1244",
+ "/ethi:qha": "\u1250",
+ "/ethi:qhaa": "\u1253",
+ "/ethi:qhe": "\u1255",
+ "/ethi:qhee": "\u1254",
+ "/ethi:qhi": "\u1252",
+ "/ethi:qho": "\u1256",
+ "/ethi:qhu": "\u1251",
+ "/ethi:qhwa": "\u1258",
+ "/ethi:qhwaa": "\u125B",
+ "/ethi:qhwe": "\u125D",
+ "/ethi:qhwee": "\u125C",
+ "/ethi:qhwi": "\u125A",
+ "/ethi:qi": "\u1242",
+ "/ethi:qo": "\u1246",
+ "/ethi:qoa": "\u1247",
+ "/ethi:qu": "\u1241",
+ "/ethi:questionmark": "\u1367",
+ "/ethi:qwa": "\u1248",
+ "/ethi:qwaa": "\u124B",
+ "/ethi:qwe": "\u124D",
+ "/ethi:qwee": "\u124C",
+ "/ethi:qwi": "\u124A",
+ "/ethi:ra": "\u1228",
+ "/ethi:raa": "\u122B",
+ "/ethi:re": "\u122D",
+ "/ethi:ree": "\u122C",
+ "/ethi:ri": "\u122A",
+ "/ethi:ro": "\u122E",
+ "/ethi:ru": "\u1229",
+ "/ethi:rwa": "\u122F",
+ "/ethi:rya": "\u1358",
+ "/ethi:sa": "\u1230",
+ "/ethi:saa": "\u1233",
+ "/ethi:se": "\u1235",
+ "/ethi:sectionmark": "\u1360",
+ "/ethi:see": "\u1234",
+ "/ethi:semicolon": "\u1364",
+ "/ethi:seven": "\u136F",
+ "/ethi:seventy": "\u1378",
+ "/ethi:sha": "\u1238",
+ "/ethi:shaa": "\u123B",
+ "/ethi:she": "\u123D",
+ "/ethi:shee": "\u123C",
+ "/ethi:shi": "\u123A",
+ "/ethi:sho": "\u123E",
+ "/ethi:shu": "\u1239",
+ "/ethi:shwa": "\u123F",
+ "/ethi:si": "\u1232",
+ "/ethi:six": "\u136E",
+ "/ethi:sixty": "\u1377",
+ "/ethi:so": "\u1236",
+ "/ethi:su": "\u1231",
+ "/ethi:swa": "\u1237",
+ "/ethi:sza": "\u1220",
+ "/ethi:szaa": "\u1223",
+ "/ethi:sze": "\u1225",
+ "/ethi:szee": "\u1224",
+ "/ethi:szi": "\u1222",
+ "/ethi:szo": "\u1226",
+ "/ethi:szu": "\u1221",
+ "/ethi:szwa": "\u1227",
+ "/ethi:ta": "\u1270",
+ "/ethi:taa": "\u1273",
+ "/ethi:te": "\u1275",
+ "/ethi:tee": "\u1274",
+ "/ethi:ten": "\u1372",
+ "/ethi:tenthousand": "\u137C",
+ "/ethi:tha": "\u1320",
+ "/ethi:thaa": "\u1323",
+ "/ethi:the": "\u1325",
+ "/ethi:thee": "\u1324",
+ "/ethi:thi": "\u1322",
+ "/ethi:thirty": "\u1374",
+ "/ethi:tho": "\u1326",
+ "/ethi:three": "\u136B",
+ "/ethi:thu": "\u1321",
+ "/ethi:thwa": "\u1327",
+ "/ethi:ti": "\u1272",
+ "/ethi:to": "\u1276",
+ "/ethi:tsa": "\u1338",
+ "/ethi:tsaa": "\u133B",
+ "/ethi:tse": "\u133D",
+ "/ethi:tsee": "\u133C",
+ "/ethi:tsi": "\u133A",
+ "/ethi:tso": "\u133E",
+ "/ethi:tsu": "\u1339",
+ "/ethi:tswa": "\u133F",
+ "/ethi:tu": "\u1271",
+ "/ethi:twa": "\u1277",
+ "/ethi:twenty": "\u1373",
+ "/ethi:two": "\u136A",
+ "/ethi:tza": "\u1340",
+ "/ethi:tzaa": "\u1343",
+ "/ethi:tze": "\u1345",
+ "/ethi:tzee": "\u1344",
+ "/ethi:tzi": "\u1342",
+ "/ethi:tzo": "\u1346",
+ "/ethi:tzoa": "\u1347",
+ "/ethi:tzu": "\u1341",
+ "/ethi:uglottal": "\u12A1",
+ "/ethi:va": "\u1268",
+ "/ethi:vaa": "\u126B",
+ "/ethi:ve": "\u126D",
+ "/ethi:vee": "\u126C",
+ "/ethi:vi": "\u126A",
+ "/ethi:vo": "\u126E",
+ "/ethi:vowellengthmarkcmb": "\u135E",
+ "/ethi:vu": "\u1269",
+ "/ethi:vwa": "\u126F",
+ "/ethi:wa": "\u12C8",
+ "/ethi:waa": "\u12CB",
+ "/ethi:waglottal": "\u12A7",
+ "/ethi:we": "\u12CD",
+ "/ethi:wee": "\u12CC",
+ "/ethi:wi": "\u12CA",
+ "/ethi:wo": "\u12CE",
+ "/ethi:woa": "\u12CF",
+ "/ethi:wordspace": "\u1361",
+ "/ethi:wu": "\u12C9",
+ "/ethi:xa": "\u1280",
+ "/ethi:xaa": "\u1283",
+ "/ethi:xe": "\u1285",
+ "/ethi:xee": "\u1284",
+ "/ethi:xi": "\u1282",
+ "/ethi:xo": "\u1286",
+ "/ethi:xoa": "\u1287",
+ "/ethi:xu": "\u1281",
+ "/ethi:xwa": "\u1288",
+ "/ethi:xwaa": "\u128B",
+ "/ethi:xwe": "\u128D",
+ "/ethi:xwee": "\u128C",
+ "/ethi:xwi": "\u128A",
+ "/ethi:ya": "\u12E8",
+ "/ethi:yaa": "\u12EB",
+ "/ethi:ye": "\u12ED",
+ "/ethi:yee": "\u12EC",
+ "/ethi:yi": "\u12EA",
+ "/ethi:yo": "\u12EE",
+ "/ethi:yoa": "\u12EF",
+ "/ethi:yu": "\u12E9",
+ "/ethi:za": "\u12D8",
+ "/ethi:zaa": "\u12DB",
+ "/ethi:ze": "\u12DD",
+ "/ethi:zee": "\u12DC",
+ "/ethi:zha": "\u12E0",
+ "/ethi:zhaa": "\u12E3",
+ "/ethi:zhe": "\u12E5",
+ "/ethi:zhee": "\u12E4",
+ "/ethi:zhi": "\u12E2",
+ "/ethi:zho": "\u12E6",
+ "/ethi:zhu": "\u12E1",
+ "/ethi:zhwa": "\u12E7",
+ "/ethi:zi": "\u12DA",
+ "/ethi:zo": "\u12DE",
+ "/ethi:zu": "\u12D9",
+ "/ethi:zwa": "\u12DF",
+ "/etilde": "\u1EBD",
+ "/etildebelow": "\u1E1B",
+ "/etnahta:hb": "\u0591",
+ "/etnahtafoukhhebrew": "\u0591",
+ "/etnahtafoukhlefthebrew": "\u0591",
+ "/etnahtahebrew": "\u0591",
+ "/etnahtalefthebrew": "\u0591",
+ "/eturned": "\u01DD",
+ "/eukorean": "\u3161",
+ "/eukrcyr": "\u0454",
+ "/euler": "\u2107",
+ "/euro": "\u20AC",
+ "/euroarchaic": "\u20A0",
+ "/europeanCastle": "\u1F3F0",
+ "/europeanPostOffice": "\u1F3E4",
+ "/evergreenTree": "\u1F332",
+ "/evowelsignbengali": "\u09C7",
+ "/evowelsigndeva": "\u0947",
+ "/evowelsigngujarati": "\u0AC7",
+ "/excellentideographiccircled": "\u329D",
+ "/excess": "\u2239",
+ "/exclam": "\u0021",
+ "/exclamarmenian": "\u055C",
+ "/exclamationquestion": "\u2049",
+ "/exclamdbl": "\u203C",
+ "/exclamdown": "\u00A1",
+ "/exclamdownsmall": "\uF7A1",
+ "/exclammonospace": "\uFF01",
+ "/exclamsmall": "\uF721",
+ "/existential": "\u2203",
+ "/expressionlessFace": "\u1F611",
+ "/extraterrestrialAlien": "\u1F47D",
+ "/eye": "\u1F441",
+ "/eyeglasses": "\u1F453",
+ "/eyes": "\u1F440",
+ "/ezh": "\u0292",
+ "/ezhcaron": "\u01EF",
+ "/ezhcurl": "\u0293",
+ "/ezhreversed": "\u01B9",
+ "/ezhtail": "\u01BA",
+ "/f": "\u0066",
+ "/f_f": "\uFB00",
+ "/f_f_i": "\uFB03",
+ "/f_f_l": "\uFB04",
+ "/faceMassage": "\u1F486",
+ "/faceSavouringDeliciousFood": "\u1F60B",
+ "/faceScreamingInFear": "\u1F631",
+ "/faceThrowingAKiss": "\u1F618",
+ "/faceWithColdSweat": "\u1F613",
+ "/faceWithLookOfTriumph": "\u1F624",
+ "/faceWithMedicalMask": "\u1F637",
+ "/faceWithNoGoodGesture": "\u1F645",
+ "/faceWithOkGesture": "\u1F646",
+ "/faceWithOpenMouth": "\u1F62E",
+ "/faceWithOpenMouthAndColdSweat": "\u1F630",
+ "/faceWithRollingEyes": "\u1F644",
+ "/faceWithStuckOutTongue": "\u1F61B",
+ "/faceWithStuckOutTongueAndTightlyClosedEyes": "\u1F61D",
+ "/faceWithStuckOutTongueAndWinkingEye": "\u1F61C",
+ "/faceWithTearsOfJoy": "\u1F602",
+ "/faceWithoutMouth": "\u1F636",
+ "/facsimile": "\u213B",
+ "/factory": "\u1F3ED",
+ "/fadeva": "\u095E",
+ "/fagurmukhi": "\u0A5E",
+ "/fahrenheit": "\u2109",
+ "/fallenLeaf": "\u1F342",
+ "/fallingdiagonal": "\u27CD",
+ "/fallingdiagonalincircleinsquareblackwhite": "\u26DE",
+ "/family": "\u1F46A",
+ "/farsi": "\u262B",
+ "/farsiYehDigitFourBelow": "\u0777",
+ "/farsiYehDigitThreeAbove": "\u0776",
+ "/farsiYehDigitTwoAbove": "\u0775",
+ "/fatha": "\u064E",
+ "/fathaIsol": "\uFE76",
+ "/fathaMedi": "\uFE77",
+ "/fathaarabic": "\u064E",
+ "/fathalowarabic": "\u064E",
+ "/fathasmall": "\u0618",
+ "/fathatan": "\u064B",
+ "/fathatanIsol": "\uFE70",
+ "/fathatanarabic": "\u064B",
+ "/fathatwodotsdots": "\u065E",
+ "/fatherChristmas": "\u1F385",
+ "/faxIcon": "\u1F5B7",
+ "/faxMachine": "\u1F4E0",
+ "/fbopomofo": "\u3108",
+ "/fcircle": "\u24D5",
+ "/fdot": "\u1E1F",
+ "/fdotaccent": "\u1E1F",
+ "/fearfulFace": "\u1F628",
+ "/februarytelegraph": "\u32C1",
+ "/feh.fina": "\uFED2",
+ "/feh.init": "\uFED3",
+ "/feh.init_alefmaksura.fina": "\uFC31",
+ "/feh.init_hah.fina": "\uFC2E",
+ "/feh.init_hah.medi": "\uFCBF",
+ "/feh.init_jeem.fina": "\uFC2D",
+ "/feh.init_jeem.medi": "\uFCBE",
+ "/feh.init_khah.fina": "\uFC2F",
+ "/feh.init_khah.medi": "\uFCC0",
+ "/feh.init_khah.medi_meem.medi": "\uFD7D",
+ "/feh.init_meem.fina": "\uFC30",
+ "/feh.init_meem.medi": "\uFCC1",
+ "/feh.init_yeh.fina": "\uFC32",
+ "/feh.isol": "\uFED1",
+ "/feh.medi": "\uFED4",
+ "/feh.medi_alefmaksura.fina": "\uFC7C",
+ "/feh.medi_khah.medi_meem.fina": "\uFD7C",
+ "/feh.medi_meem.medi_yeh.fina": "\uFDC1",
+ "/feh.medi_yeh.fina": "\uFC7D",
+ "/fehThreeDotsUpBelow": "\u0761",
+ "/fehTwoDotsBelow": "\u0760",
+ "/feharabic": "\u0641",
+ "/feharmenian": "\u0586",
+ "/fehdotbelow": "\u06A3",
+ "/fehdotbelowright": "\u06A2",
+ "/fehfinalarabic": "\uFED2",
+ "/fehinitialarabic": "\uFED3",
+ "/fehmedialarabic": "\uFED4",
+ "/fehthreedotsbelow": "\u06A5",
+ "/feicoptic": "\u03E5",
+ "/female": "\u2640",
+ "/femaleideographiccircled": "\u329B",
+ "/feng": "\u02A9",
+ "/ferrisWheel": "\u1F3A1",
+ "/ferry": "\u26F4",
+ "/festivalideographicparen": "\u3240",
+ "/ff": "\uFB00",
+ "/ffi": "\uFB03",
+ "/ffl": "\uFB04",
+ "/fhook": "\u0192",
+ "/fi": "\uFB01", # ligature "fi"
+ "/fieldHockeyStickAndBall": "\u1F3D1",
+ "/fifteencircle": "\u246E",
+ "/fifteencircleblack": "\u24EF",
+ "/fifteenparen": "\u2482",
+ "/fifteenparenthesized": "\u2482",
+ "/fifteenperiod": "\u2496",
+ "/fifty.roman": "\u216C",
+ "/fifty.romansmall": "\u217C",
+ "/fiftycircle": "\u32BF",
+ "/fiftycirclesquare": "\u324C",
+ "/fiftyearlyform.roman": "\u2186",
+ "/fiftythousand.roman": "\u2187",
+ "/figuredash": "\u2012",
+ "/figurespace": "\u2007",
+ "/fileCabinet": "\u1F5C4",
+ "/fileFolder": "\u1F4C1",
+ "/filledbox": "\u25A0",
+ "/filledrect": "\u25AC",
+ "/filledstopabove": "\u06EC",
+ "/filmFrames": "\u1F39E",
+ "/filmProjector": "\u1F4FD",
+ "/finalkaf": "\u05DA",
+ "/finalkaf:hb": "\u05DA",
+ "/finalkafdagesh": "\uFB3A",
+ "/finalkafdageshhebrew": "\uFB3A",
+ "/finalkafhebrew": "\u05DA",
+ "/finalkafqamats": "\u05DA",
+ "/finalkafqamatshebrew": "\u05DA",
+ "/finalkafsheva": "\u05DA",
+ "/finalkafshevahebrew": "\u05DA",
+ "/finalkafwithdagesh:hb": "\uFB3A",
+ "/finalmem": "\u05DD",
+ "/finalmem:hb": "\u05DD",
+ "/finalmemhebrew": "\u05DD",
+ "/finalmemwide:hb": "\uFB26",
+ "/finalnun": "\u05DF",
+ "/finalnun:hb": "\u05DF",
+ "/finalnunhebrew": "\u05DF",
+ "/finalpe": "\u05E3",
+ "/finalpe:hb": "\u05E3",
+ "/finalpehebrew": "\u05E3",
+ "/finalpewithdagesh:hb": "\uFB43",
+ "/finalsigma": "\u03C2",
+ "/finaltsadi": "\u05E5",
+ "/finaltsadi:hb": "\u05E5",
+ "/finaltsadihebrew": "\u05E5",
+ "/financialideographiccircled": "\u3296",
+ "/financialideographicparen": "\u3236",
+ "/finsular": "\uA77C",
+ "/fire": "\u1F525",
+ "/fireEngine": "\u1F692",
+ "/fireideographiccircled": "\u328B",
+ "/fireideographicparen": "\u322B",
+ "/fireworkSparkler": "\u1F387",
+ "/fireworks": "\u1F386",
+ "/firstQuarterMoon": "\u1F313",
+ "/firstQuarterMoonFace": "\u1F31B",
+ "/firstquartermoon": "\u263D",
+ "/firststrongisolate": "\u2068",
+ "/firsttonechinese": "\u02C9",
+ "/fish": "\u1F41F",
+ "/fishCakeSwirlDesign": "\u1F365",
+ "/fisheye": "\u25C9",
+ "/fishingPoleAndFish": "\u1F3A3",
+ "/fistedHandSign": "\u1F44A",
+ "/fitacyr": "\u0473",
+ "/fitacyrillic": "\u0473",
+ "/five": "\u0035",
+ "/five.inferior": "\u2085",
+ "/five.roman": "\u2164",
+ "/five.romansmall": "\u2174",
+ "/five.superior": "\u2075",
+ "/fivearabic": "\u0665",
+ "/fivebengali": "\u09EB",
+ "/fivecircle": "\u2464",
+ "/fivecircledbl": "\u24F9",
+ "/fivecircleinversesansserif": "\u278E",
+ "/fivecomma": "\u1F106",
+ "/fivedeva": "\u096B",
+ "/fivedot": "\u2E2D",
+ "/fivedotpunctuation": "\u2059",
+ "/fiveeighths": "\u215D",
+ "/fivefar": "\u06F5",
+ "/fivegujarati": "\u0AEB",
+ "/fivegurmukhi": "\u0A6B",
+ "/fivehackarabic": "\u0665",
+ "/fivehangzhou": "\u3025",
+ "/fivehundred.roman": "\u216E",
+ "/fivehundred.romansmall": "\u217E",
+ "/fiveideographiccircled": "\u3284",
+ "/fiveideographicparen": "\u3224",
+ "/fiveinferior": "\u2085",
+ "/fivemonospace": "\uFF15",
+ "/fiveoldstyle": "\uF735",
+ "/fiveparen": "\u2478",
+ "/fiveparenthesized": "\u2478",
+ "/fiveperiod": "\u248C",
+ "/fivepersian": "\u06F5",
+ "/fivepointedstar": "\u066D",
+ "/fivepointonesquare": "\u1F1A0",
+ "/fiveroman": "\u2174",
+ "/fivesixths": "\u215A",
+ "/fivesuperior": "\u2075",
+ "/fivethai": "\u0E55",
+ "/fivethousand.roman": "\u2181",
+ "/fl": "\uFB02",
+ "/flagblack": "\u2691",
+ "/flaghorizontalmiddlestripeblackwhite": "\u26FF",
+ "/flaginhole": "\u26F3",
+ "/flagwhite": "\u2690",
+ "/flatness": "\u23E5",
+ "/fleurdelis": "\u269C",
+ "/flexedBiceps": "\u1F4AA",
+ "/floorleft": "\u230A",
+ "/floorright": "\u230B",
+ "/floppyDisk": "\u1F4BE",
+ "/floralheartbulletreversedrotated": "\u2619",
+ "/florin": "\u0192",
+ "/flower": "\u2698",
+ "/flowerPlayingCards": "\u1F3B4",
+ "/flowerpunctuationmark": "\u2055",
+ "/flushedFace": "\u1F633",
+ "/flyingEnvelope": "\u1F585",
+ "/flyingSaucer": "\u1F6F8",
+ "/fmfullwidth": "\u3399",
+ "/fmonospace": "\uFF46",
+ "/fmsquare": "\u3399",
+ "/fofanthai": "\u0E1F",
+ "/fofathai": "\u0E1D",
+ "/fog": "\u1F32B",
+ "/foggy": "\u1F301",
+ "/folder": "\u1F5C0",
+ "/fongmanthai": "\u0E4F",
+ "/footnote": "\u0602",
+ "/footprints": "\u1F463",
+ "/footsquare": "\u23CD",
+ "/forall": "\u2200",
+ "/forces": "\u22A9",
+ "/fork": "\u2442",
+ "/forkKnife": "\u1F374",
+ "/forkKnifePlate": "\u1F37D",
+ "/forsamaritan": "\u214F",
+ "/fortycircle": "\u32B5",
+ "/fortycirclesquare": "\u324B",
+ "/fortyeightcircle": "\u32BD",
+ "/fortyfivecircle": "\u32BA",
+ "/fortyfourcircle": "\u32B9",
+ "/fortyninecircle": "\u32BE",
+ "/fortyonecircle": "\u32B6",
+ "/fortysevencircle": "\u32BC",
+ "/fortysixcircle": "\u32BB",
+ "/fortythreecircle": "\u32B8",
+ "/fortytwocircle": "\u32B7",
+ "/fountain": "\u26F2",
+ "/four": "\u0034",
+ "/four.inferior": "\u2084",
+ "/four.roman": "\u2163",
+ "/four.romansmall": "\u2173",
+ "/four.superior": "\u2074",
+ "/fourLeafClover": "\u1F340",
+ "/fourarabic": "\u0664",
+ "/fourbengali": "\u09EA",
+ "/fourcircle": "\u2463",
+ "/fourcircledbl": "\u24F8",
+ "/fourcircleinversesansserif": "\u278D",
+ "/fourcomma": "\u1F105",
+ "/fourdeva": "\u096A",
+ "/fourdotmark": "\u205B",
+ "/fourdotpunctuation": "\u2058",
+ "/fourfar": "\u06F4",
+ "/fourfifths": "\u2158",
+ "/fourgujarati": "\u0AEA",
+ "/fourgurmukhi": "\u0A6A",
+ "/fourhackarabic": "\u0664",
+ "/fourhangzhou": "\u3024",
+ "/fourideographiccircled": "\u3283",
+ "/fourideographicparen": "\u3223",
+ "/fourinferior": "\u2084",
+ "/fourksquare": "\u1F19E",
+ "/fourmonospace": "\uFF14",
+ "/fournumeratorbengali": "\u09F7",
+ "/fouroldstyle": "\uF734",
+ "/fourparen": "\u2477",
+ "/fourparenthesized": "\u2477",
+ "/fourperemspace": "\u2005",
+ "/fourperiod": "\u248B",
+ "/fourpersian": "\u06F4",
+ "/fourroman": "\u2173",
+ "/foursuperior": "\u2074",
+ "/fourteencircle": "\u246D",
+ "/fourteencircleblack": "\u24EE",
+ "/fourteenparen": "\u2481",
+ "/fourteenparenthesized": "\u2481",
+ "/fourteenperiod": "\u2495",
+ "/fourthai": "\u0E54",
+ "/fourthtonechinese": "\u02CB",
+ "/fparen": "\u24A1",
+ "/fparenthesized": "\u24A1",
+ "/fraction": "\u2044",
+ "/frameAnX": "\u1F5BE",
+ "/framePicture": "\u1F5BC",
+ "/frameTiles": "\u1F5BD",
+ "/franc": "\u20A3",
+ "/freesquare": "\u1F193",
+ "/frenchFries": "\u1F35F",
+ "/freversedepigraphic": "\uA7FB",
+ "/friedShrimp": "\u1F364",
+ "/frogFace": "\u1F438",
+ "/front-facingBabyChick": "\u1F425",
+ "/frown": "\u2322",
+ "/frowningFaceWithOpenMouth": "\u1F626",
+ "/frowningfacewhite": "\u2639",
+ "/fstroke": "\uA799",
+ "/fturned": "\u214E",
+ "/fuelpump": "\u26FD",
+ "/fullBlock": "\u2588",
+ "/fullMoon": "\u1F315",
+ "/fullMoonFace": "\u1F31D",
+ "/functionapplication": "\u2061",
+ "/funeralurn": "\u26B1",
+ "/fuse": "\u23DB",
+ "/fwd:A": "\uFF21",
+ "/fwd:B": "\uFF22",
+ "/fwd:C": "\uFF23",
+ "/fwd:D": "\uFF24",
+ "/fwd:E": "\uFF25",
+ "/fwd:F": "\uFF26",
+ "/fwd:G": "\uFF27",
+ "/fwd:H": "\uFF28",
+ "/fwd:I": "\uFF29",
+ "/fwd:J": "\uFF2A",
+ "/fwd:K": "\uFF2B",
+ "/fwd:L": "\uFF2C",
+ "/fwd:M": "\uFF2D",
+ "/fwd:N": "\uFF2E",
+ "/fwd:O": "\uFF2F",
+ "/fwd:P": "\uFF30",
+ "/fwd:Q": "\uFF31",
+ "/fwd:R": "\uFF32",
+ "/fwd:S": "\uFF33",
+ "/fwd:T": "\uFF34",
+ "/fwd:U": "\uFF35",
+ "/fwd:V": "\uFF36",
+ "/fwd:W": "\uFF37",
+ "/fwd:X": "\uFF38",
+ "/fwd:Y": "\uFF39",
+ "/fwd:Z": "\uFF3A",
+ "/fwd:a": "\uFF41",
+ "/fwd:ampersand": "\uFF06",
+ "/fwd:asciicircum": "\uFF3E",
+ "/fwd:asciitilde": "\uFF5E",
+ "/fwd:asterisk": "\uFF0A",
+ "/fwd:at": "\uFF20",
+ "/fwd:b": "\uFF42",
+ "/fwd:backslash": "\uFF3C",
+ "/fwd:bar": "\uFF5C",
+ "/fwd:braceleft": "\uFF5B",
+ "/fwd:braceright": "\uFF5D",
+ "/fwd:bracketleft": "\uFF3B",
+ "/fwd:bracketright": "\uFF3D",
+ "/fwd:brokenbar": "\uFFE4",
+ "/fwd:c": "\uFF43",
+ "/fwd:centsign": "\uFFE0",
+ "/fwd:colon": "\uFF1A",
+ "/fwd:comma": "\uFF0C",
+ "/fwd:d": "\uFF44",
+ "/fwd:dollar": "\uFF04",
+ "/fwd:e": "\uFF45",
+ "/fwd:eight": "\uFF18",
+ "/fwd:equal": "\uFF1D",
+ "/fwd:exclam": "\uFF01",
+ "/fwd:f": "\uFF46",
+ "/fwd:five": "\uFF15",
+ "/fwd:four": "\uFF14",
+ "/fwd:g": "\uFF47",
+ "/fwd:grave": "\uFF40",
+ "/fwd:greater": "\uFF1E",
+ "/fwd:h": "\uFF48",
+ "/fwd:hyphen": "\uFF0D",
+ "/fwd:i": "\uFF49",
+ "/fwd:j": "\uFF4A",
+ "/fwd:k": "\uFF4B",
+ "/fwd:l": "\uFF4C",
+ "/fwd:leftwhiteparenthesis": "\uFF5F",
+ "/fwd:less": "\uFF1C",
+ "/fwd:m": "\uFF4D",
+ "/fwd:macron": "\uFFE3",
+ "/fwd:n": "\uFF4E",
+ "/fwd:nine": "\uFF19",
+ "/fwd:notsign": "\uFFE2",
+ "/fwd:numbersign": "\uFF03",
+ "/fwd:o": "\uFF4F",
+ "/fwd:one": "\uFF11",
+ "/fwd:p": "\uFF50",
+ "/fwd:parenthesisleft": "\uFF08",
+ "/fwd:parenthesisright": "\uFF09",
+ "/fwd:percent": "\uFF05",
+ "/fwd:period": "\uFF0E",
+ "/fwd:plus": "\uFF0B",
+ "/fwd:poundsign": "\uFFE1",
+ "/fwd:q": "\uFF51",
+ "/fwd:question": "\uFF1F",
+ "/fwd:quotedbl": "\uFF02",
+ "/fwd:quotesingle": "\uFF07",
+ "/fwd:r": "\uFF52",
+ "/fwd:rightwhiteparenthesis": "\uFF60",
+ "/fwd:s": "\uFF53",
+ "/fwd:semicolon": "\uFF1B",
+ "/fwd:seven": "\uFF17",
+ "/fwd:six": "\uFF16",
+ "/fwd:slash": "\uFF0F",
+ "/fwd:t": "\uFF54",
+ "/fwd:three": "\uFF13",
+ "/fwd:two": "\uFF12",
+ "/fwd:u": "\uFF55",
+ "/fwd:underscore": "\uFF3F",
+ "/fwd:v": "\uFF56",
+ "/fwd:w": "\uFF57",
+ "/fwd:wonsign": "\uFFE6",
+ "/fwd:x": "\uFF58",
+ "/fwd:y": "\uFF59",
+ "/fwd:yensign": "\uFFE5",
+ "/fwd:z": "\uFF5A",
+ "/fwd:zero": "\uFF10",
+ "/g": "\u0067",
+ "/gabengali": "\u0997",
+ "/gacute": "\u01F5",
+ "/gadeva": "\u0917",
+ "/gaf": "\u06AF",
+ "/gaf.fina": "\uFB93",
+ "/gaf.init": "\uFB94",
+ "/gaf.isol": "\uFB92",
+ "/gaf.medi": "\uFB95",
+ "/gafarabic": "\u06AF",
+ "/gaffinalarabic": "\uFB93",
+ "/gafinitialarabic": "\uFB94",
+ "/gafmedialarabic": "\uFB95",
+ "/gafring": "\u06B0",
+ "/gafthreedotsabove": "\u06B4",
+ "/gaftwodotsbelow": "\u06B2",
+ "/gagujarati": "\u0A97",
+ "/gagurmukhi": "\u0A17",
+ "/gahiragana": "\u304C",
+ "/gakatakana": "\u30AC",
+ "/galsquare": "\u33FF",
+ "/gameDie": "\u1F3B2",
+ "/gamma": "\u03B3",
+ "/gammadblstruck": "\u213D",
+ "/gammalatinsmall": "\u0263",
+ "/gammasuperior": "\u02E0",
+ "/gammasupmod": "\u02E0",
+ "/gamurda": "\uA993",
+ "/gangiacoptic": "\u03EB",
+ "/ganmasquare": "\u330F",
+ "/garonsquare": "\u330E",
+ "/gbfullwidth": "\u3387",
+ "/gbopomofo": "\u310D",
+ "/gbreve": "\u011F",
+ "/gcaron": "\u01E7",
+ "/gcedilla": "\u0123",
+ "/gcircle": "\u24D6",
+ "/gcircumflex": "\u011D",
+ "/gcommaaccent": "\u0123",
+ "/gdot": "\u0121",
+ "/gdotaccent": "\u0121",
+ "/gear": "\u2699",
+ "/gearhles": "\u26EE",
+ "/gearouthub": "\u26ED",
+ "/gecyr": "\u0433",
+ "/gecyrillic": "\u0433",
+ "/gehiragana": "\u3052",
+ "/gehookcyr": "\u0495",
+ "/gehookstrokecyr": "\u04FB",
+ "/gekatakana": "\u30B2",
+ "/gemStone": "\u1F48E",
+ "/gemini": "\u264A",
+ "/geometricallyequal": "\u2251",
+ "/geometricallyequivalent": "\u224E",
+ "/geometricproportion": "\u223A",
+ "/geresh:hb": "\u05F3",
+ "/gereshMuqdam:hb": "\u059D",
+ "/gereshaccenthebrew": "\u059C",
+ "/gereshhebrew": "\u05F3",
+ "/gereshmuqdamhebrew": "\u059D",
+ "/germandbls": "\u00DF",
+ "/germanpenny": "\u20B0",
+ "/gershayim:hb": "\u05F4",
+ "/gershayimaccenthebrew": "\u059E",
+ "/gershayimhebrew": "\u05F4",
+ "/gestrokecyr": "\u0493",
+ "/getailcyr": "\u04F7",
+ "/getamark": "\u3013",
+ "/geupcyr": "\u0491",
+ "/ghabengali": "\u0998",
+ "/ghadarmenian": "\u0572",
+ "/ghadeva": "\u0918",
+ "/ghagujarati": "\u0A98",
+ "/ghagurmukhi": "\u0A18",
+ "/ghain": "\u063A",
+ "/ghain.fina": "\uFECE",
+ "/ghain.init": "\uFECF",
+ "/ghain.init_alefmaksura.fina": "\uFCF9",
+ "/ghain.init_jeem.fina": "\uFC2B",
+ "/ghain.init_jeem.medi": "\uFCBC",
+ "/ghain.init_meem.fina": "\uFC2C",
+ "/ghain.init_meem.medi": "\uFCBD",
+ "/ghain.init_yeh.fina": "\uFCFA",
+ "/ghain.isol": "\uFECD",
+ "/ghain.medi": "\uFED0",
+ "/ghain.medi_alefmaksura.fina": "\uFD15",
+ "/ghain.medi_meem.medi_alefmaksura.fina": "\uFD7B",
+ "/ghain.medi_meem.medi_meem.fina": "\uFD79",
+ "/ghain.medi_meem.medi_yeh.fina": "\uFD7A",
+ "/ghain.medi_yeh.fina": "\uFD16",
+ "/ghainarabic": "\u063A",
+ "/ghaindotbelow": "\u06FC",
+ "/ghainfinalarabic": "\uFECE",
+ "/ghaininitialarabic": "\uFECF",
+ "/ghainmedialarabic": "\uFED0",
+ "/ghemiddlehookcyrillic": "\u0495",
+ "/ghestrokecyrillic": "\u0493",
+ "/gheupturncyrillic": "\u0491",
+ "/ghhadeva": "\u095A",
+ "/ghhagurmukhi": "\u0A5A",
+ "/ghook": "\u0260",
+ "/ghost": "\u1F47B",
+ "/ghzfullwidth": "\u3393",
+ "/ghzsquare": "\u3393",
+ "/gigasquare": "\u3310",
+ "/gihiragana": "\u304E",
+ "/gikatakana": "\u30AE",
+ "/gimarmenian": "\u0563",
+ "/gimel": "\u05D2",
+ "/gimel:hb": "\u05D2",
+ "/gimeldagesh": "\uFB32",
+ "/gimeldageshhebrew": "\uFB32",
+ "/gimelhebrew": "\u05D2",
+ "/gimelwithdagesh:hb": "\uFB32",
+ "/giniisquare": "\u3311",
+ "/ginsularturned": "\uA77F",
+ "/girl": "\u1F467",
+ "/girls": "\u1F6CA",
+ "/girudaasquare": "\u3313",
+ "/gjecyr": "\u0453",
+ "/gjecyrillic": "\u0453",
+ "/globeMeridians": "\u1F310",
+ "/glottalinvertedstroke": "\u01BE",
+ "/glottalstop": "\u0294",
+ "/glottalstopinverted": "\u0296",
+ "/glottalstopmod": "\u02C0",
+ "/glottalstopreversed": "\u0295",
+ "/glottalstopreversedmod": "\u02C1",
+ "/glottalstopreversedsuperior": "\u02E4",
+ "/glottalstopstroke": "\u02A1",
+ "/glottalstopstrokereversed": "\u02A2",
+ "/glottalstopsupreversedmod": "\u02E4",
+ "/glowingStar": "\u1F31F",
+ "/gmacron": "\u1E21",
+ "/gmonospace": "\uFF47",
+ "/gmtr:diamondblack": "\u25C6",
+ "/gmtr:diamondwhite": "\u25C7",
+ "/gnrl:hyphen": "\u2010",
+ "/goat": "\u1F410",
+ "/gobliquestroke": "\uA7A1",
+ "/gohiragana": "\u3054",
+ "/gokatakana": "\u30B4",
+ "/golfer": "\u1F3CC",
+ "/gpafullwidth": "\u33AC",
+ "/gparen": "\u24A2",
+ "/gparenthesized": "\u24A2",
+ "/gpasquare": "\u33AC",
+ "/gr:acute": "\u1FFD",
+ "/gr:grave": "\u1FEF",
+ "/gr:question": "\u037E",
+ "/gr:tilde": "\u1FC0",
+ "/gradient": "\u2207",
+ "/graduationCap": "\u1F393",
+ "/grapes": "\u1F347",
+ "/grave": "\u0060",
+ "/gravebelowcmb": "\u0316",
+ "/gravecmb": "\u0300",
+ "/gravecomb": "\u0300",
+ "/gravedblmiddlemod": "\u02F5",
+ "/gravedeva": "\u0953",
+ "/gravelowmod": "\u02CE",
+ "/gravemiddlemod": "\u02F4",
+ "/gravemod": "\u02CB",
+ "/gravemonospace": "\uFF40",
+ "/gravetonecmb": "\u0340",
+ "/greater": "\u003E",
+ "/greaterbutnotequal": "\u2269",
+ "/greaterbutnotequivalent": "\u22E7",
+ "/greaterdot": "\u22D7",
+ "/greaterequal": "\u2265",
+ "/greaterequalorless": "\u22DB",
+ "/greatermonospace": "\uFF1E",
+ "/greaterorequivalent": "\u2273",
+ "/greaterorless": "\u2277",
+ "/greateroverequal": "\u2267",
+ "/greatersmall": "\uFE65",
+ "/greenApple": "\u1F34F",
+ "/greenBook": "\u1F4D7",
+ "/greenHeart": "\u1F49A",
+ "/grimacingFace": "\u1F62C",
+ "/grinningCatFaceWithSmilingEyes": "\u1F638",
+ "/grinningFace": "\u1F600",
+ "/grinningFaceWithSmilingEyes": "\u1F601",
+ "/growingHeart": "\u1F497",
+ "/gscript": "\u0261",
+ "/gstroke": "\u01E5",
+ "/guarani": "\u20B2",
+ "/guardsman": "\u1F482",
+ "/gueh": "\u06B3",
+ "/gueh.fina": "\uFB97",
+ "/gueh.init": "\uFB98",
+ "/gueh.isol": "\uFB96",
+ "/gueh.medi": "\uFB99",
+ "/guhiragana": "\u3050",
+ "/guillemetleft": "\u00AB",
+ "/guillemetright": "\u00BB",
+ "/guillemotleft": "\u00AB",
+ "/guillemotright": "\u00BB",
+ "/guilsinglleft": "\u2039",
+ "/guilsinglright": "\u203A",
+ "/guitar": "\u1F3B8",
+ "/gujr:a": "\u0A85",
+ "/gujr:aa": "\u0A86",
+ "/gujr:aasign": "\u0ABE",
+ "/gujr:abbreviation": "\u0AF0",
+ "/gujr:ai": "\u0A90",
+ "/gujr:aisign": "\u0AC8",
+ "/gujr:anusvara": "\u0A82",
+ "/gujr:au": "\u0A94",
+ "/gujr:ausign": "\u0ACC",
+ "/gujr:avagraha": "\u0ABD",
+ "/gujr:ba": "\u0AAC",
+ "/gujr:bha": "\u0AAD",
+ "/gujr:binducandra": "\u0A81",
+ "/gujr:ca": "\u0A9A",
+ "/gujr:cha": "\u0A9B",
+ "/gujr:circlenuktaabove": "\u0AFE",
+ "/gujr:da": "\u0AA6",
+ "/gujr:dda": "\u0AA1",
+ "/gujr:ddha": "\u0AA2",
+ "/gujr:dha": "\u0AA7",
+ "/gujr:e": "\u0A8F",
+ "/gujr:ecandra": "\u0A8D",
+ "/gujr:eight": "\u0AEE",
+ "/gujr:esign": "\u0AC7",
+ "/gujr:esigncandra": "\u0AC5",
+ "/gujr:five": "\u0AEB",
+ "/gujr:four": "\u0AEA",
+ "/gujr:ga": "\u0A97",
+ "/gujr:gha": "\u0A98",
+ "/gujr:ha": "\u0AB9",
+ "/gujr:i": "\u0A87",
+ "/gujr:ii": "\u0A88",
+ "/gujr:iisign": "\u0AC0",
+ "/gujr:isign": "\u0ABF",
+ "/gujr:ja": "\u0A9C",
+ "/gujr:jha": "\u0A9D",
+ "/gujr:ka": "\u0A95",
+ "/gujr:kha": "\u0A96",
+ "/gujr:la": "\u0AB2",
+ "/gujr:lla": "\u0AB3",
+ "/gujr:llvocal": "\u0AE1",
+ "/gujr:llvocalsign": "\u0AE3",
+ "/gujr:lvocal": "\u0A8C",
+ "/gujr:lvocalsign": "\u0AE2",
+ "/gujr:ma": "\u0AAE",
+ "/gujr:maddah": "\u0AFC",
+ "/gujr:na": "\u0AA8",
+ "/gujr:nga": "\u0A99",
+ "/gujr:nine": "\u0AEF",
+ "/gujr:nna": "\u0AA3",
+ "/gujr:nukta": "\u0ABC",
+ "/gujr:nya": "\u0A9E",
+ "/gujr:o": "\u0A93",
+ "/gujr:ocandra": "\u0A91",
+ "/gujr:om": "\u0AD0",
+ "/gujr:one": "\u0AE7",
+ "/gujr:osign": "\u0ACB",
+ "/gujr:osigncandra": "\u0AC9",
+ "/gujr:pa": "\u0AAA",
+ "/gujr:pha": "\u0AAB",
+ "/gujr:ra": "\u0AB0",
+ "/gujr:rrvocal": "\u0AE0",
+ "/gujr:rrvocalsign": "\u0AC4",
+ "/gujr:rupee": "\u0AF1",
+ "/gujr:rvocal": "\u0A8B",
+ "/gujr:rvocalsign": "\u0AC3",
+ "/gujr:sa": "\u0AB8",
+ "/gujr:seven": "\u0AED",
+ "/gujr:sha": "\u0AB6",
+ "/gujr:shadda": "\u0AFB",
+ "/gujr:six": "\u0AEC",
+ "/gujr:ssa": "\u0AB7",
+ "/gujr:sukun": "\u0AFA",
+ "/gujr:ta": "\u0AA4",
+ "/gujr:tha": "\u0AA5",
+ "/gujr:three": "\u0AE9",
+ "/gujr:three-dotnuktaabove": "\u0AFD",
+ "/gujr:tta": "\u0A9F",
+ "/gujr:ttha": "\u0AA0",
+ "/gujr:two": "\u0AE8",
+ "/gujr:two-circlenuktaabove": "\u0AFF",
+ "/gujr:u": "\u0A89",
+ "/gujr:usign": "\u0AC1",
+ "/gujr:uu": "\u0A8A",
+ "/gujr:uusign": "\u0AC2",
+ "/gujr:va": "\u0AB5",
+ "/gujr:virama": "\u0ACD",
+ "/gujr:visarga": "\u0A83",
+ "/gujr:ya": "\u0AAF",
+ "/gujr:zero": "\u0AE6",
+ "/gujr:zha": "\u0AF9",
+ "/gukatakana": "\u30B0",
+ "/guramusquare": "\u3318",
+ "/guramutonsquare": "\u3319",
+ "/guru:a": "\u0A05",
+ "/guru:aa": "\u0A06",
+ "/guru:aasign": "\u0A3E",
+ "/guru:adakbindisign": "\u0A01",
+ "/guru:addak": "\u0A71",
+ "/guru:ai": "\u0A10",
+ "/guru:aisign": "\u0A48",
+ "/guru:au": "\u0A14",
+ "/guru:ausign": "\u0A4C",
+ "/guru:ba": "\u0A2C",
+ "/guru:bha": "\u0A2D",
+ "/guru:bindisign": "\u0A02",
+ "/guru:ca": "\u0A1A",
+ "/guru:cha": "\u0A1B",
+ "/guru:da": "\u0A26",
+ "/guru:dda": "\u0A21",
+ "/guru:ddha": "\u0A22",
+ "/guru:dha": "\u0A27",
+ "/guru:ee": "\u0A0F",
+ "/guru:eesign": "\u0A47",
+ "/guru:eight": "\u0A6E",
+ "/guru:ekonkar": "\u0A74",
+ "/guru:fa": "\u0A5E",
+ "/guru:five": "\u0A6B",
+ "/guru:four": "\u0A6A",
+ "/guru:ga": "\u0A17",
+ "/guru:gha": "\u0A18",
+ "/guru:ghha": "\u0A5A",
+ "/guru:ha": "\u0A39",
+ "/guru:i": "\u0A07",
+ "/guru:ii": "\u0A08",
+ "/guru:iisign": "\u0A40",
+ "/guru:iri": "\u0A72",
+ "/guru:isign": "\u0A3F",
+ "/guru:ja": "\u0A1C",
+ "/guru:jha": "\u0A1D",
+ "/guru:ka": "\u0A15",
+ "/guru:kha": "\u0A16",
+ "/guru:khha": "\u0A59",
+ "/guru:la": "\u0A32",
+ "/guru:lla": "\u0A33",
+ "/guru:ma": "\u0A2E",
+ "/guru:na": "\u0A28",
+ "/guru:nga": "\u0A19",
+ "/guru:nine": "\u0A6F",
+ "/guru:nna": "\u0A23",
+ "/guru:nukta": "\u0A3C",
+ "/guru:nya": "\u0A1E",
+ "/guru:one": "\u0A67",
+ "/guru:oo": "\u0A13",
+ "/guru:oosign": "\u0A4B",
+ "/guru:pa": "\u0A2A",
+ "/guru:pha": "\u0A2B",
+ "/guru:ra": "\u0A30",
+ "/guru:rra": "\u0A5C",
+ "/guru:sa": "\u0A38",
+ "/guru:seven": "\u0A6D",
+ "/guru:sha": "\u0A36",
+ "/guru:six": "\u0A6C",
+ "/guru:ta": "\u0A24",
+ "/guru:tha": "\u0A25",
+ "/guru:three": "\u0A69",
+ "/guru:tippi": "\u0A70",
+ "/guru:tta": "\u0A1F",
+ "/guru:ttha": "\u0A20",
+ "/guru:two": "\u0A68",
+ "/guru:u": "\u0A09",
+ "/guru:udaatsign": "\u0A51",
+ "/guru:ura": "\u0A73",
+ "/guru:usign": "\u0A41",
+ "/guru:uu": "\u0A0A",
+ "/guru:uusign": "\u0A42",
+ "/guru:va": "\u0A35",
+ "/guru:virama": "\u0A4D",
+ "/guru:visarga": "\u0A03",
+ "/guru:ya": "\u0A2F",
+ "/guru:yakashsign": "\u0A75",
+ "/guru:za": "\u0A5B",
+ "/guru:zero": "\u0A66",
+ "/gyfullwidth": "\u33C9",
+ "/gysquare": "\u33C9",
+ "/h": "\u0068",
+ "/h.inferior": "\u2095",
+ "/haabkhasiancyrillic": "\u04A9",
+ "/haabkhcyr": "\u04A9",
+ "/haaltonearabic": "\u06C1",
+ "/habengali": "\u09B9",
+ "/hacirclekatakana": "\u32E9",
+ "/hacyr": "\u0445",
+ "/hadescendercyrillic": "\u04B3",
+ "/hadeva": "\u0939",
+ "/hafullwidth": "\u33CA",
+ "/hagujarati": "\u0AB9",
+ "/hagurmukhi": "\u0A39",
+ "/hah": "\u062D",
+ "/hah.fina": "\uFEA2",
+ "/hah.init": "\uFEA3",
+ "/hah.init_alefmaksura.fina": "\uFCFF",
+ "/hah.init_jeem.fina": "\uFC17",
+ "/hah.init_jeem.medi": "\uFCA9",
+ "/hah.init_meem.fina": "\uFC18",
+ "/hah.init_meem.medi": "\uFCAA",
+ "/hah.init_yeh.fina": "\uFD00",
+ "/hah.isol": "\uFEA1",
+ "/hah.medi": "\uFEA4",
+ "/hah.medi_alefmaksura.fina": "\uFD1B",
+ "/hah.medi_jeem.medi_yeh.fina": "\uFDBF",
+ "/hah.medi_meem.medi_alefmaksura.fina": "\uFD5B",
+ "/hah.medi_meem.medi_yeh.fina": "\uFD5A",
+ "/hah.medi_yeh.fina": "\uFD1C",
+ "/hahDigitFourBelow": "\u077C",
+ "/hahSmallTahAbove": "\u0772",
+ "/hahSmallTahBelow": "\u076E",
+ "/hahSmallTahTwoDots": "\u076F",
+ "/hahThreeDotsUpBelow": "\u0758",
+ "/hahTwoDotsAbove": "\u0757",
+ "/haharabic": "\u062D",
+ "/hahfinalarabic": "\uFEA2",
+ "/hahhamza": "\u0681",
+ "/hahinitialarabic": "\uFEA3",
+ "/hahiragana": "\u306F",
+ "/hahmedialarabic": "\uFEA4",
+ "/hahookcyr": "\u04FD",
+ "/hahthreedotsabove": "\u0685",
+ "/hahtwodotsvertical": "\u0682",
+ "/haircut": "\u1F487",
+ "/hairspace": "\u200A",
+ "/haitusquare": "\u332A",
+ "/hakatakana": "\u30CF",
+ "/hakatakanahalfwidth": "\uFF8A",
+ "/halantgurmukhi": "\u0A4D",
+ "/halfcircleleftblack": "\u25D6",
+ "/halfcirclerightblack": "\u25D7",
+ "/hamburger": "\u1F354",
+ "/hammer": "\u1F528",
+ "/hammerAndWrench": "\u1F6E0",
+ "/hammerpick": "\u2692",
+ "/hammersickle": "\u262D",
+ "/hamsterFace": "\u1F439",
+ "/hamza": "\u0621",
+ "/hamzaIsol": "\uFE80",
+ "/hamzaabove": "\u0654",
+ "/hamzaarabic": "\u0621",
+ "/hamzabelow": "\u0655",
+ "/hamzadammaarabic": "\u0621",
+ "/hamzadammatanarabic": "\u0621",
+ "/hamzafathaarabic": "\u0621",
+ "/hamzafathatanarabic": "\u0621",
+ "/hamzalowarabic": "\u0621",
+ "/hamzalowkasraarabic": "\u0621",
+ "/hamzalowkasratanarabic": "\u0621",
+ "/hamzasukunarabic": "\u0621",
+ "/handbag": "\u1F45C",
+ "/handtailfishhookturned": "\u02AF",
+ "/hangulchieuchaparen": "\u3217",
+ "/hangulchieuchparen": "\u3209",
+ "/hangulcieucaparen": "\u3216",
+ "/hangulcieucparen": "\u3208",
+ "/hangulcieucuparen": "\u321C",
+ "/hanguldottonemarkdbl": "\u302F",
+ "/hangulfiller": "\u3164",
+ "/hangulhieuhaparen": "\u321B",
+ "/hangulhieuhparen": "\u320D",
+ "/hangulieungaparen": "\u3215",
+ "/hangulieungparen": "\u3207",
+ "/hangulkhieukhaparen": "\u3218",
+ "/hangulkhieukhparen": "\u320A",
+ "/hangulkiyeokaparen": "\u320E",
+ "/hangulkiyeokparen": "\u3200",
+ "/hangulmieumaparen": "\u3212",
+ "/hangulmieumparen": "\u3204",
+ "/hangulnieunaparen": "\u320F",
+ "/hangulnieunparen": "\u3201",
+ "/hangulphieuphaparen": "\u321A",
+ "/hangulphieuphparen": "\u320C",
+ "/hangulpieupaparen": "\u3213",
+ "/hangulpieupparen": "\u3205",
+ "/hangulrieulaparen": "\u3211",
+ "/hangulrieulparen": "\u3203",
+ "/hangulsingledottonemark": "\u302E",
+ "/hangulsiosaparen": "\u3214",
+ "/hangulsiosparen": "\u3206",
+ "/hangulthieuthaparen": "\u3219",
+ "/hangulthieuthparen": "\u320B",
+ "/hangultikeutaparen": "\u3210",
+ "/hangultikeutparen": "\u3202",
+ "/happyPersonRaisingOneHand": "\u1F64B",
+ "/hardDisk": "\u1F5B4",
+ "/hardcyr": "\u044A",
+ "/hardsigncyrillic": "\u044A",
+ "/harpoondownbarbleft": "\u21C3",
+ "/harpoondownbarbright": "\u21C2",
+ "/harpoonleftbarbdown": "\u21BD",
+ "/harpoonleftbarbup": "\u21BC",
+ "/harpoonrightbarbdown": "\u21C1",
+ "/harpoonrightbarbup": "\u21C0",
+ "/harpoonupbarbleft": "\u21BF",
+ "/harpoonupbarbright": "\u21BE",
+ "/hasquare": "\u33CA",
+ "/hastrokecyr": "\u04FF",
+ "/hatafPatah:hb": "\u05B2",
+ "/hatafQamats:hb": "\u05B3",
+ "/hatafSegol:hb": "\u05B1",
+ "/hatafpatah": "\u05B2",
+ "/hatafpatah16": "\u05B2",
+ "/hatafpatah23": "\u05B2",
+ "/hatafpatah2f": "\u05B2",
+ "/hatafpatahhebrew": "\u05B2",
+ "/hatafpatahnarrowhebrew": "\u05B2",
+ "/hatafpatahquarterhebrew": "\u05B2",
+ "/hatafpatahwidehebrew": "\u05B2",
+ "/hatafqamats": "\u05B3",
+ "/hatafqamats1b": "\u05B3",
+ "/hatafqamats28": "\u05B3",
+ "/hatafqamats34": "\u05B3",
+ "/hatafqamatshebrew": "\u05B3",
+ "/hatafqamatsnarrowhebrew": "\u05B3",
+ "/hatafqamatsquarterhebrew": "\u05B3",
+ "/hatafqamatswidehebrew": "\u05B3",
+ "/hatafsegol": "\u05B1",
+ "/hatafsegol17": "\u05B1",
+ "/hatafsegol24": "\u05B1",
+ "/hatafsegol30": "\u05B1",
+ "/hatafsegolhebrew": "\u05B1",
+ "/hatafsegolnarrowhebrew": "\u05B1",
+ "/hatafsegolquarterhebrew": "\u05B1",
+ "/hatafsegolwidehebrew": "\u05B1",
+ "/hatchingChick": "\u1F423",
+ "/haveideographiccircled": "\u3292",
+ "/haveideographicparen": "\u3232",
+ "/hbar": "\u0127",
+ "/hbopomofo": "\u310F",
+ "/hbrevebelow": "\u1E2B",
+ "/hcaron": "\u021F",
+ "/hcedilla": "\u1E29",
+ "/hcircle": "\u24D7",
+ "/hcircumflex": "\u0125",
+ "/hcsquare": "\u1F1A6",
+ "/hdescender": "\u2C68",
+ "/hdieresis": "\u1E27",
+ "/hdot": "\u1E23",
+ "/hdotaccent": "\u1E23",
+ "/hdotbelow": "\u1E25",
+ "/hdrsquare": "\u1F1A7",
+ "/he": "\u05D4",
+ "/he:hb": "\u05D4",
+ "/headphone": "\u1F3A7",
+ "/headstonegraveyard": "\u26FC",
+ "/hearNoEvilMonkey": "\u1F649",
+ "/heart": "\u2665",
+ "/heartArrow": "\u1F498",
+ "/heartDecoration": "\u1F49F",
+ "/heartRibbon": "\u1F49D",
+ "/heartTipOnTheLeft": "\u1F394",
+ "/heartblack": "\u2665",
+ "/heartsuitblack": "\u2665",
+ "/heartsuitwhite": "\u2661",
+ "/heartwhite": "\u2661",
+ "/heavyDollarSign": "\u1F4B2",
+ "/heavyLatinCross": "\u1F547",
+ "/heavydbldashhorz": "\u254D",
+ "/heavydbldashvert": "\u254F",
+ "/heavydn": "\u257B",
+ "/heavydnhorz": "\u2533",
+ "/heavydnleft": "\u2513",
+ "/heavydnright": "\u250F",
+ "/heavyhorz": "\u2501",
+ "/heavyleft": "\u2578",
+ "/heavyleftlightright": "\u257E",
+ "/heavyquaddashhorz": "\u2509",
+ "/heavyquaddashvert": "\u250B",
+ "/heavyright": "\u257A",
+ "/heavytrpldashhorz": "\u2505",
+ "/heavytrpldashvert": "\u2507",
+ "/heavyup": "\u2579",
+ "/heavyuphorz": "\u253B",
+ "/heavyupleft": "\u251B",
+ "/heavyuplightdn": "\u257F",
+ "/heavyupright": "\u2517",
+ "/heavyvert": "\u2503",
+ "/heavyverthorz": "\u254B",
+ "/heavyvertleft": "\u252B",
+ "/heavyvertright": "\u2523",
+ "/hecirclekatakana": "\u32EC",
+ "/hedagesh": "\uFB34",
+ "/hedageshhebrew": "\uFB34",
+ "/hedinterlacedpentagramleft": "\u26E6",
+ "/hedinterlacedpentagramright": "\u26E5",
+ "/heh": "\u0647",
+ "/heh.fina": "\uFEEA",
+ "/heh.init": "\uFEEB",
+ "/heh.init_alefmaksura.fina": "\uFC53",
+ "/heh.init_jeem.fina": "\uFC51",
+ "/heh.init_jeem.medi": "\uFCD7",
+ "/heh.init_meem.fina": "\uFC52",
+ "/heh.init_meem.medi": "\uFCD8",
+ "/heh.init_meem.medi_jeem.medi": "\uFD93",
+ "/heh.init_meem.medi_meem.medi": "\uFD94",
+ "/heh.init_superscriptalef.medi": "\uFCD9",
+ "/heh.init_yeh.fina": "\uFC54",
+ "/heh.isol": "\uFEE9",
+ "/heh.medi": "\uFEEC",
+ "/hehaltonearabic": "\u06C1",
+ "/heharabic": "\u0647",
+ "/hehdoachashmee": "\u06BE",
+ "/hehdoachashmee.fina": "\uFBAB",
+ "/hehdoachashmee.init": "\uFBAC",
+ "/hehdoachashmee.isol": "\uFBAA",
+ "/hehdoachashmee.medi": "\uFBAD",
+ "/hehebrew": "\u05D4",
+ "/hehfinalaltonearabic": "\uFBA7",
+ "/hehfinalalttwoarabic": "\uFEEA",
+ "/hehfinalarabic": "\uFEEA",
+ "/hehgoal": "\u06C1",
+ "/hehgoal.fina": "\uFBA7",
+ "/hehgoal.init": "\uFBA8",
+ "/hehgoal.isol": "\uFBA6",
+ "/hehgoal.medi": "\uFBA9",
+ "/hehgoalhamza": "\u06C2",
+ "/hehhamzaabovefinalarabic": "\uFBA5",
+ "/hehhamzaaboveisolatedarabic": "\uFBA4",
+ "/hehinitialaltonearabic": "\uFBA8",
+ "/hehinitialarabic": "\uFEEB",
+ "/hehinvertedV": "\u06FF",
+ "/hehiragana": "\u3078",
+ "/hehmedialaltonearabic": "\uFBA9",
+ "/hehmedialarabic": "\uFEEC",
+ "/hehyeh": "\u06C0",
+ "/hehyeh.fina": "\uFBA5",
+ "/hehyeh.isol": "\uFBA4",
+ "/heiseierasquare": "\u337B",
+ "/hekatakana": "\u30D8",
+ "/hekatakanahalfwidth": "\uFF8D",
+ "/hekutaarusquare": "\u3336",
+ "/helicopter": "\u1F681",
+ "/helm": "\u2388",
+ "/helmetcrosswhite": "\u26D1",
+ "/heng": "\uA727",
+ "/henghook": "\u0267",
+ "/herb": "\u1F33F",
+ "/hermitianconjugatematrix": "\u22B9",
+ "/herutusquare": "\u3339",
+ "/het": "\u05D7",
+ "/het:hb": "\u05D7",
+ "/heta": "\u0371",
+ "/hethebrew": "\u05D7",
+ "/hewide:hb": "\uFB23",
+ "/hewithmapiq:hb": "\uFB34",
+ "/hfishhookturned": "\u02AE",
+ "/hhalf": "\u2C76",
+ "/hhook": "\u0266",
+ "/hhooksuperior": "\u02B1",
+ "/hhooksupmod": "\u02B1",
+ "/hi-ressquare": "\u1F1A8",
+ "/hibiscus": "\u1F33A",
+ "/hicirclekatakana": "\u32EA",
+ "/hieuhacirclekorean": "\u327B",
+ "/hieuhaparenkorean": "\u321B",
+ "/hieuhcirclekorean": "\u326D",
+ "/hieuhkorean": "\u314E",
+ "/hieuhparenkorean": "\u320D",
+ "/high-heeledShoe": "\u1F460",
+ "/highBrightness": "\u1F506",
+ "/highSpeedTrain": "\u1F684",
+ "/highSpeedTrainWithBulletNose": "\u1F685",
+ "/highhamza": "\u0674",
+ "/highideographiccircled": "\u32A4",
+ "/highvoltage": "\u26A1",
+ "/hihiragana": "\u3072",
+ "/hikatakana": "\u30D2",
+ "/hikatakanahalfwidth": "\uFF8B",
+ "/hira:a": "\u3042",
+ "/hira:asmall": "\u3041",
+ "/hira:ba": "\u3070",
+ "/hira:be": "\u3079",
+ "/hira:bi": "\u3073",
+ "/hira:bo": "\u307C",
+ "/hira:bu": "\u3076",
+ "/hira:da": "\u3060",
+ "/hira:de": "\u3067",
+ "/hira:di": "\u3062",
+ "/hira:digraphyori": "\u309F",
+ "/hira:do": "\u3069",
+ "/hira:du": "\u3065",
+ "/hira:e": "\u3048",
+ "/hira:esmall": "\u3047",
+ "/hira:ga": "\u304C",
+ "/hira:ge": "\u3052",
+ "/hira:gi": "\u304E",
+ "/hira:go": "\u3054",
+ "/hira:gu": "\u3050",
+ "/hira:ha": "\u306F",
+ "/hira:he": "\u3078",
+ "/hira:hi": "\u3072",
+ "/hira:ho": "\u307B",
+ "/hira:hu": "\u3075",
+ "/hira:i": "\u3044",
+ "/hira:ismall": "\u3043",
+ "/hira:iterationhiragana": "\u309D",
+ "/hira:ka": "\u304B",
+ "/hira:kasmall": "\u3095",
+ "/hira:ke": "\u3051",
+ "/hira:kesmall": "\u3096",
+ "/hira:ki": "\u304D",
+ "/hira:ko": "\u3053",
+ "/hira:ku": "\u304F",
+ "/hira:ma": "\u307E",
+ "/hira:me": "\u3081",
+ "/hira:mi": "\u307F",
+ "/hira:mo": "\u3082",
+ "/hira:mu": "\u3080",
+ "/hira:n": "\u3093",
+ "/hira:na": "\u306A",
+ "/hira:ne": "\u306D",
+ "/hira:ni": "\u306B",
+ "/hira:no": "\u306E",
+ "/hira:nu": "\u306C",
+ "/hira:o": "\u304A",
+ "/hira:osmall": "\u3049",
+ "/hira:pa": "\u3071",
+ "/hira:pe": "\u307A",
+ "/hira:pi": "\u3074",
+ "/hira:po": "\u307D",
+ "/hira:pu": "\u3077",
+ "/hira:ra": "\u3089",
+ "/hira:re": "\u308C",
+ "/hira:ri": "\u308A",
+ "/hira:ro": "\u308D",
+ "/hira:ru": "\u308B",
+ "/hira:sa": "\u3055",
+ "/hira:se": "\u305B",
+ "/hira:semivoicedmarkkana": "\u309C",
+ "/hira:semivoicedmarkkanacmb": "\u309A",
+ "/hira:si": "\u3057",
+ "/hira:so": "\u305D",
+ "/hira:su": "\u3059",
+ "/hira:ta": "\u305F",
+ "/hira:te": "\u3066",
+ "/hira:ti": "\u3061",
+ "/hira:to": "\u3068",
+ "/hira:tu": "\u3064",
+ "/hira:tusmall": "\u3063",
+ "/hira:u": "\u3046",
+ "/hira:usmall": "\u3045",
+ "/hira:voicediterationhiragana": "\u309E",
+ "/hira:voicedmarkkana": "\u309B",
+ "/hira:voicedmarkkanacmb": "\u3099",
+ "/hira:vu": "\u3094",
+ "/hira:wa": "\u308F",
+ "/hira:wasmall": "\u308E",
+ "/hira:we": "\u3091",
+ "/hira:wi": "\u3090",
+ "/hira:wo": "\u3092",
+ "/hira:ya": "\u3084",
+ "/hira:yasmall": "\u3083",
+ "/hira:yo": "\u3088",
+ "/hira:yosmall": "\u3087",
+ "/hira:yu": "\u3086",
+ "/hira:yusmall": "\u3085",
+ "/hira:za": "\u3056",
+ "/hira:ze": "\u305C",
+ "/hira:zi": "\u3058",
+ "/hira:zo": "\u305E",
+ "/hira:zu": "\u305A",
+ "/hiriq": "\u05B4",
+ "/hiriq14": "\u05B4",
+ "/hiriq21": "\u05B4",
+ "/hiriq2d": "\u05B4",
+ "/hiriq:hb": "\u05B4",
+ "/hiriqhebrew": "\u05B4",
+ "/hiriqnarrowhebrew": "\u05B4",
+ "/hiriqquarterhebrew": "\u05B4",
+ "/hiriqwidehebrew": "\u05B4",
+ "/historicsite": "\u26EC",
+ "/hlinebelow": "\u1E96",
+ "/hmonospace": "\uFF48",
+ "/hoarmenian": "\u0570",
+ "/hocho": "\u1F52A",
+ "/hocirclekatakana": "\u32ED",
+ "/hohipthai": "\u0E2B",
+ "/hohiragana": "\u307B",
+ "/hokatakana": "\u30DB",
+ "/hokatakanahalfwidth": "\uFF8E",
+ "/holam": "\u05B9",
+ "/holam19": "\u05B9",
+ "/holam26": "\u05B9",
+ "/holam32": "\u05B9",
+ "/holam:hb": "\u05B9",
+ "/holamHaser:hb": "\u05BA",
+ "/holamhebrew": "\u05B9",
+ "/holamnarrowhebrew": "\u05B9",
+ "/holamquarterhebrew": "\u05B9",
+ "/holamwidehebrew": "\u05B9",
+ "/hole": "\u1F573",
+ "/homotic": "\u223B",
+ "/honeyPot": "\u1F36F",
+ "/honeybee": "\u1F41D",
+ "/honokhukthai": "\u0E2E",
+ "/honsquare": "\u333F",
+ "/hook": "\u2440",
+ "/hookabovecomb": "\u0309",
+ "/hookcmb": "\u0309",
+ "/hookpalatalizedbelowcmb": "\u0321",
+ "/hookretroflexbelowcmb": "\u0322",
+ "/hoonsquare": "\u3342",
+ "/hoorusquare": "\u3341",
+ "/horicoptic": "\u03E9",
+ "/horizontalTrafficLight": "\u1F6A5",
+ "/horizontalbar": "\u2015",
+ "/horizontalbarwhitearrowonpedestalup": "\u21EC",
+ "/horizontalmalestroke": "\u26A9",
+ "/horncmb": "\u031B",
+ "/horse": "\u1F40E",
+ "/horseFace": "\u1F434",
+ "/horseRacing": "\u1F3C7",
+ "/hospital": "\u1F3E5",
+ "/hotDog": "\u1F32D",
+ "/hotPepper": "\u1F336",
+ "/hotbeverage": "\u2615",
+ "/hotel": "\u1F3E8",
+ "/hotsprings": "\u2668",
+ "/hourglass": "\u231B",
+ "/hourglassflowings": "\u23F3",
+ "/house": "\u2302",
+ "/houseBuilding": "\u1F3E0",
+ "/houseBuildings": "\u1F3D8",
+ "/houseGarden": "\u1F3E1",
+ "/hpafullwidth": "\u3371",
+ "/hpalatalhook": "\uA795",
+ "/hparen": "\u24A3",
+ "/hparenthesized": "\u24A3",
+ "/hpfullwidth": "\u33CB",
+ "/hryvnia": "\u20B4",
+ "/hsuperior": "\u02B0",
+ "/hsupmod": "\u02B0",
+ "/hturned": "\u0265",
+ "/htypeopencircuit": "\u238F",
+ "/huaraddosquare": "\u3332",
+ "/hucirclekatakana": "\u32EB",
+ "/huhiragana": "\u3075",
+ "/huiitosquare": "\u3333",
+ "/hukatakana": "\u30D5",
+ "/hukatakanahalfwidth": "\uFF8C",
+ "/hundredPoints": "\u1F4AF",
+ "/hundredthousandscmbcyr": "\u0488",
+ "/hungarumlaut": "\u02DD",
+ "/hungarumlautcmb": "\u030B",
+ "/huransquare": "\u3335",
+ "/hushedFace": "\u1F62F",
+ "/hv": "\u0195",
+ "/hwd:a": "\uFFC2",
+ "/hwd:ae": "\uFFC3",
+ "/hwd:blacksquare": "\uFFED",
+ "/hwd:chieuch": "\uFFBA",
+ "/hwd:cieuc": "\uFFB8",
+ "/hwd:downwardsarrow": "\uFFEC",
+ "/hwd:e": "\uFFC7",
+ "/hwd:eo": "\uFFC6",
+ "/hwd:eu": "\uFFDA",
+ "/hwd:formslightvertical": "\uFFE8",
+ "/hwd:hangulfiller": "\uFFA0",
+ "/hwd:hieuh": "\uFFBE",
+ "/hwd:i": "\uFFDC",
+ "/hwd:ideographiccomma": "\uFF64",
+ "/hwd:ideographicfullstop": "\uFF61",
+ "/hwd:ieung": "\uFFB7",
+ "/hwd:kata:a": "\uFF71",
+ "/hwd:kata:asmall": "\uFF67",
+ "/hwd:kata:e": "\uFF74",
+ "/hwd:kata:esmall": "\uFF6A",
+ "/hwd:kata:ha": "\uFF8A",
+ "/hwd:kata:he": "\uFF8D",
+ "/hwd:kata:hi": "\uFF8B",
+ "/hwd:kata:ho": "\uFF8E",
+ "/hwd:kata:hu": "\uFF8C",
+ "/hwd:kata:i": "\uFF72",
+ "/hwd:kata:ismall": "\uFF68",
+ "/hwd:kata:ka": "\uFF76",
+ "/hwd:kata:ke": "\uFF79",
+ "/hwd:kata:ki": "\uFF77",
+ "/hwd:kata:ko": "\uFF7A",
+ "/hwd:kata:ku": "\uFF78",
+ "/hwd:kata:ma": "\uFF8F",
+ "/hwd:kata:me": "\uFF92",
+ "/hwd:kata:mi": "\uFF90",
+ "/hwd:kata:middledot": "\uFF65",
+ "/hwd:kata:mo": "\uFF93",
+ "/hwd:kata:mu": "\uFF91",
+ "/hwd:kata:n": "\uFF9D",
+ "/hwd:kata:na": "\uFF85",
+ "/hwd:kata:ne": "\uFF88",
+ "/hwd:kata:ni": "\uFF86",
+ "/hwd:kata:no": "\uFF89",
+ "/hwd:kata:nu": "\uFF87",
+ "/hwd:kata:o": "\uFF75",
+ "/hwd:kata:osmall": "\uFF6B",
+ "/hwd:kata:prolongedkana": "\uFF70",
+ "/hwd:kata:ra": "\uFF97",
+ "/hwd:kata:re": "\uFF9A",
+ "/hwd:kata:ri": "\uFF98",
+ "/hwd:kata:ro": "\uFF9B",
+ "/hwd:kata:ru": "\uFF99",
+ "/hwd:kata:sa": "\uFF7B",
+ "/hwd:kata:se": "\uFF7E",
+ "/hwd:kata:semi-voiced": "\uFF9F",
+ "/hwd:kata:si": "\uFF7C",
+ "/hwd:kata:so": "\uFF7F",
+ "/hwd:kata:su": "\uFF7D",
+ "/hwd:kata:ta": "\uFF80",
+ "/hwd:kata:te": "\uFF83",
+ "/hwd:kata:ti": "\uFF81",
+ "/hwd:kata:to": "\uFF84",
+ "/hwd:kata:tu": "\uFF82",
+ "/hwd:kata:tusmall": "\uFF6F",
+ "/hwd:kata:u": "\uFF73",
+ "/hwd:kata:usmall": "\uFF69",
+ "/hwd:kata:voiced": "\uFF9E",
+ "/hwd:kata:wa": "\uFF9C",
+ "/hwd:kata:wo": "\uFF66",
+ "/hwd:kata:ya": "\uFF94",
+ "/hwd:kata:yasmall": "\uFF6C",
+ "/hwd:kata:yo": "\uFF96",
+ "/hwd:kata:yosmall": "\uFF6E",
+ "/hwd:kata:yu": "\uFF95",
+ "/hwd:kata:yusmall": "\uFF6D",
+ "/hwd:khieukh": "\uFFBB",
+ "/hwd:kiyeok": "\uFFA1",
+ "/hwd:kiyeoksios": "\uFFA3",
+ "/hwd:leftcornerbracket": "\uFF62",
+ "/hwd:leftwardsarrow": "\uFFE9",
+ "/hwd:mieum": "\uFFB1",
+ "/hwd:nieun": "\uFFA4",
+ "/hwd:nieuncieuc": "\uFFA5",
+ "/hwd:nieunhieuh": "\uFFA6",
+ "/hwd:o": "\uFFCC",
+ "/hwd:oe": "\uFFCF",
+ "/hwd:phieuph": "\uFFBD",
+ "/hwd:pieup": "\uFFB2",
+ "/hwd:pieupsios": "\uFFB4",
+ "/hwd:rieul": "\uFFA9",
+ "/hwd:rieulhieuh": "\uFFB0",
+ "/hwd:rieulkiyeok": "\uFFAA",
+ "/hwd:rieulmieum": "\uFFAB",
+ "/hwd:rieulphieuph": "\uFFAF",
+ "/hwd:rieulpieup": "\uFFAC",
+ "/hwd:rieulsios": "\uFFAD",
+ "/hwd:rieulthieuth": "\uFFAE",
+ "/hwd:rightcornerbracket": "\uFF63",
+ "/hwd:rightwardsarrow": "\uFFEB",
+ "/hwd:sios": "\uFFB5",
+ "/hwd:ssangcieuc": "\uFFB9",
+ "/hwd:ssangkiyeok": "\uFFA2",
+ "/hwd:ssangpieup": "\uFFB3",
+ "/hwd:ssangsios": "\uFFB6",
+ "/hwd:ssangtikeut": "\uFFA8",
+ "/hwd:thieuth": "\uFFBC",
+ "/hwd:tikeut": "\uFFA7",
+ "/hwd:u": "\uFFD3",
+ "/hwd:upwardsarrow": "\uFFEA",
+ "/hwd:wa": "\uFFCD",
+ "/hwd:wae": "\uFFCE",
+ "/hwd:we": "\uFFD5",
+ "/hwd:weo": "\uFFD4",
+ "/hwd:whitecircle": "\uFFEE",
+ "/hwd:wi": "\uFFD6",
+ "/hwd:ya": "\uFFC4",
+ "/hwd:yae": "\uFFC5",
+ "/hwd:ye": "\uFFCB",
+ "/hwd:yeo": "\uFFCA",
+ "/hwd:yi": "\uFFDB",
+ "/hwd:yo": "\uFFD2",
+ "/hwd:yu": "\uFFD7",
+ "/hyphen": "\u002D",
+ "/hyphenationpoint": "\u2027",
+ "/hyphenbullet": "\u2043",
+ "/hyphendbl": "\u2E40",
+ "/hyphendbloblique": "\u2E17",
+ "/hyphendieresis": "\u2E1A",
+ "/hypheninferior": "\uF6E5",
+ "/hyphenminus": "\u002D",
+ "/hyphenmonospace": "\uFF0D",
+ "/hyphensmall": "\uFE63",
+ "/hyphensoft": "\u00AD",
+ "/hyphensuperior": "\uF6E6",
+ "/hyphentwo": "\u2010",
+ "/hypodiastole": "\u2E12",
+ "/hysteresis": "\u238E",
+ "/hzfullwidth": "\u3390",
+ "/i": "\u0069",
+ "/i.superior": "\u2071",
+ "/iacute": "\u00ED",
+ "/iacyrillic": "\u044F",
+ "/iaepigraphic": "\uA7FE",
+ "/ibengali": "\u0987",
+ "/ibopomofo": "\u3127",
+ "/ibreve": "\u012D",
+ "/icaron": "\u01D0",
+ "/iceCream": "\u1F368",
+ "/iceHockeyStickAndPuck": "\u1F3D2",
+ "/iceskate": "\u26F8",
+ "/icircle": "\u24D8",
+ "/icirclekatakana": "\u32D1",
+ "/icircumflex": "\u00EE",
+ "/icyr": "\u0438",
+ "/icyrillic": "\u0456",
+ "/idblgrave": "\u0209",
+ "/idblstruckitalic": "\u2148",
+ "/ideographearthcircle": "\u328F",
+ "/ideographfirecircle": "\u328B",
+ "/ideographicallianceparen": "\u323F",
+ "/ideographiccallparen": "\u323A",
+ "/ideographiccentrecircle": "\u32A5",
+ "/ideographicclose": "\u3006",
+ "/ideographiccomma": "\u3001",
+ "/ideographiccommaleft": "\uFF64",
+ "/ideographiccongratulationparen": "\u3237",
+ "/ideographiccorrectcircle": "\u32A3",
+ "/ideographicdepartingtonemark": "\u302C",
+ "/ideographicearthparen": "\u322F",
+ "/ideographicenteringtonemark": "\u302D",
+ "/ideographicenterpriseparen": "\u323D",
+ "/ideographicexcellentcircle": "\u329D",
+ "/ideographicfestivalparen": "\u3240",
+ "/ideographicfinancialcircle": "\u3296",
+ "/ideographicfinancialparen": "\u3236",
+ "/ideographicfireparen": "\u322B",
+ "/ideographichalffillspace": "\u303F",
+ "/ideographichaveparen": "\u3232",
+ "/ideographichighcircle": "\u32A4",
+ "/ideographiciterationmark": "\u3005",
+ "/ideographiclaborcircle": "\u3298",
+ "/ideographiclaborparen": "\u3238",
+ "/ideographicleftcircle": "\u32A7",
+ "/ideographicleveltonemark": "\u302A",
+ "/ideographiclowcircle": "\u32A6",
+ "/ideographicmedicinecircle": "\u32A9",
+ "/ideographicmetalparen": "\u322E",
+ "/ideographicmoonparen": "\u322A",
+ "/ideographicnameparen": "\u3234",
+ "/ideographicperiod": "\u3002",
+ "/ideographicprintcircle": "\u329E",
+ "/ideographicreachparen": "\u3243",
+ "/ideographicrepresentparen": "\u3239",
+ "/ideographicresourceparen": "\u323E",
+ "/ideographicrightcircle": "\u32A8",
+ "/ideographicrisingtonemark": "\u302B",
+ "/ideographicsecretcircle": "\u3299",
+ "/ideographicselfparen": "\u3242",
+ "/ideographicsocietyparen": "\u3233",
+ "/ideographicspace": "\u3000",
+ "/ideographicspecialparen": "\u3235",
+ "/ideographicstockparen": "\u3231",
+ "/ideographicstudyparen": "\u323B",
+ "/ideographicsunparen": "\u3230",
+ "/ideographicsuperviseparen": "\u323C",
+ "/ideographictelegraphlinefeedseparatorsymbol": "\u3037",
+ "/ideographictelegraphsymbolforhoureight": "\u3360",
+ "/ideographictelegraphsymbolforhoureighteen": "\u336A",
+ "/ideographictelegraphsymbolforhoureleven": "\u3363",
+ "/ideographictelegraphsymbolforhourfifteen": "\u3367",
+ "/ideographictelegraphsymbolforhourfive": "\u335D",
+ "/ideographictelegraphsymbolforhourfour": "\u335C",
+ "/ideographictelegraphsymbolforhourfourteen": "\u3366",
+ "/ideographictelegraphsymbolforhournine": "\u3361",
+ "/ideographictelegraphsymbolforhournineteen": "\u336B",
+ "/ideographictelegraphsymbolforhourone": "\u3359",
+ "/ideographictelegraphsymbolforhourseven": "\u335F",
+ "/ideographictelegraphsymbolforhourseventeen": "\u3369",
+ "/ideographictelegraphsymbolforhoursix": "\u335E",
+ "/ideographictelegraphsymbolforhoursixteen": "\u3368",
+ "/ideographictelegraphsymbolforhourten": "\u3362",
+ "/ideographictelegraphsymbolforhourthirteen": "\u3365",
+ "/ideographictelegraphsymbolforhourthree": "\u335B",
+ "/ideographictelegraphsymbolforhourtwelve": "\u3364",
+ "/ideographictelegraphsymbolforhourtwenty": "\u336C",
+ "/ideographictelegraphsymbolforhourtwentyfour": "\u3370",
+ "/ideographictelegraphsymbolforhourtwentyone": "\u336D",
+ "/ideographictelegraphsymbolforhourtwentythree": "\u336F",
+ "/ideographictelegraphsymbolforhourtwentytwo": "\u336E",
+ "/ideographictelegraphsymbolforhourtwo": "\u335A",
+ "/ideographictelegraphsymbolforhourzero": "\u3358",
+ "/ideographicvariationindicator": "\u303E",
+ "/ideographicwaterparen": "\u322C",
+ "/ideographicwoodparen": "\u322D",
+ "/ideographiczero": "\u3007",
+ "/ideographmetalcircle": "\u328E",
+ "/ideographmooncircle": "\u328A",
+ "/ideographnamecircle": "\u3294",
+ "/ideographsuncircle": "\u3290",
+ "/ideographwatercircle": "\u328C",
+ "/ideographwoodcircle": "\u328D",
+ "/ideva": "\u0907",
+ "/idieresis": "\u00EF",
+ "/idieresisacute": "\u1E2F",
+ "/idieresiscyr": "\u04E5",
+ "/idieresiscyrillic": "\u04E5",
+ "/idotbelow": "\u1ECB",
+ "/idsquare": "\u1F194",
+ "/iebrevecyr": "\u04D7",
+ "/iebrevecyrillic": "\u04D7",
+ "/iecyr": "\u0435",
+ "/iecyrillic": "\u0435",
+ "/iegravecyr": "\u0450",
+ "/iepigraphicsideways": "\uA7F7",
+ "/ieungacirclekorean": "\u3275",
+ "/ieungaparenkorean": "\u3215",
+ "/ieungcirclekorean": "\u3267",
+ "/ieungkorean": "\u3147",
+ "/ieungparenkorean": "\u3207",
+ "/ieungucirclekorean": "\u327E",
+ "/igrave": "\u00EC",
+ "/igravecyr": "\u045D",
+ "/igravedbl": "\u0209",
+ "/igujarati": "\u0A87",
+ "/igurmukhi": "\u0A07",
+ "/ihiragana": "\u3044",
+ "/ihoi": "\u1EC9",
+ "/ihookabove": "\u1EC9",
+ "/iibengali": "\u0988",
+ "/iicyrillic": "\u0438",
+ "/iideva": "\u0908",
+ "/iigujarati": "\u0A88",
+ "/iigurmukhi": "\u0A08",
+ "/iimatragurmukhi": "\u0A40",
+ "/iinvertedbreve": "\u020B",
+ "/iishortcyrillic": "\u0439",
+ "/iivowelsignbengali": "\u09C0",
+ "/iivowelsigndeva": "\u0940",
+ "/iivowelsigngujarati": "\u0AC0",
+ "/ij": "\u0133",
+ "/ikatakana": "\u30A4",
+ "/ikatakanahalfwidth": "\uFF72",
+ "/ikawi": "\uA985",
+ "/ikorean": "\u3163",
+ "/ilde": "\u02DC",
+ "/iluy:hb": "\u05AC",
+ "/iluyhebrew": "\u05AC",
+ "/imacron": "\u012B",
+ "/imacroncyr": "\u04E3",
+ "/imacroncyrillic": "\u04E3",
+ "/image": "\u22B7",
+ "/imageorapproximatelyequal": "\u2253",
+ "/imatragurmukhi": "\u0A3F",
+ "/imonospace": "\uFF49",
+ "/imp": "\u1F47F",
+ "/inboxTray": "\u1F4E5",
+ "/incomingEnvelope": "\u1F4E8",
+ "/increaseFontSize": "\u1F5DA",
+ "/increment": "\u2206",
+ "/indianrupee": "\u20B9",
+ "/infinity": "\u221E",
+ "/information": "\u2139",
+ "/infullwidth": "\u33CC",
+ "/inhibitarabicformshaping": "\u206C",
+ "/inhibitsymmetricswapping": "\u206A",
+ "/iniarmenian": "\u056B",
+ "/iningusquare": "\u3304",
+ "/inmationDeskPerson": "\u1F481",
+ "/inputLatinCapitalLetters": "\u1F520",
+ "/inputLatinLetters": "\u1F524",
+ "/inputLatinSmallLetters": "\u1F521",
+ "/inputNumbers": "\u1F522",
+ "/inputS": "\u1F523",
+ "/insertion": "\u2380",
+ "/integral": "\u222B",
+ "/integralbottom": "\u2321",
+ "/integralbt": "\u2321",
+ "/integralclockwise": "\u2231",
+ "/integralcontour": "\u222E",
+ "/integralcontouranticlockwise": "\u2233",
+ "/integralcontourclockwise": "\u2232",
+ "/integraldbl": "\u222C",
+ "/integralex": "\uF8F5",
+ "/integralextension": "\u23AE",
+ "/integralsurface": "\u222F",
+ "/integraltop": "\u2320",
+ "/integraltp": "\u2320",
+ "/integraltpl": "\u222D",
+ "/integralvolume": "\u2230",
+ "/intercalate": "\u22BA",
+ "/interlinearanchor": "\uFFF9",
+ "/interlinearseparator": "\uFFFA",
+ "/interlinearterminator": "\uFFFB",
+ "/interlockedfemalemale": "\u26A4",
+ "/interrobang": "\u203D",
+ "/interrobanginverted": "\u2E18",
+ "/intersection": "\u2229",
+ "/intersectionarray": "\u22C2",
+ "/intersectiondbl": "\u22D2",
+ "/intisquare": "\u3305",
+ "/invbullet": "\u25D8",
+ "/invcircle": "\u25D9",
+ "/inverteddamma": "\u0657",
+ "/invertedfork": "\u2443",
+ "/invertedpentagram": "\u26E7",
+ "/invertedundertie": "\u2054",
+ "/invisibleplus": "\u2064",
+ "/invisibleseparator": "\u2063",
+ "/invisibletimes": "\u2062",
+ "/invsmileface": "\u263B",
+ "/iocyr": "\u0451",
+ "/iocyrillic": "\u0451",
+ "/iogonek": "\u012F",
+ "/iota": "\u03B9",
+ "/iotaacute": "\u1F77",
+ "/iotaadscript": "\u1FBE",
+ "/iotaasper": "\u1F31",
+ "/iotaasperacute": "\u1F35",
+ "/iotaaspergrave": "\u1F33",
+ "/iotaaspertilde": "\u1F37",
+ "/iotabreve": "\u1FD0",
+ "/iotadieresis": "\u03CA",
+ "/iotadieresisacute": "\u1FD3",
+ "/iotadieresisgrave": "\u1FD2",
+ "/iotadieresistilde": "\u1FD7",
+ "/iotadieresistonos": "\u0390",
+ "/iotafunc": "\u2373",
+ "/iotagrave": "\u1F76",
+ "/iotalatin": "\u0269",
+ "/iotalenis": "\u1F30",
+ "/iotalenisacute": "\u1F34",
+ "/iotalenisgrave": "\u1F32",
+ "/iotalenistilde": "\u1F36",
+ "/iotasub": "\u037A",
+ "/iotatilde": "\u1FD6",
+ "/iotatonos": "\u03AF",
+ "/iotaturned": "\u2129",
+ "/iotaunderlinefunc": "\u2378",
+ "/iotawithmacron": "\u1FD1",
+ "/ipa:Ismall": "\u026A",
+ "/ipa:alpha": "\u0251",
+ "/ipa:ereversed": "\u0258",
+ "/ipa:esh": "\u0283",
+ "/ipa:gamma": "\u0263",
+ "/ipa:glottalstop": "\u0294",
+ "/ipa:gscript": "\u0261",
+ "/ipa:iota": "\u0269",
+ "/ipa:phi": "\u0278",
+ "/ipa:rtail": "\u027D",
+ "/ipa:schwa": "\u0259",
+ "/ipa:upsilon": "\u028A",
+ "/iparen": "\u24A4",
+ "/iparenthesized": "\u24A4",
+ "/irigurmukhi": "\u0A72",
+ "/is": "\uA76D",
+ "/isen-isenpada": "\uA9DF",
+ "/ishortcyr": "\u0439",
+ "/ishortsharptailcyr": "\u048B",
+ "/ismallhiragana": "\u3043",
+ "/ismallkatakana": "\u30A3",
+ "/ismallkatakanahalfwidth": "\uFF68",
+ "/issharbengali": "\u09FA",
+ "/istroke": "\u0268",
+ "/isuperior": "\uF6ED",
+ "/itemideographiccircled": "\u32A0",
+ "/iterationhiragana": "\u309D",
+ "/iterationkatakana": "\u30FD",
+ "/itilde": "\u0129",
+ "/itildebelow": "\u1E2D",
+ "/iubopomofo": "\u3129",
+ "/iucyrillic": "\u044E",
+ "/iufullwidth": "\u337A",
+ "/iukrcyr": "\u0456",
+ "/ivowelsignbengali": "\u09BF",
+ "/ivowelsigndeva": "\u093F",
+ "/ivowelsigngujarati": "\u0ABF",
+ "/izakayaLantern": "\u1F3EE",
+ "/izhitsacyr": "\u0475",
+ "/izhitsacyrillic": "\u0475",
+ "/izhitsadblgravecyrillic": "\u0477",
+ "/izhitsagravedblcyr": "\u0477",
+ "/j": "\u006A",
+ "/j.inferior": "\u2C7C",
+ "/jaarmenian": "\u0571",
+ "/jabengali": "\u099C",
+ "/jackOLantern": "\u1F383",
+ "/jadeva": "\u091C",
+ "/jagujarati": "\u0A9C",
+ "/jagurmukhi": "\u0A1C",
+ "/jamahaprana": "\uA999",
+ "/januarytelegraph": "\u32C0",
+ "/japaneseBeginner": "\u1F530",
+ "/japaneseCastle": "\u1F3EF",
+ "/japaneseDolls": "\u1F38E",
+ "/japaneseGoblin": "\u1F47A",
+ "/japaneseOgre": "\u1F479",
+ "/japanesePostOffice": "\u1F3E3",
+ "/japanesebank": "\u26FB",
+ "/java:a": "\uA984",
+ "/java:ai": "\uA98D",
+ "/java:ba": "\uA9A7",
+ "/java:ca": "\uA995",
+ "/java:da": "\uA9A2",
+ "/java:dda": "\uA99D",
+ "/java:e": "\uA98C",
+ "/java:eight": "\uA9D8",
+ "/java:five": "\uA9D5",
+ "/java:four": "\uA9D4",
+ "/java:ga": "\uA992",
+ "/java:ha": "\uA9B2",
+ "/java:i": "\uA986",
+ "/java:ii": "\uA987",
+ "/java:ja": "\uA997",
+ "/java:ka": "\uA98F",
+ "/java:la": "\uA9AD",
+ "/java:ma": "\uA9A9",
+ "/java:na": "\uA9A4",
+ "/java:nga": "\uA994",
+ "/java:nine": "\uA9D9",
+ "/java:nya": "\uA99A",
+ "/java:o": "\uA98E",
+ "/java:one": "\uA9D1",
+ "/java:pa": "\uA9A5",
+ "/java:ra": "\uA9AB",
+ "/java:sa": "\uA9B1",
+ "/java:seven": "\uA9D7",
+ "/java:six": "\uA9D6",
+ "/java:ta": "\uA9A0",
+ "/java:three": "\uA9D3",
+ "/java:tta": "\uA99B",
+ "/java:two": "\uA9D2",
+ "/java:u": "\uA988",
+ "/java:wa": "\uA9AE",
+ "/java:ya": "\uA9AA",
+ "/java:zero": "\uA9D0",
+ "/jbopomofo": "\u3110",
+ "/jcaron": "\u01F0",
+ "/jcircle": "\u24D9",
+ "/jcircumflex": "\u0135",
+ "/jcrossedtail": "\u029D",
+ "/jdblstruckitalic": "\u2149",
+ "/jdotlessstroke": "\u025F",
+ "/jeans": "\u1F456",
+ "/jecyr": "\u0458",
+ "/jecyrillic": "\u0458",
+ "/jeem": "\u062C",
+ "/jeem.fina": "\uFE9E",
+ "/jeem.init": "\uFE9F",
+ "/jeem.init_alefmaksura.fina": "\uFD01",
+ "/jeem.init_hah.fina": "\uFC15",
+ "/jeem.init_hah.medi": "\uFCA7",
+ "/jeem.init_meem.fina": "\uFC16",
+ "/jeem.init_meem.medi": "\uFCA8",
+ "/jeem.init_meem.medi_hah.medi": "\uFD59",
+ "/jeem.init_yeh.fina": "\uFD02",
+ "/jeem.isol": "\uFE9D",
+ "/jeem.medi": "\uFEA0",
+ "/jeem.medi_alefmaksura.fina": "\uFD1D",
+ "/jeem.medi_hah.medi_alefmaksura.fina": "\uFDA6",
+ "/jeem.medi_hah.medi_yeh.fina": "\uFDBE",
+ "/jeem.medi_meem.medi_alefmaksura.fina": "\uFDA7",
+ "/jeem.medi_meem.medi_hah.fina": "\uFD58",
+ "/jeem.medi_meem.medi_yeh.fina": "\uFDA5",
+ "/jeem.medi_yeh.fina": "\uFD1E",
+ "/jeemabove": "\u06DA",
+ "/jeemarabic": "\u062C",
+ "/jeemfinalarabic": "\uFE9E",
+ "/jeeminitialarabic": "\uFE9F",
+ "/jeemmedialarabic": "\uFEA0",
+ "/jeh": "\u0698",
+ "/jeh.fina": "\uFB8B",
+ "/jeh.isol": "\uFB8A",
+ "/jeharabic": "\u0698",
+ "/jehfinalarabic": "\uFB8B",
+ "/jhabengali": "\u099D",
+ "/jhadeva": "\u091D",
+ "/jhagujarati": "\u0A9D",
+ "/jhagurmukhi": "\u0A1D",
+ "/jheharmenian": "\u057B",
+ "/jis": "\u3004",
+ "/jiterup": "\u2643",
+ "/jmonospace": "\uFF4A",
+ "/jotdiaeresisfunc": "\u2364",
+ "/jotunderlinefunc": "\u235B",
+ "/joystick": "\u1F579",
+ "/jparen": "\u24A5",
+ "/jparenthesized": "\u24A5",
+ "/jstroke": "\u0249",
+ "/jsuperior": "\u02B2",
+ "/jsupmod": "\u02B2",
+ "/jueuicircle": "\u327D",
+ "/julytelegraph": "\u32C6",
+ "/junetelegraph": "\u32C5",
+ "/juno": "\u26B5",
+ "/k": "\u006B",
+ "/k.inferior": "\u2096",
+ "/kaaba": "\u1F54B",
+ "/kaaleutcyr": "\u051F",
+ "/kabashkcyr": "\u04A1",
+ "/kabashkircyrillic": "\u04A1",
+ "/kabengali": "\u0995",
+ "/kacirclekatakana": "\u32D5",
+ "/kacute": "\u1E31",
+ "/kacyr": "\u043A",
+ "/kacyrillic": "\u043A",
+ "/kadescendercyrillic": "\u049B",
+ "/kadeva": "\u0915",
+ "/kaf": "\u05DB",
+ "/kaf.fina": "\uFEDA",
+ "/kaf.init": "\uFEDB",
+ "/kaf.init_alef.fina": "\uFC37",
+ "/kaf.init_alefmaksura.fina": "\uFC3D",
+ "/kaf.init_hah.fina": "\uFC39",
+ "/kaf.init_hah.medi": "\uFCC5",
+ "/kaf.init_jeem.fina": "\uFC38",
+ "/kaf.init_jeem.medi": "\uFCC4",
+ "/kaf.init_khah.fina": "\uFC3A",
+ "/kaf.init_khah.medi": "\uFCC6",
+ "/kaf.init_lam.fina": "\uFC3B",
+ "/kaf.init_lam.medi": "\uFCC7",
+ "/kaf.init_meem.fina": "\uFC3C",
+ "/kaf.init_meem.medi": "\uFCC8",
+ "/kaf.init_meem.medi_meem.medi": "\uFDC3",
+ "/kaf.init_yeh.fina": "\uFC3E",
+ "/kaf.isol": "\uFED9",
+ "/kaf.medi": "\uFEDC",
+ "/kaf.medi_alef.fina": "\uFC80",
+ "/kaf.medi_alefmaksura.fina": "\uFC83",
+ "/kaf.medi_lam.fina": "\uFC81",
+ "/kaf.medi_lam.medi": "\uFCEB",
+ "/kaf.medi_meem.fina": "\uFC82",
+ "/kaf.medi_meem.medi": "\uFCEC",
+ "/kaf.medi_meem.medi_meem.fina": "\uFDBB",
+ "/kaf.medi_meem.medi_yeh.fina": "\uFDB7",
+ "/kaf.medi_yeh.fina": "\uFC84",
+ "/kaf:hb": "\u05DB",
+ "/kafTwoDotsAbove": "\u077F",
+ "/kafarabic": "\u0643",
+ "/kafdagesh": "\uFB3B",
+ "/kafdageshhebrew": "\uFB3B",
+ "/kafdotabove": "\u06AC",
+ "/kaffinalarabic": "\uFEDA",
+ "/kafhebrew": "\u05DB",
+ "/kafinitialarabic": "\uFEDB",
+ "/kafmedialarabic": "\uFEDC",
+ "/kafrafehebrew": "\uFB4D",
+ "/kafring": "\u06AB",
+ "/kafswash": "\u06AA",
+ "/kafthreedotsbelow": "\u06AE",
+ "/kafullwidth": "\u3384",
+ "/kafwide:hb": "\uFB24",
+ "/kafwithdagesh:hb": "\uFB3B",
+ "/kafwithrafe:hb": "\uFB4D",
+ "/kagujarati": "\u0A95",
+ "/kagurmukhi": "\u0A15",
+ "/kahiragana": "\u304B",
+ "/kahookcyr": "\u04C4",
+ "/kahookcyrillic": "\u04C4",
+ "/kairisquare": "\u330B",
+ "/kaisymbol": "\u03D7",
+ "/kakatakana": "\u30AB",
+ "/kakatakanahalfwidth": "\uFF76",
+ "/kamurda": "\uA991",
+ "/kappa": "\u03BA",
+ "/kappa.math": "\u03F0",
+ "/kappasymbolgreek": "\u03F0",
+ "/kapyeounmieumkorean": "\u3171",
+ "/kapyeounphieuphkorean": "\u3184",
+ "/kapyeounpieupkorean": "\u3178",
+ "/kapyeounssangpieupkorean": "\u3179",
+ "/karattosquare": "\u330C",
+ "/karoriisquare": "\u330D",
+ "/kasasak": "\uA990",
+ "/kashida": "\u0640",
+ "/kashidaFina": "\uFE73",
+ "/kashidaautoarabic": "\u0640",
+ "/kashidaautonosidebearingarabic": "\u0640",
+ "/kashmiriyeh": "\u0620",
+ "/kasmallkatakana": "\u30F5",
+ "/kasquare": "\u3384",
+ "/kasra": "\u0650",
+ "/kasraIsol": "\uFE7A",
+ "/kasraMedi": "\uFE7B",
+ "/kasraarabic": "\u0650",
+ "/kasrasmall": "\u061A",
+ "/kasratan": "\u064D",
+ "/kasratanIsol": "\uFE74",
+ "/kasratanarabic": "\u064D",
+ "/kastrokecyr": "\u049F",
+ "/kastrokecyrillic": "\u049F",
+ "/kata:a": "\u30A2",
+ "/kata:asmall": "\u30A1",
+ "/kata:ba": "\u30D0",
+ "/kata:be": "\u30D9",
+ "/kata:bi": "\u30D3",
+ "/kata:bo": "\u30DC",
+ "/kata:bu": "\u30D6",
+ "/kata:da": "\u30C0",
+ "/kata:de": "\u30C7",
+ "/kata:di": "\u30C2",
+ "/kata:digraphkoto": "\u30FF",
+ "/kata:do": "\u30C9",
+ "/kata:doublehyphenkana": "\u30A0",
+ "/kata:du": "\u30C5",
+ "/kata:e": "\u30A8",
+ "/kata:esmall": "\u30A7",
+ "/kata:ga": "\u30AC",
+ "/kata:ge": "\u30B2",
+ "/kata:gi": "\u30AE",
+ "/kata:go": "\u30B4",
+ "/kata:gu": "\u30B0",
+ "/kata:ha": "\u30CF",
+ "/kata:he": "\u30D8",
+ "/kata:hi": "\u30D2",
+ "/kata:ho": "\u30DB",
+ "/kata:hu": "\u30D5",
+ "/kata:i": "\u30A4",
+ "/kata:ismall": "\u30A3",
+ "/kata:iteration": "\u30FD",
+ "/kata:ka": "\u30AB",
+ "/kata:kasmall": "\u30F5",
+ "/kata:ke": "\u30B1",
+ "/kata:kesmall": "\u30F6",
+ "/kata:ki": "\u30AD",
+ "/kata:ko": "\u30B3",
+ "/kata:ku": "\u30AF",
+ "/kata:ma": "\u30DE",
+ "/kata:me": "\u30E1",
+ "/kata:mi": "\u30DF",
+ "/kata:middledot": "\u30FB",
+ "/kata:mo": "\u30E2",
+ "/kata:mu": "\u30E0",
+ "/kata:n": "\u30F3",
+ "/kata:na": "\u30CA",
+ "/kata:ne": "\u30CD",
+ "/kata:ni": "\u30CB",
+ "/kata:no": "\u30CE",
+ "/kata:nu": "\u30CC",
+ "/kata:o": "\u30AA",
+ "/kata:osmall": "\u30A9",
+ "/kata:pa": "\u30D1",
+ "/kata:pe": "\u30DA",
+ "/kata:pi": "\u30D4",
+ "/kata:po": "\u30DD",
+ "/kata:prolongedkana": "\u30FC",
+ "/kata:pu": "\u30D7",
+ "/kata:ra": "\u30E9",
+ "/kata:re": "\u30EC",
+ "/kata:ri": "\u30EA",
+ "/kata:ro": "\u30ED",
+ "/kata:ru": "\u30EB",
+ "/kata:sa": "\u30B5",
+ "/kata:se": "\u30BB",
+ "/kata:si": "\u30B7",
+ "/kata:so": "\u30BD",
+ "/kata:su": "\u30B9",
+ "/kata:ta": "\u30BF",
+ "/kata:te": "\u30C6",
+ "/kata:ti": "\u30C1",
+ "/kata:to": "\u30C8",
+ "/kata:tu": "\u30C4",
+ "/kata:tusmall": "\u30C3",
+ "/kata:u": "\u30A6",
+ "/kata:usmall": "\u30A5",
+ "/kata:va": "\u30F7",
+ "/kata:ve": "\u30F9",
+ "/kata:vi": "\u30F8",
+ "/kata:vo": "\u30FA",
+ "/kata:voicediteration": "\u30FE",
+ "/kata:vu": "\u30F4",
+ "/kata:wa": "\u30EF",
+ "/kata:wasmall": "\u30EE",
+ "/kata:we": "\u30F1",
+ "/kata:wi": "\u30F0",
+ "/kata:wo": "\u30F2",
+ "/kata:ya": "\u30E4",
+ "/kata:yasmall": "\u30E3",
+ "/kata:yo": "\u30E8",
+ "/kata:yosmall": "\u30E7",
+ "/kata:yu": "\u30E6",
+ "/kata:yusmall": "\u30E5",
+ "/kata:za": "\u30B6",
+ "/kata:ze": "\u30BC",
+ "/kata:zi": "\u30B8",
+ "/kata:zo": "\u30BE",
+ "/kata:zu": "\u30BA",
+ "/katahiraprolongmarkhalfwidth": "\uFF70",
+ "/katailcyr": "\u049B",
+ "/kaverticalstrokecyr": "\u049D",
+ "/kaverticalstrokecyrillic": "\u049D",
+ "/kavykainvertedlow": "\u2E45",
+ "/kavykalow": "\u2E47",
+ "/kavykawithdotlow": "\u2E48",
+ "/kavykawithkavykaaboveinvertedlow": "\u2E46",
+ "/kbfullwidth": "\u3385",
+ "/kbopomofo": "\u310E",
+ "/kcalfullwidth": "\u3389",
+ "/kcalsquare": "\u3389",
+ "/kcaron": "\u01E9",
+ "/kcedilla": "\u0137",
+ "/kcircle": "\u24DA",
+ "/kcommaaccent": "\u0137",
+ "/kdescender": "\u2C6A",
+ "/kdiagonalstroke": "\uA743",
+ "/kdotbelow": "\u1E33",
+ "/kecirclekatakana": "\u32D8",
+ "/keesusquare": "\u331C",
+ "/keharmenian": "\u0584",
+ "/keheh": "\u06A9",
+ "/keheh.fina": "\uFB8F",
+ "/keheh.init": "\uFB90",
+ "/keheh.isol": "\uFB8E",
+ "/keheh.medi": "\uFB91",
+ "/kehehDotAbove": "\u0762",
+ "/kehehThreeDotsAbove": "\u0763",
+ "/kehehThreeDotsUpBelow": "\u0764",
+ "/kehehthreedotsbelow": "\u063C",
+ "/kehehtwodotsabove": "\u063B",
+ "/kehiragana": "\u3051",
+ "/kekatakana": "\u30B1",
+ "/kekatakanahalfwidth": "\uFF79",
+ "/kelvin": "\u212A",
+ "/kenarmenian": "\u056F",
+ "/keretconsonant": "\uA9BD",
+ "/kesmallkatakana": "\u30F6",
+ "/key": "\u1F511",
+ "/keyboardAndMouse": "\u1F5A6",
+ "/keycapTen": "\u1F51F",
+ "/kgfullwidth": "\u338F",
+ "/kgreenlandic": "\u0138",
+ "/khabengali": "\u0996",
+ "/khacyrillic": "\u0445",
+ "/khadeva": "\u0916",
+ "/khagujarati": "\u0A96",
+ "/khagurmukhi": "\u0A16",
+ "/khah": "\u062E",
+ "/khah.fina": "\uFEA6",
+ "/khah.init": "\uFEA7",
+ "/khah.init_alefmaksura.fina": "\uFD03",
+ "/khah.init_hah.fina": "\uFC1A",
+ "/khah.init_jeem.fina": "\uFC19",
+ "/khah.init_jeem.medi": "\uFCAB",
+ "/khah.init_meem.fina": "\uFC1B",
+ "/khah.init_meem.medi": "\uFCAC",
+ "/khah.init_yeh.fina": "\uFD04",
+ "/khah.isol": "\uFEA5",
+ "/khah.medi": "\uFEA8",
+ "/khah.medi_alefmaksura.fina": "\uFD1F",
+ "/khah.medi_yeh.fina": "\uFD20",
+ "/khaharabic": "\u062E",
+ "/khahfinalarabic": "\uFEA6",
+ "/khahinitialarabic": "\uFEA7",
+ "/khahmedialarabic": "\uFEA8",
+ "/kheicoptic": "\u03E7",
+ "/khhadeva": "\u0959",
+ "/khhagurmukhi": "\u0A59",
+ "/khieukhacirclekorean": "\u3278",
+ "/khieukhaparenkorean": "\u3218",
+ "/khieukhcirclekorean": "\u326A",
+ "/khieukhkorean": "\u314B",
+ "/khieukhparenkorean": "\u320A",
+ "/khokhaithai": "\u0E02",
+ "/khokhonthai": "\u0E05",
+ "/khokhuatthai": "\u0E03",
+ "/khokhwaithai": "\u0E04",
+ "/khomutthai": "\u0E5B",
+ "/khook": "\u0199",
+ "/khorakhangthai": "\u0E06",
+ "/khzfullwidth": "\u3391",
+ "/khzsquare": "\u3391",
+ "/kicirclekatakana": "\u32D6",
+ "/kihiragana": "\u304D",
+ "/kikatakana": "\u30AD",
+ "/kikatakanahalfwidth": "\uFF77",
+ "/kimono": "\u1F458",
+ "/kindergartenideographiccircled": "\u3245",
+ "/kingblack": "\u265A",
+ "/kingwhite": "\u2654",
+ "/kip": "\u20AD",
+ "/kiroguramusquare": "\u3315",
+ "/kiromeetorusquare": "\u3316",
+ "/kirosquare": "\u3314",
+ "/kirowattosquare": "\u3317",
+ "/kiss": "\u1F48F",
+ "/kissMark": "\u1F48B",
+ "/kissingCatFaceWithClosedEyes": "\u1F63D",
+ "/kissingFace": "\u1F617",
+ "/kissingFaceWithClosedEyes": "\u1F61A",
+ "/kissingFaceWithSmilingEyes": "\u1F619",
+ "/kiyeokacirclekorean": "\u326E",
+ "/kiyeokaparenkorean": "\u320E",
+ "/kiyeokcirclekorean": "\u3260",
+ "/kiyeokkorean": "\u3131",
+ "/kiyeokparenkorean": "\u3200",
+ "/kiyeoksioskorean": "\u3133",
+ "/kjecyr": "\u045C",
+ "/kjecyrillic": "\u045C",
+ "/kkfullwidth": "\u33CD",
+ "/klfullwidth": "\u3398",
+ "/klinebelow": "\u1E35",
+ "/klsquare": "\u3398",
+ "/km2fullwidth": "\u33A2",
+ "/km3fullwidth": "\u33A6",
+ "/kmcapitalfullwidth": "\u33CE",
+ "/kmcubedsquare": "\u33A6",
+ "/kmfullwidth": "\u339E",
+ "/kmonospace": "\uFF4B",
+ "/kmsquaredsquare": "\u33A2",
+ "/knda:a": "\u0C85",
+ "/knda:aa": "\u0C86",
+ "/knda:aasign": "\u0CBE",
+ "/knda:ai": "\u0C90",
+ "/knda:ailength": "\u0CD6",
+ "/knda:aisign": "\u0CC8",
+ "/knda:anusvara": "\u0C82",
+ "/knda:au": "\u0C94",
+ "/knda:ausign": "\u0CCC",
+ "/knda:avagraha": "\u0CBD",
+ "/knda:ba": "\u0CAC",
+ "/knda:bha": "\u0CAD",
+ "/knda:ca": "\u0C9A",
+ "/knda:cha": "\u0C9B",
+ "/knda:da": "\u0CA6",
+ "/knda:dda": "\u0CA1",
+ "/knda:ddha": "\u0CA2",
+ "/knda:dha": "\u0CA7",
+ "/knda:e": "\u0C8E",
+ "/knda:ee": "\u0C8F",
+ "/knda:eesign": "\u0CC7",
+ "/knda:eight": "\u0CEE",
+ "/knda:esign": "\u0CC6",
+ "/knda:fa": "\u0CDE",
+ "/knda:five": "\u0CEB",
+ "/knda:four": "\u0CEA",
+ "/knda:ga": "\u0C97",
+ "/knda:gha": "\u0C98",
+ "/knda:ha": "\u0CB9",
+ "/knda:i": "\u0C87",
+ "/knda:ii": "\u0C88",
+ "/knda:iisign": "\u0CC0",
+ "/knda:isign": "\u0CBF",
+ "/knda:ja": "\u0C9C",
+ "/knda:jha": "\u0C9D",
+ "/knda:jihvamuliya": "\u0CF1",
+ "/knda:ka": "\u0C95",
+ "/knda:kha": "\u0C96",
+ "/knda:la": "\u0CB2",
+ "/knda:length": "\u0CD5",
+ "/knda:lla": "\u0CB3",
+ "/knda:llvocal": "\u0CE1",
+ "/knda:llvocalsign": "\u0CE3",
+ "/knda:lvocal": "\u0C8C",
+ "/knda:lvocalsign": "\u0CE2",
+ "/knda:ma": "\u0CAE",
+ "/knda:na": "\u0CA8",
+ "/knda:nga": "\u0C99",
+ "/knda:nine": "\u0CEF",
+ "/knda:nna": "\u0CA3",
+ "/knda:nukta": "\u0CBC",
+ "/knda:nya": "\u0C9E",
+ "/knda:o": "\u0C92",
+ "/knda:one": "\u0CE7",
+ "/knda:oo": "\u0C93",
+ "/knda:oosign": "\u0CCB",
+ "/knda:osign": "\u0CCA",
+ "/knda:pa": "\u0CAA",
+ "/knda:pha": "\u0CAB",
+ "/knda:ra": "\u0CB0",
+ "/knda:rra": "\u0CB1",
+ "/knda:rrvocal": "\u0CE0",
+ "/knda:rrvocalsign": "\u0CC4",
+ "/knda:rvocal": "\u0C8B",
+ "/knda:rvocalsign": "\u0CC3",
+ "/knda:sa": "\u0CB8",
+ "/knda:seven": "\u0CED",
+ "/knda:sha": "\u0CB6",
+ "/knda:signcandrabindu": "\u0C81",
+ "/knda:signspacingcandrabindu": "\u0C80",
+ "/knda:six": "\u0CEC",
+ "/knda:ssa": "\u0CB7",
+ "/knda:ta": "\u0CA4",
+ "/knda:tha": "\u0CA5",
+ "/knda:three": "\u0CE9",
+ "/knda:tta": "\u0C9F",
+ "/knda:ttha": "\u0CA0",
+ "/knda:two": "\u0CE8",
+ "/knda:u": "\u0C89",
+ "/knda:upadhmaniya": "\u0CF2",
+ "/knda:usign": "\u0CC1",
+ "/knda:uu": "\u0C8A",
+ "/knda:uusign": "\u0CC2",
+ "/knda:va": "\u0CB5",
+ "/knda:virama": "\u0CCD",
+ "/knda:visarga": "\u0C83",
+ "/knda:ya": "\u0CAF",
+ "/knda:zero": "\u0CE6",
+ "/knightblack": "\u265E",
+ "/knightwhite": "\u2658",
+ "/ko:a": "\u314F",
+ "/ko:ae": "\u3150",
+ "/ko:aejungseong": "\u1162",
+ "/ko:aeujungseong": "\u11A3",
+ "/ko:ajungseong": "\u1161",
+ "/ko:aojungseong": "\u1176",
+ "/ko:araea": "\u318D",
+ "/ko:araeae": "\u318E",
+ "/ko:araeaeojungseong": "\u119F",
+ "/ko:araeaijungseong": "\u11A1",
+ "/ko:araeajungseong": "\u119E",
+ "/ko:araeaujungseong": "\u11A0",
+ "/ko:aujungseong": "\u1177",
+ "/ko:ceongchieumchieuchchoseong": "\u1155",
+ "/ko:ceongchieumcieucchoseong": "\u1150",
+ "/ko:ceongchieumsioschoseong": "\u113E",
+ "/ko:ceongchieumssangcieucchoseong": "\u1151",
+ "/ko:ceongchieumssangsioschoseong": "\u113F",
+ "/ko:chieuch": "\u314A",
+ "/ko:chieuchchoseong": "\u110E",
+ "/ko:chieuchhieuhchoseong": "\u1153",
+ "/ko:chieuchjongseong": "\u11BE",
+ "/ko:chieuchkhieukhchoseong": "\u1152",
+ "/ko:chitueumchieuchchoseong": "\u1154",
+ "/ko:chitueumcieucchoseong": "\u114E",
+ "/ko:chitueumsioschoseong": "\u113C",
+ "/ko:chitueumssangcieucchoseong": "\u114F",
+ "/ko:chitueumssangsioschoseong": "\u113D",
+ "/ko:cieuc": "\u3148",
+ "/ko:cieucchoseong": "\u110C",
+ "/ko:cieucieungchoseong": "\u114D",
+ "/ko:cieucjongseong": "\u11BD",
+ "/ko:e": "\u3154",
+ "/ko:ejungseong": "\u1166",
+ "/ko:eo": "\u3153",
+ "/ko:eo_eujungseong": "\u117C",
+ "/ko:eojungseong": "\u1165",
+ "/ko:eoojungseong": "\u117A",
+ "/ko:eoujungseong": "\u117B",
+ "/ko:eu": "\u3161",
+ "/ko:eueujungseong": "\u1196",
+ "/ko:eujungseong": "\u1173",
+ "/ko:euujungseong": "\u1195",
+ "/ko:filler": "\u3164",
+ "/ko:fillerchoseong": "\u115F",
+ "/ko:fillerjungseong": "\u1160",
+ "/ko:hieuh": "\u314E",
+ "/ko:hieuhchoseong": "\u1112",
+ "/ko:hieuhjongseong": "\u11C2",
+ "/ko:hieuhmieumjongseong": "\u11F7",
+ "/ko:hieuhnieunjongseong": "\u11F5",
+ "/ko:hieuhpieupjongseong": "\u11F8",
+ "/ko:hieuhrieuljongseong": "\u11F6",
+ "/ko:i": "\u3163",
+ "/ko:iajungseong": "\u1198",
+ "/ko:iaraeajungseong": "\u119D",
+ "/ko:ieujungseong": "\u119C",
+ "/ko:ieung": "\u3147",
+ "/ko:ieungchieuchchoseong": "\u1149",
+ "/ko:ieungchoseong": "\u110B",
+ "/ko:ieungcieucchoseong": "\u1148",
+ "/ko:ieungjongseong": "\u11BC",
+ "/ko:ieungkhieukhjongseong": "\u11EF",
+ "/ko:ieungkiyeokchoseong": "\u1141",
+ "/ko:ieungkiyeokjongseong": "\u11EC",
+ "/ko:ieungmieumchoseong": "\u1143",
+ "/ko:ieungpansioschoseong": "\u1146",
+ "/ko:ieungphieuphchoseong": "\u114B",
+ "/ko:ieungpieupchoseong": "\u1144",
+ "/ko:ieungsioschoseong": "\u1145",
+ "/ko:ieungssangkiyeokjongseong": "\u11ED",
+ "/ko:ieungthieuthchoseong": "\u114A",
+ "/ko:ieungtikeutchoseong": "\u1142",
+ "/ko:ijungseong": "\u1175",
+ "/ko:iojungseong": "\u119A",
+ "/ko:iujungseong": "\u119B",
+ "/ko:iyajungseong": "\u1199",
+ "/ko:kapyeounmieum": "\u3171",
+ "/ko:kapyeounmieumchoseong": "\u111D",
+ "/ko:kapyeounmieumjongseong": "\u11E2",
+ "/ko:kapyeounphieuph": "\u3184",
+ "/ko:kapyeounphieuphchoseong": "\u1157",
+ "/ko:kapyeounphieuphjongseong": "\u11F4",
+ "/ko:kapyeounpieup": "\u3178",
+ "/ko:kapyeounpieupchoseong": "\u112B",
+ "/ko:kapyeounpieupjongseong": "\u11E6",
+ "/ko:kapyeounrieulchoseong": "\u111B",
+ "/ko:kapyeounssangpieup": "\u3179",
+ "/ko:kapyeounssangpieupchoseong": "\u112C",
+ "/ko:khieukh": "\u314B",
+ "/ko:khieukhchoseong": "\u110F",
+ "/ko:khieukhjongseong": "\u11BF",
+ "/ko:kiyeok": "\u3131",
+ "/ko:kiyeokchieuchjongseong": "\u11FC",
+ "/ko:kiyeokchoseong": "\u1100",
+ "/ko:kiyeokhieuhjongseong": "\u11FE",
+ "/ko:kiyeokjongseong": "\u11A8",
+ "/ko:kiyeokkhieukhjongseong": "\u11FD",
+ "/ko:kiyeoknieunjongseong": "\u11FA",
+ "/ko:kiyeokpieupjongseong": "\u11FB",
+ "/ko:kiyeokrieuljongseong": "\u11C3",
+ "/ko:kiyeoksios": "\u3133",
+ "/ko:kiyeoksiosjongseong": "\u11AA",
+ "/ko:kiyeoksioskiyeokjongseong": "\u11C4",
+ "/ko:kiyeoktikeutchoseong": "\u115A",
+ "/ko:mieum": "\u3141",
+ "/ko:mieumchieuchjongseong": "\u11E0",
+ "/ko:mieumchoseong": "\u1106",
+ "/ko:mieumhieuhjongseong": "\u11E1",
+ "/ko:mieumjongseong": "\u11B7",
+ "/ko:mieumkiyeokjongseong": "\u11DA",
+ "/ko:mieumpansios": "\u3170",
+ "/ko:mieumpansiosjongseong": "\u11DF",
+ "/ko:mieumpieup": "\u316E",
+ "/ko:mieumpieupchoseong": "\u111C",
+ "/ko:mieumpieupjongseong": "\u11DC",
+ "/ko:mieumrieuljongseong": "\u11DB",
+ "/ko:mieumsios": "\u316F",
+ "/ko:mieumsiosjongseong": "\u11DD",
+ "/ko:mieumssangsiosjongseong": "\u11DE",
+ "/ko:nieun": "\u3134",
+ "/ko:nieunchoseong": "\u1102",
+ "/ko:nieuncieuc": "\u3135",
+ "/ko:nieuncieucchoseong": "\u115C",
+ "/ko:nieuncieucjongseong": "\u11AC",
+ "/ko:nieunhieuh": "\u3136",
+ "/ko:nieunhieuhchoseong": "\u115D",
+ "/ko:nieunhieuhjongseong": "\u11AD",
+ "/ko:nieunjongseong": "\u11AB",
+ "/ko:nieunkiyeokchoseong": "\u1113",
+ "/ko:nieunkiyeokjongseong": "\u11C5",
+ "/ko:nieunpansios": "\u3168",
+ "/ko:nieunpansiosjongseong": "\u11C8",
+ "/ko:nieunpieupchoseong": "\u1116",
+ "/ko:nieunsios": "\u3167",
+ "/ko:nieunsioschoseong": "\u115B",
+ "/ko:nieunsiosjongseong": "\u11C7",
+ "/ko:nieunthieuthjongseong": "\u11C9",
+ "/ko:nieuntikeut": "\u3166",
+ "/ko:nieuntikeutchoseong": "\u1115",
+ "/ko:nieuntikeutjongseong": "\u11C6",
+ "/ko:o": "\u3157",
+ "/ko:o_ejungseong": "\u1180",
+ "/ko:o_eojungseong": "\u117F",
+ "/ko:oe": "\u315A",
+ "/ko:oejungseong": "\u116C",
+ "/ko:ojungseong": "\u1169",
+ "/ko:oojungseong": "\u1182",
+ "/ko:oujungseong": "\u1183",
+ "/ko:oyaejungseong": "\u11A7",
+ "/ko:oyajungseong": "\u11A6",
+ "/ko:oyejungseong": "\u1181",
+ "/ko:pansios": "\u317F",
+ "/ko:pansioschoseong": "\u1140",
+ "/ko:pansiosjongseong": "\u11EB",
+ "/ko:phieuph": "\u314D",
+ "/ko:phieuphchoseong": "\u1111",
+ "/ko:phieuphjongseong": "\u11C1",
+ "/ko:phieuphpieupchoseong": "\u1156",
+ "/ko:phieuphpieupjongseong": "\u11F3",
+ "/ko:pieup": "\u3142",
+ "/ko:pieupchieuchchoseong": "\u1128",
+ "/ko:pieupchoseong": "\u1107",
+ "/ko:pieupcieuc": "\u3176",
+ "/ko:pieupcieucchoseong": "\u1127",
+ "/ko:pieuphieuhjongseong": "\u11E5",
+ "/ko:pieupjongseong": "\u11B8",
+ "/ko:pieupkiyeok": "\u3172",
+ "/ko:pieupkiyeokchoseong": "\u111E",
+ "/ko:pieupnieunchoseong": "\u111F",
+ "/ko:pieupphieuphchoseong": "\u112A",
+ "/ko:pieupphieuphjongseong": "\u11E4",
+ "/ko:pieuprieuljongseong": "\u11E3",
+ "/ko:pieupsios": "\u3144",
+ "/ko:pieupsioschoseong": "\u1121",
+ "/ko:pieupsioscieucchoseong": "\u1126",
+ "/ko:pieupsiosjongseong": "\u11B9",
+ "/ko:pieupsioskiyeok": "\u3174",
+ "/ko:pieupsioskiyeokchoseong": "\u1122",
+ "/ko:pieupsiospieupchoseong": "\u1124",
+ "/ko:pieupsiostikeut": "\u3175",
+ "/ko:pieupsiostikeutchoseong": "\u1123",
+ "/ko:pieupssangsioschoseong": "\u1125",
+ "/ko:pieupthieuth": "\u3177",
+ "/ko:pieupthieuthchoseong": "\u1129",
+ "/ko:pieuptikeut": "\u3173",
+ "/ko:pieuptikeutchoseong": "\u1120",
+ "/ko:rieul": "\u3139",
+ "/ko:rieulchoseong": "\u1105",
+ "/ko:rieulhieuh": "\u3140",
+ "/ko:rieulhieuhchoseong": "\u111A",
+ "/ko:rieulhieuhjongseong": "\u11B6",
+ "/ko:rieuljongseong": "\u11AF",
+ "/ko:rieulkapyeounpieupjongseong": "\u11D5",
+ "/ko:rieulkhieukhjongseong": "\u11D8",
+ "/ko:rieulkiyeok": "\u313A",
+ "/ko:rieulkiyeokjongseong": "\u11B0",
+ "/ko:rieulkiyeoksios": "\u3169",
+ "/ko:rieulkiyeoksiosjongseong": "\u11CC",
+ "/ko:rieulmieum": "\u313B",
+ "/ko:rieulmieumjongseong": "\u11B1",
+ "/ko:rieulmieumkiyeokjongseong": "\u11D1",
+ "/ko:rieulmieumsiosjongseong": "\u11D2",
+ "/ko:rieulnieunchoseong": "\u1118",
+ "/ko:rieulnieunjongseong": "\u11CD",
+ "/ko:rieulpansios": "\u316C",
+ "/ko:rieulpansiosjongseong": "\u11D7",
+ "/ko:rieulphieuph": "\u313F",
+ "/ko:rieulphieuphjongseong": "\u11B5",
+ "/ko:rieulpieup": "\u313C",
+ "/ko:rieulpieuphieuhjongseong": "\u11D4",
+ "/ko:rieulpieupjongseong": "\u11B2",
+ "/ko:rieulpieupsios": "\u316B",
+ "/ko:rieulpieupsiosjongseong": "\u11D3",
+ "/ko:rieulsios": "\u313D",
+ "/ko:rieulsiosjongseong": "\u11B3",
+ "/ko:rieulssangsiosjongseong": "\u11D6",
+ "/ko:rieulthieuth": "\u313E",
+ "/ko:rieulthieuthjongseong": "\u11B4",
+ "/ko:rieultikeut": "\u316A",
+ "/ko:rieultikeuthieuhjongseong": "\u11CF",
+ "/ko:rieultikeutjongseong": "\u11CE",
+ "/ko:rieulyeorinhieuh": "\u316D",
+ "/ko:rieulyeorinhieuhjongseong": "\u11D9",
+ "/ko:sios": "\u3145",
+ "/ko:sioschieuchchoseong": "\u1137",
+ "/ko:sioschoseong": "\u1109",
+ "/ko:sioscieuc": "\u317E",
+ "/ko:sioscieucchoseong": "\u1136",
+ "/ko:sioshieuhchoseong": "\u113B",
+ "/ko:siosieungchoseong": "\u1135",
+ "/ko:siosjongseong": "\u11BA",
+ "/ko:sioskhieukhchoseong": "\u1138",
+ "/ko:sioskiyeok": "\u317A",
+ "/ko:sioskiyeokchoseong": "\u112D",
+ "/ko:sioskiyeokjongseong": "\u11E7",
+ "/ko:siosmieumchoseong": "\u1131",
+ "/ko:siosnieun": "\u317B",
+ "/ko:siosnieunchoseong": "\u112E",
+ "/ko:siosphieuphchoseong": "\u113A",
+ "/ko:siospieup": "\u317D",
+ "/ko:siospieupchoseong": "\u1132",
+ "/ko:siospieupjongseong": "\u11EA",
+ "/ko:siospieupkiyeokchoseong": "\u1133",
+ "/ko:siosrieulchoseong": "\u1130",
+ "/ko:siosrieuljongseong": "\u11E9",
+ "/ko:siosssangsioschoseong": "\u1134",
+ "/ko:siosthieuthchoseong": "\u1139",
+ "/ko:siostikeut": "\u317C",
+ "/ko:siostikeutchoseong": "\u112F",
+ "/ko:siostikeutjongseong": "\u11E8",
+ "/ko:ssangaraeajungseong": "\u11A2",
+ "/ko:ssangcieuc": "\u3149",
+ "/ko:ssangcieucchoseong": "\u110D",
+ "/ko:ssanghieuh": "\u3185",
+ "/ko:ssanghieuhchoseong": "\u1158",
+ "/ko:ssangieung": "\u3180",
+ "/ko:ssangieungchoseong": "\u1147",
+ "/ko:ssangieungjongseong": "\u11EE",
+ "/ko:ssangkiyeok": "\u3132",
+ "/ko:ssangkiyeokchoseong": "\u1101",
+ "/ko:ssangkiyeokjongseong": "\u11A9",
+ "/ko:ssangnieun": "\u3165",
+ "/ko:ssangnieunchoseong": "\u1114",
+ "/ko:ssangnieunjongseong": "\u11FF",
+ "/ko:ssangpieup": "\u3143",
+ "/ko:ssangpieupchoseong": "\u1108",
+ "/ko:ssangrieulchoseong": "\u1119",
+ "/ko:ssangrieuljongseong": "\u11D0",
+ "/ko:ssangsios": "\u3146",
+ "/ko:ssangsioschoseong": "\u110A",
+ "/ko:ssangsiosjongseong": "\u11BB",
+ "/ko:ssangtikeut": "\u3138",
+ "/ko:ssangtikeutchoseong": "\u1104",
+ "/ko:thieuth": "\u314C",
+ "/ko:thieuthchoseong": "\u1110",
+ "/ko:thieuthjongseong": "\u11C0",
+ "/ko:tikeut": "\u3137",
+ "/ko:tikeutchoseong": "\u1103",
+ "/ko:tikeutjongseong": "\u11AE",
+ "/ko:tikeutkiyeokchoseong": "\u1117",
+ "/ko:tikeutkiyeokjongseong": "\u11CA",
+ "/ko:tikeutrieulchoseong": "\u115E",
+ "/ko:tikeutrieuljongseong": "\u11CB",
+ "/ko:u": "\u315C",
+ "/ko:uaejungseong": "\u118A",
+ "/ko:uajungseong": "\u1189",
+ "/ko:ueo_eujungseong": "\u118B",
+ "/ko:ujungseong": "\u116E",
+ "/ko:uujungseong": "\u118D",
+ "/ko:uyejungseong": "\u118C",
+ "/ko:wa": "\u3158",
+ "/ko:wae": "\u3159",
+ "/ko:waejungseong": "\u116B",
+ "/ko:wajungseong": "\u116A",
+ "/ko:we": "\u315E",
+ "/ko:wejungseong": "\u1170",
+ "/ko:weo": "\u315D",
+ "/ko:weojungseong": "\u116F",
+ "/ko:wi": "\u315F",
+ "/ko:wijungseong": "\u1171",
+ "/ko:ya": "\u3151",
+ "/ko:yae": "\u3152",
+ "/ko:yaejungseong": "\u1164",
+ "/ko:yajungseong": "\u1163",
+ "/ko:yaojungseong": "\u1178",
+ "/ko:yaujungseong": "\u11A4",
+ "/ko:yayojungseong": "\u1179",
+ "/ko:ye": "\u3156",
+ "/ko:yejungseong": "\u1168",
+ "/ko:yeo": "\u3155",
+ "/ko:yeojungseong": "\u1167",
+ "/ko:yeoojungseong": "\u117D",
+ "/ko:yeorinhieuh": "\u3186",
+ "/ko:yeorinhieuhchoseong": "\u1159",
+ "/ko:yeorinhieuhjongseong": "\u11F9",
+ "/ko:yeoujungseong": "\u117E",
+ "/ko:yeoyajungseong": "\u11A5",
+ "/ko:yesieung": "\u3181",
+ "/ko:yesieungchoseong": "\u114C",
+ "/ko:yesieungjongseong": "\u11F0",
+ "/ko:yesieungpansios": "\u3183",
+ "/ko:yesieungpansiosjongseong": "\u11F2",
+ "/ko:yesieungsios": "\u3182",
+ "/ko:yesieungsiosjongseong": "\u11F1",
+ "/ko:yi": "\u3162",
+ "/ko:yijungseong": "\u1174",
+ "/ko:yiujungseong": "\u1197",
+ "/ko:yo": "\u315B",
+ "/ko:yoi": "\u3189",
+ "/ko:yoijungseong": "\u1188",
+ "/ko:yojungseong": "\u116D",
+ "/ko:yoojungseong": "\u1187",
+ "/ko:yoya": "\u3187",
+ "/ko:yoyae": "\u3188",
+ "/ko:yoyaejungseong": "\u1185",
+ "/ko:yoyajungseong": "\u1184",
+ "/ko:yoyeojungseong": "\u1186",
+ "/ko:yu": "\u3160",
+ "/ko:yuajungseong": "\u118E",
+ "/ko:yuejungseong": "\u1190",
+ "/ko:yueojungseong": "\u118F",
+ "/ko:yui": "\u318C",
+ "/ko:yuijungseong": "\u1194",
+ "/ko:yujungseong": "\u1172",
+ "/ko:yuujungseong": "\u1193",
+ "/ko:yuye": "\u318B",
+ "/ko:yuyejungseong": "\u1192",
+ "/ko:yuyeo": "\u318A",
+ "/ko:yuyeojungseong": "\u1191",
+ "/koala": "\u1F428",
+ "/kobliquestroke": "\uA7A3",
+ "/kocirclekatakana": "\u32D9",
+ "/kohiragana": "\u3053",
+ "/kohmfullwidth": "\u33C0",
+ "/kohmsquare": "\u33C0",
+ "/kokaithai": "\u0E01",
+ "/kokatakana": "\u30B3",
+ "/kokatakanahalfwidth": "\uFF7A",
+ "/kooposquare": "\u331E",
+ "/koppa": "\u03DF",
+ "/koppaarchaic": "\u03D9",
+ "/koppacyr": "\u0481",
+ "/koppacyrillic": "\u0481",
+ "/koreanstandardsymbol": "\u327F",
+ "/koroniscmb": "\u0343",
+ "/korunasquare": "\u331D",
+ "/kotoideographiccircled": "\u3247",
+ "/kpafullwidth": "\u33AA",
+ "/kparen": "\u24A6",
+ "/kparenthesized": "\u24A6",
+ "/kpasquare": "\u33AA",
+ "/kra": "\u0138",
+ "/ksicyr": "\u046F",
+ "/ksicyrillic": "\u046F",
+ "/kstroke": "\uA741",
+ "/kstrokediagonalstroke": "\uA745",
+ "/ktfullwidth": "\u33CF",
+ "/ktsquare": "\u33CF",
+ "/kturned": "\u029E",
+ "/kucirclekatakana": "\u32D7",
+ "/kuhiragana": "\u304F",
+ "/kukatakana": "\u30AF",
+ "/kukatakanahalfwidth": "\uFF78",
+ "/kuroonesquare": "\u331B",
+ "/kuruzeirosquare": "\u331A",
+ "/kvfullwidth": "\u33B8",
+ "/kvsquare": "\u33B8",
+ "/kwfullwidth": "\u33BE",
+ "/kwsquare": "\u33BE",
+ "/kyuriisquare": "\u3312",
+ "/l": "\u006C",
+ "/l.inferior": "\u2097",
+ "/label": "\u1F3F7",
+ "/labengali": "\u09B2",
+ "/laborideographiccircled": "\u3298",
+ "/laborideographicparen": "\u3238",
+ "/lacute": "\u013A",
+ "/ladeva": "\u0932",
+ "/ladyBeetle": "\u1F41E",
+ "/lagujarati": "\u0AB2",
+ "/lagurmukhi": "\u0A32",
+ "/lakkhangyaothai": "\u0E45",
+ "/lam": "\u0644",
+ "/lam.fina": "\uFEDE",
+ "/lam.init": "\uFEDF",
+ "/lam.init_alef.fina": "\uFEFB",
+ "/lam.init_alef.medi_hamzaabove.fina": "\uFEF7",
+ "/lam.init_alef.medi_hamzabelow.fina": "\uFEF9",
+ "/lam.init_alef.medi_maddaabove.fina": "\uFEF5",
+ "/lam.init_alefmaksura.fina": "\uFC43",
+ "/lam.init_hah.fina": "\uFC40",
+ "/lam.init_hah.medi": "\uFCCA",
+ "/lam.init_hah.medi_meem.medi": "\uFDB5",
+ "/lam.init_heh.medi": "\uFCCD",
+ "/lam.init_jeem.fina": "\uFC3F",
+ "/lam.init_jeem.medi": "\uFCC9",
+ "/lam.init_jeem.medi_jeem.medi": "\uFD83",
+ "/lam.init_jeem.medi_meem.medi": "\uFDBA",
+ "/lam.init_khah.fina": "\uFC41",
+ "/lam.init_khah.medi": "\uFCCB",
+ "/lam.init_khah.medi_meem.medi": "\uFD86",
+ "/lam.init_meem.fina": "\uFC42",
+ "/lam.init_meem.medi": "\uFCCC",
+ "/lam.init_meem.medi_hah.medi": "\uFD88",
+ "/lam.init_yeh.fina": "\uFC44",
+ "/lam.isol": "\uFEDD",
+ "/lam.medi": "\uFEE0",
+ "/lam.medi_alef.fina": "\uFEFC",
+ "/lam.medi_alef.medi_hamzaabove.fina": "\uFEF8",
+ "/lam.medi_alef.medi_hamzabelow.fina": "\uFEFA",
+ "/lam.medi_alef.medi_maddaabove.fina": "\uFEF6",
+ "/lam.medi_alefmaksura.fina": "\uFC86",
+ "/lam.medi_hah.medi_alefmaksura.fina": "\uFD82",
+ "/lam.medi_hah.medi_meem.fina": "\uFD80",
+ "/lam.medi_hah.medi_yeh.fina": "\uFD81",
+ "/lam.medi_jeem.medi_jeem.fina": "\uFD84",
+ "/lam.medi_jeem.medi_meem.fina": "\uFDBC",
+ "/lam.medi_jeem.medi_yeh.fina": "\uFDAC",
+ "/lam.medi_khah.medi_meem.fina": "\uFD85",
+ "/lam.medi_meem.fina": "\uFC85",
+ "/lam.medi_meem.medi": "\uFCED",
+ "/lam.medi_meem.medi_hah.fina": "\uFD87",
+ "/lam.medi_meem.medi_yeh.fina": "\uFDAD",
+ "/lam.medi_yeh.fina": "\uFC87",
+ "/lamBar": "\u076A",
+ "/lamVabove": "\u06B5",
+ "/lamalefabove": "\u06D9",
+ "/lamaleffinalarabic": "\uFEFC",
+ "/lamalefhamzaabovefinalarabic": "\uFEF8",
+ "/lamalefhamzaaboveisolatedarabic": "\uFEF7",
+ "/lamalefhamzabelowfinalarabic": "\uFEFA",
+ "/lamalefhamzabelowisolatedarabic": "\uFEF9",
+ "/lamalefisolatedarabic": "\uFEFB",
+ "/lamalefmaddaabovefinalarabic": "\uFEF6",
+ "/lamalefmaddaaboveisolatedarabic": "\uFEF5",
+ "/lamarabic": "\u0644",
+ "/lambda": "\u03BB",
+ "/lambdastroke": "\u019B",
+ "/lamdotabove": "\u06B6",
+ "/lamed": "\u05DC",
+ "/lamed:hb": "\u05DC",
+ "/lameddagesh": "\uFB3C",
+ "/lameddageshhebrew": "\uFB3C",
+ "/lamedhebrew": "\u05DC",
+ "/lamedholam": "\u05DC",
+ "/lamedholamdagesh": "\u05DC",
+ "/lamedholamdageshhebrew": "\u05DC",
+ "/lamedholamhebrew": "\u05DC",
+ "/lamedwide:hb": "\uFB25",
+ "/lamedwithdagesh:hb": "\uFB3C",
+ "/lamfinalarabic": "\uFEDE",
+ "/lamhahinitialarabic": "\uFCCA",
+ "/laminitialarabic": "\uFEDF",
+ "/lamjeeminitialarabic": "\uFCC9",
+ "/lamkhahinitialarabic": "\uFCCB",
+ "/lamlamhehisolatedarabic": "\uFDF2",
+ "/lammedialarabic": "\uFEE0",
+ "/lammeemhahinitialarabic": "\uFD88",
+ "/lammeeminitialarabic": "\uFCCC",
+ "/lammeemjeeminitialarabic": "\uFEDF",
+ "/lammeemkhahinitialarabic": "\uFEDF",
+ "/lamthreedotsabove": "\u06B7",
+ "/lamthreedotsbelow": "\u06B8",
+ "/lanemergeleftblack": "\u26D8",
+ "/lanemergeleftwhite": "\u26D9",
+ "/largeBlueCircle": "\u1F535",
+ "/largeBlueDiamond": "\u1F537",
+ "/largeOrangeDiamond": "\u1F536",
+ "/largeRedCircle": "\u1F534",
+ "/largecircle": "\u25EF",
+ "/largetackdown": "\u27D9",
+ "/largetackup": "\u27D8",
+ "/lari": "\u20BE",
+ "/lastQuarterMoon": "\u1F317",
+ "/lastQuarterMoonFace": "\u1F31C",
+ "/lastquartermoon": "\u263E",
+ "/layar": "\uA982",
+ "/lazysinverted": "\u223E",
+ "/lbar": "\u019A",
+ "/lbbar": "\u2114",
+ "/lbelt": "\u026C",
+ "/lbeltretroflex": "\uA78E",
+ "/lbopomofo": "\u310C",
+ "/lbroken": "\uA747",
+ "/lcaron": "\u013E",
+ "/lcedilla": "\u013C",
+ "/lcircle": "\u24DB",
+ "/lcircumflexbelow": "\u1E3D",
+ "/lcommaaccent": "\u013C",
+ "/lcurl": "\u0234",
+ "/ldblbar": "\u2C61",
+ "/ldot": "\u0140",
+ "/ldotaccent": "\u0140",
+ "/ldotbelow": "\u1E37",
+ "/ldotbelowmacron": "\u1E39",
+ "/leafFlutteringInWind": "\u1F343",
+ "/ledger": "\u1F4D2",
+ "/left-pointingMagnifyingGlass": "\u1F50D",
+ "/leftAngerBubble": "\u1F5EE",
+ "/leftFiveEighthsBlock": "\u258B",
+ "/leftHalfBlock": "\u258C",
+ "/leftHandTelephoneReceiver": "\u1F57B",
+ "/leftLuggage": "\u1F6C5",
+ "/leftOneEighthBlock": "\u258F",
+ "/leftOneQuarterBlock": "\u258E",
+ "/leftSevenEighthsBlock": "\u2589",
+ "/leftSpeechBubble": "\u1F5E8",
+ "/leftThoughtBubble": "\u1F5EC",
+ "/leftThreeEighthsBlock": "\u258D",
+ "/leftThreeQuartersBlock": "\u258A",
+ "/leftWritingHand": "\u1F58E",
+ "/leftangleabovecmb": "\u031A",
+ "/leftarrowoverrightarrow": "\u21C6",
+ "/leftdnheavyrightuplight": "\u2545",
+ "/leftharpoonoverrightharpoon": "\u21CB",
+ "/leftheavyrightdnlight": "\u252D",
+ "/leftheavyrightuplight": "\u2535",
+ "/leftheavyrightvertlight": "\u253D",
+ "/leftideographiccircled": "\u32A7",
+ "/leftlightrightdnheavy": "\u2532",
+ "/leftlightrightupheavy": "\u253A",
+ "/leftlightrightvertheavy": "\u254A",
+ "/lefttackbelowcmb": "\u0318",
+ "/lefttorightembed": "\u202A",
+ "/lefttorightisolate": "\u2066",
+ "/lefttorightmark": "\u200E",
+ "/lefttorightoverride": "\u202D",
+ "/leftupheavyrightdnlight": "\u2543",
+ "/lemon": "\u1F34B",
+ "/lenis": "\u1FBF",
+ "/lenisacute": "\u1FCE",
+ "/lenisgrave": "\u1FCD",
+ "/lenistilde": "\u1FCF",
+ "/leo": "\u264C",
+ "/leopard": "\u1F406",
+ "/less": "\u003C",
+ "/lessbutnotequal": "\u2268",
+ "/lessbutnotequivalent": "\u22E6",
+ "/lessdot": "\u22D6",
+ "/lessequal": "\u2264",
+ "/lessequalorgreater": "\u22DA",
+ "/lessmonospace": "\uFF1C",
+ "/lessorequivalent": "\u2272",
+ "/lessorgreater": "\u2276",
+ "/lessoverequal": "\u2266",
+ "/lesssmall": "\uFE64",
+ "/levelSlider": "\u1F39A",
+ "/lezh": "\u026E",
+ "/lfblock": "\u258C",
+ "/lhacyr": "\u0515",
+ "/lhookretroflex": "\u026D",
+ "/libra": "\u264E",
+ "/ligaturealeflamed:hb": "\uFB4F",
+ "/ligatureoemod": "\uA7F9",
+ "/lightCheckMark": "\u1F5F8",
+ "/lightRail": "\u1F688",
+ "/lightShade": "\u2591",
+ "/lightarcdnleft": "\u256E",
+ "/lightarcdnright": "\u256D",
+ "/lightarcupleft": "\u256F",
+ "/lightarcupright": "\u2570",
+ "/lightdbldashhorz": "\u254C",
+ "/lightdbldashvert": "\u254E",
+ "/lightdiagcross": "\u2573",
+ "/lightdiagupleftdnright": "\u2572",
+ "/lightdiaguprightdnleft": "\u2571",
+ "/lightdn": "\u2577",
+ "/lightdnhorz": "\u252C",
+ "/lightdnleft": "\u2510",
+ "/lightdnright": "\u250C",
+ "/lighthorz": "\u2500",
+ "/lightleft": "\u2574",
+ "/lightleftheavyright": "\u257C",
+ "/lightning": "\u2607",
+ "/lightningMood": "\u1F5F2",
+ "/lightningMoodBubble": "\u1F5F1",
+ "/lightquaddashhorz": "\u2508",
+ "/lightquaddashvert": "\u250A",
+ "/lightright": "\u2576",
+ "/lighttrpldashhorz": "\u2504",
+ "/lighttrpldashvert": "\u2506",
+ "/lightup": "\u2575",
+ "/lightupheavydn": "\u257D",
+ "/lightuphorz": "\u2534",
+ "/lightupleft": "\u2518",
+ "/lightupright": "\u2514",
+ "/lightvert": "\u2502",
+ "/lightverthorz": "\u253C",
+ "/lightvertleft": "\u2524",
+ "/lightvertright": "\u251C",
+ "/lineextensionhorizontal": "\u23AF",
+ "/lineextensionvertical": "\u23D0",
+ "/linemiddledotvertical": "\u237F",
+ "/lineseparator": "\u2028",
+ "/lingsapada": "\uA9C8",
+ "/link": "\u1F517",
+ "/linkedPaperclips": "\u1F587",
+ "/lips": "\u1F5E2",
+ "/lipstick": "\u1F484",
+ "/lira": "\u20A4",
+ "/litre": "\u2113",
+ "/livretournois": "\u20B6",
+ "/liwnarmenian": "\u056C",
+ "/lj": "\u01C9",
+ "/ljecyr": "\u0459",
+ "/ljecyrillic": "\u0459",
+ "/ljekomicyr": "\u0509",
+ "/ll": "\uF6C0",
+ "/lladeva": "\u0933",
+ "/llagujarati": "\u0AB3",
+ "/llinebelow": "\u1E3B",
+ "/llladeva": "\u0934",
+ "/llvocalicbengali": "\u09E1",
+ "/llvocalicdeva": "\u0961",
+ "/llvocalicvowelsignbengali": "\u09E3",
+ "/llvocalicvowelsigndeva": "\u0963",
+ "/llwelsh": "\u1EFB",
+ "/lmacrondot": "\u1E39",
+ "/lmfullwidth": "\u33D0",
+ "/lmiddletilde": "\u026B",
+ "/lmonospace": "\uFF4C",
+ "/lmsquare": "\u33D0",
+ "/lnfullwidth": "\u33D1",
+ "/lochulathai": "\u0E2C",
+ "/lock": "\u1F512",
+ "/lockInkPen": "\u1F50F",
+ "/logfullwidth": "\u33D2",
+ "/logicaland": "\u2227",
+ "/logicalandarray": "\u22C0",
+ "/logicalnot": "\u00AC",
+ "/logicalnotreversed": "\u2310",
+ "/logicalor": "\u2228",
+ "/logicalorarray": "\u22C1",
+ "/lolingthai": "\u0E25",
+ "/lollipop": "\u1F36D",
+ "/longdivision": "\u27CC",
+ "/longovershortmetrical": "\u23D2",
+ "/longovertwoshortsmetrical": "\u23D4",
+ "/longs": "\u017F",
+ "/longs_t": "\uFB05",
+ "/longsdot": "\u1E9B",
+ "/longswithdiagonalstroke": "\u1E9C",
+ "/longswithhighstroke": "\u1E9D",
+ "/longtackleft": "\u27DE",
+ "/longtackright": "\u27DD",
+ "/losslesssquare": "\u1F1A9",
+ "/loudlyCryingFace": "\u1F62D",
+ "/loveHotel": "\u1F3E9",
+ "/loveLetter": "\u1F48C",
+ "/lowBrightness": "\u1F505",
+ "/lowasterisk": "\u204E",
+ "/lowerFiveEighthsBlock": "\u2585",
+ "/lowerHalfBlock": "\u2584",
+ "/lowerLeftBallpointPen": "\u1F58A",
+ "/lowerLeftCrayon": "\u1F58D",
+ "/lowerLeftFountainPen": "\u1F58B",
+ "/lowerLeftPaintbrush": "\u1F58C",
+ "/lowerLeftPencil": "\u1F589",
+ "/lowerOneEighthBlock": "\u2581",
+ "/lowerOneQuarterBlock": "\u2582",
+ "/lowerRightShadowedWhiteCircle": "\u1F53E",
+ "/lowerSevenEighthsBlock": "\u2587",
+ "/lowerThreeEighthsBlock": "\u2583",
+ "/lowerThreeQuartersBlock": "\u2586",
+ "/lowercornerdotright": "\u27D3",
+ "/lowerhalfcircle": "\u25E1",
+ "/lowerhalfcircleinversewhite": "\u25DB",
+ "/lowerquadrantcirculararcleft": "\u25DF",
+ "/lowerquadrantcirculararcright": "\u25DE",
+ "/lowertriangleleft": "\u25FA",
+ "/lowertriangleleftblack": "\u25E3",
+ "/lowertriangleright": "\u25FF",
+ "/lowertrianglerightblack": "\u25E2",
+ "/lowideographiccircled": "\u32A6",
+ "/lowlinecenterline": "\uFE4E",
+ "/lowlinecmb": "\u0332",
+ "/lowlinedashed": "\uFE4D",
+ "/lownumeralsign": "\u0375",
+ "/lowquotedblprime": "\u301F",
+ "/lozenge": "\u25CA",
+ "/lozengedividedbyrulehorizontal": "\u27E0",
+ "/lozengesquare": "\u2311",
+ "/lparen": "\u24A7",
+ "/lparenthesized": "\u24A7",
+ "/lretroflex": "\u026D",
+ "/ls": "\u02AA",
+ "/lslash": "\u0142",
+ "/lsquare": "\u2113",
+ "/lstroke": "\uA749",
+ "/lsuperior": "\uF6EE",
+ "/lsupmod": "\u02E1",
+ "/lt:Alpha": "\u2C6D",
+ "/lt:Alphaturned": "\u2C70",
+ "/lt:Beta": "\uA7B4",
+ "/lt:Chi": "\uA7B3",
+ "/lt:Gamma": "\u0194",
+ "/lt:Iota": "\u0196",
+ "/lt:Omega": "\uA7B6",
+ "/lt:Upsilon": "\u01B1",
+ "/lt:beta": "\uA7B5",
+ "/lt:delta": "\u1E9F",
+ "/lt:omega": "\uA7B7",
+ "/ltshade": "\u2591",
+ "/lttr:bet": "\u2136",
+ "/lttr:dalet": "\u2138",
+ "/lttr:gimel": "\u2137",
+ "/lttr:gscript": "\u210A",
+ "/lturned": "\uA781",
+ "/ltypeopencircuit": "\u2390",
+ "/luhurpada": "\uA9C5",
+ "/lum": "\uA772",
+ "/lungsipada": "\uA9C9",
+ "/luthai": "\u0E26",
+ "/lvocalicbengali": "\u098C",
+ "/lvocalicdeva": "\u090C",
+ "/lvocalicvowelsignbengali": "\u09E2",
+ "/lvocalicvowelsigndeva": "\u0962",
+ "/lxfullwidth": "\u33D3",
+ "/lxsquare": "\u33D3",
+ "/lzed": "\u02AB",
+ "/m": "\u006D",
+ "/m.inferior": "\u2098",
+ "/m2fullwidth": "\u33A1",
+ "/m3fullwidth": "\u33A5",
+ "/mabengali": "\u09AE",
+ "/macirclekatakana": "\u32EE",
+ "/macron": "\u00AF",
+ "/macronbelowcmb": "\u0331",
+ "/macroncmb": "\u0304",
+ "/macronlowmod": "\u02CD",
+ "/macronmod": "\u02C9",
+ "/macronmonospace": "\uFFE3",
+ "/macute": "\u1E3F",
+ "/madda": "\u0653",
+ "/maddaabove": "\u06E4",
+ "/madeva": "\u092E",
+ "/madyapada": "\uA9C4",
+ "/mafullwidth": "\u3383",
+ "/magujarati": "\u0AAE",
+ "/magurmukhi": "\u0A2E",
+ "/mahapakhhebrew": "\u05A4",
+ "/mahapakhlefthebrew": "\u05A4",
+ "/mahhasquare": "\u3345",
+ "/mahiragana": "\u307E",
+ "/mahpach:hb": "\u05A4",
+ "/maichattawalowleftthai": "\uF895",
+ "/maichattawalowrightthai": "\uF894",
+ "/maichattawathai": "\u0E4B",
+ "/maichattawaupperleftthai": "\uF893",
+ "/maieklowleftthai": "\uF88C",
+ "/maieklowrightthai": "\uF88B",
+ "/maiekthai": "\u0E48",
+ "/maiekupperleftthai": "\uF88A",
+ "/maihanakatleftthai": "\uF884",
+ "/maihanakatthai": "\u0E31",
+ "/maikurosquare": "\u3343",
+ "/mairusquare": "\u3344",
+ "/maitaikhuleftthai": "\uF889",
+ "/maitaikhuthai": "\u0E47",
+ "/maitholowleftthai": "\uF88F",
+ "/maitholowrightthai": "\uF88E",
+ "/maithothai": "\u0E49",
+ "/maithoupperleftthai": "\uF88D",
+ "/maitrilowleftthai": "\uF892",
+ "/maitrilowrightthai": "\uF891",
+ "/maitrithai": "\u0E4A",
+ "/maitriupperleftthai": "\uF890",
+ "/maiyamokthai": "\u0E46",
+ "/makatakana": "\u30DE",
+ "/makatakanahalfwidth": "\uFF8F",
+ "/male": "\u2642",
+ "/malefemale": "\u26A5",
+ "/maleideographiccircled": "\u329A",
+ "/malestroke": "\u26A6",
+ "/malestrokemalefemale": "\u26A7",
+ "/man": "\u1F468",
+ "/manAndWomanHoldingHands": "\u1F46B",
+ "/manDancing": "\u1F57A",
+ "/manGuaPiMao": "\u1F472",
+ "/manInBusinessSuitLevitating": "\u1F574",
+ "/manTurban": "\u1F473",
+ "/manat": "\u20BC",
+ "/mansShoe": "\u1F45E",
+ "/mansyonsquare": "\u3347",
+ "/mantelpieceClock": "\u1F570",
+ "/mapleLeaf": "\u1F341",
+ "/maplighthouse": "\u26EF",
+ "/maqaf:hb": "\u05BE",
+ "/maqafhebrew": "\u05BE",
+ "/marchtelegraph": "\u32C2",
+ "/mark": "\u061C",
+ "/markerdottedraisedinterpolation": "\u2E07",
+ "/markerdottedtransposition": "\u2E08",
+ "/markerraisedinterpolation": "\u2E06",
+ "/marknoonghunna": "\u0658",
+ "/marksChapter": "\u1F545",
+ "/marriage": "\u26AD",
+ "/mars": "\u2642",
+ "/marukusquare": "\u3346",
+ "/masoraCircle:hb": "\u05AF",
+ "/masoracirclehebrew": "\u05AF",
+ "/masquare": "\u3383",
+ "/masumark": "\u303C",
+ "/math:bowtie": "\u22C8",
+ "/math:cuberoot": "\u221B",
+ "/math:fourthroot": "\u221C",
+ "/maximize": "\u1F5D6",
+ "/maytelegraph": "\u32C4",
+ "/mbfullwidth": "\u3386",
+ "/mbopomofo": "\u3107",
+ "/mbsmallfullwidth": "\u33D4",
+ "/mbsquare": "\u33D4",
+ "/mcircle": "\u24DC",
+ "/mcubedsquare": "\u33A5",
+ "/mdot": "\u1E41",
+ "/mdotaccent": "\u1E41",
+ "/mdotbelow": "\u1E43",
+ "/measuredangle": "\u2221",
+ "/measuredby": "\u225E",
+ "/meatOnBone": "\u1F356",
+ "/mecirclekatakana": "\u32F1",
+ "/medicineideographiccircled": "\u32A9",
+ "/mediumShade": "\u2592",
+ "/mediumcircleblack": "\u26AB",
+ "/mediumcirclewhite": "\u26AA",
+ "/mediummathematicalspace": "\u205F",
+ "/mediumsmallcirclewhite": "\u26AC",
+ "/meem": "\u0645",
+ "/meem.fina": "\uFEE2",
+ "/meem.init": "\uFEE3",
+ "/meem.init_alefmaksura.fina": "\uFC49",
+ "/meem.init_hah.fina": "\uFC46",
+ "/meem.init_hah.medi": "\uFCCF",
+ "/meem.init_hah.medi_jeem.medi": "\uFD89",
+ "/meem.init_hah.medi_meem.medi": "\uFD8A",
+ "/meem.init_jeem.fina": "\uFC45",
+ "/meem.init_jeem.medi": "\uFCCE",
+ "/meem.init_jeem.medi_hah.medi": "\uFD8C",
+ "/meem.init_jeem.medi_khah.medi": "\uFD92",
+ "/meem.init_jeem.medi_meem.medi": "\uFD8D",
+ "/meem.init_khah.fina": "\uFC47",
+ "/meem.init_khah.medi": "\uFCD0",
+ "/meem.init_khah.medi_jeem.medi": "\uFD8E",
+ "/meem.init_khah.medi_meem.medi": "\uFD8F",
+ "/meem.init_meem.fina": "\uFC48",
+ "/meem.init_meem.medi": "\uFCD1",
+ "/meem.init_yeh.fina": "\uFC4A",
+ "/meem.isol": "\uFEE1",
+ "/meem.medi": "\uFEE4",
+ "/meem.medi_alef.fina": "\uFC88",
+ "/meem.medi_hah.medi_yeh.fina": "\uFD8B",
+ "/meem.medi_jeem.medi_yeh.fina": "\uFDC0",
+ "/meem.medi_khah.medi_yeh.fina": "\uFDB9",
+ "/meem.medi_meem.fina": "\uFC89",
+ "/meem.medi_meem.medi_yeh.fina": "\uFDB1",
+ "/meemDotAbove": "\u0765",
+ "/meemDotBelow": "\u0766",
+ "/meemabove": "\u06E2",
+ "/meemabove.init": "\u06D8",
+ "/meemarabic": "\u0645",
+ "/meembelow": "\u06ED",
+ "/meemfinalarabic": "\uFEE2",
+ "/meeminitialarabic": "\uFEE3",
+ "/meemmedialarabic": "\uFEE4",
+ "/meemmeeminitialarabic": "\uFCD1",
+ "/meemmeemisolatedarabic": "\uFC48",
+ "/meetorusquare": "\u334D",
+ "/megasquare": "\u334B",
+ "/megatonsquare": "\u334C",
+ "/mehiragana": "\u3081",
+ "/meizierasquare": "\u337E",
+ "/mekatakana": "\u30E1",
+ "/mekatakanahalfwidth": "\uFF92",
+ "/melon": "\u1F348",
+ "/mem": "\u05DE",
+ "/mem:hb": "\u05DE",
+ "/memdagesh": "\uFB3E",
+ "/memdageshhebrew": "\uFB3E",
+ "/memhebrew": "\u05DE",
+ "/memo": "\u1F4DD",
+ "/memwithdagesh:hb": "\uFB3E",
+ "/menarmenian": "\u0574",
+ "/menorahNineBranches": "\u1F54E",
+ "/menpostSindhi": "\u06FE",
+ "/mens": "\u1F6B9",
+ "/mepigraphicinverted": "\uA7FD",
+ "/mercha:hb": "\u05A5",
+ "/merchaKefulah:hb": "\u05A6",
+ "/mercury": "\u263F",
+ "/merkhahebrew": "\u05A5",
+ "/merkhakefulahebrew": "\u05A6",
+ "/merkhakefulalefthebrew": "\u05A6",
+ "/merkhalefthebrew": "\u05A5",
+ "/metalideographiccircled": "\u328E",
+ "/metalideographicparen": "\u322E",
+ "/meteg:hb": "\u05BD",
+ "/metro": "\u1F687",
+ "/mgfullwidth": "\u338E",
+ "/mhook": "\u0271",
+ "/mhzfullwidth": "\u3392",
+ "/mhzsquare": "\u3392",
+ "/micirclekatakana": "\u32EF",
+ "/microphone": "\u1F3A4",
+ "/microscope": "\u1F52C",
+ "/middledotkatakanahalfwidth": "\uFF65",
+ "/middot": "\u00B7",
+ "/mieumacirclekorean": "\u3272",
+ "/mieumaparenkorean": "\u3212",
+ "/mieumcirclekorean": "\u3264",
+ "/mieumkorean": "\u3141",
+ "/mieumpansioskorean": "\u3170",
+ "/mieumparenkorean": "\u3204",
+ "/mieumpieupkorean": "\u316E",
+ "/mieumsioskorean": "\u316F",
+ "/mihiragana": "\u307F",
+ "/mikatakana": "\u30DF",
+ "/mikatakanahalfwidth": "\uFF90",
+ "/mikuronsquare": "\u3348",
+ "/milfullwidth": "\u33D5",
+ "/militaryMedal": "\u1F396",
+ "/milkyWay": "\u1F30C",
+ "/mill": "\u20A5",
+ "/millionscmbcyr": "\u0489",
+ "/millisecond": "\u2034",
+ "/millisecondreversed": "\u2037",
+ "/minibus": "\u1F690",
+ "/minidisc": "\u1F4BD",
+ "/minimize": "\u1F5D5",
+ "/minus": "\u2212",
+ "/minus.inferior": "\u208B",
+ "/minus.superior": "\u207B",
+ "/minusbelowcmb": "\u0320",
+ "/minuscircle": "\u2296",
+ "/minusmod": "\u02D7",
+ "/minusplus": "\u2213",
+ "/minussignmod": "\u02D7",
+ "/minustilde": "\u2242",
+ "/minute": "\u2032",
+ "/minutereversed": "\u2035",
+ "/miribaarusquare": "\u334A",
+ "/mirisquare": "\u3349",
+ "/misc:baby": "\u1F476",
+ "/misc:bell": "\u1F514",
+ "/misc:dash": "\u1F4A8",
+ "/misc:decimalseparator": "\u2396",
+ "/misc:diamondblack": "\u2666",
+ "/misc:diamondwhite": "\u2662",
+ "/misc:ear": "\u1F442",
+ "/misc:om": "\u1F549",
+ "/misc:ring": "\u1F48D",
+ "/misra": "\u060F",
+ "/mlfullwidth": "\u3396",
+ "/mlonglegturned": "\u0270",
+ "/mlsquare": "\u3396",
+ "/mlym:a": "\u0D05",
+ "/mlym:aa": "\u0D06",
+ "/mlym:aasign": "\u0D3E",
+ "/mlym:ai": "\u0D10",
+ "/mlym:aisign": "\u0D48",
+ "/mlym:anusvarasign": "\u0D02",
+ "/mlym:archaicii": "\u0D5F",
+ "/mlym:au": "\u0D14",
+ "/mlym:aulength": "\u0D57",
+ "/mlym:ausign": "\u0D4C",
+ "/mlym:avagrahasign": "\u0D3D",
+ "/mlym:ba": "\u0D2C",
+ "/mlym:bha": "\u0D2D",
+ "/mlym:ca": "\u0D1A",
+ "/mlym:candrabindusign": "\u0D01",
+ "/mlym:cha": "\u0D1B",
+ "/mlym:circularviramasign": "\u0D3C",
+ "/mlym:combininganusvaraabovesign": "\u0D00",
+ "/mlym:da": "\u0D26",
+ "/mlym:date": "\u0D79",
+ "/mlym:dda": "\u0D21",
+ "/mlym:ddha": "\u0D22",
+ "/mlym:dha": "\u0D27",
+ "/mlym:dotreph": "\u0D4E",
+ "/mlym:e": "\u0D0E",
+ "/mlym:ee": "\u0D0F",
+ "/mlym:eesign": "\u0D47",
+ "/mlym:eight": "\u0D6E",
+ "/mlym:esign": "\u0D46",
+ "/mlym:five": "\u0D6B",
+ "/mlym:four": "\u0D6A",
+ "/mlym:ga": "\u0D17",
+ "/mlym:gha": "\u0D18",
+ "/mlym:ha": "\u0D39",
+ "/mlym:i": "\u0D07",
+ "/mlym:ii": "\u0D08",
+ "/mlym:iisign": "\u0D40",
+ "/mlym:isign": "\u0D3F",
+ "/mlym:ja": "\u0D1C",
+ "/mlym:jha": "\u0D1D",
+ "/mlym:ka": "\u0D15",
+ "/mlym:kchillu": "\u0D7F",
+ "/mlym:kha": "\u0D16",
+ "/mlym:la": "\u0D32",
+ "/mlym:lchillu": "\u0D7D",
+ "/mlym:lla": "\u0D33",
+ "/mlym:llchillu": "\u0D7E",
+ "/mlym:llla": "\u0D34",
+ "/mlym:lllchillu": "\u0D56",
+ "/mlym:llvocal": "\u0D61",
+ "/mlym:llvocalsign": "\u0D63",
+ "/mlym:lvocal": "\u0D0C",
+ "/mlym:lvocalsign": "\u0D62",
+ "/mlym:ma": "\u0D2E",
+ "/mlym:mchillu": "\u0D54",
+ "/mlym:na": "\u0D28",
+ "/mlym:nchillu": "\u0D7B",
+ "/mlym:nga": "\u0D19",
+ "/mlym:nine": "\u0D6F",
+ "/mlym:nna": "\u0D23",
+ "/mlym:nnchillu": "\u0D7A",
+ "/mlym:nnna": "\u0D29",
+ "/mlym:nya": "\u0D1E",
+ "/mlym:o": "\u0D12",
+ "/mlym:one": "\u0D67",
+ "/mlym:oneeighth": "\u0D77",
+ "/mlym:onefifth": "\u0D5E",
+ "/mlym:onefortieth": "\u0D59",
+ "/mlym:onehalf": "\u0D74",
+ "/mlym:onehundred": "\u0D71",
+ "/mlym:oneone-hundred-and-sixtieth": "\u0D58",
+ "/mlym:onequarter": "\u0D73",
+ "/mlym:onesixteenth": "\u0D76",
+ "/mlym:onetenth": "\u0D5C",
+ "/mlym:onethousand": "\u0D72",
+ "/mlym:onetwentieth": "\u0D5B",
+ "/mlym:oo": "\u0D13",
+ "/mlym:oosign": "\u0D4B",
+ "/mlym:osign": "\u0D4A",
+ "/mlym:pa": "\u0D2A",
+ "/mlym:parasign": "\u0D4F",
+ "/mlym:pha": "\u0D2B",
+ "/mlym:ra": "\u0D30",
+ "/mlym:rra": "\u0D31",
+ "/mlym:rrchillu": "\u0D7C",
+ "/mlym:rrvocal": "\u0D60",
+ "/mlym:rrvocalsign": "\u0D44",
+ "/mlym:rvocal": "\u0D0B",
+ "/mlym:rvocalsign": "\u0D43",
+ "/mlym:sa": "\u0D38",
+ "/mlym:seven": "\u0D6D",
+ "/mlym:sha": "\u0D36",
+ "/mlym:six": "\u0D6C",
+ "/mlym:ssa": "\u0D37",
+ "/mlym:ta": "\u0D24",
+ "/mlym:ten": "\u0D70",
+ "/mlym:tha": "\u0D25",
+ "/mlym:three": "\u0D69",
+ "/mlym:threeeightieths": "\u0D5A",
+ "/mlym:threequarters": "\u0D75",
+ "/mlym:threesixteenths": "\u0D78",
+ "/mlym:threetwentieths": "\u0D5D",
+ "/mlym:tta": "\u0D1F",
+ "/mlym:ttha": "\u0D20",
+ "/mlym:ttta": "\u0D3A",
+ "/mlym:two": "\u0D68",
+ "/mlym:u": "\u0D09",
+ "/mlym:usign": "\u0D41",
+ "/mlym:uu": "\u0D0A",
+ "/mlym:uusign": "\u0D42",
+ "/mlym:va": "\u0D35",
+ "/mlym:verticalbarviramasign": "\u0D3B",
+ "/mlym:viramasign": "\u0D4D",
+ "/mlym:visargasign": "\u0D03",
+ "/mlym:ya": "\u0D2F",
+ "/mlym:ychillu": "\u0D55",
+ "/mlym:zero": "\u0D66",
+ "/mm2fullwidth": "\u339F",
+ "/mm3fullwidth": "\u33A3",
+ "/mmcubedsquare": "\u33A3",
+ "/mmfullwidth": "\u339C",
+ "/mmonospace": "\uFF4D",
+ "/mmsquaredsquare": "\u339F",
+ "/mobilePhone": "\u1F4F1",
+ "/mobilePhoneOff": "\u1F4F4",
+ "/mobilePhoneRightwardsArrowAtLeft": "\u1F4F2",
+ "/mocirclekatakana": "\u32F2",
+ "/models": "\u22A7",
+ "/mohiragana": "\u3082",
+ "/mohmfullwidth": "\u33C1",
+ "/mohmsquare": "\u33C1",
+ "/mokatakana": "\u30E2",
+ "/mokatakanahalfwidth": "\uFF93",
+ "/molfullwidth": "\u33D6",
+ "/molsquare": "\u33D6",
+ "/momathai": "\u0E21",
+ "/moneyBag": "\u1F4B0",
+ "/moneyWings": "\u1F4B8",
+ "/mong:a": "\u1820",
+ "/mong:aaligali": "\u1887",
+ "/mong:ahaligali": "\u1897",
+ "/mong:ang": "\u1829",
+ "/mong:angsibe": "\u1862",
+ "/mong:angtodo": "\u184A",
+ "/mong:anusvaraonealigali": "\u1880",
+ "/mong:ba": "\u182A",
+ "/mong:baludaaligali": "\u1885",
+ "/mong:baludaaligalithree": "\u1886",
+ "/mong:batodo": "\u184B",
+ "/mong:bhamanchualigali": "\u18A8",
+ "/mong:birga": "\u1800",
+ "/mong:caaligali": "\u188B",
+ "/mong:camanchualigali": "\u189C",
+ "/mong:cha": "\u1834",
+ "/mong:chasibe": "\u1871",
+ "/mong:chatodo": "\u1852",
+ "/mong:chi": "\u1842",
+ "/mong:colon": "\u1804",
+ "/mong:comma": "\u1802",
+ "/mong:commamanchu": "\u1808",
+ "/mong:cyamanchualigali": "\u18A3",
+ "/mong:da": "\u1833",
+ "/mong:daaligali": "\u1891",
+ "/mong:dagalgaaligali": "\u18A9",
+ "/mong:damarualigali": "\u1882",
+ "/mong:dasibe": "\u1869",
+ "/mong:datodo": "\u1851",
+ "/mong:ddaaligali": "\u188E",
+ "/mong:ddhamanchualigali": "\u189F",
+ "/mong:dhamanchualigali": "\u18A1",
+ "/mong:dzatodo": "\u185C",
+ "/mong:e": "\u1821",
+ "/mong:ee": "\u1827",
+ "/mong:eight": "\u1818",
+ "/mong:ellipsis": "\u1801",
+ "/mong:esibe": "\u185D",
+ "/mong:etodo": "\u1844",
+ "/mong:fa": "\u1839",
+ "/mong:famanchu": "\u1876",
+ "/mong:fasibe": "\u186B",
+ "/mong:five": "\u1815",
+ "/mong:four": "\u1814",
+ "/mong:fourdots": "\u1805",
+ "/mong:freevariationselectorone": "\u180B",
+ "/mong:freevariationselectorthree": "\u180D",
+ "/mong:freevariationselectortwo": "\u180C",
+ "/mong:ga": "\u182D",
+ "/mong:gaasibe": "\u186C",
+ "/mong:gaatodo": "\u1858",
+ "/mong:gasibe": "\u1864",
+ "/mong:gatodo": "\u184E",
+ "/mong:ghamanchualigali": "\u189A",
+ "/mong:haa": "\u183E",
+ "/mong:haasibe": "\u186D",
+ "/mong:haatodo": "\u1859",
+ "/mong:hasibe": "\u1865",
+ "/mong:i": "\u1822",
+ "/mong:ialigali": "\u1888",
+ "/mong:imanchu": "\u1873",
+ "/mong:isibe": "\u185E",
+ "/mong:itodo": "\u1845",
+ "/mong:iysibe": "\u185F",
+ "/mong:ja": "\u1835",
+ "/mong:jasibe": "\u186A",
+ "/mong:jatodo": "\u1853",
+ "/mong:jhamanchualigali": "\u189D",
+ "/mong:jiatodo": "\u185A",
+ "/mong:ka": "\u183A",
+ "/mong:kaaligali": "\u1889",
+ "/mong:kamanchu": "\u1874",
+ "/mong:kasibe": "\u1863",
+ "/mong:katodo": "\u1857",
+ "/mong:kha": "\u183B",
+ "/mong:la": "\u182F",
+ "/mong:lha": "\u1840",
+ "/mong:lhamanchualigali": "\u18AA",
+ "/mong:longvowelsigntodo": "\u1843",
+ "/mong:ma": "\u182E",
+ "/mong:matodo": "\u184F",
+ "/mong:na": "\u1828",
+ "/mong:ngaaligali": "\u188A",
+ "/mong:ngamanchualigali": "\u189B",
+ "/mong:niatodo": "\u185B",
+ "/mong:nine": "\u1819",
+ "/mong:nirugu": "\u180A",
+ "/mong:nnaaligali": "\u188F",
+ "/mong:o": "\u1823",
+ "/mong:oe": "\u1825",
+ "/mong:oetodo": "\u1848",
+ "/mong:one": "\u1811",
+ "/mong:otodo": "\u1846",
+ "/mong:pa": "\u182B",
+ "/mong:paaligali": "\u1892",
+ "/mong:pasibe": "\u1866",
+ "/mong:patodo": "\u184C",
+ "/mong:period": "\u1803",
+ "/mong:periodmanchu": "\u1809",
+ "/mong:phaaligali": "\u1893",
+ "/mong:qa": "\u182C",
+ "/mong:qatodo": "\u184D",
+ "/mong:ra": "\u1837",
+ "/mong:raasibe": "\u1870",
+ "/mong:ramanchu": "\u1875",
+ "/mong:sa": "\u1830",
+ "/mong:seven": "\u1817",
+ "/mong:sha": "\u1831",
+ "/mong:shasibe": "\u1867",
+ "/mong:six": "\u1816",
+ "/mong:softhyphentodo": "\u1806",
+ "/mong:ssaaligali": "\u1894",
+ "/mong:ssamanchualigali": "\u18A2",
+ "/mong:syllableboundarymarkersibe": "\u1807",
+ "/mong:ta": "\u1832",
+ "/mong:taaligali": "\u1890",
+ "/mong:tamanchualigali": "\u18A0",
+ "/mong:tasibe": "\u1868",
+ "/mong:tatodo": "\u1850",
+ "/mong:tatodoaligali": "\u1898",
+ "/mong:three": "\u1813",
+ "/mong:tsa": "\u183C",
+ "/mong:tsasibe": "\u186E",
+ "/mong:tsatodo": "\u1854",
+ "/mong:ttaaligali": "\u188C",
+ "/mong:ttamanchualigali": "\u189E",
+ "/mong:tthaaligali": "\u188D",
+ "/mong:two": "\u1812",
+ "/mong:u": "\u1824",
+ "/mong:ualigalihalf": "\u18A6",
+ "/mong:ubadamaaligali": "\u1883",
+ "/mong:ubadamaaligaliinverted": "\u1884",
+ "/mong:ue": "\u1826",
+ "/mong:uesibe": "\u1860",
+ "/mong:uetodo": "\u1849",
+ "/mong:usibe": "\u1861",
+ "/mong:utodo": "\u1847",
+ "/mong:visargaonealigali": "\u1881",
+ "/mong:vowelseparator": "\u180E",
+ "/mong:wa": "\u1838",
+ "/mong:watodo": "\u1856",
+ "/mong:ya": "\u1836",
+ "/mong:yaaligalihalf": "\u18A7",
+ "/mong:yatodo": "\u1855",
+ "/mong:za": "\u183D",
+ "/mong:zaaligali": "\u1896",
+ "/mong:zamanchualigali": "\u18A5",
+ "/mong:zasibe": "\u186F",
+ "/mong:zero": "\u1810",
+ "/mong:zhaaligali": "\u1895",
+ "/mong:zhamanchu": "\u1877",
+ "/mong:zhamanchualigali": "\u18A4",
+ "/mong:zhasibe": "\u1872",
+ "/mong:zhatodoaligali": "\u1899",
+ "/mong:zhi": "\u1841",
+ "/mong:zra": "\u183F",
+ "/monkey": "\u1F412",
+ "/monkeyFace": "\u1F435",
+ "/monogramyang": "\u268A",
+ "/monogramyin": "\u268B",
+ "/monorail": "\u1F69D",
+ "/monostable": "\u238D",
+ "/moodBubble": "\u1F5F0",
+ "/moonViewingCeremony": "\u1F391",
+ "/moonideographiccircled": "\u328A",
+ "/moonideographicparen": "\u322A",
+ "/moonlilithblack": "\u26B8",
+ "/mosque": "\u1F54C",
+ "/motorBoat": "\u1F6E5",
+ "/motorScooter": "\u1F6F5",
+ "/motorway": "\u1F6E3",
+ "/mountFuji": "\u1F5FB",
+ "/mountain": "\u26F0",
+ "/mountainBicyclist": "\u1F6B5",
+ "/mountainCableway": "\u1F6A0",
+ "/mountainRailway": "\u1F69E",
+ "/mouse": "\u1F401",
+ "/mouseFace": "\u1F42D",
+ "/mouth": "\u1F444",
+ "/movers2fullwidth": "\u33A8",
+ "/moversfullwidth": "\u33A7",
+ "/moverssquare": "\u33A7",
+ "/moverssquaredsquare": "\u33A8",
+ "/movieCamera": "\u1F3A5",
+ "/moyai": "\u1F5FF",
+ "/mpafullwidth": "\u33AB",
+ "/mparen": "\u24A8",
+ "/mparenthesized": "\u24A8",
+ "/mpasquare": "\u33AB",
+ "/msfullwidth": "\u33B3",
+ "/mssquare": "\u33B3",
+ "/msuperior": "\uF6EF",
+ "/mturned": "\u026F",
+ "/mu": "\u00B5",
+ "/mu.math": "\u00B5",
+ "/mu1": "\u00B5",
+ "/muafullwidth": "\u3382",
+ "/muasquare": "\u3382",
+ "/muchgreater": "\u226B",
+ "/muchless": "\u226A",
+ "/mucirclekatakana": "\u32F0",
+ "/muffullwidth": "\u338C",
+ "/mufsquare": "\u338C",
+ "/mugfullwidth": "\u338D",
+ "/mugreek": "\u03BC",
+ "/mugsquare": "\u338D",
+ "/muhiragana": "\u3080",
+ "/mukatakana": "\u30E0",
+ "/mukatakanahalfwidth": "\uFF91",
+ "/mulfullwidth": "\u3395",
+ "/mulsquare": "\u3395",
+ "/multimap": "\u22B8",
+ "/multimapleft": "\u27DC",
+ "/multipleMusicalNotes": "\u1F3B6",
+ "/multiply": "\u00D7",
+ "/multiset": "\u228C",
+ "/multisetmultiplication": "\u228D",
+ "/multisetunion": "\u228E",
+ "/mum": "\uA773",
+ "/mumfullwidth": "\u339B",
+ "/mumsquare": "\u339B",
+ "/munach:hb": "\u05A3",
+ "/munahhebrew": "\u05A3",
+ "/munahlefthebrew": "\u05A3",
+ "/musfullwidth": "\u33B2",
+ "/mushroom": "\u1F344",
+ "/musicalKeyboard": "\u1F3B9",
+ "/musicalKeyboardJacks": "\u1F398",
+ "/musicalNote": "\u1F3B5",
+ "/musicalScore": "\u1F3BC",
+ "/musicalnote": "\u266A",
+ "/musicalnotedbl": "\u266B",
+ "/musicflat": "\u266D",
+ "/musicflatsign": "\u266D",
+ "/musicnatural": "\u266E",
+ "/musicsharp": "\u266F",
+ "/musicsharpsign": "\u266F",
+ "/mussquare": "\u33B2",
+ "/muvfullwidth": "\u33B6",
+ "/muvsquare": "\u33B6",
+ "/muwfullwidth": "\u33BC",
+ "/muwsquare": "\u33BC",
+ "/mvfullwidth": "\u33B7",
+ "/mvmegafullwidth": "\u33B9",
+ "/mvmegasquare": "\u33B9",
+ "/mvsquare": "\u33B7",
+ "/mwfullwidth": "\u33BD",
+ "/mwmegafullwidth": "\u33BF",
+ "/mwmegasquare": "\u33BF",
+ "/mwsquare": "\u33BD",
+ "/n": "\u006E",
+ "/n.inferior": "\u2099",
+ "/n.superior": "\u207F",
+ "/nabengali": "\u09A8",
+ "/nabla": "\u2207",
+ "/nacirclekatakana": "\u32E4",
+ "/nacute": "\u0144",
+ "/nadeva": "\u0928",
+ "/nafullwidth": "\u3381",
+ "/nagujarati": "\u0AA8",
+ "/nagurmukhi": "\u0A28",
+ "/nahiragana": "\u306A",
+ "/nailPolish": "\u1F485",
+ "/naira": "\u20A6",
+ "/nakatakana": "\u30CA",
+ "/nakatakanahalfwidth": "\uFF85",
+ "/nameBadge": "\u1F4DB",
+ "/nameideographiccircled": "\u3294",
+ "/nameideographicparen": "\u3234",
+ "/namurda": "\uA99F",
+ "/nand": "\u22BC",
+ "/nanosquare": "\u3328",
+ "/napostrophe": "\u0149",
+ "/narrownobreakspace": "\u202F",
+ "/nasquare": "\u3381",
+ "/nationalPark": "\u1F3DE",
+ "/nationaldigitshapes": "\u206E",
+ "/nbopomofo": "\u310B",
+ "/nbspace": "\u00A0",
+ "/ncaron": "\u0148",
+ "/ncedilla": "\u0146",
+ "/ncircle": "\u24DD",
+ "/ncircumflexbelow": "\u1E4B",
+ "/ncommaaccent": "\u0146",
+ "/ncurl": "\u0235",
+ "/ndescender": "\uA791",
+ "/ndot": "\u1E45",
+ "/ndotaccent": "\u1E45",
+ "/ndotbelow": "\u1E47",
+ "/necirclekatakana": "\u32E7",
+ "/necktie": "\u1F454",
+ "/negatedturnstiledblverticalbarright": "\u22AF",
+ "/nehiragana": "\u306D",
+ "/neirapproximatelynoractuallyequal": "\u2247",
+ "/neirasersetnorequalup": "\u2289",
+ "/neirasubsetnorequal": "\u2288",
+ "/neirgreaternorequal": "\u2271",
+ "/neirgreaternorequivalent": "\u2275",
+ "/neirgreaternorless": "\u2279",
+ "/neirlessnorequal": "\u2270",
+ "/neirlessnorequivalent": "\u2274",
+ "/neirlessnorgreater": "\u2278",
+ "/nekatakana": "\u30CD",
+ "/nekatakanahalfwidth": "\uFF88",
+ "/neptune": "\u2646",
+ "/neuter": "\u26B2",
+ "/neutralFace": "\u1F610",
+ "/newMoon": "\u1F311",
+ "/newMoonFace": "\u1F31A",
+ "/newsheqel": "\u20AA",
+ "/newsheqelsign": "\u20AA",
+ "/newspaper": "\u1F4F0",
+ "/newsquare": "\u1F195",
+ "/nextpage": "\u2398",
+ "/nffullwidth": "\u338B",
+ "/nfsquare": "\u338B",
+ "/ng.fina": "\uFBD4",
+ "/ng.init": "\uFBD5",
+ "/ng.isol": "\uFBD3",
+ "/ng.medi": "\uFBD6",
+ "/ngabengali": "\u0999",
+ "/ngadeva": "\u0919",
+ "/ngagujarati": "\u0A99",
+ "/ngagurmukhi": "\u0A19",
+ "/ngalelet": "\uA98A",
+ "/ngaleletraswadi": "\uA98B",
+ "/ngoeh": "\u06B1",
+ "/ngoeh.fina": "\uFB9B",
+ "/ngoeh.init": "\uFB9C",
+ "/ngoeh.isol": "\uFB9A",
+ "/ngoeh.medi": "\uFB9D",
+ "/ngonguthai": "\u0E07",
+ "/ngrave": "\u01F9",
+ "/ngsquare": "\u1F196",
+ "/nhiragana": "\u3093",
+ "/nhookleft": "\u0272",
+ "/nhookretroflex": "\u0273",
+ "/nicirclekatakana": "\u32E5",
+ "/nieunacirclekorean": "\u326F",
+ "/nieunaparenkorean": "\u320F",
+ "/nieuncieuckorean": "\u3135",
+ "/nieuncirclekorean": "\u3261",
+ "/nieunhieuhkorean": "\u3136",
+ "/nieunkorean": "\u3134",
+ "/nieunpansioskorean": "\u3168",
+ "/nieunparenkorean": "\u3201",
+ "/nieunsioskorean": "\u3167",
+ "/nieuntikeutkorean": "\u3166",
+ "/nightStars": "\u1F303",
+ "/nightideographiccircled": "\u32B0",
+ "/nihiragana": "\u306B",
+ "/nikatakana": "\u30CB",
+ "/nikatakanahalfwidth": "\uFF86",
+ "/nikhahitleftthai": "\uF899",
+ "/nikhahitthai": "\u0E4D",
+ "/nine": "\u0039",
+ "/nine.inferior": "\u2089",
+ "/nine.roman": "\u2168",
+ "/nine.romansmall": "\u2178",
+ "/nine.superior": "\u2079",
+ "/ninearabic": "\u0669",
+ "/ninebengali": "\u09EF",
+ "/ninecircle": "\u2468",
+ "/ninecircledbl": "\u24FD",
+ "/ninecircleinversesansserif": "\u2792",
+ "/ninecomma": "\u1F10A",
+ "/ninedeva": "\u096F",
+ "/ninefar": "\u06F9",
+ "/ninegujarati": "\u0AEF",
+ "/ninegurmukhi": "\u0A6F",
+ "/ninehackarabic": "\u0669",
+ "/ninehangzhou": "\u3029",
+ "/nineideographiccircled": "\u3288",
+ "/nineideographicparen": "\u3228",
+ "/nineinferior": "\u2089",
+ "/ninemonospace": "\uFF19",
+ "/nineoldstyle": "\uF739",
+ "/nineparen": "\u247C",
+ "/nineparenthesized": "\u247C",
+ "/nineperiod": "\u2490",
+ "/ninepersian": "\u06F9",
+ "/nineroman": "\u2178",
+ "/ninesuperior": "\u2079",
+ "/nineteencircle": "\u2472",
+ "/nineteencircleblack": "\u24F3",
+ "/nineteenparen": "\u2486",
+ "/nineteenparenthesized": "\u2486",
+ "/nineteenperiod": "\u249A",
+ "/ninethai": "\u0E59",
+ "/nj": "\u01CC",
+ "/njecyr": "\u045A",
+ "/njecyrillic": "\u045A",
+ "/njekomicyr": "\u050B",
+ "/nkatakana": "\u30F3",
+ "/nkatakanahalfwidth": "\uFF9D",
+ "/nlegrightlong": "\u019E",
+ "/nlinebelow": "\u1E49",
+ "/nlongrightleg": "\u019E",
+ "/nmbr:oneeighth": "\u215B",
+ "/nmbr:onefifth": "\u2155",
+ "/nmbr:onetenth": "\u2152",
+ "/nmfullwidth": "\u339A",
+ "/nmonospace": "\uFF4E",
+ "/nmsquare": "\u339A",
+ "/nnabengali": "\u09A3",
+ "/nnadeva": "\u0923",
+ "/nnagujarati": "\u0AA3",
+ "/nnagurmukhi": "\u0A23",
+ "/nnnadeva": "\u0929",
+ "/noBicycles": "\u1F6B3",
+ "/noEntrySign": "\u1F6AB",
+ "/noMobilePhones": "\u1F4F5",
+ "/noOneUnderEighteen": "\u1F51E",
+ "/noPedestrians": "\u1F6B7",
+ "/noPiracy": "\u1F572",
+ "/noSmoking": "\u1F6AD",
+ "/nobliquestroke": "\uA7A5",
+ "/nocirclekatakana": "\u32E8",
+ "/nodeascending": "\u260A",
+ "/nodedescending": "\u260B",
+ "/noentry": "\u26D4",
+ "/nohiragana": "\u306E",
+ "/nokatakana": "\u30CE",
+ "/nokatakanahalfwidth": "\uFF89",
+ "/nominaldigitshapes": "\u206F",
+ "/nonPotableWater": "\u1F6B1",
+ "/nonbreakinghyphen": "\u2011",
+ "/nonbreakingspace": "\u00A0",
+ "/nonenthai": "\u0E13",
+ "/nonuthai": "\u0E19",
+ "/noon": "\u0646",
+ "/noon.fina": "\uFEE6",
+ "/noon.init": "\uFEE7",
+ "/noon.init_alefmaksura.fina": "\uFC4F",
+ "/noon.init_hah.fina": "\uFC4C",
+ "/noon.init_hah.medi": "\uFCD3",
+ "/noon.init_hah.medi_meem.medi": "\uFD95",
+ "/noon.init_heh.medi": "\uFCD6",
+ "/noon.init_jeem.fina": "\uFC4B",
+ "/noon.init_jeem.medi": "\uFCD2",
+ "/noon.init_jeem.medi_hah.medi": "\uFDB8",
+ "/noon.init_jeem.medi_meem.medi": "\uFD98",
+ "/noon.init_khah.fina": "\uFC4D",
+ "/noon.init_khah.medi": "\uFCD4",
+ "/noon.init_meem.fina": "\uFC4E",
+ "/noon.init_meem.medi": "\uFCD5",
+ "/noon.init_yeh.fina": "\uFC50",
+ "/noon.isol": "\uFEE5",
+ "/noon.medi": "\uFEE8",
+ "/noon.medi_alefmaksura.fina": "\uFC8E",
+ "/noon.medi_hah.medi_alefmaksura.fina": "\uFD96",
+ "/noon.medi_hah.medi_yeh.fina": "\uFDB3",
+ "/noon.medi_heh.medi": "\uFCEF",
+ "/noon.medi_jeem.medi_alefmaksura.fina": "\uFD99",
+ "/noon.medi_jeem.medi_hah.fina": "\uFDBD",
+ "/noon.medi_jeem.medi_meem.fina": "\uFD97",
+ "/noon.medi_jeem.medi_yeh.fina": "\uFDC7",
+ "/noon.medi_meem.fina": "\uFC8C",
+ "/noon.medi_meem.medi": "\uFCEE",
+ "/noon.medi_meem.medi_alefmaksura.fina": "\uFD9B",
+ "/noon.medi_meem.medi_yeh.fina": "\uFD9A",
+ "/noon.medi_noon.fina": "\uFC8D",
+ "/noon.medi_reh.fina": "\uFC8A",
+ "/noon.medi_yeh.fina": "\uFC8F",
+ "/noon.medi_zain.fina": "\uFC8B",
+ "/noonSmallTah": "\u0768",
+ "/noonSmallV": "\u0769",
+ "/noonTwoDotsBelow": "\u0767",
+ "/noonabove": "\u06E8",
+ "/noonarabic": "\u0646",
+ "/noondotbelow": "\u06B9",
+ "/noonfinalarabic": "\uFEE6",
+ "/noonghunna": "\u06BA",
+ "/noonghunna.fina": "\uFB9F",
+ "/noonghunna.isol": "\uFB9E",
+ "/noonghunnaarabic": "\u06BA",
+ "/noonghunnafinalarabic": "\uFB9F",
+ "/noonhehinitialarabic": "\uFEE7",
+ "/nooninitialarabic": "\uFEE7",
+ "/noonjeeminitialarabic": "\uFCD2",
+ "/noonjeemisolatedarabic": "\uFC4B",
+ "/noonmedialarabic": "\uFEE8",
+ "/noonmeeminitialarabic": "\uFCD5",
+ "/noonmeemisolatedarabic": "\uFC4E",
+ "/noonnoonfinalarabic": "\uFC8D",
+ "/noonring": "\u06BC",
+ "/noonthreedotsabove": "\u06BD",
+ "/nor": "\u22BD",
+ "/nordicmark": "\u20BB",
+ "/normalfacrsemidirectproductleft": "\u22C9",
+ "/normalfacrsemidirectproductright": "\u22CA",
+ "/normalsubgroorequalup": "\u22B4",
+ "/normalsubgroup": "\u22B2",
+ "/northeastPointingAirplane": "\u1F6EA",
+ "/nose": "\u1F443",
+ "/notalmostequal": "\u2249",
+ "/notasersetup": "\u2285",
+ "/notasympticallyequal": "\u2244",
+ "/notcheckmark": "\u237B",
+ "/notchedLeftSemicircleThreeDots": "\u1F543",
+ "/notchedRightSemicircleThreeDots": "\u1F544",
+ "/notcontains": "\u220C",
+ "/note": "\u1F5C8",
+ "/notePad": "\u1F5CA",
+ "/notePage": "\u1F5C9",
+ "/notebook": "\u1F4D3",
+ "/notebookDecorativeCover": "\u1F4D4",
+ "/notelement": "\u2209",
+ "/notelementof": "\u2209",
+ "/notequal": "\u2260",
+ "/notequivalent": "\u226D",
+ "/notexistential": "\u2204",
+ "/notgreater": "\u226F",
+ "/notgreaternorequal": "\u2271",
+ "/notgreaternorless": "\u2279",
+ "/notidentical": "\u2262",
+ "/notless": "\u226E",
+ "/notlessnorequal": "\u2270",
+ "/notnormalsubgroorequalup": "\u22EC",
+ "/notnormalsubgroup": "\u22EA",
+ "/notparallel": "\u2226",
+ "/notprecedes": "\u2280",
+ "/notsignturned": "\u2319",
+ "/notsquareimageorequal": "\u22E2",
+ "/notsquareoriginalorequal": "\u22E3",
+ "/notsubset": "\u2284",
+ "/notsucceeds": "\u2281",
+ "/notsuperset": "\u2285",
+ "/nottilde": "\u2241",
+ "/nottosquare": "\u3329",
+ "/nottrue": "\u22AD",
+ "/novembertelegraph": "\u32CA",
+ "/nowarmenian": "\u0576",
+ "/nparen": "\u24A9",
+ "/nparenthesized": "\u24A9",
+ "/nretroflex": "\u0273",
+ "/nsfullwidth": "\u33B1",
+ "/nssquare": "\u33B1",
+ "/nsuperior": "\u207F",
+ "/ntilde": "\u00F1",
+ "/nu": "\u03BD",
+ "/nucirclekatakana": "\u32E6",
+ "/nuhiragana": "\u306C",
+ "/nukatakana": "\u30CC",
+ "/nukatakanahalfwidth": "\uFF87",
+ "/nuktabengali": "\u09BC",
+ "/nuktadeva": "\u093C",
+ "/nuktagujarati": "\u0ABC",
+ "/nuktagurmukhi": "\u0A3C",
+ "/num": "\uA774",
+ "/numbermarkabove": "\u0605",
+ "/numbersign": "\u0023",
+ "/numbersignmonospace": "\uFF03",
+ "/numbersignsmall": "\uFE5F",
+ "/numeralsign": "\u0374",
+ "/numeralsigngreek": "\u0374",
+ "/numeralsignlowergreek": "\u0375",
+ "/numero": "\u2116",
+ "/nun": "\u05E0",
+ "/nun:hb": "\u05E0",
+ "/nunHafukha:hb": "\u05C6",
+ "/nundagesh": "\uFB40",
+ "/nundageshhebrew": "\uFB40",
+ "/nunhebrew": "\u05E0",
+ "/nunwithdagesh:hb": "\uFB40",
+ "/nutAndBolt": "\u1F529",
+ "/nvfullwidth": "\u33B5",
+ "/nvsquare": "\u33B5",
+ "/nwfullwidth": "\u33BB",
+ "/nwsquare": "\u33BB",
+ "/nyabengali": "\u099E",
+ "/nyadeva": "\u091E",
+ "/nyagujarati": "\u0A9E",
+ "/nyagurmukhi": "\u0A1E",
+ "/nyamurda": "\uA998",
+ "/nyeh": "\u0683",
+ "/nyeh.fina": "\uFB77",
+ "/nyeh.init": "\uFB78",
+ "/nyeh.isol": "\uFB76",
+ "/nyeh.medi": "\uFB79",
+ "/o": "\u006F",
+ "/o.inferior": "\u2092",
+ "/oacute": "\u00F3",
+ "/oangthai": "\u0E2D",
+ "/obarcyr": "\u04E9",
+ "/obardieresiscyr": "\u04EB",
+ "/obarred": "\u0275",
+ "/obarredcyrillic": "\u04E9",
+ "/obarreddieresiscyrillic": "\u04EB",
+ "/obelosdotted": "\u2E13",
+ "/obengali": "\u0993",
+ "/obopomofo": "\u311B",
+ "/obreve": "\u014F",
+ "/observereye": "\u23FF",
+ "/ocandradeva": "\u0911",
+ "/ocandragujarati": "\u0A91",
+ "/ocandravowelsigndeva": "\u0949",
+ "/ocandravowelsigngujarati": "\u0AC9",
+ "/ocaron": "\u01D2",
+ "/ocircle": "\u24DE",
+ "/ocirclekatakana": "\u32D4",
+ "/ocircumflex": "\u00F4",
+ "/ocircumflexacute": "\u1ED1",
+ "/ocircumflexdotbelow": "\u1ED9",
+ "/ocircumflexgrave": "\u1ED3",
+ "/ocircumflexhoi": "\u1ED5",
+ "/ocircumflexhookabove": "\u1ED5",
+ "/ocircumflextilde": "\u1ED7",
+ "/ocr:bowtie": "\u2445",
+ "/ocr:dash": "\u2448",
+ "/octagonalSign": "\u1F6D1",
+ "/octobertelegraph": "\u32C9",
+ "/octopus": "\u1F419",
+ "/ocyr": "\u043E",
+ "/ocyrillic": "\u043E",
+ "/odblacute": "\u0151",
+ "/odblgrave": "\u020D",
+ "/oden": "\u1F362",
+ "/odeva": "\u0913",
+ "/odieresis": "\u00F6",
+ "/odieresiscyr": "\u04E7",
+ "/odieresiscyrillic": "\u04E7",
+ "/odieresismacron": "\u022B",
+ "/odot": "\u022F",
+ "/odotbelow": "\u1ECD",
+ "/odotmacron": "\u0231",
+ "/oe": "\u0153",
+ "/oe.fina": "\uFBDA",
+ "/oe.isol": "\uFBD9",
+ "/oekirghiz": "\u06C5",
+ "/oekirghiz.fina": "\uFBE1",
+ "/oekirghiz.isol": "\uFBE0",
+ "/oekorean": "\u315A",
+ "/officeBuilding": "\u1F3E2",
+ "/ogonek": "\u02DB",
+ "/ogonekcmb": "\u0328",
+ "/ograve": "\u00F2",
+ "/ogravedbl": "\u020D",
+ "/ogujarati": "\u0A93",
+ "/oharmenian": "\u0585",
+ "/ohiragana": "\u304A",
+ "/ohm": "\u2126",
+ "/ohminverted": "\u2127",
+ "/ohoi": "\u1ECF",
+ "/ohookabove": "\u1ECF",
+ "/ohorn": "\u01A1",
+ "/ohornacute": "\u1EDB",
+ "/ohorndotbelow": "\u1EE3",
+ "/ohorngrave": "\u1EDD",
+ "/ohornhoi": "\u1EDF",
+ "/ohornhookabove": "\u1EDF",
+ "/ohorntilde": "\u1EE1",
+ "/ohungarumlaut": "\u0151",
+ "/ohuparen": "\u321E",
+ "/oi": "\u01A3",
+ "/oilDrum": "\u1F6E2",
+ "/oinvertedbreve": "\u020F",
+ "/ojeonparen": "\u321D",
+ "/okHandSign": "\u1F44C",
+ "/okatakana": "\u30AA",
+ "/okatakanahalfwidth": "\uFF75",
+ "/okorean": "\u3157",
+ "/oksquare": "\u1F197",
+ "/oldKey": "\u1F5DD",
+ "/oldPersonalComputer": "\u1F5B3",
+ "/olderMan": "\u1F474",
+ "/olderWoman": "\u1F475",
+ "/ole:hb": "\u05AB",
+ "/olehebrew": "\u05AB",
+ "/oloop": "\uA74D",
+ "/olowringinside": "\u2C7A",
+ "/omacron": "\u014D",
+ "/omacronacute": "\u1E53",
+ "/omacrongrave": "\u1E51",
+ "/omdeva": "\u0950",
+ "/omega": "\u03C9",
+ "/omega1": "\u03D6",
+ "/omegaacute": "\u1F7D",
+ "/omegaacuteiotasub": "\u1FF4",
+ "/omegaasper": "\u1F61",
+ "/omegaasperacute": "\u1F65",
+ "/omegaasperacuteiotasub": "\u1FA5",
+ "/omegaaspergrave": "\u1F63",
+ "/omegaaspergraveiotasub": "\u1FA3",
+ "/omegaasperiotasub": "\u1FA1",
+ "/omegaaspertilde": "\u1F67",
+ "/omegaaspertildeiotasub": "\u1FA7",
+ "/omegaclosed": "\u0277",
+ "/omegacyr": "\u0461",
+ "/omegacyrillic": "\u0461",
+ "/omegafunc": "\u2375",
+ "/omegagrave": "\u1F7C",
+ "/omegagraveiotasub": "\u1FF2",
+ "/omegaiotasub": "\u1FF3",
+ "/omegalatinclosed": "\u0277",
+ "/omegalenis": "\u1F60",
+ "/omegalenisacute": "\u1F64",
+ "/omegalenisacuteiotasub": "\u1FA4",
+ "/omegalenisgrave": "\u1F62",
+ "/omegalenisgraveiotasub": "\u1FA2",
+ "/omegalenisiotasub": "\u1FA0",
+ "/omegalenistilde": "\u1F66",
+ "/omegalenistildeiotasub": "\u1FA6",
+ "/omegaroundcyr": "\u047B",
+ "/omegaroundcyrillic": "\u047B",
+ "/omegatilde": "\u1FF6",
+ "/omegatildeiotasub": "\u1FF7",
+ "/omegatitlocyr": "\u047D",
+ "/omegatitlocyrillic": "\u047D",
+ "/omegatonos": "\u03CE",
+ "/omegaunderlinefunc": "\u2379",
+ "/omgujarati": "\u0AD0",
+ "/omicron": "\u03BF",
+ "/omicronacute": "\u1F79",
+ "/omicronasper": "\u1F41",
+ "/omicronasperacute": "\u1F45",
+ "/omicronaspergrave": "\u1F43",
+ "/omicrongrave": "\u1F78",
+ "/omicronlenis": "\u1F40",
+ "/omicronlenisacute": "\u1F44",
+ "/omicronlenisgrave": "\u1F42",
+ "/omicrontonos": "\u03CC",
+ "/omonospace": "\uFF4F",
+ "/onExclamationMarkLeftRightArrowAbove": "\u1F51B",
+ "/oncomingAutomobile": "\u1F698",
+ "/oncomingBus": "\u1F68D",
+ "/oncomingFireEngine": "\u1F6F1",
+ "/oncomingPoliceCar": "\u1F694",
+ "/oncomingTaxi": "\u1F696",
+ "/one": "\u0031",
+ "/one.inferior": "\u2081",
+ "/one.roman": "\u2160",
+ "/one.romansmall": "\u2170",
+ "/oneButtonMouse": "\u1F5AF",
+ "/onearabic": "\u0661",
+ "/onebengali": "\u09E7",
+ "/onecircle": "\u2460",
+ "/onecircledbl": "\u24F5",
+ "/onecircleinversesansserif": "\u278A",
+ "/onecomma": "\u1F102",
+ "/onedeva": "\u0967",
+ "/onedotenleader": "\u2024",
+ "/onedotovertwodots": "\u2E2B",
+ "/oneeighth": "\u215B",
+ "/onefar": "\u06F1",
+ "/onefitted": "\uF6DC",
+ "/onefraction": "\u215F",
+ "/onegujarati": "\u0AE7",
+ "/onegurmukhi": "\u0A67",
+ "/onehackarabic": "\u0661",
+ "/onehalf": "\u00BD",
+ "/onehangzhou": "\u3021",
+ "/onehundred.roman": "\u216D",
+ "/onehundred.romansmall": "\u217D",
+ "/onehundredthousand.roman": "\u2188",
+ "/onehundredtwentypsquare": "\u1F1A4",
+ "/oneideographiccircled": "\u3280",
+ "/oneideographicparen": "\u3220",
+ "/oneinferior": "\u2081",
+ "/onemonospace": "\uFF11",
+ "/oneninth": "\u2151",
+ "/onenumeratorbengali": "\u09F4",
+ "/oneoldstyle": "\uF731",
+ "/oneparen": "\u2474",
+ "/oneparenthesized": "\u2474",
+ "/oneperiod": "\u2488",
+ "/onepersian": "\u06F1",
+ "/onequarter": "\u00BC",
+ "/oneroman": "\u2170",
+ "/oneseventh": "\u2150",
+ "/onesixth": "\u2159",
+ "/onesuperior": "\u00B9",
+ "/onethai": "\u0E51",
+ "/onethird": "\u2153",
+ "/onethousand.roman": "\u216F",
+ "/onethousand.romansmall": "\u217F",
+ "/onethousandcd.roman": "\u2180",
+ "/onsusquare": "\u3309",
+ "/oo": "\uA74F",
+ "/oogonek": "\u01EB",
+ "/oogonekmacron": "\u01ED",
+ "/oogurmukhi": "\u0A13",
+ "/oomatragurmukhi": "\u0A4B",
+ "/oomusquare": "\u330A",
+ "/oopen": "\u0254",
+ "/oparen": "\u24AA",
+ "/oparenthesized": "\u24AA",
+ "/openBook": "\u1F4D6",
+ "/openFileFolder": "\u1F4C2",
+ "/openFolder": "\u1F5C1",
+ "/openHandsSign": "\u1F450",
+ "/openLock": "\u1F513",
+ "/openMailboxLoweredFlag": "\u1F4ED",
+ "/openMailboxRaisedFlag": "\u1F4EC",
+ "/openbullet": "\u25E6",
+ "/openheadarrowleft": "\u21FD",
+ "/openheadarrowleftright": "\u21FF",
+ "/openheadarrowright": "\u21FE",
+ "/opensubset": "\u27C3",
+ "/opensuperset": "\u27C4",
+ "/ophiuchus": "\u26CE",
+ "/opposition": "\u260D",
+ "/opticalDisc": "\u1F4BF",
+ "/opticalDiscIcon": "\u1F5B8",
+ "/option": "\u2325",
+ "/orangeBook": "\u1F4D9",
+ "/ordfeminine": "\u00AA",
+ "/ordmasculine": "\u00BA",
+ "/ordotinside": "\u27C7",
+ "/original": "\u22B6",
+ "/ornateleftparenthesis": "\uFD3E",
+ "/ornaterightparenthesis": "\uFD3F",
+ "/orthodoxcross": "\u2626",
+ "/orthogonal": "\u221F",
+ "/orya:a": "\u0B05",
+ "/orya:aa": "\u0B06",
+ "/orya:aasign": "\u0B3E",
+ "/orya:ai": "\u0B10",
+ "/orya:ailengthmark": "\u0B56",
+ "/orya:aisign": "\u0B48",
+ "/orya:anusvara": "\u0B02",
+ "/orya:au": "\u0B14",
+ "/orya:aulengthmark": "\u0B57",
+ "/orya:ausign": "\u0B4C",
+ "/orya:avagraha": "\u0B3D",
+ "/orya:ba": "\u0B2C",
+ "/orya:bha": "\u0B2D",
+ "/orya:ca": "\u0B1A",
+ "/orya:candrabindu": "\u0B01",
+ "/orya:cha": "\u0B1B",
+ "/orya:da": "\u0B26",
+ "/orya:dda": "\u0B21",
+ "/orya:ddha": "\u0B22",
+ "/orya:dha": "\u0B27",
+ "/orya:e": "\u0B0F",
+ "/orya:eight": "\u0B6E",
+ "/orya:esign": "\u0B47",
+ "/orya:five": "\u0B6B",
+ "/orya:four": "\u0B6A",
+ "/orya:fractiononeeighth": "\u0B76",
+ "/orya:fractiononehalf": "\u0B73",
+ "/orya:fractiononequarter": "\u0B72",
+ "/orya:fractiononesixteenth": "\u0B75",
+ "/orya:fractionthreequarters": "\u0B74",
+ "/orya:fractionthreesixteenths": "\u0B77",
+ "/orya:ga": "\u0B17",
+ "/orya:gha": "\u0B18",
+ "/orya:ha": "\u0B39",
+ "/orya:i": "\u0B07",
+ "/orya:ii": "\u0B08",
+ "/orya:iisign": "\u0B40",
+ "/orya:isign": "\u0B3F",
+ "/orya:isshar": "\u0B70",
+ "/orya:ja": "\u0B1C",
+ "/orya:jha": "\u0B1D",
+ "/orya:ka": "\u0B15",
+ "/orya:kha": "\u0B16",
+ "/orya:la": "\u0B32",
+ "/orya:lla": "\u0B33",
+ "/orya:llvocal": "\u0B61",
+ "/orya:llvocalsign": "\u0B63",
+ "/orya:lvocal": "\u0B0C",
+ "/orya:lvocalsign": "\u0B62",
+ "/orya:ma": "\u0B2E",
+ "/orya:na": "\u0B28",
+ "/orya:nga": "\u0B19",
+ "/orya:nine": "\u0B6F",
+ "/orya:nna": "\u0B23",
+ "/orya:nukta": "\u0B3C",
+ "/orya:nya": "\u0B1E",
+ "/orya:o": "\u0B13",
+ "/orya:one": "\u0B67",
+ "/orya:osign": "\u0B4B",
+ "/orya:pa": "\u0B2A",
+ "/orya:pha": "\u0B2B",
+ "/orya:ra": "\u0B30",
+ "/orya:rha": "\u0B5D",
+ "/orya:rra": "\u0B5C",
+ "/orya:rrvocal": "\u0B60",
+ "/orya:rrvocalsign": "\u0B44",
+ "/orya:rvocal": "\u0B0B",
+ "/orya:rvocalsign": "\u0B43",
+ "/orya:sa": "\u0B38",
+ "/orya:seven": "\u0B6D",
+ "/orya:sha": "\u0B36",
+ "/orya:six": "\u0B6C",
+ "/orya:ssa": "\u0B37",
+ "/orya:ta": "\u0B24",
+ "/orya:tha": "\u0B25",
+ "/orya:three": "\u0B69",
+ "/orya:tta": "\u0B1F",
+ "/orya:ttha": "\u0B20",
+ "/orya:two": "\u0B68",
+ "/orya:u": "\u0B09",
+ "/orya:usign": "\u0B41",
+ "/orya:uu": "\u0B0A",
+ "/orya:uusign": "\u0B42",
+ "/orya:va": "\u0B35",
+ "/orya:virama": "\u0B4D",
+ "/orya:visarga": "\u0B03",
+ "/orya:wa": "\u0B71",
+ "/orya:ya": "\u0B2F",
+ "/orya:yya": "\u0B5F",
+ "/orya:zero": "\u0B66",
+ "/oscript": "\u2134",
+ "/oshortdeva": "\u0912",
+ "/oshortvowelsigndeva": "\u094A",
+ "/oslash": "\u00F8",
+ "/oslashacute": "\u01FF",
+ "/osmallhiragana": "\u3049",
+ "/osmallkatakana": "\u30A9",
+ "/osmallkatakanahalfwidth": "\uFF6B",
+ "/ostroke": "\uA74B",
+ "/ostrokeacute": "\u01FF",
+ "/osuperior": "\uF6F0",
+ "/otcyr": "\u047F",
+ "/otcyrillic": "\u047F",
+ "/otilde": "\u00F5",
+ "/otildeacute": "\u1E4D",
+ "/otildedieresis": "\u1E4F",
+ "/otildemacron": "\u022D",
+ "/ou": "\u0223",
+ "/oubopomofo": "\u3121",
+ "/ounce": "\u2125",
+ "/outboxTray": "\u1F4E4",
+ "/outerjoinfull": "\u27D7",
+ "/outerjoinleft": "\u27D5",
+ "/outerjoinright": "\u27D6",
+ "/outputpassiveup": "\u2392",
+ "/overlap": "\u1F5D7",
+ "/overline": "\u203E",
+ "/overlinecenterline": "\uFE4A",
+ "/overlinecmb": "\u0305",
+ "/overlinedashed": "\uFE49",
+ "/overlinedblwavy": "\uFE4C",
+ "/overlinewavy": "\uFE4B",
+ "/overscore": "\u00AF",
+ "/ovfullwidth": "\u3375",
+ "/ovowelsignbengali": "\u09CB",
+ "/ovowelsigndeva": "\u094B",
+ "/ovowelsigngujarati": "\u0ACB",
+ "/ox": "\u1F402",
+ "/p": "\u0070",
+ "/p.inferior": "\u209A",
+ "/paampsfullwidth": "\u3380",
+ "/paampssquare": "\u3380",
+ "/paasentosquare": "\u332B",
+ "/paatusquare": "\u332C",
+ "/pabengali": "\u09AA",
+ "/pacerek": "\uA989",
+ "/package": "\u1F4E6",
+ "/pacute": "\u1E55",
+ "/padeva": "\u092A",
+ "/pafullwidth": "\u33A9",
+ "/page": "\u1F5CF",
+ "/pageCircledText": "\u1F5DF",
+ "/pageCurl": "\u1F4C3",
+ "/pageFacingUp": "\u1F4C4",
+ "/pagedown": "\u21DF",
+ "/pager": "\u1F4DF",
+ "/pages": "\u1F5D0",
+ "/pageup": "\u21DE",
+ "/pagoda": "\u1F6D4",
+ "/pagujarati": "\u0AAA",
+ "/pagurmukhi": "\u0A2A",
+ "/pahiragana": "\u3071",
+ "/paiyannoithai": "\u0E2F",
+ "/pakatakana": "\u30D1",
+ "/palatalizationcyrilliccmb": "\u0484",
+ "/palatcmbcyr": "\u0484",
+ "/pallas": "\u26B4",
+ "/palmTree": "\u1F334",
+ "/palmbranch": "\u2E19",
+ "/palochkacyr": "\u04CF",
+ "/palochkacyrillic": "\u04C0",
+ "/pamurda": "\uA9A6",
+ "/pandaFace": "\u1F43C",
+ "/pangkatpada": "\uA9C7",
+ "/pangkon": "\uA9C0",
+ "/pangrangkep": "\uA9CF",
+ "/pansioskorean": "\u317F",
+ "/panyangga": "\uA980",
+ "/paperclip": "\u1F4CE",
+ "/paragraph": "\u00B6",
+ "/paragraphos": "\u2E0F",
+ "/paragraphosforked": "\u2E10",
+ "/paragraphosforkedreversed": "\u2E11",
+ "/paragraphseparator": "\u2029",
+ "/parallel": "\u2225",
+ "/parallelogramblack": "\u25B0",
+ "/parallelogramwhite": "\u25B1",
+ "/parenbottom": "\u23DD",
+ "/parendblleft": "\u2E28",
+ "/parendblright": "\u2E29",
+ "/parenextensionleft": "\u239C",
+ "/parenextensionright": "\u239F",
+ "/parenflatleft": "\u27EE",
+ "/parenflatright": "\u27EF",
+ "/parenhookupleft": "\u239B",
+ "/parenhookupright": "\u239E",
+ "/parenleft": "\u0028",
+ "/parenleft.inferior": "\u208D",
+ "/parenleft.superior": "\u207D",
+ "/parenleftaltonearabic": "\uFD3E",
+ "/parenleftbt": "\uF8ED",
+ "/parenleftex": "\uF8EC",
+ "/parenleftinferior": "\u208D",
+ "/parenleftmonospace": "\uFF08",
+ "/parenleftsmall": "\uFE59",
+ "/parenleftsuperior": "\u207D",
+ "/parenlefttp": "\uF8EB",
+ "/parenleftvertical": "\uFE35",
+ "/parenlowerhookleft": "\u239D",
+ "/parenlowerhookright": "\u23A0",
+ "/parenright": "\u0029",
+ "/parenright.inferior": "\u208E",
+ "/parenright.superior": "\u207E",
+ "/parenrightaltonearabic": "\uFD3F",
+ "/parenrightbt": "\uF8F8",
+ "/parenrightex": "\uF8F7",
+ "/parenrightinferior": "\u208E",
+ "/parenrightmonospace": "\uFF09",
+ "/parenrightsmall": "\uFE5A",
+ "/parenrightsuperior": "\u207E",
+ "/parenrighttp": "\uF8F6",
+ "/parenrightvertical": "\uFE36",
+ "/parentop": "\u23DC",
+ "/partalternationmark": "\u303D",
+ "/partialdiff": "\u2202",
+ "/partnership": "\u3250",
+ "/partyPopper": "\u1F389",
+ "/paseq:hb": "\u05C0",
+ "/paseqhebrew": "\u05C0",
+ "/pashta:hb": "\u0599",
+ "/pashtahebrew": "\u0599",
+ "/pasquare": "\u33A9",
+ "/passengerShip": "\u1F6F3",
+ "/passivedown": "\u2391",
+ "/passportControl": "\u1F6C2",
+ "/patah": "\u05B7",
+ "/patah11": "\u05B7",
+ "/patah1d": "\u05B7",
+ "/patah2a": "\u05B7",
+ "/patah:hb": "\u05B7",
+ "/patahhebrew": "\u05B7",
+ "/patahnarrowhebrew": "\u05B7",
+ "/patahquarterhebrew": "\u05B7",
+ "/patahwidehebrew": "\u05B7",
+ "/pawPrints": "\u1F43E",
+ "/pawnblack": "\u265F",
+ "/pawnwhite": "\u2659",
+ "/pazer:hb": "\u05A1",
+ "/pazerhebrew": "\u05A1",
+ "/pbopomofo": "\u3106",
+ "/pcfullwidth": "\u3376",
+ "/pcircle": "\u24DF",
+ "/pdot": "\u1E57",
+ "/pdotaccent": "\u1E57",
+ "/pe": "\u05E4",
+ "/pe:hb": "\u05E4",
+ "/peace": "\u262E",
+ "/peach": "\u1F351",
+ "/pear": "\u1F350",
+ "/pecyr": "\u043F",
+ "/pecyrillic": "\u043F",
+ "/pedagesh": "\uFB44",
+ "/pedageshhebrew": "\uFB44",
+ "/pedestrian": "\u1F6B6",
+ "/peezisquare": "\u333B",
+ "/pefinaldageshhebrew": "\uFB43",
+ "/peh.fina": "\uFB57",
+ "/peh.init": "\uFB58",
+ "/peh.isol": "\uFB56",
+ "/peh.medi": "\uFB59",
+ "/peharabic": "\u067E",
+ "/peharmenian": "\u057A",
+ "/pehebrew": "\u05E4",
+ "/peheh": "\u06A6",
+ "/peheh.fina": "\uFB6F",
+ "/peheh.init": "\uFB70",
+ "/peheh.isol": "\uFB6E",
+ "/peheh.medi": "\uFB71",
+ "/pehfinalarabic": "\uFB57",
+ "/pehinitialarabic": "\uFB58",
+ "/pehiragana": "\u307A",
+ "/pehmedialarabic": "\uFB59",
+ "/pehookcyr": "\u04A7",
+ "/pekatakana": "\u30DA",
+ "/pemiddlehookcyrillic": "\u04A7",
+ "/penOverStampedEnvelope": "\u1F586",
+ "/pengkalconsonant": "\uA9BE",
+ "/penguin": "\u1F427",
+ "/penihisquare": "\u3338",
+ "/pensiveFace": "\u1F614",
+ "/pensusquare": "\u333A",
+ "/pentagram": "\u26E4",
+ "/pentasememetrical": "\u23D9",
+ "/pepetvowel": "\uA9BC",
+ "/per": "\u214C",
+ "/perafehebrew": "\uFB4E",
+ "/percent": "\u0025",
+ "/percentarabic": "\u066A",
+ "/percentmonospace": "\uFF05",
+ "/percentsmall": "\uFE6A",
+ "/percussivebidental": "\u02AD",
+ "/percussivebilabial": "\u02AC",
+ "/performingArts": "\u1F3AD",
+ "/period": "\u002E",
+ "/periodarmenian": "\u0589",
+ "/periodcentered": "\u00B7",
+ "/periodhalfwidth": "\uFF61",
+ "/periodinferior": "\uF6E7",
+ "/periodmonospace": "\uFF0E",
+ "/periodsmall": "\uFE52",
+ "/periodsuperior": "\uF6E8",
+ "/periodurdu": "\u06D4",
+ "/perispomenigreekcmb": "\u0342",
+ "/permanentpaper": "\u267E",
+ "/permille": "\u0609",
+ "/perpendicular": "\u22A5",
+ "/perseveringFace": "\u1F623",
+ "/personBlondHair": "\u1F471",
+ "/personBowingDeeply": "\u1F647",
+ "/personFrowning": "\u1F64D",
+ "/personRaisingBothHandsInCelebration": "\u1F64C",
+ "/personWithFoldedHands": "\u1F64F",
+ "/personWithPoutingFace": "\u1F64E",
+ "/personalComputer": "\u1F4BB",
+ "/personball": "\u26F9",
+ "/perspective": "\u2306",
+ "/pertenthousandsign": "\u2031",
+ "/perthousand": "\u2030",
+ "/peseta": "\u20A7",
+ "/peso": "\u20B1",
+ "/pesosquare": "\u3337",
+ "/petailcyr": "\u0525",
+ "/pewithdagesh:hb": "\uFB44",
+ "/pewithrafe:hb": "\uFB4E",
+ "/pffullwidth": "\u338A",
+ "/pflourish": "\uA753",
+ "/pfsquare": "\u338A",
+ "/phabengali": "\u09AB",
+ "/phadeva": "\u092B",
+ "/phagujarati": "\u0AAB",
+ "/phagurmukhi": "\u0A2B",
+ "/pharyngealvoicedfricative": "\u0295",
+ "/phfullwidth": "\u33D7",
+ "/phi": "\u03C6",
+ "/phi.math": "\u03D5",
+ "/phi1": "\u03D5",
+ "/phieuphacirclekorean": "\u327A",
+ "/phieuphaparenkorean": "\u321A",
+ "/phieuphcirclekorean": "\u326C",
+ "/phieuphkorean": "\u314D",
+ "/phieuphparenkorean": "\u320C",
+ "/philatin": "\u0278",
+ "/phinthuthai": "\u0E3A",
+ "/phisymbolgreek": "\u03D5",
+ "/phitailless": "\u2C77",
+ "/phon:AEsmall": "\u1D01",
+ "/phon:Aemod": "\u1D2D",
+ "/phon:Amod": "\u1D2C",
+ "/phon:Asmall": "\u1D00",
+ "/phon:Bbarmod": "\u1D2F",
+ "/phon:Bbarsmall": "\u1D03",
+ "/phon:Bmod": "\u1D2E",
+ "/phon:Csmall": "\u1D04",
+ "/phon:Dmod": "\u1D30",
+ "/phon:Dsmall": "\u1D05",
+ "/phon:ENcyrmod": "\u1D78",
+ "/phon:Elsmallcyr": "\u1D2B",
+ "/phon:Emod": "\u1D31",
+ "/phon:Ereversedmod": "\u1D32",
+ "/phon:Esmall": "\u1D07",
+ "/phon:Ethsmall": "\u1D06",
+ "/phon:Ezhsmall": "\u1D23",
+ "/phon:Gmod": "\u1D33",
+ "/phon:Hmod": "\u1D34",
+ "/phon:Imod": "\u1D35",
+ "/phon:Ismallmod": "\u1DA6",
+ "/phon:Ismallstroke": "\u1D7B",
+ "/phon:Istrokesmallmod": "\u1DA7",
+ "/phon:Jmod": "\u1D36",
+ "/phon:Jsmall": "\u1D0A",
+ "/phon:Kmod": "\u1D37",
+ "/phon:Ksmall": "\u1D0B",
+ "/phon:Lmod": "\u1D38",
+ "/phon:Lsmallmod": "\u1DAB",
+ "/phon:Lsmallstroke": "\u1D0C",
+ "/phon:Mmod": "\u1D39",
+ "/phon:Msmall": "\u1D0D",
+ "/phon:Nmod": "\u1D3A",
+ "/phon:Nreversedmod": "\u1D3B",
+ "/phon:Nsmallmod": "\u1DB0",
+ "/phon:Nsmallreversed": "\u1D0E",
+ "/phon:OUsmall": "\u1D15",
+ "/phon:Omod": "\u1D3C",
+ "/phon:Oopensmall": "\u1D10",
+ "/phon:Osmall": "\u1D0F",
+ "/phon:Oumod": "\u1D3D",
+ "/phon:Pmod": "\u1D3E",
+ "/phon:Psmall": "\u1D18",
+ "/phon:Rmod": "\u1D3F",
+ "/phon:Rsmallreversed": "\u1D19",
+ "/phon:Rsmallturned": "\u1D1A",
+ "/phon:Tmod": "\u1D40",
+ "/phon:Tsmall": "\u1D1B",
+ "/phon:Umod": "\u1D41",
+ "/phon:Usmall": "\u1D1C",
+ "/phon:Usmallmod": "\u1DB8",
+ "/phon:Usmallstroke": "\u1D7E",
+ "/phon:Vsmall": "\u1D20",
+ "/phon:Wmod": "\u1D42",
+ "/phon:Wsmall": "\u1D21",
+ "/phon:Zsmall": "\u1D22",
+ "/phon:aeturned": "\u1D02",
+ "/phon:aeturnedmod": "\u1D46",
+ "/phon:ain": "\u1D25",
+ "/phon:ainmod": "\u1D5C",
+ "/phon:alphamod": "\u1D45",
+ "/phon:alpharetroflexhook": "\u1D90",
+ "/phon:alphaturnedmod": "\u1D9B",
+ "/phon:amod": "\u1D43",
+ "/phon:aretroflexhook": "\u1D8F",
+ "/phon:aturnedmod": "\u1D44",
+ "/phon:betamod": "\u1D5D",
+ "/phon:bmiddletilde": "\u1D6C",
+ "/phon:bmod": "\u1D47",
+ "/phon:bpalatalhook": "\u1D80",
+ "/phon:ccurlmod": "\u1D9D",
+ "/phon:chimod": "\u1D61",
+ "/phon:cmod": "\u1D9C",
+ "/phon:deltamod": "\u1D5F",
+ "/phon:dhooktail": "\u1D91",
+ "/phon:dmiddletilde": "\u1D6D",
+ "/phon:dmod": "\u1D48",
+ "/phon:dotlessjstrokemod": "\u1DA1",
+ "/phon:dpalatalhook": "\u1D81",
+ "/phon:emod": "\u1D49",
+ "/phon:engmod": "\u1D51",
+ "/phon:eopenmod": "\u1D4B",
+ "/phon:eopenretroflexhook": "\u1D93",
+ "/phon:eopenreversedmod": "\u1D9F",
+ "/phon:eopenreversedretroflexhook": "\u1D94",
+ "/phon:eopenturned": "\u1D08",
+ "/phon:eopenturnedmod": "\u1D4C",
+ "/phon:eretroflexhook": "\u1D92",
+ "/phon:eshmod": "\u1DB4",
+ "/phon:eshpalatalhook": "\u1D8B",
+ "/phon:eshretroflexhook": "\u1D98",
+ "/phon:ethmod": "\u1D9E",
+ "/phon:ezhmod": "\u1DBE",
+ "/phon:ezhretroflexhook": "\u1D9A",
+ "/phon:fmiddletilde": "\u1D6E",
+ "/phon:fmod": "\u1DA0",
+ "/phon:fpalatalhook": "\u1D82",
+ "/phon:ginsular": "\u1D79",
+ "/phon:gmod": "\u1D4D",
+ "/phon:gpalatalhook": "\u1D83",
+ "/phon:gr:Gammasmall": "\u1D26",
+ "/phon:gr:Lambdasmall": "\u1D27",
+ "/phon:gr:Pismall": "\u1D28",
+ "/phon:gr:Psismall": "\u1D2A",
+ "/phon:gr:RsmallHO": "\u1D29",
+ "/phon:gr:betasubscript": "\u1D66",
+ "/phon:gr:chisubscript": "\u1D6A",
+ "/phon:gr:gammamod": "\u1D5E",
+ "/phon:gr:gammasubscript": "\u1D67",
+ "/phon:gr:phimod": "\u1D60",
+ "/phon:gr:phisubscript": "\u1D69",
+ "/phon:gr:rhosubscript": "\u1D68",
+ "/phon:gscriptmod": "\u1DA2",
+ "/phon:gturned": "\u1D77",
+ "/phon:hturnedmod": "\u1DA3",
+ "/phon:iotamod": "\u1DA5",
+ "/phon:iotastroke": "\u1D7C",
+ "/phon:iretroflexhook": "\u1D96",
+ "/phon:istrokemod": "\u1DA4",
+ "/phon:isubscript": "\u1D62",
+ "/phon:iturned": "\u1D09",
+ "/phon:iturnedmod": "\u1D4E",
+ "/phon:jcrossedtailmod": "\u1DA8",
+ "/phon:kmod": "\u1D4F",
+ "/phon:kpalatalhook": "\u1D84",
+ "/phon:lpalatalhook": "\u1D85",
+ "/phon:lpalatalhookmod": "\u1DAA",
+ "/phon:lretroflexhookmod": "\u1DA9",
+ "/phon:mhookmod": "\u1DAC",
+ "/phon:mlonglegturnedmod": "\u1DAD",
+ "/phon:mmiddletilde": "\u1D6F",
+ "/phon:mmod": "\u1D50",
+ "/phon:mpalatalhook": "\u1D86",
+ "/phon:mturnedmod": "\u1D5A",
+ "/phon:mturnedsideways": "\u1D1F",
+ "/phon:nlefthookmod": "\u1DAE",
+ "/phon:nmiddletilde": "\u1D70",
+ "/phon:npalatalhook": "\u1D87",
+ "/phon:nretroflexhookmod": "\u1DAF",
+ "/phon:obarmod": "\u1DB1",
+ "/phon:obottomhalf": "\u1D17",
+ "/phon:obottomhalfmod": "\u1D55",
+ "/phon:oeturned": "\u1D14",
+ "/phon:omod": "\u1D52",
+ "/phon:oopenmod": "\u1D53",
+ "/phon:oopenretroflexhook": "\u1D97",
+ "/phon:oopensideways": "\u1D12",
+ "/phon:osideways": "\u1D11",
+ "/phon:ostrokesideways": "\u1D13",
+ "/phon:otophalf": "\u1D16",
+ "/phon:otophalfmod": "\u1D54",
+ "/phon:phimod": "\u1DB2",
+ "/phon:pmiddletilde": "\u1D71",
+ "/phon:pmod": "\u1D56",
+ "/phon:ppalatalhook": "\u1D88",
+ "/phon:pstroke": "\u1D7D",
+ "/phon:rfishmiddletilde": "\u1D73",
+ "/phon:rmiddletilde": "\u1D72",
+ "/phon:rpalatalhook": "\u1D89",
+ "/phon:rsubscript": "\u1D63",
+ "/phon:schwamod": "\u1D4A",
+ "/phon:schwaretroflexhook": "\u1D95",
+ "/phon:shookmod": "\u1DB3",
+ "/phon:smiddletilde": "\u1D74",
+ "/phon:spalatalhook": "\u1D8A",
+ "/phon:spirantvoicedlaryngeal": "\u1D24",
+ "/phon:thetamod": "\u1DBF",
+ "/phon:thstrike": "\u1D7A",
+ "/phon:tmiddletilde": "\u1D75",
+ "/phon:tmod": "\u1D57",
+ "/phon:tpalatalhookmod": "\u1DB5",
+ "/phon:ubarmod": "\u1DB6",
+ "/phon:ue": "\u1D6B",
+ "/phon:umod": "\u1D58",
+ "/phon:upsilonmod": "\u1DB7",
+ "/phon:upsilonstroke": "\u1D7F",
+ "/phon:uretroflexhook": "\u1D99",
+ "/phon:usideways": "\u1D1D",
+ "/phon:usidewaysdieresised": "\u1D1E",
+ "/phon:usidewaysmod": "\u1D59",
+ "/phon:usubscript": "\u1D64",
+ "/phon:vhookmod": "\u1DB9",
+ "/phon:vmod": "\u1D5B",
+ "/phon:vpalatalhook": "\u1D8C",
+ "/phon:vsubscript": "\u1D65",
+ "/phon:vturnedmod": "\u1DBA",
+ "/phon:xpalatalhook": "\u1D8D",
+ "/phon:zcurlmod": "\u1DBD",
+ "/phon:zmiddletilde": "\u1D76",
+ "/phon:zmod": "\u1DBB",
+ "/phon:zpalatalhook": "\u1D8E",
+ "/phon:zretroflexhookmod": "\u1DBC",
+ "/phook": "\u01A5",
+ "/phophanthai": "\u0E1E",
+ "/phophungthai": "\u0E1C",
+ "/phosamphaothai": "\u0E20",
+ "/pi": "\u03C0",
+ "/pi.math": "\u03D6",
+ "/piasutorusquare": "\u332E",
+ "/pick": "\u26CF",
+ "/pidblstruck": "\u213C",
+ "/pieupacirclekorean": "\u3273",
+ "/pieupaparenkorean": "\u3213",
+ "/pieupcieuckorean": "\u3176",
+ "/pieupcirclekorean": "\u3265",
+ "/pieupkiyeokkorean": "\u3172",
+ "/pieupkorean": "\u3142",
+ "/pieupparenkorean": "\u3205",
+ "/pieupsioskiyeokkorean": "\u3174",
+ "/pieupsioskorean": "\u3144",
+ "/pieupsiostikeutkorean": "\u3175",
+ "/pieupthieuthkorean": "\u3177",
+ "/pieuptikeutkorean": "\u3173",
+ "/pig": "\u1F416",
+ "/pigFace": "\u1F437",
+ "/pigNose": "\u1F43D",
+ "/pihiragana": "\u3074",
+ "/pikatakana": "\u30D4",
+ "/pikosquare": "\u3330",
+ "/pikurusquare": "\u332F",
+ "/pilcrowsignreversed": "\u204B",
+ "/pileOfPoo": "\u1F4A9",
+ "/pill": "\u1F48A",
+ "/pineDecoration": "\u1F38D",
+ "/pineapple": "\u1F34D",
+ "/pisces": "\u2653",
+ "/piselehpada": "\uA9CC",
+ "/pistol": "\u1F52B",
+ "/pisymbolgreek": "\u03D6",
+ "/pitchfork": "\u22D4",
+ "/piwrarmenian": "\u0583",
+ "/placeOfWorship": "\u1F6D0",
+ "/placeofinterestsign": "\u2318",
+ "/planck": "\u210E",
+ "/plancktwopi": "\u210F",
+ "/plus": "\u002B",
+ "/plus.inferior": "\u208A",
+ "/plus.superior": "\u207A",
+ "/plusbelowcmb": "\u031F",
+ "/pluscircle": "\u2295",
+ "/plusminus": "\u00B1",
+ "/plusmod": "\u02D6",
+ "/plusmonospace": "\uFF0B",
+ "/plussignalt:hb": "\uFB29",
+ "/plussignmod": "\u02D6",
+ "/plussmall": "\uFE62",
+ "/plussuperior": "\u207A",
+ "/pluto": "\u2647",
+ "/pmfullwidth": "\u33D8",
+ "/pmonospace": "\uFF50",
+ "/pmsquare": "\u33D8",
+ "/pocketCalculator": "\u1F5A9",
+ "/poeticverse": "\u060E",
+ "/pohiragana": "\u307D",
+ "/pointerleftblack": "\u25C4",
+ "/pointerleftwhite": "\u25C5",
+ "/pointerrightblack": "\u25BA",
+ "/pointerrightwhite": "\u25BB",
+ "/pointingindexdownwhite": "\u261F",
+ "/pointingindexleftblack": "\u261A",
+ "/pointingindexleftwhite": "\u261C",
+ "/pointingindexrightblack": "\u261B",
+ "/pointingindexrightwhite": "\u261E",
+ "/pointingindexupwhite": "\u261D",
+ "/pointingtriangledownheavywhite": "\u26DB",
+ "/pointosquare": "\u333D",
+ "/pointring": "\u2E30",
+ "/pokatakana": "\u30DD",
+ "/pokrytiecmbcyr": "\u0487",
+ "/policeCar": "\u1F693",
+ "/policeCarsRevolvingLight": "\u1F6A8",
+ "/policeOfficer": "\u1F46E",
+ "/pondosquare": "\u3340",
+ "/poodle": "\u1F429",
+ "/popcorn": "\u1F37F",
+ "/popdirectionalformatting": "\u202C",
+ "/popdirectionalisolate": "\u2069",
+ "/poplathai": "\u0E1B",
+ "/portableStereo": "\u1F4FE",
+ "/positionindicator": "\u2316",
+ "/postalHorn": "\u1F4EF",
+ "/postalmark": "\u3012",
+ "/postalmarkface": "\u3020",
+ "/postbox": "\u1F4EE",
+ "/potOfFood": "\u1F372",
+ "/potableWater": "\u1F6B0",
+ "/pouch": "\u1F45D",
+ "/poultryLeg": "\u1F357",
+ "/poutingCatFace": "\u1F63E",
+ "/poutingFace": "\u1F621",
+ "/power": "\u23FB",
+ "/poweron": "\u23FD",
+ "/poweronoff": "\u23FC",
+ "/powersleep": "\u23FE",
+ "/pparen": "\u24AB",
+ "/pparenthesized": "\u24AB",
+ "/ppmfullwidth": "\u33D9",
+ "/prayerBeads": "\u1F4FF",
+ "/precedes": "\u227A",
+ "/precedesbutnotequivalent": "\u22E8",
+ "/precedesorequal": "\u227C",
+ "/precedesorequivalent": "\u227E",
+ "/precedesunderrelation": "\u22B0",
+ "/prescription": "\u211E",
+ "/preversedepigraphic": "\uA7FC",
+ "/previouspage": "\u2397",
+ "/prfullwidth": "\u33DA",
+ "/primedblmod": "\u02BA",
+ "/primemod": "\u02B9",
+ "/primereversed": "\u2035",
+ "/princess": "\u1F478",
+ "/printer": "\u1F5A8",
+ "/printerIcon": "\u1F5B6",
+ "/printideographiccircled": "\u329E",
+ "/printscreen": "\u2399",
+ "/product": "\u220F",
+ "/prohibitedSign": "\u1F6C7",
+ "/projective": "\u2305",
+ "/prolongedkana": "\u30FC",
+ "/propellor": "\u2318",
+ "/propersubset": "\u2282",
+ "/propersuperset": "\u2283",
+ "/propertyline": "\u214A",
+ "/proportion": "\u2237",
+ "/proportional": "\u221D",
+ "/psfullwidth": "\u33B0",
+ "/psi": "\u03C8",
+ "/psicyr": "\u0471",
+ "/psicyrillic": "\u0471",
+ "/psilicmbcyr": "\u0486",
+ "/psilipneumatacyrilliccmb": "\u0486",
+ "/pssquare": "\u33B0",
+ "/pstrokedescender": "\uA751",
+ "/ptail": "\uA755",
+ "/publicAddressLoudspeaker": "\u1F4E2",
+ "/puhiragana": "\u3077",
+ "/pukatakana": "\u30D7",
+ "/punctuationspace": "\u2008",
+ "/purpleHeart": "\u1F49C",
+ "/purse": "\u1F45B",
+ "/pushpin": "\u1F4CC",
+ "/putLitterInItsPlace": "\u1F6AE",
+ "/pvfullwidth": "\u33B4",
+ "/pvsquare": "\u33B4",
+ "/pwfullwidth": "\u33BA",
+ "/pwsquare": "\u33BA",
+ "/q": "\u0071",
+ "/qacyr": "\u051B",
+ "/qadeva": "\u0958",
+ "/qadma:hb": "\u05A8",
+ "/qadmahebrew": "\u05A8",
+ "/qaf": "\u0642",
+ "/qaf.fina": "\uFED6",
+ "/qaf.init": "\uFED7",
+ "/qaf.init_alefmaksura.fina": "\uFC35",
+ "/qaf.init_hah.fina": "\uFC33",
+ "/qaf.init_hah.medi": "\uFCC2",
+ "/qaf.init_meem.fina": "\uFC34",
+ "/qaf.init_meem.medi": "\uFCC3",
+ "/qaf.init_meem.medi_hah.medi": "\uFDB4",
+ "/qaf.init_yeh.fina": "\uFC36",
+ "/qaf.isol": "\uFED5",
+ "/qaf.medi": "\uFED8",
+ "/qaf.medi_alefmaksura.fina": "\uFC7E",
+ "/qaf.medi_meem.medi_hah.fina": "\uFD7E",
+ "/qaf.medi_meem.medi_meem.fina": "\uFD7F",
+ "/qaf.medi_meem.medi_yeh.fina": "\uFDB2",
+ "/qaf.medi_yeh.fina": "\uFC7F",
+ "/qaf_lam_alefmaksuraabove": "\u06D7",
+ "/qafarabic": "\u0642",
+ "/qafdotabove": "\u06A7",
+ "/qaffinalarabic": "\uFED6",
+ "/qafinitialarabic": "\uFED7",
+ "/qafmedialarabic": "\uFED8",
+ "/qafthreedotsabove": "\u06A8",
+ "/qamats": "\u05B8",
+ "/qamats10": "\u05B8",
+ "/qamats1a": "\u05B8",
+ "/qamats1c": "\u05B8",
+ "/qamats27": "\u05B8",
+ "/qamats29": "\u05B8",
+ "/qamats33": "\u05B8",
+ "/qamats:hb": "\u05B8",
+ "/qamatsQatan:hb": "\u05C7",
+ "/qamatsde": "\u05B8",
+ "/qamatshebrew": "\u05B8",
+ "/qamatsnarrowhebrew": "\u05B8",
+ "/qamatsqatanhebrew": "\u05B8",
+ "/qamatsqatannarrowhebrew": "\u05B8",
+ "/qamatsqatanquarterhebrew": "\u05B8",
+ "/qamatsqatanwidehebrew": "\u05B8",
+ "/qamatsquarterhebrew": "\u05B8",
+ "/qamatswidehebrew": "\u05B8",
+ "/qarneFarah:hb": "\u059F",
+ "/qarneyparahebrew": "\u059F",
+ "/qbopomofo": "\u3111",
+ "/qcircle": "\u24E0",
+ "/qdiagonalstroke": "\uA759",
+ "/qhook": "\u02A0",
+ "/qhooktail": "\u024B",
+ "/qmonospace": "\uFF51",
+ "/qof": "\u05E7",
+ "/qof:hb": "\u05E7",
+ "/qofdagesh": "\uFB47",
+ "/qofdageshhebrew": "\uFB47",
+ "/qofhatafpatah": "\u05E7",
+ "/qofhatafpatahhebrew": "\u05E7",
+ "/qofhatafsegol": "\u05E7",
+ "/qofhatafsegolhebrew": "\u05E7",
+ "/qofhebrew": "\u05E7",
+ "/qofhiriq": "\u05E7",
+ "/qofhiriqhebrew": "\u05E7",
+ "/qofholam": "\u05E7",
+ "/qofholamhebrew": "\u05E7",
+ "/qofpatah": "\u05E7",
+ "/qofpatahhebrew": "\u05E7",
+ "/qofqamats": "\u05E7",
+ "/qofqamatshebrew": "\u05E7",
+ "/qofqubuts": "\u05E7",
+ "/qofqubutshebrew": "\u05E7",
+ "/qofsegol": "\u05E7",
+ "/qofsegolhebrew": "\u05E7",
+ "/qofsheva": "\u05E7",
+ "/qofshevahebrew": "\u05E7",
+ "/qoftsere": "\u05E7",
+ "/qoftserehebrew": "\u05E7",
+ "/qofwithdagesh:hb": "\uFB47",
+ "/qparen": "\u24AC",
+ "/qparenthesized": "\u24AC",
+ "/qpdigraph": "\u0239",
+ "/qstrokedescender": "\uA757",
+ "/quadarrowdownfunc": "\u2357",
+ "/quadarrowleftfunc": "\u2347",
+ "/quadarrowrightfunc": "\u2348",
+ "/quadarrowupfunc": "\u2350",
+ "/quadbackslashfunc": "\u2342",
+ "/quadcaretdownfunc": "\u234C",
+ "/quadcaretupfunc": "\u2353",
+ "/quadcirclefunc": "\u233C",
+ "/quadcolonfunc": "\u2360",
+ "/quaddelfunc": "\u2354",
+ "/quaddeltafunc": "\u234D",
+ "/quaddiamondfunc": "\u233A",
+ "/quaddividefunc": "\u2339",
+ "/quadequalfunc": "\u2338",
+ "/quadfunc": "\u2395",
+ "/quadgreaterfunc": "\u2344",
+ "/quadjotfunc": "\u233B",
+ "/quadlessfunc": "\u2343",
+ "/quadnotequalfunc": "\u236F",
+ "/quadquestionfunc": "\u2370",
+ "/quadrantLowerLeft": "\u2596",
+ "/quadrantLowerRight": "\u2597",
+ "/quadrantUpperLeft": "\u2598",
+ "/quadrantUpperLeftAndLowerLeftAndLowerRight": "\u2599",
+ "/quadrantUpperLeftAndLowerRight": "\u259A",
+ "/quadrantUpperLeftAndUpperRightAndLowerLeft": "\u259B",
+ "/quadrantUpperLeftAndUpperRightAndLowerRight": "\u259C",
+ "/quadrantUpperRight": "\u259D",
+ "/quadrantUpperRightAndLowerLeft": "\u259E",
+ "/quadrantUpperRightAndLowerLeftAndLowerRight": "\u259F",
+ "/quadrupleminute": "\u2057",
+ "/quadslashfunc": "\u2341",
+ "/quarternote": "\u2669",
+ "/qubuts": "\u05BB",
+ "/qubuts18": "\u05BB",
+ "/qubuts25": "\u05BB",
+ "/qubuts31": "\u05BB",
+ "/qubuts:hb": "\u05BB",
+ "/qubutshebrew": "\u05BB",
+ "/qubutsnarrowhebrew": "\u05BB",
+ "/qubutsquarterhebrew": "\u05BB",
+ "/qubutswidehebrew": "\u05BB",
+ "/queenblack": "\u265B",
+ "/queenwhite": "\u2655",
+ "/question": "\u003F",
+ "/questionarabic": "\u061F",
+ "/questionarmenian": "\u055E",
+ "/questiondbl": "\u2047",
+ "/questiondown": "\u00BF",
+ "/questiondownsmall": "\uF7BF",
+ "/questionedequal": "\u225F",
+ "/questionexclamationmark": "\u2048",
+ "/questiongreek": "\u037E",
+ "/questionideographiccircled": "\u3244",
+ "/questionmonospace": "\uFF1F",
+ "/questionreversed": "\u2E2E",
+ "/questionsmall": "\uF73F",
+ "/quincunx": "\u26BB",
+ "/quotedbl": "\u0022",
+ "/quotedblbase": "\u201E",
+ "/quotedblleft": "\u201C",
+ "/quotedbllowreversed": "\u2E42",
+ "/quotedblmonospace": "\uFF02",
+ "/quotedblprime": "\u301E",
+ "/quotedblprimereversed": "\u301D",
+ "/quotedblreversed": "\u201F",
+ "/quotedblright": "\u201D",
+ "/quoteleft": "\u2018",
+ "/quoteleftreversed": "\u201B",
+ "/quotequadfunc": "\u235E",
+ "/quotereversed": "\u201B",
+ "/quoteright": "\u2019",
+ "/quoterightn": "\u0149",
+ "/quotesinglbase": "\u201A",
+ "/quotesingle": "\u0027",
+ "/quotesinglemonospace": "\uFF07",
+ "/quoteunderlinefunc": "\u2358",
+ "/r": "\u0072",
+ "/raagung": "\uA9AC",
+ "/raarmenian": "\u057C",
+ "/rabbit": "\u1F407",
+ "/rabbitFace": "\u1F430",
+ "/rabengali": "\u09B0",
+ "/racingCar": "\u1F3CE",
+ "/racingMotorcycle": "\u1F3CD",
+ "/racirclekatakana": "\u32F6",
+ "/racute": "\u0155",
+ "/radeva": "\u0930",
+ "/radfullwidth": "\u33AD",
+ "/radical": "\u221A",
+ "/radicalbottom": "\u23B7",
+ "/radicalex": "\uF8E5",
+ "/radio": "\u1F4FB",
+ "/radioButton": "\u1F518",
+ "/radioactive": "\u2622",
+ "/radovers2fullwidth": "\u33AF",
+ "/radoversfullwidth": "\u33AE",
+ "/radoverssquare": "\u33AE",
+ "/radoverssquaredsquare": "\u33AF",
+ "/radsquare": "\u33AD",
+ "/rafe": "\u05BF",
+ "/rafe:hb": "\u05BF",
+ "/rafehebrew": "\u05BF",
+ "/ragujarati": "\u0AB0",
+ "/ragurmukhi": "\u0A30",
+ "/rahiragana": "\u3089",
+ "/railwayCar": "\u1F683",
+ "/railwayTrack": "\u1F6E4",
+ "/rain": "\u26C6",
+ "/rainbow": "\u1F308",
+ "/raisedHandFingersSplayed": "\u1F590",
+ "/raisedHandPartBetweenMiddleAndRingFingers": "\u1F596",
+ "/raisedmcsign": "\u1F16A",
+ "/raisedmdsign": "\u1F16B",
+ "/rakatakana": "\u30E9",
+ "/rakatakanahalfwidth": "\uFF97",
+ "/ralowerdiagonalbengali": "\u09F1",
+ "/ram": "\u1F40F",
+ "/ramiddlediagonalbengali": "\u09F0",
+ "/ramshorn": "\u0264",
+ "/rat": "\u1F400",
+ "/ratio": "\u2236",
+ "/ray": "\u0608",
+ "/rbopomofo": "\u3116",
+ "/rcaron": "\u0159",
+ "/rcedilla": "\u0157",
+ "/rcircle": "\u24E1",
+ "/rcommaaccent": "\u0157",
+ "/rdblgrave": "\u0211",
+ "/rdot": "\u1E59",
+ "/rdotaccent": "\u1E59",
+ "/rdotbelow": "\u1E5B",
+ "/rdotbelowmacron": "\u1E5D",
+ "/reachideographicparen": "\u3243",
+ "/recirclekatakana": "\u32F9",
+ "/recreationalVehicle": "\u1F699",
+ "/rectangleblack": "\u25AC",
+ "/rectangleverticalblack": "\u25AE",
+ "/rectangleverticalwhite": "\u25AF",
+ "/rectanglewhite": "\u25AD",
+ "/recycledpaper": "\u267C",
+ "/recyclefiveplastics": "\u2677",
+ "/recyclefourplastics": "\u2676",
+ "/recyclegeneric": "\u267A",
+ "/recycleoneplastics": "\u2673",
+ "/recyclepartiallypaper": "\u267D",
+ "/recyclesevenplastics": "\u2679",
+ "/recyclesixplastics": "\u2678",
+ "/recyclethreeplastics": "\u2675",
+ "/recycletwoplastics": "\u2674",
+ "/recycleuniversal": "\u2672",
+ "/recycleuniversalblack": "\u267B",
+ "/redApple": "\u1F34E",
+ "/redTriangleDOwn": "\u1F53B",
+ "/redTriangleUp": "\u1F53A",
+ "/referencemark": "\u203B",
+ "/reflexsubset": "\u2286",
+ "/reflexsuperset": "\u2287",
+ "/regionalindicatorsymbollettera": "\u1F1E6",
+ "/regionalindicatorsymbolletterb": "\u1F1E7",
+ "/regionalindicatorsymbolletterc": "\u1F1E8",
+ "/regionalindicatorsymbolletterd": "\u1F1E9",
+ "/regionalindicatorsymbollettere": "\u1F1EA",
+ "/regionalindicatorsymbolletterf": "\u1F1EB",
+ "/regionalindicatorsymbolletterg": "\u1F1EC",
+ "/regionalindicatorsymbolletterh": "\u1F1ED",
+ "/regionalindicatorsymbolletteri": "\u1F1EE",
+ "/regionalindicatorsymbolletterj": "\u1F1EF",
+ "/regionalindicatorsymbolletterk": "\u1F1F0",
+ "/regionalindicatorsymbolletterl": "\u1F1F1",
+ "/regionalindicatorsymbolletterm": "\u1F1F2",
+ "/regionalindicatorsymbollettern": "\u1F1F3",
+ "/regionalindicatorsymbollettero": "\u1F1F4",
+ "/regionalindicatorsymbolletterp": "\u1F1F5",
+ "/regionalindicatorsymbolletterq": "\u1F1F6",
+ "/regionalindicatorsymbolletterr": "\u1F1F7",
+ "/regionalindicatorsymbolletters": "\u1F1F8",
+ "/regionalindicatorsymbollettert": "\u1F1F9",
+ "/regionalindicatorsymbolletteru": "\u1F1FA",
+ "/regionalindicatorsymbolletterv": "\u1F1FB",
+ "/regionalindicatorsymbolletterw": "\u1F1FC",
+ "/regionalindicatorsymbolletterx": "\u1F1FD",
+ "/regionalindicatorsymbollettery": "\u1F1FE",
+ "/regionalindicatorsymbolletterz": "\u1F1FF",
+ "/registered": "\u00AE",
+ "/registersans": "\uF8E8",
+ "/registerserif": "\uF6DA",
+ "/reh.fina": "\uFEAE",
+ "/reh.init_superscriptalef.fina": "\uFC5C",
+ "/reh.isol": "\uFEAD",
+ "/rehHamzaAbove": "\u076C",
+ "/rehSmallTahTwoDots": "\u0771",
+ "/rehStroke": "\u075B",
+ "/rehTwoDotsVerticallyAbove": "\u076B",
+ "/rehVabove": "\u0692",
+ "/rehVbelow": "\u0695",
+ "/reharabic": "\u0631",
+ "/reharmenian": "\u0580",
+ "/rehdotbelow": "\u0694",
+ "/rehdotbelowdotabove": "\u0696",
+ "/rehfinalarabic": "\uFEAE",
+ "/rehfourdotsabove": "\u0699",
+ "/rehinvertedV": "\u06EF",
+ "/rehiragana": "\u308C",
+ "/rehring": "\u0693",
+ "/rehtwodotsabove": "\u0697",
+ "/rehyehaleflamarabic": "\u0631",
+ "/rekatakana": "\u30EC",
+ "/rekatakanahalfwidth": "\uFF9A",
+ "/relievedFace": "\u1F60C",
+ "/religionideographiccircled": "\u32AA",
+ "/reminderRibbon": "\u1F397",
+ "/remusquare": "\u3355",
+ "/rentogensquare": "\u3356",
+ "/replacementchar": "\uFFFD",
+ "/replacementcharobj": "\uFFFC",
+ "/representideographicparen": "\u3239",
+ "/rerengganleft": "\uA9C1",
+ "/rerengganright": "\uA9C2",
+ "/resh": "\u05E8",
+ "/resh:hb": "\u05E8",
+ "/reshdageshhebrew": "\uFB48",
+ "/reshhatafpatah": "\u05E8",
+ "/reshhatafpatahhebrew": "\u05E8",
+ "/reshhatafsegol": "\u05E8",
+ "/reshhatafsegolhebrew": "\u05E8",
+ "/reshhebrew": "\u05E8",
+ "/reshhiriq": "\u05E8",
+ "/reshhiriqhebrew": "\u05E8",
+ "/reshholam": "\u05E8",
+ "/reshholamhebrew": "\u05E8",
+ "/reshpatah": "\u05E8",
+ "/reshpatahhebrew": "\u05E8",
+ "/reshqamats": "\u05E8",
+ "/reshqamatshebrew": "\u05E8",
+ "/reshqubuts": "\u05E8",
+ "/reshqubutshebrew": "\u05E8",
+ "/reshsegol": "\u05E8",
+ "/reshsegolhebrew": "\u05E8",
+ "/reshsheva": "\u05E8",
+ "/reshshevahebrew": "\u05E8",
+ "/reshtsere": "\u05E8",
+ "/reshtserehebrew": "\u05E8",
+ "/reshwide:hb": "\uFB27",
+ "/reshwithdagesh:hb": "\uFB48",
+ "/resourceideographiccircled": "\u32AE",
+ "/resourceideographicparen": "\u323E",
+ "/response": "\u211F",
+ "/restideographiccircled": "\u32A1",
+ "/restideographicparen": "\u3241",
+ "/restrictedentryoneleft": "\u26E0",
+ "/restrictedentrytwoleft": "\u26E1",
+ "/restroom": "\u1F6BB",
+ "/return": "\u23CE",
+ "/reversedHandMiddleFingerExtended": "\u1F595",
+ "/reversedRaisedHandFingersSplayed": "\u1F591",
+ "/reversedThumbsDownSign": "\u1F593",
+ "/reversedThumbsUpSign": "\u1F592",
+ "/reversedVictoryHand": "\u1F594",
+ "/reversedonehundred.roman": "\u2183",
+ "/reversedtilde": "\u223D",
+ "/reversedzecyr": "\u0511",
+ "/revia:hb": "\u0597",
+ "/reviahebrew": "\u0597",
+ "/reviamugrashhebrew": "\u0597",
+ "/revlogicalnot": "\u2310",
+ "/revolvingHearts": "\u1F49E",
+ "/rfishhook": "\u027E",
+ "/rfishhookreversed": "\u027F",
+ "/rgravedbl": "\u0211",
+ "/rhabengali": "\u09DD",
+ "/rhacyr": "\u0517",
+ "/rhadeva": "\u095D",
+ "/rho": "\u03C1",
+ "/rhoasper": "\u1FE5",
+ "/rhofunc": "\u2374",
+ "/rholenis": "\u1FE4",
+ "/rhook": "\u027D",
+ "/rhookturned": "\u027B",
+ "/rhookturnedsuperior": "\u02B5",
+ "/rhookturnedsupmod": "\u02B5",
+ "/rhostrokesymbol": "\u03FC",
+ "/rhosymbol": "\u03F1",
+ "/rhosymbolgreek": "\u03F1",
+ "/rhotichookmod": "\u02DE",
+ "/rial": "\uFDFC",
+ "/ribbon": "\u1F380",
+ "/riceBall": "\u1F359",
+ "/riceCracker": "\u1F358",
+ "/ricirclekatakana": "\u32F7",
+ "/rieulacirclekorean": "\u3271",
+ "/rieulaparenkorean": "\u3211",
+ "/rieulcirclekorean": "\u3263",
+ "/rieulhieuhkorean": "\u3140",
+ "/rieulkiyeokkorean": "\u313A",
+ "/rieulkiyeoksioskorean": "\u3169",
+ "/rieulkorean": "\u3139",
+ "/rieulmieumkorean": "\u313B",
+ "/rieulpansioskorean": "\u316C",
+ "/rieulparenkorean": "\u3203",
+ "/rieulphieuphkorean": "\u313F",
+ "/rieulpieupkorean": "\u313C",
+ "/rieulpieupsioskorean": "\u316B",
+ "/rieulsioskorean": "\u313D",
+ "/rieulthieuthkorean": "\u313E",
+ "/rieultikeutkorean": "\u316A",
+ "/rieulyeorinhieuhkorean": "\u316D",
+ "/right-pointingMagnifyingGlass": "\u1F50E",
+ "/rightAngerBubble": "\u1F5EF",
+ "/rightHalfBlock": "\u2590",
+ "/rightHandTelephoneReceiver": "\u1F57D",
+ "/rightOneEighthBlock": "\u2595",
+ "/rightSpeaker": "\u1F568",
+ "/rightSpeakerOneSoundWave": "\u1F569",
+ "/rightSpeakerThreeSoundWaves": "\u1F56A",
+ "/rightSpeechBubble": "\u1F5E9",
+ "/rightThoughtBubble": "\u1F5ED",
+ "/rightangle": "\u221F",
+ "/rightarrowoverleftarrow": "\u21C4",
+ "/rightdnheavyleftuplight": "\u2546",
+ "/rightharpoonoverleftharpoon": "\u21CC",
+ "/rightheavyleftdnlight": "\u252E",
+ "/rightheavyleftuplight": "\u2536",
+ "/rightheavyleftvertlight": "\u253E",
+ "/rightideographiccircled": "\u32A8",
+ "/rightlightleftdnheavy": "\u2531",
+ "/rightlightleftupheavy": "\u2539",
+ "/rightlightleftvertheavy": "\u2549",
+ "/righttackbelowcmb": "\u0319",
+ "/righttoleftembed": "\u202B",
+ "/righttoleftisolate": "\u2067",
+ "/righttoleftmark": "\u200F",
+ "/righttoleftoverride": "\u202E",
+ "/righttriangle": "\u22BF",
+ "/rightupheavyleftdnlight": "\u2544",
+ "/rihiragana": "\u308A",
+ "/rikatakana": "\u30EA",
+ "/rikatakanahalfwidth": "\uFF98",
+ "/ring": "\u02DA",
+ "/ringbelowcmb": "\u0325",
+ "/ringcmb": "\u030A",
+ "/ringequal": "\u2257",
+ "/ringhalfleft": "\u02BF",
+ "/ringhalfleftarmenian": "\u0559",
+ "/ringhalfleftbelowcmb": "\u031C",
+ "/ringhalfleftcentered": "\u02D3",
+ "/ringhalfleftcentredmod": "\u02D3",
+ "/ringhalfleftmod": "\u02BF",
+ "/ringhalfright": "\u02BE",
+ "/ringhalfrightbelowcmb": "\u0339",
+ "/ringhalfrightcentered": "\u02D2",
+ "/ringhalfrightcentredmod": "\u02D2",
+ "/ringhalfrightmod": "\u02BE",
+ "/ringinequal": "\u2256",
+ "/ringingBell": "\u1F56D",
+ "/ringlowmod": "\u02F3",
+ "/ringoperator": "\u2218",
+ "/rinsular": "\uA783",
+ "/rinvertedbreve": "\u0213",
+ "/rirasquare": "\u3352",
+ "/risingdiagonal": "\u27CB",
+ "/rittorusquare": "\u3351",
+ "/rlinebelow": "\u1E5F",
+ "/rlongleg": "\u027C",
+ "/rlonglegturned": "\u027A",
+ "/rmacrondot": "\u1E5D",
+ "/rmonospace": "\uFF52",
+ "/rnoon": "\u06BB",
+ "/rnoon.fina": "\uFBA1",
+ "/rnoon.init": "\uFBA2",
+ "/rnoon.isol": "\uFBA0",
+ "/rnoon.medi": "\uFBA3",
+ "/roastedSweetPotato": "\u1F360",
+ "/robliquestroke": "\uA7A7",
+ "/rocirclekatakana": "\u32FA",
+ "/rocket": "\u1F680",
+ "/rohiragana": "\u308D",
+ "/rokatakana": "\u30ED",
+ "/rokatakanahalfwidth": "\uFF9B",
+ "/rolled-upNewspaper": "\u1F5DE",
+ "/rollerCoaster": "\u1F3A2",
+ "/rookblack": "\u265C",
+ "/rookwhite": "\u2656",
+ "/rooster": "\u1F413",
+ "/roruathai": "\u0E23",
+ "/rose": "\u1F339",
+ "/rosette": "\u1F3F5",
+ "/roundPushpin": "\u1F4CD",
+ "/roundedzeroabove": "\u06DF",
+ "/rowboat": "\u1F6A3",
+ "/rparen": "\u24AD",
+ "/rparenthesized": "\u24AD",
+ "/rrabengali": "\u09DC",
+ "/rradeva": "\u0931",
+ "/rragurmukhi": "\u0A5C",
+ "/rreh": "\u0691",
+ "/rreh.fina": "\uFB8D",
+ "/rreh.isol": "\uFB8C",
+ "/rreharabic": "\u0691",
+ "/rrehfinalarabic": "\uFB8D",
+ "/rrotunda": "\uA75B",
+ "/rrvocalicbengali": "\u09E0",
+ "/rrvocalicdeva": "\u0960",
+ "/rrvocalicgujarati": "\u0AE0",
+ "/rrvocalicvowelsignbengali": "\u09C4",
+ "/rrvocalicvowelsigndeva": "\u0944",
+ "/rrvocalicvowelsigngujarati": "\u0AC4",
+ "/rstroke": "\u024D",
+ "/rsuperior": "\uF6F1",
+ "/rsupmod": "\u02B3",
+ "/rtailturned": "\u2C79",
+ "/rtblock": "\u2590",
+ "/rturned": "\u0279",
+ "/rturnedsuperior": "\u02B4",
+ "/rturnedsupmod": "\u02B4",
+ "/ruble": "\u20BD",
+ "/rucirclekatakana": "\u32F8",
+ "/rugbyFootball": "\u1F3C9",
+ "/ruhiragana": "\u308B",
+ "/rukatakana": "\u30EB",
+ "/rukatakanahalfwidth": "\uFF99",
+ "/rum": "\uA775",
+ "/rumrotunda": "\uA75D",
+ "/runner": "\u1F3C3",
+ "/runningShirtSash": "\u1F3BD",
+ "/rupeemarkbengali": "\u09F2",
+ "/rupeesignbengali": "\u09F3",
+ "/rupiah": "\uF6DD",
+ "/rupiisquare": "\u3353",
+ "/ruthai": "\u0E24",
+ "/ruuburusquare": "\u3354",
+ "/rvocalicbengali": "\u098B",
+ "/rvocalicdeva": "\u090B",
+ "/rvocalicgujarati": "\u0A8B",
+ "/rvocalicvowelsignbengali": "\u09C3",
+ "/rvocalicvowelsigndeva": "\u0943",
+ "/rvocalicvowelsigngujarati": "\u0AC3",
+ "/s": "\u0073",
+ "/s.inferior": "\u209B",
+ "/s_t": "\uFB06",
+ "/sabengali": "\u09B8",
+ "/sacirclekatakana": "\u32DA",
+ "/sacute": "\u015B",
+ "/sacutedotaccent": "\u1E65",
+ "/sad": "\u0635",
+ "/sad.fina": "\uFEBA",
+ "/sad.init": "\uFEBB",
+ "/sad.init_alefmaksura.fina": "\uFD05",
+ "/sad.init_hah.fina": "\uFC20",
+ "/sad.init_hah.medi": "\uFCB1",
+ "/sad.init_hah.medi_hah.medi": "\uFD65",
+ "/sad.init_khah.medi": "\uFCB2",
+ "/sad.init_meem.fina": "\uFC21",
+ "/sad.init_meem.medi": "\uFCB3",
+ "/sad.init_meem.medi_meem.medi": "\uFDC5",
+ "/sad.init_reh.fina": "\uFD0F",
+ "/sad.init_yeh.fina": "\uFD06",
+ "/sad.isol": "\uFEB9",
+ "/sad.medi": "\uFEBC",
+ "/sad.medi_alefmaksura.fina": "\uFD21",
+ "/sad.medi_hah.medi_hah.fina": "\uFD64",
+ "/sad.medi_hah.medi_yeh.fina": "\uFDA9",
+ "/sad.medi_meem.medi_meem.fina": "\uFD66",
+ "/sad.medi_reh.fina": "\uFD2B",
+ "/sad.medi_yeh.fina": "\uFD22",
+ "/sad_lam_alefmaksuraabove": "\u06D6",
+ "/sadarabic": "\u0635",
+ "/sadeva": "\u0938",
+ "/sadfinalarabic": "\uFEBA",
+ "/sadinitialarabic": "\uFEBB",
+ "/sadmedialarabic": "\uFEBC",
+ "/sadthreedotsabove": "\u069E",
+ "/sadtwodotsbelow": "\u069D",
+ "/sagittarius": "\u2650",
+ "/sagujarati": "\u0AB8",
+ "/sagurmukhi": "\u0A38",
+ "/sahiragana": "\u3055",
+ "/saikurusquare": "\u331F",
+ "/sailboat": "\u26F5",
+ "/sakatakana": "\u30B5",
+ "/sakatakanahalfwidth": "\uFF7B",
+ "/sakeBottleAndCup": "\u1F376",
+ "/sallallahoualayhewasallamarabic": "\uFDFA",
+ "/saltillo": "\uA78C",
+ "/saltire": "\u2613",
+ "/samahaprana": "\uA9B0",
+ "/samekh": "\u05E1",
+ "/samekh:hb": "\u05E1",
+ "/samekhdagesh": "\uFB41",
+ "/samekhdageshhebrew": "\uFB41",
+ "/samekhhebrew": "\u05E1",
+ "/samekhwithdagesh:hb": "\uFB41",
+ "/sampi": "\u03E1",
+ "/sampiarchaic": "\u0373",
+ "/samurda": "\uA9AF",
+ "/samvat": "\u0604",
+ "/san": "\u03FB",
+ "/santiimusquare": "\u3320",
+ "/saraaathai": "\u0E32",
+ "/saraaethai": "\u0E41",
+ "/saraaimaimalaithai": "\u0E44",
+ "/saraaimaimuanthai": "\u0E43",
+ "/saraamthai": "\u0E33",
+ "/saraathai": "\u0E30",
+ "/saraethai": "\u0E40",
+ "/saraiileftthai": "\uF886",
+ "/saraiithai": "\u0E35",
+ "/saraileftthai": "\uF885",
+ "/saraithai": "\u0E34",
+ "/saraothai": "\u0E42",
+ "/saraueeleftthai": "\uF888",
+ "/saraueethai": "\u0E37",
+ "/saraueleftthai": "\uF887",
+ "/sarauethai": "\u0E36",
+ "/sarauthai": "\u0E38",
+ "/sarauuthai": "\u0E39",
+ "/satellite": "\u1F6F0",
+ "/satelliteAntenna": "\u1F4E1",
+ "/saturn": "\u2644",
+ "/saxophone": "\u1F3B7",
+ "/sbopomofo": "\u3119",
+ "/scales": "\u2696",
+ "/scanninehorizontal": "\u23BD",
+ "/scanonehorizontal": "\u23BA",
+ "/scansevenhorizontal": "\u23BC",
+ "/scanthreehorizontal": "\u23BB",
+ "/scaron": "\u0161",
+ "/scarondot": "\u1E67",
+ "/scarondotaccent": "\u1E67",
+ "/scedilla": "\u015F",
+ "/school": "\u1F3EB",
+ "/schoolSatchel": "\u1F392",
+ "/schoolideographiccircled": "\u3246",
+ "/schwa": "\u0259",
+ "/schwa.inferior": "\u2094",
+ "/schwacyr": "\u04D9",
+ "/schwacyrillic": "\u04D9",
+ "/schwadieresiscyr": "\u04DB",
+ "/schwadieresiscyrillic": "\u04DB",
+ "/schwahook": "\u025A",
+ "/scircle": "\u24E2",
+ "/scircumflex": "\u015D",
+ "/scommaaccent": "\u0219",
+ "/scooter": "\u1F6F4",
+ "/scorpius": "\u264F",
+ "/screen": "\u1F5B5",
+ "/scroll": "\u1F4DC",
+ "/scruple": "\u2108",
+ "/sdot": "\u1E61",
+ "/sdotaccent": "\u1E61",
+ "/sdotbelow": "\u1E63",
+ "/sdotbelowdotabove": "\u1E69",
+ "/sdotbelowdotaccent": "\u1E69",
+ "/seagullbelowcmb": "\u033C",
+ "/seat": "\u1F4BA",
+ "/secirclekatakana": "\u32DD",
+ "/second": "\u2033",
+ "/secondreversed": "\u2036",
+ "/secondscreensquare": "\u1F19C",
+ "/secondtonechinese": "\u02CA",
+ "/secretideographiccircled": "\u3299",
+ "/section": "\u00A7",
+ "/sectionsignhalftop": "\u2E39",
+ "/sector": "\u2314",
+ "/seeNoEvilMonkey": "\u1F648",
+ "/seedling": "\u1F331",
+ "/seen": "\u0633",
+ "/seen.fina": "\uFEB2",
+ "/seen.init": "\uFEB3",
+ "/seen.init_alefmaksura.fina": "\uFCFB",
+ "/seen.init_hah.fina": "\uFC1D",
+ "/seen.init_hah.medi": "\uFCAE",
+ "/seen.init_hah.medi_jeem.medi": "\uFD5C",
+ "/seen.init_heh.medi": "\uFD31",
+ "/seen.init_jeem.fina": "\uFC1C",
+ "/seen.init_jeem.medi": "\uFCAD",
+ "/seen.init_jeem.medi_hah.medi": "\uFD5D",
+ "/seen.init_khah.fina": "\uFC1E",
+ "/seen.init_khah.medi": "\uFCAF",
+ "/seen.init_meem.fina": "\uFC1F",
+ "/seen.init_meem.medi": "\uFCB0",
+ "/seen.init_meem.medi_hah.medi": "\uFD60",
+ "/seen.init_meem.medi_jeem.medi": "\uFD61",
+ "/seen.init_meem.medi_meem.medi": "\uFD63",
+ "/seen.init_reh.fina": "\uFD0E",
+ "/seen.init_yeh.fina": "\uFCFC",
+ "/seen.isol": "\uFEB1",
+ "/seen.medi": "\uFEB4",
+ "/seen.medi_alefmaksura.fina": "\uFD17",
+ "/seen.medi_hah.medi": "\uFD35",
+ "/seen.medi_heh.medi": "\uFCE8",
+ "/seen.medi_jeem.medi": "\uFD34",
+ "/seen.medi_jeem.medi_alefmaksura.fina": "\uFD5E",
+ "/seen.medi_khah.medi": "\uFD36",
+ "/seen.medi_khah.medi_alefmaksura.fina": "\uFDA8",
+ "/seen.medi_khah.medi_yeh.fina": "\uFDC6",
+ "/seen.medi_meem.medi": "\uFCE7",
+ "/seen.medi_meem.medi_hah.fina": "\uFD5F",
+ "/seen.medi_meem.medi_meem.fina": "\uFD62",
+ "/seen.medi_reh.fina": "\uFD2A",
+ "/seen.medi_yeh.fina": "\uFD18",
+ "/seenDigitFourAbove": "\u077D",
+ "/seenFourDotsAbove": "\u075C",
+ "/seenInvertedV": "\u077E",
+ "/seenSmallTahTwoDots": "\u0770",
+ "/seenTwoDotsVerticallyAbove": "\u076D",
+ "/seenabove": "\u06DC",
+ "/seenarabic": "\u0633",
+ "/seendotbelowdotabove": "\u069A",
+ "/seenfinalarabic": "\uFEB2",
+ "/seeninitialarabic": "\uFEB3",
+ "/seenlow": "\u06E3",
+ "/seenmedialarabic": "\uFEB4",
+ "/seenthreedotsbelow": "\u069B",
+ "/seenthreedotsbelowthreedotsabove": "\u069C",
+ "/segment": "\u2313",
+ "/segol": "\u05B6",
+ "/segol13": "\u05B6",
+ "/segol1f": "\u05B6",
+ "/segol2c": "\u05B6",
+ "/segol:hb": "\u05B6",
+ "/segolhebrew": "\u05B6",
+ "/segolnarrowhebrew": "\u05B6",
+ "/segolquarterhebrew": "\u05B6",
+ "/segolta:hb": "\u0592",
+ "/segoltahebrew": "\u0592",
+ "/segolwidehebrew": "\u05B6",
+ "/seharmenian": "\u057D",
+ "/sehiragana": "\u305B",
+ "/sekatakana": "\u30BB",
+ "/sekatakanahalfwidth": "\uFF7E",
+ "/selfideographicparen": "\u3242",
+ "/semicolon": "\u003B",
+ "/semicolonarabic": "\u061B",
+ "/semicolonmonospace": "\uFF1B",
+ "/semicolonreversed": "\u204F",
+ "/semicolonsmall": "\uFE54",
+ "/semicolonunderlinefunc": "\u236E",
+ "/semidirectproductleft": "\u22CB",
+ "/semidirectproductright": "\u22CC",
+ "/semisextile": "\u26BA",
+ "/semisoftcyr": "\u048D",
+ "/semivoicedmarkkana": "\u309C",
+ "/semivoicedmarkkanahalfwidth": "\uFF9F",
+ "/sentisquare": "\u3322",
+ "/sentosquare": "\u3323",
+ "/septembertelegraph": "\u32C8",
+ "/sersetdblup": "\u22D1",
+ "/sersetnotequalup": "\u228B",
+ "/servicemark": "\u2120",
+ "/sesamedot": "\uFE45",
+ "/sesquiquadrate": "\u26BC",
+ "/setminus": "\u2216",
+ "/seven": "\u0037",
+ "/seven.inferior": "\u2087",
+ "/seven.roman": "\u2166",
+ "/seven.romansmall": "\u2176",
+ "/seven.superior": "\u2077",
+ "/sevenarabic": "\u0667",
+ "/sevenbengali": "\u09ED",
+ "/sevencircle": "\u2466",
+ "/sevencircledbl": "\u24FB",
+ "/sevencircleinversesansserif": "\u2790",
+ "/sevencomma": "\u1F108",
+ "/sevendeva": "\u096D",
+ "/seveneighths": "\u215E",
+ "/sevenfar": "\u06F7",
+ "/sevengujarati": "\u0AED",
+ "/sevengurmukhi": "\u0A6D",
+ "/sevenhackarabic": "\u0667",
+ "/sevenhangzhou": "\u3027",
+ "/sevenideographiccircled": "\u3286",
+ "/sevenideographicparen": "\u3226",
+ "/seveninferior": "\u2087",
+ "/sevenmonospace": "\uFF17",
+ "/sevenoldstyle": "\uF737",
+ "/sevenparen": "\u247A",
+ "/sevenparenthesized": "\u247A",
+ "/sevenperiod": "\u248E",
+ "/sevenpersian": "\u06F7",
+ "/sevenpointonesquare": "\u1F1A1",
+ "/sevenroman": "\u2176",
+ "/sevensuperior": "\u2077",
+ "/seventeencircle": "\u2470",
+ "/seventeencircleblack": "\u24F1",
+ "/seventeenparen": "\u2484",
+ "/seventeenparenthesized": "\u2484",
+ "/seventeenperiod": "\u2498",
+ "/seventhai": "\u0E57",
+ "/seventycirclesquare": "\u324E",
+ "/sextile": "\u26B9",
+ "/sfthyphen": "\u00AD",
+ "/shaarmenian": "\u0577",
+ "/shabengali": "\u09B6",
+ "/shacyr": "\u0448",
+ "/shacyrillic": "\u0448",
+ "/shaddaAlefIsol": "\uFC63",
+ "/shaddaDammaIsol": "\uFC61",
+ "/shaddaDammaMedi": "\uFCF3",
+ "/shaddaDammatanIsol": "\uFC5E",
+ "/shaddaFathaIsol": "\uFC60",
+ "/shaddaFathaMedi": "\uFCF2",
+ "/shaddaIsol": "\uFE7C",
+ "/shaddaKasraIsol": "\uFC62",
+ "/shaddaKasraMedi": "\uFCF4",
+ "/shaddaKasratanIsol": "\uFC5F",
+ "/shaddaMedi": "\uFE7D",
+ "/shaddaarabic": "\u0651",
+ "/shaddadammaarabic": "\uFC61",
+ "/shaddadammatanarabic": "\uFC5E",
+ "/shaddafathaarabic": "\uFC60",
+ "/shaddafathatanarabic": "\u0651",
+ "/shaddakasraarabic": "\uFC62",
+ "/shaddakasratanarabic": "\uFC5F",
+ "/shade": "\u2592",
+ "/shadedark": "\u2593",
+ "/shadelight": "\u2591",
+ "/shademedium": "\u2592",
+ "/shadeva": "\u0936",
+ "/shagujarati": "\u0AB6",
+ "/shagurmukhi": "\u0A36",
+ "/shalshelet:hb": "\u0593",
+ "/shalshelethebrew": "\u0593",
+ "/shamrock": "\u2618",
+ "/shavedIce": "\u1F367",
+ "/shbopomofo": "\u3115",
+ "/shchacyr": "\u0449",
+ "/shchacyrillic": "\u0449",
+ "/sheen": "\u0634",
+ "/sheen.fina": "\uFEB6",
+ "/sheen.init": "\uFEB7",
+ "/sheen.init_alefmaksura.fina": "\uFCFD",
+ "/sheen.init_hah.fina": "\uFD0A",
+ "/sheen.init_hah.medi": "\uFD2E",
+ "/sheen.init_hah.medi_meem.medi": "\uFD68",
+ "/sheen.init_heh.medi": "\uFD32",
+ "/sheen.init_jeem.fina": "\uFD09",
+ "/sheen.init_jeem.medi": "\uFD2D",
+ "/sheen.init_khah.fina": "\uFD0B",
+ "/sheen.init_khah.medi": "\uFD2F",
+ "/sheen.init_meem.fina": "\uFD0C",
+ "/sheen.init_meem.medi": "\uFD30",
+ "/sheen.init_meem.medi_khah.medi": "\uFD6B",
+ "/sheen.init_meem.medi_meem.medi": "\uFD6D",
+ "/sheen.init_reh.fina": "\uFD0D",
+ "/sheen.init_yeh.fina": "\uFCFE",
+ "/sheen.isol": "\uFEB5",
+ "/sheen.medi": "\uFEB8",
+ "/sheen.medi_alefmaksura.fina": "\uFD19",
+ "/sheen.medi_hah.fina": "\uFD26",
+ "/sheen.medi_hah.medi": "\uFD38",
+ "/sheen.medi_hah.medi_meem.fina": "\uFD67",
+ "/sheen.medi_hah.medi_yeh.fina": "\uFDAA",
+ "/sheen.medi_heh.medi": "\uFCEA",
+ "/sheen.medi_jeem.fina": "\uFD25",
+ "/sheen.medi_jeem.medi": "\uFD37",
+ "/sheen.medi_jeem.medi_yeh.fina": "\uFD69",
+ "/sheen.medi_khah.fina": "\uFD27",
+ "/sheen.medi_khah.medi": "\uFD39",
+ "/sheen.medi_meem.fina": "\uFD28",
+ "/sheen.medi_meem.medi": "\uFCE9",
+ "/sheen.medi_meem.medi_khah.fina": "\uFD6A",
+ "/sheen.medi_meem.medi_meem.fina": "\uFD6C",
+ "/sheen.medi_reh.fina": "\uFD29",
+ "/sheen.medi_yeh.fina": "\uFD1A",
+ "/sheenarabic": "\u0634",
+ "/sheendotbelow": "\u06FA",
+ "/sheenfinalarabic": "\uFEB6",
+ "/sheeninitialarabic": "\uFEB7",
+ "/sheenmedialarabic": "\uFEB8",
+ "/sheep": "\u1F411",
+ "/sheicoptic": "\u03E3",
+ "/shelfmod": "\u02FD",
+ "/shelfopenmod": "\u02FE",
+ "/sheqel": "\u20AA",
+ "/sheqelhebrew": "\u20AA",
+ "/sheva": "\u05B0",
+ "/sheva115": "\u05B0",
+ "/sheva15": "\u05B0",
+ "/sheva22": "\u05B0",
+ "/sheva2e": "\u05B0",
+ "/sheva:hb": "\u05B0",
+ "/shevahebrew": "\u05B0",
+ "/shevanarrowhebrew": "\u05B0",
+ "/shevaquarterhebrew": "\u05B0",
+ "/shevawidehebrew": "\u05B0",
+ "/shhacyr": "\u04BB",
+ "/shhacyrillic": "\u04BB",
+ "/shhatailcyr": "\u0527",
+ "/shield": "\u1F6E1",
+ "/shimacoptic": "\u03ED",
+ "/shin": "\u05E9",
+ "/shin:hb": "\u05E9",
+ "/shinDot:hb": "\u05C1",
+ "/shindagesh": "\uFB49",
+ "/shindageshhebrew": "\uFB49",
+ "/shindageshshindot": "\uFB2C",
+ "/shindageshshindothebrew": "\uFB2C",
+ "/shindageshsindot": "\uFB2D",
+ "/shindageshsindothebrew": "\uFB2D",
+ "/shindothebrew": "\u05C1",
+ "/shinhebrew": "\u05E9",
+ "/shinshindot": "\uFB2A",
+ "/shinshindothebrew": "\uFB2A",
+ "/shinsindot": "\uFB2B",
+ "/shinsindothebrew": "\uFB2B",
+ "/shintoshrine": "\u26E9",
+ "/shinwithdagesh:hb": "\uFB49",
+ "/shinwithdageshandshinDot:hb": "\uFB2C",
+ "/shinwithdageshandsinDot:hb": "\uFB2D",
+ "/shinwithshinDot:hb": "\uFB2A",
+ "/shinwithsinDot:hb": "\uFB2B",
+ "/ship": "\u1F6A2",
+ "/sho": "\u03F8",
+ "/shoejotupfunc": "\u235D",
+ "/shoestiledownfunc": "\u2366",
+ "/shoestileleftfunc": "\u2367",
+ "/shogipieceblack": "\u2617",
+ "/shogipiecewhite": "\u2616",
+ "/shook": "\u0282",
+ "/shootingStar": "\u1F320",
+ "/shoppingBags": "\u1F6CD",
+ "/shoppingTrolley": "\u1F6D2",
+ "/shortcake": "\u1F370",
+ "/shortequalsmod": "\uA78A",
+ "/shortoverlongmetrical": "\u23D3",
+ "/shoulderedopenbox": "\u237D",
+ "/shower": "\u1F6BF",
+ "/shvsquare": "\u1F1AA",
+ "/sicirclekatakana": "\u32DB",
+ "/sidewaysBlackDownPointingIndex": "\u1F5A1",
+ "/sidewaysBlackLeftPointingIndex": "\u1F59A",
+ "/sidewaysBlackRightPointingIndex": "\u1F59B",
+ "/sidewaysBlackUpPointingIndex": "\u1F5A0",
+ "/sidewaysWhiteDownPointingIndex": "\u1F59F",
+ "/sidewaysWhiteLeftPointingIndex": "\u1F598",
+ "/sidewaysWhiteRightPointingIndex": "\u1F599",
+ "/sidewaysWhiteUpPointingIndex": "\u1F59E",
+ "/sigma": "\u03C3",
+ "/sigma1": "\u03C2",
+ "/sigmafinal": "\u03C2",
+ "/sigmalunatedottedreversedsymbol": "\u037D",
+ "/sigmalunatedottedsymbol": "\u037C",
+ "/sigmalunatereversedsymbol": "\u037B",
+ "/sigmalunatesymbol": "\u03F2",
+ "/sigmalunatesymbolgreek": "\u03F2",
+ "/sihiragana": "\u3057",
+ "/sikatakana": "\u30B7",
+ "/sikatakanahalfwidth": "\uFF7C",
+ "/silhouetteOfJapan": "\u1F5FE",
+ "/siluqhebrew": "\u05BD",
+ "/siluqlefthebrew": "\u05BD",
+ "/similar": "\u223C",
+ "/sinDot:hb": "\u05C2",
+ "/sindothebrew": "\u05C2",
+ "/sinewave": "\u223F",
+ "/sinh:a": "\u0D85",
+ "/sinh:aa": "\u0D86",
+ "/sinh:aae": "\u0D88",
+ "/sinh:aaesign": "\u0DD1",
+ "/sinh:aasign": "\u0DCF",
+ "/sinh:ae": "\u0D87",
+ "/sinh:aesign": "\u0DD0",
+ "/sinh:ai": "\u0D93",
+ "/sinh:aisign": "\u0DDB",
+ "/sinh:anusvara": "\u0D82",
+ "/sinh:au": "\u0D96",
+ "/sinh:ausign": "\u0DDE",
+ "/sinh:ba": "\u0DB6",
+ "/sinh:bha": "\u0DB7",
+ "/sinh:ca": "\u0DA0",
+ "/sinh:cha": "\u0DA1",
+ "/sinh:da": "\u0DAF",
+ "/sinh:dda": "\u0DA9",
+ "/sinh:ddha": "\u0DAA",
+ "/sinh:dha": "\u0DB0",
+ "/sinh:e": "\u0D91",
+ "/sinh:ee": "\u0D92",
+ "/sinh:eesign": "\u0DDA",
+ "/sinh:esign": "\u0DD9",
+ "/sinh:fa": "\u0DC6",
+ "/sinh:ga": "\u0D9C",
+ "/sinh:gha": "\u0D9D",
+ "/sinh:ha": "\u0DC4",
+ "/sinh:i": "\u0D89",
+ "/sinh:ii": "\u0D8A",
+ "/sinh:iisign": "\u0DD3",
+ "/sinh:isign": "\u0DD2",
+ "/sinh:ja": "\u0DA2",
+ "/sinh:jha": "\u0DA3",
+ "/sinh:jnya": "\u0DA5",
+ "/sinh:ka": "\u0D9A",
+ "/sinh:kha": "\u0D9B",
+ "/sinh:kunddaliya": "\u0DF4",
+ "/sinh:la": "\u0DBD",
+ "/sinh:litheight": "\u0DEE",
+ "/sinh:lithfive": "\u0DEB",
+ "/sinh:lithfour": "\u0DEA",
+ "/sinh:lithnine": "\u0DEF",
+ "/sinh:lithone": "\u0DE7",
+ "/sinh:lithseven": "\u0DED",
+ "/sinh:lithsix": "\u0DEC",
+ "/sinh:liththree": "\u0DE9",
+ "/sinh:lithtwo": "\u0DE8",
+ "/sinh:lithzero": "\u0DE6",
+ "/sinh:lla": "\u0DC5",
+ "/sinh:llvocal": "\u0D90",
+ "/sinh:llvocalsign": "\u0DF3",
+ "/sinh:lvocal": "\u0D8F",
+ "/sinh:lvocalsign": "\u0DDF",
+ "/sinh:ma": "\u0DB8",
+ "/sinh:mba": "\u0DB9",
+ "/sinh:na": "\u0DB1",
+ "/sinh:nda": "\u0DB3",
+ "/sinh:nga": "\u0D9E",
+ "/sinh:nna": "\u0DAB",
+ "/sinh:nndda": "\u0DAC",
+ "/sinh:nnga": "\u0D9F",
+ "/sinh:nya": "\u0DA4",
+ "/sinh:nyja": "\u0DA6",
+ "/sinh:o": "\u0D94",
+ "/sinh:oo": "\u0D95",
+ "/sinh:oosign": "\u0DDD",
+ "/sinh:osign": "\u0DDC",
+ "/sinh:pa": "\u0DB4",
+ "/sinh:pha": "\u0DB5",
+ "/sinh:ra": "\u0DBB",
+ "/sinh:rrvocal": "\u0D8E",
+ "/sinh:rrvocalsign": "\u0DF2",
+ "/sinh:rvocal": "\u0D8D",
+ "/sinh:rvocalsign": "\u0DD8",
+ "/sinh:sa": "\u0DC3",
+ "/sinh:sha": "\u0DC1",
+ "/sinh:ssa": "\u0DC2",
+ "/sinh:ta": "\u0DAD",
+ "/sinh:tha": "\u0DAE",
+ "/sinh:tta": "\u0DA7",
+ "/sinh:ttha": "\u0DA8",
+ "/sinh:u": "\u0D8B",
+ "/sinh:usign": "\u0DD4",
+ "/sinh:uu": "\u0D8C",
+ "/sinh:uusign": "\u0DD6",
+ "/sinh:va": "\u0DC0",
+ "/sinh:virama": "\u0DCA",
+ "/sinh:visarga": "\u0D83",
+ "/sinh:ya": "\u0DBA",
+ "/sinologicaldot": "\uA78F",
+ "/sinsular": "\uA785",
+ "/siosacirclekorean": "\u3274",
+ "/siosaparenkorean": "\u3214",
+ "/sioscieuckorean": "\u317E",
+ "/sioscirclekorean": "\u3266",
+ "/sioskiyeokkorean": "\u317A",
+ "/sioskorean": "\u3145",
+ "/siosnieunkorean": "\u317B",
+ "/siosparenkorean": "\u3206",
+ "/siospieupkorean": "\u317D",
+ "/siostikeutkorean": "\u317C",
+ "/siringusquare": "\u3321",
+ "/six": "\u0036",
+ "/six.inferior": "\u2086",
+ "/six.roman": "\u2165",
+ "/six.romansmall": "\u2175",
+ "/six.superior": "\u2076",
+ "/sixPointedStarMiddleDot": "\u1F52F",
+ "/sixarabic": "\u0666",
+ "/sixbengali": "\u09EC",
+ "/sixcircle": "\u2465",
+ "/sixcircledbl": "\u24FA",
+ "/sixcircleinversesansserif": "\u278F",
+ "/sixcomma": "\u1F107",
+ "/sixdeva": "\u096C",
+ "/sixdotsvertical": "\u2E3D",
+ "/sixfar": "\u06F6",
+ "/sixgujarati": "\u0AEC",
+ "/sixgurmukhi": "\u0A6C",
+ "/sixhackarabic": "\u0666",
+ "/sixhangzhou": "\u3026",
+ "/sixideographiccircled": "\u3285",
+ "/sixideographicparen": "\u3225",
+ "/sixinferior": "\u2086",
+ "/sixlateform.roman": "\u2185",
+ "/sixmonospace": "\uFF16",
+ "/sixoldstyle": "\uF736",
+ "/sixparen": "\u2479",
+ "/sixparenthesized": "\u2479",
+ "/sixperemspace": "\u2006",
+ "/sixperiod": "\u248D",
+ "/sixpersian": "\u06F6",
+ "/sixroman": "\u2175",
+ "/sixsuperior": "\u2076",
+ "/sixteencircle": "\u246F",
+ "/sixteencircleblack": "\u24F0",
+ "/sixteencurrencydenominatorbengali": "\u09F9",
+ "/sixteenparen": "\u2483",
+ "/sixteenparenthesized": "\u2483",
+ "/sixteenperiod": "\u2497",
+ "/sixthai": "\u0E56",
+ "/sixtycirclesquare": "\u324D",
+ "/sixtypsquare": "\u1F1A3",
+ "/sjekomicyr": "\u050D",
+ "/skiAndSkiBoot": "\u1F3BF",
+ "/skier": "\u26F7",
+ "/skull": "\u1F480",
+ "/skullcrossbones": "\u2620",
+ "/slash": "\u002F",
+ "/slashbarfunc": "\u233F",
+ "/slashmonospace": "\uFF0F",
+ "/sled": "\u1F6F7",
+ "/sleeping": "\u1F4A4",
+ "/sleepingAccommodation": "\u1F6CC",
+ "/sleepingFace": "\u1F634",
+ "/sleepyFace": "\u1F62A",
+ "/sleuthOrSpy": "\u1F575",
+ "/sliceOfPizza": "\u1F355",
+ "/slightlyFrowningFace": "\u1F641",
+ "/slightlySmilingFace": "\u1F642",
+ "/slong": "\u017F",
+ "/slongdotaccent": "\u1E9B",
+ "/slope": "\u2333",
+ "/slotMachine": "\u1F3B0",
+ "/smallAirplane": "\u1F6E9",
+ "/smallBlueDiamond": "\u1F539",
+ "/smallOrangeDiamond": "\u1F538",
+ "/smallRedTriangleDOwn": "\u1F53D",
+ "/smallRedTriangleUp": "\u1F53C",
+ "/smile": "\u2323",
+ "/smileface": "\u263A",
+ "/smilingCatFaceWithHeartShapedEyes": "\u1F63B",
+ "/smilingCatFaceWithOpenMouth": "\u1F63A",
+ "/smilingFaceWithHalo": "\u1F607",
+ "/smilingFaceWithHeartShapedEyes": "\u1F60D",
+ "/smilingFaceWithHorns": "\u1F608",
+ "/smilingFaceWithOpenMouth": "\u1F603",
+ "/smilingFaceWithOpenMouthAndColdSweat": "\u1F605",
+ "/smilingFaceWithOpenMouthAndSmilingEyes": "\u1F604",
+ "/smilingFaceWithOpenMouthAndTightlyClosedEyes": "\u1F606",
+ "/smilingFaceWithSmilingEyes": "\u1F60A",
+ "/smilingFaceWithSunglasses": "\u1F60E",
+ "/smilingfaceblack": "\u263B",
+ "/smilingfacewhite": "\u263A",
+ "/smirkingFace": "\u1F60F",
+ "/smll:ampersand": "\uFE60",
+ "/smll:asterisk": "\uFE61",
+ "/smll:backslash": "\uFE68",
+ "/smll:braceleft": "\uFE5B",
+ "/smll:braceright": "\uFE5C",
+ "/smll:colon": "\uFE55",
+ "/smll:comma": "\uFE50",
+ "/smll:dollar": "\uFE69",
+ "/smll:emdash": "\uFE58",
+ "/smll:equal": "\uFE66",
+ "/smll:exclam": "\uFE57",
+ "/smll:greater": "\uFE65",
+ "/smll:hyphen": "\uFE63",
+ "/smll:ideographiccomma": "\uFE51",
+ "/smll:less": "\uFE64",
+ "/smll:numbersign": "\uFE5F",
+ "/smll:parenthesisleft": "\uFE59",
+ "/smll:parenthesisright": "\uFE5A",
+ "/smll:percent": "\uFE6A",
+ "/smll:period": "\uFE52",
+ "/smll:plus": "\uFE62",
+ "/smll:question": "\uFE56",
+ "/smll:semicolon": "\uFE54",
+ "/smll:tortoiseshellbracketleft": "\uFE5D",
+ "/smll:tortoiseshellbracketright": "\uFE5E",
+ "/smoking": "\u1F6AC",
+ "/smonospace": "\uFF53",
+ "/snail": "\u1F40C",
+ "/snake": "\u1F40D",
+ "/snowboarder": "\u1F3C2",
+ "/snowcappedMountain": "\u1F3D4",
+ "/snowman": "\u2603",
+ "/snowmanblack": "\u26C7",
+ "/snowmanoutsnow": "\u26C4",
+ "/sobliquestroke": "\uA7A9",
+ "/soccerball": "\u26BD",
+ "/societyideographiccircled": "\u3293",
+ "/societyideographicparen": "\u3233",
+ "/socirclekatakana": "\u32DE",
+ "/sofPasuq:hb": "\u05C3",
+ "/sofpasuqhebrew": "\u05C3",
+ "/softIceCream": "\u1F366",
+ "/softShellFloppyDisk": "\u1F5AC",
+ "/softcyr": "\u044C",
+ "/softhyphen": "\u00AD",
+ "/softsigncyrillic": "\u044C",
+ "/softwarefunction": "\u2394",
+ "/sohiragana": "\u305D",
+ "/sokatakana": "\u30BD",
+ "/sokatakanahalfwidth": "\uFF7F",
+ "/soliduslongoverlaycmb": "\u0338",
+ "/solidusshortoverlaycmb": "\u0337",
+ "/solidussubsetreversepreceding": "\u27C8",
+ "/solidussupersetpreceding": "\u27C9",
+ "/soonRightwardsArrowAbove": "\u1F51C",
+ "/sorusithai": "\u0E29",
+ "/sosalathai": "\u0E28",
+ "/sosothai": "\u0E0B",
+ "/sossquare": "\u1F198",
+ "/sosuathai": "\u0E2A",
+ "/soundcopyright": "\u2117",
+ "/space": "\u0020",
+ "/spacehackarabic": "\u0020",
+ "/spade": "\u2660",
+ "/spadeblack": "\u2660",
+ "/spadesuitblack": "\u2660",
+ "/spadesuitwhite": "\u2664",
+ "/spadewhite": "\u2664",
+ "/spaghetti": "\u1F35D",
+ "/sparen": "\u24AE",
+ "/sparenthesized": "\u24AE",
+ "/sparklingHeart": "\u1F496",
+ "/speakNoEvilMonkey": "\u1F64A",
+ "/speaker": "\u1F508",
+ "/speakerCancellationStroke": "\u1F507",
+ "/speakerOneSoundWave": "\u1F509",
+ "/speakerThreeSoundWaves": "\u1F50A",
+ "/speakingHeadInSilhouette": "\u1F5E3",
+ "/specialideographiccircled": "\u3295",
+ "/specialideographicparen": "\u3235",
+ "/speechBalloon": "\u1F4AC",
+ "/speedboat": "\u1F6A4",
+ "/spesmilo": "\u20B7",
+ "/sphericalangle": "\u2222",
+ "/spider": "\u1F577",
+ "/spiderWeb": "\u1F578",
+ "/spiralCalendarPad": "\u1F5D3",
+ "/spiralNotePad": "\u1F5D2",
+ "/spiralShell": "\u1F41A",
+ "/splashingSweat": "\u1F4A6",
+ "/sportsMedal": "\u1F3C5",
+ "/spoutingWhale": "\u1F433",
+ "/sppl:tildevertical": "\u2E2F",
+ "/squarebelowcmb": "\u033B",
+ "/squareblack": "\u25A0",
+ "/squarebracketleftvertical": "\uFE47",
+ "/squarebracketrightvertical": "\uFE48",
+ "/squarecap": "\u2293",
+ "/squarecc": "\u33C4",
+ "/squarecm": "\u339D",
+ "/squarecup": "\u2294",
+ "/squareddotoperator": "\u22A1",
+ "/squarediagonalcrosshatchfill": "\u25A9",
+ "/squaredj": "\u1F190",
+ "/squaredkey": "\u26BF",
+ "/squaredminus": "\u229F",
+ "/squaredplus": "\u229E",
+ "/squaredsaltire": "\u26DD",
+ "/squaredtimes": "\u22A0",
+ "/squarefourcorners": "\u26F6",
+ "/squarehalfleftblack": "\u25E7",
+ "/squarehalfrightblack": "\u25E8",
+ "/squarehorizontalfill": "\u25A4",
+ "/squareimage": "\u228F",
+ "/squareimageorequal": "\u2291",
+ "/squareimageornotequal": "\u22E4",
+ "/squarekg": "\u338F",
+ "/squarekm": "\u339E",
+ "/squarekmcapital": "\u33CE",
+ "/squareln": "\u33D1",
+ "/squarelog": "\u33D2",
+ "/squarelowerdiagonalhalfrightblack": "\u25EA",
+ "/squaremediumblack": "\u25FC",
+ "/squaremediumwhite": "\u25FB",
+ "/squaremg": "\u338E",
+ "/squaremil": "\u33D5",
+ "/squaremm": "\u339C",
+ "/squaremsquared": "\u33A1",
+ "/squareoriginal": "\u2290",
+ "/squareoriginalorequal": "\u2292",
+ "/squareoriginalornotequal": "\u22E5",
+ "/squareorthogonalcrosshatchfill": "\u25A6",
+ "/squareraised": "\u2E0B",
+ "/squaresmallblack": "\u25AA",
+ "/squaresmallmediumblack": "\u25FE",
+ "/squaresmallmediumwhite": "\u25FD",
+ "/squaresmallwhite": "\u25AB",
+ "/squareupperdiagonalhalfleftblack": "\u25E9",
+ "/squareupperlefttolowerrightfill": "\u25A7",
+ "/squareupperrighttolowerleftfill": "\u25A8",
+ "/squareverticalfill": "\u25A5",
+ "/squarewhite": "\u25A1",
+ "/squarewhitebisectinglinevertical": "\u25EB",
+ "/squarewhitelowerquadrantleft": "\u25F1",
+ "/squarewhitelowerquadrantright": "\u25F2",
+ "/squarewhiteround": "\u25A2",
+ "/squarewhiteupperquadrantleft": "\u25F0",
+ "/squarewhiteupperquadrantright": "\u25F3",
+ "/squarewhitewithsmallblack": "\u25A3",
+ "/squarewhitewithsquaresmallblack": "\u25A3",
+ "/squishquadfunc": "\u2337",
+ "/srfullwidth": "\u33DB",
+ "/srsquare": "\u33DB",
+ "/ssabengali": "\u09B7",
+ "/ssadeva": "\u0937",
+ "/ssagujarati": "\u0AB7",
+ "/ssangcieuckorean": "\u3149",
+ "/ssanghieuhkorean": "\u3185",
+ "/ssangieungkorean": "\u3180",
+ "/ssangkiyeokkorean": "\u3132",
+ "/ssangnieunkorean": "\u3165",
+ "/ssangpieupkorean": "\u3143",
+ "/ssangsioskorean": "\u3146",
+ "/ssangtikeutkorean": "\u3138",
+ "/ssuperior": "\uF6F2",
+ "/ssupmod": "\u02E2",
+ "/sswashtail": "\u023F",
+ "/stackedcommadbl": "\u2E49",
+ "/stadium": "\u1F3DF",
+ "/staffofaesculapius": "\u2695",
+ "/staffofhermes": "\u269A",
+ "/stampedEnvelope": "\u1F583",
+ "/star": "\u22C6",
+ "/starblack": "\u2605",
+ "/starcrescent": "\u262A",
+ "/stardiaeresisfunc": "\u2363",
+ "/starequals": "\u225B",
+ "/staroperator": "\u22C6",
+ "/staroutlinedwhite": "\u269D",
+ "/starwhite": "\u2606",
+ "/station": "\u1F689",
+ "/statueOfLiberty": "\u1F5FD",
+ "/steamLocomotive": "\u1F682",
+ "/steamingBowl": "\u1F35C",
+ "/stenographicfullstop": "\u2E3C",
+ "/sterling": "\u00A3",
+ "/sterlingmonospace": "\uFFE1",
+ "/stigma": "\u03DB",
+ "/stiletildefunc": "\u236D",
+ "/stockChart": "\u1F5E0",
+ "/stockideographiccircled": "\u3291",
+ "/stockideographicparen": "\u3231",
+ "/stopabove": "\u06EB",
+ "/stopbelow": "\u06EA",
+ "/straightRuler": "\u1F4CF",
+ "/straightness": "\u23E4",
+ "/strawberry": "\u1F353",
+ "/stresslowtonemod": "\uA721",
+ "/stresstonemod": "\uA720",
+ "/strictlyequivalent": "\u2263",
+ "/strokelongoverlaycmb": "\u0336",
+ "/strokeshortoverlaycmb": "\u0335",
+ "/studioMicrophone": "\u1F399",
+ "/studyideographiccircled": "\u32AB",
+ "/studyideographicparen": "\u323B",
+ "/stupa": "\u1F6D3",
+ "/subscriptalef": "\u0656",
+ "/subset": "\u2282",
+ "/subsetdbl": "\u22D0",
+ "/subsetnotequal": "\u228A",
+ "/subsetorequal": "\u2286",
+ "/succeeds": "\u227B",
+ "/succeedsbutnotequivalent": "\u22E9",
+ "/succeedsorequal": "\u227D",
+ "/succeedsorequivalent": "\u227F",
+ "/succeedsunderrelation": "\u22B1",
+ "/suchthat": "\u220B",
+ "/sucirclekatakana": "\u32DC",
+ "/suhiragana": "\u3059",
+ "/suitableideographiccircled": "\u329C",
+ "/sukatakana": "\u30B9",
+ "/sukatakanahalfwidth": "\uFF7D",
+ "/sukumendutvowel": "\uA9B9",
+ "/sukunIsol": "\uFE7E",
+ "/sukunMedi": "\uFE7F",
+ "/sukunarabic": "\u0652",
+ "/sukuvowel": "\uA9B8",
+ "/summation": "\u2211",
+ "/summationbottom": "\u23B3",
+ "/summationdblstruck": "\u2140",
+ "/summationtop": "\u23B2",
+ "/sun": "\u263C",
+ "/sunFace": "\u1F31E",
+ "/sunbehindcloud": "\u26C5",
+ "/sunflower": "\u1F33B",
+ "/sunideographiccircled": "\u3290",
+ "/sunideographicparen": "\u3230",
+ "/sunraysblack": "\u2600",
+ "/sunrayswhite": "\u263C",
+ "/sunrise": "\u1F305",
+ "/sunriseOverMountains": "\u1F304",
+ "/sunsetOverBuildings": "\u1F307",
+ "/superset": "\u2283",
+ "/supersetnotequal": "\u228B",
+ "/supersetorequal": "\u2287",
+ "/superviseideographiccircled": "\u32AC",
+ "/superviseideographicparen": "\u323C",
+ "/surfer": "\u1F3C4",
+ "/sushi": "\u1F363",
+ "/suspensionRailway": "\u1F69F",
+ "/suspensiondbl": "\u2E44",
+ "/svfullwidth": "\u33DC",
+ "/svsquare": "\u33DC",
+ "/swatchtop": "\u23F1",
+ "/swimmer": "\u1F3CA",
+ "/swungdash": "\u2053",
+ "/symbolabovethreedotsabove": "\uFBB6",
+ "/symbolbelowthreedotsabove": "\uFBB7",
+ "/symboldotabove": "\uFBB2",
+ "/symboldotbelow": "\uFBB3",
+ "/symboldoubleverticalbarbelow": "\uFBBC",
+ "/symbolfourdotsabove": "\uFBBA",
+ "/symbolfourdotsbelow": "\uFBBB",
+ "/symbolpointingabovedownthreedotsabove": "\uFBB8",
+ "/symbolpointingbelowdownthreedotsabove": "\uFBB9",
+ "/symbolring": "\uFBBF",
+ "/symboltahabovesmall": "\uFBC0",
+ "/symboltahbelowsmall": "\uFBC1",
+ "/symboltwodotsabove": "\uFBB4",
+ "/symboltwodotsbelow": "\uFBB5",
+ "/symboltwodotsverticallyabove": "\uFBBD",
+ "/symboltwodotsverticallybelow": "\uFBBE",
+ "/symmetry": "\u232F",
+ "/synagogue": "\u1F54D",
+ "/syouwaerasquare": "\u337C",
+ "/syringe": "\u1F489",
+ "/t": "\u0074",
+ "/t-shirt": "\u1F455",
+ "/t.inferior": "\u209C",
+ "/tabengali": "\u09A4",
+ "/tableTennisPaddleAndBall": "\u1F3D3",
+ "/tacirclekatakana": "\u32DF",
+ "/tackcircleaboveup": "\u27DF",
+ "/tackdiaeresisupfunc": "\u2361",
+ "/tackdown": "\u22A4",
+ "/tackdownmod": "\u02D5",
+ "/tackjotdownfunc": "\u234E",
+ "/tackjotupfunc": "\u2355",
+ "/tackleft": "\u22A3",
+ "/tackleftright": "\u27DB",
+ "/tackoverbarupfunc": "\u2351",
+ "/tackright": "\u22A2",
+ "/tackunderlinedownfunc": "\u234A",
+ "/tackup": "\u22A5",
+ "/tackupmod": "\u02D4",
+ "/taco": "\u1F32E",
+ "/tadeva": "\u0924",
+ "/tagujarati": "\u0AA4",
+ "/tagurmukhi": "\u0A24",
+ "/tah": "\u0637",
+ "/tah.fina": "\uFEC2",
+ "/tah.init": "\uFEC3",
+ "/tah.init_alefmaksura.fina": "\uFCF5",
+ "/tah.init_hah.fina": "\uFC26",
+ "/tah.init_hah.medi": "\uFCB8",
+ "/tah.init_meem.fina": "\uFC27",
+ "/tah.init_meem.medi": "\uFD33",
+ "/tah.init_meem.medi_hah.medi": "\uFD72",
+ "/tah.init_meem.medi_meem.medi": "\uFD73",
+ "/tah.init_yeh.fina": "\uFCF6",
+ "/tah.isol": "\uFEC1",
+ "/tah.medi": "\uFEC4",
+ "/tah.medi_alefmaksura.fina": "\uFD11",
+ "/tah.medi_meem.medi": "\uFD3A",
+ "/tah.medi_meem.medi_hah.fina": "\uFD71",
+ "/tah.medi_meem.medi_yeh.fina": "\uFD74",
+ "/tah.medi_yeh.fina": "\uFD12",
+ "/tahabove": "\u0615",
+ "/taharabic": "\u0637",
+ "/tahfinalarabic": "\uFEC2",
+ "/tahinitialarabic": "\uFEC3",
+ "/tahiragana": "\u305F",
+ "/tahmedialarabic": "\uFEC4",
+ "/tahthreedotsabove": "\u069F",
+ "/taisyouerasquare": "\u337D",
+ "/takatakana": "\u30BF",
+ "/takatakanahalfwidth": "\uFF80",
+ "/takhallus": "\u0614",
+ "/talingvowel": "\uA9BA",
+ "/taml:a": "\u0B85",
+ "/taml:aa": "\u0B86",
+ "/taml:aasign": "\u0BBE",
+ "/taml:ai": "\u0B90",
+ "/taml:aisign": "\u0BC8",
+ "/taml:anusvarasign": "\u0B82",
+ "/taml:asabovesign": "\u0BF8",
+ "/taml:au": "\u0B94",
+ "/taml:aulengthmark": "\u0BD7",
+ "/taml:ausign": "\u0BCC",
+ "/taml:ca": "\u0B9A",
+ "/taml:creditsign": "\u0BF7",
+ "/taml:daysign": "\u0BF3",
+ "/taml:debitsign": "\u0BF6",
+ "/taml:e": "\u0B8E",
+ "/taml:ee": "\u0B8F",
+ "/taml:eesign": "\u0BC7",
+ "/taml:eight": "\u0BEE",
+ "/taml:esign": "\u0BC6",
+ "/taml:five": "\u0BEB",
+ "/taml:four": "\u0BEA",
+ "/taml:ha": "\u0BB9",
+ "/taml:i": "\u0B87",
+ "/taml:ii": "\u0B88",
+ "/taml:iisign": "\u0BC0",
+ "/taml:isign": "\u0BBF",
+ "/taml:ja": "\u0B9C",
+ "/taml:ka": "\u0B95",
+ "/taml:la": "\u0BB2",
+ "/taml:lla": "\u0BB3",
+ "/taml:llla": "\u0BB4",
+ "/taml:ma": "\u0BAE",
+ "/taml:monthsign": "\u0BF4",
+ "/taml:na": "\u0BA8",
+ "/taml:nga": "\u0B99",
+ "/taml:nine": "\u0BEF",
+ "/taml:nna": "\u0BA3",
+ "/taml:nnna": "\u0BA9",
+ "/taml:nya": "\u0B9E",
+ "/taml:o": "\u0B92",
+ "/taml:om": "\u0BD0",
+ "/taml:one": "\u0BE7",
+ "/taml:onehundred": "\u0BF1",
+ "/taml:onethousand": "\u0BF2",
+ "/taml:oo": "\u0B93",
+ "/taml:oosign": "\u0BCB",
+ "/taml:osign": "\u0BCA",
+ "/taml:pa": "\u0BAA",
+ "/taml:ra": "\u0BB0",
+ "/taml:rra": "\u0BB1",
+ "/taml:rupeesign": "\u0BF9",
+ "/taml:sa": "\u0BB8",
+ "/taml:seven": "\u0BED",
+ "/taml:sha": "\u0BB6",
+ "/taml:sign": "\u0BFA",
+ "/taml:six": "\u0BEC",
+ "/taml:ssa": "\u0BB7",
+ "/taml:ta": "\u0BA4",
+ "/taml:ten": "\u0BF0",
+ "/taml:three": "\u0BE9",
+ "/taml:tta": "\u0B9F",
+ "/taml:two": "\u0BE8",
+ "/taml:u": "\u0B89",
+ "/taml:usign": "\u0BC1",
+ "/taml:uu": "\u0B8A",
+ "/taml:uusign": "\u0BC2",
+ "/taml:va": "\u0BB5",
+ "/taml:viramasign": "\u0BCD",
+ "/taml:visargasign": "\u0B83",
+ "/taml:ya": "\u0BAF",
+ "/taml:yearsign": "\u0BF5",
+ "/taml:zero": "\u0BE6",
+ "/tamurda": "\uA9A1",
+ "/tanabataTree": "\u1F38B",
+ "/tangerine": "\u1F34A",
+ "/tapeCartridge": "\u1F5AD",
+ "/tarungvowel": "\uA9B4",
+ "/tatweelFathatanAbove": "\uFE71",
+ "/tatweelarabic": "\u0640",
+ "/tau": "\u03C4",
+ "/taurus": "\u2649",
+ "/tav": "\u05EA",
+ "/tav:hb": "\u05EA",
+ "/tavdages": "\uFB4A",
+ "/tavdagesh": "\uFB4A",
+ "/tavdageshhebrew": "\uFB4A",
+ "/tavhebrew": "\u05EA",
+ "/tavwide:hb": "\uFB28",
+ "/tavwithdagesh:hb": "\uFB4A",
+ "/taxi": "\u1F695",
+ "/tbar": "\u0167",
+ "/tbopomofo": "\u310A",
+ "/tcaron": "\u0165",
+ "/tccurl": "\u02A8",
+ "/tcedilla": "\u0163",
+ "/tcheh": "\u0686",
+ "/tcheh.fina": "\uFB7B",
+ "/tcheh.init": "\uFB7C",
+ "/tcheh.isol": "\uFB7A",
+ "/tcheh.medi": "\uFB7D",
+ "/tcheharabic": "\u0686",
+ "/tchehdotabove": "\u06BF",
+ "/tcheheh": "\u0687",
+ "/tcheheh.fina": "\uFB7F",
+ "/tcheheh.init": "\uFB80",
+ "/tcheheh.isol": "\uFB7E",
+ "/tcheheh.medi": "\uFB81",
+ "/tchehfinalarabic": "\uFB7B",
+ "/tchehinitialarabic": "\uFB7C",
+ "/tchehmedialarabic": "\uFB7D",
+ "/tchehmeeminitialarabic": "\uFB7C",
+ "/tcircle": "\u24E3",
+ "/tcircumflexbelow": "\u1E71",
+ "/tcommaaccent": "\u0163",
+ "/tcurl": "\u0236",
+ "/tdieresis": "\u1E97",
+ "/tdot": "\u1E6B",
+ "/tdotaccent": "\u1E6B",
+ "/tdotbelow": "\u1E6D",
+ "/teacupOutHandle": "\u1F375",
+ "/tear-offCalendar": "\u1F4C6",
+ "/tecirclekatakana": "\u32E2",
+ "/tecyr": "\u0442",
+ "/tecyrillic": "\u0442",
+ "/tedescendercyrillic": "\u04AD",
+ "/teh": "\u062A",
+ "/teh.fina": "\uFE96",
+ "/teh.init": "\uFE97",
+ "/teh.init_alefmaksura.fina": "\uFC0F",
+ "/teh.init_hah.fina": "\uFC0C",
+ "/teh.init_hah.medi": "\uFCA2",
+ "/teh.init_hah.medi_jeem.medi": "\uFD52",
+ "/teh.init_hah.medi_meem.medi": "\uFD53",
+ "/teh.init_heh.medi": "\uFCA5",
+ "/teh.init_jeem.fina": "\uFC0B",
+ "/teh.init_jeem.medi": "\uFCA1",
+ "/teh.init_jeem.medi_meem.medi": "\uFD50",
+ "/teh.init_khah.fina": "\uFC0D",
+ "/teh.init_khah.medi": "\uFCA3",
+ "/teh.init_khah.medi_meem.medi": "\uFD54",
+ "/teh.init_meem.fina": "\uFC0E",
+ "/teh.init_meem.medi": "\uFCA4",
+ "/teh.init_meem.medi_hah.medi": "\uFD56",
+ "/teh.init_meem.medi_jeem.medi": "\uFD55",
+ "/teh.init_meem.medi_khah.medi": "\uFD57",
+ "/teh.init_yeh.fina": "\uFC10",
+ "/teh.isol": "\uFE95",
+ "/teh.medi": "\uFE98",
+ "/teh.medi_alefmaksura.fina": "\uFC74",
+ "/teh.medi_hah.medi_jeem.fina": "\uFD51",
+ "/teh.medi_heh.medi": "\uFCE4",
+ "/teh.medi_jeem.medi_alefmaksura.fina": "\uFDA0",
+ "/teh.medi_jeem.medi_yeh.fina": "\uFD9F",
+ "/teh.medi_khah.medi_alefmaksura.fina": "\uFDA2",
+ "/teh.medi_khah.medi_yeh.fina": "\uFDA1",
+ "/teh.medi_meem.fina": "\uFC72",
+ "/teh.medi_meem.medi": "\uFCE3",
+ "/teh.medi_meem.medi_alefmaksura.fina": "\uFDA4",
+ "/teh.medi_meem.medi_yeh.fina": "\uFDA3",
+ "/teh.medi_noon.fina": "\uFC73",
+ "/teh.medi_reh.fina": "\uFC70",
+ "/teh.medi_yeh.fina": "\uFC75",
+ "/teh.medi_zain.fina": "\uFC71",
+ "/teharabic": "\u062A",
+ "/tehdownthreedotsabove": "\u067D",
+ "/teheh": "\u067F",
+ "/teheh.fina": "\uFB63",
+ "/teheh.init": "\uFB64",
+ "/teheh.isol": "\uFB62",
+ "/teheh.medi": "\uFB65",
+ "/tehfinalarabic": "\uFE96",
+ "/tehhahinitialarabic": "\uFCA2",
+ "/tehhahisolatedarabic": "\uFC0C",
+ "/tehinitialarabic": "\uFE97",
+ "/tehiragana": "\u3066",
+ "/tehjeeminitialarabic": "\uFCA1",
+ "/tehjeemisolatedarabic": "\uFC0B",
+ "/tehmarbuta": "\u0629",
+ "/tehmarbuta.fina": "\uFE94",
+ "/tehmarbuta.isol": "\uFE93",
+ "/tehmarbutaarabic": "\u0629",
+ "/tehmarbutafinalarabic": "\uFE94",
+ "/tehmarbutagoal": "\u06C3",
+ "/tehmedialarabic": "\uFE98",
+ "/tehmeeminitialarabic": "\uFCA4",
+ "/tehmeemisolatedarabic": "\uFC0E",
+ "/tehnoonfinalarabic": "\uFC73",
+ "/tehring": "\u067C",
+ "/tekatakana": "\u30C6",
+ "/tekatakanahalfwidth": "\uFF83",
+ "/telephone": "\u2121",
+ "/telephoneOnTopOfModem": "\u1F580",
+ "/telephoneReceiver": "\u1F4DE",
+ "/telephoneReceiverPage": "\u1F57C",
+ "/telephoneblack": "\u260E",
+ "/telephonerecorder": "\u2315",
+ "/telephonewhite": "\u260F",
+ "/telescope": "\u1F52D",
+ "/television": "\u1F4FA",
+ "/telishaGedolah:hb": "\u05A0",
+ "/telishaQetannah:hb": "\u05A9",
+ "/telishagedolahebrew": "\u05A0",
+ "/telishaqetanahebrew": "\u05A9",
+ "/telu:a": "\u0C05",
+ "/telu:aa": "\u0C06",
+ "/telu:aasign": "\u0C3E",
+ "/telu:ai": "\u0C10",
+ "/telu:ailengthmark": "\u0C56",
+ "/telu:aisign": "\u0C48",
+ "/telu:anusvarasign": "\u0C02",
+ "/telu:au": "\u0C14",
+ "/telu:ausign": "\u0C4C",
+ "/telu:avagrahasign": "\u0C3D",
+ "/telu:ba": "\u0C2C",
+ "/telu:bha": "\u0C2D",
+ "/telu:bindusigncandra": "\u0C01",
+ "/telu:ca": "\u0C1A",
+ "/telu:cha": "\u0C1B",
+ "/telu:combiningbinduabovesigncandra": "\u0C00",
+ "/telu:da": "\u0C26",
+ "/telu:dda": "\u0C21",
+ "/telu:ddha": "\u0C22",
+ "/telu:dha": "\u0C27",
+ "/telu:dza": "\u0C59",
+ "/telu:e": "\u0C0E",
+ "/telu:ee": "\u0C0F",
+ "/telu:eesign": "\u0C47",
+ "/telu:eight": "\u0C6E",
+ "/telu:esign": "\u0C46",
+ "/telu:five": "\u0C6B",
+ "/telu:four": "\u0C6A",
+ "/telu:fractiononeforevenpowersoffour": "\u0C7C",
+ "/telu:fractiononeforoddpowersoffour": "\u0C79",
+ "/telu:fractionthreeforevenpowersoffour": "\u0C7E",
+ "/telu:fractionthreeforoddpowersoffour": "\u0C7B",
+ "/telu:fractiontwoforevenpowersoffour": "\u0C7D",
+ "/telu:fractiontwoforoddpowersoffour": "\u0C7A",
+ "/telu:fractionzeroforoddpowersoffour": "\u0C78",
+ "/telu:ga": "\u0C17",
+ "/telu:gha": "\u0C18",
+ "/telu:ha": "\u0C39",
+ "/telu:i": "\u0C07",
+ "/telu:ii": "\u0C08",
+ "/telu:iisign": "\u0C40",
+ "/telu:isign": "\u0C3F",
+ "/telu:ja": "\u0C1C",
+ "/telu:jha": "\u0C1D",
+ "/telu:ka": "\u0C15",
+ "/telu:kha": "\u0C16",
+ "/telu:la": "\u0C32",
+ "/telu:lengthmark": "\u0C55",
+ "/telu:lla": "\u0C33",
+ "/telu:llla": "\u0C34",
+ "/telu:llsignvocal": "\u0C63",
+ "/telu:llvocal": "\u0C61",
+ "/telu:lsignvocal": "\u0C62",
+ "/telu:lvocal": "\u0C0C",
+ "/telu:ma": "\u0C2E",
+ "/telu:na": "\u0C28",
+ "/telu:nga": "\u0C19",
+ "/telu:nine": "\u0C6F",
+ "/telu:nna": "\u0C23",
+ "/telu:nya": "\u0C1E",
+ "/telu:o": "\u0C12",
+ "/telu:one": "\u0C67",
+ "/telu:oo": "\u0C13",
+ "/telu:oosign": "\u0C4B",
+ "/telu:osign": "\u0C4A",
+ "/telu:pa": "\u0C2A",
+ "/telu:pha": "\u0C2B",
+ "/telu:ra": "\u0C30",
+ "/telu:rra": "\u0C31",
+ "/telu:rrra": "\u0C5A",
+ "/telu:rrsignvocal": "\u0C44",
+ "/telu:rrvocal": "\u0C60",
+ "/telu:rsignvocal": "\u0C43",
+ "/telu:rvocal": "\u0C0B",
+ "/telu:sa": "\u0C38",
+ "/telu:seven": "\u0C6D",
+ "/telu:sha": "\u0C36",
+ "/telu:six": "\u0C6C",
+ "/telu:ssa": "\u0C37",
+ "/telu:ta": "\u0C24",
+ "/telu:tha": "\u0C25",
+ "/telu:three": "\u0C69",
+ "/telu:tsa": "\u0C58",
+ "/telu:tta": "\u0C1F",
+ "/telu:ttha": "\u0C20",
+ "/telu:tuumusign": "\u0C7F",
+ "/telu:two": "\u0C68",
+ "/telu:u": "\u0C09",
+ "/telu:usign": "\u0C41",
+ "/telu:uu": "\u0C0A",
+ "/telu:uusign": "\u0C42",
+ "/telu:va": "\u0C35",
+ "/telu:viramasign": "\u0C4D",
+ "/telu:visargasign": "\u0C03",
+ "/telu:ya": "\u0C2F",
+ "/telu:zero": "\u0C66",
+ "/ten.roman": "\u2169",
+ "/ten.romansmall": "\u2179",
+ "/tencircle": "\u2469",
+ "/tencircledbl": "\u24FE",
+ "/tencirclesquare": "\u3248",
+ "/tenge": "\u20B8",
+ "/tenhangzhou": "\u3038",
+ "/tenideographiccircled": "\u3289",
+ "/tenideographicparen": "\u3229",
+ "/tennisRacquetAndBall": "\u1F3BE",
+ "/tenparen": "\u247D",
+ "/tenparenthesized": "\u247D",
+ "/tenperiod": "\u2491",
+ "/tenroman": "\u2179",
+ "/tent": "\u26FA",
+ "/tenthousand.roman": "\u2182",
+ "/tesh": "\u02A7",
+ "/tet": "\u05D8",
+ "/tet:hb": "\u05D8",
+ "/tetailcyr": "\u04AD",
+ "/tetdagesh": "\uFB38",
+ "/tetdageshhebrew": "\uFB38",
+ "/tethebrew": "\u05D8",
+ "/tetrasememetrical": "\u23D8",
+ "/tetsecyr": "\u04B5",
+ "/tetsecyrillic": "\u04B5",
+ "/tetwithdagesh:hb": "\uFB38",
+ "/tevir:hb": "\u059B",
+ "/tevirhebrew": "\u059B",
+ "/tevirlefthebrew": "\u059B",
+ "/thabengali": "\u09A5",
+ "/thadeva": "\u0925",
+ "/thagujarati": "\u0AA5",
+ "/thagurmukhi": "\u0A25",
+ "/thai:angkhankhu": "\u0E5A",
+ "/thai:baht": "\u0E3F",
+ "/thai:bobaimai": "\u0E1A",
+ "/thai:chochan": "\u0E08",
+ "/thai:chochang": "\u0E0A",
+ "/thai:choching": "\u0E09",
+ "/thai:chochoe": "\u0E0C",
+ "/thai:dochada": "\u0E0E",
+ "/thai:dodek": "\u0E14",
+ "/thai:eight": "\u0E58",
+ "/thai:five": "\u0E55",
+ "/thai:fofa": "\u0E1D",
+ "/thai:fofan": "\u0E1F",
+ "/thai:fongman": "\u0E4F",
+ "/thai:four": "\u0E54",
+ "/thai:hohip": "\u0E2B",
+ "/thai:honokhuk": "\u0E2E",
+ "/thai:khokhai": "\u0E02",
+ "/thai:khokhon": "\u0E05",
+ "/thai:khokhuat": "\u0E03",
+ "/thai:khokhwai": "\u0E04",
+ "/thai:khomut": "\u0E5B",
+ "/thai:khorakhang": "\u0E06",
+ "/thai:kokai": "\u0E01",
+ "/thai:lakkhangyao": "\u0E45",
+ "/thai:lochula": "\u0E2C",
+ "/thai:loling": "\u0E25",
+ "/thai:lu": "\u0E26",
+ "/thai:maichattawa": "\u0E4B",
+ "/thai:maiek": "\u0E48",
+ "/thai:maihan-akat": "\u0E31",
+ "/thai:maitaikhu": "\u0E47",
+ "/thai:maitho": "\u0E49",
+ "/thai:maitri": "\u0E4A",
+ "/thai:maiyamok": "\u0E46",
+ "/thai:moma": "\u0E21",
+ "/thai:ngongu": "\u0E07",
+ "/thai:nikhahit": "\u0E4D",
+ "/thai:nine": "\u0E59",
+ "/thai:nonen": "\u0E13",
+ "/thai:nonu": "\u0E19",
+ "/thai:oang": "\u0E2D",
+ "/thai:one": "\u0E51",
+ "/thai:paiyannoi": "\u0E2F",
+ "/thai:phinthu": "\u0E3A",
+ "/thai:phophan": "\u0E1E",
+ "/thai:phophung": "\u0E1C",
+ "/thai:phosamphao": "\u0E20",
+ "/thai:popla": "\u0E1B",
+ "/thai:rorua": "\u0E23",
+ "/thai:ru": "\u0E24",
+ "/thai:saraa": "\u0E30",
+ "/thai:saraaa": "\u0E32",
+ "/thai:saraae": "\u0E41",
+ "/thai:saraaimaimalai": "\u0E44",
+ "/thai:saraaimaimuan": "\u0E43",
+ "/thai:saraam": "\u0E33",
+ "/thai:sarae": "\u0E40",
+ "/thai:sarai": "\u0E34",
+ "/thai:saraii": "\u0E35",
+ "/thai:sarao": "\u0E42",
+ "/thai:sarau": "\u0E38",
+ "/thai:saraue": "\u0E36",
+ "/thai:sarauee": "\u0E37",
+ "/thai:sarauu": "\u0E39",
+ "/thai:seven": "\u0E57",
+ "/thai:six": "\u0E56",
+ "/thai:sorusi": "\u0E29",
+ "/thai:sosala": "\u0E28",
+ "/thai:soso": "\u0E0B",
+ "/thai:sosua": "\u0E2A",
+ "/thai:thanthakhat": "\u0E4C",
+ "/thai:thonangmontho": "\u0E11",
+ "/thai:thophuthao": "\u0E12",
+ "/thai:thothahan": "\u0E17",
+ "/thai:thothan": "\u0E10",
+ "/thai:thothong": "\u0E18",
+ "/thai:thothung": "\u0E16",
+ "/thai:three": "\u0E53",
+ "/thai:topatak": "\u0E0F",
+ "/thai:totao": "\u0E15",
+ "/thai:two": "\u0E52",
+ "/thai:wowaen": "\u0E27",
+ "/thai:yamakkan": "\u0E4E",
+ "/thai:yoyak": "\u0E22",
+ "/thai:yoying": "\u0E0D",
+ "/thai:zero": "\u0E50",
+ "/thal": "\u0630",
+ "/thal.fina": "\uFEAC",
+ "/thal.init_superscriptalef.fina": "\uFC5B",
+ "/thal.isol": "\uFEAB",
+ "/thalarabic": "\u0630",
+ "/thalfinalarabic": "\uFEAC",
+ "/thanthakhatlowleftthai": "\uF898",
+ "/thanthakhatlowrightthai": "\uF897",
+ "/thanthakhatthai": "\u0E4C",
+ "/thanthakhatupperleftthai": "\uF896",
+ "/theh": "\u062B",
+ "/theh.fina": "\uFE9A",
+ "/theh.init": "\uFE9B",
+ "/theh.init_alefmaksura.fina": "\uFC13",
+ "/theh.init_jeem.fina": "\uFC11",
+ "/theh.init_meem.fina": "\uFC12",
+ "/theh.init_meem.medi": "\uFCA6",
+ "/theh.init_yeh.fina": "\uFC14",
+ "/theh.isol": "\uFE99",
+ "/theh.medi": "\uFE9C",
+ "/theh.medi_alefmaksura.fina": "\uFC7A",
+ "/theh.medi_heh.medi": "\uFCE6",
+ "/theh.medi_meem.fina": "\uFC78",
+ "/theh.medi_meem.medi": "\uFCE5",
+ "/theh.medi_noon.fina": "\uFC79",
+ "/theh.medi_reh.fina": "\uFC76",
+ "/theh.medi_yeh.fina": "\uFC7B",
+ "/theh.medi_zain.fina": "\uFC77",
+ "/theharabic": "\u062B",
+ "/thehfinalarabic": "\uFE9A",
+ "/thehinitialarabic": "\uFE9B",
+ "/thehmedialarabic": "\uFE9C",
+ "/thereexists": "\u2203",
+ "/therefore": "\u2234",
+ "/thermometer": "\u1F321",
+ "/theta": "\u03B8",
+ "/theta.math": "\u03D1",
+ "/theta1": "\u03D1",
+ "/thetasymbolgreek": "\u03D1",
+ "/thieuthacirclekorean": "\u3279",
+ "/thieuthaparenkorean": "\u3219",
+ "/thieuthcirclekorean": "\u326B",
+ "/thieuthkorean": "\u314C",
+ "/thieuthparenkorean": "\u320B",
+ "/thinspace": "\u2009",
+ "/thirteencircle": "\u246C",
+ "/thirteencircleblack": "\u24ED",
+ "/thirteenparen": "\u2480",
+ "/thirteenparenthesized": "\u2480",
+ "/thirteenperiod": "\u2494",
+ "/thirtycircle": "\u325A",
+ "/thirtycirclesquare": "\u324A",
+ "/thirtyeightcircle": "\u32B3",
+ "/thirtyfivecircle": "\u325F",
+ "/thirtyfourcircle": "\u325E",
+ "/thirtyhangzhou": "\u303A",
+ "/thirtyninecircle": "\u32B4",
+ "/thirtyonecircle": "\u325B",
+ "/thirtysevencircle": "\u32B2",
+ "/thirtysixcircle": "\u32B1",
+ "/thirtythreecircle": "\u325D",
+ "/thirtytwocircle": "\u325C",
+ "/thonangmonthothai": "\u0E11",
+ "/thook": "\u01AD",
+ "/thophuthaothai": "\u0E12",
+ "/thorn": "\u00FE",
+ "/thornstroke": "\uA765",
+ "/thornstrokedescender": "\uA767",
+ "/thothahanthai": "\u0E17",
+ "/thothanthai": "\u0E10",
+ "/thothongthai": "\u0E18",
+ "/thothungthai": "\u0E16",
+ "/thoughtBalloon": "\u1F4AD",
+ "/thousandcyrillic": "\u0482",
+ "/thousandscyr": "\u0482",
+ "/thousandsseparator": "\u066C",
+ "/thousandsseparatorarabic": "\u066C",
+ "/thousandsseparatorpersian": "\u066C",
+ "/three": "\u0033",
+ "/three.inferior": "\u2083",
+ "/three.roman": "\u2162",
+ "/three.romansmall": "\u2172",
+ "/threeButtonMouse": "\u1F5B1",
+ "/threeNetworkedComputers": "\u1F5A7",
+ "/threeRaysAbove": "\u1F5E4",
+ "/threeRaysBelow": "\u1F5E5",
+ "/threeRaysLeft": "\u1F5E6",
+ "/threeRaysRight": "\u1F5E7",
+ "/threeSpeechBubbles": "\u1F5EB",
+ "/threearabic": "\u0663",
+ "/threebengali": "\u09E9",
+ "/threecircle": "\u2462",
+ "/threecircledbl": "\u24F7",
+ "/threecircleinversesansserif": "\u278C",
+ "/threecomma": "\u1F104",
+ "/threedeva": "\u0969",
+ "/threedimensionalangle": "\u27C0",
+ "/threedotpunctuation": "\u2056",
+ "/threedotsaboveabove": "\u06DB",
+ "/threedsquare": "\u1F19B",
+ "/threeeighths": "\u215C",
+ "/threefar": "\u06F3",
+ "/threefifths": "\u2157",
+ "/threegujarati": "\u0AE9",
+ "/threegurmukhi": "\u0A69",
+ "/threehackarabic": "\u0663",
+ "/threehangzhou": "\u3023",
+ "/threeideographiccircled": "\u3282",
+ "/threeideographicparen": "\u3222",
+ "/threeinferior": "\u2083",
+ "/threelinesconvergingleft": "\u269F",
+ "/threelinesconvergingright": "\u269E",
+ "/threemonospace": "\uFF13",
+ "/threenumeratorbengali": "\u09F6",
+ "/threeoldstyle": "\uF733",
+ "/threeparen": "\u2476",
+ "/threeparenthesized": "\u2476",
+ "/threeperemspace": "\u2004",
+ "/threeperiod": "\u248A",
+ "/threepersian": "\u06F3",
+ "/threequarters": "\u00BE",
+ "/threequartersemdash": "\uF6DE",
+ "/threerightarrows": "\u21F6",
+ "/threeroman": "\u2172",
+ "/threesuperior": "\u00B3",
+ "/threethai": "\u0E53",
+ "/thumbsDownSign": "\u1F44E",
+ "/thumbsUpSign": "\u1F44D",
+ "/thundercloudrain": "\u26C8",
+ "/thunderstorm": "\u2608",
+ "/thzfullwidth": "\u3394",
+ "/thzsquare": "\u3394",
+ "/tibt:AA": "\u0F60",
+ "/tibt:a": "\u0F68",
+ "/tibt:aavowelsign": "\u0F71",
+ "/tibt:angkhanggyasmark": "\u0F3D",
+ "/tibt:angkhanggyonmark": "\u0F3C",
+ "/tibt:astrologicalkhyudpasign": "\u0F18",
+ "/tibt:astrologicalsdongtshugssign": "\u0F19",
+ "/tibt:astrologicalsgragcancharrtagssign": "\u0F17",
+ "/tibt:asubjoined": "\u0FB8",
+ "/tibt:ba": "\u0F56",
+ "/tibt:basubjoined": "\u0FA6",
+ "/tibt:bha": "\u0F57",
+ "/tibt:bhasubjoined": "\u0FA7",
+ "/tibt:bkashogyigmgomark": "\u0F0A",
+ "/tibt:brdarnyingyigmgomdunmainitialmark": "\u0FD3",
+ "/tibt:brdarnyingyigmgosgabmaclosingmark": "\u0FD4",
+ "/tibt:bsdusrtagsmark": "\u0F34",
+ "/tibt:bskashoggimgorgyanmark": "\u0FD0",
+ "/tibt:bskuryigmgomark": "\u0F09",
+ "/tibt:ca": "\u0F45",
+ "/tibt:cangteucantillationsign": "\u0FC2",
+ "/tibt:caretdzudrtagsbzhimigcanmark": "\u0F36",
+ "/tibt:caretdzudrtagsmelongcanmark": "\u0F13",
+ "/tibt:caretyigmgophurshadmamark": "\u0F06",
+ "/tibt:casubjoined": "\u0F95",
+ "/tibt:cha": "\u0F46",
+ "/tibt:chadrtagslogotypesign": "\u0F15",
+ "/tibt:chasubjoined": "\u0F96",
+ "/tibt:chemgomark": "\u0F38",
+ "/tibt:da": "\u0F51",
+ "/tibt:dasubjoined": "\u0FA1",
+ "/tibt:dda": "\u0F4C",
+ "/tibt:ddasubjoined": "\u0F9C",
+ "/tibt:ddha": "\u0F4D",
+ "/tibt:ddhasubjoined": "\u0F9D",
+ "/tibt:delimitertshegbstarmark": "\u0F0C",
+ "/tibt:dha": "\u0F52",
+ "/tibt:dhasubjoined": "\u0FA2",
+ "/tibt:drilbusymbol": "\u0FC4",
+ "/tibt:dza": "\u0F5B",
+ "/tibt:dzasubjoined": "\u0FAB",
+ "/tibt:dzha": "\u0F5C",
+ "/tibt:dzhasubjoined": "\u0FAC",
+ "/tibt:eevowelsign": "\u0F7B",
+ "/tibt:eight": "\u0F28",
+ "/tibt:evowelsign": "\u0F7A",
+ "/tibt:five": "\u0F25",
+ "/tibt:four": "\u0F24",
+ "/tibt:ga": "\u0F42",
+ "/tibt:gasubjoined": "\u0F92",
+ "/tibt:gha": "\u0F43",
+ "/tibt:ghasubjoined": "\u0F93",
+ "/tibt:grucanrgyingssign": "\u0F8A",
+ "/tibt:grumedrgyingssign": "\u0F8B",
+ "/tibt:gtertshegmark": "\u0F14",
+ "/tibt:gteryigmgotruncatedamark": "\u0F01",
+ "/tibt:gteryigmgoumgtertshegmamark": "\u0F03",
+ "/tibt:gteryigmgoumrnambcadmamark": "\u0F02",
+ "/tibt:gugrtagsgyasmark": "\u0F3B",
+ "/tibt:gugrtagsgyonmark": "\u0F3A",
+ "/tibt:ha": "\u0F67",
+ "/tibt:halantamark": "\u0F84",
+ "/tibt:halfeight": "\u0F31",
+ "/tibt:halffive": "\u0F2E",
+ "/tibt:halffour": "\u0F2D",
+ "/tibt:halfnine": "\u0F32",
+ "/tibt:halfone": "\u0F2A",
+ "/tibt:halfseven": "\u0F30",
+ "/tibt:halfsix": "\u0F2F",
+ "/tibt:halfthree": "\u0F2C",
+ "/tibt:halftwo": "\u0F2B",
+ "/tibt:halfzero": "\u0F33",
+ "/tibt:hasubjoined": "\u0FB7",
+ "/tibt:heavybeatcantillationsign": "\u0FC0",
+ "/tibt:iivowelsign": "\u0F73",
+ "/tibt:intersyllabictshegmark": "\u0F0B",
+ "/tibt:invertedmchucansign": "\u0F8C",
+ "/tibt:invertedmchucansubjoinedsign": "\u0F8F",
+ "/tibt:ivowelsign": "\u0F72",
+ "/tibt:ja": "\u0F47",
+ "/tibt:jasubjoined": "\u0F97",
+ "/tibt:ka": "\u0F40",
+ "/tibt:kasubjoined": "\u0F90",
+ "/tibt:kha": "\u0F41",
+ "/tibt:khasubjoined": "\u0F91",
+ "/tibt:kka": "\u0F6B",
+ "/tibt:kssa": "\u0F69",
+ "/tibt:kssasubjoined": "\u0FB9",
+ "/tibt:kurukha": "\u0FBE",
+ "/tibt:kurukhabzhimigcan": "\u0FBF",
+ "/tibt:la": "\u0F63",
+ "/tibt:lasubjoined": "\u0FB3",
+ "/tibt:lcetsacansign": "\u0F88",
+ "/tibt:lcetsacansubjoinedsign": "\u0F8D",
+ "/tibt:lcirtagssign": "\u0F86",
+ "/tibt:leadingmchanrtagsmark": "\u0FD9",
+ "/tibt:lhagrtagslogotypesign": "\u0F16",
+ "/tibt:lightbeatcantillationsign": "\u0FC1",
+ "/tibt:llvocalicvowelsign": "\u0F79",
+ "/tibt:lvocalicvowelsign": "\u0F78",
+ "/tibt:ma": "\u0F58",
+ "/tibt:martshessign": "\u0F3F",
+ "/tibt:masubjoined": "\u0FA8",
+ "/tibt:mchucansign": "\u0F89",
+ "/tibt:mchucansubjoinedsign": "\u0F8E",
+ "/tibt:mnyamyiggimgorgyanmark": "\u0FD1",
+ "/tibt:na": "\u0F53",
+ "/tibt:nasubjoined": "\u0FA3",
+ "/tibt:nga": "\u0F44",
+ "/tibt:ngasbzungnyizlamark": "\u0F35",
+ "/tibt:ngasbzungsgorrtagsmark": "\u0F37",
+ "/tibt:ngasubjoined": "\u0F94",
+ "/tibt:nine": "\u0F29",
+ "/tibt:nna": "\u0F4E",
+ "/tibt:nnasubjoined": "\u0F9E",
+ "/tibt:norbubzhikhyilsymbol": "\u0FCC",
+ "/tibt:norbugsumkhyilsymbol": "\u0FCB",
+ "/tibt:norbunyiskhyilsymbol": "\u0FCA",
+ "/tibt:norbusymbol": "\u0FC9",
+ "/tibt:nya": "\u0F49",
+ "/tibt:nyasubjoined": "\u0F99",
+ "/tibt:nyisshadmark": "\u0F0E",
+ "/tibt:nyistshegmark": "\u0FD2",
+ "/tibt:nyistshegshadmark": "\u0F10",
+ "/tibt:nyizlanaadasign": "\u0F82",
+ "/tibt:omsyllable": "\u0F00",
+ "/tibt:one": "\u0F21",
+ "/tibt:oovowelsign": "\u0F7D",
+ "/tibt:ovowelsign": "\u0F7C",
+ "/tibt:pa": "\u0F54",
+ "/tibt:padmagdansymbol": "\u0FC6",
+ "/tibt:palutamark": "\u0F85",
+ "/tibt:pasubjoined": "\u0FA4",
+ "/tibt:pha": "\u0F55",
+ "/tibt:phasubjoined": "\u0FA5",
+ "/tibt:phurpasymbol": "\u0FC8",
+ "/tibt:ra": "\u0F62",
+ "/tibt:rafixed": "\u0F6A",
+ "/tibt:rasubjoined": "\u0FB2",
+ "/tibt:rasubjoinedfixed": "\u0FBC",
+ "/tibt:rdeldkargcigsign": "\u0F1A",
+ "/tibt:rdeldkargnyissign": "\u0F1B",
+ "/tibt:rdeldkargsumsign": "\u0F1C",
+ "/tibt:rdeldkarrdelnagsign": "\u0F1F",
+ "/tibt:rdelnaggcigsign": "\u0F1D",
+ "/tibt:rdelnaggnyissign": "\u0F1E",
+ "/tibt:rdelnaggsumsign": "\u0FCF",
+ "/tibt:rdelnagrdeldkarsign": "\u0FCE",
+ "/tibt:rdorjergyagramsymbol": "\u0FC7",
+ "/tibt:rdorjesymbol": "\u0FC5",
+ "/tibt:reversediivowelsign": "\u0F81",
+ "/tibt:reversedivowelsign": "\u0F80",
+ "/tibt:rgyagramshadmark": "\u0F12",
+ "/tibt:rinchenspungsshadmark": "\u0F11",
+ "/tibt:rjessungarosign": "\u0F7E",
+ "/tibt:rnambcadsign": "\u0F7F",
+ "/tibt:rra": "\u0F6C",
+ "/tibt:rrvocalicvowelsign": "\u0F77",
+ "/tibt:rvocalicvowelsign": "\u0F76",
+ "/tibt:sa": "\u0F66",
+ "/tibt:sasubjoined": "\u0FB6",
+ "/tibt:sbrulshadmark": "\u0F08",
+ "/tibt:sbubchalcantillationsign": "\u0FC3",
+ "/tibt:seven": "\u0F27",
+ "/tibt:sha": "\u0F64",
+ "/tibt:shadmark": "\u0F0D",
+ "/tibt:shasubjoined": "\u0FB4",
+ "/tibt:six": "\u0F26",
+ "/tibt:snaldansign": "\u0F83",
+ "/tibt:ssa": "\u0F65",
+ "/tibt:ssasubjoined": "\u0FB5",
+ "/tibt:subjoinedAA": "\u0FB0",
+ "/tibt:svastileft": "\u0FD6",
+ "/tibt:svastileftdot": "\u0FD8",
+ "/tibt:svastiright": "\u0FD5",
+ "/tibt:svastirightdot": "\u0FD7",
+ "/tibt:ta": "\u0F4F",
+ "/tibt:tasubjoined": "\u0F9F",
+ "/tibt:tha": "\u0F50",
+ "/tibt:thasubjoined": "\u0FA0",
+ "/tibt:three": "\u0F23",
+ "/tibt:trailingmchanrtagsmark": "\u0FDA",
+ "/tibt:tsa": "\u0F59",
+ "/tibt:tsaphrumark": "\u0F39",
+ "/tibt:tsasubjoined": "\u0FA9",
+ "/tibt:tsha": "\u0F5A",
+ "/tibt:tshasubjoined": "\u0FAA",
+ "/tibt:tshegshadmark": "\u0F0F",
+ "/tibt:tta": "\u0F4A",
+ "/tibt:ttasubjoined": "\u0F9A",
+ "/tibt:ttha": "\u0F4B",
+ "/tibt:tthasubjoined": "\u0F9B",
+ "/tibt:two": "\u0F22",
+ "/tibt:uuvowelsign": "\u0F75",
+ "/tibt:uvowelsign": "\u0F74",
+ "/tibt:wa": "\u0F5D",
+ "/tibt:wasubjoined": "\u0FAD",
+ "/tibt:wasubjoinedfixed": "\u0FBA",
+ "/tibt:ya": "\u0F61",
+ "/tibt:yangrtagssign": "\u0F87",
+ "/tibt:yartshessign": "\u0F3E",
+ "/tibt:yasubjoined": "\u0FB1",
+ "/tibt:yasubjoinedfixed": "\u0FBB",
+ "/tibt:yigmgomdunmainitialmark": "\u0F04",
+ "/tibt:yigmgosgabmaclosingmark": "\u0F05",
+ "/tibt:yigmgotshegshadmamark": "\u0F07",
+ "/tibt:za": "\u0F5F",
+ "/tibt:zasubjoined": "\u0FAF",
+ "/tibt:zero": "\u0F20",
+ "/tibt:zha": "\u0F5E",
+ "/tibt:zhasubjoined": "\u0FAE",
+ "/ticirclekatakana": "\u32E0",
+ "/tickconvavediamondleftwhite": "\u27E2",
+ "/tickconvavediamondrightwhite": "\u27E3",
+ "/ticket": "\u1F3AB",
+ "/tickleftwhitesquare": "\u27E4",
+ "/tickrightwhitesquare": "\u27E5",
+ "/tifcha:hb": "\u0596",
+ "/tiger": "\u1F405",
+ "/tigerFace": "\u1F42F",
+ "/tihiragana": "\u3061",
+ "/tikatakana": "\u30C1",
+ "/tikatakanahalfwidth": "\uFF81",
+ "/tikeutacirclekorean": "\u3270",
+ "/tikeutaparenkorean": "\u3210",
+ "/tikeutcirclekorean": "\u3262",
+ "/tikeutkorean": "\u3137",
+ "/tikeutparenkorean": "\u3202",
+ "/tilde": "\u02DC",
+ "/tildebelowcmb": "\u0330",
+ "/tildecmb": "\u0303",
+ "/tildecomb": "\u0303",
+ "/tildediaeresisfunc": "\u2368",
+ "/tildedotaccent": "\u2E1E",
+ "/tildedotbelow": "\u2E1F",
+ "/tildedoublecmb": "\u0360",
+ "/tildeequalsreversed": "\u22CD",
+ "/tildelowmod": "\u02F7",
+ "/tildeoperator": "\u223C",
+ "/tildeoverlaycmb": "\u0334",
+ "/tildereversed": "\u223D",
+ "/tildering": "\u2E1B",
+ "/tildetpl": "\u224B",
+ "/tildeverticalcmb": "\u033E",
+ "/timerclock": "\u23F2",
+ "/timescircle": "\u2297",
+ "/tinsular": "\uA787",
+ "/tipehahebrew": "\u0596",
+ "/tipehalefthebrew": "\u0596",
+ "/tippigurmukhi": "\u0A70",
+ "/tiredFace": "\u1F62B",
+ "/tironiansignet": "\u204A",
+ "/tirtatumetespada": "\uA9DE",
+ "/titlocmbcyr": "\u0483",
+ "/titlocyrilliccmb": "\u0483",
+ "/tiwnarmenian": "\u057F",
+ "/tjekomicyr": "\u050F",
+ "/tlinebelow": "\u1E6F",
+ "/tmonospace": "\uFF54",
+ "/toarmenian": "\u0569",
+ "/tocirclekatakana": "\u32E3",
+ "/tocornerarrowNW": "\u21F1",
+ "/tocornerarrowSE": "\u21F2",
+ "/tohiragana": "\u3068",
+ "/toilet": "\u1F6BD",
+ "/tokatakana": "\u30C8",
+ "/tokatakanahalfwidth": "\uFF84",
+ "/tokyoTower": "\u1F5FC",
+ "/tolongvowel": "\uA9B5",
+ "/tomato": "\u1F345",
+ "/tonebarextrahighmod": "\u02E5",
+ "/tonebarextralowmod": "\u02E9",
+ "/tonebarhighmod": "\u02E6",
+ "/tonebarlowmod": "\u02E8",
+ "/tonebarmidmod": "\u02E7",
+ "/tonefive": "\u01BD",
+ "/tonehighbeginmod": "\u02F9",
+ "/tonehighendmod": "\u02FA",
+ "/tonelowbeginmod": "\u02FB",
+ "/tonelowendmod": "\u02FC",
+ "/tonesix": "\u0185",
+ "/tonetwo": "\u01A8",
+ "/tongue": "\u1F445",
+ "/tonos": "\u0384",
+ "/tonsquare": "\u3327",
+ "/topHat": "\u1F3A9",
+ "/topUpwardsArrowAbove": "\u1F51D",
+ "/topatakthai": "\u0E0F",
+ "/tortoiseshellbracketleft": "\u3014",
+ "/tortoiseshellbracketleftsmall": "\uFE5D",
+ "/tortoiseshellbracketleftvertical": "\uFE39",
+ "/tortoiseshellbracketright": "\u3015",
+ "/tortoiseshellbracketrightsmall": "\uFE5E",
+ "/tortoiseshellbracketrightvertical": "\uFE3A",
+ "/totalrunout": "\u2330",
+ "/totaothai": "\u0E15",
+ "/tpalatalhook": "\u01AB",
+ "/tparen": "\u24AF",
+ "/tparenthesized": "\u24AF",
+ "/trackball": "\u1F5B2",
+ "/tractor": "\u1F69C",
+ "/trademark": "\u2122",
+ "/trademarksans": "\uF8EA",
+ "/trademarkserif": "\uF6DB",
+ "/train": "\u1F686",
+ "/tram": "\u1F68A",
+ "/tramCar": "\u1F68B",
+ "/trapeziumwhite": "\u23E2",
+ "/tresillo": "\uA72B",
+ "/tretroflex": "\u0288",
+ "/tretroflexhook": "\u0288",
+ "/triagdn": "\u25BC",
+ "/triaglf": "\u25C4",
+ "/triagrt": "\u25BA",
+ "/triagup": "\u25B2",
+ "/triangleWithRoundedCorners": "\u1F6C6",
+ "/triangledotupwhite": "\u25EC",
+ "/triangledownblack": "\u25BC",
+ "/triangledownsmallblack": "\u25BE",
+ "/triangledownsmallwhite": "\u25BF",
+ "/triangledownwhite": "\u25BD",
+ "/trianglehalfupleftblack": "\u25ED",
+ "/trianglehalfuprightblack": "\u25EE",
+ "/triangleleftblack": "\u25C0",
+ "/triangleleftsmallblack": "\u25C2",
+ "/triangleleftsmallwhite": "\u25C3",
+ "/triangleleftwhite": "\u25C1",
+ "/triangleright": "\u22BF",
+ "/trianglerightblack": "\u25B6",
+ "/trianglerightsmallblack": "\u25B8",
+ "/trianglerightsmallwhite": "\u25B9",
+ "/trianglerightwhite": "\u25B7",
+ "/triangleupblack": "\u25B2",
+ "/triangleupsmallblack": "\u25B4",
+ "/triangleupsmallwhite": "\u25B5",
+ "/triangleupwhite": "\u25B3",
+ "/triangularFlagOnPost": "\u1F6A9",
+ "/triangularRuler": "\u1F4D0",
+ "/triangularbullet": "\u2023",
+ "/tricolon": "\u205D",
+ "/tricontainingtriwhiteanglesmall": "\u27C1",
+ "/tridentEmblem": "\u1F531",
+ "/trigramearth": "\u2637",
+ "/trigramfire": "\u2632",
+ "/trigramheaven": "\u2630",
+ "/trigramlake": "\u2631",
+ "/trigrammountain": "\u2636",
+ "/trigramthunder": "\u2633",
+ "/trigramwater": "\u2635",
+ "/trigramwind": "\u2634",
+ "/triplearrowleft": "\u21DA",
+ "/triplearrowright": "\u21DB",
+ "/tripledot": "\u061E",
+ "/trisememetrical": "\u23D7",
+ "/trns:baby": "\u1F6BC",
+ "/trolleybus": "\u1F68E",
+ "/trophy": "\u1F3C6",
+ "/tropicalDrink": "\u1F379",
+ "/tropicalFish": "\u1F420",
+ "/truckblack": "\u26DF",
+ "/true": "\u22A8",
+ "/trumpet": "\u1F3BA",
+ "/ts": "\u02A6",
+ "/tsadi": "\u05E6",
+ "/tsadi:hb": "\u05E6",
+ "/tsadidagesh": "\uFB46",
+ "/tsadidageshhebrew": "\uFB46",
+ "/tsadihebrew": "\u05E6",
+ "/tsadiwithdagesh:hb": "\uFB46",
+ "/tsecyr": "\u0446",
+ "/tsecyrillic": "\u0446",
+ "/tsere": "\u05B5",
+ "/tsere12": "\u05B5",
+ "/tsere1e": "\u05B5",
+ "/tsere2b": "\u05B5",
+ "/tsere:hb": "\u05B5",
+ "/tserehebrew": "\u05B5",
+ "/tserenarrowhebrew": "\u05B5",
+ "/tserequarterhebrew": "\u05B5",
+ "/tserewidehebrew": "\u05B5",
+ "/tshecyr": "\u045B",
+ "/tshecyrillic": "\u045B",
+ "/tsinnorit:hb": "\u05AE",
+ "/tstroke": "\u2C66",
+ "/tsuperior": "\uF6F3",
+ "/ttabengali": "\u099F",
+ "/ttadeva": "\u091F",
+ "/ttagujarati": "\u0A9F",
+ "/ttagurmukhi": "\u0A1F",
+ "/ttamahaprana": "\uA99C",
+ "/tteh": "\u0679",
+ "/tteh.fina": "\uFB67",
+ "/tteh.init": "\uFB68",
+ "/tteh.isol": "\uFB66",
+ "/tteh.medi": "\uFB69",
+ "/tteharabic": "\u0679",
+ "/tteheh": "\u067A",
+ "/tteheh.fina": "\uFB5F",
+ "/tteheh.init": "\uFB60",
+ "/tteheh.isol": "\uFB5E",
+ "/tteheh.medi": "\uFB61",
+ "/ttehfinalarabic": "\uFB67",
+ "/ttehinitialarabic": "\uFB68",
+ "/ttehmedialarabic": "\uFB69",
+ "/tthabengali": "\u09A0",
+ "/tthadeva": "\u0920",
+ "/tthagujarati": "\u0AA0",
+ "/tthagurmukhi": "\u0A20",
+ "/tturned": "\u0287",
+ "/tucirclekatakana": "\u32E1",
+ "/tugrik": "\u20AE",
+ "/tuhiragana": "\u3064",
+ "/tukatakana": "\u30C4",
+ "/tukatakanahalfwidth": "\uFF82",
+ "/tulip": "\u1F337",
+ "/tum": "\uA777",
+ "/turkishlira": "\u20BA",
+ "/turnedOkHandSign": "\u1F58F",
+ "/turnedcomma": "\u2E32",
+ "/turneddagger": "\u2E38",
+ "/turneddigitthree": "\u218B",
+ "/turneddigittwo": "\u218A",
+ "/turnedpiselehpada": "\uA9CD",
+ "/turnedsemicolon": "\u2E35",
+ "/turnedshogipieceblack": "\u26CA",
+ "/turnedshogipiecewhite": "\u26C9",
+ "/turnstiledblverticalbarright": "\u22AB",
+ "/turnstileleftrightdbl": "\u27DA",
+ "/turnstiletplverticalbarright": "\u22AA",
+ "/turtle": "\u1F422",
+ "/tusmallhiragana": "\u3063",
+ "/tusmallkatakana": "\u30C3",
+ "/tusmallkatakanahalfwidth": "\uFF6F",
+ "/twelve.roman": "\u216B",
+ "/twelve.romansmall": "\u217B",
+ "/twelvecircle": "\u246B",
+ "/twelvecircleblack": "\u24EC",
+ "/twelveparen": "\u247F",
+ "/twelveparenthesized": "\u247F",
+ "/twelveperiod": "\u2493",
+ "/twelveroman": "\u217B",
+ "/twenty-twopointtwosquare": "\u1F1A2",
+ "/twentycircle": "\u2473",
+ "/twentycircleblack": "\u24F4",
+ "/twentycirclesquare": "\u3249",
+ "/twentyeightcircle": "\u3258",
+ "/twentyfivecircle": "\u3255",
+ "/twentyfourcircle": "\u3254",
+ "/twentyhangzhou": "\u5344",
+ "/twentyninecircle": "\u3259",
+ "/twentyonecircle": "\u3251",
+ "/twentyparen": "\u2487",
+ "/twentyparenthesized": "\u2487",
+ "/twentyperiod": "\u249B",
+ "/twentysevencircle": "\u3257",
+ "/twentysixcircle": "\u3256",
+ "/twentythreecircle": "\u3253",
+ "/twentytwocircle": "\u3252",
+ "/twistedRightwardsArrows": "\u1F500",
+ "/two": "\u0032",
+ "/two.inferior": "\u2082",
+ "/two.roman": "\u2161",
+ "/two.romansmall": "\u2171",
+ "/twoButtonMouse": "\u1F5B0",
+ "/twoHearts": "\u1F495",
+ "/twoMenHoldingHands": "\u1F46C",
+ "/twoSpeechBubbles": "\u1F5EA",
+ "/twoWomenHoldingHands": "\u1F46D",
+ "/twoarabic": "\u0662",
+ "/twoasterisksalignedvertically": "\u2051",
+ "/twobengali": "\u09E8",
+ "/twocircle": "\u2461",
+ "/twocircledbl": "\u24F6",
+ "/twocircleinversesansserif": "\u278B",
+ "/twocomma": "\u1F103",
+ "/twodeva": "\u0968",
+ "/twodotenleader": "\u2025",
+ "/twodotleader": "\u2025",
+ "/twodotleadervertical": "\uFE30",
+ "/twodotpunctuation": "\u205A",
+ "/twodotsoveronedot": "\u2E2A",
+ "/twofar": "\u06F2",
+ "/twofifths": "\u2156",
+ "/twogujarati": "\u0AE8",
+ "/twogurmukhi": "\u0A68",
+ "/twohackarabic": "\u0662",
+ "/twohangzhou": "\u3022",
+ "/twoideographiccircled": "\u3281",
+ "/twoideographicparen": "\u3221",
+ "/twoinferior": "\u2082",
+ "/twoksquare": "\u1F19D",
+ "/twomonospace": "\uFF12",
+ "/twonumeratorbengali": "\u09F5",
+ "/twooldstyle": "\uF732",
+ "/twoparen": "\u2475",
+ "/twoparenthesized": "\u2475",
+ "/twoperiod": "\u2489",
+ "/twopersian": "\u06F2",
+ "/tworoman": "\u2171",
+ "/twoshortsjoinedmetrical": "\u23D6",
+ "/twoshortsoverlongmetrical": "\u23D5",
+ "/twostroke": "\u01BB",
+ "/twosuperior": "\u00B2",
+ "/twothai": "\u0E52",
+ "/twothirds": "\u2154",
+ "/twowayleftwaytrafficblack": "\u26D6",
+ "/twowayleftwaytrafficwhite": "\u26D7",
+ "/tz": "\uA729",
+ "/u": "\u0075",
+ "/u.fina": "\uFBD8",
+ "/u.isol": "\uFBD7",
+ "/uacute": "\u00FA",
+ "/uacutedblcyr": "\u04F3",
+ "/ubar": "\u0289",
+ "/ubengali": "\u0989",
+ "/ubopomofo": "\u3128",
+ "/ubracketleft": "\u2E26",
+ "/ubracketright": "\u2E27",
+ "/ubreve": "\u016D",
+ "/ucaron": "\u01D4",
+ "/ucircle": "\u24E4",
+ "/ucirclekatakana": "\u32D2",
+ "/ucircumflex": "\u00FB",
+ "/ucircumflexbelow": "\u1E77",
+ "/ucyr": "\u0443",
+ "/ucyrillic": "\u0443",
+ "/udattadeva": "\u0951",
+ "/udblacute": "\u0171",
+ "/udblgrave": "\u0215",
+ "/udeva": "\u0909",
+ "/udieresis": "\u00FC",
+ "/udieresisacute": "\u01D8",
+ "/udieresisbelow": "\u1E73",
+ "/udieresiscaron": "\u01DA",
+ "/udieresiscyr": "\u04F1",
+ "/udieresiscyrillic": "\u04F1",
+ "/udieresisgrave": "\u01DC",
+ "/udieresismacron": "\u01D6",
+ "/udotbelow": "\u1EE5",
+ "/ugrave": "\u00F9",
+ "/ugravedbl": "\u0215",
+ "/ugujarati": "\u0A89",
+ "/ugurmukhi": "\u0A09",
+ "/uhamza": "\u0677",
+ "/uhamza.isol": "\uFBDD",
+ "/uhdsquare": "\u1F1AB",
+ "/uhiragana": "\u3046",
+ "/uhoi": "\u1EE7",
+ "/uhookabove": "\u1EE7",
+ "/uhorn": "\u01B0",
+ "/uhornacute": "\u1EE9",
+ "/uhorndotbelow": "\u1EF1",
+ "/uhorngrave": "\u1EEB",
+ "/uhornhoi": "\u1EED",
+ "/uhornhookabove": "\u1EED",
+ "/uhorntilde": "\u1EEF",
+ "/uhungarumlaut": "\u0171",
+ "/uhungarumlautcyrillic": "\u04F3",
+ "/uighurkazakhkirghizalefmaksura.init": "\uFBE8",
+ "/uighurkazakhkirghizalefmaksura.medi": "\uFBE9",
+ "/uighurkirghizyeh.init_hamzaabove.medi_alefmaksura.fina": "\uFBF9",
+ "/uighurkirghizyeh.init_hamzaabove.medi_alefmaksura.medi": "\uFBFB",
+ "/uighurkirghizyeh.medi_hamzaabove.medi_alefmaksura.fina": "\uFBFA",
+ "/uinvertedbreve": "\u0217",
+ "/ukatakana": "\u30A6",
+ "/ukatakanahalfwidth": "\uFF73",
+ "/ukcyr": "\u0479",
+ "/ukcyrillic": "\u0479",
+ "/ukorean": "\u315C",
+ "/um": "\uA778",
+ "/umacron": "\u016B",
+ "/umacroncyr": "\u04EF",
+ "/umacroncyrillic": "\u04EF",
+ "/umacrondieresis": "\u1E7B",
+ "/umatragurmukhi": "\u0A41",
+ "/umbrella": "\u2602",
+ "/umbrellaonground": "\u26F1",
+ "/umbrellaraindrops": "\u2614",
+ "/umonospace": "\uFF55",
+ "/unamusedFace": "\u1F612",
+ "/unaspiratedmod": "\u02ED",
+ "/underscore": "\u005F",
+ "/underscorecenterline": "\uFE4E",
+ "/underscoredashed": "\uFE4D",
+ "/underscoredbl": "\u2017",
+ "/underscoremonospace": "\uFF3F",
+ "/underscorevertical": "\uFE33",
+ "/underscorewavy": "\uFE4F",
+ "/underscorewavyvertical": "\uFE34",
+ "/undertie": "\u203F",
+ "/undo": "\u238C",
+ "/union": "\u222A",
+ "/unionarray": "\u22C3",
+ "/uniondbl": "\u22D3",
+ "/universal": "\u2200",
+ "/unmarriedpartnership": "\u26AF",
+ "/uogonek": "\u0173",
+ "/uonsquare": "\u3306",
+ "/upPointingAirplane": "\u1F6E7",
+ "/upPointingMilitaryAirplane": "\u1F6E6",
+ "/upPointingSmallAirplane": "\u1F6E8",
+ "/uparen": "\u24B0",
+ "/uparenthesized": "\u24B0",
+ "/uparrowleftofdownarrow": "\u21C5",
+ "/upblock": "\u2580",
+ "/updblhorzsng": "\u2568",
+ "/updblleftsng": "\u255C",
+ "/updblrightsng": "\u2559",
+ "/upheavydnhorzlight": "\u2540",
+ "/upheavyhorzlight": "\u2538",
+ "/upheavyleftdnlight": "\u2526",
+ "/upheavyleftlight": "\u251A",
+ "/upheavyrightdnlight": "\u251E",
+ "/upheavyrightlight": "\u2516",
+ "/uplightdnhorzheavy": "\u2548",
+ "/uplighthorzheavy": "\u2537",
+ "/uplightleftdnheavy": "\u252A",
+ "/uplightleftheavy": "\u2519",
+ "/uplightrightdnheavy": "\u2522",
+ "/uplightrightheavy": "\u2515",
+ "/upperHalfBlock": "\u2580",
+ "/upperOneEighthBlock": "\u2594",
+ "/upperRightShadowedWhiteCircle": "\u1F53F",
+ "/upperdothebrew": "\u05C4",
+ "/upperhalfcircle": "\u25E0",
+ "/upperhalfcircleinversewhite": "\u25DA",
+ "/upperquadrantcirculararcleft": "\u25DC",
+ "/upperquadrantcirculararcright": "\u25DD",
+ "/uppertriangleleft": "\u25F8",
+ "/uppertriangleleftblack": "\u25E4",
+ "/uppertriangleright": "\u25F9",
+ "/uppertrianglerightblack": "\u25E5",
+ "/upsideDownFace": "\u1F643",
+ "/upsilon": "\u03C5",
+ "/upsilonacute": "\u1F7B",
+ "/upsilonasper": "\u1F51",
+ "/upsilonasperacute": "\u1F55",
+ "/upsilonaspergrave": "\u1F53",
+ "/upsilonaspertilde": "\u1F57",
+ "/upsilonbreve": "\u1FE0",
+ "/upsilondieresis": "\u03CB",
+ "/upsilondieresisacute": "\u1FE3",
+ "/upsilondieresisgrave": "\u1FE2",
+ "/upsilondieresistilde": "\u1FE7",
+ "/upsilondieresistonos": "\u03B0",
+ "/upsilongrave": "\u1F7A",
+ "/upsilonlatin": "\u028A",
+ "/upsilonlenis": "\u1F50",
+ "/upsilonlenisacute": "\u1F54",
+ "/upsilonlenisgrave": "\u1F52",
+ "/upsilonlenistilde": "\u1F56",
+ "/upsilontilde": "\u1FE6",
+ "/upsilontonos": "\u03CD",
+ "/upsilonwithmacron": "\u1FE1",
+ "/upsnghorzdbl": "\u2567",
+ "/upsngleftdbl": "\u255B",
+ "/upsngrightdbl": "\u2558",
+ "/uptackbelowcmb": "\u031D",
+ "/uptackmod": "\u02D4",
+ "/upwithexclamationmarksquare": "\u1F199",
+ "/uragurmukhi": "\u0A73",
+ "/uranus": "\u2645",
+ "/uring": "\u016F",
+ "/ushortcyr": "\u045E",
+ "/ushortcyrillic": "\u045E",
+ "/usmallhiragana": "\u3045",
+ "/usmallkatakana": "\u30A5",
+ "/usmallkatakanahalfwidth": "\uFF69",
+ "/usmod": "\uA770",
+ "/ustraightcyr": "\u04AF",
+ "/ustraightcyrillic": "\u04AF",
+ "/ustraightstrokecyr": "\u04B1",
+ "/ustraightstrokecyrillic": "\u04B1",
+ "/utilde": "\u0169",
+ "/utildeacute": "\u1E79",
+ "/utildebelow": "\u1E75",
+ "/uubengali": "\u098A",
+ "/uudeva": "\u090A",
+ "/uugujarati": "\u0A8A",
+ "/uugurmukhi": "\u0A0A",
+ "/uumatragurmukhi": "\u0A42",
+ "/uuvowelsignbengali": "\u09C2",
+ "/uuvowelsigndeva": "\u0942",
+ "/uuvowelsigngujarati": "\u0AC2",
+ "/uvowelsignbengali": "\u09C1",
+ "/uvowelsigndeva": "\u0941",
+ "/uvowelsigngujarati": "\u0AC1",
+ "/v": "\u0076",
+ "/vadeva": "\u0935",
+ "/vagujarati": "\u0AB5",
+ "/vagurmukhi": "\u0A35",
+ "/vakatakana": "\u30F7",
+ "/vanedownfunc": "\u2356",
+ "/vaneleftfunc": "\u2345",
+ "/vanerightfunc": "\u2346",
+ "/vaneupfunc": "\u234F",
+ "/varikajudeospanish:hb": "\uFB1E",
+ "/vav": "\u05D5",
+ "/vav:hb": "\u05D5",
+ "/vav_vav:hb": "\u05F0",
+ "/vav_yod:hb": "\u05F1",
+ "/vavdagesh": "\uFB35",
+ "/vavdagesh65": "\uFB35",
+ "/vavdageshhebrew": "\uFB35",
+ "/vavhebrew": "\u05D5",
+ "/vavholam": "\uFB4B",
+ "/vavholamhebrew": "\uFB4B",
+ "/vavvavhebrew": "\u05F0",
+ "/vavwithdagesh:hb": "\uFB35",
+ "/vavwithholam:hb": "\uFB4B",
+ "/vavyodhebrew": "\u05F1",
+ "/vcircle": "\u24E5",
+ "/vcurl": "\u2C74",
+ "/vdiagonalstroke": "\uA75F",
+ "/vdotbelow": "\u1E7F",
+ "/ve.fina": "\uFBDF",
+ "/ve.isol": "\uFBDE",
+ "/ve:abovetonecandra": "\u1CF4",
+ "/ve:anusvaraantargomukhasign": "\u1CE9",
+ "/ve:anusvarabahirgomukhasign": "\u1CEA",
+ "/ve:anusvarasignlong": "\u1CEF",
+ "/ve:anusvaraubhayatomukhasign": "\u1CF1",
+ "/ve:anusvaravamagomukhasign": "\u1CEB",
+ "/ve:anusvaravamagomukhawithtailsign": "\u1CEC",
+ "/ve:ardhavisargasign": "\u1CF2",
+ "/ve:atharvaindependentsvaritatone": "\u1CE1",
+ "/ve:atikramasign": "\u1CF7",
+ "/ve:belowtonecandra": "\u1CD8",
+ "/ve:dotbelowtone": "\u1CDD",
+ "/ve:hexiformanusvarasignlong": "\u1CEE",
+ "/ve:jihvamuliyasign": "\u1CF5",
+ "/ve:karshanatone": "\u1CD0",
+ "/ve:kathakaanudattatone": "\u1CDC",
+ "/ve:nihshvasasign": "\u1CD3",
+ "/ve:prenkhatone": "\u1CD2",
+ "/ve:rigkashmiriindependentsvaritatone": "\u1CE0",
+ "/ve:ringabovetone": "\u1CF8",
+ "/ve:ringabovetonedbl": "\u1CF9",
+ "/ve:rotatedardhavisargasign": "\u1CF3",
+ "/ve:rthanganusvarasignlong": "\u1CF0",
+ "/ve:sharatone": "\u1CD1",
+ "/ve:svaritatonedbl": "\u1CDA",
+ "/ve:svaritatonetpl": "\u1CDB",
+ "/ve:threedotsbelowtone": "\u1CDF",
+ "/ve:tiryaksign": "\u1CED",
+ "/ve:twodotsbelowtone": "\u1CDE",
+ "/ve:upadhmaniyasign": "\u1CF6",
+ "/ve:visargaanudattasign": "\u1CE5",
+ "/ve:visargaanudattasignreversed": "\u1CE6",
+ "/ve:visargaanudattawithtailsign": "\u1CE8",
+ "/ve:visargasvaritasign": "\u1CE2",
+ "/ve:visargaudattasign": "\u1CE3",
+ "/ve:visargaudattasignreversed": "\u1CE4",
+ "/ve:visargaudattawithtailsign": "\u1CE7",
+ "/ve:yajuraggravatedindependentsvaritatone": "\u1CD5",
+ "/ve:yajurindependentsvaritatone": "\u1CD6",
+ "/ve:yajurkathakaindependentsvaritaschroedertone": "\u1CD9",
+ "/ve:yajurkathakaindependentsvaritatone": "\u1CD7",
+ "/ve:yajurmidlinesvaritasign": "\u1CD4",
+ "/vecyr": "\u0432",
+ "/vecyrillic": "\u0432",
+ "/veh": "\u06A4",
+ "/veh.fina": "\uFB6B",
+ "/veh.init": "\uFB6C",
+ "/veh.isol": "\uFB6A",
+ "/veh.medi": "\uFB6D",
+ "/veharabic": "\u06A4",
+ "/vehfinalarabic": "\uFB6B",
+ "/vehinitialarabic": "\uFB6C",
+ "/vehmedialarabic": "\uFB6D",
+ "/vekatakana": "\u30F9",
+ "/vend": "\uA769",
+ "/venus": "\u2640",
+ "/versicle": "\u2123",
+ "/vert:bracketwhiteleft": "\uFE17",
+ "/vert:brakcetwhiteright": "\uFE18",
+ "/vert:colon": "\uFE13",
+ "/vert:comma": "\uFE10",
+ "/vert:ellipsishor": "\uFE19",
+ "/vert:exclam": "\uFE15",
+ "/vert:ideographiccomma": "\uFE11",
+ "/vert:ideographicfullstop": "\uFE12",
+ "/vert:question": "\uFE16",
+ "/vert:semicolon": "\uFE14",
+ "/vertdblhorzsng": "\u256B",
+ "/vertdblleftsng": "\u2562",
+ "/vertdblrightsng": "\u255F",
+ "/vertheavyhorzlight": "\u2542",
+ "/vertheavyleftlight": "\u2528",
+ "/vertheavyrightlight": "\u2520",
+ "/verticalTrafficLight": "\u1F6A6",
+ "/verticalbar": "\u007C",
+ "/verticalbardbl": "\u2016",
+ "/verticalbarhorizontalstroke": "\u27CA",
+ "/verticalbarwhitearrowonpedestalup": "\u21ED",
+ "/verticalfourdots": "\u205E",
+ "/verticalideographiciterationmark": "\u303B",
+ "/verticalkanarepeatmark": "\u3031",
+ "/verticalkanarepeatmarklowerhalf": "\u3035",
+ "/verticalkanarepeatmarkupperhalf": "\u3033",
+ "/verticalkanarepeatwithvoicedsoundmark": "\u3032",
+ "/verticalkanarepeatwithvoicedsoundmarkupperhalf": "\u3034",
+ "/verticallineabovecmb": "\u030D",
+ "/verticallinebelowcmb": "\u0329",
+ "/verticallinelowmod": "\u02CC",
+ "/verticallinemod": "\u02C8",
+ "/verticalmalestroke": "\u26A8",
+ "/verticalsdbltrokearrowleft": "\u21FA",
+ "/verticalsdbltrokearrowleftright": "\u21FC",
+ "/verticalsdbltrokearrowright": "\u21FB",
+ "/verticalstrokearrowleft": "\u21F7",
+ "/verticalstrokearrowleftright": "\u21F9",
+ "/verticalstrokearrowright": "\u21F8",
+ "/vertlighthorzheavy": "\u253F",
+ "/vertlightleftheavy": "\u2525",
+ "/vertlightrightheavy": "\u251D",
+ "/vertsnghorzdbl": "\u256A",
+ "/vertsngleftdbl": "\u2561",
+ "/vertsngrightdbl": "\u255E",
+ "/verymuchgreater": "\u22D9",
+ "/verymuchless": "\u22D8",
+ "/vesta": "\u26B6",
+ "/vewarmenian": "\u057E",
+ "/vhook": "\u028B",
+ "/vibrationMode": "\u1F4F3",
+ "/videoCamera": "\u1F4F9",
+ "/videoGame": "\u1F3AE",
+ "/videocassette": "\u1F4FC",
+ "/viewdatasquare": "\u2317",
+ "/vikatakana": "\u30F8",
+ "/violin": "\u1F3BB",
+ "/viramabengali": "\u09CD",
+ "/viramadeva": "\u094D",
+ "/viramagujarati": "\u0ACD",
+ "/virgo": "\u264D",
+ "/visargabengali": "\u0983",
+ "/visargadeva": "\u0903",
+ "/visargagujarati": "\u0A83",
+ "/visigothicz": "\uA763",
+ "/vmonospace": "\uFF56",
+ "/voarmenian": "\u0578",
+ "/vodsquare": "\u1F1AC",
+ "/voicediterationhiragana": "\u309E",
+ "/voicediterationkatakana": "\u30FE",
+ "/voicedmarkkana": "\u309B",
+ "/voicedmarkkanahalfwidth": "\uFF9E",
+ "/voicingmod": "\u02EC",
+ "/vokatakana": "\u30FA",
+ "/volapukae": "\uA79B",
+ "/volapukoe": "\uA79D",
+ "/volapukue": "\uA79F",
+ "/volcano": "\u1F30B",
+ "/volleyball": "\u1F3D0",
+ "/vovermfullwidth": "\u33DE",
+ "/vowelVabove": "\u065A",
+ "/voweldotbelow": "\u065C",
+ "/vowelinvertedVabove": "\u065B",
+ "/vparen": "\u24B1",
+ "/vparenthesized": "\u24B1",
+ "/vrighthook": "\u2C71",
+ "/vssquare": "\u1F19A",
+ "/vtilde": "\u1E7D",
+ "/vturned": "\u028C",
+ "/vuhiragana": "\u3094",
+ "/vukatakana": "\u30F4",
+ "/vwelsh": "\u1EFD",
+ "/vy": "\uA761",
+ "/w": "\u0077",
+ "/wacirclekatakana": "\u32FB",
+ "/wacute": "\u1E83",
+ "/waekorean": "\u3159",
+ "/wahiragana": "\u308F",
+ "/wakatakana": "\u30EF",
+ "/wakatakanahalfwidth": "\uFF9C",
+ "/wakorean": "\u3158",
+ "/waningCrescentMoon": "\u1F318",
+ "/waningGibbousMoon": "\u1F316",
+ "/warning": "\u26A0",
+ "/wasmallhiragana": "\u308E",
+ "/wasmallkatakana": "\u30EE",
+ "/wastebasket": "\u1F5D1",
+ "/watch": "\u231A",
+ "/waterBuffalo": "\u1F403",
+ "/waterCloset": "\u1F6BE",
+ "/waterWave": "\u1F30A",
+ "/waterideographiccircled": "\u328C",
+ "/waterideographicparen": "\u322C",
+ "/watermelon": "\u1F349",
+ "/wattosquare": "\u3357",
+ "/wavedash": "\u301C",
+ "/wavingBlackFlag": "\u1F3F4",
+ "/wavingHandSign": "\u1F44B",
+ "/wavingWhiteFlag": "\u1F3F3",
+ "/wavydash": "\u3030",
+ "/wavyhamzabelow": "\u065F",
+ "/wavyline": "\u2307",
+ "/wavyunderscorevertical": "\uFE34",
+ "/waw": "\u0648",
+ "/waw.fina": "\uFEEE",
+ "/waw.isol": "\uFEED",
+ "/wawDigitThreeAbove": "\u0779",
+ "/wawDigitTwoAbove": "\u0778",
+ "/wawarabic": "\u0648",
+ "/wawdotabove": "\u06CF",
+ "/wawfinalarabic": "\uFEEE",
+ "/wawhamza": "\u0624",
+ "/wawhamza.fina": "\uFE86",
+ "/wawhamza.isol": "\uFE85",
+ "/wawhamzaabovearabic": "\u0624",
+ "/wawhamzaabovefinalarabic": "\uFE86",
+ "/wawhighhamza": "\u0676",
+ "/wawring": "\u06C4",
+ "/wawsmall": "\u06E5",
+ "/wawtwodotsabove": "\u06CA",
+ "/waxingCrescentMoon": "\u1F312",
+ "/waxingGibbousMoon": "\u1F314",
+ "/wbfullwidth": "\u33DD",
+ "/wbsquare": "\u33DD",
+ "/wcircle": "\u24E6",
+ "/wcircumflex": "\u0175",
+ "/wcsquare": "\u1F14F",
+ "/wcsquareblack": "\u1F18F",
+ "/wdieresis": "\u1E85",
+ "/wdot": "\u1E87",
+ "/wdotaccent": "\u1E87",
+ "/wdotbelow": "\u1E89",
+ "/wearyCatFace": "\u1F640",
+ "/wearyFace": "\u1F629",
+ "/wecirclekatakana": "\u32FD",
+ "/wecyr": "\u051D",
+ "/wedding": "\u1F492",
+ "/wehiragana": "\u3091",
+ "/weierstrass": "\u2118",
+ "/weightLifter": "\u1F3CB",
+ "/wekatakana": "\u30F1",
+ "/wekorean": "\u315E",
+ "/weokorean": "\u315D",
+ "/westsyriaccross": "\u2670",
+ "/wgrave": "\u1E81",
+ "/whale": "\u1F40B",
+ "/wheelchair": "\u267F",
+ "/wheelofdharma": "\u2638",
+ "/whiteDownPointingBackhandIndex": "\u1F447",
+ "/whiteDownPointingLeftHandIndex": "\u1F597",
+ "/whiteFlower": "\u1F4AE",
+ "/whiteHardShellFloppyDisk": "\u1F5AB",
+ "/whiteLatinCross": "\u1F546",
+ "/whiteLeftPointingBackhandIndex": "\u1F448",
+ "/whitePennant": "\u1F3F1",
+ "/whiteRightPointingBackhandIndex": "\u1F449",
+ "/whiteSquareButton": "\u1F533",
+ "/whiteSun": "\u1F323",
+ "/whiteSunBehindCloud": "\u1F325",
+ "/whiteSunBehindCloudRain": "\u1F326",
+ "/whiteSunSmallCloud": "\u1F324",
+ "/whiteTouchtoneTelephone": "\u1F57E",
+ "/whiteUpPointingBackhandIndex": "\u1F446",
+ "/whitearrowdown": "\u21E9",
+ "/whitearrowfromwallright": "\u21F0",
+ "/whitearrowleft": "\u21E6",
+ "/whitearrowonpedestalup": "\u21EB",
+ "/whitearrowright": "\u21E8",
+ "/whitearrowup": "\u21E7",
+ "/whitearrowupdown": "\u21F3",
+ "/whitearrowupfrombar": "\u21EA",
+ "/whitebullet": "\u25E6",
+ "/whitecircle": "\u25CB",
+ "/whitecircleinverse": "\u25D9",
+ "/whitecornerbracketleft": "\u300E",
+ "/whitecornerbracketleftvertical": "\uFE43",
+ "/whitecornerbracketright": "\u300F",
+ "/whitecornerbracketrightvertical": "\uFE44",
+ "/whitedblarrowonpedestalup": "\u21EF",
+ "/whitedblarrowup": "\u21EE",
+ "/whitediamond": "\u25C7",
+ "/whitediamondcontainingblacksmalldiamond": "\u25C8",
+ "/whitedownpointingsmalltriangle": "\u25BF",
+ "/whitedownpointingtriangle": "\u25BD",
+ "/whiteleftpointingsmalltriangle": "\u25C3",
+ "/whiteleftpointingtriangle": "\u25C1",
+ "/whitelenticularbracketleft": "\u3016",
+ "/whitelenticularbracketright": "\u3017",
+ "/whiterightpointingsmalltriangle": "\u25B9",
+ "/whiterightpointingtriangle": "\u25B7",
+ "/whitesesamedot": "\uFE46",
+ "/whitesmallsquare": "\u25AB",
+ "/whitesmilingface": "\u263A",
+ "/whitesquare": "\u25A1",
+ "/whitesquarebracketleft": "\u301A",
+ "/whitesquarebracketright": "\u301B",
+ "/whitestar": "\u2606",
+ "/whitetelephone": "\u260F",
+ "/whitetortoiseshellbracketleft": "\u3018",
+ "/whitetortoiseshellbracketright": "\u3019",
+ "/whiteuppointingsmalltriangle": "\u25B5",
+ "/whiteuppointingtriangle": "\u25B3",
+ "/whook": "\u2C73",
+ "/wicirclekatakana": "\u32FC",
+ "/wigglylinevertical": "\u2E3E",
+ "/wignyan": "\uA983",
+ "/wihiragana": "\u3090",
+ "/wikatakana": "\u30F0",
+ "/wikorean": "\u315F",
+ "/windBlowingFace": "\u1F32C",
+ "/windChime": "\u1F390",
+ "/windupada": "\uA9C6",
+ "/wineGlass": "\u1F377",
+ "/winkingFace": "\u1F609",
+ "/wiredKeyboard": "\u1F5AE",
+ "/wmonospace": "\uFF57",
+ "/wocirclekatakana": "\u32FE",
+ "/wohiragana": "\u3092",
+ "/wokatakana": "\u30F2",
+ "/wokatakanahalfwidth": "\uFF66",
+ "/wolfFace": "\u1F43A",
+ "/woman": "\u1F469",
+ "/womanBunnyEars": "\u1F46F",
+ "/womansBoots": "\u1F462",
+ "/womansClothes": "\u1F45A",
+ "/womansHat": "\u1F452",
+ "/womansSandal": "\u1F461",
+ "/womens": "\u1F6BA",
+ "/won": "\u20A9",
+ "/wonmonospace": "\uFFE6",
+ "/woodideographiccircled": "\u328D",
+ "/woodideographicparen": "\u322D",
+ "/wordjoiner": "\u2060",
+ "/wordseparatormiddledot": "\u2E31",
+ "/worldMap": "\u1F5FA",
+ "/worriedFace": "\u1F61F",
+ "/wowaenthai": "\u0E27",
+ "/wparen": "\u24B2",
+ "/wparenthesized": "\u24B2",
+ "/wrappedPresent": "\u1F381",
+ "/wreathproduct": "\u2240",
+ "/wrench": "\u1F527",
+ "/wring": "\u1E98",
+ "/wsuperior": "\u02B7",
+ "/wsupmod": "\u02B7",
+ "/wturned": "\u028D",
+ "/wulumelikvowel": "\uA9B7",
+ "/wuluvowel": "\uA9B6",
+ "/wynn": "\u01BF",
+ "/x": "\u0078",
+ "/x.inferior": "\u2093",
+ "/xabovecmb": "\u033D",
+ "/xatailcyr": "\u04B3",
+ "/xbopomofo": "\u3112",
+ "/xcircle": "\u24E7",
+ "/xdieresis": "\u1E8D",
+ "/xdot": "\u1E8B",
+ "/xdotaccent": "\u1E8B",
+ "/xeharmenian": "\u056D",
+ "/xi": "\u03BE",
+ "/xmonospace": "\uFF58",
+ "/xor": "\u22BB",
+ "/xparen": "\u24B3",
+ "/xparenthesized": "\u24B3",
+ "/xsuperior": "\u02E3",
+ "/xsupmod": "\u02E3",
+ "/y": "\u0079",
+ "/yaadosquare": "\u334E",
+ "/yaarusquare": "\u334F",
+ "/yabengali": "\u09AF",
+ "/yacirclekatakana": "\u32F3",
+ "/yacute": "\u00FD",
+ "/yacyr": "\u044F",
+ "/yadeva": "\u092F",
+ "/yaecyr": "\u0519",
+ "/yaekorean": "\u3152",
+ "/yagujarati": "\u0AAF",
+ "/yagurmukhi": "\u0A2F",
+ "/yahiragana": "\u3084",
+ "/yakatakana": "\u30E4",
+ "/yakatakanahalfwidth": "\uFF94",
+ "/yakorean": "\u3151",
+ "/yamakkanthai": "\u0E4E",
+ "/yangtonemod": "\u02EB",
+ "/yasmallhiragana": "\u3083",
+ "/yasmallkatakana": "\u30E3",
+ "/yasmallkatakanahalfwidth": "\uFF6C",
+ "/yatcyr": "\u0463",
+ "/yatcyrillic": "\u0463",
+ "/ycircle": "\u24E8",
+ "/ycircumflex": "\u0177",
+ "/ydieresis": "\u00FF",
+ "/ydot": "\u1E8F",
+ "/ydotaccent": "\u1E8F",
+ "/ydotbelow": "\u1EF5",
+ "/yeh": "\u064A",
+ "/yeh.fina": "\uFEF2",
+ "/yeh.init": "\uFEF3",
+ "/yeh.init_alefmaksura.fina": "\uFC59",
+ "/yeh.init_hah.fina": "\uFC56",
+ "/yeh.init_hah.medi": "\uFCDB",
+ "/yeh.init_hamzaabove.medi_ae.fina": "\uFBEC",
+ "/yeh.init_hamzaabove.medi_alef.fina": "\uFBEA",
+ "/yeh.init_hamzaabove.medi_alefmaksura.fina": "\uFC03",
+ "/yeh.init_hamzaabove.medi_e.fina": "\uFBF6",
+ "/yeh.init_hamzaabove.medi_e.medi": "\uFBF8",
+ "/yeh.init_hamzaabove.medi_hah.fina": "\uFC01",
+ "/yeh.init_hamzaabove.medi_hah.medi": "\uFC98",
+ "/yeh.init_hamzaabove.medi_heh.medi": "\uFC9B",
+ "/yeh.init_hamzaabove.medi_jeem.fina": "\uFC00",
+ "/yeh.init_hamzaabove.medi_jeem.medi": "\uFC97",
+ "/yeh.init_hamzaabove.medi_khah.medi": "\uFC99",
+ "/yeh.init_hamzaabove.medi_meem.fina": "\uFC02",
+ "/yeh.init_hamzaabove.medi_meem.medi": "\uFC9A",
+ "/yeh.init_hamzaabove.medi_oe.fina": "\uFBF2",
+ "/yeh.init_hamzaabove.medi_u.fina": "\uFBF0",
+ "/yeh.init_hamzaabove.medi_waw.fina": "\uFBEE",
+ "/yeh.init_hamzaabove.medi_yeh.fina": "\uFC04",
+ "/yeh.init_hamzaabove.medi_yu.fina": "\uFBF4",
+ "/yeh.init_heh.medi": "\uFCDE",
+ "/yeh.init_jeem.fina": "\uFC55",
+ "/yeh.init_jeem.medi": "\uFCDA",
+ "/yeh.init_khah.fina": "\uFC57",
+ "/yeh.init_khah.medi": "\uFCDC",
+ "/yeh.init_meem.fina": "\uFC58",
+ "/yeh.init_meem.medi": "\uFCDD",
+ "/yeh.init_meem.medi_meem.medi": "\uFD9D",
+ "/yeh.init_yeh.fina": "\uFC5A",
+ "/yeh.isol": "\uFEF1",
+ "/yeh.medi": "\uFEF4",
+ "/yeh.medi_alefmaksura.fina": "\uFC95",
+ "/yeh.medi_hah.medi_yeh.fina": "\uFDAE",
+ "/yeh.medi_hamzaabove.medi_ae.fina": "\uFBED",
+ "/yeh.medi_hamzaabove.medi_alef.fina": "\uFBEB",
+ "/yeh.medi_hamzaabove.medi_alefmaksura.fina": "\uFC68",
+ "/yeh.medi_hamzaabove.medi_e.fina": "\uFBF7",
+ "/yeh.medi_hamzaabove.medi_heh.medi": "\uFCE0",
+ "/yeh.medi_hamzaabove.medi_meem.fina": "\uFC66",
+ "/yeh.medi_hamzaabove.medi_meem.medi": "\uFCDF",
+ "/yeh.medi_hamzaabove.medi_noon.fina": "\uFC67",
+ "/yeh.medi_hamzaabove.medi_oe.fina": "\uFBF3",
+ "/yeh.medi_hamzaabove.medi_reh.fina": "\uFC64",
+ "/yeh.medi_hamzaabove.medi_u.fina": "\uFBF1",
+ "/yeh.medi_hamzaabove.medi_waw.fina": "\uFBEF",
+ "/yeh.medi_hamzaabove.medi_yeh.fina": "\uFC69",
+ "/yeh.medi_hamzaabove.medi_yu.fina": "\uFBF5",
+ "/yeh.medi_hamzaabove.medi_zain.fina": "\uFC65",
+ "/yeh.medi_heh.medi": "\uFCF1",
+ "/yeh.medi_jeem.medi_yeh.fina": "\uFDAF",
+ "/yeh.medi_meem.fina": "\uFC93",
+ "/yeh.medi_meem.medi": "\uFCF0",
+ "/yeh.medi_meem.medi_meem.fina": "\uFD9C",
+ "/yeh.medi_meem.medi_yeh.fina": "\uFDB0",
+ "/yeh.medi_noon.fina": "\uFC94",
+ "/yeh.medi_reh.fina": "\uFC91",
+ "/yeh.medi_yeh.fina": "\uFC96",
+ "/yeh.medi_zain.fina": "\uFC92",
+ "/yehBarreeDigitThreeAbove": "\u077B",
+ "/yehBarreeDigitTwoAbove": "\u077A",
+ "/yehVabove": "\u06CE",
+ "/yehabove": "\u06E7",
+ "/yeharabic": "\u064A",
+ "/yehbarree": "\u06D2",
+ "/yehbarree.fina": "\uFBAF",
+ "/yehbarree.isol": "\uFBAE",
+ "/yehbarreearabic": "\u06D2",
+ "/yehbarreefinalarabic": "\uFBAF",
+ "/yehbarreehamza": "\u06D3",
+ "/yehbarreehamza.fina": "\uFBB1",
+ "/yehbarreehamza.isol": "\uFBB0",
+ "/yehfarsi": "\u06CC",
+ "/yehfarsi.fina": "\uFBFD",
+ "/yehfarsi.init": "\uFBFE",
+ "/yehfarsi.isol": "\uFBFC",
+ "/yehfarsi.medi": "\uFBFF",
+ "/yehfarsiinvertedV": "\u063D",
+ "/yehfarsithreedotsabove": "\u063F",
+ "/yehfarsitwodotsabove": "\u063E",
+ "/yehfinalarabic": "\uFEF2",
+ "/yehhamza": "\u0626",
+ "/yehhamza.fina": "\uFE8A",
+ "/yehhamza.init": "\uFE8B",
+ "/yehhamza.isol": "\uFE89",
+ "/yehhamza.medi": "\uFE8C",
+ "/yehhamzaabovearabic": "\u0626",
+ "/yehhamzaabovefinalarabic": "\uFE8A",
+ "/yehhamzaaboveinitialarabic": "\uFE8B",
+ "/yehhamzaabovemedialarabic": "\uFE8C",
+ "/yehhighhamza": "\u0678",
+ "/yehinitialarabic": "\uFEF3",
+ "/yehmedialarabic": "\uFEF4",
+ "/yehmeeminitialarabic": "\uFCDD",
+ "/yehmeemisolatedarabic": "\uFC58",
+ "/yehnoonfinalarabic": "\uFC94",
+ "/yehsmall": "\u06E6",
+ "/yehtail": "\u06CD",
+ "/yehthreedotsbelow": "\u06D1",
+ "/yehthreedotsbelowarabic": "\u06D1",
+ "/yekorean": "\u3156",
+ "/yellowHeart": "\u1F49B",
+ "/yen": "\u00A5",
+ "/yenmonospace": "\uFFE5",
+ "/yeokorean": "\u3155",
+ "/yeorinhieuhkorean": "\u3186",
+ "/yerachBenYomo:hb": "\u05AA",
+ "/yerahbenyomohebrew": "\u05AA",
+ "/yerahbenyomolefthebrew": "\u05AA",
+ "/yericyrillic": "\u044B",
+ "/yerudieresiscyrillic": "\u04F9",
+ "/yesieungkorean": "\u3181",
+ "/yesieungpansioskorean": "\u3183",
+ "/yesieungsioskorean": "\u3182",
+ "/yetiv:hb": "\u059A",
+ "/yetivhebrew": "\u059A",
+ "/ygrave": "\u1EF3",
+ "/yhoi": "\u1EF7",
+ "/yhook": "\u01B4",
+ "/yhookabove": "\u1EF7",
+ "/yiarmenian": "\u0575",
+ "/yicyrillic": "\u0457",
+ "/yikorean": "\u3162",
+ "/yintonemod": "\u02EA",
+ "/yinyang": "\u262F",
+ "/yiwnarmenian": "\u0582",
+ "/ylongcyr": "\u044B",
+ "/ylongdieresiscyr": "\u04F9",
+ "/yloop": "\u1EFF",
+ "/ymacron": "\u0233",
+ "/ymonospace": "\uFF59",
+ "/yocirclekatakana": "\u32F5",
+ "/yod": "\u05D9",
+ "/yod:hb": "\u05D9",
+ "/yod_yod:hb": "\u05F2",
+ "/yod_yod_patah:hb": "\uFB1F",
+ "/yoddagesh": "\uFB39",
+ "/yoddageshhebrew": "\uFB39",
+ "/yodhebrew": "\u05D9",
+ "/yodwithdagesh:hb": "\uFB39",
+ "/yodwithhiriq:hb": "\uFB1D",
+ "/yodyodhebrew": "\u05F2",
+ "/yodyodpatahhebrew": "\uFB1F",
+ "/yogh": "\u021D",
+ "/yohiragana": "\u3088",
+ "/yoikorean": "\u3189",
+ "/yokatakana": "\u30E8",
+ "/yokatakanahalfwidth": "\uFF96",
+ "/yokorean": "\u315B",
+ "/yosmallhiragana": "\u3087",
+ "/yosmallkatakana": "\u30E7",
+ "/yosmallkatakanahalfwidth": "\uFF6E",
+ "/yot": "\u03F3",
+ "/yotgreek": "\u03F3",
+ "/yoyaekorean": "\u3188",
+ "/yoyakorean": "\u3187",
+ "/yoyakthai": "\u0E22",
+ "/yoyingthai": "\u0E0D",
+ "/yparen": "\u24B4",
+ "/yparenthesized": "\u24B4",
+ "/ypogegrammeni": "\u037A",
+ "/ypogegrammenigreekcmb": "\u0345",
+ "/yr": "\u01A6",
+ "/yring": "\u1E99",
+ "/ystroke": "\u024F",
+ "/ysuperior": "\u02B8",
+ "/ysupmod": "\u02B8",
+ "/ytilde": "\u1EF9",
+ "/yturned": "\u028E",
+ "/yu.fina": "\uFBDC",
+ "/yu.isol": "\uFBDB",
+ "/yuansquare": "\u3350",
+ "/yucirclekatakana": "\u32F4",
+ "/yucyr": "\u044E",
+ "/yuhiragana": "\u3086",
+ "/yuikorean": "\u318C",
+ "/yukatakana": "\u30E6",
+ "/yukatakanahalfwidth": "\uFF95",
+ "/yukirghiz": "\u06C9",
+ "/yukirghiz.fina": "\uFBE3",
+ "/yukirghiz.isol": "\uFBE2",
+ "/yukorean": "\u3160",
+ "/yukrcyr": "\u0457",
+ "/yusbigcyr": "\u046B",
+ "/yusbigcyrillic": "\u046B",
+ "/yusbigiotifiedcyr": "\u046D",
+ "/yusbigiotifiedcyrillic": "\u046D",
+ "/yuslittlecyr": "\u0467",
+ "/yuslittlecyrillic": "\u0467",
+ "/yuslittleiotifiedcyr": "\u0469",
+ "/yuslittleiotifiedcyrillic": "\u0469",
+ "/yusmallhiragana": "\u3085",
+ "/yusmallkatakana": "\u30E5",
+ "/yusmallkatakanahalfwidth": "\uFF6D",
+ "/yuyekorean": "\u318B",
+ "/yuyeokorean": "\u318A",
+ "/yyabengali": "\u09DF",
+ "/yyadeva": "\u095F",
+ "/z": "\u007A",
+ "/zaarmenian": "\u0566",
+ "/zacute": "\u017A",
+ "/zadeva": "\u095B",
+ "/zagurmukhi": "\u0A5B",
+ "/zah": "\u0638",
+ "/zah.fina": "\uFEC6",
+ "/zah.init": "\uFEC7",
+ "/zah.init_meem.fina": "\uFC28",
+ "/zah.init_meem.medi": "\uFCB9",
+ "/zah.isol": "\uFEC5",
+ "/zah.medi": "\uFEC8",
+ "/zah.medi_meem.medi": "\uFD3B",
+ "/zaharabic": "\u0638",
+ "/zahfinalarabic": "\uFEC6",
+ "/zahinitialarabic": "\uFEC7",
+ "/zahiragana": "\u3056",
+ "/zahmedialarabic": "\uFEC8",
+ "/zain": "\u0632",
+ "/zain.fina": "\uFEB0",
+ "/zain.isol": "\uFEAF",
+ "/zainabove": "\u0617",
+ "/zainarabic": "\u0632",
+ "/zainfinalarabic": "\uFEB0",
+ "/zakatakana": "\u30B6",
+ "/zaqefGadol:hb": "\u0595",
+ "/zaqefQatan:hb": "\u0594",
+ "/zaqefgadolhebrew": "\u0595",
+ "/zaqefqatanhebrew": "\u0594",
+ "/zarqa:hb": "\u0598",
+ "/zarqahebrew": "\u0598",
+ "/zayin": "\u05D6",
+ "/zayin:hb": "\u05D6",
+ "/zayindagesh": "\uFB36",
+ "/zayindageshhebrew": "\uFB36",
+ "/zayinhebrew": "\u05D6",
+ "/zayinwithdagesh:hb": "\uFB36",
+ "/zbopomofo": "\u3117",
+ "/zcaron": "\u017E",
+ "/zcircle": "\u24E9",
+ "/zcircumflex": "\u1E91",
+ "/zcurl": "\u0291",
+ "/zdescender": "\u2C6C",
+ "/zdot": "\u017C",
+ "/zdotaccent": "\u017C",
+ "/zdotbelow": "\u1E93",
+ "/zecyr": "\u0437",
+ "/zecyrillic": "\u0437",
+ "/zedescendercyrillic": "\u0499",
+ "/zedieresiscyr": "\u04DF",
+ "/zedieresiscyrillic": "\u04DF",
+ "/zehiragana": "\u305C",
+ "/zekatakana": "\u30BC",
+ "/zero": "\u0030",
+ "/zero.inferior": "\u2080",
+ "/zero.superior": "\u2070",
+ "/zeroarabic": "\u0660",
+ "/zerobengali": "\u09E6",
+ "/zerocircle": "\u24EA",
+ "/zerocircleblack": "\u24FF",
+ "/zerocomma": "\u1F101",
+ "/zerodeva": "\u0966",
+ "/zerofar": "\u06F0",
+ "/zerofullstop": "\u1F100",
+ "/zerogujarati": "\u0AE6",
+ "/zerogurmukhi": "\u0A66",
+ "/zerohackarabic": "\u0660",
+ "/zeroinferior": "\u2080",
+ "/zeromonospace": "\uFF10",
+ "/zerooldstyle": "\uF730",
+ "/zeropersian": "\u06F0",
+ "/zerosquareabove": "\u06E0",
+ "/zerosuperior": "\u2070",
+ "/zerothai": "\u0E50",
+ "/zerothirds": "\u2189",
+ "/zerowidthjoiner": "\uFEFF",
+ "/zerowidthnobreakspace": "\uFEFF",
+ "/zerowidthnonjoiner": "\u200C",
+ "/zerowidthspace": "\u200B",
+ "/zeta": "\u03B6",
+ "/zetailcyr": "\u0499",
+ "/zhbopomofo": "\u3113",
+ "/zhearmenian": "\u056A",
+ "/zhebrevecyr": "\u04C2",
+ "/zhebrevecyrillic": "\u04C2",
+ "/zhecyr": "\u0436",
+ "/zhecyrillic": "\u0436",
+ "/zhedescendercyrillic": "\u0497",
+ "/zhedieresiscyr": "\u04DD",
+ "/zhedieresiscyrillic": "\u04DD",
+ "/zhetailcyr": "\u0497",
+ "/zhook": "\u0225",
+ "/zihiragana": "\u3058",
+ "/zikatakana": "\u30B8",
+ "/zildefunc": "\u236C",
+ "/zinorhebrew": "\u05AE",
+ "/zjekomicyr": "\u0505",
+ "/zlinebelow": "\u1E95",
+ "/zmonospace": "\uFF5A",
+ "/znotationbagmembership": "\u22FF",
+ "/zohiragana": "\u305E",
+ "/zokatakana": "\u30BE",
+ "/zparen": "\u24B5",
+ "/zparenthesized": "\u24B5",
+ "/zretroflex": "\u0290",
+ "/zretroflexhook": "\u0290",
+ "/zstroke": "\u01B6",
+ "/zswashtail": "\u0240",
+ "/zuhiragana": "\u305A",
+ "/zukatakana": "\u30BA",
+ "/zwarakay": "\u0659",
+ # manually added from
+ # https://github.com/serviceprototypinglab/latex-pdfa/blob/master/glyphtounicode-cmr.tex
+ "/angbracketleftBig": "\u28E8",
+ "/angbracketleftBigg": "\u27E8",
+ "/angbracketleftbig": "\u27E8",
+ "/angbracketleftbigg": "\u27E8",
+ "/angbracketrightBig": "\u27E9",
+ "/angbracketrightBigg": "\u27E9",
+ "/angbracketrightbig": "\u27E9",
+ "/angbracketrightbigg": "\u27E9",
+ "/arrowbt": "\u2193",
+ "/arrowdblbt": "\u21D3",
+ "/arrowdbltp": "\u21D1",
+ "/arrowhookleft": "\u21AA",
+ "/arrowhookright": "\u21A9",
+ "/arrowtp": "\u2191",
+ # diff : "/arrowvertex": "\u23D0",
+ "/arrowvertexdbl": "\uED12",
+ "/backslashBig": "\u005C",
+ "/backslashBigg": "\u005C",
+ "/backslashbig": "\u005C",
+ "/backslashbigg": "\u005C",
+ # diff : "/braceex": "\u23AA",
+ "/bracehtipdownleft": "\uED17",
+ "/bracehtipdownright": "\uED18",
+ "/bracehtipupleft": "\uED19",
+ "/bracehtipupright": "\uED1A",
+ "/braceleftBig": "\u007B",
+ "/braceleftBigg": "\u007B",
+ "/braceleftbig": "\u007B",
+ "/braceleftbigg": "\u007B",
+ # diff : "/braceleftbt": "\u23A9",
+ # diff : "/braceleftmid": "\u23A8",
+ # diff : "/bracelefttp": "\u23A7",
+ "/bracerightBig": "\u007D",
+ "/bracerightBigg": "\u007D",
+ "/bracerightbig": "\u007D",
+ "/bracerightbigg": "\u007D",
+ # diff : "/bracerightbt": "\u23AD",
+ # diff : "/bracerightmid": "\u23AC",
+ # diff : "/bracerighttp": "\u23AB",
+ "/bracketleftBig": "\u005B",
+ "/bracketleftBigg": "\u005B",
+ "/bracketleftbig": "\u005B",
+ "/bracketleftbigg": "\u005B",
+ # diff : "/bracketleftbt": "\u23A3",
+ # diff : "/bracketleftex": "\u23A2",
+ # diff : "/bracketlefttp": "\u23A1",
+ "/bracketrightBig": "\u005D",
+ "/bracketrightBigg": "\u005D",
+ "/bracketrightbig": "\u005D",
+ "/bracketrightbigg": "\u005D",
+ # diff : "/bracketrightbt": "\u23A6",
+ # diff : "/bracketrightex": "\u23A5",
+ # diff : "/bracketrighttp": "\u23A4",
+ "/ceilingleftBig": "\u2308",
+ "/ceilingleftBigg": "\u2308",
+ "/ceilingleftbig": "\u2308",
+ "/ceilingleftbigg": "\u2308",
+ "/ceilingrightBig": "\u2309",
+ "/ceilingrightBigg": "\u2309",
+ "/ceilingrightbig": "\u2309",
+ "/ceilingrightbigg": "\u2309",
+ "/circledotdisplay": "\u2A00",
+ "/circledottext": "\u2A00",
+ "/circlemultiplydisplay": "\u2A02",
+ "/circlemultiplytext": "\u2A02",
+ "/circleplusdisplay": "\u2A01",
+ "/circleplustext": "\u2A01",
+ "/contintegraldisplay": "\u222E",
+ "/contintegraltext": "\u222E",
+ "/coproductdisplay": "\u2210",
+ "/coproducttext": "\u2210",
+ "/floorleftBig": "\u230A",
+ "/floorleftBigg": "\u230A",
+ "/floorleftbig": "\u230A",
+ "/floorleftbigg": "\u230A",
+ "/floorrightBig": "\u230B",
+ "/floorrightBigg": "\u230B",
+ "/floorrightbig": "\u230B",
+ "/floorrightbigg": "\u230B",
+ "/hatwide": "\u02C6",
+ "/hatwider": "\u02C6",
+ "/hatwidest": "\u02C6",
+ "/integraldisplay": "\u222B",
+ "/integraltext": "\u222B",
+ "/intersectiondisplay": "\u22C2",
+ "/intersectiontext": "\u22C2",
+ "/logicalanddisplay": "\u22C0",
+ "/logicalandtext": "\u22C0",
+ "/logicalordisplay": "\u22C1",
+ "/logicalortext": "\u22C1",
+ "/mapsto": "\u21A6",
+ "/parenleftBig": "\u0028",
+ "/parenleftBigg": "\u0028",
+ "/parenleftbig": "\u0028",
+ "/parenleftbigg": "\u0028",
+ # diff : "/parenleftbt": "\u239D",
+ # diff : "/parenleftex": "\u239C",
+ # diff : "/parenlefttp": "\u239B",
+ "/parenrightBig": "\u0029",
+ "/parenrightBigg": "\u0029",
+ "/parenrightbig": "\u0029",
+ "/parenrightbigg": "\u0029",
+ # diff : "/parenrightbt": "\u23A0",
+ # diff : "/parenrightex": "\u239F",
+ # diff : "/parenrighttp": "\u239E",
+ "/productdisplay": "\u220F",
+ "/producttext": "\u220F",
+ "/radicalBig": "\u221A",
+ "/radicalBigg": "\u221A",
+ "/radicalbig": "\u221A",
+ "/radicalbigg": "\u221A",
+ "/radicalbt": "\u221A",
+ "/radicaltp": "\uED6A",
+ "/radicalvertex": "\uED6B",
+ "/slashBig": "\u002F",
+ "/slashBigg": "\u002F",
+ "/slashbig": "\u002F",
+ "/slashbigg": "\u002F",
+ "/summationdisplay": "\u2211",
+ "/summationtext": "\u2211",
+ "/tie": "\u2040",
+ "/tildewide": "\u02DC",
+ "/tildewider": "\u02DC",
+ "/tildewidest": "\u02DC",
+ "/uniondisplay": "\u22C3",
+ "/unionmultidisplay": "\u2A04",
+ "/unionmultitext": "\u2A04",
+ "/unionsqdisplay": "\u2A06",
+ "/unionsqtext": "\u2A06",
+ "/uniontext": "\u22C3",
+ "/vextenddouble": "\uED79",
+ "/vextendsingle": "\u23D0",
+ "/a1": "\u25C1",
+ "/a2": "\u22B4",
+ "/a3": "\u25B7",
+ "/a4": "\u22B5",
+ "/a40": "\u02C2",
+ "/a41": "\u02C3",
+ "/a42": "\u2303",
+ "/a43": "\u2304",
+ "/a48": "\u2127",
+ "/a49": "\u22C8",
+ "/a50": "\u25A1",
+ "/a51": "\u25C7",
+ "/a58": "\u2053",
+ "/a59": "\u219D",
+ "/a60": "\u228F",
+ "/a61": "\u2290",
+ "/d0": "\u2199",
+ "/d1": "\u2199",
+ "/d2": "\u2199",
+ "/d3": "\u2199",
+ "/d4": "\u2199",
+ "/d5": "\u2199",
+ "/d6": "\u2199",
+ "/d7": "\u2193",
+ "/d8": "\u2193",
+ "/d9": "\u2193",
+ "/d10": "\u2193",
+ "/d11": "\u2193",
+ "/d12": "\u2193",
+ "/d13": "\u2193",
+ "/d14": "\u2193",
+ "/d15": "\u2193",
+ "/d16": "\u2193",
+ "/d17": "\u2193",
+ "/d18": "\u2193",
+ "/d19": "\u2193",
+ "/d20": "\u2193",
+ "/d21": "\u2193",
+ "/d22": "\u2193",
+ "/d23": "\u2193",
+ "/d24": "\u2198",
+ "/d25": "\u2198",
+ "/d26": "\u2198",
+ "/d27": "\u2198",
+ "/d28": "\u2198",
+ "/d29": "\u2198",
+ "/d30": "\u2198",
+ "/d31": "\u2198",
+ "/d32": "\u2198",
+ "/d33": "\u2198",
+ "/d34": "\u2198",
+ "/d35": "\u2198",
+ "/d36": "\u2198",
+ "/d37": "\u2198",
+ "/d38": "\u2198",
+ "/d39": "\u2192",
+ "/d40": "\u2192",
+ "/d41": "\u2192",
+ "/d42": "\u2192",
+ "/d43": "\u2192",
+ "/d44": "\u2192",
+ "/d45": "\u2192",
+ "/d46": "\u2192",
+ "/d47": "\u2192",
+ "/d48": "\u2192",
+ "/d49": "\u2192",
+ "/d50": "\u2192",
+ "/d51": "\u2192",
+ "/d52": "\u2192",
+ "/d53": "\u2192",
+ "/d54": "\u2192",
+ "/d55": "\u2192",
+ "/d56": "\u2197",
+ "/d57": "\u2197",
+ "/d58": "\u2197",
+ "/d59": "\u2197",
+ "/d60": "\u2197",
+ "/d61": "\u2197",
+ "/d62": "\u2197",
+ "/d63": "\u2197",
+ "/d64": "\u2197",
+ "/d65": "\u2197",
+ "/d66": "\u2197",
+ "/d67": "\u2197",
+ "/d68": "\u2197",
+ "/d69": "\u2197",
+ "/d70": "\u2197",
+ "/d71": "\u2191",
+ "/d72": "\u2191",
+ "/d73": "\u2191",
+ "/d74": "\u2191",
+ "/d75": "\u2191",
+ "/d76": "\u2191",
+ "/d77": "\u2191",
+ "/d78": "\u2191",
+ "/d79": "\u2191",
+ "/d80": "\u2191",
+ "/d81": "\u2191",
+ "/d82": "\u2191",
+ "/d83": "\u2191",
+ "/d84": "\u2191",
+ "/d85": "\u2191",
+ "/d86": "\u2191",
+ "/d87": "\u2191",
+ "/d88": "\u2196",
+ "/d89": "\u2196",
+ "/d90": "\u2196",
+ "/d91": "\u2196",
+ "/d92": "\u2196",
+ "/d93": "\u2196",
+ "/d94": "\u2196",
+ "/d95": "\u2196",
+ "/d96": "\u2196",
+ "/d97": "\u2196",
+ "/d98": "\u2196",
+ "/d99": "\u2196",
+ "/d100": "\u2196",
+ "/d101": "\u2196",
+ "/d102": "\u2196",
+ "/d103": "\u2190",
+ "/d104": "\u2190",
+ "/d105": "\u2190",
+ "/d106": "\u2190",
+ "/d107": "\u2190",
+ "/d108": "\u2190",
+ "/d109": "\u2190",
+ "/d110": "\u2190",
+ "/d111": "\u2190",
+ "/d112": "\u2190",
+ "/d113": "\u2190",
+ "/d114": "\u2190",
+ "/d115": "\u2190",
+ "/d116": "\u2190",
+ "/d117": "\u2190",
+ "/d118": "\u2190",
+ "/d119": "\u2190",
+ "/d120": "\u2199",
+ "/d121": "\u2199",
+ "/d122": "\u2199",
+ "/d123": "\u2199",
+ "/d124": "\u2199",
+ "/d125": "\u2199",
+ "/d126": "\u2199",
+ "/d127": "\u2199",
+ # manually added from
+ # https://github.com/kohler/lcdf-typetools/blob/master/texglyphlist.txt
+ "/Ifractur": "\u2111",
+ "/FFsmall": "\uF766",
+ "/FFIsmall": "\uF766",
+ "/FFLsmall": "\uF766",
+ "/FIsmall": "\uF766",
+ "/FLsmall": "\uF766",
+ # diff : "/Germandbls": "\u0053",
+ "/Germandblssmall": "\uF773",
+ "/Ng": "\u014A",
+ "/Rfractur": "\u211C",
+ "/SS": "\u0053",
+ "/SSsmall": "\uF773",
+ "/altselector": "\uD802",
+ "/angbracketleft": "\u27E8",
+ "/angbracketright": "\u27E9",
+ "/arrowbothv": "\u2195",
+ "/arrowdblbothv": "\u21D5",
+ "/arrowleftbothalf": "\u21BD",
+ "/arrowlefttophalf": "\u21BC",
+ "/arrownortheast": "\u2197",
+ "/arrownorthwest": "\u2196",
+ "/arrowrightbothalf": "\u21C1",
+ "/arrowrighttophalf": "\u21C0",
+ "/arrowsoutheast": "\u2198",
+ "/arrowsouthwest": "\u2199",
+ "/ascendercompwordmark": "\uD80A",
+ "/asteriskcentered": "\u2217",
+ "/bardbl": "\u2225",
+ "/capitalcompwordmark": "\uD809",
+ "/circlecopyrt": "\u20DD",
+ "/circledivide": "\u2298",
+ "/circleminus": "\u2296",
+ "/coproduct": "\u2A3F",
+ "/ct": "\u0063",
+ "/cwm": "\u200C",
+ "/dblbracketleft": "\u27E6",
+ "/dblbracketright": "\u27E7",
+ # diff : "/diamond": "\u2662",
+ "/diamondmath": "\u22C4",
+ # diff : "/dotlessj": "\u0237",
+ "/emptyslot": "\uD801",
+ "/epsilon1": "\u03F5",
+ "/epsiloninv": "\u03F6",
+ "/equivasymptotic": "\u224D",
+ "/flat": "\u266D",
+ "/follows": "\u227B",
+ "/followsequal": "\u2AB0",
+ "/followsorcurly": "\u227D",
+ "/greatermuch": "\u226B",
+ # diff : "/heart": "\u2661",
+ "/interrobangdown": "\u2E18",
+ "/intersectionsq": "\u2293",
+ "/latticetop": "\u22A4",
+ "/lessmuch": "\u226A",
+ "/longdbls": "\u017F",
+ "/longsh": "\u017F",
+ "/longsi": "\u017F",
+ "/longsl": "\u017F",
+ "/longst": "\uFB05",
+ "/lscript": "\u2113",
+ "/natural": "\u266E",
+ "/negationslash": "\u0338",
+ "/ng": "\u014B",
+ "/owner": "\u220B",
+ "/pertenthousand": "\u2031",
+ # diff : "/phi": "\u03D5",
+ # diff : "/phi1": "\u03C6",
+ "/pi1": "\u03D6",
+ "/precedesequal": "\u2AAF",
+ "/precedesorcurly": "\u227C",
+ "/prime": "\u2032",
+ "/rho1": "\u03F1",
+ "/ringfitted": "\uD80D",
+ "/sharp": "\u266F",
+ "/similarequal": "\u2243",
+ "/slurabove": "\u2322",
+ "/slurbelow": "\u2323",
+ "/st": "\uFB06",
+ "/subsetsqequal": "\u2291",
+ "/supersetsqequal": "\u2292",
+ "/triangle": "\u25B3",
+ "/triangleinv": "\u25BD",
+ "/triangleleft": "\u25C1",
+ # diff : "/triangleright": "\u25B7",
+ "/turnstileleft": "\u22A2",
+ "/turnstileright": "\u22A3",
+ "/twelveudash": "\uD80C",
+ "/unionmulti": "\u228E",
+ "/unionsq": "\u2294",
+ "/vector": "\u20D7",
+ "/visualspace": "\u2423",
+ "/Dbar": "\u0110",
+ "/compwordmark": "\u200C",
+ "/dbar": "\u0111",
+ "/rangedash": "\u2013",
+ "/hyphenchar": "\u002D",
+ "/punctdash": "\u2014",
+ "/visiblespace": "\u2423",
+ "/Yen": "\u00A5",
+ "/anticlockwise": "\u27F2",
+ "/arrowparrleftright": "\u21C6",
+ "/arrowparrrightleft": "\u21C4",
+ "/arrowtailleft": "\u21A2",
+ "/arrowtailright": "\u21A3",
+ "/arrowtripleleft": "\u21DA",
+ "/arrowtripleright": "\u21DB",
+ "/check": "\u2713",
+ "/circleR": "\u00AE",
+ "/circleS": "\u24C8",
+ "/circleasterisk": "\u229B",
+ "/circleequal": "\u229C",
+ "/circlering": "\u229A",
+ "/clockwise": "\u27F3",
+ "/curlyleft": "\u21AB",
+ "/curlyright": "\u21AC",
+ "/dblarrowdwn": "\u21CA",
+ "/dblarrowheadleft": "\u219E",
+ "/dblarrowheadright": "\u21A0",
+ # diff : "/dblarrowup": "\u21C8",
+ "/defines": "\u225C",
+ "/diamondsolid": "\u2666",
+ "/difference": "\u224F",
+ "/downfall": "\u22CE",
+ "/equaldotleftright": "\u2252",
+ "/equaldotrightleft": "\u2253",
+ "/equalorfollows": "\u22DF",
+ # diff : "/equalorgreater": "\u2A96",
+ # diff : "/equalorless": "\u2A95",
+ "/equalsdots": "\u2251",
+ "/followsorequal": "\u227F",
+ "/forcesbar": "\u22AA",
+ # diff : "/fork": "\u22D4",
+ "/geomequivalent": "\u224E",
+ "/greaterdbleqlless": "\u2A8C",
+ "/greaterdblequal": "\u2267",
+ "/greaterlessequal": "\u22DB",
+ "/greaterorapproxeql": "\u2A86",
+ "/greaterorequalslant": "\u2A7E",
+ "/greaterorsimilar": "\u2273",
+ "/harpoondownleft": "\u21C3",
+ "/harpoondownright": "\u21C2",
+ "/harpoonleftright": "\u21CC",
+ "/harpoonrightleft": "\u21CB",
+ "/harpoonupleft": "\u21BF",
+ "/harpoonupright": "\u21BE",
+ "/intercal": "\u22BA",
+ "/lessdbleqlgreater": "\u2A8B",
+ "/lessdblequal": "\u2266",
+ "/lessequalgreater": "\u22DA",
+ "/lessorapproxeql": "\u2A85",
+ "/lessorequalslant": "\u2A7D",
+ "/lessorsimilar": "\u2272",
+ "/maltesecross": "\u2720",
+ "/multiopenleft": "\u22CB",
+ "/multiopenright": "\u22CC",
+ "/orunderscore": "\u22BB",
+ "/perpcorrespond": "\u2A5E",
+ # diff : "/precedesorequal": "\u227E",
+ "/primereverse": "\u2035",
+ "/revasymptequal": "\u22CD",
+ "/revsimilar": "\u223D",
+ "/rightanglene": "\u231D",
+ "/rightanglenw": "\u231C",
+ "/rightanglese": "\u231F",
+ "/rightanglesw": "\u231E",
+ "/satisfies": "\u22A8",
+ "/shiftleft": "\u21B0",
+ "/shiftright": "\u21B1",
+ "/square": "\u25A1",
+ "/squaredot": "\u22A1",
+ "/squareminus": "\u229F",
+ "/squaremultiply": "\u22A0",
+ "/squareplus": "\u229E",
+ "/squaresolid": "\u25A0",
+ "/squiggleleftright": "\u21AD",
+ "/squiggleright": "\u21DD",
+ "/subsetdblequal": "\u2AC5",
+ "/supersetdbl": "\u22D1",
+ "/supersetdblequal": "\u2AC6",
+ "/triangledownsld": "\u25BC",
+ "/triangleleftequal": "\u22B4",
+ "/triangleleftsld": "\u25C0",
+ "/trianglerightequal": "\u22B5",
+ "/trianglerightsld": "\u25B6",
+ "/trianglesolid": "\u25B2",
+ "/uprise": "\u22CF",
+ # diff : "/Digamma": "\u1D7C",
+ "/Finv": "\u2132",
+ "/Gmir": "\u2141",
+ "/Omegainv": "\u2127",
+ "/approxorequal": "\u224A",
+ "/archleftdown": "\u21B6",
+ "/archrightdown": "\u21B7",
+ "/beth": "\u2136",
+ "/daleth": "\u2138",
+ "/dividemultiply": "\u22C7",
+ "/downslope": "\u29F9",
+ "/equalorsimilar": "\u2242",
+ "/follownotdbleqv": "\u2ABA",
+ "/follownotslnteql": "\u2AB6",
+ "/followornoteqvlnt": "\u22E9",
+ "/greaternotdblequal": "\u2A8A",
+ "/greaternotequal": "\u2A88",
+ "/greaterornotdbleql": "\u2269",
+ "/greaterornotequal": "\u2269",
+ "/integerdivide": "\u2216",
+ "/lessnotdblequal": "\u2A89",
+ "/lessnotequal": "\u2A87",
+ "/lessornotdbleql": "\u2268",
+ "/lessornotequal": "\u2268",
+ "/multicloseleft": "\u22C9",
+ "/multicloseright": "\u22CA",
+ "/notapproxequal": "\u2247",
+ "/notarrowboth": "\u21AE",
+ "/notarrowleft": "\u219A",
+ "/notarrowright": "\u219B",
+ "/notbar": "\u2224",
+ "/notdblarrowboth": "\u21CE",
+ "/notdblarrowleft": "\u21CD",
+ "/notdblarrowright": "\u21CF",
+ "/notfollows": "\u2281",
+ "/notfollowsoreql": "\u2AB0",
+ "/notforces": "\u22AE",
+ "/notforcesextra": "\u22AF",
+ "/notgreaterdblequal": "\u2267",
+ "/notgreaterequal": "\u2271",
+ "/notgreaterorslnteql": "\u2A7E",
+ "/notlessdblequal": "\u2266",
+ "/notlessequal": "\u2270",
+ "/notlessorslnteql": "\u2A7D",
+ "/notprecedesoreql": "\u2AAF",
+ "/notsatisfies": "\u22AD",
+ "/notsimilar": "\u2241",
+ "/notsubseteql": "\u2288",
+ "/notsubsetordbleql": "\u2AC5",
+ "/notsubsetoreql": "\u228A",
+ "/notsuperseteql": "\u2289",
+ "/notsupersetordbleql": "\u2AC6",
+ "/notsupersetoreql": "\u228B",
+ "/nottriangeqlleft": "\u22EC",
+ "/nottriangeqlright": "\u22ED",
+ "/nottriangleleft": "\u22EA",
+ "/nottriangleright": "\u22EB",
+ "/notturnstile": "\u22AC",
+ "/planckover2pi": "\u210F",
+ "/planckover2pi1": "\u210F",
+ "/precedenotdbleqv": "\u2AB9",
+ "/precedenotslnteql": "\u2AB5",
+ "/precedeornoteqvlnt": "\u22E8",
+ "/subsetnoteql": "\u228A",
+ "/subsetornotdbleql": "\u2ACB",
+ "/supersetnoteql": "\u228B",
+ "/supersetornotdbleql": "\u2ACC",
+ "/upslope": "\u29F8",
+}
+
+
+def _complete() -> None:
+ global adobe_glyphs
+ for i in range(256):
+ adobe_glyphs[f"/a{i}"] = chr(i)
+ adobe_glyphs["/.notdef"] = "□"
+
+
_complete()
diff --git a/pypdf/_codecs/pdfdoc.py b/pypdf/_codecs/pdfdoc.py
index 86bc5961..306357a5 100644
--- a/pypdf/_codecs/pdfdoc.py
+++ b/pypdf/_codecs/pdfdoc.py
@@ -1,21 +1,264 @@
-_pdfdoc_encoding = ['\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06',
- '\x07', '\x08', '\t', '\n', '\x0b', '\x0c', '\r', '\x0e', '\x0f',
- '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x00', '\x17', '˘',
- 'ˇ', 'ˆ', '˙', '˝', '˛', '˚', '˜', ' ', '!', '"', '#', '$', '%', '&',
- "'", '(', ')', '*', '+', ',', '-', '.', '/', '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',
- '{', '|', '}', '~', '\x00', '•', '†', '‡', '…', '—', '–', 'ƒ', '⁄', '‹',
- '›', '−', '‰', '„', '“', '”', '‘', '’', '‚', '™', 'fi', 'fl', 'Ł', 'Œ',
- 'Š', 'Ÿ', 'Ž', 'ı', 'ł', 'œ', 'š', 'ž', '\x00', '€', '¡', '¢', '£', '¤',
- '¥', '¦', '§', '¨', '©', 'ª', '«', '¬', '\x00', '®', '¯', '°', '±', '²',
- '³', '´', 'µ', '¶', '·', '¸', '¹', 'º', '»', '¼', '½', '¾', '¿', 'À',
- 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î',
- 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '×', 'Ø', 'Ù', 'Ú', 'Û', 'Ü',
- 'Ý', 'Þ', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê',
- 'ë', 'ì', 'í', 'î', 'ï', 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø',
- 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ']
+# 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/pypdf/_codecs/std.py b/pypdf/_codecs/std.py
index 2aaa9eac..a6057ff3 100644
--- a/pypdf/_codecs/std.py
+++ b/pypdf/_codecs/std.py
@@ -1,22 +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', '°', '–', '†', '‡', '·', 'µ', '¶', '•',
- '‚', '„', '”', '»', '…', '‰', '¾', '¿', 'À', '`', '´', 'ˆ', '˜', '¯',
- '˘', '˙', '¨', 'É', '˚', '¸', 'Ì', '˝', '˛', 'ˇ', '—', 'Ñ', 'Ò', 'Ó',
- 'Ô', 'Õ', 'Ö', '×', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß', 'à', 'Æ',
- 'â', 'ª', 'ä', 'å', 'æ', 'ç', 'Ł', 'Ø', 'Œ', 'º', 'ì', 'í', 'î', 'ï',
- 'ð', 'æ', 'ò', 'ó', 'ô', 'ı', 'ö', '÷', 'ł', 'ø', 'œ', 'ß', 'ü', 'ý',
- 'þ', 'ÿ']
+_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/pypdf/_codecs/symbol.py b/pypdf/_codecs/symbol.py
index 38b3710f..4c0d680f 100644
--- a/pypdf/_codecs/symbol.py
+++ b/pypdf/_codecs/symbol.py
@@ -1,25 +1,260 @@
-_symbol_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', ':', ';', '<', '=', '>',
- '?', '≅', 'Α', 'Β', 'Χ', 'Δ', 'Ε', 'Φ', 'Γ', 'Η', 'Ι', 'ϑ', 'Κ', 'Λ',
- 'Μ', 'Ν', 'Ο', 'Π', 'Θ', 'Ρ', 'Σ', 'Τ', 'Υ', 'ς', 'Ω', 'Ξ', 'Ψ', 'Ζ',
- '[', '∴', ']', '⊥', '_', '\uf8e5', 'α', 'β', 'χ', 'δ', 'ε', 'φ', 'γ',
- 'η', 'ι', 'ϕ', 'κ', 'λ', 'µ', 'ν', 'ο', 'π', 'θ', 'ρ', 'σ', 'τ', 'υ',
- 'ϖ', 'ω', 'ξ', 'ψ', 'ζ', '{', '|', '}', '∼', '\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', '€', 'ϒ', '′', '≤', '⁄', '∞', 'ƒ', '♣', '♦',
- '♥', '♠', '↔', '←', '↑', '→', '↓', '°', '±', '″', '≥', '×', '∝', '∂',
- '•', '÷', '≠', '≡', '≈', '…', '\uf8e6', '\uf8e7', '↵', 'ℵ', 'ℑ', 'ℜ',
- '℘', '⊗', '⊕', '∅', '∩', '∪', '⊃', '⊇', '⊄', '⊂', '⊆', '∈', '∉', '∠',
- '∇', '\uf6da', '\uf6d9', '\uf6db', '∏', '√', '⋅', '¬', '∧', '∨', '⇔',
- '⇐', '⇑', '⇒', '⇓', '◊', '〈', '\uf8e8', '\uf8e9', '\uf8ea', '∑',
- '\uf8eb', '\uf8ec', '\uf8ed', '\uf8ee', '\uf8ef', '\uf8f0', '\uf8f1',
- '\uf8f2', '\uf8f3', '\uf8f4', 'ð', '〉', '∫', '⌠', '\uf8f5', '⌡',
- '\uf8f6', '\uf8f7', '\uf8f8', '\uf8f9', '\uf8fa', '\uf8fb', '\uf8fc',
- '\uf8fd', '\uf8fe', 'ÿ']
+# 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/pypdf/_codecs/zapfding.py b/pypdf/_codecs/zapfding.py
index 392c94b5..9b6cdbcc 100644
--- a/pypdf/_codecs/zapfding.py
+++ b/pypdf/_codecs/zapfding.py
@@ -1,23 +1,261 @@
-_zapfding_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', ' ',
- '✁', '✂', '✃', '✄', '☎', '✆', '✇', '✈', '✉', '☛', '☞', '✌', '✍', '✎',
- '✏', '✐', '✑', '✒', '✓', '✔', '✕', '✖', '✗', '✘', '✙', '✚', '✛', '✜',
- '✝', '✞', '✟', '✠', '✡', '✢', '✣', '✤', '✥', '✦', '✧', '★', '✩', '✪',
- '✫', '✬', '✭', '✮', '✯', '✰', '✱', '✲', '✳', '✴', '✵', '✶', '✷', '✸',
- '✹', '✺', '✻', '✼', '✽', '✾', '✿', '❀', '❁', '❂', '❃', '❄', '❅', '❆',
- '❇', '❈', '❉', '❊', '❋', '●', '❍', '■', '❏', '❐', '❑', '❒', '▲', '▼',
- '◆', '❖', '◗', '❘', '❙', '❚', '❛', '❜', '❝', '❞', '\x7f', '\uf8d7',
- '\uf8d8', '\uf8d9', '\uf8da', '\uf8db', '\uf8dc', '\uf8dd', '\uf8de',
- '\uf8df', '\uf8e0', '\uf8e1', '\uf8e2', '\uf8e3', '\uf8e4', '\x8e',
- '\x8f', '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
- '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f', '\xa0',
- '❡', '❢', '❣', '❤', '❥', '❦', '❧', '♣', '♦', '♥', '♠', '①', '②', '③',
- '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩', '❶', '❷', '❸', '❹', '❺', '❻', '❼',
- '❽', '❾', '❿', '➀', '➁', '➂', '➃', '➄', '➅', '➆', '➇', '➈', '➉', '➊',
- '➋', '➌', '➍', '➎', '➏', '➐', '➑', '➒', '➓', '➔', '→', '↔', '↕', '➘',
- '➙', '➚', '➛', '➜', '➝', '➞', '➟', '➠', '➡', '➢', '➣', '➤', '➥', '➦',
- '➧', '➨', '➩', '➪', '➫', '➬', '➭', '➮', '➯', 'ð', '➱', '➲', '➳', '➴',
- '➵', '➶', '➷', '➸', '➹', '➺', '➻', '➼', '➽', '➾', 'ÿ']
+# 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/pypdf/_crypt_providers/_base.py b/pypdf/_crypt_providers/_base.py
index 916f3fd6..894025f3 100644
--- a/pypdf/_crypt_providers/_base.py
+++ b/pypdf/_crypt_providers/_base.py
@@ -1,5 +1,37 @@
+# Copyright (c) 2023, exiledkingcc
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+
class CryptBase:
- pass
+ 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):
diff --git a/pypdf/_crypt_providers/_cryptography.py b/pypdf/_crypt_providers/_cryptography.py
index 2b5b94db..f5537612 100644
--- a/pypdf/_crypt_providers/_cryptography.py
+++ b/pypdf/_crypt_providers/_cryptography.py
@@ -1,24 +1,118 @@
+# Copyright (c) 2023, exiledkingcc
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
import secrets
+
from cryptography import __version__
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers.algorithms import AES
+
try:
+ # 43.0.0 - https://cryptography.io/en/latest/changelog/#v43-0-0
from cryptography.hazmat.decrepit.ciphers.algorithms import ARC4
except ImportError:
from cryptography.hazmat.primitives.ciphers.algorithms import ARC4
from cryptography.hazmat.primitives.ciphers.base import Cipher
from cryptography.hazmat.primitives.ciphers.modes import CBC, ECB
+
from pypdf._crypt_providers._base import CryptBase
-crypt_provider = 'cryptography', __version__
+crypt_provider = ("cryptography", __version__)
-class CryptRC4(CryptBase):
- def __init__(self, key: bytes) ->None:
+class CryptRC4(CryptBase):
+ def __init__(self, key: bytes) -> None:
self.cipher = Cipher(ARC4(key), mode=None)
+ def encrypt(self, data: bytes) -> bytes:
+ encryptor = self.cipher.encryptor()
+ return encryptor.update(data) + encryptor.finalize()
-class CryptAES(CryptBase):
+ def decrypt(self, data: bytes) -> bytes:
+ decryptor = self.cipher.decryptor()
+ return decryptor.update(data) + decryptor.finalize()
- def __init__(self, key: bytes) ->None:
+
+class CryptAES(CryptBase):
+ def __init__(self, key: bytes) -> None:
self.alg = AES(key)
+
+ def encrypt(self, data: bytes) -> bytes:
+ iv = secrets.token_bytes(16)
+ pad = padding.PKCS7(128).padder()
+ data = pad.update(data) + pad.finalize()
+
+ cipher = Cipher(self.alg, CBC(iv))
+ encryptor = cipher.encryptor()
+ return iv + encryptor.update(data) + encryptor.finalize()
+
+ def decrypt(self, data: bytes) -> bytes:
+ iv = data[:16]
+ data = data[16:]
+ # for empty encrypted data
+ if not data:
+ return data
+
+ # just for robustness, it does not happen under normal circumstances
+ if len(data) % 16 != 0:
+ pad = padding.PKCS7(128).padder()
+ data = pad.update(data) + pad.finalize()
+
+ cipher = Cipher(self.alg, CBC(iv))
+ decryptor = cipher.decryptor()
+ d = decryptor.update(data) + decryptor.finalize()
+ return d[: -d[-1]]
+
+
+def rc4_encrypt(key: bytes, data: bytes) -> bytes:
+ encryptor = Cipher(ARC4(key), mode=None).encryptor()
+ return encryptor.update(data) + encryptor.finalize()
+
+
+def rc4_decrypt(key: bytes, data: bytes) -> bytes:
+ decryptor = Cipher(ARC4(key), mode=None).decryptor()
+ return decryptor.update(data) + decryptor.finalize()
+
+
+def aes_ecb_encrypt(key: bytes, data: bytes) -> bytes:
+ encryptor = Cipher(AES(key), mode=ECB()).encryptor()
+ return encryptor.update(data) + encryptor.finalize()
+
+
+def aes_ecb_decrypt(key: bytes, data: bytes) -> bytes:
+ decryptor = Cipher(AES(key), mode=ECB()).decryptor()
+ return decryptor.update(data) + decryptor.finalize()
+
+
+def aes_cbc_encrypt(key: bytes, iv: bytes, data: bytes) -> bytes:
+ encryptor = Cipher(AES(key), mode=CBC(iv)).encryptor()
+ return encryptor.update(data) + encryptor.finalize()
+
+
+def aes_cbc_decrypt(key: bytes, iv: bytes, data: bytes) -> bytes:
+ decryptor = Cipher(AES(key), mode=CBC(iv)).decryptor()
+ return decryptor.update(data) + decryptor.finalize()
diff --git a/pypdf/_crypt_providers/_fallback.py b/pypdf/_crypt_providers/_fallback.py
index f69eb288..631fec19 100644
--- a/pypdf/_crypt_providers/_fallback.py
+++ b/pypdf/_crypt_providers/_fallback.py
@@ -1,20 +1,93 @@
+# Copyright (c) 2023, exiledkingcc
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
from pypdf._crypt_providers._base import CryptBase
from pypdf.errors import DependencyError
-_DEPENDENCY_ERROR_STR = 'cryptography>=3.1 is required for AES algorithm'
-crypt_provider = 'local_crypt_fallback', '0.0.0'
+_DEPENDENCY_ERROR_STR = "cryptography>=3.1 is required for AES algorithm"
-class CryptRC4(CryptBase):
- def __init__(self, key: bytes) ->None:
+crypt_provider = ("local_crypt_fallback", "0.0.0")
+
+
+class CryptRC4(CryptBase):
+ def __init__(self, key: bytes) -> None:
self.s = bytearray(range(256))
j = 0
for i in range(256):
j = (j + self.s[i] + key[i % len(key)]) % 256
self.s[i], self.s[j] = self.s[j], self.s[i]
+ def encrypt(self, data: bytes) -> bytes:
+ s = bytearray(self.s)
+ out = [0 for _ in range(len(data))]
+ i, j = 0, 0
+ for k in range(len(data)):
+ i = (i + 1) % 256
+ j = (j + s[i]) % 256
+ s[i], s[j] = s[j], s[i]
+ x = s[(s[i] + s[j]) % 256]
+ out[k] = data[k] ^ x
+ return bytes(bytearray(out))
-class CryptAES(CryptBase):
+ def decrypt(self, data: bytes) -> bytes:
+ return self.encrypt(data)
- def __init__(self, key: bytes) ->None:
+
+class CryptAES(CryptBase):
+ def __init__(self, key: bytes) -> None:
pass
+
+ def encrypt(self, data: bytes) -> bytes:
+ raise DependencyError(_DEPENDENCY_ERROR_STR)
+
+ def decrypt(self, data: bytes) -> bytes:
+ raise DependencyError(_DEPENDENCY_ERROR_STR)
+
+
+def rc4_encrypt(key: bytes, data: bytes) -> bytes:
+ return CryptRC4(key).encrypt(data)
+
+
+def rc4_decrypt(key: bytes, data: bytes) -> bytes:
+ return CryptRC4(key).decrypt(data)
+
+
+def aes_ecb_encrypt(key: bytes, data: bytes) -> bytes:
+ raise DependencyError(_DEPENDENCY_ERROR_STR)
+
+
+def aes_ecb_decrypt(key: bytes, data: bytes) -> bytes:
+ raise DependencyError(_DEPENDENCY_ERROR_STR)
+
+
+def aes_cbc_encrypt(key: bytes, iv: bytes, data: bytes) -> bytes:
+ raise DependencyError(_DEPENDENCY_ERROR_STR)
+
+
+def aes_cbc_decrypt(key: bytes, iv: bytes, data: bytes) -> bytes:
+ raise DependencyError(_DEPENDENCY_ERROR_STR)
diff --git a/pypdf/_crypt_providers/_pycryptodome.py b/pypdf/_crypt_providers/_pycryptodome.py
index 767d5e8e..30a13e18 100644
--- a/pypdf/_crypt_providers/_pycryptodome.py
+++ b/pypdf/_crypt_providers/_pycryptodome.py
@@ -1,18 +1,97 @@
+# Copyright (c) 2023, exiledkingcc
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
import secrets
+
from Crypto import __version__
from Crypto.Cipher import AES, ARC4
from Crypto.Util.Padding import pad
+
from pypdf._crypt_providers._base import CryptBase
-crypt_provider = 'pycryptodome', __version__
+crypt_provider = ("pycryptodome", __version__)
-class CryptRC4(CryptBase):
- def __init__(self, key: bytes) ->None:
+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)
-class CryptAES(CryptBase):
+ def decrypt(self, data: bytes) -> bytes:
+ return ARC4.ARC4Cipher(self.key).decrypt(data)
- def __init__(self, key: bytes) ->None:
+
+class CryptAES(CryptBase):
+ def __init__(self, key: bytes) -> None:
self.key = key
+
+ def encrypt(self, data: bytes) -> bytes:
+ iv = secrets.token_bytes(16)
+ data = pad(data, 16)
+ aes = AES.new(self.key, AES.MODE_CBC, iv)
+ return iv + aes.encrypt(data)
+
+ def decrypt(self, data: bytes) -> bytes:
+ iv = data[:16]
+ data = data[16:]
+ # for empty encrypted data
+ if not data:
+ return data
+
+ # just for robustness, it does not happen under normal circumstances
+ if len(data) % 16 != 0:
+ data = pad(data, 16)
+
+ aes = AES.new(self.key, AES.MODE_CBC, iv)
+ d = aes.decrypt(data)
+ return d[: -d[-1]]
+
+
+def rc4_encrypt(key: bytes, data: bytes) -> bytes:
+ return ARC4.ARC4Cipher(key).encrypt(data)
+
+
+def rc4_decrypt(key: bytes, data: bytes) -> bytes:
+ return ARC4.ARC4Cipher(key).decrypt(data)
+
+
+def aes_ecb_encrypt(key: bytes, data: bytes) -> bytes:
+ return AES.new(key, AES.MODE_ECB).encrypt(data)
+
+
+def aes_ecb_decrypt(key: bytes, data: bytes) -> bytes:
+ return AES.new(key, AES.MODE_ECB).decrypt(data)
+
+
+def aes_cbc_encrypt(key: bytes, iv: bytes, data: bytes) -> bytes:
+ return AES.new(key, AES.MODE_CBC, iv).encrypt(data)
+
+
+def aes_cbc_decrypt(key: bytes, iv: bytes, data: bytes) -> bytes:
+ return AES.new(key, AES.MODE_CBC, iv).decrypt(data)
diff --git a/pypdf/_doc_common.py b/pypdf/_doc_common.py
index eaec7b5c..d4c5c43c 100644
--- a/pypdf/_doc_common.py
+++ b/pypdf/_doc_common.py
@@ -1,26 +1,106 @@
+# Copyright (c) 2006, Mathieu Fenniak
+# Copyright (c) 2007, Ashish Kulkarni <kulkarni.ashish@gmail.com>
+# Copyright (c) 2024, Pubpub-ZZ
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
import struct
import zlib
from abc import abstractmethod
from datetime import datetime
-from typing import Any, Dict, Iterable, Iterator, List, Mapping, Optional, Tuple, Union, cast
+from typing import (
+ Any,
+ Dict,
+ Iterable,
+ Iterator,
+ List,
+ Mapping,
+ Optional,
+ Tuple,
+ Union,
+ cast,
+)
+
from ._encryption import Encryption
from ._page import PageObject, _VirtualList
from ._page_labels import index2label as page_index2page_label
-from ._utils import b_, deprecate_with_replacement, logger_warning, parse_iso8824_date
+from ._utils import (
+ b_,
+ deprecate_with_replacement,
+ logger_warning,
+ parse_iso8824_date,
+)
from .constants import CatalogAttributes as CA
from .constants import CatalogDictionary as CD
-from .constants import CheckboxRadioButtonAttributes, GoToActionArguments, UserAccessPermissions
+from .constants import (
+ CheckboxRadioButtonAttributes,
+ GoToActionArguments,
+ UserAccessPermissions,
+)
from .constants import Core as CO
from .constants import DocumentInformationAttributes as DI
from .constants import FieldDictionaryAttributes as FA
from .constants import PageAttributes as PG
from .constants import PagesAttributes as PA
-from .errors import PdfReadError
-from .generic import ArrayObject, BooleanObject, ByteStringObject, Destination, DictionaryObject, EncodedStreamObject, Field, Fit, FloatObject, IndirectObject, NameObject, NullObject, NumberObject, PdfObject, TextStringObject, TreeObject, ViewerPreferences, create_string_object
+from .errors import (
+ PdfReadError,
+)
+from .generic import (
+ ArrayObject,
+ BooleanObject,
+ ByteStringObject,
+ Destination,
+ DictionaryObject,
+ EncodedStreamObject,
+ Field,
+ Fit,
+ FloatObject,
+ IndirectObject,
+ NameObject,
+ NullObject,
+ NumberObject,
+ PdfObject,
+ TextStringObject,
+ TreeObject,
+ ViewerPreferences,
+ create_string_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]
+
+
class DocumentInformation(DictionaryObject):
"""
A class representing the basic document metadata provided in a PDF File.
@@ -36,56 +116,66 @@ class DocumentInformation(DictionaryObject):
as commonly accessed.
"""
- def __init__(self) ->None:
+ 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
+
@property
- def title(self) ->Optional[str]:
+ def title(self) -> Optional[str]:
"""
Read-only property accessing the document's title.
Returns a ``TextStringObject`` or ``None`` if the title is not
specified.
"""
- pass
+ 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]:
+ def title_raw(self) -> Optional[str]:
"""The "raw" version of title; can return a ``ByteStringObject``."""
- pass
+ return self.get(DI.TITLE)
@property
- def author(self) ->Optional[str]:
+ def author(self) -> Optional[str]:
"""
Read-only property accessing the document's author.
Returns a ``TextStringObject`` or ``None`` if the author is not
specified.
"""
- pass
+ return self._get_text(DI.AUTHOR)
@property
- def author_raw(self) ->Optional[str]:
+ def author_raw(self) -> Optional[str]:
"""The "raw" version of author; can return a ``ByteStringObject``."""
- pass
+ return self.get(DI.AUTHOR)
@property
- def subject(self) ->Optional[str]:
+ def subject(self) -> Optional[str]:
"""
Read-only property accessing the document's subject.
Returns a ``TextStringObject`` or ``None`` if the subject is not
specified.
"""
- pass
+ return self._get_text(DI.SUBJECT)
@property
- def subject_raw(self) ->Optional[str]:
+ def subject_raw(self) -> Optional[str]:
"""The "raw" version of subject; can return a ``ByteStringObject``."""
- pass
+ return self.get(DI.SUBJECT)
@property
- def creator(self) ->Optional[str]:
+ def creator(self) -> Optional[str]:
"""
Read-only property accessing the document's creator.
@@ -94,15 +184,15 @@ class DocumentInformation(DictionaryObject):
document from which it was converted. Returns a ``TextStringObject`` or
``None`` if the creator is not specified.
"""
- pass
+ return self._get_text(DI.CREATOR)
@property
- def creator_raw(self) ->Optional[str]:
+ def creator_raw(self) -> Optional[str]:
"""The "raw" version of creator; can return a ``ByteStringObject``."""
- pass
+ return self.get(DI.CREATOR)
@property
- def producer(self) ->Optional[str]:
+ def producer(self) -> Optional[str]:
"""
Read-only property accessing the document's producer.
@@ -111,39 +201,39 @@ class DocumentInformation(DictionaryObject):
PDF. Returns a ``TextStringObject`` or ``None`` if the producer is not
specified.
"""
- pass
+ return self._get_text(DI.PRODUCER)
@property
- def producer_raw(self) ->Optional[str]:
+ def producer_raw(self) -> Optional[str]:
"""The "raw" version of producer; can return a ``ByteStringObject``."""
- pass
+ return self.get(DI.PRODUCER)
@property
- def creation_date(self) ->Optional[datetime]:
+ def creation_date(self) -> Optional[datetime]:
"""Read-only property accessing the document's creation date."""
- pass
+ return parse_iso8824_date(self._get_text(DI.CREATION_DATE))
@property
- def creation_date_raw(self) ->Optional[str]:
+ def creation_date_raw(self) -> Optional[str]:
"""
The "raw" version of creation date; can return a ``ByteStringObject``.
Typically in the format ``D:YYYYMMDDhhmmss[+Z-]hh'mm`` where the suffix
is the offset from UTC.
"""
- pass
+ return self.get(DI.CREATION_DATE)
@property
- def modification_date(self) ->Optional[datetime]:
+ 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.
"""
- pass
+ return parse_iso8824_date(self._get_text(DI.MOD_DATE))
@property
- def modification_date_raw(self) ->Optional[str]:
+ def modification_date_raw(self) -> Optional[str]:
"""
The "raw" version of modification date; can return a
``ByteStringObject``.
@@ -151,7 +241,7 @@ class DocumentInformation(DictionaryObject):
Typically in the format ``D:YYYYMMDDhhmmss[+Z-]hh'mm`` where the suffix
is the offset from UTC.
"""
- pass
+ return self.get(DI.MOD_DATE)
class PdfDocCommon:
@@ -160,11 +250,38 @@ class PdfDocCommon:
This root class is strongly abstracted.
"""
- strict: bool = False
+
+ strict: bool = False # default
+
_encryption: Optional[Encryption] = None
@property
- def metadata(self) ->Optional[DocumentInformation]:
+ @abstractmethod
+ def root_object(self) -> DictionaryObject:
+ ... # pragma: no cover
+
+ @property
+ @abstractmethod
+ def pdf_header(self) -> str:
+ ... # pragma: no cover
+
+ @abstractmethod
+ def get_object(
+ self, indirect_reference: Union[int, IndirectObject]
+ ) -> Optional[PdfObject]:
+ ... # pragma: no cover
+
+ @abstractmethod
+ def _replace_object(self, indirect: IndirectObject, obj: PdfObject) -> PdfObject:
+ ... # pragma: no cover
+
+ @property
+ @abstractmethod
+ def _info(self) -> Optional[DictionaryObject]:
+ ... # pragma: no cover
+
+ @property
+ def metadata(self) -> Optional[DocumentInformation]:
"""
Retrieve the PDF file's document information dictionary, if it exists.
@@ -172,11 +289,22 @@ class PdfDocCommon:
information dictionaries, and these metadata streams will not be
accessed by this function.
"""
- pass
+ retval = DocumentInformation()
+ if self._info is None:
+ return None
+ retval.update(self._info)
+ return retval
+
+ @property
+ def xmp_metadata(self) -> Optional[XmpInformation]:
+ ... # pragma: no cover
@abstractmethod
- def _repr_mimebundle_(self, include: Union[None, Iterable[str]]=None,
- exclude: Union[None, Iterable[str]]=None) ->Dict[str, Any]:
+ def _repr_mimebundle_(
+ self,
+ include: Union[None, Iterable[str]] = None,
+ exclude: Union[None, Iterable[str]] = None,
+ ) -> Dict[str, Any]:
"""
Integration into Jupyter Notebooks.
@@ -185,15 +313,26 @@ class PdfDocCommon:
See https://ipython.readthedocs.io/en/stable/config/integrating.html
"""
- pass
+ ... # pragma: no cover
@property
- def viewer_preferences(self) ->Optional[ViewerPreferences]:
+ def viewer_preferences(self) -> Optional[ViewerPreferences]:
"""Returns the existing ViewerPreferences as an overloaded dictionary."""
- pass
+ o = self.root_object.get(CD.VIEWER_PREFERENCES, None)
+ if o is None:
+ return None
+ o = o.get_object()
+ if not isinstance(o, ViewerPreferences):
+ o = ViewerPreferences(o)
+ if hasattr(o, "indirect_reference"):
+ self._replace_object(o.indirect_reference, o)
+ else:
+ self.root_object[NameObject(CD.VIEWER_PREFERENCES)] = o
+ return o
+
flattened_pages: Optional[List[PageObject]] = None
- def get_num_pages(self) ->int:
+ def get_num_pages(self) -> int:
"""
Calculate the number of pages in this PDF file.
@@ -204,9 +343,18 @@ class PdfDocCommon:
PdfReadError: if file is encrypted and restrictions prevent
this action.
"""
- pass
-
- def get_page(self, page_number: int) ->PageObject:
+ # Flattened pages will not work on an encrypted PDF;
+ # the PDF file's page count is used in this case. Otherwise,
+ # the original method (flattened page count) is used.
+ if self.is_encrypted:
+ return self.root_object["/Pages"]["/Count"] # type: ignore
+ else:
+ if self.flattened_pages is None:
+ self._flatten()
+ assert self.flattened_pages is not None
+ return len(self.flattened_pages)
+
+ def get_page(self, page_number: int) -> PageObject:
"""
Retrieve a page by number from this PDF file.
Most of the time ``.pages[page_number]`` is preferred.
@@ -218,18 +366,59 @@ class PdfDocCommon:
Returns:
A :class:`PageObject<pypdf._page.PageObject>` instance.
"""
- pass
+ 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 named_destinations(self) ->Dict[str, Any]:
+ def named_destinations(self) -> Dict[str, Any]:
"""
A read-only dictionary which maps names to
:class:`Destinations<pypdf.generic.Destination>`
"""
- pass
-
- def _get_named_destinations(self, tree: Union[TreeObject, None]=None,
- retval: Optional[Any]=None) ->Dict[str, Any]:
+ return self._get_named_destinations()
+
+ def get_named_dest_root(self) -> ArrayObject:
+ named_dest = ArrayObject()
+ if CA.NAMES in self.root_object and isinstance(
+ self.root_object[CA.NAMES], DictionaryObject
+ ):
+ names = cast(DictionaryObject, self.root_object[CA.NAMES])
+ names_ref = names.indirect_reference
+ if CA.DESTS in names and isinstance(names[CA.DESTS], DictionaryObject):
+ # 3.6.3 Name Dictionary (PDF spec 1.7)
+ dests = cast(DictionaryObject, names[CA.DESTS])
+ dests_ref = dests.indirect_reference
+ if CA.NAMES in dests:
+ # §7.9.6, entries in a name tree node dictionary
+ named_dest = cast(ArrayObject, dests[CA.NAMES])
+ else:
+ named_dest = ArrayObject()
+ dests[NameObject(CA.NAMES)] = named_dest
+ elif hasattr(self, "_add_object"):
+ dests = DictionaryObject()
+ dests_ref = self._add_object(dests)
+ names[NameObject(CA.DESTS)] = dests_ref
+ dests[NameObject(CA.NAMES)] = named_dest
+
+ elif hasattr(self, "_add_object"):
+ names = DictionaryObject()
+ names_ref = self._add_object(names)
+ self.root_object[NameObject(CA.NAMES)] = names_ref
+ dests = DictionaryObject()
+ dests_ref = self._add_object(dests)
+ names[NameObject(CA.DESTS)] = dests_ref
+ dests[NameObject(CA.NAMES)] = named_dest
+
+ return named_dest
+
+ ## common
+ def _get_named_destinations(
+ self,
+ tree: Union[TreeObject, None] = None,
+ retval: Optional[Any] = None,
+ ) -> Dict[str, Any]:
"""
Retrieve the named destinations present in the document.
@@ -241,11 +430,70 @@ class PdfDocCommon:
A dictionary which maps names to
:class:`Destinations<pypdf.generic.Destination>`.
"""
- pass
-
- def get_fields(self, tree: Optional[TreeObject]=None, retval: Optional[
- Dict[Any, Any]]=None, fileobj: Optional[Any]=None, stack: Optional[
- List[PdfObject]]=None) ->Optional[Dict[str, Any]]:
+ if retval is None:
+ retval = {}
+ catalog = self.root_object
+
+ # get the name tree
+ if CA.DESTS in catalog:
+ tree = cast(TreeObject, catalog[CA.DESTS])
+ elif CA.NAMES in catalog:
+ names = cast(DictionaryObject, catalog[CA.NAMES])
+ if CA.DESTS in names:
+ tree = cast(TreeObject, names[CA.DESTS])
+
+ if tree is None:
+ return retval
+
+ if PA.KIDS in tree:
+ # recurse down the tree
+ for kid in cast(ArrayObject, tree[PA.KIDS]):
+ self._get_named_destinations(kid.get_object(), retval)
+ # §7.9.6, entries in a name tree node dictionary
+ elif CA.NAMES in tree: # /Kids and /Names are exclusives (§7.9.6)
+ names = cast(DictionaryObject, tree[CA.NAMES])
+ i = 0
+ while i < len(names):
+ key = cast(str, names[i].get_object())
+ i += 1
+ if not isinstance(key, str):
+ continue
+ try:
+ value = names[i].get_object()
+ except IndexError:
+ break
+ i += 1
+ if isinstance(value, DictionaryObject):
+ if "/D" in value:
+ value = value["/D"]
+ else:
+ continue
+ dest = self._build_destination(key, value) # type: ignore
+ if dest is not None:
+ retval[key] = dest
+ else: # case where Dests is in root catalog (PDF 1.7 specs, §2 about PDF 1.1)
+ for k__, v__ in tree.items():
+ val = v__.get_object()
+ if isinstance(val, DictionaryObject):
+ if "/D" in val:
+ val = val["/D"].get_object()
+ else:
+ continue
+ dest = self._build_destination(k__, val)
+ if dest is not None:
+ retval[k__] = dest
+ return retval
+
+ # A select group of relevant field attributes. For the complete list.
+ # See §12.3.2 of the PDF 1.7 or PDF 2.0 specification.
+
+ def get_fields(
+ self,
+ tree: Optional[TreeObject] = None,
+ retval: Optional[Dict[Any, Any]] = None,
+ fileobj: Optional[Any] = None,
+ stack: Optional[List[PdfObject]] = None,
+ ) -> Optional[Dict[str, Any]]:
"""
Extract field data if this PDF contains interactive form fields.
@@ -264,10 +512,143 @@ class PdfDocCommon:
default, the mapping name is used for keys.
``None`` if form data could not be located.
"""
- pass
-
- def get_form_text_fields(self, full_qualified_name: bool=False) ->Dict[
- str, Any]:
+ field_attributes = FA.attributes_dict()
+ field_attributes.update(CheckboxRadioButtonAttributes.attributes_dict())
+ if retval is None:
+ retval = {}
+ catalog = self.root_object
+ stack = []
+ # get the AcroForm tree
+ if CD.ACRO_FORM in catalog:
+ tree = cast(Optional[TreeObject], catalog[CD.ACRO_FORM])
+ else:
+ return None
+ if tree is None:
+ return retval
+ assert stack is not None
+ if "/Fields" in tree:
+ fields = cast(ArrayObject, tree["/Fields"])
+ for f in fields:
+ field = f.get_object()
+ self._build_field(field, retval, fileobj, field_attributes, stack)
+ elif any(attr in tree for attr in field_attributes):
+ # Tree is a field
+ self._build_field(tree, retval, fileobj, field_attributes, stack)
+ return retval
+
+ def _get_qualified_field_name(self, parent: DictionaryObject) -> str:
+ if "/TM" in parent:
+ return cast(str, parent["/TM"])
+ elif "/Parent" in parent:
+ return (
+ self._get_qualified_field_name(
+ cast(DictionaryObject, parent["/Parent"])
+ )
+ + "."
+ + cast(str, parent.get("/T", ""))
+ )
+ else:
+ return cast(str, parent.get("/T", ""))
+
+ def _build_field(
+ self,
+ field: Union[TreeObject, DictionaryObject],
+ retval: Dict[Any, Any],
+ fileobj: Any,
+ field_attributes: Any,
+ stack: List[PdfObject],
+ ) -> None:
+ if all(attr not in field for attr in ("/T", "/TM")):
+ return
+ key = self._get_qualified_field_name(field)
+ if fileobj:
+ self._write_field(fileobj, field, field_attributes)
+ fileobj.write("\n")
+ retval[key] = Field(field)
+ obj = retval[key].indirect_reference.get_object() # to get the full object
+ if obj.get(FA.FT, "") == "/Ch":
+ retval[key][NameObject("/_States_")] = obj[NameObject(FA.Opt)]
+ if obj.get(FA.FT, "") == "/Btn" and "/AP" in obj:
+ # Checkbox
+ retval[key][NameObject("/_States_")] = ArrayObject(
+ list(obj["/AP"]["/N"].keys())
+ )
+ if "/Off" not in retval[key]["/_States_"]:
+ retval[key][NameObject("/_States_")].append(NameObject("/Off"))
+ elif obj.get(FA.FT, "") == "/Btn" and obj.get(FA.Ff, 0) & FA.FfBits.Radio != 0:
+ states: List[str] = []
+ retval[key][NameObject("/_States_")] = ArrayObject(states)
+ for k in obj.get(FA.Kids, {}):
+ k = k.get_object()
+ for s in list(k["/AP"]["/N"].keys()):
+ if s not in states:
+ states.append(s)
+ retval[key][NameObject("/_States_")] = ArrayObject(states)
+ if (
+ obj.get(FA.Ff, 0) & FA.FfBits.NoToggleToOff != 0
+ and "/Off" in retval[key]["/_States_"]
+ ):
+ del retval[key]["/_States_"][retval[key]["/_States_"].index("/Off")]
+ # at last for order
+ self._check_kids(field, retval, fileobj, stack)
+
+ def _check_kids(
+ self,
+ tree: Union[TreeObject, DictionaryObject],
+ retval: Any,
+ fileobj: Any,
+ stack: List[PdfObject],
+ ) -> None:
+ if tree in stack:
+ logger_warning(
+ f"{self._get_qualified_field_name(tree)} already parsed", __name__
+ )
+ return
+ stack.append(tree)
+ if PA.KIDS in tree:
+ # recurse down the tree
+ for kid in tree[PA.KIDS]: # type: ignore
+ kid = kid.get_object()
+ self.get_fields(kid, retval, fileobj, stack)
+
+ def _write_field(self, fileobj: Any, field: Any, field_attributes: Any) -> None:
+ field_attributes_tuple = FA.attributes()
+ field_attributes_tuple = (
+ field_attributes_tuple + CheckboxRadioButtonAttributes.attributes()
+ )
+
+ for attr in field_attributes_tuple:
+ if attr in (
+ FA.Kids,
+ FA.AA,
+ ):
+ continue
+ attr_name = field_attributes[attr]
+ try:
+ if attr == FA.FT:
+ # Make the field type value more clear
+ types = {
+ "/Btn": "Button",
+ "/Tx": "Text",
+ "/Ch": "Choice",
+ "/Sig": "Signature",
+ }
+ if field[attr] in types:
+ fileobj.write(f"{attr_name}: {types[field[attr]]}\n")
+ elif attr == FA.Parent:
+ # Let's just write the name of the parent
+ try:
+ name = field[attr][FA.TM]
+ except KeyError:
+ name = field[attr][FA.T]
+ fileobj.write(f"{attr_name}: {name}\n")
+ else:
+ fileobj.write(f"{attr_name}: {field[attr]}\n")
+ except KeyError:
+ # Field attribute is N/A or unknown, so don't write anything
+ pass
+
+ def get_form_text_fields(self, full_qualified_name: bool = False) -> Dict[str, Any]:
"""
Retrieve form fields from the document with textual data.
@@ -281,10 +662,33 @@ class PdfDocCommon:
If the document contains multiple form fields with the same name, the
second and following will get the suffix .2, .3, ...
"""
- pass
- def get_pages_showing_field(self, field: Union[Field, PdfObject,
- IndirectObject]) ->List[PageObject]:
+ def indexed_key(k: str, fields: Dict[Any, Any]) -> str:
+ if k not in fields:
+ return k
+ else:
+ return (
+ k
+ + "."
+ + str(sum([1 for kk in fields if kk.startswith(k + ".")]) + 2)
+ )
+
+ # Retrieve document form fields
+ formfields = self.get_fields()
+ if formfields is None:
+ return {}
+ ff = {}
+ for field, value in formfields.items():
+ if value.get("/FT") == "/Tx":
+ if full_qualified_name:
+ ff[field] = value.get("/V")
+ else:
+ ff[indexed_key(cast(str, value["/T"]), ff)] = value.get("/V")
+ return ff
+
+ def get_pages_showing_field(
+ self, field: Union[Field, PdfObject, IndirectObject]
+ ) -> List[PageObject]:
"""
Provides list of pages where the field is called.
@@ -303,11 +707,59 @@ class PdfDocCommon:
Field with multiple kids widgets
(example: radio buttons, field repeated on multiple pages).
"""
- pass
+
+ def _get_inherited(obj: DictionaryObject, key: str) -> Any:
+ if key in obj:
+ return obj[key]
+ elif "/Parent" in obj:
+ return _get_inherited(
+ cast(DictionaryObject, obj["/Parent"].get_object()), key
+ )
+ else:
+ return None
+
+ try:
+ # to cope with all types
+ field = cast(DictionaryObject, field.indirect_reference.get_object()) # type: ignore
+ except Exception as exc:
+ raise ValueError("field type is invalid") from exc
+ if _get_inherited(field, "/FT") is None:
+ raise ValueError("field is not valid")
+ ret = []
+ if field.get("/Subtype", "") == "/Widget":
+ if "/P" in field:
+ ret = [field["/P"].get_object()]
+ else:
+ ret = [
+ p
+ for p in self.pages
+ if field.indirect_reference in p.get("/Annots", "")
+ ]
+ else:
+ kids = field.get("/Kids", ())
+ for k in kids:
+ k = k.get_object()
+ if (k.get("/Subtype", "") == "/Widget") and ("/T" not in k):
+ # Kid that is just a widget, not a field:
+ if "/P" in k:
+ ret += [k["/P"].get_object()]
+ else:
+ ret += [
+ p
+ for p in self.pages
+ if k.indirect_reference in p.get("/Annots", "")
+ ]
+ return [
+ x
+ if isinstance(x, PageObject)
+ else (self.pages[self._get_page_number_by_indirect(x.indirect_reference)]) # type: ignore
+ for x in ret
+ ]
@property
- def open_destination(self) ->Union[None, Destination, TextStringObject,
- ByteStringObject]:
+ 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
@@ -316,19 +768,80 @@ class PdfDocCommon:
Raises:
Exception: If a destination is invalid.
"""
- pass
+ if "/OpenAction" not in self.root_object:
+ return None
+ oa: Any = self.root_object["/OpenAction"]
+ if isinstance(oa, bytes): # pragma: no cover
+ oa = oa.decode()
+ if isinstance(oa, str):
+ return create_string_object(oa)
+ elif isinstance(oa, ArrayObject):
+ try:
+ page, typ = oa[0:2]
+ 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:
+ raise NotImplementedError("no setter for open_destination")
@property
- def outline(self) ->OutlineType:
+ def outline(self) -> OutlineType:
"""
Read-only property for the outline present in the document
(i.e., a collection of 'outline items' which are also known as
'bookmarks').
"""
- pass
+ return self._get_outline()
+
+ def _get_outline(
+ self, node: Optional[DictionaryObject] = None, outline: Optional[Any] = None
+ ) -> OutlineType:
+ if outline is None:
+ outline = []
+ catalog = self.root_object
+
+ # get the outline dictionary and named destinations
+ if CO.OUTLINES in catalog:
+ lines = cast(DictionaryObject, catalog[CO.OUTLINES])
+
+ if isinstance(lines, NullObject):
+ return outline
+
+ # §12.3.3 Document outline, entries in the outline dictionary
+ if 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
@property
- def threads(self) ->Optional[ArrayObject]:
+ def threads(self) -> Optional[ArrayObject]:
"""
Read-only property for the list of threads.
@@ -343,9 +856,19 @@ class PdfDocCommon:
stream containing information about the thread, such as its title,
author, and creation date.
"""
- pass
+ catalog = self.root_object
+ if CO.THREADS in catalog:
+ return cast("ArrayObject", catalog[CO.THREADS])
+ else:
+ return None
+
+ @abstractmethod
+ def _get_page_number_by_indirect(
+ self, indirect_reference: Union[None, int, NullObject, IndirectObject]
+ ) -> Optional[int]:
+ ... # pragma: no cover
- def get_page_number(self, page: PageObject) ->Optional[int]:
+ def get_page_number(self, page: PageObject) -> Optional[int]:
"""
Retrieve page number of a given PageObject.
@@ -356,10 +879,9 @@ class PdfDocCommon:
Returns:
The page number or None if page is not found
"""
- pass
+ return self._get_page_number_by_indirect(page.indirect_reference)
- def get_destination_page_number(self, destination: Destination) ->Optional[
- int]:
+ def get_destination_page_number(self, destination: Destination) -> Optional[int]:
"""
Retrieve page number of a given Destination object.
@@ -369,10 +891,117 @@ class PdfDocCommon:
Returns:
The page number or None if page is not found
"""
- pass
+ return self._get_page_number_by_indirect(destination.page)
+
+ def _build_destination(
+ self,
+ title: str,
+ array: Optional[
+ List[
+ Union[NumberObject, IndirectObject, None, NullObject, DictionaryObject]
+ ]
+ ],
+ ) -> Destination:
+ page, typ = None, None
+ # handle outline items with missing or invalid destination
+ if (
+ isinstance(array, (NullObject, str))
+ or (isinstance(array, ArrayObject) and len(array) == 0)
+ or array is None
+ ):
+ page = NullObject()
+ return Destination(title, page, Fit.fit())
+ else:
+ page, typ = array[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
+ # § 12.3.3, entries in an outline item dictionary
+ try:
+ title = cast("str", node["/Title"])
+ except KeyError:
+ if self.strict:
+ raise PdfReadError(f"Outline Entry Missing /Title attribute: {node!r}")
+ title = ""
+
+ if "/A" in node:
+ # Action, PDFv1.7 Section 12.6 (only type GoTo supported)
+ action = cast(DictionaryObject, node["/A"])
+ action_type = cast(NameObject, action[GoToActionArguments.S])
+ if action_type == "/GoTo":
+ dest = action[GoToActionArguments.D]
+ elif "/Dest" in node:
+ # Destination, PDFv1.7 Section 12.3.2
+ dest = node["/Dest"]
+ # if array was referenced in another object, will be a dict w/ key "/D"
+ if isinstance(dest, DictionaryObject) and "/D" in dest:
+ dest = dest["/D"]
+
+ if isinstance(dest, ArrayObject):
+ outline_item = self._build_destination(title, dest)
+ elif isinstance(dest, str):
+ # named destination, addresses NameObject Issue #193
+ # TODO : keep named destination instead of replacing it ?
+ try:
+ outline_item = self._build_destination(
+ title, self._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)
+
+ # if outline item created, add color, format, and child count if present
+ if outline_item:
+ if "/C" in node:
+ # Color of outline item font in (R, G, B) with values ranging 0.0-1.0
+ outline_item[NameObject("/C")] = ArrayObject(FloatObject(c) for c in node["/C"]) # type: ignore
+ if "/F" in node:
+ # specifies style characteristics bold and/or italic
+ # with 1=italic, 2=bold, 3=both
+ outline_item[NameObject("/F")] = node["/F"]
+ if "/Count" in node:
+ # absolute value = num. visible children
+ # with positive = open/unfolded, negative = closed/folded
+ outline_item[NameObject("/Count")] = node["/Count"]
+ # if count is 0 we will consider it as open ( in order to have always an is_open to simplify
+ outline_item[NameObject("/%is_open%")] = BooleanObject(
+ node.get("/Count", 0) >= 0
+ )
+ outline_item.node = node
+ try:
+ outline_item.indirect_reference = node.indirect_reference
+ except AttributeError:
+ pass
+ return outline_item
@property
- def pages(self) ->List[PageObject]:
+ def pages(self) -> List[PageObject]:
"""
Property that emulates a list of :class:`PageObject<pypdf._page.PageObject>`.
This property allows to get a page or a range of pages.
@@ -386,20 +1015,20 @@ class PdfDocCommon:
PdfWriter.
"""
- pass
+ return _VirtualList(self.get_num_pages, self.get_page) # type: ignore
@property
- def page_labels(self) ->List[str]:
+ def page_labels(self) -> List[str]:
"""
A list of labels for the pages in this document.
This property is read-only. The labels are in the order that the pages
appear in the document.
"""
- pass
+ return [page_index2page_label(self, i) for i in range(len(self.pages))]
@property
- def page_layout(self) ->Optional[str]:
+ def page_layout(self) -> Optional[str]:
"""
Get the page layout currently being used.
@@ -421,10 +1050,13 @@ class PdfDocCommon:
* - /TwoPageRight
- Show two pages at a time, odd-numbered pages on the right
"""
- pass
+ try:
+ return cast(NameObject, self.root_object[CD.PAGE_LAYOUT])
+ except KeyError:
+ return None
@property
- def page_mode(self) ->Optional[PagemodeType]:
+ def page_mode(self) -> Optional[PagemodeType]:
"""
Get the page mode currently being used.
@@ -444,10 +1076,70 @@ class PdfDocCommon:
* - /UseAttachments
- Show attachments panel
"""
- pass
-
- def remove_page(self, page: Union[int, PageObject, IndirectObject],
- clean: bool=False) ->None:
+ try:
+ return self.root_object["/PageMode"] # type: ignore
+ except KeyError:
+ return None
+
+ 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.root_object
+ pages = catalog["/Pages"].get_object() # type: ignore
+ assert isinstance(pages, DictionaryObject)
+ self.flattened_pages = []
+
+ if PA.TYPE in pages:
+ t = cast(str, pages[PA.TYPE])
+ # if pdf has no type, considered as a page if /Kids is missing
+ elif PA.KIDS not in pages:
+ t = "/Page"
+ else:
+ t = "/Pages"
+
+ if t == "/Pages":
+ for attr in inheritable_page_attributes:
+ if attr in pages:
+ inherit[attr] = pages[attr]
+ for page in cast(ArrayObject, pages[PA.KIDS]):
+ addt = {}
+ if isinstance(page, IndirectObject):
+ addt["indirect_reference"] = page
+ obj = page.get_object()
+ if obj:
+ # damaged file may have invalid child in /Pages
+ self._flatten(obj, 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 remove_page(
+ self,
+ page: Union[int, PageObject, IndirectObject],
+ clean: bool = False,
+ ) -> None:
"""
Remove page from pages list.
@@ -461,9 +1153,32 @@ class PdfDocCommon:
clean: replace PageObject with NullObject to prevent annotations
or destinations to reference a detached page.
"""
- pass
-
- def _get_indirect_object(self, num: int, gen: int) ->Optional[PdfObject]:
+ if self.flattened_pages is None:
+ self._flatten()
+ assert self.flattened_pages is not None
+ if isinstance(page, IndirectObject):
+ p = page.get_object()
+ if not isinstance(p, PageObject):
+ logger_warning("IndirectObject is not referencing a page", __name__)
+ return
+ page = p
+
+ if not isinstance(page, int):
+ try:
+ page = self.flattened_pages.index(page)
+ except ValueError:
+ logger_warning("Cannot find page in pages", __name__)
+ return
+ if not (0 <= page < len(self.flattened_pages)):
+ logger_warning("Page number is out of range", __name__)
+ return
+
+ ind = self.pages[page].indirect_reference
+ del self.pages[page]
+ if clean and ind is not None:
+ self._replace_object(ind, NullObject())
+
+ def _get_indirect_object(self, num: int, gen: int) -> Optional[PdfObject]:
"""
Used to ease development.
@@ -476,39 +1191,117 @@ class PdfDocCommon:
Returns:
A PdfObject
"""
- pass
+ return IndirectObject(num, gen, self).get_object()
- def decode_permissions(self, permissions_code: int) ->Dict[str, bool]:
+ def decode_permissions(
+ self, permissions_code: int
+ ) -> Dict[str, bool]: # pragma: no cover
"""Take the permissions as an integer, return the allowed access."""
- pass
+ deprecate_with_replacement(
+ old_name="decode_permissions",
+ new_name="user_access_permissions",
+ removed_in="5.0.0",
+ )
+
+ permissions_mapping = {
+ "print": UserAccessPermissions.PRINT,
+ "modify": UserAccessPermissions.MODIFY,
+ "copy": UserAccessPermissions.EXTRACT,
+ "annotations": UserAccessPermissions.ADD_OR_MODIFY,
+ "forms": UserAccessPermissions.FILL_FORM_FIELDS,
+ # Do not fix typo, as part of official, but deprecated API.
+ "accessability": UserAccessPermissions.EXTRACT_TEXT_AND_GRAPHICS,
+ "assemble": UserAccessPermissions.ASSEMBLE_DOC,
+ "print_high_quality": UserAccessPermissions.PRINT_TO_REPRESENTATION,
+ }
+
+ return {
+ key: permissions_code & flag != 0
+ for key, flag in permissions_mapping.items()
+ }
@property
- def user_access_permissions(self) ->Optional[UserAccessPermissions]:
+ def user_access_permissions(self) -> Optional[UserAccessPermissions]:
"""Get the user access permissions for encrypted documents. Returns None if not encrypted."""
- pass
+ if self._encryption is None:
+ return None
+ return UserAccessPermissions(self._encryption.P)
@property
@abstractmethod
- def is_encrypted(self) ->bool:
+ 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()<pypdf.PdfReader.decrypt>` method is called.
"""
- pass
+ ... # pragma: no cover
- def _list_attachments(self) ->List[str]:
+ @property
+ def xfa(self) -> Optional[Dict[str, Any]]:
+ tree: Optional[TreeObject] = None
+ retval: Dict[str, Any] = {}
+ catalog = self.root_object
+
+ if "/AcroForm" not in catalog or not catalog["/AcroForm"]:
+ return None
+
+ tree = cast(TreeObject, catalog["/AcroForm"])
+
+ if "/XFA" in tree:
+ fields = cast(ArrayObject, tree["/XFA"])
+ i = iter(fields)
+ for f in i:
+ tag = f
+ f = next(i)
+ if isinstance(f, IndirectObject):
+ field = cast(Optional[EncodedStreamObject], f.get_object())
+ if field:
+ es = zlib.decompress(b_(field._data))
+ retval[tag] = es
+ return retval
+
+ @property
+ def attachments(self) -> Mapping[str, List[bytes]]:
+ return LazyDict(
+ {
+ name: (self._get_attachment_list, name)
+ for name in self._list_attachments()
+ }
+ )
+
+ def _list_attachments(self) -> List[str]:
"""
Retrieves the list of filenames of file attachments.
Returns:
list of filenames
"""
- pass
-
- def _get_attachments(self, filename: Optional[str]=None) ->Dict[str,
- Union[bytes, List[bytes]]]:
+ catalog = self.root_object
+ # From the catalog get the embedded file names
+ try:
+ filenames = cast(
+ ArrayObject,
+ cast(
+ DictionaryObject,
+ cast(DictionaryObject, catalog["/Names"])["/EmbeddedFiles"],
+ )["/Names"],
+ )
+ except KeyError:
+ return []
+ attachments_names = [f for f in filenames if isinstance(f, str)]
+ return attachments_names
+
+ def _get_attachment_list(self, name: str) -> List[bytes]:
+ out = self._get_attachments(name)[name]
+ if isinstance(out, list):
+ return out
+ return [out]
+
+ def _get_attachments(
+ self, filename: Optional[str] = None
+ ) -> Dict[str, Union[bytes, List[bytes]]]:
"""
Retrieves all or selected file attachments of the PDF as a dictionary of file names
and the file data as a bytestring.
@@ -523,23 +1316,50 @@ class PdfDocCommon:
dictionary of filename -> Union[bytestring or List[ByteString]]
If the filename exists multiple times a list of the different versions will be provided.
"""
- pass
+ catalog = self.root_object
+ # From the catalog get the embedded file names
+ try:
+ filenames = cast(
+ ArrayObject,
+ cast(
+ DictionaryObject,
+ cast(DictionaryObject, catalog["/Names"])["/EmbeddedFiles"],
+ )["/Names"],
+ )
+ except KeyError:
+ return {}
+ attachments: Dict[str, Union[bytes, List[bytes]]] = {}
+ # Loop through attachments
+ for i in range(len(filenames)):
+ f = filenames[i]
+ if isinstance(f, str):
+ if filename is not None and f != filename:
+ continue
+ name = f
+ f_dict = filenames[i + 1].get_object()
+ f_data = f_dict["/EF"]["/F"].get_data()
+ if name in attachments:
+ if not isinstance(attachments[name], list):
+ attachments[name] = [attachments[name]] # type:ignore
+ attachments[name].append(f_data) # type:ignore
+ else:
+ attachments[name] = f_data
+ return attachments
class LazyDict(Mapping[Any, Any]):
-
- def __init__(self, *args: Any, **kw: Any) ->None:
+ def __init__(self, *args: Any, **kw: Any) -> None:
self._raw_dict = dict(*args, **kw)
- def __getitem__(self, key: str) ->Any:
+ def __getitem__(self, key: str) -> Any:
func, arg = self._raw_dict.__getitem__(key)
return func(arg)
- def __iter__(self) ->Iterator[Any]:
+ def __iter__(self) -> Iterator[Any]:
return iter(self._raw_dict)
- def __len__(self) ->int:
+ def __len__(self) -> int:
return len(self._raw_dict)
- def __str__(self) ->str:
- return f'LazyDict(keys={list(self.keys())})'
+ def __str__(self) -> str:
+ return f"LazyDict(keys={list(self.keys())})"
diff --git a/pypdf/_encryption.py b/pypdf/_encryption.py
index 515e35b7..5ddd8d0e 100644
--- a/pypdf/_encryption.py
+++ b/pypdf/_encryption.py
@@ -1,32 +1,134 @@
+# Copyright (c) 2022, exiledkingcc
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
import hashlib
import secrets
import struct
from enum import Enum, IntEnum
from typing import Any, Dict, Optional, Tuple, Union, cast
-from pypdf._crypt_providers import CryptAES, CryptBase, CryptIdentity, CryptRC4, aes_cbc_decrypt, aes_cbc_encrypt, aes_ecb_decrypt, aes_ecb_encrypt, rc4_decrypt, rc4_encrypt
+
+from pypdf._crypt_providers import (
+ CryptAES,
+ CryptBase,
+ CryptIdentity,
+ CryptRC4,
+ aes_cbc_decrypt,
+ aes_cbc_encrypt,
+ aes_ecb_decrypt,
+ aes_ecb_encrypt,
+ rc4_decrypt,
+ rc4_encrypt,
+)
+
from ._utils import b_, logger_warning
-from .generic import ArrayObject, ByteStringObject, DictionaryObject, NameObject, NumberObject, PdfObject, StreamObject, TextStringObject, create_string_object
+from .generic import (
+ ArrayObject,
+ ByteStringObject,
+ DictionaryObject,
+ NameObject,
+ NumberObject,
+ PdfObject,
+ StreamObject,
+ TextStringObject,
+ create_string_object,
+)
class CryptFilter:
-
- def __init__(self, stm_crypt: CryptBase, str_crypt: CryptBase, ef_crypt:
- CryptBase) ->None:
+ def __init__(
+ self,
+ stm_crypt: CryptBase,
+ str_crypt: CryptBase,
+ ef_crypt: CryptBase,
+ ) -> None:
self.stm_crypt = stm_crypt
self.str_crypt = str_crypt
self.ef_crypt = ef_crypt
+ def encrypt_object(self, obj: PdfObject) -> PdfObject:
+ if isinstance(obj, ByteStringObject):
+ data = self.str_crypt.encrypt(obj.original_bytes)
+ obj = ByteStringObject(data)
+ if isinstance(obj, TextStringObject):
+ data = self.str_crypt.encrypt(obj.get_encoded_bytes())
+ obj = ByteStringObject(data)
+ elif isinstance(obj, StreamObject):
+ obj2 = StreamObject()
+ obj2.update(obj)
+ obj2.set_data(self.stm_crypt.encrypt(b_(obj._data)))
+ for key, value in obj.items(): # Dont forget the Stream dict.
+ obj2[key] = self.encrypt_object(value)
+ obj = obj2
+ elif isinstance(obj, DictionaryObject):
+ obj2 = DictionaryObject() # type: ignore
+ for key, value in obj.items():
+ obj2[key] = self.encrypt_object(value)
+ obj = obj2
+ elif isinstance(obj, ArrayObject):
+ obj = ArrayObject(self.encrypt_object(x) for x in obj)
+ return obj
+
+ def decrypt_object(self, obj: PdfObject) -> PdfObject:
+ if isinstance(obj, (ByteStringObject, TextStringObject)):
+ data = self.str_crypt.decrypt(obj.original_bytes)
+ obj = create_string_object(data)
+ elif isinstance(obj, StreamObject):
+ obj._data = self.stm_crypt.decrypt(b_(obj._data))
+ for key, value in obj.items(): # Dont forget the Stream dict.
+ obj[key] = self.decrypt_object(value)
+ elif isinstance(obj, DictionaryObject):
+ for key, value in obj.items():
+ obj[key] = self.decrypt_object(value)
+ elif isinstance(obj, ArrayObject):
+ for i in range(len(obj)):
+ obj[i] = self.decrypt_object(obj[i])
+ return obj
+
_PADDING = (
- b'(\xbfN^Nu\x8aAd\x00NV\xff\xfa\x01\x08..\x00\xb6\xd0h>\x80/\x0c\xa9\xfedSiz'
- )
+ b"\x28\xbf\x4e\x5e\x4e\x75\x8a\x41\x64\x00\x4e\x56\xff\xfa\x01\x08"
+ b"\x2e\x2e\x00\xb6\xd0\x68\x3e\x80\x2f\x0c\xa9\xfe\x64\x53\x69\x7a"
+)
-class AlgV4:
+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:
+ 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.
@@ -87,11 +189,22 @@ class AlgV4:
Returns:
The u_hash digest of length key_size
"""
- pass
+ 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 not metadata_encrypted:
+ u_hash.update(b"\xff\xff\xff\xff")
+ u_hash_digest = u_hash.digest()
+ length = key_size // 8
+ if rev >= 3:
+ for _ in range(50):
+ u_hash_digest = hashlib.md5(u_hash_digest[:length]).digest()
+ return u_hash_digest[:length]
@staticmethod
- def compute_O_value_key(owner_password: bytes, rev: int, key_size: int
- ) ->bytes:
+ 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.
@@ -131,11 +244,18 @@ class AlgV4:
Returns:
The RC4 key
"""
- pass
+ 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:
+ def compute_O_value(rc4_key: bytes, user_password: bytes, rev: int) -> bytes:
"""
See :func:`compute_O_value_key`.
@@ -147,10 +267,16 @@ class AlgV4:
Returns:
The RC4 encrypted
"""
- pass
+ 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:
+ def compute_U_value(key: bytes, rev: int, id1_entry: bytes) -> bytes:
"""
Algorithm 4: Computing the encryption dictionary’s U (user password) value.
@@ -172,12 +298,54 @@ class AlgV4:
Returns:
The value
"""
- pass
+ 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:
+ 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.
@@ -214,12 +382,28 @@ class AlgV4:
Returns:
The key
"""
- pass
+ 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:
+ 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.
@@ -260,14 +444,32 @@ class AlgV4:
Returns:
bytes
"""
- pass
+ 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:
+ 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.
@@ -325,11 +527,21 @@ class AlgV5:
Returns:
The key
"""
- pass
+ 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:
+ def verify_user_password(
+ R: int, password: bytes, u_value: bytes, ue_value: bytes
+ ) -> bytes:
"""
See :func:`verify_owner_password`.
@@ -345,11 +557,38 @@ class AlgV5:
Returns:
bytes
"""
- pass
+ 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:
+ def verify_perms(
+ key: bytes, perms: bytes, p: int, metadata_encrypted: bool
+ ) -> bool:
"""
See :func:`verify_owner_password` and :func:`compute_perms_value`.
@@ -367,11 +606,35 @@ class AlgV5:
Returns:
A boolean
"""
- pass
+ 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 compute_U_value(R: int, password: bytes, key: bytes) ->Tuple[bytes,
- bytes]:
+ def generate_values(
+ R: int,
+ user_password: bytes,
+ owner_password: bytes,
+ key: bytes,
+ p: int,
+ metadata_encrypted: bool,
+ ) -> Dict[Any, Any]:
+ user_password = user_password[:127]
+ owner_password = owner_password[:127]
+ u_value, ue_value = AlgV5.compute_U_value(R, user_password, key)
+ o_value, oe_value = AlgV5.compute_O_value(R, owner_password, key, u_value)
+ perms = AlgV5.compute_Perms_value(key, p, metadata_encrypted)
+ return {
+ "/U": u_value,
+ "/UE": ue_value,
+ "/O": o_value,
+ "/OE": oe_value,
+ "/Perms": perms,
+ }
+
+ @staticmethod
+ def compute_U_value(R: int, password: bytes, key: bytes) -> Tuple[bytes, bytes]:
"""
Algorithm 3.8 Computing the encryption dictionary’s U (user password)
and UE (user encryption key) values.
@@ -396,11 +659,20 @@ class AlgV5:
Returns:
A tuple (u-value, ue value)
"""
- pass
+ random_bytes = secrets.token_bytes(16)
+ val_salt = random_bytes[:8]
+ key_salt = random_bytes[8:]
+ u_value = AlgV5.calculate_hash(R, password, val_salt, b"") + val_salt + key_salt
+
+ tmp_key = AlgV5.calculate_hash(R, password, key_salt, b"")
+ iv = bytes(0 for _ in range(16))
+ ue_value = aes_cbc_encrypt(tmp_key, iv, key)
+ return u_value, ue_value
@staticmethod
- def compute_O_value(R: int, password: bytes, key: bytes, u_value: bytes
- ) ->Tuple[bytes, bytes]:
+ def compute_O_value(
+ R: int, password: bytes, key: bytes, u_value: bytes
+ ) -> Tuple[bytes, bytes]:
"""
Algorithm 3.9 Computing the encryption dictionary’s O (owner password)
and OE (owner encryption key) values.
@@ -431,11 +703,19 @@ class AlgV5:
Returns:
A tuple (O value, OE value)
"""
- pass
+ random_bytes = secrets.token_bytes(16)
+ val_salt = random_bytes[:8]
+ key_salt = random_bytes[8:]
+ o_value = (
+ AlgV5.calculate_hash(R, password, val_salt, u_value) + val_salt + key_salt
+ )
+ tmp_key = AlgV5.calculate_hash(R, password, key_salt, u_value[:48])
+ iv = bytes(0 for _ in range(16))
+ oe_value = aes_cbc_encrypt(tmp_key, iv, key)
+ return o_value, oe_value
@staticmethod
- def compute_Perms_value(key: bytes, p: int, metadata_encrypted: bool
- ) ->bytes:
+ def compute_Perms_value(key: bytes, p: int, metadata_encrypted: bool) -> bytes:
"""
Algorithm 3.10 Computing the encryption dictionary’s Perms
(permissions) value.
@@ -466,7 +746,11 @@ class AlgV5:
Returns:
The perms value
"""
- pass
+ b8 = b"T" if metadata_encrypted else b"F"
+ rr = secrets.token_bytes(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):
@@ -475,16 +759,17 @@ class PasswordType(IntEnum):
OWNER_PASSWORD = 2
-class EncryptAlgorithm(tuple, Enum):
- RC4_40 = 1, 2, 40
- RC4_128 = 2, 3, 128
- AES_128 = 4, 4, 128
- AES_256_R5 = 5, 5, 256
- AES_256 = 5, 6, 256
+class EncryptAlgorithm(tuple, Enum): # type: ignore # noqa: SLOT001
+ # V, R, Length
+ RC4_40 = (1, 2, 40)
+ RC4_128 = (2, 3, 128)
+ AES_128 = (4, 4, 128)
+ AES_256_R5 = (5, 5, 256)
+ AES_256 = (5, 6, 256)
class EncryptionValues:
- O: bytes
+ O: bytes # noqa
U: bytes
OE: bytes
UE: bytes
@@ -515,25 +800,69 @@ class Encryption:
values: Additional encryption parameters.
"""
- def __init__(self, V: int, R: int, Length: int, P: int, entry:
- DictionaryObject, EncryptMetadata: bool, first_id_entry: bytes,
- StmF: str, StrF: str, EFF: str, values: Optional[EncryptionValues]
- ) ->None:
+ def __init__(
+ self,
+ V: int,
+ R: int,
+ Length: int,
+ P: int,
+ entry: DictionaryObject,
+ EncryptMetadata: bool,
+ first_id_entry: bytes,
+ StmF: str,
+ StrF: str,
+ EFF: str,
+ values: Optional[EncryptionValues],
+ ) -> None:
+ # §7.6.2, entries common to all encryption dictionaries
+ # use same name as keys of encryption dictionaries entries
self.V = V
self.R = R
- self.Length = Length
- self.P = (P + 4294967296) % 4294967296
+ self.Length = Length # key_size
+ self.P = (P + 0x100000000) % 0x100000000 # maybe P < 0
self.EncryptMetadata = EncryptMetadata
self.id1_entry = first_id_entry
self.StmF = StmF
self.StrF = StrF
self.EFF = EFF
- self.values: EncryptionValues = values if values else EncryptionValues(
- )
+ self.values: EncryptionValues = values if values else EncryptionValues()
+
self._password_type = PasswordType.NOT_DECRYPTED
self._key: Optional[bytes] = None
- def _make_crypt_filter(self, idnum: int, generation: int) ->CryptFilter:
+ def is_decrypted(self) -> bool:
+ return self._password_type != PasswordType.NOT_DECRYPTED
+
+ def encrypt_object(self, obj: PdfObject, idnum: int, generation: int) -> PdfObject:
+ # skip calculate key
+ if not self._is_encryption_object(obj):
+ return obj
+
+ cf = self._make_crypt_filter(idnum, generation)
+ return cf.encrypt_object(obj)
+
+ def decrypt_object(self, obj: PdfObject, idnum: int, generation: int) -> PdfObject:
+ # skip calculate key
+ if not self._is_encryption_object(obj):
+ return obj
+
+ cf = self._make_crypt_filter(idnum, generation)
+ return cf.decrypt_object(obj)
+
+ @staticmethod
+ def _is_encryption_object(obj: PdfObject) -> bool:
+ return isinstance(
+ obj,
+ (
+ ByteStringObject,
+ TextStringObject,
+ StreamObject,
+ ArrayObject,
+ DictionaryObject,
+ ),
+ )
+
+ def _make_crypt_filter(self, idnum: int, generation: int) -> CryptFilter:
"""
Algorithm 1: Encryption of data using the RC4 or AES algorithms.
@@ -573,4 +902,267 @@ class Encryption:
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.
"""
- pass
+ pack1 = struct.pack("<i", idnum)[:3]
+ pack2 = struct.pack("<i", generation)[:2]
+
+ assert self._key
+ key = self._key
+ n = 5 if self.V == 1 else self.Length // 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
+
+ stm_crypt = self._get_crypt(self.StmF, rc4_key, aes128_key, aes256_key)
+ str_crypt = self._get_crypt(self.StrF, rc4_key, aes128_key, aes256_key)
+ ef_crypt = self._get_crypt(self.EFF, rc4_key, aes128_key, aes256_key)
+
+ return CryptFilter(stm_crypt, str_crypt, ef_crypt)
+
+ @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)
+
+ @staticmethod
+ def _encode_password(password: Union[bytes, str]) -> bytes:
+ if isinstance(password, str):
+ try:
+ pwd = password.encode("latin-1")
+ except Exception:
+ pwd = password.encode("utf-8")
+ else:
+ pwd = password
+ return pwd
+
+ def verify(self, password: Union[bytes, str]) -> PasswordType:
+ pwd = self._encode_password(password)
+ key, rc = self.verify_v4(pwd) if self.V <= 4 else self.verify_v5(pwd)
+ if rc != PasswordType.NOT_DECRYPTED:
+ self._password_type = rc
+ self._key = key
+ return rc
+
+ def verify_v4(self, password: bytes) -> Tuple[bytes, PasswordType]:
+ # verify owner password first
+ key = AlgV4.verify_owner_password(
+ password,
+ self.R,
+ self.Length,
+ self.values.O,
+ self.values.U,
+ self.P,
+ self.id1_entry,
+ self.EncryptMetadata,
+ )
+ if key:
+ return key, PasswordType.OWNER_PASSWORD
+ key = AlgV4.verify_user_password(
+ password,
+ self.R,
+ self.Length,
+ self.values.O,
+ self.values.U,
+ self.P,
+ self.id1_entry,
+ self.EncryptMetadata,
+ )
+ if key:
+ return key, PasswordType.USER_PASSWORD
+ return b"", PasswordType.NOT_DECRYPTED
+
+ def verify_v5(self, password: bytes) -> Tuple[bytes, PasswordType]:
+ # TODO: use SASLprep process
+ # verify owner password first
+ key = AlgV5.verify_owner_password(
+ self.R, password, self.values.O, self.values.OE, self.values.U
+ )
+ rc = PasswordType.OWNER_PASSWORD
+ if not key:
+ key = AlgV5.verify_user_password(
+ self.R, password, self.values.U, self.values.UE
+ )
+ rc = PasswordType.USER_PASSWORD
+ if not key:
+ return b"", PasswordType.NOT_DECRYPTED
+
+ # verify Perms
+ if not AlgV5.verify_perms(key, self.values.Perms, self.P, self.EncryptMetadata):
+ logger_warning("ignore '/Perms' verify failed", __name__)
+ return key, rc
+
+ def write_entry(
+ self, user_password: str, owner_password: Optional[str]
+ ) -> DictionaryObject:
+ user_pwd = self._encode_password(user_password)
+ owner_pwd = self._encode_password(owner_password) if owner_password else None
+ if owner_pwd is None:
+ owner_pwd = user_pwd
+
+ if self.V <= 4:
+ self.compute_values_v4(user_pwd, owner_pwd)
+ else:
+ self._key = secrets.token_bytes(self.Length // 8)
+ values = AlgV5.generate_values(
+ self.R, user_pwd, owner_pwd, self._key, self.P, self.EncryptMetadata
+ )
+ self.values.O = values["/O"]
+ self.values.U = values["/U"]
+ self.values.OE = values["/OE"]
+ self.values.UE = values["/UE"]
+ self.values.Perms = values["/Perms"]
+
+ dict_obj = DictionaryObject()
+ dict_obj[NameObject("/V")] = NumberObject(self.V)
+ dict_obj[NameObject("/R")] = NumberObject(self.R)
+ dict_obj[NameObject("/Length")] = NumberObject(self.Length)
+ dict_obj[NameObject("/P")] = NumberObject(self.P)
+ dict_obj[NameObject("/Filter")] = NameObject("/Standard")
+ # ignore /EncryptMetadata
+
+ dict_obj[NameObject("/O")] = ByteStringObject(self.values.O)
+ dict_obj[NameObject("/U")] = ByteStringObject(self.values.U)
+
+ if self.V >= 4:
+ # TODO: allow different method
+ std_cf = DictionaryObject()
+ std_cf[NameObject("/AuthEvent")] = NameObject("/DocOpen")
+ std_cf[NameObject("/CFM")] = NameObject(self.StmF)
+ std_cf[NameObject("/Length")] = NumberObject(self.Length // 8)
+ cf = DictionaryObject()
+ cf[NameObject("/StdCF")] = std_cf
+ dict_obj[NameObject("/CF")] = cf
+ dict_obj[NameObject("/StmF")] = NameObject("/StdCF")
+ dict_obj[NameObject("/StrF")] = NameObject("/StdCF")
+ # ignore EFF
+ # dict_obj[NameObject("/EFF")] = NameObject("/StdCF")
+
+ if self.V >= 5:
+ dict_obj[NameObject("/OE")] = ByteStringObject(self.values.OE)
+ dict_obj[NameObject("/UE")] = ByteStringObject(self.values.UE)
+ dict_obj[NameObject("/Perms")] = ByteStringObject(self.values.Perms)
+ return dict_obj
+
+ def compute_values_v4(self, user_password: bytes, owner_password: bytes) -> None:
+ rc4_key = AlgV4.compute_O_value_key(owner_password, self.R, self.Length)
+ o_value = AlgV4.compute_O_value(rc4_key, user_password, self.R)
+
+ key = AlgV4.compute_key(
+ user_password,
+ self.R,
+ self.Length,
+ o_value,
+ self.P,
+ self.id1_entry,
+ self.EncryptMetadata,
+ )
+ u_value = AlgV4.compute_U_value(key, self.R, self.id1_entry)
+
+ self._key = key
+ self.values.O = o_value
+ self.values.U = u_value
+
+ @staticmethod
+ def read(encryption_entry: DictionaryObject, first_id_entry: bytes) -> "Encryption":
+ if encryption_entry.get("/Filter") != "/Standard":
+ raise NotImplementedError(
+ "only Standard PDF encryption handler is available"
+ )
+ if "/SubFilter" in encryption_entry:
+ raise NotImplementedError("/SubFilter NOT supported")
+
+ stm_filter = "/V2"
+ str_filter = "/V2"
+ ef_filter = "/V2"
+
+ alg_ver = encryption_entry.get("/V", 0)
+ if alg_ver not in (1, 2, 3, 4, 5):
+ raise NotImplementedError(f"Encryption V={alg_ver} NOT supported")
+ if alg_ver >= 4:
+ filters = encryption_entry["/CF"]
+
+ stm_filter = encryption_entry.get("/StmF", "/Identity")
+ str_filter = encryption_entry.get("/StrF", "/Identity")
+ ef_filter = encryption_entry.get("/EFF", stm_filter)
+
+ if stm_filter != "/Identity":
+ stm_filter = filters[stm_filter]["/CFM"] # type: ignore
+ if str_filter != "/Identity":
+ str_filter = filters[str_filter]["/CFM"] # type: ignore
+ if ef_filter != "/Identity":
+ ef_filter = filters[ef_filter]["/CFM"] # type: ignore
+
+ allowed_methods = ("/Identity", "/V2", "/AESV2", "/AESV3")
+ if stm_filter not in allowed_methods:
+ raise NotImplementedError(f"StmF Method {stm_filter} NOT supported!")
+ if str_filter not in allowed_methods:
+ raise NotImplementedError(f"StrF Method {str_filter} NOT supported!")
+ if ef_filter not in allowed_methods:
+ raise NotImplementedError(f"EFF Method {ef_filter} NOT supported!")
+
+ alg_rev = cast(int, encryption_entry["/R"])
+ perm_flags = cast(int, encryption_entry["/P"])
+ key_bits = encryption_entry.get("/Length", 40)
+ encrypt_metadata = encryption_entry.get("/EncryptMetadata")
+ encrypt_metadata = (
+ encrypt_metadata.value if encrypt_metadata is not None else True
+ )
+ values = EncryptionValues()
+ values.O = cast(ByteStringObject, encryption_entry["/O"]).original_bytes
+ values.U = cast(ByteStringObject, encryption_entry["/U"]).original_bytes
+ values.OE = encryption_entry.get("/OE", ByteStringObject()).original_bytes
+ values.UE = encryption_entry.get("/UE", ByteStringObject()).original_bytes
+ values.Perms = encryption_entry.get("/Perms", ByteStringObject()).original_bytes
+ return Encryption(
+ V=alg_ver,
+ R=alg_rev,
+ Length=key_bits,
+ P=perm_flags,
+ EncryptMetadata=encrypt_metadata,
+ first_id_entry=first_id_entry,
+ values=values,
+ StrF=str_filter,
+ StmF=stm_filter,
+ EFF=ef_filter,
+ entry=encryption_entry, # Dummy entry for the moment; will get removed
+ )
+
+ @staticmethod
+ def make(
+ alg: EncryptAlgorithm, permissions: int, first_id_entry: bytes
+ ) -> "Encryption":
+ alg_ver, alg_rev, key_bits = alg
+
+ stm_filter, str_filter, ef_filter = "/V2", "/V2", "/V2"
+
+ if alg == EncryptAlgorithm.AES_128:
+ stm_filter, str_filter, ef_filter = "/AESV2", "/AESV2", "/AESV2"
+ elif alg in (EncryptAlgorithm.AES_256_R5, EncryptAlgorithm.AES_256):
+ stm_filter, str_filter, ef_filter = "/AESV3", "/AESV3", "/AESV3"
+
+ return Encryption(
+ V=alg_ver,
+ R=alg_rev,
+ Length=key_bits,
+ P=permissions,
+ EncryptMetadata=True,
+ first_id_entry=first_id_entry,
+ values=None,
+ StrF=str_filter,
+ StmF=stm_filter,
+ EFF=ef_filter,
+ entry=DictionaryObject(), # Dummy entry for the moment; will get removed
+ )
diff --git a/pypdf/_merger.py b/pypdf/_merger.py
index db1073fd..7176a1ad 100644
--- a/pypdf/_merger.py
+++ b/pypdf/_merger.py
@@ -1,25 +1,81 @@
+# Copyright (c) 2006, Mathieu Fenniak
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
from 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 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, deprecate_with_replacement, str_
+from ._utils import (
+ StrByteType,
+ deprecate_with_replacement,
+ str_,
+)
from ._writer import PdfWriter
from .constants import GoToActionArguments, TypArguments, TypFitArguments
from .constants import PagesAttributes as PA
-from .generic import PAGE_FIT, ArrayObject, Destination, DictionaryObject, Fit, FloatObject, IndirectObject, NameObject, NullObject, NumberObject, OutlineItem, TextStringObject, TreeObject
+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 LayoutType, OutlineType, PagemodeType
-ERR_CLOSED_WRITER = (
- 'close() was called and thus the writer cannot be used anymore')
+
+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:
+ def __init__(self, pagedata: PageObject, src: PdfReader, id: int) -> None:
self.src = src
self.pagedata = pagedata
self.out_pagedata = None
@@ -33,9 +89,10 @@ class PdfMerger:
.. deprecated:: 5.0.0
"""
- def __init__(self, strict: bool=False, fileobj: Union[Path, StrByteType]=''
- ) ->None:
- deprecate_with_replacement('PdfMerger', 'PdfWriter', '5.0.0')
+ def __init__(
+ self, strict: bool = False, fileobj: Union[Path, StrByteType] = ""
+ ) -> None:
+ deprecate_with_replacement("PdfMerger", "PdfWriter", "5.0.0")
self.inputs: List[Tuple[Any, PdfReader]] = []
self.pages: List[Any] = []
self.output: Optional[PdfWriter] = PdfWriter()
@@ -45,20 +102,30 @@ class PdfMerger:
self.fileobj = fileobj
self.strict = strict
- def __enter__(self) ->'PdfMerger':
- deprecate_with_replacement('PdfMerger', 'PdfWriter', '5.0.0')
+ def __enter__(self) -> "PdfMerger":
+ # There is nothing to do.
+ deprecate_with_replacement("PdfMerger", "PdfWriter", "5.0.0")
return self
- def __exit__(self, exc_type: Optional[Type[BaseException]], exc:
- Optional[BaseException], traceback: Optional[TracebackType]) ->None:
+ 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()
- def merge(self, page_number: int, fileobj: Union[Path, StrByteType,
- PdfReader], outline_item: Optional[str]=None, pages: Optional[
- PageRangeSpec]=None, import_outline: bool=True) ->None:
+ def merge(
+ self,
+ page_number: int,
+ fileobj: Union[Path, StrByteType, PdfReader],
+ outline_item: Optional[str] = None,
+ pages: Optional[PageRangeSpec] = None,
+ import_outline: bool = True,
+ ) -> None:
"""
Merge the pages from the given file into the output file at the
specified page number.
@@ -81,12 +148,107 @@ class PdfMerger:
outline (collection of outline items, previously referred to as
'bookmarks') from being imported by specifying this as ``False``.
"""
- pass
-
- 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:
+ 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)
+ file_content = fileobj.read()
+ stream = BytesIO(file_content)
+ 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: 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
@@ -108,9 +270,9 @@ class PdfMerger:
outline (collection of outline items, previously referred to as
'bookmarks') from being imported by specifying this as ``False``.
"""
- pass
+ self.merge(len(self.pages), fileobj, outline_item, pages, import_outline)
- def write(self, fileobj: Union[Path, StrByteType]) ->None:
+ def write(self, fileobj: Union[Path, StrByteType]) -> None:
"""
Write all data that has been merged to the given output file.
@@ -118,13 +280,39 @@ class PdfMerger:
fileobj: Output file. Can be a filename or any kind of
file-like object.
"""
- pass
-
- def close(self) ->None:
+ 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()
+ )
+
+ # 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."""
- pass
+ self.pages = []
+ for file_descriptor, _reader in self.inputs:
+ file_descriptor.close()
- def add_metadata(self, infos: Dict[str, Any]) ->None:
+ self.inputs = []
+ self.output = None
+
+ def add_metadata(self, infos: Dict[str, Any]) -> None:
"""
Add custom metadata to the output.
@@ -133,9 +321,11 @@ class PdfMerger:
and each value is your new metadata.
An example is ``{'/Title': 'My title'}``
"""
- pass
+ if self.output is None:
+ raise RuntimeError(ERR_CLOSED_WRITER)
+ self.output.add_metadata(infos)
- def set_page_layout(self, layout: LayoutType) ->None:
+ def set_page_layout(self, layout: LayoutType) -> None:
"""
Set the page layout.
@@ -160,9 +350,11 @@ class PdfMerger:
* - /TwoPageRight
- Show two pages at a time, odd-numbered pages on the right
"""
- pass
+ if self.output is None:
+ raise RuntimeError(ERR_CLOSED_WRITER)
+ self.output._set_page_layout(layout)
- def set_page_mode(self, mode: PagemodeType) ->None:
+ def set_page_mode(self, mode: PagemodeType) -> None:
"""
Set the page mode.
@@ -185,10 +377,10 @@ class PdfMerger:
* - /UseAttachments
- Show attachments panel
"""
- pass
+ self.page_mode = mode
@property
- def page_mode(self) ->Optional[PagemodeType]:
+ def page_mode(self) -> Optional[PagemodeType]:
"""
Set the page mode.
@@ -211,11 +403,22 @@ class PdfMerger:
* - /UseAttachments
- Show attachments panel
"""
- pass
-
- 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]]:
+ if self.output is None:
+ raise RuntimeError(ERR_CLOSED_WRITER)
+ return self.output.page_mode
+
+ @page_mode.setter
+ def page_mode(self, mode: PagemodeType) -> None:
+ if self.output is None:
+ raise RuntimeError(ERR_CLOSED_WRITER)
+ self.output.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.
@@ -224,10 +427,23 @@ class PdfMerger:
dests:
pages:
"""
- pass
-
- def _trim_outline(self, pdf: PdfReader, outline: OutlineType, pages:
- Union[Tuple[int, int], Tuple[int, int, int], List[int]]) ->OutlineType:
+ 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.
@@ -239,12 +455,181 @@ class PdfMerger:
Returns:
An outline type
"""
- pass
-
- def add_outline_item(self, title: str, page_number: int, parent: Union[
- None, TreeObject, IndirectObject]=None, color: Optional[Tuple[float,
- float, float]]=None, bold: bool=False, italic: bool=False, fit: Fit
- =PAGE_FIT) ->IndirectObject:
+ 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:
+ page_index = None
+ if "/Page" in named_dest: # deprecated
+ for page_index, page in enumerate(self.pages): # noqa: B007
+ if page.id == named_dest["/Page"]:
+ named_dest[NameObject("/Page")] = page.out_pagedata
+ break
+
+ if page_index is not None: # deprecated
+ self.output.add_named_destination_object(named_dest)
+
+ 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)
+
+ 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, ()):
+ 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:
+ page_index = None
+ np = named_dest["/Page"]
+
+ if isinstance(np, NumberObject):
+ continue
+
+ for page in pages:
+ if np.get_object() == page.pagedata.get_object():
+ page_index = page.id
+
+ if page_index is None: # deprecated
+ raise ValueError(
+ f"Unresolved named destination '{named_dest['/Title']}'"
+ )
+ named_dest[NameObject("/Page")] = NumberObject(page_index)
+
+ 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
+
+ page_index = 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():
+ page_index = p.id
+
+ if page_index is not None:
+ outline_item[NameObject("/Page")] = NumberObject(page_index)
+
+ 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: # deprecated
+ 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
+
+ def add_outline_item(
+ self,
+ title: str,
+ page_number: int,
+ parent: Union[None, TreeObject, IndirectObject] = None,
+ color: Optional[Tuple[float, float, float]] = None,
+ bold: bool = False,
+ italic: bool = False,
+ fit: Fit = PAGE_FIT,
+ ) -> IndirectObject:
"""
Add an outline item (commonly referred to as a "Bookmark") to this PDF file.
@@ -259,9 +644,25 @@ class PdfMerger:
italic: Outline item font is italic
fit: The fit of the destination page.
"""
- pass
-
- def add_named_destination(self, title: str, page_number: int) ->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 add_named_destination(
+ self,
+ title: str,
+ page_number: int,
+ ) -> None:
"""
Add a destination to the output.
@@ -269,4 +670,9 @@ class PdfMerger:
title: Title to use
page_number: Page number this destination points at.
"""
- pass
+ dest = Destination(
+ TextStringObject(title),
+ NumberObject(page_number),
+ Fit.fit_horizontally(top=826),
+ )
+ self.named_dests.append(dest)
diff --git a/pypdf/_page.py b/pypdf/_page.py
index 9d11d1c7..63038d9d 100644
--- a/pypdf/_page.py
+++ b/pypdf/_page.py
@@ -1,24 +1,130 @@
+# 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 sys
from decimal import Decimal
from pathlib import Path
-from typing import Any, Callable, Dict, Iterable, Iterator, List, Optional, Sequence, Set, Tuple, Union, cast, overload
+from typing import (
+ Any,
+ Callable,
+ Dict,
+ Iterable,
+ Iterator,
+ List,
+ Optional,
+ Sequence,
+ Set,
+ Tuple,
+ Union,
+ cast,
+ overload,
+)
+
from ._cmap import build_char_map, unknown_char_map
from ._protocols import PdfCommonDocProtocol
-from ._text_extraction import OrientationNotFoundError, _layout_mode, crlf_space_check, handle_tj, mult
-from ._utils import CompressedTransformationMatrix, File, ImageFile, TransformationMatrixType, logger_warning, matrix_multiply
+from ._text_extraction import (
+ OrientationNotFoundError,
+ _layout_mode,
+ crlf_space_check,
+ handle_tj,
+ mult,
+)
+from ._utils import (
+ CompressedTransformationMatrix,
+ File,
+ ImageFile,
+ TransformationMatrixType,
+ logger_warning,
+ matrix_multiply,
+)
from .constants import AnnotationDictionaryAttributes as ADA
from .constants import ImageAttributes as IA
from .constants import PageAttributes as PG
from .constants import Resources as RES
from .errors import PageSizeNotDefinedError, PdfReadError
from .filters import _xobj_to_image
-from .generic import ArrayObject, ContentStream, DictionaryObject, EncodedStreamObject, FloatObject, IndirectObject, NameObject, NullObject, NumberObject, PdfObject, RectangleObject, StreamObject
+from .generic import (
+ ArrayObject,
+ ContentStream,
+ DictionaryObject,
+ EncodedStreamObject,
+ FloatObject,
+ IndirectObject,
+ NameObject,
+ NullObject,
+ NumberObject,
+ PdfObject,
+ RectangleObject,
+ StreamObject,
+)
+
if sys.version_info >= (3, 8):
from typing import Literal
else:
from typing_extensions import Literal
-MERGE_CROP_BOX = 'cropbox'
+
+
+MERGE_CROP_BOX = "cropbox" # pypdf<=3.4.0 used 'trimbox'
+
+
+def _get_rectangle(self: Any, name: str, defaults: Iterable[str]) -> RectangleObject:
+ retval: Union[None, RectangleObject, IndirectObject] = self.get(name)
+ if isinstance(retval, RectangleObject):
+ return retval
+ if 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 _set_rectangle(self: Any, name: str, value: Union[RectangleObject, float]) -> None:
+ name = NameObject(name)
+ self[name] = value
+
+
+def _delete_rectangle(self: Any, name: str) -> None:
+ del self[name]
+
+
+def _create_rectangle_accessor(name: str, fallback: Iterable[str]) -> property:
+ return property(
+ lambda self: _get_rectangle(self, name, fallback),
+ lambda self, value: _set_rectangle(self, name, value),
+ lambda self: _delete_rectangle(self, name),
+ )
class Transformation:
@@ -48,21 +154,26 @@ class Transformation:
>>> page.add_transformation(op)
"""
- def __init__(self, ctm: CompressedTransformationMatrix=(1, 0, 0, 1, 0, 0)):
+ # 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:
+ 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))
"""
- pass
+ 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:
+ def compress(matrix: TransformationMatrixType) -> CompressedTransformationMatrix:
"""
Compresses the transformation matrix into a tuple of (a, b, c, d, e, f).
@@ -72,9 +183,16 @@ class Transformation:
Returns:
A tuple representing the transformation matrix as (a, b, c, d, e, f)
"""
- pass
+ return (
+ matrix[0][0],
+ matrix[0][1],
+ matrix[1][0],
+ matrix[1][1],
+ matrix[2][0],
+ matrix[2][1],
+ )
- def transform(self, m: 'Transformation') ->'Transformation':
+ def transform(self, m: "Transformation") -> "Transformation":
"""
Apply one transformation to another.
@@ -90,9 +208,10 @@ class Transformation:
>>> op = Transformation().transform(Transformation((-1, 0, 0, 1, iwidth, 0))) # horizontal mirror
>>> page.add_transformation(op)
"""
- pass
+ ctm = Transformation.compress(matrix_multiply(self.matrix, m.matrix))
+ return Transformation(ctm)
- def translate(self, tx: float=0, ty: float=0) ->'Transformation':
+ def translate(self, tx: float = 0, ty: float = 0) -> "Transformation":
"""
Translate the contents of a page.
@@ -103,10 +222,12 @@ class Transformation:
Returns:
A new ``Transformation`` instance
"""
- pass
+ 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':
+ 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.
@@ -120,9 +241,19 @@ class Transformation:
Returns:
A new Transformation instance with the scaled matrix.
"""
- pass
+ 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':
+ def rotate(self, rotation: float) -> "Transformation":
"""
Rotate the contents of a page.
@@ -132,13 +263,33 @@ class Transformation:
Returns:
A new ``Transformation`` instance with the rotated matrix.
"""
- pass
+ 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 __repr__(self) ->str:
- return f'Transformation(ctm={self.ctm})'
+ @overload
+ def apply_on(self, pt: List[float], as_object: bool = False) -> List[float]:
+ ...
- def apply_on(self, pt: Union[Tuple[float, float], List[float]],
- as_object: bool=False) ->Union[Tuple[float, float], List[float]]:
+ @overload
+ def apply_on(
+ self, pt: Tuple[float, float], as_object: bool = False
+ ) -> Tuple[float, float]:
+ ...
+
+ def apply_on(
+ self,
+ pt: Union[Tuple[float, float], List[float]],
+ as_object: bool = False,
+ ) -> Union[Tuple[float, float], List[float]]:
"""
Apply the transformation matrix on the given point.
@@ -148,7 +299,12 @@ class Transformation:
Returns:
A tuple or list representing the transformed point in the form (x', y')
"""
- pass
+ typ = FloatObject if as_object else float
+ pt1 = (
+ typ(float(pt[0]) * self.ctm[0] + float(pt[1]) * self.ctm[2] + self.ctm[4]),
+ typ(float(pt[0]) * self.ctm[1] + float(pt[1]) * self.ctm[3] + self.ctm[5]),
+ )
+ return list(pt1) if isinstance(pt, list) else pt1
class PageObject(DictionaryObject):
@@ -166,17 +322,27 @@ class PageObject(DictionaryObject):
indirect_reference: Stores the original indirect reference to
this object in its source PDF
"""
- original_page: 'PageObject'
- def __init__(self, pdf: Optional[PdfCommonDocProtocol]=None,
- indirect_reference: Optional[IndirectObject]=None) ->None:
+ original_page: "PageObject" # very local use in writer when appending
+
+ def __init__(
+ self,
+ pdf: Optional[PdfCommonDocProtocol] = None,
+ indirect_reference: Optional[IndirectObject] = None,
+ ) -> None:
DictionaryObject.__init__(self)
self.pdf = pdf
self.inline_images: Optional[Dict[str, ImageFile]] = None
+ # below Union for mypy but actually Optional[List[str]]
self.indirect_reference = indirect_reference
+ def hash_value_data(self) -> bytes:
+ data = super().hash_value_data()
+ data += b"%d" % id(self)
+ return data
+
@property
- def user_unit(self) ->float:
+ def user_unit(self) -> float:
"""
A read-only positive number giving the size of user space units.
@@ -184,12 +350,14 @@ class PageObject(DictionaryObject):
space unit is 1/72 inch, and a value of 3 means that a user
space unit is 3/72 inch.
"""
- pass
+ return self.get(PG.USER_UNIT, 1)
@staticmethod
- def create_blank_page(pdf: Optional[PdfCommonDocProtocol]=None, width:
- Union[float, Decimal, None]=None, height: Union[float, Decimal,
- None]=None) ->'PageObject':
+ def create_blank_page(
+ pdf: Optional[PdfCommonDocProtocol] = None,
+ width: Union[float, Decimal, None] = None,
+ height: Union[float, Decimal, None] = None,
+ ) -> "PageObject":
"""
Return a new blank page.
@@ -210,10 +378,27 @@ class PageObject(DictionaryObject):
PageSizeNotDefinedError: if ``pdf`` is ``None`` or contains
no page
"""
- pass
+ 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
@property
- def _old_images(self) ->List[File]:
+ def _old_images(self) -> List[File]: # deprecated
"""
Get a list of all images of the page.
@@ -222,10 +407,101 @@ class PageObject(DictionaryObject):
For the moment, this does NOT include inline images. They will be added
in future.
"""
- pass
+ 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, img = _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))
+ images_extracted[-1].image = img
+ images_extracted[-1].indirect_reference = x_object[
+ obj
+ ].indirect_reference
+ return images_extracted
+
+ def _get_ids_image(
+ self,
+ obj: Optional[DictionaryObject] = None,
+ ancest: Optional[List[str]] = None,
+ call_stack: Optional[List[Any]] = None,
+ ) -> List[Union[str, List[str]]]:
+ if call_stack is None:
+ call_stack = []
+ _i = getattr(obj, "indirect_reference", None)
+ if _i in call_stack:
+ return []
+ else:
+ call_stack.append(_i)
+ if self.inline_images is None:
+ self.inline_images = self._get_inline_images()
+ if obj is None:
+ obj = self
+ if ancest is None:
+ ancest = []
+ lst: List[Union[str, List[str]]] = []
+ if PG.RESOURCES not in obj or RES.XOBJECT not in cast(
+ DictionaryObject, obj[PG.RESOURCES]
+ ):
+ return [] if self.inline_images is None else list(self.inline_images.keys())
+
+ x_object = obj[PG.RESOURCES][RES.XOBJECT].get_object() # type: ignore
+ for o in x_object:
+ if not isinstance(x_object[o], StreamObject):
+ continue
+ if x_object[o][IA.SUBTYPE] == "/Image":
+ lst.append(o if len(ancest) == 0 else ancest + [o])
+ else: # is a form with possible images inside
+ lst.extend(self._get_ids_image(x_object[o], ancest + [o], call_stack))
+ assert self.inline_images is not None
+ lst.extend(list(self.inline_images.keys()))
+ return lst
+
+ def _get_image(
+ self,
+ id: Union[str, List[str], Tuple[str]],
+ obj: Optional[DictionaryObject] = None,
+ ) -> ImageFile:
+ if obj is None:
+ obj = cast(DictionaryObject, self)
+ if isinstance(id, tuple):
+ id = list(id)
+ if isinstance(id, List) and len(id) == 1:
+ id = id[0]
+ try:
+ xobjs = cast(
+ DictionaryObject, cast(DictionaryObject, obj[PG.RESOURCES])[RES.XOBJECT]
+ )
+ except KeyError:
+ if not (id[0] == "~" and id[-1] == "~"):
+ raise
+ if isinstance(id, str):
+ if id[0] == "~" and id[-1] == "~":
+ if self.inline_images is None:
+ self.inline_images = self._get_inline_images()
+ if self.inline_images is None: # pragma: no cover
+ raise KeyError("no inline image can be found")
+ return self.inline_images[id]
+
+ imgd = _xobj_to_image(cast(DictionaryObject, xobjs[id]))
+ extension, byte_stream = imgd[:2]
+ f = ImageFile(
+ name=f"{id[1:]}{extension}",
+ data=byte_stream,
+ image=imgd[2],
+ indirect_reference=xobjs[id].indirect_reference,
+ )
+ return f
+ else: # in a sub object
+ ids = id[1:]
+ return self._get_image(ids, cast(DictionaryObject, xobjs[id[0]]))
@property
- def images(self) ->List[ImageFile]:
+ def images(self) -> List[ImageFile]:
"""
Read-only property emulating a list of images on a page.
@@ -262,39 +538,184 @@ class PageObject(DictionaryObject):
Inline images are extracted and named ~0~, ~1~, ..., with the
indirect_reference set to None.
"""
- pass
+ return _VirtualListImages(self._get_ids_image, self._get_image) # type: ignore
- def _translate_value_inlineimage(self, k: str, v: PdfObject) ->PdfObject:
+ def _translate_value_inlineimage(self, k: str, v: PdfObject) -> PdfObject:
"""Translate values used in inline image"""
- pass
+ try:
+ v = NameObject(
+ {
+ "/G": "/DeviceGray",
+ "/RGB": "/DeviceRGB",
+ "/CMYK": "/DeviceCMYK",
+ "/I": "/Indexed",
+ "/AHx": "/ASCIIHexDecode",
+ "/A85": "/ASCII85Decode",
+ "/LZW": "/LZWDecode",
+ "/Fl": "/FlateDecode",
+ "/RL": "/RunLengthDecode",
+ "/CCF": "/CCITTFaxDecode",
+ "/DCT": "/DCTDecode",
+ "/DeviceGray": "/DeviceGray",
+ "/DeviceRGB": "/DeviceRGB",
+ "/DeviceCMYK": "/DeviceCMYK",
+ "/Indexed": "/Indexed",
+ "/ASCIIHexDecode": "/ASCIIHexDecode",
+ "/ASCII85Decode": "/ASCII85Decode",
+ "/LZWDecode": "/LZWDecode",
+ "/FlateDecode": "/FlateDecode",
+ "/RunLengthDecode": "/RunLengthDecode",
+ "/CCITTFaxDecode": "/CCITTFaxDecode",
+ "/DCTDecode": "/DCTDecode",
+ }[cast(str, v)]
+ )
+ except (TypeError, KeyError):
+ if isinstance(v, NameObject):
+ # It is a custom name, thus we have to look in resources.
+ # The only applicable case is for ColorSpace.
+ try:
+ res = cast(DictionaryObject, self["/Resources"])["/ColorSpace"]
+ v = cast(DictionaryObject, res)[v]
+ except KeyError: # for res and v
+ raise PdfReadError(f"Cannot find resource entry {v} for {k}")
+ return v
- def _get_inline_images(self) ->Dict[str, ImageFile]:
+ def _get_inline_images(self) -> Dict[str, ImageFile]:
"""
get inline_images
entries will be identified as ~1~
"""
- pass
+ content = self.get_contents()
+ if content is None:
+ return {}
+ imgs_data = []
+ for param, ope in content.operations:
+ if ope == b"INLINE IMAGE":
+ imgs_data.append(
+ {"settings": param["settings"], "__streamdata__": param["data"]}
+ )
+ elif ope in (b"BI", b"EI", b"ID"): # pragma: no cover
+ raise PdfReadError(
+ f"{ope} operator met whereas not expected,"
+ "please share usecase with pypdf dev team"
+ )
+ """backup
+ elif ope == b"BI":
+ img_data["settings"] = {}
+ elif ope == b"EI":
+ imgs_data.append(img_data)
+ img_data = {}
+ elif ope == b"ID":
+ img_data["__streamdata__"] = b""
+ elif "__streamdata__" in img_data:
+ if len(img_data["__streamdata__"]) > 0:
+ img_data["__streamdata__"] += b"\n"
+ raise Exception("check append")
+ img_data["__streamdata__"] += param
+ elif "settings" in img_data:
+ img_data["settings"][ope.decode()] = param
+ """
+ files = {}
+ for num, ii in enumerate(imgs_data):
+ init = {
+ "__streamdata__": ii["__streamdata__"],
+ "/Length": len(ii["__streamdata__"]),
+ }
+ for k, v in ii["settings"].items():
+ if k in {"/Length", "/L"}: # no length is expected
+ continue
+ if isinstance(v, list):
+ v = ArrayObject(
+ [self._translate_value_inlineimage(k, x) for x in v]
+ )
+ else:
+ v = self._translate_value_inlineimage(k, v)
+ k = NameObject(
+ {
+ "/BPC": "/BitsPerComponent",
+ "/CS": "/ColorSpace",
+ "/D": "/Decode",
+ "/DP": "/DecodeParms",
+ "/F": "/Filter",
+ "/H": "/Height",
+ "/W": "/Width",
+ "/I": "/Interpolate",
+ "/Intent": "/Intent",
+ "/IM": "/ImageMask",
+ "/BitsPerComponent": "/BitsPerComponent",
+ "/ColorSpace": "/ColorSpace",
+ "/Decode": "/Decode",
+ "/DecodeParms": "/DecodeParms",
+ "/Filter": "/Filter",
+ "/Height": "/Height",
+ "/Width": "/Width",
+ "/Interpolate": "/Interpolate",
+ "/ImageMask": "/ImageMask",
+ }[k]
+ )
+ if k not in init:
+ init[k] = v
+ ii["object"] = EncodedStreamObject.initialize_from_dictionary(init)
+ extension, byte_stream, img = _xobj_to_image(ii["object"])
+ files[f"~{num}~"] = ImageFile(
+ name=f"~{num}~{extension}",
+ data=byte_stream,
+ image=img,
+ indirect_reference=None,
+ )
+ return files
@property
- def rotation(self) ->int:
+ def rotation(self) -> int:
"""
The visual rotation of the page.
This number has to be a multiple of 90 degrees: 0, 90, 180, or 270 are
valid values. This property does not affect ``/Contents``.
"""
- pass
+ rotate_obj = self.get(PG.ROTATE, 0)
+ return rotate_obj if isinstance(rotate_obj, int) else rotate_obj.get_object()
+
+ @rotation.setter
+ def rotation(self, r: float) -> None:
+ self[NameObject(PG.ROTATE)] = NumberObject((((int(r) + 45) // 90) * 90) % 360)
- def transfer_rotation_to_content(self) ->None:
+ def transfer_rotation_to_content(self) -> None:
"""
Apply the rotation of the page to the content and the media/crop/...
boxes.
It is recommended to apply this function before page merging.
"""
- pass
-
- def rotate(self, angle: int) ->'PageObject':
+ 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.
@@ -304,16 +725,139 @@ class PageObject(DictionaryObject):
Returns:
The rotated PageObject
"""
- pass
+ if angle % 90 != 0:
+ raise ValueError("Rotation angle must be a multiple of 90")
+ self[NameObject(PG.ROTATE)] = NumberObject(self.rotation + angle)
+ return self
+
+ def _merge_resources(
+ self,
+ res1: DictionaryObject,
+ res2: DictionaryObject,
+ resource: Any,
+ new_res1: bool = True,
+ ) -> Tuple[Dict[str, Any], Dict[str, Any]]:
+ try:
+ assert isinstance(self.indirect_reference, IndirectObject)
+ pdf = self.indirect_reference.pdf
+ is_pdf_writer = hasattr(
+ pdf, "_add_object"
+ ) # ---------- expect isinstance(pdf,PdfWriter)
+ except (AssertionError, AttributeError):
+ pdf = None
+ is_pdf_writer = False
+
+ def compute_unique_key(base_key: str) -> Tuple[str, bool]:
+ """
+ Find a key that either doesn't already exist or has the same value
+ (indicated by the bool)
+
+ Args:
+ base_key: An index is added to this to get the computed key
+
+ Returns:
+ A tuple (computed key, bool) where the boolean indicates
+ if there is a resource of the given computed_key with the same
+ value.
+ """
+ value = page2res.raw_get(base_key)
+ # TODO : possible improvement : in case of writer, the indirect_reference
+ # can not be found because translated : this may be improved
+
+ # try the current key first (e.g. "foo"), but otherwise iterate
+ # through "foo-0", "foo-1", etc. new_res can contain only finitely
+ # many keys, thus this'll eventually end, even if it's been crafted
+ # to be maximally annoying.
+ computed_key = base_key
+ idx = 0
+ while computed_key in new_res:
+ if new_res.raw_get(computed_key) == value:
+ # there's already a resource of this name, with the exact
+ # same value
+ return computed_key, True
+ computed_key = f"{base_key}-{idx}"
+ idx += 1
+ return computed_key, False
+
+ if new_res1:
+ new_res = DictionaryObject()
+ new_res.update(res1.get(resource, DictionaryObject()).get_object())
+ else:
+ new_res = cast(DictionaryObject, res1[resource])
+ page2res = cast(
+ DictionaryObject, res2.get(resource, DictionaryObject()).get_object()
+ )
+ rename_res = {}
+ for key in page2res:
+ unique_key, same_value = compute_unique_key(key)
+ newname = NameObject(unique_key)
+ if key != unique_key:
+ # we have to use a different name for this
+ rename_res[key] = newname
+
+ if not same_value:
+ if is_pdf_writer:
+ new_res[newname] = page2res.raw_get(key).clone(pdf)
+ try:
+ new_res[newname] = new_res[newname].indirect_reference
+ except AttributeError:
+ pass
+ else:
+ new_res[newname] = page2res.raw_get(key)
+ lst = sorted(new_res.items())
+ new_res.clear()
+ for el in lst:
+ new_res[el[0]] = el[1]
+ return new_res, rename_res
@staticmethod
- def _add_transformation_matrix(contents: Any, pdf: Optional[
- PdfCommonDocProtocol], ctm: CompressedTransformationMatrix
- ) ->ContentStream:
- """Add transformation matrix at the beginning of the given contents stream."""
- pass
+ def _content_stream_rename(
+ stream: ContentStream,
+ rename: Dict[Any, Any],
+ pdf: Optional[PdfCommonDocProtocol],
+ ) -> ContentStream:
+ if not rename:
+ return stream
+ stream = ContentStream(stream, pdf)
+ for operands, _operator in stream.operations:
+ if isinstance(operands, list):
+ for i, op in enumerate(operands):
+ if isinstance(op, NameObject):
+ operands[i] = rename.get(op, op)
+ elif isinstance(operands, dict):
+ for i, op in operands.items():
+ if isinstance(op, NameObject):
+ operands[i] = rename.get(op, op)
+ else:
+ raise KeyError(f"type of operands is {type(operands)}")
+ return stream
- def _get_contents_as_bytes(self) ->Optional[bytes]:
+ @staticmethod
+ def _add_transformation_matrix(
+ contents: Any,
+ pdf: Optional[PdfCommonDocProtocol],
+ ctm: CompressedTransformationMatrix,
+ ) -> ContentStream:
+ """Add 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_as_bytes(self) -> Optional[bytes]:
"""
Return the page contents as bytes.
@@ -321,9 +865,16 @@ class PageObject(DictionaryObject):
The ``/Contents`` object as bytes, or ``None`` if it doesn't exist.
"""
- pass
+ if PG.CONTENTS in self:
+ obj = self[PG.CONTENTS].get_object()
+ if isinstance(obj, list):
+ return b"".join(x.get_object().get_data() for x in obj)
+ else:
+ return cast(bytes, cast(EncodedStreamObject, obj).get_data())
+ else:
+ return None
- def get_contents(self) ->Optional[ContentStream]:
+ def get_contents(self) -> Optional[ContentStream]:
"""
Access the page contents.
@@ -331,19 +882,81 @@ class PageObject(DictionaryObject):
The ``/Contents`` object, or ``None`` if it does not exist.
``/Contents`` is optional, as described in §7.7.3.3 of the PDF Reference.
"""
- pass
-
- def replace_contents(self, content: Union[None, ContentStream,
- EncodedStreamObject, ArrayObject]) ->None:
+ if PG.CONTENTS in self:
+ try:
+ pdf = cast(IndirectObject, self.indirect_reference).pdf
+ except AttributeError:
+ pdf = None
+ obj = self[PG.CONTENTS].get_object()
+ if isinstance(obj, NullObject):
+ return None
+ else:
+ return ContentStream(obj, pdf)
+ else:
+ return None
+
+ def replace_contents(
+ self, content: Union[None, ContentStream, EncodedStreamObject, ArrayObject]
+ ) -> None:
"""
Replace the page contents with the new content and nullify old objects
Args:
content: new content; if None delete the content field.
"""
- pass
+ if not hasattr(self, "indirect_reference") or self.indirect_reference is None:
+ # the page is not attached : the content is directly attached.
+ self[NameObject(PG.CONTENTS)] = content
+ return
+ if isinstance(self.get(PG.CONTENTS, None), ArrayObject):
+ for o in self[PG.CONTENTS]: # type: ignore[attr-defined]
+ try:
+ self._objects[o.indirect_reference.idnum - 1] = NullObject() # type: ignore
+ except AttributeError:
+ pass
- def merge_page(self, page2: 'PageObject', expand: bool=False, over:
- bool=True) ->None:
+ if isinstance(content, ArrayObject):
+ for i in range(len(content)):
+ content[i] = self.indirect_reference.pdf._add_object(content[i])
+
+ if content is None:
+ if PG.CONTENTS not in self:
+ return
+ else:
+ assert self.indirect_reference is not None
+ assert self[PG.CONTENTS].indirect_reference is not None
+ self.indirect_reference.pdf._objects[
+ self[PG.CONTENTS].indirect_reference.idnum - 1 # type: ignore
+ ] = NullObject()
+ del self[PG.CONTENTS]
+ elif not hasattr(self.get(PG.CONTENTS, None), "indirect_reference"):
+ try:
+ self[NameObject(PG.CONTENTS)] = self.indirect_reference.pdf._add_object(
+ content
+ )
+ except AttributeError:
+ # applies at least for page not in writer
+ # as a backup solution, we put content as an object although not in accordance with pdf ref
+ # this will be fixed with the _add_object
+ self[NameObject(PG.CONTENTS)] = content
+ else:
+ content.indirect_reference = self[
+ PG.CONTENTS
+ ].indirect_reference # TODO: in a future may required generation management
+ try:
+ self.indirect_reference.pdf._objects[
+ content.indirect_reference.idnum - 1 # type: ignore
+ ] = content
+ except AttributeError:
+ # applies at least for page not in writer
+ # as a backup solution, we put content as an object although not in accordance with pdf ref
+ # this will be fixed with the _add_object
+ self[NameObject(PG.CONTENTS)] = content
+ # forces recalculation of inline_images
+ self.inline_images = None
+
+ def merge_page(
+ self, page2: "PageObject", expand: bool = False, over: bool = True
+ ) -> None:
"""
Merge the content streams of two pages into one.
@@ -360,11 +973,309 @@ class PageObject(DictionaryObject):
expand: If True, the current page dimensions will be
expanded to accommodate the dimensions of the page to be merged.
"""
- pass
+ self._merge_page(page2, over=over, expand=expand)
+
+ def _merge_page(
+ self,
+ page2: "PageObject",
+ page2transformation: Optional[Callable[[Any], ContentStream]] = None,
+ ctm: Optional[CompressedTransformationMatrix] = None,
+ over: bool = True,
+ expand: bool = False,
+ ) -> None:
+ # First we work on merging the resource dictionaries. This allows us
+ # to find out what symbols in the content streams we might need to
+ # rename.
+ try:
+ assert isinstance(self.indirect_reference, IndirectObject)
+ if hasattr(
+ self.indirect_reference.pdf, "_add_object"
+ ): # ---------- to detect PdfWriter
+ return self._merge_page_writer(
+ page2, page2transformation, ctm, over, expand
+ )
+ except (AssertionError, AttributeError):
+ pass
+
+ new_resources = DictionaryObject()
+ rename = {}
+ try:
+ original_resources = cast(DictionaryObject, self[PG.RESOURCES].get_object())
+ except KeyError:
+ original_resources = DictionaryObject()
+ try:
+ page2resources = cast(DictionaryObject, page2[PG.RESOURCES].get_object())
+ except KeyError:
+ page2resources = DictionaryObject()
+ new_annots = ArrayObject()
+
+ for page in (self, page2):
+ if PG.ANNOTS in page:
+ annots = page[PG.ANNOTS]
+ if isinstance(annots, ArrayObject):
+ new_annots.extend(annots)
+
+ for res in (
+ RES.EXT_G_STATE,
+ RES.FONT,
+ RES.XOBJECT,
+ RES.COLOR_SPACE,
+ RES.PATTERN,
+ RES.SHADING,
+ RES.PROPERTIES,
+ ):
+ new, newrename = self._merge_resources(
+ original_resources, page2resources, res
+ )
+ if new:
+ new_resources[NameObject(res)] = new
+ rename.update(newrename)
+
+ # Combine /ProcSet sets, making sure there's a consistent order
+ new_resources[NameObject(RES.PROC_SET)] = ArrayObject(
+ sorted(
+ set(
+ original_resources.get(RES.PROC_SET, ArrayObject()).get_object()
+ ).union(
+ set(page2resources.get(RES.PROC_SET, ArrayObject()).get_object())
+ )
+ )
+ )
+
+ new_content_array = ArrayObject()
+ original_content = self.get_contents()
+ if original_content is not None:
+ original_content.isolate_graphics_state()
+ new_content_array.append(original_content)
+
+ page2content = page2.get_contents()
+ if page2content is not None:
+ rect = getattr(page2, MERGE_CROP_BOX)
+ page2content.operations.insert(
+ 0,
+ (
+ map(
+ FloatObject,
+ [
+ rect.left,
+ rect.bottom,
+ rect.width,
+ rect.height,
+ ],
+ ),
+ "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.isolate_graphics_state()
+ if over:
+ new_content_array.append(page2content)
+ else:
+ new_content_array.insert(0, page2content)
+
+ # if expanding the page to fit a new page, calculate the new media box size
+ if expand:
+ self._expand_mediabox(page2, ctm)
+
+ self.replace_contents(ContentStream(new_content_array, self.pdf))
+ self[NameObject(PG.RESOURCES)] = new_resources
+ self[NameObject(PG.ANNOTS)] = new_annots
+
+ def _merge_page_writer(
+ self,
+ page2: "PageObject",
+ page2transformation: Optional[Callable[[Any], ContentStream]] = None,
+ ctm: Optional[CompressedTransformationMatrix] = None,
+ over: bool = True,
+ expand: bool = False,
+ ) -> None:
+ # First we work on merging the resource dictionaries. This allows us
+ # to find which symbols in the content streams we might need to
+ # rename.
+ assert isinstance(self.indirect_reference, IndirectObject)
+ pdf = self.indirect_reference.pdf
+
+ rename = {}
+ if PG.RESOURCES not in self:
+ self[NameObject(PG.RESOURCES)] = DictionaryObject()
+ original_resources = cast(DictionaryObject, self[PG.RESOURCES].get_object())
+ if PG.RESOURCES not in page2:
+ page2resources = DictionaryObject()
+ else:
+ page2resources = cast(DictionaryObject, page2[PG.RESOURCES].get_object())
+
+ for res in (
+ RES.EXT_G_STATE,
+ RES.FONT,
+ RES.XOBJECT,
+ RES.COLOR_SPACE,
+ RES.PATTERN,
+ RES.SHADING,
+ RES.PROPERTIES,
+ ):
+ if res in page2resources:
+ if res not in original_resources:
+ original_resources[NameObject(res)] = DictionaryObject()
+ _, newrename = self._merge_resources(
+ original_resources, page2resources, res, False
+ )
+ rename.update(newrename)
+ # Combine /ProcSet sets.
+ if RES.PROC_SET in page2resources:
+ if RES.PROC_SET not in original_resources:
+ original_resources[NameObject(RES.PROC_SET)] = ArrayObject()
+ arr = cast(ArrayObject, original_resources[RES.PROC_SET])
+ for x in cast(ArrayObject, page2resources[RES.PROC_SET]):
+ if x not in arr:
+ arr.append(x)
+ arr.sort()
+
+ if PG.ANNOTS in page2:
+ if PG.ANNOTS not in self:
+ self[NameObject(PG.ANNOTS)] = ArrayObject()
+ annots = cast(ArrayObject, self[PG.ANNOTS].get_object())
+ if ctm is None:
+ trsf = Transformation()
+ else:
+ trsf = Transformation(ctm)
+ for a in cast(ArrayObject, page2[PG.ANNOTS]):
+ a = a.get_object()
+ aa = a.clone(
+ pdf,
+ ignore_fields=("/P", "/StructParent", "/Parent"),
+ force_duplicate=True,
+ )
+ r = cast(ArrayObject, a["/Rect"])
+ pt1 = trsf.apply_on((r[0], r[1]), True)
+ pt2 = trsf.apply_on((r[2], r[3]), True)
+ aa[NameObject("/Rect")] = ArrayObject(
+ (
+ min(pt1[0], pt2[0]),
+ min(pt1[1], pt2[1]),
+ max(pt1[0], pt2[0]),
+ max(pt1[1], pt2[1]),
+ )
+ )
+ if "/QuadPoints" in a:
+ q = cast(ArrayObject, a["/QuadPoints"])
+ aa[NameObject("/QuadPoints")] = ArrayObject(
+ trsf.apply_on((q[0], q[1]), True)
+ + trsf.apply_on((q[2], q[3]), True)
+ + trsf.apply_on((q[4], q[5]), True)
+ + trsf.apply_on((q[6], q[7]), True)
+ )
+ try:
+ aa["/Popup"][NameObject("/Parent")] = aa.indirect_reference
+ except KeyError:
+ pass
+ try:
+ aa[NameObject("/P")] = self.indirect_reference
+ annots.append(aa.indirect_reference)
+ except AttributeError:
+ pass
- def merge_transformed_page(self, page2: 'PageObject', ctm: Union[
- CompressedTransformationMatrix, Transformation], over: bool=True,
- expand: bool=False) ->None:
+ new_content_array = ArrayObject()
+ original_content = self.get_contents()
+ if original_content is not None:
+ original_content.isolate_graphics_state()
+ new_content_array.append(original_content)
+
+ page2content = page2.get_contents()
+ if page2content is not None:
+ rect = getattr(page2, MERGE_CROP_BOX)
+ page2content.operations.insert(
+ 0,
+ (
+ map(
+ FloatObject,
+ [
+ rect.left,
+ rect.bottom,
+ rect.width,
+ rect.height,
+ ],
+ ),
+ "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.isolate_graphics_state()
+ if over:
+ new_content_array.append(page2content)
+ else:
+ new_content_array.insert(0, page2content)
+
+ # if expanding the page to fit a new page, calculate the new media box size
+ if expand:
+ self._expand_mediabox(page2, ctm)
+
+ self.replace_contents(new_content_array)
+ # self[NameObject(PG.CONTENTS)] = ContentStream(new_content_array, pdf)
+ # self[NameObject(PG.RESOURCES)] = new_resources
+ # self[NameObject(PG.ANNOTS)] = new_annots
+
+ def _expand_mediabox(
+ self, page2: "PageObject", ctm: Optional[CompressedTransformationMatrix]
+ ) -> None:
+ corners1 = (
+ self.mediabox.left.as_numeric(),
+ self.mediabox.bottom.as_numeric(),
+ self.mediabox.right.as_numeric(),
+ self.mediabox.top.as_numeric(),
+ )
+ corners2 = (
+ page2.mediabox.left.as_numeric(),
+ page2.mediabox.bottom.as_numeric(),
+ page2.mediabox.left.as_numeric(),
+ page2.mediabox.top.as_numeric(),
+ page2.mediabox.right.as_numeric(),
+ page2.mediabox.top.as_numeric(),
+ page2.mediabox.right.as_numeric(),
+ page2.mediabox.bottom.as_numeric(),
+ )
+ if ctm is not None:
+ ctm = tuple(float(x) for x in ctm) # type: ignore[assignment]
+ new_x = tuple(
+ ctm[0] * corners2[i] + ctm[2] * corners2[i + 1] + ctm[4]
+ for i in range(0, 8, 2)
+ )
+ new_y = tuple(
+ ctm[1] * corners2[i] + ctm[3] * corners2[i + 1] + ctm[5]
+ for i in range(0, 8, 2)
+ )
+ else:
+ new_x = corners2[0:8:2]
+ new_y = corners2[1:8:2]
+ lowerleft = (min(new_x), min(new_y))
+ upperright = (max(new_x), max(new_y))
+ lowerleft = (min(corners1[0], lowerleft[0]), min(corners1[1], lowerleft[1]))
+ upperright = (
+ max(corners1[2], upperright[0]),
+ max(corners1[3], upperright[1]),
+ )
+
+ self.mediabox.lower_left = lowerleft
+ self.mediabox.upper_right = upperright
+
+ def merge_transformed_page(
+ self,
+ page2: "PageObject",
+ ctm: Union[CompressedTransformationMatrix, Transformation],
+ over: bool = True,
+ expand: bool = False,
+ ) -> None:
"""
merge_transformed_page is similar to merge_page, but a transformation
matrix is applied to the merged stream.
@@ -377,10 +1288,21 @@ class PageObject(DictionaryObject):
expand: Whether the page should be expanded to fit the dimensions
of the page to be merged.
"""
- pass
-
- def merge_scaled_page(self, page2: 'PageObject', scale: float, over:
- bool=True, expand: bool=False) ->None:
+ if isinstance(ctm, Transformation):
+ ctm = ctm.ctm
+ self._merge_page(
+ page2,
+ lambda page2Content: PageObject._add_transformation_matrix(
+ page2Content, page2.pdf, cast(CompressedTransformationMatrix, ctm)
+ ),
+ ctm,
+ over,
+ expand,
+ )
+
+ def merge_scaled_page(
+ self, page2: "PageObject", scale: float, over: bool = True, expand: bool = False
+ ) -> None:
"""
merge_scaled_page is similar to merge_page, but the stream to be merged
is scaled by applying a transformation matrix.
@@ -392,10 +1314,16 @@ class PageObject(DictionaryObject):
expand: Whether the page should be expanded to fit the
dimensions of the page to be merged.
"""
- pass
+ op = Transformation().scale(scale, scale)
+ self.merge_transformed_page(page2, op, over, expand)
- def merge_rotated_page(self, page2: 'PageObject', rotation: float, over:
- bool=True, expand: bool=False) ->None:
+ def merge_rotated_page(
+ self,
+ page2: "PageObject",
+ rotation: float,
+ over: bool = True,
+ expand: bool = False,
+ ) -> None:
"""
merge_rotated_page is similar to merge_page, but the stream to be merged
is rotated by applying a transformation matrix.
@@ -407,10 +1335,17 @@ class PageObject(DictionaryObject):
expand: Whether the page should be expanded to fit the
dimensions of the page to be merged.
"""
- pass
+ op = Transformation().rotate(rotation)
+ self.merge_transformed_page(page2, op, over, expand)
- def merge_translated_page(self, page2: 'PageObject', tx: float, ty:
- float, over: bool=True, expand: bool=False) ->None:
+ def merge_translated_page(
+ self,
+ page2: "PageObject",
+ tx: float,
+ ty: float,
+ over: bool = True,
+ expand: bool = False,
+ ) -> None:
"""
mergeTranslatedPage is similar to merge_page, but the stream to be
merged is translated by applying a transformation matrix.
@@ -423,10 +1358,14 @@ class PageObject(DictionaryObject):
expand: Whether the page should be expanded to fit the
dimensions of the page to be merged.
"""
- pass
+ op = Transformation().translate(tx, ty)
+ self.merge_transformed_page(page2, op, over, expand)
- def add_transformation(self, ctm: Union[Transformation,
- CompressedTransformationMatrix], expand: bool=False) ->None:
+ def add_transformation(
+ self,
+ ctm: Union[Transformation, CompressedTransformationMatrix],
+ expand: bool = False,
+ ) -> None:
"""
Apply a transformation matrix to the page.
@@ -438,9 +1377,43 @@ class PageObject(DictionaryObject):
See :doc:`/user/cropping-and-transforming`.
"""
- pass
-
- def scale(self, sx: float, sy: float) ->None:
+ if isinstance(ctm, Transformation):
+ ctm = ctm.ctm
+ content = self.get_contents()
+ if content is not None:
+ content = PageObject._add_transformation_matrix(content, self.pdf, ctm)
+ content.isolate_graphics_state()
+ self.replace_contents(content)
+ # if expanding the page to fit a new page, calculate the new media box size
+ if expand:
+ corners = [
+ self.mediabox.left.as_numeric(),
+ self.mediabox.bottom.as_numeric(),
+ self.mediabox.left.as_numeric(),
+ self.mediabox.top.as_numeric(),
+ self.mediabox.right.as_numeric(),
+ self.mediabox.top.as_numeric(),
+ self.mediabox.right.as_numeric(),
+ self.mediabox.bottom.as_numeric(),
+ ]
+
+ ctm = tuple(float(x) for x in ctm) # type: ignore[assignment]
+ new_x = [
+ ctm[0] * corners[i] + ctm[2] * corners[i + 1] + ctm[4]
+ for i in range(0, 8, 2)
+ ]
+ new_y = [
+ ctm[1] * corners[i] + ctm[3] * corners[i + 1] + ctm[5]
+ for i in range(0, 8, 2)
+ ]
+
+ lowerleft = (min(new_x), min(new_y))
+ upperright = (max(new_x), max(new_y))
+
+ self.mediabox.lower_left = lowerleft
+ self.mediabox.upper_right = upperright
+
+ def scale(self, sx: float, sy: float) -> None:
"""
Scale a page by the given factors by applying a transformation matrix
to its content and updating the page size.
@@ -452,9 +1425,48 @@ class PageObject(DictionaryObject):
sx: The scaling factor on horizontal axis.
sy: The scaling factor on vertical axis.
"""
- pass
-
- def scale_by(self, factor: float) ->None:
+ 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.
@@ -462,9 +1474,9 @@ class PageObject(DictionaryObject):
Args:
factor: The scaling factor (for both X and Y axis).
"""
- pass
+ self.scale(factor, factor)
- def scale_to(self, width: float, height: float) ->None:
+ 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.
@@ -473,9 +1485,11 @@ class PageObject(DictionaryObject):
width: The new width.
height: The new height.
"""
- pass
+ sx = width / float(self.mediabox.width)
+ sy = height / float(self.mediabox.height)
+ self.scale(sx, sy)
- def compress_content_streams(self, level: int=-1) ->None:
+ def compress_content_streams(self, level: int = -1) -> None:
"""
Compress the size of this page by joining all content streams and
applying a FlateDecode filter.
@@ -483,24 +1497,87 @@ class PageObject(DictionaryObject):
However, it is possible that this function will perform no action if
content stream compression becomes "automatic".
"""
- pass
+ content = self.get_contents()
+ if content is not None:
+ content_obj = content.flate_encode(level)
+ try:
+ content.indirect_reference.pdf._objects[ # type: ignore
+ content.indirect_reference.idnum - 1 # type: ignore
+ ] = content_obj
+ except AttributeError:
+ if self.indirect_reference is not None and hasattr(
+ self.indirect_reference.pdf, "_add_object"
+ ):
+ self.replace_contents(content_obj)
+ else:
+ raise ValueError("Page must be part of a PdfWriter")
@property
- def page_number(self) ->Optional[int]:
+ def page_number(self) -> Optional[int]:
"""
Read-only property which returns the page number within the PDF file.
Returns:
int : page number; None if the page is not attached to a PDF.
"""
- pass
+ if self.indirect_reference is None:
+ return None
+ else:
+ try:
+ lst = self.indirect_reference.pdf.pages
+ return lst.index(self)
+ except ValueError:
+ return None
+
+ def _debug_for_extract(self) -> str: # pragma: no cover
+ out = ""
+ for ope, op in ContentStream(
+ self["/Contents"].get_object(), self.pdf, "bytes"
+ ).operations:
+ if op == b"TJ":
+ s = [x for x in ope[0] if isinstance(x, str)]
+ else:
+ s = []
+ out += op.decode("utf-8") + " " + "".join(s) + ope.__repr__() + "\n"
+ out += "\n=============================\n"
+ try:
+ for fo in self[PG.RESOURCES]["/Font"]: # type:ignore
+ out += fo + "\n"
+ out += self[PG.RESOURCES]["/Font"][fo].__repr__() + "\n" # type:ignore
+ try:
+ enc_repr = self[PG.RESOURCES]["/Font"][fo][ # type:ignore
+ "/Encoding"
+ ].__repr__()
+ out += enc_repr + "\n"
+ except Exception:
+ pass
+ try:
+ out += (
+ self[PG.RESOURCES]["/Font"][fo][ # type:ignore
+ "/ToUnicode"
+ ]
+ .get_data()
+ .decode()
+ + "\n"
+ )
+ except Exception:
+ pass
- 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:
+ 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.
@@ -509,20 +1586,363 @@ class PageObject(DictionaryObject):
None = the object; this allow to reuse the function on XObject
default = "/Content"
"""
- pass
-
- def _layout_mode_fonts(self) ->Dict[str, _layout_mode.Font]:
+ 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 will be raised
+ resources_dict = cast(DictionaryObject, objr[PG.RESOURCES])
+ except Exception:
+ # no resources means no text is possible (no font) we consider the
+ # file as not damaged, no need to check for TJ or Tj
+ return ""
+ if "/Font" in resources_dict:
+ for f in cast(DictionaryObject, resources_dict["/Font"]):
+ cmaps[f] = build_char_map(f, space_width, obj)
+ cmap: Tuple[
+ Union[str, Dict[int, str]], Dict[str, str], str, Optional[DictionaryObject]
+ ] = (
+ "charmap",
+ {},
+ "NotInitialized",
+ None,
+ ) # (encoding,CMAP,font resource name,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]
+
+ # cm/tm_prev stores the last modified matrices can be an intermediate position
+ cm_prev: List[float] = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0]
+ tm_prev: List[float] = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0]
+
+ # memo_cm/tm will be used to store the position at the beginning of building the text
+ memo_cm: List[float] = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0]
+ memo_tm: List[float] = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0]
+ char_scale = 1.0
+ space_scale = 1.0
+ _space_width: float = 500.0 # will be set correctly at first Tf
+ TL = 0.0
+ font_size = 12.0 # init just in case of
+
+ def current_spacewidth() -> float:
+ return _space_width / 1000.0
+
+ def process_operation(operator: bytes, operands: List[Any]) -> None:
+ nonlocal cm_matrix, cm_stack, tm_matrix, cm_prev, tm_prev, memo_cm, memo_tm
+ nonlocal char_scale, space_scale, _space_width, TL, font_size, cmap
+ nonlocal orientations, rtl_dir, visitor_text, output, text
+ 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]
+ output += text
+ if visitor_text is not None:
+ visitor_text(text, memo_cm, memo_tm, cmap[3], font_size)
+ text = ""
+ memo_cm = cm_matrix.copy()
+ memo_tm = tm_matrix.copy()
+ return None
+ elif operator == b"ET":
+ output += text
+ if visitor_text is not None:
+ visitor_text(text, memo_cm, memo_tm, cmap[3], font_size)
+ text = ""
+ memo_cm = cm_matrix.copy()
+ memo_tm = tm_matrix.copy()
+ # table 4.7 "Graphics state operators", page 219
+ # cm_matrix calculation is 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]
+ elif operator == b"cm":
+ output += text
+ if visitor_text is not None:
+ visitor_text(text, memo_cm, memo_tm, cmap[3], font_size)
+ text = ""
+ cm_matrix = mult(
+ [
+ float(operands[0]),
+ float(operands[1]),
+ float(operands[2]),
+ float(operands[3]),
+ float(operands[4]),
+ float(operands[5]),
+ ],
+ cm_matrix,
+ )
+ memo_cm = cm_matrix.copy()
+ memo_tm = tm_matrix.copy()
+ # Table 5.2 page 398
+ elif operator == b"Tz":
+ char_scale = float(operands[0]) / 100.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, memo_cm, memo_tm, cmap[3], font_size)
+ text = ""
+ memo_cm = cm_matrix.copy()
+ memo_tm = tm_matrix.copy()
+ 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
+ text, rtl_dir = handle_tj(
+ text,
+ operands,
+ cm_matrix,
+ tm_matrix, # text matrix
+ cmap,
+ orientations,
+ output,
+ font_size,
+ rtl_dir,
+ visitor_text,
+ )
+ else:
+ return None
+ if check_crlf_space:
+ try:
+ text, output, cm_prev, tm_prev = crlf_space_check(
+ text,
+ (cm_prev, tm_prev),
+ (cm_matrix, tm_matrix),
+ (memo_cm, memo_tm),
+ cmap,
+ orientations,
+ output,
+ font_size,
+ visitor_text,
+ current_spacewidth(),
+ )
+ if text == "":
+ memo_cm = cm_matrix.copy()
+ memo_tm = tm_matrix.copy()
+ except OrientationNotFoundError:
+ return None
+
+ for operands, operator in content.operations:
+ if visitor_operand_before is not None:
+ visitor_operand_before(operator, operands, cm_matrix, tm_matrix)
+ # multiple operators are 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)) and (
+ (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, memo_cm, memo_tm, cmap[3], font_size)
+ try:
+ if output[-1] != "\n":
+ output += "\n"
+ if visitor_text is not None:
+ visitor_text(
+ "\n",
+ memo_cm,
+ memo_tm,
+ cmap[3],
+ font_size,
+ )
+ except IndexError:
+ pass
+ try:
+ xobj = resources_dict["/XObject"]
+ if xobj[operands[0]]["/Subtype"] != "/Image": # type: ignore
+ text = self.extract_xform_text(
+ xobj[operands[0]], # type: ignore
+ orientations,
+ space_width,
+ visitor_operand_before,
+ visitor_operand_after,
+ visitor_text,
+ )
+ output += text
+ if visitor_text is not None:
+ visitor_text(
+ text,
+ memo_cm,
+ memo_tm,
+ cmap[3],
+ font_size,
+ )
+ except Exception:
+ logger_warning(
+ f" impossible to decode XFormObject {operands[0]}",
+ __name__,
+ )
+ finally:
+ text = ""
+ memo_cm = cm_matrix.copy()
+ memo_tm = tm_matrix.copy()
+
+ else:
+ process_operation(operator, operands)
+ if visitor_operand_after is not None:
+ visitor_operand_after(operator, operands, cm_matrix, tm_matrix)
+ output += text # just in case of
+ if text != "" and visitor_text is not None:
+ visitor_text(text, memo_cm, memo_tm, cmap[3], font_size)
+ return output
+
+ def _layout_mode_fonts(self) -> Dict[str, _layout_mode.Font]:
"""
Get fonts formatted for "layout" mode text extraction.
Returns:
Dict[str, Font]: dictionary of _layout_mode.Font instances keyed by font name
"""
- pass
+ # Font retrieval logic adapted from pypdf.PageObject._extract_text()
+ objr: Any = self
+ fonts: Dict[str, _layout_mode.Font] = {}
+ while objr is not None:
+ try:
+ resources_dict: Any = objr[PG.RESOURCES]
+ except KeyError:
+ resources_dict = {}
+ if "/Font" in resources_dict and self.pdf is not None:
+ for font_name in resources_dict["/Font"]:
+ *cmap, font_dict_obj = build_char_map(font_name, 200.0, self)
+ font_dict = {
+ k: v.get_object()
+ if isinstance(v, IndirectObject)
+ else [_v.get_object() for _v in v]
+ if isinstance(v, ArrayObject)
+ else v
+ for k, v in font_dict_obj.items()
+ }
+ # mypy really sucks at unpacking
+ fonts[font_name] = _layout_mode.Font(*cmap, font_dict) # type: ignore[call-arg,arg-type]
+ try:
+ objr = objr["/Parent"].get_object()
+ except KeyError:
+ objr = None
- def _layout_mode_text(self, space_vertically: bool=True, scale_weight:
- float=1.25, strip_rotated: bool=True, debug_path: Optional[Path]=None
- ) ->str:
+ return fonts
+
+ def _layout_mode_text(
+ self,
+ space_vertically: bool = True,
+ scale_weight: float = 1.25,
+ strip_rotated: bool = True,
+ debug_path: Optional[Path] = None,
+ ) -> str:
"""
Get text preserving fidelity to source PDF text layout.
@@ -546,15 +1966,44 @@ class PageObject(DictionaryObject):
str: multiline string containing page text in a fixed width format that
closely adheres to the rendered layout in the source pdf.
"""
- pass
-
- def extract_text(self, *args: Any, orientations: Union[int, Tuple[int,
- ...]]=(0, 90, 180, 270), space_width: float=200.0,
- visitor_operand_before: Optional[Callable[[Any, Any, Any, Any],
- None]]=None, visitor_operand_after: Optional[Callable[[Any, Any,
- Any, Any], None]]=None, visitor_text: Optional[Callable[[Any, Any,
- Any, Any, Any], None]]=None, extraction_mode: Literal['plain',
- 'layout']='plain', **kwargs: Any) ->str:
+ fonts = self._layout_mode_fonts()
+ if debug_path: # pragma: no cover
+ import json
+
+ debug_path.joinpath("fonts.json").write_text(
+ json.dumps(
+ fonts, indent=2, default=lambda x: getattr(x, "to_dict", str)(x)
+ ),
+ "utf-8",
+ )
+
+ ops = iter(
+ ContentStream(self["/Contents"].get_object(), self.pdf, "bytes").operations
+ )
+ bt_groups = _layout_mode.text_show_operations(
+ ops, fonts, strip_rotated, debug_path
+ )
+
+ if not bt_groups:
+ return ""
+
+ ty_groups = _layout_mode.y_coordinate_groups(bt_groups, debug_path)
+
+ char_width = _layout_mode.fixed_char_width(bt_groups, scale_weight)
+
+ return _layout_mode.fixed_width_page(ty_groups, char_width, space_vertically)
+
+ def extract_text(
+ self,
+ *args: Any,
+ orientations: Union[int, Tuple[int, ...]] = (0, 90, 180, 270),
+ space_width: float = 200.0,
+ visitor_operand_before: Optional[Callable[[Any, Any, Any, Any], None]] = None,
+ visitor_operand_after: Optional[Callable[[Any, Any, Any, Any], None]] = None,
+ visitor_text: Optional[Callable[[Any, Any, Any, Any, Any], None]] = None,
+ extraction_mode: Literal["plain", "layout"] = "plain",
+ **kwargs: Any,
+ ) -> str:
"""
Locate all text drawing commands, in the order they are provided in the
content stream, and extract the text.
@@ -616,14 +2065,60 @@ class PageObject(DictionaryObject):
Returns:
The extracted text
"""
- pass
-
- 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:
+ if extraction_mode not in ["plain", "layout"]:
+ raise ValueError(f"Invalid text extraction mode '{extraction_mode}'")
+ if extraction_mode == "layout":
+ return self._layout_mode_text(
+ space_vertically=kwargs.get("layout_mode_space_vertically", True),
+ scale_weight=kwargs.get("layout_mode_scale_weight", 1.25),
+ strip_rotated=kwargs.get("layout_mode_strip_rotated", True),
+ debug_path=kwargs.get("layout_mode_debug_path", None),
+ )
+ if len(args) >= 1:
+ if isinstance(args[0], str):
+ if len(args) >= 3:
+ if isinstance(args[2], (tuple, int)):
+ orientations = args[2]
+ else:
+ raise TypeError(f"Invalid positional parameter {args[2]}")
+ if len(args) >= 4:
+ if isinstance(args[3], (float, int)):
+ space_width = args[3]
+ else:
+ raise TypeError(f"Invalid positional parameter {args[3]}")
+ elif isinstance(args[0], (tuple, int)):
+ orientations = args[0]
+ if len(args) >= 2:
+ if isinstance(args[1], (float, int)):
+ space_width = args[1]
+ else:
+ raise TypeError(f"Invalid positional parameter {args[1]}")
+ else:
+ raise TypeError(f"Invalid positional parameter {args[0]}")
+
+ if isinstance(orientations, int):
+ orientations = (orientations,)
+
+ return self._extract_text(
+ self,
+ self.pdf,
+ orientations,
+ space_width,
+ PG.CONTENTS,
+ visitor_operand_before,
+ visitor_operand_after,
+ visitor_text,
+ )
+
+ def extract_xform_text(
+ self,
+ xform: EncodedStreamObject,
+ orientations: Tuple[int, ...] = (0, 90, 270, 360),
+ space_width: float = 200.0,
+ visitor_operand_before: Optional[Callable[[Any, Any, Any, Any], None]] = None,
+ visitor_operand_after: Optional[Callable[[Any, Any, Any, Any], None]] = None,
+ visitor_text: Optional[Callable[[Any, Any, Any, Any, Any], None]] = None,
+ ) -> str:
"""
Extract text from an XObject.
@@ -638,21 +2133,38 @@ class PageObject(DictionaryObject):
Returns:
The extracted text
"""
- pass
+ return self._extract_text(
+ xform,
+ self.pdf,
+ orientations,
+ space_width,
+ None,
+ visitor_operand_before,
+ visitor_operand_after,
+ visitor_text,
+ )
- def _get_fonts(self) ->Tuple[Set[str], Set[str]]:
+ def _get_fonts(self) -> Tuple[Set[str], Set[str]]:
"""
Get the names of embedded fonts and unembedded fonts.
Returns:
A tuple (Set of embedded fonts, set of unembedded fonts)
"""
- pass
+ obj = self.get_object()
+ assert isinstance(obj, DictionaryObject)
+ fonts: Set[str] = set()
+ embedded: Set[str] = set()
+ fonts, embedded = _get_fonts_walk(obj, fonts, embedded)
+ unembedded = fonts - embedded
+ return embedded, unembedded
+
mediabox = _create_rectangle_accessor(PG.MEDIABOX, ())
"""A :class:`RectangleObject<pypdf.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."""
- cropbox = _create_rectangle_accessor('/CropBox', (PG.MEDIABOX,))
+
+ cropbox = _create_rectangle_accessor("/CropBox", (PG.MEDIABOX,))
"""
A :class:`RectangleObject<pypdf.generic.RectangleObject>`, expressed in
default user space units, defining the visible region of default user
@@ -663,22 +2175,31 @@ class PageObject(DictionaryObject):
implementation-defined manner. Default value: same as
:attr:`mediabox<mediabox>`.
"""
- bleedbox = _create_rectangle_accessor('/BleedBox', ('/CropBox', PG.
- MEDIABOX))
+
+ bleedbox = _create_rectangle_accessor("/BleedBox", ("/CropBox", PG.MEDIABOX))
"""A :class:`RectangleObject<pypdf.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."""
- trimbox = _create_rectangle_accessor('/TrimBox', ('/CropBox', PG.MEDIABOX))
+
+ trimbox = _create_rectangle_accessor("/TrimBox", ("/CropBox", PG.MEDIABOX))
"""A :class:`RectangleObject<pypdf.generic.RectangleObject>`, expressed in
default user space units, defining the intended dimensions of the finished
page after trimming."""
- artbox = _create_rectangle_accessor('/ArtBox', ('/CropBox', PG.MEDIABOX))
+
+ artbox = _create_rectangle_accessor("/ArtBox", ("/CropBox", PG.MEDIABOX))
"""A :class:`RectangleObject<pypdf.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 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:
+ def annotations(self, value: Optional[ArrayObject]) -> None:
"""
Set the annotations array of the page.
@@ -686,94 +2207,105 @@ class PageObject(DictionaryObject):
If you append to it, remember to add the object first to the writer
and only add the indirect object.
"""
- pass
+ if value is None:
+ del self[NameObject("/Annots")]
+ else:
+ self[NameObject("/Annots")] = value
class _VirtualList(Sequence[PageObject]):
-
- def __init__(self, length_function: Callable[[], int], get_function:
- Callable[[int], PageObject]) ->None:
+ 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:
+ def __len__(self) -> int:
return self.length_function()
@overload
- def __getitem__(self, index: int) ->PageObject:
+ def __getitem__(self, index: int) -> PageObject:
...
@overload
- def __getitem__(self, index: slice) ->Sequence[PageObject]:
+ def __getitem__(self, index: slice) -> Sequence[PageObject]:
...
- def __getitem__(self, index: Union[int, slice]) ->Union[PageObject,
- Sequence[PageObject]]:
+ def __getitem__(
+ self, index: Union[int, slice]
+ ) -> Union[PageObject, Sequence[PageObject]]:
if isinstance(index, slice):
indices = range(*index.indices(len(self)))
cls = type(self)
return cls(indices.__len__, lambda idx: self[indices[idx]])
if not isinstance(index, int):
- raise TypeError('sequence indices must be integers')
+ 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')
+ raise IndexError("sequence index out of range")
return self.get_function(index)
- def __delitem__(self, index: Union[int, slice]) ->None:
+ def __delitem__(self, index: Union[int, slice]) -> None:
if isinstance(index, slice):
r = list(range(*index.indices(len(self))))
+ # pages have to be deleted from last to first
r.sort()
r.reverse()
for p in r:
- del self[p]
+ del self[p] # recursive call
return
if not isinstance(index, int):
- raise TypeError('index must be integers')
+ raise TypeError("index must be integers")
len_self = len(self)
if index < 0:
+ # support negative indexes
index = len_self + index
if index < 0 or index >= len_self:
- raise IndexError('index out of range')
+ raise IndexError("index out of range")
ind = self[index].indirect_reference
assert ind is not None
- parent = cast(DictionaryObject, ind.get_object()).get('/Parent', None)
+ parent = cast(DictionaryObject, ind.get_object()).get("/Parent", None)
while parent is not None:
parent = cast(DictionaryObject, parent.get_object())
try:
- i = parent['/Kids'].index(ind)
- del parent['/Kids'][i]
+ i = parent["/Kids"].index(ind)
+ del parent["/Kids"][i]
try:
assert ind is not None
- del ind.pdf.flattened_pages[index]
- except Exception:
+ del ind.pdf.flattened_pages[index] # case of page in a Reader
+ except Exception: # pragma: no cover
pass
- if '/Count' in parent:
- parent[NameObject('/Count')] = NumberObject(parent[
- '/Count'] - 1)
- if len(parent['/Kids']) == 0:
+ if "/Count" in parent:
+ parent[NameObject("/Count")] = NumberObject(parent["/Count"] - 1)
+ if len(parent["/Kids"]) == 0:
+ # No more objects in this part of this sub tree
ind = parent.indirect_reference
- parent = cast(DictionaryObject, parent.get('/Parent', None)
- )
+ parent = cast(DictionaryObject, parent.get("/Parent", None))
else:
parent = None
- except ValueError:
- raise PdfReadError(f'Page Not Found in Page Tree {ind}')
+ except ValueError: # from index
+ raise PdfReadError(f"Page Not Found in Page Tree {ind}")
- def __iter__(self) ->Iterator[PageObject]:
+ def __iter__(self) -> Iterator[PageObject]:
for i in range(len(self)):
yield self[i]
- def __str__(self) ->str:
- p = [f'PageObject({i})' for i in range(self.length_function())]
+ def __str__(self) -> str:
+ p = [f"PageObject({i})" for i in range(self.length_function())]
return f"[{', '.join(p)}]"
-def _get_fonts_walk(obj: DictionaryObject, fnt: Set[str], emb: Set[str]
- ) ->Tuple[Set[str], Set[str]]:
+def _get_fonts_walk(
+ obj: DictionaryObject,
+ fnt: Set[str],
+ emb: Set[str],
+) -> Tuple[Set[str], Set[str]]:
"""
Get the set of all fonts and all embedded fonts.
@@ -792,52 +2324,135 @@ def _get_fonts_walk(obj: DictionaryObject, fnt: Set[str], emb: Set[str]
We create and add to two sets, fnt = fonts used and emb = fonts embedded.
"""
- pass
+ fontkeys = ("/FontFile", "/FontFile2", "/FontFile3")
+
+ def process_font(f: DictionaryObject) -> None:
+ nonlocal fnt, emb
+ f = cast(DictionaryObject, f.get_object()) # to be sure
+ if "/BaseFont" in f:
+ fnt.add(cast(str, f["/BaseFont"]))
+
+ if (
+ ("/CharProcs" in f)
+ or (
+ "/FontDescriptor" in f
+ and any(
+ x in cast(DictionaryObject, f["/FontDescriptor"]) for x in fontkeys
+ )
+ )
+ or (
+ "/DescendantFonts" in f
+ and "/FontDescriptor"
+ in cast(
+ DictionaryObject,
+ cast(ArrayObject, f["/DescendantFonts"])[0].get_object(),
+ )
+ and any(
+ x
+ in cast(
+ DictionaryObject,
+ cast(
+ DictionaryObject,
+ cast(ArrayObject, f["/DescendantFonts"])[0].get_object(),
+ )["/FontDescriptor"],
+ )
+ for x in fontkeys
+ )
+ )
+ ):
+ # the list comprehension ensures there is FontFile
+ try:
+ emb.add(cast(str, f["/BaseFont"]))
+ except KeyError:
+ emb.add("(" + cast(str, f["/Subtype"]) + ")")
+
+ if "/DR" in obj and "/Font" in cast(DictionaryObject, obj["/DR"]):
+ for f in cast(DictionaryObject, cast(DictionaryObject, obj["/DR"])["/Font"]):
+ process_font(f)
+ if "/Resources" in obj:
+ if "/Font" in cast(DictionaryObject, obj["/Resources"]):
+ for f in cast(
+ DictionaryObject, cast(DictionaryObject, obj["/Resources"])["/Font"]
+ ).values():
+ process_font(f)
+ if "/XObject" in cast(DictionaryObject, obj["/Resources"]):
+ for x in cast(
+ DictionaryObject, cast(DictionaryObject, obj["/Resources"])["/XObject"]
+ ).values():
+ _get_fonts_walk(cast(DictionaryObject, x.get_object()), fnt, emb)
+ if "/Annots" in obj:
+ for a in cast(ArrayObject, obj["/Annots"]):
+ _get_fonts_walk(cast(DictionaryObject, a.get_object()), fnt, emb)
+ if "/AP" in obj:
+ if (
+ cast(DictionaryObject, cast(DictionaryObject, obj["/AP"])["/N"]).get(
+ "/Type"
+ )
+ == "/XObject"
+ ):
+ _get_fonts_walk(
+ cast(DictionaryObject, cast(DictionaryObject, obj["/AP"])["/N"]),
+ fnt,
+ emb,
+ )
+ else:
+ for a in cast(DictionaryObject, cast(DictionaryObject, obj["/AP"])["/N"]):
+ _get_fonts_walk(cast(DictionaryObject, a), fnt, emb)
+ return fnt, emb # return the sets for each page
class _VirtualListImages(Sequence[ImageFile]):
-
- def __init__(self, ids_function: Callable[[], List[Union[str, List[str]
- ]]], get_function: Callable[[Union[str, List[str], Tuple[str]]],
- ImageFile]) ->None:
+ def __init__(
+ self,
+ ids_function: Callable[[], List[Union[str, List[str]]]],
+ get_function: Callable[[Union[str, List[str], Tuple[str]]], ImageFile],
+ ) -> None:
self.ids_function = ids_function
self.get_function = get_function
self.current = -1
- def __len__(self) ->int:
+ def __len__(self) -> int:
return len(self.ids_function())
+ def keys(self) -> List[Union[str, List[str]]]:
+ return self.ids_function()
+
+ def items(self) -> List[Tuple[Union[str, List[str]], ImageFile]]:
+ return [(x, self[x]) for x in self.ids_function()]
+
@overload
- def __getitem__(self, index: Union[int, str, List[str]]) ->ImageFile:
+ def __getitem__(self, index: Union[int, str, List[str]]) -> ImageFile:
...
@overload
- def __getitem__(self, index: slice) ->Sequence[ImageFile]:
+ def __getitem__(self, index: slice) -> Sequence[ImageFile]:
...
- def __getitem__(self, index: Union[int, slice, str, List[str], Tuple[str]]
- ) ->Union[ImageFile, Sequence[ImageFile]]:
+ def __getitem__(
+ self, index: Union[int, slice, str, List[str], Tuple[str]]
+ ) -> Union[ImageFile, Sequence[ImageFile]]:
lst = self.ids_function()
if isinstance(index, slice):
indices = range(*index.indices(len(self)))
lst = [lst[x] for x in indices]
cls = type(self)
- return cls(lambda : lst, self.get_function)
+ return cls((lambda: lst), self.get_function)
if isinstance(index, (str, list, tuple)):
return self.get_function(index)
if not isinstance(index, int):
- raise TypeError('invalid sequence indices type')
+ raise TypeError("invalid sequence indices type")
len_self = len(lst)
if index < 0:
+ # support negative indexes
index = len_self + index
if index < 0 or index >= len_self:
- raise IndexError('sequence index out of range')
+ raise IndexError("sequence index out of range")
return self.get_function(lst[index])
- def __iter__(self) ->Iterator[ImageFile]:
+ def __iter__(self) -> Iterator[ImageFile]:
for i in range(len(self)):
yield self[i]
- def __str__(self) ->str:
- p = [f'Image_{i}={n}' for i, n in enumerate(self.ids_function())]
+ def __str__(self) -> str:
+ p = [f"Image_{i}={n}" for i, n in enumerate(self.ids_function())]
return f"[{', '.join(p)}]"
diff --git a/pypdf/_page_labels.py b/pypdf/_page_labels.py
index f0613016..b0252795 100644
--- a/pypdf/_page_labels.py
+++ b/pypdf/_page_labels.py
@@ -57,13 +57,103 @@ A Uppercase letters (A to Z for the first 26 pages,
a Lowercase letters (a to z for the first 26 pages,
aa to zz for the next 26, and so on)
"""
+
from typing import Iterator, List, Optional, Tuple, cast
+
from ._protocols import PdfCommonDocProtocol
from ._utils import logger_warning
from .generic import ArrayObject, DictionaryObject, NullObject, NumberObject
-def index2label(reader: PdfCommonDocProtocol, index: int) ->str:
+def number2uppercase_roman_numeral(num: int) -> str:
+ roman = [
+ (1000, "M"),
+ (900, "CM"),
+ (500, "D"),
+ (400, "CD"),
+ (100, "C"),
+ (90, "XC"),
+ (50, "L"),
+ (40, "XL"),
+ (10, "X"),
+ (9, "IX"),
+ (5, "V"),
+ (4, "IV"),
+ (1, "I"),
+ ]
+
+ def roman_num(num: int) -> Iterator[str]:
+ for decimal, roman_repr in roman:
+ x, _ = divmod(num, decimal)
+ yield roman_repr * x
+ num -= decimal * x
+ if num <= 0:
+ break
+
+ return "".join(list(roman_num(num)))
+
+
+def number2lowercase_roman_numeral(number: int) -> str:
+ return number2uppercase_roman_numeral(number).lower()
+
+
+def number2uppercase_letter(number: int) -> str:
+ if number <= 0:
+ raise ValueError("Expecting a positive number")
+ alphabet = [chr(i) for i in range(ord("A"), ord("Z") + 1)]
+ rep = ""
+ while number > 0:
+ remainder = number % 26
+ if remainder == 0:
+ remainder = 26
+ rep = alphabet[remainder - 1] + rep
+ # update
+ number -= remainder
+ number = number // 26
+ return rep
+
+
+def number2lowercase_letter(number: int) -> str:
+ return number2uppercase_letter(number).lower()
+
+
+def get_label_from_nums(dictionary_object: DictionaryObject, index: int) -> str:
+ # [Nums] shall be an array of the form
+ # [ key 1 value 1 key 2 value 2 ... key n value n ]
+ # where each key_i is an integer and the corresponding
+ # value_i shall be the object associated with that key.
+ # The keys shall be sorted in numerical order,
+ # analogously to the arrangement of keys in a name tree
+ # as described in 7.9.6, "Name Trees."
+ nums = cast(ArrayObject, dictionary_object["/Nums"])
+ i = 0
+ value = None
+ start_index = 0
+ while i < len(nums):
+ start_index = nums[i]
+ value = nums[i + 1].get_object()
+ if i + 2 == len(nums):
+ break
+ if nums[i + 2] > index:
+ break
+ i += 2
+ m = {
+ None: lambda n: "",
+ "/D": lambda n: str(n),
+ "/R": number2uppercase_roman_numeral,
+ "/r": number2lowercase_roman_numeral,
+ "/A": number2uppercase_letter,
+ "/a": number2lowercase_letter,
+ }
+ # if /Nums array is not following the specification or if /Nums is empty
+ if not isinstance(value, dict):
+ return str(index + 1) # Fallback
+ start = value.get("/St", 1)
+ prefix = value.get("/P", "")
+ return prefix + m[value.get("/S")](index - start_index + start)
+
+
+def index2label(reader: PdfCommonDocProtocol, index: int) -> str:
"""
See 7.9.7 "Number Trees".
@@ -74,11 +164,49 @@ def index2label(reader: PdfCommonDocProtocol, index: int) ->str:
Returns:
The label of the page, e.g. "iv" or "4".
"""
- pass
+ root = cast(DictionaryObject, reader.root_object)
+ if "/PageLabels" not in root:
+ return str(index + 1) # Fallback
+ number_tree = cast(DictionaryObject, root["/PageLabels"].get_object())
+ if "/Nums" in number_tree:
+ return get_label_from_nums(number_tree, index)
+ if "/Kids" in number_tree and not isinstance(number_tree["/Kids"], NullObject):
+ # number_tree = {'/Kids': [IndirectObject(7333, 0, 140132998195856), ...]}
+ # Limit maximum depth.
+ level = 0
+ while level < 100:
+ kids = cast(List[DictionaryObject], number_tree["/Kids"])
+ for kid in kids:
+ # kid = {'/Limits': [0, 63], '/Nums': [0, {'/P': 'C1'}, ...]}
+ limits = cast(List[int], kid["/Limits"])
+ if limits[0] <= index <= limits[1]:
+ if kid.get("/Kids", None) is not None:
+ # Recursive definition.
+ level += 1
+ if level == 100: # pragma: no cover
+ raise NotImplementedError("Too deep nesting is not supported.")
+ number_tree = kid
+ # Exit the inner `for` loop and continue at the next level with the
+ # next iteration of the `while` loop.
+ break
+ return get_label_from_nums(kid, index)
+ else:
+ # When there are no kids, make sure to exit the `while` loop directly
+ # and continue with the fallback.
+ break
+
+ logger_warning(
+ f"Could not reliably determine page label for {index}.",
+ __name__
+ )
+ return str(index + 1) # Fallback if neither /Nums nor /Kids is in the number_tree
-def nums_insert(key: NumberObject, value: DictionaryObject, nums: ArrayObject
- ) ->None:
+def nums_insert(
+ key: NumberObject,
+ value: DictionaryObject,
+ nums: ArrayObject,
+) -> None:
"""
Insert a key, value pair in a Nums array.
@@ -89,11 +217,25 @@ def nums_insert(key: NumberObject, value: DictionaryObject, nums: ArrayObject
value: value of the entry
nums: Nums array to modify
"""
- pass
+ if len(nums) % 2 != 0:
+ raise ValueError("a nums like array must have an even number of elements")
+ i = len(nums)
+ while i != 0 and key <= nums[i - 2]:
+ i = i - 2
-def nums_clear_range(key: NumberObject, page_index_to: int, nums: ArrayObject
- ) ->None:
+ if i < len(nums) and key == nums[i]:
+ nums[i + 1] = value
+ else:
+ nums.insert(i, key)
+ nums.insert(i + 1, value)
+
+
+def nums_clear_range(
+ key: NumberObject,
+ page_index_to: int,
+ nums: ArrayObject,
+) -> None:
"""
Remove all entries in a number tree in a range after an entry.
@@ -104,11 +246,21 @@ def nums_clear_range(key: NumberObject, page_index_to: int, nums: ArrayObject
page_index_to: The page index of the upper limit of the range
nums: Nums array to modify
"""
- pass
+ if len(nums) % 2 != 0:
+ raise ValueError("a nums like array must have an even number of elements")
+ if page_index_to < key:
+ raise ValueError("page_index_to must be greater or equal than key")
+ i = nums.index(key) + 2
+ while i < len(nums) and nums[i] <= page_index_to:
+ nums.pop(i)
+ nums.pop(i)
-def nums_next(key: NumberObject, nums: ArrayObject) ->Tuple[Optional[
- NumberObject], Optional[DictionaryObject]]:
+
+def nums_next(
+ key: NumberObject,
+ nums: ArrayObject,
+) -> Tuple[Optional[NumberObject], Optional[DictionaryObject]]:
"""
Return the (key, value) pair of the entry after the given one.
@@ -118,4 +270,11 @@ def nums_next(key: NumberObject, nums: ArrayObject) ->Tuple[Optional[
key: number key of the entry
nums: Nums array
"""
- pass
+ if len(nums) % 2 != 0:
+ raise ValueError("a nums like array must have an even number of elements")
+
+ i = nums.index(key) + 2
+ if i < len(nums):
+ return (nums[i], nums[i + 1])
+ else:
+ return (None, None)
diff --git a/pypdf/_protocols.py b/pypdf/_protocols.py
index 2ae0694c..9f413660 100644
--- a/pypdf/_protocols.py
+++ b/pypdf/_protocols.py
@@ -1,30 +1,89 @@
"""Helpers for working with PDF types."""
+
from abc import abstractmethod
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
except ImportError:
- from typing_extensions import Protocol
+ from typing_extensions import Protocol # type: ignore[assignment]
+
from ._utils import StrByteType, StreamType
class PdfObjectProtocol(Protocol):
indirect_reference: Any
+ def clone(
+ self,
+ pdf_dest: Any,
+ force_duplicate: bool = False,
+ ignore_fields: Union[Tuple[str, ...], List[str], None] = (),
+ ) -> Any:
+ ... # pragma: no cover
+
+ def _reference_clone(self, clone: Any, pdf_dest: Any) -> Any:
+ ... # pragma: no cover
+
+ def get_object(self) -> Optional["PdfObjectProtocol"]:
+ ... # pragma: no cover
+
+ def hash_value(self) -> bytes:
+ ... # pragma: no cover
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ ... # pragma: no cover
+
class XmpInformationProtocol(PdfObjectProtocol):
pass
class PdfCommonDocProtocol(Protocol):
- pass
+ @property
+ def pdf_header(self) -> str:
+ ... # pragma: no cover
+
+ @property
+ def pages(self) -> List[Any]:
+ ... # pragma: no cover
+
+ @property
+ def root_object(self) -> PdfObjectProtocol:
+ ... # pragma: no cover
+
+ def get_object(self, indirect_reference: Any) -> Optional[PdfObjectProtocol]:
+ ... # pragma: no cover
+
+ @property
+ def strict(self) -> bool:
+ ... # pragma: no cover
class PdfReaderProtocol(PdfCommonDocProtocol, Protocol):
- pass
+ @property
+ @abstractmethod
+ def xref(self) -> Dict[int, Dict[int, Any]]:
+ ... # pragma: no cover
+
+ @property
+ @abstractmethod
+ def trailer(self) -> Dict[str, Any]:
+ ... # pragma: no cover
class PdfWriterProtocol(PdfCommonDocProtocol, Protocol):
_objects: List[Any]
_id_translated: Dict[int, Dict[int, int]]
+
+ @abstractmethod
+ def write(self, stream: Union[Path, StrByteType]) -> Tuple[bool, IO[Any]]:
+ ... # pragma: no cover
+
+ @abstractmethod
+ def _add_object(self, obj: Any) -> Any:
+ ... # pragma: no cover
diff --git a/pypdf/_reader.py b/pypdf/_reader.py
index aa95113d..aeababa7 100644
--- a/pypdf/_reader.py
+++ b/pypdf/_reader.py
@@ -1,16 +1,86 @@
+# 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
from io import BytesIO, UnsupportedOperation
from pathlib import Path
from types import TracebackType
-from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Type, Union, cast
+from typing import (
+ Any,
+ Callable,
+ Dict,
+ Iterable,
+ List,
+ Optional,
+ Tuple,
+ Type,
+ Union,
+ cast,
+)
+
from ._doc_common import PdfDocCommon, convert_to_int
from ._encryption import Encryption, PasswordType
from ._page import PageObject
-from ._utils import StrByteType, StreamType, b_, logger_warning, read_non_whitespace, read_previous_line, read_until_whitespace, skip_over_comment, skip_over_whitespace
+from ._utils import (
+ StrByteType,
+ StreamType,
+ b_,
+ logger_warning,
+ read_non_whitespace,
+ read_previous_line,
+ read_until_whitespace,
+ skip_over_comment,
+ skip_over_whitespace,
+)
from .constants import TrailerKeys as TK
-from .errors import EmptyFileError, FileNotDecryptedError, PdfReadError, PdfStreamError, WrongPasswordError
-from .generic import ArrayObject, ContentStream, DecodedStreamObject, DictionaryObject, EncodedStreamObject, IndirectObject, NameObject, NullObject, NumberObject, PdfObject, TextStringObject, read_object
+from .errors import (
+ EmptyFileError,
+ FileNotDecryptedError,
+ PdfReadError,
+ PdfStreamError,
+ WrongPasswordError,
+)
+from .generic import (
+ ArrayObject,
+ ContentStream,
+ DecodedStreamObject,
+ DictionaryObject,
+ EncodedStreamObject,
+ IndirectObject,
+ NameObject,
+ NullObject,
+ NumberObject,
+ PdfObject,
+ TextStringObject,
+ read_object,
+)
from .xmp import XmpInformation
@@ -33,84 +103,128 @@ class PdfReader(PdfDocCommon):
Defaults to ``None``.
"""
- def __init__(self, stream: Union[StrByteType, Path], strict: bool=False,
- password: Union[None, str, bytes]=None) ->None:
+ def __init__(
+ self,
+ stream: Union[StrByteType, Path],
+ strict: bool = False,
+ password: Union[None, str, bytes] = None,
+ ) -> None:
self.strict = strict
self.flattened_pages: Optional[List[PageObject]] = None
+ #: Storage of parsed PDF objects.
self.resolved_objects: Dict[Tuple[Any, Any], Optional[PdfObject]] = {}
+
self.xref_index = 0
self.xref: Dict[int, Dict[Any, Any]] = {}
self.xref_free_entry: Dict[int, Dict[Any, Any]] = {}
self.xref_objStm: Dict[int, Tuple[Any, Any]] = {}
self.trailer = DictionaryObject()
- self._page_id2num: Optional[Dict[Any, Any]] = None
- if hasattr(stream, 'mode') and 'b' not in stream.mode:
+
+ 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:
logger_warning(
- 'PdfReader stream/file object is not in binary mode. It may not be read correctly.'
- , __name__)
+ "PdfReader stream/file object is not in binary mode. "
+ "It may not be read correctly.",
+ __name__,
+ )
self._stream_opened = False
if isinstance(stream, (str, Path)):
- with open(stream, 'rb') as fh:
+ with open(stream, "rb") as fh:
stream = BytesIO(fh.read())
self._stream_opened = True
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/py-pdf/pypdf/issues/608
id_entry = self.trailer.get(TK.ID)
- id1_entry = id_entry[0].get_object(
- ).original_bytes if id_entry else b''
- encrypt_entry = cast(DictionaryObject, self.trailer[TK.ENCRYPT]
- .get_object())
+ 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)
- pwd = password if password is not None else b''
- if self._encryption.verify(pwd
- ) == PasswordType.NOT_DECRYPTED and password is not None:
- raise WrongPasswordError('Wrong password')
+
+ # 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
elif password is not None:
- raise PdfReadError('Not encrypted file')
+ raise PdfReadError("Not encrypted file")
- def __enter__(self) ->'PdfReader':
+ def __enter__(self) -> "PdfReader":
return self
- def __exit__(self, exc_type: Optional[Type[BaseException]], exc_val:
- Optional[BaseException], exc_tb: Optional[TracebackType]) ->None:
+ def __exit__(
+ self,
+ exc_type: Optional[Type[BaseException]],
+ exc_val: Optional[BaseException],
+ exc_tb: Optional[TracebackType],
+ ) -> None:
self.close()
- def close(self) ->None:
+ def close(self) -> None:
"""Close the stream if opened in __init__ and clear memory."""
- pass
+ if self._stream_opened:
+ self.stream.close()
+ self.flattened_pages = []
+ self.resolved_objects = {}
+ self.trailer = DictionaryObject()
+ self.xref = {}
+ self.xref_free_entry = {}
+ self.xref_objStm = {}
@property
- def root_object(self) ->DictionaryObject:
+ def root_object(self) -> DictionaryObject:
"""Provide access to "/Root". Standardized with PdfWriter."""
- pass
+ return cast(DictionaryObject, self.trailer[TK.ROOT].get_object())
@property
- def _info(self) ->Optional[DictionaryObject]:
+ def _info(self) -> Optional[DictionaryObject]:
"""
Provide access to "/Info". Standardized with PdfWriter.
Returns:
/Info Dictionary; None if the entry does not exist
"""
- pass
+ info = self.trailer.get(TK.INFO, None)
+ if info is None:
+ return None
+ else:
+ info = info.get_object()
+ if info is None:
+ raise PdfReadError(
+ "Trailer not found or does not point to document information directory"
+ )
+ return cast(DictionaryObject, info)
@property
- def _ID(self) ->Optional[ArrayObject]:
+ def _ID(self) -> Optional[ArrayObject]:
"""
Provide access to "/ID". Standardized with PdfWriter.
Returns:
/ID array; None if the entry does not exist
"""
- pass
+ id = self.trailer.get(TK.ID, None)
+ return None if id is None else cast(ArrayObject, id.get_object())
- def _repr_mimebundle_(self, include: Union[None, Iterable[str]]=None,
- exclude: Union[None, Iterable[str]]=None) ->Dict[str, Any]:
+ def _repr_mimebundle_(
+ self,
+ include: Union[None, Iterable[str]] = None,
+ exclude: Union[None, Iterable[str]] = None,
+ ) -> Dict[str, Any]:
"""
Integration into Jupyter Notebooks.
@@ -119,24 +233,48 @@ class PdfReader(PdfDocCommon):
See https://ipython.readthedocs.io/en/stable/config/integrating.html
"""
- pass
+ self.stream.seek(0)
+ pdf_data = self.stream.read()
+ data = {
+ "application/pdf": pdf_data,
+ }
+
+ if include is not None:
+ # Filter representations based on include list
+ data = {k: v for k, v in data.items() if k in include}
+
+ if exclude is not None:
+ # Remove representations based on exclude list
+ data = {k: v for k, v in data.items() if k not in exclude}
+
+ return data
@property
- def pdf_header(self) ->str:
+ def pdf_header(self) -> str:
"""
The first 8 bytes of the file.
This is typically something like ``'%PDF-1.6'`` and can be used to
detect if the file is actually a PDF file and which version it is.
"""
- pass
+ # TODO: Make this return a bytes object for consistency
+ # but that needs a deprecation
+ loc = self.stream.tell()
+ self.stream.seek(0, 0)
+ pdf_file_version = self.stream.read(8).decode("utf-8", "backslashreplace")
+ self.stream.seek(loc, 0) # return to where it was
+ return pdf_file_version
@property
- def xmp_metadata(self) ->Optional[XmpInformation]:
+ def xmp_metadata(self) -> Optional[XmpInformation]:
"""XMP (Extensible Metadata Platform) data."""
- pass
+ try:
+ self._override_encryption = True
+ return cast(XmpInformation, self.root_object.xmp_metadata)
+ finally:
+ self._override_encryption = False
- def _get_page(self, page_number: int) ->PageObject:
+ def _get_page(self, page_number: int) -> PageObject:
"""
Retrieve a page by number from this PDF file.
@@ -147,10 +285,14 @@ class PdfReader(PdfDocCommon):
Returns:
A :class:`PageObject<pypdf._page.PageObject>` instance.
"""
- pass
+ if self.flattened_pages is None:
+ self._flatten()
+ assert self.flattened_pages is not None, "hint for mypy"
+ return self.flattened_pages[page_number]
- def _get_page_number_by_indirect(self, indirect_reference: Union[None,
- int, NullObject, IndirectObject]) ->Optional[int]:
+ def _get_page_number_by_indirect(
+ self, indirect_reference: Union[None, int, NullObject, IndirectObject]
+ ) -> Optional[int]:
"""
Generate _page_id2num.
@@ -160,13 +302,349 @@ class PdfReader(PdfDocCommon):
Returns:
The page number or None
"""
- pass
+ 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 None
+ 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, None)
+ return ret
+
+ 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()))
+ for i in range(obj_stm["/N"]): # type: ignore
+ read_non_whitespace(stream_data)
+ stream_data.seek(-1, 1)
+ objnum = NumberObject.read_from_stream(stream_data)
+ read_non_whitespace(stream_data)
+ stream_data.seek(-1, 1)
+ offset = NumberObject.read_from_stream(stream_data)
+ read_non_whitespace(stream_data)
+ stream_data.seek(-1, 1)
+ if objnum != indirect_reference.idnum:
+ # We're only interested in one object
+ continue
+ if self.strict and idx != i:
+ raise PdfReadError("Object is in wrong index.")
+ stream_data.seek(int(obj_stm["/First"] + offset), 0) # type: ignore
+
+ # to cope with some case where the 'pointer' is on a white space
+ read_non_whitespace(stream_data)
+ stream_data.seek(-1, 1)
+
+ try:
+ obj = read_object(stream_data, self)
+ except PdfStreamError as exc:
+ # Stream object cannot be read. Normally, a critical error, but
+ # Adobe Reader doesn't complain, so continue (in strict mode?)
+ logger_warning(
+ f"Invalid stream (index {i}) within object "
+ f"{indirect_reference.idnum} {indirect_reference.generation}: "
+ f"{exc}",
+ __name__,
+ )
+
+ if self.strict: # pragma: no cover
+ raise PdfReadError(
+ f"Cannot read object stream: {exc}"
+ ) # pragma: no cover
+ # Replace with null. Hopefully it's nothing important.
+ obj = NullObject() # pragma: no cover
+ return obj
+
+ if self.strict: # pragma: no cover
+ raise PdfReadError(
+ "This is a fatal error in strict mode."
+ ) # pragma: no cover
+ return NullObject() # pragma: no cover
+
+ def get_object(
+ self, indirect_reference: Union[int, IndirectObject]
+ ) -> Optional[PdfObject]:
+ if isinstance(indirect_reference, int):
+ indirect_reference = IndirectObject(indirect_reference, 0, self)
+ retval = self.cache_get_indirect_object(
+ indirect_reference.generation, indirect_reference.idnum
+ )
+ if retval is not None:
+ return retval
+ if (
+ indirect_reference.generation == 0
+ and indirect_reference.idnum in self.xref_objStm
+ ):
+ retval = self._get_object_from_stream(indirect_reference) # type: ignore
+ elif (
+ indirect_reference.generation in self.xref
+ and indirect_reference.idnum in self.xref[indirect_reference.generation]
+ ):
+ if self.xref_free_entry.get(indirect_reference.generation, {}).get(
+ indirect_reference.idnum, False
+ ):
+ return NullObject()
+ start = self.xref[indirect_reference.generation][indirect_reference.idnum]
+ self.stream.seek(start, 0)
+ try:
+ idnum, generation = self.read_object_header(self.stream)
+ if (
+ idnum != indirect_reference.idnum
+ or generation != indirect_reference.generation
+ ):
+ raise PdfReadError("not matching, we parse the file for it")
+ except Exception:
+ if hasattr(self.stream, "getbuffer"):
+ buf = bytes(self.stream.getbuffer())
+ else:
+ p = self.stream.tell()
+ self.stream.seek(0, 0)
+ buf = self.stream.read(-1)
+ self.stream.seek(p, 0)
+ m = re.search(
+ rf"\s{indirect_reference.idnum}\s+{indirect_reference.generation}\s+obj".encode(),
+ buf,
+ )
+ if m is not None:
+ logger_warning(
+ f"Object ID {indirect_reference.idnum},{indirect_reference.generation} ref repaired",
+ __name__,
+ )
+ self.xref[indirect_reference.generation][
+ indirect_reference.idnum
+ ] = (m.start(0) + 1)
+ self.stream.seek(m.start(0) + 1)
+ idnum, generation = self.read_object_header(self.stream)
+ else:
+ idnum = -1
+ generation = -1 # exception will be raised below
+ if idnum != indirect_reference.idnum and self.xref_index:
+ # Xref table probably had bad indexes due to not being zero-indexed
+ if self.strict:
+ raise PdfReadError(
+ f"Expected object ID ({indirect_reference.idnum} {indirect_reference.generation}) "
+ f"does not match actual ({idnum} {generation}); "
+ "xref table not zero-indexed."
+ )
+ # xref table is corrected in non-strict mode
+ elif idnum != indirect_reference.idnum and self.strict:
+ # some other problem
+ raise PdfReadError(
+ f"Expected object ID ({indirect_reference.idnum} "
+ 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())
+ else:
+ p = self.stream.tell()
+ self.stream.seek(0, 0)
+ buf = self.stream.read(-1)
+ self.stream.seek(p, 0)
+ m = re.search(
+ rf"\s{indirect_reference.idnum}\s+{indirect_reference.generation}\s+obj".encode(),
+ buf,
+ )
+ if m is not None:
+ logger_warning(
+ f"Object {indirect_reference.idnum} {indirect_reference.generation} found",
+ __name__,
+ )
+ if indirect_reference.generation not in self.xref:
+ self.xref[indirect_reference.generation] = {}
+ self.xref[indirect_reference.generation][indirect_reference.idnum] = (
+ m.start(0) + 1
+ )
+ self.stream.seek(m.end(0) + 1)
+ skip_over_whitespace(self.stream)
+ self.stream.seek(-1, 1)
+ retval = read_object(self.stream, self) # type: ignore
+
+ # override encryption is used for the /Encrypt dictionary
+ if not self._override_encryption and self._encryption is not None:
+ # if we don't have the encryption key:
+ if not self._encryption.is_decrypted():
+ raise FileNotDecryptedError("File has not been decrypted")
+ # otherwise, decrypt here...
+ retval = cast(PdfObject, retval)
+ retval = self._encryption.decrypt_object(
+ retval, indirect_reference.idnum, indirect_reference.generation
+ )
+ else:
+ logger_warning(
+ f"Object {indirect_reference.idnum} {indirect_reference.generation} not defined.",
+ __name__,
+ )
+ if self.strict:
+ raise PdfReadError("Could not find object.")
+ self.cache_indirect_object(
+ indirect_reference.generation, indirect_reference.idnum, retval
+ )
+ return retval
+
+ def read_object_header(self, stream: StreamType) -> Tuple[int, int]:
+ # Should never be necessary to read out whitespace, since the
+ # cross-reference table should put us in the right spot to read the
+ # object header. In reality some files have stupid cross reference
+ # tables that are off by whitespace bytes.
+ 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)
+
+ read_non_whitespace(stream)
+ stream.seek(-1, 1)
+ if extra and self.strict:
+ logger_warning(
+ f"Superfluous whitespace found in object header {idnum} {generation}", # type: ignore
+ __name__,
+ )
+ return int(idnum), int(generation)
+
+ def cache_get_indirect_object(
+ self, generation: int, idnum: int
+ ) -> Optional[PdfObject]:
+ return self.resolved_objects.get((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 _replace_object(self, indirect: IndirectObject, obj: PdfObject) -> PdfObject:
+ # function reserved for future dev
+ if indirect.pdf != self:
+ raise ValueError("Cannot update PdfReader with external object")
+ if (indirect.generation, indirect.idnum) not in self.resolved_objects:
+ raise ValueError("Cannot find referenced object")
+ self.resolved_objects[(indirect.generation, indirect.idnum)] = obj
+ obj.indirect_reference = indirect
+ return obj
+
+ def read(self, stream: StreamType) -> None:
+ self._basic_validation(stream)
+ self._find_eof_marker(stream)
+ startxref = self._find_startxref_pos(stream)
- def _basic_validation(self, stream: StreamType) ->None:
+ # 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 damage
+ for id in xref_k:
+ stream.seek(xref_entry[id], 0)
+ try:
+ pid, _pgen = self.read_object_header(stream)
+ except ValueError:
+ self._rebuild_xref_table(stream)
+ break
+ if pid == id - self.xref_index:
+ # fixing index item per item is required for revised PDF.
+ self.xref[gen][pid] = self.xref[gen][id]
+ del self.xref[gen][id]
+ # if not, then either it's just plain wrong, or the
+ # non-zero-index is actually correct
+ stream.seek(loc, 0) # return to where it was
+
+ # remove wrong objects (not pointing to correct structures) - cf #2326
+ if not self.strict:
+ loc = stream.tell()
+ for gen, xref_entry in self.xref.items():
+ if gen == 65535:
+ continue
+ ids = list(xref_entry.keys())
+ for id in ids:
+ stream.seek(xref_entry[id], 0)
+ try:
+ self.read_object_header(stream)
+ except ValueError:
+ logger_warning(
+ f"Ignoring wrong pointing object {id} {gen} (offset {xref_entry[id]})",
+ __name__,
+ )
+ del xref_entry[id] # we can delete the id, we are parsing ids
+ stream.seek(loc, 0) # return to where it was
+
+ def _basic_validation(self, stream: StreamType) -> None:
"""Ensure file is not empty. Read at most 5 bytes."""
- pass
+ stream.seek(0, os.SEEK_SET)
+ try:
+ header_byte = stream.read(5)
+ except UnicodeDecodeError:
+ raise UnsupportedOperation("cannot read header")
+ if header_byte == b"":
+ raise EmptyFileError("Cannot read an empty file")
+ elif header_byte != b"%PDF-":
+ if self.strict:
+ raise PdfReadError(
+ f"PDF starts with '{header_byte.decode('utf8')}', "
+ "but '%PDF-' expected"
+ )
+ else:
+ logger_warning(f"invalid pdf header: {header_byte}", __name__)
+ stream.seek(0, os.SEEK_END)
- def _find_eof_marker(self, stream: StreamType) ->None:
+ def _find_eof_marker(self, stream: StreamType) -> None:
"""
Jump to the %%EOF marker.
@@ -174,9 +652,17 @@ class PdfReader(PdfDocCommon):
the file. Hence for standard-compliant PDF documents this function will
read only the last part (DEFAULT_BUFFER_SIZE).
"""
- pass
+ HEADER_SIZE = 8 # to parse whole file, Header is e.g. '%PDF-1.6'
+ line = b""
+ while line[:5] != b"%%EOF":
+ if stream.tell() < HEADER_SIZE:
+ if self.strict:
+ raise PdfReadError("EOF marker not found")
+ else:
+ logger_warning("EOF marker not found", __name__)
+ line = read_previous_line(stream)
- def _find_startxref_pos(self, stream: StreamType) ->int:
+ def _find_startxref_pos(self, stream: StreamType) -> int:
"""
Find startxref entry - the location of the xref table.
@@ -186,10 +672,299 @@ class PdfReader(PdfDocCommon):
Returns:
The bytes offset
"""
- pass
+ 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(3)
+ if ref != b"ref":
+ raise PdfReadError("xref table read error")
+ read_non_whitespace(stream)
+ stream.seek(-1, 1)
+ first_time = True # check if the first time looking at the xref table
+ while True:
+ num = cast(int, read_object(stream, self))
+ if first_time and num != 0:
+ self.xref_index = num
+ if self.strict:
+ logger_warning(
+ "Xref table not zero-indexed. ID numbers for objects will be corrected.",
+ __name__,
+ )
+ # if table not zero indexed, could be due to error from when PDF was created
+ # which will lead to mismatched indices later on, only warned and corrected if self.strict==True
+ first_time = False
+ read_non_whitespace(stream)
+ stream.seek(-1, 1)
+ size = cast(int, read_object(stream, self))
+ if not isinstance(size, int):
+ logger_warning(
+ "Invalid/Truncated xref table. Rebuilding it.",
+ __name__,
+ )
+ self._rebuild_xref_table(stream)
+ stream.read()
+ return
+ read_non_whitespace(stream)
+ stream.seek(-1, 1)
+ cnt = 0
+ while cnt < size:
+ line = stream.read(20)
+
+ # 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 occurred
+ if hasattr(stream, "getbuffer"):
+ buf = bytes(stream.getbuffer())
+ else:
+ p = stream.tell()
+ stream.seek(0, 0)
+ buf = stream.read(-1)
+ stream.seek(p)
+
+ f = re.search(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:
+ if entry_type_b == b"n":
+ self.xref[generation][num] = offset
+ try:
+ self.xref_free_entry[generation][num] = entry_type_b == b"f"
+ except Exception:
+ pass
+ try:
+ self.xref_free_entry[65535][num] = entry_type_b == b"f"
+ except Exception:
+ pass
+ cnt += 1
+ num += 1
+ read_non_whitespace(stream)
+ stream.seek(-1, 1)
+ trailer_tag = stream.read(7)
+ if trailer_tag != b"trailer":
+ # more xrefs!
+ stream.seek(-7, 1)
+ else:
+ break
+
+ def _read_xref_tables_and_trailers(
+ self, stream: StreamType, startxref: Optional[int], xref_issue_nr: int
+ ) -> None:
+ self.xref = {}
+ self.xref_free_entry = {}
+ self.xref_objStm = {}
+ self.trailer = DictionaryObject()
+ while startxref is not None:
+ # load the xref table
+ stream.seek(startxref, 0)
+ x = stream.read(1)
+ if x in b"\r\n":
+ x = stream.read(1)
+ if x == b"x":
+ startxref = self._read_xref(stream)
+ elif xref_issue_nr:
+ try:
+ self._rebuild_xref_table(stream)
+ break
+ except Exception:
+ xref_issue_nr = 0
+ elif x.isdigit():
+ try:
+ xrefstream = self._read_pdf15_xref_stream(stream)
+ except Exception as e:
+ if TK.ROOT in self.trailer:
+ logger_warning(
+ f"Previous trailer 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, TK.SIZE
+ for key in trailer_keys:
+ if key in xrefstream and key not in self.trailer:
+ self.trailer[NameObject(key)] = xrefstream.raw_get(key)
+ if "/XRefStm" in xrefstream:
+ p = 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)
+ if stream.read(1) == b"":
+ return None
+ stream.seek(-1, 1)
+ read_non_whitespace(stream)
+ stream.seek(-1, 1)
+ new_trailer = cast(Dict[str, Any], read_object(stream, self))
+ for key, value in new_trailer.items():
+ if key not in self.trailer:
+ self.trailer[key] = value
+ if "/XRefStm" in new_trailer:
+ p = stream.tell()
+ stream.seek(cast(int, new_trailer["/XRefStm"]) + 1, 0)
+ try:
+ self._read_pdf15_xref_stream(stream)
+ except Exception:
+ logger_warning(
+ f"XRef object at {new_trailer['/XRefStm']} can not be read, some object may be missing",
+ __name__,
+ )
+ stream.seek(p, 0)
+ if "/Prev" in new_trailer:
+ 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(25): # value extended to cope with more linearized files
+ if stream.read(1).isdigit():
+ # This is not a standard PDF, consider adding a warning
+ startxref += look
+ return startxref
+ # no xref table found at specified location
+ if "/Root" in self.trailer and not self.strict:
+ # if Root has been already found, just raise warning
+ logger_warning("Invalid parent xref., rebuild xref", __name__)
+ try:
+ self._rebuild_xref_table(stream)
+ return None
+ except Exception:
+ raise PdfReadError("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:
+ def _get_xref_issues(stream: StreamType, startxref: int) -> int:
"""
Return an int which indicates an issue. 0 means there is no issue.
@@ -200,9 +975,87 @@ class PdfReader(PdfDocCommon):
Returns:
0 means no issue, other values represent specific issues.
"""
- pass
+ stream.seek(startxref - 1, 0) # -1 to check character before
+ line = stream.read(1)
+ if line == b"j":
+ line = stream.read(1)
+ if line not in b"\r\n \t":
+ return 1
+ line = stream.read(4)
+ if line != b"xref":
+ # not 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
+ return 0
+
+ def _rebuild_xref_table(self, stream: StreamType) -> None:
+ self.xref = {}
+ stream.seek(0, 0)
+ f_ = stream.read(-1)
- def decrypt(self, password: Union[str, bytes]) ->PasswordType:
+ 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:
+ for start, size in self._pairs(idx_pairs):
+ # The subsections must increase
+ for num in range(start, start + size):
+ # The first entry is the type
+ xref_type = get_entry(0)
+ # The rest of the elements depend on the xref_type
+ if xref_type == 0:
+ # linked list of free objects
+ next_free_object = get_entry(1) # noqa: F841
+ next_generation = get_entry(2) # noqa: F841
+ elif xref_type == 1:
+ # objects that are in use but are not compressed
+ byte_offset = get_entry(1)
+ generation = get_entry(2)
+ if generation not in self.xref:
+ self.xref[generation] = {} # type: ignore
+ if not used_before(num, generation):
+ self.xref[generation][num] = byte_offset # type: ignore
+ elif xref_type == 2:
+ # compressed objects
+ objstr_num = get_entry(1)
+ obstr_idx = get_entry(2)
+ generation = 0 # PDF spec table 18, generation is 0
+ if not used_before(num, generation):
+ self.xref_objStm[num] = (objstr_num, obstr_idx)
+ elif self.strict:
+ raise PdfReadError(f"Unknown xref type: {xref_type}")
+
+ def _pairs(self, array: List[int]) -> Iterable[Tuple[int, int]]:
+ i = 0
+ while True:
+ yield array[i], array[i + 1]
+ i += 2
+ if (i + 1) >= len(array):
+ break
+
+ 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.
@@ -221,19 +1074,22 @@ class PdfReader(PdfDocCommon):
An indicator if the document was decrypted and whether it was the
owner password or the user password.
"""
- pass
+ if not self._encryption:
+ raise PdfReadError("Not encrypted file")
+ # TODO: raise Exception for wrong password
+ return self._encryption.verify(password)
@property
- def is_encrypted(self) ->bool:
+ 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()<pypdf.PdfReader.decrypt>` method is called.
"""
- pass
+ return TK.ENCRYPT in self.trailer
- def add_form_topname(self, name: str) ->Optional[DictionaryObject]:
+ def add_form_topname(self, name: str) -> Optional[DictionaryObject]:
"""
Add a top level form that groups all form fields below it.
@@ -243,9 +1099,39 @@ class PdfReader(PdfDocCommon):
Returns:
The created object. ``None`` means no object was created.
"""
- pass
+ catalog = self.root_object
+
+ if "/AcroForm" not in catalog or not isinstance(
+ catalog["/AcroForm"], DictionaryObject
+ ):
+ return None
+ acroform = cast(DictionaryObject, catalog[NameObject("/AcroForm")])
+ if "/Fields" not in acroform:
+ # TODO: :No error returns but may be extended for XFA Forms
+ return None
- def rename_form_topname(self, name: str) ->Optional[DictionaryObject]:
+ interim = DictionaryObject()
+ interim[NameObject("/T")] = TextStringObject(name)
+ interim[NameObject("/Kids")] = acroform[NameObject("/Fields")]
+ self.cache_indirect_object(
+ 0,
+ max([i for (g, i) in self.resolved_objects if g == 0]) + 1,
+ interim,
+ )
+ arr = ArrayObject()
+ arr.append(interim.indirect_reference)
+ acroform[NameObject("/Fields")] = arr
+ for o in cast(ArrayObject, interim["/Kids"]):
+ obj = o.get_object()
+ if "/Parent" in obj:
+ logger_warning(
+ f"Top Level Form Field {obj.indirect_reference} have a non-expected parent",
+ __name__,
+ )
+ obj[NameObject("/Parent")] = interim.indirect_reference
+ return interim
+
+ def rename_form_topname(self, name: str) -> Optional[DictionaryObject]:
"""
Rename top level form field that all form fields below it.
@@ -255,4 +1141,19 @@ class PdfReader(PdfDocCommon):
Returns:
The modified object. ``None`` means no object was modified.
"""
- pass
+ catalog = self.root_object
+
+ if "/AcroForm" not in catalog or not isinstance(
+ catalog["/AcroForm"], DictionaryObject
+ ):
+ return None
+ acroform = cast(DictionaryObject, catalog[NameObject("/AcroForm")])
+ if "/Fields" not in acroform:
+ return None
+
+ interim = cast(
+ DictionaryObject,
+ cast(ArrayObject, acroform[NameObject("/Fields")])[0].get_object(),
+ )
+ interim[NameObject("/T")] = TextStringObject(name)
+ return interim
diff --git a/pypdf/_text_extraction/_layout_mode/_fixed_width_page.py b/pypdf/_text_extraction/_layout_mode/_fixed_width_page.py
index 4d943bc4..1be50095 100644
--- a/pypdf/_text_extraction/_layout_mode/_fixed_width_page.py
+++ b/pypdf/_text_extraction/_layout_mode/_fixed_width_page.py
@@ -1,14 +1,17 @@
"""Extract PDF text preserving the layout of the source PDF"""
+
import sys
from itertools import groupby
from math import ceil
from pathlib import Path
from typing import Any, Dict, Iterator, List, Optional, Tuple
+
from ..._utils import logger_warning
from .. import LAYOUT_NEW_BT_GROUP_SPACE_WIDTHS
from ._font import Font
from ._text_state_manager import TextStateManager
from ._text_state_params import TextStateParams
+
if sys.version_info >= (3, 8):
from typing import Literal, TypedDict
else:
@@ -30,6 +33,7 @@ class BTGroup(TypedDict):
displaced_tx: x coordinate of last character in BTGroup
flip_sort: -1 if page is upside down, else 1
"""
+
tx: float
ty: float
font_size: float
@@ -39,8 +43,7 @@ class BTGroup(TypedDict):
flip_sort: Literal[-1, 1]
-def bt_group(tj_op: TextStateParams, rendered_text: str, dispaced_tx: float
- ) ->BTGroup:
+def bt_group(tj_op: TextStateParams, rendered_text: str, dispaced_tx: float) -> BTGroup:
"""
BTGroup constructed from a TextStateParams instance, rendered text, and
displaced tx value.
@@ -50,13 +53,24 @@ def bt_group(tj_op: TextStateParams, rendered_text: str, dispaced_tx: float
rendered_text (str): rendered text
dispaced_tx (float): x coordinate of last character in BTGroup
"""
- pass
+ return BTGroup(
+ tx=tj_op.tx,
+ ty=tj_op.ty,
+ font_size=tj_op.font_size,
+ font_height=tj_op.font_height,
+ text=rendered_text,
+ displaced_tx=dispaced_tx,
+ flip_sort=-1 if tj_op.flip_vertical else 1,
+ )
-def recurs_to_target_op(ops: Iterator[Tuple[List[Any], bytes]],
- text_state_mgr: TextStateManager, end_target: Literal[b'Q', b'ET'],
- fonts: Dict[str, Font], strip_rotated: bool=True) ->Tuple[List[BTGroup],
- List[TextStateParams]]:
+def recurs_to_target_op(
+ ops: Iterator[Tuple[List[Any], bytes]],
+ text_state_mgr: TextStateManager,
+ end_target: Literal[b"Q", b"ET"],
+ fonts: Dict[str, Font],
+ strip_rotated: bool = True,
+) -> Tuple[List[BTGroup], List[TextStateParams]]:
"""
Recurse operators between BT/ET and/or q/Q operators managing the transform
stack and capturing text positioning and rendering data.
@@ -70,11 +84,128 @@ def recurs_to_target_op(ops: Iterator[Tuple[List[Any], bytes]],
Returns:
tuple: list of BTGroup dicts + list of TextStateParams dataclass instances.
"""
- pass
+ # 1 entry per line of text rendered within each BT/ET operation.
+ bt_groups: List[BTGroup] = []
+
+ # 1 entry per text show operator (Tj/TJ/'/")
+ tj_ops: List[TextStateParams] = []
+
+ if end_target == b"Q":
+ # add new q level. cm's added at this level will be popped at next b'Q'
+ text_state_mgr.add_q()
+
+ while True:
+ try:
+ operands, op = next(ops)
+ except StopIteration:
+ return bt_groups, tj_ops
+ if op == end_target:
+ if op == b"Q":
+ text_state_mgr.remove_q()
+ if op == b"ET":
+ if not tj_ops:
+ return bt_groups, tj_ops
+ _text = ""
+ bt_idx = 0 # idx of first tj in this bt group
+ last_displaced_tx = tj_ops[bt_idx].displaced_tx
+ last_ty = tj_ops[bt_idx].ty
+ for _idx, _tj in enumerate(
+ tj_ops
+ ): # ... build text from new Tj operators
+ if strip_rotated and _tj.rotated:
+ continue
+ # if the y position of the text is greater than the font height, assume
+ # the text is on a new line and start a new group
+ if abs(_tj.ty - last_ty) > _tj.font_height:
+ if _text.strip():
+ bt_groups.append(
+ bt_group(tj_ops[bt_idx], _text, last_displaced_tx)
+ )
+ bt_idx = _idx
+ _text = ""
+ # if the x position of the text is less than the last x position by
+ # more than 5 spaces widths, assume the text order should be flipped
+ # and start a new group
+ if (
+ last_displaced_tx - _tj.tx
+ > _tj.space_tx * LAYOUT_NEW_BT_GROUP_SPACE_WIDTHS
+ ):
+ if _text.strip():
+ bt_groups.append(
+ bt_group(tj_ops[bt_idx], _text, last_displaced_tx)
+ )
+ bt_idx = _idx
+ last_displaced_tx = _tj.displaced_tx
+ _text = ""
-def y_coordinate_groups(bt_groups: List[BTGroup], debug_path: Optional[Path
- ]=None) ->Dict[int, List[BTGroup]]:
+ # calculate excess x translation based on ending tx of previous Tj.
+ # multiply by bool (_idx != bt_idx) to ensure spaces aren't double
+ # applied to the first tj of a BTGroup in fixed_width_page().
+ excess_tx = round(_tj.tx - last_displaced_tx, 3) * (_idx != bt_idx)
+ # space_tx could be 0 if either Tz or font_size was 0 for this _tj.
+ spaces = int(excess_tx // _tj.space_tx) if _tj.space_tx else 0
+ new_text = f'{" " * spaces}{_tj.txt}'
+
+ last_ty = _tj.ty
+ _text = f"{_text}{new_text}"
+ last_displaced_tx = _tj.displaced_tx
+ if _text:
+ bt_groups.append(bt_group(tj_ops[bt_idx], _text, last_displaced_tx))
+ text_state_mgr.reset_tm()
+ return bt_groups, tj_ops
+ if op == b"q":
+ bts, tjs = recurs_to_target_op(
+ ops, text_state_mgr, b"Q", fonts, strip_rotated
+ )
+ bt_groups.extend(bts)
+ tj_ops.extend(tjs)
+ elif op == b"cm":
+ text_state_mgr.add_cm(*operands)
+ elif op == b"BT":
+ bts, tjs = recurs_to_target_op(
+ ops, text_state_mgr, b"ET", fonts, strip_rotated
+ )
+ bt_groups.extend(bts)
+ tj_ops.extend(tjs)
+ elif op == b"Tj":
+ tj_ops.append(text_state_mgr.text_state_params(operands[0]))
+ elif op == b"TJ":
+ _tj = text_state_mgr.text_state_params()
+ for tj_op in operands[0]:
+ if isinstance(tj_op, bytes):
+ _tj = text_state_mgr.text_state_params(tj_op)
+ tj_ops.append(_tj)
+ else:
+ text_state_mgr.add_trm(_tj.displacement_matrix(TD_offset=tj_op))
+ elif op == b"'":
+ text_state_mgr.reset_trm()
+ text_state_mgr.add_tm([0, -text_state_mgr.TL])
+ tj_ops.append(text_state_mgr.text_state_params(operands[0]))
+ elif op == b'"':
+ text_state_mgr.reset_trm()
+ text_state_mgr.set_state_param(b"Tw", operands[0])
+ text_state_mgr.set_state_param(b"Tc", operands[1])
+ text_state_mgr.add_tm([0, -text_state_mgr.TL])
+ tj_ops.append(text_state_mgr.text_state_params(operands[2]))
+ elif op in (b"Td", b"Tm", b"TD", b"T*"):
+ text_state_mgr.reset_trm()
+ if op == b"Tm":
+ text_state_mgr.reset_tm()
+ elif op == b"TD":
+ text_state_mgr.set_state_param(b"TL", -operands[1])
+ elif op == b"T*":
+ operands = [0, -text_state_mgr.TL]
+ text_state_mgr.add_tm(operands)
+ elif op == b"Tf":
+ text_state_mgr.set_font(fonts[operands[0]], operands[1])
+ else: # handle Tc, Tw, Tz, TL, and Ts operators
+ text_state_mgr.set_state_param(op, operands)
+
+
+def y_coordinate_groups(
+ bt_groups: List[BTGroup], debug_path: Optional[Path] = None
+) -> Dict[int, List[BTGroup]]:
"""
Group text operations by rendered y coordinate, i.e. the line number.
@@ -86,12 +217,45 @@ def y_coordinate_groups(bt_groups: List[BTGroup], debug_path: Optional[Path
Dict[int, List[BTGroup]]: dict of lists of text rendered by each BT operator
keyed by y coordinate
"""
- pass
+ ty_groups = {
+ ty: sorted(grp, key=lambda x: x["tx"])
+ for ty, grp in groupby(
+ bt_groups, key=lambda bt_grp: int(bt_grp["ty"] * bt_grp["flip_sort"])
+ )
+ }
+ # combine groups whose y coordinates differ by less than the effective font height
+ # (accounts for mixed fonts and other minor oddities)
+ last_ty = next(iter(ty_groups))
+ last_txs = {int(_t["tx"]) for _t in ty_groups[last_ty] if _t["text"].strip()}
+ for ty in list(ty_groups)[1:]:
+ fsz = min(ty_groups[_y][0]["font_height"] for _y in (ty, last_ty))
+ txs = {int(_t["tx"]) for _t in ty_groups[ty] if _t["text"].strip()}
+ # prevent merge if both groups are rendering in the same x position.
+ no_text_overlap = not (txs & last_txs)
+ offset_less_than_font_height = abs(ty - last_ty) < fsz
+ if no_text_overlap and offset_less_than_font_height:
+ ty_groups[last_ty] = sorted(
+ ty_groups.pop(ty) + ty_groups[last_ty], key=lambda x: x["tx"]
+ )
+ last_txs |= txs
+ else:
+ last_ty = ty
+ last_txs = txs
+ if debug_path: # pragma: no cover
+ import json
+
+ debug_path.joinpath("bt_groups.json").write_text(
+ json.dumps(ty_groups, indent=2, default=str), "utf-8"
+ )
+ return ty_groups
-def text_show_operations(ops: Iterator[Tuple[List[Any], bytes]], fonts:
- Dict[str, Font], strip_rotated: bool=True, debug_path: Optional[Path]=None
- ) ->List[BTGroup]:
+def text_show_operations(
+ ops: Iterator[Tuple[List[Any], bytes]],
+ fonts: Dict[str, Font],
+ strip_rotated: bool = True,
+ debug_path: Optional[Path] = None,
+) -> List[BTGroup]:
"""
Extract text from BT/ET operator pairs.
@@ -104,11 +268,63 @@ def text_show_operations(ops: Iterator[Tuple[List[Any], bytes]], fonts:
Returns:
List[BTGroup]: list of dicts of text rendered by each BT operator
"""
- pass
+ state_mgr = TextStateManager() # transformation stack manager
+ debug = bool(debug_path)
+ bt_groups: List[BTGroup] = [] # BT operator dict
+ tj_debug: List[TextStateParams] = [] # Tj/TJ operator data (debug only)
+ try:
+ warned_rotation = False
+ while True:
+ operands, op = next(ops)
+ if op in (b"BT", b"q"):
+ bts, tjs = recurs_to_target_op(
+ ops, state_mgr, b"ET" if op == b"BT" else b"Q", fonts, strip_rotated
+ )
+ if not warned_rotation and any(tj.rotated for tj in tjs):
+ warned_rotation = True
+ if strip_rotated:
+ logger_warning(
+ "Rotated text discovered. Output will be incomplete.",
+ __name__,
+ )
+ else:
+ logger_warning(
+ "Rotated text discovered. Layout will be degraded.",
+ __name__,
+ )
+ bt_groups.extend(bts)
+ if debug: # pragma: no cover
+ tj_debug.extend(tjs)
+ else: # set Tc, Tw, Tz, TL, and Ts if required. ignores all other ops
+ state_mgr.set_state_param(op, operands)
+ except StopIteration:
+ pass
+
+ # left align the data, i.e. decrement all tx values by min(tx)
+ min_x = min((x["tx"] for x in bt_groups), default=0.0)
+ bt_groups = [
+ dict(ogrp, tx=ogrp["tx"] - min_x, displaced_tx=ogrp["displaced_tx"] - min_x) # type: ignore[misc]
+ for ogrp in sorted(
+ bt_groups, key=lambda x: (x["ty"] * x["flip_sort"], -x["tx"]), reverse=True
+ )
+ ]
+
+ if debug_path: # pragma: no cover
+ import json
+
+ debug_path.joinpath("bts.json").write_text(
+ json.dumps(bt_groups, indent=2, default=str), "utf-8"
+ )
+ debug_path.joinpath("tjs.json").write_text(
+ json.dumps(
+ tj_debug, indent=2, default=lambda x: getattr(x, "to_dict", str)(x)
+ ),
+ "utf-8",
+ )
+ return bt_groups
-def fixed_char_width(bt_groups: List[BTGroup], scale_weight: float=1.25
- ) ->float:
+def fixed_char_width(bt_groups: List[BTGroup], scale_weight: float = 1.25) -> float:
"""
Calculate average character width weighted by the length of the rendered
text in each sample for conversion to fixed-width layout.
@@ -120,11 +336,16 @@ def fixed_char_width(bt_groups: List[BTGroup], scale_weight: float=1.25
Returns:
float: fixed character width
"""
- pass
+ char_widths = []
+ for _bt in bt_groups:
+ _len = len(_bt["text"]) * scale_weight
+ char_widths.append(((_bt["displaced_tx"] - _bt["tx"]) / _len, _len))
+ return sum(_w * _l for _w, _l in char_widths) / sum(_l for _, _l in char_widths)
-def fixed_width_page(ty_groups: Dict[int, List[BTGroup]], char_width: float,
- space_vertically: bool) ->str:
+def fixed_width_page(
+ ty_groups: Dict[int, List[BTGroup]], char_width: float, space_vertically: bool
+) -> str:
"""
Generate page text from text operations grouped by rendered y coordinate.
@@ -137,4 +358,24 @@ def fixed_width_page(ty_groups: Dict[int, List[BTGroup]], char_width: float,
str: page text in a fixed width format that closely adheres to the rendered
layout in the source pdf.
"""
- pass
+ lines: List[str] = []
+ last_y_coord = 0
+ for y_coord, line_data in ty_groups.items():
+ if space_vertically and lines:
+ blank_lines = (
+ int(abs(y_coord - last_y_coord) / line_data[0]["font_height"]) - 1
+ )
+ lines.extend([""] * blank_lines)
+ line = ""
+ last_disp = 0.0
+ for bt_op in line_data:
+ offset = int(bt_op["tx"] // char_width)
+ spaces = (offset - len(line)) * (ceil(last_disp) < int(bt_op["tx"]))
+ line = f"{line}{' ' * spaces}{bt_op['text']}"
+ last_disp = bt_op["displaced_tx"]
+ if line.strip() or lines:
+ lines.append(
+ "".join(c if ord(c) < 14 or ord(c) > 31 else " " for c in line)
+ )
+ last_y_coord = y_coord
+ return "\n".join(ln.rstrip() for ln in lines if space_vertically or ln.strip())
diff --git a/pypdf/_text_extraction/_layout_mode/_font.py b/pypdf/_text_extraction/_layout_mode/_font.py
index f63da233..a912fddb 100644
--- a/pypdf/_text_extraction/_layout_mode/_font.py
+++ b/pypdf/_text_extraction/_layout_mode/_font.py
@@ -1,6 +1,8 @@
"""Font constants and classes for "layout" mode text operations"""
+
from dataclasses import dataclass, field
from typing import Any, Dict, Sequence, Union
+
from ...generic import IndirectObject
from ._font_widths import STANDARD_WIDTHS
@@ -17,6 +19,7 @@ class Font:
char_map (dict): character map
font_dictionary (dict): font dictionary
"""
+
subtype: str
space_width: Union[int, float]
encoding: Union[str, Dict[int, str]]
@@ -24,55 +27,86 @@ class Font:
font_dictionary: Dict[Any, Any]
width_map: Dict[str, int] = field(default_factory=dict, init=False)
- def __post_init__(self) ->None:
- if isinstance(self.encoding, dict
- ) and '/Widths' in self.font_dictionary:
- first_char = self.font_dictionary.get('/FirstChar', 0)
- self.width_map = {self.encoding.get(idx + first_char, chr(idx +
- first_char)): width for idx, width in enumerate(self.
- font_dictionary['/Widths'])}
- if '/DescendantFonts' in self.font_dictionary:
+ def __post_init__(self) -> None:
+ # TrueType fonts have a /Widths array mapping character codes to widths
+ if isinstance(self.encoding, dict) and "/Widths" in self.font_dictionary:
+ first_char = self.font_dictionary.get("/FirstChar", 0)
+ self.width_map = {
+ self.encoding.get(idx + first_char, chr(idx + first_char)): width
+ for idx, width in enumerate(self.font_dictionary["/Widths"])
+ }
+
+ # CID fonts have a /W array mapping character codes to widths stashed in /DescendantFonts
+ if "/DescendantFonts" in self.font_dictionary:
d_font: Dict[Any, Any]
- for d_font_idx, d_font in enumerate(self.font_dictionary[
- '/DescendantFonts']):
+ for d_font_idx, d_font in enumerate(
+ self.font_dictionary["/DescendantFonts"]
+ ):
while isinstance(d_font, IndirectObject):
- d_font = d_font.get_object()
- self.font_dictionary['/DescendantFonts'][d_font_idx] = d_font
- ord_map = {ord(_target): _surrogate for _target, _surrogate in
- self.char_map.items() if isinstance(_target, str)}
+ d_font = d_font.get_object() # type: ignore[assignment]
+ self.font_dictionary["/DescendantFonts"][d_font_idx] = d_font
+ ord_map = {
+ ord(_target): _surrogate
+ for _target, _surrogate in self.char_map.items()
+ if isinstance(_target, str)
+ }
+ # /W width definitions have two valid formats which can be mixed and matched:
+ # (1) A character start index followed by a list of widths, e.g.
+ # `45 [500 600 700]` applies widths 500, 600, 700 to characters 45-47.
+ # (2) A character start index, a character stop index, and a width, e.g.
+ # `45 65 500` applies width 500 to characters 45-65.
skip_count = 0
- _w = d_font.get('/W', [])
+ _w = d_font.get("/W", [])
for idx, w_entry in enumerate(_w):
if skip_count:
skip_count -= 1
continue
- if not isinstance(w_entry, (int, float)):
+ if not isinstance(w_entry, (int, float)): # pragma: no cover
+ # We should never get here due to skip_count above. Add a
+ # warning and or use reader's "strict" to force an ex???
continue
+ # check for format (1): `int [int int int int ...]`
if isinstance(_w[idx + 1], Sequence):
- start_idx, width_list = _w[idx:idx + 2]
- self.width_map.update({ord_map[_cidx]: _width for
- _cidx, _width in zip(range(start_idx, start_idx +
- len(width_list), 1), width_list) if _cidx in
- ord_map})
+ start_idx, width_list = _w[idx : idx + 2]
+ self.width_map.update(
+ {
+ ord_map[_cidx]: _width
+ for _cidx, _width in zip(
+ range(start_idx, start_idx + len(width_list), 1),
+ width_list,
+ )
+ if _cidx in ord_map
+ }
+ )
skip_count = 1
- if not isinstance(_w[idx + 1], Sequence
- ) and not isinstance(_w[idx + 2], Sequence):
- start_idx, stop_idx, const_width = _w[idx:idx + 3]
- self.width_map.update({ord_map[_cidx]: const_width for
- _cidx in range(start_idx, stop_idx + 1, 1) if
- _cidx in ord_map})
+ # check for format (2): `int int int`
+ if not isinstance(_w[idx + 1], Sequence) and not isinstance(
+ _w[idx + 2], Sequence
+ ):
+ start_idx, stop_idx, const_width = _w[idx : idx + 3]
+ self.width_map.update(
+ {
+ ord_map[_cidx]: const_width
+ for _cidx in range(start_idx, stop_idx + 1, 1)
+ if _cidx in ord_map
+ }
+ )
skip_count = 2
- if not self.width_map and '/BaseFont' in self.font_dictionary:
+ if not self.width_map and "/BaseFont" in self.font_dictionary:
for key in STANDARD_WIDTHS:
- if self.font_dictionary['/BaseFont'].startswith(f'/{key}'):
+ if self.font_dictionary["/BaseFont"].startswith(f"/{key}"):
self.width_map = STANDARD_WIDTHS[key]
break
- def word_width(self, word: str) ->float:
+ def word_width(self, word: str) -> float:
"""Sum of character widths specified in PDF font for the supplied word"""
- pass
+ return sum(
+ [self.width_map.get(char, self.space_width * 2) for char in word], 0.0
+ )
@staticmethod
- def to_dict(font_instance: 'Font') ->Dict[str, Any]:
+ def to_dict(font_instance: "Font") -> Dict[str, Any]:
"""Dataclass to dict for json.dumps serialization."""
- pass
+ return {
+ k: getattr(font_instance, k) for k in font_instance.__dataclass_fields__
+ }
diff --git a/pypdf/_text_extraction/_layout_mode/_font_widths.py b/pypdf/_text_extraction/_layout_mode/_font_widths.py
index 4c1d7b8d..39092bcd 100644
--- a/pypdf/_text_extraction/_layout_mode/_font_widths.py
+++ b/pypdf/_text_extraction/_layout_mode/_font_widths.py
@@ -1,34 +1,208 @@
-STANDARD_WIDTHS = {'Helvetica': {' ': 278, '!': 278, '"': 355, '#': 556,
- '$': 556, '%': 889, '&': 667, "'": 191, '(': 333, ')': 333, '*': 389,
- '+': 584, ',': 278, '-': 333, '.': 278, '/': 278, '0': 556, '1': 556,
- '2': 556, '3': 556, '4': 556, '5': 556, '6': 556, '7': 556, '8': 556,
- '9': 556, ':': 278, ';': 278, '<': 584, '=': 584, '>': 584, '?': 611,
- '@': 975, 'A': 667, 'B': 667, 'C': 722, 'D': 722, 'E': 667, 'F': 611,
- 'G': 778, 'H': 722, 'I': 278, 'J': 500, 'K': 667, 'L': 556, 'M': 833,
- 'N': 722, 'O': 778, 'P': 667, 'Q': 944, 'R': 667, 'S': 667, 'T': 611,
- 'U': 278, 'V': 278, 'W': 584, 'X': 556, 'Y': 556, 'Z': 500, '[': 556,
- '\\': 556, ']': 556, '^': 278, '_': 278, '`': 278, 'a': 278, 'b': 278,
- 'c': 333, 'd': 556, 'e': 556, 'f': 556, 'g': 556, 'h': 556, 'i': 556,
- 'j': 556, 'k': 556, 'l': 556, 'm': 556, 'n': 278, 'o': 278, 'p': 556,
- 'q': 556, 'r': 500, 's': 556, 't': 556, 'u': 278, 'v': 500, 'w': 500,
- 'x': 222, 'y': 222, 'z': 556, '{': 222, '|': 833, '}': 556, '~': 556},
- 'Times': {' ': 250, '!': 333, '"': 408, '#': 500, '$': 500, '%': 833,
- '&': 778, "'": 180, '(': 333, ')': 333, '*': 500, '+': 564, ',': 250,
- '-': 333, '.': 250, '/': 564, '0': 500, '1': 500, '2': 500, '3': 500,
- '4': 500, '5': 500, '6': 500, '7': 500, '8': 500, '9': 500, ':': 278,
- ';': 278, '<': 564, '=': 564, '>': 564, '?': 444, '@': 921, 'A': 722,
- 'B': 667, 'C': 667, 'D': 722, 'E': 611, 'F': 556, 'G': 722, 'H': 722,
- 'I': 333, 'J': 389, 'K': 722, 'L': 611, 'M': 889, 'N': 722, 'O': 722,
- 'P': 556, 'Q': 722, 'R': 667, 'S': 556, 'T': 611, 'U': 722, 'V': 722,
- 'W': 944, 'X': 722, 'Y': 722, 'Z': 611, '[': 333, '\\': 278, ']': 333,
- '^': 469, '_': 500, '`': 333, 'a': 444, 'b': 500, 'c': 444, 'd': 500,
- 'e': 444, 'f': 333, 'g': 500, 'h': 500, 'i': 278, 'j': 278, 'k': 500,
- 'l': 278, 'm': 722, 'n': 500, 'o': 500, 'p': 500, 'q': 500, 'r': 333,
- 's': 389, 't': 278, 'u': 500, 'v': 444, 'w': 722, 'x': 500, 'y': 444,
- 'z': 389, '{': 348, '|': 220, '}': 348, '~': 469}}
-STANDARD_WIDTHS['Courier'] = {c: (600) for c in STANDARD_WIDTHS['Times']}
-STANDARD_WIDTHS['ZapfDingbats'] = {c: (1000) for c in STANDARD_WIDTHS['Times']}
-STANDARD_WIDTHS['Symbol'] = {c: (500) for c in STANDARD_WIDTHS['Times']}
-STANDARD_WIDTHS['CourierNew'] = STANDARD_WIDTHS['Courier']
-STANDARD_WIDTHS['Arial'] = STANDARD_WIDTHS['Helvetica']
-STANDARD_WIDTHS['TimesNewRoman'] = STANDARD_WIDTHS['Times']
+# Widths for the standard 14 fonts as described on page 416 of the PDF 1.7 standard
+STANDARD_WIDTHS = {
+ "Helvetica": { # 4 fonts, includes bold, oblique and boldoblique variants
+ " ": 278,
+ "!": 278,
+ '"': 355,
+ "#": 556,
+ "$": 556,
+ "%": 889,
+ "&": 667,
+ "'": 191,
+ "(": 333,
+ ")": 333,
+ "*": 389,
+ "+": 584,
+ ",": 278,
+ "-": 333,
+ ".": 278,
+ "/": 278,
+ "0": 556,
+ "1": 556,
+ "2": 556,
+ "3": 556,
+ "4": 556,
+ "5": 556,
+ "6": 556,
+ "7": 556,
+ "8": 556,
+ "9": 556,
+ ":": 278,
+ ";": 278,
+ "<": 584,
+ "=": 584,
+ ">": 584,
+ "?": 611,
+ "@": 975,
+ "A": 667,
+ "B": 667,
+ "C": 722,
+ "D": 722,
+ "E": 667,
+ "F": 611,
+ "G": 778,
+ "H": 722,
+ "I": 278,
+ "J": 500,
+ "K": 667,
+ "L": 556,
+ "M": 833,
+ "N": 722,
+ "O": 778,
+ "P": 667,
+ "Q": 944,
+ "R": 667,
+ "S": 667,
+ "T": 611,
+ "U": 278,
+ "V": 278,
+ "W": 584,
+ "X": 556,
+ "Y": 556,
+ "Z": 500,
+ "[": 556,
+ "\\": 556,
+ "]": 556,
+ "^": 278,
+ "_": 278,
+ "`": 278,
+ "a": 278,
+ "b": 278,
+ "c": 333,
+ "d": 556,
+ "e": 556,
+ "f": 556,
+ "g": 556,
+ "h": 556,
+ "i": 556,
+ "j": 556,
+ "k": 556,
+ "l": 556,
+ "m": 556,
+ "n": 278,
+ "o": 278,
+ "p": 556,
+ "q": 556,
+ "r": 500,
+ "s": 556,
+ "t": 556,
+ "u": 278,
+ "v": 500,
+ "w": 500,
+ "x": 222,
+ "y": 222,
+ "z": 556,
+ "{": 222,
+ "|": 833,
+ "}": 556,
+ "~": 556,
+ },
+ "Times": { # 4 fonts, includes bold, oblique and boldoblique variants
+ " ": 250,
+ "!": 333,
+ '"': 408,
+ "#": 500,
+ "$": 500,
+ "%": 833,
+ "&": 778,
+ "'": 180,
+ "(": 333,
+ ")": 333,
+ "*": 500,
+ "+": 564,
+ ",": 250,
+ "-": 333,
+ ".": 250,
+ "/": 564,
+ "0": 500,
+ "1": 500,
+ "2": 500,
+ "3": 500,
+ "4": 500,
+ "5": 500,
+ "6": 500,
+ "7": 500,
+ "8": 500,
+ "9": 500,
+ ":": 278,
+ ";": 278,
+ "<": 564,
+ "=": 564,
+ ">": 564,
+ "?": 444,
+ "@": 921,
+ "A": 722,
+ "B": 667,
+ "C": 667,
+ "D": 722,
+ "E": 611,
+ "F": 556,
+ "G": 722,
+ "H": 722,
+ "I": 333,
+ "J": 389,
+ "K": 722,
+ "L": 611,
+ "M": 889,
+ "N": 722,
+ "O": 722,
+ "P": 556,
+ "Q": 722,
+ "R": 667,
+ "S": 556,
+ "T": 611,
+ "U": 722,
+ "V": 722,
+ "W": 944,
+ "X": 722,
+ "Y": 722,
+ "Z": 611,
+ "[": 333,
+ "\\": 278,
+ "]": 333,
+ "^": 469,
+ "_": 500,
+ "`": 333,
+ "a": 444,
+ "b": 500,
+ "c": 444,
+ "d": 500,
+ "e": 444,
+ "f": 333,
+ "g": 500,
+ "h": 500,
+ "i": 278,
+ "j": 278,
+ "k": 500,
+ "l": 278,
+ "m": 722,
+ "n": 500,
+ "o": 500,
+ "p": 500,
+ "q": 500,
+ "r": 333,
+ "s": 389,
+ "t": 278,
+ "u": 500,
+ "v": 444,
+ "w": 722,
+ "x": 500,
+ "y": 444,
+ "z": 389,
+ "{": 348,
+ "|": 220,
+ "}": 348,
+ "~": 469,
+ },
+}
+STANDARD_WIDTHS[
+ "Courier"
+] = { # 4 fonts, includes bold, oblique and boldoblique variants
+ c: 600 for c in STANDARD_WIDTHS["Times"] # fixed width
+}
+STANDARD_WIDTHS["ZapfDingbats"] = {c: 1000 for c in STANDARD_WIDTHS["Times"]} # 1 font
+STANDARD_WIDTHS["Symbol"] = {c: 500 for c in STANDARD_WIDTHS["Times"]} # 1 font
+# add aliases per table H.3 on page 1110 of the PDF 1.7 standard
+STANDARD_WIDTHS["CourierNew"] = STANDARD_WIDTHS["Courier"]
+STANDARD_WIDTHS["Arial"] = STANDARD_WIDTHS["Helvetica"]
+STANDARD_WIDTHS["TimesNewRoman"] = STANDARD_WIDTHS["Times"]
diff --git a/pypdf/_text_extraction/_layout_mode/_text_state_manager.py b/pypdf/_text_extraction/_layout_mode/_text_state_manager.py
index 3dc8948f..3c5d4736 100644
--- a/pypdf/_text_extraction/_layout_mode/_text_state_manager.py
+++ b/pypdf/_text_extraction/_layout_mode/_text_state_manager.py
@@ -1,14 +1,16 @@
"""manage the PDF transform stack during "layout" mode text extraction"""
+
from collections import ChainMap, Counter
from typing import Any, Dict, List, MutableMapping, Union
from typing import ChainMap as ChainMapType
from typing import Counter as CounterType
+
from ...errors import PdfReadError
from .. import mult
from ._font import Font
from ._text_state_params import TextStateParams
-TextStateManagerChainMapType = ChainMapType[Union[int, str], Union[float, bool]
- ]
+
+TextStateManagerChainMapType = ChainMapType[Union[int, str], Union[float, bool]]
TextStateManagerDictType = MutableMapping[Union[int, str], Union[float, bool]]
@@ -29,9 +31,10 @@ class TextStateManager:
font_size (int | float): font size
"""
- def __init__(self) ->None:
- self.transform_stack: TextStateManagerChainMapType = ChainMap(self.
- new_transform())
+ def __init__(self) -> None:
+ self.transform_stack: TextStateManagerChainMapType = ChainMap(
+ self.new_transform()
+ )
self.q_queue: CounterType[int] = Counter()
self.q_depth = [0]
self.Tc: float = 0.0
@@ -42,8 +45,7 @@ class TextStateManager:
self.font: Union[Font, None] = None
self.font_size: Union[int, float] = 0
- def set_state_param(self, op: bytes, value: Union[float, List[Any]]
- ) ->None:
+ def set_state_param(self, op: bytes, value: Union[float, List[Any]]) -> None:
"""
Set a text state parameter. Supports Tc, Tz, Tw, TL, and Ts operators.
@@ -53,9 +55,11 @@ class TextStateManager:
value (float | List[Any]): new parameter value. If a list,
value[0] is used.
"""
- pass
+ if op not in [b"Tc", b"Tz", b"Tw", b"TL", b"Ts"]:
+ return
+ self.__setattr__(op.decode(), value[0] if isinstance(value, list) else value)
- def set_font(self, font: Font, size: float) ->None:
+ def set_font(self, font: Font, size: float) -> None:
"""
Set the current font and font_size.
@@ -63,9 +67,10 @@ class TextStateManager:
font (Font): a layout mode Font
size (float): font size
"""
- pass
+ self.font = font
+ self.font_size = size
- def text_state_params(self, value: Union[bytes, str]='') ->TextStateParams:
+ def text_state_params(self, value: Union[bytes, str] = "") -> TextStateParams:
"""
Create a TextStateParams instance to display a text string. Type[bytes] values
will be decoded implicitly.
@@ -79,54 +84,130 @@ class TextStateManager:
Returns:
TextStateParams: current text state parameters
"""
- pass
+ if not isinstance(self.font, Font):
+ raise PdfReadError(
+ "font not set: is PDF missing a Tf operator?"
+ ) # pragma: no cover
+ if isinstance(value, bytes):
+ try:
+ if isinstance(self.font.encoding, str):
+ txt = value.decode(self.font.encoding, "surrogatepass")
+ else:
+ txt = "".join(
+ self.font.encoding[x]
+ if x in self.font.encoding
+ else bytes((x,)).decode()
+ for x in value
+ )
+ except (UnicodeEncodeError, UnicodeDecodeError):
+ txt = value.decode("utf-8", "replace")
+ txt = "".join(
+ self.font.char_map[x] if x in self.font.char_map else x for x in txt
+ )
+ else:
+ txt = value
+ return TextStateParams(
+ txt,
+ self.font,
+ self.font_size,
+ self.Tc,
+ self.Tw,
+ self.Tz,
+ self.TL,
+ self.Ts,
+ self.effective_transform,
+ )
@staticmethod
- def raw_transform(_a: float=1.0, _b: float=0.0, _c: float=0.0, _d:
- float=1.0, _e: float=0.0, _f: float=0.0) ->Dict[int, float]:
+ def raw_transform(
+ _a: float = 1.0,
+ _b: float = 0.0,
+ _c: float = 0.0,
+ _d: float = 1.0,
+ _e: float = 0.0,
+ _f: float = 0.0,
+ ) -> Dict[int, float]:
"""Only a/b/c/d/e/f matrix params"""
- pass
+ return dict(zip(range(6), map(float, (_a, _b, _c, _d, _e, _f))))
@staticmethod
- def new_transform(_a: float=1.0, _b: float=0.0, _c: float=0.0, _d:
- float=1.0, _e: float=0.0, _f: float=0.0, is_text: bool=False,
- is_render: bool=False) ->TextStateManagerDictType:
+ def new_transform(
+ _a: float = 1.0,
+ _b: float = 0.0,
+ _c: float = 0.0,
+ _d: float = 1.0,
+ _e: float = 0.0,
+ _f: float = 0.0,
+ is_text: bool = False,
+ is_render: bool = False,
+ ) -> TextStateManagerDictType:
"""Standard a/b/c/d/e/f matrix params + 'is_text' and 'is_render' keys"""
- pass
+ result: Any = TextStateManager.raw_transform(_a, _b, _c, _d, _e, _f)
+ result.update({"is_text": is_text, "is_render": is_render})
+ return result
- def reset_tm(self) ->TextStateManagerChainMapType:
+ def reset_tm(self) -> TextStateManagerChainMapType:
"""Clear all transforms from chainmap having is_text==True or is_render==True"""
- pass
-
- def reset_trm(self) ->TextStateManagerChainMapType:
+ while (
+ self.transform_stack.maps[0]["is_text"]
+ or self.transform_stack.maps[0]["is_render"]
+ ):
+ self.transform_stack = self.transform_stack.parents
+ return self.transform_stack
+
+ def reset_trm(self) -> TextStateManagerChainMapType:
"""Clear all transforms from chainmap having is_render==True"""
- pass
+ while self.transform_stack.maps[0]["is_render"]:
+ self.transform_stack = self.transform_stack.parents
+ return self.transform_stack
- def remove_q(self) ->TextStateManagerChainMapType:
+ def remove_q(self) -> TextStateManagerChainMapType:
"""Rewind to stack prior state after closing a 'q' with internal 'cm' ops"""
- pass
+ self.transform_stack = self.reset_tm()
+ self.transform_stack.maps = self.transform_stack.maps[
+ self.q_queue.pop(self.q_depth.pop(), 0) :
+ ]
+ return self.transform_stack
- def add_q(self) ->None:
+ def add_q(self) -> None:
"""Add another level to q_queue"""
- pass
+ self.q_depth.append(len(self.q_depth))
- def add_cm(self, *args: Any) ->TextStateManagerChainMapType:
+ def add_cm(self, *args: Any) -> TextStateManagerChainMapType:
"""Concatenate an additional transform matrix"""
- pass
+ self.transform_stack = self.reset_tm()
+ self.q_queue.update(self.q_depth[-1:])
+ self.transform_stack = self.transform_stack.new_child(self.new_transform(*args))
+ return self.transform_stack
- def _complete_matrix(self, operands: List[float]) ->List[float]:
+ def _complete_matrix(self, operands: List[float]) -> List[float]:
"""Adds a, b, c, and d to an "e/f only" operand set (e.g Td)"""
- pass
+ if len(operands) == 2: # this is a Td operator or equivalent
+ operands = [1.0, 0.0, 0.0, 1.0, *operands]
+ return operands
- def add_tm(self, operands: List[float]) ->TextStateManagerChainMapType:
+ def add_tm(self, operands: List[float]) -> TextStateManagerChainMapType:
"""Append a text transform matrix"""
- pass
-
- def add_trm(self, operands: List[float]) ->TextStateManagerChainMapType:
+ self.transform_stack = self.transform_stack.new_child(
+ self.new_transform( # type: ignore[misc]
+ *self._complete_matrix(operands), is_text=True # type: ignore[arg-type]
+ )
+ )
+ return self.transform_stack
+
+ def add_trm(self, operands: List[float]) -> TextStateManagerChainMapType:
"""Append a text rendering transform matrix"""
- pass
+ self.transform_stack = self.transform_stack.new_child(
+ self.new_transform( # type: ignore[misc]
+ *self._complete_matrix(operands), is_text=True, is_render=True # type: ignore[arg-type]
+ )
+ )
+ return self.transform_stack
@property
- def effective_transform(self) ->List[float]:
+ def effective_transform(self) -> List[float]:
"""Current effective transform accounting for cm, tm, and trm transforms"""
- pass
+ eff_transform = [*self.transform_stack.maps[0].values()]
+ for transform in self.transform_stack.maps[1:]:
+ eff_transform = mult(eff_transform, transform) # type: ignore[arg-type] # dict has int keys 0-5
+ return eff_transform
diff --git a/pypdf/_text_extraction/_layout_mode/_text_state_params.py b/pypdf/_text_extraction/_layout_mode/_text_state_params.py
index 341ce6cd..b6e6930c 100644
--- a/pypdf/_text_extraction/_layout_mode/_text_state_params.py
+++ b/pypdf/_text_extraction/_layout_mode/_text_state_params.py
@@ -1,7 +1,9 @@
"""A dataclass that captures the CTM and Text State for a tj operation"""
+
import math
from dataclasses import dataclass, field
from typing import Any, Dict, List, Union
+
from .. import mult, orient
from ._font import Font
@@ -30,6 +32,7 @@ class TextStateParams:
flip_vertical (bool): True if y axis has been inverted (i.e. if self.transform[3] < 0.)
rotated (bool): True if the text orientation is rotated with respect to the page.
"""
+
txt: str
font: Font
font_size: Union[int, float]
@@ -38,8 +41,9 @@ class TextStateParams:
Tz: float = 100.0
TL: float = 0.0
Ts: float = 0.0
- transform: List[float] = field(default_factory=lambda : [1.0, 0.0, 0.0,
- 1.0, 0.0, 0.0])
+ transform: List[float] = field(
+ default_factory=lambda: [1.0, 0.0, 0.0, 1.0, 0.0, 0.0]
+ )
tx: float = field(default=0.0, init=False)
ty: float = field(default=0.0, init=False)
displaced_tx: float = field(default=0.0, init=False)
@@ -48,40 +52,56 @@ class TextStateParams:
flip_vertical: bool = field(default=False, init=False)
rotated: bool = field(default=False, init=False)
- def __post_init__(self) ->None:
+ def __post_init__(self) -> None:
if orient(self.transform) in (90, 270):
- self.transform = mult([1.0, -self.transform[1], -self.transform
- [2], 1.0, 0.0, 0.0], self.transform)
+ self.transform = mult(
+ [1.0, -self.transform[1], -self.transform[2], 1.0, 0.0, 0.0],
+ self.transform,
+ )
self.rotated = True
- if orient(self.transform) == 180 and self.transform[0] < -1e-06:
- self.transform = mult([-1.0, 0.0, 0.0, -1.0, 0.0, 0.0], self.
- transform)
+ # self.transform[0] AND self.transform[3] < 0 indicates true rotation.
+ # If only self.transform[3] < 0, the y coords are simply inverted.
+ if orient(self.transform) == 180 and self.transform[0] < -1e-6:
+ self.transform = mult([-1.0, 0.0, 0.0, -1.0, 0.0, 0.0], self.transform)
self.rotated = True
self.displaced_tx = self.displaced_transform()[4]
self.tx = self.transform[4]
self.ty = self.render_transform()[5]
- self.space_tx = round(self.word_tx(' '), 3)
- if self.space_tx < 1e-06:
- self.space_tx = round(self.word_tx('', self.font.space_width *
- -2), 3)
- self.font_height = self.font_size * math.sqrt(self.transform[1] **
- 2 + self.transform[3] ** 2)
- self.flip_vertical = self.transform[3] < -1e-06
+ self.space_tx = round(self.word_tx(" "), 3)
+ if self.space_tx < 1e-6:
+ # if the " " char is assigned 0 width (e.g. for fine tuned spacing
+ # with TJ int operators a la crazyones.pdf), calculate space_tx as
+ # a TD_offset of -2 * font.space_width where font.space_width is
+ # the space_width calculated in _cmap.py.
+ self.space_tx = round(self.word_tx("", self.font.space_width * -2), 3)
+ self.font_height = self.font_size * math.sqrt(
+ self.transform[1] ** 2 + self.transform[3] ** 2
+ )
+ # flip_vertical handles PDFs generated by Microsoft Word's "publish" command.
+ self.flip_vertical = self.transform[3] < -1e-6 # inverts y axis
- def font_size_matrix(self) ->List[float]:
+ def font_size_matrix(self) -> List[float]:
"""Font size matrix"""
- pass
+ return [
+ self.font_size * (self.Tz / 100.0),
+ 0.0,
+ 0.0,
+ self.font_size,
+ 0.0,
+ self.Ts,
+ ]
- def displaced_transform(self) ->List[float]:
+ def displaced_transform(self) -> List[float]:
"""Effective transform matrix after text has been rendered."""
- pass
+ return mult(self.displacement_matrix(), self.transform)
- def render_transform(self) ->List[float]:
+ def render_transform(self) -> List[float]:
"""Effective transform matrix accounting for font size, Tz, and Ts."""
- pass
+ return mult(self.font_size_matrix(), self.transform)
- def displacement_matrix(self, word: Union[str, None]=None, TD_offset:
- float=0.0) ->List[float]:
+ def displacement_matrix(
+ self, word: Union[str, None] = None, TD_offset: float = 0.0
+ ) -> List[float]:
"""
Text displacement matrix
@@ -90,13 +110,18 @@ class TextStateParams:
returned.
TD_offset (float, optional): translation applied by TD operator. Defaults to 0.0.
"""
- pass
+ word = word if word is not None else self.txt
+ return [1.0, 0.0, 0.0, 1.0, self.word_tx(word, TD_offset), 0.0]
- def word_tx(self, word: str, TD_offset: float=0.0) ->float:
+ def word_tx(self, word: str, TD_offset: float = 0.0) -> float:
"""Horizontal text displacement for any word according this text state"""
- pass
+ return (
+ (self.font_size * ((self.font.word_width(word) - TD_offset) / 1000.0))
+ + self.Tc
+ + word.count(" ") * self.Tw
+ ) * (self.Tz / 100.0)
@staticmethod
- def to_dict(inst: 'TextStateParams') ->Dict[str, Any]:
+ def to_dict(inst: "TextStateParams") -> Dict[str, Any]:
"""Dataclass to dict for json.dumps serialization"""
- pass
+ return {k: getattr(inst, k) for k in inst.__dataclass_fields__ if k != "font"}
diff --git a/pypdf/_utils.py b/pypdf/_utils.py
index d2f9468e..97565369 100644
--- a/pypdf/_utils.py
+++ b/pypdf/_utils.py
@@ -1,6 +1,34 @@
+# 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'
+__author__ = "Mathieu Fenniak"
+__author_email__ = "biziqe@mathieu.fenniak.net"
+
import functools
import logging
import re
@@ -10,22 +38,94 @@ from dataclasses import dataclass
from datetime import datetime, timezone
from io import DEFAULT_BUFFER_SIZE, BytesIO
from os import SEEK_CUR
-from typing import IO, Any, Dict, List, Optional, Pattern, Tuple, Union, cast, overload
+from typing import (
+ IO,
+ Any,
+ Dict,
+ List,
+ Optional,
+ Pattern,
+ Tuple,
+ Union,
+ cast,
+ overload,
+)
+
if sys.version_info[:2] >= (3, 10):
+ # Python 3.10+: https://www.python.org/dev/peps/pep-0484/
from typing import TypeAlias
else:
from typing_extensions import TypeAlias
-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]
+
+from .errors import (
+ STREAM_TRUNCATED_PREMATURELY,
+ DeprecationError,
+ PdfStreamError,
+)
+
+TransformationMatrixType: TypeAlias = Tuple[
+ Tuple[float, float, float], Tuple[float, float, float], Tuple[float, float, float]
+]
+CompressedTransformationMatrix: TypeAlias = Tuple[
+ float, float, float, float, float, float
+]
+
StreamType = IO[Any]
StrByteType = Union[str, StreamType]
-def read_until_whitespace(stream: StreamType, maxchars: Optional[int]=None
- ) ->bytes:
+def parse_iso8824_date(text: Optional[str]) -> Optional[datetime]:
+ orgtext = text
+ if text is None:
+ return None
+ if text[0].isdigit():
+ text = "D:" + text
+ if text.endswith(("Z", "z")):
+ text += "0000"
+ text = text.replace("z", "+").replace("Z", "+").replace("'", "")
+ i = max(text.find("+"), text.find("-"))
+ if i > 0 and i != len(text) - 5:
+ text += "00"
+ for f in (
+ "D:%Y",
+ "D:%Y%m",
+ "D:%Y%m%d",
+ "D:%Y%m%d%H",
+ "D:%Y%m%d%H%M",
+ "D:%Y%m%d%H%M%S",
+ "D:%Y%m%d%H%M%S%z",
+ ):
+ try:
+ d = datetime.strptime(text, f) # noqa: DTZ007
+ except ValueError:
+ continue
+ else:
+ if text.endswith("+0000"):
+ d = d.replace(tzinfo=timezone.utc)
+ return d
+ raise ValueError(f"Can not convert date: {orgtext}")
+
+
+def _get_max_pdf_version_header(header1: str, header2: str) -> str:
+ versions = (
+ "%PDF-1.3",
+ "%PDF-1.4",
+ "%PDF-1.5",
+ "%PDF-1.6",
+ "%PDF-1.7",
+ "%PDF-2.0",
+ )
+ pdf_header_indices = []
+ if header1 in versions:
+ pdf_header_indices.append(versions.index(header1))
+ if header2 in versions:
+ pdf_header_indices.append(versions.index(header2))
+ if len(pdf_header_indices) == 0:
+ raise ValueError(f"neither {header1!r} nor {header2!r} are proper headers")
+ return versions[max(pdf_header_indices)]
+
+
+def read_until_whitespace(stream: StreamType, maxchars: Optional[int] = None) -> bytes:
"""
Read non-whitespace characters and return them.
@@ -38,10 +138,18 @@ def read_until_whitespace(stream: StreamType, maxchars: Optional[int]=None
Returns:
The data which was read.
"""
- pass
-
-
-def read_non_whitespace(stream: StreamType) ->bytes:
+ 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).
@@ -51,10 +159,13 @@ def read_non_whitespace(stream: StreamType) ->bytes:
Returns:
The data which was read.
"""
- pass
+ tok = stream.read(1)
+ while tok in WHITESPACES:
+ tok = stream.read(1)
+ return tok
-def skip_over_whitespace(stream: StreamType) ->bool:
+def skip_over_whitespace(stream: StreamType) -> bool:
"""
Similar to read_non_whitespace, but return a boolean if more than one
whitespace character was read.
@@ -65,10 +176,15 @@ def skip_over_whitespace(stream: StreamType) ->bool:
Returns:
True if more than one whitespace was skipped, otherwise return False.
"""
- pass
+ tok = WHITESPACES[0]
+ cnt = 0
+ while tok in WHITESPACES:
+ tok = stream.read(1)
+ cnt += 1
+ return cnt > 1
-def check_if_whitespace_only(value: bytes) ->bool:
+def check_if_whitespace_only(value: bytes) -> bool:
"""
Check if the given value consists of whitespace characters only.
@@ -78,10 +194,22 @@ def check_if_whitespace_only(value: bytes) ->bool:
Returns:
True if the value only has whitespace characters, otherwise return False.
"""
- pass
+ for index in range(len(value)):
+ current = value[index : index + 1]
+ if current not in WHITESPACES:
+ return False
+ return True
-def read_until_regex(stream: StreamType, regex: Pattern[bytes]) ->bytes:
+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]) -> bytes:
"""
Read until the regular expression pattern matched (ignore the match).
Treats EOF on the underlying stream as the end of the token to be matched.
@@ -92,10 +220,21 @@ def read_until_regex(stream: StreamType, regex: Pattern[bytes]) ->bytes:
Returns:
The read bytes.
"""
- pass
-
-
-def read_block_backwards(stream: StreamType, to_read: int) ->bytes:
+ name = b""
+ while True:
+ tok = stream.read(16)
+ if not tok:
+ return name
+ m = regex.search(name + tok)
+ if m is not None:
+ stream.seek(m.start() - (len(name) + len(tok)), 1)
+ name = (name + tok)[: m.start()]
+ break
+ name += tok
+ return name
+
+
+def read_block_backwards(stream: StreamType, to_read: int) -> bytes:
"""
Given a stream at position X, read a block of size to_read ending at position X.
@@ -109,10 +248,17 @@ def read_block_backwards(stream: StreamType, to_read: int) ->bytes:
Returns:
The data which was read.
"""
- pass
+ 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:
+def read_previous_line(stream: StreamType) -> bytes:
"""
Given a byte stream with current position X, return the previous line.
@@ -128,43 +274,165 @@ def read_previous_line(stream: StreamType) ->bytes:
Returns:
The data which was read.
"""
- pass
-
-
-def mark_location(stream: StreamType) ->None:
+ 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."""
- pass
+ # Mainly for debugging
+ radius = 5000
+ stream.seek(-radius, 1)
+ with open("pypdf_pdfLocation.txt", "wb") as output_fh:
+ output_fh.write(stream.read(radius))
+ output_fh.write(b"HERE")
+ output_fh.write(stream.read(radius))
+ stream.seek(-radius, 1)
B_CACHE: Dict[Union[str, bytes], bytes] = {}
-WHITESPACES = b' ', b'\n', b'\r', b'\t', b'\x00'
-WHITESPACES_AS_BYTES = b''.join(WHITESPACES)
-WHITESPACES_AS_REGEXP = b'[' + WHITESPACES_AS_BYTES + b']'
-def deprecate_with_replacement(old_name: str, new_name: str, removed_in: str
- ) ->None:
+def b_(s: Union[str, bytes]) -> bytes:
+ if isinstance(s, bytes):
+ return s
+ bc = B_CACHE
+ if s in bc:
+ return bc[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
+
+
+def str_(b: Any) -> str:
+ if isinstance(b, bytes):
+ return b.decode("latin-1")
+ else:
+ return str(b) # will return b.__str__() if defined
+
+
+@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
+
+
+WHITESPACES = (b" ", b"\n", b"\r", b"\t", b"\x00")
+WHITESPACES_AS_BYTES = b"".join(WHITESPACES)
+WHITESPACES_AS_REGEXP = b"[" + WHITESPACES_AS_BYTES + b"]"
+
+
+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) -> None:
"""Raise an exception that a feature will be removed, but has a replacement."""
- pass
+ deprecate(f"{old_name} is deprecated and will be removed in pypdf {removed_in}. Use {new_name} instead.", 4)
-def deprecation_with_replacement(old_name: str, new_name: str, removed_in: str
- ) ->None:
+def deprecation_with_replacement(old_name: str, new_name: str, removed_in: str) -> None:
"""Raise an exception that a feature was already removed, but has a replacement."""
- pass
+ deprecation(f"{old_name} is deprecated and was removed in pypdf {removed_in}. Use {new_name} instead.")
-def deprecate_no_replacement(name: str, removed_in: str) ->None:
+def deprecate_no_replacement(name: str, removed_in: str) -> None:
"""Raise an exception that a feature will be removed without replacement."""
- pass
+ deprecate(f"{name} is deprecated and will be removed in pypdf {removed_in}.", 4)
-def deprecation_no_replacement(name: str, removed_in: str) ->None:
+def deprecation_no_replacement(name: str, removed_in: str) -> None:
"""Raise an exception that a feature was already removed without replacement."""
- pass
+ deprecation(f"{name} is deprecated and was removed in pypdf {removed_in}.")
-def logger_error(msg: str, src: str) ->None:
+def logger_error(msg: str, src: str) -> None:
"""
Use this instead of logger.error directly.
@@ -173,10 +441,10 @@ def logger_error(msg: str, src: str) ->None:
See the docs on when to use which:
https://pypdf.readthedocs.io/en/latest/user/suppress-warnings.html
"""
- pass
+ logging.getLogger(src).error(msg)
-def logger_warning(msg: str, src: str) ->None:
+def logger_warning(msg: str, src: str) -> None:
"""
Use this instead of logger.warning directly.
@@ -192,11 +460,12 @@ def logger_warning(msg: str, src: str) ->None:
pypdf could apply a robustness fix to still read it. This applies mainly
to strict=False mode.
"""
- pass
+ logging.getLogger(src).warning(msg)
-def rename_kwargs(func_name: str, kwargs: Dict[str, Any], aliases: Dict[str,
- str], fail: bool=False) ->None:
+def rename_kwargs(
+ func_name: str, kwargs: Dict[str, Any], aliases: Dict[str, str], fail: bool = False
+) -> None:
"""
Helper function to deprecate arguments.
@@ -206,46 +475,113 @@ def rename_kwargs(func_name: str, kwargs: Dict[str, Any], aliases: Dict[str,
aliases:
fail:
"""
- pass
+ for old_term, new_term in aliases.items():
+ if old_term in kwargs:
+ if fail:
+ raise DeprecationError(
+ f"{old_term} is deprecated as an argument. Use {new_term} instead"
+ )
+ if new_term in kwargs:
+ raise TypeError(
+ f"{func_name} received both {old_term} and {new_term} as "
+ f"an argument. {old_term} is deprecated. "
+ f"Use {new_term} instead."
+ )
+ kwargs[new_term] = kwargs.pop(old_term)
+ warnings.warn(
+ message=(
+ f"{old_term} is deprecated as an argument. Use {new_term} instead"
+ ),
+ category=DeprecationWarning,
+ )
-class classproperty:
+def _human_readable_bytes(bytes: int) -> str:
+ if bytes < 10**3:
+ return f"{bytes} Byte"
+ elif bytes < 10**6:
+ return f"{bytes / 10**3:.1f} kB"
+ elif bytes < 10**9:
+ return f"{bytes / 10**6:.1f} MB"
+ else:
+ return f"{bytes / 10**9:.1f} GB"
+
+
+# The following class has been copied from Django:
+# https://github.com/django/django/blob/adae619426b6f50046b3daaa744db52989c9d6db/django/utils/functional.py#L51-L65
+#
+# Original license:
+#
+# ---------------------------------------------------------------------------------
+# Copyright (c) Django Software Foundation and individual contributors.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of Django nor the names of its contributors may be used
+# to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# ---------------------------------------------------------------------------------
+class classproperty: # noqa: N801
"""
Decorator that converts a method with a single cls argument into a property
that can be accessed directly from the class.
"""
- def __init__(self, method=None):
+ def __init__(self, method=None): # type: ignore # noqa: ANN001
self.fget = method
- def __get__(self, instance, cls=None) ->Any:
+ def __get__(self, instance, cls=None) -> Any: # type: ignore # noqa: ANN001
return self.fget(cls)
+ def getter(self, method): # type: ignore # noqa: ANN001, ANN202
+ self.fget = method
+ return self
+
@dataclass
class File:
from .generic import IndirectObject
+
name: str
data: bytes
- image: Optional[Any] = None
- indirect_reference: Optional[IndirectObject] = None
+ image: Optional[Any] = None # optional ; direct image access
+ indirect_reference: Optional[IndirectObject] = None # optional ; link to PdfObject
- def __str__(self) ->str:
- return (
- f'{self.__class__.__name__}(name={self.name}, data: {_human_readable_bytes(len(self.data))})'
- )
+ def __str__(self) -> str:
+ return f"{self.__class__.__name__}(name={self.name}, data: {_human_readable_bytes(len(self.data))})"
- def __repr__(self) ->str:
- return self.__str__()[:-1] + f', hash: {hash(self.data)})'
+ def __repr__(self) -> str:
+ return self.__str__()[:-1] + f", hash: {hash(self.data)})"
@dataclass
class ImageFile(File):
from .generic import IndirectObject
- image: Optional[Any] = None
- indirect_reference: Optional[IndirectObject] = None
- def replace(self, new_image: Any, **kwargs: Any) ->None:
+ image: Optional[Any] = None # optional ; direct PIL image access
+ indirect_reference: Optional[IndirectObject] = None # optional ; link to PdfObject
+
+ def replace(self, new_image: Any, **kwargs: Any) -> None:
"""
Replace the Image with a new PIL image.
@@ -264,36 +600,84 @@ class ImageFile(File):
The `kwargs` parameter allows passing additional parameters
to `Image.Image.save()`, such as quality.
"""
- pass
+ from PIL import Image
+
+ from ._reader import PdfReader
+
+ # to prevent circular import
+ from .filters import _xobj_to_image
+ from .generic import DictionaryObject, PdfObject
+
+ if self.indirect_reference is None:
+ raise TypeError("Can not update an inline image")
+ if not hasattr(self.indirect_reference.pdf, "_id_translated"):
+ raise TypeError("Can not update an image not belonging to a PdfWriter")
+ if not isinstance(new_image, Image.Image):
+ raise TypeError("new_image shall be a PIL Image")
+ b = BytesIO()
+ new_image.save(b, "PDF", **kwargs)
+ reader = PdfReader(b)
+ assert reader.pages[0].images[0].indirect_reference is not None
+ self.indirect_reference.pdf._objects[self.indirect_reference.idnum - 1] = (
+ reader.pages[0].images[0].indirect_reference.get_object()
+ )
+ cast(
+ PdfObject, self.indirect_reference.get_object()
+ ).indirect_reference = self.indirect_reference
+ # change the object attributes
+ extension, byte_stream, img = _xobj_to_image(
+ cast(DictionaryObject, self.indirect_reference.get_object())
+ )
+ assert extension is not None
+ self.name = self.name[: self.name.rfind(".")] + extension
+ self.data = byte_stream
+ self.image = img
@functools.total_ordering
class Version:
- COMPONENT_PATTERN = re.compile('^(\\d+)(.*)$')
+ COMPONENT_PATTERN = re.compile(r"^(\d+)(.*)$")
- def __init__(self, version_str: str) ->None:
+ def __init__(self, version_str: str) -> None:
self.version_str = version_str
self.components = self._parse_version(version_str)
- def __eq__(self, other: object) ->bool:
+ def _parse_version(self, version_str: str) -> List[Tuple[int, str]]:
+ components = version_str.split(".")
+ parsed_components = []
+ for component in components:
+ match = Version.COMPONENT_PATTERN.match(component)
+ if not match:
+ parsed_components.append((0, component))
+ continue
+ integer_prefix = match.group(1)
+ suffix = match.group(2)
+ if integer_prefix is None:
+ integer_prefix = 0
+ parsed_components.append((int(integer_prefix), suffix))
+ return parsed_components
+
+ def __eq__(self, other: object) -> bool:
if not isinstance(other, Version):
return False
return self.components == other.components
- def __lt__(self, other: Any) ->bool:
+ def __lt__(self, other: Any) -> bool:
if not isinstance(other, Version):
- raise ValueError(
- f'Version cannot be compared against {type(other)}')
+ raise ValueError(f"Version cannot be compared against {type(other)}")
min_len = min(len(self.components), len(other.components))
for i in range(min_len):
self_value, self_suffix = self.components[i]
other_value, other_suffix = other.components[i]
+
if self_value < other_value:
return True
elif self_value > other_value:
return False
+
if self_suffix < other_suffix:
return True
elif self_suffix > other_suffix:
return False
+
return len(self.components) < len(other.components)
diff --git a/pypdf/_version.py b/pypdf/_version.py
index 376d9ccc..ed48cdab 100644
--- a/pypdf/_version.py
+++ b/pypdf/_version.py
@@ -1 +1 @@
-__version__ = '4.3.1'
+__version__ = "4.3.1"
diff --git a/pypdf/_writer.py b/pypdf/_writer.py
index 9c092665..00b9d498 100644
--- a/pypdf/_writer.py
+++ b/pypdf/_writer.py
@@ -1,3 +1,32 @@
+# 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 collections
import decimal
import enum
@@ -7,27 +36,89 @@ import uuid
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 typing import (
+ IO,
+ Any,
+ Callable,
+ Deque,
+ Dict,
+ Iterable,
+ List,
+ Optional,
+ Pattern,
+ Tuple,
+ Type,
+ Union,
+ cast,
+)
+
from ._cmap import _default_fonts_space_width, build_char_map_from_dict
from ._doc_common import PdfDocCommon
from ._encryption import EncryptAlgorithm, Encryption
from ._page import PageObject
from ._page_labels import nums_clear_range, nums_insert, nums_next
from ._reader import PdfReader
-from ._utils import StrByteType, StreamType, _get_max_pdf_version_header, b_, deprecate_with_replacement, logger_warning
+from ._utils import (
+ StrByteType,
+ StreamType,
+ _get_max_pdf_version_header,
+ b_,
+ deprecate_with_replacement,
+ logger_warning,
+)
from .constants import AnnotationDictionaryAttributes as AA
from .constants import CatalogAttributes as CA
-from .constants import CatalogDictionary, FileSpecificationDictionaryEntries, GoToActionArguments, ImageType, InteractiveFormDictEntries, PageLabelStyle, TypFitArguments, UserAccessPermissions
+from .constants import (
+ CatalogDictionary,
+ FileSpecificationDictionaryEntries,
+ GoToActionArguments,
+ ImageType,
+ InteractiveFormDictEntries,
+ PageLabelStyle,
+ TypFitArguments,
+ UserAccessPermissions,
+)
from .constants import Core as CO
from .constants import FieldDictionaryAttributes as FA
from .constants import PageAttributes as PG
from .constants import PagesAttributes as PA
from .constants import TrailerKeys as TK
from .errors import PyPdfError
-from .generic import PAGE_FIT, ArrayObject, BooleanObject, ByteStringObject, ContentStream, DecodedStreamObject, Destination, DictionaryObject, Fit, FloatObject, IndirectObject, NameObject, NullObject, NumberObject, PdfObject, RectangleObject, StreamObject, TextStringObject, TreeObject, ViewerPreferences, create_string_object, hex_to_rgb
+from .generic import (
+ PAGE_FIT,
+ ArrayObject,
+ BooleanObject,
+ ByteStringObject,
+ ContentStream,
+ DecodedStreamObject,
+ Destination,
+ DictionaryObject,
+ Fit,
+ FloatObject,
+ IndirectObject,
+ NameObject,
+ NullObject,
+ NumberObject,
+ PdfObject,
+ RectangleObject,
+ StreamObject,
+ TextStringObject,
+ TreeObject,
+ ViewerPreferences,
+ create_string_object,
+ hex_to_rgb,
+)
from .pagerange import PageRange, PageRangeSpec
-from .types import AnnotationSubtype, BorderArrayType, LayoutType, OutlineItemType, OutlineType, PagemodeType
+from .types import (
+ AnnotationSubtype,
+ BorderArrayType,
+ LayoutType,
+ OutlineItemType,
+ OutlineType,
+ PagemodeType,
+)
from .xmp import XmpInformation
+
ALL_DOCUMENT_PERMISSIONS = UserAccessPermissions.all()
DEFAULT_FONT_HEIGHT_IN_MULTILINE = 12
@@ -45,6 +136,13 @@ class ObjectDeletionFlag(enum.IntFlag):
IMAGES = XOBJECT_IMAGES | INLINE_IMAGES | DRAWING_IMAGES
+def _rolling_checksum(stream: BytesIO, blocksize: int = 65536) -> str:
+ hash = hashlib.md5()
+ for block in iter(lambda: stream.read(blocksize), b""):
+ hash.update(block)
+ return hash.hexdigest()
+
+
class PdfWriter(PdfDocCommon):
"""
Write a PDF file out, given pages produced by another class or through
@@ -53,37 +151,62 @@ class PdfWriter(PdfDocCommon):
Typically data is added from a :class:`PdfReader<pypdf.PdfReader>`.
"""
- def __init__(self, fileobj: Union[None, PdfReader, StrByteType, Path]=
- '', clone_from: Union[None, PdfReader, StrByteType, Path]=None) ->None:
- self._header = b'%PDF-1.3'
+ def __init__(
+ self,
+ fileobj: Union[None, PdfReader, StrByteType, Path] = "",
+ clone_from: Union[None, PdfReader, StrByteType, Path] = None,
+ ) -> None:
+ self._header = b"%PDF-1.3"
self._objects: List[PdfObject] = []
"""The indirect objects in the PDF."""
+
self._idnum_hash: Dict[bytes, IndirectObject] = {}
"""Maps hash values of indirect objects to their IndirectObject instances."""
+
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()})
+ pages.update(
+ {
+ NameObject(PA.TYPE): NameObject("/Pages"),
+ NameObject(PA.COUNT): NumberObject(0),
+ NameObject(PA.KIDS): ArrayObject(),
+ }
+ )
self._pages = self._add_object(pages)
self.flattened_pages = []
+
+ # info object
info = DictionaryObject()
- info.update({NameObject('/Producer'): create_string_object('pypdf')})
+ info.update({NameObject("/Producer"): create_string_object("pypdf")})
self._info_obj: PdfObject = 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_object.update(
+ {
+ NameObject(PA.TYPE): NameObject(CO.CATALOG),
+ NameObject(CO.PAGES): self._pages,
+ }
+ )
self._root = self._add_object(self._root_object)
- def _get_clone_from(fileobj: Union[None, PdfReader, str, Path, IO[
- Any], BytesIO], clone_from: Union[None, PdfReader, str, Path,
- IO[Any], BytesIO]) ->Union[None, PdfReader, str, Path, IO[Any],
- BytesIO]:
- if not isinstance(fileobj, (str, Path, IO, BytesIO)
- ) or fileobj != '' and clone_from is None:
+ def _get_clone_from(
+ fileobj: Union[None, PdfReader, str, Path, IO[Any], BytesIO],
+ clone_from: Union[None, PdfReader, str, Path, IO[Any], BytesIO],
+ ) -> Union[None, PdfReader, str, Path, IO[Any], BytesIO]:
+ if not isinstance(fileobj, (str, Path, IO, BytesIO)) or (
+ fileobj != "" and clone_from is None
+ ):
cloning = True
- if not (not isinstance(fileobj, (str, Path)) or Path(str(
- fileobj)).exists() and Path(str(fileobj)).stat().
- st_size > 0):
+ if not (
+ not isinstance(fileobj, (str, Path))
+ or (
+ Path(str(fileobj)).exists()
+ and Path(str(fileobj)).stat().st_size > 0
+ )
+ ):
cloning = False
if isinstance(fileobj, (IO, BytesIO)):
t = fileobj.tell()
@@ -94,74 +217,97 @@ class PdfWriter(PdfDocCommon):
if cloning:
clone_from = fileobj
return clone_from
+
clone_from = _get_clone_from(fileobj, clone_from)
+ # to prevent overwriting
self.temp_fileobj = fileobj
- self.fileobj = ''
+ self.fileobj = ""
self.with_as_usage = False
if clone_from is not None:
if not isinstance(clone_from, PdfReader):
clone_from = PdfReader(clone_from)
self.clone_document_from_reader(clone_from)
+
self._encryption: Optional[Encryption] = None
self._encrypt_entry: Optional[DictionaryObject] = None
self._ID: Union[ArrayObject, None] = None
+ # for commonality
@property
- def is_encrypted(self) ->bool:
+ 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()<pypdf.PdfReader.decrypt>` method is called.
"""
- pass
+ return False
@property
- def root_object(self) ->DictionaryObject:
+ def root_object(self) -> DictionaryObject:
"""
Provide direct access to PDF Structure.
Note:
Recommended only for read access.
"""
- pass
+ return self._root_object
@property
- def _info(self) ->Optional[DictionaryObject]:
+ def _info(self) -> Optional[DictionaryObject]:
"""
Provide access to "/Info". Standardized with PdfReader.
Returns:
/Info Dictionary; None if the entry does not exist
"""
- pass
+ return cast(DictionaryObject, self._info_obj.get_object())
+
+ @_info.setter
+ def _info(self, value: Union[IndirectObject, DictionaryObject]) -> None:
+ obj = cast(DictionaryObject, self._info_obj.get_object())
+ obj.clear()
+ obj.update(cast(DictionaryObject, value.get_object()))
@property
- def xmp_metadata(self) ->Optional[XmpInformation]:
+ def xmp_metadata(self) -> Optional[XmpInformation]:
"""XMP (Extensible Metadata Platform) data."""
- pass
+ return cast(XmpInformation, self.root_object.xmp_metadata)
@xmp_metadata.setter
- def xmp_metadata(self, value: Optional[XmpInformation]) ->None:
+ def xmp_metadata(self, value: Optional[XmpInformation]) -> None:
"""XMP (Extensible Metadata Platform) data."""
- pass
+ if value is None:
+ if "/Metadata" in self.root_object:
+ del self.root_object["/Metadata"]
+ else:
+ self.root_object[NameObject("/Metadata")] = value
- def __enter__(self) ->'PdfWriter':
+ return self.root_object.xmp_metadata # type: ignore
+
+ def __enter__(self) -> "PdfWriter":
"""Store that writer is initialized by 'with'."""
t = self.temp_fileobj
- self.__init__()
+ self.__init__() # type: ignore
self.with_as_usage = True
- self.fileobj = t
+ self.fileobj = t # type: ignore
return self
- def __exit__(self, exc_type: Optional[Type[BaseException]], exc:
- Optional[BaseException], traceback: Optional[TracebackType]) ->None:
+ 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)
- def _repr_mimebundle_(self, include: Union[None, Iterable[str]]=None,
- exclude: Union[None, Iterable[str]]=None) ->Dict[str, Any]:
+ def _repr_mimebundle_(
+ self,
+ include: Union[None, Iterable[str]] = None,
+ exclude: Union[None, Iterable[str]] = None,
+ ) -> Dict[str, Any]:
"""
Integration into Jupyter Notebooks.
@@ -170,10 +316,24 @@ class PdfWriter(PdfDocCommon):
See https://ipython.readthedocs.io/en/stable/config/integrating.html
"""
- pass
+ pdf_data = BytesIO()
+ self.write(pdf_data)
+ data = {
+ "application/pdf": pdf_data,
+ }
+
+ if include is not None:
+ # Filter representations based on include list
+ data = {k: v for k, v in data.items() if k in include}
+
+ if exclude is not None:
+ # Remove representations based on exclude list
+ data = {k: v for k, v in data.items() if k not in exclude}
+
+ return data
@property
- def pdf_header(self) ->str:
+ def pdf_header(self) -> str:
"""
Read/Write property of the PDF header that is written.
@@ -183,9 +343,92 @@ class PdfWriter(PdfDocCommon):
Note: `pdf_header` returns a string but accepts bytes or str for writing
"""
- pass
-
- def set_need_appearances_writer(self, state: bool=True) ->None:
+ return self._header.decode()
+
+ @pdf_header.setter
+ def pdf_header(self, new_header: Union[str, bytes]) -> None:
+ if isinstance(new_header, str):
+ new_header = new_header.encode()
+ self._header = new_header
+
+ def _add_object(self, obj: PdfObject) -> IndirectObject:
+ if (
+ getattr(obj, "indirect_reference", None) is not None
+ and obj.indirect_reference.pdf == self # type: ignore
+ ):
+ return obj.indirect_reference # type: ignore
+ # check for /Contents in Pages (/Contents in annotation are strings)
+ if isinstance(obj, DictionaryObject) and isinstance(
+ obj.get(PG.CONTENTS, None), (ArrayObject, DictionaryObject)
+ ):
+ obj[NameObject(PG.CONTENTS)] = self._add_object(obj[PG.CONTENTS])
+ self._objects.append(obj)
+ obj.indirect_reference = IndirectObject(len(self._objects), 0, self)
+ return obj.indirect_reference
+
+ def get_object(
+ self,
+ indirect_reference: Union[int, IndirectObject],
+ ) -> PdfObject:
+ if isinstance(indirect_reference, int):
+ return self._objects[indirect_reference - 1]
+ if indirect_reference.pdf != self:
+ raise ValueError("pdf must be self")
+ return self._objects[indirect_reference.idnum - 1]
+
+ def _replace_object(
+ self,
+ indirect_reference: Union[int, IndirectObject],
+ obj: PdfObject,
+ ) -> PdfObject:
+ if isinstance(indirect_reference, IndirectObject):
+ if indirect_reference.pdf != self:
+ raise ValueError("pdf must be self")
+ indirect_reference = indirect_reference.idnum
+ gen = self._objects[indirect_reference - 1].indirect_reference.generation # type: ignore
+ if (
+ getattr(obj, "indirect_reference", None) is not None
+ and obj.indirect_reference.pdf != self # type: ignore
+ ):
+ obj = obj.clone(self)
+ self._objects[indirect_reference - 1] = obj
+ obj.indirect_reference = IndirectObject(indirect_reference, gen, self)
+ return self._objects[indirect_reference - 1]
+
+ def _add_page(
+ self,
+ page: PageObject,
+ action: Callable[[Any, Union[PageObject, 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) are not duplicated:
+ try: # delete an already existing page
+ del self._id_translated[id(page_org.indirect_reference.pdf)][ # type: ignore
+ page_org.indirect_reference.idnum # type: ignore
+ ]
+ except Exception:
+ pass
+ page = cast("PageObject", page_org.clone(self, False, excluded_keys))
+ if page_org.pdf is not None:
+ other = page_org.pdf.pdf_header
+ self.pdf_header = _get_max_pdf_version_header(self.pdf_header, other)
+ 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)
+ action(self.flattened_pages, page)
+ page_count = cast(int, pages[PA.COUNT])
+ pages[NameObject(PA.COUNT)] = NumberObject(page_count + 1)
+ return page
+
+ def set_need_appearances_writer(self, state: bool = True) -> None:
"""
Sets the "NeedAppearances" flag in the PDF writer.
@@ -199,10 +442,36 @@ class PdfWriter(PdfDocCommon):
Returns:
None
"""
- pass
-
- def add_page(self, page: PageObject, excluded_keys: Iterable[str]=()
- ) ->PageObject:
+ # See 12.7.2 and 7.7.2 for more information:
+ # https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf
+ try:
+ # get the AcroForm tree
+ if CatalogDictionary.ACRO_FORM not in self._root_object:
+ self._root_object[
+ NameObject(CatalogDictionary.ACRO_FORM)
+ ] = self._add_object(DictionaryObject())
+
+ need_appearances = NameObject(InteractiveFormDictEntries.NeedAppearances)
+ cast(DictionaryObject, self._root_object[CatalogDictionary.ACRO_FORM])[
+ need_appearances
+ ] = BooleanObject(state)
+ except Exception as exc: # pragma: no cover
+ logger_warning(
+ f"set_need_appearances_writer({state}) catch : {exc}", __name__
+ )
+
+ def create_viewer_preferences(self) -> ViewerPreferences:
+ o = ViewerPreferences()
+ self._root_object[
+ NameObject(CatalogDictionary.VIEWER_PREFERENCES)
+ ] = self._add_object(o)
+ return o
+
+ def add_page(
+ self,
+ page: PageObject,
+ excluded_keys: Iterable[str] = (),
+ ) -> PageObject:
"""
Add a page to this PDF file.
@@ -219,10 +488,14 @@ class PdfWriter(PdfDocCommon):
Returns:
The added PageObject.
"""
- pass
+ return self._add_page(page, list.append, excluded_keys)
- def insert_page(self, page: PageObject, index: int=0, excluded_keys:
- Iterable[str]=()) ->PageObject:
+ 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<pypdf.PdfReader>` instance.
@@ -235,10 +508,11 @@ class PdfWriter(PdfDocCommon):
Returns:
The added PageObject.
"""
- pass
+ return self._add_page(page, lambda kids, p: kids.insert(index, p))
- def _get_page_number_by_indirect(self, indirect_reference: Union[None,
- int, NullObject, IndirectObject]) ->Optional[int]:
+ def _get_page_number_by_indirect(
+ self, indirect_reference: Union[None, int, NullObject, IndirectObject]
+ ) -> Optional[int]:
"""
Generate _page_id2num.
@@ -248,10 +522,19 @@ class PdfWriter(PdfDocCommon):
Returns:
The page number or None
"""
- pass
+ # to provide same function as in PdfReader
+ if indirect_reference is None or isinstance(indirect_reference, NullObject):
+ return None
+ if isinstance(indirect_reference, int):
+ indirect_reference = IndirectObject(indirect_reference, 0, self)
+ obj = indirect_reference.get_object()
+ if isinstance(obj, PageObject):
+ return obj.page_number
+ return None
- def add_blank_page(self, width: Optional[float]=None, height: Optional[
- float]=None) ->PageObject:
+ def add_blank_page(
+ self, width: Optional[float] = None, height: Optional[float] = None
+ ) -> PageObject:
"""
Append a blank page to this PDF file and return it.
@@ -270,11 +553,15 @@ class PdfWriter(PdfDocCommon):
PageSizeNotDefinedError: if width and height are not defined
and previous page does not exist.
"""
- pass
+ page = PageObject.create_blank_page(self, width, height)
+ return self.add_page(page)
- def insert_blank_page(self, width: Optional[Union[float, decimal.
- Decimal]]=None, height: Optional[Union[float, decimal.Decimal]]=
- None, index: int=0) ->PageObject:
+ def insert_blank_page(
+ self,
+ width: Optional[Union[float, decimal.Decimal]] = None,
+ height: Optional[Union[float, decimal.Decimal]] = None,
+ index: int = 0,
+ ) -> PageObject:
"""
Insert a blank page to this PDF file and return it.
@@ -294,9 +581,41 @@ class PdfWriter(PdfDocCommon):
PageSizeNotDefinedError: if width and height are not defined
and previous page does not exist.
"""
- pass
+ 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 add_js(self, javascript: str) ->None:
+ @property
+ def open_destination(
+ self,
+ ) -> Union[None, Destination, TextStringObject, ByteStringObject]:
+ return super().open_destination
+
+ @open_destination.setter
+ def open_destination(self, dest: Union[None, str, Destination, PageObject]) -> None:
+ if dest is None:
+ try:
+ del self._root_object["/OpenAction"]
+ except KeyError:
+ pass
+ elif isinstance(dest, str):
+ self._root_object[NameObject("/OpenAction")] = TextStringObject(dest)
+ elif isinstance(dest, Destination):
+ self._root_object[NameObject("/OpenAction")] = dest.dest_array
+ elif isinstance(dest, PageObject):
+ self._root_object[NameObject("/OpenAction")] = Destination(
+ "Opening",
+ dest.indirect_reference
+ if dest.indirect_reference is not None
+ else NullObject(),
+ PAGE_FIT,
+ ).dest_array
+
+ def add_js(self, javascript: str) -> None:
"""
Add JavaScript which will launch upon opening this PDF.
@@ -306,9 +625,32 @@ class PdfWriter(PdfDocCommon):
>>> output.add_js("this.print({bUI:true,bSilent:false,bShrinkToFit:true});")
# Example: This will launch the print window when the PDF is opened.
"""
- pass
-
- def add_attachment(self, filename: str, data: Union[str, bytes]) ->None:
+ # Names / JavaScript preferred to be able to add multiple scripts
+ if "/Names" not in self._root_object:
+ self._root_object[NameObject(CA.NAMES)] = DictionaryObject()
+ names = cast(DictionaryObject, self._root_object[CA.NAMES])
+ if "/JavaScript" not in names:
+ names[NameObject("/JavaScript")] = DictionaryObject(
+ {NameObject("/Names"): ArrayObject()}
+ )
+ js_list = cast(
+ ArrayObject, cast(DictionaryObject, names["/JavaScript"])["/Names"]
+ )
+
+ js = DictionaryObject()
+ js.update(
+ {
+ NameObject(PA.TYPE): NameObject("/Action"),
+ NameObject("/S"): NameObject("/JavaScript"),
+ NameObject("/JS"): TextStringObject(f"{javascript}"),
+ }
+ )
+ # We need a name for parameterized javascript in the pdf file,
+ # but it can be anything.
+ js_list.append(create_string_object(str(uuid.uuid4())))
+ js_list.append(self._add_object(js))
+
+ def add_attachment(self, filename: str, data: Union[str, bytes]) -> None:
"""
Embed a file inside the PDF.
@@ -320,10 +662,88 @@ class PdfWriter(PdfDocCommon):
filename: The filename to display.
data: The data in the file.
"""
- pass
-
- def append_pages_from_reader(self, reader: PdfReader, after_page_append:
- Optional[Callable[[PageObject], None]]=None) ->None:
+ # 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(b_(data))
+ file_entry.update({NameObject(PA.TYPE): NameObject("/EmbeddedFile")})
+
+ # The Filespec entry
+ # Sample:
+ # 7 0 obj
+ # <<
+ # /Type /Filespec
+ # /F (hello.txt)
+ # /EF << /F 8 0 R >>
+ # >>
+ # endobj
+
+ ef_entry = DictionaryObject()
+ ef_entry.update({NameObject("/F"): self._add_object(file_entry)})
+
+ filespec = DictionaryObject()
+ filespec.update(
+ {
+ NameObject(PA.TYPE): NameObject("/Filespec"),
+ NameObject(FileSpecificationDictionaryEntries.F): create_string_object(
+ filename
+ ), # Perhaps also try TextStringObject
+ NameObject(FileSpecificationDictionaryEntries.EF): ef_entry,
+ }
+ )
+
+ # Then create the entry for the root, as it needs
+ # a reference to the Filespec
+ # Sample:
+ # 1 0 obj
+ # <<
+ # /Type /Catalog
+ # /Outlines 2 0 R
+ # /Pages 3 0 R
+ # /Names << /EmbeddedFiles << /Names [(hello.txt) 7 0 R] >> >>
+ # >>
+ # endobj
+
+ if CA.NAMES not in self._root_object:
+ self._root_object[NameObject(CA.NAMES)] = self._add_object(
+ DictionaryObject()
+ )
+ if "/EmbeddedFiles" not in cast(DictionaryObject, self._root_object[CA.NAMES]):
+ embedded_files_names_dictionary = DictionaryObject(
+ {NameObject(CA.NAMES): ArrayObject()}
+ )
+ cast(DictionaryObject, self._root_object[CA.NAMES])[
+ NameObject("/EmbeddedFiles")
+ ] = self._add_object(embedded_files_names_dictionary)
+ else:
+ embedded_files_names_dictionary = cast(
+ DictionaryObject,
+ cast(DictionaryObject, self._root_object[CA.NAMES])["/EmbeddedFiles"],
+ )
+ cast(ArrayObject, embedded_files_names_dictionary[CA.NAMES]).extend(
+ [create_string_object(filename), filespec]
+ )
+
+ def append_pages_from_reader(
+ self,
+ reader: PdfReader,
+ after_page_append: Optional[Callable[[PageObject], None]] = None,
+ ) -> None:
"""
Copy pages from reader to writer. Includes an optional callback
parameter which is invoked after pages are appended to the writer.
@@ -341,12 +761,191 @@ class PdfWriter(PdfDocCommon):
the callback is a reference to the page just appended to the
document.
"""
- pass
+ # 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 _update_field_annotation(
+ self,
+ field: DictionaryObject,
+ anno: DictionaryObject,
+ font_name: str = "",
+ font_size: float = -1,
+ ) -> None:
+ # Calculate rectangle dimensions
+ _rct = cast(RectangleObject, anno[AA.Rect])
+ rct = RectangleObject((0, 0, abs(_rct[2] - _rct[0]), abs(_rct[3] - _rct[1])))
+
+ # Extract font information
+ da = anno.get_inherited(
+ AA.DA,
+ cast(DictionaryObject, self.root_object[CatalogDictionary.ACRO_FORM]).get(
+ AA.DA, None
+ ),
+ )
+ if da is None:
+ da = TextStringObject("/Helv 0 Tf 0 g")
+ else:
+ da = da.get_object()
+ font_properties = da.replace("\n", " ").replace("\r", " ").split(" ")
+ font_properties = [x for x in font_properties if x != ""]
+ if font_name:
+ font_properties[font_properties.index("Tf") - 2] = font_name
+ else:
+ font_name = font_properties[font_properties.index("Tf") - 2]
+ font_height = (
+ font_size
+ if font_size >= 0
+ else float(font_properties[font_properties.index("Tf") - 1])
+ )
+ if font_height == 0:
+ if field.get(FA.Ff, 0) & FA.FfBits.Multiline:
+ font_height = DEFAULT_FONT_HEIGHT_IN_MULTILINE
+ else:
+ font_height = rct.height - 2
+ font_properties[font_properties.index("Tf") - 1] = str(font_height)
+ da = " ".join(font_properties)
+ y_offset = rct.height - 1 - font_height
+
+ # Retrieve font information from local DR ...
+ dr: Any = cast(
+ DictionaryObject,
+ cast(
+ DictionaryObject,
+ anno.get_inherited(
+ "/DR",
+ cast(
+ DictionaryObject, self.root_object[CatalogDictionary.ACRO_FORM]
+ ).get("/DR", DictionaryObject()),
+ ),
+ ).get_object(),
+ )
+ dr = dr.get("/Font", DictionaryObject()).get_object()
+ # _default_fonts_space_width keys is the list of Standard fonts
+ if font_name not in dr and font_name not in _default_fonts_space_width:
+ # ...or AcroForm dictionary
+ dr = cast(
+ Dict[Any, Any],
+ cast(
+ DictionaryObject, self.root_object[CatalogDictionary.ACRO_FORM]
+ ).get("/DR", {}),
+ )
+ dr = dr.get_object().get("/Font", DictionaryObject()).get_object()
+ font_res = dr.get(font_name, None)
+ if font_res is not None:
+ font_res = cast(DictionaryObject, font_res.get_object())
+ font_subtype, _, font_encoding, font_map = build_char_map_from_dict(
+ 200, font_res
+ )
+ try: # get rid of width stored in -1 key
+ del font_map[-1]
+ except KeyError:
+ pass
+ font_full_rev: Dict[str, bytes]
+ if isinstance(font_encoding, str):
+ font_full_rev = {
+ v: k.encode(font_encoding) for k, v in font_map.items()
+ }
+ else:
+ font_full_rev = {v: bytes((k,)) for k, v in font_encoding.items()}
+ font_encoding_rev = {v: bytes((k,)) for k, v in font_encoding.items()}
+ for kk, v in font_map.items():
+ font_full_rev[v] = font_encoding_rev.get(kk, kk)
+ else:
+ logger_warning(f"Font dictionary for {font_name} not found.", __name__)
+ font_full_rev = {}
+
+ # Retrieve field text and selected values
+ field_flags = field.get(FA.Ff, 0)
+ if field.get(FA.FT, "/Tx") == "/Ch" and field_flags & FA.FfBits.Combo == 0:
+ txt = "\n".join(anno.get_inherited(FA.Opt, []))
+ sel = field.get("/V", [])
+ if not isinstance(sel, list):
+ sel = [sel]
+ else: # /Tx
+ txt = field.get("/V", "")
+ sel = []
+ # Escape parentheses (pdf 1.7 reference, table 3.2 Literal Strings)
+ txt = txt.replace("\\", "\\\\").replace("(", r"\(").replace(")", r"\)")
+ # Generate appearance stream
+ ap_stream = f"q\n/Tx BMC \nq\n1 1 {rct.width - 1} {rct.height - 1} re\nW\nBT\n{da}\n".encode()
+ for line_number, line in enumerate(txt.replace("\n", "\r").split("\r")):
+ if line in sel:
+ # may be improved but cannot find how to get fill working => replaced with lined box
+ ap_stream += (
+ f"1 {y_offset - (line_number * font_height * 1.4) - 1} {rct.width - 2} {font_height + 2} re\n"
+ f"0.5 0.5 0.5 rg s\n{da}\n"
+ ).encode()
+ if line_number == 0:
+ ap_stream += f"2 {y_offset} Td\n".encode()
+ else:
+ # Td is a relative translation
+ ap_stream += f"0 {- font_height * 1.4} Td\n".encode()
+ enc_line: List[bytes] = [
+ font_full_rev.get(c, c.encode("utf-16-be")) for c in line
+ ]
+ if any(len(c) >= 2 for c in enc_line):
+ ap_stream += b"<" + (b"".join(enc_line)).hex().encode() + b"> Tj\n"
+ else:
+ ap_stream += b"(" + b"".join(enc_line) + b") Tj\n"
+ ap_stream += b"ET\nQ\nEMC\nQ\n"
+
+ # Create appearance dictionary
+ dct = DecodedStreamObject.initialize_from_dictionary(
+ {
+ NameObject("/Type"): NameObject("/XObject"),
+ NameObject("/Subtype"): NameObject("/Form"),
+ NameObject("/BBox"): rct,
+ "__streamdata__": ByteStringObject(ap_stream),
+ "/Length": 0,
+ }
+ )
+ if AA.AP in anno:
+ for k, v in cast(DictionaryObject, anno[AA.AP]).get("/N", {}).items():
+ if k not in {"/BBox", "/Length", "/Subtype", "/Type", "/Filter"}:
+ dct[k] = v
+
+ # Update Resources with font information if necessary
+ if font_res is not None:
+ dct[NameObject("/Resources")] = DictionaryObject(
+ {
+ NameObject("/Font"): DictionaryObject(
+ {
+ NameObject(font_name): getattr(
+ font_res, "indirect_reference", font_res
+ )
+ }
+ )
+ }
+ )
+ if AA.AP not in anno:
+ anno[NameObject(AA.AP)] = DictionaryObject(
+ {NameObject("/N"): self._add_object(dct)}
+ )
+ elif "/N" not in cast(DictionaryObject, anno[AA.AP]):
+ cast(DictionaryObject, anno[NameObject(AA.AP)])[
+ NameObject("/N")
+ ] = self._add_object(dct)
+ else: # [/AP][/N] exists
+ n = anno[AA.AP]["/N"].indirect_reference.idnum # type: ignore
+ self._objects[n - 1] = dct
+ dct.indirect_reference = IndirectObject(n, 0, self)
+
FFBITS_NUL = FA.FfBits(0)
- def update_page_form_field_values(self, page: Union[PageObject, List[
- PageObject], None], fields: Dict[str, Any], flags: FA.FfBits=
- FFBITS_NUL, auto_regenerate: Optional[bool]=True) ->None:
+ def update_page_form_field_values(
+ self,
+ page: Union[PageObject, List[PageObject], None],
+ fields: Dict[str, Any],
+ flags: FA.FfBits = FFBITS_NUL,
+ auto_regenerate: Optional[bool] = True,
+ ) -> None:
"""
Update the form field values for a given page from a fields dictionary.
@@ -372,10 +971,84 @@ class PdfWriter(PdfDocCommon):
auto_regenerate: Set/unset the need_appearances flag;
the flag is unchanged if auto_regenerate is None.
"""
- pass
-
- def reattach_fields(self, page: Optional[PageObject]=None) ->List[
- DictionaryObject]:
+ if CatalogDictionary.ACRO_FORM not in self._root_object:
+ raise PyPdfError("No /AcroForm dictionary in PdfWriter Object")
+ af = cast(DictionaryObject, self._root_object[CatalogDictionary.ACRO_FORM])
+ if InteractiveFormDictEntries.Fields not in af:
+ raise PyPdfError("No /Fields dictionary in Pdf in PdfWriter Object")
+ if isinstance(auto_regenerate, bool):
+ self.set_need_appearances_writer(auto_regenerate)
+ # Iterate through pages, update field values
+ if page is None:
+ page = list(self.pages)
+ if isinstance(page, list):
+ for p in page:
+ if PG.ANNOTS in p: # just to prevent warnings
+ self.update_page_form_field_values(p, fields, flags, None)
+ return None
+ if PG.ANNOTS not in page:
+ logger_warning("No fields to update on this page", __name__)
+ return
+ for writer_annot in page[PG.ANNOTS]: # type: ignore
+ writer_annot = cast(DictionaryObject, writer_annot.get_object())
+ if writer_annot.get("/Subtype", "") != "/Widget":
+ continue
+ if "/FT" in writer_annot and "/T" in writer_annot:
+ writer_parent_annot = writer_annot
+ else:
+ writer_parent_annot = writer_annot.get(
+ PG.PARENT, DictionaryObject()
+ ).get_object()
+
+ for field, value in fields.items():
+ if not (
+ self._get_qualified_field_name(writer_parent_annot) == field
+ or writer_parent_annot.get("/T", None) == field
+ ):
+ continue
+ if (
+ writer_parent_annot.get("/FT", None) == "/Ch"
+ and "/I" in writer_parent_annot
+ ):
+ del writer_parent_annot["/I"]
+ if flags:
+ writer_annot[NameObject(FA.Ff)] = NumberObject(flags)
+ if isinstance(value, list):
+ lst = ArrayObject(TextStringObject(v) for v in value)
+ writer_parent_annot[NameObject(FA.V)] = lst
+ elif isinstance(value, tuple):
+ writer_annot[NameObject(FA.V)] = TextStringObject(
+ value[0],
+ )
+ else:
+ writer_parent_annot[NameObject(FA.V)] = TextStringObject(value)
+ if writer_parent_annot.get(FA.FT) in ("/Btn"):
+ # case of Checkbox button (no /FT found in Radio widgets
+ v = NameObject(value)
+ if v not in writer_annot[NameObject(AA.AP)][NameObject("/N")]:
+ v = NameObject("/Off")
+ # other cases will be updated through the for loop
+ writer_annot[NameObject(AA.AS)] = v
+ elif (
+ writer_parent_annot.get(FA.FT) == "/Tx"
+ or writer_parent_annot.get(FA.FT) == "/Ch"
+ ):
+ # textbox
+ if isinstance(value, tuple):
+ self._update_field_annotation(
+ writer_parent_annot, writer_annot, value[1], value[2]
+ )
+ else:
+ self._update_field_annotation(writer_parent_annot, writer_annot)
+ elif (
+ writer_annot.get(FA.FT) == "/Sig"
+ ): # deprecated # not implemented yet
+ # signature
+ logger_warning("Signature forms not implemented yet", __name__)
+
+ def reattach_fields(
+ self, page: Optional[PageObject] = None
+ ) -> List[DictionaryObject]:
"""
Parse annotations within the page looking for orphan fields and
reattach then into the Fields Structure.
@@ -387,9 +1060,43 @@ class PdfWriter(PdfDocCommon):
Returns:
list of reattached fields.
"""
- pass
-
- def clone_reader_document_root(self, reader: PdfReader) ->None:
+ lst = []
+ if page is None:
+ for p in self.pages:
+ lst += self.reattach_fields(p)
+ return lst
+
+ try:
+ af = cast(DictionaryObject, self._root_object[CatalogDictionary.ACRO_FORM])
+ except KeyError:
+ af = DictionaryObject()
+ self._root_object[NameObject(CatalogDictionary.ACRO_FORM)] = af
+ try:
+ fields = cast(ArrayObject, af[InteractiveFormDictEntries.Fields])
+ except KeyError:
+ fields = ArrayObject()
+ af[NameObject(InteractiveFormDictEntries.Fields)] = fields
+
+ if "/Annots" not in page:
+ return lst
+ annots = cast(ArrayObject, page["/Annots"])
+ for idx in range(len(annots)):
+ ano = annots[idx]
+ indirect = isinstance(ano, IndirectObject)
+ ano = cast(DictionaryObject, ano.get_object())
+ if ano.get("/Subtype", "") == "/Widget" and "/FT" in ano:
+ if (
+ "indirect_reference" in ano.__dict__
+ and ano.indirect_reference in fields
+ ):
+ continue
+ if not indirect:
+ annots[idx] = self._add_object(ano)
+ fields.append(ano.indirect_reference)
+ lst.append(ano)
+ return lst
+
+ def clone_reader_document_root(self, reader: PdfReader) -> None:
"""
Copy the reader document root to the writer and all sub-elements,
including pages, threads, outlines,... For partial insertion, ``append``
@@ -398,10 +1105,24 @@ class PdfWriter(PdfDocCommon):
Args:
reader: PdfReader from which the document root should be copied.
"""
- pass
-
- def clone_document_from_reader(self, reader: PdfReader,
- after_page_append: Optional[Callable[[PageObject], None]]=None) ->None:
+ self._objects.clear()
+ self._root_object = reader.root_object.clone(self)
+ self._root = self._root_object.indirect_reference # type: ignore[assignment]
+ self._pages = self._root_object.raw_get("/Pages")
+ self._flatten()
+ assert self.flattened_pages is not None
+ for p in self.flattened_pages:
+ p[NameObject("/Parent")] = self._pages
+ self._objects[cast(IndirectObject, p.indirect_reference).idnum - 1] = p
+ cast(DictionaryObject, self._pages.get_object())[
+ NameObject("/Kids")
+ ] = ArrayObject([p.indirect_reference for p in self.flattened_pages])
+
+ def clone_document_from_reader(
+ self,
+ reader: PdfReader,
+ after_page_append: Optional[Callable[[PageObject], None]] = None,
+ ) -> None:
"""
Create a copy (clone) of a document from a PDF file reader cloning
section '/Root' and '/Info' and '/ID' of the pdf.
@@ -416,9 +1137,27 @@ class PdfWriter(PdfDocCommon):
the callback is a reference to the page just appended to the
document.
"""
- pass
-
- def generate_file_identifiers(self) ->None:
+ self.clone_reader_document_root(reader)
+ self._info_obj = self._add_object(DictionaryObject())
+ if TK.INFO in reader.trailer:
+ self._info = reader._info # actually copy fields
+ try:
+ self._ID = cast(ArrayObject, reader._ID).clone(self)
+ except AttributeError:
+ pass
+ if callable(after_page_append):
+ for page in cast(
+ ArrayObject, cast(DictionaryObject, self._pages.get_object())["/Kids"]
+ ):
+ after_page_append(page.get_object())
+
+ def _compute_document_identifier(self) -> ByteStringObject:
+ stream = BytesIO()
+ self._write_pdf_structure(stream)
+ stream.seek(0)
+ return ByteStringObject(_rolling_checksum(stream).encode("utf8"))
+
+ def generate_file_identifiers(self) -> None:
"""
Generate an identifier for the PDF that will be written.
@@ -430,12 +1169,23 @@ class PdfWriter(PdfDocCommon):
identifier matches, a different version of the correct file has been found.
see 14.4 "File Identifiers".
"""
- pass
-
- def encrypt(self, user_password: str, owner_password: Optional[str]=
- None, use_128bit: bool=True, permissions_flag:
- UserAccessPermissions=ALL_DOCUMENT_PERMISSIONS, *, algorithm:
- Optional[str]=None) ->None:
+ if self._ID:
+ id1 = self._ID[0]
+ id2 = self._compute_document_identifier()
+ else:
+ id1 = self._compute_document_identifier()
+ id2 = id1
+ self._ID = ArrayObject((id1, id2))
+
+ def encrypt(
+ self,
+ user_password: str,
+ owner_password: Optional[str] = None,
+ use_128bit: bool = True,
+ permissions_flag: UserAccessPermissions = ALL_DOCUMENT_PERMISSIONS,
+ *,
+ algorithm: Optional[str] = None,
+ ) -> None:
"""
Encrypt this PDF file with the PDF Standard encryption handler.
@@ -459,9 +1209,50 @@ class PdfWriter(PdfDocCommon):
"AES-128", "AES-256-R5", "AES-256". If it is valid,
`use_128bit` will be ignored.
"""
- pass
-
- def write(self, stream: Union[Path, StrByteType]) ->Tuple[bool, IO[Any]]:
+ if owner_password is None:
+ owner_password = user_password
+
+ if algorithm is not None:
+ try:
+ alg = getattr(EncryptAlgorithm, algorithm.replace("-", "_"))
+ except AttributeError:
+ raise ValueError(f"algorithm '{algorithm}' NOT supported")
+ else:
+ alg = EncryptAlgorithm.RC4_128
+ if not use_128bit:
+ alg = EncryptAlgorithm.RC4_40
+ self.generate_file_identifiers()
+ assert self._ID
+ self._encryption = Encryption.make(alg, permissions_flag, self._ID[0])
+ # in case call `encrypt` again
+ entry = self._encryption.write_entry(user_password, owner_password)
+ if self._encrypt_entry:
+ # replace old encrypt_entry
+ assert self._encrypt_entry.indirect_reference is not None
+ entry.indirect_reference = self._encrypt_entry.indirect_reference
+ self._objects[entry.indirect_reference.idnum - 1] = entry
+ else:
+ self._add_object(entry)
+ self._encrypt_entry = entry
+
+ def write_stream(self, stream: StreamType) -> None:
+ if hasattr(stream, "mode") and "b" not in stream.mode:
+ logger_warning(
+ f"File <{stream.name}> to write to is not in binary mode. "
+ "It may not be written to correctly.",
+ __name__,
+ )
+
+ if not self._root:
+ self._root = self._add_object(self._root_object)
+
+ self._sweep_indirect_references(self._root)
+
+ object_positions = self._write_pdf_structure(stream)
+ xref_location = self._write_xref_table(stream, object_positions)
+ self._write_trailer(stream, xref_location)
+
+ def write(self, stream: Union[Path, StrByteType]) -> Tuple[bool, IO[Any]]:
"""
Write the collection of pages added to this object out as a PDF file.
@@ -474,9 +1265,49 @@ class PdfWriter(PdfDocCommon):
Returns:
A tuple (bool, IO).
"""
- pass
+ 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()
- def _write_trailer(self, stream: StreamType, xref_location: int) ->None:
+ return my_file, stream
+
+ def _write_pdf_structure(self, stream: StreamType) -> List[int]:
+ object_positions = []
+ stream.write(self.pdf_header.encode() + b"\n")
+ stream.write(b"%\xE2\xE3\xCF\xD3\n")
+
+ for i, obj in enumerate(self._objects):
+ if obj is not None:
+ idnum = i + 1
+ object_positions.append(stream.tell())
+ stream.write(f"{idnum} 0 obj\n".encode())
+ if self._encryption and obj != self._encrypt_entry:
+ obj = self._encryption.encrypt_object(obj, idnum, 0)
+ obj.write_to_stream(stream)
+ stream.write(b"\nendobj\n")
+ 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(f"0 {len(self._objects) + 1}\n".encode())
+ stream.write(f"{0:0>10} {65535:0>5} f \n".encode())
+ for offset in object_positions:
+ stream.write(f"{offset:0>10} {0:0>5} n \n".encode())
+ return xref_location
+
+ def _write_trailer(self, stream: StreamType, xref_location: int) -> None:
"""
Write the PDF trailer to the stream.
@@ -484,9 +1315,23 @@ class PdfWriter(PdfDocCommon):
[The] trailer [gives] the location of the cross-reference table and
of certain special objects within the body of the file.
"""
- pass
-
- def add_metadata(self, infos: Dict[str, Any]) ->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_obj,
+ }
+ )
+ if self._ID:
+ trailer[NameObject(TK.ID)] = self._ID
+ if self._encrypt_entry:
+ trailer[NameObject(TK.ENCRYPT)] = self._encrypt_entry.indirect_reference
+ trailer.write_to_stream(stream)
+ stream.write(f"\nstartxref\n{xref_location}\n%%EOF\n".encode()) # eof
+
+ def add_metadata(self, infos: Dict[str, Any]) -> None:
"""
Add custom metadata to the output.
@@ -494,12 +1339,31 @@ class PdfWriter(PdfDocCommon):
infos: a Python dictionary where each key is a field
and each value is your new metadata.
"""
- pass
-
- def _sweep_indirect_references(self, root: Union[ArrayObject,
- BooleanObject, DictionaryObject, FloatObject, IndirectObject,
- NameObject, PdfObject, NumberObject, TextStringObject, NullObject]
- ) ->None:
+ args = {}
+ if isinstance(infos, PdfObject):
+ infos = cast(DictionaryObject, infos.get_object())
+ for key, value in list(infos.items()):
+ if isinstance(value, PdfObject):
+ value = value.get_object()
+ args[NameObject(key)] = create_string_object(str(value))
+ assert isinstance(self._info, DictionaryObject)
+ self._info.update(args)
+
+ def _sweep_indirect_references(
+ self,
+ root: Union[
+ ArrayObject,
+ BooleanObject,
+ DictionaryObject,
+ FloatObject,
+ IndirectObject,
+ NameObject,
+ PdfObject,
+ NumberObject,
+ TextStringObject,
+ NullObject,
+ ],
+ ) -> None:
"""
Resolving any circular references to Page objects.
@@ -515,9 +1379,73 @@ class PdfWriter(PdfDocCommon):
Args:
root: The root of the PDF object tree to sweep.
"""
- pass
-
- def _resolve_indirect_object(self, data: IndirectObject) ->IndirectObject:
+ 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) and 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 an indirect object to an indirect object in this PDF file.
@@ -542,9 +1470,63 @@ class PdfWriter(PdfDocCommon):
Raises:
ValueError: If the input stream is closed.
"""
- pass
-
- def get_threads_root(self) ->ArrayObject:
+ 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 get_outline_root(self) -> TreeObject:
+ if CO.OUTLINES in self._root_object:
+ # Table 3.25 Entries in the catalog dictionary
+ outline = cast(TreeObject, self._root_object[CO.OUTLINES])
+ if not isinstance(outline, TreeObject):
+ t = TreeObject(outline)
+ self._replace_object(outline.indirect_reference.idnum, t)
+ outline = t
+ idnum = self._objects.index(outline) + 1
+ outline_ref = IndirectObject(idnum, 0, self)
+ assert outline_ref.get_object() == outline
+ else:
+ outline = TreeObject()
+ outline.update({})
+ outline_ref = self._add_object(outline)
+ self._root_object[NameObject(CO.OUTLINES)] = outline_ref
+
+ return outline
+
+ def get_threads_root(self) -> ArrayObject:
"""
The list of threads.
@@ -554,10 +1536,16 @@ class PdfWriter(PdfDocCommon):
An array (possibly empty) of Dictionaries with ``/F`` and
``/I`` properties.
"""
- pass
+ 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:
+ def threads(self) -> ArrayObject:
"""
Read-only property for the list of threads.
@@ -565,14 +1553,80 @@ class PdfWriter(PdfDocCommon):
Each element is a dictionaries with ``/F`` and ``/I`` keys.
"""
- pass
-
- def add_outline_item(self, title: str, page_number: Union[None,
- PageObject, IndirectObject, int], parent: Union[None, TreeObject,
- IndirectObject]=None, before: Union[None, TreeObject,
- IndirectObject]=None, color: Optional[Union[Tuple[float, float,
- float], str]]=None, bold: bool=False, italic: bool=False, fit: Fit=
- PAGE_FIT, is_open: bool=True) ->IndirectObject:
+ return self.get_threads_root()
+
+ def add_outline_item_destination(
+ self,
+ page_destination: Union[IndirectObject, PageObject, TreeObject],
+ parent: Union[None, TreeObject, IndirectObject] = None,
+ before: Union[None, TreeObject, IndirectObject] = None,
+ is_open: bool = True,
+ ) -> IndirectObject:
+ page_destination = cast(PageObject, page_destination.get_object())
+ if isinstance(page_destination, PageObject):
+ return self.add_outline_item_destination(
+ Destination(
+ f"page #{page_destination.page_number}",
+ cast(IndirectObject, page_destination.indirect_reference),
+ Fit.fit(),
+ )
+ )
+
+ if parent is None:
+ parent = self.get_outline_root()
+
+ page_destination[NameObject("/%is_open%")] = BooleanObject(is_open)
+ parent = cast(TreeObject, parent.get_object())
+ page_destination_ref = self._add_object(page_destination)
+ if before is not None:
+ before = before.indirect_reference
+ parent.insert_child(
+ page_destination_ref,
+ before,
+ self,
+ page_destination.inc_parent_counter_outline
+ if is_open
+ else (lambda x, y: 0),
+ )
+ if "/Count" not in page_destination:
+ page_destination[NameObject("/Count")] = NumberObject(0)
+
+ return page_destination_ref
+
+ def add_outline_item_dict(
+ self,
+ outline_item: OutlineItemType,
+ parent: Union[None, TreeObject, IndirectObject] = None,
+ before: Union[None, TreeObject, IndirectObject] = None,
+ is_open: bool = True,
+ ) -> IndirectObject:
+ outline_item_object = TreeObject()
+ outline_item_object.update(outline_item)
+
+ if "/A" in outline_item:
+ action = DictionaryObject()
+ a_dict = cast(DictionaryObject, outline_item["/A"])
+ for k, v in list(a_dict.items()):
+ action[NameObject(str(k))] = v
+ action_ref = self._add_object(action)
+ outline_item_object[NameObject("/A")] = action_ref
+
+ return self.add_outline_item_destination(
+ outline_item_object, parent, before, is_open
+ )
+
+ def add_outline_item(
+ self,
+ title: str,
+ page_number: Union[None, PageObject, IndirectObject, int],
+ parent: Union[None, TreeObject, IndirectObject] = None,
+ before: Union[None, TreeObject, IndirectObject] = None,
+ color: Optional[Union[Tuple[float, float, float], str]] = None,
+ bold: bool = False,
+ italic: bool = False,
+ fit: Fit = PAGE_FIT,
+ is_open: bool = True,
+ ) -> IndirectObject:
"""
Add an outline item (commonly referred to as a "Bookmark") to the PDF file.
@@ -591,14 +1645,115 @@ class PdfWriter(PdfDocCommon):
Returns:
The added outline item as an indirect object.
"""
- pass
-
- def remove_links(self) ->None:
+ 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, is_open=is_open # type: ignore
+ )
+ if page_number is None:
+ action_ref = None
+ else:
+ if isinstance(page_number, IndirectObject):
+ page_ref = page_number
+ elif isinstance(page_number, PageObject):
+ page_ref = page_number.indirect_reference
+ elif isinstance(page_number, int):
+ try:
+ page_ref = self.pages[page_number].indirect_reference
+ except IndexError:
+ page_ref = NumberObject(page_number)
+ if page_ref is None:
+ logger_warning(
+ f"can not find reference of page {page_number}",
+ __name__,
+ )
+ page_ref = NullObject()
+ dest = Destination(
+ NameObject("/" + title + " outline item"),
+ page_ref,
+ fit,
+ )
+
+ action_ref = self._add_object(
+ DictionaryObject(
+ {
+ NameObject(GoToActionArguments.D): dest.dest_array,
+ NameObject(GoToActionArguments.S): NameObject("/GoTo"),
+ }
+ )
+ )
+ outline_item = self._add_object(
+ _create_outline_item(action_ref, title, color, italic, bold)
+ )
+
+ if parent is None:
+ parent = self.get_outline_root()
+ return self.add_outline_item_destination(outline_item, parent, before, is_open)
+
+ def add_outline(self) -> None:
+ raise NotImplementedError(
+ "This method is not yet implemented. Use :meth:`add_outline_item` instead."
+ )
+
+ def add_named_destination_array(
+ self, title: TextStringObject, destination: Union[IndirectObject, ArrayObject]
+ ) -> None:
+ named_dest = self.get_named_dest_root()
+ i = 0
+ while i < len(named_dest):
+ if title < named_dest[i]:
+ named_dest.insert(i, destination)
+ named_dest.insert(i, TextStringObject(title))
+ return
+ else:
+ i += 2
+ named_dest.extend([TextStringObject(title), destination])
+ return
+
+ def add_named_destination_object(
+ self,
+ page_destination: PdfObject,
+ ) -> IndirectObject:
+ page_destination_ref = self._add_object(page_destination.dest_array) # type: ignore
+ self.add_named_destination_array(
+ cast("TextStringObject", page_destination["/Title"]), page_destination_ref # type: ignore
+ )
+
+ return page_destination_ref
+
+ def add_named_destination(
+ self,
+ title: str,
+ page_number: int,
+ ) -> IndirectObject:
+ page_ref = self.get_object(self._pages)[PA.KIDS][page_number] # type: ignore
+ dest = DictionaryObject()
+ dest.update(
+ {
+ NameObject(GoToActionArguments.D): ArrayObject(
+ [page_ref, NameObject(TypFitArguments.FIT_H), NumberObject(826)]
+ ),
+ NameObject(GoToActionArguments.S): NameObject("/GoTo"),
+ }
+ )
+
+ dest_ref = self._add_object(dest)
+ if not isinstance(title, TextStringObject):
+ title = TextStringObject(str(title))
+
+ self.add_named_destination_array(title, dest_ref)
+ return dest_ref
+
+ def remove_links(self) -> None:
"""Remove links and annotations from this output."""
- pass
+ for page in self.pages:
+ self.remove_objects_from_page(page, ObjectDeletionFlag.ALL_ANNOTATIONS)
- def remove_annotations(self, subtypes: Optional[Union[AnnotationSubtype,
- Iterable[AnnotationSubtype]]]) ->None:
+ def remove_annotations(
+ self, subtypes: Optional[Union[AnnotationSubtype, Iterable[AnnotationSubtype]]]
+ ) -> None:
"""
Remove annotations by annotation subtype.
@@ -608,11 +1763,32 @@ class PdfWriter(PdfDocCommon):
"/Movie", "/Screen", ...
If you want to remove all annotations, use subtypes=None.
"""
- pass
-
- def remove_objects_from_page(self, page: Union[PageObject,
- DictionaryObject], to_delete: Union[ObjectDeletionFlag, Iterable[
- ObjectDeletionFlag]]) ->None:
+ for page in self.pages:
+ self._remove_annots_from_page(page, subtypes)
+
+ def _remove_annots_from_page(
+ self,
+ page: Union[IndirectObject, PageObject, DictionaryObject],
+ subtypes: Optional[Iterable[str]],
+ ) -> None:
+ page = cast(DictionaryObject, page.get_object())
+ if PG.ANNOTS in page:
+ i = 0
+ while i < len(cast(ArrayObject, page[PG.ANNOTS])):
+ an = cast(ArrayObject, page[PG.ANNOTS])[i]
+ obj = cast(DictionaryObject, an.get_object())
+ if subtypes is None or cast(str, obj["/Subtype"]) in subtypes:
+ if isinstance(an, IndirectObject):
+ self._objects[an.idnum - 1] = NullObject() # to reduce PDF size
+ del page[PG.ANNOTS][i] # type:ignore
+ else:
+ i += 1
+
+ def remove_objects_from_page(
+ self,
+ page: Union[PageObject, DictionaryObject],
+ to_delete: Union[ObjectDeletionFlag, Iterable[ObjectDeletionFlag]],
+ ) -> None:
"""
Remove objects specified by ``to_delete`` from the given page.
@@ -621,9 +1797,142 @@ class PdfWriter(PdfDocCommon):
to_delete: Objects to be deleted; can be a ``ObjectDeletionFlag``
or a list of ObjectDeletionFlag
"""
- pass
-
- def remove_images(self, to_delete: ImageType=ImageType.ALL) ->None:
+ if isinstance(to_delete, (list, tuple)):
+ for to_d in to_delete:
+ self.remove_objects_from_page(page, to_d)
+ return
+ assert isinstance(to_delete, ObjectDeletionFlag)
+
+ if to_delete & ObjectDeletionFlag.LINKS:
+ return self._remove_annots_from_page(page, ("/Link",))
+ if to_delete & ObjectDeletionFlag.ATTACHMENTS:
+ return self._remove_annots_from_page(
+ page, ("/FileAttachment", "/Sound", "/Movie", "/Screen")
+ )
+ if to_delete & ObjectDeletionFlag.OBJECTS_3D:
+ return self._remove_annots_from_page(page, ("/3D",))
+ if to_delete & ObjectDeletionFlag.ALL_ANNOTATIONS:
+ return self._remove_annots_from_page(page, None)
+
+ jump_operators = []
+ if to_delete & ObjectDeletionFlag.DRAWING_IMAGES:
+ jump_operators = (
+ [b"w", b"J", b"j", b"M", b"d", b"i"]
+ + [b"W", b"W*"]
+ + [b"b", b"b*", b"B", b"B*", b"S", b"s", b"f", b"f*", b"F", b"n"]
+ + [b"m", b"l", b"c", b"v", b"y", b"h", b"re"]
+ + [b"sh"]
+ )
+ if to_delete & ObjectDeletionFlag.TEXT:
+ jump_operators = [b"Tj", b"TJ", b"'", b'"']
+
+ def clean(content: ContentStream, images: List[str], forms: List[str]) -> None:
+ nonlocal jump_operators, to_delete
+ i = 0
+ while i < len(content.operations):
+ operands, operator = content.operations[i]
+ if (
+ (
+ operator == b"INLINE IMAGE"
+ and (to_delete & ObjectDeletionFlag.INLINE_IMAGES)
+ )
+ or (operator in jump_operators)
+ or (
+ operator == b"Do"
+ and (to_delete & ObjectDeletionFlag.XOBJECT_IMAGES)
+ and (operands[0] in images)
+ )
+ ):
+ del content.operations[i]
+ else:
+ i += 1
+ content.get_data() # this ensures ._data is rebuilt from the .operations
+
+ def clean_forms(
+ elt: DictionaryObject, stack: List[DictionaryObject]
+ ) -> Tuple[List[str], List[str]]:
+ nonlocal to_delete
+ # elt in recursive call is a new ContentStream object, so we have to check the indirect_reference
+ if (elt in stack) or (
+ hasattr(elt, "indirect_reference")
+ and any(
+ elt.indirect_reference == getattr(x, "indirect_reference", -1)
+ for x in stack
+ )
+ ):
+ # to prevent infinite looping
+ return [], [] # pragma: no cover
+ try:
+ d = cast(
+ Dict[Any, Any],
+ cast(DictionaryObject, elt["/Resources"])["/XObject"],
+ )
+ except KeyError:
+ d = {}
+ images = []
+ forms = []
+ for k, v in d.items():
+ o = v.get_object()
+ try:
+ content: Any = None
+ if (
+ to_delete & ObjectDeletionFlag.XOBJECT_IMAGES
+ and o["/Subtype"] == "/Image"
+ ):
+ content = NullObject() # to delete the image keeping the entry
+ images.append(k)
+ if o["/Subtype"] == "/Form":
+ forms.append(k)
+ if isinstance(o, ContentStream):
+ content = o
+ else:
+ content = ContentStream(o, self)
+ content.update(
+ {
+ k1: v1
+ for k1, v1 in o.items()
+ if k1 not in ["/Length", "/Filter", "/DecodeParms"]
+ }
+ )
+ try:
+ content.indirect_reference = o.indirect_reference
+ except AttributeError: # pragma: no cover
+ pass
+ stack.append(elt)
+ clean_forms(content, stack) # clean subforms
+ if content is not None:
+ if isinstance(v, IndirectObject):
+ self._objects[v.idnum - 1] = content
+ else:
+ # should only occur with pdf not respecting pdf spec
+ # where streams must be indirected.
+ d[k] = self._add_object(content) # pragma: no cover
+ except (TypeError, KeyError):
+ pass
+ for im in images:
+ del d[im] # for clean-up
+ if isinstance(elt, StreamObject): # for /Form
+ if not isinstance(elt, ContentStream): # pragma: no cover
+ e = ContentStream(elt, self)
+ e.update(elt.items())
+ elt = e
+ clean(elt, images, forms) # clean the content
+ return images, forms
+
+ if not isinstance(page, PageObject):
+ page = PageObject(self, page.indirect_reference) # pragma: no cover
+ if "/Contents" in page:
+ content = cast(ContentStream, page.get_contents())
+
+ images, forms = clean_forms(page, [])
+
+ clean(content, images, forms)
+ page.replace_contents(content)
+
+ def remove_images(
+ self,
+ to_delete: ImageType = ImageType.ALL,
+ ) -> None:
"""
Remove images from this output.
@@ -631,14 +1940,40 @@ class PdfWriter(PdfDocCommon):
to_delete : The type of images to be deleted
(default = all images types)
"""
- pass
-
- def remove_text(self) ->None:
+ if isinstance(to_delete, bool):
+ to_delete = ImageType.ALL
+ i = (
+ (
+ ObjectDeletionFlag.XOBJECT_IMAGES
+ if to_delete & ImageType.XOBJECT_IMAGES
+ else ObjectDeletionFlag.NONE
+ )
+ | (
+ ObjectDeletionFlag.INLINE_IMAGES
+ if to_delete & ImageType.INLINE_IMAGES
+ else ObjectDeletionFlag.NONE
+ )
+ | (
+ ObjectDeletionFlag.DRAWING_IMAGES
+ if to_delete & ImageType.DRAWING_IMAGES
+ else ObjectDeletionFlag.NONE
+ )
+ )
+ for page in self.pages:
+ self.remove_objects_from_page(page, i)
+
+ def remove_text(self) -> None:
"""Remove text from this output."""
- pass
+ for page in self.pages:
+ self.remove_objects_from_page(page, ObjectDeletionFlag.TEXT)
- def add_uri(self, page_number: int, uri: str, rect: RectangleObject,
- border: Optional[ArrayObject]=None) ->None:
+ def add_uri(
+ self,
+ page_number: int,
+ uri: str,
+ rect: RectangleObject,
+ border: Optional[ArrayObject] = None,
+ ) -> None:
"""
Add an URI from a rectangular area to the specified page.
@@ -653,11 +1988,68 @@ class PdfWriter(PdfDocCommon):
properties. See the PDF spec for details. No border will be
drawn if this argument is omitted.
"""
- pass
- _valid_layouts = ('/NoLayout', '/SinglePage', '/OneColumn',
- '/TwoColumnLeft', '/TwoColumnRight', '/TwoPageLeft', '/TwoPageRight')
-
- def _set_page_layout(self, layout: Union[NameObject, LayoutType]) ->None:
+ page_link = self.get_object(self._pages)[PA.KIDS][page_number] # type: ignore
+ page_ref = cast(Dict[str, Any], self.get_object(page_link))
+
+ border_arr: BorderArrayType
+ if border is not None:
+ border_arr = [NumberObject(n) for n in border[:3]]
+ if len(border) == 4:
+ dash_pattern = ArrayObject([NumberObject(n) for n in border[3]])
+ border_arr.append(dash_pattern)
+ else:
+ border_arr = [NumberObject(2), NumberObject(2), NumberObject(2)]
+
+ if isinstance(rect, str):
+ rect = NumberObject(rect)
+ elif isinstance(rect, RectangleObject):
+ pass
+ else:
+ rect = RectangleObject(rect)
+
+ lnk2 = DictionaryObject()
+ lnk2.update(
+ {
+ NameObject("/S"): NameObject("/URI"),
+ NameObject("/URI"): TextStringObject(uri),
+ }
+ )
+ lnk = DictionaryObject()
+ lnk.update(
+ {
+ NameObject(AA.Type): NameObject("/Annot"),
+ NameObject(AA.Subtype): NameObject("/Link"),
+ NameObject(AA.P): page_link,
+ NameObject(AA.Rect): rect,
+ NameObject("/H"): NameObject("/I"),
+ NameObject(AA.Border): ArrayObject(border_arr),
+ NameObject("/A"): lnk2,
+ }
+ )
+ lnk_ref = self._add_object(lnk)
+
+ if PG.ANNOTS in page_ref:
+ page_ref[PG.ANNOTS].append(lnk_ref)
+ else:
+ page_ref[NameObject(PG.ANNOTS)] = ArrayObject([lnk_ref])
+
+ _valid_layouts = (
+ "/NoLayout",
+ "/SinglePage",
+ "/OneColumn",
+ "/TwoColumnLeft",
+ "/TwoColumnRight",
+ "/TwoPageLeft",
+ "/TwoPageRight",
+ )
+
+ def _get_page_layout(self) -> Optional[LayoutType]:
+ try:
+ return cast(LayoutType, self._root_object["/PageLayout"])
+ except KeyError:
+ return None
+
+ def _set_page_layout(self, layout: Union[NameObject, LayoutType]) -> None:
"""
Set the page layout.
@@ -682,9 +2074,16 @@ class PdfWriter(PdfDocCommon):
* - /TwoPageRight
- Show two pages at a time, odd-numbered pages on the right
"""
- pass
+ 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:
+ def set_page_layout(self, layout: LayoutType) -> None:
"""
Set the page layout.
@@ -709,10 +2108,10 @@ class PdfWriter(PdfDocCommon):
* - /TwoPageRight
- Show two pages at a time, odd-numbered pages on the right
"""
- pass
+ self._set_page_layout(layout)
@property
- def page_layout(self) ->Optional[LayoutType]:
+ def page_layout(self) -> Optional[LayoutType]:
"""
Page layout property.
@@ -734,12 +2133,29 @@ class PdfWriter(PdfDocCommon):
* - /TwoPageRight
- Show two pages at a time, odd-numbered pages on the right
"""
- pass
- _valid_modes = ('/UseNone', '/UseOutlines', '/UseThumbs', '/FullScreen',
- '/UseOC', '/UseAttachments')
+ return self._get_page_layout()
+
+ @page_layout.setter
+ def page_layout(self, layout: LayoutType) -> None:
+ self._set_page_layout(layout)
+
+ _valid_modes = (
+ "/UseNone",
+ "/UseOutlines",
+ "/UseThumbs",
+ "/FullScreen",
+ "/UseOC",
+ "/UseAttachments",
+ )
+
+ def _get_page_mode(self) -> Optional[PagemodeType]:
+ try:
+ return cast(PagemodeType, self._root_object["/PageMode"])
+ except KeyError:
+ return None
@property
- def page_mode(self) ->Optional[PagemodeType]:
+ def page_mode(self) -> Optional[PagemodeType]:
"""
Page mode property.
@@ -759,10 +2175,25 @@ class PdfWriter(PdfDocCommon):
* - /UseAttachments
- Show attachments panel
"""
- pass
-
- def add_annotation(self, page_number: Union[int, PageObject],
- annotation: Dict[str, Any]) ->DictionaryObject:
+ return self._get_page_mode()
+
+ @page_mode.setter
+ def page_mode(self, mode: PagemodeType) -> None:
+ if isinstance(mode, NameObject):
+ mode_name: NameObject = mode
+ else:
+ if mode not in self._valid_modes:
+ logger_warning(
+ f"Mode should be one of: {', '.join(self._valid_modes)}", __name__
+ )
+ mode_name = NameObject(mode)
+ self._root_object.update({NameObject("/PageMode"): mode_name})
+
+ def add_annotation(
+ self,
+ page_number: Union[int, PageObject],
+ annotation: Dict[str, Any],
+ ) -> DictionaryObject:
"""
Add a single annotation to the page.
The added annotation must be a new annotation.
@@ -776,9 +2207,42 @@ class PdfWriter(PdfDocCommon):
The inserted object.
This can be used for popup creation, for example.
"""
- pass
+ page = page_number
+ if isinstance(page, int):
+ page = self.pages[page]
+ elif not isinstance(page, PageObject):
+ raise TypeError("page: invalid type")
+
+ to_add = cast(DictionaryObject, _pdf_objectify(annotation))
+ to_add[NameObject("/P")] = page.indirect_reference
+
+ if page.annotations is None:
+ page[NameObject("/Annots")] = ArrayObject()
+ assert page.annotations is not None
+
+ # Internal link annotations need the correct object type for the
+ # destination
+ if to_add.get("/Subtype") == "/Link" and "/Dest" in to_add:
+ tmp = cast(Dict[Any, Any], to_add[NameObject("/Dest")])
+ dest = Destination(
+ NameObject("/LinkName"),
+ tmp["target_page_index"],
+ Fit(
+ fit_type=tmp["fit"], fit_args=dict(tmp)["fit_args"]
+ ), # I have no clue why this dict-hack is necessary
+ )
+ to_add[NameObject("/Dest")] = dest.dest_array
- def clean_page(self, page: Union[PageObject, IndirectObject]) ->PageObject:
+ page.annotations.append(self._add_object(to_add))
+
+ if to_add.get("/Subtype") == "/Popup" and NameObject("/Parent") in to_add:
+ cast(DictionaryObject, to_add["/Parent"].get_object())[
+ NameObject("/Popup")
+ ] = to_add.indirect_reference
+
+ return to_add
+
+ def clean_page(self, page: Union[PageObject, IndirectObject]) -> PageObject:
"""
Perform some clean up in the page.
Currently: convert NameObject named destination to TextStringObject
@@ -790,14 +2254,73 @@ class PdfWriter(PdfDocCommon):
Returns:
The cleaned PageObject
"""
- pass
-
- def append(self, fileobj: Union[StrByteType, PdfReader, Path],
- outline_item: Union[str, None, PageRange, Tuple[int, int], Tuple[
- int, int, int], List[int]]=None, pages: Union[None, PageRange,
- Tuple[int, int], Tuple[int, int, int], List[int], List[PageObject]]
- =None, import_outline: bool=True, excluded_fields: Optional[Union[
- List[str], Tuple[str, ...]]]=None) ->None:
+ 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],
+ List[PageObject],
+ ] = 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
@@ -822,13 +2345,41 @@ class PdfWriter(PdfDocCommon):
if ``/Annots`` is part of the list, the annotation will be ignored
if ``/B`` is part of the list, the articles will be ignored
"""
- pass
-
- def merge(self, position: Optional[int], fileobj: Union[Path,
- StrByteType, PdfReader], outline_item: Optional[str]=None, pages:
- Optional[Union[PageRangeSpec, List[PageObject]]]=None,
- import_outline: bool=True, excluded_fields: Optional[Union[List[str
- ], Tuple[str, ...]]]=()) ->None:
+ if excluded_fields is None:
+ excluded_fields = ()
+ if isinstance(outline_item, (tuple, list, PageRange)):
+ if isinstance(pages, bool):
+ if not isinstance(import_outline, bool):
+ excluded_fields = import_outline
+ import_outline = pages
+ pages = outline_item
+ self.merge(
+ None,
+ fileobj,
+ None,
+ pages,
+ import_outline,
+ excluded_fields,
+ )
+ else: # if isinstance(outline_item,str):
+ self.merge(
+ None,
+ fileobj,
+ outline_item,
+ pages,
+ import_outline,
+ excluded_fields,
+ )
+
+ def merge(
+ self,
+ position: Optional[int],
+ fileobj: Union[Path, StrByteType, PdfReader],
+ outline_item: Optional[str] = None,
+ pages: Optional[Union[PageRangeSpec, List[PageObject]]] = None,
+ import_outline: bool = True,
+ excluded_fields: Optional[Union[List[str], Tuple[str, ...]]] = (),
+ ) -> None:
"""
Merge the pages from the given file into the output file at the
specified page number.
@@ -857,10 +2408,155 @@ class PdfWriter(PdfDocCommon):
Raises:
TypeError: The pages attribute is not configured properly
"""
- pass
-
- def _add_articles_thread(self, thread: DictionaryObject, pages: Dict[
- int, PageObject], reader: PdfReader) ->IndirectObject:
+ if isinstance(fileobj, PdfDocCommon):
+ reader = fileobj
+ else:
+ stream, encryption_obj = self._create_stream(fileobj)
+ # Create a new PdfReader instance using the stream
+ # (either file or BytesIO or StringIO) created above
+ reader = PdfReader(stream, strict=False) # type: ignore[arg-type]
+
+ if excluded_fields is None:
+ excluded_fields = ()
+ # Find the range of pages to merge.
+ if pages is None:
+ pages = list(range(len(reader.pages)))
+ elif isinstance(pages, PageRange):
+ pages = list(range(*pages.indices(len(reader.pages))))
+ elif isinstance(pages, list):
+ pass # keep unchanged
+ elif isinstance(pages, tuple) and len(pages) <= 3:
+ pages = list(range(*pages))
+ elif not isinstance(pages, tuple):
+ raise TypeError(
+ '"pages" must be a tuple of (start, stop[, step]) or a list'
+ )
+
+ srcpages = {}
+ for page in pages:
+ if isinstance(page, PageObject):
+ pg = page
+ else:
+ pg = reader.pages[page]
+ assert pg.indirect_reference is not None
+ if position is None:
+ # numbers in the exclude list identifies that the exclusion is
+ # only applicable to 1st level of cloning
+ srcpages[pg.indirect_reference.idnum] = self.add_page(
+ pg, list(excluded_fields) + [1, "/B", 1, "/Annots"] # type: ignore
+ )
+ else:
+ srcpages[pg.indirect_reference.idnum] = self.insert_page(
+ pg, position, list(excluded_fields) + [1, "/B", 1, "/Annots"] # type: ignore
+ )
+ position += 1
+ srcpages[pg.indirect_reference.idnum].original_page = pg
+
+ reader._namedDests = (
+ reader.named_destinations
+ ) # need for the outline processing below
+ for dest in reader._namedDests.values():
+ arr = dest.dest_array
+ if "/Names" in self._root_object and dest["/Title"] in cast(
+ List[Any],
+ cast(
+ DictionaryObject,
+ cast(DictionaryObject, self._root_object["/Names"])["/Dests"],
+ )["/Names"],
+ ):
+ # already exists : should not duplicate it
+ pass
+ elif isinstance(dest["/Page"], NullObject):
+ pass
+ elif isinstance(dest["/Page"], int):
+ # the page reference is a page number normally not a PDF Reference
+ # page numbers as int are normally accepted only in external goto
+ p = reader.pages[dest["/Page"]]
+ assert p.indirect_reference is not None
+ try:
+ arr[NumberObject(0)] = NumberObject(
+ srcpages[p.indirect_reference.idnum].page_number
+ )
+ self.add_named_destination_array(dest["/Title"], arr)
+ except KeyError:
+ pass
+ elif dest["/Page"].indirect_reference.idnum in srcpages:
+ arr[NumberObject(0)] = srcpages[
+ dest["/Page"].indirect_reference.idnum
+ ].indirect_reference
+ self.add_named_destination_array(dest["/Title"], arr)
+
+ outline_item_typ: TreeObject
+ if outline_item is not None:
+ outline_item_typ = cast(
+ "TreeObject",
+ self.add_outline_item(
+ TextStringObject(outline_item),
+ next(iter(srcpages.values())).indirect_reference,
+ fit=PAGE_FIT,
+ ).get_object(),
+ )
+ else:
+ outline_item_typ = self.get_outline_root()
+
+ _ro = reader.root_object
+ if import_outline and CO.OUTLINES in _ro:
+ outline = self._get_filtered_outline(
+ _ro.get(CO.OUTLINES, None), srcpages, reader
+ )
+ self._insert_filtered_outline(
+ outline, outline_item_typ, None
+ ) # TODO : use before parameter
+
+ if "/Annots" not in excluded_fields:
+ for pag in srcpages.values():
+ lst = self._insert_filtered_annotations(
+ pag.original_page.get("/Annots", ()), pag, srcpages, reader
+ )
+ if len(lst) > 0:
+ pag[NameObject("/Annots")] = lst
+ self.clean_page(pag)
+
+ if "/AcroForm" in _ro and _ro["/AcroForm"] is not None:
+ if "/AcroForm" not in self._root_object:
+ self._root_object[NameObject("/AcroForm")] = self._add_object(
+ cast(
+ DictionaryObject,
+ reader.root_object["/AcroForm"],
+ ).clone(self, False, ("/Fields",))
+ )
+ arr = ArrayObject()
+ else:
+ arr = cast(
+ ArrayObject,
+ cast(DictionaryObject, self._root_object["/AcroForm"])["/Fields"],
+ )
+ trslat = self._id_translated[id(reader)]
+ try:
+ for f in reader.root_object["/AcroForm"]["/Fields"]: # type: ignore
+ try:
+ ind = IndirectObject(trslat[f.idnum], 0, self)
+ if ind not in arr:
+ arr.append(ind)
+ except KeyError:
+ # for trslat[] which mean the field has not be copied
+ # through the page
+ pass
+ except KeyError: # for /Acroform or /Fields are not existing
+ arr = self._add_object(ArrayObject())
+ cast(DictionaryObject, self._root_object["/AcroForm"])[
+ NameObject("/Fields")
+ ] = arr
+
+ if "/B" not in excluded_fields:
+ self.add_filtered_articles("", srcpages, reader)
+
+ def _add_articles_thread(
+ self,
+ thread: DictionaryObject, # thread entry from the reader's array of threads
+ pages: Dict[int, PageObject],
+ reader: PdfReader,
+ ) -> IndirectObject:
"""
Clone the thread with only the applicable articles.
@@ -872,10 +2568,61 @@ class PdfWriter(PdfDocCommon):
Returns:
The added thread as an indirect reference
"""
- pass
-
- def add_filtered_articles(self, fltr: Union[Pattern[Any], str], pages:
- Dict[int, PageObject], reader: PdfReader) ->None:
+ nthread = thread.clone(
+ self, force_duplicate=True, ignore_fields=("/F",)
+ ) # use of clone to keep link between reader and writer
+ self.threads.append(nthread.indirect_reference)
+ first_article = cast("DictionaryObject", thread["/F"])
+ current_article: Optional[DictionaryObject] = first_article
+ new_article: Optional[DictionaryObject] = None
+ while current_article is not None:
+ pag = self._get_cloned_page(
+ cast("PageObject", current_article["/P"]), pages, reader
+ )
+ if pag is not None:
+ if new_article is None:
+ new_article = cast(
+ "DictionaryObject",
+ self._add_object(DictionaryObject()).get_object(),
+ )
+ new_first = new_article
+ nthread[NameObject("/F")] = new_article.indirect_reference
+ else:
+ new_article2 = cast(
+ "DictionaryObject",
+ self._add_object(
+ DictionaryObject(
+ {NameObject("/V"): new_article.indirect_reference}
+ )
+ ).get_object(),
+ )
+ new_article[NameObject("/N")] = new_article2.indirect_reference
+ new_article = new_article2
+ new_article[NameObject("/P")] = pag
+ new_article[NameObject("/T")] = nthread.indirect_reference
+ new_article[NameObject("/R")] = current_article["/R"]
+ pag_obj = cast("PageObject", pag.get_object())
+ if "/B" not in pag_obj:
+ pag_obj[NameObject("/B")] = ArrayObject()
+ cast("ArrayObject", pag_obj["/B"]).append(
+ new_article.indirect_reference
+ )
+ current_article = cast("DictionaryObject", current_article["/N"])
+ if current_article == first_article:
+ new_article[NameObject("/N")] = new_first.indirect_reference # type: ignore
+ new_first[NameObject("/V")] = new_article.indirect_reference # type: ignore
+ current_article = None
+ assert nthread.indirect_reference is not None
+ return nthread.indirect_reference
+
+ def add_filtered_articles(
+ self,
+ fltr: Union[
+ Pattern[Any], str
+ ], # thread entry from the reader's array of threads
+ pages: Dict[int, PageObject],
+ reader: PdfReader,
+ ) -> None:
"""
Add articles matching the defined criteria.
@@ -884,10 +2631,98 @@ class PdfWriter(PdfDocCommon):
pages:
reader:
"""
- pass
-
- def _get_filtered_outline(self, node: Any, pages: Dict[int, PageObject],
- reader: PdfReader) ->List[Destination]:
+ if isinstance(fltr, str):
+ fltr = re.compile(fltr)
+ elif not isinstance(fltr, Pattern):
+ fltr = re.compile("")
+ for p in pages.values():
+ pp = p.original_page
+ for a in pp.get("/B", ()):
+ thr = a.get_object().get("/T")
+ if thr is None:
+ continue
+ else:
+ thr = thr.get_object()
+ if thr.indirect_reference.idnum not in self._id_translated[
+ id(reader)
+ ] and fltr.search((thr["/I"] if "/I" in thr else {}).get("/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, 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[Any]", 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(self._add_object(ano.clone(self)))
+ else:
+ d = ano["/Dest"]
+ if isinstance(d, str):
+ # it is a named dest
+ if str(d) in self.get_named_dest_root():
+ outlist.append(ano.clone(self).indirect_reference)
+ else:
+ d = cast("ArrayObject", d)
+ p = self._get_cloned_page(d[0], pages, reader)
+ if p is not None:
+ anc = ano.clone(self, ignore_fields=("/Dest",))
+ anc[NameObject("/Dest")] = ArrayObject([p] + d[1:])
+ outlist.append(self._add_object(anc))
+ else:
+ d = cast("DictionaryObject", ano["/A"])["/D"]
+ if isinstance(d, str):
+ # it is a named dest
+ if str(d) in self.get_named_dest_root():
+ outlist.append(ano.clone(self).indirect_reference)
+ else:
+ d = cast("ArrayObject", d)
+ p = self._get_cloned_page(d[0], pages, reader)
+ if p is not None:
+ anc = ano.clone(self, ignore_fields=("/D",))
+ cast("DictionaryObject", anc["/A"])[
+ NameObject("/D")
+ ] = ArrayObject([p] + d[1:])
+ outlist.append(self._add_object(anc))
+ return outlist
+
+ def _get_filtered_outline(
+ self,
+ node: Any,
+ pages: Dict[int, PageObject],
+ reader: PdfReader,
+ ) -> List[Destination]:
"""
Extract outline item entries that are part of the specified page set.
@@ -899,22 +2734,123 @@ class PdfWriter(PdfDocCommon):
Returns:
A list of destination objects.
"""
- pass
-
- def close(self) ->None:
+ new_outline = []
+ if node is None:
+ node = NullObject()
+ node = node.get_object()
+ if node is None or isinstance(node, NullObject):
+ node = DictionaryObject()
+ if node.get("/Type", "") == "/Outlines" or "/Title" not in node:
+ node = node.get("/First", None)
+ if node is not None:
+ node = node.get_object()
+ new_outline += self._get_filtered_outline(node, pages, reader)
+ else:
+ v: Union[None, IndirectObject, NullObject]
+ while node is not None:
+ node = node.get_object()
+ o = cast("Destination", reader._build_outline_item(node))
+ v = self._get_cloned_page(cast("PageObject", o["/Page"]), pages, reader)
+ if v is None:
+ v = NullObject()
+ o[NameObject("/Page")] = v
+ if "/First" in node:
+ o._filtered_children = self._get_filtered_outline(
+ node["/First"], pages, reader
+ )
+ else:
+ o._filtered_children = []
+ if (
+ not isinstance(o["/Page"], NullObject)
+ or len(o._filtered_children) > 0
+ ):
+ new_outline.append(o)
+ node = node.get("/Next", None)
+ return new_outline
+
+ def _clone_outline(self, dest: Destination) -> TreeObject:
+ n_ol = TreeObject()
+ self._add_object(n_ol)
+ n_ol[NameObject("/Title")] = TextStringObject(dest["/Title"])
+ if not isinstance(dest["/Page"], NullObject):
+ if dest.node is not None and "/A" in dest.node:
+ n_ol[NameObject("/A")] = dest.node["/A"].clone(self)
+ else:
+ n_ol[NameObject("/Dest")] = dest.dest_array
+ # TODO: /SE
+ if dest.node is not None:
+ n_ol[NameObject("/F")] = NumberObject(dest.node.get("/F", 0))
+ n_ol[NameObject("/C")] = ArrayObject(
+ dest.node.get(
+ "/C", [FloatObject(0.0), FloatObject(0.0), FloatObject(0.0)]
+ )
+ )
+ return n_ol
+
+ def _insert_filtered_outline(
+ self,
+ outlines: List[Destination],
+ parent: Union[TreeObject, IndirectObject],
+ before: Union[None, TreeObject, IndirectObject] = None,
+ ) -> None:
+ for dest in outlines:
+ # TODO : can be improved to keep A and SE entries (ignored for the moment)
+ # with np=self.add_outline_item_destination(dest,parent,before)
+ if dest.get("/Type", "") == "/Outlines" or "/Title" not in dest:
+ np = parent
+ else:
+ np = self._clone_outline(dest)
+ cast(TreeObject, parent.get_object()).insert_child(np, before, self)
+ self._insert_filtered_outline(dest._filtered_children, np, None)
+
+ def close(self) -> None:
"""Implemented for API harmonization."""
- pass
-
- def find_bookmark(self, outline_item: Dict[str, Any], root: Optional[
- OutlineType]=None) ->Optional[List[int]]:
+ return
+
+ def find_outline_item(
+ self,
+ outline_item: Dict[str, Any],
+ root: Optional[OutlineType] = None,
+ ) -> Optional[List[int]]:
+ if root is None:
+ o = self.get_outline_root()
+ else:
+ o = cast("TreeObject", root)
+
+ i = 0
+ while o is not None:
+ if (
+ o.indirect_reference == outline_item
+ or o.get("/Title", None) == outline_item
+ ):
+ return [i]
+ elif "/First" in o:
+ res = self.find_outline_item(
+ outline_item, cast(OutlineType, o["/First"])
+ )
+ if res:
+ return ([i] if "/Title" in o else []) + res
+ if "/Next" in o:
+ i += 1
+ o = cast(TreeObject, o["/Next"])
+ else:
+ return None
+
+ def find_bookmark(
+ self,
+ outline_item: Dict[str, Any],
+ root: Optional[OutlineType] = None,
+ ) -> Optional[List[int]]: # deprecated
"""
.. deprecated:: 2.9.0
Use :meth:`find_outline_item` instead.
"""
- pass
+ deprecate_with_replacement("find_bookmark", "find_outline_item", "5.0.0")
+ return self.find_outline_item(outline_item, root)
- def reset_translation(self, reader: Union[None, PdfReader,
- IndirectObject]=None) ->None:
+ def reset_translation(
+ self, reader: Union[None, PdfReader, IndirectObject] = None
+ ) -> None:
"""
Reset the translation table between reader and the writer object.
@@ -924,11 +2860,29 @@ class PdfWriter(PdfDocCommon):
reader: PdfReader or IndirectObject referencing a PdfReader object.
if set to None or omitted, all tables will be reset.
"""
- pass
-
- def set_page_label(self, page_index_from: int, page_index_to: int,
- style: Optional[PageLabelStyle]=None, prefix: Optional[str]=None,
- start: Optional[int]=0) ->None:
+ if reader is None:
+ self._id_translated = {}
+ elif isinstance(reader, PdfReader):
+ try:
+ del self._id_translated[id(reader)]
+ except Exception:
+ pass
+ elif isinstance(reader, IndirectObject):
+ try:
+ del self._id_translated[id(reader.pdf)]
+ except Exception:
+ pass
+ else:
+ raise Exception("invalid parameter {reader}")
+
+ def set_page_label(
+ self,
+ page_index_from: int,
+ page_index_to: int,
+ style: Optional[PageLabelStyle] = None,
+ prefix: Optional[str] = None,
+ start: Optional[int] = 0,
+ ) -> None:
"""
Set a page label to a range of pages.
@@ -956,11 +2910,29 @@ class PdfWriter(PdfDocCommon):
which must be greater than or equal to 1.
Default value: 1.
"""
- pass
-
- def _set_page_label(self, page_index_from: int, page_index_to: int,
- style: Optional[PageLabelStyle]=None, prefix: Optional[str]=None,
- start: Optional[int]=0) ->None:
+ if style is None and prefix is None:
+ raise ValueError("at least one between style and prefix must be given")
+ if page_index_from < 0:
+ raise ValueError("page_index_from must be equal or greater then 0")
+ if page_index_to < page_index_from:
+ raise ValueError(
+ "page_index_to must be equal or greater then page_index_from"
+ )
+ if page_index_to >= len(self.pages):
+ raise ValueError("page_index_to exceeds number of pages")
+ if start is not None and start != 0 and start < 1:
+ raise ValueError("if given, start must be equal or greater than one")
+
+ self._set_page_label(page_index_from, page_index_to, style, prefix, start)
+
+ def _set_page_label(
+ self,
+ page_index_from: int,
+ page_index_to: int,
+ style: Optional[PageLabelStyle] = None,
+ prefix: Optional[str] = None,
+ start: Optional[int] = 0,
+ ) -> None:
"""
Set a page label to a range of pages.
@@ -986,4 +2958,90 @@ class PdfWriter(PdfDocCommon):
Subsequent pages are numbered sequentially from this value,
which must be greater than or equal to 1. Default value: 1.
"""
- pass
+ default_page_label = DictionaryObject()
+ default_page_label[NameObject("/S")] = NameObject("/D")
+
+ new_page_label = DictionaryObject()
+ if style is not None:
+ new_page_label[NameObject("/S")] = NameObject(style)
+ if prefix is not None:
+ new_page_label[NameObject("/P")] = TextStringObject(prefix)
+ if start != 0:
+ new_page_label[NameObject("/St")] = NumberObject(start)
+
+ if NameObject(CatalogDictionary.PAGE_LABELS) not in self._root_object:
+ nums = ArrayObject()
+ nums_insert(NumberObject(0), default_page_label, nums)
+ page_labels = TreeObject()
+ page_labels[NameObject("/Nums")] = nums
+ self._root_object[NameObject(CatalogDictionary.PAGE_LABELS)] = page_labels
+
+ page_labels = cast(
+ TreeObject, self._root_object[NameObject(CatalogDictionary.PAGE_LABELS)]
+ )
+ nums = cast(ArrayObject, page_labels[NameObject("/Nums")])
+
+ nums_insert(NumberObject(page_index_from), new_page_label, nums)
+ nums_clear_range(NumberObject(page_index_from), page_index_to, nums)
+ next_label_pos, *_ = nums_next(NumberObject(page_index_from), nums)
+ if next_label_pos != page_index_to + 1 and page_index_to + 1 < len(self.pages):
+ nums_insert(NumberObject(page_index_to + 1), default_page_label, nums)
+
+ page_labels[NameObject("/Nums")] = nums
+ self._root_object[NameObject(CatalogDictionary.PAGE_LABELS)] = page_labels
+
+
+def _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):
+ return ArrayObject(_pdf_objectify(el) for el in obj)
+ 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)
+ outline_item.update(
+ {NameObject("/C"): ArrayObject([FloatObject(c) 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
diff --git a/pypdf/_xobj_image_helpers.py b/pypdf/_xobj_image_helpers.py
index 658d357c..45b0c145 100644
--- a/pypdf/_xobj_image_helpers.py
+++ b/pypdf/_xobj_image_helpers.py
@@ -1,55 +1,307 @@
"""Code in here is only used by pypdf.filters._xobj_to_image"""
+
import sys
from io import BytesIO
from typing import Any, List, Tuple, Union, cast
+
from ._utils import check_if_whitespace_only, logger_warning
from .constants import ColorSpaces
from .errors import PdfReadError
-from .generic import ArrayObject, DecodedStreamObject, EncodedStreamObject, IndirectObject, NullObject
+from .generic import (
+ ArrayObject,
+ DecodedStreamObject,
+ EncodedStreamObject,
+ IndirectObject,
+ NullObject,
+)
+
if sys.version_info[:2] >= (3, 8):
from typing import Literal
else:
+ # PEP 586 introduced typing.Literal with Python 3.8
+ # For older Python versions, the backport typing_extensions is necessary:
from typing_extensions import Literal
+
if sys.version_info[:2] >= (3, 10):
from typing import TypeAlias
else:
from typing_extensions import TypeAlias
+
+
try:
- from PIL import Image, UnidentifiedImageError
+ from PIL import Image, UnidentifiedImageError # noqa: F401
except ImportError:
raise ImportError(
- "pillow is required to do image extraction. It can be installed via 'pip install pypdf[image]'"
- )
-mode_str_type: TypeAlias = Literal['', '1', 'RGB', '2bits', '4bits', 'P',
- 'L', 'RGBA', 'CMYK']
+ "pillow is required to do image extraction. "
+ "It can be installed via 'pip install pypdf[image]'"
+ )
+
+mode_str_type: TypeAlias = Literal[
+ "", "1", "RGB", "2bits", "4bits", "P", "L", "RGBA", "CMYK"
+]
+
MAX_IMAGE_MODE_NESTING_DEPTH: int = 10
-def _get_imagemode(color_space: Union[str, List[Any], Any],
- color_components: int, prev_mode: mode_str_type, depth: int=0) ->Tuple[
- mode_str_type, bool]:
+def _get_imagemode(
+ color_space: Union[str, List[Any], Any],
+ color_components: int,
+ prev_mode: mode_str_type,
+ depth: int = 0,
+) -> Tuple[mode_str_type, bool]:
"""
Returns
Image mode not taking into account mask(transparency)
ColorInversion is required (like for some DeviceCMYK)
"""
- pass
+ if depth > MAX_IMAGE_MODE_NESTING_DEPTH:
+ raise PdfReadError(
+ "Color spaces nested too deep. If required, consider increasing MAX_IMAGE_MODE_NESTING_DEPTH."
+ )
+ if isinstance(color_space, NullObject):
+ return "", False
+ if isinstance(color_space, str):
+ pass
+ elif not isinstance(color_space, list):
+ raise PdfReadError(
+ "Cannot interpret colorspace", color_space
+ ) # pragma: no cover
+ elif color_space[0].startswith("/Cal"): # /CalRGB and /CalGray
+ color_space = "/Device" + color_space[0][4:]
+ elif color_space[0] == "/ICCBased":
+ icc_profile = color_space[1].get_object()
+ color_components = cast(int, icc_profile["/N"])
+ color_space = icc_profile.get("/Alternate", "")
+ elif color_space[0] == "/Indexed":
+ color_space = color_space[1].get_object()
+ mode2, invert_color = _get_imagemode(
+ color_space, color_components, prev_mode, depth + 1
+ )
+ if mode2 in ("RGB", "CMYK"):
+ mode2 = "P"
+ return mode2, invert_color
+ elif color_space[0] == "/Separation":
+ color_space = color_space[2]
+ if isinstance(color_space, IndirectObject):
+ color_space = color_space.get_object()
+ mode2, invert_color = _get_imagemode(
+ color_space, color_components, prev_mode, depth + 1
+ )
+ return mode2, True
+ elif color_space[0] == "/DeviceN":
+ original_color_space = color_space
+ color_components = len(color_space[1])
+ color_space = color_space[2]
+ if isinstance(color_space, IndirectObject): # pragma: no cover
+ color_space = color_space.get_object()
+ if color_space == "/DeviceCMYK" and color_components == 1:
+ if original_color_space[1][0] != "/Black":
+ logger_warning(
+ f"Color {original_color_space[1][0]} converted to Gray. Please share PDF with pypdf dev team",
+ __name__,
+ )
+ return "L", True
+ mode2, invert_color = _get_imagemode(
+ color_space, color_components, prev_mode, depth + 1
+ )
+ return mode2, invert_color
+
+ mode_map = {
+ "1bit": "1", # pos [0] will be used for 1 bit
+ "/DeviceGray": "L", # must be in pos [1]
+ "palette": "P", # must be in pos [2] for color_components align.
+ "/DeviceRGB": "RGB", # must be in pos [3]
+ "/DeviceCMYK": "CMYK", # must be in pos [4]
+ "2bit": "2bits", # 2 bits images
+ "4bit": "4bits", # 4 bits
+ }
+ mode: mode_str_type = (
+ mode_map.get(color_space) # type: ignore
+ or list(mode_map.values())[color_components]
+ or prev_mode
+ )
+ return mode, mode == "CMYK"
+
+def bits2byte(data: bytes, size: Tuple[int, int], bits: int) -> bytes:
+ mask = (1 << bits) - 1
+ nbuff = bytearray(size[0] * size[1])
+ by = 0
+ bit = 8 - bits
+ for y in range(size[1]):
+ if (bit != 0) and (bit != 8 - bits):
+ by += 1
+ bit = 8 - bits
+ for x in range(size[0]):
+ nbuff[y * size[0] + x] = (data[by] >> bit) & mask
+ bit -= bits
+ if bit < 0:
+ by += 1
+ bit = 8 - bits
+ return bytes(nbuff)
-def _handle_flate(size: Tuple[int, int], data: bytes, mode: mode_str_type,
- color_space: str, colors: int, obj_as_text: str) ->Tuple[Image.Image,
- str, str, bool]:
+
+def _extended_image_frombytes(
+ mode: str, size: Tuple[int, int], data: bytes
+) -> Image.Image:
+ try:
+ img = Image.frombytes(mode, size, data)
+ except ValueError as exc:
+ nb_pix = size[0] * size[1]
+ if len(data) % nb_pix != 0:
+ raise exc
+ k = nb_pix * len(mode) / len(data)
+ data = b"".join([bytes((x,) * int(k)) for x in data])
+ img = Image.frombytes(mode, size, data)
+ return img
+
+
+def _handle_flate(
+ size: Tuple[int, int],
+ data: bytes,
+ mode: mode_str_type,
+ color_space: str,
+ colors: int,
+ obj_as_text: str,
+) -> Tuple[Image.Image, str, str, bool]:
"""
Process image encoded in flateEncode
Returns img, image_format, extension, color inversion
"""
- pass
+ extension = ".png" # mime_type = "image/png"
+ image_format = "PNG"
+ lookup: Any
+ base: Any
+ hival: Any
+ if isinstance(color_space, ArrayObject) and color_space[0] == "/Indexed":
+ color_space, base, hival, lookup = (value.get_object() for value in color_space)
+ if mode == "2bits":
+ mode = "P"
+ data = bits2byte(data, size, 2)
+ elif mode == "4bits":
+ mode = "P"
+ data = bits2byte(data, size, 4)
+ img = _extended_image_frombytes(mode, size, data)
+ if color_space == "/Indexed":
+ from .generic import TextStringObject
+
+ if isinstance(lookup, (EncodedStreamObject, DecodedStreamObject)):
+ lookup = lookup.get_data()
+ if isinstance(lookup, TextStringObject):
+ lookup = lookup.original_bytes
+ if isinstance(lookup, str):
+ lookup = lookup.encode()
+ try:
+ nb, conv, mode = { # type: ignore
+ "1": (0, "", ""),
+ "L": (1, "P", "L"),
+ "P": (0, "", ""),
+ "RGB": (3, "P", "RGB"),
+ "CMYK": (4, "P", "CMYK"),
+ }[_get_imagemode(base, 0, "")[0]]
+ except KeyError: # pragma: no cover
+ logger_warning(
+ f"Base {base} not coded please share the pdf file with pypdf dev team",
+ __name__,
+ )
+ lookup = None
+ else:
+ if img.mode == "1":
+ # Two values ("high" and "low").
+ expected_count = 2 * nb
+ if len(lookup) != expected_count:
+ if len(lookup) < expected_count:
+ raise PdfReadError(
+ f"Not enough lookup values: Expected {expected_count}, got {len(lookup)}."
+ )
+ if not check_if_whitespace_only(lookup[expected_count:]):
+ raise PdfReadError(
+ f"Too many lookup values: Expected {expected_count}, got {len(lookup)}."
+ )
+ lookup = lookup[:expected_count]
+ colors_arr = [lookup[:nb], lookup[nb:]]
+ arr = b"".join(
+ [
+ b"".join(
+ [
+ colors_arr[1 if img.getpixel((x, y)) > 127 else 0]
+ for x in range(img.size[0])
+ ]
+ )
+ for y in range(img.size[1])
+ ]
+ )
+ img = Image.frombytes(mode, img.size, arr)
+ else:
+ img = img.convert(conv)
+ if len(lookup) != (hival + 1) * nb:
+ logger_warning(f"Invalid Lookup Table in {obj_as_text}", __name__)
+ lookup = None
+ elif mode == "L":
+ # gray lookup does not work : it is converted to a similar RGB lookup
+ lookup = b"".join([bytes([b, b, b]) for b in lookup])
+ mode = "RGB"
+ # TODO : cf https://github.com/py-pdf/pypdf/pull/2039
+ # this is a work around until PIL is able to process CMYK images
+ elif mode == "CMYK":
+ _rgb = []
+ for _c, _m, _y, _k in (
+ lookup[n : n + 4] for n in range(0, 4 * (len(lookup) // 4), 4)
+ ):
+ _r = int(255 * (1 - _c / 255) * (1 - _k / 255))
+ _g = int(255 * (1 - _m / 255) * (1 - _k / 255))
+ _b = int(255 * (1 - _y / 255) * (1 - _k / 255))
+ _rgb.append(bytes((_r, _g, _b)))
+ lookup = b"".join(_rgb)
+ mode = "RGB"
+ if lookup is not None:
+ img.putpalette(lookup, rawmode=mode)
+ img = img.convert("L" if base == ColorSpaces.DEVICE_GRAY else "RGB")
+ elif not isinstance(color_space, NullObject) and color_space[0] == "/ICCBased":
+ # see Table 66 - Additional Entries Specific to an ICC Profile
+ # Stream Dictionary
+ mode2 = _get_imagemode(color_space, colors, mode)[0]
+ if mode != mode2:
+ img = Image.frombytes(mode2, size, data) # reloaded as mode may have change
+ if mode == "CMYK":
+ extension = ".tif"
+ image_format = "TIFF"
+ return img, image_format, extension, False
-def _handle_jpx(size: Tuple[int, int], data: bytes, mode: mode_str_type,
- color_space: str, colors: int) ->Tuple[Image.Image, str, str, bool]:
+def _handle_jpx(
+ size: Tuple[int, int],
+ data: bytes,
+ mode: mode_str_type,
+ color_space: str,
+ colors: int,
+) -> Tuple[Image.Image, str, str, bool]:
"""
Process image encoded in flateEncode
Returns img, image_format, extension, inversion
"""
- pass
+ extension = ".jp2" # mime_type = "image/x-jp2"
+ img1 = Image.open(BytesIO(data), formats=("JPEG2000",))
+ mode, invert_color = _get_imagemode(color_space, colors, mode)
+ if mode == "":
+ mode = cast(mode_str_type, img1.mode)
+ invert_color = mode in ("CMYK",)
+ if img1.mode == "RGBA" and mode == "RGB":
+ mode = "RGBA"
+ # we need to convert to the good mode
+ if img1.mode == mode or {img1.mode, mode} == {"L", "P"}: # compare (unordered) sets
+ # L,P are indexed modes which should not be changed.
+ img = img1
+ elif {img1.mode, mode} == {"RGBA", "CMYK"}:
+ # RGBA / CMYK are 4bytes encoding where
+ # the encoding should be corrected
+ img = Image.frombytes(mode, img1.size, img1.tobytes())
+ else: # pragma: no cover
+ img = img1.convert(mode)
+ # for CMYK conversion :
+ # https://stcom/questions/38855022/conversion-from-cmyk-to-rgb-with-pillow-is-different-from-that-of-photoshop
+ # not implemented for the moment as I need to get properly the ICC
+ if img.mode == "CMYK":
+ img = img.convert("RGB")
+ image_format = "JPEG2000"
+ return img, image_format, extension, invert_color
diff --git a/pypdf/annotations/_base.py b/pypdf/annotations/_base.py
index 2ef3df10..f235acf3 100644
--- a/pypdf/annotations/_base.py
+++ b/pypdf/annotations/_base.py
@@ -1,14 +1,27 @@
from abc import ABC
+
from ..constants import AnnotationFlag
from ..generic import NameObject, NumberObject
from ..generic._data_structures import DictionaryObject
class AnnotationDictionary(DictionaryObject, ABC):
-
- def __init__(self) ->None:
+ def __init__(self) -> None:
from ..generic._base import NameObject
- self[NameObject('/Type')] = NameObject('/Annot')
+
+ # "rect" should not be added here as PolyLine can automatically set it
+ self[NameObject("/Type")] = NameObject("/Annot")
+ # The flags was NOT added to the constructor on purpose: We expect that
+ # most users don't want to change the default. If they want, they
+ # can use the property. The default is 0.
+
+ @property
+ def flags(self) -> AnnotationFlag:
+ return self.get(NameObject("/F"), AnnotationFlag(0))
+
+ @flags.setter
+ def flags(self, value: AnnotationFlag) -> None:
+ self[NameObject("/F")] = NumberObject(value)
NO_FLAGS = AnnotationFlag(0)
diff --git a/pypdf/annotations/_markup_annotations.py b/pypdf/annotations/_markup_annotations.py
index fa5fab6f..4db8dfdb 100644
--- a/pypdf/annotations/_markup_annotations.py
+++ b/pypdf/annotations/_markup_annotations.py
@@ -1,20 +1,44 @@
import sys
from abc import ABC
from typing import Any, List, Optional, Tuple, Union
+
from .._utils import deprecate_with_replacement
from ..constants import AnnotationFlag
from ..generic import ArrayObject, DictionaryObject
-from ..generic._base import BooleanObject, FloatObject, NameObject, NumberObject, TextStringObject
+from ..generic._base import (
+ BooleanObject,
+ FloatObject,
+ NameObject,
+ NumberObject,
+ TextStringObject,
+)
from ..generic._rectangle import RectangleObject
from ..generic._utils import hex_to_rgb
from ._base import NO_FLAGS, AnnotationDictionary
+
if sys.version_info[:2] >= (3, 10):
from typing import TypeAlias
else:
+ # PEP 613 introduced typing.TypeAlias with Python 3.10
+ # For older Python versions, the backport typing_extensions is necessary:
from typing_extensions import TypeAlias
+
+
Vertex: TypeAlias = Tuple[float, float]
+def _get_bounding_rectangle(vertices: List[Vertex]) -> RectangleObject:
+ x_min, y_min = vertices[0][0], vertices[0][1]
+ x_max, y_max = vertices[0][0], vertices[0][1]
+ for x, y in vertices:
+ x_min = min(x_min, x)
+ y_min = min(y_min, y)
+ x_max = max(x_max, x)
+ y_max = max(y_max, y)
+ rect = RectangleObject((x_min, y_min, x_max, y_max))
+ return rect
+
+
class MarkupAnnotation(AnnotationDictionary, ABC):
"""
Base class for all markup annotations.
@@ -24,9 +48,9 @@ class MarkupAnnotation(AnnotationDictionary, ABC):
by convention this is the name of the author
"""
- def __init__(self, *, title_bar: Optional[str]=None):
+ def __init__(self, *, title_bar: Optional[str] = None):
if title_bar is not None:
- self[NameObject('T')] = TextStringObject(title_bar)
+ self[NameObject("T")] = TextStringObject(title_bar)
class Text(MarkupAnnotation):
@@ -41,147 +65,244 @@ class Text(MarkupAnnotation):
flags:
"""
- def __init__(self, *, rect: Union[RectangleObject, Tuple[float, float,
- float, float]], text: str, open: bool=False, flags: int=NO_FLAGS,
- **kwargs: Any):
+ def __init__(
+ self,
+ *,
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ text: str,
+ open: bool = False,
+ flags: int = NO_FLAGS,
+ **kwargs: Any,
+ ):
super().__init__(**kwargs)
- self[NameObject('/Subtype')] = NameObject('/Text')
- self[NameObject('/Rect')] = RectangleObject(rect)
- self[NameObject('/Contents')] = TextStringObject(text)
- self[NameObject('/Open')] = BooleanObject(open)
- self[NameObject('/Flags')] = NumberObject(flags)
+ self[NameObject("/Subtype")] = NameObject("/Text")
+ self[NameObject("/Rect")] = RectangleObject(rect)
+ self[NameObject("/Contents")] = TextStringObject(text)
+ self[NameObject("/Open")] = BooleanObject(open)
+ self[NameObject("/Flags")] = NumberObject(flags)
class FreeText(MarkupAnnotation):
"""A FreeText annotation"""
- def __init__(self, *, text: str, rect: Union[RectangleObject, Tuple[
- float, float, float, float]], font: str='Helvetica', bold: bool=
- False, italic: bool=False, font_size: str='14pt', font_color: str=
- '000000', border_color: Optional[str]='000000', background_color:
- Optional[str]='ffffff', **kwargs: Any):
+ def __init__(
+ self,
+ *,
+ text: str,
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ font: str = "Helvetica",
+ bold: bool = False,
+ italic: bool = False,
+ font_size: str = "14pt",
+ font_color: str = "000000",
+ border_color: Optional[str] = "000000",
+ background_color: Optional[str] = "ffffff",
+ **kwargs: Any,
+ ):
super().__init__(**kwargs)
- self[NameObject('/Subtype')] = NameObject('/FreeText')
- self[NameObject('/Rect')] = RectangleObject(rect)
- font_str = 'font: '
+ self[NameObject("/Subtype")] = NameObject("/FreeText")
+ self[NameObject("/Rect")] = RectangleObject(rect)
+
+ font_str = "font: "
if bold is True:
- font_str = f'{font_str}bold '
+ font_str = f"{font_str}bold "
if italic is True:
- font_str = f'{font_str}italic '
- font_str = f'{font_str}{font} {font_size}'
- font_str = f'{font_str};text-align:left;color:#{font_color}'
- default_appearance_string = ''
+ font_str = f"{font_str}italic "
+ font_str = f"{font_str}{font} {font_size}"
+ font_str = f"{font_str};text-align:left;color:#{font_color}"
+
+ default_appearance_string = ""
if border_color:
for st in hex_to_rgb(border_color):
- default_appearance_string = f'{default_appearance_string}{st} '
- default_appearance_string = f'{default_appearance_string}rg'
- self.update({NameObject('/Subtype'): NameObject('/FreeText'),
- NameObject('/Rect'): RectangleObject(rect), NameObject(
- '/Contents'): TextStringObject(text), NameObject('/DS'):
- TextStringObject(font_str), NameObject('/DA'): TextStringObject
- (default_appearance_string)})
+ default_appearance_string = f"{default_appearance_string}{st} "
+ default_appearance_string = f"{default_appearance_string}rg"
+
+ self.update(
+ {
+ NameObject("/Subtype"): NameObject("/FreeText"),
+ NameObject("/Rect"): RectangleObject(rect),
+ NameObject("/Contents"): TextStringObject(text),
+ # font size color
+ NameObject("/DS"): TextStringObject(font_str),
+ NameObject("/DA"): TextStringObject(default_appearance_string),
+ }
+ )
if border_color is None:
- self[NameObject('/BS')] = DictionaryObject({NameObject('/W'):
- NumberObject(0)})
+ # Border Style
+ self[NameObject("/BS")] = DictionaryObject(
+ {
+ # width of 0 means no border
+ NameObject("/W"): NumberObject(0)
+ }
+ )
if background_color is not None:
- self[NameObject('/C')] = ArrayObject([FloatObject(n) for n in
- hex_to_rgb(background_color)])
+ self[NameObject("/C")] = ArrayObject(
+ [FloatObject(n) for n in hex_to_rgb(background_color)]
+ )
class Line(MarkupAnnotation):
-
- def __init__(self, p1: Vertex, p2: Vertex, rect: Union[RectangleObject,
- Tuple[float, float, float, float]], text: str='', **kwargs: Any):
+ def __init__(
+ self,
+ p1: Vertex,
+ p2: Vertex,
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ text: str = "",
+ **kwargs: Any,
+ ):
super().__init__(**kwargs)
- self.update({NameObject('/Subtype'): NameObject('/Line'),
- NameObject('/Rect'): RectangleObject(rect), NameObject('/L'):
- ArrayObject([FloatObject(p1[0]), FloatObject(p1[1]),
- FloatObject(p2[0]), FloatObject(p2[1])]), NameObject('/LE'):
- ArrayObject([NameObject('/None'), NameObject('/None')]),
- NameObject('/IC'): ArrayObject([FloatObject(0.5), FloatObject(
- 0.5), FloatObject(0.5)]), NameObject('/Contents'):
- TextStringObject(text)})
+ self.update(
+ {
+ NameObject("/Subtype"): NameObject("/Line"),
+ NameObject("/Rect"): RectangleObject(rect),
+ NameObject("/L"): ArrayObject(
+ [
+ FloatObject(p1[0]),
+ FloatObject(p1[1]),
+ FloatObject(p2[0]),
+ FloatObject(p2[1]),
+ ]
+ ),
+ NameObject("/LE"): ArrayObject(
+ [
+ NameObject("/None"),
+ NameObject("/None"),
+ ]
+ ),
+ NameObject("/IC"): ArrayObject(
+ [
+ FloatObject(0.5),
+ FloatObject(0.5),
+ FloatObject(0.5),
+ ]
+ ),
+ NameObject("/Contents"): TextStringObject(text),
+ }
+ )
class PolyLine(MarkupAnnotation):
-
- def __init__(self, vertices: List[Vertex], **kwargs: Any):
+ def __init__(
+ self,
+ vertices: List[Vertex],
+ **kwargs: Any,
+ ):
super().__init__(**kwargs)
if len(vertices) == 0:
- raise ValueError(
- 'A polygon needs at least 1 vertex with two coordinates')
+ raise ValueError("A polygon needs at least 1 vertex with two coordinates")
coord_list = []
for x, y in vertices:
coord_list.append(NumberObject(x))
coord_list.append(NumberObject(y))
- self.update({NameObject('/Subtype'): NameObject('/PolyLine'),
- NameObject('/Vertices'): ArrayObject(coord_list), NameObject(
- '/Rect'): RectangleObject(_get_bounding_rectangle(vertices))})
+ self.update(
+ {
+ NameObject("/Subtype"): NameObject("/PolyLine"),
+ NameObject("/Vertices"): ArrayObject(coord_list),
+ NameObject("/Rect"): RectangleObject(_get_bounding_rectangle(vertices)),
+ }
+ )
class Rectangle(MarkupAnnotation):
-
- def __init__(self, rect: Union[RectangleObject, Tuple[float, float,
- float, float]], *, interior_color: Optional[str]=None, **kwargs: Any):
- if 'interiour_color' in kwargs:
- deprecate_with_replacement('interiour_color', 'interior_color',
- '6.0.0')
- interior_color = kwargs['interiour_color']
- del kwargs['interiour_color']
+ def __init__(
+ self,
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ *,
+ interior_color: Optional[str] = None,
+ **kwargs: Any,
+ ):
+ if "interiour_color" in kwargs:
+ deprecate_with_replacement("interiour_color", "interior_color", "6.0.0")
+ interior_color = kwargs["interiour_color"]
+ del kwargs["interiour_color"]
super().__init__(**kwargs)
- self.update({NameObject('/Type'): NameObject('/Annot'), NameObject(
- '/Subtype'): NameObject('/Square'), NameObject('/Rect'):
- RectangleObject(rect)})
+ self.update(
+ {
+ NameObject("/Type"): NameObject("/Annot"),
+ NameObject("/Subtype"): NameObject("/Square"),
+ NameObject("/Rect"): RectangleObject(rect),
+ }
+ )
+
if interior_color:
- self[NameObject('/IC')] = ArrayObject([FloatObject(n) for n in
- hex_to_rgb(interior_color)])
+ self[NameObject("/IC")] = ArrayObject(
+ [FloatObject(n) for n in hex_to_rgb(interior_color)]
+ )
class Highlight(MarkupAnnotation):
-
- def __init__(self, *, rect: Union[RectangleObject, Tuple[float, float,
- float, float]], quad_points: ArrayObject, highlight_color: str=
- 'ff0000', printing: bool=False, **kwargs: Any):
+ def __init__(
+ self,
+ *,
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ quad_points: ArrayObject,
+ highlight_color: str = "ff0000",
+ printing: bool = False,
+ **kwargs: Any,
+ ):
super().__init__(**kwargs)
- self.update({NameObject('/Subtype'): NameObject('/Highlight'),
- NameObject('/Rect'): RectangleObject(rect), NameObject(
- '/QuadPoints'): quad_points, NameObject('/C'): ArrayObject([
- FloatObject(n) for n in hex_to_rgb(highlight_color)])})
+ self.update(
+ {
+ NameObject("/Subtype"): NameObject("/Highlight"),
+ NameObject("/Rect"): RectangleObject(rect),
+ NameObject("/QuadPoints"): quad_points,
+ NameObject("/C"): ArrayObject(
+ [FloatObject(n) for n in hex_to_rgb(highlight_color)]
+ ),
+ }
+ )
if printing:
self.flags = AnnotationFlag.PRINT
class Ellipse(MarkupAnnotation):
-
- def __init__(self, rect: Union[RectangleObject, Tuple[float, float,
- float, float]], *, interior_color: Optional[str]=None, **kwargs: Any):
- if 'interiour_color' in kwargs:
- deprecate_with_replacement('interiour_color', 'interior_color',
- '6.0.0')
- interior_color = kwargs['interiour_color']
- del kwargs['interiour_color']
+ def __init__(
+ self,
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ *,
+ interior_color: Optional[str] = None,
+ **kwargs: Any,
+ ):
+ if "interiour_color" in kwargs:
+ deprecate_with_replacement("interiour_color", "interior_color", "6.0.0")
+ interior_color = kwargs["interiour_color"]
+ del kwargs["interiour_color"]
super().__init__(**kwargs)
- self.update({NameObject('/Type'): NameObject('/Annot'), NameObject(
- '/Subtype'): NameObject('/Circle'), NameObject('/Rect'):
- RectangleObject(rect)})
+
+ self.update(
+ {
+ NameObject("/Type"): NameObject("/Annot"),
+ NameObject("/Subtype"): NameObject("/Circle"),
+ NameObject("/Rect"): RectangleObject(rect),
+ }
+ )
+
if interior_color:
- self[NameObject('/IC')] = ArrayObject([FloatObject(n) for n in
- hex_to_rgb(interior_color)])
+ self[NameObject("/IC")] = ArrayObject(
+ [FloatObject(n) for n in hex_to_rgb(interior_color)]
+ )
class Polygon(MarkupAnnotation):
-
- def __init__(self, vertices: List[Tuple[float, float]], **kwargs: Any):
+ def __init__(
+ self,
+ vertices: List[Tuple[float, float]],
+ **kwargs: Any,
+ ):
super().__init__(**kwargs)
if len(vertices) == 0:
- raise ValueError(
- 'A polygon needs at least 1 vertex with two coordinates')
+ raise ValueError("A polygon needs at least 1 vertex with two coordinates")
+
coord_list = []
for x, y in vertices:
coord_list.append(NumberObject(x))
coord_list.append(NumberObject(y))
- self.update({NameObject('/Type'): NameObject('/Annot'), NameObject(
- '/Subtype'): NameObject('/Polygon'), NameObject('/Vertices'):
- ArrayObject(coord_list), NameObject('/IT'): NameObject(
- '/PolygonCloud'), NameObject('/Rect'): RectangleObject(
- _get_bounding_rectangle(vertices))})
+ self.update(
+ {
+ NameObject("/Type"): NameObject("/Annot"),
+ NameObject("/Subtype"): NameObject("/Polygon"),
+ NameObject("/Vertices"): ArrayObject(coord_list),
+ NameObject("/IT"): NameObject("/PolygonCloud"),
+ NameObject("/Rect"): RectangleObject(_get_bounding_rectangle(vertices)),
+ }
+ )
diff --git a/pypdf/annotations/_non_markup_annotations.py b/pypdf/annotations/_non_markup_annotations.py
index 3b3b9053..dcdb3b0f 100644
--- a/pypdf/annotations/_non_markup_annotations.py
+++ b/pypdf/annotations/_non_markup_annotations.py
@@ -1,70 +1,109 @@
from typing import TYPE_CHECKING, Any, Optional, Tuple, Union
+
from ..constants import AnnotationFlag
-from ..generic._base import BooleanObject, NameObject, NumberObject, TextStringObject
+from ..generic._base import (
+ BooleanObject,
+ NameObject,
+ NumberObject,
+ TextStringObject,
+)
from ..generic._data_structures import ArrayObject, DictionaryObject
from ..generic._fit import DEFAULT_FIT, Fit
from ..generic._rectangle import RectangleObject
from ._base import AnnotationDictionary
+
DEFAULT_ANNOTATION_FLAG = AnnotationFlag(0)
class Link(AnnotationDictionary):
-
- def __init__(self, *, rect: Union[RectangleObject, Tuple[float, float,
- float, float]], border: Optional[ArrayObject]=None, url: Optional[
- str]=None, target_page_index: Optional[int]=None, fit: Fit=
- DEFAULT_FIT, **kwargs: Any):
+ def __init__(
+ self,
+ *,
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ border: Optional[ArrayObject] = None,
+ url: Optional[str] = None,
+ target_page_index: Optional[int] = None,
+ fit: Fit = DEFAULT_FIT,
+ **kwargs: Any,
+ ):
super().__init__(**kwargs)
if TYPE_CHECKING:
from ..types import BorderArrayType
+
is_external = url is not None
is_internal = target_page_index is not None
if not is_external and not is_internal:
raise ValueError(
"Either 'url' or 'target_page_index' have to be provided. Both were None."
- )
+ )
if is_external and is_internal:
raise ValueError(
- f"Either 'url' or 'target_page_index' have to be provided. url={url}, target_page_index={target_page_index}"
- )
+ "Either 'url' or 'target_page_index' have to be provided. "
+ f"url={url}, target_page_index={target_page_index}"
+ )
+
border_arr: BorderArrayType
if border is not None:
border_arr = [NumberObject(n) for n in border[:3]]
if len(border) == 4:
- dash_pattern = ArrayObject([NumberObject(n) for n in border[3]]
- )
+ dash_pattern = ArrayObject([NumberObject(n) for n in border[3]])
border_arr.append(dash_pattern)
else:
border_arr = [NumberObject(0)] * 3
- self.update({NameObject('/Type'): NameObject('/Annot'), NameObject(
- '/Subtype'): NameObject('/Link'), NameObject('/Rect'):
- RectangleObject(rect), NameObject('/Border'): ArrayObject(
- border_arr)})
+
+ self.update(
+ {
+ NameObject("/Type"): NameObject("/Annot"),
+ NameObject("/Subtype"): NameObject("/Link"),
+ NameObject("/Rect"): RectangleObject(rect),
+ NameObject("/Border"): ArrayObject(border_arr),
+ }
+ )
if is_external:
- self[NameObject('/A')] = DictionaryObject({NameObject('/S'):
- NameObject('/URI'), NameObject('/Type'): NameObject(
- '/Action'), NameObject('/URI'): TextStringObject(url)})
+ self[NameObject("/A")] = DictionaryObject(
+ {
+ NameObject("/S"): NameObject("/URI"),
+ NameObject("/Type"): NameObject("/Action"),
+ NameObject("/URI"): TextStringObject(url),
+ }
+ )
if is_internal:
- dest_deferred = DictionaryObject({'target_page_index':
- NumberObject(target_page_index), 'fit': NameObject(fit.
- fit_type), 'fit_args': fit.fit_args})
- self[NameObject('/Dest')] = dest_deferred
+ # This needs to be updated later!
+ dest_deferred = DictionaryObject(
+ {
+ "target_page_index": NumberObject(target_page_index),
+ "fit": NameObject(fit.fit_type),
+ "fit_args": fit.fit_args,
+ }
+ )
+ self[NameObject("/Dest")] = dest_deferred
class Popup(AnnotationDictionary):
-
- def __init__(self, *, rect: Union[RectangleObject, Tuple[float, float,
- float, float]], parent: Optional[DictionaryObject]=None, open: bool
- =False, **kwargs: Any):
+ def __init__(
+ self,
+ *,
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ parent: Optional[DictionaryObject] = None,
+ open: bool = False,
+ **kwargs: Any,
+ ):
super().__init__(**kwargs)
- self.update({NameObject('/Subtype'): NameObject('/Popup'),
- NameObject('/Rect'): RectangleObject(rect), NameObject('/Open'):
- BooleanObject(open)})
+ self.update(
+ {
+ NameObject("/Subtype"): NameObject("/Popup"),
+ NameObject("/Rect"): RectangleObject(rect),
+ NameObject("/Open"): BooleanObject(open),
+ }
+ )
if parent:
+ # This needs to be an indirect object
try:
- self[NameObject('/Parent')] = parent.indirect_reference
+ self[NameObject("/Parent")] = parent.indirect_reference
except AttributeError:
from .._utils import logger_warning
+
logger_warning(
- 'Unregistered Parent object : No Parent field set',
- __name__)
+ "Unregistered Parent object : No Parent field set",
+ __name__,
+ )
diff --git a/pypdf/constants.py b/pypdf/constants.py
index 5c0b0cf1..745774e2 100644
--- a/pypdf/constants.py
+++ b/pypdf/constants.py
@@ -10,31 +10,34 @@ https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf
ISO 32000-2:2020 (PDF 2.0)
"""
+
from enum import IntFlag, auto
from typing import Dict, Tuple
+
from ._utils import classproperty, deprecate_with_replacement
class Core:
"""Keywords that don't quite belong anywhere else."""
- OUTLINES = '/Outlines'
- THREADS = '/Threads'
- PAGE = '/Page'
- PAGES = '/Pages'
- CATALOG = '/Catalog'
+
+ OUTLINES = "/Outlines"
+ THREADS = "/Threads"
+ PAGE = "/Page"
+ PAGES = "/Pages"
+ CATALOG = "/Catalog"
class TrailerKeys:
- ROOT = '/Root'
- ENCRYPT = '/Encrypt'
- ID = '/ID'
- INFO = '/Info'
- SIZE = '/Size'
+ ROOT = "/Root"
+ ENCRYPT = "/Encrypt"
+ ID = "/ID"
+ INFO = "/Info"
+ SIZE = "/Size"
class CatalogAttributes:
- NAMES = '/Names'
- DESTS = '/Dests'
+ NAMES = "/Names"
+ DESTS = "/Dests"
class EncryptionDictAttributes:
@@ -44,11 +47,12 @@ class EncryptionDictAttributes:
Table 3.19, Page 122.
Table 21 of the 2.0 manual.
"""
- R = '/R'
- O = '/O'
- U = '/U'
- P = '/P'
- ENCRYPT_METADATA = '/EncryptMetadata'
+
+ R = "/R" # number, required; revision of the standard security handler
+ O = "/O" # 32-byte string, required # noqa
+ U = "/U" # 32-byte string, required
+ P = "/P" # integer flag, required; permitted operations
+ ENCRYPT_METADATA = "/EncryptMetadata" # boolean flag, optional
class UserAccessPermissions(IntFlag):
@@ -56,6 +60,7 @@ class UserAccessPermissions(IntFlag):
Table 3.20 User access permissions.
Table 22 of the 2.0 manual.
"""
+
R1 = 1
R2 = 2
PRINT = 4
@@ -68,45 +73,67 @@ class UserAccessPermissions(IntFlag):
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
+ R13 = 2**12
+ R14 = 2**13
+ R15 = 2**14
+ R16 = 2**15
+ R17 = 2**16
+ R18 = 2**17
+ R19 = 2**18
+ R20 = 2**19
+ R21 = 2**20
+ R22 = 2**21
+ R23 = 2**22
+ R24 = 2**23
+ R25 = 2**24
+ R26 = 2**25
+ R27 = 2**26
+ R28 = 2**27
+ R29 = 2**28
+ R30 = 2**29
+ R31 = 2**30
+ R32 = 2**31
@classmethod
- def _is_reserved(cls, name: str) ->bool:
+ def _is_reserved(cls, name: str) -> bool:
"""Check if the given name corresponds to a reserved flag entry."""
- pass
+ return name.startswith("R") and name[1:].isdigit()
@classmethod
- def _is_active(cls, name: str) ->bool:
+ def _is_active(cls, name: str) -> bool:
"""Check if the given reserved name defaults to 1 = active."""
- pass
+ return name not in {"R1", "R2"}
- def to_dict(self) ->Dict[str, bool]:
+ def to_dict(self) -> Dict[str, bool]:
"""Convert the given flag value to a corresponding verbose name mapping."""
- pass
+ result: Dict[str, bool] = {}
+ for name, flag in UserAccessPermissions.__members__.items():
+ if UserAccessPermissions._is_reserved(name):
+ continue
+ result[name.lower()] = (self & flag) == flag
+ return result
@classmethod
- def from_dict(cls, value: Dict[str, bool]) ->'UserAccessPermissions':
+ def from_dict(cls, value: Dict[str, bool]) -> "UserAccessPermissions":
"""Convert the verbose name mapping to the corresponding flag value."""
- pass
+ value_copy = value.copy()
+ result = cls(0)
+ for name, flag in cls.__members__.items():
+ if cls._is_reserved(name):
+ # Reserved names have a required value. Use it.
+ if cls._is_active(name):
+ result |= flag
+ continue
+ is_active = value_copy.pop(name.lower(), False)
+ if is_active:
+ result |= flag
+ if value_copy:
+ raise ValueError(f"Unknown dictionary keys: {value_copy!r}")
+ return result
+
+ @classmethod
+ def all(cls) -> "UserAccessPermissions":
+ return cls((2**32 - 1) - cls.R1 - cls.R2)
class Resources:
@@ -116,84 +143,129 @@ class Resources:
Table 34 in the 2.0 reference.
"""
- EXT_G_STATE = '/ExtGState'
- COLOR_SPACE = '/ColorSpace'
- PATTERN = '/Pattern'
- SHADING = '/Shading'
- XOBJECT = '/XObject'
- FONT = '/Font'
- PROC_SET = '/ProcSet'
- PROPERTIES = '/Properties'
+
+ EXT_G_STATE = "/ExtGState" # dictionary, optional
+ COLOR_SPACE = "/ColorSpace" # dictionary, optional
+ PATTERN = "/Pattern" # dictionary, optional
+ SHADING = "/Shading" # dictionary, optional
+ XOBJECT = "/XObject" # dictionary, optional
+ FONT = "/Font" # dictionary, optional
+ PROC_SET = "/ProcSet" # array, optional
+ PROPERTIES = "/Properties" # dictionary, optional
-class Ressources:
+class Ressources: # deprecated
"""
Use :class: `Resources` instead.
.. deprecated:: 5.0.0
"""
+ @classproperty
+ def EXT_G_STATE(cls) -> str: # noqa: N805
+ deprecate_with_replacement("Ressources", "Resources", "5.0.0")
+ return "/ExtGState" # dictionary, optional
+
+ @classproperty
+ def COLOR_SPACE(cls) -> str: # noqa: N805
+ deprecate_with_replacement("Ressources", "Resources", "5.0.0")
+ return "/ColorSpace" # dictionary, optional
+
+ @classproperty
+ def PATTERN(cls) -> str: # noqa: N805
+ deprecate_with_replacement("Ressources", "Resources", "5.0.0")
+ return "/Pattern" # dictionary, optional
+
+ @classproperty
+ def SHADING(cls) -> str: # noqa: N805
+ deprecate_with_replacement("Ressources", "Resources", "5.0.0")
+ return "/Shading" # dictionary, optional
+
+ @classproperty
+ def XOBJECT(cls) -> str: # noqa: N805
+ deprecate_with_replacement("Ressources", "Resources", "5.0.0")
+ return "/XObject" # dictionary, optional
+
+ @classproperty
+ def FONT(cls) -> str: # noqa: N805
+ deprecate_with_replacement("Ressources", "Resources", "5.0.0")
+ return "/Font" # dictionary, optional
+
+ @classproperty
+ def PROC_SET(cls) -> str: # noqa: N805
+ deprecate_with_replacement("Ressources", "Resources", "5.0.0")
+ return "/ProcSet" # array, optional
+
+ @classproperty
+ def PROPERTIES(cls) -> str: # noqa: N805
+ deprecate_with_replacement("Ressources", "Resources", "5.0.0")
+ return "/Properties" # dictionary, optional
+
class PagesAttributes:
"""§7.7.3.2 of the 1.7 and 2.0 reference."""
- TYPE = '/Type'
- PARENT = '/Parent'
- KIDS = '/Kids'
- COUNT = '/Count'
+
+ TYPE = "/Type" # name, required; must be /Pages
+ PARENT = "/Parent" # dictionary, required; indirect reference to pages object
+ KIDS = "/Kids" # array, required; List of indirect references
+ COUNT = "/Count" # integer, required; the number of leaf nodes (page objects)
+ # that are descendants of this node within the page tree
class PageAttributes:
"""§7.7.3.3 of the 1.7 and 2.0 reference."""
- TYPE = '/Type'
- PARENT = '/Parent'
- LAST_MODIFIED = '/LastModified'
- RESOURCES = '/Resources'
- MEDIABOX = '/MediaBox'
- CROPBOX = '/CropBox'
- BLEEDBOX = '/BleedBox'
- TRIMBOX = '/TrimBox'
- ARTBOX = '/ArtBox'
- BOX_COLOR_INFO = '/BoxColorInfo'
- CONTENTS = '/Contents'
- ROTATE = '/Rotate'
- GROUP = '/Group'
- THUMB = '/Thumb'
- B = '/B'
- DUR = '/Dur'
- TRANS = '/Trans'
- ANNOTS = '/Annots'
- AA = '/AA'
- METADATA = '/Metadata'
- PIECE_INFO = '/PieceInfo'
- STRUCT_PARENTS = '/StructParents'
- ID = '/ID'
- PZ = '/PZ'
- SEPARATION_INFO = '/SeparationInfo'
- TABS = '/Tabs'
- TEMPLATE_INSTANTIATED = '/TemplateInstantiated'
- PRES_STEPS = '/PresSteps'
- USER_UNIT = '/UserUnit'
- VP = '/VP'
- AF = '/AF'
- OUTPUT_INTENTS = '/OutputIntents'
- D_PART = '/DPart'
+
+ TYPE = "/Type" # name, required; must be /Page
+ PARENT = "/Parent" # dictionary, required; a pages object
+ LAST_MODIFIED = "/LastModified" # date, optional; date and time of last modification
+ RESOURCES = "/Resources" # dictionary, required if there are any
+ MEDIABOX = "/MediaBox" # rectangle, required; rectangle specifying page size
+ CROPBOX = "/CropBox" # rectangle, optional
+ BLEEDBOX = "/BleedBox" # rectangle, optional
+ TRIMBOX = "/TrimBox" # rectangle, optional
+ ARTBOX = "/ArtBox" # rectangle, optional
+ BOX_COLOR_INFO = "/BoxColorInfo" # dictionary, optional
+ CONTENTS = "/Contents" # stream or array, optional
+ ROTATE = "/Rotate" # integer, optional; page rotation in degrees
+ GROUP = "/Group" # dictionary, optional; page group
+ THUMB = "/Thumb" # stream, optional; indirect reference to image of the page
+ B = "/B" # array, optional
+ DUR = "/Dur" # number, optional
+ TRANS = "/Trans" # dictionary, optional
+ ANNOTS = "/Annots" # array, optional; an array of annotations
+ AA = "/AA" # dictionary, optional
+ METADATA = "/Metadata" # stream, optional
+ PIECE_INFO = "/PieceInfo" # dictionary, optional
+ STRUCT_PARENTS = "/StructParents" # integer, optional
+ ID = "/ID" # byte string, optional
+ PZ = "/PZ" # number, optional
+ SEPARATION_INFO = "/SeparationInfo" # dictionary, optional
+ TABS = "/Tabs" # name, optional
+ TEMPLATE_INSTANTIATED = "/TemplateInstantiated" # name, optional
+ PRES_STEPS = "/PresSteps" # dictionary, optional
+ USER_UNIT = "/UserUnit" # number, optional
+ VP = "/VP" # dictionary, optional
+ AF = "/AF" # array of dictionaries, optional
+ OUTPUT_INTENTS = "/OutputIntents" # array, optional
+ D_PART = "/DPart" # dictionary, required, if this page is within the range of a DPart, not permitted otherwise
class FileSpecificationDictionaryEntries:
"""Table 3.41 Entries in a file specification dictionary."""
- Type = '/Type'
- FS = '/FS'
- F = '/F'
- UF = '/UF'
- DOS = '/DOS'
- Mac = '/Mac'
- Unix = '/Unix'
- ID = '/ID'
- V = '/V'
- EF = '/EF'
- RF = '/RF'
- DESC = '/Desc'
- Cl = '/Cl'
+
+ 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
+ UF = "/UF" # A unicode string of the file as described in Section 3.10.1
+ DOS = "/DOS"
+ Mac = "/Mac"
+ Unix = "/Unix"
+ ID = "/ID"
+ V = "/V"
+ EF = "/EF" # dictionary, containing a subset of the keys F , UF , DOS , Mac , and Unix
+ RF = "/RF" # dictionary, containing arrays of /EmbeddedFile
+ DESC = "/Desc" # description of the file
+ Cl = "/Cl"
class StreamAttributes:
@@ -201,32 +273,35 @@ class StreamAttributes:
Table 4.2.
Table 5 in the 2.0 reference.
"""
- LENGTH = '/Length'
- FILTER = '/Filter'
- DECODE_PARMS = '/DecodeParms'
+
+ LENGTH = "/Length" # integer, required
+ FILTER = "/Filter" # name or array of names, optional
+ DECODE_PARMS = "/DecodeParms" # variable, optional -- 'decodeParams is wrong
class FilterTypes:
"""§7.4 of the 1.7 and 2.0 references."""
- ASCII_HEX_DECODE = '/ASCIIHexDecode'
- ASCII_85_DECODE = '/ASCII85Decode'
- LZW_DECODE = '/LZWDecode'
- FLATE_DECODE = '/FlateDecode'
- RUN_LENGTH_DECODE = '/RunLengthDecode'
- CCITT_FAX_DECODE = '/CCITTFaxDecode'
- DCT_DECODE = '/DCTDecode'
- JPX_DECODE = '/JPXDecode'
+
+ ASCII_HEX_DECODE = "/ASCIIHexDecode" # abbreviation: AHx
+ ASCII_85_DECODE = "/ASCII85Decode" # abbreviation: A85
+ LZW_DECODE = "/LZWDecode" # abbreviation: LZW
+ FLATE_DECODE = "/FlateDecode" # abbreviation: Fl, PDF 1.2
+ RUN_LENGTH_DECODE = "/RunLengthDecode" # abbreviation: RL
+ CCITT_FAX_DECODE = "/CCITTFaxDecode" # abbreviation: CCF
+ DCT_DECODE = "/DCTDecode" # abbreviation: DCT
+ JPX_DECODE = "/JPXDecode"
class FilterTypeAbbreviations:
"""§8.9.7 of the 1.7 and 2.0 references."""
- AHx = '/AHx'
- A85 = '/A85'
- LZW = '/LZW'
- FL = '/Fl'
- RL = '/RL'
- CCF = '/CCF'
- DCT = '/DCT'
+
+ AHx = "/AHx"
+ A85 = "/A85"
+ LZW = "/LZW"
+ FL = "/Fl" # FlateDecode
+ RL = "/RL"
+ CCF = "/CCF"
+ DCT = "/DCT"
class LzwFilterParameters:
@@ -234,11 +309,12 @@ class LzwFilterParameters:
Table 4.4.
Table 8 in the 2.0 reference.
"""
- PREDICTOR = '/Predictor'
- COLORS = '/Colors'
- BITS_PER_COMPONENT = '/BitsPerComponent'
- COLUMNS = '/Columns'
- EARLY_CHANGE = '/EarlyChange'
+
+ PREDICTOR = "/Predictor" # integer
+ COLORS = "/Colors" # integer
+ BITS_PER_COMPONENT = "/BitsPerComponent" # integer
+ COLUMNS = "/Columns" # integer
+ EARLY_CHANGE = "/EarlyChange" # integer
class CcittFaxDecodeParameters:
@@ -246,92 +322,97 @@ class CcittFaxDecodeParameters:
Table 4.5.
Table 11 in the 2.0 reference.
"""
- K = '/K'
- END_OF_LINE = '/EndOfLine'
- ENCODED_BYTE_ALIGN = '/EncodedByteAlign'
- COLUMNS = '/Columns'
- ROWS = '/Rows'
- END_OF_BLOCK = '/EndOfBlock'
- BLACK_IS_1 = '/BlackIs1'
- DAMAGED_ROWS_BEFORE_ERROR = '/DamagedRowsBeforeError'
+
+ K = "/K" # integer
+ END_OF_LINE = "/EndOfLine" # boolean
+ ENCODED_BYTE_ALIGN = "/EncodedByteAlign" # boolean
+ COLUMNS = "/Columns" # integer
+ ROWS = "/Rows" # integer
+ END_OF_BLOCK = "/EndOfBlock" # boolean
+ BLACK_IS_1 = "/BlackIs1" # boolean
+ DAMAGED_ROWS_BEFORE_ERROR = "/DamagedRowsBeforeError" # integer
class ImageAttributes:
"""§11.6.5 of the 1.7 and 2.0 references."""
- TYPE = '/Type'
- SUBTYPE = '/Subtype'
- NAME = '/Name'
- WIDTH = '/Width'
- HEIGHT = '/Height'
- BITS_PER_COMPONENT = '/BitsPerComponent'
- COLOR_SPACE = '/ColorSpace'
- DECODE = '/Decode'
- INTENT = '/Intent'
- INTERPOLATE = '/Interpolate'
- IMAGE_MASK = '/ImageMask'
- MASK = '/Mask'
- S_MASK = '/SMask'
+
+ TYPE = "/Type" # name, required; must be /XObject
+ SUBTYPE = "/Subtype" # name, required; must be /Image
+ NAME = "/Name" # name, required
+ WIDTH = "/Width" # integer, required
+ HEIGHT = "/Height" # integer, required
+ BITS_PER_COMPONENT = "/BitsPerComponent" # integer, required
+ COLOR_SPACE = "/ColorSpace" # name, required
+ DECODE = "/Decode" # array, optional
+ INTENT = "/Intent" # string, optional
+ INTERPOLATE = "/Interpolate" # boolean, optional
+ IMAGE_MASK = "/ImageMask" # boolean, optional
+ MASK = "/Mask" # 1-bit image mask stream
+ S_MASK = "/SMask" # dictionary or name, optional
class ColorSpaces:
- DEVICE_RGB = '/DeviceRGB'
- DEVICE_CMYK = '/DeviceCMYK'
- DEVICE_GRAY = '/DeviceGray'
+ 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'
+
+ 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'
+
+ 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'
- D = '/D'
+ S = "/S" # name, required: type of action
+ D = "/D" # name / byte string /array, required: Destination to jump to
class AnnotationDictionaryAttributes:
"""Table 8.15 Entries common to all annotation dictionaries."""
- Type = '/Type'
- Subtype = '/Subtype'
- Rect = '/Rect'
- Contents = '/Contents'
- P = '/P'
- NM = '/NM'
- M = '/M'
- F = '/F'
- AP = '/AP'
- AS = '/AS'
- DA = '/DA'
- Border = '/Border'
- C = '/C'
- StructParent = '/StructParent'
- OC = '/OC'
+
+ Type = "/Type"
+ Subtype = "/Subtype"
+ Rect = "/Rect"
+ Contents = "/Contents"
+ P = "/P"
+ NM = "/NM"
+ M = "/M"
+ F = "/F"
+ AP = "/AP"
+ AS = "/AS"
+ DA = "/DA"
+ Border = "/Border"
+ C = "/C"
+ StructParent = "/StructParent"
+ OC = "/OC"
class InteractiveFormDictEntries:
- Fields = '/Fields'
- NeedAppearances = '/NeedAppearances'
- SigFlags = '/SigFlags'
- CO = '/CO'
- DR = '/DR'
- DA = '/DA'
- Q = '/Q'
- XFA = '/XFA'
+ Fields = "/Fields"
+ NeedAppearances = "/NeedAppearances"
+ SigFlags = "/SigFlags"
+ CO = "/CO"
+ DR = "/DR"
+ DA = "/DA"
+ Q = "/Q"
+ XFA = "/XFA"
class FieldDictionaryAttributes:
@@ -341,18 +422,18 @@ class FieldDictionaryAttributes:
FFBits provides the constants used for `/Ff` from Table 8.70/8.75/8.77/8.79
"""
- FT = '/FT'
- Parent = '/Parent'
- Kids = '/Kids'
- T = '/T'
- TU = '/TU'
- TM = '/TM'
- Ff = '/Ff'
- V = '/V'
- DV = '/DV'
- AA = '/AA'
- Opt = '/Opt'
+ FT = "/FT" # name, required for terminal fields
+ Parent = "/Parent" # dictionary, required for children
+ Kids = "/Kids" # array, sometimes required
+ T = "/T" # text string, optional
+ TU = "/TU" # text string, optional
+ TM = "/TM" # text string, optional
+ Ff = "/Ff" # integer, optional
+ V = "/V" # text string or array, optional
+ DV = "/DV" # text string, optional
+ AA = "/AA" # dictionary, optional
+ Opt = "/Opt"
class FfBits(IntFlag):
"""
@@ -363,47 +444,57 @@ class FieldDictionaryAttributes:
* Buttons(Btn) (Table 8.77 PDF 1.7 reference)
* List(Ch) (Table 8.79 PDF 1.7 reference)
"""
+
ReadOnly = 1 << 0
"""common to Tx/Btn/Ch in Table 8.70"""
Required = 1 << 1
"""common to Tx/Btn/Ch in Table 8.70"""
NoExport = 1 << 2
"""common to Tx/Btn/Ch in Table 8.70"""
+
Multiline = 1 << 12
"""Tx"""
Password = 1 << 13
"""Tx"""
+
NoToggleToOff = 1 << 14
"""Btn"""
Radio = 1 << 15
"""Btn"""
Pushbutton = 1 << 16
"""Btn"""
+
Combo = 1 << 17
"""Ch"""
Edit = 1 << 18
"""Ch"""
Sort = 1 << 19
"""Ch"""
+
FileSelect = 1 << 20
"""Tx"""
+
MultiSelect = 1 << 21
"""Tx"""
+
DoNotSpellCheck = 1 << 22
"""Tx/Ch"""
DoNotScroll = 1 << 23
"""Tx"""
Comb = 1 << 24
"""Tx"""
+
RadiosInUnison = 1 << 25
"""Btn"""
+
RichText = 1 << 25
"""Tx"""
+
CommitOnSelChange = 1 << 26
"""Ch"""
@classmethod
- def attributes(cls) ->Tuple[str, ...]:
+ def attributes(cls) -> Tuple[str, ...]:
"""
Get a tuple of all the attributes present in a Field Dictionary.
@@ -415,10 +506,21 @@ class FieldDictionaryAttributes:
Returns:
A tuple containing all the attribute constants.
"""
- pass
+ 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]:
+ def attributes_dict(cls) -> Dict[str, str]:
"""
Get a dictionary of attribute keys and their human-readable names.
@@ -431,15 +533,25 @@ class FieldDictionaryAttributes:
Returns:
A dictionary containing attribute keys and their names.
"""
- pass
+ 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'
+
+ Opt = "/Opt" # Options, Optional
@classmethod
- def attributes(cls) ->Tuple[str, ...]:
+ def attributes(cls) -> Tuple[str, ...]:
"""
Get a tuple of all the attributes present in a Field Dictionary.
@@ -451,10 +563,10 @@ class CheckboxRadioButtonAttributes:
Returns:
A tuple containing all the attribute constants.
"""
- pass
+ return (cls.Opt,)
@classmethod
- def attributes_dict(cls) ->Dict[str, str]:
+ def attributes_dict(cls) -> Dict[str, str]:
"""
Get a dictionary of attribute keys and their human-readable names.
@@ -467,11 +579,14 @@ class CheckboxRadioButtonAttributes:
Returns:
A dictionary containing attribute keys and their names.
"""
- pass
+ 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
@@ -479,15 +594,16 @@ class FieldFlag(IntFlag):
class DocumentInformationAttributes:
"""Table 10.2 Entries in the document information dictionary."""
- TITLE = '/Title'
- AUTHOR = '/Author'
- SUBJECT = '/Subject'
- KEYWORDS = '/Keywords'
- CREATOR = '/Creator'
- PRODUCER = '/Producer'
- CREATION_DATE = '/CreationDate'
- MOD_DATE = '/ModDate'
- TRAPPED = '/Trapped'
+
+ 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:
@@ -495,83 +611,87 @@ class PageLayouts:
Page 84, PDF 1.4 reference.
Page 115, PDF 2.0 reference.
"""
- SINGLE_PAGE = '/SinglePage'
- ONE_COLUMN = '/OneColumn'
- TWO_COLUMN_LEFT = '/TwoColumnLeft'
- TWO_COLUMN_RIGHT = '/TwoColumnRight'
- TWO_PAGE_LEFT = '/TwoPageLeft'
- TWO_PAGE_RIGHT = '/TwoPageRight'
+
+ SINGLE_PAGE = "/SinglePage"
+ ONE_COLUMN = "/OneColumn"
+ TWO_COLUMN_LEFT = "/TwoColumnLeft"
+ TWO_COLUMN_RIGHT = "/TwoColumnRight"
+ TWO_PAGE_LEFT = "/TwoPageLeft" # (PDF 1.5)
+ TWO_PAGE_RIGHT = "/TwoPageRight" # (PDF 1.5)
class GraphicsStateParameters:
"""Table 58 – Entries in a Graphics State Parameter Dictionary"""
- TYPE = '/Type'
- LW = '/LW'
- LC = '/LC'
- LJ = '/LJ'
- ML = '/ML'
- D = '/D'
- RI = '/RI'
- OP = '/OP'
- op = '/op'
- OPM = '/OPM'
- FONT = '/Font'
- BG = '/BG'
- BG2 = '/BG2'
- UCR = '/UCR'
- UCR2 = '/UCR2'
- TR = '/TR'
- TR2 = '/TR2'
- HT = '/HT'
- FL = '/FL'
- SM = '/SM'
- SA = '/SA'
- BM = '/BM'
- S_MASK = '/SMask'
- CA = '/CA'
- ca = '/ca'
- AIS = '/AIS'
- TK = '/TK'
+
+ TYPE = "/Type" # name, optional
+ LW = "/LW" # number, optional
+ LC = "/LC" # integer, optional
+ LJ = "/LJ" # integer, optional
+ ML = "/ML" # number, optional
+ D = "/D" # array, optional
+ RI = "/RI" # name, optional
+ OP = "/OP"
+ op = "/op"
+ OPM = "/OPM"
+ FONT = "/Font" # array, optional
+ BG = "/BG"
+ BG2 = "/BG2"
+ UCR = "/UCR"
+ UCR2 = "/UCR2"
+ TR = "/TR"
+ TR2 = "/TR2"
+ HT = "/HT"
+ FL = "/FL"
+ SM = "/SM"
+ SA = "/SA"
+ BM = "/BM"
+ S_MASK = "/SMask" # dictionary or name, optional
+ CA = "/CA"
+ ca = "/ca"
+ AIS = "/AIS"
+ TK = "/TK"
class CatalogDictionary:
"""§7.7.2 of the 1.7 and 2.0 references."""
- TYPE = '/Type'
- VERSION = '/Version'
- EXTENSIONS = '/Extensions'
- PAGES = '/Pages'
- PAGE_LABELS = '/PageLabels'
- NAMES = '/Names'
- DESTS = '/Dests'
- VIEWER_PREFERENCES = '/ViewerPreferences'
- PAGE_LAYOUT = '/PageLayout'
- PAGE_MODE = '/PageMode'
- OUTLINES = '/Outlines'
- THREADS = '/Threads'
- OPEN_ACTION = '/OpenAction'
- AA = '/AA'
- URI = '/URI'
- ACRO_FORM = '/AcroForm'
- METADATA = '/Metadata'
- STRUCT_TREE_ROOT = '/StructTreeRoot'
- MARK_INFO = '/MarkInfo'
- LANG = '/Lang'
- SPIDER_INFO = '/SpiderInfo'
- OUTPUT_INTENTS = '/OutputIntents'
- PIECE_INFO = '/PieceInfo'
- OC_PROPERTIES = '/OCProperties'
- PERMS = '/Perms'
- LEGAL = '/Legal'
- REQUIREMENTS = '/Requirements'
- COLLECTION = '/Collection'
- NEEDS_RENDERING = '/NeedsRendering'
- DSS = '/DSS'
- AF = '/AF'
- D_PART_ROOT = '/DPartRoot'
+
+ TYPE = "/Type" # name, required; must be /Catalog
+ VERSION = "/Version" # name
+ EXTENSIONS = "/Extensions" # dictionary, optional; ISO 32000-1
+ PAGES = "/Pages" # dictionary, required
+ PAGE_LABELS = "/PageLabels" # number tree, optional
+ NAMES = "/Names" # dictionary, optional
+ DESTS = "/Dests" # dictionary, optional
+ VIEWER_PREFERENCES = "/ViewerPreferences" # dictionary, optional
+ PAGE_LAYOUT = "/PageLayout" # name, optional
+ PAGE_MODE = "/PageMode" # name, optional
+ OUTLINES = "/Outlines" # dictionary, optional
+ THREADS = "/Threads" # array, optional
+ OPEN_ACTION = "/OpenAction" # array or dictionary or name, optional
+ AA = "/AA" # dictionary, optional
+ URI = "/URI" # dictionary, optional
+ ACRO_FORM = "/AcroForm" # dictionary, optional
+ METADATA = "/Metadata" # stream, optional
+ STRUCT_TREE_ROOT = "/StructTreeRoot" # dictionary, optional
+ MARK_INFO = "/MarkInfo" # dictionary, optional
+ LANG = "/Lang" # text string, optional
+ SPIDER_INFO = "/SpiderInfo" # dictionary, optional
+ OUTPUT_INTENTS = "/OutputIntents" # array, optional
+ PIECE_INFO = "/PieceInfo" # dictionary, optional
+ OC_PROPERTIES = "/OCProperties" # dictionary, optional
+ PERMS = "/Perms" # dictionary, optional
+ LEGAL = "/Legal" # dictionary, optional
+ REQUIREMENTS = "/Requirements" # array, optional
+ COLLECTION = "/Collection" # dictionary, optional
+ NEEDS_RENDERING = "/NeedsRendering" # boolean, optional
+ DSS = "/DSS" # dictionary, optional
+ AF = "/AF" # array of dictionaries, optional
+ D_PART_ROOT = "/DPartRoot" # dictionary, optional
class OutlineFontFlag(IntFlag):
"""A class used as an enumerable flag for formatting an outline font."""
+
italic = 1
bold = 2
@@ -581,15 +701,17 @@ class PageLabelStyle:
Table 8.10 in the 1.7 reference.
Table 161 in the 2.0 reference.
"""
- DECIMAL = '/D'
- UPPERCASE_ROMAN = '/R'
- LOWERCASE_ROMAN = '/r'
- UPPERCASE_LETTER = '/A'
- LOWERCASE_LETTER = '/a'
+
+ DECIMAL = "/D" # Decimal Arabic numerals
+ UPPERCASE_ROMAN = "/R" # Uppercase Roman numerals
+ LOWERCASE_ROMAN = "/r" # Lowercase Roman numerals
+ UPPERCASE_LETTER = "/A" # Uppercase letters
+ LOWERCASE_LETTER = "/a" # Lowercase letters
class AnnotationFlag(IntFlag):
"""See §12.5.3 "Annotation Flags"."""
+
INVISIBLE = 1
HIDDEN = 2
PRINT = 4
@@ -602,15 +724,33 @@ class AnnotationFlag(IntFlag):
LOCKED_CONTENTS = 512
-PDF_KEYS = (AnnotationDictionaryAttributes, CatalogAttributes,
- CatalogDictionary, CcittFaxDecodeParameters,
- CheckboxRadioButtonAttributes, ColorSpaces, Core,
- DocumentInformationAttributes, EncryptionDictAttributes,
- FieldDictionaryAttributes, FilterTypeAbbreviations, FilterTypes,
- GoToActionArguments, GraphicsStateParameters, ImageAttributes,
- FileSpecificationDictionaryEntries, LzwFilterParameters, PageAttributes,
- PageLayouts, PagesAttributes, Resources, StreamAttributes, TrailerKeys,
- TypArguments, TypFitArguments)
+PDF_KEYS = (
+ AnnotationDictionaryAttributes,
+ CatalogAttributes,
+ CatalogDictionary,
+ CcittFaxDecodeParameters,
+ CheckboxRadioButtonAttributes,
+ ColorSpaces,
+ Core,
+ DocumentInformationAttributes,
+ EncryptionDictAttributes,
+ FieldDictionaryAttributes,
+ FilterTypeAbbreviations,
+ FilterTypes,
+ GoToActionArguments,
+ GraphicsStateParameters,
+ ImageAttributes,
+ FileSpecificationDictionaryEntries,
+ LzwFilterParameters,
+ PageAttributes,
+ PageLayouts,
+ PagesAttributes,
+ Resources,
+ StreamAttributes,
+ TrailerKeys,
+ TypArguments,
+ TypFitArguments,
+)
class ImageType(IntFlag):
@@ -619,4 +759,4 @@ class ImageType(IntFlag):
INLINE_IMAGES = auto()
DRAWING_IMAGES = auto()
ALL = XOBJECT_IMAGES | INLINE_IMAGES | DRAWING_IMAGES
- IMAGES = ALL
+ IMAGES = ALL # for consistency with ObjectDeletionFlag
diff --git a/pypdf/errors.py b/pypdf/errors.py
index 0fa6a717..c962dec6 100644
--- a/pypdf/errors.py
+++ b/pypdf/errors.py
@@ -59,4 +59,4 @@ class EmptyFileError(PdfReadError):
"""Raised when a PDF file is empty or has no content."""
-STREAM_TRUNCATED_PREMATURELY = 'Stream has ended unexpectedly'
+STREAM_TRUNCATED_PREMATURELY = "Stream has ended unexpectedly"
diff --git a/pypdf/filters.py b/pypdf/filters.py
index c0443ef7..5e6a10f7 100644
--- a/pypdf/filters.py
+++ b/pypdf/filters.py
@@ -1,17 +1,54 @@
+# 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'
+__author__ = "Mathieu Fenniak"
+__author_email__ = "biziqe@mathieu.fenniak.net"
+
import math
import struct
import zlib
from base64 import a85decode
from io import BytesIO
from typing import Any, Dict, List, Optional, Tuple, Union, cast
-from ._utils import WHITESPACES_AS_BYTES, b_, deprecate_with_replacement, deprecation_no_replacement, logger_warning, ord_
+
+from ._utils import (
+ WHITESPACES_AS_BYTES,
+ b_,
+ deprecate_with_replacement,
+ deprecation_no_replacement,
+ logger_warning,
+ ord_,
+)
from .constants import CcittFaxDecodeParameters as CCITT
from .constants import ColorSpaces
from .constants import FilterTypeAbbreviations as FTA
@@ -20,10 +57,15 @@ from .constants import ImageAttributes as IA
from .constants import LzwFilterParameters as LZW
from .constants import StreamAttributes as SA
from .errors import DeprecationError, PdfReadError, PdfStreamError
-from .generic import ArrayObject, DictionaryObject, IndirectObject, NullObject
+from .generic import (
+ ArrayObject,
+ DictionaryObject,
+ IndirectObject,
+ NullObject,
+)
-def decompress(data: bytes) ->bytes:
+def decompress(data: bytes) -> bytes:
"""
Decompress the given data using zlib.
@@ -37,14 +79,31 @@ def decompress(data: bytes) ->bytes:
Returns:
The decompressed data.
"""
- pass
+ try:
+ return zlib.decompress(data)
+ except zlib.error:
+ try:
+ # For larger files, use Decompress object to enable buffered reading
+ return zlib.decompressobj().decompress(data)
+ except zlib.error:
+ # If still failed, then try with increased window size
+ d = zlib.decompressobj(zlib.MAX_WBITS | 32)
+ result_str = b""
+ for b in [data[i : i + 1] for i in range(len(data))]:
+ try:
+ result_str += d.decompress(b)
+ except zlib.error:
+ pass
+ return result_str
class FlateDecode:
-
@staticmethod
- def decode(data: bytes, decode_parms: Optional[DictionaryObject]=None,
- **kwargs: Any) ->bytes:
+ def decode(
+ data: bytes,
+ decode_parms: Optional[DictionaryObject] = None,
+ **kwargs: Any,
+ ) -> bytes:
"""
Decode data which is flate-encoded.
@@ -59,10 +118,130 @@ class FlateDecode:
Raises:
PdfReadError:
"""
- pass
+ if "decodeParms" in kwargs: # deprecated
+ deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
+ decode_parms = kwargs["decodeParms"]
+ if isinstance(decode_parms, ArrayObject):
+ raise DeprecationError("decode_parms as ArrayObject is depreciated")
+
+ str_data = decompress(data)
+ predictor = 1
+
+ if decode_parms:
+ try:
+ predictor = decode_parms.get("/Predictor", 1)
+ except (AttributeError, TypeError): # Type Error is NullObject
+ pass # Usually an array with a null object was read
+ # predictor 1 == no predictor
+ if predictor != 1:
+ # /Columns, the number of samples in each row, has a default value of 1;
+ # §7.4.4.3, ISO 32000.
+ DEFAULT_BITS_PER_COMPONENT = 8
+ try:
+ columns = cast(int, decode_parms[LZW.COLUMNS].get_object()) # type: ignore
+ except (TypeError, KeyError):
+ columns = 1
+ try:
+ colors = cast(int, decode_parms[LZW.COLORS].get_object()) # type: ignore
+ except (TypeError, KeyError):
+ colors = 1
+ try:
+ bits_per_component = cast(
+ int,
+ decode_parms[LZW.BITS_PER_COMPONENT].get_object(), # type: ignore
+ )
+ except (TypeError, KeyError):
+ bits_per_component = DEFAULT_BITS_PER_COMPONENT
+
+ # PNG predictor can vary by row and so is the lead byte on each row
+ rowlength = (
+ math.ceil(columns * colors * bits_per_component / 8) + 1
+ ) # number of bytes
+
+ # TIFF prediction:
+ if predictor == 2:
+ rowlength -= 1 # remove the predictor byte
+ bpp = rowlength // columns
+ str_data = bytearray(str_data)
+ for i in range(len(str_data)):
+ if i % rowlength >= bpp:
+ str_data[i] = (str_data[i] + str_data[i - bpp]) % 256
+ str_data = bytes(str_data)
+ # PNG prediction:
+ elif 10 <= predictor <= 15:
+ str_data = FlateDecode._decode_png_prediction(
+ str_data, columns, rowlength
+ )
+ else:
+ # unsupported predictor
+ raise PdfReadError(f"Unsupported flatedecode predictor {predictor!r}")
+ return str_data
@staticmethod
- def encode(data: bytes, level: int=-1) ->bytes:
+ def _decode_png_prediction(data: bytes, columns: int, rowlength: int) -> bytes:
+ # PNG prediction can vary from row to row
+ if len(data) % rowlength != 0:
+ raise PdfReadError("Image data is not rectangular")
+ output = []
+ prev_rowdata = (0,) * rowlength
+ bpp = (rowlength - 1) // columns # recomputed locally to not change params
+ for row in range(0, len(data), rowlength):
+ rowdata: List[int] = list(data[row : row + rowlength])
+ filter_byte = rowdata[0]
+
+ if filter_byte == 0:
+ pass
+ elif filter_byte == 1:
+ for i in range(bpp + 1, rowlength):
+ rowdata[i] = (rowdata[i] + rowdata[i - bpp]) % 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, bpp + 1):
+ # left = 0
+ floor = prev_rowdata[i] // 2
+ rowdata[i] = (rowdata[i] + floor) % 256
+ for i in range(bpp + 1, rowlength):
+ left = rowdata[i - bpp]
+ floor = (left + prev_rowdata[i]) // 2
+ rowdata[i] = (rowdata[i] + floor) % 256
+ elif filter_byte == 4:
+ for i in range(1, bpp + 1):
+ # left = 0
+ up = prev_rowdata[i]
+ # up_left = 0
+ paeth = up
+ rowdata[i] = (rowdata[i] + paeth) % 256
+ for i in range(bpp + 1, rowlength):
+ left = rowdata[i - bpp]
+ up = prev_rowdata[i]
+ up_left = prev_rowdata[i - bpp]
+
+ p = left + up - up_left
+ dist_left = abs(p - left)
+ dist_up = abs(p - up)
+ dist_up_left = abs(p - up_left)
+
+ if dist_left <= dist_up and dist_left <= dist_up_left:
+ paeth = left
+ elif dist_up <= dist_up_left:
+ paeth = up
+ else:
+ paeth = up_left
+
+ rowdata[i] = (rowdata[i] + paeth) % 256
+ else:
+ # unsupported PNG filter
+ raise PdfReadError(
+ f"Unsupported PNG filter {filter_byte!r}"
+ ) # pragma: no cover
+ prev_rowdata = tuple(rowdata)
+ output.extend(rowdata[1:])
+ return bytes(output)
+
+ @staticmethod
+ def encode(data: bytes, level: int = -1) -> bytes:
"""
Compress the input data using zlib.
@@ -73,7 +252,7 @@ class FlateDecode:
Returns:
The compressed data.
"""
- pass
+ return zlib.compress(data, level)
class ASCIIHexDecode:
@@ -83,8 +262,11 @@ class ASCIIHexDecode:
"""
@staticmethod
- def decode(data: Union[str, bytes], decode_parms: Optional[
- DictionaryObject]=None, **kwargs: Any) ->bytes:
+ def decode(
+ data: Union[str, bytes],
+ decode_parms: Optional[DictionaryObject] = None,
+ **kwargs: Any,
+ ) -> bytes:
"""
Decode an ASCII-Hex encoded data stream.
@@ -101,7 +283,32 @@ class ASCIIHexDecode:
Raises:
PdfStreamError:
"""
- pass
+ # decode_parms is unused here
+
+ if isinstance(data, str):
+ data = data.encode()
+ retval = b""
+ hex_pair = b""
+ index = 0
+ while True:
+ if index >= len(data):
+ logger_warning(
+ "missing EOD in ASCIIHexDecode, check if output is OK", __name__
+ )
+ break # reach End Of String even if no EOD
+ char = data[index : index + 1]
+ if char == b">":
+ break
+ elif char.isspace():
+ index += 1
+ continue
+ hex_pair += char
+ if len(hex_pair) == 2:
+ retval += bytes((int(hex_pair, base=16),))
+ hex_pair = b""
+ index += 1
+ assert hex_pair == b""
+ return retval
class RunLengthDecode:
@@ -119,8 +326,11 @@ class RunLengthDecode:
"""
@staticmethod
- def decode(data: bytes, decode_parms: Optional[DictionaryObject]=None,
- **kwargs: Any) ->bytes:
+ def decode(
+ data: bytes,
+ decode_parms: Optional[DictionaryObject] = None,
+ **kwargs: Any,
+ ) -> bytes:
"""
Decode a run length encoded data stream.
@@ -134,7 +344,32 @@ class RunLengthDecode:
Raises:
PdfStreamError:
"""
- pass
+ # decode_parms is unused here
+
+ lst = []
+ index = 0
+ while True:
+ if index >= len(data):
+ logger_warning(
+ "missing EOD in RunLengthDecode, check if output is OK", __name__
+ )
+ break # reach End Of String even if no EOD
+ length = data[index]
+ index += 1
+ if length == 128:
+ if index < len(data):
+ raise PdfStreamError("early EOD in RunLengthDecode")
+ else:
+ break
+ elif length < 128:
+ length += 1
+ lst.append(data[index : (index + length)])
+ index += length
+ else: # >128
+ length = 257 - length
+ lst.append(bytes((data[index],)) * length)
+ index += 1
+ return b"".join(lst)
class LZWDecode:
@@ -145,21 +380,43 @@ class LZWDecode:
Renderer/com/sun/pdfview/decode/LZWDecode.java.htm
"""
-
class Decoder:
-
- def __init__(self, data: bytes) ->None:
+ def __init__(self, data: bytes) -> None:
self.STOP = 257
self.CLEARDICT = 256
self.data = data
self.bytepos = 0
self.bitpos = 0
- self.dict = [''] * 4096
+ self.dict = [""] * 4096
for i in range(256):
self.dict[i] = chr(i)
self.reset_dict()
- def decode(self) ->str:
+ 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.
@@ -171,11 +428,43 @@ class LZWDecode:
Raises:
PdfReadError: If the stop code is missing
"""
- pass
+ 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: Optional[DictionaryObject]=None,
- **kwargs: Any) ->str:
+ def decode(
+ data: bytes,
+ decode_parms: Optional[DictionaryObject] = None,
+ **kwargs: Any,
+ ) -> str:
"""
Decode an LZW encoded data stream.
@@ -186,15 +475,20 @@ class LZWDecode:
Returns:
decoded data.
"""
- pass
+ # decode_parms is unused here
+
+ 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: Optional[
- DictionaryObject]=None, **kwargs: Any) ->bytes:
+ def decode(
+ data: Union[str, bytes],
+ decode_parms: Optional[DictionaryObject] = None,
+ **kwargs: Any,
+ ) -> bytes:
"""
Decode an Ascii85 encoded data stream.
@@ -205,29 +499,56 @@ class ASCII85Decode:
Returns:
decoded data.
"""
- pass
+ if isinstance(data, str):
+ data = data.encode()
+ data = data.strip(WHITESPACES_AS_BYTES)
+ return a85decode(data, adobe=True, ignorechars=WHITESPACES_AS_BYTES)
class DCTDecode:
- pass
+ @staticmethod
+ def decode(
+ data: bytes,
+ decode_parms: Optional[DictionaryObject] = None,
+ **kwargs: Any,
+ ) -> bytes:
+ # decode_parms is unused here
+ return data
class JPXDecode:
- pass
+ @staticmethod
+ def decode(
+ data: bytes,
+ decode_parms: Optional[DictionaryObject] = None,
+ **kwargs: Any,
+ ) -> bytes:
+ # decode_parms is unused here
+ return data
class CCITParameters:
"""§7.4.6, optional parameters for the CCITTFaxDecode filter."""
- def __init__(self, K: int=0, columns: int=0, rows: int=0) ->None:
+ 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
- self.rows = rows
+ 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:
"""
@@ -239,8 +560,98 @@ class CCITTFaxDecode:
§7.4.6, optional parameters for the CCITTFaxDecode filter.
"""
+ @staticmethod
+ def _get_parameters(
+ parameters: Union[None, ArrayObject, DictionaryObject, IndirectObject],
+ rows: int,
+ ) -> CCITParameters:
+ # §7.4.6, optional parameters for the CCITTFaxDecode filter
+ k = 0
+ columns = 1728
+ if parameters:
+ parameters_unwrapped = cast(
+ Union[ArrayObject, DictionaryObject], parameters.get_object()
+ )
+ if isinstance(parameters_unwrapped, ArrayObject):
+ for decode_parm in parameters_unwrapped:
+ if CCITT.COLUMNS in decode_parm:
+ columns = decode_parm[CCITT.COLUMNS]
+ if CCITT.K in decode_parm:
+ k = decode_parm[CCITT.K]
+ else:
+ if CCITT.COLUMNS in parameters_unwrapped:
+ columns = parameters_unwrapped[CCITT.COLUMNS] # type: ignore
+ if CCITT.K in parameters_unwrapped:
+ k = parameters_unwrapped[CCITT.K] # type: ignore
+
+ return CCITParameters(k, columns, rows)
-def decode_stream_data(stream: Any) ->Union[bytes, str]:
+ @staticmethod
+ def decode(
+ data: bytes,
+ decode_parms: Optional[DictionaryObject] = None,
+ height: int = 0,
+ **kwargs: Any,
+ ) -> bytes:
+ # decode_parms is unused here
+ if "decodeParms" in kwargs: # deprecated
+ deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
+ decode_parms = kwargs["decodeParms"]
+ if isinstance(decode_parms, ArrayObject): # deprecated
+ deprecation_no_replacement(
+ "decode_parms being an ArrayObject", removed_in="3.15.5"
+ )
+ params = CCITTFaxDecode._get_parameters(decode_parms, height)
+
+ img_size = len(data)
+ tiff_header_struct = "<2shlh" + "hhll" * 8 + "h"
+ tiff_header = struct.pack(
+ tiff_header_struct,
+ b"II", # Byte order indication: Little endian
+ 42, # Version number (always 42)
+ 8, # Offset to first IFD
+ 8, # Number of tags in IFD
+ 256,
+ 4,
+ 1,
+ params.columns, # ImageWidth, LONG, 1, width
+ 257,
+ 4,
+ 1,
+ params.rows, # ImageLength, LONG, 1, length
+ 258,
+ 3,
+ 1,
+ 1, # BitsPerSample, SHORT, 1, 1
+ 259,
+ 3,
+ 1,
+ params.group, # Compression, SHORT, 1, 4 = CCITT Group 4 fax encoding
+ 262,
+ 3,
+ 1,
+ 0, # Thresholding, SHORT, 1, 0 = WhiteIsZero
+ 273,
+ 4,
+ 1,
+ struct.calcsize(
+ tiff_header_struct
+ ), # StripOffsets, LONG, 1, length of header
+ 278,
+ 4,
+ 1,
+ params.rows, # RowsPerStrip, LONG, 1, length
+ 279,
+ 4,
+ 1,
+ img_size, # StripByteCounts, LONG, 1, size of image
+ 0, # last IFD
+ )
+
+ return tiff_header + data
+
+
+def decode_stream_data(stream: Any) -> Union[bytes, str]: # utils.StreamObject
"""
Decode the stream data based on the specified filters.
@@ -258,16 +669,56 @@ def decode_stream_data(stream: Any) ->Union[bytes, str]:
Raises:
NotImplementedError: If an unsupported filter type is encountered.
"""
- pass
-
-
-def decodeStreamData(stream: Any) ->Union[str, bytes]:
+ filters = stream.get(SA.FILTER, ())
+ if isinstance(filters, IndirectObject):
+ filters = cast(ArrayObject, filters.get_object())
+ if not isinstance(filters, ArrayObject):
+ # we have a single filter instance
+ filters = (filters,)
+ decodparms = stream.get(SA.DECODE_PARMS, ({},) * len(filters))
+ if not isinstance(decodparms, (list, tuple)):
+ decodparms = (decodparms,)
+ data: bytes = b_(stream._data)
+ # If there is not data to decode we should not try to decode the data.
+ if data:
+ for filter_type, params in zip(filters, decodparms):
+ if isinstance(params, NullObject):
+ params = {}
+ if filter_type in (FT.FLATE_DECODE, FTA.FL):
+ data = FlateDecode.decode(data, params)
+ elif filter_type in (FT.ASCII_HEX_DECODE, FTA.AHx):
+ data = ASCIIHexDecode.decode(data)
+ elif filter_type in (FT.RUN_LENGTH_DECODE, FTA.RL):
+ data = RunLengthDecode.decode(data)
+ elif filter_type in (FT.LZW_DECODE, FTA.LZW):
+ data = LZWDecode.decode(data, params) # 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 == FT.JPX_DECODE:
+ data = JPXDecode.decode(data)
+ elif filter_type == FT.CCITT_FAX_DECODE:
+ height = stream.get(IA.HEIGHT, ())
+ data = CCITTFaxDecode.decode(data, params, height)
+ elif filter_type == "/Crypt":
+ if "/Name" in params or "/Type" in params:
+ 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]: # deprecated
"""Deprecated. Use decode_stream_data."""
- pass
+ 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, Any]:
+def _xobj_to_image(x_object_obj: Dict[str, Any]) -> Tuple[Optional[str], bytes, Any]:
"""
Users need to have the pillow package installed.
@@ -280,4 +731,180 @@ def _xobj_to_image(x_object_obj: Dict[str, Any]) ->Tuple[Optional[str],
Returns:
Tuple[file extension, bytes, PIL.Image.Image]
"""
- pass
+ from ._xobj_image_helpers import (
+ Image,
+ UnidentifiedImageError,
+ _extended_image_frombytes,
+ _get_imagemode,
+ _handle_flate,
+ _handle_jpx,
+ mode_str_type,
+ )
+
+ # for error reporting
+ if (
+ hasattr(x_object_obj, "indirect_reference") and x_object_obj is None
+ ): # pragma: no cover
+ obj_as_text = x_object_obj.indirect_reference.__repr__()
+ else:
+ obj_as_text = x_object_obj.__repr__()
+
+ size = (cast(int, x_object_obj[IA.WIDTH]), cast(int, x_object_obj[IA.HEIGHT]))
+ data = x_object_obj.get_data() # type: ignore
+ if isinstance(data, str): # pragma: no cover
+ data = data.encode()
+ if len(data) % (size[0] * size[1]) == 1 and data[-1] == 0x0A: # ie. '\n'
+ data = data[:-1]
+ colors = x_object_obj.get("/Colors", 1)
+ color_space: Any = x_object_obj.get("/ColorSpace", NullObject()).get_object()
+ if isinstance(color_space, list) and len(color_space) == 1:
+ color_space = color_space[0].get_object()
+ if (
+ IA.COLOR_SPACE in x_object_obj
+ and x_object_obj[IA.COLOR_SPACE] == ColorSpaces.DEVICE_RGB
+ ):
+ # https://pillow.readthedocs.io/en/stable/handbook/concepts.html#modes
+ mode: mode_str_type = "RGB"
+ if x_object_obj.get("/BitsPerComponent", 8) < 8:
+ mode, invert_color = _get_imagemode(
+ f"{x_object_obj.get('/BitsPerComponent', 8)}bit", 0, ""
+ )
+ else:
+ mode, invert_color = _get_imagemode(
+ color_space,
+ 2
+ if (
+ colors == 1
+ and (
+ not isinstance(color_space, NullObject)
+ and "Gray" not in color_space
+ )
+ )
+ else colors,
+ "",
+ )
+ extension = None
+ alpha = None
+ filters = x_object_obj.get(SA.FILTER, NullObject()).get_object()
+ lfilters = filters[-1] if isinstance(filters, list) else filters
+ if lfilters in (FT.FLATE_DECODE, FT.RUN_LENGTH_DECODE):
+ img, image_format, extension, _ = _handle_flate(
+ size,
+ data,
+ mode,
+ color_space,
+ colors,
+ obj_as_text,
+ )
+ elif lfilters in (FT.LZW_DECODE, FT.ASCII_85_DECODE, FT.CCITT_FAX_DECODE):
+ # I'm not sure if the following logic is correct.
+ # There might not be any relationship between the filters and the
+ # extension
+ if lfilters in (FT.LZW_DECODE, FT.CCITT_FAX_DECODE):
+ extension = ".tiff" # mime_type = "image/tiff"
+ image_format = "TIFF"
+ else:
+ extension = ".png" # mime_type = "image/png"
+ image_format = "PNG"
+ try:
+ img = Image.open(BytesIO(data), formats=("TIFF", "PNG"))
+ except UnidentifiedImageError:
+ img = _extended_image_frombytes(mode, size, data)
+ elif lfilters == FT.DCT_DECODE:
+ img, image_format, extension = Image.open(BytesIO(data)), "JPEG", ".jpg"
+ # invert_color kept unchanged
+ elif lfilters == FT.JPX_DECODE:
+ img, image_format, extension, invert_color = _handle_jpx(
+ size, data, mode, color_space, colors
+ )
+ elif lfilters == FT.CCITT_FAX_DECODE:
+ img, image_format, extension, invert_color = (
+ Image.open(BytesIO(data), formats=("TIFF",)),
+ "TIFF",
+ ".tiff",
+ False,
+ )
+ elif mode == "CMYK":
+ img, image_format, extension, invert_color = (
+ _extended_image_frombytes(mode, size, data),
+ "TIFF",
+ ".tif",
+ False,
+ )
+ elif mode == "":
+ raise PdfReadError(f"ColorSpace field not found in {x_object_obj}")
+ else:
+ img, image_format, extension, invert_color = (
+ _extended_image_frombytes(mode, size, data),
+ "PNG",
+ ".png",
+ False,
+ )
+ # CMYK image and other colorspaces without decode
+ # requires reverting scale (cf p243,2§ last sentence)
+ decode = x_object_obj.get(
+ IA.DECODE,
+ ([1.0, 0.0] * len(img.getbands()))
+ if (
+ (img.mode == "CMYK" and lfilters in (FT.DCT_DECODE, FT.JPX_DECODE))
+ or (invert_color and img.mode == "L")
+ )
+ else None,
+ )
+ if (
+ isinstance(color_space, ArrayObject)
+ and color_space[0].get_object() == "/Indexed"
+ ):
+ decode = None # decode is meanless of Indexed
+ if (
+ isinstance(color_space, ArrayObject)
+ and color_space[0].get_object() == "/Separation"
+ ):
+ decode = [1.0, 0.0] * len(img.getbands())
+ if decode is not None and not all(decode[i] == i % 2 for i in range(len(decode))):
+ lut: List[int] = []
+ for i in range(0, len(decode), 2):
+ dmin = decode[i]
+ dmax = decode[i + 1]
+ lut.extend(
+ round(255.0 * (j / 255.0 * (dmax - dmin) + dmin)) for j in range(256)
+ )
+ img = img.point(lut)
+
+ if IA.S_MASK in x_object_obj: # add alpha channel
+ alpha = _xobj_to_image(x_object_obj[IA.S_MASK])[2]
+ if img.size != alpha.size:
+ logger_warning(f"image and mask size not matching: {obj_as_text}", __name__)
+ else:
+ # TODO : implement mask
+ if alpha.mode != "L":
+ alpha = alpha.convert("L")
+ if img.mode == "P":
+ img = img.convert("RGB")
+ elif img.mode == "1":
+ img = img.convert("L")
+ img.putalpha(alpha)
+ if "JPEG" in image_format:
+ extension = ".jp2"
+ image_format = "JPEG2000"
+ else:
+ extension = ".png"
+ image_format = "PNG"
+
+ img_byte_arr = BytesIO()
+ try:
+ img.save(img_byte_arr, format=image_format)
+ except OSError: # pragma: no cover # covered with pillow 10.3
+ # in case of we convert to RGBA and then to PNG
+ img1 = img.convert("RGBA")
+ image_format = "PNG"
+ extension = ".png"
+ img_byte_arr = BytesIO()
+ img1.save(img_byte_arr, format=image_format)
+ data = img_byte_arr.getvalue()
+
+ try: # temporary try/except until other fixes of images
+ img = Image.open(BytesIO(data))
+ except Exception:
+ img = None # type: ignore
+ return extension, data, img
diff --git a/pypdf/generic/_base.py b/pypdf/generic/_base.py
index 0b650fd4..2d606b41 100644
--- a/pypdf/generic/_base.py
+++ b/pypdf/generic/_base.py
@@ -1,3 +1,29 @@
+# Copyright (c) 2006, Mathieu Fenniak
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
import binascii
import codecs
import hashlib
@@ -5,21 +31,47 @@ import re
from binascii import unhexlify
from math import log10
from typing import Any, Callable, ClassVar, Dict, Optional, Sequence, Union, cast
+
from .._codecs import _pdfdoc_encoding_rev
from .._protocols import PdfObjectProtocol, PdfWriterProtocol
-from .._utils import StreamType, b_, deprecate_no_replacement, logger_warning, read_non_whitespace, read_until_regex, str_
+from .._utils import (
+ StreamType,
+ b_,
+ deprecate_no_replacement,
+ 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'
+
+__author__ = "Mathieu Fenniak"
+__author_email__ = "biziqe@mathieu.fenniak.net"
class PdfObject(PdfObjectProtocol):
- hash_func: Callable[..., 'hashlib._Hash'] = hashlib.sha1
- indirect_reference: Optional['IndirectObject']
+ # function for calculating a hash value
+ hash_func: Callable[..., "hashlib._Hash"] = hashlib.sha1
+ indirect_reference: Optional["IndirectObject"]
- def clone(self, pdf_dest: PdfWriterProtocol, force_duplicate: bool=
- False, ignore_fields: Optional[Sequence[Union[str, int]]]=()
- ) ->'PdfObject':
+ 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: Optional[Sequence[Union[str, int]]] = (),
+ ) -> "PdfObject":
"""
Clone object into pdf_dest (PdfWriterProtocol which is an interface for PdfWriter).
@@ -40,10 +92,13 @@ class PdfObject(PdfObjectProtocol):
Returns:
The cloned PdfObject
"""
- pass
+ raise NotImplementedError(
+ f"{self.__class__.__name__} does not implement .clone so far"
+ )
- def _reference_clone(self, clone: Any, pdf_dest: PdfWriterProtocol,
- force_duplicate: bool=False) ->PdfObjectProtocol:
+ def _reference_clone(
+ self, clone: Any, pdf_dest: PdfWriterProtocol, force_duplicate: bool = False
+ ) -> PdfObjectProtocol:
"""
Reference the object within the _objects of pdf_dest only if
indirect_reference attribute exists (which means the objects was
@@ -57,37 +112,94 @@ class PdfObject(PdfObjectProtocol):
Returns:
The clone
"""
- pass
-
- def get_object(self) ->Optional['PdfObject']:
+ try:
+ if not force_duplicate and clone.indirect_reference.pdf == pdf_dest:
+ return clone
+ except Exception:
+ pass
+ # if hasattr(clone, "indirect_reference"):
+ try:
+ ind = self.indirect_reference
+ except AttributeError:
+ return clone
+ i = len(pdf_dest._objects) + 1
+ if ind is not None:
+ if id(ind.pdf) not in pdf_dest._id_translated:
+ pdf_dest._id_translated[id(ind.pdf)] = {}
+ pdf_dest._id_translated[id(ind.pdf)]["PreventGC"] = ind.pdf # type: ignore
+ if (
+ not force_duplicate
+ and ind.idnum in pdf_dest._id_translated[id(ind.pdf)]
+ ):
+ obj = pdf_dest.get_object(
+ pdf_dest._id_translated[id(ind.pdf)][ind.idnum]
+ )
+ assert obj is not None
+ return obj
+ pdf_dest._id_translated[id(ind.pdf)][ind.idnum] = i
+ pdf_dest._objects.append(clone)
+ clone.indirect_reference = IndirectObject(i, 0, pdf_dest)
+ return clone
+
+ def get_object(self) -> Optional["PdfObject"]:
"""Resolve indirect references."""
- pass
+ return self
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ raise NotImplementedError
-class NullObject(PdfObject):
- def clone(self, pdf_dest: PdfWriterProtocol, force_duplicate: bool=
- False, ignore_fields: Optional[Sequence[Union[str, int]]]=()
- ) ->'NullObject':
+class NullObject(PdfObject):
+ def clone(
+ self,
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool = False,
+ ignore_fields: Optional[Sequence[Union[str, int]]] = (),
+ ) -> "NullObject":
"""Clone object into pdf_dest."""
- pass
+ return cast(
+ "NullObject", self._reference_clone(NullObject(), pdf_dest, force_duplicate)
+ )
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ if encryption_key is not None: # deprecated
+ deprecate_no_replacement(
+ "the encryption_key parameter of write_to_stream", "5.0.0"
+ )
+ stream.write(b"null")
- def __repr__(self) ->str:
- return 'NullObject'
+ @staticmethod
+ def read_from_stream(stream: StreamType) -> "NullObject":
+ nulltxt = stream.read(4)
+ if nulltxt != b"null":
+ raise PdfReadError("Could not read Null object")
+ return NullObject()
+ def __repr__(self) -> str:
+ return "NullObject"
-class BooleanObject(PdfObject):
- def __init__(self, value: Any) ->None:
+class BooleanObject(PdfObject):
+ def __init__(self, value: Any) -> None:
self.value = value
- def clone(self, pdf_dest: PdfWriterProtocol, force_duplicate: bool=
- False, ignore_fields: Optional[Sequence[Union[str, int]]]=()
- ) ->'BooleanObject':
+ def clone(
+ self,
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool = False,
+ ignore_fields: Optional[Sequence[Union[str, int]]] = (),
+ ) -> "BooleanObject":
"""Clone object into pdf_dest."""
- pass
+ return cast(
+ "BooleanObject",
+ self._reference_clone(BooleanObject(self.value), pdf_dest, force_duplicate),
+ )
- def __eq__(self, __o: object) ->bool:
+ def __eq__(self, __o: object) -> bool:
if isinstance(__o, BooleanObject):
return self.value == __o.value
elif isinstance(__o, bool):
@@ -95,95 +207,256 @@ class BooleanObject(PdfObject):
else:
return False
- def __repr__(self) ->str:
- return 'True' if self.value else 'False'
+ def __repr__(self) -> str:
+ return "True" if self.value else "False"
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ if encryption_key is not None: # deprecated
+ deprecate_no_replacement(
+ "the encryption_key parameter of write_to_stream", "5.0.0"
+ )
+ if self.value:
+ stream.write(b"true")
+ else:
+ stream.write(b"false")
+
+ @staticmethod
+ def read_from_stream(stream: StreamType) -> "BooleanObject":
+ word = stream.read(4)
+ if word == b"true":
+ return BooleanObject(True)
+ elif word == b"fals":
+ stream.read(1)
+ return BooleanObject(False)
+ else:
+ raise PdfReadError("Could not read Boolean object")
-class IndirectObject(PdfObject):
- def __init__(self, idnum: int, generation: int, pdf: Any) ->None:
+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: Optional[Sequence[Union[str, int]]]=()
- ) ->'IndirectObject':
+ def clone(
+ self,
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool = False,
+ ignore_fields: Optional[Sequence[Union[str, int]]] = (),
+ ) -> "IndirectObject":
"""Clone object into pdf_dest."""
- pass
+ if self.pdf == pdf_dest and not force_duplicate:
+ # Already duplicated and no extra duplication required
+ return self
+ if id(self.pdf) not in pdf_dest._id_translated:
+ pdf_dest._id_translated[id(self.pdf)] = {}
+
+ if self.idnum in pdf_dest._id_translated[id(self.pdf)]:
+ dup = pdf_dest.get_object(pdf_dest._id_translated[id(self.pdf)][self.idnum])
+ if force_duplicate:
+ assert dup is not None
+ assert dup.indirect_reference is not None
+ idref = dup.indirect_reference
+ return IndirectObject(idref.idnum, idref.generation, idref.pdf)
+ else:
+ obj = self.get_object()
+ # case observed : a pointed object can not be found
+ if obj is None:
+ # this normally
+ obj = NullObject()
+ assert isinstance(self, (IndirectObject,))
+ obj.indirect_reference = self
+ dup = pdf_dest._add_object(
+ obj.clone(pdf_dest, force_duplicate, ignore_fields)
+ )
+ # asserts added to prevent errors in mypy
+ assert dup is not None
+ assert dup.indirect_reference is not None
+ return dup.indirect_reference
- def __deepcopy__(self, memo: Any) ->'IndirectObject':
+ @property
+ def indirect_reference(self) -> "IndirectObject": # type: ignore[override]
+ return self
+
+ def get_object(self) -> Optional["PdfObject"]:
+ return self.pdf.get_object(self)
+
+ def __deepcopy__(self, memo: Any) -> "IndirectObject":
return IndirectObject(self.idnum, self.generation, self.pdf)
- def __getattr__(self, name: str) ->Any:
+ def _get_object_with_check(self) -> Optional["PdfObject"]:
+ o = self.get_object()
+ # the check is done here to not slow down get_object()
+ if isinstance(o, IndirectObject):
+ raise PdfStreamError(
+ f"{self.__repr__()} references an IndirectObject {o.__repr__()}"
+ )
+ return o
+
+ def __getattr__(self, name: str) -> Any:
+ # Attribute not found in object: look in pointed object
try:
return getattr(self._get_object_with_check(), name)
except AttributeError:
raise AttributeError(
- f'No attribute {name} found in IndirectObject or pointed object'
- )
+ f"No attribute {name} found in IndirectObject or pointed object"
+ )
- def __getitem__(self, key: Any) ->Any:
- return self._get_object_with_check()[key]
+ def __getitem__(self, key: Any) -> Any:
+ # items should be extracted from pointed Object
+ return self._get_object_with_check()[key] # type: ignore
- def __str__(self) ->str:
+ def __str__(self) -> str:
+ # in this case we are looking for the pointed data
return self.get_object().__str__()
- def __repr__(self) ->str:
- return (
- f'IndirectObject({self.idnum!r}, {self.generation!r}, {id(self.pdf)})'
- )
-
- def __eq__(self, other: object) ->bool:
- return (other is not None and isinstance(other, IndirectObject) and
- self.idnum == other.idnum and self.generation == other.
- generation and self.pdf is other.pdf)
+ def __repr__(self) -> str:
+ return f"IndirectObject({self.idnum!r}, {self.generation!r}, {id(self.pdf)})"
- def __ne__(self, other: object) ->bool:
+ def __eq__(self, other: object) -> bool:
+ return (
+ other is not None
+ and isinstance(other, IndirectObject)
+ and self.idnum == other.idnum
+ and self.generation == other.generation
+ and self.pdf is other.pdf
+ )
+
+ def __ne__(self, other: object) -> bool:
return not self.__eq__(other)
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ if encryption_key is not None: # deprecated
+ deprecate_no_replacement(
+ "the encryption_key parameter of write_to_stream", "5.0.0"
+ )
+ stream.write(f"{self.idnum} {self.generation} R".encode())
+
+ @staticmethod
+ def read_from_stream(stream: StreamType, pdf: Any) -> "IndirectObject": # PdfReader
+ idnum = b""
+ while True:
+ tok = stream.read(1)
+ if not tok:
+ raise PdfStreamError(STREAM_TRUNCATED_PREMATURELY)
+ if tok.isspace():
+ break
+ idnum += tok
+ generation = b""
+ while True:
+ tok = stream.read(1)
+ if not tok:
+ raise PdfStreamError(STREAM_TRUNCATED_PREMATURELY)
+ if tok.isspace():
+ if not generation:
+ continue
+ break
+ generation += tok
+ r = read_non_whitespace(stream)
+ if r != b"R":
+ raise PdfReadError(
+ f"Error reading indirect object reference at byte {hex(stream.tell())}"
+ )
+ return IndirectObject(int(idnum), int(generation), pdf)
+
-FLOAT_WRITE_PRECISION = 8
+FLOAT_WRITE_PRECISION = 8 # shall be min 5 digits max, allow user adj
class FloatObject(float, PdfObject):
-
- def __new__(cls, value: Union[str, Any]='0.0', context: Optional[Any]=None
- ) ->'FloatObject':
+ def __new__(
+ cls, value: Union[str, Any] = "0.0", context: Optional[Any] = None
+ ) -> "FloatObject":
try:
value = float(str_(value))
return float.__new__(cls, value)
except Exception as e:
+ # If this isn't a valid decimal (happens in malformed PDFs)
+ # fallback to 0
logger_warning(
- f'{e} : FloatObject ({value}) invalid; use 0.0 instead',
- __name__)
+ f"{e} : FloatObject ({value}) invalid; use 0.0 instead", __name__
+ )
return float.__new__(cls, 0.0)
- def clone(self, pdf_dest: Any, force_duplicate: bool=False,
- ignore_fields: Optional[Sequence[Union[str, int]]]=()) ->'FloatObject':
+ def clone(
+ self,
+ pdf_dest: Any,
+ force_duplicate: bool = False,
+ ignore_fields: Optional[Sequence[Union[str, int]]] = (),
+ ) -> "FloatObject":
"""Clone object into pdf_dest."""
- pass
-
- def __repr__(self) ->str:
- return self.myrepr()
+ return cast(
+ "FloatObject",
+ self._reference_clone(FloatObject(self), pdf_dest, force_duplicate),
+ )
+
+ def myrepr(self) -> str:
+ if self == 0:
+ return "0.0"
+ nb = FLOAT_WRITE_PRECISION - int(log10(abs(self)))
+ s = f"{self:.{max(1,nb)}f}".rstrip("0").rstrip(".")
+ return s
+
+ def __repr__(self) -> str:
+ return self.myrepr() # repr(float(self))
+
+ def as_numeric(self) -> float:
+ return float(self)
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ if encryption_key is not None: # deprecated
+ deprecate_no_replacement(
+ "the encryption_key parameter of write_to_stream", "5.0.0"
+ )
+ stream.write(self.myrepr().encode("utf8"))
class NumberObject(int, PdfObject):
- NumberPattern = re.compile(b'[^+-.0-9]')
+ NumberPattern = re.compile(b"[^+-.0-9]")
- def __new__(cls, value: Any) ->'NumberObject':
+ 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__)
+ logger_warning(f"NumberObject({value}) invalid; use 0 instead", __name__)
return int.__new__(cls, 0)
- def clone(self, pdf_dest: Any, force_duplicate: bool=False,
- ignore_fields: Optional[Sequence[Union[str, int]]]=()
- ) ->'NumberObject':
+ def clone(
+ self,
+ pdf_dest: Any,
+ force_duplicate: bool = False,
+ ignore_fields: Optional[Sequence[Union[str, int]]] = (),
+ ) -> "NumberObject":
"""Clone object into pdf_dest."""
- pass
+ return cast(
+ "NumberObject",
+ self._reference_clone(NumberObject(self), pdf_dest, force_duplicate),
+ )
+
+ def as_numeric(self) -> int:
+ return int(repr(self).encode("utf8"))
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ if encryption_key is not None: # deprecated
+ deprecate_no_replacement(
+ "the encryption_key parameter of write_to_stream", "5.0.0"
+ )
+ stream.write(repr(self).encode("utf8"))
+
+ @staticmethod
+ def read_from_stream(stream: StreamType) -> Union["NumberObject", "FloatObject"]:
+ num = read_until_regex(stream, NumberObject.NumberPattern)
+ if num.find(b".") != -1:
+ return FloatObject(num)
+ return NumberObject(num)
class ByteStringObject(bytes, PdfObject):
@@ -195,19 +468,38 @@ class ByteStringObject(bytes, PdfObject):
/O) is clearly not text, but is still stored in a "String" object.
"""
- def clone(self, pdf_dest: Any, force_duplicate: bool=False,
- ignore_fields: Optional[Sequence[Union[str, int]]]=()
- ) ->'ByteStringObject':
+ def clone(
+ self,
+ pdf_dest: Any,
+ force_duplicate: bool = False,
+ ignore_fields: Optional[Sequence[Union[str, int]]] = (),
+ ) -> "ByteStringObject":
"""Clone object into pdf_dest."""
- pass
+ return cast(
+ "ByteStringObject",
+ self._reference_clone(
+ ByteStringObject(bytes(self)), pdf_dest, force_duplicate
+ ),
+ )
@property
- def original_bytes(self) ->bytes:
+ def original_bytes(self) -> bytes:
"""For compatibility with TextStringObject.original_bytes."""
- pass
+ return self
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ if encryption_key is not None: # deprecated
+ deprecate_no_replacement(
+ "the encryption_key parameter of write_to_stream", "5.0.0"
+ )
+ stream.write(b"<")
+ stream.write(binascii.hexlify(self))
+ stream.write(b">")
-class TextStringObject(str, PdfObject):
+class TextStringObject(str, PdfObject): # noqa: SLOT000
"""
A string object that has been decoded into a real unicode string.
@@ -215,20 +507,21 @@ class TextStringObject(str, PdfObject):
PDFDocEncoding, or contained a UTF-16BE BOM mark to cause UTF-16 decoding
to occur.
"""
+
autodetect_pdfdocencoding: bool
autodetect_utf16: bool
utf16_bom: bytes
- def __new__(cls, value: Any) ->'TextStringObject':
+ def __new__(cls, value: Any) -> "TextStringObject":
if isinstance(value, bytes):
- value = value.decode('charmap')
+ value = value.decode("charmap")
o = str.__new__(cls, value)
o.autodetect_utf16 = False
o.autodetect_pdfdocencoding = False
- o.utf16_bom = b''
- if value.startswith(('þÿ', 'ÿþ')):
+ o.utf16_bom = b""
+ if value.startswith(("\xfe\xff", "\xff\xfe")):
o.autodetect_utf16 = True
- o.utf16_bom = value[:2].encode('charmap')
+ o.utf16_bom = value[:2].encode("charmap")
else:
try:
encode_pdfdocencoding(o)
@@ -237,32 +530,192 @@ class TextStringObject(str, PdfObject):
o.autodetect_utf16 = True
return o
- def clone(self, pdf_dest: Any, force_duplicate: bool=False,
- ignore_fields: Optional[Sequence[Union[str, int]]]=()
- ) ->'TextStringObject':
+ def clone(
+ self,
+ pdf_dest: Any,
+ force_duplicate: bool = False,
+ ignore_fields: Optional[Sequence[Union[str, int]]] = (),
+ ) -> "TextStringObject":
"""Clone object into pdf_dest."""
- pass
+ obj = TextStringObject(self)
+ obj.autodetect_pdfdocencoding = self.autodetect_pdfdocencoding
+ obj.autodetect_utf16 = self.autodetect_utf16
+ obj.utf16_bom = self.utf16_bom
+ return cast(
+ "TextStringObject", self._reference_clone(obj, pdf_dest, force_duplicate)
+ )
@property
- def original_bytes(self) ->bytes:
+ 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.
"""
- pass
+ return self.get_original_bytes()
+
+ def get_original_bytes(self) -> bytes:
+ # We're a text string object, but the library is trying to get our raw
+ # bytes. This can happen if we auto-detected this string as text, but
+ # we were wrong. It's pretty common. Return the original bytes that
+ # would have been used to create this object, based upon the autodetect
+ # method.
+ if self.autodetect_utf16:
+ if self.utf16_bom == codecs.BOM_UTF16_LE:
+ return codecs.BOM_UTF16_LE + self.encode("utf-16le")
+ elif self.utf16_bom == codecs.BOM_UTF16_BE:
+ return codecs.BOM_UTF16_BE + self.encode("utf-16be")
+ else:
+ return self.encode("utf-16be")
+ elif self.autodetect_pdfdocencoding:
+ return encode_pdfdocencoding(self)
+ else:
+ raise Exception("no information about original bytes") # pragma: no cover
+ def get_encoded_bytes(self) -> bytes:
+ # Try to write the string out as a PDFDocEncoding encoded string. It's
+ # nicer to look at in the PDF file. Sadly, we take a performance hit
+ # here for trying...
+ try:
+ if self.autodetect_utf16:
+ raise UnicodeEncodeError("", "forced", -1, -1, "")
+ bytearr = encode_pdfdocencoding(self)
+ except UnicodeEncodeError:
+ if self.utf16_bom == codecs.BOM_UTF16_LE:
+ bytearr = codecs.BOM_UTF16_LE + self.encode("utf-16le")
+ elif self.utf16_bom == codecs.BOM_UTF16_BE:
+ bytearr = codecs.BOM_UTF16_BE + self.encode("utf-16be")
+ else:
+ bytearr = self.encode("utf-16be")
+ return bytearr
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ if encryption_key is not None: # deprecated
+ deprecate_no_replacement(
+ "the encryption_key parameter of write_to_stream", "5.0.0"
+ )
+ bytearr = self.get_encoded_bytes()
+ stream.write(b"(")
+ for c in bytearr:
+ if not chr(c).isalnum() and c != b" ":
+ # This:
+ # stream.write(rf"\{c:0>3o}".encode())
+ # gives
+ # https://github.com/davidhalter/parso/issues/207
+ stream.write(("\\%03o" % c).encode())
+ else:
+ stream.write(b_(chr(c)))
+ stream.write(b")")
+
+
+class NameObject(str, PdfObject): # noqa: SLOT000
+ delimiter_pattern = re.compile(rb"\s+|[\(\)<>\[\]{}/%]")
+ surfix = b"/"
+ renumber_table: ClassVar[Dict[str, bytes]] = {
+ "#": b"#23",
+ "(": b"#28",
+ ")": b"#29",
+ "/": b"#2F",
+ "%": b"#25",
+ **{chr(i): f"#{i:02X}".encode() for i in range(33)},
+ }
+
+ def clone(
+ self,
+ pdf_dest: Any,
+ force_duplicate: bool = False,
+ ignore_fields: Optional[Sequence[Union[str, int]]] = (),
+ ) -> "NameObject":
+ """Clone object into pdf_dest."""
+ return cast(
+ "NameObject",
+ self._reference_clone(NameObject(self), pdf_dest, force_duplicate),
+ )
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ if encryption_key is not None: # deprecated
+ deprecate_no_replacement(
+ "the encryption_key parameter of write_to_stream", "5.0.0"
+ )
+ stream.write(self.renumber())
+
+ def renumber(self) -> bytes:
+ out = self[0].encode("utf-8")
+ if out != b"/":
+ deprecate_no_replacement(
+ f"Incorrect first char in NameObject, should start with '/': ({self})",
+ "6.0.0",
+ )
+ for c in self[1:]:
+ if c > "~":
+ for x in c.encode("utf-8"):
+ out += f"#{x:02X}".encode()
+ else:
+ try:
+ out += self.renumber_table[c]
+ except KeyError:
+ out += c.encode("utf-8")
+ return out
+
+ @staticmethod
+ def unnumber(sin: bytes) -> bytes:
+ i = sin.find(b"#", 0)
+ while i >= 0:
+ try:
+ sin = sin[:i] + unhexlify(sin[i + 1 : i + 3]) + sin[i + 3 :]
+ i = sin.find(b"#", i + 1)
+ except ValueError:
+ # if the 2 characters after # can not be converted to hex
+ # we change nothing and carry on
+ i = i + 1
+ return sin
+
+ CHARSETS = ("utf-8", "gbk", "latin1")
+
+ @staticmethod
+ def read_from_stream(stream: StreamType, pdf: Any) -> "NameObject": # PdfReader
+ name = stream.read(1)
+ if name != NameObject.surfix:
+ raise PdfReadError("name read error")
+ name += read_until_regex(stream, NameObject.delimiter_pattern)
+ try:
+ # Name objects should represent irregular characters
+ # with a '#' followed by the symbol's hex number
+ name = NameObject.unnumber(name)
+ for enc in NameObject.CHARSETS:
+ try:
+ ret = name.decode(enc)
+ return NameObject(ret)
+ except Exception:
+ pass
+ raise UnicodeDecodeError("", name, 0, 0, "Code Not Found")
+ except (UnicodeEncodeError, UnicodeDecodeError) as e:
+ if not pdf.strict:
+ logger_warning(
+ f"Illegal character in NameObject ({name!r}), "
+ "you may need to adjust NameObject.CHARSETS",
+ __name__,
+ )
+ return NameObject(name.decode("charmap"))
+ else:
+ raise PdfReadError(
+ f"Illegal character in NameObject ({name!r}). "
+ "You may need to adjust NameObject.CHARSETS.",
+ ) from e
-class NameObject(str, PdfObject):
- delimiter_pattern = re.compile(b'\\s+|[\\(\\)<>\\[\\]{}/%]')
- surfix = b'/'
- renumber_table: ClassVar[Dict[str, bytes]] = {'#': b'#23', '(': b'#28',
- ')': b'#29', '/': b'#2F', '%': b'#25', **{chr(i): f'#{i:02X}'.
- encode() for i in range(33)}}
- def clone(self, pdf_dest: Any, force_duplicate: bool=False,
- ignore_fields: Optional[Sequence[Union[str, int]]]=()) ->'NameObject':
- """Clone object into pdf_dest."""
- pass
- CHARSETS = 'utf-8', 'gbk', 'latin1'
+def encode_pdfdocencoding(unicode_string: str) -> bytes:
+ retval = bytearray()
+ 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 bytes(retval)
diff --git a/pypdf/generic/_data_structures.py b/pypdf/generic/_data_structures.py
index 50631533..87d68867 100644
--- a/pypdf/generic/_data_structures.py
+++ b/pypdf/generic/_data_structures.py
@@ -1,45 +1,159 @@
-__author__ = 'Mathieu Fenniak'
-__author_email__ = 'biziqe@mathieu.fenniak.net'
+# Copyright (c) 2006, Mathieu Fenniak
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+
+__author__ = "Mathieu Fenniak"
+__author_email__ = "biziqe@mathieu.fenniak.net"
+
import logging
import re
import sys
from io import BytesIO
from math import ceil
-from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, Set, Tuple, Union, cast
+from typing import (
+ Any,
+ Callable,
+ Dict,
+ Iterable,
+ List,
+ Optional,
+ Sequence,
+ Set,
+ Tuple,
+ Union,
+ cast,
+)
+
from .._protocols import PdfReaderProtocol, PdfWriterProtocol, XmpInformationProtocol
-from .._utils import WHITESPACES, StreamType, b_, deprecate_no_replacement, deprecate_with_replacement, logger_warning, read_non_whitespace, read_until_regex, skip_over_comment
-from ..constants import CheckboxRadioButtonAttributes, FieldDictionaryAttributes, OutlineFontFlag
+from .._utils import (
+ WHITESPACES,
+ StreamType,
+ b_,
+ deprecate_no_replacement,
+ deprecate_with_replacement,
+ logger_warning,
+ read_non_whitespace,
+ read_until_regex,
+ skip_over_comment,
+)
+from ..constants import (
+ CheckboxRadioButtonAttributes,
+ FieldDictionaryAttributes,
+ OutlineFontFlag,
+)
from ..constants import FilterTypes as FT
from ..constants import StreamAttributes as SA
from ..constants import TypArguments as TA
from ..constants import TypFitArguments as TF
from ..errors import STREAM_TRUNCATED_PREMATURELY, PdfReadError, PdfStreamError
-from ._base import BooleanObject, ByteStringObject, FloatObject, IndirectObject, NameObject, NullObject, NumberObject, PdfObject, TextStringObject
+from ._base import (
+ BooleanObject,
+ ByteStringObject,
+ FloatObject,
+ IndirectObject,
+ NameObject,
+ NullObject,
+ NumberObject,
+ PdfObject,
+ TextStringObject,
+)
from ._fit import Fit
-from ._image_inline import extract_inline_A85, extract_inline_AHx, extract_inline_DCT, extract_inline_default, extract_inline_RL
+from ._image_inline import (
+ extract_inline_A85,
+ extract_inline_AHx,
+ extract_inline_DCT,
+ extract_inline_default,
+ extract_inline_RL,
+)
from ._utils import read_hex_string_from_stream, read_string_from_stream
+
if sys.version_info >= (3, 11):
from typing import Self
else:
from typing_extensions import Self
+
logger = logging.getLogger(__name__)
-NumberSigns = b'+-'
-IndirectPattern = re.compile(b'[+-]?(\\d+)\\s+(\\d+)\\s+R[^a-zA-Z]')
+NumberSigns = b"+-"
+IndirectPattern = re.compile(rb"[+-]?(\d+)\s+(\d+)\s+R[^a-zA-Z]")
class ArrayObject(List[Any], PdfObject):
-
- def clone(self, pdf_dest: PdfWriterProtocol, force_duplicate: bool=
- False, ignore_fields: Optional[Sequence[Union[str, int]]]=()
- ) ->'ArrayObject':
+ def clone(
+ self,
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool = False,
+ ignore_fields: Optional[Sequence[Union[str, int]]] = (),
+ ) -> "ArrayObject":
"""Clone object into pdf_dest."""
- pass
+ try:
+ if self.indirect_reference.pdf == pdf_dest and not force_duplicate: # type: ignore
+ return self
+ except Exception:
+ pass
+ arr = cast(
+ "ArrayObject",
+ self._reference_clone(ArrayObject(), pdf_dest, force_duplicate),
+ )
+ for data in self:
+ if isinstance(data, StreamObject):
+ dup = data._reference_clone(
+ data.clone(pdf_dest, force_duplicate, ignore_fields),
+ pdf_dest,
+ force_duplicate,
+ )
+ arr.append(dup.indirect_reference)
+ elif hasattr(data, "clone"):
+ arr.append(data.clone(pdf_dest, force_duplicate, ignore_fields))
+ else:
+ arr.append(data)
+ return arr
- def items(self) ->Iterable[Any]:
+ def items(self) -> Iterable[Any]:
"""Emulate DictionaryObject.items for a list (index, object)."""
- pass
+ return enumerate(self)
- def __add__(self, lst: Any) ->'ArrayObject':
+ def _to_lst(self, lst: Any) -> List[Any]:
+ # Convert to list, internal
+ if isinstance(lst, (list, tuple, set)):
+ pass
+ elif isinstance(lst, PdfObject):
+ lst = [lst]
+ elif isinstance(lst, str):
+ if lst[0] == "/":
+ lst = [NameObject(lst)]
+ else:
+ lst = [TextStringObject(lst)]
+ elif isinstance(lst, bytes):
+ lst = [ByteStringObject(lst)]
+ else: # for numbers,...
+ lst = [lst]
+ return lst
+
+ def __add__(self, lst: Any) -> "ArrayObject":
"""
Allow extension by adding list or add one element only
@@ -57,7 +171,7 @@ class ArrayObject(List[Any], PdfObject):
temp.extend(self._to_lst(lst))
return temp
- def __iadd__(self, lst: Any) ->Self:
+ def __iadd__(self, lst: Any) -> Self:
"""
Allow extension by adding list or add one element only
@@ -71,7 +185,7 @@ class ArrayObject(List[Any], PdfObject):
self.extend(self._to_lst(lst))
return self
- def __isub__(self, lst: Any) ->Self:
+ def __isub__(self, lst: Any) -> Self:
"""Allow to remove items"""
for x in self._to_lst(lst):
try:
@@ -81,18 +195,78 @@ class ArrayObject(List[Any], PdfObject):
pass
return self
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ if encryption_key is not None: # deprecated
+ deprecate_no_replacement(
+ "the encryption_key parameter of write_to_stream", "5.0.0"
+ )
+ stream.write(b"[")
+ for data in self:
+ stream.write(b" ")
+ data.write_to_stream(stream)
+ stream.write(b" ]")
+
+ @staticmethod
+ def read_from_stream(
+ stream: StreamType,
+ pdf: Optional[PdfReaderProtocol],
+ forced_encoding: Union[None, str, List[str], Dict[int, str]] = None,
+ ) -> "ArrayObject":
+ arr = ArrayObject()
+ tmp = stream.read(1)
+ if tmp != b"[":
+ raise PdfReadError("Could not read array")
+ while True:
+ # skip leading whitespace
+ tok = stream.read(1)
+ while tok.isspace():
+ tok = stream.read(1)
+ stream.seek(-1, 1)
+ # check for array ending
+ peek_ahead = stream.read(1)
+ if peek_ahead == b"]":
+ break
+ stream.seek(-1, 1)
+ # read and append obj
+ arr.append(read_object(stream, pdf, forced_encoding))
+ return arr
-class DictionaryObject(Dict[Any, Any], PdfObject):
- def clone(self, pdf_dest: PdfWriterProtocol, force_duplicate: bool=
- False, ignore_fields: Optional[Sequence[Union[str, int]]]=()
- ) ->'DictionaryObject':
+class DictionaryObject(Dict[Any, Any], PdfObject):
+ def clone(
+ self,
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool = False,
+ ignore_fields: Optional[Sequence[Union[str, int]]] = (),
+ ) -> "DictionaryObject":
"""Clone object into pdf_dest."""
- pass
+ try:
+ if self.indirect_reference.pdf == pdf_dest and not force_duplicate: # type: ignore
+ return self
+ except Exception:
+ pass
- def _clone(self, src: 'DictionaryObject', pdf_dest: PdfWriterProtocol,
- force_duplicate: bool, ignore_fields: Optional[Sequence[Union[str,
- int]]], visited: Set[Tuple[int, int]]) ->None:
+ visited: Set[Tuple[int, int]] = set() # (idnum, generation)
+ d__ = cast(
+ "DictionaryObject",
+ self._reference_clone(self.__class__(), pdf_dest, force_duplicate),
+ )
+ if ignore_fields is None:
+ ignore_fields = []
+ if len(d__.keys()) == 0:
+ d__._clone(self, pdf_dest, force_duplicate, ignore_fields, visited)
+ return d__
+
+ def _clone(
+ self,
+ src: "DictionaryObject",
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool,
+ ignore_fields: Optional[Sequence[Union[str, int]]],
+ visited: Set[Tuple[int, int]], # (idnum, generation)
+ ) -> None:
"""
Update the object from src.
@@ -102,9 +276,106 @@ class DictionaryObject(Dict[Any, Any], PdfObject):
force_duplicate:
ignore_fields:
"""
- pass
-
- def get_inherited(self, key: str, default: Any=None) ->Any:
+ # first we remove for the ignore_fields
+ # that are for a limited number of levels
+ x = 0
+ assert ignore_fields is not None
+ ignore_fields = list(ignore_fields)
+ while x < len(ignore_fields):
+ if isinstance(ignore_fields[x], int):
+ if cast(int, ignore_fields[x]) <= 0:
+ del ignore_fields[x]
+ del ignore_fields[x]
+ continue
+ else:
+ ignore_fields[x] -= 1 # type:ignore
+ x += 1
+ # First check if this is a chain list, we need to loop to prevent recur
+ if any(
+ field not in ignore_fields
+ and field in src
+ and isinstance(src.raw_get(field), IndirectObject)
+ and isinstance(src[field], DictionaryObject)
+ and (
+ src.get("/Type", None) is None
+ or cast(DictionaryObject, src[field]).get("/Type", None) is None
+ or src.get("/Type", None)
+ == cast(DictionaryObject, src[field]).get("/Type", None)
+ )
+ for field in ["/Next", "/Prev", "/N", "/V"]
+ ):
+ ignore_fields = list(ignore_fields)
+ for lst in (("/Next", "/Prev"), ("/N", "/V")):
+ for k in lst:
+ objs = []
+ if (
+ k in src
+ and k not in self
+ and isinstance(src.raw_get(k), IndirectObject)
+ and isinstance(src[k], DictionaryObject)
+ # IF need to go further the idea is to check
+ # that the types are the same:
+ and (
+ src.get("/Type", None) is None
+ or cast(DictionaryObject, src[k]).get("/Type", None) is None
+ or src.get("/Type", None)
+ == cast(DictionaryObject, src[k]).get("/Type", None)
+ )
+ ):
+ cur_obj: Optional[DictionaryObject] = cast(
+ "DictionaryObject", src[k]
+ )
+ prev_obj: Optional[DictionaryObject] = self
+ while cur_obj is not None:
+ clon = cast(
+ "DictionaryObject",
+ cur_obj._reference_clone(
+ cur_obj.__class__(), pdf_dest, force_duplicate
+ ),
+ )
+ # check to see if we've previously processed our item
+ if clon.indirect_reference is not None:
+ idnum = clon.indirect_reference.idnum
+ generation = clon.indirect_reference.generation
+ if (idnum, generation) in visited:
+ cur_obj = None
+ break
+ visited.add((idnum, generation))
+ objs.append((cur_obj, clon))
+ assert prev_obj is not None
+ prev_obj[NameObject(k)] = clon.indirect_reference
+ prev_obj = clon
+ try:
+ if cur_obj == src:
+ cur_obj = None
+ else:
+ cur_obj = cast("DictionaryObject", cur_obj[k])
+ except Exception:
+ cur_obj = None
+ for s, c in objs:
+ c._clone(
+ s, pdf_dest, force_duplicate, ignore_fields, visited
+ )
+
+ for k, v in src.items():
+ if k not in ignore_fields:
+ if isinstance(v, StreamObject):
+ if not hasattr(v, "indirect_reference"):
+ v.indirect_reference = None
+ vv = v.clone(pdf_dest, force_duplicate, ignore_fields)
+ assert vv.indirect_reference is not None
+ self[k.clone(pdf_dest)] = vv.indirect_reference # type: ignore[attr-defined]
+ elif k not in self:
+ self[NameObject(k)] = (
+ v.clone(pdf_dest, force_duplicate, ignore_fields)
+ if hasattr(v, "clone")
+ else v
+ )
+
+ def raw_get(self, key: Any) -> Any:
+ return dict.__getitem__(self, key)
+
+ def get_inherited(self, key: str, default: Any = None) -> Any:
"""
Returns the value of a key or from the parent if not found.
If not found returns default.
@@ -117,20 +388,36 @@ class DictionaryObject(Dict[Any, Any], PdfObject):
Returns:
Current key or inherited one, otherwise default value.
"""
- pass
-
- def __setitem__(self, key: Any, value: Any) ->Any:
+ if key in self:
+ return self[key]
+ try:
+ if "/Parent" not in self:
+ return default
+ raise KeyError("not present")
+ except KeyError:
+ return cast("DictionaryObject", self["/Parent"].get_object()).get_inherited(
+ key, default
+ )
+
+ def __setitem__(self, key: Any, value: Any) -> Any:
if not isinstance(key, PdfObject):
- raise ValueError('key must be PdfObject')
+ raise ValueError("key must be PdfObject")
if not isinstance(value, PdfObject):
- raise ValueError('value must be PdfObject')
+ raise ValueError("value must be PdfObject")
return dict.__setitem__(self, key, value)
- def __getitem__(self, key: Any) ->PdfObject:
+ 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[XmpInformationProtocol]:
+ def xmp_metadata(self) -> Optional[XmpInformationProtocol]:
"""
Retrieve XMP (Extensible Metadata Platform) data relevant to the this
object, if available.
@@ -142,21 +429,302 @@ class DictionaryObject(Dict[Any, Any], PdfObject):
that can be used to access XMP metadata from the document. Can also
return None if no metadata was found on the document root.
"""
- pass
+ 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 write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ if encryption_key is not None: # deprecated
+ deprecate_no_replacement(
+ "the encryption_key parameter of write_to_stream", "5.0.0"
+ )
+ stream.write(b"<<\n")
+ for key, value in list(self.items()):
+ if len(key) > 2 and key[1] == "%" and key[-1] == "%":
+ continue
+ key.write_to_stream(stream, encryption_key)
+ stream.write(b" ")
+ value.write_to_stream(stream)
+ stream.write(b"\n")
+ stream.write(b">>")
+
+ @staticmethod
+ def read_from_stream(
+ stream: StreamType,
+ pdf: Optional[PdfReaderProtocol],
+ forced_encoding: Union[None, str, List[str], Dict[int, str]] = None,
+ ) -> "DictionaryObject":
+ def get_next_obj_pos(
+ p: int, p1: int, rem_gens: List[int], pdf: PdfReaderProtocol
+ ) -> int:
+ out = p1
+ for gen in rem_gens:
+ loc = pdf.xref[gen]
+ try:
+ out = min(out, min([x for x in loc.values() if p < x <= p1]))
+ except ValueError:
+ pass
+ return out
+
+ def read_unsized_from_stream(
+ stream: StreamType, pdf: PdfReaderProtocol
+ ) -> bytes:
+ # we are just pointing at beginning of the stream
+ eon = get_next_obj_pos(stream.tell(), 2**32, list(pdf.xref), pdf) - 1
+ curr = stream.tell()
+ rw = stream.read(eon - stream.tell())
+ p = rw.find(b"endstream")
+ if p < 0:
+ raise PdfReadError(
+ f"Unable to find 'endstream' marker for obj starting at {curr}."
+ )
+ stream.seek(curr + p + 9)
+ return rw[: p - 1]
+
+ tmp = stream.read(2)
+ if tmp != b"<<":
+ raise PdfReadError(
+ f"Dictionary read error at byte {hex(stream.tell())}: "
+ "stream must begin with '<<'"
+ )
+ data: Dict[Any, Any] = {}
+ while True:
+ tok = read_non_whitespace(stream)
+ if tok == b"\x00":
+ continue
+ 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(stream.tell())} for key {key}"
+ )
+ if pdf is not None and pdf.strict:
+ raise PdfReadError(msg)
+ logger_warning(msg, __name__)
+
+ pos = stream.tell()
+ s = read_non_whitespace(stream)
+ if s == b"s" and stream.read(5) == b"tream":
+ eol = stream.read(1)
+ # odd PDF file output has spaces after 'stream' keyword but before EOL.
+ # patch provided by Danial Sandler
+ while eol == b" ":
+ eol = stream.read(1)
+ if eol not in (b"\n", b"\r"):
+ raise PdfStreamError("Stream data must be followed by a newline")
+ if eol == b"\r" and stream.read(1) != b"\n":
+ stream.seek(-1, 1)
+ # this is a stream object, not a dictionary
+ if SA.LENGTH not in data:
+ if pdf is not None and pdf.strict:
+ raise PdfStreamError("Stream length not defined")
+ else:
+ logger_warning(
+ f"Stream length not defined @pos={stream.tell()}", __name__
+ )
+ data[NameObject(SA.LENGTH)] = NumberObject(-1)
+ length = data[SA.LENGTH]
+ if isinstance(length, IndirectObject):
+ t = stream.tell()
+ assert pdf is not None # hint for mypy
+ length = pdf.get_object(length)
+ stream.seek(t, 0)
+ if length is None: # if the PDF is damaged
+ length = -1
+ pstart = stream.tell()
+ if length > 0:
+ data["__streamdata__"] = stream.read(length)
+ else:
+ data["__streamdata__"] = read_until_regex(
+ stream, re.compile(b"endstream")
+ )
+ e = read_non_whitespace(stream)
+ ndstream = stream.read(8)
+ if (e + ndstream) != b"endstream":
+ # (sigh) - the odd PDF file has a length that is too long, so
+ # we need to read backwards to find the "endstream" ending.
+ # ReportLab (unknown version) generates files with this bug,
+ # and Python users into PDF files tend to be our audience.
+ # we need to do this to correct the streamdata and chop off
+ # an extra character.
+ pos = stream.tell()
+ stream.seek(-10, 1)
+ end = stream.read(9)
+ if end == b"endstream":
+ # we found it by looking back one character further.
+ data["__streamdata__"] = data["__streamdata__"][:-1]
+ elif pdf is not None and not pdf.strict:
+ stream.seek(pstart, 0)
+ data["__streamdata__"] = read_unsized_from_stream(stream, pdf)
+ pos = stream.tell()
+ else:
+ stream.seek(pos, 0)
+ raise PdfReadError(
+ "Unable to find 'endstream' marker after stream at byte "
+ f"{hex(stream.tell())} (nd='{ndstream!r}', end='{end!r}')."
+ )
+ else:
+ stream.seek(pos, 0)
+ if "__streamdata__" in data:
+ return StreamObject.initialize_from_dictionary(data)
+ else:
+ retval = DictionaryObject()
+ retval.update(data)
+ return retval
class TreeObject(DictionaryObject):
-
- def __init__(self, dct: Optional[DictionaryObject]=None) ->None:
+ def __init__(self, dct: Optional[DictionaryObject] = None) -> None:
DictionaryObject.__init__(self)
if dct:
self.update(dct)
- def __iter__(self) ->Any:
+ def hasChildren(self) -> bool: # deprecated
+ 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 _remove_node_from_tree(self, prev: Any, prev_ref: Any, cur: Any,
- last: Any) ->None:
+ 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 add_child(self, child: Any, pdf: PdfWriterProtocol) -> None:
+ self.insert_child(child, None, pdf)
+
+ def inc_parent_counter_default(
+ self, parent: Union[None, IndirectObject, "TreeObject"], n: int
+ ) -> None:
+ if parent is None:
+ return
+ parent = cast("TreeObject", parent.get_object())
+ if "/Count" in parent:
+ parent[NameObject("/Count")] = NumberObject(
+ max(0, cast(int, parent[NameObject("/Count")]) + n)
+ )
+ self.inc_parent_counter_default(parent.get("/Parent", None), n)
+
+ def inc_parent_counter_outline(
+ self, parent: Union[None, IndirectObject, "TreeObject"], n: int
+ ) -> None:
+ if parent is None:
+ return
+ parent = cast("TreeObject", parent.get_object())
+ # BooleanObject requires comparison with == not is
+ opn = parent.get("/%is_open%", True) == True # noqa
+ c = cast(int, parent.get("/Count", 0))
+ if c < 0:
+ c = abs(c)
+ parent[NameObject("/Count")] = NumberObject((c + n) * (1 if opn else -1))
+ if not opn:
+ return
+ self.inc_parent_counter_outline(parent.get("/Parent", None), n)
+
+ def insert_child(
+ self,
+ child: Any,
+ before: Any,
+ pdf: PdfWriterProtocol,
+ inc_parent_counter: Optional[Callable[..., Any]] = None,
+ ) -> IndirectObject:
+ if inc_parent_counter is None:
+ inc_parent_counter = self.inc_parent_counter_default
+ child_obj = child.get_object()
+ child = child.indirect_reference # get_reference(child_obj)
+
+ prev: Optional[DictionaryObject]
+ if "/First" not in self: # no child yet
+ self[NameObject("/First")] = child
+ self[NameObject("/Count")] = NumberObject(0)
+ self[NameObject("/Last")] = child
+ child_obj[NameObject("/Parent")] = self.indirect_reference
+ inc_parent_counter(self, child_obj.get("/Count", 1))
+ if "/Next" in child_obj:
+ del child_obj["/Next"]
+ if "/Prev" in child_obj:
+ del child_obj["/Prev"]
+ return child
+ else:
+ prev = cast("DictionaryObject", self["/Last"])
+
+ while prev.indirect_reference != before:
+ if "/Next" in prev:
+ prev = cast("TreeObject", prev["/Next"])
+ else: # append at the end
+ prev[NameObject("/Next")] = cast("TreeObject", child)
+ child_obj[NameObject("/Prev")] = prev.indirect_reference
+ child_obj[NameObject("/Parent")] = self.indirect_reference
+ if "/Next" in child_obj:
+ del child_obj["/Next"]
+ self[NameObject("/Last")] = child
+ inc_parent_counter(self, child_obj.get("/Count", 1))
+ return child
+ try: # insert as first or in the middle
+ assert isinstance(prev["/Prev"], DictionaryObject)
+ prev["/Prev"][NameObject("/Next")] = child
+ child_obj[NameObject("/Prev")] = prev["/Prev"]
+ except Exception: # it means we are inserting in first position
+ del child_obj["/Next"]
+ child_obj[NameObject("/Next")] = prev
+ prev[NameObject("/Prev")] = child
+ child_obj[NameObject("/Parent")] = self.indirect_reference
+ inc_parent_counter(self, child_obj.get("/Count", 1))
+ return child
+
+ def _remove_node_from_tree(
+ self, prev: Any, prev_ref: Any, cur: Any, last: Any
+ ) -> None:
"""
Adjust the pointers of the linked list and tree node count.
@@ -166,14 +734,98 @@ class TreeObject(DictionaryObject):
cur:
last:
"""
- pass
+ 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
+ )
- def remove_from_tree(self) ->None:
+ else:
+ # Removing only tree node
+ self[NameObject("/Count")] = NumberObject(0)
+ del self[NameObject("/First")]
+ if NameObject("/Last") in self:
+ del self[NameObject("/Last")]
+ else:
+ if next_ref:
+ # Removing middle tree node
+ next_obj = next_ref.get_object()
+ next_obj[NameObject("/Prev")] = prev_ref
+ prev[NameObject("/Next")] = next_ref
+ else:
+ # Removing last tree node
+ assert cur == last
+ del prev[NameObject("/Next")]
+ self[NameObject("/Last")] = prev_ref
+ self[NameObject("/Count")] = NumberObject(self[NameObject("/Count")] - 1) # type: ignore
+
+ def remove_child(self, child: Any) -> None:
+ child_obj = child.get_object()
+ child = child_obj.indirect_reference
+
+ if NameObject("/Parent") not in child_obj:
+ raise ValueError("Removed child does not appear to be a tree item")
+ elif child_obj[NameObject("/Parent")] != self:
+ raise ValueError("Removed child is not a member of this tree")
+
+ found = False
+ prev_ref = None
+ prev = None
+ cur_ref: Optional[Any] = self[NameObject("/First")]
+ cur: Optional[Dict[str, Any]] = cur_ref.get_object() # type: ignore
+ last_ref = self[NameObject("/Last")]
+ last = last_ref.get_object()
+ while cur is not None:
+ if cur == child_obj:
+ self._remove_node_from_tree(prev, prev_ref, cur, last)
+ found = True
+ break
+
+ # Go to the next node
+ prev_ref = cur_ref
+ prev = cur
+ if NameObject("/Next") in cur:
+ cur_ref = cur[NameObject("/Next")]
+ cur = cur_ref.get_object()
+ else:
+ cur_ref = None
+ cur = None
+
+ if not found:
+ raise ValueError("Removal couldn't find item in tree")
+
+ _reset_node_tree_relationship(child_obj)
+
+ def remove_from_tree(self) -> None:
"""Remove the object from the tree it is in."""
- pass
+ 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: # deprecated
+ 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)
-def _reset_node_tree_relationship(child_obj: Any) ->None:
+ 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.
@@ -182,18 +834,26 @@ def _reset_node_tree_relationship(child_obj: Any) ->None:
Args:
child_obj:
"""
- pass
+ 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: Union[bytes, str] = b''
+ def __init__(self) -> None:
+ self._data: Union[bytes, str] = b""
self.decoded_self: Optional[DecodedStreamObject] = None
- def _clone(self, src: DictionaryObject, pdf_dest: PdfWriterProtocol,
- force_duplicate: bool, ignore_fields: Optional[Sequence[Union[str,
- int]]], visited: Set[Tuple[int, int]]) ->None:
+ def _clone(
+ self,
+ src: DictionaryObject,
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool,
+ ignore_fields: Optional[Sequence[Union[str, int]]],
+ visited: Set[Tuple[int, int]],
+ ) -> None:
"""
Update the object from src.
@@ -203,9 +863,102 @@ class StreamObject(DictionaryObject):
force_duplicate:
ignore_fields:
"""
- pass
-
- def decode_as_image(self) ->Any:
+ self._data = cast("StreamObject", src)._data
+ try:
+ decoded_self = cast("StreamObject", src).decoded_self
+ if decoded_self is None:
+ self.decoded_self = None
+ else:
+ self.decoded_self = cast(
+ "DecodedStreamObject",
+ decoded_self.clone(pdf_dest, force_duplicate, ignore_fields),
+ )
+ except Exception:
+ pass
+ super()._clone(src, pdf_dest, force_duplicate, ignore_fields, visited)
+
+ def get_data(self) -> Union[bytes, str]:
+ return self._data
+
+ def set_data(self, data: bytes) -> None:
+ self._data = data
+
+ def hash_value_data(self) -> bytes:
+ data = super().hash_value_data()
+ data += b_(self._data)
+ return data
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ if encryption_key is not None: # deprecated
+ deprecate_no_replacement(
+ "the encryption_key parameter of write_to_stream", "5.0.0"
+ )
+ self[NameObject(SA.LENGTH)] = NumberObject(len(self._data))
+ DictionaryObject.write_to_stream(self, stream)
+ del self[SA.LENGTH]
+ stream.write(b"\nstream\n")
+ stream.write(self._data)
+ stream.write(b"\nendstream")
+
+ @staticmethod
+ def initializeFromDictionary(
+ data: Dict[str, Any]
+ ) -> Union["EncodedStreamObject", "DecodedStreamObject"]:
+ deprecate_with_replacement(
+ "initializeFromDictionary", "initialize_from_dictionary", "5.0.0"
+ ) # pragma: no cover
+ return StreamObject.initialize_from_dictionary(data) # pragma: no cover
+
+ @staticmethod
+ def initialize_from_dictionary(
+ data: Dict[str, Any]
+ ) -> Union["EncodedStreamObject", "DecodedStreamObject"]:
+ retval: Union[EncodedStreamObject, DecodedStreamObject]
+ if SA.FILTER in data:
+ retval = EncodedStreamObject()
+ else:
+ retval = DecodedStreamObject()
+ retval._data = data["__streamdata__"]
+ del data["__streamdata__"]
+ del data[SA.LENGTH]
+ retval.update(data)
+ return retval
+
+ def flate_encode(self, level: int = -1) -> "EncodedStreamObject":
+ from ..filters import FlateDecode
+
+ if SA.FILTER in self:
+ f = self[SA.FILTER]
+ if isinstance(f, ArrayObject):
+ f = ArrayObject([NameObject(FT.FLATE_DECODE), *f])
+ try:
+ params = ArrayObject(
+ [NullObject(), *self.get(SA.DECODE_PARMS, ArrayObject())]
+ )
+ except TypeError:
+ # case of error where the * operator is not working (not an array
+ params = ArrayObject(
+ [NullObject(), self.get(SA.DECODE_PARMS, ArrayObject())]
+ )
+ else:
+ f = ArrayObject([NameObject(FT.FLATE_DECODE), f])
+ params = ArrayObject(
+ [NullObject(), self.get(SA.DECODE_PARMS, NullObject())]
+ )
+ else:
+ f = NameObject(FT.FLATE_DECODE)
+ params = None
+ retval = EncodedStreamObject()
+ retval.update(self)
+ retval[NameObject(SA.FILTER)] = f
+ if params is not None:
+ retval[NameObject(SA.DECODE_PARMS)] = params
+ retval._data = FlateDecode.encode(b_(self._data), level)
+ return retval
+
+ def decode_as_image(self) -> Any:
"""
Try to decode the stream object as an image
@@ -217,7 +970,18 @@ class StreamObject(DictionaryObject):
It is recommended to catch exceptions to prevent
stops in your program.
"""
- pass
+ from ..filters import _xobj_to_image
+
+ if self.get("/Subtype", "") != "/Image":
+ try:
+ msg = f"{self.indirect_reference} does not seem to be an Image" # pragma: no cover
+ except AttributeError:
+ msg = f"{self.__repr__()} object does not seem to be an Image" # pragma: no cover
+ logger_warning(msg, __name__)
+ extension, byte_stream, img = _xobj_to_image(self)
+ if extension is None:
+ return None # pragma: no cover
+ return img
class DecodedStreamObject(StreamObject):
@@ -225,10 +989,42 @@ class DecodedStreamObject(StreamObject):
class EncodedStreamObject(StreamObject):
-
- def __init__(self) ->None:
+ def __init__(self) -> None:
self.decoded_self: Optional[DecodedStreamObject] = None
+ # This overrides the parent method:
+ def get_data(self) -> Union[bytes, str]:
+ from ..filters import decode_stream_data
+
+ if self.decoded_self is not None:
+ # cached version of decoded object
+ return self.decoded_self.get_data()
+ else:
+ # create decoded object
+ decoded = DecodedStreamObject()
+
+ decoded.set_data(b_(decode_stream_data(self)))
+ for key, value in list(self.items()):
+ if key not in (SA.LENGTH, SA.FILTER, SA.DECODE_PARMS):
+ decoded[key] = value
+ self.decoded_self = decoded
+ return decoded.get_data()
+
+ # This overrides the parent method:
+ def set_data(self, data: bytes) -> None: # deprecated
+ from ..filters import FlateDecode
+
+ if self.get(SA.FILTER, "") == FT.FLATE_DECODE:
+ if not isinstance(data, bytes):
+ raise TypeError("data must be bytes")
+ assert self.decoded_self is not None
+ self.decoded_self.set_data(data)
+ super().set_data(FlateDecode.encode(data))
+ else:
+ raise PdfReadError(
+ "Streams encoded with different filter from only FlateDecode is not supported"
+ )
+
class ContentStream(DecodedStreamObject):
"""
@@ -251,20 +1047,31 @@ class ContentStream(DecodedStreamObject):
* when .operations is set, ._data is set to None.
"""
- def __init__(self, stream: Any, pdf: Any, forced_encoding: Union[None,
- str, List[str], Dict[int, str]]=None) ->None:
+ def __init__(
+ self,
+ stream: Any,
+ pdf: Any,
+ forced_encoding: Union[None, str, List[str], Dict[int, str]] = None,
+ ) -> None:
self.pdf = pdf
+
+ # The inner list has two elements:
+ # Element 0: List
+ # Element 1: str
self._operations: List[Tuple[Any, Any]] = []
+
+ # stream may be a StreamObject or an ArrayObject containing
+ # multiple StreamObjects to be cat'd together.
if stream is None:
- super().set_data(b'')
+ super().set_data(b"")
else:
stream = stream.get_object()
if isinstance(stream, ArrayObject):
- data = b''
+ 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'
+ if len(data) == 0 or data[-1] != b"\n":
+ data += b"\n"
super().set_data(bytes(data))
else:
stream_data = stream.get_data()
@@ -272,9 +1079,12 @@ class ContentStream(DecodedStreamObject):
super().set_data(b_(stream_data))
self.forced_encoding = forced_encoding
- def clone(self, pdf_dest: Any, force_duplicate: bool=False,
- ignore_fields: Optional[Sequence[Union[str, int]]]=()
- ) ->'ContentStream':
+ def clone(
+ self,
+ pdf_dest: Any,
+ force_duplicate: bool = False,
+ ignore_fields: Optional[Sequence[Union[str, int]]] = (),
+ ) -> "ContentStream":
"""
Clone object into pdf_dest.
@@ -286,11 +1096,32 @@ class ContentStream(DecodedStreamObject):
Returns:
The cloned ContentStream
"""
- pass
+ try:
+ if self.indirect_reference.pdf == pdf_dest and not force_duplicate: # type: ignore
+ return self
+ except Exception:
+ pass
- def _clone(self, src: DictionaryObject, pdf_dest: PdfWriterProtocol,
- force_duplicate: bool, ignore_fields: Optional[Sequence[Union[str,
- int]]], visited: Set[Tuple[int, int]]) ->None:
+ visited: Set[Tuple[int, int]] = set()
+ d__ = cast(
+ "ContentStream",
+ self._reference_clone(
+ self.__class__(None, None), pdf_dest, force_duplicate
+ ),
+ )
+ if ignore_fields is None:
+ ignore_fields = []
+ d__._clone(self, pdf_dest, force_duplicate, ignore_fields, visited)
+ return d__
+
+ def _clone(
+ self,
+ src: DictionaryObject,
+ pdf_dest: PdfWriterProtocol,
+ force_duplicate: bool,
+ ignore_fields: Optional[Sequence[Union[str, int]]],
+ visited: Set[Tuple[int, int]],
+ ) -> None:
"""
Update the object from src.
@@ -300,7 +1131,215 @@ class ContentStream(DecodedStreamObject):
force_duplicate:
ignore_fields:
"""
- pass
+ src_cs = cast("ContentStream", src)
+ super().set_data(b_(src_cs._data))
+ self.pdf = pdf_dest
+ self._operations = list(src_cs._operations)
+ self.forced_encoding = src_cs.forced_encoding
+ # no need to call DictionaryObjection or anything
+ # like super(DictionaryObject,self)._clone(src, pdf_dest, force_duplicate, ignore_fields, visited)
+
+ def _parse_content_stream(self, stream: StreamType) -> None:
+ # 7.8.2 Content Streams
+ stream.seek(0, 0)
+ operands: List[Union[int, str, PdfObject]] = []
+ while True:
+ peek = read_non_whitespace(stream)
+ if peek == 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)
+ if operator == b"BI":
+ # begin inline image - a completely different parsing
+ # mechanism is required, of course... thanks buddy...
+ assert operands == []
+ ii = self._read_inline_image(stream)
+ self._operations.append((ii, b"INLINE IMAGE"))
+ else:
+ self._operations.append((operands, operator))
+ operands = []
+ elif peek == b"%":
+ # If we encounter a comment in the content stream, we have to
+ # handle it here. Typically, read_object will handle
+ # encountering a comment -- but read_object assumes that
+ # following the comment must be the object we're trying to
+ # read. In this case, it could be an operator instead.
+ while peek not in (b"\r", b"\n", b""):
+ peek = stream.read(1)
+ else:
+ operands.append(read_object(stream, None, self.forced_encoding))
+
+ def _read_inline_image(self, stream: StreamType) -> Dict[str, Any]:
+ # begin reading just after the "BI" - begin image
+ # first read the dictionary of settings.
+ settings = DictionaryObject()
+ while True:
+ tok = read_non_whitespace(stream)
+ stream.seek(-1, 1)
+ if tok == b"I":
+ # "ID" - begin of image data
+ break
+ key = read_object(stream, self.pdf)
+ tok = read_non_whitespace(stream)
+ stream.seek(-1, 1)
+ value = read_object(stream, self.pdf)
+ settings[key] = value
+ # left at beginning of ID
+ tmp = stream.read(3)
+ assert tmp[:2] == b"ID"
+ filtr = settings.get("/F", settings.get("/Filter", "not set"))
+ savpos = stream.tell()
+ if isinstance(filtr, list):
+ filtr = filtr[0] # used forencoding
+ if "AHx" in filtr or "ASCIIHexDecode" in filtr:
+ data = extract_inline_AHx(stream)
+ elif "A85" in filtr or "ASCII85Decode" in filtr:
+ data = extract_inline_A85(stream)
+ elif "RL" in filtr or "RunLengthDecode" in filtr:
+ data = extract_inline_RL(stream)
+ elif "DCT" in filtr or "DCTDecode" in filtr:
+ data = extract_inline_DCT(stream)
+ elif filtr == "not set":
+ cs = settings.get("/CS", "")
+ if "RGB" in cs:
+ lcs = 3
+ elif "CMYK" in cs:
+ lcs = 4
+ else:
+ bits = settings.get(
+ "/BPC",
+ 8 if cs in {"/I", "/G", "/Indexed", "/DeviceGray"} else -1,
+ )
+ if bits > 0:
+ lcs = bits / 8.0
+ else:
+ data = extract_inline_default(stream)
+ lcs = -1
+ if lcs > 0:
+ data = stream.read(
+ ceil(cast(int, settings["/W"]) * lcs) * cast(int, settings["/H"])
+ )
+ ei = read_non_whitespace(stream)
+ stream.seek(-1, 1)
+ else:
+ data = extract_inline_default(stream)
+
+ ei = stream.read(3)
+ stream.seek(-1, 1)
+ if ei[0:2] != b"EI" or ei[2:3] not in WHITESPACES:
+ stream.seek(savpos, 0)
+ data = extract_inline_default(stream)
+ return {"settings": settings, "data": data}
+
+ # This overrides the parent method:
+ def get_data(self) -> bytes:
+ if not self._data:
+ new_data = BytesIO()
+ for operands, operator in self._operations:
+ if operator == b"INLINE IMAGE":
+ new_data.write(b"BI")
+ dict_text = BytesIO()
+ operands["settings"].write_to_stream(dict_text)
+ new_data.write(dict_text.getvalue()[2:-2])
+ new_data.write(b"ID ")
+ new_data.write(operands["data"])
+ new_data.write(b"EI")
+ else:
+ for op in operands:
+ op.write_to_stream(new_data)
+ new_data.write(b" ")
+ new_data.write(b_(operator))
+ new_data.write(b"\n")
+ self._data = new_data.getvalue()
+ return b_(self._data)
+
+ # This overrides the parent method:
+ def set_data(self, data: bytes) -> None:
+ super().set_data(data)
+ self._operations = []
+
+ @property
+ def operations(self) -> List[Tuple[Any, Any]]:
+ if not self._operations and self._data:
+ self._parse_content_stream(BytesIO(b_(self._data)))
+ self._data = b""
+ return self._operations
+
+ @operations.setter
+ def operations(self, operations: List[Tuple[Any, Any]]) -> None:
+ self._operations = operations
+ self._data = b""
+
+ def isolate_graphics_state(self) -> None:
+ if self._operations:
+ self._operations.insert(0, ([], "q"))
+ self._operations.append(([], "Q"))
+ elif self._data:
+ self._data = b"q\n" + b_(self._data) + b"\nQ\n"
+
+ # This overrides the parent method:
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ if not self._data and self._operations:
+ self.get_data() # this ensures ._data is rebuilt
+ super().write_to_stream(stream, encryption_key)
+
+
+def read_object(
+ stream: StreamType,
+ pdf: Optional[PdfReaderProtocol],
+ forced_encoding: Union[None, str, List[str], Dict[int, str]] = None,
+) -> Union[PdfObject, int, str, ContentStream]:
+ tok = stream.read(1)
+ stream.seek(-1, 1) # reset to start
+ if tok == b"/":
+ return NameObject.read_from_stream(stream, pdf)
+ elif tok == b"<":
+ # hexadecimal string OR dictionary
+ peek = stream.read(2)
+ stream.seek(-2, 1) # reset to start
+ if peek == b"<<":
+ return DictionaryObject.read_from_stream(stream, pdf, forced_encoding)
+ else:
+ return read_hex_string_from_stream(stream, forced_encoding)
+ elif tok == b"[":
+ return ArrayObject.read_from_stream(stream, pdf, forced_encoding)
+ elif tok == 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:
+ assert pdf is not None # hint for mypy
+ 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):
@@ -311,92 +1350,95 @@ class Field(TreeObject):
:meth:`get_fields()<pypdf.PdfReader.get_fields>`
"""
- def __init__(self, data: DictionaryObject) ->None:
+ def __init__(self, data: DictionaryObject) -> None:
DictionaryObject.__init__(self)
- field_attributes = FieldDictionaryAttributes.attributes(
- ) + CheckboxRadioButtonAttributes.attributes()
+ field_attributes = (
+ FieldDictionaryAttributes.attributes()
+ + CheckboxRadioButtonAttributes.attributes()
+ )
self.indirect_reference = data.indirect_reference
for attr in field_attributes:
try:
self[NameObject(attr)] = data[attr]
except KeyError:
pass
- if isinstance(self.get('/V'), EncodedStreamObject):
- d = cast(EncodedStreamObject, self[NameObject('/V')]).get_data()
+ if isinstance(self.get("/V"), EncodedStreamObject):
+ d = cast(EncodedStreamObject, self[NameObject("/V")]).get_data()
if isinstance(d, bytes):
d_str = d.decode()
elif d is None:
- d_str = ''
+ d_str = ""
else:
- raise Exception('Should never happen')
- self[NameObject('/V')] = TextStringObject(d_str)
+ raise Exception("Should never happen")
+ self[NameObject("/V")] = TextStringObject(d_str)
+ # TABLE 8.69 Entries common to all field dictionaries
@property
- def field_type(self) ->Optional[NameObject]:
+ def field_type(self) -> Optional[NameObject]:
"""Read-only property accessing the type of this field."""
- pass
+ return self.get(FieldDictionaryAttributes.FT)
@property
- def parent(self) ->Optional[DictionaryObject]:
+ def parent(self) -> Optional[DictionaryObject]:
"""Read-only property accessing the parent of this field."""
- pass
+ return self.get(FieldDictionaryAttributes.Parent)
@property
- def kids(self) ->Optional['ArrayObject']:
+ def kids(self) -> Optional["ArrayObject"]:
"""Read-only property accessing the kids of this field."""
- pass
+ return self.get(FieldDictionaryAttributes.Kids)
@property
- def name(self) ->Optional[str]:
+ def name(self) -> Optional[str]:
"""Read-only property accessing the name of this field."""
- pass
+ return self.get(FieldDictionaryAttributes.T)
@property
- def alternate_name(self) ->Optional[str]:
+ def alternate_name(self) -> Optional[str]:
"""Read-only property accessing the alternate name of this field."""
- pass
+ return self.get(FieldDictionaryAttributes.TU)
@property
- def mapping_name(self) ->Optional[str]:
+ def mapping_name(self) -> Optional[str]:
"""
Read-only property accessing the mapping name of this field.
This name is used by pypdf as a key in the dictionary returned by
:meth:`get_fields()<pypdf.PdfReader.get_fields>`
"""
- pass
+ return self.get(FieldDictionaryAttributes.TM)
@property
- def flags(self) ->Optional[int]:
+ 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).
"""
- pass
+ return self.get(FieldDictionaryAttributes.Ff)
@property
- def value(self) ->Optional[Any]:
+ def value(self) -> Optional[Any]:
"""
Read-only property accessing the value of this field.
Format varies based on field type.
"""
- pass
+ return self.get(FieldDictionaryAttributes.V)
@property
- def default_value(self) ->Optional[Any]:
+ def default_value(self) -> Optional[Any]:
"""Read-only property accessing the default value of this field."""
- pass
+ return self.get(FieldDictionaryAttributes.DV)
@property
- def additional_actions(self) ->Optional[DictionaryObject]:
+ 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.
"""
- pass
+ return self.get(FieldDictionaryAttributes.AA)
class Destination(TreeObject):
@@ -414,102 +1456,156 @@ class Destination(TreeObject):
Raises:
PdfReadError: If destination type is invalid.
"""
- node: Optional[DictionaryObject] = None
- def __init__(self, title: str, page: Union[NumberObject, IndirectObject,
- NullObject, DictionaryObject], fit: Fit) ->None:
- self._filtered_children: List[Any] = []
+ node: Optional[
+ DictionaryObject
+ ] = None # node provide access to the original Object
+
+ def __init__(
+ self,
+ title: str,
+ page: Union[NumberObject, IndirectObject, NullObject, DictionaryObject],
+ fit: Fit,
+ ) -> None:
+ self._filtered_children: List[Any] = [] # used in PdfWriter
+
typ = fit.fit_type
args = fit.fit_args
+
DictionaryObject.__init__(self)
- self[NameObject('/Title')] = TextStringObject(title)
- self[NameObject('/Page')] = page
- self[NameObject('/Type')] = typ
- if typ == '/XYZ':
- if len(args) < 1:
+ self[NameObject("/Title")] = TextStringObject(title)
+ self[NameObject("/Page")] = page
+ self[NameObject("/Type")] = typ
+
+ # from table 8.2 of the PDF 1.7 reference.
+ if typ == "/XYZ":
+ if len(args) < 1: # left is missing : should never occur
args.append(NumberObject(0.0))
- if len(args) < 2:
+ if len(args) < 2: # top is missing
args.append(NumberObject(0.0))
- if len(args) < 3:
+ if len(args) < 3: # zoom is missing
args.append(NumberObject(0.0))
- self[NameObject(TA.LEFT)], self[NameObject(TA.TOP)], self[
- NameObject('/Zoom')] = args
+ (
+ self[NameObject(TA.LEFT)],
+ self[NameObject(TA.TOP)],
+ self[NameObject("/Zoom")],
+ ) = args
elif len(args) == 0:
pass
elif typ == TF.FIT_R:
- self[NameObject(TA.LEFT)], self[NameObject(TA.BOTTOM)], self[
- NameObject(TA.RIGHT)], self[NameObject(TA.TOP)] = args
+ (
+ 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:
- self[NameObject(TA.TOP)], = args
+ try: # Preferred to be more robust not only to null parameters
+ (self[NameObject(TA.TOP)],) = args
except Exception:
- self[NameObject(TA.TOP)], = NullObject(),
+ (self[NameObject(TA.TOP)],) = (NullObject(),)
elif typ in [TF.FIT_V, TF.FIT_BV]:
- try:
- self[NameObject(TA.LEFT)], = args
+ try: # Preferred to be more robust not only to null parameters
+ (self[NameObject(TA.LEFT)],) = args
except Exception:
- self[NameObject(TA.LEFT)], = NullObject(),
+ (self[NameObject(TA.LEFT)],) = (NullObject(),)
elif typ in [TF.FIT, TF.FIT_B]:
pass
else:
- raise PdfReadError(f'Unknown Destination Type: {typ!r}')
+ raise PdfReadError(f"Unknown Destination Type: {typ!r}")
+
+ @property
+ def dest_array(self) -> "ArrayObject":
+ return ArrayObject(
+ [self.raw_get("/Page"), self["/Type"]]
+ + [
+ self[x]
+ for x in ["/Left", "/Bottom", "/Right", "/Top", "/Zoom"]
+ if x in self
+ ]
+ )
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ if encryption_key is not None: # deprecated
+ deprecate_no_replacement(
+ "the encryption_key parameter of write_to_stream", "5.0.0"
+ )
+ stream.write(b"<<\n")
+ key = NameObject("/D")
+ key.write_to_stream(stream)
+ stream.write(b" ")
+ value = self.dest_array
+ value.write_to_stream(stream)
+
+ key = NameObject("/S")
+ key.write_to_stream(stream)
+ stream.write(b" ")
+ value_s = NameObject("/GoTo")
+ value_s.write_to_stream(stream)
+
+ stream.write(b"\n")
+ stream.write(b">>")
@property
- def title(self) ->Optional[str]:
+ def title(self) -> Optional[str]:
"""Read-only property accessing the destination title."""
- pass
+ return self.get("/Title")
@property
- def page(self) ->Optional[int]:
+ def page(self) -> Optional[int]:
"""Read-only property accessing the destination page number."""
- pass
+ return self.get("/Page")
@property
- def typ(self) ->Optional[str]:
+ def typ(self) -> Optional[str]:
"""Read-only property accessing the destination type."""
- pass
+ return self.get("/Type")
@property
- def zoom(self) ->Optional[int]:
+ def zoom(self) -> Optional[int]:
"""Read-only property accessing the zoom factor."""
- pass
+ return self.get("/Zoom", None)
@property
- def left(self) ->Optional[FloatObject]:
+ def left(self) -> Optional[FloatObject]:
"""Read-only property accessing the left horizontal coordinate."""
- pass
+ return self.get("/Left", None)
@property
- def right(self) ->Optional[FloatObject]:
+ def right(self) -> Optional[FloatObject]:
"""Read-only property accessing the right horizontal coordinate."""
- pass
+ return self.get("/Right", None)
@property
- def top(self) ->Optional[FloatObject]:
+ def top(self) -> Optional[FloatObject]:
"""Read-only property accessing the top vertical coordinate."""
- pass
+ return self.get("/Top", None)
@property
- def bottom(self) ->Optional[FloatObject]:
+ def bottom(self) -> Optional[FloatObject]:
"""Read-only property accessing the bottom vertical coordinate."""
- pass
+ return self.get("/Bottom", None)
@property
- def color(self) ->Optional['ArrayObject']:
+ def color(self) -> Optional["ArrayObject"]:
"""Read-only property accessing the color in (R, G, B) with values 0.0-1.0."""
- pass
+ return self.get(
+ "/C", ArrayObject([FloatObject(0), FloatObject(0), FloatObject(0)])
+ )
@property
- def font_format(self) ->Optional[OutlineFontFlag]:
+ def font_format(self) -> Optional[OutlineFontFlag]:
"""
Read-only property accessing the font type.
1=italic, 2=bold, 3=both
"""
- pass
+ return self.get("/F", 0)
@property
- def outline_count(self) ->Optional[int]:
+ def outline_count(self) -> Optional[int]:
"""
Read-only property accessing the outline count.
@@ -517,4 +1613,4 @@ class Destination(TreeObject):
negative = collapsed
absolute value = number of visible descendants at all levels
"""
- pass
+ return self.get("/Count", None)
diff --git a/pypdf/generic/_fit.py b/pypdf/generic/_fit.py
index c30240ce..4132f4b7 100644
--- a/pypdf/generic/_fit.py
+++ b/pypdf/generic/_fit.py
@@ -2,17 +2,24 @@ from typing import Any, Optional, Tuple, Union
class Fit:
-
- def __init__(self, fit_type: str, fit_args: Tuple[Union[None, float,
- Any], ...]=()):
+ def __init__(
+ self, fit_type: str, fit_args: Tuple[Union[None, float, Any], ...] = ()
+ ):
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]
+ 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':
+ 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
@@ -31,10 +38,10 @@ class Fit:
Returns:
The created fit object.
"""
- pass
+ return Fit(fit_type="/XYZ", fit_args=(left, top, zoom))
@classmethod
- def fit(cls) ->'Fit':
+ 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
@@ -44,10 +51,10 @@ class Fit:
different, use the smaller of the two, centering the page within the
window in the other dimension.
"""
- pass
+ return Fit(fit_type="/Fit")
@classmethod
- def fit_horizontally(cls, top: Optional[float]=None) ->'Fit':
+ 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
@@ -63,12 +70,20 @@ class Fit:
Returns:
The created fit object.
"""
- pass
+ 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':
+ 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
@@ -91,10 +106,10 @@ class Fit:
Returns:
The created fit object.
"""
- pass
+ return Fit(fit_type="/FitR", fit_args=(left, bottom, right, top))
@classmethod
- def fit_box(cls) ->'Fit':
+ 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
@@ -104,10 +119,10 @@ class Fit:
different, use the smaller of the two, centering the bounding box
within the window in the other dimension.
"""
- pass
+ return Fit(fit_type="/FitB")
@classmethod
- def fit_box_horizontally(cls, top: Optional[float]=None) ->'Fit':
+ 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
@@ -123,10 +138,10 @@ class Fit:
Returns:
The created fit object.
"""
- pass
+ return Fit(fit_type="/FitBH", fit_args=(top,))
@classmethod
- def fit_box_vertically(cls, left: Optional[float]=None) ->'Fit':
+ 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
@@ -142,12 +157,12 @@ class Fit:
Returns:
The created fit object.
"""
- pass
+ return Fit(fit_type="/FitBV", fit_args=(left,))
- def __str__(self) ->str:
+ def __str__(self) -> str:
if not self.fit_args:
- return f'Fit({self.fit_type})'
- return f'Fit({self.fit_type}, {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/pypdf/generic/_image_inline.py b/pypdf/generic/_image_inline.py
index 8a46ea73..41826ac3 100644
--- a/pypdf/generic/_image_inline.py
+++ b/pypdf/generic/_image_inline.py
@@ -1,46 +1,235 @@
+# Copyright (c) 2024, pypdf contributors
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
import logging
from io import BytesIO
-from .._utils import WHITESPACES, StreamType, read_non_whitespace
+
+from .._utils import (
+ WHITESPACES,
+ StreamType,
+ read_non_whitespace,
+)
from ..errors import PdfReadError
+
logger = logging.getLogger(__name__)
+
BUFFER_SIZE = 8192
-def extract_inline_AHx(stream: StreamType) ->bytes:
+def extract_inline_AHx(stream: StreamType) -> bytes:
"""
Extract HexEncoded Stream from Inline Image.
the stream will be moved onto the EI
"""
- pass
+ data_out: bytes = b""
+ # Read data until delimiter > and EI as backup
+ # ignoring backup.
+ while True:
+ data_buffered = read_non_whitespace(stream) + stream.read(BUFFER_SIZE)
+ if not data_buffered:
+ raise PdfReadError("Unexpected end of stream")
+ pos_tok = data_buffered.find(b">")
+ if pos_tok >= 0: # found >
+ data_out += data_buffered[: (pos_tok + 1)]
+ stream.seek(-len(data_buffered) + pos_tok + 1, 1)
+ break
+ pos_ei = data_buffered.find(b"EI")
+ if pos_ei >= 0: # found EI
+ stream.seek(-len(data_buffered) + pos_ei - 1, 1)
+ c = stream.read(1)
+ while c in WHITESPACES:
+ stream.seek(-2, 1)
+ c = stream.read(1)
+ pos_ei -= 1
+ data_out += data_buffered[:pos_ei]
+ break
+ elif len(data_buffered) == 2:
+ data_out += data_buffered
+ raise PdfReadError("Unexpected end of stream")
+ else: # > nor EI found
+ data_out += data_buffered[:-2]
+ stream.seek(-2, 1)
+
+ ei_tok = read_non_whitespace(stream)
+ ei_tok += stream.read(2)
+ stream.seek(-3, 1)
+ if ei_tok[0:2] != b"EI" or not (ei_tok[2:3] == b"" or ei_tok[2:3] in WHITESPACES):
+ raise PdfReadError("EI stream not found")
+ return data_out
-def extract_inline_A85(stream: StreamType) ->bytes:
+def extract_inline_A85(stream: StreamType) -> bytes:
"""
Extract A85 Stream from Inline Image.
the stream will be moved onto the EI
"""
- pass
+ data_out: bytes = b""
+ # Read data up to delimiter ~>
+ # see §3.3.2 from PDF ref 1.7
+ while True:
+ data_buffered = read_non_whitespace(stream) + stream.read(BUFFER_SIZE)
+ if not data_buffered:
+ raise PdfReadError("Unexpected end of stream")
+ pos_tok = data_buffered.find(b"~>")
+ if pos_tok >= 0: # found!
+ data_out += data_buffered[: pos_tok + 2]
+ stream.seek(-len(data_buffered) + pos_tok + 2, 1)
+ break
+ elif len(data_buffered) == 2: # end of buffer
+ data_out += data_buffered
+ raise PdfReadError("Unexpected end of stream")
+ data_out += data_buffered[
+ :-2
+ ] # back by one char in case of in the middle of ~>
+ stream.seek(-2, 1)
+ ei_tok = read_non_whitespace(stream)
+ ei_tok += stream.read(2)
+ stream.seek(-3, 1)
+ if ei_tok[0:2] != b"EI" or not (ei_tok[2:3] == b"" or ei_tok[2:3] in WHITESPACES):
+ raise PdfReadError("EI stream not found")
+ return data_out
-def extract_inline_RL(stream: StreamType) ->bytes:
+
+def extract_inline_RL(stream: StreamType) -> bytes:
"""
Extract RL Stream from Inline Image.
the stream will be moved onto the EI
"""
- pass
+ data_out: bytes = b""
+ # Read data up to delimiter ~>
+ # see §3.3.4 from PDF ref 1.7
+ while True:
+ data_buffered = stream.read(BUFFER_SIZE)
+ if not data_buffered:
+ raise PdfReadError("Unexpected end of stream")
+ pos_tok = data_buffered.find(b"\x80")
+ if pos_tok >= 0: # found
+ data_out += data_buffered[: pos_tok + 1]
+ stream.seek(-len(data_buffered) + pos_tok + 1, 1)
+ break
+ data_out += data_buffered
+
+ ei_tok = read_non_whitespace(stream)
+ ei_tok += stream.read(2)
+ stream.seek(-3, 1)
+ if ei_tok[0:2] != b"EI" or not (ei_tok[2:3] == b"" or ei_tok[2:3] in WHITESPACES):
+ raise PdfReadError("EI stream not found")
+ return data_out
-def extract_inline_DCT(stream: StreamType) ->bytes:
+def extract_inline_DCT(stream: StreamType) -> bytes:
"""
Extract DCT (JPEG) Stream from Inline Image.
the stream will be moved onto the EI
"""
- pass
+ data_out: bytes = b""
+ # Read Blocks of data (ID/Size/data) up to ID=FF/D9
+ # see https://www.digicamsoft.com/itu/itu-t81-36.html
+ notfirst = False
+ while True:
+ c = stream.read(1)
+ if notfirst or (c == b"\xff"):
+ data_out += c
+ if c != b"\xff":
+ continue
+ else:
+ notfirst = True
+ c = stream.read(1)
+ data_out += c
+ if c == b"\xff":
+ stream.seek(-1, 1) # pragma: no cover
+ elif c == b"\x00": # stuffing
+ pass
+ elif c == b"\xd9": # end
+ break
+ elif c in (
+ b"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc9\xca\xcb\xcc\xcd\xce\xcf"
+ b"\xda\xdb\xdc\xdd\xde\xdf"
+ b"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xfe"
+ ):
+ c = stream.read(2)
+ data_out += c
+ sz = c[0] * 256 + c[1]
+ data_out += stream.read(sz - 2)
+ # else: pass
+
+ ei_tok = read_non_whitespace(stream)
+ ei_tok += stream.read(2)
+ stream.seek(-3, 1)
+ if ei_tok[0:2] != b"EI" or not (ei_tok[2:3] == b"" or ei_tok[2:3] in WHITESPACES):
+ raise PdfReadError("EI stream not found")
+ return data_out
-def extract_inline_default(stream: StreamType) ->bytes:
+def extract_inline_default(stream: StreamType) -> bytes:
"""
Legacy method
used by default
"""
- pass
+ stream_out = BytesIO()
+ # Read the inline image, while checking for EI (End Image) operator.
+ while True:
+ data_buffered = stream.read(BUFFER_SIZE)
+ if not data_buffered:
+ raise PdfReadError("Unexpected end of stream")
+ pos_ei = data_buffered.find(
+ b"E"
+ ) # we can not look straight for "EI" because it may not have been loaded in the buffer
+
+ if pos_ei == -1:
+ stream_out.write(data_buffered)
+ else:
+ # Write out everything including E (the one from EI to be removed).
+ stream_out.write(data_buffered[0 : pos_ei + 1])
+ sav_pos_ei = stream_out.tell() - 1
+ # Seek back in the stream to read the E next.
+ stream.seek(pos_ei + 1 - len(data_buffered), 1)
+ saved_pos = stream.tell()
+ # Check for End Image
+ tok2 = stream.read(1) # I of "EI"
+ if tok2 != b"I":
+ stream.seek(saved_pos, 0)
+ continue
+ tok3 = stream.read(1) # possible space after "EI"
+ if tok3 not in WHITESPACES:
+ stream.seek(saved_pos, 0)
+ continue
+ while tok3 in WHITESPACES:
+ tok3 = stream.read(1)
+ if data_buffered[pos_ei - 1 : pos_ei] not in WHITESPACES and tok3 not in {
+ b"Q",
+ b"E",
+ }: # for Q ou EMC
+ stream.seek(saved_pos, 0)
+ continue
+ # Data contains [\s]EI[\s](Q|EMC): 4 chars are sufficients
+ # remove E(I) wrongly inserted earlier
+ stream_out.truncate(sav_pos_ei)
+ break
+
+ return stream_out.getvalue()
diff --git a/pypdf/generic/_outline.py b/pypdf/generic/_outline.py
index 3c300f6a..4d6a47da 100644
--- a/pypdf/generic/_outline.py
+++ b/pypdf/generic/_outline.py
@@ -1,8 +1,33 @@
from typing import Union
+
from .._utils import StreamType, deprecate_no_replacement
from ._base import NameObject
from ._data_structures import Destination
class OutlineItem(Destination):
- pass
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ if encryption_key is not None: # deprecated
+ deprecate_no_replacement(
+ "the encryption_key parameter of write_to_stream", "5.0.0"
+ )
+ stream.write(b"<<\n")
+ for key in [
+ NameObject(x)
+ for x in ["/Title", "/Parent", "/First", "/Last", "/Next", "/Prev"]
+ if x in self
+ ]:
+ key.write_to_stream(stream)
+ stream.write(b" ")
+ value = self.raw_get(key)
+ value.write_to_stream(stream)
+ stream.write(b"\n")
+ key = NameObject("/Dest")
+ key.write_to_stream(stream)
+ stream.write(b" ")
+ value = self.dest_array
+ value.write_to_stream(stream)
+ stream.write(b"\n")
+ stream.write(b">>")
diff --git a/pypdf/generic/_rectangle.py b/pypdf/generic/_rectangle.py
index 5e885b2a..690b5217 100644
--- a/pypdf/generic/_rectangle.py
+++ b/pypdf/generic/_rectangle.py
@@ -1,4 +1,5 @@
from typing import Any, Tuple, Union
+
from ._base import FloatObject, NumberObject
from ._data_structures import ArrayObject
@@ -16,42 +17,116 @@ class RectangleObject(ArrayObject):
* :attr:`trimbox <pypdf._page.PageObject.trimbox>`
"""
- def __init__(self, arr: Union['RectangleObject', Tuple[float, float,
- float, float]]) ->None:
+ def __init__(
+ self, arr: Union["RectangleObject", Tuple[float, float, float, float]]
+ ) -> None:
+ # must have four points
assert len(arr) == 4
- ArrayObject.__init__(self, [self._ensure_is_number(x) for x in arr])
+ # 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 __repr__(self) -> str:
+ return f"RectangleObject({list(self)!r})"
+
+ @property
+ def left(self) -> FloatObject:
+ return self[0]
+
+ @left.setter
+ def left(self, f: float) -> None:
+ self[0] = FloatObject(f)
+
+ @property
+ def bottom(self) -> FloatObject:
+ return self[1]
+
+ @bottom.setter
+ def bottom(self, f: float) -> None:
+ self[1] = FloatObject(f)
+
+ @property
+ def right(self) -> FloatObject:
+ return self[2]
- def __repr__(self) ->str:
- return f'RectangleObject({list(self)!r})'
+ @right.setter
+ def right(self, f: float) -> None:
+ self[2] = FloatObject(f)
@property
- def lower_left(self) ->Tuple[float, float]:
+ def top(self) -> FloatObject:
+ return self[3]
+
+ @top.setter
+ def top(self, f: float) -> None:
+ self[3] = FloatObject(f)
+
+ @property
+ def lower_left(self) -> Tuple[float, float]:
"""
Property to read and modify the lower left coordinate of this box
in (x,y) form.
"""
- pass
+ return self.left, self.bottom
+
+ @lower_left.setter
+ def lower_left(self, value: Tuple[float, float]) -> None:
+ self[0], self[1] = (self._ensure_is_number(x) for x in value)
@property
- def lower_right(self) ->Tuple[float, float]:
+ def lower_right(self) -> Tuple[float, float]:
"""
Property to read and modify the lower right coordinate of this box
in (x,y) form.
"""
- pass
+ return self.right, self.bottom
+
+ @lower_right.setter
+ def lower_right(self, value: Tuple[float, float]) -> None:
+ self[2], self[1] = (self._ensure_is_number(x) for x in value)
@property
- def upper_left(self) ->Tuple[float, float]:
+ def upper_left(self) -> Tuple[float, float]:
"""
Property to read and modify the upper left coordinate of this box
in (x,y) form.
"""
- pass
+ return self.left, self.top
+
+ @upper_left.setter
+ def upper_left(self, value: Tuple[float, float]) -> None:
+ self[0], self[3] = (self._ensure_is_number(x) for x in value)
@property
- def upper_right(self) ->Tuple[float, float]:
+ def upper_right(self) -> Tuple[float, float]:
"""
Property to read and modify the upper right coordinate of this box
in (x,y) form.
"""
- pass
+ return self.right, self.top
+
+ @upper_right.setter
+ def upper_right(self, value: Tuple[float, float]) -> None:
+ self[2], self[3] = (self._ensure_is_number(x) for x in value)
+
+ @property
+ def width(self) -> float:
+ return self.right - self.left
+
+ @property
+ def height(self) -> float:
+ return self.top - self.bottom
diff --git a/pypdf/generic/_utils.py b/pypdf/generic/_utils.py
index f259fc92..fdcdc333 100644
--- a/pypdf/generic/_utils.py
+++ b/pypdf/generic/_utils.py
@@ -1,14 +1,119 @@
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 create_string_object(string: Union[str, bytes], forced_encoding: Union[
- None, str, List[str], Dict[int, str]]=None) ->Union[TextStringObject,
- ByteStringObject]:
+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 <= 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 <= b"7":
+ tok += ntok
+ else:
+ stream.seek(-1, 1) # ntok has to be analyzed
+ 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 = f"Unexpected escaped string: {tok.decode('utf-8','ignore')}"
+ 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.
@@ -22,4 +127,54 @@ def create_string_object(string: Union[str, bytes], forced_encoding: Union[
Raises:
TypeError: If string is not of type str or bytes.
"""
- pass
+ 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, codecs.BOM_UTF16_LE)):
+ retval = TextStringObject(string.decode("utf-16"))
+ retval.autodetect_utf16 = True
+ retval.utf16_bom = string[:2]
+ 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/pypdf/generic/_viewerpref.py b/pypdf/generic/_viewerpref.py
index af352e7f..a12f2d44 100644
--- a/pypdf/generic/_viewerpref.py
+++ b/pypdf/generic/_viewerpref.py
@@ -1,75 +1,164 @@
-from typing import Any, List, Optional
+# Copyright (c) 2023, Pubpub-ZZ
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+from typing import (
+ Any,
+ List,
+ Optional,
+)
+
from ._base import BooleanObject, NameObject, NumberObject
from ._data_structures import ArrayObject, DictionaryObject
+
f_obj = BooleanObject(False)
class ViewerPreferences(DictionaryObject):
+ def _get_bool(self, key: str, deft: Optional[BooleanObject]) -> BooleanObject:
+ return self.get(key, deft)
+
+ def _set_bool(self, key: str, v: bool) -> None:
+ self[NameObject(key)] = BooleanObject(v is True)
+
+ def _get_name(self, key: str, deft: Optional[NameObject]) -> Optional[NameObject]:
+ return self.get(key, deft)
+
+ def _set_name(self, key: str, lst: List[str], v: NameObject) -> None:
+ if v[0] != "/":
+ raise ValueError(f"{v} is not starting with '/'")
+ if lst != [] and v not in lst:
+ raise ValueError(f"{v} is not par of acceptable values")
+ self[NameObject(key)] = NameObject(v)
+
+ def _get_arr(self, key: str, deft: Optional[List[Any]]) -> NumberObject:
+ return self.get(key, None if deft is None else ArrayObject(deft))
- def __new__(cls: Any, value: Any=None) ->'ViewerPreferences':
+ def _set_arr(self, key: str, v: Optional[ArrayObject]) -> None:
+ if v is None:
+ try:
+ del self[NameObject(key)]
+ except KeyError:
+ pass
+ return
+ if not isinstance(v, ArrayObject):
+ raise ValueError("ArrayObject is expected")
+ self[NameObject(key)] = v
- def _add_prop_bool(key: str, deft: Optional[BooleanObject]) ->property:
- return property(lambda self: self._get_bool(key, deft), lambda
- self, v: self._set_bool(key, v), None,
+ def _get_int(self, key: str, deft: Optional[NumberObject]) -> NumberObject:
+ return self.get(key, deft)
+
+ def _set_int(self, key: str, v: int) -> None:
+ self[NameObject(key)] = NumberObject(v)
+
+ @property
+ def PRINT_SCALING(self) -> NameObject:
+ return NameObject("/PrintScaling")
+
+ def __new__(cls: Any, value: Any = None) -> "ViewerPreferences":
+ def _add_prop_bool(key: str, deft: Optional[BooleanObject]) -> property:
+ return property(
+ lambda self: self._get_bool(key, deft),
+ lambda self, v: self._set_bool(key, v),
+ None,
f"""
Returns/Modify the status of {key}, Returns {deft} if not defined
- """
- )
+ """,
+ )
- def _add_prop_name(key: str, lst: List[str], deft: Optional[NameObject]
- ) ->property:
- return property(lambda self: self._get_name(key, deft), lambda
- self, v: self._set_name(key, lst, v), None,
+ def _add_prop_name(
+ key: str, lst: List[str], deft: Optional[NameObject]
+ ) -> property:
+ return property(
+ lambda self: self._get_name(key, deft),
+ lambda self, v: self._set_name(key, lst, v),
+ None,
f"""
Returns/Modify the status of {key}, Returns {deft} if not defined.
Acceptable values: {lst}
- """
- )
+ """,
+ )
- def _add_prop_arr(key: str, deft: Optional[ArrayObject]) ->property:
- return property(lambda self: self._get_arr(key, deft), lambda
- self, v: self._set_arr(key, v), None,
+ def _add_prop_arr(key: str, deft: Optional[ArrayObject]) -> property:
+ return property(
+ lambda self: self._get_arr(key, deft),
+ lambda self, v: self._set_arr(key, v),
+ None,
f"""
Returns/Modify the status of {key}, Returns {deft} if not defined
- """
- )
+ """,
+ )
- def _add_prop_int(key: str, deft: Optional[int]) ->property:
- return property(lambda self: self._get_int(key, deft), lambda
- self, v: self._set_int(key, v), None,
+ def _add_prop_int(key: str, deft: Optional[int]) -> property:
+ return property(
+ lambda self: self._get_int(key, deft),
+ lambda self, v: self._set_int(key, v),
+ None,
f"""
Returns/Modify the status of {key}, Returns {deft} if not defined
- """
- )
- cls.hide_toolbar = _add_prop_bool('/HideToolbar', f_obj)
- cls.hide_menubar = _add_prop_bool('/HideMenubar', f_obj)
- cls.hide_windowui = _add_prop_bool('/HideWindowUI', f_obj)
- cls.fit_window = _add_prop_bool('/FitWindow', f_obj)
- cls.center_window = _add_prop_bool('/CenterWindow', f_obj)
- cls.display_doctitle = _add_prop_bool('/DisplayDocTitle', f_obj)
- cls.non_fullscreen_pagemode = _add_prop_name('/NonFullScreenPageMode',
- ['/UseNone', '/UseOutlines', '/UseThumbs', '/UseOC'],
- NameObject('/UseNone'))
- cls.direction = _add_prop_name('/Direction', ['/L2R', '/R2L'],
- NameObject('/L2R'))
- cls.view_area = _add_prop_name('/ViewArea', [], None)
- cls.view_clip = _add_prop_name('/ViewClip', [], None)
- cls.print_area = _add_prop_name('/PrintArea', [], None)
- cls.print_clip = _add_prop_name('/PrintClip', [], None)
- cls.print_scaling = _add_prop_name('/PrintScaling', [], None)
- cls.duplex = _add_prop_name('/Duplex', ['/Simplex',
- '/DuplexFlipShortEdge', '/DuplexFlipLongEdge'], None)
- cls.pick_tray_by_pdfsize = _add_prop_bool('/PickTrayByPDFSize', None)
- cls.print_pagerange = _add_prop_arr('/PrintPageRange', None)
- cls.num_copies = _add_prop_int('/NumCopies', None)
- cls.enforce = _add_prop_arr('/Enforce', ArrayObject())
+ """,
+ )
+
+ cls.hide_toolbar = _add_prop_bool("/HideToolbar", f_obj)
+ cls.hide_menubar = _add_prop_bool("/HideMenubar", f_obj)
+ cls.hide_windowui = _add_prop_bool("/HideWindowUI", f_obj)
+ cls.fit_window = _add_prop_bool("/FitWindow", f_obj)
+ cls.center_window = _add_prop_bool("/CenterWindow", f_obj)
+ cls.display_doctitle = _add_prop_bool("/DisplayDocTitle", f_obj)
+
+ cls.non_fullscreen_pagemode = _add_prop_name(
+ "/NonFullScreenPageMode",
+ ["/UseNone", "/UseOutlines", "/UseThumbs", "/UseOC"],
+ NameObject("/UseNone"),
+ )
+ cls.direction = _add_prop_name(
+ "/Direction", ["/L2R", "/R2L"], NameObject("/L2R")
+ )
+ cls.view_area = _add_prop_name("/ViewArea", [], None)
+ cls.view_clip = _add_prop_name("/ViewClip", [], None)
+ cls.print_area = _add_prop_name("/PrintArea", [], None)
+ cls.print_clip = _add_prop_name("/PrintClip", [], None)
+ cls.print_scaling = _add_prop_name("/PrintScaling", [], None)
+ cls.duplex = _add_prop_name(
+ "/Duplex", ["/Simplex", "/DuplexFlipShortEdge", "/DuplexFlipLongEdge"], None
+ )
+ cls.pick_tray_by_pdfsize = _add_prop_bool("/PickTrayByPDFSize", None)
+ cls.print_pagerange = _add_prop_arr("/PrintPageRange", None)
+ cls.num_copies = _add_prop_int("/NumCopies", None)
+
+ cls.enforce = _add_prop_arr("/Enforce", ArrayObject())
+
return DictionaryObject.__new__(cls)
- def __init__(self, obj: Optional[DictionaryObject]=None) ->None:
+ def __init__(self, obj: Optional[DictionaryObject] = None) -> None:
super().__init__(self)
if obj is not None:
self.update(obj.items())
try:
- self.indirect_reference = obj.indirect_reference
+ self.indirect_reference = obj.indirect_reference # type: ignore
except AttributeError:
pass
diff --git a/pypdf/pagerange.py b/pypdf/pagerange.py
index 2bc1277e..47a72c72 100644
--- a/pypdf/pagerange.py
+++ b/pypdf/pagerange.py
@@ -5,11 +5,15 @@ 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/pypdf/blob/main/LICENSE
"""
+
import re
from typing import Any, List, Tuple, Union
+
from .errors import ParseError
-_INT_RE = '(0|-?[1-9]\\d*)'
-PAGE_RANGE_RE = f'^({_INT_RE}|({_INT_RE}?(:{_INT_RE}?(:{_INT_RE}?)?)))$'
+
+_INT_RE = r"(0|-?[1-9]\d*)" # A decimal int, don't allow "-0".
+PAGE_RANGE_RE = f"^({_INT_RE}|({_INT_RE}?(:{_INT_RE}?(:{_INT_RE}?)?)))$"
+# groups: 12 34 5 6 7 8
class PageRange:
@@ -29,7 +33,7 @@ class PageRange:
- indices(n) is like slice.indices(n).
"""
- def __init__(self, arg: Union[slice, 'PageRange', str]) ->None:
+ 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,
@@ -56,22 +60,24 @@ class PageRange:
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)])
+ self._slice = slice(*[int(g) if g else None for g in m.group(4, 6, 8)])
@staticmethod
- def valid(input: Any) ->bool:
+ def valid(input: Any) -> bool:
"""
True if input is a valid initializer for a PageRange.
@@ -81,29 +87,32 @@ class PageRange:
Returns:
True, if the ``input`` is a valid PageRange.
"""
- pass
+ return isinstance(input, (slice, PageRange)) or (
+ isinstance(input, str) and bool(re.match(PAGE_RANGE_RE, input))
+ )
- def to_slice(self) ->slice:
+ def to_slice(self) -> slice:
"""Return the slice equivalent of this page range."""
- pass
+ return self._slice
- def __str__(self) ->str:
+ 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)
+ return ":".join("" if i is None else str(i) for i in indices)
- def __repr__(self) ->str:
+ def __repr__(self) -> str:
"""A string like "PageRange('1:2:3')"."""
- return 'PageRange(' + repr(str(self)) + ')'
+ return "PageRange(" + repr(str(self)) + ")"
- def indices(self, n: int) ->Tuple[int, int, int]:
+ def indices(self, n: int) -> Tuple[int, int, int]:
"""
Assuming a sequence of length n, calculate the start and stop indices,
and the stride length of the PageRange.
@@ -116,32 +125,37 @@ class PageRange:
Returns:
Arguments for range().
"""
- pass
+ return self._slice.indices(n)
- def __eq__(self, other: object) ->bool:
+ def __eq__(self, other: object) -> bool:
if not isinstance(other, PageRange):
return False
return self._slice == other._slice
- def __add__(self, other: 'PageRange') ->'PageRange':
+ 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(':')
+PAGE_RANGE_ALL = PageRange(":") # The range of all pages.
-def parse_filename_page_ranges(args: List[Union[str, PageRange, None]]) ->List[
- Tuple[str, PageRange]]:
+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.
@@ -153,8 +167,26 @@ def parse_filename_page_ranges(args: List[Union[str, PageRange, None]]) ->List[
Returns:
A list of (filename, page_range) pairs.
"""
- pass
+ 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]]
+PageRangeSpec = Union[str, PageRange, Tuple[int, int], Tuple[int, int, int], List[int]]
diff --git a/pypdf/papersizes.py b/pypdf/papersizes.py
index 0a7a025a..2d83e1d5 100644
--- a/pypdf/papersizes.py
+++ b/pypdf/papersizes.py
@@ -1,4 +1,5 @@
"""Helper to get paper sizes."""
+
from typing import NamedTuple
@@ -9,17 +10,42 @@ class Dimensions(NamedTuple):
class PaperSize:
"""(width, height) of the paper in portrait mode in pixels at 72 ppi."""
- A0 = Dimensions(2384, 3370)
+
+ # 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)
- A5 = Dimensions(420, 595)
- A6 = Dimensions(298, 420)
+ A4 = Dimensions(
+ 595, 842
+ ) # Printer paper, documents - this is by far the most common
+ A5 = Dimensions(420, 595) # Paperback books
+ A6 = Dimensions(298, 420) # Postcards
A7 = Dimensions(210, 298)
A8 = Dimensions(147, 210)
+
+ # Envelopes
C4 = Dimensions(649, 918)
-_din_a = (PaperSize.A0, PaperSize.A1, PaperSize.A2, PaperSize.A3, PaperSize
- .A4, PaperSize.A5, PaperSize.A6, PaperSize.A7, PaperSize.A8)
+_din_a = (
+ PaperSize.A0,
+ PaperSize.A1,
+ PaperSize.A2,
+ PaperSize.A3,
+ PaperSize.A4,
+ PaperSize.A5,
+ PaperSize.A6,
+ PaperSize.A7,
+ PaperSize.A8,
+)
diff --git a/pypdf/types.py b/pypdf/types.py
index f823cdfe..b8fbab92 100644
--- a/pypdf/types.py
+++ b/pypdf/types.py
@@ -1,32 +1,83 @@
"""Helpers for working with PDF types."""
+
import sys
from typing import List, Union
+
if sys.version_info[:2] >= (3, 8):
+ # Python 3.8+: https://peps.python.org/pep-0586
from typing import Literal
else:
from typing_extensions import Literal
+
if sys.version_info[:2] >= (3, 10):
+ # Python 3.10+: https://www.python.org/dev/peps/pep-0484
from typing import TypeAlias
else:
from typing_extensions import TypeAlias
+
from .generic._base import NameObject, NullObject, NumberObject
from .generic._data_structures import ArrayObject, Destination
from .generic._outline import OutlineItem
+
BorderArrayType: TypeAlias = List[Union[NameObject, NumberObject, ArrayObject]]
OutlineItemType: TypeAlias = Union[OutlineItem, Destination]
-FitType: TypeAlias = Literal['/XYZ', '/Fit', '/FitH', '/FitV', '/FitR',
- '/FitB', '/FitBH', '/FitBV']
+FitType: TypeAlias = Literal[
+ "/XYZ", "/Fit", "/FitH", "/FitV", "/FitR", "/FitB", "/FitBH", "/FitBV"
+]
+# Those go with the FitType: They specify values for the fit
ZoomArgType: TypeAlias = Union[NumberObject, NullObject, float]
ZoomArgsType: TypeAlias = List[ZoomArgType]
-OutlineType = List[Union[Destination, List[Union[Destination, List[
- Destination]]]]]
-LayoutType: TypeAlias = Literal['/NoLayout', '/SinglePage', '/OneColumn',
- '/TwoColumnLeft', '/TwoColumnRight', '/TwoPageLeft', '/TwoPageRight']
-PagemodeType: TypeAlias = Literal['/UseNone', '/UseOutlines', '/UseThumbs',
- '/FullScreen', '/UseOC', '/UseAttachments']
-AnnotationSubtype: TypeAlias = Literal['/Text', '/Link', '/FreeText',
- '/Line', '/Square', '/Circle', '/Polygon', '/PolyLine', '/Highlight',
- '/Underline', '/Squiggly', '/StrikeOut', '/Caret', '/Stamp', '/Ink',
- '/Popup', '/FileAttachment', '/Sound', '/Movie', '/Screen', '/Widget',
- '/PrinterMark', '/TrapNet', '/Watermark', '/3D', '/Redact',
- '/Projection', '/RichMedia']
+
+# Recursive types like the following are not yet supported by mypy:
+# OutlineType = List[Union[Destination, "OutlineType"]]
+# See https://github.com/python/mypy/issues/731
+# Hence use this for the moment:
+OutlineType = List[Union[Destination, List[Union[Destination, List[Destination]]]]]
+
+LayoutType: TypeAlias = Literal[
+ "/NoLayout",
+ "/SinglePage",
+ "/OneColumn",
+ "/TwoColumnLeft",
+ "/TwoColumnRight",
+ "/TwoPageLeft",
+ "/TwoPageRight",
+]
+PagemodeType: TypeAlias = Literal[
+ "/UseNone",
+ "/UseOutlines",
+ "/UseThumbs",
+ "/FullScreen",
+ "/UseOC",
+ "/UseAttachments",
+]
+AnnotationSubtype: TypeAlias = Literal[
+ "/Text",
+ "/Link",
+ "/FreeText",
+ "/Line",
+ "/Square",
+ "/Circle",
+ "/Polygon",
+ "/PolyLine",
+ "/Highlight",
+ "/Underline",
+ "/Squiggly",
+ "/StrikeOut",
+ "/Caret",
+ "/Stamp",
+ "/Ink",
+ "/Popup",
+ "/FileAttachment",
+ "/Sound",
+ "/Movie",
+ "/Screen",
+ "/Widget",
+ "/PrinterMark",
+ "/TrapNet",
+ "/Watermark",
+ "/3D",
+ "/Redact",
+ "/Projection",
+ "/RichMedia",
+]
diff --git a/pypdf/xmp.py b/pypdf/xmp.py
index 78c923e3..df55c905 100644
--- a/pypdf/xmp.py
+++ b/pypdf/xmp.py
@@ -3,22 +3,54 @@ Anything related to Extensible Metadata Platform (XMP) metadata.
https://en.wikipedia.org/wiki/Extensible_Metadata_Platform
"""
+
import datetime
import decimal
import re
-from typing import Any, Callable, Dict, Iterator, List, Optional, TypeVar, Union
+from typing import (
+ Any,
+ Callable,
+ Dict,
+ Iterator,
+ List,
+ Optional,
+ TypeVar,
+ Union,
+)
from xml.dom.minidom import Document, parseString
from xml.dom.minidom import Element as XmlElement
from xml.parsers.expat import ExpatError
+
from ._utils import StreamType, deprecate_no_replacement
from .errors import PdfReadError
from .generic import ContentStream, PdfObject
-RDF_NAMESPACE = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
-DC_NAMESPACE = 'http://purl.org/dc/elements/1.1/'
-XMP_NAMESPACE = 'http://ns.adobe.com/xap/1.0/'
-PDF_NAMESPACE = 'http://ns.adobe.com/pdf/1.3/'
-XMPMM_NAMESPACE = 'http://ns.adobe.com/xap/1.0/mm/'
-PDFX_NAMESPACE = 'http://ns.adobe.com/pdfx/1.3/'
+
+RDF_NAMESPACE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+DC_NAMESPACE = "http://purl.org/dc/elements/1.1/"
+XMP_NAMESPACE = "http://ns.adobe.com/xap/1.0/"
+PDF_NAMESPACE = "http://ns.adobe.com/pdf/1.3/"
+XMPMM_NAMESPACE = "http://ns.adobe.com/xap/1.0/mm/"
+
+# What is the PDFX namespace, you might ask?
+# It's documented here: https://github.com/adobe/xmp-docs/raw/master/XMPSpecifications/XMPSpecificationPart3.pdf
+# This namespace is used to place "custom metadata"
+# properties, which are arbitrary metadata properties with no semantic or
+# documented meaning.
+#
+# Elements in the namespace are key/value-style storage,
+# where the element name is the key and the content is the value. The keys
+# are transformed into valid XML identifiers by substituting an invalid
+# identifier character with \u2182 followed by the unicode hex ID of the
+# original character. A key like "my car" is therefore "my\u21820020car".
+#
+# \u2182 is the unicode character \u{ROMAN NUMERAL TEN THOUSAND}
+#
+# The pdfx namespace should be avoided.
+# A custom data schema and sensical XML elements could be used instead, as is
+# suggested by Adobe's own documentation on XMP under "Extensibility of
+# Schemas".
+PDFX_NAMESPACE = "http://ns.adobe.com/pdfx/1.3/"
+
iso8601 = re.compile(
"""
(?P<year>[0-9]{4})
@@ -34,9 +66,138 @@ iso8601 = re.compile(
)?
)?
)?
- """
- , re.VERBOSE)
-K = TypeVar('K')
+ """,
+ re.VERBOSE,
+)
+
+
+K = TypeVar("K")
+
+
+def _identity(value: K) -> K:
+ return value
+
+
+def _converter_date(value: str) -> datetime.datetime:
+ matches = iso8601.match(value)
+ if matches is None:
+ raise ValueError(f"Invalid date format: {value}")
+ year = int(matches.group("year"))
+ month = int(matches.group("month") or "1")
+ day = int(matches.group("day") or "1")
+ hour = int(matches.group("hour") or "0")
+ minute = int(matches.group("minute") or "0")
+ second = decimal.Decimal(matches.group("second") or "0")
+ seconds_dec = second.to_integral(decimal.ROUND_FLOOR)
+ milliseconds_dec = (second - seconds_dec) * 1_000_000
+
+ seconds = int(seconds_dec)
+ milliseconds = int(milliseconds_dec)
+
+ tzd = matches.group("tzd") or "Z"
+ dt = datetime.datetime(year, month, day, hour, minute, seconds, milliseconds)
+ if tzd != "Z":
+ tzd_hours, tzd_minutes = (int(x) for x in tzd.split(":"))
+ tzd_hours *= -1
+ if tzd_hours < 0:
+ tzd_minutes *= -1
+ dt = dt + datetime.timedelta(hours=tzd_hours, minutes=tzd_minutes)
+ return dt
+
+
+def _getter_bag(
+ namespace: str, name: str
+) -> Callable[["XmpInformation"], Optional[List[str]]]:
+ def get(self: "XmpInformation") -> Optional[List[str]]:
+ cached = self.cache.get(namespace, {}).get(name)
+ if cached:
+ return cached
+ retval = []
+ for element in self.get_element("", namespace, name):
+ bags = element.getElementsByTagNameNS(RDF_NAMESPACE, "Bag")
+ if len(bags):
+ for bag in bags:
+ for item in bag.getElementsByTagNameNS(RDF_NAMESPACE, "li"):
+ value = self._get_text(item)
+ retval.append(value)
+ ns_cache = self.cache.setdefault(namespace, {})
+ ns_cache[name] = retval
+ return retval
+
+ return get
+
+
+def _getter_seq(
+ namespace: str, name: str, converter: Callable[[Any], Any] = _identity
+) -> Callable[["XmpInformation"], Optional[List[Any]]]:
+ def get(self: "XmpInformation") -> Optional[List[Any]]:
+ cached = self.cache.get(namespace, {}).get(name)
+ if cached:
+ return cached
+ retval = []
+ for element in self.get_element("", namespace, name):
+ seqs = element.getElementsByTagNameNS(RDF_NAMESPACE, "Seq")
+ if len(seqs):
+ for seq in seqs:
+ for item in seq.getElementsByTagNameNS(RDF_NAMESPACE, "li"):
+ value = self._get_text(item)
+ value = converter(value)
+ retval.append(value)
+ else:
+ value = converter(self._get_text(element))
+ retval.append(value)
+ ns_cache = self.cache.setdefault(namespace, {})
+ ns_cache[name] = retval
+ return retval
+
+ return get
+
+
+def _getter_langalt(
+ namespace: str, name: str
+) -> Callable[["XmpInformation"], Optional[Dict[Any, Any]]]:
+ def get(self: "XmpInformation") -> Optional[Dict[Any, Any]]:
+ cached = self.cache.get(namespace, {}).get(name)
+ if cached:
+ return cached
+ retval = {}
+ for element in self.get_element("", namespace, name):
+ alts = element.getElementsByTagNameNS(RDF_NAMESPACE, "Alt")
+ if len(alts):
+ for alt in alts:
+ for item in alt.getElementsByTagNameNS(RDF_NAMESPACE, "li"):
+ value = self._get_text(item)
+ retval[item.getAttribute("xml:lang")] = value
+ else:
+ retval["x-default"] = self._get_text(element)
+ ns_cache = self.cache.setdefault(namespace, {})
+ ns_cache[name] = retval
+ return retval
+
+ return get
+
+
+def _getter_single(
+ namespace: str, name: str, converter: Callable[[str], Any] = _identity
+) -> Callable[["XmpInformation"], Optional[Any]]:
+ def get(self: "XmpInformation") -> Optional[Any]:
+ cached = self.cache.get(namespace, {}).get(name)
+ if cached:
+ return cached
+ value = None
+ for element in self.get_element("", namespace, name):
+ if element.nodeType == element.ATTRIBUTE_NODE:
+ value = element.nodeValue
+ else:
+ value = self._get_text(element)
+ break
+ if value is not None:
+ value = converter(value)
+ ns_cache = self.cache.setdefault(namespace, {})
+ ns_cache[name] = value
+ return value
+
+ return get
class XmpInformation(PdfObject):
@@ -48,97 +209,160 @@ class XmpInformation(PdfObject):
PdfReadError: if XML is invalid
"""
- def __init__(self, stream: ContentStream) ->None:
+ def __init__(self, stream: ContentStream) -> None:
self.stream = stream
try:
data = self.stream.get_data()
- doc_root: Document = parseString(data)
+ doc_root: Document = parseString(data) # noqa: S318
except ExpatError as e:
- raise PdfReadError(f'XML in XmpInformation was invalid: {e}')
+ raise PdfReadError(f"XML in XmpInformation was invalid: {e}")
self.rdf_root: XmlElement = doc_root.getElementsByTagNameNS(
- RDF_NAMESPACE, 'RDF')[0]
+ RDF_NAMESPACE, "RDF"
+ )[0]
self.cache: Dict[Any, Any] = {}
- dc_contributor = property(_getter_bag(DC_NAMESPACE, 'contributor'))
+
+ def write_to_stream(
+ self, stream: StreamType, encryption_key: Union[None, str, bytes] = None
+ ) -> None:
+ if encryption_key is not None: # deprecated
+ deprecate_no_replacement(
+ "the encryption_key parameter of write_to_stream", "5.0.0"
+ )
+ self.stream.write_to_stream(stream)
+
+ def get_element(self, about_uri: str, namespace: str, name: str) -> Iterator[Any]:
+ for desc in self.rdf_root.getElementsByTagNameNS(RDF_NAMESPACE, "Description"):
+ if desc.getAttributeNS(RDF_NAMESPACE, "about") == about_uri:
+ attr = desc.getAttributeNodeNS(namespace, name)
+ if attr is not None:
+ yield attr
+ yield from desc.getElementsByTagNameNS(namespace, name)
+
+ def get_nodes_in_namespace(self, about_uri: str, namespace: str) -> Iterator[Any]:
+ for desc in self.rdf_root.getElementsByTagNameNS(RDF_NAMESPACE, "Description"):
+ if desc.getAttributeNS(RDF_NAMESPACE, "about") == about_uri:
+ for i in range(desc.attributes.length):
+ attr = desc.attributes.item(i)
+ if attr.namespaceURI == namespace:
+ yield attr
+ for child in desc.childNodes:
+ if child.namespaceURI == namespace:
+ yield child
+
+ def _get_text(self, element: XmlElement) -> str:
+ text = ""
+ for child in element.childNodes:
+ if child.nodeType == child.TEXT_NODE:
+ text += child.data
+ return text
+
+ dc_contributor = property(_getter_bag(DC_NAMESPACE, "contributor"))
"""
Contributors to the resource (other than the authors).
An unsorted array of names.
"""
- dc_coverage = property(_getter_single(DC_NAMESPACE, 'coverage'))
+
+ 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'))
+
+ 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))
+
+ 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'))
+
+ 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'))
+
+ dc_format = property(_getter_single(DC_NAMESPACE, "format"))
"""The mime-type of the resource."""
- dc_identifier = property(_getter_single(DC_NAMESPACE, 'identifier'))
+
+ dc_identifier = property(_getter_single(DC_NAMESPACE, "identifier"))
"""Unique identifier of the resource."""
- dc_language = property(_getter_bag(DC_NAMESPACE, 'language'))
+
+ 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'))
+
+ dc_publisher = property(_getter_bag(DC_NAMESPACE, "publisher"))
"""An unordered array of publisher names."""
- dc_relation = property(_getter_bag(DC_NAMESPACE, 'relation'))
+
+ 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'))
+
+ 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'))
+
+ 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'))
+
+ 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'))
+
+ 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'))
+
+ 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'))
+
+ pdf_keywords = property(_getter_single(PDF_NAMESPACE, "Keywords"))
"""An unformatted text string representing document keywords."""
- pdf_pdfversion = property(_getter_single(PDF_NAMESPACE, 'PDFVersion'))
+
+ pdf_pdfversion = property(_getter_single(PDF_NAMESPACE, "PDFVersion"))
"""The PDF file version, for example 1.0 or 1.3."""
- pdf_producer = property(_getter_single(PDF_NAMESPACE, 'Producer'))
+
+ 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))
+
+ xmp_create_date = property(
+ _getter_single(XMP_NAMESPACE, "CreateDate", _converter_date)
+ )
"""
The date and time the resource was originally created.
The date and time are returned as a UTC datetime.datetime object.
"""
- xmp_modify_date = property(_getter_single(XMP_NAMESPACE, 'ModifyDate',
- _converter_date))
+
+ xmp_modify_date = property(
+ _getter_single(XMP_NAMESPACE, "ModifyDate", _converter_date)
+ )
"""
The date and time the resource was last modified.
The date and time are returned as a UTC datetime.datetime object.
"""
- xmp_metadata_date = property(_getter_single(XMP_NAMESPACE,
- 'MetadataDate', _converter_date))
+
+ xmp_metadata_date = property(
+ _getter_single(XMP_NAMESPACE, "MetadataDate", _converter_date)
+ )
"""
The date and time that any metadata for this resource was last changed.
The date and time are returned as a UTC datetime.datetime object.
"""
- xmp_creator_tool = property(_getter_single(XMP_NAMESPACE, 'CreatorTool'))
+
+ xmp_creator_tool = property(_getter_single(XMP_NAMESPACE, "CreatorTool"))
"""The name of the first known tool used to create the resource."""
- xmpmm_document_id = property(_getter_single(XMPMM_NAMESPACE, 'DocumentID'))
+
+ xmpmm_document_id = property(_getter_single(XMPMM_NAMESPACE, "DocumentID"))
"""The common identifier for all versions and renditions of this resource."""
- xmpmm_instance_id = property(_getter_single(XMPMM_NAMESPACE, 'InstanceID'))
+
+ xmpmm_instance_id = property(_getter_single(XMPMM_NAMESPACE, "InstanceID"))
"""An identifier for a specific incarnation of a document, updated each
time a file is saved."""
@property
- def custom_properties(self) ->Dict[Any, Any]:
+ def custom_properties(self) -> Dict[Any, Any]:
"""
Retrieve custom metadata properties defined in the undocumented pdfx
metadata schema.
@@ -146,4 +370,23 @@ class XmpInformation(PdfObject):
Returns:
A dictionary of key/value items for custom metadata properties.
"""
- pass
+ 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