• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fpdfapi/font/cpdf_truetypefont.h"
8 
9 #include <algorithm>
10 #include <utility>
11 
12 #include "core/fpdfapi/parser/cpdf_dictionary.h"
13 #include "core/fxge/fx_font.h"
14 
15 namespace {
16 
17 constexpr uint8_t kPrefix[4] = {0x00, 0xf0, 0xf1, 0xf2};
18 
GetGlyphIndexForMSSymbol(FXFT_FaceRec * face,uint32_t charcode)19 uint16_t GetGlyphIndexForMSSymbol(FXFT_FaceRec* face, uint32_t charcode) {
20   for (uint8_t c : kPrefix) {
21     uint16_t unicode = c * 256 + charcode;
22     uint16_t val = FT_Get_Char_Index(face, unicode);
23     if (val)
24       return val;
25   }
26   return 0;
27 }
28 
IsWinAnsiOrMacRomanEncoding(FontEncoding encoding)29 bool IsWinAnsiOrMacRomanEncoding(FontEncoding encoding) {
30   return encoding == FontEncoding::kWinAnsi ||
31          encoding == FontEncoding::kMacRoman;
32 }
33 
34 }  // namespace
35 
CPDF_TrueTypeFont(CPDF_Document * pDocument,RetainPtr<CPDF_Dictionary> pFontDict)36 CPDF_TrueTypeFont::CPDF_TrueTypeFont(CPDF_Document* pDocument,
37                                      RetainPtr<CPDF_Dictionary> pFontDict)
38     : CPDF_SimpleFont(pDocument, std::move(pFontDict)) {}
39 
40 CPDF_TrueTypeFont::~CPDF_TrueTypeFont() = default;
41 
IsTrueTypeFont() const42 bool CPDF_TrueTypeFont::IsTrueTypeFont() const {
43   return true;
44 }
45 
AsTrueTypeFont() const46 const CPDF_TrueTypeFont* CPDF_TrueTypeFont::AsTrueTypeFont() const {
47   return this;
48 }
49 
AsTrueTypeFont()50 CPDF_TrueTypeFont* CPDF_TrueTypeFont::AsTrueTypeFont() {
51   return this;
52 }
53 
Load()54 bool CPDF_TrueTypeFont::Load() {
55   return LoadCommon();
56 }
57 
LoadGlyphMap()58 void CPDF_TrueTypeFont::LoadGlyphMap() {
59   FXFT_FaceRec* face = m_Font.GetFaceRec();
60   if (!face)
61     return;
62 
63   const FontEncoding base_encoding = DetermineEncoding();
64   if ((IsWinAnsiOrMacRomanEncoding(base_encoding) && m_CharNames.empty()) ||
65       FontStyleIsNonSymbolic(m_Flags)) {
66     if (!FXFT_Has_Glyph_Names(face) &&
67         (!face->num_charmaps || !face->charmaps)) {
68       SetGlyphIndicesFromFirstChar();
69       return;
70     }
71 
72     const CharmapType charmap_type = DetermineCharmapType();
73     bool bToUnicode = m_pFontDict->KeyExist("ToUnicode");
74     for (uint32_t charcode = 0; charcode < 256; charcode++) {
75       const char* name = GetAdobeCharName(base_encoding, m_CharNames, charcode);
76       if (!name) {
77         m_GlyphIndex[charcode] =
78             m_pFontFile ? FT_Get_Char_Index(face, charcode) : -1;
79         continue;
80       }
81       m_Encoding.SetUnicode(charcode, UnicodeFromAdobeName(name));
82       if (charmap_type == CharmapType::kMSSymbol) {
83         m_GlyphIndex[charcode] = GetGlyphIndexForMSSymbol(face, charcode);
84       } else if (m_Encoding.UnicodeFromCharCode(charcode)) {
85         if (charmap_type == CharmapType::kMSUnicode) {
86           m_GlyphIndex[charcode] =
87               FT_Get_Char_Index(face, m_Encoding.UnicodeFromCharCode(charcode));
88         } else if (charmap_type == CharmapType::kMacRoman) {
89           uint32_t maccode = CharCodeFromUnicodeForFreetypeEncoding(
90               FT_ENCODING_APPLE_ROMAN,
91               m_Encoding.UnicodeFromCharCode(charcode));
92           if (!maccode) {
93             m_GlyphIndex[charcode] = FT_Get_Name_Index(face, name);
94           } else {
95             m_GlyphIndex[charcode] = FT_Get_Char_Index(face, maccode);
96           }
97         }
98       }
99       if ((m_GlyphIndex[charcode] != 0 && m_GlyphIndex[charcode] != 0xffff) ||
100           !name) {
101         continue;
102       }
103       if (strcmp(name, ".notdef") == 0) {
104         m_GlyphIndex[charcode] = FT_Get_Char_Index(face, 32);
105         continue;
106       }
107       m_GlyphIndex[charcode] = FT_Get_Name_Index(face, name);
108       if (m_GlyphIndex[charcode] != 0 || !bToUnicode)
109         continue;
110 
111       WideString wsUnicode = UnicodeFromCharCode(charcode);
112       if (!wsUnicode.IsEmpty()) {
113         m_GlyphIndex[charcode] = FT_Get_Char_Index(face, wsUnicode[0]);
114         m_Encoding.SetUnicode(charcode, wsUnicode[0]);
115       }
116     }
117     return;
118   }
119   if (UseTTCharmapMSSymbol(face)) {
120     for (uint32_t charcode = 0; charcode < 256; charcode++)
121       m_GlyphIndex[charcode] = GetGlyphIndexForMSSymbol(face, charcode);
122     if (HasAnyGlyphIndex()) {
123       if (base_encoding != FontEncoding::kBuiltin) {
124         for (uint32_t charcode = 0; charcode < 256; charcode++) {
125           const char* name =
126               GetAdobeCharName(base_encoding, m_CharNames, charcode);
127           if (name)
128             m_Encoding.SetUnicode(charcode, UnicodeFromAdobeName(name));
129         }
130       } else if (UseTTCharmapMacRoman(face)) {
131         for (uint32_t charcode = 0; charcode < 256; charcode++) {
132           m_Encoding.SetUnicode(charcode,
133                                 UnicodeFromAppleRomanCharCode(charcode));
134         }
135       }
136       return;
137     }
138   }
139   if (UseTTCharmapMacRoman(face)) {
140     for (uint32_t charcode = 0; charcode < 256; charcode++) {
141       m_GlyphIndex[charcode] = FT_Get_Char_Index(face, charcode);
142       m_Encoding.SetUnicode(charcode, UnicodeFromAppleRomanCharCode(charcode));
143     }
144     if (m_pFontFile || HasAnyGlyphIndex())
145       return;
146   }
147   if (FXFT_Select_Charmap(face, FT_ENCODING_UNICODE) == 0) {
148     const uint16_t* pUnicodes = UnicodesForPredefinedCharSet(base_encoding);
149     for (uint32_t charcode = 0; charcode < 256; charcode++) {
150       if (m_pFontFile) {
151         m_Encoding.SetUnicode(charcode, charcode);
152       } else {
153         const char* name =
154             GetAdobeCharName(FontEncoding::kBuiltin, m_CharNames, charcode);
155         if (name)
156           m_Encoding.SetUnicode(charcode, UnicodeFromAdobeName(name));
157         else if (pUnicodes)
158           m_Encoding.SetUnicode(charcode, pUnicodes[charcode]);
159       }
160       m_GlyphIndex[charcode] =
161           FT_Get_Char_Index(face, m_Encoding.UnicodeFromCharCode(charcode));
162     }
163     if (HasAnyGlyphIndex())
164       return;
165   }
166   for (int charcode = 0; charcode < 256; charcode++)
167     m_GlyphIndex[charcode] = charcode;
168 }
169 
HasAnyGlyphIndex() const170 bool CPDF_TrueTypeFont::HasAnyGlyphIndex() const {
171   for (uint32_t charcode = 0; charcode < kInternalTableSize; charcode++) {
172     if (m_GlyphIndex[charcode])
173       return true;
174   }
175   return false;
176 }
177 
DetermineCharmapType() const178 CPDF_TrueTypeFont::CharmapType CPDF_TrueTypeFont::DetermineCharmapType() const {
179   if (UseTTCharmapMSUnicode(m_Font.GetFaceRec()))
180     return CharmapType::kMSUnicode;
181 
182   if (FontStyleIsNonSymbolic(m_Flags)) {
183     if (UseTTCharmapMacRoman(m_Font.GetFaceRec()))
184       return CharmapType::kMacRoman;
185     if (UseTTCharmapMSSymbol(m_Font.GetFaceRec()))
186       return CharmapType::kMSSymbol;
187   } else {
188     if (UseTTCharmapMSSymbol(m_Font.GetFaceRec()))
189       return CharmapType::kMSSymbol;
190     if (UseTTCharmapMacRoman(m_Font.GetFaceRec()))
191       return CharmapType::kMacRoman;
192   }
193   return CharmapType::kOther;
194 }
195 
DetermineEncoding() const196 FontEncoding CPDF_TrueTypeFont::DetermineEncoding() const {
197   if (!m_pFontFile || !FontStyleIsSymbolic(m_Flags) ||
198       !IsWinAnsiOrMacRomanEncoding(m_BaseEncoding)) {
199     return m_BaseEncoding;
200   }
201 
202   // Not null - caller checked.
203   FXFT_FaceRec* face = m_Font.GetFaceRec();
204   if (face->num_charmaps <= 0)
205     return m_BaseEncoding;
206 
207   bool support_win = false;
208   bool support_mac = false;
209   for (int i = 0; i < face->num_charmaps; i++) {
210     int platform_id = FXFT_Get_Charmap_PlatformID(face->charmaps[i]);
211     if (platform_id == kNamePlatformAppleUnicode ||
212         platform_id == kNamePlatformWindows) {
213       support_win = true;
214     } else if (platform_id == kNamePlatformMac) {
215       support_mac = true;
216     }
217     if (support_win && support_mac)
218       break;
219   }
220 
221   if (m_BaseEncoding == FontEncoding::kWinAnsi && !support_win)
222     return support_mac ? FontEncoding::kMacRoman : FontEncoding::kBuiltin;
223   if (m_BaseEncoding == FontEncoding::kMacRoman && !support_mac)
224     return support_win ? FontEncoding::kWinAnsi : FontEncoding::kBuiltin;
225   return m_BaseEncoding;
226 }
227 
SetGlyphIndicesFromFirstChar()228 void CPDF_TrueTypeFont::SetGlyphIndicesFromFirstChar() {
229   int start_char = m_pFontDict->GetIntegerFor("FirstChar");
230   if (start_char < 0 || start_char > 255)
231     return;
232 
233   auto* it = std::begin(m_GlyphIndex);
234   std::fill(it, it + start_char, 0);
235   uint16_t glyph = 3;
236   for (int charcode = start_char; charcode < 256; charcode++, glyph++)
237     m_GlyphIndex[charcode] = glyph;
238 }
239