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