• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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