Wed, 31 Dec 2014 06:09:35 +0100
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 <cstring> |
michael@0 | 28 | |
michael@0 | 29 | #include "inc/Main.h" |
michael@0 | 30 | #include "inc/bits.h" |
michael@0 | 31 | #include "inc/Endian.h" |
michael@0 | 32 | #include "inc/FeatureMap.h" |
michael@0 | 33 | #include "inc/FeatureVal.h" |
michael@0 | 34 | #include "graphite2/Font.h" |
michael@0 | 35 | #include "inc/TtfUtil.h" |
michael@0 | 36 | #include <cstdlib> |
michael@0 | 37 | #include "inc/Face.h" |
michael@0 | 38 | |
michael@0 | 39 | |
michael@0 | 40 | using namespace graphite2; |
michael@0 | 41 | |
michael@0 | 42 | namespace |
michael@0 | 43 | { |
michael@0 | 44 | static int cmpNameAndFeatures(const void *ap, const void *bp) |
michael@0 | 45 | { |
michael@0 | 46 | const NameAndFeatureRef & a = *static_cast<const NameAndFeatureRef *>(ap), |
michael@0 | 47 | & b = *static_cast<const NameAndFeatureRef *>(bp); |
michael@0 | 48 | return (a < b ? -1 : (b < a ? 1 : 0)); |
michael@0 | 49 | } |
michael@0 | 50 | |
michael@0 | 51 | const size_t FEAT_HEADER = sizeof(uint32) + 2*sizeof(uint16) + sizeof(uint32), |
michael@0 | 52 | FEATURE_SIZE = sizeof(uint32) |
michael@0 | 53 | + 2*sizeof(uint16) |
michael@0 | 54 | + sizeof(uint32) |
michael@0 | 55 | + 2*sizeof(uint16), |
michael@0 | 56 | FEATURE_SETTING_SIZE = sizeof(int16) + sizeof(uint16); |
michael@0 | 57 | |
michael@0 | 58 | uint16 readFeatureSettings(const byte * p, FeatureSetting * s, size_t num_settings) |
michael@0 | 59 | { |
michael@0 | 60 | uint16 max_val = 0; |
michael@0 | 61 | for (FeatureSetting * const end = s + num_settings; s != end; ++s) |
michael@0 | 62 | { |
michael@0 | 63 | const int16 value = be::read<int16>(p); |
michael@0 | 64 | ::new (s) FeatureSetting(value, be::read<uint16>(p)); |
michael@0 | 65 | if (uint16(value) > max_val) max_val = value; |
michael@0 | 66 | } |
michael@0 | 67 | |
michael@0 | 68 | return max_val; |
michael@0 | 69 | } |
michael@0 | 70 | } |
michael@0 | 71 | |
michael@0 | 72 | FeatureRef::FeatureRef(const Face & face, |
michael@0 | 73 | unsigned short & bits_offset, uint32 max_val, |
michael@0 | 74 | uint32 name, uint16 uiName, uint16 flags, |
michael@0 | 75 | FeatureSetting *settings, uint16 num_set) throw() |
michael@0 | 76 | : m_pFace(&face), |
michael@0 | 77 | m_nameValues(settings), |
michael@0 | 78 | m_mask(mask_over_val(max_val)), |
michael@0 | 79 | m_max(max_val), |
michael@0 | 80 | m_id(name), |
michael@0 | 81 | m_nameid(uiName), |
michael@0 | 82 | m_flags(flags), |
michael@0 | 83 | m_numSet(num_set) |
michael@0 | 84 | { |
michael@0 | 85 | const uint8 need_bits = bit_set_count(m_mask); |
michael@0 | 86 | m_index = (bits_offset + need_bits) / SIZEOF_CHUNK; |
michael@0 | 87 | if (m_index > bits_offset / SIZEOF_CHUNK) |
michael@0 | 88 | bits_offset = m_index*SIZEOF_CHUNK; |
michael@0 | 89 | m_bits = bits_offset % SIZEOF_CHUNK; |
michael@0 | 90 | bits_offset += need_bits; |
michael@0 | 91 | m_mask <<= m_bits; |
michael@0 | 92 | } |
michael@0 | 93 | |
michael@0 | 94 | FeatureRef::~FeatureRef() throw() |
michael@0 | 95 | { |
michael@0 | 96 | free(m_nameValues); |
michael@0 | 97 | } |
michael@0 | 98 | |
michael@0 | 99 | bool FeatureMap::readFeats(const Face & face) |
michael@0 | 100 | { |
michael@0 | 101 | const Face::Table feat(face, TtfUtil::Tag::Feat); |
michael@0 | 102 | const byte * p = feat; |
michael@0 | 103 | if (!p) return true; |
michael@0 | 104 | if (feat.size() < FEAT_HEADER) return false; |
michael@0 | 105 | |
michael@0 | 106 | const byte *const feat_start = p, |
michael@0 | 107 | *const feat_end = p + feat.size(); |
michael@0 | 108 | |
michael@0 | 109 | const uint32 version = be::read<uint32>(p); |
michael@0 | 110 | m_numFeats = be::read<uint16>(p); |
michael@0 | 111 | be::skip<uint16>(p); |
michael@0 | 112 | be::skip<uint32>(p); |
michael@0 | 113 | |
michael@0 | 114 | // Sanity checks |
michael@0 | 115 | if (m_numFeats == 0) return true; |
michael@0 | 116 | if (version < 0x00010000 || |
michael@0 | 117 | p + m_numFeats*FEATURE_SIZE > feat_end) |
michael@0 | 118 | { //defensive |
michael@0 | 119 | m_numFeats = 0; |
michael@0 | 120 | return false; |
michael@0 | 121 | } |
michael@0 | 122 | |
michael@0 | 123 | m_feats = new FeatureRef [m_numFeats]; |
michael@0 | 124 | uint16 * const defVals = gralloc<uint16>(m_numFeats); |
michael@0 | 125 | if (!defVals || !m_feats) return false; |
michael@0 | 126 | unsigned short bits = 0; //to cause overflow on first Feature |
michael@0 | 127 | |
michael@0 | 128 | for (int i = 0, ie = m_numFeats; i != ie; i++) |
michael@0 | 129 | { |
michael@0 | 130 | const uint32 label = version < 0x00020000 ? be::read<uint16>(p) : be::read<uint32>(p); |
michael@0 | 131 | const uint16 num_settings = be::read<uint16>(p); |
michael@0 | 132 | if (version >= 0x00020000) |
michael@0 | 133 | be::skip<uint16>(p); |
michael@0 | 134 | const byte * const feat_setts = feat_start + be::read<uint32>(p); |
michael@0 | 135 | const uint16 flags = be::read<uint16>(p), |
michael@0 | 136 | uiName = be::read<uint16>(p); |
michael@0 | 137 | |
michael@0 | 138 | if (feat_setts + num_settings * FEATURE_SETTING_SIZE > feat_end) |
michael@0 | 139 | { |
michael@0 | 140 | free(defVals); |
michael@0 | 141 | return false; |
michael@0 | 142 | } |
michael@0 | 143 | |
michael@0 | 144 | FeatureSetting *uiSet; |
michael@0 | 145 | uint32 maxVal; |
michael@0 | 146 | if (num_settings != 0) |
michael@0 | 147 | { |
michael@0 | 148 | uiSet = gralloc<FeatureSetting>(num_settings); |
michael@0 | 149 | if (!uiSet) |
michael@0 | 150 | { |
michael@0 | 151 | free(defVals); |
michael@0 | 152 | return false; |
michael@0 | 153 | } |
michael@0 | 154 | maxVal = readFeatureSettings(feat_setts, uiSet, num_settings); |
michael@0 | 155 | defVals[i] = uiSet[0].value(); |
michael@0 | 156 | } |
michael@0 | 157 | else |
michael@0 | 158 | { |
michael@0 | 159 | uiSet = 0; |
michael@0 | 160 | maxVal = 0xffffffff; |
michael@0 | 161 | defVals[i] = 0; |
michael@0 | 162 | } |
michael@0 | 163 | |
michael@0 | 164 | ::new (m_feats + i) FeatureRef (face, bits, maxVal, |
michael@0 | 165 | label, uiName, flags, |
michael@0 | 166 | uiSet, num_settings); |
michael@0 | 167 | } |
michael@0 | 168 | m_defaultFeatures = new Features(bits/(sizeof(uint32)*8) + 1, *this); |
michael@0 | 169 | m_pNamedFeats = new NameAndFeatureRef[m_numFeats]; |
michael@0 | 170 | if (!m_defaultFeatures || !m_pNamedFeats) |
michael@0 | 171 | { |
michael@0 | 172 | free(defVals); |
michael@0 | 173 | return false; |
michael@0 | 174 | } |
michael@0 | 175 | for (int i = 0; i < m_numFeats; ++i) |
michael@0 | 176 | { |
michael@0 | 177 | m_feats[i].applyValToFeature(defVals[i], *m_defaultFeatures); |
michael@0 | 178 | m_pNamedFeats[i] = m_feats+i; |
michael@0 | 179 | } |
michael@0 | 180 | |
michael@0 | 181 | free(defVals); |
michael@0 | 182 | |
michael@0 | 183 | qsort(m_pNamedFeats, m_numFeats, sizeof(NameAndFeatureRef), &cmpNameAndFeatures); |
michael@0 | 184 | |
michael@0 | 185 | return true; |
michael@0 | 186 | } |
michael@0 | 187 | |
michael@0 | 188 | bool SillMap::readFace(const Face & face) |
michael@0 | 189 | { |
michael@0 | 190 | if (!m_FeatureMap.readFeats(face)) return false; |
michael@0 | 191 | if (!readSill(face)) return false; |
michael@0 | 192 | return true; |
michael@0 | 193 | } |
michael@0 | 194 | |
michael@0 | 195 | |
michael@0 | 196 | bool SillMap::readSill(const Face & face) |
michael@0 | 197 | { |
michael@0 | 198 | const Face::Table sill(face, TtfUtil::Tag::Sill); |
michael@0 | 199 | const byte *p = sill; |
michael@0 | 200 | |
michael@0 | 201 | if (!p) return true; |
michael@0 | 202 | if (sill.size() < 12) return false; |
michael@0 | 203 | if (be::read<uint32>(p) != 0x00010000UL) return false; |
michael@0 | 204 | m_numLanguages = be::read<uint16>(p); |
michael@0 | 205 | m_langFeats = new LangFeaturePair[m_numLanguages]; |
michael@0 | 206 | if (!m_langFeats || !m_FeatureMap.m_numFeats) { m_numLanguages = 0; return true; } //defensive |
michael@0 | 207 | |
michael@0 | 208 | p += 6; // skip the fast search |
michael@0 | 209 | if (sill.size() < m_numLanguages * 8U + 12) return false; |
michael@0 | 210 | |
michael@0 | 211 | for (int i = 0; i < m_numLanguages; i++) |
michael@0 | 212 | { |
michael@0 | 213 | uint32 langid = be::read<uint32>(p); |
michael@0 | 214 | uint16 numSettings = be::read<uint16>(p); |
michael@0 | 215 | uint16 offset = be::read<uint16>(p); |
michael@0 | 216 | if (offset + 8U * numSettings > sill.size() && numSettings > 0) return false; |
michael@0 | 217 | Features* feats = new Features(*m_FeatureMap.m_defaultFeatures); |
michael@0 | 218 | if (!feats) return false; |
michael@0 | 219 | const byte *pLSet = sill + offset; |
michael@0 | 220 | |
michael@0 | 221 | // Apply langauge specific settings |
michael@0 | 222 | for (int j = 0; j < numSettings; j++) |
michael@0 | 223 | { |
michael@0 | 224 | uint32 name = be::read<uint32>(pLSet); |
michael@0 | 225 | uint16 val = be::read<uint16>(pLSet); |
michael@0 | 226 | pLSet += 2; |
michael@0 | 227 | const FeatureRef* pRef = m_FeatureMap.findFeatureRef(name); |
michael@0 | 228 | if (pRef) pRef->applyValToFeature(val, *feats); |
michael@0 | 229 | } |
michael@0 | 230 | // Add the language id feature which is always feature id 1 |
michael@0 | 231 | const FeatureRef* pRef = m_FeatureMap.findFeatureRef(1); |
michael@0 | 232 | if (pRef) pRef->applyValToFeature(langid, *feats); |
michael@0 | 233 | |
michael@0 | 234 | m_langFeats[i].m_lang = langid; |
michael@0 | 235 | m_langFeats[i].m_pFeatures = feats; |
michael@0 | 236 | } |
michael@0 | 237 | return true; |
michael@0 | 238 | } |
michael@0 | 239 | |
michael@0 | 240 | |
michael@0 | 241 | Features* SillMap::cloneFeatures(uint32 langname/*0 means default*/) const |
michael@0 | 242 | { |
michael@0 | 243 | if (langname) |
michael@0 | 244 | { |
michael@0 | 245 | // the number of languages in a font is usually small e.g. 8 in Doulos |
michael@0 | 246 | // so this loop is not very expensive |
michael@0 | 247 | for (uint16 i = 0; i < m_numLanguages; i++) |
michael@0 | 248 | { |
michael@0 | 249 | if (m_langFeats[i].m_lang == langname) |
michael@0 | 250 | return new Features(*m_langFeats[i].m_pFeatures); |
michael@0 | 251 | } |
michael@0 | 252 | } |
michael@0 | 253 | return new Features (*m_FeatureMap.m_defaultFeatures); |
michael@0 | 254 | } |
michael@0 | 255 | |
michael@0 | 256 | |
michael@0 | 257 | |
michael@0 | 258 | const FeatureRef *FeatureMap::findFeatureRef(uint32 name) const |
michael@0 | 259 | { |
michael@0 | 260 | NameAndFeatureRef *it; |
michael@0 | 261 | |
michael@0 | 262 | for (it = m_pNamedFeats; it < m_pNamedFeats + m_numFeats; ++it) |
michael@0 | 263 | if (it->m_name == name) |
michael@0 | 264 | return it->m_pFRef; |
michael@0 | 265 | return NULL; |
michael@0 | 266 | } |
michael@0 | 267 | |
michael@0 | 268 | bool FeatureRef::applyValToFeature(uint32 val, Features & pDest) const |
michael@0 | 269 | { |
michael@0 | 270 | if (val>maxVal() || !m_pFace) |
michael@0 | 271 | return false; |
michael@0 | 272 | if (pDest.m_pMap==NULL) |
michael@0 | 273 | pDest.m_pMap = &m_pFace->theSill().theFeatureMap(); |
michael@0 | 274 | else |
michael@0 | 275 | if (pDest.m_pMap!=&m_pFace->theSill().theFeatureMap()) |
michael@0 | 276 | return false; //incompatible |
michael@0 | 277 | pDest.reserve(m_index); |
michael@0 | 278 | pDest[m_index] &= ~m_mask; |
michael@0 | 279 | pDest[m_index] |= (uint32(val) << m_bits); |
michael@0 | 280 | return true; |
michael@0 | 281 | } |
michael@0 | 282 | |
michael@0 | 283 | uint32 FeatureRef::getFeatureVal(const Features& feats) const |
michael@0 | 284 | { |
michael@0 | 285 | if (m_index < feats.size() && &m_pFace->theSill().theFeatureMap()==feats.m_pMap) |
michael@0 | 286 | return (feats[m_index] & m_mask) >> m_bits; |
michael@0 | 287 | else |
michael@0 | 288 | return 0; |
michael@0 | 289 | } |
michael@0 | 290 | |
michael@0 | 291 |