Home | History | Annotate | Download | only in font
      1 // Copyright 2016 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "core/fpdfapi/font/cpdf_font.h"
      8 
      9 #include <limits>
     10 #include <memory>
     11 #include <utility>
     12 #include <vector>
     13 
     14 #include "core/fpdfapi/cpdf_modulemgr.h"
     15 #include "core/fpdfapi/font/cpdf_fontencoding.h"
     16 #include "core/fpdfapi/font/cpdf_truetypefont.h"
     17 #include "core/fpdfapi/font/cpdf_type1font.h"
     18 #include "core/fpdfapi/font/cpdf_type3font.h"
     19 #include "core/fpdfapi/page/cpdf_docpagedata.h"
     20 #include "core/fpdfapi/page/cpdf_pagemodule.h"
     21 #include "core/fpdfapi/parser/cpdf_array.h"
     22 #include "core/fpdfapi/parser/cpdf_dictionary.h"
     23 #include "core/fpdfapi/parser/cpdf_document.h"
     24 #include "core/fpdfapi/parser/cpdf_name.h"
     25 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
     26 #include "core/fxcrt/fx_memory.h"
     27 #include "core/fxge/fx_freetype.h"
     28 #include "third_party/base/logging.h"
     29 #include "third_party/base/ptr_util.h"
     30 #include "third_party/base/stl_util.h"
     31 
     32 namespace {
     33 
     34 const uint8_t kChineseFontNames[][5] = {{0xCB, 0xCE, 0xCC, 0xE5, 0x00},
     35                                         {0xBF, 0xAC, 0xCC, 0xE5, 0x00},
     36                                         {0xBA, 0xDA, 0xCC, 0xE5, 0x00},
     37                                         {0xB7, 0xC2, 0xCB, 0xCE, 0x00},
     38                                         {0xD0, 0xC2, 0xCB, 0xCE, 0x00}};
     39 
     40 void GetPredefinedEncoding(const ByteString& value, int* basemap) {
     41   if (value == "WinAnsiEncoding")
     42     *basemap = PDFFONT_ENCODING_WINANSI;
     43   else if (value == "MacRomanEncoding")
     44     *basemap = PDFFONT_ENCODING_MACROMAN;
     45   else if (value == "MacExpertEncoding")
     46     *basemap = PDFFONT_ENCODING_MACEXPERT;
     47   else if (value == "PDFDocEncoding")
     48     *basemap = PDFFONT_ENCODING_PDFDOC;
     49 }
     50 
     51 }  // namespace
     52 
     53 CPDF_Font::CPDF_Font()
     54     : m_pFontFile(nullptr),
     55       m_pFontDict(nullptr),
     56       m_bToUnicodeLoaded(false),
     57       m_Flags(0),
     58       m_StemV(0),
     59       m_Ascent(0),
     60       m_Descent(0),
     61       m_ItalicAngle(0) {}
     62 
     63 CPDF_Font::~CPDF_Font() {
     64   if (m_pFontFile) {
     65     auto* pPageData = m_pDocument->GetPageData();
     66     if (pPageData) {
     67       pPageData->MaybePurgeFontFileStreamAcc(
     68           m_pFontFile->GetStream()->AsStream());
     69     }
     70   }
     71 }
     72 
     73 bool CPDF_Font::IsType1Font() const {
     74   return false;
     75 }
     76 
     77 bool CPDF_Font::IsTrueTypeFont() const {
     78   return false;
     79 }
     80 
     81 bool CPDF_Font::IsType3Font() const {
     82   return false;
     83 }
     84 
     85 bool CPDF_Font::IsCIDFont() const {
     86   return false;
     87 }
     88 
     89 const CPDF_Type1Font* CPDF_Font::AsType1Font() const {
     90   return nullptr;
     91 }
     92 
     93 CPDF_Type1Font* CPDF_Font::AsType1Font() {
     94   return nullptr;
     95 }
     96 
     97 const CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() const {
     98   return nullptr;
     99 }
    100 
    101 CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() {
    102   return nullptr;
    103 }
    104 
    105 const CPDF_Type3Font* CPDF_Font::AsType3Font() const {
    106   return nullptr;
    107 }
    108 
    109 CPDF_Type3Font* CPDF_Font::AsType3Font() {
    110   return nullptr;
    111 }
    112 
    113 const CPDF_CIDFont* CPDF_Font::AsCIDFont() const {
    114   return nullptr;
    115 }
    116 
    117 CPDF_CIDFont* CPDF_Font::AsCIDFont() {
    118   return nullptr;
    119 }
    120 
    121 bool CPDF_Font::IsUnicodeCompatible() const {
    122   return false;
    123 }
    124 
    125 int CPDF_Font::CountChar(const char* pString, int size) const {
    126   return size;
    127 }
    128 
    129 int CPDF_Font::GlyphFromCharCodeExt(uint32_t charcode) {
    130   return GlyphFromCharCode(charcode, nullptr);
    131 }
    132 
    133 bool CPDF_Font::IsVertWriting() const {
    134   const CPDF_CIDFont* pCIDFont = AsCIDFont();
    135   return pCIDFont ? pCIDFont->IsVertWriting() : m_Font.IsVertical();
    136 }
    137 
    138 int CPDF_Font::AppendChar(char* buf, uint32_t charcode) const {
    139   *buf = static_cast<char>(charcode);
    140   return 1;
    141 }
    142 
    143 void CPDF_Font::AppendChar(ByteString* str, uint32_t charcode) const {
    144   char buf[4];
    145   int len = AppendChar(buf, charcode);
    146   *str += ByteStringView(buf, len);
    147 }
    148 
    149 WideString CPDF_Font::UnicodeFromCharCode(uint32_t charcode) const {
    150   if (!m_bToUnicodeLoaded)
    151     LoadUnicodeMap();
    152 
    153   return m_pToUnicodeMap ? m_pToUnicodeMap->Lookup(charcode) : WideString();
    154 }
    155 
    156 uint32_t CPDF_Font::CharCodeFromUnicode(wchar_t unicode) const {
    157   if (!m_bToUnicodeLoaded)
    158     LoadUnicodeMap();
    159 
    160   return m_pToUnicodeMap ? m_pToUnicodeMap->ReverseLookup(unicode) : 0;
    161 }
    162 
    163 bool CPDF_Font::HasFontWidths() const {
    164   return true;
    165 }
    166 
    167 void CPDF_Font::LoadFontDescriptor(CPDF_Dictionary* pFontDesc) {
    168   m_Flags = pFontDesc->GetIntegerFor("Flags", FXFONT_NONSYMBOLIC);
    169   int ItalicAngle = 0;
    170   bool bExistItalicAngle = false;
    171   if (pFontDesc->KeyExist("ItalicAngle")) {
    172     ItalicAngle = pFontDesc->GetIntegerFor("ItalicAngle");
    173     bExistItalicAngle = true;
    174   }
    175   if (ItalicAngle < 0) {
    176     m_Flags |= FXFONT_ITALIC;
    177     m_ItalicAngle = ItalicAngle;
    178   }
    179   bool bExistStemV = false;
    180   if (pFontDesc->KeyExist("StemV")) {
    181     m_StemV = pFontDesc->GetIntegerFor("StemV");
    182     bExistStemV = true;
    183   }
    184   bool bExistAscent = false;
    185   if (pFontDesc->KeyExist("Ascent")) {
    186     m_Ascent = pFontDesc->GetIntegerFor("Ascent");
    187     bExistAscent = true;
    188   }
    189   bool bExistDescent = false;
    190   if (pFontDesc->KeyExist("Descent")) {
    191     m_Descent = pFontDesc->GetIntegerFor("Descent");
    192     bExistDescent = true;
    193   }
    194   bool bExistCapHeight = false;
    195   if (pFontDesc->KeyExist("CapHeight"))
    196     bExistCapHeight = true;
    197   if (bExistItalicAngle && bExistAscent && bExistCapHeight && bExistDescent &&
    198       bExistStemV) {
    199     m_Flags |= FXFONT_USEEXTERNATTR;
    200   }
    201   if (m_Descent > 10)
    202     m_Descent = -m_Descent;
    203   CPDF_Array* pBBox = pFontDesc->GetArrayFor("FontBBox");
    204   if (pBBox) {
    205     m_FontBBox.left = pBBox->GetIntegerAt(0);
    206     m_FontBBox.bottom = pBBox->GetIntegerAt(1);
    207     m_FontBBox.right = pBBox->GetIntegerAt(2);
    208     m_FontBBox.top = pBBox->GetIntegerAt(3);
    209   }
    210 
    211   CPDF_Stream* pFontFile = pFontDesc->GetStreamFor("FontFile");
    212   if (!pFontFile)
    213     pFontFile = pFontDesc->GetStreamFor("FontFile2");
    214   if (!pFontFile)
    215     pFontFile = pFontDesc->GetStreamFor("FontFile3");
    216   if (!pFontFile)
    217     return;
    218 
    219   m_pFontFile = m_pDocument->LoadFontFile(pFontFile);
    220   if (!m_pFontFile)
    221     return;
    222 
    223   const uint8_t* pFontData = m_pFontFile->GetData();
    224   uint32_t dwFontSize = m_pFontFile->GetSize();
    225   if (!m_Font.LoadEmbedded(pFontData, dwFontSize)) {
    226     m_pDocument->GetPageData()->MaybePurgeFontFileStreamAcc(
    227         m_pFontFile->GetStream()->AsStream());
    228     m_pFontFile = nullptr;
    229   }
    230 }
    231 
    232 void CPDF_Font::CheckFontMetrics() {
    233   if (m_FontBBox.top == 0 && m_FontBBox.bottom == 0 && m_FontBBox.left == 0 &&
    234       m_FontBBox.right == 0) {
    235     FXFT_Face face = m_Font.GetFace();
    236     if (face) {
    237       m_FontBBox.left = TT2PDF(FXFT_Get_Face_xMin(face), face);
    238       m_FontBBox.bottom = TT2PDF(FXFT_Get_Face_yMin(face), face);
    239       m_FontBBox.right = TT2PDF(FXFT_Get_Face_xMax(face), face);
    240       m_FontBBox.top = TT2PDF(FXFT_Get_Face_yMax(face), face);
    241       m_Ascent = TT2PDF(FXFT_Get_Face_Ascender(face), face);
    242       m_Descent = TT2PDF(FXFT_Get_Face_Descender(face), face);
    243     } else {
    244       bool bFirst = true;
    245       for (int i = 0; i < 256; i++) {
    246         FX_RECT rect = GetCharBBox(i);
    247         if (rect.left == rect.right) {
    248           continue;
    249         }
    250         if (bFirst) {
    251           m_FontBBox = rect;
    252           bFirst = false;
    253         } else {
    254           if (m_FontBBox.top < rect.top) {
    255             m_FontBBox.top = rect.top;
    256           }
    257           if (m_FontBBox.right < rect.right) {
    258             m_FontBBox.right = rect.right;
    259           }
    260           if (m_FontBBox.left > rect.left) {
    261             m_FontBBox.left = rect.left;
    262           }
    263           if (m_FontBBox.bottom > rect.bottom) {
    264             m_FontBBox.bottom = rect.bottom;
    265           }
    266         }
    267       }
    268     }
    269   }
    270   if (m_Ascent == 0 && m_Descent == 0) {
    271     FX_RECT rect = GetCharBBox('A');
    272     m_Ascent = rect.bottom == rect.top ? m_FontBBox.top : rect.top;
    273     rect = GetCharBBox('g');
    274     m_Descent = rect.bottom == rect.top ? m_FontBBox.bottom : rect.bottom;
    275   }
    276 }
    277 
    278 void CPDF_Font::LoadUnicodeMap() const {
    279   m_bToUnicodeLoaded = true;
    280   CPDF_Stream* pStream = m_pFontDict->GetStreamFor("ToUnicode");
    281   if (!pStream) {
    282     return;
    283   }
    284   m_pToUnicodeMap = pdfium::MakeUnique<CPDF_ToUnicodeMap>();
    285   m_pToUnicodeMap->Load(pStream);
    286 }
    287 
    288 int CPDF_Font::GetStringWidth(const char* pString, int size) {
    289   int offset = 0;
    290   int width = 0;
    291   while (offset < size) {
    292     uint32_t charcode = GetNextChar(pString, size, offset);
    293     width += GetCharWidthF(charcode);
    294   }
    295   return width;
    296 }
    297 
    298 // static
    299 CPDF_Font* CPDF_Font::GetStockFont(CPDF_Document* pDoc,
    300                                    const ByteStringView& name) {
    301   ByteString fontname(name);
    302   int font_id = PDF_GetStandardFontName(&fontname);
    303   if (font_id < 0)
    304     return nullptr;
    305 
    306   CPDF_FontGlobals* pFontGlobals =
    307       CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
    308   CPDF_Font* pFont = pFontGlobals->Find(pDoc, font_id);
    309   if (pFont)
    310     return pFont;
    311 
    312   CPDF_Dictionary* pDict = new CPDF_Dictionary(pDoc->GetByteStringPool());
    313   pDict->SetNewFor<CPDF_Name>("Type", "Font");
    314   pDict->SetNewFor<CPDF_Name>("Subtype", "Type1");
    315   pDict->SetNewFor<CPDF_Name>("BaseFont", fontname);
    316   pDict->SetNewFor<CPDF_Name>("Encoding", "WinAnsiEncoding");
    317   return pFontGlobals->Set(pDoc, font_id, CPDF_Font::Create(nullptr, pDict));
    318 }
    319 
    320 std::unique_ptr<CPDF_Font> CPDF_Font::Create(CPDF_Document* pDoc,
    321                                              CPDF_Dictionary* pFontDict) {
    322   ByteString type = pFontDict->GetStringFor("Subtype");
    323   std::unique_ptr<CPDF_Font> pFont;
    324   if (type == "TrueType") {
    325     ByteString tag = pFontDict->GetStringFor("BaseFont").Left(4);
    326     for (size_t i = 0; i < FX_ArraySize(kChineseFontNames); ++i) {
    327       if (tag == ByteString(kChineseFontNames[i], 4)) {
    328         CPDF_Dictionary* pFontDesc = pFontDict->GetDictFor("FontDescriptor");
    329         if (!pFontDesc || !pFontDesc->KeyExist("FontFile2"))
    330           pFont = pdfium::MakeUnique<CPDF_CIDFont>();
    331         break;
    332       }
    333     }
    334     if (!pFont)
    335       pFont = pdfium::MakeUnique<CPDF_TrueTypeFont>();
    336   } else if (type == "Type3") {
    337     pFont = pdfium::MakeUnique<CPDF_Type3Font>();
    338   } else if (type == "Type0") {
    339     pFont = pdfium::MakeUnique<CPDF_CIDFont>();
    340   } else {
    341     pFont = pdfium::MakeUnique<CPDF_Type1Font>();
    342   }
    343   pFont->m_pFontDict = pFontDict;
    344   pFont->m_pDocument = pDoc;
    345   pFont->m_BaseFont = pFontDict->GetStringFor("BaseFont");
    346   return pFont->Load() ? std::move(pFont) : nullptr;
    347 }
    348 
    349 uint32_t CPDF_Font::GetNextChar(const char* pString,
    350                                 int nStrLen,
    351                                 int& offset) const {
    352   if (offset < 0 || nStrLen < 1) {
    353     return 0;
    354   }
    355   uint8_t ch = offset < nStrLen ? pString[offset++] : pString[nStrLen - 1];
    356   return static_cast<uint32_t>(ch);
    357 }
    358 
    359 void CPDF_Font::LoadPDFEncoding(CPDF_Object* pEncoding,
    360                                 int& iBaseEncoding,
    361                                 std::vector<ByteString>* pCharNames,
    362                                 bool bEmbedded,
    363                                 bool bTrueType) {
    364   if (!pEncoding) {
    365     if (m_BaseFont == "Symbol") {
    366       iBaseEncoding = bTrueType ? PDFFONT_ENCODING_MS_SYMBOL
    367                                 : PDFFONT_ENCODING_ADOBE_SYMBOL;
    368     } else if (!bEmbedded && iBaseEncoding == PDFFONT_ENCODING_BUILTIN) {
    369       iBaseEncoding = PDFFONT_ENCODING_WINANSI;
    370     }
    371     return;
    372   }
    373   if (pEncoding->IsName()) {
    374     if (iBaseEncoding == PDFFONT_ENCODING_ADOBE_SYMBOL ||
    375         iBaseEncoding == PDFFONT_ENCODING_ZAPFDINGBATS) {
    376       return;
    377     }
    378     if (FontStyleIsSymbolic(m_Flags) && m_BaseFont == "Symbol") {
    379       if (!bTrueType)
    380         iBaseEncoding = PDFFONT_ENCODING_ADOBE_SYMBOL;
    381       return;
    382     }
    383     ByteString bsEncoding = pEncoding->GetString();
    384     if (bsEncoding.Compare("MacExpertEncoding") == 0) {
    385       bsEncoding = "WinAnsiEncoding";
    386     }
    387     GetPredefinedEncoding(bsEncoding, &iBaseEncoding);
    388     return;
    389   }
    390 
    391   CPDF_Dictionary* pDict = pEncoding->AsDictionary();
    392   if (!pDict)
    393     return;
    394 
    395   if (iBaseEncoding != PDFFONT_ENCODING_ADOBE_SYMBOL &&
    396       iBaseEncoding != PDFFONT_ENCODING_ZAPFDINGBATS) {
    397     ByteString bsEncoding = pDict->GetStringFor("BaseEncoding");
    398     if (bTrueType && bsEncoding.Compare("MacExpertEncoding") == 0)
    399       bsEncoding = "WinAnsiEncoding";
    400     GetPredefinedEncoding(bsEncoding, &iBaseEncoding);
    401   }
    402   if ((!bEmbedded || bTrueType) && iBaseEncoding == PDFFONT_ENCODING_BUILTIN)
    403     iBaseEncoding = PDFFONT_ENCODING_STANDARD;
    404 
    405   CPDF_Array* pDiffs = pDict->GetArrayFor("Differences");
    406   if (!pDiffs)
    407     return;
    408 
    409   pCharNames->resize(256);
    410   uint32_t cur_code = 0;
    411   for (uint32_t i = 0; i < pDiffs->GetCount(); i++) {
    412     CPDF_Object* pElement = pDiffs->GetDirectObjectAt(i);
    413     if (!pElement)
    414       continue;
    415 
    416     if (CPDF_Name* pName = pElement->AsName()) {
    417       if (cur_code < 256)
    418         (*pCharNames)[cur_code] = pName->GetString();
    419       cur_code++;
    420     } else {
    421       cur_code = pElement->GetInteger();
    422     }
    423   }
    424 }
    425 
    426 bool CPDF_Font::IsStandardFont() const {
    427   if (!IsType1Font())
    428     return false;
    429   if (m_pFontFile)
    430     return false;
    431   if (AsType1Font()->GetBase14Font() < 0)
    432     return false;
    433   return true;
    434 }
    435 
    436 const char* CPDF_Font::GetAdobeCharName(
    437     int iBaseEncoding,
    438     const std::vector<ByteString>& charnames,
    439     int charcode) {
    440   if (charcode < 0 || charcode >= 256) {
    441     NOTREACHED();
    442     return nullptr;
    443   }
    444 
    445   if (!charnames.empty() && !charnames[charcode].IsEmpty())
    446     return charnames[charcode].c_str();
    447 
    448   const char* name = nullptr;
    449   if (iBaseEncoding)
    450     name = PDF_CharNameFromPredefinedCharSet(iBaseEncoding, charcode);
    451   return name && name[0] ? name : nullptr;
    452 }
    453 
    454 uint32_t CPDF_Font::FallbackFontFromCharcode(uint32_t charcode) {
    455   if (m_FontFallbacks.empty()) {
    456     m_FontFallbacks.push_back(pdfium::MakeUnique<CFX_Font>());
    457     m_FontFallbacks[0]->LoadSubst("Arial", IsTrueTypeFont(), m_Flags,
    458                                   m_StemV * 5, m_ItalicAngle, 0,
    459                                   IsVertWriting());
    460   }
    461   return 0;
    462 }
    463 
    464 int CPDF_Font::FallbackGlyphFromCharcode(int fallbackFont, uint32_t charcode) {
    465   if (!pdfium::IndexInBounds(m_FontFallbacks, fallbackFont))
    466     return -1;
    467 
    468   WideString str = UnicodeFromCharCode(charcode);
    469   uint32_t unicode = !str.IsEmpty() ? str[0] : charcode;
    470   int glyph =
    471       FXFT_Get_Char_Index(m_FontFallbacks[fallbackFont]->GetFace(), unicode);
    472   if (glyph == 0)
    473     return -1;
    474 
    475   return glyph;
    476 }
    477 
    478 CFX_Font* CPDF_Font::GetFontFallback(int position) {
    479   if (position < 0 || static_cast<size_t>(position) >= m_FontFallbacks.size())
    480     return nullptr;
    481   return m_FontFallbacks[position].get();
    482 }
    483 
    484 // static
    485 int CPDF_Font::TT2PDF(int m, FXFT_Face face) {
    486   int upm = FXFT_Get_Face_UnitsPerEM(face);
    487   if (upm == 0)
    488     return m;
    489 
    490   return static_cast<int>(
    491       pdfium::clamp((m * 1000.0 + upm / 2) / upm,
    492                     static_cast<double>(std::numeric_limits<int>::min()),
    493                     static_cast<double>(std::numeric_limits<int>::max())));
    494 }
    495 
    496 // static
    497 bool CPDF_Font::FT_UseTTCharmap(FXFT_Face face,
    498                                 int platform_id,
    499                                 int encoding_id) {
    500   auto** pCharMap = FXFT_Get_Face_Charmaps(face);
    501   for (int i = 0; i < FXFT_Get_Face_CharmapCount(face); i++) {
    502     if (FXFT_Get_Charmap_PlatformID(pCharMap[i]) == platform_id &&
    503         FXFT_Get_Charmap_EncodingID(pCharMap[i]) == encoding_id) {
    504       FXFT_Set_Charmap(face, pCharMap[i]);
    505       return true;
    506     }
    507   }
    508   return false;
    509 }
    510