Home | History | Annotate | Download | only in font
      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/fpdfapi/font/cpdf_type3font.h"
      8 
      9 #include <utility>
     10 
     11 #include "core/fpdfapi/font/cpdf_type3char.h"
     12 #include "core/fpdfapi/page/cpdf_form.h"
     13 #include "core/fpdfapi/page/pageint.h"
     14 #include "core/fpdfapi/parser/cpdf_array.h"
     15 #include "core/fpdfapi/parser/cpdf_dictionary.h"
     16 #include "core/fpdfapi/parser/cpdf_stream.h"
     17 #include "core/fxcrt/fx_system.h"
     18 #include "third_party/base/stl_util.h"
     19 
     20 #define FPDF_MAX_TYPE3_FORM_LEVEL 4
     21 
     22 CPDF_Type3Font::CPDF_Type3Font()
     23     : m_pCharProcs(nullptr),
     24       m_pPageResources(nullptr),
     25       m_pFontResources(nullptr),
     26       m_CharLoadingDepth(0) {
     27   FXSYS_memset(m_CharWidthL, 0, sizeof(m_CharWidthL));
     28 }
     29 
     30 CPDF_Type3Font::~CPDF_Type3Font() {}
     31 
     32 bool CPDF_Type3Font::IsType3Font() const {
     33   return true;
     34 }
     35 
     36 const CPDF_Type3Font* CPDF_Type3Font::AsType3Font() const {
     37   return this;
     38 }
     39 
     40 CPDF_Type3Font* CPDF_Type3Font::AsType3Font() {
     41   return this;
     42 }
     43 
     44 bool CPDF_Type3Font::Load() {
     45   m_pFontResources = m_pFontDict->GetDictFor("Resources");
     46   CPDF_Array* pMatrix = m_pFontDict->GetArrayFor("FontMatrix");
     47   FX_FLOAT xscale = 1.0f, yscale = 1.0f;
     48   if (pMatrix) {
     49     m_FontMatrix = pMatrix->GetMatrix();
     50     xscale = m_FontMatrix.a;
     51     yscale = m_FontMatrix.d;
     52   }
     53   CPDF_Array* pBBox = m_pFontDict->GetArrayFor("FontBBox");
     54   if (pBBox) {
     55     m_FontBBox.left = (int32_t)(pBBox->GetNumberAt(0) * xscale * 1000);
     56     m_FontBBox.bottom = (int32_t)(pBBox->GetNumberAt(1) * yscale * 1000);
     57     m_FontBBox.right = (int32_t)(pBBox->GetNumberAt(2) * xscale * 1000);
     58     m_FontBBox.top = (int32_t)(pBBox->GetNumberAt(3) * yscale * 1000);
     59   }
     60   int StartChar = m_pFontDict->GetIntegerFor("FirstChar");
     61   CPDF_Array* pWidthArray = m_pFontDict->GetArrayFor("Widths");
     62   if (pWidthArray && (StartChar >= 0 && StartChar < 256)) {
     63     size_t count = pWidthArray->GetCount();
     64     if (count > 256)
     65       count = 256;
     66     if (StartChar + count > 256)
     67       count = 256 - StartChar;
     68     for (size_t i = 0; i < count; i++) {
     69       m_CharWidthL[StartChar + i] =
     70           FXSYS_round(pWidthArray->GetNumberAt(i) * xscale * 1000);
     71     }
     72   }
     73   m_pCharProcs = m_pFontDict->GetDictFor("CharProcs");
     74   CPDF_Object* pEncoding = m_pFontDict->GetDirectObjectFor("Encoding");
     75   if (pEncoding)
     76     LoadPDFEncoding(pEncoding, m_BaseEncoding, &m_CharNames, false, false);
     77   return true;
     78 }
     79 
     80 void CPDF_Type3Font::CheckType3FontMetrics() {
     81   CheckFontMetrics();
     82 }
     83 
     84 CPDF_Type3Char* CPDF_Type3Font::LoadChar(uint32_t charcode) {
     85   if (m_CharLoadingDepth >= FPDF_MAX_TYPE3_FORM_LEVEL)
     86     return nullptr;
     87 
     88   auto it = m_CacheMap.find(charcode);
     89   if (it != m_CacheMap.end())
     90     return it->second.get();
     91 
     92   const FX_CHAR* name = GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
     93   if (!name)
     94     return nullptr;
     95 
     96   CPDF_Stream* pStream =
     97       ToStream(m_pCharProcs ? m_pCharProcs->GetDirectObjectFor(name) : nullptr);
     98   if (!pStream)
     99     return nullptr;
    100 
    101   std::unique_ptr<CPDF_Type3Char> pNewChar(new CPDF_Type3Char(new CPDF_Form(
    102       m_pDocument, m_pFontResources ? m_pFontResources : m_pPageResources,
    103       pStream, nullptr)));
    104 
    105   // This can trigger recursion into this method. The content of |m_CacheMap|
    106   // can change as a result. Thus after it returns, check the cache again for
    107   // a cache hit.
    108   m_CharLoadingDepth++;
    109   pNewChar->m_pForm->ParseContent(nullptr, nullptr, pNewChar.get());
    110   m_CharLoadingDepth--;
    111   it = m_CacheMap.find(charcode);
    112   if (it != m_CacheMap.end())
    113     return it->second.get();
    114 
    115   FX_FLOAT scale = m_FontMatrix.GetXUnit();
    116   pNewChar->m_Width = (int32_t)(pNewChar->m_Width * scale + 0.5f);
    117   FX_RECT& rcBBox = pNewChar->m_BBox;
    118   CFX_FloatRect char_rect(
    119       (FX_FLOAT)rcBBox.left / 1000.0f, (FX_FLOAT)rcBBox.bottom / 1000.0f,
    120       (FX_FLOAT)rcBBox.right / 1000.0f, (FX_FLOAT)rcBBox.top / 1000.0f);
    121   if (rcBBox.right <= rcBBox.left || rcBBox.bottom >= rcBBox.top)
    122     char_rect = pNewChar->m_pForm->CalcBoundingBox();
    123 
    124   m_FontMatrix.TransformRect(char_rect);
    125   rcBBox.left = FXSYS_round(char_rect.left * 1000);
    126   rcBBox.right = FXSYS_round(char_rect.right * 1000);
    127   rcBBox.top = FXSYS_round(char_rect.top * 1000);
    128   rcBBox.bottom = FXSYS_round(char_rect.bottom * 1000);
    129 
    130   ASSERT(!pdfium::ContainsKey(m_CacheMap, charcode));
    131   m_CacheMap[charcode] = std::move(pNewChar);
    132   CPDF_Type3Char* pCachedChar = m_CacheMap[charcode].get();
    133   if (pCachedChar->m_pForm->GetPageObjectList()->empty())
    134     pCachedChar->m_pForm.reset();
    135   return pCachedChar;
    136 }
    137 
    138 int CPDF_Type3Font::GetCharWidthF(uint32_t charcode) {
    139   if (charcode >= FX_ArraySize(m_CharWidthL))
    140     charcode = 0;
    141 
    142   if (m_CharWidthL[charcode])
    143     return m_CharWidthL[charcode];
    144 
    145   const CPDF_Type3Char* pChar = LoadChar(charcode);
    146   return pChar ? pChar->m_Width : 0;
    147 }
    148 
    149 FX_RECT CPDF_Type3Font::GetCharBBox(uint32_t charcode) {
    150   const CPDF_Type3Char* pChar = LoadChar(charcode);
    151   return pChar ? pChar->m_BBox : FX_RECT();
    152 }
    153