1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* 2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * 3b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * (C) Copyright IBM Corp. 1998-2011 - All Rights Reserved 4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * 5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "LETypes.h" 8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "OpenTypeUtilities.h" 9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "LEFontInstance.h" 10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "OpenTypeTables.h" 1150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "ICUFeatures.h" 12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "Lookups.h" 13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ScriptAndLanguage.h" 14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "GlyphDefinitionTables.h" 15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "GlyphIterator.h" 16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "LookupProcessor.h" 17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "LEGlyphStorage.h" 18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "LESwaps.h" 19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN 21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_uint32 LookupProcessor::applyLookupTable(const LookupTable *lookupTable, GlyphIterator *glyphIterator, 23b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const LEFontInstance *fontInstance, LEErrorCode& success) const 24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 25b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (LE_FAILURE(success)) { 26b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 27b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 28b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_uint16 lookupType = SWAPW(lookupTable->lookupType); 30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_uint16 subtableCount = SWAPW(lookupTable->subTableCount); 31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_int32 startPosition = glyphIterator->getCurrStreamPosition(); 32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_uint32 delta; 33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (le_uint16 subtable = 0; subtable < subtableCount; subtable += 1) { 35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const LookupSubtable *lookupSubtable = lookupTable->getLookupSubtable(subtable); 36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 37b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru delta = applySubtable(lookupSubtable, lookupType, glyphIterator, fontInstance, success); 38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 39b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (delta > 0 && LE_FAILURE(success)) { 40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 1; 41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru glyphIterator->setCurrStreamPosition(startPosition); 44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 1; 47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments, 50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_bool rightToLeft, const GlyphDefinitionTableHeader *glyphDefinitionTableHeader, 51b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const LEFontInstance *fontInstance, LEErrorCode& success) const 52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 53b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (LE_FAILURE(success)) { 54b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 55b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 56b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_int32 glyphCount = glyphStorage.getGlyphCount(); 58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (lookupSelectArray == NULL) { 60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return glyphCount; 61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru GlyphIterator glyphIterator(glyphStorage, glyphPositionAdjustments, 64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rightToLeft, 0, 0, glyphDefinitionTableHeader); 65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_int32 newGlyphCount = glyphCount; 66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (le_uint16 order = 0; order < lookupOrderCount; order += 1) { 68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_uint16 lookup = lookupOrderArray[order]; 69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru FeatureMask selectMask = lookupSelectArray[lookup]; 70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (selectMask != 0) { 72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const LookupTable *lookupTable = lookupListTable->getLookupTable(lookup); 73b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!lookupTable) { 74b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho continue; 75b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags); 77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru glyphIterator.reset(lookupFlags, selectMask); 79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (glyphIterator.findFeatureTag()) { 81b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru applyLookupTable(lookupTable, &glyphIterator, fontInstance, success); 82b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (LE_FAILURE(success)) { 83b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 84b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru newGlyphCount = glyphIterator.applyInsertions(); 88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return newGlyphCount; 92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIterator *glyphIterator, 95b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const LEFontInstance *fontInstance, LEErrorCode& success) const 96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 97b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (LE_FAILURE(success)) { 98b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 99b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 100b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const LookupTable *lookupTable = lookupListTable->getLookupTable(lookupTableIndex); 102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags); 103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru GlyphIterator tempIterator(*glyphIterator, lookupFlags); 104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru le_uint32 delta = applyLookupTable(lookupTable, &tempIterator, fontInstance, success); 105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return delta; 107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querule_int32 LookupProcessor::selectLookups(const FeatureTable *featureTable, FeatureMask featureMask, le_int32 order) 110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_uint16 lookupCount = featureTable? SWAPW(featureTable->lookupCount) : 0; 112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_int32 store = order; 113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (le_uint16 lookup = 0; lookup < lookupCount; lookup += 1) { 115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_uint16 lookupListIndex = SWAPW(featureTable->lookupListIndexArray[lookup]); 116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (lookupListIndex >= lookupSelectCount) { 117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho continue; 118b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lookupSelectArray[lookupListIndex] |= featureMask; 121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lookupOrderArray[store++] = lookupListIndex; 122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return store - order; 125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruLookupProcessor::LookupProcessor(const char *baseAddress, 128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Offset scriptListOffset, Offset featureListOffset, Offset lookupListOffset, 129b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru LETag scriptTag, LETag languageTag, const FeatureMap *featureMap, le_int32 featureMapCount, le_bool orderFeatures, 130b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru LEErrorCode& success) 131b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho : lookupListTable(NULL), featureListTable(NULL), lookupSelectArray(NULL), lookupSelectCount(0), 132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lookupOrderArray(NULL), lookupOrderCount(0) 133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const ScriptListTable *scriptListTable = NULL; 135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const LangSysTable *langSysTable = NULL; 136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_uint16 featureCount = 0; 137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_uint16 lookupListCount = 0; 138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_uint16 requiredFeatureIndex; 139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 140b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (LE_FAILURE(success)) { 141b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (scriptListOffset != 0) { 145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru scriptListTable = (const ScriptListTable *) (baseAddress + scriptListOffset); 146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru langSysTable = scriptListTable->findLanguage(scriptTag, languageTag); 147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (langSysTable != 0) { 149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru featureCount = SWAPW(langSysTable->featureCount); 150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (featureListOffset != 0) { 154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru featureListTable = (const FeatureListTable *) (baseAddress + featureListOffset); 155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (lookupListOffset != 0) { 158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lookupListTable = (const LookupListTable *) (baseAddress + lookupListOffset); 159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lookupListCount = SWAPW(lookupListTable->lookupCount); 160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (langSysTable == NULL || featureListTable == NULL || lookupListTable == NULL || 163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru featureCount == 0 || lookupListCount == 0) { 164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru requiredFeatureIndex = SWAPW(langSysTable->reqFeatureIndex); 168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lookupSelectArray = LE_NEW_ARRAY(FeatureMask, lookupListCount); 170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (lookupSelectArray == NULL) { 171b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru success = LE_MEMORY_ALLOCATION_ERROR; 172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 173b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (int i = 0; i < lookupListCount; i += 1) { 176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lookupSelectArray[i] = 0; 177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 178b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho lookupSelectCount = lookupListCount; 179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_int32 count, order = 0; 181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_int32 featureReferences = 0; 182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const FeatureTable *featureTable = NULL; 183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru LETag featureTag; 184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const FeatureTable *requiredFeatureTable = NULL; 186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru LETag requiredFeatureTag = 0x00000000U; 187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Count the total number of lookups referenced by all features. This will 189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // be the maximum number of entries in the lookupOrderArray. We can't use 190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // lookupListCount because some lookups might be referenced by more than 191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // one feature. 192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (le_int32 feature = 0; feature < featureCount; feature += 1) { 193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]); 194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag); 196b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!featureTable) { 197b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho continue; 198b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru featureReferences += SWAPW(featureTable->lookupCount); 200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (requiredFeatureIndex != 0xFFFF) { 203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru requiredFeatureTable = featureListTable->getFeatureTable(requiredFeatureIndex, &requiredFeatureTag); 204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru featureReferences += SWAPW(featureTable->lookupCount); 205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lookupOrderArray = LE_NEW_ARRAY(le_uint16, featureReferences); 208b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (lookupOrderArray == NULL) { 209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru success = LE_MEMORY_ALLOCATION_ERROR; 210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 211b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (le_int32 f = 0; f < featureMapCount; f += 1) { 214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru FeatureMap fm = featureMap[f]; 215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru count = 0; 216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If this is the required feature, add its lookups 218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (requiredFeatureTag == fm.tag) { 219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru count += selectLookups(requiredFeatureTable, fm.mask, order); 220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (orderFeatures) { 223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If we added lookups from the required feature, sort them 224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (count > 1) { 225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru OpenTypeUtilities::sort(lookupOrderArray, order); 226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (le_uint16 feature = 0; feature < featureCount; feature += 1) { 229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]); 230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // don't add the required feature to the list more than once... 232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // TODO: Do we need this check? (Spec. says required feature won't be in feature list...) 233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (featureIndex == requiredFeatureIndex) { 234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru continue; 235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag); 238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (featureTag == fm.tag) { 240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru count += selectLookups(featureTable, fm.mask, order + count); 241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (count > 1) { 245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru OpenTypeUtilities::sort(&lookupOrderArray[order], count); 246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru order += count; 249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (le_uint16 feature = 0; feature < featureCount; feature += 1) { 251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]); 252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // don't add the required feature to the list more than once... 254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // NOTE: This check is commented out because the spec. says that 255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the required feature won't be in the feature list, and because 256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // any duplicate entries will be removed below. 257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if 0 258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (featureIndex == requiredFeatureIndex) { 259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru continue; 260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag); 264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (featureTag == fm.tag) { 266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru order += selectLookups(featureTable, fm.mask, order); 267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!orderFeatures && (order > 1)) { 273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru OpenTypeUtilities::sort(lookupOrderArray, order); 274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If there's no specified feature order, 276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // we will apply the lookups in the order 277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // that they're in the font. If a particular 278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // lookup may be referenced by more than one feature, 279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // it will apprear in the lookupOrderArray more than 280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // once, so remove any duplicate entries in the sorted array. 281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru le_int32 out = 1; 282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (le_int32 in = 1; in < order; in += 1) { 284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (lookupOrderArray[out - 1] != lookupOrderArray[in]) { 285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (out != in) { 286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lookupOrderArray[out] = lookupOrderArray[in]; 287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru out += 1; 290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru order = out; 294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lookupOrderCount = order; 297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruLookupProcessor::LookupProcessor() 300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru lookupOrderArray = NULL; 302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru lookupSelectArray = NULL; 303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruLookupProcessor::~LookupProcessor() 306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru LE_DELETE_ARRAY(lookupOrderArray); 308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru LE_DELETE_ARRAY(lookupSelectArray); 309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END 312