1 // Copyright 2016 PDFium Authors. All rights reserved.
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_type1font.h"
8 
9 #include "core/fpdfapi/font/font_int.h"
10 #include "core/fpdfapi/parser/cpdf_dictionary.h"
11 #include "core/fxge/cfx_gemodule.h"
12 #include "core/fxge/fx_freetype.h"
13 
14 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
15 #include "core/fxge/apple/apple_int.h"
16 #endif
17 
18 namespace {
19 
20 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
21 struct GlyphNameMap {
22   const FX_CHAR* m_pStrAdobe;
23   const FX_CHAR* m_pStrUnicode;
24 };
25 
26 const GlyphNameMap g_GlyphNameSubsts[] = {{"ff", "uniFB00"},
27                                           {"ffi", "uniFB03"},
28                                           {"ffl", "uniFB04"},
29                                           {"fi", "uniFB01"},
30                                           {"fl", "uniFB02"}};
31 
compareString(const void * key,const void * element)32 int compareString(const void* key, const void* element) {
33   return FXSYS_stricmp(static_cast<const FX_CHAR*>(key),
34                        static_cast<const GlyphNameMap*>(element)->m_pStrAdobe);
35 }
36 
GlyphNameRemap(const FX_CHAR * pStrAdobe)37 const FX_CHAR* GlyphNameRemap(const FX_CHAR* pStrAdobe) {
38   const GlyphNameMap* found = static_cast<const GlyphNameMap*>(FXSYS_bsearch(
39       pStrAdobe, g_GlyphNameSubsts, FX_ArraySize(g_GlyphNameSubsts),
40       sizeof(GlyphNameMap), compareString));
41   return found ? found->m_pStrUnicode : nullptr;
42 }
43 
44 #endif  // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
45 
FT_UseType1Charmap(FXFT_Face face)46 bool FT_UseType1Charmap(FXFT_Face face) {
47   if (FXFT_Get_Face_CharmapCount(face) == 0) {
48     return false;
49   }
50   if (FXFT_Get_Face_CharmapCount(face) == 1 &&
51       FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[0]) ==
52           FXFT_ENCODING_UNICODE) {
53     return false;
54   }
55   if (FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[0]) ==
56       FXFT_ENCODING_UNICODE) {
57     FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[1]);
58   } else {
59     FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[0]);
60   }
61   return true;
62 }
63 
64 }  // namespace
65 
CPDF_Type1Font()66 CPDF_Type1Font::CPDF_Type1Font() : m_Base14Font(-1) {}
67 
IsType1Font() const68 bool CPDF_Type1Font::IsType1Font() const {
69   return true;
70 }
71 
AsType1Font() const72 const CPDF_Type1Font* CPDF_Type1Font::AsType1Font() const {
73   return this;
74 }
75 
AsType1Font()76 CPDF_Type1Font* CPDF_Type1Font::AsType1Font() {
77   return this;
78 }
79 
Load()80 bool CPDF_Type1Font::Load() {
81   m_Base14Font = PDF_GetStandardFontName(&m_BaseFont);
82   if (m_Base14Font >= 0) {
83     CPDF_Dictionary* pFontDesc = m_pFontDict->GetDictFor("FontDescriptor");
84     if (pFontDesc && pFontDesc->KeyExist("Flags"))
85       m_Flags = pFontDesc->GetIntegerFor("Flags");
86     else
87       m_Flags = m_Base14Font >= 12 ? FXFONT_SYMBOLIC : FXFONT_NONSYMBOLIC;
88 
89     if (m_Base14Font < 4) {
90       for (int i = 0; i < 256; i++)
91         m_CharWidth[i] = 600;
92     }
93     if (m_Base14Font == 12)
94       m_BaseEncoding = PDFFONT_ENCODING_ADOBE_SYMBOL;
95     else if (m_Base14Font == 13)
96       m_BaseEncoding = PDFFONT_ENCODING_ZAPFDINGBATS;
97     else if (m_Flags & FXFONT_NONSYMBOLIC)
98       m_BaseEncoding = PDFFONT_ENCODING_STANDARD;
99   }
100   return LoadCommon();
101 }
102 
GlyphFromCharCodeExt(uint32_t charcode)103 int CPDF_Type1Font::GlyphFromCharCodeExt(uint32_t charcode) {
104   if (charcode > 0xff) {
105     return -1;
106   }
107   int index = m_ExtGID[(uint8_t)charcode];
108   if (index == 0xffff) {
109     return -1;
110   }
111   return index;
112 }
113 
LoadGlyphMap()114 void CPDF_Type1Font::LoadGlyphMap() {
115   if (!m_Font.GetFace())
116     return;
117 
118 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
119   bool bCoreText = true;
120   CQuartz2D& quartz2d =
121       static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatformData())
122           ->m_quartz2d;
123   if (!m_Font.GetPlatformFont()) {
124     if (m_Font.GetPsName() == "DFHeiStd-W5")
125       bCoreText = false;
126 
127     m_Font.SetPlatformFont(
128         quartz2d.CreateFont(m_Font.GetFontData(), m_Font.GetSize()));
129     if (!m_Font.GetPlatformFont())
130       bCoreText = false;
131   }
132 #endif
133   if (!IsEmbedded() && (m_Base14Font < 12) && m_Font.IsTTFont()) {
134     if (FT_UseTTCharmap(m_Font.GetFace(), 3, 0)) {
135       bool bGotOne = false;
136       for (int charcode = 0; charcode < 256; charcode++) {
137         const uint8_t prefix[4] = {0x00, 0xf0, 0xf1, 0xf2};
138         for (int j = 0; j < 4; j++) {
139           uint16_t unicode = prefix[j] * 256 + charcode;
140           m_GlyphIndex[charcode] =
141               FXFT_Get_Char_Index(m_Font.GetFace(), unicode);
142 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
143           CalcExtGID(charcode);
144 #endif
145           if (m_GlyphIndex[charcode]) {
146             bGotOne = true;
147             break;
148           }
149         }
150       }
151       if (bGotOne) {
152 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
153         if (!bCoreText)
154           FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256);
155 #endif
156         return;
157       }
158     }
159     FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE);
160     if (m_BaseEncoding == 0) {
161       m_BaseEncoding = PDFFONT_ENCODING_STANDARD;
162     }
163     for (int charcode = 0; charcode < 256; charcode++) {
164       const FX_CHAR* name =
165           GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
166       if (!name)
167         continue;
168 
169       m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
170       m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
171           m_Font.GetFace(), m_Encoding.m_Unicodes[charcode]);
172 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
173       CalcExtGID(charcode);
174 #endif
175       if (m_GlyphIndex[charcode] == 0 && FXSYS_strcmp(name, ".notdef") == 0) {
176         m_Encoding.m_Unicodes[charcode] = 0x20;
177         m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), 0x20);
178 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
179         CalcExtGID(charcode);
180 #endif
181       }
182     }
183 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
184     if (!bCoreText)
185       FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256);
186 #endif
187     return;
188   }
189   FT_UseType1Charmap(m_Font.GetFace());
190 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
191   if (bCoreText) {
192     if (m_Flags & FXFONT_SYMBOLIC) {
193       for (int charcode = 0; charcode < 256; charcode++) {
194         const FX_CHAR* name =
195             GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
196         if (name) {
197           m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
198           m_GlyphIndex[charcode] =
199               FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
200           SetExtGID(name, charcode);
201         } else {
202           m_GlyphIndex[charcode] =
203               FXFT_Get_Char_Index(m_Font.GetFace(), charcode);
204           FX_WCHAR unicode = 0;
205           if (m_GlyphIndex[charcode]) {
206             unicode =
207                 FT_UnicodeFromCharCode(PDFFONT_ENCODING_STANDARD, charcode);
208           }
209           FX_CHAR name_glyph[256];
210           FXSYS_memset(name_glyph, 0, sizeof(name_glyph));
211           FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
212                               name_glyph, 256);
213           name_glyph[255] = 0;
214           if (unicode == 0 && name_glyph[0] != 0) {
215             unicode = PDF_UnicodeFromAdobeName(name_glyph);
216           }
217           m_Encoding.m_Unicodes[charcode] = unicode;
218           SetExtGID(name_glyph, charcode);
219         }
220       }
221       return;
222     }
223     bool bUnicode = false;
224     if (0 == FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE)) {
225       bUnicode = true;
226     }
227     for (int charcode = 0; charcode < 256; charcode++) {
228       const FX_CHAR* name =
229           GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
230       if (!name) {
231         continue;
232       }
233       m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
234       const FX_CHAR* pStrUnicode = GlyphNameRemap(name);
235       if (pStrUnicode &&
236           0 == FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name)) {
237         name = pStrUnicode;
238       }
239       m_GlyphIndex[charcode] =
240           FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
241       SetExtGID(name, charcode);
242       if (m_GlyphIndex[charcode] == 0) {
243         if (FXSYS_strcmp(name, ".notdef") != 0 &&
244             FXSYS_strcmp(name, "space") != 0) {
245           m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
246               m_Font.GetFace(),
247               bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode);
248           CalcExtGID(charcode);
249         } else {
250           m_Encoding.m_Unicodes[charcode] = 0x20;
251           m_GlyphIndex[charcode] =
252               bUnicode ? FXFT_Get_Char_Index(m_Font.GetFace(), 0x20) : 0xffff;
253           CalcExtGID(charcode);
254         }
255       }
256     }
257     return;
258   }
259 #endif  // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
260   if (m_Flags & FXFONT_SYMBOLIC) {
261     for (int charcode = 0; charcode < 256; charcode++) {
262       const FX_CHAR* name =
263           GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
264       if (name) {
265         m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
266         m_GlyphIndex[charcode] =
267             FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
268       } else {
269         m_GlyphIndex[charcode] =
270             FXFT_Get_Char_Index(m_Font.GetFace(), charcode);
271         if (m_GlyphIndex[charcode]) {
272           FX_WCHAR unicode =
273               FT_UnicodeFromCharCode(PDFFONT_ENCODING_STANDARD, charcode);
274           if (unicode == 0) {
275             FX_CHAR name_glyph[256];
276             FXSYS_memset(name_glyph, 0, sizeof(name_glyph));
277             FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
278                                 name_glyph, 256);
279             name_glyph[255] = 0;
280             if (name_glyph[0] != 0) {
281               unicode = PDF_UnicodeFromAdobeName(name_glyph);
282             }
283           }
284           m_Encoding.m_Unicodes[charcode] = unicode;
285         }
286       }
287     }
288 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
289     if (!bCoreText)
290       FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256);
291 
292 #endif
293     return;
294   }
295   bool bUnicode = false;
296   if (0 == FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE)) {
297     bUnicode = true;
298   }
299   for (int charcode = 0; charcode < 256; charcode++) {
300     const FX_CHAR* name =
301         GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
302     if (!name) {
303       continue;
304     }
305     m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
306     m_GlyphIndex[charcode] = FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
307     if (m_GlyphIndex[charcode] == 0) {
308       if (FXSYS_strcmp(name, ".notdef") != 0 &&
309           FXSYS_strcmp(name, "space") != 0) {
310         m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
311             m_Font.GetFace(),
312             bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode);
313       } else {
314         m_Encoding.m_Unicodes[charcode] = 0x20;
315         m_GlyphIndex[charcode] = 0xffff;
316       }
317     }
318   }
319 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
320   if (!bCoreText)
321     FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256);
322 #endif
323 }
324 
325 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
SetExtGID(const FX_CHAR * name,int charcode)326 void CPDF_Type1Font::SetExtGID(const FX_CHAR* name, int charcode) {
327   CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
328       kCFAllocatorDefault, name, kCFStringEncodingASCII, kCFAllocatorNull);
329   m_ExtGID[charcode] =
330       CGFontGetGlyphWithGlyphName((CGFontRef)m_Font.GetPlatformFont(), name_ct);
331   if (name_ct)
332     CFRelease(name_ct);
333 }
334 
CalcExtGID(int charcode)335 void CPDF_Type1Font::CalcExtGID(int charcode) {
336   FX_CHAR name_glyph[256];
337   FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode], name_glyph,
338                       256);
339   name_glyph[255] = 0;
340   SetExtGID(name_glyph, charcode);
341 }
342 #endif  // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
343