// Copyright 2014 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "core/fpdfapi/fpdf_font/font_int.h" #include "core/fpdfapi/fpdf_page/include/cpdf_form.h" #include "core/fpdfapi/fpdf_page/pageint.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_name.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_number.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h" #include "core/fpdfapi/include/cpdf_modulemgr.h" #include "core/fxcrt/include/fx_ext.h" #include "core/include/fxge/fx_freetype.h" #include "third_party/base/stl_util.h" FX_BOOL FT_UseTTCharmap(FXFT_Face face, int platform_id, int encoding_id) { for (int i = 0; i < FXFT_Get_Face_CharmapCount(face); i++) { if (FXFT_Get_Charmap_PlatformID(FXFT_Get_Face_Charmaps(face)[i]) == platform_id && FXFT_Get_Charmap_EncodingID(FXFT_Get_Face_Charmaps(face)[i]) == encoding_id) { FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[i]); return TRUE; } } return FALSE; } CFX_StockFontArray::CFX_StockFontArray() {} CFX_StockFontArray::~CFX_StockFontArray() { for (size_t i = 0; i < FX_ArraySize(m_StockFonts); ++i) { if (!m_StockFonts[i]) continue; CPDF_Dictionary* pFontDict = m_StockFonts[i]->GetFontDict(); if (pFontDict) pFontDict->Release(); } } CPDF_Font* CFX_StockFontArray::GetFont(int index) const { if (index < 0 || index >= FX_ArraySize(m_StockFonts)) return nullptr; return m_StockFonts[index].get(); } void CFX_StockFontArray::SetFont(int index, CPDF_Font* font) { if (index < 0 || index >= FX_ArraySize(m_StockFonts)) return; m_StockFonts[index].reset(font); } CPDF_FontGlobals::CPDF_FontGlobals() { FXSYS_memset(m_EmbeddedCharsets, 0, sizeof(m_EmbeddedCharsets)); FXSYS_memset(m_EmbeddedToUnicodes, 0, sizeof(m_EmbeddedToUnicodes)); } CPDF_FontGlobals::~CPDF_FontGlobals() {} CPDF_Font* CPDF_FontGlobals::Find(CPDF_Document* pDoc, int index) { auto it = m_StockMap.find(pDoc); if (it == m_StockMap.end()) return nullptr; return it->second ? it->second->GetFont(index) : nullptr; } void CPDF_FontGlobals::Set(CPDF_Document* pDoc, int index, CPDF_Font* pFont) { if (!pdfium::ContainsKey(m_StockMap, pDoc)) m_StockMap[pDoc].reset(new CFX_StockFontArray); m_StockMap[pDoc]->SetFont(index, pFont); } void CPDF_FontGlobals::Clear(CPDF_Document* pDoc) { m_StockMap.erase(pDoc); } short TT2PDF(int m, FXFT_Face face) { int upm = FXFT_Get_Face_UnitsPerEM(face); if (upm == 0) return (short)m; return (m * 1000 + upm / 2) / upm; } CFX_WideString CPDF_ToUnicodeMap::Lookup(uint32_t charcode) { auto it = m_Map.find(charcode); if (it != m_Map.end()) { uint32_t value = it->second; FX_WCHAR unicode = (FX_WCHAR)(value & 0xffff); if (unicode != 0xffff) { return unicode; } const FX_WCHAR* buf = m_MultiCharBuf.GetBuffer(); uint32_t buf_len = m_MultiCharBuf.GetLength(); if (!buf || buf_len == 0) { return CFX_WideString(); } uint32_t index = value >> 16; if (index >= buf_len) { return CFX_WideString(); } uint32_t len = buf[index]; if (index + len < index || index + len >= buf_len) { return CFX_WideString(); } return CFX_WideString(buf + index + 1, len); } if (m_pBaseMap) { return m_pBaseMap->UnicodeFromCID((uint16_t)charcode); } return CFX_WideString(); } uint32_t CPDF_ToUnicodeMap::ReverseLookup(FX_WCHAR unicode) { for (const auto& pair : m_Map) { if (pair.second == unicode) return pair.first; } return 0; } // Static. uint32_t CPDF_ToUnicodeMap::StringToCode(const CFX_ByteStringC& str) { const FX_CHAR* buf = str.GetCStr(); int len = str.GetLength(); if (len == 0) return 0; int result = 0; if (buf[0] == '<') { for (int i = 1; i < len && std::isxdigit(buf[i]); ++i) result = result * 16 + FXSYS_toHexDigit(buf[i]); return result; } for (int i = 0; i < len && std::isdigit(buf[i]); ++i) result = result * 10 + FXSYS_toDecimalDigit(buf[i]); return result; } static CFX_WideString StringDataAdd(CFX_WideString str) { CFX_WideString ret; int len = str.GetLength(); FX_WCHAR value = 1; for (int i = len - 1; i >= 0; --i) { FX_WCHAR ch = str[i] + value; if (ch < str[i]) { ret.Insert(0, 0); } else { ret.Insert(0, ch); value = 0; } } if (value) { ret.Insert(0, value); } return ret; } // Static. CFX_WideString CPDF_ToUnicodeMap::StringToWideString( const CFX_ByteStringC& str) { const FX_CHAR* buf = str.GetCStr(); int len = str.GetLength(); if (len == 0) return CFX_WideString(); CFX_WideString result; if (buf[0] == '<') { int byte_pos = 0; FX_WCHAR ch = 0; for (int i = 1; i < len && std::isxdigit(buf[i]); ++i) { ch = ch * 16 + FXSYS_toHexDigit(buf[i]); byte_pos++; if (byte_pos == 4) { result += ch; byte_pos = 0; ch = 0; } } return result; } return result; } void CPDF_ToUnicodeMap::Load(CPDF_Stream* pStream) { CIDSet cid_set = CIDSET_UNKNOWN; CPDF_StreamAcc stream; stream.LoadAllData(pStream, FALSE); CPDF_SimpleParser parser(stream.GetData(), stream.GetSize()); while (1) { CFX_ByteStringC word = parser.GetWord(); if (word.IsEmpty()) { break; } if (word == "beginbfchar") { while (1) { word = parser.GetWord(); if (word.IsEmpty() || word == "endbfchar") { break; } uint32_t srccode = StringToCode(word); word = parser.GetWord(); CFX_WideString destcode = StringToWideString(word); int len = destcode.GetLength(); if (len == 0) { continue; } if (len == 1) { m_Map[srccode] = destcode.GetAt(0); } else { m_Map[srccode] = m_MultiCharBuf.GetLength() * 0x10000 + 0xffff; m_MultiCharBuf.AppendChar(destcode.GetLength()); m_MultiCharBuf << destcode; } } } else if (word == "beginbfrange") { while (1) { CFX_ByteString low, high; low = parser.GetWord(); if (low.IsEmpty() || low == "endbfrange") { break; } high = parser.GetWord(); uint32_t lowcode = StringToCode(low); uint32_t highcode = (lowcode & 0xffffff00) | (StringToCode(high) & 0xff); if (highcode == (uint32_t)-1) { break; } CFX_ByteString start = parser.GetWord(); if (start == "[") { for (uint32_t code = lowcode; code <= highcode; code++) { CFX_ByteString dest = parser.GetWord(); CFX_WideString destcode = StringToWideString(dest); int len = destcode.GetLength(); if (len == 0) { continue; } if (len == 1) { m_Map[code] = destcode.GetAt(0); } else { m_Map[code] = m_MultiCharBuf.GetLength() * 0x10000 + 0xffff; m_MultiCharBuf.AppendChar(destcode.GetLength()); m_MultiCharBuf << destcode; } } parser.GetWord(); } else { CFX_WideString destcode = StringToWideString(start); int len = destcode.GetLength(); uint32_t value = 0; if (len == 1) { value = StringToCode(start); for (uint32_t code = lowcode; code <= highcode; code++) { m_Map[code] = value++; } } else { for (uint32_t code = lowcode; code <= highcode; code++) { CFX_WideString retcode; if (code == lowcode) { retcode = destcode; } else { retcode = StringDataAdd(destcode); } m_Map[code] = m_MultiCharBuf.GetLength() * 0x10000 + 0xffff; m_MultiCharBuf.AppendChar(retcode.GetLength()); m_MultiCharBuf << retcode; destcode = retcode; } } } } } else if (word == "/Adobe-Korea1-UCS2") { cid_set = CIDSET_KOREA1; } else if (word == "/Adobe-Japan1-UCS2") { cid_set = CIDSET_JAPAN1; } else if (word == "/Adobe-CNS1-UCS2") { cid_set = CIDSET_CNS1; } else if (word == "/Adobe-GB1-UCS2") { cid_set = CIDSET_GB1; } } if (cid_set) { m_pBaseMap = CPDF_ModuleMgr::Get() ->GetPageModule() ->GetFontGlobals() ->m_CMapManager.GetCID2UnicodeMap(cid_set, FALSE); } else { m_pBaseMap = NULL; } }