ICU-1069 Changes to enforce a fixed feature order for Indic OT fonts.

X-SVN-Rev: 7844
This commit is contained in:
Eric Mader 2002-03-01 22:24:10 +00:00
parent 8758e2858c
commit 85efdc753e
19 changed files with 159 additions and 26 deletions

View File

@ -6,6 +6,7 @@
*/
#include "LETypes.h"
#include "OpenTypeUtilities.h"
#include "OpenTypeTables.h"
#include "Features.h"
#include "LESwaps.h"
@ -25,4 +26,28 @@ const FeatureTable *FeatureListTable::getFeatureTable(le_uint16 featureIndex, LE
return (const FeatureTable *) ((char *) this + SWAPW(featureTableOffset));
}
const FeatureTable *FeatureListTable::getFeatureTable(LETag featureTag) const
{
#if 0
Offset featureTableOffset =
OpenTypeUtilities::getTagOffset(featureTag, (TagAndOffsetRecord *) featureRecordArray, SWAPW(featureCount));
if (featureTableOffset == 0) {
return 0;
}
return (const FeatureTable *) ((char *) this + SWAPW(featureTableOffset));
#else
int count = SWAPW(featureCount);
for (int i = 0; i < count; i += 1) {
if (SWAPT(featureRecordArray[i].featureTag) == featureTag) {
return (const FeatureTable *) ((char *) this + SWAPW(featureRecordArray[i].featureTableOffset));
}
}
return 0;
#endif
}
U_NAMESPACE_END

View File

@ -32,6 +32,8 @@ struct FeatureListTable
FeatureRecord featureRecordArray[ANY_NUMBER];
const FeatureTable *getFeatureTable(le_uint16 featureIndex, LETag *featureTag) const;
const FeatureTable *getFeatureTable(LETag featureTag) const;
};
U_NAMESPACE_END

View File

@ -20,9 +20,9 @@ void GlyphPositioningTableHeader::process(LEGlyphID *glyphs, GlyphPositionAdjust
const LETag **glyphTags, le_int32 glyphCount, le_bool rightToLeft,
LETag scriptTag, LETag languageTag,
const GlyphDefinitionTableHeader *glyphDefinitionTableHeader,
const LEFontInstance *fontInstance) const
const LEFontInstance *fontInstance, const LETag *featureOrder) const
{
GlyphPositioningLookupProcessor processor(this, scriptTag, languageTag);
GlyphPositioningLookupProcessor processor(this, scriptTag, languageTag, featureOrder);
processor.process(glyphs, glyphPositionAdjustments, glyphTags, glyphCount, rightToLeft,
glyphDefinitionTableHeader, fontInstance);

View File

@ -28,7 +28,7 @@ struct GlyphPositioningTableHeader
const LETag **glyphTags, le_int32 glyphCount,
le_bool rightToLeft, LETag scriptTag, LETag languageTag,
const GlyphDefinitionTableHeader *glyphDefinitionTableHeader,
const LEFontInstance *fontInstance) const;
const LEFontInstance *fontInstance, const LETag *featureOrder) const;
};
enum GlyphPositioningSubtableTypes

View File

@ -34,13 +34,13 @@ typedef ChainingContextualSubstitutionSubtable ChainingContextualPositioningSubt
GlyphPositioningLookupProcessor::GlyphPositioningLookupProcessor(
const GlyphPositioningTableHeader *glyphPositioningTableHeader,
LETag scriptTag, LETag languageTag)
LETag scriptTag, LETag languageTag, const LETag *featureOrder)
: LookupProcessor(
(char *) glyphPositioningTableHeader,
SWAPW(glyphPositioningTableHeader->scriptListOffset),
SWAPW(glyphPositioningTableHeader->featureListOffset),
SWAPW(glyphPositioningTableHeader->lookupListOffset),
scriptTag, languageTag)
scriptTag, languageTag, featureOrder)
{
// anything?
}

View File

@ -24,7 +24,7 @@ class GlyphPositioningLookupProcessor : public LookupProcessor
{
public:
GlyphPositioningLookupProcessor(const GlyphPositioningTableHeader *glyphPositioningTableHeader,
LETag scriptTag, LETag languageTag);
LETag scriptTag, LETag languageTag, const LETag *featureOrder);
virtual ~GlyphPositioningLookupProcessor();

View File

@ -27,13 +27,13 @@ U_NAMESPACE_BEGIN
GlyphSubstitutionLookupProcessor::GlyphSubstitutionLookupProcessor(
const GlyphSubstitutionTableHeader *glyphSubstitutionTableHeader,
LETag scriptTag, LETag languageTag, const LEGlyphFilter *filter)
LETag scriptTag, LETag languageTag, const LEGlyphFilter *filter, const LETag *featureOrder)
: LookupProcessor(
(char *) glyphSubstitutionTableHeader,
SWAPW(glyphSubstitutionTableHeader->scriptListOffset),
SWAPW(glyphSubstitutionTableHeader->featureListOffset),
SWAPW(glyphSubstitutionTableHeader->lookupListOffset),
scriptTag, languageTag), fFilter(filter)
scriptTag, languageTag, featureOrder), fFilter(filter)
{
// anything?
}

View File

@ -25,7 +25,7 @@ class GlyphSubstitutionLookupProcessor : public LookupProcessor
{
public:
GlyphSubstitutionLookupProcessor(const GlyphSubstitutionTableHeader *glyphSubstitutionTableHeader,
LETag scriptTag, LETag languageTag, const LEGlyphFilter *filter = NULL);
LETag scriptTag, LETag languageTag, const LEGlyphFilter *filter = NULL, const LETag *featureOrder = NULL);
virtual ~GlyphSubstitutionLookupProcessor();

View File

@ -21,9 +21,9 @@ U_NAMESPACE_BEGIN
void GlyphSubstitutionTableHeader::process(LEGlyphID *glyphs, const LETag **glyphTags, le_int32 glyphCount,
le_bool rightToLeft, LETag scriptTag, LETag languageTag,
const GlyphDefinitionTableHeader *glyphDefinitionTableHeader,
const LEGlyphFilter *filter) const
const LEGlyphFilter *filter, const LETag *featureOrder) const
{
GlyphSubstitutionLookupProcessor processor(this, scriptTag, languageTag, filter);
GlyphSubstitutionLookupProcessor processor(this, scriptTag, languageTag, filter, featureOrder);
processor.process(glyphs, NULL, glyphTags, glyphCount, rightToLeft, glyphDefinitionTableHeader, NULL);
}

View File

@ -27,7 +27,7 @@ struct GlyphSubstitutionTableHeader
void process(LEGlyphID *glyphs, const LETag **glyphTags, le_int32 glyphCount,
le_bool rightToLeft, LETag scriptTag, LETag languageTag,
const GlyphDefinitionTableHeader *glyphDefinitionTableHeader,
const LEGlyphFilter *filter = NULL) const;
const LEGlyphFilter *filter = NULL, const LETag *featureOrder = NULL) const;
le_bool coversScript(LETag scriptTag) const;
};

View File

@ -26,13 +26,13 @@ IndicOpenTypeLayoutEngine::IndicOpenTypeLayoutEngine(const LEFontInstance *fontI
const GlyphSubstitutionTableHeader *gsubTable)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, gsubTable)
{
// nothing else to do...
fFeatureOrder = IndicReordering::getFeatureOrder();
}
IndicOpenTypeLayoutEngine::IndicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode)
{
// nothing else to do...
fFeatureOrder = IndicReordering::getFeatureOrder();
}
IndicOpenTypeLayoutEngine::~IndicOpenTypeLayoutEngine()

View File

@ -158,12 +158,25 @@ const LETag blwmFeatureTag = 0x626C776D; // 'blwm'
const LETag abvmFeatureTag = 0x6162766D; // 'abvm'
const LETag distFeatureTag = 0x64697374; // 'dist'
// These are in the order in which the features need to be applied
// for correct processing
const LETag featureOrder[] =
{
nuktFeatureTag, akhnFeatureTag, rphfFeatureTag, blwfFeatureTag, halfFeatureTag, pstfFeatureTag,
vatuFeatureTag, presFeatureTag, blwsFeatureTag, abvsFeatureTag, pstsFeatureTag, halnFeatureTag,
blwmFeatureTag, abvmFeatureTag, distFeatureTag, emptyTag
};
// The order of these is determined so that the tag array of each glyph can start
// at an offset into this array
// FIXME: do we want a seperate tag array for each kind of character??
// FIXME: are there cases where this ordering causes glyphs to get tags
// that they shouldn't?
const LETag tagArray[] =
{
rphfFeatureTag, blwfFeatureTag, halfFeatureTag, nuktFeatureTag, akhnFeatureTag, pstfFeatureTag,
vatuFeatureTag, presFeatureTag, blwsFeatureTag, abvsFeatureTag, pstsFeatureTag, halnFeatureTag,
blwmFeatureTag, abvmFeatureTag, emptyTag
blwmFeatureTag, abvmFeatureTag, distFeatureTag, emptyTag
};
const le_int8 stateTable[][IndicClassTable::CC_COUNT] =
@ -181,6 +194,11 @@ const le_int8 stateTable[][IndicClassTable::CC_COUNT] =
};
const LETag *IndicReordering::getFeatureOrder()
{
return featureOrder;
}
le_int32 IndicReordering::findSyllable(const IndicClassTable *classTable, const LEUnicode *chars, le_int32 prev, le_int32 charCount)
{
le_int32 cursor = prev;

View File

@ -136,6 +136,8 @@ public:
static void adjustMPres(const LEUnicode *chars, le_int32 charCount, LEGlyphID *glyphs,
le_int32 *charIndices, le_int32 scriptCode);
static const LETag *getFeatureOrder();
private:
static le_int32 findSyllable(const IndicClassTable *classTable, const LEUnicode *chars, le_int32 prev, le_int32 charCount);

View File

@ -6,6 +6,7 @@
*/
#include "LETypes.h"
#include "OpenTypeUtilities.h"
#include "LEFontInstance.h"
#include "OpenTypeTables.h"
#include "Features.h"
@ -21,6 +22,8 @@ U_NAMESPACE_BEGIN
LETag LookupProcessor::notSelected = 0x00000000;
LETag LookupProcessor::defaultFeature = 0xFFFFFFFF;
LETag emptyTag = 0x00000000;
le_uint32 LookupProcessor::applyLookupTable(const LookupTable *lookupTable, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance) const
@ -53,9 +56,8 @@ void LookupProcessor::process(LEGlyphID *glyphs, GlyphPositionAdjustment *glyphP
return;
}
le_uint16 lookupListCount = SWAPW(lookupListTable->lookupCount);
for (le_uint16 lookup = 0; lookup < lookupListCount; lookup += 1) {
for (le_uint16 order = 0; order < lookupOrderCount; order += 1) {
le_uint16 lookup = lookupOrderArray[order];
LETag selectTag = lookupSelectArray[lookup];
if (selectTag != notSelected) {
@ -109,7 +111,7 @@ LETag LookupProcessor::selectFeature(le_uint16 featureIndex, LETag tagOverride)
LookupProcessor::LookupProcessor(const char *baseAddress,
Offset scriptListOffset, Offset featureListOffset, Offset lookupListOffset,
LETag scriptTag, LETag languageTag)
LETag scriptTag, LETag languageTag, const LETag *featureOrder)
: lookupListTable(NULL), featureListTable(NULL), lookupSelectArray(NULL),
requiredFeatureTag(notSelected)
{
@ -159,6 +161,54 @@ LookupProcessor::LookupProcessor(const char *baseAddress,
selectFeature(featureIndex);
}
int lookup;
lookupOrderArray = new le_uint16[lookupListCount];
// FIXME: selectFeature looks at all the lookups for a given feature, and
// so does this code. It should be possible to combine the processing:
// use a routine that takes a featureTable (or a feature index if we add
// a routine to get the feature index from the tag) dumps the lookups into
// lookupOrderArray starting at a given index, sets the lookupSelectArray,
// and returns the number of lookups added. Then both branches below can
// call the routine - the featureOrder branch will sort as it goes, and
// the other branch will sort when it's done
if (featureOrder != 0) {
int tag, order = 0;
// FIXME: figure out where the default feature goes in all of this...
// (a hack that will work for Devamt.ttf is to just put it first)
for (tag = 0; featureOrder[tag] != emptyTag; tag += 1) {
const FeatureTable *featureTable = featureListTable->getFeatureTable(featureOrder[tag]);
le_uint16 lookupCount = featureTable? SWAPW(featureTable->lookupCount) : 0;
if (featureTable != 0) {
le_uint16 lookupCount = SWAPW(featureTable->lookupCount);
for (lookup = 0; lookup < lookupCount; lookup += 1) {
lookupOrderArray[order + lookup] = SWAPW(featureTable->lookupListIndexArray[lookup]);
}
if (lookupCount > 1) {
OpenTypeUtilities::sort(&lookupOrderArray[order], lookupCount);
}
order += lookupCount;
}
}
lookupOrderCount = order;
} else {
// FIXME - lookup up the features from the featureListTable by feature index,
// and add the lookups to the lookupOrderArray in the order they come. Sort the
// whole array when finished.
for (lookup = 0; lookup < lookupListCount; lookup += 1) {
lookupOrderArray[lookup] = lookup;
}
lookupOrderCount = lookupListCount;
}
}
LookupProcessor::LookupProcessor()
@ -167,6 +217,7 @@ LookupProcessor::LookupProcessor()
LookupProcessor::~LookupProcessor()
{
delete[] lookupOrderArray;
delete[] lookupSelectArray;
};

View File

@ -40,7 +40,7 @@ public:
protected:
LookupProcessor(const char *baseAddress,
Offset scriptListOffset, Offset featureListOffset, Offset lookupListOffset,
LETag scriptTag, LETag languageTag);
LETag scriptTag, LETag languageTag, const LETag *featureOrder);
LookupProcessor();
@ -51,6 +51,9 @@ protected:
LETag *lookupSelectArray;
LETag requiredFeatureTag;
le_uint16 *lookupOrderArray;
le_uint32 lookupOrderCount;
};
U_NAMESPACE_END

View File

@ -21,7 +21,8 @@ U_NAMESPACE_BEGIN
OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
const GlyphSubstitutionTableHeader *gsubTable)
: LayoutEngine(fontInstance, scriptCode, languageCode), fFeatureTags(NULL), fGSUBTable(gsubTable), fSubstitutionFilter(NULL)
: LayoutEngine(fontInstance, scriptCode, languageCode), fFeatureTags(NULL), fGSUBTable(gsubTable),
fSubstitutionFilter(NULL), fFeatureOrder(NULL)
{
static le_uint32 gdefTableTag = 0x47444546; // "GDEF"
static le_uint32 gposTableTag = 0x47504F53; // "GPOS"
@ -52,7 +53,7 @@ void OpenTypeLayoutEngine::reset()
OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode)
: LayoutEngine(fontInstance, scriptCode, languageCode), fFeatureTags(NULL), fGSUBTable(NULL), fGDEFTable(NULL), fGPOSTable(NULL),
fSubstitutionFilter(NULL)
fSubstitutionFilter(NULL), fFeatureOrder(NULL)
{
setScriptAndLanguageTags();
}
@ -104,7 +105,7 @@ le_int32 OpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_int32
}
if (fGSUBTable != NULL) {
fGSUBTable->process(glyphs, featureTags, count, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter);
fGSUBTable->process(glyphs, featureTags, count, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter, fFeatureOrder);
}
return count;
@ -174,7 +175,7 @@ void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int3
return;
}
fGPOSTable->process(glyphs, adjustments, fFeatureTags, glyphCount, reverse, fScriptTag, fLangSysTag, fGDEFTable, fFontInstance);
fGPOSTable->process(glyphs, adjustments, fFeatureTags, glyphCount, reverse, fScriptTag, fLangSysTag, fGDEFTable, fFontInstance, fFeatureOrder);
float xAdjust = 0, yAdjust = 0;
le_int32 i;

View File

@ -1,8 +1,8 @@
/*
* %W% %W%
* %W% %E%
*
* (C) Copyright IBM Corp. 1998, 1999, 2000, 2001 - All Rights Reserved
* (C) Copyright IBM Corp. 1998, 1999, 2000, 2001, 2002 - All Rights Reserved
*
*/
@ -119,6 +119,13 @@ protected:
*/
const LETag **fFeatureTags;
/**
* A list of tags in the order in which the features in
* the font should be applied, as opposed to using the
* order of the lookups in the font.
*/
const LETag *fFeatureOrder;
/**
* The address of the GSUB table.
*/

View File

@ -164,4 +164,27 @@ le_int32 OpenTypeUtilities::search(le_uint16 value, const le_uint16 array[], le_
return index;
}
//
// Straight insertion sort from Knuth vol. III, pg. 81
//
void OpenTypeUtilities::sort(le_uint16 *array, le_int32 count)
{
for (le_int32 j = 1; j < count; j += 1) {
le_int32 i;
le_uint16 v = array[j];
for (i = j - 1; i >= 0; i -= 1) {
if (v >= array[i]) {
break;
}
array[i + 1] = array[i];
}
array[i + 1] = v;
}
}
U_NAMESPACE_END

View File

@ -21,6 +21,7 @@ public:
static le_int32 getGlyphRangeIndex(LEGlyphID glyphID, const GlyphRangeRecord *records, le_int32 recordCount);
static le_int32 search(le_uint16 value, const le_uint16 array[], le_int32 count);
static le_int32 search(le_uint32 value, const le_uint32 array[], le_int32 count);
static void sort(le_uint16 *array, le_int32 count);
};
U_NAMESPACE_END