Home | History | Annotate | Download | only in formfiller
      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 "fpdfsdk/include/formfiller/FFL_CBA_Fontmap.h"
      8 
      9 #include "core/include/fpdfapi/fpdf_page.h"
     10 #include "fpdfsdk/include/fsdk_baseannot.h"
     11 
     12 CBA_FontMap::CBA_FontMap(CPDFSDK_Annot* pAnnot,
     13                          IFX_SystemHandler* pSystemHandler)
     14     : CPWL_FontMap(pSystemHandler),
     15       m_pDocument(NULL),
     16       m_pAnnotDict(NULL),
     17       m_pDefaultFont(NULL),
     18       m_sAPType("N") {
     19   CPDF_Page* pPage = pAnnot->GetPDFPage();
     20 
     21   m_pDocument = pPage->m_pDocument;
     22   m_pAnnotDict = pAnnot->GetPDFAnnot()->GetAnnotDict();
     23   Initialize();
     24 }
     25 
     26 CBA_FontMap::~CBA_FontMap() {}
     27 
     28 void CBA_FontMap::Reset() {
     29   Empty();
     30   m_pDefaultFont = NULL;
     31   m_sDefaultFontName = "";
     32 }
     33 
     34 void CBA_FontMap::Initialize() {
     35   int32_t nCharset = DEFAULT_CHARSET;
     36 
     37   if (!m_pDefaultFont) {
     38     m_pDefaultFont = GetAnnotDefaultFont(m_sDefaultFontName);
     39     if (m_pDefaultFont) {
     40       if (const CFX_SubstFont* pSubstFont = m_pDefaultFont->GetSubstFont()) {
     41         nCharset = pSubstFont->m_Charset;
     42       } else {
     43         if (m_sDefaultFontName == "Wingdings" ||
     44             m_sDefaultFontName == "Wingdings2" ||
     45             m_sDefaultFontName == "Wingdings3" ||
     46             m_sDefaultFontName == "Webdings")
     47           nCharset = SYMBOL_CHARSET;
     48         else
     49           nCharset = ANSI_CHARSET;
     50       }
     51       AddFontData(m_pDefaultFont, m_sDefaultFontName, nCharset);
     52       AddFontToAnnotDict(m_pDefaultFont, m_sDefaultFontName);
     53     }
     54   }
     55 
     56   if (nCharset != ANSI_CHARSET)
     57     CPWL_FontMap::Initialize();
     58 }
     59 
     60 void CBA_FontMap::SetDefaultFont(CPDF_Font* pFont,
     61                                  const CFX_ByteString& sFontName) {
     62   ASSERT(pFont != NULL);
     63 
     64   if (m_pDefaultFont)
     65     return;
     66 
     67   m_pDefaultFont = pFont;
     68   m_sDefaultFontName = sFontName;
     69 
     70   int32_t nCharset = DEFAULT_CHARSET;
     71   if (const CFX_SubstFont* pSubstFont = m_pDefaultFont->GetSubstFont())
     72     nCharset = pSubstFont->m_Charset;
     73   AddFontData(m_pDefaultFont, m_sDefaultFontName, nCharset);
     74 }
     75 
     76 CPDF_Font* CBA_FontMap::FindFontSameCharset(CFX_ByteString& sFontAlias,
     77                                             int32_t nCharset) {
     78   ASSERT(m_pAnnotDict != NULL);
     79 
     80   if (m_pAnnotDict->GetString("Subtype") == "Widget") {
     81     CPDF_Document* pDocument = GetDocument();
     82     ASSERT(pDocument != NULL);
     83 
     84     CPDF_Dictionary* pRootDict = pDocument->GetRoot();
     85     if (!pRootDict)
     86       return NULL;
     87 
     88     CPDF_Dictionary* pAcroFormDict = pRootDict->GetDict("AcroForm");
     89     if (!pAcroFormDict)
     90       return NULL;
     91 
     92     CPDF_Dictionary* pDRDict = pAcroFormDict->GetDict("DR");
     93     if (!pDRDict)
     94       return NULL;
     95 
     96     return FindResFontSameCharset(pDRDict, sFontAlias, nCharset);
     97   }
     98 
     99   return NULL;
    100 }
    101 
    102 CPDF_Document* CBA_FontMap::GetDocument() {
    103   return m_pDocument;
    104 }
    105 
    106 CPDF_Font* CBA_FontMap::FindResFontSameCharset(CPDF_Dictionary* pResDict,
    107                                                CFX_ByteString& sFontAlias,
    108                                                int32_t nCharset) {
    109   if (!pResDict)
    110     return NULL;
    111 
    112   CPDF_Document* pDocument = GetDocument();
    113   ASSERT(pDocument != NULL);
    114 
    115   CPDF_Dictionary* pFonts = pResDict->GetDict("Font");
    116   if (!pFonts)
    117     return NULL;
    118 
    119   CPDF_Font* pFind = NULL;
    120 
    121   for (const auto& it : *pFonts) {
    122     const CFX_ByteString& csKey = it.first;
    123     CPDF_Object* pObj = it.second;
    124     if (!pObj)
    125       continue;
    126 
    127     CPDF_Dictionary* pElement = ToDictionary(pObj->GetDirect());
    128     if (!pElement)
    129       continue;
    130     if (pElement->GetString("Type") != "Font")
    131       continue;
    132 
    133     CPDF_Font* pFont = pDocument->LoadFont(pElement);
    134     if (!pFont)
    135       continue;
    136     const CFX_SubstFont* pSubst = pFont->GetSubstFont();
    137     if (!pSubst)
    138       continue;
    139     if (pSubst->m_Charset == nCharset) {
    140       sFontAlias = csKey;
    141       pFind = pFont;
    142     }
    143   }
    144   return pFind;
    145 }
    146 
    147 void CBA_FontMap::AddedFont(CPDF_Font* pFont,
    148                             const CFX_ByteString& sFontAlias) {
    149   AddFontToAnnotDict(pFont, sFontAlias);
    150 }
    151 
    152 void CBA_FontMap::AddFontToAnnotDict(CPDF_Font* pFont,
    153                                      const CFX_ByteString& sAlias) {
    154   if (!pFont)
    155     return;
    156 
    157   ASSERT(m_pAnnotDict != NULL);
    158   ASSERT(m_pDocument != NULL);
    159 
    160   CPDF_Dictionary* pAPDict = m_pAnnotDict->GetDict("AP");
    161 
    162   if (!pAPDict) {
    163     pAPDict = new CPDF_Dictionary;
    164     m_pAnnotDict->SetAt("AP", pAPDict);
    165   }
    166 
    167   // to avoid checkbox and radiobutton
    168   CPDF_Object* pObject = pAPDict->GetElement(m_sAPType);
    169   if (ToDictionary(pObject))
    170     return;
    171 
    172   CPDF_Stream* pStream = pAPDict->GetStream(m_sAPType);
    173   if (!pStream) {
    174     pStream = new CPDF_Stream(NULL, 0, NULL);
    175     int32_t objnum = m_pDocument->AddIndirectObject(pStream);
    176     pAPDict->SetAtReference(m_sAPType, m_pDocument, objnum);
    177   }
    178 
    179   CPDF_Dictionary* pStreamDict = pStream->GetDict();
    180 
    181   if (!pStreamDict) {
    182     pStreamDict = new CPDF_Dictionary;
    183     pStream->InitStream(NULL, 0, pStreamDict);
    184   }
    185 
    186   if (pStreamDict) {
    187     CPDF_Dictionary* pStreamResList = pStreamDict->GetDict("Resources");
    188     if (!pStreamResList) {
    189       pStreamResList = new CPDF_Dictionary();
    190       pStreamDict->SetAt("Resources", pStreamResList);
    191     }
    192 
    193     if (pStreamResList) {
    194       CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDict("Font");
    195       if (!pStreamResFontList) {
    196         pStreamResFontList = new CPDF_Dictionary;
    197         int32_t objnum = m_pDocument->AddIndirectObject(pStreamResFontList);
    198         pStreamResList->SetAtReference("Font", m_pDocument, objnum);
    199       }
    200       if (!pStreamResFontList->KeyExist(sAlias))
    201         pStreamResFontList->SetAtReference(sAlias, m_pDocument,
    202                                            pFont->GetFontDict());
    203     }
    204   }
    205 }
    206 
    207 CPDF_Font* CBA_FontMap::GetAnnotDefaultFont(CFX_ByteString& sAlias) {
    208   ASSERT(m_pAnnotDict != NULL);
    209   ASSERT(m_pDocument != NULL);
    210 
    211   CPDF_Dictionary* pAcroFormDict = NULL;
    212 
    213   FX_BOOL bWidget = (m_pAnnotDict->GetString("Subtype") == "Widget");
    214 
    215   if (bWidget) {
    216     if (CPDF_Dictionary* pRootDict = m_pDocument->GetRoot())
    217       pAcroFormDict = pRootDict->GetDict("AcroForm");
    218   }
    219 
    220   CFX_ByteString sDA;
    221   CPDF_Object* pObj;
    222   if ((pObj = FPDF_GetFieldAttr(m_pAnnotDict, "DA")))
    223     sDA = pObj->GetString();
    224 
    225   if (bWidget) {
    226     if (sDA.IsEmpty()) {
    227       pObj = FPDF_GetFieldAttr(pAcroFormDict, "DA");
    228       sDA = pObj ? pObj->GetString() : CFX_ByteString();
    229     }
    230   }
    231 
    232   CPDF_Dictionary* pFontDict = NULL;
    233 
    234   if (!sDA.IsEmpty()) {
    235     CPDF_SimpleParser syntax(sDA);
    236     syntax.FindTagParam("Tf", 2);
    237     CFX_ByteString sFontName = syntax.GetWord();
    238     sAlias = PDF_NameDecode(sFontName).Mid(1);
    239 
    240     if (CPDF_Dictionary* pDRDict = m_pAnnotDict->GetDict("DR"))
    241       if (CPDF_Dictionary* pDRFontDict = pDRDict->GetDict("Font"))
    242         pFontDict = pDRFontDict->GetDict(sAlias);
    243 
    244     if (!pFontDict)
    245       if (CPDF_Dictionary* pAPDict = m_pAnnotDict->GetDict("AP"))
    246         if (CPDF_Dictionary* pNormalDict = pAPDict->GetDict("N"))
    247           if (CPDF_Dictionary* pNormalResDict =
    248                   pNormalDict->GetDict("Resources"))
    249             if (CPDF_Dictionary* pResFontDict = pNormalResDict->GetDict("Font"))
    250               pFontDict = pResFontDict->GetDict(sAlias);
    251 
    252     if (bWidget) {
    253       if (!pFontDict) {
    254         if (pAcroFormDict) {
    255           if (CPDF_Dictionary* pDRDict = pAcroFormDict->GetDict("DR"))
    256             if (CPDF_Dictionary* pDRFontDict = pDRDict->GetDict("Font"))
    257               pFontDict = pDRFontDict->GetDict(sAlias);
    258         }
    259       }
    260     }
    261   }
    262 
    263   return pFontDict ? m_pDocument->LoadFont(pFontDict) : nullptr;
    264 }
    265 
    266 void CBA_FontMap::SetAPType(const CFX_ByteString& sAPType) {
    267   m_sAPType = sAPType;
    268 
    269   Reset();
    270   Initialize();
    271 }
    272