ICU-2257 implement glyph insertion.
X-SVN-Rev: 13191
This commit is contained in:
parent
6746ee1158
commit
8fead94be5
@ -15,13 +15,79 @@
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
GlyphIterator::GlyphIterator(LEGlyphID *theGlyphs, GlyphPositionAdjustment *theGlyphPositionAdjustments, le_int32 theGlyphCount,
|
||||
le_bool rightToLeft, le_uint16 theLookupFlags, LETag theFeatureTag, const LETag *theGlyphTags[],
|
||||
const char InsertionList::fgClassID = 0;
|
||||
|
||||
InsertionList::InsertionList(le_bool rightToLeft)
|
||||
: head(NULL), tail(NULL), growAmount(0), append(rightToLeft)
|
||||
{
|
||||
tail = (InsertionRecord *) &head;
|
||||
}
|
||||
|
||||
InsertionList::~InsertionList()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void InsertionList::reset()
|
||||
{
|
||||
while (head != NULL) {
|
||||
InsertionRecord *record = head;
|
||||
|
||||
head = head->next;
|
||||
LE_DELETE_ARRAY(record);
|
||||
}
|
||||
|
||||
tail = (InsertionRecord *) &head;
|
||||
growAmount = 0;
|
||||
}
|
||||
|
||||
le_int32 InsertionList::getGrowAmount()
|
||||
{
|
||||
return growAmount;
|
||||
}
|
||||
|
||||
LEGlyphID *InsertionList::insert(le_int32 position, le_int32 count)
|
||||
{
|
||||
InsertionRecord *insertion = (InsertionRecord *) LE_NEW_ARRAY(char, sizeof(InsertionRecord) + (count - ANY_NUMBER) * sizeof (LEGlyphID));
|
||||
|
||||
insertion->position = position;
|
||||
insertion->count = count;
|
||||
|
||||
growAmount += count - 1;
|
||||
|
||||
if (append) {
|
||||
// insert on end of list...
|
||||
insertion->next = NULL;
|
||||
tail->next = insertion;
|
||||
tail = insertion;
|
||||
} else {
|
||||
// insert on front of list...
|
||||
insertion->next = head;
|
||||
head = insertion;
|
||||
}
|
||||
|
||||
return insertion->glyphs;
|
||||
}
|
||||
|
||||
le_bool InsertionList::applyInsertions(InsertionCallback *callback)
|
||||
{
|
||||
for (InsertionRecord *rec = head; rec != NULL; rec = rec->next) {
|
||||
if (callback->applyInsertion(rec->position, rec->count, rec->glyphs)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
GlyphIterator::GlyphIterator(LEGlyphID *&theGlyphs, GlyphPositionAdjustment *theGlyphPositionAdjustments, le_int32 *&theCharIndices, le_int32 theGlyphCount,
|
||||
le_bool rightToLeft, le_uint16 theLookupFlags, LETag theFeatureTag, const LETag **&theGlyphTags,
|
||||
const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader)
|
||||
: direction(1), position(-1), nextLimit(theGlyphCount), prevLimit(-1),
|
||||
cursiveFirstPosition(-1), cursiveLastPosition(-1), cursiveBaselineAdjustment(0),
|
||||
glyphs(theGlyphs), glyphPositionAdjustments(theGlyphPositionAdjustments), lookupFlags(theLookupFlags),
|
||||
featureTag(theFeatureTag), glyphTags(theGlyphTags),
|
||||
glyphsRef(&theGlyphs), glyphs(theGlyphs), glyphPositionAdjustments(theGlyphPositionAdjustments),
|
||||
charIndicesRef(&theCharIndices), charIndices(theCharIndices), glyphCount(theGlyphCount), insertionList(NULL), ownInsertionList(true), srcIndex(-1), destIndex(-1),
|
||||
lookupFlags(theLookupFlags), featureTag(theFeatureTag), glyphTagsRef(&theGlyphTags), glyphTags(theGlyphTags),
|
||||
glyphClassDefinitionTable(NULL),
|
||||
markAttachClassDefinitionTable(NULL)
|
||||
|
||||
@ -37,6 +103,8 @@ GlyphIterator::GlyphIterator(LEGlyphID *theGlyphs, GlyphPositionAdjustment *theG
|
||||
nextLimit = -1;
|
||||
prevLimit = theGlyphCount;
|
||||
}
|
||||
|
||||
insertionList = new InsertionList(rightToLeft);
|
||||
}
|
||||
|
||||
GlyphIterator::GlyphIterator(GlyphIterator &that)
|
||||
@ -49,10 +117,19 @@ GlyphIterator::GlyphIterator(GlyphIterator &that)
|
||||
cursiveFirstPosition = that.cursiveFirstPosition;
|
||||
cursiveLastPosition = that.cursiveLastPosition;
|
||||
|
||||
glyphs = that.glyphs;
|
||||
glyphsRef = that.glyphsRef;
|
||||
glyphs = that.glyphs;
|
||||
glyphPositionAdjustments = that.glyphPositionAdjustments;
|
||||
charIndicesRef = that.charIndicesRef;
|
||||
charIndices = that.charIndices;
|
||||
glyphCount = that.glyphCount;
|
||||
insertionList = that.insertionList;
|
||||
ownInsertionList = false;
|
||||
srcIndex = that.srcIndex;
|
||||
destIndex = that.destIndex;
|
||||
lookupFlags = that.lookupFlags;
|
||||
featureTag = that.featureTag;
|
||||
glyphTagsRef = that.glyphTagsRef;
|
||||
glyphTags = that.glyphTags;
|
||||
glyphClassDefinitionTable = that.glyphClassDefinitionTable;
|
||||
markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
|
||||
@ -68,10 +145,19 @@ GlyphIterator::GlyphIterator(GlyphIterator &that, LETag newFeatureTag)
|
||||
cursiveFirstPosition = that.cursiveFirstPosition;
|
||||
cursiveLastPosition = that.cursiveLastPosition;
|
||||
|
||||
glyphs = that.glyphs;
|
||||
glyphsRef = that.glyphsRef;
|
||||
glyphs = that.glyphs;
|
||||
glyphPositionAdjustments = that.glyphPositionAdjustments;
|
||||
charIndicesRef = that.charIndicesRef;
|
||||
charIndices = that.charIndices;
|
||||
glyphCount = that.glyphCount;
|
||||
insertionList = that.insertionList;
|
||||
ownInsertionList = false;
|
||||
srcIndex = that.srcIndex;
|
||||
destIndex = that.destIndex;
|
||||
lookupFlags = that.lookupFlags;
|
||||
featureTag = newFeatureTag;
|
||||
glyphTagsRef = that.glyphTagsRef;
|
||||
glyphTags = that.glyphTags;
|
||||
glyphClassDefinitionTable = that.glyphClassDefinitionTable;
|
||||
markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
|
||||
@ -88,10 +174,19 @@ GlyphIterator::GlyphIterator(GlyphIterator &that, le_uint16 newLookupFlags)
|
||||
cursiveFirstPosition = that.cursiveFirstPosition;
|
||||
cursiveLastPosition = that.cursiveLastPosition;
|
||||
|
||||
glyphsRef = that.glyphsRef;
|
||||
glyphs = that.glyphs;
|
||||
glyphPositionAdjustments = that.glyphPositionAdjustments;
|
||||
charIndicesRef = that.charIndicesRef;
|
||||
charIndices = that.charIndices;
|
||||
glyphCount = that.glyphCount;
|
||||
insertionList = that.insertionList;
|
||||
ownInsertionList = false;
|
||||
srcIndex = that.srcIndex;
|
||||
destIndex = that.destIndex;
|
||||
lookupFlags = newLookupFlags;
|
||||
featureTag = that.featureTag;
|
||||
glyphTagsRef = that.glyphTagsRef;
|
||||
glyphTags = that.glyphTags;
|
||||
glyphClassDefinitionTable = that.glyphClassDefinitionTable;
|
||||
markAttachClassDefinitionTable = that.markAttachClassDefinitionTable;
|
||||
@ -103,6 +198,92 @@ GlyphIterator::GlyphIterator()
|
||||
|
||||
GlyphIterator::~GlyphIterator()
|
||||
{
|
||||
if (ownInsertionList) {
|
||||
delete insertionList;
|
||||
}
|
||||
}
|
||||
|
||||
void GlyphIterator::reset(le_uint16 newLookupFlags, LETag newFeatureTag)
|
||||
{
|
||||
position = prevLimit;
|
||||
featureTag = newFeatureTag;
|
||||
lookupFlags = newLookupFlags;
|
||||
}
|
||||
|
||||
LEGlyphID *GlyphIterator::insertGlyphs(le_int32 count)
|
||||
{
|
||||
return insertionList->insert(position, count);
|
||||
}
|
||||
|
||||
le_int32 GlyphIterator::applyInsertions()
|
||||
{
|
||||
le_int32 growAmount = insertionList->getGrowAmount();
|
||||
|
||||
if (growAmount == 0) {
|
||||
return glyphCount;
|
||||
}
|
||||
|
||||
le_int32 newGlyphCount = glyphCount + growAmount;
|
||||
le_int32 dest = newGlyphCount - 1;
|
||||
|
||||
*glyphsRef = glyphs = (LEGlyphID *) LE_GROW_ARRAY(glyphs, newGlyphCount);
|
||||
*glyphTagsRef = glyphTags = (const LETag **) LE_GROW_ARRAY(glyphTags, newGlyphCount);
|
||||
*charIndicesRef = charIndices = (le_int32 *) LE_GROW_ARRAY(charIndices, newGlyphCount);
|
||||
|
||||
srcIndex = glyphCount - 1;
|
||||
destIndex = newGlyphCount - 1;
|
||||
|
||||
// If the current position is at the end of the array
|
||||
// update it to point to the end of the new array. The
|
||||
// insertion callback will handle all other cases.
|
||||
if (position == glyphCount) {
|
||||
position = newGlyphCount;
|
||||
}
|
||||
|
||||
insertionList->applyInsertions(this);
|
||||
|
||||
insertionList->reset();
|
||||
|
||||
if (direction < 0) {
|
||||
prevLimit = newGlyphCount;
|
||||
} else {
|
||||
nextLimit = newGlyphCount;
|
||||
}
|
||||
|
||||
return glyphCount = newGlyphCount;
|
||||
}
|
||||
|
||||
le_bool GlyphIterator::applyInsertion(le_int32 atPosition, le_int32 count, LEGlyphID newGlyphs[])
|
||||
{
|
||||
// if the current position is within the block we're shifting
|
||||
// it needs to be updated to the current glyph's
|
||||
// new location.
|
||||
if (position >= atPosition && position <= srcIndex) {
|
||||
position += destIndex - srcIndex;
|
||||
}
|
||||
|
||||
while (srcIndex > atPosition) {
|
||||
glyphs[destIndex] = glyphs[srcIndex];
|
||||
glyphTags[destIndex] = glyphTags[srcIndex];
|
||||
charIndices[destIndex] = charIndices[srcIndex];
|
||||
|
||||
destIndex -= 1;
|
||||
srcIndex -= 1;
|
||||
}
|
||||
|
||||
for (le_int32 i = count - 1; i >= 0; i -= 1) {
|
||||
glyphs[destIndex] = newGlyphs[i];
|
||||
glyphTags[destIndex] = glyphTags[atPosition];
|
||||
charIndices[destIndex] = charIndices[atPosition];
|
||||
|
||||
destIndex -= 1;
|
||||
}
|
||||
|
||||
// the source glyph we're pointing at
|
||||
// just got replaced by the insertion
|
||||
srcIndex -= 1;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
le_int32 GlyphIterator::getCurrStreamPosition() const
|
||||
|
@ -20,10 +20,66 @@
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class GlyphIterator : public UMemory {
|
||||
struct InsertionRecord
|
||||
{
|
||||
InsertionRecord *next;
|
||||
le_int32 position;
|
||||
le_int32 count;
|
||||
LEGlyphID glyphs[ANY_NUMBER];
|
||||
};
|
||||
|
||||
class InsertionCallback
|
||||
{
|
||||
public:
|
||||
GlyphIterator(LEGlyphID *theGlyphs, GlyphPositionAdjustment *theGlyphPositionAdjustments, le_int32 theGlyphCount,
|
||||
le_bool rightToLeft, le_uint16 theLookupFlags, LETag theFeatureTag, const LETag *theGlyphTags[],
|
||||
virtual le_bool applyInsertion(le_int32 atPosition, le_int32 count, LEGlyphID newGlyphs[]) = 0;
|
||||
};
|
||||
|
||||
class InsertionList : public UObject
|
||||
{
|
||||
public:
|
||||
InsertionList(le_bool rightToLeft);
|
||||
~InsertionList();
|
||||
|
||||
LEGlyphID *insert(le_int32 position, le_int32 count);
|
||||
le_int32 getGrowAmount();
|
||||
|
||||
le_bool applyInsertions(InsertionCallback *callback);
|
||||
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* ICU "poor man's RTTI", returns a UClassID for the actual class.
|
||||
*
|
||||
* @draft ICU 2.2
|
||||
*/
|
||||
virtual inline UClassID getDynamicClassID() const { return getStaticClassID(); }
|
||||
|
||||
/**
|
||||
* ICU "poor man's RTTI", returns a UClassID for this class.
|
||||
*
|
||||
* @draft ICU 2.2
|
||||
*/
|
||||
static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; }
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* The address of this static class variable serves as this class's ID
|
||||
* for ICU "poor man's RTTI".
|
||||
*/
|
||||
static const char fgClassID;
|
||||
|
||||
InsertionRecord *head;
|
||||
InsertionRecord *tail;
|
||||
|
||||
le_int32 growAmount;
|
||||
le_bool append;
|
||||
};
|
||||
|
||||
class GlyphIterator : public UMemory, protected InsertionCallback {
|
||||
public:
|
||||
GlyphIterator(LEGlyphID *&theGlyphs, GlyphPositionAdjustment *theGlyphPositionAdjustments, le_int32 *&theCharIndices, le_int32 theGlyphCount,
|
||||
le_bool rightToLeft, le_uint16 theLookupFlags, LETag theFeatureTag, const LETag **&theGlyphTags,
|
||||
const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader);
|
||||
|
||||
GlyphIterator(GlyphIterator &that);
|
||||
@ -34,6 +90,8 @@ public:
|
||||
|
||||
~GlyphIterator();
|
||||
|
||||
void reset(le_uint16 newLookupFlags, LETag newFeatureTag);
|
||||
|
||||
le_bool next(le_uint32 delta = 1);
|
||||
le_bool prev(le_uint32 delta = 1);
|
||||
le_bool findFeatureTag();
|
||||
@ -71,6 +129,12 @@ public:
|
||||
void adjustCursiveLastGlyphPositionAdjustment(float xPlacmentAdjust, float yPlacementAdjust,
|
||||
float xAdvanceAdjust, float yAdvanceAdjust);
|
||||
|
||||
LEGlyphID *insertGlyphs(le_int32 count);
|
||||
le_int32 applyInsertions();
|
||||
|
||||
protected:
|
||||
virtual le_bool applyInsertion(le_int32 atPosition, le_int32 count, LEGlyphID newGlyphs[]);
|
||||
|
||||
private:
|
||||
GlyphIterator();
|
||||
le_bool filterGlyph(le_uint32 index) const;
|
||||
@ -86,10 +150,19 @@ private:
|
||||
le_int32 cursiveLastPosition;
|
||||
float cursiveBaselineAdjustment;
|
||||
LEPoint cursiveLastExitPoint;
|
||||
LEGlyphID **glyphsRef;
|
||||
LEGlyphID *glyphs;
|
||||
GlyphPositionAdjustment *glyphPositionAdjustments;
|
||||
le_int32 **charIndicesRef;
|
||||
le_int32 *charIndices;
|
||||
le_int32 glyphCount;
|
||||
InsertionList *insertionList;
|
||||
le_bool ownInsertionList;
|
||||
le_int32 srcIndex;
|
||||
le_int32 destIndex;
|
||||
le_uint16 lookupFlags;
|
||||
LETag featureTag;
|
||||
const LETag ***glyphTagsRef;
|
||||
const LETag **glyphTags;
|
||||
const GlyphClassDefinitionTable *glyphClassDefinitionTable;
|
||||
const MarkAttachClassDefinitionTable *markAttachClassDefinitionTable;
|
||||
|
@ -23,8 +23,9 @@ void GlyphPositioningTableHeader::process(LEGlyphID *glyphs, GlyphPositionAdjust
|
||||
const LEFontInstance *fontInstance, const LETag *featureOrder) const
|
||||
{
|
||||
GlyphPositioningLookupProcessor processor(this, scriptTag, languageTag, featureOrder);
|
||||
le_int32 *charIndices = NULL;
|
||||
|
||||
processor.process(glyphs, glyphPositionAdjustments, glyphTags, glyphCount, rightToLeft,
|
||||
processor.process(glyphs, glyphPositionAdjustments, glyphTags, charIndices, glyphCount, rightToLeft,
|
||||
glyphDefinitionTableHeader, fontInstance);
|
||||
}
|
||||
|
||||
|
@ -18,14 +18,14 @@
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
void GlyphSubstitutionTableHeader::process(LEGlyphID *glyphs, const LETag **glyphTags, le_int32 glyphCount,
|
||||
le_int32 GlyphSubstitutionTableHeader::process(LEGlyphID *&glyphs, const LETag **&glyphTags, le_int32 *&charIndices, le_int32 glyphCount,
|
||||
le_bool rightToLeft, LETag scriptTag, LETag languageTag,
|
||||
const GlyphDefinitionTableHeader *glyphDefinitionTableHeader,
|
||||
const LEGlyphFilter *filter, const LETag *featureOrder) const
|
||||
{
|
||||
GlyphSubstitutionLookupProcessor processor(this, scriptTag, languageTag, filter, featureOrder);
|
||||
|
||||
processor.process(glyphs, NULL, glyphTags, glyphCount, rightToLeft, glyphDefinitionTableHeader, NULL);
|
||||
return processor.process(glyphs, NULL, glyphTags, charIndices, glyphCount, rightToLeft, glyphDefinitionTableHeader, NULL);
|
||||
}
|
||||
|
||||
le_bool GlyphSubstitutionTableHeader::coversScript(LETag scriptTag) const
|
||||
|
@ -29,7 +29,7 @@ struct GlyphSubstitutionTableHeader
|
||||
Offset featureListOffset;
|
||||
Offset lookupListOffset;
|
||||
|
||||
void process(LEGlyphID *glyphs, const LETag **glyphTags, le_int32 glyphCount,
|
||||
le_int32 process(LEGlyphID *&glyphs, const LETag **&glyphTags, le_int32 *&charIndices, le_int32 glyphCount,
|
||||
le_bool rightToLeft, LETag scriptTag, LETag languageTag,
|
||||
const GlyphDefinitionTableHeader *glyphDefinitionTableHeader,
|
||||
const LEGlyphFilter *filter = NULL, const LETag *featureOrder = NULL) const;
|
||||
|
@ -48,14 +48,18 @@ le_uint32 LookupProcessor::applyLookupTable(const LookupTable *lookupTable, Glyp
|
||||
return 1;
|
||||
}
|
||||
|
||||
void LookupProcessor::process(LEGlyphID *glyphs, GlyphPositionAdjustment *glyphPositionAdjustments, const LETag **glyphTags, le_int32 glyphCount,
|
||||
le_int32 LookupProcessor::process(LEGlyphID *&glyphs, GlyphPositionAdjustment *glyphPositionAdjustments, const LETag **&glyphTags, le_int32 *&charIndices, le_int32 glyphCount,
|
||||
le_bool rightToLeft, const GlyphDefinitionTableHeader *glyphDefinitionTableHeader,
|
||||
const LEFontInstance *fontInstance) const
|
||||
{
|
||||
if (lookupSelectArray == NULL) {
|
||||
return;
|
||||
return glyphCount;
|
||||
}
|
||||
|
||||
GlyphIterator glyphIterator(glyphs, glyphPositionAdjustments, charIndices, glyphCount,
|
||||
rightToLeft, 0, 0, glyphTags, glyphDefinitionTableHeader);
|
||||
le_int32 newGlyphCount = glyphCount;
|
||||
|
||||
for (le_uint16 order = 0; order < lookupOrderCount; order += 1) {
|
||||
le_uint16 lookup = lookupOrderArray[order];
|
||||
LETag selectTag = lookupSelectArray[lookup];
|
||||
@ -63,9 +67,8 @@ void LookupProcessor::process(LEGlyphID *glyphs, GlyphPositionAdjustment *glyphP
|
||||
if (selectTag != notSelected) {
|
||||
const LookupTable *lookupTable = lookupListTable->getLookupTable(lookup);
|
||||
le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags);
|
||||
GlyphIterator glyphIterator(glyphs, glyphPositionAdjustments, glyphCount,
|
||||
rightToLeft, lookupFlags, selectTag, glyphTags,
|
||||
glyphDefinitionTableHeader);
|
||||
|
||||
glyphIterator.reset(lookupFlags, selectTag);
|
||||
|
||||
while (glyphIterator.findFeatureTag()) {
|
||||
le_uint32 delta = 1;
|
||||
@ -74,8 +77,12 @@ void LookupProcessor::process(LEGlyphID *glyphs, GlyphPositionAdjustment *glyphP
|
||||
delta = applyLookupTable(lookupTable, &glyphIterator, fontInstance);
|
||||
}
|
||||
}
|
||||
|
||||
newGlyphCount = glyphIterator.applyInsertions();
|
||||
}
|
||||
}
|
||||
|
||||
return newGlyphCount;
|
||||
}
|
||||
|
||||
le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIterator *glyphIterator,
|
||||
|
@ -29,7 +29,7 @@ public:
|
||||
static const LETag notSelected;
|
||||
static const LETag defaultFeature;
|
||||
|
||||
void process(LEGlyphID *glyphs, GlyphPositionAdjustment *glyphPositionAdjustments, const LETag **glyphTags, le_int32 glyphCount,
|
||||
le_int32 process(LEGlyphID *&glyphs, GlyphPositionAdjustment *glyphPositionAdjustments, const LETag **&glyphTags, le_int32 *&charIndices, le_int32 glyphCount,
|
||||
le_bool rightToLeft, const GlyphDefinitionTableHeader *glyphDefinitionTableHeader, const LEFontInstance *fontInstance) const;
|
||||
|
||||
le_uint32 applyLookupTable(const LookupTable *lookupTable, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
|
||||
|
@ -2,8 +2,8 @@
|
||||
* (C) Copyright IBM Corp. 2002-2003 - All Rights Reserved
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu/source/layout/MPreFixups.h,v $
|
||||
* $Date: 2003/06/03 20:58:22 $
|
||||
* $Revision: 1.3 $
|
||||
* $Date: 2003/09/24 21:05:13 $
|
||||
* $Revision: 1.4 $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -30,7 +30,7 @@ public:
|
||||
|
||||
void add(le_int32 baseIndex, le_int32 mpreIndex);
|
||||
|
||||
void apply(LEGlyphID *glyphs, le_int32 *charIndicies);
|
||||
void apply(LEGlyphID *glyphs, le_int32 *charIndices);
|
||||
|
||||
private:
|
||||
FixupData *fFixupData;
|
||||
|
@ -29,7 +29,7 @@ le_uint32 MultipleSubstitutionSubtable::process(GlyphIterator *glyphIterator, co
|
||||
if (glyphCount == 0) {
|
||||
glyphIterator->setCurrGlyphID(0xFFFF);
|
||||
return 1;
|
||||
} else if (glyphCount >= 1) {
|
||||
} else if (glyphCount == 1) {
|
||||
TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[0]);
|
||||
|
||||
if (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, substitute))) {
|
||||
@ -38,8 +38,21 @@ le_uint32 MultipleSubstitutionSubtable::process(GlyphIterator *glyphIterator, co
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
// Can't do this 'till there's a way to
|
||||
// grow the glyph array...
|
||||
LEGlyphID *newGlyphs = glyphIterator->insertGlyphs(glyphCount);
|
||||
le_int32 insert = 0, direction = 1;
|
||||
|
||||
if (glyphIterator->isRightToLeft()) {
|
||||
insert = glyphCount - 1;
|
||||
direction = -1;
|
||||
}
|
||||
|
||||
for (le_int32 i = 0; i < glyphCount; i += 1) {
|
||||
TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]);
|
||||
|
||||
newGlyphs[insert] = LE_SET_GLYPH(glyph, substitute);
|
||||
insert += direction;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -109,8 +109,8 @@ le_int32 OpenTypeLayoutEngine::characterProcessing(const LEUnicode /*chars*/[],
|
||||
|
||||
// Input: characters, tags
|
||||
// Output: glyphs, char indices
|
||||
le_int32 OpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, const LETag **featureTags,
|
||||
LEGlyphID *&glyphs, le_int32 *&charIndices, LEErrorCode &success)
|
||||
le_int32 OpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
|
||||
const LETag **&featureTags, LEGlyphID *&glyphs, le_int32 *&charIndices, LEErrorCode &success)
|
||||
{
|
||||
if (LE_FAILURE(success)) {
|
||||
return 0;
|
||||
@ -128,7 +128,7 @@ le_int32 OpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_int32
|
||||
}
|
||||
|
||||
if (fGSUBTable != NULL) {
|
||||
fGSUBTable->process(glyphs, featureTags, count, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter, fFeatureOrder);
|
||||
count = fGSUBTable->process(glyphs, featureTags, charIndices, count, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter, fFeatureOrder);
|
||||
}
|
||||
|
||||
return count;
|
||||
|
@ -270,7 +270,7 @@ protected:
|
||||
* @internal
|
||||
*/
|
||||
virtual le_int32 glyphProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
|
||||
const LETag **featureTags, LEGlyphID *&glyphs, le_int32 *&charIndices, LEErrorCode &success);
|
||||
const LETag **&featureTags, LEGlyphID *&glyphs, le_int32 *&charIndices, LEErrorCode &success);
|
||||
|
||||
/**
|
||||
* This method does any processing necessary to convert "fake"
|
||||
|
@ -143,36 +143,36 @@ LEUnicode ThaiShaping::noDescenderCOD(LEUnicode cod, le_uint8 glyphSet)
|
||||
}
|
||||
|
||||
le_uint8 ThaiShaping::doTransition (StateTransition transition, LEUnicode currChar, le_int32 inputIndex, le_uint8 glyphSet,
|
||||
LEUnicode errorChar, LEUnicode *outputBuffer, le_int32 *charIndicies, le_int32 &outputIndex)
|
||||
LEUnicode errorChar, LEUnicode *outputBuffer, le_int32 *charIndices, le_int32 &outputIndex)
|
||||
{
|
||||
switch (transition.action) {
|
||||
case tA:
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
charIndices[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = currChar;
|
||||
break;
|
||||
|
||||
case tC:
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
charIndices[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = currChar;
|
||||
break;
|
||||
|
||||
case tD:
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
charIndices[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = leftAboveVowel(currChar, glyphSet);
|
||||
break;
|
||||
|
||||
case tE:
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
charIndices[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = lowerRightTone(currChar, glyphSet);
|
||||
break;
|
||||
|
||||
case tF:
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
charIndices[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = lowerLeftTone(currChar, glyphSet);
|
||||
break;
|
||||
|
||||
case tG:
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
charIndices[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = upperLeftTone(currChar, glyphSet);
|
||||
break;
|
||||
|
||||
@ -184,38 +184,38 @@ le_uint8 ThaiShaping::doTransition (StateTransition transition, LEUnicode currCh
|
||||
if (cod != coa) {
|
||||
outputBuffer[outputIndex - 1] = coa;
|
||||
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
charIndices[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = currChar;
|
||||
break;
|
||||
}
|
||||
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
charIndices[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = lowerBelowVowel(currChar, glyphSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case tR:
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
charIndices[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = errorChar;
|
||||
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
charIndices[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = currChar;
|
||||
break;
|
||||
|
||||
case tS:
|
||||
if (currChar == CH_SARA_AM) {
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
charIndices[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = errorChar;
|
||||
}
|
||||
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
charIndices[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = currChar;
|
||||
break;
|
||||
|
||||
default:
|
||||
// FIXME: if we get here, there's an error
|
||||
// in the state table!
|
||||
charIndicies[outputIndex] = inputIndex;
|
||||
charIndices[outputIndex] = inputIndex;
|
||||
outputBuffer[outputIndex++] = currChar;
|
||||
break;
|
||||
}
|
||||
@ -224,14 +224,14 @@ le_uint8 ThaiShaping::doTransition (StateTransition transition, LEUnicode currCh
|
||||
}
|
||||
|
||||
le_uint8 ThaiShaping::getNextState(LEUnicode ch, le_uint8 prevState, le_int32 inputIndex, le_uint8 glyphSet, LEUnicode errorChar,
|
||||
le_uint8 &charClass, LEUnicode *output, le_int32 *charIndicies, le_int32 &outputIndex)
|
||||
le_uint8 &charClass, LEUnicode *output, le_int32 *charIndices, le_int32 &outputIndex)
|
||||
{
|
||||
StateTransition transition;
|
||||
|
||||
charClass = getCharClass(ch);
|
||||
transition = getTransition(prevState, charClass);
|
||||
|
||||
return doTransition(transition, ch, inputIndex, glyphSet, errorChar, output, charIndicies, outputIndex);
|
||||
return doTransition(transition, ch, inputIndex, glyphSet, errorChar, output, charIndices, outputIndex);
|
||||
}
|
||||
|
||||
le_bool ThaiShaping::isLegalHere(LEUnicode ch, le_uint8 prevState)
|
||||
@ -261,7 +261,7 @@ le_bool ThaiShaping::isLegalHere(LEUnicode ch, le_uint8 prevState)
|
||||
}
|
||||
|
||||
le_int32 ThaiShaping::compose(const LEUnicode *input, le_int32 offset, le_int32 charCount, le_uint8 glyphSet,
|
||||
LEUnicode errorChar, LEUnicode *output, le_int32 *charIndicies)
|
||||
LEUnicode errorChar, LEUnicode *output, le_int32 *charIndices)
|
||||
{
|
||||
le_uint8 state = 0;
|
||||
le_int32 inputIndex;
|
||||
@ -278,19 +278,19 @@ le_int32 ThaiShaping::compose(const LEUnicode *input, le_int32 offset, le_int32
|
||||
if (ch == CH_SARA_AM && isLegalHere(ch, state)) {
|
||||
outputIndex = conOutput;
|
||||
state = getNextState(CH_NIKHAHIT, conState, inputIndex, glyphSet, errorChar, charClass,
|
||||
output, charIndicies, outputIndex);
|
||||
output, charIndices, outputIndex);
|
||||
|
||||
for (int j = conInput + 1; j < inputIndex; j += 1) {
|
||||
ch = input[j + offset];
|
||||
state = getNextState(ch, state, j, glyphSet, errorChar, charClass,
|
||||
output, charIndicies, outputIndex);
|
||||
output, charIndices, outputIndex);
|
||||
}
|
||||
|
||||
ch = CH_SARA_AA;
|
||||
}
|
||||
|
||||
state = getNextState(ch, state, inputIndex, glyphSet, errorChar, charClass,
|
||||
output, charIndicies, outputIndex);
|
||||
output, charIndices, outputIndex);
|
||||
|
||||
if (charClass >= CON && charClass <= COD) {
|
||||
conState = state;
|
||||
|
@ -67,7 +67,7 @@ public:
|
||||
};
|
||||
|
||||
static le_int32 compose(const LEUnicode *input, le_int32 offset, le_int32 charCount, le_uint8 glyphSet,
|
||||
LEUnicode errorChar, LEUnicode *output, le_int32 *charIndicies);
|
||||
LEUnicode errorChar, LEUnicode *output, le_int32 *charIndices);
|
||||
|
||||
private:
|
||||
// forbid instantiation
|
||||
@ -78,10 +78,10 @@ private:
|
||||
|
||||
static StateTransition getTransition(le_uint8 state, le_uint8 currClass);
|
||||
static le_uint8 doTransition(StateTransition transition, LEUnicode currChar, le_int32 inputIndex, le_uint8 glyphSet,
|
||||
LEUnicode errorChar, LEUnicode *outputBuffer, le_int32 *charIndicies, le_int32 &outputIndex);
|
||||
LEUnicode errorChar, LEUnicode *outputBuffer, le_int32 *charIndices, le_int32 &outputIndex);
|
||||
|
||||
static le_uint8 getNextState(LEUnicode ch, le_uint8 state, le_int32 inputIndex, le_uint8 glyphSet, LEUnicode errorChar,
|
||||
le_uint8 &charClass, LEUnicode *output, le_int32 *charIndicies, le_int32 &outputIndex);
|
||||
le_uint8 &charClass, LEUnicode *output, le_int32 *charIndices, le_int32 &outputIndex);
|
||||
|
||||
static le_bool isLegalHere(LEUnicode ch, le_uint8 prevState);
|
||||
static le_uint8 getCharClass(LEUnicode ch);
|
||||
|
@ -221,7 +221,7 @@ ParagraphLayout::ParagraphLayout(const LEUnicode chars[], le_int32 count,
|
||||
fFontRuns(NULL), fLevelRuns(levelRuns), fScriptRuns(scriptRuns), fLocaleRuns(localeRuns),
|
||||
fVertical(vertical), fClientLevels(true), fClientScripts(true), fClientLocales(true), fEmbeddingLevels(NULL),
|
||||
fAscent(0), fDescent(0), fLeading(0),
|
||||
fGlyphToCharMap(NULL), fCharToGlyphMap(NULL), fGlyphWidths(NULL), fGlyphCount(0),
|
||||
fGlyphToCharMap(NULL), fCharToMinGlyphMap(NULL), fCharToMaxGlyphMap(NULL), fGlyphWidths(NULL), fGlyphCount(0),
|
||||
fParaBidi(NULL), fLineBidi(NULL),
|
||||
fStyleRunLimits(NULL), fStyleIndices(NULL), fStyleRunCount(0),
|
||||
fBreakIterator(NULL), fLineStart(-1), fLineEnd(0),
|
||||
@ -287,17 +287,19 @@ ParagraphLayout::ParagraphLayout(const LEUnicode chars[], le_int32 count,
|
||||
//
|
||||
// For each layout get the positions and convert them into glyph widths, in
|
||||
// logical order. Get the glyph-to-char mapping, offset by starting index in the
|
||||
// width array, and swap it into logical order. Then fill in the char-to-glyph map
|
||||
// from this. (charToGlyph[glyphToChar[i]] = i)
|
||||
fGlyphWidths = LE_NEW_ARRAY(float, fGlyphCount);
|
||||
fGlyphToCharMap = LE_NEW_ARRAY(le_int32, fGlyphCount + 1);
|
||||
fCharToGlyphMap = LE_NEW_ARRAY(le_int32, fCharCount + 1);
|
||||
// character array. Swap the glyph width and glyph-to-char arrays into logical order.
|
||||
// Finally, fill in the char-to-glyph mappings.
|
||||
fGlyphWidths = LE_NEW_ARRAY(float, fGlyphCount);
|
||||
fGlyphToCharMap = LE_NEW_ARRAY(le_int32, fGlyphCount + 1);
|
||||
fCharToMinGlyphMap = LE_NEW_ARRAY(le_int32, fCharCount + 1);
|
||||
fCharToMaxGlyphMap = LE_NEW_ARRAY(le_int32, fCharCount + 1);
|
||||
|
||||
le_int32 glyph;
|
||||
|
||||
for (runStart = 0, run = 0; run < fStyleRunCount; run += 1) {
|
||||
LayoutEngine *engine = fStyleRunInfo[run].engine;
|
||||
le_int32 glyphCount = fStyleRunInfo[run].glyphCount;
|
||||
le_int32 glyphBase = fStyleRunInfo[run].glyphBase;
|
||||
le_int32 glyph;
|
||||
|
||||
fStyleRunInfo[run].glyphs = LE_NEW_ARRAY(LEGlyphID, glyphCount);
|
||||
fStyleRunInfo[run].positions = LE_NEW_ARRAY(float, glyphCount * 2 + 2);
|
||||
@ -308,23 +310,11 @@ ParagraphLayout::ParagraphLayout(const LEUnicode chars[], le_int32 count,
|
||||
|
||||
for (glyph = 0; glyph < glyphCount; glyph += 1) {
|
||||
fGlyphWidths[glyphBase + glyph] = fStyleRunInfo[run].positions[glyph * 2 + 2] - fStyleRunInfo[run].positions[glyph * 2];
|
||||
fCharToGlyphMap[fGlyphToCharMap[glyphBase + glyph]] = glyphBase + glyph;
|
||||
}
|
||||
|
||||
if ((fStyleRunInfo[run].level & 1) != 0) {
|
||||
LXUtilities::reverse(&fGlyphWidths[glyphBase], glyphCount);
|
||||
LXUtilities::reverse(&fGlyphToCharMap[glyphBase], glyphCount);
|
||||
|
||||
// LXUtilities::reverse(&fCharToGlyphMap[runStart], fStyleRunLimits[run] - runStart);
|
||||
// convert from visual to logical glyph indices
|
||||
for (glyph = glyphBase; glyph < glyphBase + glyphCount; glyph += 1) {
|
||||
le_int32 ch = fGlyphToCharMap[glyph];
|
||||
le_int32 lastGlyph = glyphBase + glyphCount - 1;
|
||||
|
||||
// both lastGlyph and fCharToGlyphMap[ch] are biased by
|
||||
// glyphBase, so subtracting them will remove the bias.
|
||||
fCharToGlyphMap[ch] = lastGlyph - fCharToGlyphMap[ch] + glyphBase;
|
||||
}
|
||||
}
|
||||
|
||||
runStart = fStyleRunLimits[run];
|
||||
@ -333,8 +323,23 @@ ParagraphLayout::ParagraphLayout(const LEUnicode chars[], le_int32 count,
|
||||
fStyleRunInfo[run].engine = NULL;
|
||||
}
|
||||
|
||||
fCharToGlyphMap[fCharCount] = fGlyphCount;
|
||||
fGlyphToCharMap[fGlyphCount] = fCharCount;
|
||||
|
||||
for (glyph = fGlyphCount - 1; glyph >= 0; glyph -= 1) {
|
||||
le_int32 ch = fGlyphToCharMap[glyph];
|
||||
|
||||
fCharToMinGlyphMap[ch] = glyph;
|
||||
}
|
||||
|
||||
fCharToMinGlyphMap[fCharCount] = fGlyphCount;
|
||||
|
||||
for (glyph = 0; glyph < fGlyphCount; glyph += 1) {
|
||||
le_int32 ch = fGlyphToCharMap[glyph];
|
||||
|
||||
fCharToMaxGlyphMap[ch] = glyph;
|
||||
}
|
||||
|
||||
fCharToMaxGlyphMap[fCharCount] = fGlyphCount;
|
||||
}
|
||||
|
||||
ParagraphLayout::~ParagraphLayout()
|
||||
@ -372,11 +377,16 @@ ParagraphLayout::~ParagraphLayout()
|
||||
fGlyphToCharMap = NULL;
|
||||
}
|
||||
|
||||
if (fCharToGlyphMap != NULL) {
|
||||
LE_DELETE_ARRAY(fCharToGlyphMap);
|
||||
fCharToGlyphMap = NULL;
|
||||
if (fCharToMinGlyphMap != NULL) {
|
||||
LE_DELETE_ARRAY(fCharToMinGlyphMap);
|
||||
fCharToMinGlyphMap = NULL;
|
||||
}
|
||||
|
||||
if (fCharToMaxGlyphMap != NULL) {
|
||||
LE_DELETE_ARRAY(fCharToMaxGlyphMap);
|
||||
fCharToMaxGlyphMap = NULL;
|
||||
}
|
||||
|
||||
if (fGlyphWidths != NULL) {
|
||||
LE_DELETE_ARRAY(fGlyphWidths);
|
||||
fGlyphWidths = NULL;
|
||||
@ -472,7 +482,7 @@ ParagraphLayout::Line *ParagraphLayout::nextLine(float width)
|
||||
fLineStart = fLineEnd;
|
||||
|
||||
if (width > 0) {
|
||||
le_int32 glyph = fCharToGlyphMap[fLineStart];
|
||||
le_int32 glyph = fCharToMinGlyphMap[fLineStart];
|
||||
float widthSoFar = 0;
|
||||
|
||||
while (glyph < fGlyphCount && widthSoFar + fGlyphWidths[glyph] <= width) {
|
||||
@ -810,14 +820,15 @@ void ParagraphLayout::appendRun(ParagraphLayout::Line *line, le_int32 run, le_in
|
||||
le_int32 ch;
|
||||
|
||||
for (ch = firstChar; ch <= lastChar; ch += 1) {
|
||||
le_int32 glyph = fCharToGlyphMap[ch];
|
||||
le_int32 minGlyph = fCharToMinGlyphMap[ch];
|
||||
le_int32 maxGlyph = fCharToMaxGlyphMap[ch];
|
||||
|
||||
if (glyph < leftGlyph) {
|
||||
leftGlyph = glyph;
|
||||
if (minGlyph < leftGlyph) {
|
||||
leftGlyph = minGlyph;
|
||||
}
|
||||
|
||||
if (glyph > rightGlyph) {
|
||||
rightGlyph = glyph;
|
||||
if (maxGlyph > rightGlyph) {
|
||||
rightGlyph = maxGlyph;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -580,7 +580,8 @@ private:
|
||||
le_int32 fLeading;
|
||||
|
||||
le_int32 *fGlyphToCharMap;
|
||||
le_int32 *fCharToGlyphMap;
|
||||
le_int32 *fCharToMinGlyphMap;
|
||||
le_int32 *fCharToMaxGlyphMap;
|
||||
float *fGlyphWidths;
|
||||
le_int32 fGlyphCount;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user