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 <algorithm>
     10 #include <utility>
     11 
     12 #include "core/fpdfapi/font/cpdf_type3char.h"
     13 #include "core/fpdfapi/page/cpdf_form.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 namespace {
     21 
     22 constexpr int kMaxType3FormLevel = 4;
     23 
     24 }  // namespace
     25 
     26 CPDF_Type3Font::CPDF_Type3Font() {
     27   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   float xscale = 1.0f;
     48   float yscale = 1.0f;
     49   if (pMatrix) {
     50     m_FontMatrix = pMatrix->GetMatrix();
     51     xscale = m_FontMatrix.a;
     52     yscale = m_FontMatrix.d;
     53   }
     54 
     55   CPDF_Array* pBBox = m_pFontDict->GetArrayFor("FontBBox");
     56   if (pBBox) {
     57     CFX_FloatRect box(
     58         pBBox->GetNumberAt(0) * xscale, pBBox->GetNumberAt(1) * yscale,
     59         pBBox->GetNumberAt(2) * xscale, pBBox->GetNumberAt(3) * yscale);
     60     CPDF_Type3Char::TextUnitRectToGlyphUnitRect(&box);
     61     m_FontBBox = box.ToFxRect();
     62   }
     63 
     64   static constexpr size_t kCharLimit = FX_ArraySize(m_CharWidthL);
     65   int StartChar = m_pFontDict->GetIntegerFor("FirstChar");
     66   if (StartChar >= 0 && static_cast<size_t>(StartChar) < kCharLimit) {
     67     CPDF_Array* pWidthArray = m_pFontDict->GetArrayFor("Widths");
     68     if (pWidthArray) {
     69       size_t count = std::min(pWidthArray->GetCount(), kCharLimit);
     70       count = std::min(count, kCharLimit - StartChar);
     71       for (size_t i = 0; i < count; i++) {
     72         m_CharWidthL[StartChar + i] =
     73             FXSYS_round(CPDF_Type3Char::TextUnitToGlyphUnit(
     74                 pWidthArray->GetNumberAt(i) * xscale));
     75       }
     76     }
     77   }
     78   m_pCharProcs = m_pFontDict->GetDictFor("CharProcs");
     79   CPDF_Object* pEncoding = m_pFontDict->GetDirectObjectFor("Encoding");
     80   if (pEncoding)
     81     LoadPDFEncoding(pEncoding, m_BaseEncoding, &m_CharNames, false, false);
     82   return true;
     83 }
     84 
     85 void CPDF_Type3Font::LoadGlyphMap() {}
     86 
     87 void CPDF_Type3Font::CheckType3FontMetrics() {
     88   CheckFontMetrics();
     89 }
     90 
     91 CPDF_Type3Char* CPDF_Type3Font::LoadChar(uint32_t charcode) {
     92   if (m_CharLoadingDepth >= kMaxType3FormLevel)
     93     return nullptr;
     94 
     95   auto it = m_CacheMap.find(charcode);
     96   if (it != m_CacheMap.end())
     97     return it->second.get();
     98 
     99   const char* name = GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
    100   if (!name)
    101     return nullptr;
    102 
    103   CPDF_Stream* pStream =
    104       ToStream(m_pCharProcs ? m_pCharProcs->GetDirectObjectFor(name) : nullptr);
    105   if (!pStream)
    106     return nullptr;
    107 
    108   auto pNewChar =
    109       pdfium::MakeUnique<CPDF_Type3Char>(pdfium::MakeUnique<CPDF_Form>(
    110           m_pDocument.Get(),
    111           m_pFontResources ? m_pFontResources.Get() : m_pPageResources.Get(),
    112           pStream, nullptr));
    113 
    114   // This can trigger recursion into this method. The content of |m_CacheMap|
    115   // can change as a result. Thus after it returns, check the cache again for
    116   // a cache hit.
    117   m_CharLoadingDepth++;
    118   pNewChar->form()->ParseContentWithParams(nullptr, nullptr, pNewChar.get(), 0);
    119   m_CharLoadingDepth--;
    120   it = m_CacheMap.find(charcode);
    121   if (it != m_CacheMap.end())
    122     return it->second.get();
    123 
    124   pNewChar->Transform(m_FontMatrix);
    125   m_CacheMap[charcode] = std::move(pNewChar);
    126   CPDF_Type3Char* pCachedChar = m_CacheMap[charcode].get();
    127   if (pCachedChar->form()->GetPageObjectList()->empty())
    128     pCachedChar->ResetForm();
    129   return pCachedChar;
    130 }
    131 
    132 int CPDF_Type3Font::GetCharWidthF(uint32_t charcode) {
    133   if (charcode >= FX_ArraySize(m_CharWidthL))
    134     charcode = 0;
    135 
    136   if (m_CharWidthL[charcode])
    137     return m_CharWidthL[charcode];
    138 
    139   const CPDF_Type3Char* pChar = LoadChar(charcode);
    140   return pChar ? pChar->width() : 0;
    141 }
    142 
    143 FX_RECT CPDF_Type3Font::GetCharBBox(uint32_t charcode) {
    144   FX_RECT ret;
    145   const CPDF_Type3Char* pChar = LoadChar(charcode);
    146   if (pChar)
    147     ret = pChar->bbox();
    148   return ret;
    149 }
    150