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_truetypefont.h"
8 
9 #include "core/fpdfapi/parser/cpdf_dictionary.h"
10 #include "core/fxge/fx_font.h"
11 #include "third_party/base/stl_util.h"
12 
13 namespace {
14 
15 const uint8_t kPrefix[4] = {0x00, 0xf0, 0xf1, 0xf2};
16 
17 }  // namespace
18 
CPDF_TrueTypeFont(CPDF_Document * pDocument,CPDF_Dictionary * pFontDict)19 CPDF_TrueTypeFont::CPDF_TrueTypeFont(CPDF_Document* pDocument,
20                                      CPDF_Dictionary* pFontDict)
21     : CPDF_SimpleFont(pDocument, pFontDict) {}
22 
23 CPDF_TrueTypeFont::~CPDF_TrueTypeFont() = default;
24 
IsTrueTypeFont() const25 bool CPDF_TrueTypeFont::IsTrueTypeFont() const {
26   return true;
27 }
28 
AsTrueTypeFont() const29 const CPDF_TrueTypeFont* CPDF_TrueTypeFont::AsTrueTypeFont() const {
30   return this;
31 }
32 
AsTrueTypeFont()33 CPDF_TrueTypeFont* CPDF_TrueTypeFont::AsTrueTypeFont() {
34   return this;
35 }
36 
Load()37 bool CPDF_TrueTypeFont::Load() {
38   return LoadCommon();
39 }
40 
LoadGlyphMap()41 void CPDF_TrueTypeFont::LoadGlyphMap() {
42   FXFT_FaceRec* face = m_Font.GetFaceRec();
43   if (!face)
44     return;
45 
46   int baseEncoding = m_BaseEncoding;
47   if (m_pFontFile && face->num_charmaps > 0 &&
48       (baseEncoding == PDFFONT_ENCODING_MACROMAN ||
49        baseEncoding == PDFFONT_ENCODING_WINANSI) &&
50       FontStyleIsSymbolic(m_Flags)) {
51     bool bSupportWin = false;
52     bool bSupportMac = false;
53     for (int i = 0; i < FXFT_Get_Face_CharmapCount(face); i++) {
54       int platform_id =
55           FXFT_Get_Charmap_PlatformID(FXFT_Get_Face_Charmaps(face)[i]);
56       if (platform_id == 0 || platform_id == 3) {
57         bSupportWin = true;
58       } else if (platform_id == 0 || platform_id == 1) {
59         bSupportMac = true;
60       }
61     }
62     if (baseEncoding == PDFFONT_ENCODING_WINANSI && !bSupportWin) {
63       baseEncoding =
64           bSupportMac ? PDFFONT_ENCODING_MACROMAN : PDFFONT_ENCODING_BUILTIN;
65     } else if (baseEncoding == PDFFONT_ENCODING_MACROMAN && !bSupportMac) {
66       baseEncoding =
67           bSupportWin ? PDFFONT_ENCODING_WINANSI : PDFFONT_ENCODING_BUILTIN;
68     }
69   }
70   if (((baseEncoding == PDFFONT_ENCODING_MACROMAN ||
71         baseEncoding == PDFFONT_ENCODING_WINANSI) &&
72        m_CharNames.empty()) ||
73       FontStyleIsNonSymbolic(m_Flags)) {
74     if (!FXFT_Has_Glyph_Names(face) &&
75         (!face->num_charmaps || !face->charmaps)) {
76       int nStartChar = m_pFontDict->GetIntegerFor("FirstChar");
77       if (nStartChar < 0 || nStartChar > 255)
78         return;
79 
80       int charcode = 0;
81       for (; charcode < nStartChar; charcode++)
82         m_GlyphIndex[charcode] = 0;
83       uint16_t nGlyph = charcode - nStartChar + 3;
84       for (; charcode < 256; charcode++, nGlyph++)
85         m_GlyphIndex[charcode] = nGlyph;
86       return;
87     }
88     bool bMSUnicode = FT_UseTTCharmap(face, 3, 1);
89     bool bMacRoman = false;
90     bool bMSSymbol = false;
91     if (!bMSUnicode) {
92       if (FontStyleIsNonSymbolic(m_Flags)) {
93         bMacRoman = FT_UseTTCharmap(face, 1, 0);
94         bMSSymbol = !bMacRoman && FT_UseTTCharmap(face, 3, 0);
95       } else {
96         bMSSymbol = FT_UseTTCharmap(face, 3, 0);
97         bMacRoman = !bMSSymbol && FT_UseTTCharmap(face, 1, 0);
98       }
99     }
100     bool bToUnicode = m_pFontDict->KeyExist("ToUnicode");
101     for (uint32_t charcode = 0; charcode < 256; charcode++) {
102       const char* name = GetAdobeCharName(baseEncoding, m_CharNames, charcode);
103       if (!name) {
104         m_GlyphIndex[charcode] =
105             m_pFontFile ? FT_Get_Char_Index(face, charcode) : -1;
106         continue;
107       }
108       m_Encoding.SetUnicode(charcode, PDF_UnicodeFromAdobeName(name));
109       if (bMSSymbol) {
110         for (size_t j = 0; j < pdfium::size(kPrefix); j++) {
111           uint16_t unicode = kPrefix[j] * 256 + charcode;
112           m_GlyphIndex[charcode] = FT_Get_Char_Index(face, unicode);
113           if (m_GlyphIndex[charcode])
114             break;
115         }
116       } else if (m_Encoding.UnicodeFromCharCode(charcode)) {
117         if (bMSUnicode) {
118           m_GlyphIndex[charcode] =
119               FT_Get_Char_Index(face, m_Encoding.UnicodeFromCharCode(charcode));
120         } else if (bMacRoman) {
121           uint32_t maccode =
122               FT_CharCodeFromUnicode(FT_ENCODING_APPLE_ROMAN,
123                                      m_Encoding.UnicodeFromCharCode(charcode));
124           if (!maccode) {
125             m_GlyphIndex[charcode] = FXFT_Get_Name_Index(face, name);
126           } else {
127             m_GlyphIndex[charcode] = FT_Get_Char_Index(face, maccode);
128           }
129         }
130       }
131       if ((m_GlyphIndex[charcode] != 0 && m_GlyphIndex[charcode] != 0xffff) ||
132           !name) {
133         continue;
134       }
135       if (strcmp(name, ".notdef") == 0) {
136         m_GlyphIndex[charcode] = FT_Get_Char_Index(face, 32);
137         continue;
138       }
139       m_GlyphIndex[charcode] = FXFT_Get_Name_Index(face, name);
140       if (m_GlyphIndex[charcode] != 0 || !bToUnicode)
141         continue;
142 
143       WideString wsUnicode = UnicodeFromCharCode(charcode);
144       if (!wsUnicode.IsEmpty()) {
145         m_GlyphIndex[charcode] = FT_Get_Char_Index(face, wsUnicode[0]);
146         m_Encoding.SetUnicode(charcode, wsUnicode[0]);
147       }
148     }
149     return;
150   }
151   if (FT_UseTTCharmap(face, 3, 0)) {
152     bool bFound = false;
153     for (int charcode = 0; charcode < 256; charcode++) {
154       for (size_t j = 0; j < pdfium::size(kPrefix); j++) {
155         uint16_t unicode = kPrefix[j] * 256 + charcode;
156         m_GlyphIndex[charcode] = FT_Get_Char_Index(face, unicode);
157         if (m_GlyphIndex[charcode]) {
158           bFound = true;
159           break;
160         }
161       }
162     }
163     if (bFound) {
164       if (baseEncoding != PDFFONT_ENCODING_BUILTIN) {
165         for (uint32_t charcode = 0; charcode < 256; charcode++) {
166           const char* name =
167               GetAdobeCharName(baseEncoding, m_CharNames, charcode);
168           if (name)
169             m_Encoding.SetUnicode(charcode, PDF_UnicodeFromAdobeName(name));
170         }
171       } else if (FT_UseTTCharmap(face, 1, 0)) {
172         for (int charcode = 0; charcode < 256; charcode++) {
173           m_Encoding.SetUnicode(
174               charcode,
175               FT_UnicodeFromCharCode(FT_ENCODING_APPLE_ROMAN, charcode));
176         }
177       }
178       return;
179     }
180   }
181   if (FT_UseTTCharmap(face, 1, 0)) {
182     bool bFound = false;
183     for (int charcode = 0; charcode < 256; charcode++) {
184       m_GlyphIndex[charcode] = FT_Get_Char_Index(face, charcode);
185       m_Encoding.SetUnicode(
186           charcode, FT_UnicodeFromCharCode(FT_ENCODING_APPLE_ROMAN, charcode));
187       if (m_GlyphIndex[charcode]) {
188         bFound = true;
189       }
190     }
191     if (m_pFontFile || bFound)
192       return;
193   }
194   if (FXFT_Select_Charmap(face, FT_ENCODING_UNICODE) == 0) {
195     bool bFound = false;
196     const uint16_t* pUnicodes = PDF_UnicodesForPredefinedCharSet(baseEncoding);
197     for (uint32_t charcode = 0; charcode < 256; charcode++) {
198       if (m_pFontFile) {
199         m_Encoding.SetUnicode(charcode, charcode);
200       } else {
201         const char* name = GetAdobeCharName(0, m_CharNames, charcode);
202         if (name)
203           m_Encoding.SetUnicode(charcode, PDF_UnicodeFromAdobeName(name));
204         else if (pUnicodes)
205           m_Encoding.SetUnicode(charcode, pUnicodes[charcode]);
206       }
207       m_GlyphIndex[charcode] =
208           FT_Get_Char_Index(face, m_Encoding.UnicodeFromCharCode(charcode));
209       if (m_GlyphIndex[charcode])
210         bFound = true;
211     }
212     if (bFound)
213       return;
214   }
215   for (int charcode = 0; charcode < 256; charcode++)
216     m_GlyphIndex[charcode] = charcode;
217 }
218