Index: core/fpdfapi/fpdf_font/cpdf_font.cpp |
diff --git a/core/fpdfapi/fpdf_font/cpdf_font.cpp b/core/fpdfapi/fpdf_font/cpdf_font.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..bb63966161cdbf244d53b6a4507be4ec08abb49d |
--- /dev/null |
+++ b/core/fpdfapi/fpdf_font/cpdf_font.cpp |
@@ -0,0 +1,492 @@ |
+// Copyright 2016 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/include/cpdf_font.h" |
+ |
+#include "core/fpdfapi/fpdf_font/cpdf_truetypefont.h" |
+#include "core/fpdfapi/fpdf_font/cpdf_type1font.h" |
+#include "core/fpdfapi/fpdf_font/cpdf_type3font.h" |
+#include "core/fpdfapi/fpdf_font/font_int.h" |
+#include "core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h" |
+#include "core/fpdfapi/fpdf_page/pageint.h" |
+#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" |
+#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" |
+#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" |
+#include "core/fpdfapi/fpdf_parser/include/cpdf_name.h" |
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h" |
+#include "core/fpdfapi/include/cpdf_modulemgr.h" |
+#include "core/include/fxge/fx_freetype.h" |
+ |
+namespace { |
+ |
+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; |
+} |
+ |
+} // namespace |
+ |
+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; |
+ } |
+} |
+ |
+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; |
+} |
+ |
+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; |
+} |
+ |
+const FX_CHAR* CPDF_Font::GetAdobeCharName(int iBaseEncoding, |
+ const CFX_ByteString* pCharNames, |
+ int charcode) { |
+ ASSERT(charcode >= 0 && charcode < 256); |
+ if (charcode < 0 || charcode >= 256) |
+ return nullptr; |
+ |
+ const FX_CHAR* name = nullptr; |
+ if (pCharNames) |
+ name = pCharNames[charcode]; |
+ if ((!name || name[0] == 0) && iBaseEncoding) |
+ name = PDF_CharNameFromPredefinedCharSet(iBaseEncoding, charcode); |
+ return name && name[0] ? name : nullptr; |
+} |