summaryrefslogtreecommitdiff
path: root/Build/source/libs/graphite-engine/src/segment/GrFeature.cpp
blob: 7863220b80a88395c8373b8fee70e3ab105afad2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
/*--------------------------------------------------------------------*//*:Ignore this sentence.
Copyright (C) 1999, 2001 SIL International. All rights reserved.

Distributable under the terms of either the Common Public License or the
GNU Lesser General Public License, as specified in the LICENSING.txt file.

File: GrFeature.cpp
Responsibility: Sharon Correll
Last reviewed: Not yet.

Description:
    Implements the GrFeature class.
-------------------------------------------------------------------------------*//*:End Ignore*/

//:>********************************************************************************************
//:>	Include files
//:>********************************************************************************************
#include "Main.h"

#ifdef _MSC_VER
#pragma hdrstop
#endif
#undef THIS_FILE
DEFINE_THIS_FILE

//:>********************************************************************************************
//:>	Forward declarations
//:>********************************************************************************************

//:>********************************************************************************************
//:>	Local Constants and static variables
//:>********************************************************************************************

namespace gr
{

//:>********************************************************************************************
//:>	GrFeature Methods
//:>********************************************************************************************

/*----------------------------------------------------------------------------------------------
	Initialize the feature.
----------------------------------------------------------------------------------------------*/	
void GrFeature::Initialize(featid nID, int nNameId, int cfset, int nDefault)
{
	m_nID = nID;
	m_nNameId = nNameId;
	m_nDefault = nDefault;

	m_vnVal.resize(cfset);
	for (unsigned int ifset = 0; ifset < m_vnVal.size(); ifset++)
		m_vnVal[ifset] = INT_MAX;
	m_vnNameId.resize(cfset);
}

/*----------------------------------------------------------------------------------------------
	Return the feature settings.
----------------------------------------------------------------------------------------------*/
int GrFeature::Settings(int cMax, int * prgnVal)
{
	int cRet = min(cMax, signed(m_vnVal.size()));
	for (int ifset = 0; ifset < cRet; ifset++)
		prgnVal[ifset] = m_vnVal[ifset];
	return cRet;
}

/*----------------------------------------------------------------------------------------------
	Add a feature setting.
----------------------------------------------------------------------------------------------*/
void GrFeature::AddSetting(int nVal, int nNameId)
{
	Assert(nVal != INT_MAX);
	unsigned int ifset;
	for (ifset = 0; ifset < m_vnVal.size(); ifset++)
	{
		if (m_vnVal[ifset] == nVal)
			return; // already there
	}
	for (ifset = 0; ifset < m_vnVal.size(); ifset++)
	{
		if (m_vnVal[ifset] == INT_MAX)
		{
			m_vnVal[ifset] = nVal;
			m_vnNameId[ifset] = nNameId;
			return;
		}
	}
	m_vnVal.push_back(nVal);
	m_vnNameId.push_back(nNameId);
}

/*----------------------------------------------------------------------------------------------
	Return true if the given setting is valid according to the font's feature table.
----------------------------------------------------------------------------------------------*/
bool GrFeature::IsValidSetting(int nVal)
{
	for (unsigned int ifset = 0; ifset < m_vnVal.size(); ifset++)
	{
		if (m_vnVal[ifset] == nVal)
			return true;
	}
	return false;
}

/*----------------------------------------------------------------------------------------------
	Read the feature label from the name table.
----------------------------------------------------------------------------------------------*/
std::wstring GrFeature::Label(GrEngine * pgreng, int nLang)
{
	std::wstring stu = pgreng->StringFromNameTable(nLang, m_nNameId);
	if (stu == L"NoName")
		stu.erase();
	return stu;
}

/*----------------------------------------------------------------------------------------------
	Read the feature value label from the name table.
----------------------------------------------------------------------------------------------*/
std::wstring GrFeature::SettingLabel(GrEngine * pgreng, int nVal, int nLang)
{
	for (unsigned int ifset = 0; ifset < m_vnVal.size(); ifset++)
	{
		if (m_vnVal[ifset] == nVal)
		{
			std::wstring stu = pgreng->StringFromNameTable(nLang, m_vnNameId[ifset]);
			if (stu == L"NoName")
				stu.erase();
			return stu;
		}
	}
	Assert(false); // setting is not valid
	return L"";
}

/*----------------------------------------------------------------------------------------------
	Return the given setting value.
----------------------------------------------------------------------------------------------*/
int GrFeature::NthSetting(int ifset)
{
	if (ifset >= (int)m_vnVal.size())
		return -1;
	else
		return m_vnVal[ifset];
}

/*----------------------------------------------------------------------------------------------
	Read the feature value label for the given index.
----------------------------------------------------------------------------------------------*/
std::wstring GrFeature::NthSettingLabel(GrEngine * pgreng, int ifset, int nLang)
{
	std::wstring stu;

	if (ifset >= (int)m_vnVal.size())
		stu.erase();
	else
	{
        stu = pgreng->StringFromNameTable(nLang, m_vnNameId[ifset]);
		if (stu == L"NoName")
			stu.erase();
	}
	return stu;
}

/*----------------------------------------------------------------------------------------------
	Return the feature setting label.
----------------------------------------------------------------------------------------------*/
//	void GrFeature::SetSettingLabel(int nVal, std::wstring stuLabel, int nLang)
//	{
//		for (int ifset = 0; ifset < m_vfset.size(); ifset++)
//		{
//			if (m_vfset[ifset].m_nVal == nVal)
//			{
//				m_vfset[ifset].m_hmnstuLabels.Insert(nLang, stuLabel, true);
//				return;
//			}			
//		}
//		Assert(false); // setting is not valid
//	}


//:>********************************************************************************************
//:>	GrLangTable Methods
//:>********************************************************************************************

/*----------------------------------------------------------------------------------------------
	Read the languages from the font.
----------------------------------------------------------------------------------------------*/
bool GrLangTable::ReadFromFont(GrIStream * pgrstrm, int fxdVersion)
{
	GrIStream & grstrm = *pgrstrm;
	
	// number of languages
	m_clang = (size_t)grstrm.ReadUShortFromFont();

	// search constants
	m_dilangInit = grstrm.ReadUShortFromFont();
	m_cLoop = grstrm.ReadUShortFromFont();
	m_ilangStart = grstrm.ReadUShortFromFont();

	// Slurp the data into the buffers. The "+1" represents a bogus ending entry that quickly
	// gives us the size of the feature list. Note that the resulting data is all big-endian.
	int cb = (m_clang + 1) * sizeof(LangEntry);
	m_prglang = new LangEntry[m_clang + 1];
	grstrm.ReadBlockFromFont(m_prglang, cb);

	m_cbOffset0 = (lsbf)(m_prglang[0].cbOffsetBIG);

	Assert((lsbf)(m_prglang[m_clang].cFeaturesBIG) == 0); // bogus entry has no settings
	cb = (lsbf)(m_prglang[m_clang].cbOffsetBIG) - m_cbOffset0;
	Assert(cb % sizeof(FeatSet) == 0); // # of bytes fits nicely into FeatSet class
	int cfset = cb / sizeof(FeatSet);
	m_prgfset = new FeatSet[cfset];
	m_cfset = cfset;
	grstrm.ReadBlockFromFont(m_prgfset, cb);

	return true;
}

/*----------------------------------------------------------------------------------------------
	Create an empty language table to use for dumb rendering, or when there is no valid
	Sill table.
----------------------------------------------------------------------------------------------*/
void GrLangTable::CreateEmpty()
{
	m_prglang = NULL;
	m_prgfset = NULL;
	m_clang = 0;
	m_dilangInit = 0;
	m_cLoop = 0;
	m_ilangStart = 0;
}

/*----------------------------------------------------------------------------------------------
	Return information about the language with the given ID by filling in the given vectors
	with the feature ids and values. Will wipe out any data in the vectors already.
----------------------------------------------------------------------------------------------*/
void GrLangTable::LanguageFeatureSettings(isocode lgcode,
	std::vector<featid> & vnFeatId, std::vector<int> & vnValues)
{
	vnFeatId.clear();
	vnValues.clear();

	int ilang = FindIndex(lgcode);
	if (ilang == -1)
		return;	// no such language: leave vectors empty

	LangEntry * plang = m_prglang + ilang;
	int cbOffset = lsbf(plang->cbOffsetBIG) - m_cbOffset0;
	Assert(cbOffset % sizeof(FeatSet) == 0);
	byte * pbFeatSet = reinterpret_cast<byte*>(m_prgfset) + cbOffset;
	FeatSet * pfset = reinterpret_cast<FeatSet*>(pbFeatSet);
	for (int ifset = 0; ifset < lsbf(plang->cFeaturesBIG); ifset++)
	{
		vnFeatId.push_back(lsbf(pfset[ifset].featidBIG));
		vnValues.push_back(lsbf(pfset[ifset].valueBIG));
	}
}

/*----------------------------------------------------------------------------------------------
	Return the code for the language at the given index.
----------------------------------------------------------------------------------------------*/
isocode GrLangTable::LanguageCode(size_t ilang)
{
	isocode lgcodeRet;
	if (ilang > m_clang)
	{
		std::fill_n(lgcodeRet.rgch, 4, '\0');
		return lgcodeRet;
	}
	LangEntry * plang = m_prglang + ilang;
	std::copy(plang->rgchCode, plang->rgchCode + 4, lgcodeRet.rgch);
	return lgcodeRet;
}

/*----------------------------------------------------------------------------------------------
	Return the index of the language in the list.
----------------------------------------------------------------------------------------------*/
int GrLangTable::FindIndex(isocode lgcode)
{
	if (m_clang == 0)
		return -1;
#ifdef _DEBUG
	int nPowerOf2 = 1;
	while (nPowerOf2 <= signed(m_clang))
		nPowerOf2 <<= 1;
	nPowerOf2 >>= 1;
	//	Now nPowerOf2 is the max power of 2 <= m_clang
	gAssert((1 << m_cLoop) == nPowerOf2);		// m_cLoop == log2(nPowerOf2)
	gAssert(m_dilangInit == nPowerOf2);
	gAssert(m_ilangStart == m_clang - m_dilangInit);
#endif // _DEBUG

	int dilangCurr = m_dilangInit;

	int ilangCurr = m_ilangStart; // may become < 0
	while (dilangCurr > 0) 
	{
		int nTest;
		if (ilangCurr < 0)
			nTest = -1;
		else
		{
			LangEntry * plangCurr = m_prglang + ilangCurr;
			nTest = strcmp(plangCurr->rgchCode, lgcode.rgch);
		}

		if (nTest == 0)
			return ilangCurr;

		dilangCurr >>= 1;	// divide by 2
		if (nTest < 0)
			ilangCurr += dilangCurr;
		else // (nTest > 0)
			ilangCurr -= dilangCurr;
	}

	return -1;
}

} // namespace gr