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/cttfontdesc.h" 15 #include "core/fxge/fontdata/chromefontdata/chromefontdata.h" 16 #include "core/fxge/fx_font.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 49 ByteString KeyNameFromFace(const ByteString& face_name, 50 int weight, 51 bool bItalic) { 52 ByteString key(face_name); 53 key += ','; 54 key += ByteString::FormatInteger(weight); 55 key += bItalic ? 'I' : 'N'; 56 return key; 57 } 58 59 ByteString KeyNameFromSize(int ttc_size, uint32_t checksum) { 60 return ByteString::Format("%d:%d", ttc_size, checksum); 61 } 62 63 int GetTTCIndex(const uint8_t* pFontData, 64 uint32_t ttc_size, 65 uint32_t font_offset) { 66 const uint8_t* p = pFontData + 8; 67 uint32_t nfont = GET_TT_LONG(p); 68 uint32_t index; 69 for (index = 0; index < nfont; index++) { 70 p = pFontData + 12 + index * 4; 71 if (GET_TT_LONG(p) == font_offset) 72 break; 73 } 74 return index < nfont ? index : 0; 75 } 76 77 } // namespace 78 79 CFX_FontMgr::CFX_FontMgr() 80 : m_FTLibrary(nullptr), m_FTLibrarySupportsHinting(false) { 81 m_pBuiltinMapper = pdfium::MakeUnique<CFX_FontMapper>(this); 82 } 83 84 CFX_FontMgr::~CFX_FontMgr() { 85 // |m_FaceMap| and |m_pBuiltinMapper| reference |m_FTLibrary|, so they must 86 // be destroyed first. 87 m_FaceMap.clear(); 88 m_pBuiltinMapper.reset(); 89 FXFT_Done_FreeType(m_FTLibrary); 90 } 91 92 void CFX_FontMgr::InitFTLibrary() { 93 if (m_FTLibrary) 94 return; 95 96 FXFT_Init_FreeType(&m_FTLibrary); 97 m_FTLibrarySupportsHinting = 98 SetLcdFilterMode() || FreeTypeVersionSupportsHinting(); 99 } 100 101 void CFX_FontMgr::SetSystemFontInfo( 102 std::unique_ptr<IFX_SystemFontInfo> pFontInfo) { 103 m_pBuiltinMapper->SetSystemFontInfo(std::move(pFontInfo)); 104 } 105 106 FXFT_Face CFX_FontMgr::FindSubstFont(const ByteString& face_name, 107 bool bTrueType, 108 uint32_t flags, 109 int weight, 110 int italic_angle, 111 int CharsetCP, 112 CFX_SubstFont* pSubstFont) { 113 InitFTLibrary(); 114 return m_pBuiltinMapper->FindSubstFont(face_name, bTrueType, flags, weight, 115 italic_angle, CharsetCP, pSubstFont); 116 } 117 118 FXFT_Face CFX_FontMgr::GetCachedFace(const ByteString& face_name, 119 int weight, 120 bool bItalic, 121 uint8_t** pFontData) { 122 auto it = m_FaceMap.find(KeyNameFromFace(face_name, weight, bItalic)); 123 if (it == m_FaceMap.end()) 124 return nullptr; 125 126 CTTFontDesc* pFontDesc = it->second.get(); 127 *pFontData = pFontDesc->FontData(); 128 pFontDesc->AddRef(); 129 return pFontDesc->SingleFace(); 130 } 131 132 FXFT_Face CFX_FontMgr::AddCachedFace(const ByteString& face_name, 133 int weight, 134 bool bItalic, 135 uint8_t* pData, 136 uint32_t size, 137 int face_index) { 138 InitFTLibrary(); 139 140 FXFT_Face face = nullptr; 141 int ret = FXFT_New_Memory_Face(m_FTLibrary, pData, size, face_index, &face); 142 if (ret) 143 return nullptr; 144 145 ret = FXFT_Set_Pixel_Sizes(face, 64, 64); 146 if (ret) 147 return nullptr; 148 149 auto pFontDesc = pdfium::MakeUnique<CTTFontDesc>(pData, face); 150 CTTFontDesc* pResult = pFontDesc.get(); 151 m_FaceMap[KeyNameFromFace(face_name, weight, bItalic)] = std::move(pFontDesc); 152 return pResult->SingleFace(); 153 } 154 155 FXFT_Face CFX_FontMgr::GetCachedTTCFace(int ttc_size, 156 uint32_t checksum, 157 int font_offset, 158 uint8_t** pFontData) { 159 auto it = m_FaceMap.find(KeyNameFromSize(ttc_size, checksum)); 160 if (it == m_FaceMap.end()) 161 return nullptr; 162 163 CTTFontDesc* pFontDesc = it->second.get(); 164 *pFontData = pFontDesc->FontData(); 165 int face_index = GetTTCIndex(pFontDesc->FontData(), ttc_size, font_offset); 166 if (!pFontDesc->TTCFace(face_index)) { 167 pFontDesc->SetTTCFace( 168 face_index, GetFixedFace(pFontDesc->FontData(), ttc_size, face_index)); 169 } 170 pFontDesc->AddRef(); 171 return pFontDesc->TTCFace(face_index); 172 } 173 174 FXFT_Face CFX_FontMgr::AddCachedTTCFace(int ttc_size, 175 uint32_t checksum, 176 uint8_t* pData, 177 uint32_t size, 178 int font_offset) { 179 int face_index = GetTTCIndex(pData, ttc_size, font_offset); 180 FXFT_Face face = GetFixedFace(pData, ttc_size, face_index); 181 auto pFontDesc = pdfium::MakeUnique<CTTFontDesc>(pData, face_index, face); 182 m_FaceMap[KeyNameFromSize(ttc_size, checksum)] = std::move(pFontDesc); 183 return face; 184 } 185 186 FXFT_Face CFX_FontMgr::GetFixedFace(const uint8_t* pData, 187 uint32_t size, 188 int face_index) { 189 InitFTLibrary(); 190 FXFT_Face face = nullptr; 191 if (FXFT_New_Memory_Face(m_FTLibrary, pData, size, face_index, &face)) 192 return nullptr; 193 return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; 194 } 195 196 FXFT_Face CFX_FontMgr::GetFileFace(const char* filename, int face_index) { 197 InitFTLibrary(); 198 FXFT_Face face = nullptr; 199 if (FXFT_New_Face(m_FTLibrary, filename, face_index, &face)) 200 return nullptr; 201 return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; 202 } 203 204 void CFX_FontMgr::ReleaseFace(FXFT_Face face) { 205 if (!face) 206 return; 207 bool bNeedFaceDone = true; 208 for (auto it = m_FaceMap.begin(); it != m_FaceMap.end(); ++it) { 209 CTTFontDesc::ReleaseStatus nRet = it->second->ReleaseFace(face); 210 if (nRet == CTTFontDesc::kNotAppropriate) 211 continue; 212 bNeedFaceDone = false; 213 if (nRet == CTTFontDesc::kReleased) 214 m_FaceMap.erase(it); 215 break; 216 } 217 if (bNeedFaceDone && !m_pBuiltinMapper->IsBuiltinFace(face)) 218 FXFT_Done_Face(face); 219 } 220 221 bool CFX_FontMgr::GetBuiltinFont(size_t index, 222 const uint8_t** pFontData, 223 uint32_t* size) { 224 if (index < FX_ArraySize(g_FoxitFonts)) { 225 *pFontData = g_FoxitFonts[index].m_pFontData; 226 *size = g_FoxitFonts[index].m_dwSize; 227 return true; 228 } 229 size_t mm_index = index - FX_ArraySize(g_FoxitFonts); 230 if (mm_index < FX_ArraySize(g_MMFonts)) { 231 *pFontData = g_MMFonts[mm_index].m_pFontData; 232 *size = g_MMFonts[mm_index].m_dwSize; 233 return true; 234 } 235 return false; 236 } 237 238 bool CFX_FontMgr::FreeTypeVersionSupportsHinting() const { 239 FT_Int major; 240 FT_Int minor; 241 FT_Int patch; 242 FXFT_Library_Version(m_FTLibrary, &major, &minor, &patch); 243 // Freetype versions >= 2.8.1 support hinting even if subpixel rendering is 244 // disabled. https://sourceforge.net/projects/freetype/files/freetype2/2.8.1/ 245 return major > 2 || (major == 2 && minor > 8) || 246 (major == 2 && minor == 8 && patch >= 1); 247 } 248 249 bool CFX_FontMgr::SetLcdFilterMode() const { 250 return FXFT_Library_SetLcdFilter(m_FTLibrary, FT_LCD_FILTER_DEFAULT) != 251 FT_Err_Unimplemented_Feature; 252 } 253