1 // Copyright 2014 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 "public/fpdf_sysfontinfo.h"
8
9 #include <stddef.h>
10
11 #include <memory>
12 #include <utility>
13
14 #include "core/fxcrt/compiler_specific.h"
15 #include "core/fxcrt/fx_codepage.h"
16 #include "core/fxcrt/numerics/safe_conversions.h"
17 #include "core/fxcrt/span.h"
18 #include "core/fxcrt/stl_util.h"
19 #include "core/fxcrt/unowned_ptr.h"
20 #include "core/fxge/cfx_font.h"
21 #include "core/fxge/cfx_fontmapper.h"
22 #include "core/fxge/cfx_fontmgr.h"
23 #include "core/fxge/cfx_gemodule.h"
24 #include "core/fxge/fx_font.h"
25 #include "core/fxge/systemfontinfo_iface.h"
26
27 #ifdef PDF_ENABLE_XFA
28 #include "xfa/fgas/font/cfgas_fontmgr.h"
29 #include "xfa/fgas/font/cfgas_gemodule.h"
30 #endif
31
32 static_assert(FXFONT_ANSI_CHARSET == static_cast<int>(FX_Charset::kANSI),
33 "Charset must match");
34 static_assert(FXFONT_DEFAULT_CHARSET == static_cast<int>(FX_Charset::kDefault),
35 "Charset must match");
36 static_assert(FXFONT_SYMBOL_CHARSET == static_cast<int>(FX_Charset::kSymbol),
37 "Charset must match");
38 static_assert(FXFONT_SHIFTJIS_CHARSET ==
39 static_cast<int>(FX_Charset::kShiftJIS),
40 "Charset must match");
41 static_assert(FXFONT_HANGEUL_CHARSET == static_cast<int>(FX_Charset::kHangul),
42 "Charset must match");
43 static_assert(FXFONT_GB2312_CHARSET ==
44 static_cast<int>(FX_Charset::kChineseSimplified),
45 "Charset must match");
46 static_assert(FXFONT_CHINESEBIG5_CHARSET ==
47 static_cast<int>(FX_Charset::kChineseTraditional),
48 "Charset must match");
49 static_assert(FXFONT_GREEK_CHARSET ==
50 static_cast<int>(FX_Charset::kMSWin_Greek),
51 "Charset must match");
52 static_assert(FXFONT_VIETNAMESE_CHARSET ==
53 static_cast<int>(FX_Charset::kMSWin_Vietnamese),
54 "Charset must match");
55 static_assert(FXFONT_HEBREW_CHARSET ==
56 static_cast<int>(FX_Charset::kMSWin_Hebrew),
57 "Charset must match");
58 static_assert(FXFONT_ARABIC_CHARSET ==
59 static_cast<int>(FX_Charset::kMSWin_Arabic),
60 "Charset must match");
61 static_assert(FXFONT_CYRILLIC_CHARSET ==
62 static_cast<int>(FX_Charset::kMSWin_Cyrillic),
63 "Charset must match");
64 static_assert(FXFONT_THAI_CHARSET == static_cast<int>(FX_Charset::kThai),
65 "Charset must match");
66 static_assert(FXFONT_EASTERNEUROPEAN_CHARSET ==
67 static_cast<int>(FX_Charset::kMSWin_EasternEuropean),
68 "Charset must match");
69 static_assert(offsetof(CFX_Font::CharsetFontMap, charset) ==
70 offsetof(FPDF_CharsetFontMap, charset),
71 "CFX_Font::CharsetFontMap must be same as FPDF_CharsetFontMap");
72 static_assert(offsetof(CFX_Font::CharsetFontMap, fontname) ==
73 offsetof(FPDF_CharsetFontMap, fontname),
74 "CFX_Font::CharsetFontMap must be same as FPDF_CharsetFontMap");
75 static_assert(sizeof(CFX_Font::CharsetFontMap) == sizeof(FPDF_CharsetFontMap),
76 "CFX_Font::CharsetFontMap must be same as FPDF_CharsetFontMap");
77
78 class CFX_ExternalFontInfo final : public SystemFontInfoIface {
79 public:
CFX_ExternalFontInfo(FPDF_SYSFONTINFO * pInfo)80 explicit CFX_ExternalFontInfo(FPDF_SYSFONTINFO* pInfo) : m_pInfo(pInfo) {}
~CFX_ExternalFontInfo()81 ~CFX_ExternalFontInfo() override {
82 if (m_pInfo->Release)
83 m_pInfo->Release(m_pInfo);
84 }
85
EnumFontList(CFX_FontMapper * pMapper)86 bool EnumFontList(CFX_FontMapper* pMapper) override {
87 if (m_pInfo->EnumFonts) {
88 m_pInfo->EnumFonts(m_pInfo, pMapper);
89 return true;
90 }
91 return false;
92 }
93
MapFont(int weight,bool bItalic,FX_Charset charset,int pitch_family,const ByteString & face)94 void* MapFont(int weight,
95 bool bItalic,
96 FX_Charset charset,
97 int pitch_family,
98 const ByteString& face) override {
99 if (!m_pInfo->MapFont)
100 return nullptr;
101
102 int iExact;
103 return m_pInfo->MapFont(m_pInfo, weight, bItalic, static_cast<int>(charset),
104 pitch_family, face.c_str(), &iExact);
105 }
106
GetFont(const ByteString & family)107 void* GetFont(const ByteString& family) override {
108 if (!m_pInfo->GetFont)
109 return nullptr;
110 return m_pInfo->GetFont(m_pInfo, family.c_str());
111 }
112
GetFontData(void * hFont,uint32_t table,pdfium::span<uint8_t> buffer)113 size_t GetFontData(void* hFont,
114 uint32_t table,
115 pdfium::span<uint8_t> buffer) override {
116 if (!m_pInfo->GetFontData)
117 return 0;
118 return m_pInfo->GetFontData(m_pInfo, hFont, table, buffer.data(),
119 fxcrt::CollectionSize<unsigned long>(buffer));
120 }
121
GetFaceName(void * hFont,ByteString * name)122 bool GetFaceName(void* hFont, ByteString* name) override {
123 if (!m_pInfo->GetFaceName)
124 return false;
125 unsigned long size = m_pInfo->GetFaceName(m_pInfo, hFont, nullptr, 0);
126 if (size == 0)
127 return false;
128 ByteString result;
129 auto result_span = result.GetBuffer(size);
130 size = m_pInfo->GetFaceName(m_pInfo, hFont, result_span.data(), size);
131 result.ReleaseBuffer(size);
132 *name = std::move(result);
133 return true;
134 }
135
GetFontCharset(void * hFont,FX_Charset * charset)136 bool GetFontCharset(void* hFont, FX_Charset* charset) override {
137 if (!m_pInfo->GetFontCharset)
138 return false;
139
140 *charset = FX_GetCharsetFromInt(m_pInfo->GetFontCharset(m_pInfo, hFont));
141 return true;
142 }
143
DeleteFont(void * hFont)144 void DeleteFont(void* hFont) override {
145 if (m_pInfo->DeleteFont)
146 m_pInfo->DeleteFont(m_pInfo, hFont);
147 }
148
149 private:
150 UnownedPtr<FPDF_SYSFONTINFO> const m_pInfo;
151 };
152
FPDF_AddInstalledFont(void * mapper,const char * face,int charset)153 FPDF_EXPORT void FPDF_CALLCONV FPDF_AddInstalledFont(void* mapper,
154 const char* face,
155 int charset) {
156 CFX_FontMapper* pMapper = static_cast<CFX_FontMapper*>(mapper);
157 pMapper->AddInstalledFont(face, FX_GetCharsetFromInt(charset));
158 }
159
160 FPDF_EXPORT void FPDF_CALLCONV
FPDF_SetSystemFontInfo(FPDF_SYSFONTINFO * pFontInfoExt)161 FPDF_SetSystemFontInfo(FPDF_SYSFONTINFO* pFontInfoExt) {
162 auto* mapper = CFX_GEModule::Get()->GetFontMgr()->GetBuiltinMapper();
163 if (!pFontInfoExt) {
164 std::unique_ptr<SystemFontInfoIface> info = mapper->TakeSystemFontInfo();
165 // Delete `info` when it goes out of scope here.
166 return;
167 }
168
169 if (pFontInfoExt->version != 1)
170 return;
171
172 mapper->SetSystemFontInfo(
173 std::make_unique<CFX_ExternalFontInfo>(pFontInfoExt));
174
175 #ifdef PDF_ENABLE_XFA
176 CFGAS_GEModule::Get()->GetFontMgr()->EnumFonts();
177 #endif
178 }
179
FPDF_GetDefaultTTFMap()180 FPDF_EXPORT const FPDF_CharsetFontMap* FPDF_CALLCONV FPDF_GetDefaultTTFMap() {
181 return reinterpret_cast<const FPDF_CharsetFontMap*>(
182 CFX_Font::GetDefaultTTFMapSpan().data());
183 }
184
FPDF_GetDefaultTTFMapCount()185 FPDF_EXPORT size_t FPDF_CALLCONV FPDF_GetDefaultTTFMapCount() {
186 return CFX_Font::GetDefaultTTFMapSpan().size();
187 }
188
189 FPDF_EXPORT const FPDF_CharsetFontMap* FPDF_CALLCONV
FPDF_GetDefaultTTFMapEntry(size_t index)190 FPDF_GetDefaultTTFMapEntry(size_t index) {
191 pdfium::span<const CFX_Font::CharsetFontMap> entries =
192 CFX_Font::GetDefaultTTFMapSpan();
193 return index < entries.size()
194 ? reinterpret_cast<const FPDF_CharsetFontMap*>(&entries[index])
195 : nullptr;
196 }
197
198 struct FPDF_SYSFONTINFO_DEFAULT final : public FPDF_SYSFONTINFO {
199 UnownedPtr<SystemFontInfoIface> m_pFontInfo;
200 };
201
DefaultRelease(struct _FPDF_SYSFONTINFO * pThis)202 static void DefaultRelease(struct _FPDF_SYSFONTINFO* pThis) {
203 auto* pDefault = static_cast<FPDF_SYSFONTINFO_DEFAULT*>(pThis);
204 pDefault->m_pFontInfo.ClearAndDelete();
205 }
206
DefaultEnumFonts(struct _FPDF_SYSFONTINFO * pThis,void * pMapper)207 static void DefaultEnumFonts(struct _FPDF_SYSFONTINFO* pThis, void* pMapper) {
208 auto* pDefault = static_cast<FPDF_SYSFONTINFO_DEFAULT*>(pThis);
209 pDefault->m_pFontInfo->EnumFontList(static_cast<CFX_FontMapper*>(pMapper));
210 }
211
DefaultMapFont(struct _FPDF_SYSFONTINFO * pThis,int weight,FPDF_BOOL use_italic,int charset,int pitch_family,const char * family,FPDF_BOOL *)212 static void* DefaultMapFont(struct _FPDF_SYSFONTINFO* pThis,
213 int weight,
214 FPDF_BOOL use_italic,
215 int charset,
216 int pitch_family,
217 const char* family,
218 FPDF_BOOL* /*exact*/) {
219 auto* pDefault = static_cast<FPDF_SYSFONTINFO_DEFAULT*>(pThis);
220 return pDefault->m_pFontInfo->MapFont(weight, !!use_italic,
221 FX_GetCharsetFromInt(charset),
222 pitch_family, family);
223 }
224
DefaultGetFont(struct _FPDF_SYSFONTINFO * pThis,const char * family)225 void* DefaultGetFont(struct _FPDF_SYSFONTINFO* pThis, const char* family) {
226 auto* pDefault = static_cast<FPDF_SYSFONTINFO_DEFAULT*>(pThis);
227 return pDefault->m_pFontInfo->GetFont(family);
228 }
229
230 // TODO(tsepez): should be UNSAFE_BUFFER_USAGE.
DefaultGetFontData(struct _FPDF_SYSFONTINFO * pThis,void * hFont,unsigned int table,unsigned char * buffer,unsigned long buf_size)231 static unsigned long DefaultGetFontData(struct _FPDF_SYSFONTINFO* pThis,
232 void* hFont,
233 unsigned int table,
234 unsigned char* buffer,
235 unsigned long buf_size) {
236 auto* pDefault = static_cast<FPDF_SYSFONTINFO_DEFAULT*>(pThis);
237 // SAFETY: required from caller.
238 return pdfium::checked_cast<unsigned long>(pDefault->m_pFontInfo->GetFontData(
239 hFont, table, UNSAFE_BUFFERS(pdfium::make_span(buffer, buf_size))));
240 }
241
242 // TODO(tsepez): should be UNSAFE_BUFFER_USAGE.
DefaultGetFaceName(struct _FPDF_SYSFONTINFO * pThis,void * hFont,char * buffer,unsigned long buf_size)243 static unsigned long DefaultGetFaceName(struct _FPDF_SYSFONTINFO* pThis,
244 void* hFont,
245 char* buffer,
246 unsigned long buf_size) {
247 ByteString name;
248 auto* pDefault = static_cast<FPDF_SYSFONTINFO_DEFAULT*>(pThis);
249 if (!pDefault->m_pFontInfo->GetFaceName(hFont, &name))
250 return 0;
251
252 const unsigned long copy_length =
253 pdfium::checked_cast<unsigned long>(name.GetLength() + 1);
254 if (copy_length <= buf_size)
255 strncpy(buffer, name.c_str(), copy_length * sizeof(ByteString::CharType));
256
257 return copy_length;
258 }
259
DefaultGetFontCharset(struct _FPDF_SYSFONTINFO * pThis,void * hFont)260 static int DefaultGetFontCharset(struct _FPDF_SYSFONTINFO* pThis, void* hFont) {
261 FX_Charset charset;
262 auto* pDefault = static_cast<FPDF_SYSFONTINFO_DEFAULT*>(pThis);
263 if (!pDefault->m_pFontInfo->GetFontCharset(hFont, &charset))
264 return 0;
265 return static_cast<int>(charset);
266 }
267
DefaultDeleteFont(struct _FPDF_SYSFONTINFO * pThis,void * hFont)268 static void DefaultDeleteFont(struct _FPDF_SYSFONTINFO* pThis, void* hFont) {
269 auto* pDefault = static_cast<FPDF_SYSFONTINFO_DEFAULT*>(pThis);
270 pDefault->m_pFontInfo->DeleteFont(hFont);
271 }
272
FPDF_GetDefaultSystemFontInfo()273 FPDF_EXPORT FPDF_SYSFONTINFO* FPDF_CALLCONV FPDF_GetDefaultSystemFontInfo() {
274 std::unique_ptr<SystemFontInfoIface> pFontInfo =
275 CFX_GEModule::Get()->GetPlatform()->CreateDefaultSystemFontInfo();
276 if (!pFontInfo)
277 return nullptr;
278
279 FPDF_SYSFONTINFO_DEFAULT* pFontInfoExt =
280 FX_Alloc(FPDF_SYSFONTINFO_DEFAULT, 1);
281 pFontInfoExt->DeleteFont = DefaultDeleteFont;
282 pFontInfoExt->EnumFonts = DefaultEnumFonts;
283 pFontInfoExt->GetFaceName = DefaultGetFaceName;
284 pFontInfoExt->GetFont = DefaultGetFont;
285 pFontInfoExt->GetFontCharset = DefaultGetFontCharset;
286 pFontInfoExt->GetFontData = DefaultGetFontData;
287 pFontInfoExt->MapFont = DefaultMapFont;
288 pFontInfoExt->Release = DefaultRelease;
289 pFontInfoExt->version = 1;
290 pFontInfoExt->m_pFontInfo = pFontInfo.release();
291 return pFontInfoExt;
292 }
293
294 FPDF_EXPORT void FPDF_CALLCONV
FPDF_FreeDefaultSystemFontInfo(FPDF_SYSFONTINFO * pFontInfo)295 FPDF_FreeDefaultSystemFontInfo(FPDF_SYSFONTINFO* pFontInfo) {
296 FX_Free(static_cast<FPDF_SYSFONTINFO_DEFAULT*>(pFontInfo));
297 }
298