# 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, <>} _ -> :error end end end