1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/graphite2/src/FeatureMap.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,291 @@ 1.4 +/* GRAPHITE2 LICENSING 1.5 + 1.6 + Copyright 2010, SIL International 1.7 + All rights reserved. 1.8 + 1.9 + This library is free software; you can redistribute it and/or modify 1.10 + it under the terms of the GNU Lesser General Public License as published 1.11 + by the Free Software Foundation; either version 2.1 of License, or 1.12 + (at your option) any later version. 1.13 + 1.14 + This program is distributed in the hope that it will be useful, 1.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of 1.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.17 + Lesser General Public License for more details. 1.18 + 1.19 + You should also have received a copy of the GNU Lesser General Public 1.20 + License along with this library in the file named "LICENSE". 1.21 + If not, write to the Free Software Foundation, 51 Franklin Street, 1.22 + Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 1.23 + internet at http://www.fsf.org/licenses/lgpl.html. 1.24 + 1.25 +Alternatively, the contents of this file may be used under the terms of the 1.26 +Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public 1.27 +License, as published by the Free Software Foundation, either version 2 1.28 +of the License or (at your option) any later version. 1.29 +*/ 1.30 +#include <cstring> 1.31 + 1.32 +#include "inc/Main.h" 1.33 +#include "inc/bits.h" 1.34 +#include "inc/Endian.h" 1.35 +#include "inc/FeatureMap.h" 1.36 +#include "inc/FeatureVal.h" 1.37 +#include "graphite2/Font.h" 1.38 +#include "inc/TtfUtil.h" 1.39 +#include <cstdlib> 1.40 +#include "inc/Face.h" 1.41 + 1.42 + 1.43 +using namespace graphite2; 1.44 + 1.45 +namespace 1.46 +{ 1.47 + static int cmpNameAndFeatures(const void *ap, const void *bp) 1.48 + { 1.49 + const NameAndFeatureRef & a = *static_cast<const NameAndFeatureRef *>(ap), 1.50 + & b = *static_cast<const NameAndFeatureRef *>(bp); 1.51 + return (a < b ? -1 : (b < a ? 1 : 0)); 1.52 + } 1.53 + 1.54 + const size_t FEAT_HEADER = sizeof(uint32) + 2*sizeof(uint16) + sizeof(uint32), 1.55 + FEATURE_SIZE = sizeof(uint32) 1.56 + + 2*sizeof(uint16) 1.57 + + sizeof(uint32) 1.58 + + 2*sizeof(uint16), 1.59 + FEATURE_SETTING_SIZE = sizeof(int16) + sizeof(uint16); 1.60 + 1.61 + uint16 readFeatureSettings(const byte * p, FeatureSetting * s, size_t num_settings) 1.62 + { 1.63 + uint16 max_val = 0; 1.64 + for (FeatureSetting * const end = s + num_settings; s != end; ++s) 1.65 + { 1.66 + const int16 value = be::read<int16>(p); 1.67 + ::new (s) FeatureSetting(value, be::read<uint16>(p)); 1.68 + if (uint16(value) > max_val) max_val = value; 1.69 + } 1.70 + 1.71 + return max_val; 1.72 + } 1.73 +} 1.74 + 1.75 +FeatureRef::FeatureRef(const Face & face, 1.76 + unsigned short & bits_offset, uint32 max_val, 1.77 + uint32 name, uint16 uiName, uint16 flags, 1.78 + FeatureSetting *settings, uint16 num_set) throw() 1.79 +: m_pFace(&face), 1.80 + m_nameValues(settings), 1.81 + m_mask(mask_over_val(max_val)), 1.82 + m_max(max_val), 1.83 + m_id(name), 1.84 + m_nameid(uiName), 1.85 + m_flags(flags), 1.86 + m_numSet(num_set) 1.87 +{ 1.88 + const uint8 need_bits = bit_set_count(m_mask); 1.89 + m_index = (bits_offset + need_bits) / SIZEOF_CHUNK; 1.90 + if (m_index > bits_offset / SIZEOF_CHUNK) 1.91 + bits_offset = m_index*SIZEOF_CHUNK; 1.92 + m_bits = bits_offset % SIZEOF_CHUNK; 1.93 + bits_offset += need_bits; 1.94 + m_mask <<= m_bits; 1.95 +} 1.96 + 1.97 +FeatureRef::~FeatureRef() throw() 1.98 +{ 1.99 + free(m_nameValues); 1.100 +} 1.101 + 1.102 +bool FeatureMap::readFeats(const Face & face) 1.103 +{ 1.104 + const Face::Table feat(face, TtfUtil::Tag::Feat); 1.105 + const byte * p = feat; 1.106 + if (!p) return true; 1.107 + if (feat.size() < FEAT_HEADER) return false; 1.108 + 1.109 + const byte *const feat_start = p, 1.110 + *const feat_end = p + feat.size(); 1.111 + 1.112 + const uint32 version = be::read<uint32>(p); 1.113 + m_numFeats = be::read<uint16>(p); 1.114 + be::skip<uint16>(p); 1.115 + be::skip<uint32>(p); 1.116 + 1.117 + // Sanity checks 1.118 + if (m_numFeats == 0) return true; 1.119 + if (version < 0x00010000 || 1.120 + p + m_numFeats*FEATURE_SIZE > feat_end) 1.121 + { //defensive 1.122 + m_numFeats = 0; 1.123 + return false; 1.124 + } 1.125 + 1.126 + m_feats = new FeatureRef [m_numFeats]; 1.127 + uint16 * const defVals = gralloc<uint16>(m_numFeats); 1.128 + if (!defVals || !m_feats) return false; 1.129 + unsigned short bits = 0; //to cause overflow on first Feature 1.130 + 1.131 + for (int i = 0, ie = m_numFeats; i != ie; i++) 1.132 + { 1.133 + const uint32 label = version < 0x00020000 ? be::read<uint16>(p) : be::read<uint32>(p); 1.134 + const uint16 num_settings = be::read<uint16>(p); 1.135 + if (version >= 0x00020000) 1.136 + be::skip<uint16>(p); 1.137 + const byte * const feat_setts = feat_start + be::read<uint32>(p); 1.138 + const uint16 flags = be::read<uint16>(p), 1.139 + uiName = be::read<uint16>(p); 1.140 + 1.141 + if (feat_setts + num_settings * FEATURE_SETTING_SIZE > feat_end) 1.142 + { 1.143 + free(defVals); 1.144 + return false; 1.145 + } 1.146 + 1.147 + FeatureSetting *uiSet; 1.148 + uint32 maxVal; 1.149 + if (num_settings != 0) 1.150 + { 1.151 + uiSet = gralloc<FeatureSetting>(num_settings); 1.152 + if (!uiSet) 1.153 + { 1.154 + free(defVals); 1.155 + return false; 1.156 + } 1.157 + maxVal = readFeatureSettings(feat_setts, uiSet, num_settings); 1.158 + defVals[i] = uiSet[0].value(); 1.159 + } 1.160 + else 1.161 + { 1.162 + uiSet = 0; 1.163 + maxVal = 0xffffffff; 1.164 + defVals[i] = 0; 1.165 + } 1.166 + 1.167 + ::new (m_feats + i) FeatureRef (face, bits, maxVal, 1.168 + label, uiName, flags, 1.169 + uiSet, num_settings); 1.170 + } 1.171 + m_defaultFeatures = new Features(bits/(sizeof(uint32)*8) + 1, *this); 1.172 + m_pNamedFeats = new NameAndFeatureRef[m_numFeats]; 1.173 + if (!m_defaultFeatures || !m_pNamedFeats) 1.174 + { 1.175 + free(defVals); 1.176 + return false; 1.177 + } 1.178 + for (int i = 0; i < m_numFeats; ++i) 1.179 + { 1.180 + m_feats[i].applyValToFeature(defVals[i], *m_defaultFeatures); 1.181 + m_pNamedFeats[i] = m_feats+i; 1.182 + } 1.183 + 1.184 + free(defVals); 1.185 + 1.186 + qsort(m_pNamedFeats, m_numFeats, sizeof(NameAndFeatureRef), &cmpNameAndFeatures); 1.187 + 1.188 + return true; 1.189 +} 1.190 + 1.191 +bool SillMap::readFace(const Face & face) 1.192 +{ 1.193 + if (!m_FeatureMap.readFeats(face)) return false; 1.194 + if (!readSill(face)) return false; 1.195 + return true; 1.196 +} 1.197 + 1.198 + 1.199 +bool SillMap::readSill(const Face & face) 1.200 +{ 1.201 + const Face::Table sill(face, TtfUtil::Tag::Sill); 1.202 + const byte *p = sill; 1.203 + 1.204 + if (!p) return true; 1.205 + if (sill.size() < 12) return false; 1.206 + if (be::read<uint32>(p) != 0x00010000UL) return false; 1.207 + m_numLanguages = be::read<uint16>(p); 1.208 + m_langFeats = new LangFeaturePair[m_numLanguages]; 1.209 + if (!m_langFeats || !m_FeatureMap.m_numFeats) { m_numLanguages = 0; return true; } //defensive 1.210 + 1.211 + p += 6; // skip the fast search 1.212 + if (sill.size() < m_numLanguages * 8U + 12) return false; 1.213 + 1.214 + for (int i = 0; i < m_numLanguages; i++) 1.215 + { 1.216 + uint32 langid = be::read<uint32>(p); 1.217 + uint16 numSettings = be::read<uint16>(p); 1.218 + uint16 offset = be::read<uint16>(p); 1.219 + if (offset + 8U * numSettings > sill.size() && numSettings > 0) return false; 1.220 + Features* feats = new Features(*m_FeatureMap.m_defaultFeatures); 1.221 + if (!feats) return false; 1.222 + const byte *pLSet = sill + offset; 1.223 + 1.224 + // Apply langauge specific settings 1.225 + for (int j = 0; j < numSettings; j++) 1.226 + { 1.227 + uint32 name = be::read<uint32>(pLSet); 1.228 + uint16 val = be::read<uint16>(pLSet); 1.229 + pLSet += 2; 1.230 + const FeatureRef* pRef = m_FeatureMap.findFeatureRef(name); 1.231 + if (pRef) pRef->applyValToFeature(val, *feats); 1.232 + } 1.233 + // Add the language id feature which is always feature id 1 1.234 + const FeatureRef* pRef = m_FeatureMap.findFeatureRef(1); 1.235 + if (pRef) pRef->applyValToFeature(langid, *feats); 1.236 + 1.237 + m_langFeats[i].m_lang = langid; 1.238 + m_langFeats[i].m_pFeatures = feats; 1.239 + } 1.240 + return true; 1.241 +} 1.242 + 1.243 + 1.244 +Features* SillMap::cloneFeatures(uint32 langname/*0 means default*/) const 1.245 +{ 1.246 + if (langname) 1.247 + { 1.248 + // the number of languages in a font is usually small e.g. 8 in Doulos 1.249 + // so this loop is not very expensive 1.250 + for (uint16 i = 0; i < m_numLanguages; i++) 1.251 + { 1.252 + if (m_langFeats[i].m_lang == langname) 1.253 + return new Features(*m_langFeats[i].m_pFeatures); 1.254 + } 1.255 + } 1.256 + return new Features (*m_FeatureMap.m_defaultFeatures); 1.257 +} 1.258 + 1.259 + 1.260 + 1.261 +const FeatureRef *FeatureMap::findFeatureRef(uint32 name) const 1.262 +{ 1.263 + NameAndFeatureRef *it; 1.264 + 1.265 + for (it = m_pNamedFeats; it < m_pNamedFeats + m_numFeats; ++it) 1.266 + if (it->m_name == name) 1.267 + return it->m_pFRef; 1.268 + return NULL; 1.269 +} 1.270 + 1.271 +bool FeatureRef::applyValToFeature(uint32 val, Features & pDest) const 1.272 +{ 1.273 + if (val>maxVal() || !m_pFace) 1.274 + return false; 1.275 + if (pDest.m_pMap==NULL) 1.276 + pDest.m_pMap = &m_pFace->theSill().theFeatureMap(); 1.277 + else 1.278 + if (pDest.m_pMap!=&m_pFace->theSill().theFeatureMap()) 1.279 + return false; //incompatible 1.280 + pDest.reserve(m_index); 1.281 + pDest[m_index] &= ~m_mask; 1.282 + pDest[m_index] |= (uint32(val) << m_bits); 1.283 + return true; 1.284 +} 1.285 + 1.286 +uint32 FeatureRef::getFeatureVal(const Features& feats) const 1.287 +{ 1.288 + if (m_index < feats.size() && &m_pFace->theSill().theFeatureMap()==feats.m_pMap) 1.289 + return (feats[m_index] & m_mask) >> m_bits; 1.290 + else 1.291 + return 0; 1.292 +} 1.293 + 1.294 +