Packages

Pure Elixir PDF utilities for tokenizing, merging, text extraction, and native HTML/CSS rendering.

Current section

Files

Jump to
native_elixir_pdf_utilities lib pdf glyph_name.ex
Raw

lib/pdf/glyph_name.ex

# The glyph-name assignments follow the Adobe Glyph List and ITC Zapf Dingbats
# Glyph List. The Elixir lookup and decoding implementation is maintained here.
#
# 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:
#
# 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 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.
defmodule NativeElixirPdfUtilities.Pdf.GlyphName do
@moduledoc "Converts glyph names used by supported PDF simple-font encodings to Unicode."
@glyphs %{
"A" => "A",
"AE" => "Æ",
"AEsmall" => "",
"Aacute" => "Á",
"Aacutesmall" => "",
"Acircumflex" => "Â",
"Acircumflexsmall" => "",
"Acutesmall" => "",
"Adieresis" => "Ä",
"Adieresissmall" => "",
"Agrave" => "À",
"Agravesmall" => "",
"Alpha" => "Α",
"Aring" => "Å",
"Aringsmall" => "",
"Asmall" => "",
"Atilde" => "Ã",
"Atildesmall" => "",
"B" => "B",
"Beta" => "Β",
"Brevesmall" => "",
"Bsmall" => "",
"C" => "C",
"Caronsmall" => "",
"Ccedilla" => "Ç",
"Ccedillasmall" => "",
"Cedillasmall" => "",
"Chi" => "Χ",
"Circumflexsmall" => "",
"Csmall" => "",
"D" => "D",
"Delta" => "∆",
"Dieresissmall" => "",
"Dotaccentsmall" => "",
"Dsmall" => "",
"E" => "E",
"Eacute" => "É",
"Eacutesmall" => "",
"Ecircumflex" => "Ê",
"Ecircumflexsmall" => "",
"Edieresis" => "Ë",
"Edieresissmall" => "",
"Egrave" => "È",
"Egravesmall" => "",
"Epsilon" => "Ε",
"Esmall" => "",
"Eta" => "Η",
"Eth" => "Ð",
"Ethsmall" => "",
"Euro" => "€",
"F" => "F",
"Fsmall" => "",
"G" => "G",
"Gamma" => "Γ",
"Gravesmall" => "",
"Gsmall" => "",
"H" => "H",
"Hsmall" => "",
"Hungarumlautsmall" => "",
"I" => "I",
"Iacute" => "Í",
"Iacutesmall" => "",
"Icircumflex" => "Î",
"Icircumflexsmall" => "",
"Idieresis" => "Ï",
"Idieresissmall" => "",
"Ifraktur" => "ℑ",
"Igrave" => "Ì",
"Igravesmall" => "",
"Iota" => "Ι",
"Ismall" => "",
"J" => "J",
"Jsmall" => "",
"K" => "K",
"Kappa" => "Κ",
"Ksmall" => "",
"L" => "L",
"Lambda" => "Λ",
"Lslash" => "Ł",
"Lslashsmall" => "",
"Lsmall" => "",
"M" => "M",
"Macronsmall" => "",
"Msmall" => "",
"Mu" => "Μ",
"N" => "N",
"Nsmall" => "",
"Ntilde" => "Ñ",
"Ntildesmall" => "",
"Nu" => "Ν",
"O" => "O",
"OE" => "Œ",
"OEsmall" => "",
"Oacute" => "Ó",
"Oacutesmall" => "",
"Ocircumflex" => "Ô",
"Ocircumflexsmall" => "",
"Odieresis" => "Ö",
"Odieresissmall" => "",
"Ogoneksmall" => "",
"Ograve" => "Ò",
"Ogravesmall" => "",
"Omega" => "Ω",
"Omicron" => "Ο",
"Oslash" => "Ø",
"Oslashsmall" => "",
"Osmall" => "",
"Otilde" => "Õ",
"Otildesmall" => "",
"P" => "P",
"Phi" => "Φ",
"Pi" => "Π",
"Psi" => "Ψ",
"Psmall" => "",
"Q" => "Q",
"Qsmall" => "",
"R" => "R",
"Rfraktur" => "ℜ",
"Rho" => "Ρ",
"Ringsmall" => "",
"Rsmall" => "",
"S" => "S",
"Scaron" => "Š",
"Scaronsmall" => "",
"Sigma" => "Σ",
"Ssmall" => "",
"T" => "T",
"Tau" => "Τ",
"Theta" => "Θ",
"Thorn" => "Þ",
"Thornsmall" => "",
"Tildesmall" => "",
"Tsmall" => "",
"U" => "U",
"Uacute" => "Ú",
"Uacutesmall" => "",
"Ucircumflex" => "Û",
"Ucircumflexsmall" => "",
"Udieresis" => "Ü",
"Udieresissmall" => "",
"Ugrave" => "Ù",
"Ugravesmall" => "",
"Upsilon" => "Υ",
"Upsilon1" => "ϒ",
"Usmall" => "",
"V" => "V",
"Vsmall" => "",
"W" => "W",
"Wsmall" => "",
"X" => "X",
"Xi" => "Ξ",
"Xsmall" => "",
"Y" => "Y",
"Yacute" => "Ý",
"Yacutesmall" => "",
"Ydieresis" => "Ÿ",
"Ydieresissmall" => "",
"Ysmall" => "",
"Z" => "Z",
"Zcaron" => "Ž",
"Zcaronsmall" => "",
"Zeta" => "Ζ",
"Zsmall" => "",
"a" => "a",
"a1" => "✁",
"a10" => "✡",
"a100" => "❞",
"a101" => "❡",
"a102" => "❢",
"a103" => "❣",
"a104" => "❤",
"a105" => "✐",
"a106" => "❥",
"a107" => "❦",
"a108" => "❧",
"a109" => "♠",
"a11" => "☛",
"a110" => "♥",
"a111" => "♦",
"a112" => "♣",
"a117" => "✉",
"a118" => "✈",
"a119" => "✇",
"a12" => "☞",
"a120" => "①",
"a121" => "②",
"a122" => "③",
"a123" => "④",
"a124" => "⑤",
"a125" => "⑥",
"a126" => "⑦",
"a127" => "⑧",
"a128" => "⑨",
"a129" => "⑩",
"a13" => "✌",
"a130" => "❶",
"a131" => "❷",
"a132" => "❸",
"a133" => "❹",
"a134" => "❺",
"a135" => "❻",
"a136" => "❼",
"a137" => "❽",
"a138" => "❾",
"a139" => "❿",
"a14" => "✍",
"a140" => "➀",
"a141" => "➁",
"a142" => "➂",
"a143" => "➃",
"a144" => "➄",
"a145" => "➅",
"a146" => "➆",
"a147" => "➇",
"a148" => "➈",
"a149" => "➉",
"a15" => "✎",
"a150" => "➊",
"a151" => "➋",
"a152" => "➌",
"a153" => "➍",
"a154" => "➎",
"a155" => "➏",
"a156" => "➐",
"a157" => "➑",
"a158" => "➒",
"a159" => "➓",
"a16" => "✏",
"a160" => "➔",
"a161" => "→",
"a162" => "➣",
"a163" => "↔",
"a164" => "↕",
"a165" => "➙",
"a166" => "➛",
"a167" => "➜",
"a168" => "➝",
"a169" => "➞",
"a17" => "✑",
"a170" => "➟",
"a171" => "➠",
"a172" => "➡",
"a173" => "➢",
"a174" => "➤",
"a175" => "➥",
"a176" => "➦",
"a177" => "➧",
"a178" => "➨",
"a179" => "➩",
"a18" => "✒",
"a180" => "➫",
"a181" => "➭",
"a182" => "➯",
"a183" => "➲",
"a184" => "➳",
"a185" => "➵",
"a186" => "➸",
"a187" => "➺",
"a188" => "➻",
"a189" => "➼",
"a19" => "✓",
"a190" => "➽",
"a191" => "➾",
"a192" => "➚",
"a193" => "➪",
"a194" => "➶",
"a195" => "➹",
"a196" => "➘",
"a197" => "➴",
"a198" => "➷",
"a199" => "➬",
"a2" => "✂",
"a20" => "✔",
"a200" => "➮",
"a201" => "➱",
"a202" => "✃",
"a203" => "❐",
"a204" => "❒",
"a205" => "❮",
"a206" => "❰",
"a21" => "✕",
"a22" => "✖",
"a23" => "✗",
"a24" => "✘",
"a25" => "✙",
"a26" => "✚",
"a27" => "✛",
"a28" => "✜",
"a29" => "✢",
"a3" => "✄",
"a30" => "✣",
"a31" => "✤",
"a32" => "✥",
"a33" => "✦",
"a34" => "✧",
"a35" => "★",
"a36" => "✩",
"a37" => "✪",
"a38" => "✫",
"a39" => "✬",
"a4" => "☎",
"a40" => "✭",
"a41" => "✮",
"a42" => "✯",
"a43" => "✰",
"a44" => "✱",
"a45" => "✲",
"a46" => "✳",
"a47" => "✴",
"a48" => "✵",
"a49" => "✶",
"a5" => "✆",
"a50" => "✷",
"a51" => "✸",
"a52" => "✹",
"a53" => "✺",
"a54" => "✻",
"a55" => "✼",
"a56" => "✽",
"a57" => "✾",
"a58" => "✿",
"a59" => "❀",
"a6" => "✝",
"a60" => "❁",
"a61" => "❂",
"a62" => "❃",
"a63" => "❄",
"a64" => "❅",
"a65" => "❆",
"a66" => "❇",
"a67" => "❈",
"a68" => "❉",
"a69" => "❊",
"a7" => "✞",
"a70" => "❋",
"a71" => "●",
"a72" => "❍",
"a73" => "■",
"a74" => "❏",
"a75" => "❑",
"a76" => "▲",
"a77" => "▼",
"a78" => "◆",
"a79" => "❖",
"a8" => "✟",
"a81" => "◗",
"a82" => "❘",
"a83" => "❙",
"a84" => "❚",
"a85" => "❯",
"a86" => "❱",
"a87" => "❲",
"a88" => "❳",
"a89" => "❨",
"a9" => "✠",
"a90" => "❩",
"a91" => "❬",
"a92" => "❭",
"a93" => "❪",
"a94" => "❫",
"a95" => "❴",
"a96" => "❵",
"a97" => "❛",
"a98" => "❜",
"a99" => "❝",
"aacute" => "á",
"acircumflex" => "â",
"acute" => "´",
"adieresis" => "ä",
"ae" => "æ",
"agrave" => "à",
"aleph" => "ℵ",
"alpha" => "α",
"ampersand" => "&",
"ampersandsmall" => "",
"angle" => "∠",
"angleleft" => "〈",
"angleright" => "〉",
"approxequal" => "≈",
"aring" => "å",
"arrowboth" => "↔",
"arrowdblboth" => "⇔",
"arrowdbldown" => "⇓",
"arrowdblleft" => "⇐",
"arrowdblright" => "⇒",
"arrowdblup" => "⇑",
"arrowdown" => "↓",
"arrowhorizex" => "",
"arrowleft" => "←",
"arrowright" => "→",
"arrowup" => "↑",
"arrowvertex" => "",
"asciicircum" => "^",
"asciitilde" => "~",
"asterisk" => "*",
"asteriskmath" => "∗",
"asuperior" => "",
"at" => "@",
"atilde" => "ã",
"b" => "b",
"backslash" => "\\",
"bar" => "|",
"beta" => "β",
"braceex" => "",
"braceleft" => "{",
"braceleftbt" => "",
"braceleftmid" => "",
"bracelefttp" => "",
"braceright" => "}",
"bracerightbt" => "",
"bracerightmid" => "",
"bracerighttp" => "",
"bracketleft" => "[",
"bracketleftbt" => "",
"bracketleftex" => "",
"bracketlefttp" => "",
"bracketright" => "]",
"bracketrightbt" => "",
"bracketrightex" => "",
"bracketrighttp" => "",
"breve" => "˘",
"brokenbar" => "¦",
"bsuperior" => "",
"bullet" => "•",
"c" => "c",
"caron" => "ˇ",
"carriagereturn" => "↵",
"ccedilla" => "ç",
"cedilla" => "¸",
"cent" => "¢",
"centinferior" => "",
"centoldstyle" => "",
"centsuperior" => "",
"chi" => "χ",
"circlemultiply" => "⊗",
"circleplus" => "⊕",
"circumflex" => "ˆ",
"club" => "♣",
"colon" => ":",
"colonmonetary" => "₡",
"comma" => ",",
"commainferior" => "",
"commasuperior" => "",
"congruent" => "≅",
"copyright" => "©",
"copyrightsans" => "",
"copyrightserif" => "",
"currency" => "¤",
"d" => "d",
"dagger" => "†",
"daggerdbl" => "‡",
"degree" => "°",
"delta" => "δ",
"diamond" => "♦",
"dieresis" => "¨",
"divide" => "÷",
"dollar" => "$",
"dollarinferior" => "",
"dollaroldstyle" => "",
"dollarsuperior" => "",
"dotaccent" => "˙",
"dotlessi" => "ı",
"dotmath" => "⋅",
"dsuperior" => "",
"e" => "e",
"eacute" => "é",
"ecircumflex" => "ê",
"edieresis" => "ë",
"egrave" => "è",
"eight" => "8",
"eightinferior" => "₈",
"eightoldstyle" => "",
"eightsuperior" => "⁸",
"element" => "∈",
"ellipsis" => "…",
"emdash" => "—",
"emptyset" => "∅",
"endash" => "–",
"epsilon" => "ε",
"equal" => "=",
"equivalence" => "≡",
"esuperior" => "",
"eta" => "η",
"eth" => "ð",
"exclam" => "!",
"exclamdown" => "¡",
"exclamdownsmall" => "",
"exclamsmall" => "",
"existential" => "∃",
"f" => "f",
"ff" => "ff",
"ffi" => "ffi",
"ffl" => "ffl",
"fi" => "fi",
"figuredash" => "‒",
"five" => "5",
"fiveeighths" => "⅝",
"fiveinferior" => "₅",
"fiveoldstyle" => "",
"fivesuperior" => "⁵",
"fl" => "fl",
"florin" => "ƒ",
"four" => "4",
"fourinferior" => "₄",
"fouroldstyle" => "",
"foursuperior" => "⁴",
"fraction" => "⁄",
"g" => "g",
"gamma" => "γ",
"germandbls" => "ß",
"gradient" => "∇",
"grave" => "`",
"greater" => ">",
"greaterequal" => "≥",
"guillemotleft" => "«",
"guillemotright" => "»",
"guilsinglleft" => "‹",
"guilsinglright" => "›",
"h" => "h",
"heart" => "♥",
"hungarumlaut" => "˝",
"hyphen" => "-",
"hypheninferior" => "",
"hyphensuperior" => "",
"i" => "i",
"iacute" => "í",
"icircumflex" => "î",
"idieresis" => "ï",
"igrave" => "ì",
"infinity" => "∞",
"integral" => "∫",
"integralbt" => "⌡",
"integralex" => "",
"integraltp" => "⌠",
"intersection" => "∩",
"iota" => "ι",
"isuperior" => "",
"j" => "j",
"k" => "k",
"kappa" => "κ",
"l" => "l",
"lambda" => "λ",
"less" => "<",
"lessequal" => "≤",
"logicaland" => "∧",
"logicalnot" => "¬",
"logicalor" => "∨",
"lozenge" => "◊",
"lslash" => "ł",
"lsuperior" => "",
"m" => "m",
"macron" => "¯",
"minus" => "−",
"minute" => "′",
"msuperior" => "",
"mu" => "µ",
"multiply" => "×",
"n" => "n",
"nine" => "9",
"nineinferior" => "₉",
"nineoldstyle" => "",
"ninesuperior" => "⁹",
"notelement" => "∉",
"notequal" => "≠",
"notsubset" => "⊄",
"nsuperior" => "ⁿ",
"ntilde" => "ñ",
"nu" => "ν",
"numbersign" => "#",
"o" => "o",
"oacute" => "ó",
"ocircumflex" => "ô",
"odieresis" => "ö",
"oe" => "œ",
"ogonek" => "˛",
"ograve" => "ò",
"omega" => "ω",
"omega1" => "ϖ",
"omicron" => "ο",
"one" => "1",
"onedotenleader" => "․",
"oneeighth" => "⅛",
"onefitted" => "",
"onehalf" => "½",
"oneinferior" => "₁",
"oneoldstyle" => "",
"onequarter" => "¼",
"onesuperior" => "¹",
"onethird" => "⅓",
"ordfeminine" => "ª",
"ordmasculine" => "º",
"oslash" => "ø",
"osuperior" => "",
"otilde" => "õ",
"p" => "p",
"paragraph" => "¶",
"parenleft" => "(",
"parenleftbt" => "",
"parenleftex" => "",
"parenleftinferior" => "₍",
"parenleftsuperior" => "⁽",
"parenlefttp" => "",
"parenright" => ")",
"parenrightbt" => "",
"parenrightex" => "",
"parenrightinferior" => "₎",
"parenrightsuperior" => "⁾",
"parenrighttp" => "",
"partialdiff" => "∂",
"percent" => "%",
"period" => ".",
"periodcentered" => "·",
"periodinferior" => "",
"periodsuperior" => "",
"perpendicular" => "⊥",
"perthousand" => "‰",
"phi" => "φ",
"phi1" => "ϕ",
"pi" => "π",
"plus" => "+",
"plusminus" => "±",
"product" => "∏",
"propersubset" => "⊂",
"propersuperset" => "⊃",
"proportional" => "∝",
"psi" => "ψ",
"q" => "q",
"question" => "?",
"questiondown" => "¿",
"questiondownsmall" => "",
"questionsmall" => "",
"quotedbl" => "\"",
"quotedblbase" => "„",
"quotedblleft" => "“",
"quotedblright" => "”",
"quoteleft" => "‘",
"quoteright" => "’",
"quotesinglbase" => "‚",
"quotesingle" => "'",
"r" => "r",
"radical" => "√",
"radicalex" => "",
"reflexsubset" => "⊆",
"reflexsuperset" => "⊇",
"registered" => "®",
"registersans" => "",
"registerserif" => "",
"rho" => "ρ",
"ring" => "˚",
"rsuperior" => "",
"rupiah" => "",
"s" => "s",
"scaron" => "š",
"second" => "″",
"section" => "§",
"semicolon" => ";",
"seven" => "7",
"seveneighths" => "⅞",
"seveninferior" => "₇",
"sevenoldstyle" => "",
"sevensuperior" => "⁷",
"sigma" => "σ",
"sigma1" => "ς",
"similar" => "∼",
"six" => "6",
"sixinferior" => "₆",
"sixoldstyle" => "",
"sixsuperior" => "⁶",
"slash" => "/",
"space" => " ",
"spade" => "♠",
"ssuperior" => "",
"sterling" => "£",
"suchthat" => "∋",
"summation" => "∑",
"t" => "t",
"tau" => "τ",
"therefore" => "∴",
"theta" => "θ",
"theta1" => "ϑ",
"thorn" => "þ",
"three" => "3",
"threeeighths" => "⅜",
"threeinferior" => "₃",
"threeoldstyle" => "",
"threequarters" => "¾",
"threequartersemdash" => "",
"threesuperior" => "³",
"tilde" => "˜",
"trademark" => "™",
"trademarksans" => "",
"trademarkserif" => "",
"tsuperior" => "",
"two" => "2",
"twodotenleader" => "‥",
"twoinferior" => "₂",
"twooldstyle" => "",
"twosuperior" => "²",
"twothirds" => "⅔",
"u" => "u",
"uacute" => "ú",
"ucircumflex" => "û",
"udieresis" => "ü",
"ugrave" => "ù",
"underscore" => "_",
"union" => "∪",
"universal" => "∀",
"upsilon" => "υ",
"v" => "v",
"w" => "w",
"weierstrass" => "℘",
"x" => "x",
"xi" => "ξ",
"y" => "y",
"yacute" => "ý",
"ydieresis" => "ÿ",
"yen" => "¥",
"z" => "z",
"zcaron" => "ž",
"zero" => "0",
"zeroinferior" => "₀",
"zerooldstyle" => "",
"zerosuperior" => "⁰",
"zeta" => "ζ"
}
@doc "Converts a PDF glyph name to its Unicode text representation."
@spec to_unicode(term()) :: {:ok, String.t()} | :error
def to_unicode(name) do
case name do
name when is_binary(name) ->
if String.valid?(name) do
base = name |> String.split(".", parts: 2) |> hd()
case Map.get(@glyphs, base) do
text when is_binary(text) -> {:ok, text}
nil -> derived_glyph(base)
end
else
:error
end
_ ->
:error
end
end
defp derived_glyph(name) do
parts = String.split(name, "_")
cond do
length(parts) > 1 ->
parts
|> Enum.reduce_while({:ok, []}, fn part, {:ok, characters} ->
case to_unicode(part) do
{:ok, character} -> {:cont, {:ok, [character | characters]}}
:error -> {:halt, :error}
end
end)
|> case do
{:ok, characters} -> {:ok, characters |> Enum.reverse() |> Enum.join()}
:error -> :error
end
String.starts_with?(name, "uni") ->
name |> String.trim_leading("uni") |> unicode_chunks()
String.starts_with?(name, "u") ->
name |> String.trim_leading("u") |> unicode_scalar()
true ->
:error
end
end
defp unicode_chunks(hex) do
if byte_size(hex) > 0 and rem(byte_size(hex), 4) == 0 do
hex
|> String.codepoints()
|> Enum.chunk_every(4)
|> Enum.reduce_while({:ok, []}, fn chunk, {:ok, characters} ->
case unicode_scalar(Enum.join(chunk)) do
{:ok, character} -> {:cont, {:ok, [character | characters]}}
:error -> {:halt, :error}
end
end)
|> case do
{:ok, characters} -> {:ok, characters |> Enum.reverse() |> Enum.join()}
:error -> :error
end
else
:error
end
end
defp unicode_scalar(hex) do
case Integer.parse(hex, 16) do
{value, ""} when value >= 0 and value <= 0x10FFFF and value not in 0xD800..0xDFFF ->
{:ok, <<value::utf8>>}
_ ->
:error
end
end
end