From 764ec513eecbebd12781bcc96ce81ed5e736ee92 Mon Sep 17 00:00:00 2001 From: Dan Sinclair Date: Mon, 14 Mar 2016 13:35:12 -0400 Subject: Move core/src/ up to core/. This CL moves the core/src/ files up to core/ and fixes up the include guards, includes and build files. R=tsepez@chromium.org Review URL: https://codereview.chromium.org/1800523005 . --- core/fpdfapi/fpdf_font/fpdf_font.cpp | 1814 ++++++++++++++++++++++++++++++++++ 1 file changed, 1814 insertions(+) create mode 100644 core/fpdfapi/fpdf_font/fpdf_font.cpp (limited to 'core/fpdfapi/fpdf_font/fpdf_font.cpp') diff --git a/core/fpdfapi/fpdf_font/fpdf_font.cpp b/core/fpdfapi/fpdf_font/fpdf_font.cpp new file mode 100644 index 0000000000..98411ef0f1 --- /dev/null +++ b/core/fpdfapi/fpdf_font/fpdf_font.cpp @@ -0,0 +1,1814 @@ +// 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/pageint.h" +#include "core/include/fpdfapi/cpdf_array.h" +#include "core/include/fpdfapi/cpdf_dictionary.h" +#include "core/include/fpdfapi/cpdf_document.h" +#include "core/include/fpdfapi/cpdf_name.h" +#include "core/include/fpdfapi/cpdf_number.h" +#include "core/include/fpdfapi/cpdf_simple_parser.h" +#include "core/include/fpdfapi/fpdf_module.h" +#include "core/include/fpdfapi/fpdf_page.h" +#include "core/include/fpdfapi/fpdf_pageobj.h" +#include "core/include/fpdfapi/fpdf_resource.h" +#include "core/include/fxcrt/fx_ext.h" +#include "core/include/fxge/fx_freetype.h" +#include "third_party/base/stl_util.h" + +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +#include "core/fxge/apple/apple_int.h" +#endif + +namespace { + +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ +struct GlyphNameMap { + const FX_CHAR* m_pStrAdobe; + const FX_CHAR* m_pStrUnicode; +}; + +const GlyphNameMap g_GlyphNameSubsts[] = {{"ff", "uniFB00"}, + {"fi", "uniFB01"}, + {"fl", "uniFB02"}, + {"ffi", "uniFB03"}, + {"ffl", "uniFB04"}}; + +int compareString(const void* key, const void* element) { + return FXSYS_stricmp((const FX_CHAR*)key, + ((GlyphNameMap*)element)->m_pStrAdobe); +} + +const FX_CHAR* GlyphNameRemap(const FX_CHAR* pStrAdobe) { + GlyphNameMap* found = (GlyphNameMap*)FXSYS_bsearch( + pStrAdobe, g_GlyphNameSubsts, + sizeof(g_GlyphNameSubsts) / sizeof(GlyphNameMap), sizeof(GlyphNameMap), + compareString); + if (found) + return found->m_pStrUnicode; + return NULL; +} +#endif + +const uint8_t ChineseFontNames[][5] = {{0xCB, 0xCE, 0xCC, 0xE5, 0x00}, + {0xBF, 0xAC, 0xCC, 0xE5, 0x00}, + {0xBA, 0xDA, 0xCC, 0xE5, 0x00}, + {0xB7, 0xC2, 0xCB, 0xCE, 0x00}, + {0xD0, 0xC2, 0xCB, 0xCE, 0x00}}; + +FX_BOOL GetPredefinedEncoding(int& basemap, const CFX_ByteString& value) { + if (value == "WinAnsiEncoding") { + basemap = PDFFONT_ENCODING_WINANSI; + } else if (value == "MacRomanEncoding") { + basemap = PDFFONT_ENCODING_MACROMAN; + } else if (value == "MacExpertEncoding") { + basemap = PDFFONT_ENCODING_MACEXPERT; + } else if (value == "PDFDocEncoding") { + basemap = PDFFONT_ENCODING_PDFDOC; + } else { + return FALSE; + } + return TRUE; +} + +FX_BOOL FT_UseType1Charmap(FXFT_Face face) { + if (FXFT_Get_Face_CharmapCount(face) == 0) { + return FALSE; + } + if (FXFT_Get_Face_CharmapCount(face) == 1 && + FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[0]) == + FXFT_ENCODING_UNICODE) { + return FALSE; + } + if (FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[0]) == + FXFT_ENCODING_UNICODE) { + FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[1]); + } else { + FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[0]); + } + return TRUE; +} + +} // namespace + +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); +} + +CPDF_Font::CPDF_Font() + : m_pFontFile(nullptr), + m_pFontDict(nullptr), + m_pToUnicodeMap(nullptr), + m_bToUnicodeLoaded(FALSE), + m_Flags(0), + m_StemV(0), + m_Ascent(0), + m_Descent(0), + m_ItalicAngle(0) {} + +CPDF_Font::~CPDF_Font() { + delete m_pToUnicodeMap; + m_pToUnicodeMap = NULL; + + if (m_pFontFile) { + m_pDocument->GetPageData()->ReleaseFontFileStreamAcc( + const_cast(m_pFontFile->GetStream()->AsStream())); + } +} + +bool CPDF_Font::IsType1Font() const { + return false; +} + +bool CPDF_Font::IsTrueTypeFont() const { + return false; +} + +bool CPDF_Font::IsType3Font() const { + return false; +} + +bool CPDF_Font::IsCIDFont() const { + return false; +} + +const CPDF_Type1Font* CPDF_Font::AsType1Font() const { + return nullptr; +} + +CPDF_Type1Font* CPDF_Font::AsType1Font() { + return nullptr; +} + +const CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() const { + return nullptr; +} + +CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() { + return nullptr; +} + +const CPDF_Type3Font* CPDF_Font::AsType3Font() const { + return nullptr; +} + +CPDF_Type3Font* CPDF_Font::AsType3Font() { + return nullptr; +} + +const CPDF_CIDFont* CPDF_Font::AsCIDFont() const { + return nullptr; +} + +CPDF_CIDFont* CPDF_Font::AsCIDFont() { + return nullptr; +} + +FX_BOOL CPDF_Font::IsUnicodeCompatible() const { + return FALSE; +} + +int CPDF_Font::CountChar(const FX_CHAR* pString, int size) const { + return size; +} + +int CPDF_Font::GetCharSize(FX_DWORD charcode) const { + return 1; +} + +int CPDF_Font::GlyphFromCharCode(FX_DWORD charcode, FX_BOOL* pVertGlyph) { + ASSERT(false); + return 0; +} + +int CPDF_Font::GlyphFromCharCodeExt(FX_DWORD charcode) { + return GlyphFromCharCode(charcode); +} + +FX_BOOL CPDF_Font::IsVertWriting() const { + FX_BOOL bVertWriting = FALSE; + const CPDF_CIDFont* pCIDFont = AsCIDFont(); + if (pCIDFont) { + bVertWriting = pCIDFont->IsVertWriting(); + } else { + bVertWriting = m_Font.IsVertical(); + } + return bVertWriting; +} + +int CPDF_Font::AppendChar(FX_CHAR* buf, FX_DWORD charcode) const { + *buf = (FX_CHAR)charcode; + return 1; +} + +void CPDF_Font::AppendChar(CFX_ByteString& str, FX_DWORD charcode) const { + char buf[4]; + int len = AppendChar(buf, charcode); + if (len == 1) { + str += buf[0]; + } else { + str += CFX_ByteString(buf, len); + } +} + +CFX_WideString CPDF_Font::UnicodeFromCharCode(FX_DWORD charcode) const { + if (!m_bToUnicodeLoaded) + ((CPDF_Font*)this)->LoadUnicodeMap(); + + if (m_pToUnicodeMap) + return m_pToUnicodeMap->Lookup(charcode); + return CFX_WideString(); +} + +FX_DWORD CPDF_Font::CharCodeFromUnicode(FX_WCHAR unicode) const { + if (!m_bToUnicodeLoaded) + ((CPDF_Font*)this)->LoadUnicodeMap(); + + if (m_pToUnicodeMap) + return m_pToUnicodeMap->ReverseLookup(unicode); + return 0; +} + +void CPDF_Font::LoadFontDescriptor(CPDF_Dictionary* pFontDesc) { + m_Flags = pFontDesc->GetIntegerBy("Flags", PDFFONT_NONSYMBOLIC); + int ItalicAngle = 0; + FX_BOOL bExistItalicAngle = FALSE; + if (pFontDesc->KeyExist("ItalicAngle")) { + ItalicAngle = pFontDesc->GetIntegerBy("ItalicAngle"); + bExistItalicAngle = TRUE; + } + if (ItalicAngle < 0) { + m_Flags |= PDFFONT_ITALIC; + m_ItalicAngle = ItalicAngle; + } + FX_BOOL bExistStemV = FALSE; + if (pFontDesc->KeyExist("StemV")) { + m_StemV = pFontDesc->GetIntegerBy("StemV"); + bExistStemV = TRUE; + } + FX_BOOL bExistAscent = FALSE; + if (pFontDesc->KeyExist("Ascent")) { + m_Ascent = pFontDesc->GetIntegerBy("Ascent"); + bExistAscent = TRUE; + } + FX_BOOL bExistDescent = FALSE; + if (pFontDesc->KeyExist("Descent")) { + m_Descent = pFontDesc->GetIntegerBy("Descent"); + bExistDescent = TRUE; + } + FX_BOOL bExistCapHeight = FALSE; + if (pFontDesc->KeyExist("CapHeight")) { + bExistCapHeight = TRUE; + } + if (bExistItalicAngle && bExistAscent && bExistCapHeight && bExistDescent && + bExistStemV) { + m_Flags |= PDFFONT_USEEXTERNATTR; + } + if (m_Descent > 10) { + m_Descent = -m_Descent; + } + CPDF_Array* pBBox = pFontDesc->GetArrayBy("FontBBox"); + if (pBBox) { + m_FontBBox.left = pBBox->GetIntegerAt(0); + m_FontBBox.bottom = pBBox->GetIntegerAt(1); + m_FontBBox.right = pBBox->GetIntegerAt(2); + m_FontBBox.top = pBBox->GetIntegerAt(3); + } + + CPDF_Stream* pFontFile = pFontDesc->GetStreamBy("FontFile"); + if (!pFontFile) + pFontFile = pFontDesc->GetStreamBy("FontFile2"); + if (!pFontFile) + pFontFile = pFontDesc->GetStreamBy("FontFile3"); + if (!pFontFile) + return; + + m_pFontFile = m_pDocument->LoadFontFile(pFontFile); + if (!m_pFontFile) + return; + + const uint8_t* pFontData = m_pFontFile->GetData(); + FX_DWORD dwFontSize = m_pFontFile->GetSize(); + if (!m_Font.LoadEmbedded(pFontData, dwFontSize)) { + m_pDocument->GetPageData()->ReleaseFontFileStreamAcc( + const_cast(m_pFontFile->GetStream()->AsStream())); + m_pFontFile = nullptr; + } +} + +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; +} + +void CPDF_Font::CheckFontMetrics() { + if (m_FontBBox.top == 0 && m_FontBBox.bottom == 0 && m_FontBBox.left == 0 && + m_FontBBox.right == 0) { + FXFT_Face face = m_Font.GetFace(); + if (face) { + m_FontBBox.left = TT2PDF(FXFT_Get_Face_xMin(face), face); + m_FontBBox.bottom = TT2PDF(FXFT_Get_Face_yMin(face), face); + m_FontBBox.right = TT2PDF(FXFT_Get_Face_xMax(face), face); + m_FontBBox.top = TT2PDF(FXFT_Get_Face_yMax(face), face); + m_Ascent = TT2PDF(FXFT_Get_Face_Ascender(face), face); + m_Descent = TT2PDF(FXFT_Get_Face_Descender(face), face); + } else { + FX_BOOL bFirst = TRUE; + for (int i = 0; i < 256; i++) { + FX_RECT rect = GetCharBBox(i); + if (rect.left == rect.right) { + continue; + } + if (bFirst) { + m_FontBBox = rect; + bFirst = FALSE; + } else { + if (m_FontBBox.top < rect.top) { + m_FontBBox.top = rect.top; + } + if (m_FontBBox.right < rect.right) { + m_FontBBox.right = rect.right; + } + if (m_FontBBox.left > rect.left) { + m_FontBBox.left = rect.left; + } + if (m_FontBBox.bottom > rect.bottom) { + m_FontBBox.bottom = rect.bottom; + } + } + } + } + } + if (m_Ascent == 0 && m_Descent == 0) { + FX_RECT rect = GetCharBBox('A'); + m_Ascent = rect.bottom == rect.top ? m_FontBBox.top : rect.top; + rect = GetCharBBox('g'); + m_Descent = rect.bottom == rect.top ? m_FontBBox.bottom : rect.bottom; + } +} + +void CPDF_Font::LoadUnicodeMap() { + m_bToUnicodeLoaded = TRUE; + CPDF_Stream* pStream = m_pFontDict->GetStreamBy("ToUnicode"); + if (!pStream) { + return; + } + m_pToUnicodeMap = new CPDF_ToUnicodeMap; + m_pToUnicodeMap->Load(pStream); +} + +int CPDF_Font::GetStringWidth(const FX_CHAR* pString, int size) { + int offset = 0; + int width = 0; + while (offset < size) { + FX_DWORD charcode = GetNextChar(pString, size, offset); + width += GetCharWidthF(charcode); + } + return width; +} + +CPDF_Font* CPDF_Font::GetStockFont(CPDF_Document* pDoc, + const CFX_ByteStringC& name) { + CFX_ByteString fontname(name); + int font_id = PDF_GetStandardFontName(&fontname); + if (font_id < 0) { + return nullptr; + } + CPDF_FontGlobals* pFontGlobals = + CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals(); + CPDF_Font* pFont = pFontGlobals->Find(pDoc, font_id); + if (pFont) { + return pFont; + } + CPDF_Dictionary* pDict = new CPDF_Dictionary; + pDict->SetAtName("Type", "Font"); + pDict->SetAtName("Subtype", "Type1"); + pDict->SetAtName("BaseFont", fontname); + pDict->SetAtName("Encoding", "WinAnsiEncoding"); + pFont = CPDF_Font::CreateFontF(NULL, pDict); + pFontGlobals->Set(pDoc, font_id, pFont); + return pFont; +} + +CPDF_Font* CPDF_Font::CreateFontF(CPDF_Document* pDoc, + CPDF_Dictionary* pFontDict) { + CFX_ByteString type = pFontDict->GetStringBy("Subtype"); + CPDF_Font* pFont; + if (type == "TrueType") { + { +#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ || \ + _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ || \ + _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ || \ + _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + CFX_ByteString basefont = pFontDict->GetStringBy("BaseFont"); + CFX_ByteString tag = basefont.Left(4); + int i; + int count = sizeof(ChineseFontNames) / sizeof(ChineseFontNames[0]); + for (i = 0; i < count; ++i) { + if (tag == CFX_ByteString((const FX_CHAR*)ChineseFontNames[i])) { + break; + } + } + if (i < count) { + CPDF_Dictionary* pFontDesc = pFontDict->GetDictBy("FontDescriptor"); + if (!pFontDesc || !pFontDesc->KeyExist("FontFile2")) { + pFont = new CPDF_CIDFont; + pFont->m_pFontDict = pFontDict; + pFont->m_pDocument = pDoc; + pFont->m_BaseFont = pFontDict->GetStringBy("BaseFont"); + if (!pFont->Load()) { + delete pFont; + return NULL; + } + return pFont; + } + } +#endif + } + pFont = new CPDF_TrueTypeFont; + } else if (type == "Type3") { + pFont = new CPDF_Type3Font; + } else if (type == "Type0") { + pFont = new CPDF_CIDFont; + } else { + pFont = new CPDF_Type1Font; + } + pFont->m_pFontDict = pFontDict; + pFont->m_pDocument = pDoc; + pFont->m_BaseFont = pFontDict->GetStringBy("BaseFont"); + if (!pFont->Load()) { + delete pFont; + return NULL; + } + return pFont; +} + +CFX_WideString CPDF_ToUnicodeMap::Lookup(FX_DWORD charcode) { + auto it = m_Map.find(charcode); + if (it != m_Map.end()) { + FX_DWORD value = it->second; + FX_WCHAR unicode = (FX_WCHAR)(value & 0xffff); + if (unicode != 0xffff) { + return unicode; + } + const FX_WCHAR* buf = m_MultiCharBuf.GetBuffer(); + FX_DWORD buf_len = m_MultiCharBuf.GetLength(); + if (!buf || buf_len == 0) { + return CFX_WideString(); + } + FX_DWORD index = value >> 16; + if (index >= buf_len) { + return CFX_WideString(); + } + FX_DWORD 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((FX_WORD)charcode); + } + return CFX_WideString(); +} + +FX_DWORD CPDF_ToUnicodeMap::ReverseLookup(FX_WCHAR unicode) { + for (const auto& pair : m_Map) { + if (pair.second == unicode) + return pair.first; + } + return 0; +} + +// Static. +FX_DWORD 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; + } + FX_DWORD 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(); + FX_DWORD lowcode = StringToCode(low); + FX_DWORD highcode = + (lowcode & 0xffffff00) | (StringToCode(high) & 0xff); + if (highcode == (FX_DWORD)-1) { + break; + } + CFX_ByteString start = parser.GetWord(); + if (start == "[") { + for (FX_DWORD 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(); + FX_DWORD value = 0; + if (len == 1) { + value = StringToCode(start); + for (FX_DWORD code = lowcode; code <= highcode; code++) { + m_Map[code] = value++; + } + } else { + for (FX_DWORD 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; + } +} + +FX_DWORD CPDF_Font::GetNextChar(const FX_CHAR* pString, + int nStrLen, + int& offset) const { + if (offset < 0 || nStrLen < 1) { + return 0; + } + uint8_t ch = offset < nStrLen ? pString[offset++] : pString[nStrLen - 1]; + return static_cast(ch); +} + +void CPDF_Font::LoadPDFEncoding(CPDF_Object* pEncoding, + int& iBaseEncoding, + CFX_ByteString*& pCharNames, + FX_BOOL bEmbedded, + FX_BOOL bTrueType) { + if (!pEncoding) { + if (m_BaseFont == "Symbol") { + iBaseEncoding = bTrueType ? PDFFONT_ENCODING_MS_SYMBOL + : PDFFONT_ENCODING_ADOBE_SYMBOL; + } else if (!bEmbedded && iBaseEncoding == PDFFONT_ENCODING_BUILTIN) { + iBaseEncoding = PDFFONT_ENCODING_WINANSI; + } + return; + } + if (pEncoding->IsName()) { + if (iBaseEncoding == PDFFONT_ENCODING_ADOBE_SYMBOL || + iBaseEncoding == PDFFONT_ENCODING_ZAPFDINGBATS) { + return; + } + if ((m_Flags & PDFFONT_SYMBOLIC) && m_BaseFont == "Symbol") { + if (!bTrueType) { + iBaseEncoding = PDFFONT_ENCODING_ADOBE_SYMBOL; + } + return; + } + CFX_ByteString bsEncoding = pEncoding->GetString(); + if (bsEncoding.Compare("MacExpertEncoding") == 0) { + bsEncoding = "WinAnsiEncoding"; + } + GetPredefinedEncoding(iBaseEncoding, bsEncoding); + return; + } + + CPDF_Dictionary* pDict = pEncoding->AsDictionary(); + if (!pDict) + return; + + if (iBaseEncoding != PDFFONT_ENCODING_ADOBE_SYMBOL && + iBaseEncoding != PDFFONT_ENCODING_ZAPFDINGBATS) { + CFX_ByteString bsEncoding = pDict->GetStringBy("BaseEncoding"); + if (bsEncoding.Compare("MacExpertEncoding") == 0 && bTrueType) { + bsEncoding = "WinAnsiEncoding"; + } + GetPredefinedEncoding(iBaseEncoding, bsEncoding); + } + if ((!bEmbedded || bTrueType) && iBaseEncoding == PDFFONT_ENCODING_BUILTIN) { + iBaseEncoding = PDFFONT_ENCODING_STANDARD; + } + CPDF_Array* pDiffs = pDict->GetArrayBy("Differences"); + if (!pDiffs) { + return; + } + pCharNames = new CFX_ByteString[256]; + FX_DWORD cur_code = 0; + for (FX_DWORD i = 0; i < pDiffs->GetCount(); i++) { + CPDF_Object* pElement = pDiffs->GetElementValue(i); + if (!pElement) + continue; + + if (CPDF_Name* pName = pElement->AsName()) { + if (cur_code < 256) + pCharNames[cur_code] = pName->GetString(); + cur_code++; + } else { + cur_code = pElement->GetInteger(); + } + } +} + +FX_BOOL CPDF_Font::IsStandardFont() const { + if (!IsType1Font()) + return FALSE; + if (m_pFontFile) + return FALSE; + if (AsType1Font()->GetBase14Font() < 0) + return FALSE; + return TRUE; +} + +CPDF_SimpleFont::CPDF_SimpleFont() + : m_pCharNames(nullptr), m_BaseEncoding(PDFFONT_ENCODING_BUILTIN) { + FXSYS_memset(m_CharWidth, 0xff, sizeof m_CharWidth); + FXSYS_memset(m_GlyphIndex, 0xff, sizeof m_GlyphIndex); + FXSYS_memset(m_ExtGID, 0xff, sizeof m_ExtGID); +} + +CPDF_SimpleFont::~CPDF_SimpleFont() { + delete[] m_pCharNames; +} + +int CPDF_SimpleFont::GlyphFromCharCode(FX_DWORD charcode, FX_BOOL* pVertGlyph) { + if (pVertGlyph) { + *pVertGlyph = FALSE; + } + if (charcode > 0xff) { + return -1; + } + int index = m_GlyphIndex[(uint8_t)charcode]; + if (index == 0xffff) { + return -1; + } + return index; +} + +void CPDF_SimpleFont::LoadCharMetrics(int charcode) { + if (!m_Font.GetFace()) + return; + + if (charcode < 0 || charcode > 0xff) { + return; + } + int glyph_index = m_GlyphIndex[charcode]; + if (glyph_index == 0xffff) { + if (!m_pFontFile && charcode != 32) { + LoadCharMetrics(32); + m_CharBBox[charcode] = m_CharBBox[32]; + if (m_bUseFontWidth) { + m_CharWidth[charcode] = m_CharWidth[32]; + } + } + return; + } + FXFT_Face face = m_Font.GetFace(); + int err = FXFT_Load_Glyph( + face, glyph_index, + FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + if (err) { + return; + } + m_CharBBox[charcode] = FX_SMALL_RECT( + TT2PDF(FXFT_Get_Glyph_HoriBearingX(face), face), + TT2PDF(FXFT_Get_Glyph_HoriBearingY(face), face), + TT2PDF(FXFT_Get_Glyph_HoriBearingX(face) + FXFT_Get_Glyph_Width(face), + face), + TT2PDF(FXFT_Get_Glyph_HoriBearingY(face) - FXFT_Get_Glyph_Height(face), + face)); + + if (m_bUseFontWidth) { + int TT_Width = TT2PDF(FXFT_Get_Glyph_HoriAdvance(face), face); + if (m_CharWidth[charcode] == 0xffff) { + m_CharWidth[charcode] = TT_Width; + } else if (TT_Width && !IsEmbedded()) { + m_CharBBox[charcode].right = + m_CharBBox[charcode].right * m_CharWidth[charcode] / TT_Width; + m_CharBBox[charcode].left = + m_CharBBox[charcode].left * m_CharWidth[charcode] / TT_Width; + } + } +} + +int CPDF_SimpleFont::GetCharWidthF(FX_DWORD charcode, int level) { + if (charcode > 0xff) { + charcode = 0; + } + if (m_CharWidth[charcode] == 0xffff) { + LoadCharMetrics(charcode); + if (m_CharWidth[charcode] == 0xffff) { + m_CharWidth[charcode] = 0; + } + } + return (int16_t)m_CharWidth[charcode]; +} + +FX_RECT CPDF_SimpleFont::GetCharBBox(FX_DWORD charcode, int level) { + if (charcode > 0xff) + charcode = 0; + + if (m_CharBBox[charcode].left == FX_SMALL_RECT::kInvalid) + LoadCharMetrics(charcode); + + return FX_RECT(m_CharBBox[charcode]); +} + +const FX_CHAR* GetAdobeCharName(int iBaseEncoding, + const CFX_ByteString* pCharNames, + int charcode) { + ASSERT(charcode >= 0 && charcode < 256); + if (charcode < 0 || charcode >= 256) { + return NULL; + } + const FX_CHAR* name = NULL; + if (pCharNames) { + name = pCharNames[charcode]; + } + if ((!name || name[0] == 0) && iBaseEncoding) { + name = PDF_CharNameFromPredefinedCharSet(iBaseEncoding, charcode); + } + return name && name[0] ? name : nullptr; +} + +FX_BOOL CPDF_SimpleFont::LoadCommon() { + CPDF_Dictionary* pFontDesc = m_pFontDict->GetDictBy("FontDescriptor"); + if (pFontDesc) { + LoadFontDescriptor(pFontDesc); + } + CPDF_Array* pWidthArray = m_pFontDict->GetArrayBy("Widths"); + int width_start = 0, width_end = -1; + m_bUseFontWidth = TRUE; + if (pWidthArray) { + m_bUseFontWidth = FALSE; + if (pFontDesc && pFontDesc->KeyExist("MissingWidth")) { + int MissingWidth = pFontDesc->GetIntegerBy("MissingWidth"); + for (int i = 0; i < 256; i++) { + m_CharWidth[i] = MissingWidth; + } + } + width_start = m_pFontDict->GetIntegerBy("FirstChar", 0); + width_end = m_pFontDict->GetIntegerBy("LastChar", 0); + if (width_start >= 0 && width_start <= 255) { + if (width_end <= 0 || + width_end >= width_start + (int)pWidthArray->GetCount()) { + width_end = width_start + pWidthArray->GetCount() - 1; + } + if (width_end > 255) { + width_end = 255; + } + for (int i = width_start; i <= width_end; i++) { + m_CharWidth[i] = pWidthArray->GetIntegerAt(i - width_start); + } + } + } + if (m_pFontFile) { + if (m_BaseFont.GetLength() > 8 && m_BaseFont[7] == '+') { + m_BaseFont = m_BaseFont.Mid(8); + } + } else { + LoadSubstFont(); + } + if (!(m_Flags & PDFFONT_SYMBOLIC)) { + m_BaseEncoding = PDFFONT_ENCODING_STANDARD; + } + CPDF_Object* pEncoding = m_pFontDict->GetElementValue("Encoding"); + LoadPDFEncoding(pEncoding, m_BaseEncoding, m_pCharNames, m_pFontFile != NULL, + m_Font.IsTTFont()); + LoadGlyphMap(); + delete[] m_pCharNames; + m_pCharNames = NULL; + if (!m_Font.GetFace()) + return TRUE; + + if (m_Flags & PDFFONT_ALLCAP) { + unsigned char lowercases[] = {'a', 'z', 0xe0, 0xf6, 0xf8, 0xfd}; + for (size_t range = 0; range < sizeof lowercases / 2; range++) { + for (int i = lowercases[range * 2]; i <= lowercases[range * 2 + 1]; i++) { + if (m_GlyphIndex[i] != 0xffff && m_pFontFile) { + continue; + } + m_GlyphIndex[i] = m_GlyphIndex[i - 32]; + if (m_CharWidth[i - 32]) { + m_CharWidth[i] = m_CharWidth[i - 32]; + m_CharBBox[i] = m_CharBBox[i - 32]; + } + } + } + } + CheckFontMetrics(); + return TRUE; +} + +void CPDF_SimpleFont::LoadSubstFont() { + if (!m_bUseFontWidth && !(m_Flags & PDFFONT_FIXEDPITCH)) { + int width = 0, i; + for (i = 0; i < 256; i++) { + if (m_CharWidth[i] == 0 || m_CharWidth[i] == 0xffff) { + continue; + } + if (width == 0) { + width = m_CharWidth[i]; + } else if (width != m_CharWidth[i]) { + break; + } + } + if (i == 256 && width) { + m_Flags |= PDFFONT_FIXEDPITCH; + } + } + int weight = m_StemV < 140 ? m_StemV * 5 : (m_StemV * 4 + 140); + m_Font.LoadSubst(m_BaseFont, IsTrueTypeFont(), m_Flags, weight, m_ItalicAngle, + 0); + if (m_Font.GetSubstFont()->m_SubstFlags & FXFONT_SUBST_NONSYMBOL) { + } +} + +FX_BOOL CPDF_SimpleFont::IsUnicodeCompatible() const { + return m_BaseEncoding != PDFFONT_ENCODING_BUILTIN && + m_BaseEncoding != PDFFONT_ENCODING_ADOBE_SYMBOL && + m_BaseEncoding != PDFFONT_ENCODING_ZAPFDINGBATS; +} + +CFX_WideString CPDF_SimpleFont::UnicodeFromCharCode(FX_DWORD charcode) const { + CFX_WideString unicode = CPDF_Font::UnicodeFromCharCode(charcode); + if (!unicode.IsEmpty()) + return unicode; + FX_WCHAR ret = m_Encoding.UnicodeFromCharCode((uint8_t)charcode); + if (ret == 0) + return CFX_WideString(); + return ret; +} + +FX_DWORD CPDF_SimpleFont::CharCodeFromUnicode(FX_WCHAR unicode) const { + FX_DWORD ret = CPDF_Font::CharCodeFromUnicode(unicode); + if (ret) + return ret; + return m_Encoding.CharCodeFromUnicode(unicode); +} + +CPDF_Type1Font::CPDF_Type1Font() : m_Base14Font(-1) {} + +bool CPDF_Type1Font::IsType1Font() const { + return true; +} + +const CPDF_Type1Font* CPDF_Type1Font::AsType1Font() const { + return this; +} + +CPDF_Type1Font* CPDF_Type1Font::AsType1Font() { + return this; +} + +FX_BOOL CPDF_Type1Font::Load() { + m_Base14Font = PDF_GetStandardFontName(&m_BaseFont); + if (m_Base14Font >= 0) { + CPDF_Dictionary* pFontDesc = m_pFontDict->GetDictBy("FontDescriptor"); + if (pFontDesc && pFontDesc->KeyExist("Flags")) + m_Flags = pFontDesc->GetIntegerBy("Flags"); + else + m_Flags = m_Base14Font >= 12 ? PDFFONT_SYMBOLIC : PDFFONT_NONSYMBOLIC; + + if (m_Base14Font < 4) { + for (int i = 0; i < 256; i++) + m_CharWidth[i] = 600; + } + if (m_Base14Font == 12) + m_BaseEncoding = PDFFONT_ENCODING_ADOBE_SYMBOL; + else if (m_Base14Font == 13) + m_BaseEncoding = PDFFONT_ENCODING_ZAPFDINGBATS; + else if (m_Flags & PDFFONT_NONSYMBOLIC) + m_BaseEncoding = PDFFONT_ENCODING_STANDARD; + } + return LoadCommon(); +} + +int CPDF_Type1Font::GlyphFromCharCodeExt(FX_DWORD charcode) { + if (charcode > 0xff) { + return -1; + } + int index = m_ExtGID[(uint8_t)charcode]; + if (index == 0xffff) { + return -1; + } + return index; +} + +void CPDF_Type1Font::LoadGlyphMap() { + if (!m_Font.GetFace()) + return; + +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + FX_BOOL bCoreText = TRUE; + CQuartz2D& quartz2d = + ((CApplePlatform*)CFX_GEModule::Get()->GetPlatformData())->_quartz2d; + if (!m_Font.GetPlatformFont()) { + if (m_Font.GetPsName() == CFX_WideString::FromLocal("DFHeiStd-W5")) { + bCoreText = FALSE; + } + m_Font.SetPlatformFont( + quartz2d.CreateFont(m_Font.GetFontData(), m_Font.GetSize())); + if (!m_Font.GetPlatformFont()) { + bCoreText = FALSE; + } + } +#endif + if (!IsEmbedded() && (m_Base14Font < 12) && m_Font.IsTTFont()) { + if (FT_UseTTCharmap(m_Font.GetFace(), 3, 0)) { + FX_BOOL bGotOne = FALSE; + for (int charcode = 0; charcode < 256; charcode++) { + const uint8_t prefix[4] = {0x00, 0xf0, 0xf1, 0xf2}; + for (int j = 0; j < 4; j++) { + FX_WORD unicode = prefix[j] * 256 + charcode; + m_GlyphIndex[charcode] = + FXFT_Get_Char_Index(m_Font.GetFace(), unicode); +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + FX_CHAR name_glyph[256]; + FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode], + name_glyph, 256); + name_glyph[255] = 0; + CFStringRef name_ct = CFStringCreateWithCStringNoCopy( + kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII, + kCFAllocatorNull); + m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName( + (CGFontRef)m_Font.GetPlatformFont(), name_ct); + if (name_ct) { + CFRelease(name_ct); + } +#endif + if (m_GlyphIndex[charcode]) { + bGotOne = TRUE; + break; + } + } + } + if (bGotOne) { +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + if (!bCoreText) { + FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256); + } +#endif + return; + } + } + FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE); + if (m_BaseEncoding == 0) { + m_BaseEncoding = PDFFONT_ENCODING_STANDARD; + } + for (int charcode = 0; charcode < 256; charcode++) { + const FX_CHAR* name = + GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode); + if (!name) { + continue; + } + m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name); + m_GlyphIndex[charcode] = FXFT_Get_Char_Index( + m_Font.GetFace(), m_Encoding.m_Unicodes[charcode]); +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + FX_CHAR name_glyph[256]; + FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode], name_glyph, + 256); + name_glyph[255] = 0; + CFStringRef name_ct = CFStringCreateWithCStringNoCopy( + kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII, + kCFAllocatorNull); + m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName( + (CGFontRef)m_Font.GetPlatformFont(), name_ct); + if (name_ct) { + CFRelease(name_ct); + } +#endif + if (m_GlyphIndex[charcode] == 0 && FXSYS_strcmp(name, ".notdef") == 0) { + m_Encoding.m_Unicodes[charcode] = 0x20; + m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), 0x20); +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + FX_CHAR name_glyph[256]; + FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode], + name_glyph, 256); + name_glyph[255] = 0; + CFStringRef name_ct = CFStringCreateWithCStringNoCopy( + kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII, + kCFAllocatorNull); + m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName( + (CGFontRef)m_Font.GetPlatformFont(), name_ct); + if (name_ct) { + CFRelease(name_ct); + } +#endif + } + } +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + if (!bCoreText) { + FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256); + } +#endif + return; + } + FT_UseType1Charmap(m_Font.GetFace()); +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + if (bCoreText) { + if (m_Flags & PDFFONT_SYMBOLIC) { + for (int charcode = 0; charcode < 256; charcode++) { + const FX_CHAR* name = + GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode); + if (name) { + m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name); + m_GlyphIndex[charcode] = + FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name); + CFStringRef name_ct = CFStringCreateWithCStringNoCopy( + kCFAllocatorDefault, name, kCFStringEncodingASCII, + kCFAllocatorNull); + m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName( + (CGFontRef)m_Font.GetPlatformFont(), name_ct); + if (name_ct) { + CFRelease(name_ct); + } + } else { + m_GlyphIndex[charcode] = + FXFT_Get_Char_Index(m_Font.GetFace(), charcode); + FX_WCHAR unicode = 0; + if (m_GlyphIndex[charcode]) { + unicode = + FT_UnicodeFromCharCode(PDFFONT_ENCODING_STANDARD, charcode); + } + FX_CHAR name_glyph[256]; + FXSYS_memset(name_glyph, 0, sizeof(name_glyph)); + FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode], + name_glyph, 256); + name_glyph[255] = 0; + if (unicode == 0 && name_glyph[0] != 0) { + unicode = PDF_UnicodeFromAdobeName(name_glyph); + } + m_Encoding.m_Unicodes[charcode] = unicode; + CFStringRef name_ct = CFStringCreateWithCStringNoCopy( + kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII, + kCFAllocatorNull); + m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName( + (CGFontRef)m_Font.GetPlatformFont(), name_ct); + if (name_ct) { + CFRelease(name_ct); + } + } + } + return; + } + FX_BOOL bUnicode = FALSE; + if (0 == FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE)) { + bUnicode = TRUE; + } + for (int charcode = 0; charcode < 256; charcode++) { + const FX_CHAR* name = + GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode); + if (!name) { + continue; + } + m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name); + const FX_CHAR* pStrUnicode = GlyphNameRemap(name); + if (pStrUnicode && + 0 == FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name)) { + name = pStrUnicode; + } + m_GlyphIndex[charcode] = + FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name); + CFStringRef name_ct = CFStringCreateWithCStringNoCopy( + kCFAllocatorDefault, name, kCFStringEncodingASCII, kCFAllocatorNull); + m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName( + (CGFontRef)m_Font.GetPlatformFont(), name_ct); + if (name_ct) { + CFRelease(name_ct); + } + if (m_GlyphIndex[charcode] == 0) { + if (FXSYS_strcmp(name, ".notdef") != 0 && + FXSYS_strcmp(name, "space") != 0) { + m_GlyphIndex[charcode] = FXFT_Get_Char_Index( + m_Font.GetFace(), + bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode); + FX_CHAR name_glyph[256]; + FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode], + name_glyph, 256); + name_glyph[255] = 0; + CFStringRef name_ct = CFStringCreateWithCStringNoCopy( + kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII, + kCFAllocatorNull); + m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName( + (CGFontRef)m_Font.GetPlatformFont(), name_ct); + if (name_ct) { + CFRelease(name_ct); + } + } else { + m_Encoding.m_Unicodes[charcode] = 0x20; + m_GlyphIndex[charcode] = + bUnicode ? FXFT_Get_Char_Index(m_Font.GetFace(), 0x20) : 0xffff; + FX_CHAR name_glyph[256]; + FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode], + name_glyph, 256); + name_glyph[255] = 0; + CFStringRef name_ct = CFStringCreateWithCStringNoCopy( + kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII, + kCFAllocatorNull); + m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName( + (CGFontRef)m_Font.GetPlatformFont(), name_ct); + if (name_ct) { + CFRelease(name_ct); + } + } + } + } + return; + } +#endif + if (m_Flags & PDFFONT_SYMBOLIC) { + for (int charcode = 0; charcode < 256; charcode++) { + const FX_CHAR* name = + GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode); + if (name) { + m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name); + m_GlyphIndex[charcode] = + FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name); + } else { + m_GlyphIndex[charcode] = + FXFT_Get_Char_Index(m_Font.GetFace(), charcode); + if (m_GlyphIndex[charcode]) { + FX_WCHAR unicode = + FT_UnicodeFromCharCode(PDFFONT_ENCODING_STANDARD, charcode); + if (unicode == 0) { + FX_CHAR name_glyph[256]; + FXSYS_memset(name_glyph, 0, sizeof(name_glyph)); + FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode], + name_glyph, 256); + name_glyph[255] = 0; + if (name_glyph[0] != 0) { + unicode = PDF_UnicodeFromAdobeName(name_glyph); + } + } + m_Encoding.m_Unicodes[charcode] = unicode; + } + } + } +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + if (!bCoreText) { + FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256); + } +#endif + return; + } + FX_BOOL bUnicode = FALSE; + if (0 == FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE)) { + bUnicode = TRUE; + } + for (int charcode = 0; charcode < 256; charcode++) { + const FX_CHAR* name = + GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode); + if (!name) { + continue; + } + m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name); + m_GlyphIndex[charcode] = FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name); + if (m_GlyphIndex[charcode] == 0) { + if (FXSYS_strcmp(name, ".notdef") != 0 && + FXSYS_strcmp(name, "space") != 0) { + m_GlyphIndex[charcode] = FXFT_Get_Char_Index( + m_Font.GetFace(), + bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode); + } else { + m_Encoding.m_Unicodes[charcode] = 0x20; + m_GlyphIndex[charcode] = 0xffff; + } + } + } +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + if (!bCoreText) { + FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256); + } +#endif +} + +CPDF_FontEncoding::CPDF_FontEncoding() { + FXSYS_memset(m_Unicodes, 0, sizeof(m_Unicodes)); +} + +int CPDF_FontEncoding::CharCodeFromUnicode(FX_WCHAR unicode) const { + for (int i = 0; i < 256; i++) + if (m_Unicodes[i] == unicode) { + return i; + } + return -1; +} + +CPDF_FontEncoding::CPDF_FontEncoding(int PredefinedEncoding) { + const FX_WORD* pSrc = PDF_UnicodesForPredefinedCharSet(PredefinedEncoding); + if (!pSrc) { + FXSYS_memset(m_Unicodes, 0, sizeof(m_Unicodes)); + } else { + for (int i = 0; i < 256; i++) + m_Unicodes[i] = pSrc[i]; + } +} + +FX_BOOL CPDF_FontEncoding::IsIdentical(CPDF_FontEncoding* pAnother) const { + return FXSYS_memcmp(m_Unicodes, pAnother->m_Unicodes, sizeof(m_Unicodes)) == + 0; +} + +CPDF_Object* CPDF_FontEncoding::Realize() { + int predefined = 0; + for (int cs = PDFFONT_ENCODING_WINANSI; cs < PDFFONT_ENCODING_ZAPFDINGBATS; + cs++) { + const FX_WORD* pSrc = PDF_UnicodesForPredefinedCharSet(cs); + FX_BOOL match = TRUE; + for (int i = 0; i < 256; ++i) { + if (m_Unicodes[i] != pSrc[i]) { + match = FALSE; + break; + } + } + if (match) { + predefined = cs; + break; + } + } + if (predefined) { + if (predefined == PDFFONT_ENCODING_WINANSI) { + return new CPDF_Name("WinAnsiEncoding"); + } + if (predefined == PDFFONT_ENCODING_MACROMAN) { + return new CPDF_Name("MacRomanEncoding"); + } + if (predefined == PDFFONT_ENCODING_MACEXPERT) { + return new CPDF_Name("MacExpertEncoding"); + } + return NULL; + } + const FX_WORD* pStandard = + PDF_UnicodesForPredefinedCharSet(PDFFONT_ENCODING_WINANSI); + CPDF_Array* pDiff = new CPDF_Array; + for (int i = 0; i < 256; i++) { + if (pStandard[i] == m_Unicodes[i]) { + continue; + } + pDiff->Add(new CPDF_Number(i)); + pDiff->Add(new CPDF_Name(PDF_AdobeNameFromUnicode(m_Unicodes[i]))); + } + + CPDF_Dictionary* pDict = new CPDF_Dictionary; + pDict->SetAtName("BaseEncoding", "WinAnsiEncoding"); + pDict->SetAt("Differences", pDiff); + return pDict; +} + +CPDF_TrueTypeFont::CPDF_TrueTypeFont() {} + +bool CPDF_TrueTypeFont::IsTrueTypeFont() const { + return true; +} + +const CPDF_TrueTypeFont* CPDF_TrueTypeFont::AsTrueTypeFont() const { + return this; +} + +CPDF_TrueTypeFont* CPDF_TrueTypeFont::AsTrueTypeFont() { + return this; +} + +FX_BOOL CPDF_TrueTypeFont::Load() { + return LoadCommon(); +} + +void CPDF_TrueTypeFont::LoadGlyphMap() { + if (!m_Font.GetFace()) + return; + + int baseEncoding = m_BaseEncoding; + if (m_pFontFile && m_Font.GetFace()->num_charmaps > 0 && + (baseEncoding == PDFFONT_ENCODING_MACROMAN || + baseEncoding == PDFFONT_ENCODING_WINANSI) && + (m_Flags & PDFFONT_SYMBOLIC)) { + FX_BOOL bSupportWin = FALSE; + FX_BOOL bSupportMac = FALSE; + for (int i = 0; i < FXFT_Get_Face_CharmapCount(m_Font.GetFace()); i++) { + int platform_id = FXFT_Get_Charmap_PlatformID( + FXFT_Get_Face_Charmaps(m_Font.GetFace())[i]); + if (platform_id == 0 || platform_id == 3) { + bSupportWin = TRUE; + } else if (platform_id == 0 || platform_id == 1) { + bSupportMac = TRUE; + } + } + if (baseEncoding == PDFFONT_ENCODING_WINANSI && !bSupportWin) { + baseEncoding = + bSupportMac ? PDFFONT_ENCODING_MACROMAN : PDFFONT_ENCODING_BUILTIN; + } else if (baseEncoding == PDFFONT_ENCODING_MACROMAN && !bSupportMac) { + baseEncoding = + bSupportWin ? PDFFONT_ENCODING_WINANSI : PDFFONT_ENCODING_BUILTIN; + } + } + if (((baseEncoding == PDFFONT_ENCODING_MACROMAN || + baseEncoding == PDFFONT_ENCODING_WINANSI) && + !m_pCharNames) || + (m_Flags & PDFFONT_NONSYMBOLIC)) { + if (!FXFT_Has_Glyph_Names(m_Font.GetFace()) && + (!m_Font.GetFace()->num_charmaps || !m_Font.GetFace()->charmaps)) { + int nStartChar = m_pFontDict->GetIntegerBy("FirstChar"); + if (nStartChar < 0 || nStartChar > 255) + return; + + int charcode = 0; + for (; charcode < nStartChar; charcode++) { + m_GlyphIndex[charcode] = 0; + } + FX_WORD nGlyph = charcode - nStartChar + 3; + for (; charcode < 256; charcode++, nGlyph++) { + m_GlyphIndex[charcode] = nGlyph; + } + return; + } + FX_BOOL bMSUnicode = FT_UseTTCharmap(m_Font.GetFace(), 3, 1); + FX_BOOL bMacRoman = FALSE, bMSSymbol = FALSE; + if (!bMSUnicode) { + if (m_Flags & PDFFONT_NONSYMBOLIC) { + bMacRoman = FT_UseTTCharmap(m_Font.GetFace(), 1, 0); + bMSSymbol = !bMacRoman && FT_UseTTCharmap(m_Font.GetFace(), 3, 0); + } else { + bMSSymbol = FT_UseTTCharmap(m_Font.GetFace(), 3, 0); + bMacRoman = !bMSSymbol && FT_UseTTCharmap(m_Font.GetFace(), 1, 0); + } + } + FX_BOOL bToUnicode = m_pFontDict->KeyExist("ToUnicode"); + for (int charcode = 0; charcode < 256; charcode++) { + const FX_CHAR* name = + GetAdobeCharName(baseEncoding, m_pCharNames, charcode); + if (!name) { + m_GlyphIndex[charcode] = + m_pFontFile ? FXFT_Get_Char_Index(m_Font.GetFace(), charcode) : -1; + continue; + } + m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name); + if (bMSSymbol) { + const uint8_t prefix[4] = {0x00, 0xf0, 0xf1, 0xf2}; + for (int j = 0; j < 4; j++) { + FX_WORD unicode = prefix[j] * 256 + charcode; + m_GlyphIndex[charcode] = + FXFT_Get_Char_Index(m_Font.GetFace(), unicode); + if (m_GlyphIndex[charcode]) { + break; + } + } + } else if (m_Encoding.m_Unicodes[charcode]) { + if (bMSUnicode) { + m_GlyphIndex[charcode] = FXFT_Get_Char_Index( + m_Font.GetFace(), m_Encoding.m_Unicodes[charcode]); + } else if (bMacRoman) { + FX_DWORD maccode = FT_CharCodeFromUnicode( + FXFT_ENCODING_APPLE_ROMAN, m_Encoding.m_Unicodes[charcode]); + if (!maccode) { + m_GlyphIndex[charcode] = + FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name); + } else { + m_GlyphIndex[charcode] = + FXFT_Get_Char_Index(m_Font.GetFace(), maccode); + } + } + } + if ((m_GlyphIndex[charcode] == 0 || m_GlyphIndex[charcode] == 0xffff) && + name) { + if (name[0] == '.' && FXSYS_strcmp(name, ".notdef") == 0) { + m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), 32); + } else { + m_GlyphIndex[charcode] = + FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name); + if (m_GlyphIndex[charcode] == 0) { + if (bToUnicode) { + CFX_WideString wsUnicode = UnicodeFromCharCode(charcode); + if (!wsUnicode.IsEmpty()) { + m_GlyphIndex[charcode] = + FXFT_Get_Char_Index(m_Font.GetFace(), wsUnicode[0]); + m_Encoding.m_Unicodes[charcode] = wsUnicode[0]; + } + } + if (m_GlyphIndex[charcode] == 0) { + m_GlyphIndex[charcode] = + FXFT_Get_Char_Index(m_Font.GetFace(), charcode); + } + } + } + } + } + return; + } + if (FT_UseTTCharmap(m_Font.GetFace(), 3, 0)) { + const uint8_t prefix[4] = {0x00, 0xf0, 0xf1, 0xf2}; + FX_BOOL bGotOne = FALSE; + for (int charcode = 0; charcode < 256; charcode++) { + for (int j = 0; j < 4; j++) { + FX_WORD unicode = prefix[j] * 256 + charcode; + m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), unicode); + if (m_GlyphIndex[charcode]) { + bGotOne = TRUE; + break; + } + } + } + if (bGotOne) { + if (baseEncoding != PDFFONT_ENCODING_BUILTIN) { + for (int charcode = 0; charcode < 256; charcode++) { + const FX_CHAR* name = + GetAdobeCharName(baseEncoding, m_pCharNames, charcode); + if (!name) { + continue; + } + m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name); + } + } else if (FT_UseTTCharmap(m_Font.GetFace(), 1, 0)) { + for (int charcode = 0; charcode < 256; charcode++) { + m_Encoding.m_Unicodes[charcode] = + FT_UnicodeFromCharCode(FXFT_ENCODING_APPLE_ROMAN, charcode); + } + } + return; + } + } + if (FT_UseTTCharmap(m_Font.GetFace(), 1, 0)) { + FX_BOOL bGotOne = FALSE; + for (int charcode = 0; charcode < 256; charcode++) { + m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), charcode); + m_Encoding.m_Unicodes[charcode] = + FT_UnicodeFromCharCode(FXFT_ENCODING_APPLE_ROMAN, charcode); + if (m_GlyphIndex[charcode]) { + bGotOne = TRUE; + } + } + if (m_pFontFile || bGotOne) { + return; + } + } + if (FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE) == 0) { + FX_BOOL bGotOne = FALSE; + const FX_WORD* pUnicodes = PDF_UnicodesForPredefinedCharSet(baseEncoding); + for (int charcode = 0; charcode < 256; charcode++) { + if (m_pFontFile) { + m_Encoding.m_Unicodes[charcode] = charcode; + } else { + const FX_CHAR* name = GetAdobeCharName(0, m_pCharNames, charcode); + if (name) { + m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name); + } else if (pUnicodes) { + m_Encoding.m_Unicodes[charcode] = pUnicodes[charcode]; + } + } + m_GlyphIndex[charcode] = FXFT_Get_Char_Index( + m_Font.GetFace(), m_Encoding.m_Unicodes[charcode]); + if (m_GlyphIndex[charcode]) { + bGotOne = TRUE; + } + } + if (bGotOne) { + return; + } + } + for (int charcode = 0; charcode < 256; charcode++) { + m_GlyphIndex[charcode] = charcode; + } +} + +CPDF_Type3Font::CPDF_Type3Font() + : m_pCharProcs(nullptr), + m_pPageResources(nullptr), + m_pFontResources(nullptr) { + FXSYS_memset(m_CharWidthL, 0, sizeof(m_CharWidthL)); +} + +CPDF_Type3Font::~CPDF_Type3Font() { + for (auto it : m_CacheMap) + delete it.second; +} + +bool CPDF_Type3Font::IsType3Font() const { + return true; +} + +const CPDF_Type3Font* CPDF_Type3Font::AsType3Font() const { + return this; +} + +CPDF_Type3Font* CPDF_Type3Font::AsType3Font() { + return this; +} + +FX_BOOL CPDF_Type3Font::Load() { + m_pFontResources = m_pFontDict->GetDictBy("Resources"); + CPDF_Array* pMatrix = m_pFontDict->GetArrayBy("FontMatrix"); + FX_FLOAT xscale = 1.0f, yscale = 1.0f; + if (pMatrix) { + m_FontMatrix = pMatrix->GetMatrix(); + xscale = m_FontMatrix.a; + yscale = m_FontMatrix.d; + } + CPDF_Array* pBBox = m_pFontDict->GetArrayBy("FontBBox"); + if (pBBox) { + m_FontBBox.left = (int32_t)(pBBox->GetNumberAt(0) * xscale * 1000); + m_FontBBox.bottom = (int32_t)(pBBox->GetNumberAt(1) * yscale * 1000); + m_FontBBox.right = (int32_t)(pBBox->GetNumberAt(2) * xscale * 1000); + m_FontBBox.top = (int32_t)(pBBox->GetNumberAt(3) * yscale * 1000); + } + int StartChar = m_pFontDict->GetIntegerBy("FirstChar"); + CPDF_Array* pWidthArray = m_pFontDict->GetArrayBy("Widths"); + if (pWidthArray && (StartChar >= 0 && StartChar < 256)) { + FX_DWORD count = pWidthArray->GetCount(); + if (count > 256) { + count = 256; + } + if (StartChar + count > 256) { + count = 256 - StartChar; + } + for (FX_DWORD i = 0; i < count; i++) { + m_CharWidthL[StartChar + i] = + FXSYS_round(pWidthArray->GetNumberAt(i) * xscale * 1000); + } + } + m_pCharProcs = m_pFontDict->GetDictBy("CharProcs"); + CPDF_Object* pEncoding = m_pFontDict->GetElementValue("Encoding"); + if (pEncoding) { + LoadPDFEncoding(pEncoding, m_BaseEncoding, m_pCharNames, FALSE, FALSE); + if (m_pCharNames) { + for (int i = 0; i < 256; i++) { + m_Encoding.m_Unicodes[i] = PDF_UnicodeFromAdobeName(m_pCharNames[i]); + if (m_Encoding.m_Unicodes[i] == 0) { + m_Encoding.m_Unicodes[i] = i; + } + } + } + } + return TRUE; +} + +void CPDF_Type3Font::CheckType3FontMetrics() { + CheckFontMetrics(); +} + +CPDF_Type3Char* CPDF_Type3Font::LoadChar(FX_DWORD charcode, int level) { + if (level >= _FPDF_MAX_TYPE3_FORM_LEVEL_) + return nullptr; + + auto it = m_CacheMap.find(charcode); + if (it != m_CacheMap.end()) + return it->second; + + const FX_CHAR* name = + GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode); + if (!name) + return nullptr; + + CPDF_Stream* pStream = + ToStream(m_pCharProcs ? m_pCharProcs->GetElementValue(name) : nullptr); + if (!pStream) + return nullptr; + + std::unique_ptr pNewChar(new CPDF_Type3Char(new CPDF_Form( + m_pDocument, m_pFontResources ? m_pFontResources : m_pPageResources, + pStream, nullptr))); + + // This can trigger recursion into this method. The content of |m_CacheMap| + // can change as a result. Thus after it returns, check the cache again for + // a cache hit. + pNewChar->m_pForm->ParseContent(nullptr, nullptr, pNewChar.get(), nullptr, + level + 1); + it = m_CacheMap.find(charcode); + if (it != m_CacheMap.end()) + return it->second; + + FX_FLOAT scale = m_FontMatrix.GetXUnit(); + pNewChar->m_Width = (int32_t)(pNewChar->m_Width * scale + 0.5f); + FX_RECT& rcBBox = pNewChar->m_BBox; + CFX_FloatRect char_rect( + (FX_FLOAT)rcBBox.left / 1000.0f, (FX_FLOAT)rcBBox.bottom / 1000.0f, + (FX_FLOAT)rcBBox.right / 1000.0f, (FX_FLOAT)rcBBox.top / 1000.0f); + if (rcBBox.right <= rcBBox.left || rcBBox.bottom >= rcBBox.top) + char_rect = pNewChar->m_pForm->CalcBoundingBox(); + + char_rect.Transform(&m_FontMatrix); + rcBBox.left = FXSYS_round(char_rect.left * 1000); + rcBBox.right = FXSYS_round(char_rect.right * 1000); + rcBBox.top = FXSYS_round(char_rect.top * 1000); + rcBBox.bottom = FXSYS_round(char_rect.bottom * 1000); + + ASSERT(!pdfium::ContainsKey(m_CacheMap, charcode)); + CPDF_Type3Char* pCachedChar = pNewChar.release(); + m_CacheMap[charcode] = pCachedChar; + if (pCachedChar->m_pForm->GetPageObjectList()->empty()) { + delete pCachedChar->m_pForm; + pCachedChar->m_pForm = nullptr; + } + return pCachedChar; +} + +int CPDF_Type3Font::GetCharWidthF(FX_DWORD charcode, int level) { + if (charcode >= FX_ArraySize(m_CharWidthL)) + charcode = 0; + + if (m_CharWidthL[charcode]) + return m_CharWidthL[charcode]; + + const CPDF_Type3Char* pChar = LoadChar(charcode, level); + return pChar ? pChar->m_Width : 0; +} + +FX_RECT CPDF_Type3Font::GetCharBBox(FX_DWORD charcode, int level) { + const CPDF_Type3Char* pChar = LoadChar(charcode, level); + return pChar ? pChar->m_BBox : FX_RECT(); +} + +CPDF_Type3Char::CPDF_Type3Char(CPDF_Form* pForm) + : m_pForm(pForm), m_pBitmap(nullptr), m_bColored(FALSE) {} + +CPDF_Type3Char::~CPDF_Type3Char() { + delete m_pForm; + delete m_pBitmap; +} -- cgit v1.2.3