Home | History | Annotate | Download | only in font
      1 // Copyright 2017 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_pdffontmgr.h"
      8 
      9 #include <algorithm>
     10 
     11 #include "core/fpdfapi/font/cpdf_font.h"
     12 #include "core/fpdfapi/parser/cpdf_document.h"
     13 #include "xfa/fgas/font/cfgas_fontmgr.h"
     14 #include "xfa/fgas/font/cfgas_gefont.h"
     15 
     16 namespace {
     17 
     18 // The 5 names per entry are: PsName, Normal, Bold, Italic, BoldItalic.
     19 const char* const g_XFAPDFFontName[][5] = {
     20     {"Adobe PI Std", "AdobePIStd", "AdobePIStd", "AdobePIStd", "AdobePIStd"},
     21     {"Myriad Pro Light", "MyriadPro-Light", "MyriadPro-Semibold",
     22      "MyriadPro-LightIt", "MyriadPro-SemiboldIt"},
     23 };
     24 
     25 }  // namespace
     26 
     27 CFGAS_PDFFontMgr::CFGAS_PDFFontMgr(CPDF_Document* pDoc, CFGAS_FontMgr* pFontMgr)
     28     : m_pDoc(pDoc), m_pFontMgr(pFontMgr) {
     29   ASSERT(pDoc);
     30   ASSERT(pFontMgr);
     31 }
     32 
     33 CFGAS_PDFFontMgr::~CFGAS_PDFFontMgr() {}
     34 
     35 RetainPtr<CFGAS_GEFont> CFGAS_PDFFontMgr::FindFont(const ByteString& strPsName,
     36                                                    bool bBold,
     37                                                    bool bItalic,
     38                                                    CPDF_Font** pDstPDFFont,
     39                                                    bool bStrictMatch) {
     40   CPDF_Dictionary* pFontSetDict =
     41       m_pDoc->GetRoot()->GetDictFor("AcroForm")->GetDictFor("DR");
     42   if (!pFontSetDict)
     43     return nullptr;
     44 
     45   pFontSetDict = pFontSetDict->GetDictFor("Font");
     46   if (!pFontSetDict)
     47     return nullptr;
     48 
     49   ByteString name = strPsName;
     50   name.Remove(' ');
     51   for (const auto& it : *pFontSetDict) {
     52     const ByteString& key = it.first;
     53     CPDF_Object* pObj = it.second.get();
     54     if (!PsNameMatchDRFontName(name.AsStringView(), bBold, bItalic, key,
     55                                bStrictMatch)) {
     56       continue;
     57     }
     58     CPDF_Dictionary* pFontDict = ToDictionary(pObj->GetDirect());
     59     if (!pFontDict || pFontDict->GetStringFor("Type") != "Font")
     60       return nullptr;
     61 
     62     CPDF_Font* pPDFFont = m_pDoc->LoadFont(pFontDict);
     63     if (!pPDFFont)
     64       return nullptr;
     65 
     66     if (!pPDFFont->IsEmbedded()) {
     67       *pDstPDFFont = pPDFFont;
     68       return nullptr;
     69     }
     70     return CFGAS_GEFont::LoadFont(pPDFFont->GetFont(), m_pFontMgr.Get());
     71   }
     72   return nullptr;
     73 }
     74 
     75 RetainPtr<CFGAS_GEFont> CFGAS_PDFFontMgr::GetFont(
     76     const WideStringView& wsFontFamily,
     77     uint32_t dwFontStyles,
     78     CPDF_Font** pPDFFont,
     79     bool bStrictMatch) {
     80   uint32_t dwHashCode = FX_HashCode_GetW(wsFontFamily, false);
     81   ByteString strKey = ByteString::Format("%u%u", dwHashCode, dwFontStyles);
     82   auto it = m_FontMap.find(strKey);
     83   if (it != m_FontMap.end())
     84     return it->second;
     85 
     86   ByteString bsPsName = ByteString::FromUnicode(WideString(wsFontFamily));
     87   bool bBold = FontStyleIsBold(dwFontStyles);
     88   bool bItalic = FontStyleIsItalic(dwFontStyles);
     89   ByteString strFontName = PsNameToFontName(bsPsName, bBold, bItalic);
     90   RetainPtr<CFGAS_GEFont> pFont =
     91       FindFont(strFontName, bBold, bItalic, pPDFFont, bStrictMatch);
     92   if (pFont)
     93     m_FontMap[strKey] = pFont;
     94 
     95   return pFont;
     96 }
     97 
     98 ByteString CFGAS_PDFFontMgr::PsNameToFontName(const ByteString& strPsName,
     99                                               bool bBold,
    100                                               bool bItalic) {
    101   for (size_t i = 0; i < FX_ArraySize(g_XFAPDFFontName); ++i) {
    102     if (strPsName == g_XFAPDFFontName[i][0]) {
    103       size_t index = 1;
    104       if (bBold)
    105         ++index;
    106       if (bItalic)
    107         index += 2;
    108       return g_XFAPDFFontName[i][index];
    109     }
    110   }
    111   return strPsName;
    112 }
    113 
    114 bool CFGAS_PDFFontMgr::PsNameMatchDRFontName(const ByteStringView& bsPsName,
    115                                              bool bBold,
    116                                              bool bItalic,
    117                                              const ByteString& bsDRFontName,
    118                                              bool bStrictMatch) {
    119   ByteString bsDRName = bsDRFontName;
    120   bsDRName.Remove('-');
    121   size_t iPsLen = bsPsName.GetLength();
    122   auto nIndex = bsDRName.Find(bsPsName);
    123   if (nIndex.has_value() && !bStrictMatch)
    124     return true;
    125 
    126   if (!nIndex.has_value() || nIndex.value() != 0)
    127     return false;
    128 
    129   size_t iDifferLength = bsDRName.GetLength() - iPsLen;
    130   if (iDifferLength > 1 || (bBold || bItalic)) {
    131     auto iBoldIndex = bsDRName.Find("Bold");
    132     if (bBold != iBoldIndex.has_value())
    133       return false;
    134 
    135     if (iBoldIndex.has_value()) {
    136       iDifferLength = std::min(iDifferLength - 4,
    137                                bsDRName.GetLength() - iBoldIndex.value() - 4);
    138     }
    139     bool bItalicFont = true;
    140     if (bsDRName.Contains("Italic"))
    141       iDifferLength -= 6;
    142     else if (bsDRName.Contains("It"))
    143       iDifferLength -= 2;
    144     else if (bsDRName.Contains("Oblique"))
    145       iDifferLength -= 7;
    146     else
    147       bItalicFont = false;
    148 
    149     if (bItalic != bItalicFont)
    150       return false;
    151 
    152     if (iDifferLength > 1) {
    153       ByteString bsDRTailer = bsDRName.Right(iDifferLength);
    154       if (bsDRTailer == "MT" || bsDRTailer == "PSMT" ||
    155           bsDRTailer == "Regular" || bsDRTailer == "Reg") {
    156         return true;
    157       }
    158       if (iBoldIndex.has_value() || bItalicFont)
    159         return false;
    160 
    161       bool bMatch = false;
    162       switch (bsPsName[iPsLen - 1]) {
    163         case 'L':
    164           if (bsDRName.Right(5) == "Light")
    165             bMatch = true;
    166 
    167           break;
    168         case 'R':
    169           if (bsDRName.Right(7) == "Regular" || bsDRName.Right(3) == "Reg")
    170             bMatch = true;
    171 
    172           break;
    173         case 'M':
    174           if (bsDRName.Right(5) == "Medium")
    175             bMatch = true;
    176           break;
    177         default:
    178           break;
    179       }
    180       return bMatch;
    181     }
    182   }
    183   return true;
    184 }
    185 
    186 bool CFGAS_PDFFontMgr::GetCharWidth(const RetainPtr<CFGAS_GEFont>& pFont,
    187                                     wchar_t wUnicode,
    188                                     int32_t* pWidth) {
    189   if (wUnicode != 0x20)
    190     return false;
    191 
    192   auto it = m_FDE2PDFFont.find(pFont);
    193   if (it == m_FDE2PDFFont.end())
    194     return false;
    195 
    196   CPDF_Font* pPDFFont = it->second;
    197   *pWidth = pPDFFont->GetCharWidthF(pPDFFont->CharCodeFromUnicode(wUnicode));
    198   return true;
    199 }
    200 
    201 void CFGAS_PDFFontMgr::SetFont(const RetainPtr<CFGAS_GEFont>& pFont,
    202                                CPDF_Font* pPDFFont) {
    203   m_FDE2PDFFont[pFont] = pPDFFont;
    204 }
    205