diff options
Diffstat (limited to 'core/fpdfapi/fpdf_font/cpdf_font.cpp')
-rw-r--r-- | core/fpdfapi/fpdf_font/cpdf_font.cpp | 492 |
1 files changed, 492 insertions, 0 deletions
diff --git a/core/fpdfapi/fpdf_font/cpdf_font.cpp b/core/fpdfapi/fpdf_font/cpdf_font.cpp new file mode 100644 index 0000000000..bb63966161 --- /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; +} |