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