ICU-1069 Changes to enforce a fixed feature order for Indic OT fonts.
X-SVN-Rev: 7844
This commit is contained in:
parent
8758e2858c
commit
85efdc753e
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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?
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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?
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user