os/textandloc/fontservices/textshaperplugin/IcuSource/layout/ContextualSubstSubtables.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/textandloc/fontservices/textshaperplugin/IcuSource/layout/ContextualSubstSubtables.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,563 @@
1.4 +/*
1.5 + *
1.6 + * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
1.7 + *
1.8 + */
1.9 +
1.10 +#include "LETypes.h"
1.11 +#include "LEFontInstance.h"
1.12 +#include "OpenTypeTables.h"
1.13 +#include "GlyphSubstitutionTables.h"
1.14 +#include "ContextualSubstSubtables.h"
1.15 +#include "GlyphIterator.h"
1.16 +#include "LookupProcessor.h"
1.17 +#include "CoverageTables.h"
1.18 +#include "LESwaps.h"
1.19 +
1.20 +U_NAMESPACE_BEGIN
1.21 +
1.22 +/*
1.23 + NOTE: This could be optimized somewhat by keeping track
1.24 + of the previous sequenceIndex in the loop and doing next()
1.25 + or prev() of the delta between that and the current
1.26 + sequenceIndex instead of always resetting to the front.
1.27 +*/
1.28 +void ContextualSubstitutionBase::applySubstitutionLookups(
1.29 + const LookupProcessor *lookupProcessor,
1.30 + const SubstitutionLookupRecord *substLookupRecordArray,
1.31 + le_uint16 substCount,
1.32 + GlyphIterator *glyphIterator,
1.33 + const LEFontInstance *fontInstance,
1.34 + le_int32 position,
1.35 + LEErrorCode& success)
1.36 +{
1.37 + if (LE_FAILURE(success)) {
1.38 + return;
1.39 + }
1.40 +
1.41 + GlyphIterator tempIterator(*glyphIterator);
1.42 +
1.43 + for (le_int16 subst = 0; subst < substCount && LE_SUCCESS(success); subst += 1) {
1.44 + le_uint16 sequenceIndex = SWAPW(substLookupRecordArray[subst].sequenceIndex);
1.45 + le_uint16 lookupListIndex = SWAPW(substLookupRecordArray[subst].lookupListIndex);
1.46 +
1.47 + tempIterator.setCurrStreamPosition(position);
1.48 + tempIterator.next(sequenceIndex);
1.49 +
1.50 + lookupProcessor->applySingleLookup(lookupListIndex, &tempIterator,
1.51 + fontInstance, success);
1.52 + }
1.53 +}
1.54 +
1.55 +le_bool ContextualSubstitutionBase::matchGlyphIDs(const TTGlyphID *glyphArray, le_uint16 glyphCount,
1.56 + GlyphIterator *glyphIterator, le_bool backtrack)
1.57 +{
1.58 + le_int32 direction = 1;
1.59 + le_int32 match = 0;
1.60 +
1.61 + if (backtrack) {
1.62 + match = glyphCount -1;
1.63 + direction = -1;
1.64 + }
1.65 +
1.66 + while (glyphCount > 0) {
1.67 + if (! glyphIterator->next()) {
1.68 + return FALSE;
1.69 + }
1.70 +
1.71 + TTGlyphID glyph = (TTGlyphID) glyphIterator->getCurrGlyphID();
1.72 +
1.73 + if (glyph != SWAPW(glyphArray[match])) {
1.74 + return FALSE;
1.75 + }
1.76 +
1.77 + glyphCount -= 1;
1.78 + match += direction;
1.79 + }
1.80 +
1.81 + return TRUE;
1.82 +}
1.83 +
1.84 +le_bool ContextualSubstitutionBase::matchGlyphClasses(const le_uint16 *classArray, le_uint16 glyphCount,
1.85 + GlyphIterator *glyphIterator,
1.86 + const ClassDefinitionTable *classDefinitionTable,
1.87 + le_bool backtrack)
1.88 +{
1.89 + le_int32 direction = 1;
1.90 + le_int32 match = 0;
1.91 +
1.92 + if (backtrack) {
1.93 + match = glyphCount - 1;
1.94 + direction = -1;
1.95 + }
1.96 +
1.97 + while (glyphCount > 0) {
1.98 + if (! glyphIterator->next()) {
1.99 + return FALSE;
1.100 + }
1.101 +
1.102 + LEGlyphID glyph = glyphIterator->getCurrGlyphID();
1.103 + le_int32 glyphClass = classDefinitionTable->getGlyphClass(glyph);
1.104 + le_int32 matchClass = SWAPW(classArray[match]);
1.105 +
1.106 + if (glyphClass != matchClass) {
1.107 + // Some fonts, e.g. Traditional Arabic, have classes
1.108 + // in the class array which aren't in the class definition
1.109 + // table. If we're looking for such a class, pretend that
1.110 + // we found it.
1.111 + if (classDefinitionTable->hasGlyphClass(matchClass)) {
1.112 + return FALSE;
1.113 + }
1.114 + }
1.115 +
1.116 + glyphCount -= 1;
1.117 + match += direction;
1.118 + }
1.119 +
1.120 + return TRUE;
1.121 +}
1.122 +
1.123 +le_bool ContextualSubstitutionBase::matchGlyphCoverages(const Offset *coverageTableOffsetArray, le_uint16 glyphCount,
1.124 + GlyphIterator *glyphIterator, const char *offsetBase, le_bool backtrack)
1.125 +{
1.126 + le_int32 direction = 1;
1.127 + le_int32 glyph = 0;
1.128 +
1.129 + if (backtrack) {
1.130 + glyph = glyphCount - 1;
1.131 + direction = -1;
1.132 + }
1.133 +
1.134 + while (glyphCount > 0) {
1.135 + Offset coverageTableOffset = SWAPW(coverageTableOffsetArray[glyph]);
1.136 + const CoverageTable *coverageTable = (const CoverageTable *) (offsetBase + coverageTableOffset);
1.137 +
1.138 + if (! glyphIterator->next()) {
1.139 + return FALSE;
1.140 + }
1.141 +
1.142 + if (coverageTable->getGlyphCoverage((LEGlyphID) glyphIterator->getCurrGlyphID()) < 0) {
1.143 + return FALSE;
1.144 + }
1.145 +
1.146 + glyphCount -= 1;
1.147 + glyph += direction;
1.148 + }
1.149 +
1.150 + return TRUE;
1.151 +}
1.152 +
1.153 +le_uint32 ContextualSubstitutionSubtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
1.154 + const LEFontInstance *fontInstance, LEErrorCode& success) const
1.155 +{
1.156 + if (LE_FAILURE(success)) {
1.157 + return 0;
1.158 + }
1.159 +
1.160 + switch(SWAPW(subtableFormat))
1.161 + {
1.162 + case 0:
1.163 + return 0;
1.164 +
1.165 + case 1:
1.166 + {
1.167 + const ContextualSubstitutionFormat1Subtable *subtable = (const ContextualSubstitutionFormat1Subtable *) this;
1.168 +
1.169 + return subtable->process(lookupProcessor, glyphIterator, fontInstance, success);
1.170 + }
1.171 +
1.172 + case 2:
1.173 + {
1.174 + const ContextualSubstitutionFormat2Subtable *subtable = (const ContextualSubstitutionFormat2Subtable *) this;
1.175 +
1.176 + return subtable->process(lookupProcessor, glyphIterator, fontInstance, success);
1.177 + }
1.178 +
1.179 + case 3:
1.180 + {
1.181 + const ContextualSubstitutionFormat3Subtable *subtable = (const ContextualSubstitutionFormat3Subtable *) this;
1.182 +
1.183 + return subtable->process(lookupProcessor, glyphIterator, fontInstance, success);
1.184 + }
1.185 +
1.186 + default:
1.187 + return 0;
1.188 + }
1.189 +}
1.190 +
1.191 +le_uint32 ContextualSubstitutionFormat1Subtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
1.192 + const LEFontInstance *fontInstance, LEErrorCode& success) const
1.193 +{
1.194 + if (LE_FAILURE(success)) {
1.195 + return 0;
1.196 + }
1.197 +
1.198 + LEGlyphID glyph = glyphIterator->getCurrGlyphID();
1.199 + le_int32 coverageIndex = getGlyphCoverage(glyph);
1.200 +
1.201 + if (coverageIndex >= 0) {
1.202 + le_uint16 srSetCount = SWAPW(subRuleSetCount);
1.203 +
1.204 + if (coverageIndex < srSetCount) {
1.205 + Offset subRuleSetTableOffset = SWAPW(subRuleSetTableOffsetArray[coverageIndex]);
1.206 + const SubRuleSetTable *subRuleSetTable =
1.207 + (const SubRuleSetTable *) ((char *) this + subRuleSetTableOffset);
1.208 + le_uint16 subRuleCount = SWAPW(subRuleSetTable->subRuleCount);
1.209 + le_int32 position = glyphIterator->getCurrStreamPosition();
1.210 +
1.211 + for (le_uint16 subRule = 0; subRule < subRuleCount; subRule += 1) {
1.212 + Offset subRuleTableOffset =
1.213 + SWAPW(subRuleSetTable->subRuleTableOffsetArray[subRule]);
1.214 + const SubRuleTable *subRuleTable =
1.215 + (const SubRuleTable *) ((char *) subRuleSetTable + subRuleTableOffset);
1.216 + le_uint16 matchCount = SWAPW(subRuleTable->glyphCount) - 1;
1.217 + le_uint16 substCount = SWAPW(subRuleTable->substCount);
1.218 +
1.219 + if (matchGlyphIDs(subRuleTable->inputGlyphArray, matchCount, glyphIterator)) {
1.220 + const SubstitutionLookupRecord *substLookupRecordArray =
1.221 + (const SubstitutionLookupRecord *) &subRuleTable->inputGlyphArray[matchCount];
1.222 +
1.223 + applySubstitutionLookups(lookupProcessor, substLookupRecordArray,
1.224 + substCount, glyphIterator, fontInstance, position, success);
1.225 +
1.226 + return matchCount + 1;
1.227 + }
1.228 +
1.229 + glyphIterator->setCurrStreamPosition(position);
1.230 + }
1.231 + }
1.232 +
1.233 + // XXX If we get here, the table is mal-formed...
1.234 + }
1.235 +
1.236 + return 0;
1.237 +}
1.238 +
1.239 +le_uint32 ContextualSubstitutionFormat2Subtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
1.240 + const LEFontInstance *fontInstance, LEErrorCode& success) const
1.241 +{
1.242 + if (LE_FAILURE(success)) {
1.243 + return 0;
1.244 + }
1.245 +
1.246 + LEGlyphID glyph = glyphIterator->getCurrGlyphID();
1.247 + le_int32 coverageIndex = getGlyphCoverage(glyph);
1.248 +
1.249 + if (coverageIndex >= 0) {
1.250 + const ClassDefinitionTable *classDefinitionTable =
1.251 + (const ClassDefinitionTable *) ((char *) this + SWAPW(classDefTableOffset));
1.252 + le_uint16 scSetCount = SWAPW(subClassSetCount);
1.253 + le_int32 setClass = classDefinitionTable->getGlyphClass(glyphIterator->getCurrGlyphID());
1.254 +
1.255 + if (setClass < scSetCount && subClassSetTableOffsetArray[setClass] != 0) {
1.256 + Offset subClassSetTableOffset = SWAPW(subClassSetTableOffsetArray[setClass]);
1.257 + const SubClassSetTable *subClassSetTable =
1.258 + (const SubClassSetTable *) ((char *) this + subClassSetTableOffset);
1.259 + le_uint16 subClassRuleCount = SWAPW(subClassSetTable->subClassRuleCount);
1.260 + le_int32 position = glyphIterator->getCurrStreamPosition();
1.261 +
1.262 + for (le_uint16 scRule = 0; scRule < subClassRuleCount; scRule += 1) {
1.263 + Offset subClassRuleTableOffset =
1.264 + SWAPW(subClassSetTable->subClassRuleTableOffsetArray[scRule]);
1.265 + const SubClassRuleTable *subClassRuleTable =
1.266 + (const SubClassRuleTable *) ((char *) subClassSetTable + subClassRuleTableOffset);
1.267 + le_uint16 matchCount = SWAPW(subClassRuleTable->glyphCount) - 1;
1.268 + le_uint16 substCount = SWAPW(subClassRuleTable->substCount);
1.269 +
1.270 + if (matchGlyphClasses(subClassRuleTable->classArray, matchCount, glyphIterator, classDefinitionTable)) {
1.271 + const SubstitutionLookupRecord *substLookupRecordArray =
1.272 + (const SubstitutionLookupRecord *) &subClassRuleTable->classArray[matchCount];
1.273 +
1.274 + applySubstitutionLookups(lookupProcessor, substLookupRecordArray,
1.275 + substCount, glyphIterator, fontInstance, position, success);
1.276 +
1.277 + return matchCount + 1;
1.278 + }
1.279 +
1.280 + glyphIterator->setCurrStreamPosition(position);
1.281 + }
1.282 + }
1.283 +
1.284 + // XXX If we get here, the table is mal-formed...
1.285 + }
1.286 +
1.287 + return 0;
1.288 +}
1.289 +
1.290 +le_uint32 ContextualSubstitutionFormat3Subtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
1.291 + const LEFontInstance *fontInstance, LEErrorCode& success) const
1.292 +{
1.293 + if (LE_FAILURE(success)) {
1.294 + return 0;
1.295 + }
1.296 +
1.297 + le_uint16 gCount = SWAPW(glyphCount);
1.298 + le_uint16 subCount = SWAPW(substCount);
1.299 + le_int32 position = glyphIterator->getCurrStreamPosition();
1.300 +
1.301 + // Back up the glyph iterator so that we
1.302 + // can call next() before the check, which
1.303 + // will leave it pointing at the last glyph
1.304 + // that matched when we're done.
1.305 + glyphIterator->prev();
1.306 +
1.307 + if (ContextualSubstitutionBase::matchGlyphCoverages(coverageTableOffsetArray, gCount, glyphIterator, (const char *) this)) {
1.308 + const SubstitutionLookupRecord *substLookupRecordArray =
1.309 + (const SubstitutionLookupRecord *) &coverageTableOffsetArray[gCount];
1.310 +
1.311 + ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray,
1.312 + subCount, glyphIterator, fontInstance, position, success);
1.313 +
1.314 + return gCount + 1;
1.315 + }
1.316 +
1.317 + glyphIterator->setCurrStreamPosition(position);
1.318 +
1.319 + return 0;
1.320 +}
1.321 +
1.322 +le_uint32 ChainingContextualSubstitutionSubtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
1.323 + const LEFontInstance *fontInstance, LEErrorCode& success) const
1.324 +{
1.325 + if (LE_FAILURE(success)) {
1.326 + return 0;
1.327 + }
1.328 +
1.329 + switch(SWAPW(subtableFormat))
1.330 + {
1.331 + case 0:
1.332 + return 0;
1.333 +
1.334 + case 1:
1.335 + {
1.336 + const ChainingContextualSubstitutionFormat1Subtable *subtable = (const ChainingContextualSubstitutionFormat1Subtable *) this;
1.337 +
1.338 + return subtable->process(lookupProcessor, glyphIterator, fontInstance, success);
1.339 + }
1.340 +
1.341 + case 2:
1.342 + {
1.343 + const ChainingContextualSubstitutionFormat2Subtable *subtable = (const ChainingContextualSubstitutionFormat2Subtable *) this;
1.344 +
1.345 + return subtable->process(lookupProcessor, glyphIterator, fontInstance, success);
1.346 + }
1.347 +
1.348 + case 3:
1.349 + {
1.350 + const ChainingContextualSubstitutionFormat3Subtable *subtable = (const ChainingContextualSubstitutionFormat3Subtable *) this;
1.351 +
1.352 + return subtable->process(lookupProcessor, glyphIterator, fontInstance, success);
1.353 + }
1.354 +
1.355 + default:
1.356 + return 0;
1.357 + }
1.358 +}
1.359 +
1.360 +static const LETag emptyTag = 0;
1.361 +
1.362 +le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
1.363 + const LEFontInstance *fontInstance, LEErrorCode& success) const
1.364 +{
1.365 + if (LE_FAILURE(success)) {
1.366 + return 0;
1.367 + }
1.368 +
1.369 + LEGlyphID glyph = glyphIterator->getCurrGlyphID();
1.370 + le_int32 coverageIndex = getGlyphCoverage(glyph);
1.371 +
1.372 + if (coverageIndex >= 0) {
1.373 + le_uint16 srSetCount = SWAPW(chainSubRuleSetCount);
1.374 +
1.375 + if (coverageIndex < srSetCount) {
1.376 + Offset chainSubRuleSetTableOffset = SWAPW(chainSubRuleSetTableOffsetArray[coverageIndex]);
1.377 + const ChainSubRuleSetTable *chainSubRuleSetTable =
1.378 + (const ChainSubRuleSetTable *) ((char *) this + chainSubRuleSetTableOffset);
1.379 + le_uint16 chainSubRuleCount = SWAPW(chainSubRuleSetTable->chainSubRuleCount);
1.380 + le_int32 position = glyphIterator->getCurrStreamPosition();
1.381 + GlyphIterator tempIterator(*glyphIterator, emptyTag);
1.382 +
1.383 + for (le_uint16 subRule = 0; subRule < chainSubRuleCount; subRule += 1) {
1.384 + Offset chainSubRuleTableOffset =
1.385 + SWAPW(chainSubRuleSetTable->chainSubRuleTableOffsetArray[subRule]);
1.386 + const ChainSubRuleTable *chainSubRuleTable =
1.387 + (const ChainSubRuleTable *) ((char *) chainSubRuleSetTable + chainSubRuleTableOffset);
1.388 + le_uint16 backtrackGlyphCount = SWAPW(chainSubRuleTable->backtrackGlyphCount);
1.389 + le_uint16 inputGlyphCount = (le_uint16) SWAPW(chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount]) - 1;
1.390 + const TTGlyphID *inputGlyphArray = &chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount + 1];
1.391 + le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputGlyphArray[inputGlyphCount]);
1.392 + const TTGlyphID *lookaheadGlyphArray = &inputGlyphArray[inputGlyphCount + 1];
1.393 + le_uint16 substCount = (le_uint16) SWAPW(lookaheadGlyphArray[lookaheadGlyphCount]);
1.394 +
1.395 + tempIterator.setCurrStreamPosition(position);
1.396 +
1.397 + if (! tempIterator.prev(backtrackGlyphCount)) {
1.398 + continue;
1.399 + }
1.400 +
1.401 + tempIterator.prev();
1.402 + if (! matchGlyphIDs(chainSubRuleTable->backtrackGlyphArray, backtrackGlyphCount, &tempIterator, TRUE)) {
1.403 + continue;
1.404 + }
1.405 +
1.406 + tempIterator.setCurrStreamPosition(position);
1.407 + tempIterator.next(inputGlyphCount);
1.408 + if (!matchGlyphIDs(lookaheadGlyphArray, lookaheadGlyphCount, &tempIterator)) {
1.409 + continue;
1.410 + }
1.411 +
1.412 + if (matchGlyphIDs(inputGlyphArray, inputGlyphCount, glyphIterator)) {
1.413 + const SubstitutionLookupRecord *substLookupRecordArray =
1.414 + (const SubstitutionLookupRecord *) &lookaheadGlyphArray[lookaheadGlyphCount + 1];
1.415 +
1.416 + applySubstitutionLookups(lookupProcessor, substLookupRecordArray,
1.417 + substCount, glyphIterator, fontInstance, position, success);
1.418 +
1.419 + return inputGlyphCount + 1;
1.420 + }
1.421 +
1.422 + glyphIterator->setCurrStreamPosition(position);
1.423 + }
1.424 + }
1.425 +
1.426 + // XXX If we get here, the table is mal-formed...
1.427 + }
1.428 +
1.429 + return 0;
1.430 +}
1.431 +
1.432 +le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
1.433 + const LEFontInstance *fontInstance, LEErrorCode& success) const
1.434 +{
1.435 + if (LE_FAILURE(success)) {
1.436 + return 0;
1.437 + }
1.438 +
1.439 + LEGlyphID glyph = glyphIterator->getCurrGlyphID();
1.440 + le_int32 coverageIndex = getGlyphCoverage(glyph);
1.441 +
1.442 + if (coverageIndex >= 0) {
1.443 + const ClassDefinitionTable *backtrackClassDefinitionTable =
1.444 + (const ClassDefinitionTable *) ((char *) this + SWAPW(backtrackClassDefTableOffset));
1.445 + const ClassDefinitionTable *inputClassDefinitionTable =
1.446 + (const ClassDefinitionTable *) ((char *) this + SWAPW(inputClassDefTableOffset));
1.447 + const ClassDefinitionTable *lookaheadClassDefinitionTable =
1.448 + (const ClassDefinitionTable *) ((char *) this + SWAPW(lookaheadClassDefTableOffset));
1.449 + le_uint16 scSetCount = SWAPW(chainSubClassSetCount);
1.450 + le_int32 setClass = inputClassDefinitionTable->getGlyphClass(glyphIterator->getCurrGlyphID());
1.451 +
1.452 + if (setClass < scSetCount && chainSubClassSetTableOffsetArray[setClass] != 0) {
1.453 + Offset chainSubClassSetTableOffset = SWAPW(chainSubClassSetTableOffsetArray[setClass]);
1.454 + const ChainSubClassSetTable *chainSubClassSetTable =
1.455 + (const ChainSubClassSetTable *) ((char *) this + chainSubClassSetTableOffset);
1.456 + le_uint16 chainSubClassRuleCount = SWAPW(chainSubClassSetTable->chainSubClassRuleCount);
1.457 + le_int32 position = glyphIterator->getCurrStreamPosition();
1.458 + GlyphIterator tempIterator(*glyphIterator, emptyTag);
1.459 +
1.460 + for (le_uint16 scRule = 0; scRule < chainSubClassRuleCount; scRule += 1) {
1.461 + Offset chainSubClassRuleTableOffset =
1.462 + SWAPW(chainSubClassSetTable->chainSubClassRuleTableOffsetArray[scRule]);
1.463 + const ChainSubClassRuleTable *chainSubClassRuleTable =
1.464 + (const ChainSubClassRuleTable *) ((char *) chainSubClassSetTable + chainSubClassRuleTableOffset);
1.465 + le_uint16 backtrackGlyphCount = SWAPW(chainSubClassRuleTable->backtrackGlyphCount);
1.466 + le_uint16 inputGlyphCount = SWAPW(chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount]) - 1;
1.467 + const le_uint16 *inputClassArray = &chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount + 1];
1.468 + le_uint16 lookaheadGlyphCount = SWAPW(inputClassArray[inputGlyphCount]);
1.469 + const le_uint16 *lookaheadClassArray = &inputClassArray[inputGlyphCount + 1];
1.470 + le_uint16 substCount = SWAPW(lookaheadClassArray[lookaheadGlyphCount]);
1.471 +
1.472 +
1.473 + tempIterator.setCurrStreamPosition(position);
1.474 +
1.475 + if (! tempIterator.prev(backtrackGlyphCount)) {
1.476 + continue;
1.477 + }
1.478 +
1.479 + tempIterator.prev();
1.480 + if (! matchGlyphClasses(chainSubClassRuleTable->backtrackClassArray, backtrackGlyphCount,
1.481 + &tempIterator, backtrackClassDefinitionTable, TRUE)) {
1.482 + continue;
1.483 + }
1.484 +
1.485 + tempIterator.setCurrStreamPosition(position);
1.486 + tempIterator.next(inputGlyphCount);
1.487 + if (! matchGlyphClasses(lookaheadClassArray, lookaheadGlyphCount, &tempIterator, lookaheadClassDefinitionTable)) {
1.488 + continue;
1.489 + }
1.490 +
1.491 + if (matchGlyphClasses(inputClassArray, inputGlyphCount, glyphIterator, inputClassDefinitionTable)) {
1.492 + const SubstitutionLookupRecord *substLookupRecordArray =
1.493 + (const SubstitutionLookupRecord *) &lookaheadClassArray[lookaheadGlyphCount + 1];
1.494 +
1.495 + applySubstitutionLookups(lookupProcessor, substLookupRecordArray,
1.496 + substCount, glyphIterator, fontInstance, position, success);
1.497 +
1.498 + return inputGlyphCount + 1;
1.499 + }
1.500 +
1.501 + glyphIterator->setCurrStreamPosition(position);
1.502 + }
1.503 + }
1.504 +
1.505 + // XXX If we get here, the table is mal-formed...
1.506 + }
1.507 +
1.508 + return 0;
1.509 +}
1.510 +
1.511 +le_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
1.512 + const LEFontInstance *fontInstance, LEErrorCode& success) const
1.513 +{
1.514 + if (LE_FAILURE(success)) {
1.515 + return 0;
1.516 + }
1.517 +
1.518 + le_uint16 backtrkGlyphCount = SWAPW(backtrackGlyphCount);
1.519 + le_uint16 inputGlyphCount = (le_uint16) SWAPW(backtrackCoverageTableOffsetArray[backtrkGlyphCount]);
1.520 + const Offset *inputCoverageTableOffsetArray = &backtrackCoverageTableOffsetArray[backtrkGlyphCount + 1];
1.521 + const le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputCoverageTableOffsetArray[inputGlyphCount]);
1.522 + const Offset *lookaheadCoverageTableOffsetArray = &inputCoverageTableOffsetArray[inputGlyphCount + 1];
1.523 + le_uint16 substCount = (le_uint16) SWAPW(lookaheadCoverageTableOffsetArray[lookaheadGlyphCount]);
1.524 + le_int32 position = glyphIterator->getCurrStreamPosition();
1.525 + GlyphIterator tempIterator(*glyphIterator, emptyTag);
1.526 +
1.527 + if (! tempIterator.prev(backtrkGlyphCount)) {
1.528 + return 0;
1.529 + }
1.530 +
1.531 + tempIterator.prev();
1.532 + if (! ContextualSubstitutionBase::matchGlyphCoverages(backtrackCoverageTableOffsetArray,
1.533 + backtrkGlyphCount, &tempIterator, (const char *) this, TRUE)) {
1.534 + return 0;
1.535 + }
1.536 +
1.537 + tempIterator.setCurrStreamPosition(position);
1.538 + tempIterator.next(inputGlyphCount - 1);
1.539 + if (! ContextualSubstitutionBase::matchGlyphCoverages(lookaheadCoverageTableOffsetArray,
1.540 + lookaheadGlyphCount, &tempIterator, (const char *) this)) {
1.541 + return 0;
1.542 + }
1.543 +
1.544 + // Back up the glyph iterator so that we
1.545 + // can call next() before the check, which
1.546 + // will leave it pointing at the last glyph
1.547 + // that matched when we're done.
1.548 + glyphIterator->prev();
1.549 +
1.550 + if (ContextualSubstitutionBase::matchGlyphCoverages(inputCoverageTableOffsetArray,
1.551 + inputGlyphCount, glyphIterator, (const char *) this)) {
1.552 + const SubstitutionLookupRecord *substLookupRecordArray =
1.553 + (const SubstitutionLookupRecord *) &lookaheadCoverageTableOffsetArray[lookaheadGlyphCount + 1];
1.554 +
1.555 + ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray,
1.556 + substCount, glyphIterator, fontInstance, position, success);
1.557 +
1.558 + return inputGlyphCount;
1.559 + }
1.560 +
1.561 + glyphIterator->setCurrStreamPosition(position);
1.562 +
1.563 + return 0;
1.564 +}
1.565 +
1.566 +U_NAMESPACE_END