Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/graphite/src/FeatureMap.cpp
9903 views
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 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
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
272