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/fxge/cfx_fontmgr.h"
8 
9 #include <memory>
10 #include <utility>
11 
12 #include "core/fxge/cfx_fontmapper.h"
13 #include "core/fxge/cfx_substfont.h"
14 #include "core/fxge/fontdata/chromefontdata/chromefontdata.h"
15 #include "core/fxge/fx_font.h"
16 #include "core/fxge/ge/cttfontdesc.h"
17 #include "core/fxge/ifx_systemfontinfo.h"
18 #include "third_party/base/ptr_util.h"
19 
20 namespace {
21 
22 struct BuiltinFont {
23   const uint8_t* m_pFontData;
24   uint32_t m_dwSize;
25 };
26 
27 const BuiltinFont g_FoxitFonts[14] = {
28     {g_FoxitFixedFontData, 17597},
29     {g_FoxitFixedBoldFontData, 18055},
30     {g_FoxitFixedBoldItalicFontData, 19151},
31     {g_FoxitFixedItalicFontData, 18746},
32     {g_FoxitSansFontData, 15025},
33     {g_FoxitSansBoldFontData, 16344},
34     {g_FoxitSansBoldItalicFontData, 16418},
35     {g_FoxitSansItalicFontData, 16339},
36     {g_FoxitSerifFontData, 19469},
37     {g_FoxitSerifBoldFontData, 19395},
38     {g_FoxitSerifBoldItalicFontData, 20733},
39     {g_FoxitSerifItalicFontData, 21227},
40     {g_FoxitSymbolFontData, 16729},
41     {g_FoxitDingbatsFontData, 29513},
42 };
43 
44 const BuiltinFont g_MMFonts[2] = {
45     {g_FoxitSerifMMFontData, 113417},
46     {g_FoxitSansMMFontData, 66919},
47 };
48 
KeyNameFromFace(const CFX_ByteString & face_name,int weight,bool bItalic)49 CFX_ByteString KeyNameFromFace(const CFX_ByteString& face_name,
50                                int weight,
51                                bool bItalic) {
52   CFX_ByteString key(face_name);
53   key += ',';
54   key += CFX_ByteString::FormatInteger(weight);
55   key += bItalic ? 'I' : 'N';
56   return key;
57 }
58 
KeyNameFromSize(int ttc_size,uint32_t checksum)59 CFX_ByteString KeyNameFromSize(int ttc_size, uint32_t checksum) {
60   CFX_ByteString key;
61   key.Format("%d:%d", ttc_size, checksum);
62   return key;
63 }
64 
GetTTCIndex(const uint8_t * pFontData,uint32_t ttc_size,uint32_t font_offset)65 int GetTTCIndex(const uint8_t* pFontData,
66                 uint32_t ttc_size,
67                 uint32_t font_offset) {
68   int face_index = 0;
69   const uint8_t* p = pFontData + 8;
70   uint32_t nfont = GET_TT_LONG(p);
71   uint32_t index;
72   for (index = 0; index < nfont; index++) {
73     p = pFontData + 12 + index * 4;
74     if (GET_TT_LONG(p) == font_offset)
75       break;
76   }
77   if (index >= nfont)
78     face_index = 0;
79   else
80     face_index = index;
81   return face_index;
82 }
83 
84 }  // namespace
85 
CFX_FontMgr()86 CFX_FontMgr::CFX_FontMgr()
87     : m_FTLibrary(nullptr), m_FTLibrarySupportsHinting(false) {
88   m_pBuiltinMapper = pdfium::MakeUnique<CFX_FontMapper>(this);
89 }
90 
~CFX_FontMgr()91 CFX_FontMgr::~CFX_FontMgr() {
92   for (const auto& pair : m_FaceMap)
93     delete pair.second;
94 
95   // |m_pBuiltinMapper| references |m_FTLibrary|, so it has to be destroyed
96   // first.
97   m_pBuiltinMapper.reset();
98   FXFT_Done_FreeType(m_FTLibrary);
99 }
100 
InitFTLibrary()101 void CFX_FontMgr::InitFTLibrary() {
102   if (m_FTLibrary)
103     return;
104   FXFT_Init_FreeType(&m_FTLibrary);
105   m_FTLibrarySupportsHinting =
106       FXFT_Library_SetLcdFilter(m_FTLibrary, FT_LCD_FILTER_DEFAULT) !=
107       FT_Err_Unimplemented_Feature;
108 }
109 
SetSystemFontInfo(std::unique_ptr<IFX_SystemFontInfo> pFontInfo)110 void CFX_FontMgr::SetSystemFontInfo(
111     std::unique_ptr<IFX_SystemFontInfo> pFontInfo) {
112   m_pBuiltinMapper->SetSystemFontInfo(std::move(pFontInfo));
113 }
114 
FindSubstFont(const CFX_ByteString & face_name,bool bTrueType,uint32_t flags,int weight,int italic_angle,int CharsetCP,CFX_SubstFont * pSubstFont)115 FXFT_Face CFX_FontMgr::FindSubstFont(const CFX_ByteString& face_name,
116                                      bool bTrueType,
117                                      uint32_t flags,
118                                      int weight,
119                                      int italic_angle,
120                                      int CharsetCP,
121                                      CFX_SubstFont* pSubstFont) {
122   InitFTLibrary();
123   return m_pBuiltinMapper->FindSubstFont(face_name, bTrueType, flags, weight,
124                                          italic_angle, CharsetCP, pSubstFont);
125 }
126 
GetCachedFace(const CFX_ByteString & face_name,int weight,bool bItalic,uint8_t * & pFontData)127 FXFT_Face CFX_FontMgr::GetCachedFace(const CFX_ByteString& face_name,
128                                      int weight,
129                                      bool bItalic,
130                                      uint8_t*& pFontData) {
131   auto it = m_FaceMap.find(KeyNameFromFace(face_name, weight, bItalic));
132   if (it == m_FaceMap.end())
133     return nullptr;
134 
135   CTTFontDesc* pFontDesc = it->second;
136   pFontData = pFontDesc->m_pFontData;
137   pFontDesc->m_RefCount++;
138   return pFontDesc->m_SingleFace;
139 }
140 
AddCachedFace(const CFX_ByteString & face_name,int weight,bool bItalic,uint8_t * pData,uint32_t size,int face_index)141 FXFT_Face CFX_FontMgr::AddCachedFace(const CFX_ByteString& face_name,
142                                      int weight,
143                                      bool bItalic,
144                                      uint8_t* pData,
145                                      uint32_t size,
146                                      int face_index) {
147   CTTFontDesc* pFontDesc = new CTTFontDesc;
148   pFontDesc->m_Type = 1;
149   pFontDesc->m_SingleFace = nullptr;
150   pFontDesc->m_pFontData = pData;
151   pFontDesc->m_RefCount = 1;
152 
153   InitFTLibrary();
154   FXFT_Library library = m_FTLibrary;
155   int ret = FXFT_New_Memory_Face(library, pData, size, face_index,
156                                  &pFontDesc->m_SingleFace);
157   if (ret) {
158     delete pFontDesc;
159     return nullptr;
160   }
161   ret = FXFT_Set_Pixel_Sizes(pFontDesc->m_SingleFace, 64, 64);
162   if (ret) {
163     delete pFontDesc;
164     return nullptr;
165   }
166   m_FaceMap[KeyNameFromFace(face_name, weight, bItalic)] = pFontDesc;
167   return pFontDesc->m_SingleFace;
168 }
169 
GetCachedTTCFace(int ttc_size,uint32_t checksum,int font_offset,uint8_t * & pFontData)170 FXFT_Face CFX_FontMgr::GetCachedTTCFace(int ttc_size,
171                                         uint32_t checksum,
172                                         int font_offset,
173                                         uint8_t*& pFontData) {
174   auto it = m_FaceMap.find(KeyNameFromSize(ttc_size, checksum));
175   if (it == m_FaceMap.end())
176     return nullptr;
177 
178   CTTFontDesc* pFontDesc = it->second;
179   pFontData = pFontDesc->m_pFontData;
180   pFontDesc->m_RefCount++;
181   int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset);
182   if (!pFontDesc->m_TTCFaces[face_index]) {
183     pFontDesc->m_TTCFaces[face_index] =
184         GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index);
185   }
186   return pFontDesc->m_TTCFaces[face_index];
187 }
188 
AddCachedTTCFace(int ttc_size,uint32_t checksum,uint8_t * pData,uint32_t size,int font_offset)189 FXFT_Face CFX_FontMgr::AddCachedTTCFace(int ttc_size,
190                                         uint32_t checksum,
191                                         uint8_t* pData,
192                                         uint32_t size,
193                                         int font_offset) {
194   CTTFontDesc* pFontDesc = new CTTFontDesc;
195   pFontDesc->m_Type = 2;
196   pFontDesc->m_pFontData = pData;
197   for (int i = 0; i < 16; i++)
198     pFontDesc->m_TTCFaces[i] = nullptr;
199   pFontDesc->m_RefCount++;
200   m_FaceMap[KeyNameFromSize(ttc_size, checksum)] = pFontDesc;
201   int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset);
202   pFontDesc->m_TTCFaces[face_index] =
203       GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index);
204   return pFontDesc->m_TTCFaces[face_index];
205 }
206 
GetFixedFace(const uint8_t * pData,uint32_t size,int face_index)207 FXFT_Face CFX_FontMgr::GetFixedFace(const uint8_t* pData,
208                                     uint32_t size,
209                                     int face_index) {
210   InitFTLibrary();
211   FXFT_Library library = m_FTLibrary;
212   FXFT_Face face = nullptr;
213   if (FXFT_New_Memory_Face(library, pData, size, face_index, &face))
214     return nullptr;
215   return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face;
216 }
217 
GetFileFace(const FX_CHAR * filename,int face_index)218 FXFT_Face CFX_FontMgr::GetFileFace(const FX_CHAR* filename, int face_index) {
219   InitFTLibrary();
220   FXFT_Library library = m_FTLibrary;
221   FXFT_Face face = nullptr;
222   if (FXFT_New_Face(library, filename, face_index, &face))
223     return nullptr;
224   return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face;
225 }
226 
ReleaseFace(FXFT_Face face)227 void CFX_FontMgr::ReleaseFace(FXFT_Face face) {
228   if (!face)
229     return;
230   bool bNeedFaceDone = true;
231   auto it = m_FaceMap.begin();
232   while (it != m_FaceMap.end()) {
233     auto temp = it++;
234     int nRet = temp->second->ReleaseFace(face);
235     if (nRet == -1)
236       continue;
237     bNeedFaceDone = false;
238     if (nRet == 0)
239       m_FaceMap.erase(temp);
240     break;
241   }
242   if (bNeedFaceDone && !m_pBuiltinMapper->IsBuiltinFace(face))
243     FXFT_Done_Face(face);
244 }
245 
GetBuiltinFont(size_t index,const uint8_t ** pFontData,uint32_t * size)246 bool CFX_FontMgr::GetBuiltinFont(size_t index,
247                                  const uint8_t** pFontData,
248                                  uint32_t* size) {
249   if (index < FX_ArraySize(g_FoxitFonts)) {
250     *pFontData = g_FoxitFonts[index].m_pFontData;
251     *size = g_FoxitFonts[index].m_dwSize;
252     return true;
253   }
254   index -= FX_ArraySize(g_FoxitFonts);
255   if (index < FX_ArraySize(g_MMFonts)) {
256     *pFontData = g_MMFonts[index].m_pFontData;
257     *size = g_MMFonts[index].m_dwSize;
258     return true;
259   }
260   return false;
261 }
262