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
17using namespace graphite2;
18
19namespace
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 FEAT_HEADER = 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
49FeatureRef::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
71FeatureRef::~FeatureRef() throw()
72{
73 free(m_nameValues);
74}
75
76bool 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
167bool 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
175bool 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
220Features* 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
237const 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
247bool 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
263uint32 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