summaryrefslogtreecommitdiff
path: root/core/fpdfapi/fpdf_font/fpdf_font.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/fpdfapi/fpdf_font/fpdf_font.cpp')
-rw-r--r--core/fpdfapi/fpdf_font/fpdf_font.cpp1814
1 files changed, 1814 insertions, 0 deletions
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<CPDF_Stream*>(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<CPDF_Stream*>(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<FX_DWORD>(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<CPDF_Type3Char> 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;
+}