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