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