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/fxcrt/fx_codepage.h"
     13 #include "core/fxge/cfx_font.h"
     14 #include "core/fxge/cfx_substfont.h"
     15 #include "core/fxge/cfx_unicodeencoding.h"
     16 #include "core/fxge/cfx_unicodeencodingex.h"
     17 #include "third_party/base/ptr_util.h"
     18 #include "xfa/fgas/font/fgas_fontutils.h"
     19 
     20 // static
     21 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(const wchar_t* pszFontFamily,
     22                                                uint32_t dwFontStyles,
     23                                                uint16_t wCodePage,
     24                                                CFGAS_FontMgr* pFontMgr) {
     25 #if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_
     26   if (!pFontMgr)
     27     return nullptr;
     28 
     29   return pFontMgr->GetFontByCodePage(wCodePage, dwFontStyles, pszFontFamily);
     30 #else
     31   auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
     32   if (!pFont->LoadFontInternal(pszFontFamily, dwFontStyles, wCodePage))
     33     return nullptr;
     34   return pFont;
     35 #endif
     36 }
     37 
     38 // static
     39 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(CFX_Font* pExternalFont,
     40                                                CFGAS_FontMgr* pFontMgr) {
     41   auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
     42   if (!pFont->LoadFontInternal(pExternalFont))
     43     return nullptr;
     44   return pFont;
     45 }
     46 
     47 // static
     48 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(
     49     std::unique_ptr<CFX_Font> pInternalFont,
     50     CFGAS_FontMgr* pFontMgr) {
     51   auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
     52   if (!pFont->LoadFontInternal(std::move(pInternalFont)))
     53     return nullptr;
     54   return pFont;
     55 }
     56 
     57 CFGAS_GEFont::CFGAS_GEFont(CFGAS_FontMgr* pFontMgr)
     58     :
     59       m_bUseLogFontStyle(false),
     60       m_dwLogFontStyle(0),
     61       m_pFont(nullptr),
     62       m_bExternalFont(false),
     63       m_pFontMgr(pFontMgr) {
     64 }
     65 
     66 CFGAS_GEFont::~CFGAS_GEFont() {
     67   if (!m_bExternalFont)
     68     delete m_pFont;
     69 }
     70 
     71 #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
     72 bool CFGAS_GEFont::LoadFontInternal(const wchar_t* pszFontFamily,
     73                                     uint32_t dwFontStyles,
     74                                     uint16_t wCodePage) {
     75   if (m_pFont)
     76     return false;
     77   ByteString csFontFamily;
     78   if (pszFontFamily)
     79     csFontFamily = ByteString::FromUnicode(pszFontFamily);
     80 
     81   int32_t iWeight =
     82       FontStyleIsBold(dwFontStyles) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL;
     83   m_pFont = new CFX_Font;
     84   if (FontStyleIsItalic(dwFontStyles) && FontStyleIsBold(dwFontStyles))
     85     csFontFamily += ",BoldItalic";
     86   else if (FontStyleIsBold(dwFontStyles))
     87     csFontFamily += ",Bold";
     88   else if (FontStyleIsItalic(dwFontStyles))
     89     csFontFamily += ",Italic";
     90 
     91   m_pFont->LoadSubst(csFontFamily, true, dwFontStyles, iWeight, 0, wCodePage,
     92                      false);
     93   if (!m_pFont->GetFace())
     94     return false;
     95   return InitFont();
     96 }
     97 #endif  // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
     98 
     99 bool CFGAS_GEFont::LoadFontInternal(CFX_Font* pExternalFont) {
    100   if (m_pFont || !pExternalFont)
    101     return false;
    102 
    103   m_pFont = pExternalFont;
    104   m_bExternalFont = true;
    105   return InitFont();
    106 }
    107 
    108 bool CFGAS_GEFont::LoadFontInternal(std::unique_ptr<CFX_Font> pInternalFont) {
    109   if (m_pFont || !pInternalFont)
    110     return false;
    111 
    112   m_pFont = pInternalFont.release();
    113   m_bExternalFont = false;
    114   return InitFont();
    115 }
    116 
    117 bool CFGAS_GEFont::InitFont() {
    118   if (!m_pFont)
    119     return false;
    120 
    121   if (m_pFontEncoding)
    122     return true;
    123 
    124   m_pFontEncoding = FX_CreateFontEncodingEx(m_pFont, FXFM_ENCODING_NONE);
    125   return !!m_pFontEncoding;
    126 }
    127 
    128 WideString CFGAS_GEFont::GetFamilyName() const {
    129   if (!m_pFont->GetSubstFont() ||
    130       m_pFont->GetSubstFont()->m_Family.GetLength() == 0) {
    131     return WideString::FromLocal(m_pFont->GetFamilyName().AsStringView());
    132   }
    133   return WideString::FromLocal(
    134       m_pFont->GetSubstFont()->m_Family.AsStringView());
    135 }
    136 
    137 uint32_t CFGAS_GEFont::GetFontStyles() const {
    138   ASSERT(m_pFont);
    139   if (m_bUseLogFontStyle)
    140     return m_dwLogFontStyle;
    141 
    142   uint32_t dwStyles = 0;
    143   auto* pSubstFont = m_pFont->GetSubstFont();
    144   if (pSubstFont) {
    145     if (pSubstFont->m_Weight == FXFONT_FW_BOLD)
    146       dwStyles |= FXFONT_BOLD;
    147     if (pSubstFont->m_bFlagItalic)
    148       dwStyles |= FXFONT_ITALIC;
    149   } else {
    150     if (m_pFont->IsBold())
    151       dwStyles |= FXFONT_BOLD;
    152     if (m_pFont->IsItalic())
    153       dwStyles |= FXFONT_ITALIC;
    154   }
    155   return dwStyles;
    156 }
    157 
    158 bool CFGAS_GEFont::GetCharWidth(wchar_t wUnicode, int32_t& iWidth) {
    159   auto it = m_CharWidthMap.find(wUnicode);
    160   iWidth = it != m_CharWidthMap.end() ? it->second : 0;
    161   if (iWidth == 65535)
    162     return false;
    163 
    164   if (iWidth > 0)
    165     return true;
    166 
    167   if (!m_pProvider || !m_pProvider->GetCharWidth(RetainPtr<CFGAS_GEFont>(this),
    168                                                  wUnicode, &iWidth)) {
    169     RetainPtr<CFGAS_GEFont> pFont;
    170     int32_t iGlyph;
    171     std::tie(iGlyph, pFont) = GetGlyphIndexAndFont(wUnicode, true);
    172     if (iGlyph != 0xFFFF && pFont) {
    173       if (pFont.Get() == this) {
    174         iWidth = m_pFont->GetGlyphWidth(iGlyph);
    175         if (iWidth < 0)
    176           iWidth = -1;
    177       } else if (pFont->GetCharWidth(wUnicode, iWidth)) {
    178         return true;
    179       }
    180     } else {
    181       iWidth = -1;
    182     }
    183   }
    184   m_CharWidthMap[wUnicode] = iWidth;
    185   return iWidth > 0;
    186 }
    187 
    188 bool CFGAS_GEFont::GetCharBBox(wchar_t wUnicode, CFX_Rect* bbox) {
    189   auto it = m_BBoxMap.find(wUnicode);
    190   if (it != m_BBoxMap.end()) {
    191     *bbox = it->second;
    192     return true;
    193   }
    194 
    195   RetainPtr<CFGAS_GEFont> pFont;
    196   int32_t iGlyph;
    197   std::tie(iGlyph, pFont) = GetGlyphIndexAndFont(wUnicode, true);
    198   if (!pFont || iGlyph == 0xFFFF)
    199     return false;
    200 
    201   if (pFont.Get() != this)
    202     return pFont->GetCharBBox(wUnicode, bbox);
    203 
    204   FX_RECT rtBBox;
    205   if (!m_pFont->GetGlyphBBox(iGlyph, rtBBox))
    206     return false;
    207 
    208   CFX_Rect rt(rtBBox.left, rtBBox.top, rtBBox.Width(), rtBBox.Height());
    209   m_BBoxMap[wUnicode] = rt;
    210   *bbox = rt;
    211   return true;
    212 }
    213 
    214 bool CFGAS_GEFont::GetBBox(CFX_Rect* bbox) {
    215   FX_RECT rt(0, 0, 0, 0);
    216   if (!m_pFont->GetBBox(rt))
    217     return false;
    218 
    219   bbox->left = rt.left;
    220   bbox->width = rt.Width();
    221   bbox->top = rt.bottom;
    222   bbox->height = -rt.Height();
    223   return true;
    224 }
    225 
    226 int32_t CFGAS_GEFont::GetGlyphIndex(wchar_t wUnicode) {
    227   int32_t glyph;
    228   RetainPtr<CFGAS_GEFont> font;
    229   std::tie(glyph, font) = GetGlyphIndexAndFont(wUnicode, true);
    230   return glyph;
    231 }
    232 
    233 std::pair<int32_t, RetainPtr<CFGAS_GEFont>> CFGAS_GEFont::GetGlyphIndexAndFont(
    234     wchar_t wUnicode,
    235     bool bRecursive) {
    236   int32_t iGlyphIndex = m_pFontEncoding->GlyphFromCharCode(wUnicode);
    237   if (iGlyphIndex > 0)
    238     return {iGlyphIndex, RetainPtr<CFGAS_GEFont>(this)};
    239 
    240   const FGAS_FONTUSB* pFontUSB = FGAS_GetUnicodeBitField(wUnicode);
    241   if (!pFontUSB)
    242     return {0xFFFF, nullptr};
    243 
    244   uint16_t wBitField = pFontUSB->wBitField;
    245   if (wBitField >= 128)
    246     return {0xFFFF, nullptr};
    247 
    248   auto it = m_FontMapper.find(wUnicode);
    249   if (it != m_FontMapper.end() && it->second && it->second.Get() != this) {
    250     RetainPtr<CFGAS_GEFont> font;
    251     std::tie(iGlyphIndex, font) =
    252         it->second->GetGlyphIndexAndFont(wUnicode, false);
    253     if (iGlyphIndex != 0xFFFF) {
    254       for (size_t i = 0; i < m_SubstFonts.size(); ++i) {
    255         if (m_SubstFonts[i] == it->second)
    256           return {(iGlyphIndex | ((i + 1) << 24)), it->second};
    257       }
    258     }
    259   }
    260   if (!m_pFontMgr || !bRecursive)
    261     return {0xFFFF, nullptr};
    262 
    263   WideString wsFamily = GetFamilyName();
    264   RetainPtr<CFGAS_GEFont> pFont =
    265       m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), wsFamily.c_str());
    266 #if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_
    267   if (!pFont)
    268     pFont = m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), nullptr);
    269 #endif
    270   if (!pFont || pFont.Get() == this)  // Avoids direct cycles below.
    271     return {0xFFFF, nullptr};
    272 
    273   m_FontMapper[wUnicode] = pFont;
    274   m_SubstFonts.push_back(pFont);
    275 
    276   RetainPtr<CFGAS_GEFont> font;
    277   std::tie(iGlyphIndex, font) = pFont->GetGlyphIndexAndFont(wUnicode, false);
    278   if (iGlyphIndex == 0xFFFF)
    279     return {0xFFFF, nullptr};
    280 
    281   return {(iGlyphIndex | (m_SubstFonts.size() << 24)), pFont};
    282 }
    283 
    284 int32_t CFGAS_GEFont::GetAscent() const {
    285   return m_pFont->GetAscent();
    286 }
    287 
    288 int32_t CFGAS_GEFont::GetDescent() const {
    289   return m_pFont->GetDescent();
    290 }
    291 
    292 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::GetSubstFont(int32_t iGlyphIndex) {
    293   iGlyphIndex = static_cast<uint32_t>(iGlyphIndex) >> 24;
    294   if (iGlyphIndex == 0)
    295     return RetainPtr<CFGAS_GEFont>(this);
    296   return m_SubstFonts[iGlyphIndex - 1];
    297 }
    298