Home | History | Annotate | Download | only in cmaps
      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/cmaps/cmap_int.h"
      8 
      9 #include "core/fpdfapi/cpdf_modulemgr.h"
     10 #include "core/fpdfapi/font/font_int.h"
     11 #include "core/fpdfapi/page/cpdf_pagemodule.h"
     12 
     13 extern "C" {
     14 
     15 static int compareWord(const void* p1, const void* p2) {
     16   return (*(uint16_t*)p1) - (*(uint16_t*)p2);
     17 }
     18 
     19 static int compareWordRange(const void* key, const void* element) {
     20   if (*(uint16_t*)key < *(uint16_t*)element)
     21     return -1;
     22   if (*(uint16_t*)key > ((uint16_t*)element)[1])
     23     return 1;
     24   return 0;
     25 }
     26 
     27 static int compareDWordRange(const void* p1, const void* p2) {
     28   uint32_t key = *(uint32_t*)p1;
     29   uint16_t hiword = (uint16_t)(key >> 16);
     30   uint16_t* element = (uint16_t*)p2;
     31   if (hiword < element[0])
     32     return -1;
     33   if (hiword > element[0])
     34     return 1;
     35 
     36   uint16_t loword = (uint16_t)key;
     37   if (loword < element[1])
     38     return -1;
     39   if (loword > element[2])
     40     return 1;
     41   return 0;
     42 }
     43 
     44 static int compareDWordSingle(const void* p1, const void* p2) {
     45   uint32_t key = *(uint32_t*)p1;
     46   uint32_t value = ((*(uint16_t*)p2) << 16) | ((uint16_t*)p2)[1];
     47   if (key < value)
     48     return -1;
     49   if (key > value)
     50     return 1;
     51   return 0;
     52 }
     53 
     54 };  // extern "C"
     55 
     56 void FPDFAPI_FindEmbeddedCMap(const CFX_ByteString& bsName,
     57                               int charset,
     58                               int coding,
     59                               const FXCMAP_CMap*& pMap) {
     60   pMap = nullptr;
     61   CPDF_FontGlobals* pFontGlobals =
     62       CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
     63   const FXCMAP_CMap* pCMaps =
     64       pFontGlobals->m_EmbeddedCharsets[charset].m_pMapList;
     65   for (uint32_t i = 0; i < pFontGlobals->m_EmbeddedCharsets[charset].m_Count;
     66        i++) {
     67     if (bsName == pCMaps[i].m_Name) {
     68       pMap = &pCMaps[i];
     69       break;
     70     }
     71   }
     72 }
     73 
     74 uint16_t FPDFAPI_CIDFromCharCode(const FXCMAP_CMap* pMap, uint32_t charcode) {
     75   if (charcode >> 16) {
     76     while (1) {
     77       if (pMap->m_DWordMapType == FXCMAP_CMap::Range) {
     78         uint16_t* found = static_cast<uint16_t*>(
     79             FXSYS_bsearch(&charcode, pMap->m_pDWordMap, pMap->m_DWordCount, 8,
     80                           compareDWordRange));
     81         if (found)
     82           return found[3] + (uint16_t)charcode - found[1];
     83 
     84       } else if (pMap->m_DWordMapType == FXCMAP_CMap::Single) {
     85         uint16_t* found = static_cast<uint16_t*>(
     86             FXSYS_bsearch(&charcode, pMap->m_pDWordMap, pMap->m_DWordCount, 6,
     87                           compareDWordSingle));
     88         if (found)
     89           return found[2];
     90       }
     91       if (pMap->m_UseOffset == 0)
     92         return 0;
     93 
     94       pMap = pMap + pMap->m_UseOffset;
     95     }
     96     return 0;
     97   }
     98 
     99   uint16_t code = (uint16_t)charcode;
    100   while (1) {
    101     if (!pMap->m_pWordMap)
    102       return 0;
    103     if (pMap->m_WordMapType == FXCMAP_CMap::Single) {
    104       uint16_t* found = static_cast<uint16_t*>(FXSYS_bsearch(
    105           &code, pMap->m_pWordMap, pMap->m_WordCount, 4, compareWord));
    106       if (found)
    107         return found[1];
    108 
    109     } else if (pMap->m_WordMapType == FXCMAP_CMap::Range) {
    110       uint16_t* found = static_cast<uint16_t*>(FXSYS_bsearch(
    111           &code, pMap->m_pWordMap, pMap->m_WordCount, 6, compareWordRange));
    112       if (found)
    113         return found[2] + code - found[0];
    114     }
    115     if (pMap->m_UseOffset == 0)
    116       return 0;
    117 
    118     pMap = pMap + pMap->m_UseOffset;
    119   }
    120   return 0;
    121 }
    122 
    123 uint32_t FPDFAPI_CharCodeFromCID(const FXCMAP_CMap* pMap, uint16_t cid) {
    124   // TODO(dsinclair): This should be checking both pMap->m_WordMap and
    125   // pMap->m_DWordMap. There was a second while() but it was never reached as
    126   // the first always returns. Investigate and determine how this should
    127   // really be working. (https://codereview.chromium.org/2235743003 removed the
    128   // second while loop.)
    129   while (1) {
    130     if (pMap->m_WordMapType == FXCMAP_CMap::Single) {
    131       const uint16_t* pCur = pMap->m_pWordMap;
    132       const uint16_t* pEnd = pMap->m_pWordMap + pMap->m_WordCount * 2;
    133       while (pCur < pEnd) {
    134         if (pCur[1] == cid)
    135           return pCur[0];
    136 
    137         pCur += 2;
    138       }
    139     } else if (pMap->m_WordMapType == FXCMAP_CMap::Range) {
    140       const uint16_t* pCur = pMap->m_pWordMap;
    141       const uint16_t* pEnd = pMap->m_pWordMap + pMap->m_WordCount * 3;
    142       while (pCur < pEnd) {
    143         if (cid >= pCur[2] && cid <= pCur[2] + pCur[1] - pCur[0])
    144           return pCur[0] + cid - pCur[2];
    145 
    146         pCur += 3;
    147       }
    148     }
    149     if (pMap->m_UseOffset == 0)
    150       return 0;
    151 
    152     pMap = pMap + pMap->m_UseOffset;
    153   }
    154 }
    155