Home | History | Annotate | Download | only in fxge
      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