1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 31b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert * (C) Copyright IBM Corp. 1998-2015 - 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 1759d709d503bab6e2b61931737e662dd293b40578ccorneliusle_uint32 MultipleSubstitutionSubtable::process(const LETableReference &base, 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 3659d709d503bab6e2b61931737e662dd293b40578ccornelius le_int32 coverageIndex = getGlyphCoverage(base, glyph, success); 37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 seqCount = SWAPW(sequenceCount); 381b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert LEReferenceToArrayOf<Offset> 391b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert sequenceTableOffsetArrayRef(base, success, sequenceTableOffsetArray, seqCount); 40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 411b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if (LE_FAILURE(success)) { 421b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return 0; 431b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (coverageIndex >= 0 && coverageIndex < seqCount) { 45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru Offset sequenceTableOffset = SWAPW(sequenceTableOffsetArray[coverageIndex]); 46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru const SequenceTable *sequenceTable = (const SequenceTable *) ((char *) this + sequenceTableOffset); 47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 glyphCount = SWAPW(sequenceTable->glyphCount); 48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (glyphCount == 0) { 50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphIterator->setCurrGlyphID(0xFFFF); 51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 1; 52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (glyphCount == 1) { 53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[0]); 54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (filter != NULL && ! filter->accept(LE_SET_GLYPH(glyph, substitute))) { 56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyphIterator->setCurrGlyphID(substitute); 60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 1; 61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // If there's a filter, make sure all of the output glyphs 63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // exist. 64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (filter != NULL) { 65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (le_int32 i = 0; i < glyphCount; i += 1) { 66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]); 67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (! filter->accept(substitute)) { 69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 7485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho LEGlyphID *newGlyphs = glyphIterator->insertGlyphs(glyphCount, success); 7585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (LE_FAILURE(success)) { 7685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return 0; 7785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 7885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 insert = 0, direction = 1; 80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (glyphIterator->isRightToLeft()) { 82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru insert = glyphCount - 1; 83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru direction = -1; 84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (le_int32 i = 0; i < glyphCount; i += 1) { 87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]); 88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru newGlyphs[insert] = LE_SET_GLYPH(glyph, substitute); 90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru insert += direction; 91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 1; 94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END 101