Home | History | Annotate | Download | only in font
      1 // Copyright 2014 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 "xfa/fgas/font/cfgas_gefont.h"
      8 
      9 #include <memory>
     10 #include <utility>
     11 
     12 #include "core/fxge/cfx_substfont.h"
     13 #include "core/fxge/cfx_unicodeencoding.h"
     14 #include "core/fxge/cfx_unicodeencodingex.h"
     15 #include "third_party/base/ptr_util.h"
     16 #include "xfa/fgas/crt/fgas_codepage.h"
     17 #include "xfa/fgas/font/fgas_fontutils.h"
     18 #include "xfa/fxfa/xfa_fontmgr.h"
     19 
     20 // static
     21 CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(
     22     const FX_WCHAR* pszFontFamily,
     23     uint32_t dwFontStyles,
     24     uint16_t wCodePage,
     25     CFGAS_FontMgr* pFontMgr) {
     26 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
     27   if (!pFontMgr)
     28     return nullptr;
     29 
     30   return pFontMgr->GetFontByCodePage(wCodePage, dwFontStyles, pszFontFamily);
     31 #else
     32   auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
     33   if (!pFont->LoadFontInternal(pszFontFamily, dwFontStyles, wCodePage))
     34     return nullptr;
     35   return pFont;
     36 #endif
     37 }
     38 
     39 // static
     40 CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(CFX_Font* pExternalFont,
     41                                                    CFGAS_FontMgr* pFontMgr) {
     42   auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
     43   if (!pFont->LoadFontInternal(pExternalFont))
     44     return nullptr;
     45   return pFont;
     46 }
     47 
     48 // static
     49 CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(
     50     std::unique_ptr<CFX_Font> pInternalFont,
     51     CFGAS_FontMgr* pFontMgr) {
     52   auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
     53   if (!pFont->LoadFontInternal(std::move(pInternalFont)))
     54     return nullptr;
     55   return pFont;
     56 }
     57 
     58 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
     59 // static
     60 CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(const uint8_t* pBuffer,
     61                                                    int32_t iLength,
     62                                                    CFGAS_FontMgr* pFontMgr) {
     63   auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
     64   if (pFont->LoadFontInternal(pBuffer, iLength))
     65     return nullptr;
     66   return pFont;
     67 }
     68 
     69 // static
     70 CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(
     71     const CFX_RetainPtr<IFGAS_Stream>& pFontStream,
     72     CFGAS_FontMgr* pFontMgr,
     73     bool bSaveStream) {
     74   auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
     75   if (!pFont->LoadFontInternal(pFontStream, bSaveStream))
     76     return nullptr;
     77   return pFont;
     78 }
     79 #endif  // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
     80 
     81 CFGAS_GEFont::CFGAS_GEFont(CFGAS_FontMgr* pFontMgr)
     82     :
     83 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
     84       m_bUseLogFontStyle(false),
     85       m_dwLogFontStyle(0),
     86 #endif
     87       m_pFont(nullptr),
     88       m_pFontMgr(pFontMgr),
     89       m_bExternalFont(false),
     90       m_pProvider(nullptr) {
     91 }
     92 
     93 CFGAS_GEFont::CFGAS_GEFont(const CFX_RetainPtr<CFGAS_GEFont>& src,
     94                            uint32_t dwFontStyles)
     95     :
     96 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
     97       m_bUseLogFontStyle(false),
     98       m_dwLogFontStyle(0),
     99 #endif
    100       m_pFont(nullptr),
    101       m_pSrcFont(src),
    102       m_pFontMgr(src->m_pFontMgr),
    103       m_bExternalFont(false),
    104       m_pProvider(nullptr) {
    105   ASSERT(m_pSrcFont->m_pFont);
    106   m_pFont = new CFX_Font;
    107   m_pFont->LoadClone(m_pSrcFont->m_pFont);
    108   CFX_SubstFont* pSubst = m_pFont->GetSubstFont();
    109   if (!pSubst) {
    110     pSubst = new CFX_SubstFont;
    111     m_pFont->SetSubstFont(std::unique_ptr<CFX_SubstFont>(pSubst));
    112   }
    113   pSubst->m_Weight =
    114       (dwFontStyles & FX_FONTSTYLE_Bold) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL;
    115   if (dwFontStyles & FX_FONTSTYLE_Italic)
    116     pSubst->m_SubstFlags |= FXFONT_SUBST_ITALIC;
    117   InitFont();
    118 }
    119 
    120 CFGAS_GEFont::~CFGAS_GEFont() {
    121   if (!m_bExternalFont)
    122     delete m_pFont;
    123 }
    124 
    125 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    126 bool CFGAS_GEFont::LoadFontInternal(const FX_WCHAR* pszFontFamily,
    127                                     uint32_t dwFontStyles,
    128                                     uint16_t wCodePage) {
    129   if (m_pFont)
    130     return false;
    131   CFX_ByteString csFontFamily;
    132   if (pszFontFamily)
    133     csFontFamily = CFX_ByteString::FromUnicode(pszFontFamily);
    134   uint32_t dwFlags = 0;
    135   if (dwFontStyles & FX_FONTSTYLE_FixedPitch)
    136     dwFlags |= FXFONT_FIXED_PITCH;
    137   if (dwFontStyles & FX_FONTSTYLE_Serif)
    138     dwFlags |= FXFONT_SERIF;
    139   if (dwFontStyles & FX_FONTSTYLE_Symbolic)
    140     dwFlags |= FXFONT_SYMBOLIC;
    141   if (dwFontStyles & FX_FONTSTYLE_Script)
    142     dwFlags |= FXFONT_SCRIPT;
    143   if (dwFontStyles & FX_FONTSTYLE_Italic)
    144     dwFlags |= FXFONT_ITALIC;
    145   if (dwFontStyles & FX_FONTSTYLE_Bold)
    146     dwFlags |= FXFONT_BOLD;
    147   if (dwFontStyles & FX_FONTSTYLE_ExactMatch)
    148     dwFlags |= FXFONT_EXACTMATCH;
    149   int32_t iWeight =
    150       (dwFontStyles & FX_FONTSTYLE_Bold) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL;
    151   m_pFont = new CFX_Font;
    152   if ((dwFlags & FXFONT_ITALIC) && (dwFlags & FXFONT_BOLD))
    153     csFontFamily += ",BoldItalic";
    154   else if (dwFlags & FXFONT_BOLD)
    155     csFontFamily += ",Bold";
    156   else if (dwFlags & FXFONT_ITALIC)
    157     csFontFamily += ",Italic";
    158   m_pFont->LoadSubst(csFontFamily, true, dwFlags, iWeight, 0, wCodePage, false);
    159   if (!m_pFont->GetFace())
    160     return false;
    161   return InitFont();
    162 }
    163 
    164 bool CFGAS_GEFont::LoadFontInternal(const uint8_t* pBuffer, int32_t length) {
    165   if (m_pFont)
    166     return false;
    167 
    168   m_pFont = new CFX_Font;
    169   if (!m_pFont->LoadEmbedded(pBuffer, length))
    170     return false;
    171   return InitFont();
    172 }
    173 
    174 bool CFGAS_GEFont::LoadFontInternal(
    175     const CFX_RetainPtr<IFGAS_Stream>& pFontStream,
    176     bool bSaveStream) {
    177   if (m_pFont || m_pFileRead || !pFontStream || pFontStream->GetLength() < 1)
    178     return false;
    179   if (bSaveStream)
    180     m_pStream = pFontStream;
    181 
    182   m_pFileRead = pFontStream->MakeSeekableReadStream();
    183   m_pFont = new CFX_Font;
    184   if (!m_pFont->LoadFile(m_pFileRead)) {
    185     m_pFileRead.Reset();
    186     return false;
    187   }
    188   return InitFont();
    189 }
    190 #endif  // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    191 
    192 bool CFGAS_GEFont::LoadFontInternal(CFX_Font* pExternalFont) {
    193   if (m_pFont || !pExternalFont)
    194     return false;
    195 
    196   m_pFont = pExternalFont;
    197   m_bExternalFont = true;
    198   return InitFont();
    199 }
    200 
    201 bool CFGAS_GEFont::LoadFontInternal(std::unique_ptr<CFX_Font> pInternalFont) {
    202   if (m_pFont || !pInternalFont)
    203     return false;
    204 
    205   m_pFont = pInternalFont.release();
    206   m_bExternalFont = false;
    207   return InitFont();
    208 }
    209 
    210 bool CFGAS_GEFont::InitFont() {
    211   if (!m_pFont)
    212     return false;
    213 
    214   if (!m_pFontEncoding) {
    215     m_pFontEncoding.reset(FX_CreateFontEncodingEx(m_pFont));
    216     if (!m_pFontEncoding)
    217       return false;
    218   }
    219   if (!m_pCharWidthMap) {
    220     m_pCharWidthMap =
    221         pdfium::MakeUnique<CFX_DiscreteArrayTemplate<uint16_t>>(1024);
    222   }
    223   return true;
    224 }
    225 
    226 CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::Derive(uint32_t dwFontStyles,
    227                                                  uint16_t wCodePage) {
    228   CFX_RetainPtr<CFGAS_GEFont> pFont(this);
    229   if (GetFontStyles() == dwFontStyles)
    230     return pFont;
    231   return pdfium::MakeRetain<CFGAS_GEFont>(pFont, dwFontStyles);
    232 }
    233 
    234 CFX_WideString CFGAS_GEFont::GetFamilyName() const {
    235   if (!m_pFont->GetSubstFont() ||
    236       m_pFont->GetSubstFont()->m_Family.GetLength() == 0) {
    237     return CFX_WideString::FromLocal(m_pFont->GetFamilyName().AsStringC());
    238   }
    239   return CFX_WideString::FromLocal(
    240       m_pFont->GetSubstFont()->m_Family.AsStringC());
    241 }
    242 
    243 uint32_t CFGAS_GEFont::GetFontStyles() const {
    244   ASSERT(m_pFont);
    245 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
    246   if (m_bUseLogFontStyle)
    247     return m_dwLogFontStyle;
    248 #endif
    249 
    250   uint32_t dwStyles = 0;
    251   auto* pSubstFont = m_pFont->GetSubstFont();
    252   if (pSubstFont) {
    253     if (pSubstFont->m_Weight == FXFONT_FW_BOLD)
    254       dwStyles |= FX_FONTSTYLE_Bold;
    255     if (pSubstFont->m_SubstFlags & FXFONT_SUBST_ITALIC)
    256       dwStyles |= FX_FONTSTYLE_Italic;
    257   } else {
    258     if (m_pFont->IsBold())
    259       dwStyles |= FX_FONTSTYLE_Bold;
    260     if (m_pFont->IsItalic())
    261       dwStyles |= FX_FONTSTYLE_Italic;
    262   }
    263   return dwStyles;
    264 }
    265 
    266 bool CFGAS_GEFont::GetCharWidth(FX_WCHAR wUnicode,
    267                                 int32_t& iWidth,
    268                                 bool bCharCode) {
    269   return GetCharWidthInternal(wUnicode, iWidth, true, bCharCode);
    270 }
    271 
    272 bool CFGAS_GEFont::GetCharWidthInternal(FX_WCHAR wUnicode,
    273                                         int32_t& iWidth,
    274                                         bool bRecursive,
    275                                         bool bCharCode) {
    276   ASSERT(m_pCharWidthMap);
    277   iWidth = m_pCharWidthMap->GetAt(wUnicode, 0);
    278   if (iWidth == 65535)
    279     return false;
    280 
    281   if (iWidth > 0)
    282     return true;
    283 
    284   if (!m_pProvider ||
    285       !m_pProvider->GetCharWidth(CFX_RetainPtr<CFGAS_GEFont>(this), wUnicode,
    286                                  bCharCode, &iWidth)) {
    287     CFX_RetainPtr<CFGAS_GEFont> pFont;
    288     int32_t iGlyph = GetGlyphIndex(wUnicode, true, &pFont, bCharCode);
    289     if (iGlyph != 0xFFFF && pFont) {
    290       if (pFont.Get() == this) {
    291         iWidth = m_pFont->GetGlyphWidth(iGlyph);
    292         if (iWidth < 0)
    293           iWidth = -1;
    294       } else if (pFont->GetCharWidthInternal(wUnicode, iWidth, false,
    295                                              bCharCode)) {
    296         return true;
    297       }
    298     } else {
    299       iWidth = -1;
    300     }
    301   }
    302   m_pCharWidthMap->SetAtGrow(wUnicode, iWidth);
    303   return iWidth > 0;
    304 }
    305 
    306 bool CFGAS_GEFont::GetCharBBox(FX_WCHAR wUnicode,
    307                                CFX_Rect* bbox,
    308                                bool bCharCode) {
    309   return GetCharBBoxInternal(wUnicode, bbox, true, bCharCode);
    310 }
    311 
    312 bool CFGAS_GEFont::GetCharBBoxInternal(FX_WCHAR wUnicode,
    313                                        CFX_Rect* bbox,
    314                                        bool bRecursive,
    315                                        bool bCharCode) {
    316   auto it = m_BBoxMap.find(wUnicode);
    317   if (it != m_BBoxMap.end()) {
    318     *bbox = it->second;
    319     return true;
    320   }
    321 
    322   CFX_RetainPtr<CFGAS_GEFont> pFont;
    323   int32_t iGlyph = GetGlyphIndex(wUnicode, true, &pFont, bCharCode);
    324   if (!pFont || iGlyph == 0xFFFF)
    325     return false;
    326 
    327   if (pFont.Get() != this)
    328     return pFont->GetCharBBoxInternal(wUnicode, bbox, false, bCharCode);
    329 
    330   FX_RECT rtBBox;
    331   if (!m_pFont->GetGlyphBBox(iGlyph, rtBBox))
    332     return false;
    333 
    334   CFX_Rect rt(rtBBox.left, rtBBox.top, rtBBox.Width(), rtBBox.Height());
    335   m_BBoxMap[wUnicode] = rt;
    336   *bbox = rt;
    337   return true;
    338 }
    339 
    340 bool CFGAS_GEFont::GetBBox(CFX_Rect* bbox) {
    341   FX_RECT rt(0, 0, 0, 0);
    342   if (!m_pFont->GetBBox(rt))
    343     return false;
    344 
    345   bbox->left = rt.left;
    346   bbox->width = rt.Width();
    347   bbox->top = rt.bottom;
    348   bbox->height = -rt.Height();
    349   return true;
    350 }
    351 
    352 int32_t CFGAS_GEFont::GetGlyphIndex(FX_WCHAR wUnicode, bool bCharCode) {
    353   return GetGlyphIndex(wUnicode, true, nullptr, bCharCode);
    354 }
    355 
    356 int32_t CFGAS_GEFont::GetGlyphIndex(FX_WCHAR wUnicode,
    357                                     bool bRecursive,
    358                                     CFX_RetainPtr<CFGAS_GEFont>* ppFont,
    359                                     bool bCharCode) {
    360   int32_t iGlyphIndex = m_pFontEncoding->GlyphFromCharCode(wUnicode);
    361   if (iGlyphIndex > 0) {
    362     if (ppFont)
    363       ppFont->Reset(this);
    364     return iGlyphIndex;
    365   }
    366   const FGAS_FONTUSB* pFontUSB = FGAS_GetUnicodeBitField(wUnicode);
    367   if (!pFontUSB)
    368     return 0xFFFF;
    369 
    370   uint16_t wBitField = pFontUSB->wBitField;
    371   if (wBitField >= 128)
    372     return 0xFFFF;
    373 
    374   auto it = m_FontMapper.find(wUnicode);
    375   if (it != m_FontMapper.end() && it->second && it->second.Get() != this) {
    376     iGlyphIndex =
    377         it->second->GetGlyphIndex(wUnicode, false, nullptr, bCharCode);
    378     if (iGlyphIndex != 0xFFFF) {
    379       for (size_t i = 0; i < m_SubstFonts.size(); ++i) {
    380         if (m_SubstFonts[i] == it->second) {
    381           if (ppFont)
    382             *ppFont = it->second;
    383           return (iGlyphIndex | ((i + 1) << 24));
    384         }
    385       }
    386     }
    387   }
    388   if (!m_pFontMgr || !bRecursive)
    389     return 0xFFFF;
    390 
    391   CFX_WideString wsFamily = GetFamilyName();
    392   CFX_RetainPtr<CFGAS_GEFont> pFont =
    393       m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), wsFamily.c_str());
    394 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
    395   if (!pFont)
    396     pFont = m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), nullptr);
    397 #endif
    398   if (!pFont || pFont.Get() == this)  // Avoids direct cycles below.
    399     return 0xFFFF;
    400 
    401   m_FontMapper[wUnicode] = pFont;
    402   m_SubstFonts.push_back(pFont);
    403   iGlyphIndex = pFont->GetGlyphIndex(wUnicode, false, nullptr, bCharCode);
    404   if (iGlyphIndex == 0xFFFF)
    405     return 0xFFFF;
    406 
    407   if (ppFont)
    408     *ppFont = pFont;
    409   return (iGlyphIndex | (m_SubstFonts.size() << 24));
    410 }
    411 
    412 int32_t CFGAS_GEFont::GetAscent() const {
    413   return m_pFont->GetAscent();
    414 }
    415 
    416 int32_t CFGAS_GEFont::GetDescent() const {
    417   return m_pFont->GetDescent();
    418 }
    419 
    420 CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::GetSubstFont(int32_t iGlyphIndex) {
    421   iGlyphIndex = static_cast<uint32_t>(iGlyphIndex) >> 24;
    422   if (iGlyphIndex == 0)
    423     return CFX_RetainPtr<CFGAS_GEFont>(this);
    424   return m_SubstFonts[iGlyphIndex - 1];
    425 }
    426