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
20namespace {
21
22struct BuiltinFont {
23  const uint8_t* m_pFontData;
24  uint32_t m_dwSize;
25};
26
27const 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
44const BuiltinFont g_MMFonts[2] = {
45    {g_FoxitSerifMMFontData, 113417},
46    {g_FoxitSansMMFontData, 66919},
47};
48
49CFX_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
59CFX_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
65int 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
86CFX_FontMgr::CFX_FontMgr()
87    : m_FTLibrary(nullptr), m_FTLibrarySupportsHinting(false) {
88  m_pBuiltinMapper = pdfium::MakeUnique<CFX_FontMapper>(this);
89}
90
91CFX_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
101void 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
110void CFX_FontMgr::SetSystemFontInfo(
111    std::unique_ptr<IFX_SystemFontInfo> pFontInfo) {
112  m_pBuiltinMapper->SetSystemFontInfo(std::move(pFontInfo));
113}
114
115FXFT_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
127FXFT_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
141FXFT_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
170FXFT_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
189FXFT_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
207FXFT_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
218FXFT_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
227void 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
246bool 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