• 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_type1font.h"
8 
9 #include <algorithm>
10 #include <iterator>
11 #include <utility>
12 
13 #include "build/build_config.h"
14 #include "core/fpdfapi/parser/cpdf_dictionary.h"
15 #include "core/fxcrt/fx_system.h"
16 #include "core/fxcrt/span_util.h"
17 #include "core/fxge/cfx_fontmapper.h"
18 #include "core/fxge/cfx_gemodule.h"
19 #include "core/fxge/freetype/fx_freetype.h"
20 #include "core/fxge/fx_font.h"
21 
22 #if BUILDFLAG(IS_APPLE)
23 #include <CoreFoundation/CFString.h>
24 #include <CoreGraphics/CoreGraphics.h>
25 #endif  // BUILDFLAG(IS_APPLE)
26 
27 namespace {
28 
29 #if BUILDFLAG(IS_APPLE)
30 struct GlyphNameMap {
31   const char* m_pStrAdobe;    // Raw, POD struct.
32   const char* m_pStrUnicode;  // Raw, POD struct.
33 };
34 
35 const GlyphNameMap kGlyphNameSubsts[] = {{"ff", "uniFB00"},
36                                          {"ffi", "uniFB03"},
37                                          {"ffl", "uniFB04"},
38                                          {"fi", "uniFB01"},
39                                          {"fl", "uniFB02"}};
40 
GlyphNameRemap(const char * pStrAdobe)41 const char* GlyphNameRemap(const char* pStrAdobe) {
42   for (const auto& element : kGlyphNameSubsts) {
43     if (!FXSYS_stricmp(element.m_pStrAdobe, pStrAdobe))
44       return element.m_pStrUnicode;
45   }
46   return nullptr;
47 }
48 
49 #endif  // BUILDFLAG(IS_APPLE)
50 
FT_UseType1Charmap(FXFT_FaceRec * face)51 bool FT_UseType1Charmap(FXFT_FaceRec* face) {
52   if (face->num_charmaps == 0)
53     return false;
54 
55   bool is_first_charmap_unicode =
56       FXFT_Get_Charmap_Encoding(face->charmaps[0]) == FT_ENCODING_UNICODE;
57   if (face->num_charmaps == 1 && is_first_charmap_unicode)
58     return false;
59 
60   int index = is_first_charmap_unicode ? 1 : 0;
61   FT_Set_Charmap(face, face->charmaps[index]);
62   return true;
63 }
64 
65 }  // namespace
66 
CPDF_Type1Font(CPDF_Document * pDocument,RetainPtr<CPDF_Dictionary> pFontDict)67 CPDF_Type1Font::CPDF_Type1Font(CPDF_Document* pDocument,
68                                RetainPtr<CPDF_Dictionary> pFontDict)
69     : CPDF_SimpleFont(pDocument, std::move(pFontDict)) {
70 #if BUILDFLAG(IS_APPLE)
71   memset(m_ExtGID, 0xff, sizeof(m_ExtGID));
72 #endif
73 }
74 
75 CPDF_Type1Font::~CPDF_Type1Font() = default;
76 
IsType1Font() const77 bool CPDF_Type1Font::IsType1Font() const {
78   return true;
79 }
80 
AsType1Font() const81 const CPDF_Type1Font* CPDF_Type1Font::AsType1Font() const {
82   return this;
83 }
84 
AsType1Font()85 CPDF_Type1Font* CPDF_Type1Font::AsType1Font() {
86   return this;
87 }
88 
Load()89 bool CPDF_Type1Font::Load() {
90   m_Base14Font = CFX_FontMapper::GetStandardFontName(&m_BaseFontName);
91   if (!IsBase14Font())
92     return LoadCommon();
93 
94   RetainPtr<const CPDF_Dictionary> pFontDesc =
95       m_pFontDict->GetDictFor("FontDescriptor");
96   if (pFontDesc && pFontDesc->KeyExist("Flags")) {
97     m_Flags = pFontDesc->GetIntegerFor("Flags");
98   } else if (IsSymbolicFont()) {
99     m_Flags = FXFONT_SYMBOLIC;
100   } else {
101     m_Flags = FXFONT_NONSYMBOLIC;
102   }
103   if (IsFixedFont()) {
104     std::fill(std::begin(m_CharWidth), std::end(m_CharWidth), 600);
105   }
106   if (m_Base14Font == CFX_FontMapper::kSymbol)
107     m_BaseEncoding = FontEncoding::kAdobeSymbol;
108   else if (m_Base14Font == CFX_FontMapper::kDingbats)
109     m_BaseEncoding = FontEncoding::kZapfDingbats;
110   else if (FontStyleIsNonSymbolic(m_Flags))
111     m_BaseEncoding = FontEncoding::kStandard;
112   return LoadCommon();
113 }
114 
115 #if BUILDFLAG(IS_APPLE)
GlyphFromCharCodeExt(uint32_t charcode)116 int CPDF_Type1Font::GlyphFromCharCodeExt(uint32_t charcode) {
117   if (charcode > 0xff)
118     return -1;
119 
120   int index = m_ExtGID[static_cast<uint8_t>(charcode)];
121   return index != 0xffff ? index : -1;
122 }
123 #endif
124 
LoadGlyphMap()125 void CPDF_Type1Font::LoadGlyphMap() {
126   if (!m_Font.GetFaceRec())
127     return;
128 
129 #if BUILDFLAG(IS_APPLE)
130   bool bCoreText = true;
131   if (!m_Font.GetPlatformFont()) {
132     if (m_Font.GetPsName() == "DFHeiStd-W5")
133       bCoreText = false;
134 
135     auto* pPlatform = CFX_GEModule::Get()->GetPlatform();
136     pdfium::span<const uint8_t> span = m_Font.GetFontSpan();
137     m_Font.SetPlatformFont(pPlatform->CreatePlatformFont(span));
138     if (!m_Font.GetPlatformFont())
139       bCoreText = false;
140   }
141 #endif
142   if (!IsEmbedded() && !IsSymbolicFont() && m_Font.IsTTFont()) {
143     if (UseTTCharmapMSSymbol(m_Font.GetFaceRec())) {
144       bool bGotOne = false;
145       for (uint32_t charcode = 0; charcode < kInternalTableSize; charcode++) {
146         const uint8_t prefix[4] = {0x00, 0xf0, 0xf1, 0xf2};
147         for (int j = 0; j < 4; j++) {
148           uint16_t unicode = prefix[j] * 256 + charcode;
149           m_GlyphIndex[charcode] =
150               FT_Get_Char_Index(m_Font.GetFaceRec(), unicode);
151 #if BUILDFLAG(IS_APPLE)
152           CalcExtGID(charcode);
153 #endif
154           if (m_GlyphIndex[charcode]) {
155             bGotOne = true;
156             break;
157           }
158         }
159       }
160       if (bGotOne) {
161 #if BUILDFLAG(IS_APPLE)
162         if (!bCoreText)
163           memcpy(m_ExtGID, m_GlyphIndex, sizeof(m_ExtGID));
164 #endif
165         return;
166       }
167     }
168     FXFT_Select_Charmap(m_Font.GetFaceRec(), FT_ENCODING_UNICODE);
169     if (m_BaseEncoding == FontEncoding::kBuiltin)
170       m_BaseEncoding = FontEncoding::kStandard;
171 
172     for (uint32_t charcode = 0; charcode < kInternalTableSize; charcode++) {
173       const char* name =
174           GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
175       if (!name)
176         continue;
177 
178       m_Encoding.SetUnicode(charcode, UnicodeFromAdobeName(name));
179       m_GlyphIndex[charcode] = FT_Get_Char_Index(
180           m_Font.GetFaceRec(), m_Encoding.UnicodeFromCharCode(charcode));
181 #if BUILDFLAG(IS_APPLE)
182       CalcExtGID(charcode);
183 #endif
184       if (m_GlyphIndex[charcode] == 0 && strcmp(name, ".notdef") == 0) {
185         m_Encoding.SetUnicode(charcode, 0x20);
186         m_GlyphIndex[charcode] = FT_Get_Char_Index(m_Font.GetFaceRec(), 0x20);
187 #if BUILDFLAG(IS_APPLE)
188         CalcExtGID(charcode);
189 #endif
190       }
191     }
192 #if BUILDFLAG(IS_APPLE)
193     if (!bCoreText) {
194       fxcrt::spancpy(pdfium::make_span(m_ExtGID),
195                      pdfium::make_span(m_GlyphIndex));
196     }
197 #endif
198     return;
199   }
200   FT_UseType1Charmap(m_Font.GetFaceRec());
201 #if BUILDFLAG(IS_APPLE)
202   if (bCoreText) {
203     if (FontStyleIsSymbolic(m_Flags)) {
204       for (uint32_t charcode = 0; charcode < kInternalTableSize; charcode++) {
205         const char* name =
206             GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
207         if (name) {
208           m_Encoding.SetUnicode(charcode, UnicodeFromAdobeName(name));
209           m_GlyphIndex[charcode] = FT_Get_Name_Index(m_Font.GetFaceRec(), name);
210           SetExtGID(name, charcode);
211         } else {
212           m_GlyphIndex[charcode] =
213               FT_Get_Char_Index(m_Font.GetFaceRec(), charcode);
214           char name_glyph[kInternalTableSize] = {};
215           FT_Get_Glyph_Name(m_Font.GetFaceRec(), m_GlyphIndex[charcode],
216                             name_glyph, sizeof(name_glyph));
217           name_glyph[kInternalTableSize - 1] = 0;
218           const wchar_t unicode =
219               name_glyph[0] != 0 ? UnicodeFromAdobeName(name_glyph) : 0;
220           m_Encoding.SetUnicode(charcode, unicode);
221           SetExtGID(name_glyph, charcode);
222         }
223       }
224       return;
225     }
226 
227     bool bUnicode =
228         FXFT_Select_Charmap(m_Font.GetFaceRec(), FT_ENCODING_UNICODE) == 0;
229     for (uint32_t charcode = 0; charcode < kInternalTableSize; charcode++) {
230       const char* name =
231           GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
232       if (!name)
233         continue;
234 
235       m_Encoding.SetUnicode(charcode, UnicodeFromAdobeName(name));
236       const char* pStrUnicode = GlyphNameRemap(name);
237       if (pStrUnicode && FT_Get_Name_Index(m_Font.GetFaceRec(), name) == 0) {
238         name = pStrUnicode;
239       }
240       m_GlyphIndex[charcode] = FT_Get_Name_Index(m_Font.GetFaceRec(), name);
241       SetExtGID(name, charcode);
242       if (m_GlyphIndex[charcode] != 0)
243         continue;
244 
245       if (strcmp(name, ".notdef") != 0 && strcmp(name, "space") != 0) {
246         m_GlyphIndex[charcode] = FT_Get_Char_Index(
247             m_Font.GetFaceRec(),
248             bUnicode ? m_Encoding.UnicodeFromCharCode(charcode) : charcode);
249         CalcExtGID(charcode);
250       } else {
251         m_Encoding.SetUnicode(charcode, 0x20);
252         m_GlyphIndex[charcode] =
253             bUnicode ? FT_Get_Char_Index(m_Font.GetFaceRec(), 0x20) : 0xffff;
254         CalcExtGID(charcode);
255       }
256     }
257     return;
258   }
259 #endif  // BUILDFLAG(IS_APPLE)
260   if (FontStyleIsSymbolic(m_Flags)) {
261     for (size_t charcode = 0; charcode < kInternalTableSize; charcode++) {
262       const char* name = GetAdobeCharName(m_BaseEncoding, m_CharNames,
263                                           static_cast<uint32_t>(charcode));
264       if (name) {
265         m_Encoding.SetUnicode(charcode, UnicodeFromAdobeName(name));
266         m_GlyphIndex[charcode] = FT_Get_Name_Index(m_Font.GetFaceRec(), name);
267       } else {
268         m_GlyphIndex[charcode] = FT_Get_Char_Index(
269             m_Font.GetFaceRec(), static_cast<uint32_t>(charcode));
270         if (m_GlyphIndex[charcode]) {
271           char name_glyph[kInternalTableSize] = {};
272           FT_Get_Glyph_Name(m_Font.GetFaceRec(), m_GlyphIndex[charcode],
273                             name_glyph, sizeof(name_glyph));
274           name_glyph[kInternalTableSize - 1] = 0;
275           const wchar_t unicode =
276               name_glyph[0] != 0 ? UnicodeFromAdobeName(name_glyph) : 0;
277           m_Encoding.SetUnicode(charcode, unicode);
278         }
279       }
280     }
281 #if BUILDFLAG(IS_APPLE)
282     if (!bCoreText)
283       memcpy(m_ExtGID, m_GlyphIndex, sizeof(m_ExtGID));
284 #endif
285     return;
286   }
287 
288   bool bUnicode =
289       FXFT_Select_Charmap(m_Font.GetFaceRec(), FT_ENCODING_UNICODE) == 0;
290   for (size_t charcode = 0; charcode < kInternalTableSize; charcode++) {
291     const char* name = GetAdobeCharName(m_BaseEncoding, m_CharNames,
292                                         static_cast<uint32_t>(charcode));
293     if (!name)
294       continue;
295 
296     m_Encoding.SetUnicode(charcode, UnicodeFromAdobeName(name));
297     m_GlyphIndex[charcode] = FT_Get_Name_Index(m_Font.GetFaceRec(), name);
298     if (m_GlyphIndex[charcode] != 0)
299       continue;
300 
301     if (strcmp(name, ".notdef") != 0 && strcmp(name, "space") != 0) {
302       m_GlyphIndex[charcode] =
303           FT_Get_Char_Index(m_Font.GetFaceRec(),
304                             bUnicode ? m_Encoding.UnicodeFromCharCode(charcode)
305                                      : static_cast<uint32_t>(charcode));
306     } else {
307       m_Encoding.SetUnicode(charcode, 0x20);
308       m_GlyphIndex[charcode] = 0xffff;
309     }
310   }
311 #if BUILDFLAG(IS_APPLE)
312   if (!bCoreText)
313     memcpy(m_ExtGID, m_GlyphIndex, sizeof(m_ExtGID));
314 #endif
315 }
316 
IsSymbolicFont() const317 bool CPDF_Type1Font::IsSymbolicFont() const {
318   return m_Base14Font.has_value() &&
319          CFX_FontMapper::IsSymbolicFont(m_Base14Font.value());
320 }
321 
IsFixedFont() const322 bool CPDF_Type1Font::IsFixedFont() const {
323   return m_Base14Font.has_value() &&
324          CFX_FontMapper::IsFixedFont(m_Base14Font.value());
325 }
326 
327 #if BUILDFLAG(IS_APPLE)
SetExtGID(const char * name,uint32_t charcode)328 void CPDF_Type1Font::SetExtGID(const char* name, uint32_t charcode) {
329   CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
330       kCFAllocatorDefault, name, kCFStringEncodingASCII, kCFAllocatorNull);
331   m_ExtGID[charcode] =
332       CGFontGetGlyphWithGlyphName((CGFontRef)m_Font.GetPlatformFont(), name_ct);
333   if (name_ct)
334     CFRelease(name_ct);
335 }
336 
CalcExtGID(uint32_t charcode)337 void CPDF_Type1Font::CalcExtGID(uint32_t charcode) {
338   char name_glyph[kInternalTableSize] = {};
339   FT_Get_Glyph_Name(m_Font.GetFaceRec(), m_GlyphIndex[charcode], name_glyph,
340                     sizeof(name_glyph));
341   name_glyph[kInternalTableSize - 1] = 0;
342   SetExtGID(name_glyph, charcode);
343 }
344 #endif  // BUILDFLAG(IS_APPLE)
345