tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

NameTable.cpp (8392B)


      1 /*  GRAPHITE2 LICENSING
      2 
      3    Copyright 2010, SIL International
      4    All rights reserved.
      5 
      6    This library is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU Lesser General Public License as published
      8    by the Free Software Foundation; either version 2.1 of License, or
      9    (at your option) any later version.
     10 
     11    This program is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14    Lesser General Public License for more details.
     15 
     16    You should also have received a copy of the GNU Lesser General Public
     17    License along with this library in the file named "LICENSE".
     18    If not, write to the Free Software Foundation, 51 Franklin Street,
     19    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
     20    internet at http://www.fsf.org/licenses/lgpl.html.
     21 
     22 Alternatively, the contents of this file may be used under the terms of the
     23 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
     24 License, as published by the Free Software Foundation, either version 2
     25 of the License or (at your option) any later version.
     26 */
     27 #include "inc/Main.h"
     28 #include "inc/Endian.h"
     29 
     30 #include "inc/NameTable.h"
     31 #include "inc/UtfCodec.h"
     32 
     33 using namespace graphite2;
     34 
     35 NameTable::NameTable(const void* data, size_t length, uint16 platformId, uint16 encodingID)
     36 : m_platformId(0), m_encodingId(0), m_languageCount(0),
     37   m_platformOffset(0), m_platformLastRecord(0), m_nameDataLength(0),
     38   m_table(0), m_nameData(NULL)
     39 {
     40    void *pdata = gralloc<byte>(length);
     41    if (!pdata) return;
     42    memcpy(pdata, data, length);
     43    m_table = reinterpret_cast<const TtfUtil::Sfnt::FontNames*>(pdata);
     44 
     45    if ((length > sizeof(TtfUtil::Sfnt::FontNames)) &&
     46        (length > sizeof(TtfUtil::Sfnt::FontNames) +
     47         sizeof(TtfUtil::Sfnt::NameRecord) * ( be::swap<uint16>(m_table->count) - 1)))
     48    {
     49        uint16 offset = be::swap<uint16>(m_table->string_offset);
     50        if (offset < length)
     51        {
     52            m_nameData = reinterpret_cast<const uint8*>(pdata) + offset;
     53            setPlatformEncoding(platformId, encodingID);
     54            m_nameDataLength = uint16(length - offset);
     55            return;
     56        }
     57    }
     58    free(const_cast<TtfUtil::Sfnt::FontNames*>(m_table));
     59    m_table = NULL;
     60 }
     61 
     62 uint16 NameTable::setPlatformEncoding(uint16 platformId, uint16 encodingID)
     63 {
     64    if (!m_nameData) return 0;
     65    uint16 i = 0;
     66    uint16 count = be::swap<uint16>(m_table->count);
     67    for (; i < count; i++)
     68    {
     69        if (be::swap<uint16>(m_table->name_record[i].platform_id) == platformId &&
     70            be::swap<uint16>(m_table->name_record[i].platform_specific_id) == encodingID)
     71        {
     72            m_platformOffset = i;
     73            break;
     74        }
     75    }
     76    while ((++i < count) &&
     77           (be::swap<uint16>(m_table->name_record[i].platform_id) == platformId) &&
     78           (be::swap<uint16>(m_table->name_record[i].platform_specific_id) == encodingID))
     79    {
     80        m_platformLastRecord = i;
     81    }
     82    m_encodingId = encodingID;
     83    m_platformId = platformId;
     84    return 0;
     85 }
     86 
     87 void* NameTable::getName(uint16& languageId, uint16 nameId, gr_encform enc, uint32& length)
     88 {
     89    uint16 anyLang = 0;
     90    uint16 enUSLang = 0;
     91    uint16 bestLang = 0;
     92    if (!m_table)
     93    {
     94        languageId = 0;
     95        length = 0;
     96        return NULL;
     97    }
     98    for (uint16 i = m_platformOffset; i <= m_platformLastRecord; i++)
     99    {
    100        if (be::swap<uint16>(m_table->name_record[i].name_id) == nameId)
    101        {
    102            uint16 langId = be::swap<uint16>(m_table->name_record[i].language_id);
    103            if (langId == languageId)
    104            {
    105                bestLang = i;
    106                break;
    107            }
    108            // MS language tags have the language in the lower byte, region in the higher
    109            else if ((langId & 0xFF) == (languageId & 0xFF))
    110            {
    111                bestLang = i;
    112            }
    113            else if (langId == 0x409)
    114            {
    115                enUSLang = i;
    116            }
    117            else
    118            {
    119                anyLang = i;
    120            }
    121        }
    122    }
    123    if (!bestLang)
    124    {
    125        if (enUSLang) bestLang = enUSLang;
    126        else
    127        {
    128            bestLang = anyLang;
    129            if (!anyLang)
    130            {
    131                languageId = 0;
    132                length = 0;
    133                return NULL;
    134            }
    135        }
    136    }
    137    const TtfUtil::Sfnt::NameRecord & nameRecord = m_table->name_record[bestLang];
    138    languageId = be::swap<uint16>(nameRecord.language_id);
    139    uint16 utf16Length = be::swap<uint16>(nameRecord.length);
    140    uint16 offset = be::swap<uint16>(nameRecord.offset);
    141    if(offset + utf16Length > m_nameDataLength)
    142    {
    143        languageId = 0;
    144        length = 0;
    145        return NULL;
    146    }
    147    utf16Length >>= 1; // in utf16 units
    148    utf16::codeunit_t * utf16Name = gralloc<utf16::codeunit_t>(utf16Length + 1);
    149    if (!utf16Name)
    150    {
    151        languageId = 0;
    152        length = 0;
    153        return NULL;
    154    }
    155    const uint8* pName = m_nameData + offset;
    156    for (size_t i = 0; i < utf16Length; i++)
    157    {
    158        utf16Name[i] = be::read<uint16>(pName);
    159    }
    160    utf16Name[utf16Length] = 0;
    161    if (!utf16::validate(utf16Name, utf16Name + utf16Length))
    162    {
    163        free(utf16Name);
    164        languageId = 0;
    165        length = 0;
    166        return NULL;
    167    }
    168    switch (enc)
    169    {
    170    case gr_utf8:
    171    {
    172        utf8::codeunit_t* uniBuffer = gralloc<utf8::codeunit_t>(3 * utf16Length + 1);
    173        if (!uniBuffer)
    174        {
    175            free(utf16Name);
    176            languageId = 0;
    177            length = 0;
    178            return NULL;
    179        }
    180        utf8::iterator d = uniBuffer;
    181        for (utf16::const_iterator s = utf16Name, e = utf16Name + utf16Length; s != e; ++s, ++d)
    182            *d = *s;
    183        length = uint32(d - uniBuffer);
    184        uniBuffer[length] = 0;
    185        free(utf16Name);
    186        return uniBuffer;
    187    }
    188    case gr_utf16:
    189        length = utf16Length;
    190        return utf16Name;
    191    case gr_utf32:
    192    {
    193        utf32::codeunit_t * uniBuffer = gralloc<utf32::codeunit_t>(utf16Length  + 1);
    194        if (!uniBuffer)
    195        {
    196            free(utf16Name);
    197            languageId = 0;
    198            length = 0;
    199            return NULL;
    200        }
    201        utf32::iterator d = uniBuffer;
    202        for (utf16::const_iterator s = utf16Name, e = utf16Name + utf16Length; s != e; ++s, ++d)
    203            *d = *s;
    204        length = uint32(d - uniBuffer);
    205        uniBuffer[length] = 0;
    206        free(utf16Name);
    207        return uniBuffer;
    208    }
    209    }
    210    free(utf16Name);
    211    languageId = 0;
    212    length = 0;
    213    return NULL;
    214 }
    215 
    216 uint16 NameTable::getLanguageId(const char * bcp47Locale)
    217 {
    218    size_t localeLength = strlen(bcp47Locale);
    219    uint16 localeId = m_locale2Lang.getMsId(bcp47Locale);
    220    if (m_table && (be::swap<uint16>(m_table->format) == 1))
    221    {
    222        const uint8 * pLangEntries = reinterpret_cast<const uint8*>(m_table) +
    223            sizeof(TtfUtil::Sfnt::FontNames)
    224            + sizeof(TtfUtil::Sfnt::NameRecord) * ( be::swap<uint16>(m_table->count) - 1);
    225        uint16 numLangEntries = be::read<uint16>(pLangEntries);
    226        const TtfUtil::Sfnt::LangTagRecord * langTag =
    227            reinterpret_cast<const TtfUtil::Sfnt::LangTagRecord*>(pLangEntries);
    228        if (pLangEntries + numLangEntries * sizeof(TtfUtil::Sfnt::LangTagRecord) <= m_nameData)
    229        {
    230            for (uint16 i = 0; i < numLangEntries; i++)
    231            {
    232                uint16 offset = be::swap<uint16>(langTag[i].offset);
    233                uint16 length = be::swap<uint16>(langTag[i].length);
    234                if ((offset + length <= m_nameDataLength) && (length == 2 * localeLength))
    235                {
    236                    const uint8* pName = m_nameData + offset;
    237                    bool match = true;
    238                    for (size_t j = 0; j < localeLength; j++)
    239                    {
    240                        uint16 code = be::read<uint16>(pName);
    241                        if ((code > 0x7F) || (code != bcp47Locale[j]))
    242                        {
    243                            match = false;
    244                            break;
    245                        }
    246                    }
    247                    if (match)
    248                        return 0x8000 + i;
    249                }
    250            }
    251        }
    252    }
    253    return localeId;
    254 }