1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * (C) Copyright IBM Corp. 1998-2008 - All Rights Reserved 4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LETypes.h" 8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LEGlyphFilter.h" 9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "OpenTypeTables.h" 10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "GlyphSubstitutionTables.h" 11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "MultipleSubstSubtables.h" 12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "GlyphIterator.h" 13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LESwaps.h" 14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN 16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hole_uint32 MultipleSubstitutionSubtable::process(GlyphIterator *glyphIterator, LEErrorCode& success, const LEGlyphFilter *filter) const 18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 1985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (LE_FAILURE(success)) { 2085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return 0; 2185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 2285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru LEGlyphID glyph = glyphIterator->getCurrGlyphID(); 24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // If there's a filter, we only want to do the 26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // substitution if the *input* glyphs doesn't 27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // exist. 28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // 29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // FIXME: is this always the right thing to do? 30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // FIXME: should this only be done for a non-zero 31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // glyphCount? 32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (filter != NULL && filter->accept(glyph)) { 33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 coverageIndex = getGlyphCoverage(glyph); 37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 seqCount = SWAPW(sequenceCount); 38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (coverageIndex >= 0 && coverageIndex < seqCount) { 40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru Offset sequenceTableOffset = SWAPW(sequenceTableOffsetArray[coverageIndex]); 41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru const SequenceTable *sequenceTable = (const SequenceTable *) ((char *) this + sequenceTableOffset); 42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 glyphCount = SWAPW(sequenceTable->glyphCount); 43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (glyphCount == 0) { 45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphIterator->setCurrGlyphID(0xFFFF); 46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 1; 47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (glyphCount == 1) { 48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[0]); 49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (filter != NULL && ! filter->accept(LE_SET_GLYPH(glyph, substitute))) { 51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphIterator->setCurrGlyphID(substitute); 55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 1; 56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // If there's a filter, make sure all of the output glyphs 58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // exist. 59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (filter != NULL) { 60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (le_int32 i = 0; i < glyphCount; i += 1) { 61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]); 62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (! filter->accept(substitute)) { 64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 6985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho LEGlyphID *newGlyphs = glyphIterator->insertGlyphs(glyphCount, success); 7085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (LE_FAILURE(success)) { 7185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return 0; 7285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 7385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 insert = 0, direction = 1; 75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (glyphIterator->isRightToLeft()) { 77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru insert = glyphCount - 1; 78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru direction = -1; 79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (le_int32 i = 0; i < glyphCount; i += 1) { 82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]); 83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru newGlyphs[insert] = LE_SET_GLYPH(glyph, substitute); 85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru insert += direction; 86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 1; 89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END 96