X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/374ca955a76ecab1204ca8bfa63ff9238d998416..48b980fed3435926e0b3a8d72ecb58be703a1c7a:/icuSources/layout/LookupProcessor.cpp diff --git a/icuSources/layout/LookupProcessor.cpp b/icuSources/layout/LookupProcessor.cpp index 2fc88448..6f26a13b 100644 --- a/icuSources/layout/LookupProcessor.cpp +++ b/icuSources/layout/LookupProcessor.cpp @@ -1,6 +1,6 @@ /* * - * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved + * (C) Copyright IBM Corp. 1998-2007 - All Rights Reserved * */ @@ -12,19 +12,13 @@ #include "Lookups.h" #include "ScriptAndLanguage.h" #include "GlyphDefinitionTables.h" -#include "GlyphPositionAdjustments.h" +#include "GlyphIterator.h" #include "LookupProcessor.h" #include "LEGlyphStorage.h" #include "LESwaps.h" U_NAMESPACE_BEGIN -const LETag LookupProcessor::notSelected = 0x00000000; -const LETag LookupProcessor::defaultFeature = 0xFFFFFFFF; - -static const LETag emptyTag = 0x00000000; - - le_uint32 LookupProcessor::applyLookupTable(const LookupTable *lookupTable, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const { @@ -48,7 +42,7 @@ le_uint32 LookupProcessor::applyLookupTable(const LookupTable *lookupTable, Glyp return 1; } -le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdjustment *glyphPositionAdjustments, +le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments, le_bool rightToLeft, const GlyphDefinitionTableHeader *glyphDefinitionTableHeader, const LEFontInstance *fontInstance) const { @@ -64,20 +58,16 @@ le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdj for (le_uint16 order = 0; order < lookupOrderCount; order += 1) { le_uint16 lookup = lookupOrderArray[order]; - LETag selectTag = lookupSelectArray[lookup]; + FeatureMask selectMask = lookupSelectArray[lookup]; - if (selectTag != notSelected) { + if (selectMask != 0) { const LookupTable *lookupTable = lookupListTable->getLookupTable(lookup); le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags); - glyphIterator.reset(lookupFlags, selectTag); + glyphIterator.reset(lookupFlags, selectMask); while (glyphIterator.findFeatureTag()) { - le_uint32 delta = 1; - - while (glyphIterator.next(delta)) { - delta = applyLookupTable(lookupTable, &glyphIterator, fontInstance); - } + applyLookupTable(lookupTable, &glyphIterator, fontInstance); } newGlyphCount = glyphIterator.applyInsertions(); @@ -98,7 +88,7 @@ le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIt return delta; } -le_int32 LookupProcessor::selectLookups(const FeatureTable *featureTable, LETag featureTag, le_int32 order) +le_int32 LookupProcessor::selectLookups(const FeatureTable *featureTable, FeatureMask featureMask, le_int32 order) { le_uint16 lookupCount = featureTable? SWAPW(featureTable->lookupCount) : 0; le_int32 store = order; @@ -106,10 +96,8 @@ le_int32 LookupProcessor::selectLookups(const FeatureTable *featureTable, LETag for (le_uint16 lookup = 0; lookup < lookupCount; lookup += 1) { le_uint16 lookupListIndex = SWAPW(featureTable->lookupListIndexArray[lookup]); - if (lookupSelectArray[lookupListIndex] == notSelected) { - lookupSelectArray[lookupListIndex] = featureTag; - lookupOrderArray[store++] = lookupListIndex; - } + lookupSelectArray[lookupListIndex] |= featureMask; + lookupOrderArray[store++] = lookupListIndex; } return store - order; @@ -117,9 +105,9 @@ le_int32 LookupProcessor::selectLookups(const FeatureTable *featureTable, LETag LookupProcessor::LookupProcessor(const char *baseAddress, Offset scriptListOffset, Offset featureListOffset, Offset lookupListOffset, - LETag scriptTag, LETag languageTag, const LETag *featureOrder) + LETag scriptTag, LETag languageTag, const FeatureMap *featureMap, le_int32 featureMapCount, le_bool orderFeatures) : lookupListTable(NULL), featureListTable(NULL), lookupSelectArray(NULL), - requiredFeatureTag(notSelected), lookupOrderArray(NULL), lookupOrderCount(0) + lookupOrderArray(NULL), lookupOrderCount(0) { const ScriptListTable *scriptListTable = NULL; const LangSysTable *langSysTable = NULL; @@ -152,39 +140,66 @@ LookupProcessor::LookupProcessor(const char *baseAddress, requiredFeatureIndex = SWAPW(langSysTable->reqFeatureIndex); - lookupSelectArray = LE_NEW_ARRAY(LETag, lookupListCount); + lookupSelectArray = LE_NEW_ARRAY(FeatureMask, lookupListCount); for (int i = 0; i < lookupListCount; i += 1) { - lookupSelectArray[i] = notSelected; + lookupSelectArray[i] = 0; } le_int32 count, order = 0; - const FeatureTable *featureTable = 0; + le_int32 featureReferences = 0; + const FeatureTable *featureTable = NULL; LETag featureTag; - lookupOrderArray = LE_NEW_ARRAY(le_uint16, lookupListCount); + const FeatureTable *requiredFeatureTable = NULL; + LETag requiredFeatureTag = 0x00000000U; + + // Count the total number of lookups referenced by all features. This will + // be the maximum number of entries in the lookupOrderArray. We can't use + // lookupListCount because some lookups might be referenced by more than + // one feature. + for (le_int32 feature = 0; feature < featureCount; feature += 1) { + le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]); + + featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag); + featureReferences += SWAPW(featureTable->lookupCount); + } if (requiredFeatureIndex != 0xFFFF) { - featureTable = featureListTable->getFeatureTable(requiredFeatureIndex, &featureTag); - order += selectLookups(featureTable, defaultFeature, order); + requiredFeatureTable = featureListTable->getFeatureTable(requiredFeatureIndex, &requiredFeatureTag); + featureReferences += SWAPW(featureTable->lookupCount); } - if (featureOrder != NULL) { - if (order > 1) { - OpenTypeUtilities::sort(lookupOrderArray, order); + lookupOrderArray = LE_NEW_ARRAY(le_uint16, featureReferences); + + for (le_int32 f = 0; f < featureMapCount; f += 1) { + FeatureMap fm = featureMap[f]; + count = 0; + + // If this is the required feature, add its lookups + if (requiredFeatureTag == fm.tag) { + count += selectLookups(requiredFeatureTable, fm.mask, order); } - for (le_int32 tag = 0; featureOrder[tag] != emptyTag; tag += 1) { - featureTag = featureOrder[tag]; - count = 0; + if (orderFeatures) { + // If we added lookups from the required feature, sort them + if (count > 1) { + OpenTypeUtilities::sort(lookupOrderArray, order); + } for (le_uint16 feature = 0; feature < featureCount; feature += 1) { le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]); + + // don't add the required feature to the list more than once... + // TODO: Do we need this check? (Spec. says required feature won't be in feature list...) + if (featureIndex == requiredFeatureIndex) { + continue; + } featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag); - if (featureTag == featureOrder[tag]) { - count += selectLookups(featureTable, featureTag, order + count); + if (featureTag == fm.tag) { + count += selectLookups(featureTable, fm.mask, order + count); } } @@ -193,24 +208,51 @@ LookupProcessor::LookupProcessor(const char *baseAddress, } order += count; - } - } else { - for (le_uint16 feature = 0; feature < featureCount; feature += 1) { - le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]); + } else { + for (le_uint16 feature = 0; feature < featureCount; feature += 1) { + le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]); - // don't add the required feature to the list more than once... - if (featureIndex == requiredFeatureIndex) { - continue; - } + // don't add the required feature to the list more than once... + // NOTE: This check is commented out because the spec. says that + // the required feature won't be in the feature list, and because + // any duplicate entries will be removed below. +#if 0 + if (featureIndex == requiredFeatureIndex) { + continue; + } +#endif - featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag); - count = selectLookups(featureTable, featureTag, order); - order += count; + featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag); + + if (featureTag == fm.tag) { + order += selectLookups(featureTable, fm.mask, order); + } + } } + } + + if (!orderFeatures && (order > 1)) { + OpenTypeUtilities::sort(lookupOrderArray, order); + + // If there's no specified feature order, + // we will apply the lookups in the order + // that they're in the font. If a particular + // lookup may be referenced by more than one feature, + // it will apprear in the lookupOrderArray more than + // once, so remove any duplicate entries in the sorted array. + le_int32 out = 1; + + for (le_int32 in = 1; in < order; in += 1) { + if (lookupOrderArray[out - 1] != lookupOrderArray[in]) { + if (out != in) { + lookupOrderArray[out] = lookupOrderArray[in]; + } - if (order > 1) { - OpenTypeUtilities::sort(lookupOrderArray, order); + out += 1; + } } + + order = out; } lookupOrderCount = order; @@ -224,6 +266,6 @@ LookupProcessor::~LookupProcessor() { LE_DELETE_ARRAY(lookupOrderArray); LE_DELETE_ARRAY(lookupSelectArray); -}; +} U_NAMESPACE_END