summaryrefslogtreecommitdiff
path: root/core/fpdfapi/fpdf_font/cpdf_font.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/fpdfapi/fpdf_font/cpdf_font.cpp')
-rw-r--r--core/fpdfapi/fpdf_font/cpdf_font.cpp492
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;
+}