gfx/graphite2/src/NameTable.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial