// Copyright 2016 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "core/fxge/cfx_fontmgr.h" #include <memory> #include <utility> #include "core/fxge/cfx_fontmapper.h" #include "core/fxge/cfx_substfont.h" #include "core/fxge/fontdata/chromefontdata/chromefontdata.h" #include "core/fxge/fx_font.h" #include "core/fxge/ge/cttfontdesc.h" #include "core/fxge/ifx_systemfontinfo.h" #include "third_party/base/ptr_util.h" namespace { struct BuiltinFont { const uint8_t* m_pFontData; uint32_t m_dwSize; }; const BuiltinFont g_FoxitFonts[14] = { {g_FoxitFixedFontData, 17597}, {g_FoxitFixedBoldFontData, 18055}, {g_FoxitFixedBoldItalicFontData, 19151}, {g_FoxitFixedItalicFontData, 18746}, {g_FoxitSansFontData, 15025}, {g_FoxitSansBoldFontData, 16344}, {g_FoxitSansBoldItalicFontData, 16418}, {g_FoxitSansItalicFontData, 16339}, {g_FoxitSerifFontData, 19469}, {g_FoxitSerifBoldFontData, 19395}, {g_FoxitSerifBoldItalicFontData, 20733}, {g_FoxitSerifItalicFontData, 21227}, {g_FoxitSymbolFontData, 16729}, {g_FoxitDingbatsFontData, 29513}, }; const BuiltinFont g_MMFonts[2] = { {g_FoxitSerifMMFontData, 113417}, {g_FoxitSansMMFontData, 66919}, }; CFX_ByteString KeyNameFromFace(const CFX_ByteString& face_name, int weight, bool bItalic) { CFX_ByteString key(face_name); key += ','; key += CFX_ByteString::FormatInteger(weight); key += bItalic ? 'I' : 'N'; return key; } CFX_ByteString KeyNameFromSize(int ttc_size, uint32_t checksum) { CFX_ByteString key; key.Format("%d:%d", ttc_size, checksum); return key; } int GetTTCIndex(const uint8_t* pFontData, uint32_t ttc_size, uint32_t font_offset) { int face_index = 0; const uint8_t* p = pFontData + 8; uint32_t nfont = GET_TT_LONG(p); uint32_t index; for (index = 0; index < nfont; index++) { p = pFontData + 12 + index * 4; if (GET_TT_LONG(p) == font_offset) break; } if (index >= nfont) face_index = 0; else face_index = index; return face_index; } } // namespace CFX_FontMgr::CFX_FontMgr() : m_FTLibrary(nullptr), m_FTLibrarySupportsHinting(false) { m_pBuiltinMapper = pdfium::MakeUnique<CFX_FontMapper>(this); } CFX_FontMgr::~CFX_FontMgr() { for (const auto& pair : m_FaceMap) delete pair.second; // |m_pBuiltinMapper| references |m_FTLibrary|, so it has to be destroyed // first. m_pBuiltinMapper.reset(); FXFT_Done_FreeType(m_FTLibrary); } void CFX_FontMgr::InitFTLibrary() { if (m_FTLibrary) return; FXFT_Init_FreeType(&m_FTLibrary); m_FTLibrarySupportsHinting = FXFT_Library_SetLcdFilter(m_FTLibrary, FT_LCD_FILTER_DEFAULT) != FT_Err_Unimplemented_Feature; } void CFX_FontMgr::SetSystemFontInfo( std::unique_ptr<IFX_SystemFontInfo> pFontInfo) { m_pBuiltinMapper->SetSystemFontInfo(std::move(pFontInfo)); } FXFT_Face CFX_FontMgr::FindSubstFont(const CFX_ByteString& face_name, bool bTrueType, uint32_t flags, int weight, int italic_angle, int CharsetCP, CFX_SubstFont* pSubstFont) { InitFTLibrary(); return m_pBuiltinMapper->FindSubstFont(face_name, bTrueType, flags, weight, italic_angle, CharsetCP, pSubstFont); } FXFT_Face CFX_FontMgr::GetCachedFace(const CFX_ByteString& face_name, int weight, bool bItalic, uint8_t*& pFontData) { auto it = m_FaceMap.find(KeyNameFromFace(face_name, weight, bItalic)); if (it == m_FaceMap.end()) return nullptr; CTTFontDesc* pFontDesc = it->second; pFontData = pFontDesc->m_pFontData; pFontDesc->m_RefCount++; return pFontDesc->m_SingleFace; } FXFT_Face CFX_FontMgr::AddCachedFace(const CFX_ByteString& face_name, int weight, bool bItalic, uint8_t* pData, uint32_t size, int face_index) { CTTFontDesc* pFontDesc = new CTTFontDesc; pFontDesc->m_Type = 1; pFontDesc->m_SingleFace = nullptr; pFontDesc->m_pFontData = pData; pFontDesc->m_RefCount = 1; InitFTLibrary(); FXFT_Library library = m_FTLibrary; int ret = FXFT_New_Memory_Face(library, pData, size, face_index, &pFontDesc->m_SingleFace); if (ret) { delete pFontDesc; return nullptr; } ret = FXFT_Set_Pixel_Sizes(pFontDesc->m_SingleFace, 64, 64); if (ret) { delete pFontDesc; return nullptr; } m_FaceMap[KeyNameFromFace(face_name, weight, bItalic)] = pFontDesc; return pFontDesc->m_SingleFace; } FXFT_Face CFX_FontMgr::GetCachedTTCFace(int ttc_size, uint32_t checksum, int font_offset, uint8_t*& pFontData) { auto it = m_FaceMap.find(KeyNameFromSize(ttc_size, checksum)); if (it == m_FaceMap.end()) return nullptr; CTTFontDesc* pFontDesc = it->second; pFontData = pFontDesc->m_pFontData; pFontDesc->m_RefCount++; int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset); if (!pFontDesc->m_TTCFaces[face_index]) { pFontDesc->m_TTCFaces[face_index] = GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index); } return pFontDesc->m_TTCFaces[face_index]; } FXFT_Face CFX_FontMgr::AddCachedTTCFace(int ttc_size, uint32_t checksum, uint8_t* pData, uint32_t size, int font_offset) { CTTFontDesc* pFontDesc = new CTTFontDesc; pFontDesc->m_Type = 2; pFontDesc->m_pFontData = pData; for (int i = 0; i < 16; i++) pFontDesc->m_TTCFaces[i] = nullptr; pFontDesc->m_RefCount++; m_FaceMap[KeyNameFromSize(ttc_size, checksum)] = pFontDesc; int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset); pFontDesc->m_TTCFaces[face_index] = GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index); return pFontDesc->m_TTCFaces[face_index]; } FXFT_Face CFX_FontMgr::GetFixedFace(const uint8_t* pData, uint32_t size, int face_index) { InitFTLibrary(); FXFT_Library library = m_FTLibrary; FXFT_Face face = nullptr; if (FXFT_New_Memory_Face(library, pData, size, face_index, &face)) return nullptr; return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; } FXFT_Face CFX_FontMgr::GetFileFace(const FX_CHAR* filename, int face_index) { InitFTLibrary(); FXFT_Library library = m_FTLibrary; FXFT_Face face = nullptr; if (FXFT_New_Face(library, filename, face_index, &face)) return nullptr; return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; } void CFX_FontMgr::ReleaseFace(FXFT_Face face) { if (!face) return; bool bNeedFaceDone = true; auto it = m_FaceMap.begin(); while (it != m_FaceMap.end()) { auto temp = it++; int nRet = temp->second->ReleaseFace(face); if (nRet == -1) continue; bNeedFaceDone = false; if (nRet == 0) m_FaceMap.erase(temp); break; } if (bNeedFaceDone && !m_pBuiltinMapper->IsBuiltinFace(face)) FXFT_Done_Face(face); } bool CFX_FontMgr::GetBuiltinFont(size_t index, const uint8_t** pFontData, uint32_t* size) { if (index < FX_ArraySize(g_FoxitFonts)) { *pFontData = g_FoxitFonts[index].m_pFontData; *size = g_FoxitFonts[index].m_dwSize; return true; } index -= FX_ArraySize(g_FoxitFonts); if (index < FX_ArraySize(g_MMFonts)) { *pFontData = g_MMFonts[index].m_pFontData; *size = g_MMFonts[index].m_dwSize; return true; } return false; }