Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/font/layout/ContextualSubstSubtables.cpp
38918 views
1
/*
2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3
*
4
* This code is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 2 only, as
6
* published by the Free Software Foundation. Oracle designates this
7
* particular file as subject to the "Classpath" exception as provided
8
* by Oracle in the LICENSE file that accompanied this code.
9
*
10
* This code is distributed in the hope that it will be useful, but WITHOUT
11
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13
* version 2 for more details (a copy is included in the LICENSE file that
14
* accompanied this code).
15
*
16
* You should have received a copy of the GNU General Public License version
17
* 2 along with this work; if not, write to the Free Software Foundation,
18
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
*
20
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21
* or visit www.oracle.com if you need additional information or have any
22
* questions.
23
*
24
*/
25
26
/*
27
* (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved
28
*
29
*/
30
31
#include "LETypes.h"
32
#include "LEFontInstance.h"
33
#include "OpenTypeTables.h"
34
#include "GlyphSubstitutionTables.h"
35
#include "ContextualSubstSubtables.h"
36
#include "GlyphIterator.h"
37
#include "LookupProcessor.h"
38
#include "CoverageTables.h"
39
#include "LESwaps.h"
40
41
U_NAMESPACE_BEGIN
42
43
/*
44
NOTE: This could be optimized somewhat by keeping track
45
of the previous sequenceIndex in the loop and doing next()
46
or prev() of the delta between that and the current
47
sequenceIndex instead of always resetting to the front.
48
*/
49
void ContextualSubstitutionBase::applySubstitutionLookups(
50
const LookupProcessor *lookupProcessor,
51
const LEReferenceToArrayOf<SubstitutionLookupRecord>& substLookupRecordArray,
52
le_uint16 substCount,
53
GlyphIterator *glyphIterator,
54
const LEFontInstance *fontInstance,
55
le_int32 position,
56
LEErrorCode& success)
57
{
58
if (LE_FAILURE(success)) {
59
return;
60
}
61
62
GlyphIterator tempIterator(*glyphIterator);
63
const SubstitutionLookupRecord *substLookupRecordArrayPtr = substLookupRecordArray.getAlias(); // OK to dereference, range checked against substCount below.
64
65
for (le_int16 subst = 0; subst < substCount && LE_SUCCESS(success); subst += 1) {
66
le_uint16 sequenceIndex = SWAPW(substLookupRecordArrayPtr[subst].sequenceIndex);
67
le_uint16 lookupListIndex = SWAPW(substLookupRecordArrayPtr[subst].lookupListIndex);
68
69
tempIterator.setCurrStreamPosition(position);
70
if (!tempIterator.next(sequenceIndex)) {
71
success = LE_INTERNAL_ERROR;
72
return;
73
}
74
75
lookupProcessor->applySingleLookup(lookupListIndex, &tempIterator, fontInstance, success);
76
}
77
}
78
79
le_bool ContextualSubstitutionBase::matchGlyphIDs(const LEReferenceToArrayOf<TTGlyphID>& glyphArray, le_uint16 glyphCount,
80
GlyphIterator *glyphIterator, le_bool backtrack)
81
{
82
le_int32 direction = 1;
83
le_int32 match = 0;
84
85
if (backtrack) {
86
match = glyphCount -1;
87
direction = -1;
88
}
89
90
while (glyphCount > 0) {
91
if (! glyphIterator->next()) {
92
return FALSE;
93
}
94
95
TTGlyphID glyph = (TTGlyphID) glyphIterator->getCurrGlyphID();
96
97
if (glyph != SWAPW(glyphArray[match])) {
98
return FALSE;
99
}
100
101
glyphCount -= 1;
102
match += direction;
103
}
104
105
return TRUE;
106
}
107
108
le_bool ContextualSubstitutionBase::matchGlyphClasses(
109
const LEReferenceToArrayOf<le_uint16> &classArray,
110
le_uint16 glyphCount,
111
GlyphIterator *glyphIterator,
112
const LEReferenceTo<ClassDefinitionTable> &classDefinitionTable,
113
LEErrorCode &success,
114
le_bool backtrack)
115
{
116
if (LE_FAILURE(success)) { return FALSE; }
117
118
le_int32 direction = 1;
119
le_int32 match = 0;
120
121
if (backtrack) {
122
match = glyphCount - 1;
123
direction = -1;
124
}
125
126
while (glyphCount > 0) {
127
if (! glyphIterator->next()) {
128
return FALSE;
129
}
130
131
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
132
le_int32 glyphClass = classDefinitionTable->getGlyphClass(classDefinitionTable, glyph, success);
133
le_int32 matchClass = SWAPW(classArray[match]);
134
135
if (glyphClass != matchClass) {
136
// Some fonts, e.g. Traditional Arabic, have classes
137
// in the class array which aren't in the class definition
138
// table. If we're looking for such a class, pretend that
139
// we found it.
140
if (classDefinitionTable->hasGlyphClass(classDefinitionTable, matchClass, success)) {
141
return FALSE;
142
}
143
}
144
145
glyphCount -= 1;
146
match += direction;
147
}
148
149
return TRUE;
150
}
151
152
le_bool ContextualSubstitutionBase::matchGlyphCoverages(const LEReferenceToArrayOf<Offset> &coverageTableOffsetArray, le_uint16 glyphCount,
153
GlyphIterator *glyphIterator, const LETableReference &offsetBase, LEErrorCode &success, le_bool backtrack)
154
{
155
le_int32 direction = 1;
156
le_int32 glyph = 0;
157
158
if (backtrack) {
159
glyph = glyphCount - 1;
160
direction = -1;
161
}
162
163
while (glyphCount > 0) {
164
Offset coverageTableOffset = SWAPW(coverageTableOffsetArray[glyph]);
165
LEReferenceTo<CoverageTable> coverageTable(offsetBase, success, coverageTableOffset);
166
167
if (LE_FAILURE(success) || ! glyphIterator->next()) {
168
return FALSE;
169
}
170
171
if (coverageTable->getGlyphCoverage(coverageTable,
172
(LEGlyphID) glyphIterator->getCurrGlyphID(),
173
success) < 0) {
174
return FALSE;
175
}
176
177
glyphCount -= 1;
178
glyph += direction;
179
}
180
181
return TRUE;
182
}
183
184
le_uint32 ContextualSubstitutionSubtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
185
GlyphIterator *glyphIterator,
186
const LEFontInstance *fontInstance,
187
LEErrorCode& success) const
188
{
189
if (LE_FAILURE(success)) {
190
return 0;
191
}
192
193
switch(SWAPW(subtableFormat))
194
{
195
case 0:
196
return 0;
197
198
case 1:
199
{
200
LEReferenceTo<ContextualSubstitutionFormat1Subtable> subtable(base, success, (const ContextualSubstitutionFormat1Subtable *) this);
201
if( LE_FAILURE(success) ) {
202
return 0;
203
}
204
return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
205
}
206
207
case 2:
208
{
209
LEReferenceTo<ContextualSubstitutionFormat2Subtable> subtable(base, success, (const ContextualSubstitutionFormat2Subtable *) this);
210
if( LE_FAILURE(success) ) {
211
return 0;
212
}
213
return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
214
}
215
216
case 3:
217
{
218
LEReferenceTo<ContextualSubstitutionFormat3Subtable> subtable(base, success, (const ContextualSubstitutionFormat3Subtable *) this);
219
if( LE_FAILURE(success) ) {
220
return 0;
221
}
222
return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
223
}
224
225
default:
226
return 0;
227
}
228
}
229
230
le_uint32 ContextualSubstitutionFormat1Subtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
231
GlyphIterator *glyphIterator,
232
const LEFontInstance *fontInstance,
233
LEErrorCode& success) const
234
{
235
if (LE_FAILURE(success)) {
236
return 0;
237
}
238
239
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
240
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
241
if (LE_FAILURE(success)) {
242
return 0;
243
}
244
245
if (coverageIndex >= 0) {
246
le_uint16 srSetCount = SWAPW(subRuleSetCount);
247
248
if (coverageIndex < srSetCount) {
249
LEReferenceToArrayOf<Offset>
250
subRuleSetTableOffsetArrayRef(base, success, subRuleSetTableOffsetArray, srSetCount);
251
if (LE_FAILURE(success)) {
252
return 0;
253
}
254
Offset subRuleSetTableOffset = SWAPW(subRuleSetTableOffsetArray[coverageIndex]);
255
LEReferenceTo<SubRuleSetTable> subRuleSetTable(base, success, subRuleSetTableOffset);
256
if (LE_FAILURE(success)) { return 0; }
257
le_uint16 subRuleCount = SWAPW(subRuleSetTable->subRuleCount);
258
le_int32 position = glyphIterator->getCurrStreamPosition();
259
260
LEReferenceToArrayOf<Offset> subRuleTableOffsetArrayRef(base, success,
261
subRuleSetTable->subRuleTableOffsetArray, subRuleCount);
262
if (LE_FAILURE(success)) {
263
return 0;
264
}
265
for (le_uint16 subRule = 0; subRule < subRuleCount; subRule += 1) {
266
Offset subRuleTableOffset =
267
SWAPW(subRuleSetTable->subRuleTableOffsetArray[subRule]);
268
LEReferenceTo<SubRuleTable>
269
subRuleTable(subRuleSetTable, success, subRuleTableOffset);
270
if (LE_FAILURE(success)) { return 0; }
271
le_uint16 matchCount = SWAPW(subRuleTable->glyphCount) - 1;
272
le_uint16 substCount = SWAPW(subRuleTable->substCount);
273
LEReferenceToArrayOf<TTGlyphID> inputGlyphArray(base, success, subRuleTable->inputGlyphArray, matchCount+2);
274
if (LE_FAILURE(success)) { return 0; }
275
if (matchGlyphIDs(inputGlyphArray, matchCount, glyphIterator)) {
276
LEReferenceToArrayOf<SubstitutionLookupRecord>
277
substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &subRuleTable->inputGlyphArray[matchCount], substCount);
278
279
applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
280
281
return matchCount + 1;
282
}
283
284
glyphIterator->setCurrStreamPosition(position);
285
}
286
}
287
288
// XXX If we get here, the table is mal-formed...
289
}
290
291
return 0;
292
}
293
294
le_uint32 ContextualSubstitutionFormat2Subtable::process(const LETableReference &base,
295
const LookupProcessor *lookupProcessor,
296
GlyphIterator *glyphIterator,
297
const LEFontInstance *fontInstance,
298
LEErrorCode& success) const
299
{
300
if (LE_FAILURE(success)) {
301
return 0;
302
}
303
304
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
305
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
306
if (LE_FAILURE(success)) {
307
return 0;
308
}
309
310
if (coverageIndex >= 0) {
311
LEReferenceTo<ClassDefinitionTable> classDefinitionTable(base, success, SWAPW(classDefTableOffset));
312
if (LE_FAILURE(success)) { return 0; }
313
le_uint16 scSetCount = SWAPW(subClassSetCount);
314
le_int32 setClass = classDefinitionTable->getGlyphClass(classDefinitionTable,
315
glyphIterator->getCurrGlyphID(),
316
success);
317
318
if (setClass < scSetCount) {
319
LEReferenceToArrayOf<Offset>
320
subClassSetTableOffsetArrayRef(base, success, subClassSetTableOffsetArray, scSetCount);
321
if (LE_FAILURE(success)) { return 0; }
322
if (subClassSetTableOffsetArray[setClass] != 0) {
323
324
Offset subClassSetTableOffset = SWAPW(subClassSetTableOffsetArray[setClass]);
325
LEReferenceTo<SubClassSetTable> subClassSetTable(base, success, subClassSetTableOffset);
326
if (LE_FAILURE(success)) { return 0; }
327
le_uint16 subClassRuleCount = SWAPW(subClassSetTable->subClassRuleCount);
328
le_int32 position = glyphIterator->getCurrStreamPosition();
329
LEReferenceToArrayOf<Offset>
330
subClassRuleTableOffsetArrayRef(base, success, subClassSetTable->subClassRuleTableOffsetArray, subClassRuleCount);
331
if (LE_FAILURE(success)) {
332
return 0;
333
}
334
for (le_uint16 scRule = 0; scRule < subClassRuleCount; scRule += 1) {
335
Offset subClassRuleTableOffset =
336
SWAPW(subClassSetTable->subClassRuleTableOffsetArray[scRule]);
337
LEReferenceTo<SubClassRuleTable>
338
subClassRuleTable(subClassSetTable, success, subClassRuleTableOffset);
339
if (LE_FAILURE(success)) { return 0; }
340
le_uint16 matchCount = SWAPW(subClassRuleTable->glyphCount) - 1;
341
le_uint16 substCount = SWAPW(subClassRuleTable->substCount);
342
343
LEReferenceToArrayOf<le_uint16> classArray(base, success, subClassRuleTable->classArray, matchCount+1);
344
345
if (LE_FAILURE(success)) { return 0; }
346
if (matchGlyphClasses(classArray, matchCount, glyphIterator, classDefinitionTable, success)) {
347
LEReferenceToArrayOf<SubstitutionLookupRecord>
348
substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &subClassRuleTable->classArray[matchCount], substCount);
349
350
applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
351
352
return matchCount + 1;
353
}
354
355
glyphIterator->setCurrStreamPosition(position);
356
}
357
}
358
}
359
360
// XXX If we get here, the table is mal-formed...
361
}
362
363
return 0;
364
}
365
366
le_uint32 ContextualSubstitutionFormat3Subtable::process(const LETableReference &base,
367
const LookupProcessor *lookupProcessor,
368
GlyphIterator *glyphIterator,
369
const LEFontInstance *fontInstance,
370
LEErrorCode& success)const
371
{
372
if (LE_FAILURE(success)) {
373
return 0;
374
}
375
376
le_uint16 gCount = SWAPW(glyphCount);
377
le_uint16 subCount = SWAPW(substCount);
378
le_int32 position = glyphIterator->getCurrStreamPosition();
379
380
// Back up the glyph iterator so that we
381
// can call next() before the check, which
382
// will leave it pointing at the last glyph
383
// that matched when we're done.
384
glyphIterator->prev();
385
386
LEReferenceToArrayOf<Offset> covTableOffsetArray(base, success, coverageTableOffsetArray, gCount);
387
388
if( LE_FAILURE(success) ) { return 0; }
389
390
if (ContextualSubstitutionBase::matchGlyphCoverages(covTableOffsetArray, gCount, glyphIterator, base, success)) {
391
LEReferenceToArrayOf<SubstitutionLookupRecord>
392
substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &coverageTableOffsetArray[gCount], subCount);
393
394
ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray, subCount, glyphIterator, fontInstance, position, success);
395
396
return gCount + 1;
397
}
398
399
glyphIterator->setCurrStreamPosition(position);
400
401
return 0;
402
}
403
404
le_uint32 ChainingContextualSubstitutionSubtable::process(const LEReferenceTo<ChainingContextualSubstitutionSubtable> &base,
405
const LookupProcessor *lookupProcessor,
406
GlyphIterator *glyphIterator,
407
const LEFontInstance *fontInstance,
408
LEErrorCode& success) const
409
{
410
if (LE_FAILURE(success)) {
411
return 0;
412
}
413
414
switch(SWAPW(subtableFormat))
415
{
416
case 0:
417
return 0;
418
419
case 1:
420
{
421
LEReferenceTo<ChainingContextualSubstitutionFormat1Subtable> subtable(base, success, (ChainingContextualSubstitutionFormat1Subtable *) this);
422
if(LE_FAILURE(success)) return 0;
423
return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
424
}
425
426
case 2:
427
{
428
LEReferenceTo<ChainingContextualSubstitutionFormat2Subtable> subtable(base, success, (const ChainingContextualSubstitutionFormat2Subtable *) this);
429
if( LE_FAILURE(success) ) { return 0; }
430
return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
431
}
432
433
case 3:
434
{
435
LEReferenceTo<ChainingContextualSubstitutionFormat3Subtable> subtable(base, success, (const ChainingContextualSubstitutionFormat3Subtable *) this);
436
if( LE_FAILURE(success) ) { return 0; }
437
return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
438
}
439
440
default:
441
return 0;
442
}
443
}
444
445
// NOTE: This could be a #define, but that seems to confuse
446
// the Visual Studio .NET 2003 compiler on the calls to the
447
// GlyphIterator constructor. It somehow can't decide if
448
// emptyFeatureList matches an le_uint32 or an le_uint16...
449
static const FeatureMask emptyFeatureList = 0x00000000UL;
450
451
le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
452
GlyphIterator *glyphIterator,
453
const LEFontInstance *fontInstance,
454
LEErrorCode& success) const
455
{
456
if (LE_FAILURE(success)) {
457
return 0;
458
}
459
460
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
461
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
462
if (LE_FAILURE(success)) {
463
return 0;
464
}
465
466
if (coverageIndex >= 0) {
467
le_uint16 srSetCount = SWAPW(chainSubRuleSetCount);
468
469
if (coverageIndex < srSetCount) {
470
LEReferenceToArrayOf<Offset>
471
chainSubRuleSetTableOffsetArrayRef(base, success, chainSubRuleSetTableOffsetArray, srSetCount);
472
if (LE_FAILURE(success)) {
473
return 0;
474
}
475
Offset chainSubRuleSetTableOffset = SWAPW(chainSubRuleSetTableOffsetArray[coverageIndex]);
476
LEReferenceTo<ChainSubRuleSetTable> chainSubRuleSetTable(base, success, chainSubRuleSetTableOffset);
477
if (LE_FAILURE(success)) { return 0; }
478
le_uint16 chainSubRuleCount = SWAPW(chainSubRuleSetTable->chainSubRuleCount);
479
le_int32 position = glyphIterator->getCurrStreamPosition();
480
GlyphIterator tempIterator(*glyphIterator, emptyFeatureList);
481
LEReferenceToArrayOf<Offset>
482
chainSubRuleTableOffsetArrayRef(base, success, chainSubRuleSetTable->chainSubRuleTableOffsetArray, chainSubRuleCount);
483
if (LE_FAILURE(success)) {
484
return 0;
485
}
486
for (le_uint16 subRule = 0; subRule < chainSubRuleCount; subRule += 1) {
487
Offset chainSubRuleTableOffset =
488
SWAPW(chainSubRuleSetTable->chainSubRuleTableOffsetArray[subRule]);
489
LEReferenceTo<ChainSubRuleTable>
490
chainSubRuleTable = LEReferenceTo<ChainSubRuleTable>(chainSubRuleSetTable, success, chainSubRuleTableOffset);
491
if( LE_FAILURE(success) ) { return 0; }
492
le_uint16 backtrackGlyphCount = SWAPW(chainSubRuleTable->backtrackGlyphCount);
493
LEReferenceToArrayOf<TTGlyphID> backtrackGlyphArray(base, success, chainSubRuleTable->backtrackGlyphArray, backtrackGlyphCount);
494
if( LE_FAILURE(success) ) { return 0; }
495
le_uint16 inputGlyphCount = (le_uint16) SWAPW(chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount]) - 1;
496
LEReferenceToArrayOf<TTGlyphID> inputGlyphArray(base, success, &chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount + 1], inputGlyphCount+2);
497
498
if( LE_FAILURE(success) ) { return 0; }
499
le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputGlyphArray[inputGlyphCount]);
500
LEReferenceToArrayOf<TTGlyphID> lookaheadGlyphArray(base, success, inputGlyphArray.getAlias(inputGlyphCount + 1,success), lookaheadGlyphCount+2);
501
if( LE_FAILURE(success) ) { return 0; }
502
le_uint16 substCount = (le_uint16) SWAPW(lookaheadGlyphArray[lookaheadGlyphCount]);
503
504
tempIterator.setCurrStreamPosition(position);
505
506
if (! tempIterator.prev(backtrackGlyphCount)) {
507
continue;
508
}
509
510
tempIterator.prev();
511
512
if (! matchGlyphIDs(backtrackGlyphArray, backtrackGlyphCount, &tempIterator, TRUE)) {
513
continue;
514
}
515
516
tempIterator.setCurrStreamPosition(position);
517
tempIterator.next(inputGlyphCount);
518
if (!matchGlyphIDs(lookaheadGlyphArray, lookaheadGlyphCount, &tempIterator)) {
519
continue;
520
}
521
522
if (matchGlyphIDs(inputGlyphArray, inputGlyphCount, glyphIterator)) {
523
LEReferenceToArrayOf<SubstitutionLookupRecord>
524
substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) lookaheadGlyphArray.getAlias(lookaheadGlyphCount + 1,success), substCount);
525
526
applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
527
528
return inputGlyphCount + 1;
529
}
530
531
glyphIterator->setCurrStreamPosition(position);
532
}
533
}
534
535
// XXX If we get here, the table is mal-formed...
536
}
537
538
return 0;
539
}
540
541
le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
542
GlyphIterator *glyphIterator,
543
const LEFontInstance *fontInstance,
544
LEErrorCode& success) const
545
{
546
if (LE_FAILURE(success)) {
547
return 0;
548
}
549
550
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
551
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
552
if (LE_FAILURE(success)) {
553
return 0;
554
}
555
556
if (coverageIndex >= 0) {
557
LEReferenceTo<ClassDefinitionTable>
558
backtrackClassDefinitionTable(base, success, SWAPW(backtrackClassDefTableOffset));
559
LEReferenceTo<ClassDefinitionTable>
560
inputClassDefinitionTable(base, success, SWAPW(inputClassDefTableOffset));
561
LEReferenceTo<ClassDefinitionTable>
562
lookaheadClassDefinitionTable(base, success, SWAPW(lookaheadClassDefTableOffset));
563
le_uint16 scSetCount = SWAPW(chainSubClassSetCount);
564
le_int32 setClass = inputClassDefinitionTable->getGlyphClass(inputClassDefinitionTable,
565
glyphIterator->getCurrGlyphID(),
566
success);
567
LEReferenceToArrayOf<Offset>
568
chainSubClassSetTableOffsetArrayRef(base, success, chainSubClassSetTableOffsetArray, scSetCount);
569
if (LE_FAILURE(success)) {
570
return 0;
571
}
572
573
if (setClass < scSetCount && chainSubClassSetTableOffsetArray[setClass] != 0) {
574
Offset chainSubClassSetTableOffset = SWAPW(chainSubClassSetTableOffsetArray[setClass]);
575
LEReferenceTo<ChainSubClassSetTable>
576
chainSubClassSetTable(base, success, chainSubClassSetTableOffset);
577
if (LE_FAILURE(success)) { return 0; }
578
le_uint16 chainSubClassRuleCount = SWAPW(chainSubClassSetTable->chainSubClassRuleCount);
579
le_int32 position = glyphIterator->getCurrStreamPosition();
580
GlyphIterator tempIterator(*glyphIterator, emptyFeatureList);
581
LEReferenceToArrayOf<Offset>
582
chainSubClassRuleTableOffsetArrayRef(base, success, chainSubClassSetTable->chainSubClassRuleTableOffsetArray, chainSubClassRuleCount);
583
if (LE_FAILURE(success)) {
584
return 0;
585
}
586
for (le_uint16 scRule = 0; scRule < chainSubClassRuleCount; scRule += 1) {
587
Offset chainSubClassRuleTableOffset =
588
SWAPW(chainSubClassSetTable->chainSubClassRuleTableOffsetArray[scRule]);
589
LEReferenceTo<ChainSubClassRuleTable>
590
chainSubClassRuleTable(chainSubClassSetTable, success, chainSubClassRuleTableOffset);
591
if (LE_FAILURE(success)) { return 0; }
592
le_uint16 backtrackGlyphCount = SWAPW(chainSubClassRuleTable->backtrackGlyphCount);
593
LEReferenceToArrayOf<le_uint16> backtrackClassArray(base, success, chainSubClassRuleTable->backtrackClassArray, backtrackGlyphCount);
594
if( LE_FAILURE(success) ) { return 0; }
595
le_uint16 inputGlyphCount = SWAPW(chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount]) - 1;
596
LEReferenceToArrayOf<le_uint16> inputClassArray(base, success, &chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount + 1],inputGlyphCount+2); // +2 for the lookaheadGlyphCount count
597
le_uint16 lookaheadGlyphCount = SWAPW(inputClassArray.getObject(inputGlyphCount, success));
598
LEReferenceToArrayOf<le_uint16> lookaheadClassArray(base, success, inputClassArray.getAlias(inputGlyphCount + 1,success), lookaheadGlyphCount+2); // +2 for the substCount
599
600
if( LE_FAILURE(success) ) { return 0; }
601
le_uint16 substCount = SWAPW(lookaheadClassArray[lookaheadGlyphCount]);
602
603
604
tempIterator.setCurrStreamPosition(position);
605
606
if (! tempIterator.prev(backtrackGlyphCount)) {
607
continue;
608
}
609
610
tempIterator.prev();
611
if (! matchGlyphClasses(backtrackClassArray, backtrackGlyphCount,
612
&tempIterator, backtrackClassDefinitionTable, success, TRUE)) {
613
continue;
614
}
615
616
tempIterator.setCurrStreamPosition(position);
617
tempIterator.next(inputGlyphCount);
618
if (! matchGlyphClasses(lookaheadClassArray, lookaheadGlyphCount, &tempIterator, lookaheadClassDefinitionTable, success)) {
619
continue;
620
}
621
622
if (matchGlyphClasses(inputClassArray, inputGlyphCount, glyphIterator, inputClassDefinitionTable, success)) {
623
LEReferenceToArrayOf<SubstitutionLookupRecord>
624
substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) lookaheadClassArray.getAlias(lookaheadGlyphCount + 1, success), substCount);
625
if (LE_FAILURE(success)) { return 0; }
626
applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
627
628
return inputGlyphCount + 1;
629
}
630
631
glyphIterator->setCurrStreamPosition(position);
632
}
633
}
634
635
// XXX If we get here, the table is mal-formed...
636
}
637
638
return 0;
639
}
640
641
le_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
642
GlyphIterator *glyphIterator,
643
const LEFontInstance *fontInstance,
644
LEErrorCode & success) const
645
{
646
if (LE_FAILURE(success)) {
647
return 0;
648
}
649
650
le_uint16 backtrkGlyphCount = SWAPW(backtrackGlyphCount);
651
LEReferenceToArrayOf<Offset> backtrackGlyphArrayRef(base, success, backtrackCoverageTableOffsetArray, backtrkGlyphCount);
652
if (LE_FAILURE(success)) {
653
return 0;
654
}
655
le_uint16 inputGlyphCount = (le_uint16) SWAPW(backtrackCoverageTableOffsetArray[backtrkGlyphCount]);
656
LEReferenceToArrayOf<Offset> inputCoverageTableOffsetArray(base, success, &backtrackCoverageTableOffsetArray[backtrkGlyphCount + 1], inputGlyphCount+2); // offset
657
if (LE_FAILURE(success)) { return 0; }
658
const le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputCoverageTableOffsetArray[inputGlyphCount]);
659
LEReferenceToArrayOf<Offset> lookaheadCoverageTableOffsetArray(base, success, inputCoverageTableOffsetArray.getAlias(inputGlyphCount + 1, success), lookaheadGlyphCount+2);
660
661
if( LE_FAILURE(success) ) { return 0; }
662
le_uint16 substCount = (le_uint16) SWAPW(lookaheadCoverageTableOffsetArray[lookaheadGlyphCount]);
663
le_int32 position = glyphIterator->getCurrStreamPosition();
664
GlyphIterator tempIterator(*glyphIterator, emptyFeatureList);
665
666
if (! tempIterator.prev(backtrkGlyphCount)) {
667
return 0;
668
}
669
670
tempIterator.prev();
671
if (! ContextualSubstitutionBase::matchGlyphCoverages(backtrackCoverageTableOffsetArray,
672
backtrkGlyphCount, &tempIterator, base, success, TRUE)) {
673
return 0;
674
}
675
676
tempIterator.setCurrStreamPosition(position);
677
tempIterator.next(inputGlyphCount - 1);
678
if (! ContextualSubstitutionBase::matchGlyphCoverages(lookaheadCoverageTableOffsetArray,
679
lookaheadGlyphCount, &tempIterator, base, success)) {
680
return 0;
681
}
682
683
// Back up the glyph iterator so that we
684
// can call next() before the check, which
685
// will leave it pointing at the last glyph
686
// that matched when we're done.
687
glyphIterator->prev();
688
689
if (ContextualSubstitutionBase::matchGlyphCoverages(inputCoverageTableOffsetArray,
690
inputGlyphCount, glyphIterator, base, success)) {
691
LEReferenceToArrayOf<SubstitutionLookupRecord>
692
substLookupRecordArray(base, success,
693
(const SubstitutionLookupRecord *) lookaheadCoverageTableOffsetArray.getAlias(lookaheadGlyphCount + 1,success), substCount);
694
695
ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
696
697
return inputGlyphCount;
698
}
699
700
glyphIterator->setCurrStreamPosition(position);
701
702
return 0;
703
}
704
705
U_NAMESPACE_END
706
707