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 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 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 50 CFX_StockFontArray::CFX_StockFontArray() {} 51 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 59 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 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 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 78 CPDF_FontGlobals::~CPDF_FontGlobals() {} 79 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 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 95 void CPDF_FontGlobals::Clear(CPDF_Document* pDoc) { 96 m_StockMap.erase(pDoc); 97 } 98 99 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 128 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. 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 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. 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 199 CPDF_ToUnicodeMap::CPDF_ToUnicodeMap() : m_pBaseMap(nullptr) {} 200 201 CPDF_ToUnicodeMap::~CPDF_ToUnicodeMap() {} 202 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 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