Home | History | Annotate | Download | only in font
      1 // Copyright 2014 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/font_int.h"
      8 
      9 #include <memory>
     10 #include <utility>
     11 
     12 #include "core/fpdfapi/cpdf_modulemgr.h"
     13 #include "core/fpdfapi/page/cpdf_form.h"
     14 #include "core/fpdfapi/page/cpdf_pagemodule.h"
     15 #include "core/fpdfapi/page/pageint.h"
     16 #include "core/fpdfapi/parser/cpdf_array.h"
     17 #include "core/fpdfapi/parser/cpdf_dictionary.h"
     18 #include "core/fpdfapi/parser/cpdf_document.h"
     19 #include "core/fpdfapi/parser/cpdf_name.h"
     20 #include "core/fpdfapi/parser/cpdf_number.h"
     21 #include "core/fpdfapi/parser/cpdf_simple_parser.h"
     22 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
     23 #include "core/fxcrt/fx_ext.h"
     24 #include "core/fxcrt/fx_safe_types.h"
     25 #include "core/fxge/fx_freetype.h"
     26 #include "third_party/base/numerics/safe_conversions.h"
     27 #include "third_party/base/ptr_util.h"
     28 #include "third_party/base/stl_util.h"
     29 
     30 int TT2PDF(int m, FXFT_Face face) {
     31   int upm = FXFT_Get_Face_UnitsPerEM(face);
     32   if (upm == 0)
     33     return m;
     34   return pdfium::base::checked_cast<int>(
     35       (static_cast<double>(m) * 1000 + upm / 2) / upm);
     36 }
     37 
     38 bool FT_UseTTCharmap(FXFT_Face face, int platform_id, int encoding_id) {
     39   auto* pCharMap = FXFT_Get_Face_Charmaps(face);
     40   for (int i = 0; i < FXFT_Get_Face_CharmapCount(face); i++) {
     41     if (FXFT_Get_Charmap_PlatformID(pCharMap[i]) == platform_id &&
     42         FXFT_Get_Charmap_EncodingID(pCharMap[i]) == encoding_id) {
     43       FXFT_Set_Charmap(face, pCharMap[i]);
     44       return true;
     45     }
     46   }
     47   return false;
     48 }
     49 
     50 CFX_StockFontArray::CFX_StockFontArray() {}
     51 
     52 CFX_StockFontArray::~CFX_StockFontArray() {
     53   for (size_t i = 0; i < FX_ArraySize(m_StockFonts); ++i) {
     54     if (m_StockFonts[i])
     55       delete m_StockFonts[i]->GetFontDict();
     56   }
     57 }
     58 
     59 CPDF_Font* CFX_StockFontArray::GetFont(uint32_t index) const {
     60   if (index >= FX_ArraySize(m_StockFonts))
     61     return nullptr;
     62   return m_StockFonts[index].get();
     63 }
     64 
     65 CPDF_Font* CFX_StockFontArray::SetFont(uint32_t index,
     66                                        std::unique_ptr<CPDF_Font> pFont) {
     67   CPDF_Font* result = pFont.get();
     68   if (index < FX_ArraySize(m_StockFonts))
     69     m_StockFonts[index] = std::move(pFont);
     70   return result;
     71 }
     72 
     73 CPDF_FontGlobals::CPDF_FontGlobals() {
     74   FXSYS_memset(m_EmbeddedCharsets, 0, sizeof(m_EmbeddedCharsets));
     75   FXSYS_memset(m_EmbeddedToUnicodes, 0, sizeof(m_EmbeddedToUnicodes));
     76 }
     77 
     78 CPDF_FontGlobals::~CPDF_FontGlobals() {}
     79 
     80 CPDF_Font* CPDF_FontGlobals::Find(CPDF_Document* pDoc, uint32_t index) {
     81   auto it = m_StockMap.find(pDoc);
     82   if (it == m_StockMap.end())
     83     return nullptr;
     84   return it->second ? it->second->GetFont(index) : nullptr;
     85 }
     86 
     87 CPDF_Font* CPDF_FontGlobals::Set(CPDF_Document* pDoc,
     88                                  uint32_t index,
     89                                  std::unique_ptr<CPDF_Font> pFont) {
     90   if (!pdfium::ContainsKey(m_StockMap, pDoc))
     91     m_StockMap[pDoc] = pdfium::MakeUnique<CFX_StockFontArray>();
     92   return m_StockMap[pDoc]->SetFont(index, std::move(pFont));
     93 }
     94 
     95 void CPDF_FontGlobals::Clear(CPDF_Document* pDoc) {
     96   m_StockMap.erase(pDoc);
     97 }
     98 
     99 CFX_WideString CPDF_ToUnicodeMap::Lookup(uint32_t charcode) const {
    100   auto it = m_Map.find(charcode);
    101   if (it != m_Map.end()) {
    102     uint32_t value = it->second;
    103     FX_WCHAR unicode = (FX_WCHAR)(value & 0xffff);
    104     if (unicode != 0xffff) {
    105       return unicode;
    106     }
    107     const FX_WCHAR* buf = m_MultiCharBuf.GetBuffer();
    108     uint32_t buf_len = m_MultiCharBuf.GetLength();
    109     if (!buf || buf_len == 0) {
    110       return CFX_WideString();
    111     }
    112     uint32_t index = value >> 16;
    113     if (index >= buf_len) {
    114       return CFX_WideString();
    115     }
    116     uint32_t len = buf[index];
    117     if (index + len < index || index + len >= buf_len) {
    118       return CFX_WideString();
    119     }
    120     return CFX_WideString(buf + index + 1, len);
    121   }
    122   if (m_pBaseMap) {
    123     return m_pBaseMap->UnicodeFromCID((uint16_t)charcode);
    124   }
    125   return CFX_WideString();
    126 }
    127 
    128 uint32_t CPDF_ToUnicodeMap::ReverseLookup(FX_WCHAR unicode) const {
    129   for (const auto& pair : m_Map) {
    130     if (pair.second == static_cast<uint32_t>(unicode))
    131       return pair.first;
    132   }
    133   return 0;
    134 }
    135 
    136 // Static.
    137 uint32_t CPDF_ToUnicodeMap::StringToCode(const CFX_ByteStringC& str) {
    138   int len = str.GetLength();
    139   if (len == 0)
    140     return 0;
    141 
    142   uint32_t result = 0;
    143   if (str[0] == '<') {
    144     for (int i = 1; i < len && std::isxdigit(str[i]); ++i)
    145       result = result * 16 + FXSYS_toHexDigit(str.CharAt(i));
    146     return result;
    147   }
    148 
    149   for (int i = 0; i < len && std::isdigit(str[i]); ++i)
    150     result = result * 10 + FXSYS_toDecimalDigit(str.CharAt(i));
    151 
    152   return result;
    153 }
    154 
    155 static CFX_WideString StringDataAdd(CFX_WideString str) {
    156   CFX_WideString ret;
    157   int len = str.GetLength();
    158   FX_WCHAR value = 1;
    159   for (int i = len - 1; i >= 0; --i) {
    160     FX_WCHAR ch = str[i] + value;
    161     if (ch < str[i]) {
    162       ret.Insert(0, 0);
    163     } else {
    164       ret.Insert(0, ch);
    165       value = 0;
    166     }
    167   }
    168   if (value) {
    169     ret.Insert(0, value);
    170   }
    171   return ret;
    172 }
    173 
    174 // Static.
    175 CFX_WideString CPDF_ToUnicodeMap::StringToWideString(
    176     const CFX_ByteStringC& str) {
    177   int len = str.GetLength();
    178   if (len == 0)
    179     return CFX_WideString();
    180 
    181   CFX_WideString result;
    182   if (str[0] == '<') {
    183     int byte_pos = 0;
    184     FX_WCHAR ch = 0;
    185     for (int i = 1; i < len && std::isxdigit(str[i]); ++i) {
    186       ch = ch * 16 + FXSYS_toHexDigit(str[i]);
    187       byte_pos++;
    188       if (byte_pos == 4) {
    189         result += ch;
    190         byte_pos = 0;
    191         ch = 0;
    192       }
    193     }
    194     return result;
    195   }
    196   return result;
    197 }
    198 
    199 CPDF_ToUnicodeMap::CPDF_ToUnicodeMap() : m_pBaseMap(nullptr) {}
    200 
    201 CPDF_ToUnicodeMap::~CPDF_ToUnicodeMap() {}
    202 
    203 uint32_t CPDF_ToUnicodeMap::GetUnicode() {
    204   FX_SAFE_UINT32 uni = m_MultiCharBuf.GetLength();
    205   uni = uni * 0x10000 + 0xffff;
    206   return uni.ValueOrDefault(0);
    207 }
    208 
    209 void CPDF_ToUnicodeMap::Load(CPDF_Stream* pStream) {
    210   CIDSet cid_set = CIDSET_UNKNOWN;
    211   CPDF_StreamAcc stream;
    212   stream.LoadAllData(pStream, false);
    213   CPDF_SimpleParser parser(stream.GetData(), stream.GetSize());
    214   while (1) {
    215     CFX_ByteStringC word = parser.GetWord();
    216     if (word.IsEmpty()) {
    217       break;
    218     }
    219     if (word == "beginbfchar") {
    220       while (1) {
    221         word = parser.GetWord();
    222         if (word.IsEmpty() || word == "endbfchar") {
    223           break;
    224         }
    225         uint32_t srccode = StringToCode(word);
    226         word = parser.GetWord();
    227         CFX_WideString destcode = StringToWideString(word);
    228         int len = destcode.GetLength();
    229         if (len == 0) {
    230           continue;
    231         }
    232         if (len == 1) {
    233           m_Map[srccode] = destcode.GetAt(0);
    234         } else {
    235           m_Map[srccode] = GetUnicode();
    236           m_MultiCharBuf.AppendChar(destcode.GetLength());
    237           m_MultiCharBuf << destcode;
    238         }
    239       }
    240     } else if (word == "beginbfrange") {
    241       while (1) {
    242         CFX_ByteString low, high;
    243         low = parser.GetWord();
    244         if (low.IsEmpty() || low == "endbfrange") {
    245           break;
    246         }
    247         high = parser.GetWord();
    248         uint32_t lowcode = StringToCode(low.AsStringC());
    249         uint32_t highcode =
    250             (lowcode & 0xffffff00) | (StringToCode(high.AsStringC()) & 0xff);
    251         if (highcode == (uint32_t)-1) {
    252           break;
    253         }
    254         CFX_ByteString start(parser.GetWord());
    255         if (start == "[") {
    256           for (uint32_t code = lowcode; code <= highcode; code++) {
    257             CFX_ByteString dest(parser.GetWord());
    258             CFX_WideString destcode = StringToWideString(dest.AsStringC());
    259             int len = destcode.GetLength();
    260             if (len == 0) {
    261               continue;
    262             }
    263             if (len == 1) {
    264               m_Map[code] = destcode.GetAt(0);
    265             } else {
    266               m_Map[code] = GetUnicode();
    267               m_MultiCharBuf.AppendChar(destcode.GetLength());
    268               m_MultiCharBuf << destcode;
    269             }
    270           }
    271           parser.GetWord();
    272         } else {
    273           CFX_WideString destcode = StringToWideString(start.AsStringC());
    274           int len = destcode.GetLength();
    275           uint32_t value = 0;
    276           if (len == 1) {
    277             value = StringToCode(start.AsStringC());
    278             for (uint32_t code = lowcode; code <= highcode; code++) {
    279               m_Map[code] = value++;
    280             }
    281           } else {
    282             for (uint32_t code = lowcode; code <= highcode; code++) {
    283               CFX_WideString retcode;
    284               if (code == lowcode) {
    285                 retcode = destcode;
    286               } else {
    287                 retcode = StringDataAdd(destcode);
    288               }
    289               m_Map[code] = GetUnicode();
    290               m_MultiCharBuf.AppendChar(retcode.GetLength());
    291               m_MultiCharBuf << retcode;
    292               destcode = retcode;
    293             }
    294           }
    295         }
    296       }
    297     } else if (word == "/Adobe-Korea1-UCS2") {
    298       cid_set = CIDSET_KOREA1;
    299     } else if (word == "/Adobe-Japan1-UCS2") {
    300       cid_set = CIDSET_JAPAN1;
    301     } else if (word == "/Adobe-CNS1-UCS2") {
    302       cid_set = CIDSET_CNS1;
    303     } else if (word == "/Adobe-GB1-UCS2") {
    304       cid_set = CIDSET_GB1;
    305     }
    306   }
    307   if (cid_set) {
    308     m_pBaseMap = CPDF_ModuleMgr::Get()
    309                      ->GetPageModule()
    310                      ->GetFontGlobals()
    311                      ->m_CMapManager.GetCID2UnicodeMap(cid_set, false);
    312   } else {
    313     m_pBaseMap = nullptr;
    314   }
    315 }
    316