• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/fpdfapi/font/font_int.h"
8 
9 #include <memory>
10 #include <utility>
11 
12 #include "core/fpdfapi/cpdf_modulemgr.h"
13 #include "core/fpdfapi/page/cpdf_form.h"
14 #include "core/fpdfapi/page/cpdf_pagemodule.h"
15 #include "core/fpdfapi/page/pageint.h"
16 #include "core/fpdfapi/parser/cpdf_array.h"
17 #include "core/fpdfapi/parser/cpdf_dictionary.h"
18 #include "core/fpdfapi/parser/cpdf_document.h"
19 #include "core/fpdfapi/parser/cpdf_name.h"
20 #include "core/fpdfapi/parser/cpdf_number.h"
21 #include "core/fpdfapi/parser/cpdf_simple_parser.h"
22 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
23 #include "core/fxcrt/fx_ext.h"
24 #include "core/fxcrt/fx_safe_types.h"
25 #include "core/fxge/fx_freetype.h"
26 #include "third_party/base/numerics/safe_conversions.h"
27 #include "third_party/base/ptr_util.h"
28 #include "third_party/base/stl_util.h"
29 
TT2PDF(int m,FXFT_Face face)30 int TT2PDF(int m, FXFT_Face face) {
31   int upm = FXFT_Get_Face_UnitsPerEM(face);
32   if (upm == 0)
33     return m;
34   return pdfium::base::checked_cast<int>(
35       (static_cast<double>(m) * 1000 + upm / 2) / upm);
36 }
37 
FT_UseTTCharmap(FXFT_Face face,int platform_id,int encoding_id)38 bool FT_UseTTCharmap(FXFT_Face face, int platform_id, int encoding_id) {
39   auto* pCharMap = FXFT_Get_Face_Charmaps(face);
40   for (int i = 0; i < FXFT_Get_Face_CharmapCount(face); i++) {
41     if (FXFT_Get_Charmap_PlatformID(pCharMap[i]) == platform_id &&
42         FXFT_Get_Charmap_EncodingID(pCharMap[i]) == encoding_id) {
43       FXFT_Set_Charmap(face, pCharMap[i]);
44       return true;
45     }
46   }
47   return false;
48 }
49 
CFX_StockFontArray()50 CFX_StockFontArray::CFX_StockFontArray() {}
51 
~CFX_StockFontArray()52 CFX_StockFontArray::~CFX_StockFontArray() {
53   for (size_t i = 0; i < FX_ArraySize(m_StockFonts); ++i) {
54     if (m_StockFonts[i])
55       delete m_StockFonts[i]->GetFontDict();
56   }
57 }
58 
GetFont(uint32_t index) const59 CPDF_Font* CFX_StockFontArray::GetFont(uint32_t index) const {
60   if (index >= FX_ArraySize(m_StockFonts))
61     return nullptr;
62   return m_StockFonts[index].get();
63 }
64 
SetFont(uint32_t index,std::unique_ptr<CPDF_Font> pFont)65 CPDF_Font* CFX_StockFontArray::SetFont(uint32_t index,
66                                        std::unique_ptr<CPDF_Font> pFont) {
67   CPDF_Font* result = pFont.get();
68   if (index < FX_ArraySize(m_StockFonts))
69     m_StockFonts[index] = std::move(pFont);
70   return result;
71 }
72 
CPDF_FontGlobals()73 CPDF_FontGlobals::CPDF_FontGlobals() {
74   FXSYS_memset(m_EmbeddedCharsets, 0, sizeof(m_EmbeddedCharsets));
75   FXSYS_memset(m_EmbeddedToUnicodes, 0, sizeof(m_EmbeddedToUnicodes));
76 }
77 
~CPDF_FontGlobals()78 CPDF_FontGlobals::~CPDF_FontGlobals() {}
79 
Find(CPDF_Document * pDoc,uint32_t index)80 CPDF_Font* CPDF_FontGlobals::Find(CPDF_Document* pDoc, uint32_t index) {
81   auto it = m_StockMap.find(pDoc);
82   if (it == m_StockMap.end())
83     return nullptr;
84   return it->second ? it->second->GetFont(index) : nullptr;
85 }
86 
Set(CPDF_Document * pDoc,uint32_t index,std::unique_ptr<CPDF_Font> pFont)87 CPDF_Font* CPDF_FontGlobals::Set(CPDF_Document* pDoc,
88                                  uint32_t index,
89                                  std::unique_ptr<CPDF_Font> pFont) {
90   if (!pdfium::ContainsKey(m_StockMap, pDoc))
91     m_StockMap[pDoc] = pdfium::MakeUnique<CFX_StockFontArray>();
92   return m_StockMap[pDoc]->SetFont(index, std::move(pFont));
93 }
94 
Clear(CPDF_Document * pDoc)95 void CPDF_FontGlobals::Clear(CPDF_Document* pDoc) {
96   m_StockMap.erase(pDoc);
97 }
98 
Lookup(uint32_t charcode) const99 CFX_WideString CPDF_ToUnicodeMap::Lookup(uint32_t charcode) const {
100   auto it = m_Map.find(charcode);
101   if (it != m_Map.end()) {
102     uint32_t value = it->second;
103     FX_WCHAR unicode = (FX_WCHAR)(value & 0xffff);
104     if (unicode != 0xffff) {
105       return unicode;
106     }
107     const FX_WCHAR* buf = m_MultiCharBuf.GetBuffer();
108     uint32_t buf_len = m_MultiCharBuf.GetLength();
109     if (!buf || buf_len == 0) {
110       return CFX_WideString();
111     }
112     uint32_t index = value >> 16;
113     if (index >= buf_len) {
114       return CFX_WideString();
115     }
116     uint32_t len = buf[index];
117     if (index + len < index || index + len >= buf_len) {
118       return CFX_WideString();
119     }
120     return CFX_WideString(buf + index + 1, len);
121   }
122   if (m_pBaseMap) {
123     return m_pBaseMap->UnicodeFromCID((uint16_t)charcode);
124   }
125   return CFX_WideString();
126 }
127 
ReverseLookup(FX_WCHAR unicode) const128 uint32_t CPDF_ToUnicodeMap::ReverseLookup(FX_WCHAR unicode) const {
129   for (const auto& pair : m_Map) {
130     if (pair.second == static_cast<uint32_t>(unicode))
131       return pair.first;
132   }
133   return 0;
134 }
135 
136 // Static.
StringToCode(const CFX_ByteStringC & str)137 uint32_t CPDF_ToUnicodeMap::StringToCode(const CFX_ByteStringC& str) {
138   int len = str.GetLength();
139   if (len == 0)
140     return 0;
141 
142   uint32_t result = 0;
143   if (str[0] == '<') {
144     for (int i = 1; i < len && std::isxdigit(str[i]); ++i)
145       result = result * 16 + FXSYS_toHexDigit(str.CharAt(i));
146     return result;
147   }
148 
149   for (int i = 0; i < len && std::isdigit(str[i]); ++i)
150     result = result * 10 + FXSYS_toDecimalDigit(str.CharAt(i));
151 
152   return result;
153 }
154 
StringDataAdd(CFX_WideString str)155 static CFX_WideString StringDataAdd(CFX_WideString str) {
156   CFX_WideString ret;
157   int len = str.GetLength();
158   FX_WCHAR value = 1;
159   for (int i = len - 1; i >= 0; --i) {
160     FX_WCHAR ch = str[i] + value;
161     if (ch < str[i]) {
162       ret.Insert(0, 0);
163     } else {
164       ret.Insert(0, ch);
165       value = 0;
166     }
167   }
168   if (value) {
169     ret.Insert(0, value);
170   }
171   return ret;
172 }
173 
174 // Static.
StringToWideString(const CFX_ByteStringC & str)175 CFX_WideString CPDF_ToUnicodeMap::StringToWideString(
176     const CFX_ByteStringC& str) {
177   int len = str.GetLength();
178   if (len == 0)
179     return CFX_WideString();
180 
181   CFX_WideString result;
182   if (str[0] == '<') {
183     int byte_pos = 0;
184     FX_WCHAR ch = 0;
185     for (int i = 1; i < len && std::isxdigit(str[i]); ++i) {
186       ch = ch * 16 + FXSYS_toHexDigit(str[i]);
187       byte_pos++;
188       if (byte_pos == 4) {
189         result += ch;
190         byte_pos = 0;
191         ch = 0;
192       }
193     }
194     return result;
195   }
196   return result;
197 }
198 
CPDF_ToUnicodeMap()199 CPDF_ToUnicodeMap::CPDF_ToUnicodeMap() : m_pBaseMap(nullptr) {}
200 
~CPDF_ToUnicodeMap()201 CPDF_ToUnicodeMap::~CPDF_ToUnicodeMap() {}
202 
GetUnicode()203 uint32_t CPDF_ToUnicodeMap::GetUnicode() {
204   FX_SAFE_UINT32 uni = m_MultiCharBuf.GetLength();
205   uni = uni * 0x10000 + 0xffff;
206   return uni.ValueOrDefault(0);
207 }
208 
Load(CPDF_Stream * pStream)209 void CPDF_ToUnicodeMap::Load(CPDF_Stream* pStream) {
210   CIDSet cid_set = CIDSET_UNKNOWN;
211   CPDF_StreamAcc stream;
212   stream.LoadAllData(pStream, false);
213   CPDF_SimpleParser parser(stream.GetData(), stream.GetSize());
214   while (1) {
215     CFX_ByteStringC word = parser.GetWord();
216     if (word.IsEmpty()) {
217       break;
218     }
219     if (word == "beginbfchar") {
220       while (1) {
221         word = parser.GetWord();
222         if (word.IsEmpty() || word == "endbfchar") {
223           break;
224         }
225         uint32_t srccode = StringToCode(word);
226         word = parser.GetWord();
227         CFX_WideString destcode = StringToWideString(word);
228         int len = destcode.GetLength();
229         if (len == 0) {
230           continue;
231         }
232         if (len == 1) {
233           m_Map[srccode] = destcode.GetAt(0);
234         } else {
235           m_Map[srccode] = GetUnicode();
236           m_MultiCharBuf.AppendChar(destcode.GetLength());
237           m_MultiCharBuf << destcode;
238         }
239       }
240     } else if (word == "beginbfrange") {
241       while (1) {
242         CFX_ByteString low, high;
243         low = parser.GetWord();
244         if (low.IsEmpty() || low == "endbfrange") {
245           break;
246         }
247         high = parser.GetWord();
248         uint32_t lowcode = StringToCode(low.AsStringC());
249         uint32_t highcode =
250             (lowcode & 0xffffff00) | (StringToCode(high.AsStringC()) & 0xff);
251         if (highcode == (uint32_t)-1) {
252           break;
253         }
254         CFX_ByteString start(parser.GetWord());
255         if (start == "[") {
256           for (uint32_t code = lowcode; code <= highcode; code++) {
257             CFX_ByteString dest(parser.GetWord());
258             CFX_WideString destcode = StringToWideString(dest.AsStringC());
259             int len = destcode.GetLength();
260             if (len == 0) {
261               continue;
262             }
263             if (len == 1) {
264               m_Map[code] = destcode.GetAt(0);
265             } else {
266               m_Map[code] = GetUnicode();
267               m_MultiCharBuf.AppendChar(destcode.GetLength());
268               m_MultiCharBuf << destcode;
269             }
270           }
271           parser.GetWord();
272         } else {
273           CFX_WideString destcode = StringToWideString(start.AsStringC());
274           int len = destcode.GetLength();
275           uint32_t value = 0;
276           if (len == 1) {
277             value = StringToCode(start.AsStringC());
278             for (uint32_t code = lowcode; code <= highcode; code++) {
279               m_Map[code] = value++;
280             }
281           } else {
282             for (uint32_t code = lowcode; code <= highcode; code++) {
283               CFX_WideString retcode;
284               if (code == lowcode) {
285                 retcode = destcode;
286               } else {
287                 retcode = StringDataAdd(destcode);
288               }
289               m_Map[code] = GetUnicode();
290               m_MultiCharBuf.AppendChar(retcode.GetLength());
291               m_MultiCharBuf << retcode;
292               destcode = retcode;
293             }
294           }
295         }
296       }
297     } else if (word == "/Adobe-Korea1-UCS2") {
298       cid_set = CIDSET_KOREA1;
299     } else if (word == "/Adobe-Japan1-UCS2") {
300       cid_set = CIDSET_JAPAN1;
301     } else if (word == "/Adobe-CNS1-UCS2") {
302       cid_set = CIDSET_CNS1;
303     } else if (word == "/Adobe-GB1-UCS2") {
304       cid_set = CIDSET_GB1;
305     }
306   }
307   if (cid_set) {
308     m_pBaseMap = CPDF_ModuleMgr::Get()
309                      ->GetPageModule()
310                      ->GetFontGlobals()
311                      ->m_CMapManager.GetCID2UnicodeMap(cid_set, false);
312   } else {
313     m_pBaseMap = nullptr;
314   }
315 }
316