提交 f1732ae0 编写于 作者: P prr

8001031: Better font processing

Reviewed-by: srl, vadim
上级 ccd00899
......@@ -66,8 +66,21 @@ FontInstanceAdapter::FontInstanceAdapter(JNIEnv *theEnv,
yScalePixelsToUnits = upem / yppem;
};
const void *FontInstanceAdapter::getFontTable(LETag tableTag) const
{
size_t ignored = 0;
return getFontTable(tableTag, ignored);
}
static const LETag cacheMap[LAYOUTCACHE_ENTRIES] = {
GPOS_TAG, GDEF_TAG, GSUB_TAG, MORT_TAG, MORX_TAG, KERN_TAG
};
const void *FontInstanceAdapter::getFontTable(LETag tableTag, size_t &length) const
{
length = 0;
if (!layoutTables) { // t1 font
return 0;
}
......@@ -75,14 +88,19 @@ const void *FontInstanceAdapter::getFontTable(LETag tableTag) const
// cache in font's pscaler object
// font disposer will handle for us
switch(tableTag) {
case GSUB_TAG: if (layoutTables->gsub_len != -1) return (void*)layoutTables->gsub; break;
case GPOS_TAG: if (layoutTables->gpos_len != -1) return (void*)layoutTables->gpos; break;
case GDEF_TAG: if (layoutTables->gdef_len != -1) return (void*)layoutTables->gdef; break;
case MORT_TAG: if (layoutTables->mort_len != -1) return (void*)layoutTables->mort; break;
case KERN_TAG: if (layoutTables->kern_len != -1) return (void*)layoutTables->kern; break;
default:
int cacheIdx;
for (cacheIdx=0;cacheIdx<LAYOUTCACHE_ENTRIES;cacheIdx++) {
if (tableTag==cacheMap[cacheIdx]) break;
}
if (cacheIdx<LAYOUTCACHE_ENTRIES) { // if found
if (layoutTables->entries[cacheIdx].len != -1) {
length = layoutTables->entries[cacheIdx].len;
return layoutTables->entries[cacheIdx].ptr;
}
} else {
//fprintf(stderr, "unexpected table request from font instance adapter: %x\n", tableTag);
// (don't load any other tables)
return 0;
}
......@@ -96,16 +114,13 @@ const void *FontInstanceAdapter::getFontTable(LETag tableTag) const
env->GetByteArrayRegion(tableBytes, 0, len, result);
}
switch(tableTag) {
case GSUB_TAG: layoutTables->gsub = (void*)result; layoutTables->gsub_len = len; break;
case GPOS_TAG: layoutTables->gpos = (void*)result; layoutTables->gpos_len = len; break;
case GDEF_TAG: layoutTables->gdef = (void*)result; layoutTables->gdef_len = len; break;
case MORT_TAG: layoutTables->mort = (void*)result; layoutTables->mort_len = len; break;
case KERN_TAG: layoutTables->kern = (void*)result; layoutTables->kern_len = len; break;
default: break;
if (cacheIdx<LAYOUTCACHE_ENTRIES) { // if cacheable table
layoutTables->entries[cacheIdx].len = len;
layoutTables->entries[cacheIdx].ptr = (const void*)result;
}
return (void*)result;
length = len;
return (const void*)result;
};
LEGlyphID FontInstanceAdapter::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const
......
......@@ -86,6 +86,7 @@ public:
// tables are cached with the native font scaler data
// only supports gsub, gpos, gdef, mort tables at present
virtual const void *getFontTable(LETag tableTag) const;
virtual const void *getFontTable(LETag tableTag, size_t &len) const;
virtual void *getKernPairs() const {
return layoutTables->kernPairs;
......
......@@ -120,20 +120,19 @@ typedef struct GlyphInfo {
#define GPOS_TAG 0x47504F53 /* 'GPOS' */
#define GDEF_TAG 0x47444546 /* 'GDEF' */
#define MORT_TAG 0x6D6F7274 /* 'mort' */
#define MORX_TAG 0x6D6F7278 /* 'morx' */
#define KERN_TAG 0x6B65726E /* 'kern' */
typedef struct TTLayoutTableCacheEntry {
const void* ptr;
int len;
} TTLayoutTableCacheEntry;
#define LAYOUTCACHE_ENTRIES 6
typedef struct TTLayoutTableCache {
void* gsub;
void* gpos;
void* gdef;
void* mort;
void* kern;
TTLayoutTableCacheEntry entries[LAYOUTCACHE_ENTRIES];
void* kernPairs;
int gsub_len;
int gpos_len;
int gdef_len;
int mort_len;
int kern_len;
} TTLayoutTableCache;
#include "sunfontids.h"
......
......@@ -39,19 +39,20 @@
U_NAMESPACE_BEGIN
le_uint32 AlternateSubstitutionSubtable::process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter) const
le_uint32 AlternateSubstitutionSubtable::process(const LEReferenceTo<AlternateSubstitutionSubtable> &base,
GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter) const
{
// NOTE: For now, we'll just pick the first alternative...
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(glyph);
le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
if (coverageIndex >= 0) {
if (coverageIndex >= 0 && LE_SUCCESS(success)) {
le_uint16 altSetCount = SWAPW(alternateSetCount);
if (coverageIndex < altSetCount) {
Offset alternateSetTableOffset = SWAPW(alternateSetTableOffsetArray[coverageIndex]);
const AlternateSetTable *alternateSetTable =
(const AlternateSetTable *) ((char *) this + alternateSetTableOffset);
const LEReferenceTo<AlternateSetTable> alternateSetTable(base, success,
(const AlternateSetTable *) ((char *) this + alternateSetTableOffset));
TTGlyphID alternate = SWAPW(alternateSetTable->alternateArray[0]);
if (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, alternate))) {
......
......@@ -51,13 +51,17 @@ struct AlternateSetTable
TTGlyphID alternateArray[ANY_NUMBER];
};
LE_VAR_ARRAY(AlternateSetTable, alternateArray)
struct AlternateSubstitutionSubtable : GlyphSubstitutionSubtable
{
le_uint16 alternateSetCount;
Offset alternateSetTableOffsetArray[ANY_NUMBER];
le_uint32 process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter = NULL) const;
le_uint32 process(const LEReferenceTo<AlternateSubstitutionSubtable> &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter = NULL) const;
};
LE_VAR_ARRAY(AlternateSubstitutionSubtable, alternateSetTableOffsetArray)
U_NAMESPACE_END
#endif
......@@ -58,15 +58,18 @@ le_bool CharSubstitutionFilter::accept(LEGlyphID glyph) const
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ArabicOpenTypeLayoutEngine)
ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode,
le_int32 languageCode, le_int32 typoFlags,
const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable,
LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success)
{
fFeatureMap = ArabicShaping::getFeatureMap(fFeatureMapCount);
fFeatureOrder = TRUE;
}
ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode,
le_int32 languageCode,
le_int32 typoFlags, LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success)
{
......@@ -88,8 +91,9 @@ ArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine()
// Input: characters
// Output: characters, char indices, tags
// Returns: output character count
le_int32 ArabicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success)
le_int32 ArabicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count,
le_int32 max, le_bool rightToLeft, LEUnicode *&outChars,
LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
if (LE_FAILURE(success)) {
return 0;
......@@ -137,15 +141,14 @@ void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], l
return;
}
if (fGPOSTable != NULL) {
if (!fGPOSTable.isEmpty()) {
OpenTypeLayoutEngine::adjustGlyphPositions(chars, offset, count, reverse, glyphStorage, success);
} else if (fGDEFTable != NULL) {
GDEFMarkFilter filter(fGDEFTable);
} else if (!fGDEFTable.isEmpty()) {
GDEFMarkFilter filter(fGDEFTable, success);
adjustMarkGlyphs(glyphStorage, &filter, success);
} else {
GlyphDefinitionTableHeader *gdefTable = (GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
GDEFMarkFilter filter(gdefTable);
LEReferenceTo<GlyphDefinitionTableHeader> gdefTable(CanonShaping::glyphDefinitionTable, CanonShaping::glyphDefinitionTableLen);
GDEFMarkFilter filter(gdefTable, success);
adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
}
......@@ -232,7 +235,7 @@ void UnicodeArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode cha
return;
}
GDEFMarkFilter filter(fGDEFTable);
GDEFMarkFilter filter(fGDEFTable, success);
adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
}
......
......@@ -75,7 +75,7 @@ public:
* @internal
*/
ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success);
le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success);
/**
* This constructor is used when the font requires a "canned" GSUB table which can't be known
......
......@@ -58,10 +58,12 @@ const ArabicShaping::ShapeType ArabicShaping::shapeTypes[] =
*/
ArabicShaping::ShapeType ArabicShaping::getShapeType(LEUnicode c)
{
const ClassDefinitionTable *joiningTypes = (const ClassDefinitionTable *) ArabicShaping::shapingTypeTable;
le_int32 joiningType = joiningTypes->getGlyphClass(c);
LEErrorCode success = LE_NO_ERROR;
const LEReferenceTo<ClassDefinitionTable> joiningTypes((const ClassDefinitionTable *) ArabicShaping::shapingTypeTable,
ArabicShaping::shapingTypeTableLen);
le_int32 joiningType = joiningTypes->getGlyphClass(joiningTypes, c, success);
if (joiningType >= 0 && joiningType < ArabicShaping::JT_COUNT) {
if (joiningType >= 0 && joiningType < ArabicShaping::JT_COUNT && LE_SUCCESS(success)) {
return ArabicShaping::shapeTypes[joiningType];
}
......
......@@ -93,6 +93,8 @@ private:
static ShapeType getShapeType(LEUnicode c);
static const le_uint8 shapingTypeTable[];
static const size_t shapingTypeTableLen;
static const ShapeType shapeTypes[];
static void adjustTags(le_int32 outIndex, le_int32 shapeOffset, LEGlyphStorage &glyphStorage);
......
......@@ -52,14 +52,14 @@ struct AttachmentPositioningSubtable : GlyphPositioningSubtable
Offset markArrayOffset;
Offset baseArrayOffset;
inline le_int32 getBaseCoverage(LEGlyphID baseGlyphId) const;
inline le_int32 getBaseCoverage(const LETableReference &base, LEGlyphID baseGlyphId, LEErrorCode &success) const;
le_uint32 process(GlyphIterator *glyphIterator) const;
};
inline le_int32 AttachmentPositioningSubtable::getBaseCoverage(LEGlyphID baseGlyphID) const
inline le_int32 AttachmentPositioningSubtable::getBaseCoverage(const LETableReference &base, LEGlyphID baseGlyphID, LEErrorCode &success) const
{
return getGlyphCoverage(baseCoverageTableOffset, baseGlyphID);
return getGlyphCoverage(base, baseCoverageTableOffset, baseGlyphID, success);
}
U_NAMESPACE_END
......
......@@ -3641,4 +3641,9 @@ const le_uint8 CanonShaping::glyphDefinitionTable[] = {
0x00, 0xE6, 0xD2, 0x42, 0xD2, 0x44, 0x00, 0xE6
};
const size_t CanonShaping::glyphSubstitutionTableLen = sizeof(glyphSubstitutionTable)/sizeof(glyphSubstitutionTable[0]);
const size_t CanonShaping::glyphDefinitionTableLen = sizeof(glyphDefinitionTable)/sizeof(glyphDefinitionTable[0]);
U_NAMESPACE_END
......@@ -59,15 +59,15 @@ void CanonShaping::sortMarks(le_int32 *indices, const le_int32 *combiningClasses
void CanonShaping::reorderMarks(const LEUnicode *inChars, le_int32 charCount, le_bool rightToLeft,
LEUnicode *outChars, LEGlyphStorage &glyphStorage)
{
const GlyphDefinitionTableHeader *gdefTable = (const GlyphDefinitionTableHeader *) glyphDefinitionTable;
const ClassDefinitionTable *classTable = gdefTable->getMarkAttachClassDefinitionTable();
LEErrorCode success = LE_NO_ERROR;
LEReferenceTo<GlyphDefinitionTableHeader> gdefTable(CanonShaping::glyphDefinitionTable, CanonShaping::glyphDefinitionTableLen);
LEReferenceTo<ClassDefinitionTable> classTable = gdefTable->getMarkAttachClassDefinitionTable(gdefTable, success);
le_int32 *combiningClasses = LE_NEW_ARRAY(le_int32, charCount);
le_int32 *indices = LE_NEW_ARRAY(le_int32, charCount);
LEErrorCode status = LE_NO_ERROR;
le_int32 i;
for (i = 0; i < charCount; i += 1) {
combiningClasses[i] = classTable->getGlyphClass((LEGlyphID) inChars[i]);
combiningClasses[i] = classTable->getGlyphClass(classTable, (LEGlyphID) inChars[i], success);
indices[i] = i;
}
......@@ -96,7 +96,7 @@ void CanonShaping::reorderMarks(const LEUnicode *inChars, le_int32 charCount, le
le_int32 index = indices[i];
outChars[i] = inChars[index];
glyphStorage.setCharIndex(out, index, status);
glyphStorage.setCharIndex(out, index, success);
}
LE_DELETE_ARRAY(indices);
......
......@@ -42,7 +42,9 @@ class U_LAYOUT_API CanonShaping /* not : public UObject because all members are
{
public:
static const le_uint8 glyphSubstitutionTable[];
static const size_t glyphSubstitutionTableLen;
static const le_uint8 glyphDefinitionTable[];
static const size_t glyphDefinitionTableLen;
static void reorderMarks(const LEUnicode *inChars, le_int32 charCount, le_bool rightToLeft,
LEUnicode *outChars, LEGlyphStorage &glyphStorage);
......
......@@ -37,24 +37,25 @@
U_NAMESPACE_BEGIN
le_int32 ClassDefinitionTable::getGlyphClass(LEGlyphID glyphID) const
le_int32 ClassDefinitionTable::getGlyphClass(const LETableReference& base, LEGlyphID glyphID, LEErrorCode &success) const
{
LEReferenceTo<ClassDefinitionTable> thisRef(base, success);
if (LE_FAILURE(success)) return 0;
switch(SWAPW(classFormat)) {
case 0:
return 0;
case 1:
{
const ClassDefFormat1Table *f1Table = (const ClassDefFormat1Table *) this;
return f1Table->getGlyphClass(glyphID);
const LEReferenceTo<ClassDefFormat1Table> f1Table(thisRef, success);
return f1Table->getGlyphClass(f1Table, glyphID, success);
}
case 2:
{
const ClassDefFormat2Table *f2Table = (const ClassDefFormat2Table *) this;
return f2Table->getGlyphClass(glyphID);
const LEReferenceTo<ClassDefFormat2Table> f2Table(thisRef, success);
return f2Table->getGlyphClass(f2Table, glyphID, success);
}
default:
......@@ -62,24 +63,25 @@ le_int32 ClassDefinitionTable::getGlyphClass(LEGlyphID glyphID) const
}
}
le_bool ClassDefinitionTable::hasGlyphClass(le_int32 glyphClass) const
le_bool ClassDefinitionTable::hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const
{
LEReferenceTo<ClassDefinitionTable> thisRef(base, success);
if (LE_FAILURE(success)) return 0;
switch(SWAPW(classFormat)) {
case 0:
return 0;
case 1:
{
const ClassDefFormat1Table *f1Table = (const ClassDefFormat1Table *) this;
return f1Table->hasGlyphClass(glyphClass);
const LEReferenceTo<ClassDefFormat1Table> f1Table(thisRef, success);
return f1Table->hasGlyphClass(f1Table, glyphClass, success);
}
case 2:
{
const ClassDefFormat2Table *f2Table = (const ClassDefFormat2Table *) this;
return f2Table->hasGlyphClass(glyphClass);
const LEReferenceTo<ClassDefFormat2Table> f2Table(thisRef, success);
return f2Table->hasGlyphClass(f2Table, glyphClass, success);
}
default:
......@@ -87,26 +89,32 @@ le_bool ClassDefinitionTable::hasGlyphClass(le_int32 glyphClass) const
}
}
le_int32 ClassDefFormat1Table::getGlyphClass(LEGlyphID glyphID) const
le_int32 ClassDefFormat1Table::getGlyphClass(const LETableReference& base, LEGlyphID glyphID, LEErrorCode &success) const
{
if(LE_FAILURE(success)) return 0;
le_uint16 count = SWAPW(glyphCount);
LEReferenceToArrayOf<le_uint16> classValueArrayRef(base, success, &classValueArray[0], count);
TTGlyphID ttGlyphID = (TTGlyphID) LE_GET_GLYPH(glyphID);
TTGlyphID firstGlyph = SWAPW(startGlyph);
TTGlyphID lastGlyph = firstGlyph + SWAPW(glyphCount);
TTGlyphID lastGlyph = firstGlyph + count;
if (ttGlyphID >= firstGlyph && ttGlyphID < lastGlyph) {
return SWAPW(classValueArray[ttGlyphID - firstGlyph]);
if (LE_SUCCESS(success) && ttGlyphID >= firstGlyph && ttGlyphID < lastGlyph) {
return SWAPW( classValueArrayRef(ttGlyphID - firstGlyph, success) );
}
return 0;
}
le_bool ClassDefFormat1Table::hasGlyphClass(le_int32 glyphClass) const
le_bool ClassDefFormat1Table::hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const
{
if(LE_FAILURE(success)) return 0;
le_uint16 count = SWAPW(glyphCount);
LEReferenceToArrayOf<le_uint16> classValueArrayRef(base, success, &classValueArray[0], count);
int i;
for (i = 0; i < count; i += 1) {
if (SWAPW(classValueArray[i]) == glyphClass) {
for (i = 0; LE_SUCCESS(success)&& (i < count); i += 1) {
if (SWAPW(classValueArrayRef(i,success)) == glyphClass) {
return TRUE;
}
}
......@@ -114,27 +122,31 @@ le_bool ClassDefFormat1Table::hasGlyphClass(le_int32 glyphClass) const
return FALSE;
}
le_int32 ClassDefFormat2Table::getGlyphClass(LEGlyphID glyphID) const
le_int32 ClassDefFormat2Table::getGlyphClass(const LETableReference& base, LEGlyphID glyphID, LEErrorCode &success) const
{
if(LE_FAILURE(success)) return 0;
TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyphID);
le_uint16 rangeCount = SWAPW(classRangeCount);
LEReferenceToArrayOf<GlyphRangeRecord> classRangeRecordArrayRef(base, success, &classRangeRecordArray[0], rangeCount);
le_int32 rangeIndex =
OpenTypeUtilities::getGlyphRangeIndex(ttGlyph, classRangeRecordArray, rangeCount);
OpenTypeUtilities::getGlyphRangeIndex(ttGlyph, classRangeRecordArrayRef, success);
if (rangeIndex < 0) {
if (rangeIndex < 0 || LE_FAILURE(success)) {
return 0;
}
return SWAPW(classRangeRecordArray[rangeIndex].rangeValue);
return SWAPW(classRangeRecordArrayRef(rangeIndex, success).rangeValue);
}
le_bool ClassDefFormat2Table::hasGlyphClass(le_int32 glyphClass) const
le_bool ClassDefFormat2Table::hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const
{
if(LE_FAILURE(success)) return 0;
le_uint16 rangeCount = SWAPW(classRangeCount);
LEReferenceToArrayOf<GlyphRangeRecord> classRangeRecordArrayRef(base, success, &classRangeRecordArray[0], rangeCount);
int i;
for (i = 0; i < rangeCount; i += 1) {
if (SWAPW(classRangeRecordArray[i].rangeValue) == glyphClass) {
for (i = 0; i < rangeCount && LE_SUCCESS(success); i += 1) {
if (SWAPW(classRangeRecordArrayRef(i,success).rangeValue) == glyphClass) {
return TRUE;
}
}
......
......@@ -46,8 +46,20 @@ struct ClassDefinitionTable
{
le_uint16 classFormat;
le_int32 getGlyphClass(LEGlyphID glyphID) const;
le_bool hasGlyphClass(le_int32 glyphClass) const;
le_int32 getGlyphClass(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
le_bool hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const;
le_int32 getGlyphClass(LEGlyphID glyphID) const {
LETableReference base((const le_uint8*)this);
LEErrorCode ignored = LE_NO_ERROR;
return getGlyphClass(base,glyphID,ignored);
}
le_bool hasGlyphClass(le_int32 glyphClass) const {
LETableReference base((const le_uint8*)this);
LEErrorCode ignored = LE_NO_ERROR;
return hasGlyphClass(base,glyphClass,ignored);
}
};
struct ClassDefFormat1Table : ClassDefinitionTable
......@@ -56,9 +68,11 @@ struct ClassDefFormat1Table : ClassDefinitionTable
le_uint16 glyphCount;
le_uint16 classValueArray[ANY_NUMBER];
le_int32 getGlyphClass(LEGlyphID glyphID) const;
le_bool hasGlyphClass(le_int32 glyphClass) const;
le_int32 getGlyphClass(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
le_bool hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const;
};
LE_VAR_ARRAY(ClassDefFormat1Table, classValueArray)
struct ClassRangeRecord
{
......@@ -72,9 +86,10 @@ struct ClassDefFormat2Table : ClassDefinitionTable
le_uint16 classRangeCount;
GlyphRangeRecord classRangeRecordArray[ANY_NUMBER];
le_int32 getGlyphClass(LEGlyphID glyphID) const;
le_bool hasGlyphClass(le_int32 glyphClass) const;
le_int32 getGlyphClass(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
le_bool hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const;
};
LE_VAR_ARRAY(ClassDefFormat2Table, classRangeRecordArray)
U_NAMESPACE_END
#endif
......@@ -43,13 +43,15 @@ U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphInsertionProcessor2)
ContextualGlyphInsertionProcessor2::ContextualGlyphInsertionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
: StateTableProcessor2(morphSubtableHeader)
ContextualGlyphInsertionProcessor2::ContextualGlyphInsertionProcessor2(
const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
: StateTableProcessor2(morphSubtableHeader, success)
{
contextualGlyphHeader = (const ContextualGlyphInsertionHeader2 *) morphSubtableHeader;
contextualGlyphHeader = LEReferenceTo<ContextualGlyphInsertionHeader2>(morphSubtableHeader, success);
if(LE_FAILURE(success) || !contextualGlyphHeader.isValid()) return;
le_uint32 insertionTableOffset = SWAPL(contextualGlyphHeader->insertionTableOffset);
insertionTable = ((le_uint16 *) ((char *)&stateTableHeader->stHeader + insertionTableOffset));
entryTable = (const ContextualGlyphInsertionStateEntry2 *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
insertionTable = LEReferenceToArrayOf<le_uint16>(stHeader, success, insertionTableOffset, LE_UNBOUNDED_ARRAY);
entryTable = LEReferenceToArrayOf<ContextualGlyphInsertionStateEntry2>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY);
}
ContextualGlyphInsertionProcessor2::~ContextualGlyphInsertionProcessor2()
......@@ -61,93 +63,62 @@ void ContextualGlyphInsertionProcessor2::beginStateTable()
markGlyph = 0;
}
le_uint16 ContextualGlyphInsertionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index)
{
const ContextualGlyphInsertionStateEntry2 *entry = &entryTable[index];
le_uint16 newState = SWAPW(entry->newStateIndex);
le_uint16 flags = SWAPW(entry->flags);
le_int16 currIndex = SWAPW(entry->currentInsertionListIndex);
le_int16 markIndex = SWAPW(entry->markedInsertionListIndex);
int i = 0;
void ContextualGlyphInsertionProcessor2::doInsertion(LEGlyphStorage &glyphStorage,
le_int16 atGlyph,
le_int16 &index,
le_int16 count,
le_bool /* isKashidaLike */,
le_bool isBefore,
LEErrorCode &success) {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(atGlyph, count + 1, success);
if (markIndex > 0) {
le_int16 count = (flags & cgiMarkedInsertCountMask) >> 5;
if (!(flags & cgiMarkedIsKashidaLike)) {
// extra glyph(s) will be added directly before/after the specified marked glyph
if (!(flags & cgiMarkInsertBefore)) {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
for (i = 0; i < count; i++, markIndex++) {
insertGlyphs[i] = insertionTable[markIndex];
}
insertGlyphs[i] = glyphStorage[markGlyph];
glyphStorage.applyInsertions();
} else {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
insertGlyphs[0] = glyphStorage[markGlyph];
for (i = 1; i < count + 1; i++, markIndex++) {
insertGlyphs[i] = insertionTable[markIndex];
}
glyphStorage.applyInsertions();
if(LE_FAILURE(success) || insertGlyphs==NULL) {
return;
}
// Note: Kashida vs Split Vowel seems to only affect selection and highlighting.
// We note the flag, but do not layout different.
// https://developer.apple.com/fonts/TTRefMan/RM06/Chap6mort.html
le_int16 targetIndex = 0;
if(isBefore) {
// insert at beginning
insertGlyphs[targetIndex++] = glyphStorage[atGlyph];
} else {
// inserted as a split-vowel-like insertion
// extra glyph(s) will be inserted some distance away from the marked glyph
if (!(flags & cgiMarkInsertBefore)) {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
for (i = 0; i < count; i++, markIndex++) {
insertGlyphs[i] = insertionTable[markIndex];
// insert at end
insertGlyphs[count] = glyphStorage[atGlyph];
}
insertGlyphs[i] = glyphStorage[markGlyph];
glyphStorage.applyInsertions();
} else {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(markGlyph, count + 1);
insertGlyphs[0] = glyphStorage[markGlyph];
for (i = 1; i < count + 1; i++, markIndex++) {
insertGlyphs[i] = insertionTable[markIndex];
while(count--) {
insertGlyphs[targetIndex++] = insertionTable.getObject(index++, success);
}
glyphStorage.applyInsertions();
}
}
}
le_uint16 ContextualGlyphInsertionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph,
EntryTableIndex2 index, LEErrorCode &success)
{
const ContextualGlyphInsertionStateEntry2 *entry = entryTable.getAlias(index, success);
if(LE_FAILURE(success)) return 0; // TODO- which state?
le_uint16 newState = SWAPW(entry->newStateIndex);
le_uint16 flags = SWAPW(entry->flags);
le_int16 markIndex = SWAPW(entry->markedInsertionListIndex);
if (markIndex > 0) {
le_int16 count = (flags & cgiMarkedInsertCountMask) >> 5;
le_bool isKashidaLike = (flags & cgiMarkedIsKashidaLike);
le_bool isBefore = (flags & cgiMarkInsertBefore);
doInsertion(glyphStorage, markGlyph, markIndex, count, isKashidaLike, isBefore, success);
}
le_int16 currIndex = SWAPW(entry->currentInsertionListIndex);
if (currIndex > 0) {
le_int16 count = flags & cgiCurrentInsertCountMask;
if (!(flags & cgiCurrentIsKashidaLike)) {
// extra glyph(s) will be added directly before/after the specified current glyph
if (!(flags & cgiCurrentInsertBefore)) {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
for (i = 0; i < count; i++, currIndex++) {
insertGlyphs[i] = insertionTable[currIndex];
}
insertGlyphs[i] = glyphStorage[currGlyph];
glyphStorage.applyInsertions();
} else {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
insertGlyphs[0] = glyphStorage[currGlyph];
for (i = 1; i < count + 1; i++, currIndex++) {
insertGlyphs[i] = insertionTable[currIndex];
}
glyphStorage.applyInsertions();
}
} else {
// inserted as a split-vowel-like insertion
// extra glyph(s) will be inserted some distance away from the current glyph
if (!(flags & cgiCurrentInsertBefore)) {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
for (i = 0; i < count; i++, currIndex++) {
insertGlyphs[i] = insertionTable[currIndex];
}
insertGlyphs[i] = glyphStorage[currGlyph];
glyphStorage.applyInsertions();
} else {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(currGlyph, count + 1);
insertGlyphs[0] = glyphStorage[currGlyph];
for (i = 1; i < count + 1; i++, currIndex++) {
insertGlyphs[i] = insertionTable[currIndex];
}
glyphStorage.applyInsertions();
}
}
le_bool isKashidaLike = (flags & cgiCurrentIsKashidaLike);
le_bool isBefore = (flags & cgiCurrentInsertBefore);
doInsertion(glyphStorage, currGlyph, currIndex, count, isKashidaLike, isBefore, success);
}
if (flags & cgiSetMark) {
......
......@@ -53,11 +53,12 @@ class ContextualGlyphInsertionProcessor2 : public StateTableProcessor2
public:
virtual void beginStateTable();
virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index);
virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage,
le_int32 &currGlyph, EntryTableIndex2 index, LEErrorCode &success);
virtual void endStateTable();
ContextualGlyphInsertionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
ContextualGlyphInsertionProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
virtual ~ContextualGlyphInsertionProcessor2();
/**
......@@ -77,12 +78,28 @@ public:
private:
ContextualGlyphInsertionProcessor2();
/**
* Perform the actual insertion
* @param atGlyph index of glyph to insert at
* @param index index into the insertionTable (in/out)
* @param count number of insertions
* @param isKashidaLike Kashida like (vs Split Vowel like). No effect currently.
* @param isBefore if true, insert extra glyphs before the marked glyph
*/
void doInsertion(LEGlyphStorage &glyphStorage,
le_int16 atGlyph,
le_int16 &index,
le_int16 count,
le_bool isKashidaLike,
le_bool isBefore,
LEErrorCode &success);
protected:
le_int32 markGlyph;
const le_uint16* insertionTable;
const ContextualGlyphInsertionStateEntry2 *entryTable;
const ContextualGlyphInsertionHeader2 *contextualGlyphHeader;
LEReferenceToArrayOf<le_uint16> insertionTable;
LEReferenceToArrayOf<ContextualGlyphInsertionStateEntry2> entryTable;
LEReferenceTo<ContextualGlyphInsertionHeader2> contextualGlyphHeader;
};
U_NAMESPACE_END
......
......@@ -43,13 +43,18 @@ U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphSubstitutionProcessor)
ContextualGlyphSubstitutionProcessor::ContextualGlyphSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader)
: StateTableProcessor(morphSubtableHeader)
ContextualGlyphSubstitutionProcessor::ContextualGlyphSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
: StateTableProcessor(morphSubtableHeader, success), entryTable(), contextualGlyphSubstitutionHeader(morphSubtableHeader, success)
{
contextualGlyphSubstitutionHeader = (const ContextualGlyphSubstitutionHeader *) morphSubtableHeader;
contextualGlyphSubstitutionHeader.orphan();
substitutionTableOffset = SWAPW(contextualGlyphSubstitutionHeader->substitutionTableOffset);
entryTable = (const ContextualGlyphSubstitutionStateEntry *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
entryTable = LEReferenceToArrayOf<ContextualGlyphSubstitutionStateEntry>(stateTableHeader, success,
(const ContextualGlyphSubstitutionStateEntry*)(&stateTableHeader->stHeader),
entryTableOffset, LE_UNBOUNDED_ARRAY);
int16Table = LEReferenceToArrayOf<le_int16>(stateTableHeader, success, (const le_int16*)(&stateTableHeader->stHeader),
0, LE_UNBOUNDED_ARRAY); // rest of the table as le_int16s
}
ContextualGlyphSubstitutionProcessor::~ContextualGlyphSubstitutionProcessor()
......@@ -63,24 +68,23 @@ void ContextualGlyphSubstitutionProcessor::beginStateTable()
ByteOffset ContextualGlyphSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index)
{
const ContextualGlyphSubstitutionStateEntry *entry = &entryTable[index];
LEErrorCode success = LE_NO_ERROR;
const ContextualGlyphSubstitutionStateEntry *entry = entryTable.getAlias(index, success);
ByteOffset newState = SWAPW(entry->newStateOffset);
le_int16 flags = SWAPW(entry->flags);
WordOffset markOffset = SWAPW(entry->markOffset);
WordOffset currOffset = SWAPW(entry->currOffset);
if (markOffset != 0) {
const le_int16 *table = (const le_int16 *) ((char *) &stateTableHeader->stHeader + markOffset * 2);
if (markOffset != 0 && LE_SUCCESS(success)) {
LEGlyphID mGlyph = glyphStorage[markGlyph];
TTGlyphID newGlyph = SWAPW(table[LE_GET_GLYPH(mGlyph)]);
TTGlyphID newGlyph = SWAPW(int16Table.getObject(markOffset + LE_GET_GLYPH(mGlyph), success)); // whew.
glyphStorage[markGlyph] = LE_SET_GLYPH(mGlyph, newGlyph);
}
if (currOffset != 0) {
const le_int16 *table = (const le_int16 *) ((char *) &stateTableHeader->stHeader + currOffset * 2);
LEGlyphID thisGlyph = glyphStorage[currGlyph];
TTGlyphID newGlyph = SWAPW(table[LE_GET_GLYPH(thisGlyph)]);
TTGlyphID newGlyph = SWAPW(int16Table.getObject(currOffset + LE_GET_GLYPH(thisGlyph), success)); // whew.
glyphStorage[currGlyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
}
......
......@@ -56,7 +56,7 @@ public:
virtual void endStateTable();
ContextualGlyphSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader);
ContextualGlyphSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
virtual ~ContextualGlyphSubstitutionProcessor();
/**
......@@ -78,11 +78,11 @@ private:
protected:
ByteOffset substitutionTableOffset;
const ContextualGlyphSubstitutionStateEntry *entryTable;
LEReferenceToArrayOf<ContextualGlyphSubstitutionStateEntry> entryTable;
LEReferenceToArrayOf<le_int16> int16Table;
le_int32 markGlyph;
const ContextualGlyphSubstitutionHeader *contextualGlyphSubstitutionHeader;
LEReferenceTo<ContextualGlyphSubstitutionHeader> contextualGlyphSubstitutionHeader;
};
......
......@@ -43,13 +43,14 @@ U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphSubstitutionProcessor2)
ContextualGlyphSubstitutionProcessor2::ContextualGlyphSubstitutionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
: StateTableProcessor2(morphSubtableHeader)
ContextualGlyphSubstitutionProcessor2::ContextualGlyphSubstitutionProcessor2(
const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
: StateTableProcessor2(morphSubtableHeader, success), contextualGlyphHeader(morphSubtableHeader, success)
{
contextualGlyphHeader = (const ContextualGlyphHeader2 *) morphSubtableHeader;
if(LE_FAILURE(success)) return;
le_uint32 perGlyphTableOffset = SWAPL(contextualGlyphHeader->perGlyphTableOffset);
perGlyphTable = ((le_uint32 *) ((char *)&stateTableHeader->stHeader + perGlyphTableOffset));
entryTable = (const ContextualGlyphStateEntry2 *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
perGlyphTable = LEReferenceToArrayOf<le_uint32> (stHeader, success, perGlyphTableOffset, LE_UNBOUNDED_ARRAY);
entryTable = LEReferenceToArrayOf<ContextualGlyphStateEntry2>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY);
}
ContextualGlyphSubstitutionProcessor2::~ContextualGlyphSubstitutionProcessor2()
......@@ -61,25 +62,28 @@ void ContextualGlyphSubstitutionProcessor2::beginStateTable()
markGlyph = 0;
}
le_uint16 ContextualGlyphSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index)
le_uint16 ContextualGlyphSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph,
EntryTableIndex2 index, LEErrorCode &success)
{
const ContextualGlyphStateEntry2 *entry = &entryTable[index];
if(LE_FAILURE(success)) return 0;
const ContextualGlyphStateEntry2 *entry = entryTable.getAlias(index, success);
if(LE_FAILURE(success)) return 0;
le_uint16 newState = SWAPW(entry->newStateIndex);
le_uint16 flags = SWAPW(entry->flags);
le_int16 markIndex = SWAPW(entry->markIndex);
le_int16 currIndex = SWAPW(entry->currIndex);
if (markIndex != -1) {
le_uint32 offset = SWAPL(perGlyphTable[markIndex]);
le_uint32 offset = SWAPL(perGlyphTable(markIndex, success));
LEGlyphID mGlyph = glyphStorage[markGlyph];
TTGlyphID newGlyph = lookup(offset, mGlyph);
TTGlyphID newGlyph = lookup(offset, mGlyph, success);
glyphStorage[markGlyph] = LE_SET_GLYPH(mGlyph, newGlyph);
}
if (currIndex != -1) {
le_uint32 offset = SWAPL(perGlyphTable[currIndex]);
le_uint32 offset = SWAPL(perGlyphTable(currIndex, success));
LEGlyphID thisGlyph = glyphStorage[currGlyph];
TTGlyphID newGlyph = lookup(offset, thisGlyph);
TTGlyphID newGlyph = lookup(offset, thisGlyph, success);
glyphStorage[currGlyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
}
......@@ -94,26 +98,30 @@ le_uint16 ContextualGlyphSubstitutionProcessor2::processStateEntry(LEGlyphStorag
return newState;
}
TTGlyphID ContextualGlyphSubstitutionProcessor2::lookup(le_uint32 offset, LEGlyphID gid)
TTGlyphID ContextualGlyphSubstitutionProcessor2::lookup(le_uint32 offset, LEGlyphID gid, LEErrorCode &success)
{
LookupTable *lookupTable = ((LookupTable *) ((char *)perGlyphTable + offset));
le_int16 format = SWAPW(lookupTable->format);
TTGlyphID newGlyph = 0xFFFF;
if(LE_FAILURE(success)) return newGlyph;
LEReferenceTo<LookupTable> lookupTable(perGlyphTable, success, offset);
if(LE_FAILURE(success)) return newGlyph;
le_int16 format = SWAPW(lookupTable->format);
switch (format) {
case ltfSimpleArray: {
#ifdef TEST_FORMAT
// Disabled pending for design review
SimpleArrayLookupTable *lookupTable0 = (SimpleArrayLookupTable *) lookupTable;
LEReferenceTo<SimpleArrayLookupTable> lookupTable0(lookupTable, success);
LEReferenceToArrayOf<LookupValue> valueArray(lookupTable0, success, &lookupTable0->valueArray[0], LE_UNBOUNDED_ARRAY);
if(LE_FAILURE(success)) return newGlyph;
TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
newGlyph = SWAPW(lookupTable0->valueArray[glyphCode]);
newGlyph = SWAPW(lookupTable0->valueArray(glyphCode, success));
#endif
break;
}
case ltfSegmentSingle: {
#ifdef TEST_FORMAT
// Disabled pending for design review
SegmentSingleLookupTable *lookupTable2 = (SegmentSingleLookupTable *) lookupTable;
LEReferenceTo<SegmentSingleLookupTable> lookupTable2 = (SegmentSingleLookupTable *) lookupTable;
const LookupSegment *segment = lookupTable2->lookupSegment(lookupTable2->segments, gid);
if (segment != NULL) {
newGlyph = SWAPW(segment->value);
......@@ -129,8 +137,8 @@ TTGlyphID ContextualGlyphSubstitutionProcessor2::lookup(le_uint32 offset, LEGlyp
{
#ifdef TEST_FORMAT
// Disabled pending for design review
SingleTableLookupTable *lookupTable6 = (SingleTableLookupTable *) lookupTable;
const LookupSingle *segment = lookupTable6->lookupSingle(lookupTable6->entries, gid);
LEReferenceTo<SingleTableLookupTable> lookupTable6 = (SingleTableLookupTable *) lookupTable;
const LEReferenceTo<LookupSingle> segment = lookupTable6->lookupSingle(lookupTable6->entries, gid);
if (segment != NULL) {
newGlyph = SWAPW(segment->value);
}
......@@ -138,12 +146,15 @@ TTGlyphID ContextualGlyphSubstitutionProcessor2::lookup(le_uint32 offset, LEGlyp
break;
}
case ltfTrimmedArray: {
TrimmedArrayLookupTable *lookupTable8 = (TrimmedArrayLookupTable *) lookupTable;
LEReferenceTo<TrimmedArrayLookupTable> lookupTable8(lookupTable, success);
if (LE_FAILURE(success)) return newGlyph;
TTGlyphID firstGlyph = SWAPW(lookupTable8->firstGlyph);
TTGlyphID lastGlyph = firstGlyph + SWAPW(lookupTable8->glyphCount);
TTGlyphID glyphCount = SWAPW(lookupTable8->glyphCount);
TTGlyphID lastGlyph = firstGlyph + glyphCount;
TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) {
newGlyph = SWAPW(lookupTable8->valueArray[glyphCode - firstGlyph]);
LEReferenceToArrayOf<LookupValue> valueArray(lookupTable8, success, &lookupTable8->valueArray[0], glyphCount);
newGlyph = SWAPW(valueArray(glyphCode - firstGlyph, success));
}
}
default:
......
......@@ -52,11 +52,11 @@ class ContextualGlyphSubstitutionProcessor2 : public StateTableProcessor2
public:
virtual void beginStateTable();
virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index);
virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index, LEErrorCode &success);
virtual void endStateTable();
ContextualGlyphSubstitutionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
ContextualGlyphSubstitutionProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
virtual ~ContextualGlyphSubstitutionProcessor2();
/**
......@@ -75,16 +75,16 @@ public:
private:
ContextualGlyphSubstitutionProcessor2();
TTGlyphID lookup(le_uint32 offset, LEGlyphID gid);
TTGlyphID lookup(le_uint32 offset, LEGlyphID gid, LEErrorCode &success);
protected:
const le_uint32* perGlyphTable;
const ContextualGlyphStateEntry2 *entryTable;
LEReferenceToArrayOf<le_uint32> perGlyphTable;
LEReferenceToArrayOf<ContextualGlyphStateEntry2> entryTable;
le_int16 perGlyphTableFormat;
le_int32 markGlyph;
const ContextualGlyphHeader2 *contextualGlyphHeader;
LEReferenceTo<ContextualGlyphHeader2> contextualGlyphHeader;
};
......
......@@ -217,7 +217,7 @@ le_uint32 ContextualSubstitutionFormat1Subtable::process(const LookupProcessor *
}
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(glyph);
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
if (coverageIndex >= 0) {
le_uint16 srSetCount = SWAPW(subRuleSetCount);
......@@ -266,7 +266,7 @@ le_uint32 ContextualSubstitutionFormat2Subtable::process(const LookupProcessor *
}
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(glyph);
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
if (coverageIndex >= 0) {
const ClassDefinitionTable *classDefinitionTable =
......@@ -394,7 +394,7 @@ le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupPro
}
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(glyph);
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
if (coverageIndex >= 0) {
le_uint16 srSetCount = SWAPW(chainSubRuleSetCount);
......@@ -465,7 +465,7 @@ le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupPro
}
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(glyph);
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
if (coverageIndex >= 0) {
const ClassDefinitionTable *backtrackClassDefinitionTable =
......
......@@ -43,6 +43,7 @@
#include "GlyphSubstitutionTables.h"
#include "GlyphIterator.h"
#include "LookupProcessor.h"
#include "LETableReference.h"
U_NAMESPACE_BEGIN
......@@ -88,6 +89,8 @@ struct ContextualSubstitutionFormat1Subtable : ContextualSubstitutionSubtable
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
};
LE_VAR_ARRAY(ContextualSubstitutionFormat1Subtable, subRuleSetTableOffsetArray)
struct SubRuleSetTable
{
......@@ -95,6 +98,7 @@ struct SubRuleSetTable
Offset subRuleTableOffsetArray[ANY_NUMBER];
};
LE_VAR_ARRAY(SubRuleSetTable, subRuleTableOffsetArray)
// NOTE: Multiple variable size arrays!!
struct SubRuleTable
......@@ -104,6 +108,7 @@ struct SubRuleTable
TTGlyphID inputGlyphArray[ANY_NUMBER];
//SubstitutionLookupRecord substLookupRecordArray[ANY_NUMBER];
};
LE_VAR_ARRAY(SubRuleTable, inputGlyphArray)
struct ContextualSubstitutionFormat2Subtable : ContextualSubstitutionSubtable
{
......@@ -113,12 +118,16 @@ struct ContextualSubstitutionFormat2Subtable : ContextualSubstitutionSubtable
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
};
LE_VAR_ARRAY(ContextualSubstitutionFormat2Subtable, subClassSetTableOffsetArray)
struct SubClassSetTable
{
le_uint16 subClassRuleCount;
Offset subClassRuleTableOffsetArray[ANY_NUMBER];
};
LE_VAR_ARRAY(SubClassSetTable, subClassRuleTableOffsetArray)
// NOTE: Multiple variable size arrays!!
struct SubClassRuleTable
......@@ -128,6 +137,8 @@ struct SubClassRuleTable
le_uint16 classArray[ANY_NUMBER];
//SubstitutionLookupRecord substLookupRecordArray[ANY_NUMBER];
};
LE_VAR_ARRAY(SubClassRuleTable, classArray)
// NOTE: This isn't a subclass of GlyphSubstitutionSubtable 'cause
// it has an array of coverage tables instead of a single coverage table...
......@@ -143,6 +154,7 @@ struct ContextualSubstitutionFormat3Subtable
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
};
LE_VAR_ARRAY(ContextualSubstitutionFormat3Subtable, coverageTableOffsetArray)
struct ChainingContextualSubstitutionSubtable : ContextualSubstitutionBase
{
......@@ -156,6 +168,8 @@ struct ChainingContextualSubstitutionFormat1Subtable : ChainingContextualSubstit
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
};
LE_VAR_ARRAY(ChainingContextualSubstitutionFormat1Subtable, chainSubRuleSetTableOffsetArray)
struct ChainSubRuleSetTable
{
......@@ -163,6 +177,7 @@ struct ChainSubRuleSetTable
Offset chainSubRuleTableOffsetArray[ANY_NUMBER];
};
LE_VAR_ARRAY(ChainSubRuleSetTable, chainSubRuleTableOffsetArray)
// NOTE: Multiple variable size arrays!!
struct ChainSubRuleTable
......@@ -176,6 +191,7 @@ struct ChainSubRuleTable
//le_uint16 substCount;
//SubstitutionLookupRecord substLookupRecordArray[ANY_NUMBER];
};
LE_VAR_ARRAY(ChainSubRuleTable, backtrackGlyphArray)
struct ChainingContextualSubstitutionFormat2Subtable : ChainingContextualSubstitutionSubtable
{
......@@ -187,12 +203,15 @@ struct ChainingContextualSubstitutionFormat2Subtable : ChainingContextualSubstit
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
};
LE_VAR_ARRAY(ChainingContextualSubstitutionFormat2Subtable, chainSubClassSetTableOffsetArray)
struct ChainSubClassSetTable
{
le_uint16 chainSubClassRuleCount;
Offset chainSubClassRuleTableOffsetArray[ANY_NUMBER];
};
LE_VAR_ARRAY(ChainSubClassSetTable, chainSubClassRuleTableOffsetArray)
// NOTE: Multiple variable size arrays!!
struct ChainSubClassRuleTable
......@@ -206,6 +225,7 @@ struct ChainSubClassRuleTable
//le_uint16 substCount;
//SubstitutionLookupRecord substLookupRecordArray[ANY_NUMBER];
};
LE_VAR_ARRAY(ChainSubClassRuleTable, backtrackClassArray)
// NOTE: This isn't a subclass of GlyphSubstitutionSubtable 'cause
// it has arrays of coverage tables instead of a single coverage table...
......@@ -225,6 +245,8 @@ struct ChainingContextualSubstitutionFormat3Subtable
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
};
LE_VAR_ARRAY(ChainingContextualSubstitutionFormat3Subtable, backtrackCoverageTableOffsetArray)
U_NAMESPACE_END
#endif
......@@ -56,6 +56,8 @@ struct CoverageFormat1Table : CoverageTable
le_int32 getGlyphCoverage(LEGlyphID glyphID) const;
};
LE_VAR_ARRAY(CoverageFormat1Table, glyphArray)
struct CoverageFormat2Table : CoverageTable
{
......@@ -64,6 +66,7 @@ struct CoverageFormat2Table : CoverageTable
le_int32 getGlyphCoverage(LEGlyphID glyphID) const;
};
LE_VAR_ARRAY(CoverageFormat2Table, rangeRecordArray)
U_NAMESPACE_END
#endif
......@@ -39,10 +39,10 @@
U_NAMESPACE_BEGIN
le_uint32 CursiveAttachmentSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
le_uint32 CursiveAttachmentSubtable::process(const LEReferenceTo<CursiveAttachmentSubtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
LEGlyphID glyphID = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(glyphID);
le_int32 coverageIndex = getGlyphCoverage(base, glyphID, success);
le_uint16 eeCount = SWAPW(entryExitCount);
if (coverageIndex < 0 || coverageIndex >= eeCount) {
......@@ -51,7 +51,7 @@ le_uint32 CursiveAttachmentSubtable::process(GlyphIterator *glyphIterator, const
}
LEPoint entryAnchor, exitAnchor;
Offset entryOffset = SWAPW(entryExitRecords[coverageIndex].entryAnchor);
Offset entryOffset = SWAPW(entryExitRecords[coverageIndex].entryAnchor); // TODO
Offset exitOffset = SWAPW(entryExitRecords[coverageIndex].exitAnchor);
if (entryOffset != 0) {
......
......@@ -57,8 +57,9 @@ struct CursiveAttachmentSubtable : GlyphPositioningSubtable
le_uint16 entryExitCount;
EntryExitRecord entryExitRecords[ANY_NUMBER];
le_uint32 process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
le_uint32 process(const LEReferenceTo<CursiveAttachmentSubtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
};
LE_VAR_ARRAY(CursiveAttachmentSubtable, entryExitRecords)
U_NAMESPACE_END
#endif
......
......@@ -57,6 +57,7 @@ private:
static const le_uint16 fieldSignBits[];
static const le_uint16 fieldBits[];
};
LE_VAR_ARRAY(DeviceTable, deltaValues)
U_NAMESPACE_END
#endif
......
......@@ -47,6 +47,8 @@ U_NAMESPACE_BEGIN
le_uint32 ExtensionSubtable::process(const LookupProcessor *lookupProcessor, le_uint16 lookupType,
GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const
{
const LEReferenceTo<ExtensionSubtable> thisRef(lookupProcessor->getReference(), success); // create a reference to this
if (LE_FAILURE(success)) {
return 0;
}
......@@ -55,10 +57,12 @@ le_uint32 ExtensionSubtable::process(const LookupProcessor *lookupProcessor, le_
if (elt != lookupType) {
le_uint32 extOffset = READ_LONG(extensionOffset);
LookupSubtable *subtable = (LookupSubtable *) ((char *) this + extOffset);
LEReferenceTo<LookupSubtable> subtable(thisRef, success, extOffset);
if(LE_SUCCESS(success)) {
return lookupProcessor->applySubtable(subtable, elt, glyphIterator, fontInstance, success);
}
}
return 0;
}
......
......@@ -38,19 +38,20 @@
U_NAMESPACE_BEGIN
const FeatureTable *FeatureListTable::getFeatureTable(le_uint16 featureIndex, LETag *featureTag) const
LEReferenceTo<FeatureTable> FeatureListTable::getFeatureTable(const LETableReference &base, le_uint16 featureIndex, LETag *featureTag, LEErrorCode &success) const
{
if (featureIndex >= SWAPW(featureCount)) {
return 0;
if (featureIndex >= SWAPW(featureCount) || LE_FAILURE(success)) {
return LEReferenceTo<FeatureTable>();
}
Offset featureTableOffset = featureRecordArray[featureIndex].featureTableOffset;
*featureTag = SWAPT(featureRecordArray[featureIndex].featureTag);
return (const FeatureTable *) ((char *) this + SWAPW(featureTableOffset));
return LEReferenceTo<FeatureTable>(base, success, SWAPW(featureTableOffset));
}
#if 0
/*
* Note: according to the OpenType Spec. v 1.4, the entries in the Feature
* List Table are sorted alphabetically by feature tag; however, there seem
......@@ -82,5 +83,6 @@ const FeatureTable *FeatureListTable::getFeatureTable(LETag featureTag) const
return 0;
#endif
}
#endif
U_NAMESPACE_END
......@@ -36,9 +36,12 @@
U_NAMESPACE_BEGIN
GDEFMarkFilter::GDEFMarkFilter(const GlyphDefinitionTableHeader *gdefTable)
GDEFMarkFilter::GDEFMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success)
: classDefTable(gdefTable->getGlyphClassDefinitionTable(gdefTable, success))
{
classDefTable = gdefTable->getGlyphClassDefinitionTable();
if(!classDefTable.isValid()) {
success = LE_INTERNAL_ERROR;
}
}
GDEFMarkFilter::~GDEFMarkFilter()
......
......@@ -46,13 +46,13 @@ U_NAMESPACE_BEGIN
class GDEFMarkFilter : public UMemory, public LEGlyphFilter
{
private:
const GlyphClassDefinitionTable *classDefTable;
const LEReferenceTo<GlyphClassDefinitionTable> classDefTable;
GDEFMarkFilter(const GDEFMarkFilter &other); // forbid copying of this class
GDEFMarkFilter &operator=(const GDEFMarkFilter &other); // forbid copying of this class
public:
GDEFMarkFilter(const GlyphDefinitionTableHeader *gdefTable);
GDEFMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success);
virtual ~GDEFMarkFilter();
virtual le_bool accept(LEGlyphID glyph) const;
......
......@@ -41,9 +41,10 @@ U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(GXLayoutEngine)
GXLayoutEngine::GXLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const MorphTableHeader *morphTable, LEErrorCode &success)
GXLayoutEngine::GXLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const LEReferenceTo<MorphTableHeader> &morphTable, LEErrorCode &success)
: LayoutEngine(fontInstance, scriptCode, languageCode, 0, success), fMorphTable(morphTable)
{
fMorphTable.orphan();
// nothing else to do?
}
......@@ -70,7 +71,7 @@ le_int32 GXLayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset,
return 0;
}
fMorphTable->process(glyphStorage);
fMorphTable->process(fMorphTable, glyphStorage, success);
return count;
}
......
......@@ -74,7 +74,7 @@ public:
*
* @internal
*/
GXLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const MorphTableHeader *morphTable, LEErrorCode &success);
GXLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const LEReferenceTo<MorphTableHeader> &morphTable, LEErrorCode &success);
/**
* The destructor, virtual for correct polymorphic invocation.
......@@ -104,7 +104,7 @@ protected:
*
* @internal
*/
const MorphTableHeader *fMorphTable;
LEReferenceTo<MorphTableHeader> fMorphTable;
/**
* This method does GX layout using the font's 'mort' table. It converts the
......
......@@ -39,7 +39,7 @@ U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(GXLayoutEngine2)
GXLayoutEngine2::GXLayoutEngine2(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const MorphTableHeader2 *morphTable, le_int32 typoFlags, LEErrorCode &success)
GXLayoutEngine2::GXLayoutEngine2(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const LEReferenceTo<MorphTableHeader2> &morphTable, le_int32 typoFlags, LEErrorCode &success)
: LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success), fMorphTable(morphTable)
{
// nothing else to do?
......@@ -68,7 +68,7 @@ le_int32 GXLayoutEngine2::computeGlyphs(const LEUnicode chars[], le_int32 offset
return 0;
}
fMorphTable->process(glyphStorage, fTypoFlags);
fMorphTable->process(fMorphTable, glyphStorage, fTypoFlags, success);
return count;
}
......
......@@ -73,7 +73,7 @@ public:
*
* @internal
*/
GXLayoutEngine2(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const MorphTableHeader2 *morphTable, le_int32 typoFlags, LEErrorCode &success);
GXLayoutEngine2(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const LEReferenceTo<MorphTableHeader2> &morphTable, le_int32 typoFlags, LEErrorCode &success);
/**
* The destructor, virtual for correct polymorphic invocation.
......@@ -103,7 +103,7 @@ protected:
*
* @internal
*/
const MorphTableHeader2 *fMorphTable;
const LEReferenceTo<MorphTableHeader2> fMorphTable;
/**
* This method does GX layout using the font's 'mort' table. It converts the
......
......@@ -36,24 +36,36 @@
U_NAMESPACE_BEGIN
const GlyphClassDefinitionTable *GlyphDefinitionTableHeader::getGlyphClassDefinitionTable() const
const LEReferenceTo<GlyphClassDefinitionTable>
GlyphDefinitionTableHeader::getGlyphClassDefinitionTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
LEErrorCode &success) const
{
return (const GlyphClassDefinitionTable *) ((char *) this + SWAPW(glyphClassDefOffset));
if(LE_FAILURE(success)) return LEReferenceTo<GlyphClassDefinitionTable>();
return LEReferenceTo<GlyphClassDefinitionTable>(base, success, SWAPW(glyphClassDefOffset));
}
const AttachmentListTable *GlyphDefinitionTableHeader::getAttachmentListTable() const
const LEReferenceTo<AttachmentListTable>
GlyphDefinitionTableHeader::getAttachmentListTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
LEErrorCode &success) const
{
return (const AttachmentListTable *) ((char *) this + SWAPW(attachListOffset));
if(LE_FAILURE(success)) return LEReferenceTo<AttachmentListTable>();
return LEReferenceTo<AttachmentListTable>(base, success, SWAPW(attachListOffset));
}
const LigatureCaretListTable *GlyphDefinitionTableHeader::getLigatureCaretListTable() const
const LEReferenceTo<LigatureCaretListTable>
GlyphDefinitionTableHeader::getLigatureCaretListTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
LEErrorCode &success) const
{
return (const LigatureCaretListTable *) ((char *) this + SWAPW(ligCaretListOffset));
if(LE_FAILURE(success)) return LEReferenceTo<LigatureCaretListTable>();
return LEReferenceTo<LigatureCaretListTable>(base, success, SWAPW(ligCaretListOffset));
}
const MarkAttachClassDefinitionTable *GlyphDefinitionTableHeader::getMarkAttachClassDefinitionTable() const
const LEReferenceTo<MarkAttachClassDefinitionTable>
GlyphDefinitionTableHeader::getMarkAttachClassDefinitionTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
LEErrorCode &success) const
{
return (const MarkAttachClassDefinitionTable *) ((char *) this + SWAPW(MarkAttachClassDefOffset));
if(LE_FAILURE(success)) return LEReferenceTo<MarkAttachClassDefinitionTable>();
return LEReferenceTo<MarkAttachClassDefinitionTable>(base, success, SWAPW(MarkAttachClassDefOffset));
}
U_NAMESPACE_END
......@@ -60,12 +60,14 @@ struct AttachmentListTable
le_uint16 glyphCount;
Offset attachPointTableOffsetArray[ANY_NUMBER];
};
LE_VAR_ARRAY(AttachmentListTable, attachPointTableOffsetArray)
struct AttachPointTable
{
le_uint16 pointCount;
le_uint16 pointIndexArray[ANY_NUMBER];
};
LE_VAR_ARRAY(AttachPointTable, pointIndexArray)
struct LigatureCaretListTable
{
......@@ -73,12 +75,14 @@ struct LigatureCaretListTable
le_uint16 ligGlyphCount;
Offset ligGlyphTableOffsetArray[ANY_NUMBER];
};
LE_VAR_ARRAY(LigatureCaretListTable, ligGlyphTableOffsetArray)
struct LigatureGlyphTable
{
le_uint16 caretCount;
Offset caretValueTableOffsetArray[ANY_NUMBER];
};
LE_VAR_ARRAY(LigatureGlyphTable, caretValueTableOffsetArray)
struct CaretValueTable
{
......@@ -111,10 +115,18 @@ struct GlyphDefinitionTableHeader
Offset ligCaretListOffset;
Offset MarkAttachClassDefOffset;
const GlyphClassDefinitionTable *getGlyphClassDefinitionTable() const;
const AttachmentListTable *getAttachmentListTable()const ;
const LigatureCaretListTable *getLigatureCaretListTable() const;
const MarkAttachClassDefinitionTable *getMarkAttachClassDefinitionTable() const;
const LEReferenceTo<GlyphClassDefinitionTable>
getGlyphClassDefinitionTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
LEErrorCode &success) const;
const LEReferenceTo<AttachmentListTable>
getAttachmentListTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
LEErrorCode &success)const ;
const LEReferenceTo<LigatureCaretListTable>
getLigatureCaretListTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
LEErrorCode &success) const;
const LEReferenceTo<MarkAttachClassDefinitionTable>
getMarkAttachClassDefinitionTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
LEErrorCode &success) const;
};
U_NAMESPACE_END
......
......@@ -41,18 +41,21 @@
U_NAMESPACE_BEGIN
GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags,
FeatureMask theFeatureMask, const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader)
FeatureMask theFeatureMask, const LEReferenceTo<GlyphDefinitionTableHeader> &theGlyphDefinitionTableHeader)
: direction(1), position(-1), nextLimit(-1), prevLimit(-1),
glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments),
srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureMask(theFeatureMask), glyphGroup(0),
glyphClassDefinitionTable(NULL), markAttachClassDefinitionTable(NULL)
glyphClassDefinitionTable(), markAttachClassDefinitionTable()
{
LEErrorCode success = LE_NO_ERROR; // TODO
le_int32 glyphCount = glyphStorage.getGlyphCount();
if (theGlyphDefinitionTableHeader != NULL) {
glyphClassDefinitionTable = theGlyphDefinitionTableHeader->getGlyphClassDefinitionTable();
markAttachClassDefinitionTable = theGlyphDefinitionTableHeader->getMarkAttachClassDefinitionTable();
if (theGlyphDefinitionTableHeader.isValid()) {
glyphClassDefinitionTable = theGlyphDefinitionTableHeader
-> getGlyphClassDefinitionTable(theGlyphDefinitionTableHeader, success);
markAttachClassDefinitionTable = theGlyphDefinitionTableHeader
->getMarkAttachClassDefinitionTable(theGlyphDefinitionTableHeader, success);
}
nextLimit = glyphCount;
......@@ -380,6 +383,7 @@ void GlyphIterator::setCursiveGlyph()
le_bool GlyphIterator::filterGlyph(le_uint32 index) const
{
LEErrorCode success = LE_NO_ERROR;
LEGlyphID glyphID = glyphStorage[index];
le_int32 glyphClass = gcdNoGlyphClass;
......@@ -387,8 +391,8 @@ le_bool GlyphIterator::filterGlyph(le_uint32 index) const
return TRUE;
}
if (glyphClassDefinitionTable != NULL) {
glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphID);
if (glyphClassDefinitionTable.isValid()) {
glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphClassDefinitionTable, glyphID, success);
}
switch (glyphClass)
......@@ -410,8 +414,9 @@ le_bool GlyphIterator::filterGlyph(le_uint32 index) const
le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift;
if ((markAttachType != 0) && (markAttachClassDefinitionTable != NULL)) {
return markAttachClassDefinitionTable->getGlyphClass(glyphID) != markAttachType;
if ((markAttachType != 0) && (markAttachClassDefinitionTable.isValid())) {
return markAttachClassDefinitionTable
-> getGlyphClass(markAttachClassDefinitionTable, glyphID, success) != markAttachType;
}
return FALSE;
......@@ -461,6 +466,7 @@ le_bool GlyphIterator::nextInternal(le_uint32 delta)
while (newPosition != nextLimit && delta > 0) {
do {
newPosition += direction;
//fprintf(stderr,"%s:%d:%s: newPosition = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, newPosition, delta);
} while (newPosition != nextLimit && filterGlyph(newPosition));
delta -= 1;
......@@ -468,6 +474,7 @@ le_bool GlyphIterator::nextInternal(le_uint32 delta)
position = newPosition;
//fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);
return position != nextLimit;
}
......@@ -483,6 +490,7 @@ le_bool GlyphIterator::prevInternal(le_uint32 delta)
while (newPosition != prevLimit && delta > 0) {
do {
newPosition -= direction;
//fprintf(stderr,"%s:%d:%s: newPosition = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, newPosition, delta);
} while (newPosition != prevLimit && filterGlyph(newPosition));
delta -= 1;
......@@ -490,6 +498,7 @@ le_bool GlyphIterator::prevInternal(le_uint32 delta)
position = newPosition;
//fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);
return position != prevLimit;
}
......
......@@ -49,7 +49,7 @@ class GlyphPositionAdjustments;
class GlyphIterator : public UMemory {
public:
GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags,
FeatureMask theFeatureMask, const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader);
FeatureMask theFeatureMask, const LEReferenceTo<GlyphDefinitionTableHeader> &theGlyphDefinitionTableHeader);
GlyphIterator(GlyphIterator &that);
......@@ -117,8 +117,8 @@ private:
FeatureMask featureMask;
le_int32 glyphGroup;
const GlyphClassDefinitionTable *glyphClassDefinitionTable;
const MarkAttachClassDefinitionTable *markAttachClassDefinitionTable;
LEReferenceTo<GlyphClassDefinitionTable> glyphClassDefinitionTable;
LEReferenceTo<MarkAttachClassDefinitionTable> markAttachClassDefinitionTable;
GlyphIterator &operator=(const GlyphIterator &other); // forbid copying of this class
};
......
......@@ -37,21 +37,22 @@
U_NAMESPACE_BEGIN
le_bool GlyphLookupTableHeader::coversScript(LETag scriptTag) const
le_bool GlyphLookupTableHeader::coversScript(const LETableReference &base, LETag scriptTag, LEErrorCode &success) const
{
const ScriptListTable *scriptListTable = (const ScriptListTable *) ((char *)this + SWAPW(scriptListOffset));
LEReferenceTo<ScriptListTable> scriptListTable(base, success, SWAPW(scriptListOffset));
return scriptListOffset != 0 && scriptListTable->findScript(scriptTag) != NULL;
return (scriptListOffset != 0) && scriptListTable->findScript(scriptListTable, scriptTag, success) .isValid();
}
le_bool GlyphLookupTableHeader::coversScriptAndLanguage(LETag scriptTag, LETag languageTag, le_bool exactMatch) const
le_bool GlyphLookupTableHeader::coversScriptAndLanguage(const LETableReference &base, LETag scriptTag, LETag languageTag, LEErrorCode &success, le_bool exactMatch) const
{
const ScriptListTable *scriptListTable = (const ScriptListTable *) ((char *)this + SWAPW(scriptListOffset));
const LangSysTable *langSysTable = scriptListTable->findLanguage(scriptTag, languageTag, exactMatch);
LEReferenceTo<ScriptListTable> scriptListTable(base, success, SWAPW(scriptListOffset));
LEReferenceTo<LangSysTable> langSysTable = scriptListTable->findLanguage(scriptListTable,
scriptTag, languageTag, success, exactMatch);
// FIXME: could check featureListOffset, lookupListOffset, and lookup count...
// Note: don't have to SWAPW langSysTable->featureCount to check for non-zero.
return langSysTable != NULL && langSysTable->featureCount != 0;
return LE_SUCCESS(success)&&langSysTable.isValid() && langSysTable->featureCount != 0;
}
U_NAMESPACE_END
......@@ -49,8 +49,8 @@ struct GlyphLookupTableHeader
Offset featureListOffset;
Offset lookupListOffset;
le_bool coversScript(LETag scriptTag) const;
le_bool coversScriptAndLanguage(LETag scriptTag, LETag languageTag, le_bool exactMatch = FALSE) const;
le_bool coversScript(const LETableReference &base, LETag scriptTag, LEErrorCode &success) const;
le_bool coversScriptAndLanguage(const LETableReference &base, LETag scriptTag, LETag languageTag, LEErrorCode &success, le_bool exactMatch = FALSE) const;
};
U_NAMESPACE_END
......
......@@ -41,16 +41,16 @@
U_NAMESPACE_BEGIN
void GlyphPositioningTableHeader::process(LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments, le_bool rightToLeft,
void GlyphPositioningTableHeader::process(const LEReferenceTo<GlyphPositioningTableHeader> &base, LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments, le_bool rightToLeft,
LETag scriptTag, LETag languageTag,
const GlyphDefinitionTableHeader *glyphDefinitionTableHeader, LEErrorCode &success,
const LEReferenceTo<GlyphDefinitionTableHeader> &glyphDefinitionTableHeader, LEErrorCode &success,
const LEFontInstance *fontInstance, const FeatureMap *featureMap, le_int32 featureMapCount, le_bool featureOrder) const
{
if (LE_FAILURE(success)) {
return;
}
GlyphPositioningLookupProcessor processor(this, scriptTag, languageTag, featureMap, featureMapCount, featureOrder, success);
GlyphPositioningLookupProcessor processor(base, scriptTag, languageTag, featureMap, featureMapCount, featureOrder, success);
if (LE_FAILURE(success)) {
return;
}
......
......@@ -40,6 +40,7 @@
#include "OpenTypeTables.h"
#include "Lookups.h"
#include "GlyphLookupTables.h"
#include "LETableReference.h"
U_NAMESPACE_BEGIN
......@@ -51,9 +52,9 @@ struct GlyphDefinitionTableHeader;
struct GlyphPositioningTableHeader : public GlyphLookupTableHeader
{
void process(LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments,
void process(const LEReferenceTo<GlyphPositioningTableHeader> &base, LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments,
le_bool rightToLeft, LETag scriptTag, LETag languageTag,
const GlyphDefinitionTableHeader *glyphDefinitionTableHeader, LEErrorCode &success,
const LEReferenceTo<GlyphDefinitionTableHeader> &glyphDefinitionTableHeader, LEErrorCode &success,
const LEFontInstance *fontInstance, const FeatureMap *featureMap, le_int32 featureMapCount, le_bool featureOrder) const;
};
......
......@@ -57,7 +57,7 @@ typedef ContextualSubstitutionSubtable ContextualPositioningSubtable;
typedef ChainingContextualSubstitutionSubtable ChainingContextualPositioningSubtable;
GlyphPositioningLookupProcessor::GlyphPositioningLookupProcessor(
const GlyphPositioningTableHeader *glyphPositioningTableHeader,
const LEReferenceTo<GlyphPositioningTableHeader> &glyphPositioningTableHeader,
LETag scriptTag,
LETag languageTag,
const FeatureMap *featureMap,
......@@ -65,7 +65,7 @@ GlyphPositioningLookupProcessor::GlyphPositioningLookupProcessor(
le_bool featureOrder,
LEErrorCode& success)
: LookupProcessor(
(char *) glyphPositioningTableHeader,
glyphPositioningTableHeader,
SWAPW(glyphPositioningTableHeader->scriptListOffset),
SWAPW(glyphPositioningTableHeader->featureListOffset),
SWAPW(glyphPositioningTableHeader->lookupListOffset),
......@@ -84,7 +84,7 @@ GlyphPositioningLookupProcessor::GlyphPositioningLookupProcessor()
{
}
le_uint32 GlyphPositioningLookupProcessor::applySubtable(const LookupSubtable *lookupSubtable, le_uint16 lookupType,
le_uint32 GlyphPositioningLookupProcessor::applySubtable(const LEReferenceTo<LookupSubtable> &lookupSubtable, le_uint16 lookupType,
GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance,
LEErrorCode& success) const
......@@ -102,55 +102,55 @@ le_uint32 GlyphPositioningLookupProcessor::applySubtable(const LookupSubtable *l
case gpstSingle:
{
const SinglePositioningSubtable *subtable = (const SinglePositioningSubtable *) lookupSubtable;
LEReferenceTo<SinglePositioningSubtable> subtable(lookupSubtable, success);
delta = subtable->process(glyphIterator, fontInstance);
delta = subtable->process(subtable, glyphIterator, fontInstance, success);
break;
}
case gpstPair:
{
const PairPositioningSubtable *subtable = (const PairPositioningSubtable *) lookupSubtable;
LEReferenceTo<PairPositioningSubtable> subtable(lookupSubtable, success);
delta = subtable->process(glyphIterator, fontInstance);
delta = subtable->process(subtable, glyphIterator, fontInstance, success);
break;
}
case gpstCursive:
{
const CursiveAttachmentSubtable *subtable = (const CursiveAttachmentSubtable *) lookupSubtable;
LEReferenceTo<CursiveAttachmentSubtable> subtable(lookupSubtable, success);
delta = subtable->process(glyphIterator, fontInstance);
delta = subtable->process(subtable, glyphIterator, fontInstance, success);
break;
}
case gpstMarkToBase:
{
const MarkToBasePositioningSubtable *subtable = (const MarkToBasePositioningSubtable *) lookupSubtable;
LEReferenceTo<MarkToBasePositioningSubtable> subtable(lookupSubtable, success);
delta = subtable->process(glyphIterator, fontInstance);
delta = subtable->process(subtable, glyphIterator, fontInstance, success);
break;
}
case gpstMarkToLigature:
{
const MarkToLigaturePositioningSubtable *subtable = (const MarkToLigaturePositioningSubtable *) lookupSubtable;
LEReferenceTo<MarkToLigaturePositioningSubtable> subtable(lookupSubtable, success);
delta = subtable->process(glyphIterator, fontInstance);
delta = subtable->process(subtable, glyphIterator, fontInstance, success);
break;
}
case gpstMarkToMark:
{
const MarkToMarkPositioningSubtable *subtable = (const MarkToMarkPositioningSubtable *) lookupSubtable;
LEReferenceTo<MarkToMarkPositioningSubtable> subtable(lookupSubtable, success);
delta = subtable->process(glyphIterator, fontInstance);
delta = subtable->process(subtable, glyphIterator, fontInstance, success);
break;
}
case gpstContext:
{
const ContextualPositioningSubtable *subtable = (const ContextualPositioningSubtable *) lookupSubtable;
LEReferenceTo<ContextualPositioningSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, glyphIterator, fontInstance, success);
break;
......@@ -158,7 +158,7 @@ le_uint32 GlyphPositioningLookupProcessor::applySubtable(const LookupSubtable *l
case gpstChainedContext:
{
const ChainingContextualPositioningSubtable *subtable = (const ChainingContextualPositioningSubtable *) lookupSubtable;
LEReferenceTo<ChainingContextualPositioningSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, glyphIterator, fontInstance, success);
break;
......@@ -166,7 +166,7 @@ le_uint32 GlyphPositioningLookupProcessor::applySubtable(const LookupSubtable *l
case gpstExtension:
{
const ExtensionSubtable *subtable = (const ExtensionSubtable *) lookupSubtable;
LEReferenceTo<ExtensionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, lookupType, glyphIterator, fontInstance, success);
break;
......
......@@ -51,7 +51,7 @@ U_NAMESPACE_BEGIN
class GlyphPositioningLookupProcessor : public LookupProcessor
{
public:
GlyphPositioningLookupProcessor(const GlyphPositioningTableHeader *glyphPositioningTableHeader,
GlyphPositioningLookupProcessor(const LEReferenceTo<GlyphPositioningTableHeader> &glyphPositioningTableHeader,
LETag scriptTag,
LETag languageTag,
const FeatureMap *featureMap,
......@@ -61,7 +61,7 @@ public:
virtual ~GlyphPositioningLookupProcessor();
virtual le_uint32 applySubtable(const LookupSubtable *lookupSubtable, le_uint16 lookupType, GlyphIterator *glyphIterator,
virtual le_uint32 applySubtable(const LEReferenceTo<LookupSubtable> &lookupSubtable, le_uint16 lookupType, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, LEErrorCode& success) const;
protected:
......
......@@ -51,7 +51,7 @@
U_NAMESPACE_BEGIN
GlyphSubstitutionLookupProcessor::GlyphSubstitutionLookupProcessor(
const GlyphSubstitutionTableHeader *glyphSubstitutionTableHeader,
const LEReferenceTo<GlyphSubstitutionTableHeader> &glyphSubstitutionTableHeader,
LETag scriptTag,
LETag languageTag,
const LEGlyphFilter *filter,
......@@ -60,7 +60,7 @@ GlyphSubstitutionLookupProcessor::GlyphSubstitutionLookupProcessor(
le_bool featureOrder,
LEErrorCode& success)
: LookupProcessor(
(char *) glyphSubstitutionTableHeader,
glyphSubstitutionTableHeader,
SWAPW(glyphSubstitutionTableHeader->scriptListOffset),
SWAPW(glyphSubstitutionTableHeader->featureListOffset),
SWAPW(glyphSubstitutionTableHeader->lookupListOffset),
......@@ -73,7 +73,7 @@ GlyphSubstitutionLookupProcessor::GlyphSubstitutionLookupProcessor()
{
}
le_uint32 GlyphSubstitutionLookupProcessor::applySubtable(const LookupSubtable *lookupSubtable, le_uint16 lookupType,
le_uint32 GlyphSubstitutionLookupProcessor::applySubtable(const LEReferenceTo<LookupSubtable> &lookupSubtable, le_uint16 lookupType,
GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const
{
if (LE_FAILURE(success)) {
......@@ -89,39 +89,39 @@ le_uint32 GlyphSubstitutionLookupProcessor::applySubtable(const LookupSubtable *
case gsstSingle:
{
const SingleSubstitutionSubtable *subtable = (const SingleSubstitutionSubtable *) lookupSubtable;
const LEReferenceTo<SingleSubstitutionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(glyphIterator, fFilter);
delta = subtable->process(subtable, glyphIterator, success, fFilter);
break;
}
case gsstMultiple:
{
const MultipleSubstitutionSubtable *subtable = (const MultipleSubstitutionSubtable *) lookupSubtable;
const LEReferenceTo<MultipleSubstitutionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(glyphIterator, success, fFilter);
delta = subtable->process(subtable, glyphIterator, success, fFilter);
break;
}
case gsstAlternate:
{
const AlternateSubstitutionSubtable *subtable = (const AlternateSubstitutionSubtable *) lookupSubtable;
const LEReferenceTo<AlternateSubstitutionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(glyphIterator, fFilter);
delta = subtable->process(subtable, glyphIterator, success, fFilter);
break;
}
case gsstLigature:
{
const LigatureSubstitutionSubtable *subtable = (const LigatureSubstitutionSubtable *) lookupSubtable;
const LEReferenceTo<LigatureSubstitutionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(glyphIterator, fFilter);
delta = subtable->process(subtable, glyphIterator, success, fFilter);
break;
}
case gsstContext:
{
const ContextualSubstitutionSubtable *subtable = (const ContextualSubstitutionSubtable *) lookupSubtable;
const LEReferenceTo<ContextualSubstitutionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, glyphIterator, fontInstance, success);
break;
......@@ -129,7 +129,7 @@ le_uint32 GlyphSubstitutionLookupProcessor::applySubtable(const LookupSubtable *
case gsstChainingContext:
{
const ChainingContextualSubstitutionSubtable *subtable = (const ChainingContextualSubstitutionSubtable *) lookupSubtable;
const LEReferenceTo<ChainingContextualSubstitutionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, glyphIterator, fontInstance, success);
break;
......@@ -137,7 +137,7 @@ le_uint32 GlyphSubstitutionLookupProcessor::applySubtable(const LookupSubtable *
case gsstExtension:
{
const ExtensionSubtable *subtable = (const ExtensionSubtable *) lookupSubtable;
const LEReferenceTo<ExtensionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, lookupType, glyphIterator, fontInstance, success);
break;
......
......@@ -52,7 +52,7 @@ U_NAMESPACE_BEGIN
class GlyphSubstitutionLookupProcessor : public LookupProcessor
{
public:
GlyphSubstitutionLookupProcessor(const GlyphSubstitutionTableHeader *glyphSubstitutionTableHeader,
GlyphSubstitutionLookupProcessor(const LEReferenceTo<GlyphSubstitutionTableHeader> &glyphSubstitutionTableHeader,
LETag scriptTag,
LETag languageTag,
const LEGlyphFilter *filter,
......@@ -63,7 +63,7 @@ public:
virtual ~GlyphSubstitutionLookupProcessor();
virtual le_uint32 applySubtable(const LookupSubtable *lookupSubtable, le_uint16 lookupType, GlyphIterator *glyphIterator,
virtual le_uint32 applySubtable(const LEReferenceTo<LookupSubtable> &lookupSubtable, le_uint16 lookupType, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, LEErrorCode& success) const;
protected:
......
......@@ -42,11 +42,12 @@
U_NAMESPACE_BEGIN
le_int32 GlyphSubstitutionTableHeader::process(LEGlyphStorage &glyphStorage,
le_int32 GlyphSubstitutionTableHeader::process(const LEReferenceTo<GlyphSubstitutionTableHeader> &base,
LEGlyphStorage &glyphStorage,
le_bool rightToLeft,
LETag scriptTag,
LETag languageTag,
const GlyphDefinitionTableHeader *glyphDefinitionTableHeader,
const LEReferenceTo<GlyphDefinitionTableHeader> &glyphDefinitionTableHeader,
const LEGlyphFilter *filter,
const FeatureMap *featureMap,
le_int32 featureMapCount,
......@@ -57,7 +58,7 @@ le_int32 GlyphSubstitutionTableHeader::process(LEGlyphStorage &glyphStorage,
return 0;
}
GlyphSubstitutionLookupProcessor processor(this, scriptTag, languageTag, filter, featureMap, featureMapCount, featureOrder, success);
GlyphSubstitutionLookupProcessor processor(base, scriptTag, languageTag, filter, featureMap, featureMapCount, featureOrder, success);
return processor.process(glyphStorage, NULL, rightToLeft, glyphDefinitionTableHeader, NULL, success);
}
......
......@@ -50,11 +50,12 @@ struct GlyphDefinitionTableHeader;
struct GlyphSubstitutionTableHeader : public GlyphLookupTableHeader
{
le_int32 process(LEGlyphStorage &glyphStorage,
le_int32 process(const LEReferenceTo<GlyphSubstitutionTableHeader> &base,
LEGlyphStorage &glyphStorage,
le_bool rightToLeft,
LETag scriptTag,
LETag languageTag,
const GlyphDefinitionTableHeader *glyphDefinitionTableHeader,
const LEReferenceTo<GlyphDefinitionTableHeader> &glyphDefinitionTableHeader,
const LEGlyphFilter *filter,
const FeatureMap *featureMap,
le_int32 featureMapCount,
......
......@@ -64,7 +64,7 @@ static const le_int32 featureMapCount = LE_ARRAY_SIZE(featureMap);
#define features (loclFeatureMask)
HanOpenTypeLayoutEngine::HanOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success)
{
fFeatureMap = featureMap;
......
......@@ -73,7 +73,7 @@ public:
* @internal
*/
HanOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTablem, LEErrorCode &success);
le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTablem, LEErrorCode &success);
/**
......
......@@ -209,7 +209,7 @@ static le_int32 getCharClass(LEUnicode ch, LEUnicode &lead, LEUnicode &vowel, LE
}
HangulOpenTypeLayoutEngine::HangulOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 /*languageCode*/,
le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, korLanguageCode, typoFlags, gsubTable, success)
{
fFeatureMap = featureMap;
......
......@@ -79,7 +79,7 @@ public:
* @internal
*/
HangulOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success);
le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success);
/**
* This constructor is used when the font requires a "canned" GSUB table which can't be known
......
......@@ -54,16 +54,21 @@ struct FeatureTable
le_uint16 lookupCount;
le_uint16 lookupListIndexArray[ANY_NUMBER];
};
LE_VAR_ARRAY(FeatureTable, lookupListIndexArray)
struct FeatureListTable
{
le_uint16 featureCount;
FeatureRecord featureRecordArray[ANY_NUMBER];
const FeatureTable *getFeatureTable(le_uint16 featureIndex, LETag *featureTag) const;
LEReferenceTo<FeatureTable> getFeatureTable(const LETableReference &base, le_uint16 featureIndex, LETag *featureTag, LEErrorCode &success) const;
const FeatureTable *getFeatureTable(LETag featureTag) const;
#if 0
const LEReferenceTo<FeatureTable> getFeatureTable(const LETableReference &base, LETag featureTag, LEErrorCode &success) const;
#endif
};
LE_VAR_ARRAY(FeatureListTable, featureRecordArray)
U_NAMESPACE_END
#endif
......@@ -50,7 +50,7 @@ U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndicOpenTypeLayoutEngine)
IndicOpenTypeLayoutEngine::IndicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
le_int32 typoFlags, le_bool version2, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
le_int32 typoFlags, le_bool version2, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success), fMPreFixups(NULL)
{
if ( version2 ) {
......
......@@ -81,7 +81,7 @@ public:
* @internal
*/
IndicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
le_int32 typoFlags, le_bool version2, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success);
le_int32 typoFlags, le_bool version2, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success);
/**
* This constructor is used when the font requires a "canned" GSUB table which can't be known
......
......@@ -43,11 +43,14 @@ U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndicRearrangementProcessor)
IndicRearrangementProcessor::IndicRearrangementProcessor(const MorphSubtableHeader *morphSubtableHeader)
: StateTableProcessor(morphSubtableHeader)
IndicRearrangementProcessor::IndicRearrangementProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
: StateTableProcessor(morphSubtableHeader, success),
indicRearrangementSubtableHeader(morphSubtableHeader, success),
entryTable(stateTableHeader, success, (const IndicRearrangementStateEntry*)(&stateTableHeader->stHeader),
entryTableOffset, LE_UNBOUNDED_ARRAY),
int16Table(stateTableHeader, success, (const le_int16*)entryTable.getAlias(), 0, LE_UNBOUNDED_ARRAY)
{
indicRearrangementSubtableHeader = (const IndicRearrangementSubtableHeader *) morphSubtableHeader;
entryTable = (const IndicRearrangementStateEntry *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
}
IndicRearrangementProcessor::~IndicRearrangementProcessor()
......@@ -62,7 +65,8 @@ void IndicRearrangementProcessor::beginStateTable()
ByteOffset IndicRearrangementProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index)
{
const IndicRearrangementStateEntry *entry = &entryTable[index];
LEErrorCode success = LE_NO_ERROR; // todo- make a param?
const IndicRearrangementStateEntry *entry = entryTable.getAlias(index,success);
ByteOffset newState = SWAPW(entry->newStateOffset);
IndicRearrangementFlags flags = (IndicRearrangementFlags) SWAPW(entry->flags);
......
......@@ -58,7 +58,7 @@ public:
void doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb) const;
IndicRearrangementProcessor(const MorphSubtableHeader *morphSubtableHeader);
IndicRearrangementProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
virtual ~IndicRearrangementProcessor();
/**
......@@ -79,8 +79,9 @@ protected:
le_int32 firstGlyph;
le_int32 lastGlyph;
const IndicRearrangementStateEntry *entryTable;
const IndicRearrangementSubtableHeader *indicRearrangementSubtableHeader;
LEReferenceTo<IndicRearrangementSubtableHeader> indicRearrangementSubtableHeader;
LEReferenceToArrayOf<IndicRearrangementStateEntry> entryTable;
LEReferenceToArrayOf<le_int16> int16Table;
};
......
......@@ -43,11 +43,11 @@ U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndicRearrangementProcessor2)
IndicRearrangementProcessor2::IndicRearrangementProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
: StateTableProcessor2(morphSubtableHeader)
IndicRearrangementProcessor2::IndicRearrangementProcessor2(
const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
: StateTableProcessor2(morphSubtableHeader, success), indicRearrangementSubtableHeader(morphSubtableHeader, success),
entryTable(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY)
{
indicRearrangementSubtableHeader = (const IndicRearrangementSubtableHeader2 *) morphSubtableHeader;
entryTable = (const IndicRearrangementStateEntry2 *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
}
IndicRearrangementProcessor2::~IndicRearrangementProcessor2()
......@@ -60,9 +60,11 @@ void IndicRearrangementProcessor2::beginStateTable()
lastGlyph = 0;
}
le_uint16 IndicRearrangementProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index)
le_uint16 IndicRearrangementProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph,
EntryTableIndex2 index, LEErrorCode &success)
{
const IndicRearrangementStateEntry2 *entry = &entryTable[index];
const IndicRearrangementStateEntry2 *entry = entryTable.getAlias(index, success);
if (LE_FAILURE(success)) return 0; // TODO - what to return in bad state?
le_uint16 newState = SWAPW(entry->newStateIndex); // index to the new state
IndicRearrangementFlags flags = (IndicRearrangementFlags) SWAPW(entry->flags);
......
......@@ -52,13 +52,13 @@ class IndicRearrangementProcessor2 : public StateTableProcessor2
public:
virtual void beginStateTable();
virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index);
virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index, LEErrorCode &success);
virtual void endStateTable();
void doRearrangementAction(LEGlyphStorage &glyphStorage, IndicRearrangementVerb verb) const;
IndicRearrangementProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
IndicRearrangementProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
virtual ~IndicRearrangementProcessor2();
/**
......@@ -79,8 +79,8 @@ protected:
le_int32 firstGlyph;
le_int32 lastGlyph;
const IndicRearrangementStateEntry2 *entryTable;
const IndicRearrangementSubtableHeader2 *indicRearrangementSubtableHeader;
LEReferenceToArrayOf<IndicRearrangementStateEntry2> entryTable;
LEReferenceTo<IndicRearrangementSubtableHeader2> indicRearrangementSubtableHeader;
};
......
......@@ -658,6 +658,11 @@ le_int32 IndicReordering::reorder(const LEUnicode *chars, le_int32 charCount, le
MPreFixups *mpreFixups = NULL;
const IndicClassTable *classTable = IndicClassTable::getScriptClassTable(scriptCode);
if(classTable==NULL) {
success = LE_MEMORY_ALLOCATION_ERROR;
return 0;
}
if (classTable->scriptFlags & SF_MPRE_FIXUP) {
mpreFixups = new MPreFixups(charCount);
if (mpreFixups == NULL) {
......
......@@ -48,7 +48,7 @@ struct PairInfo {
le_int16 value; // fword, kern value in funits
};
#define KERN_PAIRINFO_SIZE 6
LE_CORRECT_SIZE(PairInfo, KERN_PAIRINFO_SIZE)
struct Subtable_0 {
le_uint16 nPairs;
le_uint16 searchRange;
......@@ -56,6 +56,7 @@ struct Subtable_0 {
le_uint16 rangeShift;
};
#define KERN_SUBTABLE_0_HEADER_SIZE 8
LE_CORRECT_SIZE(Subtable_0, KERN_SUBTABLE_0_HEADER_SIZE)
// Kern table version 0 only
struct SubtableHeader {
......@@ -64,6 +65,7 @@ struct SubtableHeader {
le_uint16 coverage;
};
#define KERN_SUBTABLE_HEADER_SIZE 6
LE_CORRECT_SIZE(SubtableHeader, KERN_SUBTABLE_HEADER_SIZE)
// Version 0 only, version 1 has different layout
struct KernTableHeader {
......@@ -71,6 +73,7 @@ struct KernTableHeader {
le_uint16 nTables;
};
#define KERN_TABLE_HEADER_SIZE 4
LE_CORRECT_SIZE(KernTableHeader, KERN_TABLE_HEADER_SIZE)
#define COVERAGE_HORIZONTAL 0x1
#define COVERAGE_MINIMUM 0x2
......@@ -92,21 +95,21 @@ struct KernTableHeader {
* TODO: support multiple subtables
* TODO: respect header flags
*/
KernTable::KernTable(const LEFontInstance* font_, const void* tableData)
: pairs(0), font(font_)
KernTable::KernTable(const LETableReference& base, LEErrorCode &success)
: pairs(), pairsSwapped(NULL), fTable(base)
{
const KernTableHeader* header = (const KernTableHeader*)tableData;
if (header == 0) {
if(LE_FAILURE(success) || (fTable.isEmpty())) {
#if DEBUG
fprintf(stderr, "no kern data\n");
#endif
return;
}
LEReferenceTo<KernTableHeader> header(fTable, success);
#if DEBUG
// dump first 32 bytes of header
for (int i = 0; i < 64; ++i) {
fprintf(stderr, "%0.2x ", ((const char*)tableData)[i]&0xff);
fprintf(stderr, "%0.2x ", ((const char*)header.getAlias())[i]&0xff);
if (((i+1)&0xf) == 0) {
fprintf(stderr, "\n");
} else if (((i+1)&0x7) == 0) {
......@@ -115,12 +118,17 @@ KernTable::KernTable(const LEFontInstance* font_, const void* tableData)
}
#endif
if (header->version == 0 && SWAPW(header->nTables) > 0) {
const SubtableHeader* subhead = (const SubtableHeader*)((char*)tableData + KERN_TABLE_HEADER_SIZE);
if (subhead->version == 0) {
if(LE_FAILURE(success)) return;
if (!header.isEmpty() && header->version == 0 && SWAPW(header->nTables) > 0) {
LEReferenceTo<SubtableHeader> subhead(header, success, KERN_TABLE_HEADER_SIZE);
if (LE_SUCCESS(success) && !subhead.isEmpty() && subhead->version == 0) {
coverage = SWAPW(subhead->coverage);
if (coverage & COVERAGE_HORIZONTAL) { // only handle horizontal kerning
const Subtable_0* table = (const Subtable_0*)((char*)subhead + KERN_SUBTABLE_HEADER_SIZE);
LEReferenceTo<Subtable_0> table(subhead, success, KERN_SUBTABLE_HEADER_SIZE);
if(table.isEmpty() || LE_FAILURE(success)) return;
nPairs = SWAPW(table->nPairs);
......@@ -134,19 +142,31 @@ KernTable::KernTable(const LEFontInstance* font_, const void* tableData)
rangeShift = (nPairs * KERN_PAIRINFO_SIZE) - searchRange;
#endif
pairs = (PairInfo*)font->getKernPairs();
if (pairs == NULL) {
char *pairData = (char*)table + KERN_SUBTABLE_0_HEADER_SIZE;
char *pptr = pairData;
pairs = (PairInfo*)(malloc(nPairs*sizeof(PairInfo)));
PairInfo *p = (PairInfo*)pairs;
for (int i = 0; i < nPairs; i++, pptr += KERN_PAIRINFO_SIZE, p++) {
memcpy(p, pptr, KERN_PAIRINFO_SIZE);
if(LE_SUCCESS(success) && nPairs>0) {
// pairs is an instance member, and table is on the stack.
// set 'pairs' based on table.getAlias(). This will range check it.
pairs = LEReferenceToArrayOf<PairInfo>(fTable, // based on overall table
success,
(const PairInfo*)table.getAlias(), // subtable 0 + ..
KERN_SUBTABLE_0_HEADER_SIZE, // .. offset of header size
nPairs); // count
}
if (LE_SUCCESS(success) && pairs.isValid()) {
pairsSwapped = (PairInfo*)(malloc(nPairs*sizeof(PairInfo)));
PairInfo *p = (PairInfo*)pairsSwapped;
for (int i = 0; LE_SUCCESS(success) && i < nPairs; i++, p++) {
memcpy(p, pairs.getAlias(i,success), KERN_PAIRINFO_SIZE);
p->key = SWAPL(p->key);
}
font->setKernPairs((void*)pairs);
fTable.getFont()->setKernPairs((void*)pairsSwapped); // store it
}
#if 0
fprintf(stderr, "coverage: %0.4x nPairs: %d pairs %p\n", coverage, nPairs, pairs.getAlias());
fprintf(stderr, " searchRange: %d entrySelector: %d rangeShift: %d\n", searchRange, entrySelector, rangeShift);
fprintf(stderr, "[[ ignored font table entries: range %d selector %d shift %d ]]\n", SWAPW(table->searchRange), SWAPW(table->entrySelector), SWAPW(table->rangeShift));
#endif
#if DEBUG
fprintf(stderr, "coverage: %0.4x nPairs: %d pairs 0x%x\n", coverage, nPairs, pairs);
fprintf(stderr,
......@@ -194,14 +214,17 @@ KernTable::KernTable(const LEFontInstance* font_, const void* tableData)
* Process the glyph positions. The positions array has two floats for each
* glyph, plus a trailing pair to mark the end of the last glyph.
*/
void KernTable::process(LEGlyphStorage& storage)
void KernTable::process(LEGlyphStorage& storage, LEErrorCode &success)
{
if (pairs) {
LEErrorCode success = LE_NO_ERROR;
if(LE_FAILURE(success)) return;
if (pairsSwapped) {
success = LE_NO_ERROR;
le_uint32 key = storage[0]; // no need to mask off high bits
float adjust = 0;
for (int i = 1, e = storage.getGlyphCount(); i < e; ++i) {
for (int i = 1, e = storage.getGlyphCount(); LE_SUCCESS(success)&& i < e; ++i) {
key = key << 16 | (storage[i] & 0xffff);
// argh, to do a binary search, we need to have the pair list in sorted order
......@@ -209,7 +232,7 @@ void KernTable::process(LEGlyphStorage& storage)
// so either I have to swap the element each time I examine it, or I have to swap
// all the elements ahead of time and store them in the font
const PairInfo* p = pairs;
const PairInfo* p = pairsSwapped;
const PairInfo* tp = (const PairInfo*)(p + (rangeShift/KERN_PAIRINFO_SIZE)); /* rangeshift is in original table bytes */
if (key > tp->key) {
p = tp;
......@@ -225,7 +248,7 @@ void KernTable::process(LEGlyphStorage& storage)
tp = (const PairInfo*)(p + (probe/KERN_PAIRINFO_SIZE));
le_uint32 tkey = tp->key;
#if DEBUG
fprintf(stdout, " %.3d (%0.8x)\n", (tp - pairs), tkey);
fprintf(stdout, " %.3d (%0.8x)\n", (tp - pairsSwapped), tkey);
#endif
if (tkey <= key) {
if (tkey == key) {
......@@ -240,10 +263,10 @@ void KernTable::process(LEGlyphStorage& storage)
// device transform, or a faster way, such as moving the
// entire kern table up to Java.
LEPoint pt;
pt.fX = font->xUnitsToPoints(value);
pt.fX = fTable.getFont()->xUnitsToPoints(value);
pt.fY = 0;
font->getKerningAdjustment(pt);
fTable.getFont()->getKerningAdjustment(pt);
adjust += pt.fX;
break;
}
......
......@@ -26,7 +26,7 @@
/*
*
*
* (C) Copyright IBM Corp. 2004-2005 - All Rights Reserved
* (C) Copyright IBM Corp. 2004-2013 - All Rights Reserved
*
*/
......@@ -38,6 +38,7 @@
#endif
#include "LETypes.h"
#include "LETableReference.h"
//#include "LEFontInstance.h"
//#include "LEGlyphStorage.h"
......@@ -56,19 +57,20 @@ class U_LAYOUT_API KernTable
private:
le_uint16 coverage;
le_uint16 nPairs;
const PairInfo* pairs;
const LEFontInstance* font;
LEReferenceToArrayOf<PairInfo> pairs;
PairInfo *pairsSwapped;
const LETableReference &fTable;
le_uint16 searchRange;
le_uint16 entrySelector;
le_uint16 rangeShift;
public:
KernTable(const LEFontInstance* font, const void* tableData);
KernTable(const LETableReference &table, LEErrorCode &success);
/*
* Process the glyph positions.
*/
void process(LEGlyphStorage& storage);
void process(LEGlyphStorage& storage, LEErrorCode &success);
};
U_NAMESPACE_END
......
......@@ -43,7 +43,7 @@ U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(KhmerOpenTypeLayoutEngine)
KhmerOpenTypeLayoutEngine::KhmerOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success)
{
fFeatureMap = KhmerReordering::getFeatureMap(fFeatureMapCount);
......
......@@ -83,7 +83,7 @@ public:
* @internal
*/
KhmerOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success);
le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success);
/**
* This constructor is used when the font requires a "canned" GSUB table which can't be known
......
......@@ -258,10 +258,11 @@ enum ScriptCodes {
* @stable ICU 49
*/
khojScriptCode = 156,
tirhScriptCode = 157,
hluwScriptCode = 156, /* bump to match current ICU */
khojScriptCode = 157,
tirhScriptCode = 158,
scriptCodeCount = 158
scriptCodeCount = 159
};
U_NAMESPACE_END
......
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* -*- c++ -*-
*
* (C) Copyright IBM Corp. and others 2013 - All Rights Reserved
*
* Range checking
*
*/
#ifndef __LETABLEREFERENCE_H
#define __LETABLEREFERENCE_H
#include "LETypes.h"
#include "LEFontInstance.h"
#define kQuestionmarkTableTag 0x3F3F3F3FUL
#define kTildeTableTag 0x7e7e7e7eUL
#ifdef __cplusplus
// internal - interface for range checking
U_NAMESPACE_BEGIN
#if LE_ASSERT_BAD_FONT
class LETableReference; // fwd
/**
* defined in OpenTypeUtilities.cpp
* @internal
*/
extern void _debug_LETableReference(const char *f, int l, const char *msg, const LETableReference *what, const void *ptr, size_t len);
#define LE_DEBUG_TR(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0);
#define LE_DEBUG_TR3(x,y,z) _debug_LETableReference(__FILE__, __LINE__, x, this, (const void*)y, (size_t)z);
#if 0
#define LE_TRACE_TR(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0);
#else
#define LE_TRACE_TR(x)
#endif
#else
#define LE_DEBUG_TR(x)
#define LE_DEBUG_TR3(x,y,z)
#define LE_TRACE_TR(x)
#endif
/**
* @internal
*/
class LETableReference {
public:
/**
* @internal
* Construct from a specific tag
*/
LETableReference(const LEFontInstance* font, LETag tableTag, LEErrorCode &success) :
fFont(font), fTag(tableTag), fParent(NULL), fStart(NULL),fLength(LE_UINTPTR_MAX) {
loadTable(success);
LE_TRACE_TR("INFO: new table load")
}
LETableReference(const LETableReference &parent, LEErrorCode &success) : fFont(parent.fFont), fTag(parent.fTag), fParent(&parent), fStart(parent.fStart), fLength(parent.fLength) {
if(LE_FAILURE(success)) {
clear();
}
LE_TRACE_TR("INFO: new clone")
}
LETableReference(const le_uint8* data, size_t length = LE_UINTPTR_MAX) :
fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(data), fLength(length) {
LE_TRACE_TR("INFO: new raw")
}
LETableReference() :
fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(NULL), fLength(0) {
LE_TRACE_TR("INFO: new empty")
}
~LETableReference() {
fTag=kTildeTableTag;
LE_TRACE_TR("INFO: new dtor")
}
/**
* @internal
* @param length if LE_UINTPTR_MAX means "whole table"
* subset
*/
LETableReference(const LETableReference &parent, size_t offset, size_t length,
LEErrorCode &err) :
fFont(parent.fFont), fTag(parent.fTag), fParent(&parent),
fStart((parent.fStart)+offset), fLength(length) {
if(LE_SUCCESS(err)) {
if(isEmpty()) {
//err = LE_MISSING_FONT_TABLE_ERROR;
clear(); // it's just empty. Not an error.
} else if(offset >= fParent->fLength) {
LE_DEBUG_TR3("offset out of range: (%p) +%d", NULL, offset);
err = LE_INDEX_OUT_OF_BOUNDS_ERROR;
clear();
} else {
if(fLength == LE_UINTPTR_MAX &&
fParent->fLength != LE_UINTPTR_MAX) {
fLength = (fParent->fLength) - offset; // decrement length as base address is incremented
}
if(fLength != LE_UINTPTR_MAX) { // if we have bounds:
if(offset+fLength > fParent->fLength) {
LE_DEBUG_TR3("offset+fLength out of range: (%p) +%d", NULL, offset+fLength);
err = LE_INDEX_OUT_OF_BOUNDS_ERROR; // exceeded
clear();
}
}
}
} else {
clear();
}
LE_TRACE_TR("INFO: new subset")
}
const void* getAlias() const { return (const void*)fStart; }
const void* getAliasTODO() const { LE_DEBUG_TR("getAliasTODO()"); return (const void*)fStart; }
le_bool isEmpty() const { return fStart==NULL || fLength==0; }
le_bool isValid() const { return !isEmpty(); }
le_bool hasBounds() const { return fLength!=LE_UINTPTR_MAX; }
void clear() { fLength=0; fStart=NULL; }
size_t getLength() const { return fLength; }
const LEFontInstance* getFont() const { return fFont; }
LETag getTag() const { return fTag; }
const LETableReference* getParent() const { return fParent; }
void addOffset(size_t offset, LEErrorCode &success) {
if(hasBounds()) {
if(offset > fLength) {
LE_DEBUG_TR("addOffset off end");
success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
return;
} else {
fLength -= offset;
}
}
fStart += offset;
}
size_t ptrToOffset(const void *atPtr, LEErrorCode &success) const {
if(atPtr==NULL) return 0;
if(LE_FAILURE(success)) return LE_UINTPTR_MAX;
if((atPtr < fStart) ||
(hasBounds() && (atPtr > fStart+fLength))) {
LE_DEBUG_TR3("ptrToOffset args out of range: %p", atPtr, 0);
success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
return LE_UINTPTR_MAX;
}
return ((const le_uint8*)atPtr)-fStart;
}
/**
* Clamp down the length, for range checking.
*/
size_t contractLength(size_t newLength) {
if(fLength!=LE_UINTPTR_MAX&&newLength>0&&newLength<=fLength) {
fLength = newLength;
}
return fLength;
}
/**
* Throw an error if offset+length off end
*/
public:
size_t verifyLength(size_t offset, size_t length, LEErrorCode &success) {
if(isValid()&&
LE_SUCCESS(success) &&
fLength!=LE_UINTPTR_MAX && length!=LE_UINTPTR_MAX && offset!=LE_UINTPTR_MAX &&
(offset+length)>fLength) {
LE_DEBUG_TR3("verifyLength failed (%p) %d",NULL, offset+length);
success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
#if LE_ASSERT_BAD_FONT
fprintf(stderr, "offset=%lu, len=%lu, would be at %p, (%lu) off end. End at %p\n", offset,length, fStart+offset+length, (offset+length-fLength), (offset+length-fLength)+fStart);
#endif
}
return fLength;
}
/**
* Change parent link to another
*/
LETableReference &reparent(const LETableReference &base) {
fParent = &base;
return *this;
}
/**
* remove parent link. Factory functions should do this.
*/
void orphan(void) {
fParent=NULL;
}
protected:
const LEFontInstance* fFont;
LETag fTag;
const LETableReference *fParent;
const le_uint8 *fStart; // keep as 8 bit internally, for pointer math
size_t fLength;
void loadTable(LEErrorCode &success) {
if(LE_SUCCESS(success)) {
fStart = (const le_uint8*)(fFont->getFontTable(fTag, fLength)); // note - a null table is not an error.
}
}
void setRaw(const void *data, size_t length = LE_UINTPTR_MAX) {
fFont = NULL;
fTag = kQuestionmarkTableTag;
fParent = NULL;
fStart = (const le_uint8*)data;
fLength = length;
}
};
template<class T>
class LETableVarSizer {
public:
inline static size_t getSize();
};
// base definition- could override for adjustments
template<class T> inline
size_t LETableVarSizer<T>::getSize() {
return sizeof(T);
}
/**
* \def LE_VAR_ARRAY
* @param x Type (T)
* @param y some member that is of length ANY_NUMBER
* Call this after defining a class, for example:
* LE_VAR_ARRAY(FeatureListTable,featureRecordArray)
* this is roughly equivalent to:
* template<> inline size_t LETableVarSizer<FeatureListTable>::getSize() { return sizeof(FeatureListTable) - (sizeof(le_uint16)*ANY_NUMBER); }
* it's a specialization that informs the LETableReference subclasses to NOT include the variable array in the size.
* dereferencing NULL is valid here because we never actually dereference it, just inside sizeof.
*/
#define LE_VAR_ARRAY(x,y) template<> inline size_t LETableVarSizer<x>::getSize() { return sizeof(x) - (sizeof(((const x*)0)->y)); }
/**
* \def LE_CORRECT_SIZE
* @param x type (T)
* @param y fixed size for T
*/
#define LE_CORRECT_SIZE(x,y) template<> inline size_t LETableVarSizer<x>::getSize() { return y; }
/**
* Open a new entry based on an existing table
*/
/**
* \def LE_UNBOUNDED_ARRAY
* define an array with no *known* bound. Will trim to available size.
* @internal
*/
#define LE_UNBOUNDED_ARRAY LE_UINT32_MAX
template<class T>
class LEReferenceToArrayOf : public LETableReference {
public:
LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, size_t offset, le_uint32 count)
: LETableReference(parent, offset, LE_UINTPTR_MAX, success), fCount(count) {
LE_TRACE_TR("INFO: new RTAO by offset")
if(LE_SUCCESS(success)) {
if(count == LE_UNBOUNDED_ARRAY) { // not a known length
count = getLength()/LETableVarSizer<T>::getSize(); // fit to max size
}
LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*count, success);
}
if(LE_FAILURE(success)) {
fCount=0;
clear();
}
}
LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, le_uint32 count)
: LETableReference(parent, parent.ptrToOffset(array, success), LE_UINTPTR_MAX, success), fCount(count) {
LE_TRACE_TR("INFO: new RTAO")
if(LE_SUCCESS(success)) {
if(count == LE_UNBOUNDED_ARRAY) { // not a known length
count = getLength()/LETableVarSizer<T>::getSize(); // fit to max size
}
LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*count, success);
}
if(LE_FAILURE(success)) clear();
}
LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, size_t offset, le_uint32 count)
: LETableReference(parent, parent.ptrToOffset(array, success)+offset, LE_UINTPTR_MAX, success), fCount(count) {
LE_TRACE_TR("INFO: new RTAO")
if(LE_SUCCESS(success)) {
if(count == LE_UNBOUNDED_ARRAY) { // not a known length
count = getLength()/LETableVarSizer<T>::getSize(); // fit to max size
}
LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*count, success);
}
if(LE_FAILURE(success)) clear();
}
LEReferenceToArrayOf() :LETableReference(), fCount(0) {}
le_uint32 getCount() const { return fCount; }
using LETableReference::getAlias;
const T *getAlias(le_uint32 i, LEErrorCode &success) const {
return ((const T*)(((const char*)getAlias())+getOffsetFor(i, success)));
}
const T *getAliasTODO() const { LE_DEBUG_TR("getAliasTODO<>"); return (const T*)fStart; }
const T& getObject(le_uint32 i, LEErrorCode &success) const {
return *getAlias(i,success);
}
const T& operator()(le_uint32 i, LEErrorCode &success) const {
return *getAlias(i,success);
}
size_t getOffsetFor(le_uint32 i, LEErrorCode &success) const {
if(LE_SUCCESS(success)&&i<getCount()) {
return LETableVarSizer<T>::getSize()*i;
} else {
success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
}
return 0;
}
LEReferenceToArrayOf<T> &reparent(const LETableReference &base) {
fParent = &base;
return *this;
}
LEReferenceToArrayOf(const LETableReference& parent, LEErrorCode & success) : LETableReference(parent,0, LE_UINTPTR_MAX, success), fCount(0) {
LE_TRACE_TR("INFO: null RTAO")
}
private:
le_uint32 fCount;
};
template<class T>
class LEReferenceTo : public LETableReference {
public:
/**
* open a sub reference.
* @param parent parent reference
* @param success error status
* @param atPtr location of reference - if NULL, will be at offset zero (i.e. downcast of parent). Otherwise must be a pointer within parent's bounds.
*/
LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr)
: LETableReference(parent, parent.ptrToOffset(atPtr, success), LE_UINTPTR_MAX, success) {
verifyLength(0, LETableVarSizer<T>::getSize(), success);
if(LE_FAILURE(success)) clear();
}
/**
* ptr plus offset
*/
LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr, size_t offset)
: LETableReference(parent, parent.ptrToOffset(atPtr, success)+offset, LE_UINTPTR_MAX, success) {
verifyLength(0, LETableVarSizer<T>::getSize(), success);
if(LE_FAILURE(success)) clear();
}
LEReferenceTo(const LETableReference &parent, LEErrorCode &success, size_t offset)
: LETableReference(parent, offset, LE_UINTPTR_MAX, success) {
verifyLength(0, LETableVarSizer<T>::getSize(), success);
if(LE_FAILURE(success)) clear();
}
LEReferenceTo(const LETableReference &parent, LEErrorCode &success)
: LETableReference(parent, 0, LE_UINTPTR_MAX, success) {
verifyLength(0, LETableVarSizer<T>::getSize(), success);
if(LE_FAILURE(success)) clear();
}
LEReferenceTo(const LEFontInstance *font, LETag tableTag, LEErrorCode &success)
: LETableReference(font, tableTag, success) {
verifyLength(0, LETableVarSizer<T>::getSize(), success);
if(LE_FAILURE(success)) clear();
}
LEReferenceTo(const le_uint8 *data, size_t length = LE_UINTPTR_MAX) : LETableReference(data, length) {}
LEReferenceTo(const T *data, size_t length = LE_UINTPTR_MAX) : LETableReference((const le_uint8*)data, length) {}
LEReferenceTo() : LETableReference(NULL) {}
LEReferenceTo<T>& operator=(const T* other) {
setRaw(other);
return *this;
}
LEReferenceTo<T> &reparent(const LETableReference &base) {
fParent = &base;
return *this;
}
/**
* roll forward by one <T> size.
* same as addOffset(LETableVarSizer<T>::getSize(),success)
*/
void addObject(LEErrorCode &success) {
addOffset(LETableVarSizer<T>::getSize(), success);
}
void addObject(size_t count, LEErrorCode &success) {
addOffset(LETableVarSizer<T>::getSize()*count, success);
}
const T *operator->() const { return getAlias(); }
const T *getAlias() const { return (const T*)fStart; }
const T *getAliasTODO() const { LE_DEBUG_TR("getAliasTODO<>"); return (const T*)fStart; }
};
U_NAMESPACE_END
#endif
#endif
......@@ -354,12 +354,15 @@ typedef struct LEPoint LEPoint;
/**
* Max value representable by a uintptr
*/
#ifndef UINTPTR_MAX
#ifndef UINT32_MAX
#define LE_UINTPTR_MAX 0xFFFFFFFFU
#define LE_UINT32_MAX 0xFFFFFFFFU
#else
#define LE_UINTPTR_MAX UINT32_MAX
#define LE_UINT32_MAX UINT32_MAX
#endif
#ifndef UINTPTR_MAX
#define LE_UINTPTR_MAX LE_UINT32_MAX
#else
#define LE_UINTPTR_MAX UINTPTR_MAX
#endif
......
......@@ -147,21 +147,21 @@ CharSubstitutionFilter::~CharSubstitutionFilter()
class CanonMarkFilter : public UMemory, public LEGlyphFilter
{
private:
const GlyphClassDefinitionTable *classDefTable;
const LEReferenceTo<GlyphClassDefinitionTable> classDefTable;
CanonMarkFilter(const CanonMarkFilter &other); // forbid copying of this class
CanonMarkFilter &operator=(const CanonMarkFilter &other); // forbid copying of this class
public:
CanonMarkFilter(const GlyphDefinitionTableHeader *gdefTable);
CanonMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success);
virtual ~CanonMarkFilter();
virtual le_bool accept(LEGlyphID glyph) const;
};
CanonMarkFilter::CanonMarkFilter(const GlyphDefinitionTableHeader *gdefTable)
CanonMarkFilter::CanonMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success)
: classDefTable(gdefTable->getMarkAttachClassDefinitionTable(gdefTable, success))
{
classDefTable = gdefTable->getMarkAttachClassDefinitionTable();
}
CanonMarkFilter::~CanonMarkFilter()
......@@ -171,8 +171,9 @@ CanonMarkFilter::~CanonMarkFilter()
le_bool CanonMarkFilter::accept(LEGlyphID glyph) const
{
le_int32 glyphClass = classDefTable->getGlyphClass(glyph);
LEErrorCode success = LE_NO_ERROR;
le_int32 glyphClass = classDefTable->getGlyphClass(classDefTable, glyph, success);
if(LE_FAILURE(success)) return false;
return glyphClass != 0;
}
......@@ -262,12 +263,12 @@ le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 off
return count;
}
const GlyphSubstitutionTableHeader *canonGSUBTable = (GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
LEReferenceTo<GlyphSubstitutionTableHeader> canonGSUBTable((GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable);
LETag scriptTag = OpenTypeLayoutEngine::getScriptTag(fScriptCode);
LETag langSysTag = OpenTypeLayoutEngine::getLangSysTag(fLanguageCode);
le_int32 i, dir = 1, out = 0, outCharCount = count;
if (canonGSUBTable->coversScript(scriptTag)) {
if (canonGSUBTable->coversScript(canonGSUBTable,scriptTag, success) || LE_SUCCESS(success)) {
CharSubstitutionFilter *substitutionFilter = new CharSubstitutionFilter(fFontInstance);
if (substitutionFilter == NULL) {
success = LE_MEMORY_ALLOCATION_ERROR;
......@@ -322,7 +323,7 @@ le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 off
LE_DELETE_ARRAY(reordered);
}
outCharCount = canonGSUBTable->process(fakeGlyphStorage, rightToLeft, scriptTag, langSysTag, NULL, substitutionFilter, canonFeatureMap, canonFeatureMapCount, FALSE, success);
outCharCount = canonGSUBTable->process(canonGSUBTable, fakeGlyphStorage, rightToLeft, scriptTag, langSysTag, (const GlyphDefinitionTableHeader*)NULL, substitutionFilter, canonFeatureMap, canonFeatureMapCount, FALSE, success);
if (LE_FAILURE(success)) {
delete substitutionFilter;
......@@ -423,16 +424,16 @@ void LayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset
return;
}
GlyphDefinitionTableHeader *gdefTable = (GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
CanonMarkFilter filter(gdefTable);
LEReferenceTo<GlyphDefinitionTableHeader> gdefTable((GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable,
CanonShaping::glyphDefinitionTableLen);
CanonMarkFilter filter(gdefTable, success);
adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
if (fTypoFlags & LE_Kerning_FEATURE_FLAG) { /* kerning enabled */
static const le_uint32 kernTableTag = LE_KERN_TABLE_TAG;
KernTable kt(fFontInstance, getFontTable(kernTableTag));
kt.process(glyphStorage);
LETableReference kernTable(fFontInstance, LE_KERN_TABLE_TAG, success);
KernTable kt(kernTable, success);
kt.process(glyphStorage, success);
}
// default is no adjustments
......@@ -517,9 +518,9 @@ void LayoutEngine::adjustMarkGlyphs(const LEUnicode chars[], le_int32 charCount,
glyphStorage.adjustPosition(glyphCount, xAdjust, 0, success);
}
const void *LayoutEngine::getFontTable(LETag tableTag) const
const void *LayoutEngine::getFontTable(LETag tableTag, size_t &length) const
{
return fFontInstance->getFontTable(tableTag);
return fFontInstance->getFontTable(tableTag, length);
}
void LayoutEngine::mapCharsToGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, le_bool mirror,
......@@ -566,7 +567,10 @@ le_int32 LayoutEngine::layoutChars(const LEUnicode chars[], le_int32 offset, le_
void LayoutEngine::reset()
{
if(fGlyphStorage!=NULL) {
fGlyphStorage->reset();
fGlyphStorage = NULL;
}
}
LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, LEErrorCode &success)
......@@ -585,7 +589,7 @@ LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstan
return NULL;
}
const GlyphSubstitutionTableHeader *gsubTable = (const GlyphSubstitutionTableHeader *) fontInstance->getFontTable(gsubTableTag);
LEReferenceTo<GlyphSubstitutionTableHeader> gsubTable(fontInstance,gsubTableTag,success);
LayoutEngine *result = NULL;
LETag scriptTag = 0x00000000;
LETag languageTag = 0x00000000;
......@@ -594,10 +598,10 @@ LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstan
// Right now, only invoke V2 processing for Devanagari. TODO: Allow more V2 scripts as they are
// properly tested.
if ( v2ScriptTag == dev2ScriptTag && gsubTable != NULL && gsubTable->coversScript( v2ScriptTag )) {
if ( v2ScriptTag == dev2ScriptTag && gsubTable.isValid() && gsubTable->coversScript(gsubTable, v2ScriptTag, success )) {
result = new IndicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, TRUE, gsubTable, success);
}
else if (gsubTable != NULL && gsubTable->coversScript(scriptTag = OpenTypeLayoutEngine::getScriptTag(scriptCode))) {
else if (gsubTable.isValid() && gsubTable->coversScript(gsubTable, scriptTag = OpenTypeLayoutEngine::getScriptTag(scriptCode), success)) {
switch (scriptCode) {
case bengScriptCode:
case devaScriptCode:
......@@ -633,7 +637,7 @@ LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstan
case janLanguageCode:
case zhtLanguageCode:
case zhsLanguageCode:
if (gsubTable->coversScriptAndLanguage(scriptTag, languageTag, TRUE)) {
if (gsubTable->coversScriptAndLanguage(gsubTable, scriptTag, languageTag, success, TRUE)) {
result = new HanOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success);
break;
}
......@@ -663,8 +667,8 @@ LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstan
if (morxTable != NULL && SWAPL(morxTable->version)==0x00020000) {
result = new GXLayoutEngine2(fontInstance, scriptCode, languageCode, morxTable, typoFlags, success);
} else {
const MorphTableHeader *mortTable = (MorphTableHeader *) fontInstance->getFontTable(mortTableTag);
if (mortTable != NULL && SWAPL(mortTable->version)==0x00010000) { // mort
LEReferenceTo<MorphTableHeader> mortTable(fontInstance, mortTableTag, success);
if (LE_SUCCESS(success) && mortTable.isValid() && SWAPL(mortTable->version)==0x00010000) { // mort
result = new GXLayoutEngine(fontInstance, scriptCode, languageCode, mortTable, success);
} else {
switch (scriptCode) {
......
......@@ -280,12 +280,18 @@ protected:
* some other way must override this method.
*
* @param tableTag - the four byte table tag.
* @param length - length to use
*
* @return the address of the table.
*
* @internal
*/
virtual const void *getFontTable(LETag tableTag) const;
virtual const void *getFontTable(LETag tableTag, size_t &length) const;
/**
* @deprecated
*/
virtual const void *getFontTable(LETag tableTag) const { size_t ignored; return getFontTable(tableTag, ignored); }
/**
* This method does character to glyph mapping. The default implementation
......
......@@ -47,15 +47,15 @@ U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LigatureSubstitutionProcessor)
LigatureSubstitutionProcessor::LigatureSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader)
: StateTableProcessor(morphSubtableHeader)
LigatureSubstitutionProcessor::LigatureSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
: StateTableProcessor(morphSubtableHeader, success), ligatureSubstitutionHeader(morphSubtableHeader, success)
{
ligatureSubstitutionHeader = (const LigatureSubstitutionHeader *) morphSubtableHeader;
if(LE_FAILURE(success)) return;
ligatureActionTableOffset = SWAPW(ligatureSubstitutionHeader->ligatureActionTableOffset);
componentTableOffset = SWAPW(ligatureSubstitutionHeader->componentTableOffset);
ligatureTableOffset = SWAPW(ligatureSubstitutionHeader->ligatureTableOffset);
entryTable = (const LigatureSubstitutionStateEntry *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
entryTable = LEReferenceToArrayOf<LigatureSubstitutionStateEntry>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY);
}
LigatureSubstitutionProcessor::~LigatureSubstitutionProcessor()
......@@ -69,7 +69,9 @@ void LigatureSubstitutionProcessor::beginStateTable()
ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index)
{
const LigatureSubstitutionStateEntry *entry = &entryTable[index];
LEErrorCode success = LE_NO_ERROR;
const LigatureSubstitutionStateEntry *entry = entryTable.getAlias(index, success);
ByteOffset newState = SWAPW(entry->newStateOffset);
le_int16 flags = SWAPW(entry->flags);
......@@ -88,7 +90,7 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp
ByteOffset actionOffset = flags & lsfActionOffsetMask;
if (actionOffset != 0) {
const LigatureActionEntry *ap = (const LigatureActionEntry *) ((char *) &ligatureSubstitutionHeader->stHeader + actionOffset);
LEReferenceTo<LigatureActionEntry> ap(stHeader, success, actionOffset);
LigatureActionEntry action;
le_int32 offset, i = 0;
le_int32 stack[nComponents];
......@@ -97,7 +99,8 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp
do {
le_uint32 componentGlyph = componentStack[m--];
action = SWAPL(*ap++);
action = SWAPL(*ap.getAlias());
ap.addObject(success); // ap++
if (m < 0) {
m = nComponents - 1;
......@@ -105,27 +108,23 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp
offset = action & lafComponentOffsetMask;
if (offset != 0) {
const le_int16 *offsetTable = (const le_int16 *)((char *) &ligatureSubstitutionHeader->stHeader + 2 * SignExtend(offset, lafComponentOffsetMask));
const le_int16 *tableEnd = (const le_int16 *)((char *) &ligatureSubstitutionHeader + 1 * SWAPW(ligatureSubstitutionHeader->length));
LEReferenceToArrayOf<le_int16> offsetTable(stHeader, success, 2 * SignExtend(offset, lafComponentOffsetMask), LE_UNBOUNDED_ARRAY);
// Check if the font is internally consistent
if(tableEnd < (const le_int16*)&ligatureSubstitutionHeader // stated end wrapped around?
|| offsetTable > tableEnd) { // offset past end of stated length?
if(LE_FAILURE(success)) {
currGlyph++;
LE_DEBUG_BAD_FONT("off end of ligature substitution header");
return newState; // get out! bad font
}
if(componentGlyph > glyphStorage.getGlyphCount()) {
LE_DEBUG_BAD_FONT("preposterous componentGlyph");
currGlyph++;
return newState; // get out! bad font
}
i += SWAPW(offsetTable[LE_GET_GLYPH(glyphStorage[componentGlyph])]);
i += SWAPW(offsetTable.getObject(LE_GET_GLYPH(glyphStorage[componentGlyph]), success));
if (action & (lafLast | lafStore)) {
const TTGlyphID *ligatureOffset = (const TTGlyphID *) ((char *) &ligatureSubstitutionHeader->stHeader + i);
TTGlyphID ligatureGlyph = SWAPW(*ligatureOffset);
LEReferenceTo<TTGlyphID> ligatureOffset(stHeader, success, i);
TTGlyphID ligatureGlyph = SWAPW(*ligatureOffset.getAlias());
glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph);
if(mm==nComponents) {
......
......@@ -58,7 +58,7 @@ public:
virtual void endStateTable();
LigatureSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader);
LigatureSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
virtual ~LigatureSubstitutionProcessor();
/**
......@@ -83,12 +83,12 @@ protected:
ByteOffset componentTableOffset;
ByteOffset ligatureTableOffset;
const LigatureSubstitutionStateEntry *entryTable;
LEReferenceToArrayOf<LigatureSubstitutionStateEntry> entryTable;
le_int32 componentStack[nComponents];
le_int16 m;
const LigatureSubstitutionHeader *ligatureSubstitutionHeader;
LEReferenceTo<LigatureSubstitutionHeader> ligatureSubstitutionHeader;
};
......
......@@ -47,15 +47,18 @@ U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LigatureSubstitutionProcessor2)
LigatureSubstitutionProcessor2::LigatureSubstitutionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
: StateTableProcessor2(morphSubtableHeader)
LigatureSubstitutionProcessor2::LigatureSubstitutionProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
: StateTableProcessor2(morphSubtableHeader, success),
ligActionOffset(0),
ligatureSubstitutionHeader(morphSubtableHeader, success), componentOffset(0), ligatureOffset(0), entryTable()
{
ligatureSubstitutionHeader = (const LigatureSubstitutionHeader2 *) morphSubtableHeader;
if (LE_FAILURE(success)) return;
ligActionOffset = SWAPL(ligatureSubstitutionHeader->ligActionOffset);
componentOffset = SWAPL(ligatureSubstitutionHeader->componentOffset);
ligatureOffset = SWAPL(ligatureSubstitutionHeader->ligatureOffset);
entryTable = (const LigatureSubstitutionStateEntry2 *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
entryTable = LEReferenceToArrayOf<LigatureSubstitutionStateEntry2>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY);
}
LigatureSubstitutionProcessor2::~LigatureSubstitutionProcessor2()
......@@ -67,9 +70,11 @@ void LigatureSubstitutionProcessor2::beginStateTable()
m = -1;
}
le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index)
le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index, LEErrorCode &success)
{
const LigatureSubstitutionStateEntry2 *entry = &entryTable[index];
const LigatureSubstitutionStateEntry2 *entry = entryTable.getAlias(index, success);
if(LE_FAILURE(success)) return 0;
le_uint16 nextStateIndex = SWAPW(entry->nextStateIndex);
le_uint16 flags = SWAPW(entry->entryFlags);
le_uint16 ligActionIndex = SWAPW(entry->ligActionIndex);
......@@ -81,7 +86,7 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp
componentStack[m] = currGlyph;
} else if ( m == -1) {
// bad font- skip this glyph.
LE_DEBUG_BAD_FONT("m==-1")
//LE_DEBUG_BAD_FONT("m==-1 (componentCount went negative)")
currGlyph+= dir;
return nextStateIndex;
}
......@@ -89,29 +94,25 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp
ByteOffset actionOffset = flags & lsfPerformAction;
if (actionOffset != 0) {
const LigatureActionEntry *ap = (const LigatureActionEntry *) ((char *) &ligatureSubstitutionHeader->stHeader + ligActionOffset) + ligActionIndex;
const TTGlyphID *ligatureTable = (const TTGlyphID *) ((char *) &ligatureSubstitutionHeader->stHeader + ligatureOffset);
LEReferenceTo<LigatureActionEntry> ap(stHeader, success, ligActionOffset); // byte offset
ap.addObject(ligActionIndex - 1, success); // index offset ( one before the actual start, because we will pre-increment)
LEReferenceToArrayOf<TTGlyphID> ligatureTable(stHeader, success, ligatureOffset, LE_UNBOUNDED_ARRAY);
LigatureActionEntry action;
le_int32 offset, i = 0;
le_int32 stack[nComponents];
le_int16 mm = -1;
const le_uint16 *componentTable = (const le_uint16 *)((char *) &ligatureSubstitutionHeader->stHeader + componentOffset);
const le_uint16 *tableEnd = (const le_uint16 *)((char *) &ligatureSubstitutionHeader + SWAPL(ligatureSubstitutionHeader->length));
// Check if the font is internally consistent
if(tableEnd < (const le_uint16*)&ligatureSubstitutionHeader // stated end wrapped around?
|| componentTable > tableEnd) { // offset past end of stated length?
LEReferenceToArrayOf<le_uint16> componentTable(stHeader, success, componentOffset, LE_UNBOUNDED_ARRAY);
if(LE_FAILURE(success)) {
currGlyph+= dir;
LE_DEBUG_BAD_FONT("ligatureSubstHeader off end of table")
return nextStateIndex; // get out! bad font
}
do {
le_uint32 componentGlyph = componentStack[m--]; // pop off
action = SWAPL(*ap++);
ap.addObject(success);
action = SWAPL(*ap.getAlias());
if (m < 0) {
m = nComponents - 1;
......@@ -124,10 +125,10 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp
currGlyph+= dir;
return nextStateIndex; // get out! bad font
}
i += SWAPW(componentTable[LE_GET_GLYPH(glyphStorage[componentGlyph]) + (SignExtend(offset, lafComponentOffsetMask))]);
i += SWAPW(componentTable(LE_GET_GLYPH(glyphStorage[componentGlyph]) + (SignExtend(offset, lafComponentOffsetMask)),success));
if (action & (lafLast | lafStore)) {
TTGlyphID ligatureGlyph = SWAPW(ligatureTable[i]);
TTGlyphID ligatureGlyph = SWAPW(ligatureTable(i,success));
glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph);
if(mm==nComponents) {
LE_DEBUG_BAD_FONT("exceeded nComponents");
......
......@@ -54,11 +54,12 @@ class LigatureSubstitutionProcessor2 : public StateTableProcessor2
public:
virtual void beginStateTable();
virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index);
virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph,
EntryTableIndex2 index, LEErrorCode &success);
virtual void endStateTable();
LigatureSubstitutionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
LigatureSubstitutionProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
virtual ~LigatureSubstitutionProcessor2();
/**
......@@ -83,12 +84,12 @@ protected:
le_uint32 componentOffset;
le_uint32 ligatureOffset;
const LigatureSubstitutionStateEntry2 *entryTable;
LEReferenceToArrayOf<LigatureSubstitutionStateEntry2> entryTable;
le_int32 componentStack[nComponents];
le_int16 m;
const LigatureSubstitutionHeader2 *ligatureSubstitutionHeader;
const LEReferenceTo<LigatureSubstitutionHeader2> ligatureSubstitutionHeader;
};
......
......@@ -40,10 +40,10 @@
U_NAMESPACE_BEGIN
le_uint32 LigatureSubstitutionSubtable::process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter) const
le_uint32 LigatureSubstitutionSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter) const
{
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(glyph);
le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
if (coverageIndex >= 0) {
Offset ligSetTableOffset = SWAPW(ligSetTableOffsetArray[coverageIndex]);
......
......@@ -50,6 +50,7 @@ struct LigatureSetTable
le_uint16 ligatureCount;
Offset ligatureTableOffsetArray[ANY_NUMBER];
};
LE_VAR_ARRAY(LigatureSetTable, ligatureTableOffsetArray)
struct LigatureTable
{
......@@ -57,14 +58,16 @@ struct LigatureTable
le_uint16 compCount;
TTGlyphID componentArray[ANY_NUMBER];
};
LE_VAR_ARRAY(LigatureTable, componentArray)
struct LigatureSubstitutionSubtable : GlyphSubstitutionSubtable
{
le_uint16 ligSetCount;
Offset ligSetTableOffsetArray[ANY_NUMBER];
le_uint32 process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter = NULL) const;
le_uint32 process(const LETableReference &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter = NULL) const;
};
LE_VAR_ARRAY(LigatureSubstitutionSubtable, ligSetTableOffsetArray)
U_NAMESPACE_END
#endif
......@@ -44,7 +44,7 @@
U_NAMESPACE_BEGIN
le_uint32 LookupProcessor::applyLookupTable(const LookupTable *lookupTable, GlyphIterator *glyphIterator,
le_uint32 LookupProcessor::applyLookupTable(const LEReferenceTo<LookupTable> &lookupTable, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, LEErrorCode& success) const
{
if (LE_FAILURE(success)) {
......@@ -57,7 +57,7 @@ le_uint32 LookupProcessor::applyLookupTable(const LookupTable *lookupTable, Glyp
le_uint32 delta;
for (le_uint16 subtable = 0; subtable < subtableCount; subtable += 1) {
const LookupSubtable *lookupSubtable = lookupTable->getLookupSubtable(subtable);
LEReferenceTo<LookupSubtable> lookupSubtable = lookupTable->getLookupSubtable(lookupTable, subtable, success);
delta = applySubtable(lookupSubtable, lookupType, glyphIterator, fontInstance, success);
......@@ -72,7 +72,7 @@ le_uint32 LookupProcessor::applyLookupTable(const LookupTable *lookupTable, Glyp
}
le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments,
le_bool rightToLeft, const GlyphDefinitionTableHeader *glyphDefinitionTableHeader,
le_bool rightToLeft, const LEReferenceTo<GlyphDefinitionTableHeader> &glyphDefinitionTableHeader,
const LEFontInstance *fontInstance, LEErrorCode& success) const
{
if (LE_FAILURE(success)) {
......@@ -89,13 +89,13 @@ le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdj
rightToLeft, 0, 0, glyphDefinitionTableHeader);
le_int32 newGlyphCount = glyphCount;
for (le_uint16 order = 0; order < lookupOrderCount; order += 1) {
for (le_uint16 order = 0; order < lookupOrderCount && LE_SUCCESS(success); order += 1) {
le_uint16 lookup = lookupOrderArray[order];
FeatureMask selectMask = lookupSelectArray[lookup];
if (selectMask != 0) {
const LookupTable *lookupTable = lookupListTable->getLookupTable(lookup);
if (!lookupTable) {
const LEReferenceTo<LookupTable> lookupTable = lookupListTable->getLookupTable(lookupListTable, lookup, success);
if (!lookupTable.isValid() ||LE_FAILURE(success) ) {
continue;
}
le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags);
......@@ -103,7 +103,7 @@ le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdj
glyphIterator.reset(lookupFlags, selectMask);
while (glyphIterator.findFeatureTag()) {
applyLookupTable(lookupTable, &glyphIterator, fontInstance, success);
applyLookupTable(lookupTable, &glyphIterator, fontInstance, success); // TODO
if (LE_FAILURE(success)) {
return 0;
}
......@@ -123,8 +123,8 @@ le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIt
return 0;
}
const LookupTable *lookupTable = lookupListTable->getLookupTable(lookupTableIndex);
if (lookupTable == NULL) {
const LEReferenceTo<LookupTable> lookupTable = lookupListTable->getLookupTable(lookupListTable, lookupTableIndex, success);
if (!lookupTable.isValid()) {
success = LE_INTERNAL_ERROR;
return 0;
}
......@@ -135,13 +135,15 @@ le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIt
return delta;
}
le_int32 LookupProcessor::selectLookups(const FeatureTable *featureTable, FeatureMask featureMask, le_int32 order)
le_int32 LookupProcessor::selectLookups(const LEReferenceTo<FeatureTable> &featureTable, FeatureMask featureMask, le_int32 order, LEErrorCode &success)
{
le_uint16 lookupCount = featureTable? SWAPW(featureTable->lookupCount) : 0;
le_uint16 lookupCount = featureTable.isValid()? SWAPW(featureTable->lookupCount) : 0;
le_int32 store = order;
for (le_uint16 lookup = 0; lookup < lookupCount; lookup += 1) {
le_uint16 lookupListIndex = SWAPW(featureTable->lookupListIndexArray[lookup]);
LEReferenceToArrayOf<le_uint16> lookupListIndexArray(featureTable, success, featureTable->lookupListIndexArray, lookupCount);
for (le_uint16 lookup = 0; LE_SUCCESS(success) && lookup < lookupCount; lookup += 1) {
le_uint16 lookupListIndex = SWAPW(lookupListIndexArray.getObject(lookup,success));
if (lookupListIndex >= lookupSelectCount) {
continue;
}
......@@ -153,15 +155,15 @@ le_int32 LookupProcessor::selectLookups(const FeatureTable *featureTable, Featur
return store - order;
}
LookupProcessor::LookupProcessor(const char *baseAddress,
LookupProcessor::LookupProcessor(const LETableReference &baseAddress,
Offset scriptListOffset, Offset featureListOffset, Offset lookupListOffset,
LETag scriptTag, LETag languageTag, const FeatureMap *featureMap, le_int32 featureMapCount, le_bool orderFeatures,
LEErrorCode& success)
: lookupListTable(NULL), featureListTable(NULL), lookupSelectArray(NULL), lookupSelectCount(0),
lookupOrderArray(NULL), lookupOrderCount(0)
: lookupListTable(), featureListTable(), lookupSelectArray(NULL), lookupSelectCount(0),
lookupOrderArray(NULL), lookupOrderCount(0), fReference(baseAddress)
{
const ScriptListTable *scriptListTable = NULL;
const LangSysTable *langSysTable = NULL;
LEReferenceTo<ScriptListTable> scriptListTable;
LEReferenceTo<LangSysTable> langSysTable;
le_uint16 featureCount = 0;
le_uint16 lookupListCount = 0;
le_uint16 requiredFeatureIndex;
......@@ -171,29 +173,33 @@ LookupProcessor::LookupProcessor(const char *baseAddress,
}
if (scriptListOffset != 0) {
scriptListTable = (const ScriptListTable *) (baseAddress + scriptListOffset);
langSysTable = scriptListTable->findLanguage(scriptTag, languageTag);
scriptListTable = LEReferenceTo<ScriptListTable>(baseAddress, success, scriptListOffset);
langSysTable = scriptListTable->findLanguage(scriptListTable, scriptTag, languageTag, success);
if (langSysTable != 0) {
if (langSysTable.isValid() && LE_SUCCESS(success)) {
featureCount = SWAPW(langSysTable->featureCount);
}
}
if (featureListOffset != 0) {
featureListTable = (const FeatureListTable *) (baseAddress + featureListOffset);
featureListTable = LEReferenceTo<FeatureListTable>(baseAddress, success, featureListOffset);
}
if (lookupListOffset != 0) {
lookupListTable = (const LookupListTable *) (baseAddress + lookupListOffset);
lookupListTable = LEReferenceTo<LookupListTable>(baseAddress,success, lookupListOffset);
if(LE_SUCCESS(success) && lookupListTable.isValid()) {
lookupListCount = SWAPW(lookupListTable->lookupCount);
}
}
if (langSysTable == NULL || featureListTable == NULL || lookupListTable == NULL ||
if (langSysTable.isEmpty() || featureListTable.isEmpty() || lookupListTable.isEmpty() ||
featureCount == 0 || lookupListCount == 0) {
return;
}
if(langSysTable.isValid()) {
requiredFeatureIndex = SWAPW(langSysTable->reqFeatureIndex);
}
lookupSelectArray = LE_NEW_ARRAY(FeatureMask, lookupListCount);
if (lookupSelectArray == NULL) {
......@@ -209,33 +215,37 @@ LookupProcessor::LookupProcessor(const char *baseAddress,
le_int32 count, order = 0;
le_uint32 featureReferences = 0;
const FeatureTable *featureTable = NULL;
LEReferenceTo<FeatureTable> featureTable;
LETag featureTag;
const FeatureTable *requiredFeatureTable = NULL;
LEReferenceTo<FeatureTable> requiredFeatureTable;
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_uint32 feature = 0; feature < featureCount; feature += 1) {
le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]);
if(featureListTable.isValid() && LE_SUCCESS(success)) {
LEReferenceToArrayOf<le_uint16> featureIndexArray(langSysTable, success, langSysTable->featureIndexArray, featureCount);
featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag);
if (!featureTable) {
for (le_uint32 feature = 0; LE_SUCCESS(success)&&(feature < featureCount); feature += 1) {
le_uint16 featureIndex = SWAPW(featureIndexArray.getObject(feature, success));
featureTable = featureListTable->getFeatureTable(featureListTable, featureIndex, &featureTag, success);
if (!featureTable.isValid() || LE_FAILURE(success)) {
continue;
}
featureReferences += SWAPW(featureTable->lookupCount);
}
}
if (!featureTable) {
if (!featureTable.isValid() || LE_FAILURE(success)) {
success = LE_INTERNAL_ERROR;
return;
}
if (requiredFeatureIndex != 0xFFFF) {
requiredFeatureTable = featureListTable->getFeatureTable(requiredFeatureIndex, &requiredFeatureTag);
requiredFeatureTable = featureListTable->getFeatureTable(featureListTable, requiredFeatureIndex, &requiredFeatureTag, success);
featureReferences += SWAPW(featureTable->lookupCount);
}
......@@ -251,7 +261,7 @@ LookupProcessor::LookupProcessor(const char *baseAddress,
// If this is the required feature, add its lookups
if (requiredFeatureTag == fm.tag) {
count += selectLookups(requiredFeatureTable, fm.mask, order);
count += selectLookups(requiredFeatureTable, fm.mask, order, success);
}
if (orderFeatures) {
......@@ -261,7 +271,8 @@ LookupProcessor::LookupProcessor(const char *baseAddress,
}
for (le_uint16 feature = 0; feature < featureCount; feature += 1) {
le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]);
LEReferenceToArrayOf<le_uint16> featureIndexArray(langSysTable, success, langSysTable->featureIndexArray, featureCount);
le_uint16 featureIndex = SWAPW(featureIndexArray.getObject(feature,success));
// 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...)
......@@ -269,10 +280,10 @@ LookupProcessor::LookupProcessor(const char *baseAddress,
continue;
}
featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag);
featureTable = featureListTable->getFeatureTable(featureListTable, featureIndex, &featureTag, success);
if (featureTag == fm.tag) {
count += selectLookups(featureTable, fm.mask, order + count);
count += selectLookups(featureTable, fm.mask, order + count, success);
}
}
......@@ -281,9 +292,10 @@ 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 if(langSysTable.isValid()) {
LEReferenceToArrayOf<le_uint16> featureIndexArray(langSysTable, success, langSysTable->featureIndexArray, featureCount);
for (le_uint16 feature = 0; LE_SUCCESS(success)&& (feature < featureCount); feature += 1) {
le_uint16 featureIndex = SWAPW(featureIndexArray.getObject(feature,success));
// don't add the required feature to the list more than once...
// NOTE: This check is commented out because the spec. says that
......@@ -295,10 +307,10 @@ LookupProcessor::LookupProcessor(const char *baseAddress,
}
#endif
featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag);
featureTable = featureListTable->getFeatureTable(featureListTable, featureIndex, &featureTag, success);
if (featureTag == fm.tag) {
order += selectLookups(featureTable, fm.mask, order);
order += selectLookups(featureTable, fm.mask, order, success);
}
}
}
......
......@@ -41,6 +41,7 @@
#include "LETypes.h"
#include "LEFontInstance.h"
#include "OpenTypeTables.h"
#include "LETableReference.h"
//#include "Lookups.h"
//#include "Features.h"
......@@ -59,19 +60,21 @@ struct LookupTable;
class LookupProcessor : public UMemory {
public:
le_int32 process(LEGlyphStorage &glyphStorage, GlyphPositionAdjustments *glyphPositionAdjustments,
le_bool rightToLeft, const GlyphDefinitionTableHeader *glyphDefinitionTableHeader, const LEFontInstance *fontInstance, LEErrorCode& success) const;
le_bool rightToLeft, const LEReferenceTo<GlyphDefinitionTableHeader> &glyphDefinitionTableHeader, const LEFontInstance *fontInstance, LEErrorCode& success) const;
le_uint32 applyLookupTable(const LookupTable *lookupTable, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
le_uint32 applyLookupTable(const LEReferenceTo<LookupTable> &lookupTable, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
le_uint32 applySingleLookup(le_uint16 lookupTableIndex, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
virtual le_uint32 applySubtable(const LookupSubtable *lookupSubtable, le_uint16 subtableType,
virtual le_uint32 applySubtable(const LEReferenceTo<LookupSubtable> &lookupSubtable, le_uint16 subtableType,
GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const = 0;
virtual ~LookupProcessor();
const LETableReference &getReference() const { return fReference; }
protected:
LookupProcessor(const char *baseAddress,
LookupProcessor(const LETableReference &baseAddress,
Offset scriptListOffset,
Offset featureListOffset,
Offset lookupListOffset,
......@@ -84,10 +87,10 @@ protected:
LookupProcessor();
le_int32 selectLookups(const FeatureTable *featureTable, FeatureMask featureMask, le_int32 order);
le_int32 selectLookups(const LEReferenceTo<FeatureTable> &featureTable, FeatureMask featureMask, le_int32 order, LEErrorCode &success);
const LookupListTable *lookupListTable;
const FeatureListTable *featureListTable;
LEReferenceTo<LookupListTable> lookupListTable;
LEReferenceTo<FeatureListTable> featureListTable;
FeatureMask *lookupSelectArray;
le_uint32 lookupSelectCount;
......@@ -95,6 +98,8 @@ protected:
le_uint16 *lookupOrderArray;
le_uint32 lookupOrderCount;
LETableReference fReference;
private:
LookupProcessor(const LookupProcessor &other); // forbid copying of this class
......
......@@ -49,22 +49,26 @@ U_NAMESPACE_BEGIN
of the derived classes, and implement it in the others by casting
the "this" pointer to the type that has the implementation.
*/
const LookupSegment *BinarySearchLookupTable::lookupSegment(const LookupSegment *segments, LEGlyphID glyph) const
const LookupSegment *BinarySearchLookupTable::lookupSegment(const LETableReference &base, const LookupSegment *segments, LEGlyphID glyph, LEErrorCode &success) const
{
le_int16 unity = SWAPW(unitSize);
le_int16 probe = SWAPW(searchRange);
le_int16 extra = SWAPW(rangeShift);
TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyph);
const LookupSegment *entry = segments;
const LookupSegment *trial = (const LookupSegment *) ((char *) entry + extra);
LEReferenceTo<LookupSegment> entry(base, success, segments);
LEReferenceTo<LookupSegment> trial(entry, success, extra);
if(LE_FAILURE(success)) return NULL;
if (SWAPW(trial->lastGlyph) <= ttGlyph) {
entry = trial;
}
while (probe > unity) {
while (probe > unity && LE_SUCCESS(success)) {
probe >>= 1;
trial = (const LookupSegment *) ((char *) entry + probe);
trial = entry; // copy
trial.addOffset(probe, success);
if (SWAPW(trial->lastGlyph) <= ttGlyph) {
entry = trial;
......@@ -72,28 +76,29 @@ const LookupSegment *BinarySearchLookupTable::lookupSegment(const LookupSegment
}
if (SWAPW(entry->firstGlyph) <= ttGlyph) {
return entry;
return entry.getAlias();
}
return NULL;
}
const LookupSingle *BinarySearchLookupTable::lookupSingle(const LookupSingle *entries, LEGlyphID glyph) const
const LookupSingle *BinarySearchLookupTable::lookupSingle(const LETableReference &base, const LookupSingle *entries, LEGlyphID glyph, LEErrorCode &success) const
{
le_int16 unity = SWAPW(unitSize);
le_int16 probe = SWAPW(searchRange);
le_int16 extra = SWAPW(rangeShift);
TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyph);
const LookupSingle *entry = entries;
const LookupSingle *trial = (const LookupSingle *) ((char *) entry + extra);
LEReferenceTo<LookupSingle> entry(base, success, entries);
LEReferenceTo<LookupSingle> trial(entry, success, extra);
if (SWAPW(trial->glyph) <= ttGlyph) {
entry = trial;
}
while (probe > unity) {
while (probe > unity && LE_SUCCESS(success)) {
probe >>= 1;
trial = (const LookupSingle *) ((char *) entry + probe);
trial = entry;
trial.addOffset(probe, success);
if (SWAPW(trial->glyph) <= ttGlyph) {
entry = trial;
......@@ -101,7 +106,7 @@ const LookupSingle *BinarySearchLookupTable::lookupSingle(const LookupSingle *en
}
if (SWAPW(entry->glyph) == ttGlyph) {
return entry;
return entry.getAlias();
}
return NULL;
......
......@@ -39,6 +39,7 @@
#include "LETypes.h"
#include "LayoutTables.h"
#include "LETableReference.h"
U_NAMESPACE_BEGIN
......@@ -79,30 +80,34 @@ struct BinarySearchLookupTable : LookupTable
le_int16 entrySelector;
le_int16 rangeShift;
const LookupSegment *lookupSegment(const LookupSegment *segments, LEGlyphID glyph) const;
const LookupSegment *lookupSegment(const LETableReference &base, const LookupSegment *segments, LEGlyphID glyph, LEErrorCode &success) const;
const LookupSingle *lookupSingle(const LookupSingle *entries, LEGlyphID glyph) const;
const LookupSingle *lookupSingle(const LETableReference &base, const LookupSingle *entries, LEGlyphID glyph, LEErrorCode &success) const;
};
struct SimpleArrayLookupTable : LookupTable
{
LookupValue valueArray[ANY_NUMBER];
};
LE_VAR_ARRAY(SimpleArrayLookupTable, valueArray)
struct SegmentSingleLookupTable : BinarySearchLookupTable
{
LookupSegment segments[ANY_NUMBER];
};
LE_VAR_ARRAY(SegmentSingleLookupTable, segments)
struct SegmentArrayLookupTable : BinarySearchLookupTable
{
LookupSegment segments[ANY_NUMBER];
};
LE_VAR_ARRAY(SegmentArrayLookupTable, segments)
struct SingleTableLookupTable : BinarySearchLookupTable
{
LookupSingle entries[ANY_NUMBER];
};
LE_VAR_ARRAY(SingleTableLookupTable, entries)
struct TrimmedArrayLookupTable : LookupTable
{
......@@ -110,6 +115,7 @@ struct TrimmedArrayLookupTable : LookupTable
TTGlyphID glyphCount;
LookupValue valueArray[ANY_NUMBER];
};
LE_VAR_ARRAY(TrimmedArrayLookupTable, valueArray)
U_NAMESPACE_END
#endif
......@@ -37,31 +37,33 @@
U_NAMESPACE_BEGIN
const LookupTable *LookupListTable::getLookupTable(le_uint16 lookupTableIndex) const
const LEReferenceTo<LookupTable> LookupListTable::getLookupTable(const LEReferenceTo<LookupListTable> &base, le_uint16 lookupTableIndex, LEErrorCode &success) const
{
if (lookupTableIndex >= SWAPW(lookupCount)) {
return 0;
}
Offset lookupTableOffset = lookupTableOffsetArray[lookupTableIndex];
LEReferenceToArrayOf<Offset> lookupTableOffsetArrayRef(base, success, (const Offset*)&lookupTableOffsetArray, SWAPW(lookupCount));
return (const LookupTable *) ((char *) this + SWAPW(lookupTableOffset));
if(LE_FAILURE(success) || lookupTableIndex>lookupTableOffsetArrayRef.getCount()) {
return LEReferenceTo<LookupTable>();
} else {
return LEReferenceTo<LookupTable>(base, success, SWAPW(lookupTableOffsetArrayRef.getObject(lookupTableIndex, success)));
}
}
const LookupSubtable *LookupTable::getLookupSubtable(le_uint16 subtableIndex) const
const LEReferenceTo<LookupSubtable> LookupTable::getLookupSubtable(const LEReferenceTo<LookupTable> &base, le_uint16 subtableIndex, LEErrorCode &success) const
{
if (subtableIndex >= SWAPW(subTableCount)) {
return 0;
}
LEReferenceToArrayOf<Offset> subTableOffsetArrayRef(base, success, (const Offset*)&subTableOffsetArray, SWAPW(subTableCount));
Offset subtableOffset = subTableOffsetArray[subtableIndex];
return (const LookupSubtable *) ((char *) this + SWAPW(subtableOffset));
if(LE_FAILURE(success) || subtableIndex>subTableOffsetArrayRef.getCount()) {
return LEReferenceTo<LookupSubtable>();
} else {
return LEReferenceTo<LookupSubtable>(base, success, SWAPW(subTableOffsetArrayRef.getObject(subtableIndex, success)));
}
}
le_int32 LookupSubtable::getGlyphCoverage(Offset tableOffset, LEGlyphID glyphID) const
le_int32 LookupSubtable::getGlyphCoverage(const LEReferenceTo<LookupSubtable> &base, Offset tableOffset, LEGlyphID glyphID, LEErrorCode &success) const
{
const CoverageTable *coverageTable = (const CoverageTable *) ((char *) this + SWAPW(tableOffset));
const LEReferenceTo<CoverageTable> coverageTable(base, success, SWAPW(tableOffset));
if(LE_FAILURE(success)) return 0;
return coverageTable->getGlyphCoverage(glyphID);
}
......
......@@ -58,9 +58,14 @@ struct LookupSubtable
le_uint16 subtableFormat;
Offset coverageTableOffset;
inline le_int32 getGlyphCoverage(LEGlyphID glyphID) const;
inline le_int32 getGlyphCoverage(const LEReferenceTo<LookupSubtable> &base, LEGlyphID glyphID, LEErrorCode &success) const;
le_int32 getGlyphCoverage(Offset tableOffset, LEGlyphID glyphID) const;
le_int32 getGlyphCoverage(const LEReferenceTo<LookupSubtable> &base, Offset tableOffset, LEGlyphID glyphID, LEErrorCode &success) const;
// convenience
inline le_int32 getGlyphCoverage(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
inline le_int32 getGlyphCoverage(const LETableReference &base, Offset tableOffset, LEGlyphID glyphID, LEErrorCode &success) const;
};
struct LookupTable
......@@ -70,20 +75,32 @@ struct LookupTable
le_uint16 subTableCount;
Offset subTableOffsetArray[ANY_NUMBER];
const LookupSubtable *getLookupSubtable(le_uint16 subtableIndex) const;
const LEReferenceTo<LookupSubtable> getLookupSubtable(const LEReferenceTo<LookupTable> &base, le_uint16 subtableIndex, LEErrorCode &success) const;
};
LE_VAR_ARRAY(LookupTable, subTableOffsetArray)
struct LookupListTable
{
le_uint16 lookupCount;
Offset lookupTableOffsetArray[ANY_NUMBER];
const LookupTable *getLookupTable(le_uint16 lookupTableIndex) const;
const LEReferenceTo<LookupTable> getLookupTable(const LEReferenceTo<LookupListTable> &base, le_uint16 lookupTableIndex, LEErrorCode &success) const;
};
LE_VAR_ARRAY(LookupListTable, lookupTableOffsetArray)
inline le_int32 LookupSubtable::getGlyphCoverage(LEGlyphID glyphID) const
inline le_int32 LookupSubtable::getGlyphCoverage(const LEReferenceTo<LookupSubtable> &base, LEGlyphID glyphID, LEErrorCode &success) const
{
return getGlyphCoverage(coverageTableOffset, glyphID);
return getGlyphCoverage(base, coverageTableOffset, glyphID, success);
}
inline le_int32 LookupSubtable::getGlyphCoverage(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const {
LEReferenceTo<LookupSubtable> thisRef(base, success, this);
return getGlyphCoverage(thisRef, glyphID, success);
}
inline le_int32 LookupSubtable::getGlyphCoverage(const LETableReference &base, Offset tableOffset, LEGlyphID glyphID, LEErrorCode &success) const {
LEReferenceTo<LookupSubtable> thisRef(base, success, this);
return getGlyphCoverage(thisRef, tableOffset, glyphID, success);
}
U_NAMESPACE_END
......
......@@ -57,6 +57,7 @@ struct MarkArray
le_int32 getMarkClass(LEGlyphID glyphID, le_int32 coverageIndex, const LEFontInstance *fontInstance,
LEPoint &anchor) const;
};
LE_VAR_ARRAY(MarkArray, markRecordArray)
U_NAMESPACE_END
#endif
......
......@@ -51,10 +51,10 @@ LEGlyphID MarkToBasePositioningSubtable::findBaseGlyph(GlyphIterator *glyphItera
return 0xFFFF;
}
le_int32 MarkToBasePositioningSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
LEGlyphID markGlyph = glyphIterator->getCurrGlyphID();
le_int32 markCoverage = getGlyphCoverage((LEGlyphID) markGlyph);
le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success);
if (markCoverage < 0) {
// markGlyph isn't a covered mark glyph
......@@ -75,7 +75,7 @@ le_int32 MarkToBasePositioningSubtable::process(GlyphIterator *glyphIterator, co
// FIXME: We probably don't want to find a base glyph before a previous ligature...
GlyphIterator baseIterator(*glyphIterator, (le_uint16) (lfIgnoreMarks /*| lfIgnoreLigatures*/));
LEGlyphID baseGlyph = findBaseGlyph(&baseIterator);
le_int32 baseCoverage = getBaseCoverage((LEGlyphID) baseGlyph);
le_int32 baseCoverage = getBaseCoverage(base, (LEGlyphID) baseGlyph, success);
const BaseArray *baseArray = (const BaseArray *) ((char *) this + SWAPW(baseArrayOffset));
le_uint16 baseCount = SWAPW(baseArray->baseRecordCount);
......
......@@ -48,7 +48,7 @@ U_NAMESPACE_BEGIN
struct MarkToBasePositioningSubtable : AttachmentPositioningSubtable
{
le_int32 process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
le_int32 process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
LEGlyphID findBaseGlyph(GlyphIterator *glyphIterator) const;
};
......@@ -56,12 +56,14 @@ struct BaseRecord
{
Offset baseAnchorTableOffsetArray[ANY_NUMBER];
};
LE_VAR_ARRAY(BaseRecord, baseAnchorTableOffsetArray)
struct BaseArray
{
le_int16 baseRecordCount;
BaseRecord baseRecordArray[ANY_NUMBER];
};
LE_VAR_ARRAY(BaseArray, baseRecordArray)
U_NAMESPACE_END
#endif
......
......@@ -50,10 +50,10 @@ LEGlyphID MarkToLigaturePositioningSubtable::findLigatureGlyph(GlyphIterator *gl
return 0xFFFF;
}
le_int32 MarkToLigaturePositioningSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
LEGlyphID markGlyph = glyphIterator->getCurrGlyphID();
le_int32 markCoverage = getGlyphCoverage((LEGlyphID) markGlyph);
le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success);
if (markCoverage < 0) {
// markGlyph isn't a covered mark glyph
......@@ -74,7 +74,7 @@ le_int32 MarkToLigaturePositioningSubtable::process(GlyphIterator *glyphIterator
// FIXME: we probably don't want to find a ligature before a previous base glyph...
GlyphIterator ligatureIterator(*glyphIterator, (le_uint16) (lfIgnoreMarks /*| lfIgnoreBaseGlyphs*/));
LEGlyphID ligatureGlyph = findLigatureGlyph(&ligatureIterator);
le_int32 ligatureCoverage = getBaseCoverage((LEGlyphID) ligatureGlyph);
le_int32 ligatureCoverage = getBaseCoverage(base, (LEGlyphID) ligatureGlyph, success);
const LigatureArray *ligatureArray = (const LigatureArray *) ((char *) this + SWAPW(baseArrayOffset));
le_uint16 ligatureCount = SWAPW(ligatureArray->ligatureCount);
......
......@@ -48,7 +48,7 @@ U_NAMESPACE_BEGIN
struct MarkToLigaturePositioningSubtable : AttachmentPositioningSubtable
{
le_int32 process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
le_int32 process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
LEGlyphID findLigatureGlyph(GlyphIterator *glyphIterator) const;
};
......@@ -56,18 +56,21 @@ struct ComponentRecord
{
Offset ligatureAnchorTableOffsetArray[ANY_NUMBER];
};
LE_VAR_ARRAY(ComponentRecord, ligatureAnchorTableOffsetArray)
struct LigatureAttachTable
{
le_uint16 componentCount;
ComponentRecord componentRecordArray[ANY_NUMBER];
};
LE_VAR_ARRAY(LigatureAttachTable, componentRecordArray)
struct LigatureArray
{
le_uint16 ligatureCount;
Offset ligatureAttachTableOffsetArray[ANY_NUMBER];
};
LE_VAR_ARRAY(LigatureArray, ligatureAttachTableOffsetArray)
U_NAMESPACE_END
#endif
......
......@@ -51,10 +51,10 @@ LEGlyphID MarkToMarkPositioningSubtable::findMark2Glyph(GlyphIterator *glyphIter
return 0xFFFF;
}
le_int32 MarkToMarkPositioningSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
LEGlyphID markGlyph = glyphIterator->getCurrGlyphID();
le_int32 markCoverage = getGlyphCoverage((LEGlyphID) markGlyph);
le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success);
if (markCoverage < 0) {
// markGlyph isn't a covered mark glyph
......@@ -74,7 +74,7 @@ le_int32 MarkToMarkPositioningSubtable::process(GlyphIterator *glyphIterator, co
GlyphIterator mark2Iterator(*glyphIterator);
LEGlyphID mark2Glyph = findMark2Glyph(&mark2Iterator);
le_int32 mark2Coverage = getBaseCoverage((LEGlyphID) mark2Glyph);
le_int32 mark2Coverage = getBaseCoverage(base, (LEGlyphID) mark2Glyph, success);
const Mark2Array *mark2Array = (const Mark2Array *) ((char *) this + SWAPW(baseArrayOffset));
le_uint16 mark2Count = SWAPW(mark2Array->mark2RecordCount);
......
......@@ -48,7 +48,7 @@ U_NAMESPACE_BEGIN
struct MarkToMarkPositioningSubtable : AttachmentPositioningSubtable
{
le_int32 process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
le_int32 process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
LEGlyphID findMark2Glyph(GlyphIterator *glyphIterator) const;
};
......@@ -56,12 +56,14 @@ struct Mark2Record
{
Offset mark2AnchorTableOffsetArray[ANY_NUMBER];
};
LE_VAR_ARRAY(Mark2Record, mark2AnchorTableOffsetArray)
struct Mark2Array
{
le_uint16 mark2RecordCount;
Mark2Record mark2RecordArray[ANY_NUMBER];
};
LE_VAR_ARRAY(Mark2Array, mark2RecordArray)
U_NAMESPACE_END
#endif
......
......@@ -44,61 +44,61 @@
U_NAMESPACE_BEGIN
void MorphTableHeader::process(LEGlyphStorage &glyphStorage) const
void MorphTableHeader::process(const LETableReference &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const
{
const ChainHeader *chainHeader = chains;
le_uint32 chainCount = SWAPL(this->nChains);
LEReferenceTo<ChainHeader> chainHeader(base, success, chains); // moving header
LEReferenceToArrayOf<ChainHeader> chainHeaderArray(base, success, chains, chainCount);
le_uint32 chain;
for (chain = 0; chain < chainCount; chain += 1) {
for (chain = 0; LE_SUCCESS(success) && (chain < chainCount); chain += 1) {
FeatureFlags defaultFlags = SWAPL(chainHeader->defaultFlags);
le_uint32 chainLength = SWAPL(chainHeader->chainLength);
le_int16 nFeatureEntries = SWAPW(chainHeader->nFeatureEntries);
le_int16 nSubtables = SWAPW(chainHeader->nSubtables);
const MorphSubtableHeader *subtableHeader =
(const MorphSubtableHeader *)&chainHeader->featureTable[nFeatureEntries];
LEReferenceTo<MorphSubtableHeader> subtableHeader =
LEReferenceTo<MorphSubtableHeader>(chainHeader,success, &(chainHeader->featureTable[nFeatureEntries]));
le_int16 subtable;
for (subtable = 0; subtable < nSubtables; subtable += 1) {
for (subtable = 0; LE_SUCCESS(success) && (subtable < nSubtables); subtable += 1) {
le_int16 length = SWAPW(subtableHeader->length);
SubtableCoverage coverage = SWAPW(subtableHeader->coverage);
FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures);
// should check coverage more carefully...
if ((coverage & scfVertical) == 0 && (subtableFeatures & defaultFlags) != 0) {
subtableHeader->process(glyphStorage);
if ((coverage & scfVertical) == 0 && (subtableFeatures & defaultFlags) != 0 && LE_SUCCESS(success)) {
subtableHeader->process(subtableHeader, glyphStorage, success);
}
subtableHeader = (const MorphSubtableHeader *) ((char *)subtableHeader + length);
subtableHeader.addOffset(length, success);
}
chainHeader = (const ChainHeader *)((char *)chainHeader + chainLength);
chainHeader.addOffset(chainLength, success);
}
}
void MorphSubtableHeader::process(LEGlyphStorage &glyphStorage) const
void MorphSubtableHeader::process(const LEReferenceTo<MorphSubtableHeader> &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const
{
SubtableProcessor *processor = NULL;
switch (SWAPW(coverage) & scfTypeMask)
{
case mstIndicRearrangement:
processor = new IndicRearrangementProcessor(this);
processor = new IndicRearrangementProcessor(base, success);
break;
case mstContextualGlyphSubstitution:
processor = new ContextualGlyphSubstitutionProcessor(this);
processor = new ContextualGlyphSubstitutionProcessor(base, success);
break;
case mstLigatureSubstitution:
processor = new LigatureSubstitutionProcessor(this);
processor = new LigatureSubstitutionProcessor(base, success);
break;
case mstReservedUnused:
break;
case mstNonContextualGlyphSubstitution:
processor = NonContextualGlyphSubstitutionProcessor::createInstance(this);
processor = NonContextualGlyphSubstitutionProcessor::createInstance(base, success);
break;
/*
......@@ -112,7 +112,9 @@ void MorphSubtableHeader::process(LEGlyphStorage &glyphStorage) const
}
if (processor != NULL) {
processor->process(glyphStorage);
if(LE_SUCCESS(success)) {
processor->process(glyphStorage, success);
}
delete processor;
}
}
......
......@@ -39,6 +39,7 @@
#include "LETypes.h"
#include "LayoutTables.h"
#include "LETableReference.h"
U_NAMESPACE_BEGIN
......@@ -65,6 +66,7 @@ struct ChainHeader
le_int16 nSubtables;
FeatureTableEntry featureTable[ANY_NUMBER];
};
LE_VAR_ARRAY(ChainHeader, featureTable)
struct MorphTableHeader
{
......@@ -72,8 +74,9 @@ struct MorphTableHeader
le_uint32 nChains;
ChainHeader chains[ANY_NUMBER];
void process(LEGlyphStorage &glyphStorage) const;
void process(const LETableReference& base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const;
};
LE_VAR_ARRAY(MorphTableHeader, chains)
typedef le_int16 SubtableCoverage;
typedef le_uint32 SubtableCoverage2;
......@@ -103,7 +106,7 @@ struct MorphSubtableHeader
SubtableCoverage coverage;
FeatureFlags subtableFeatures;
void process(LEGlyphStorage &glyphStorage) const;
void process(const LEReferenceTo<MorphSubtableHeader> &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const;
};
enum SubtableCoverageFlags2
......@@ -121,7 +124,7 @@ struct MorphSubtableHeader2
SubtableCoverage2 coverage;
FeatureFlags subtableFeatures;
void process(LEGlyphStorage &glyphStorage) const;
void process(const LEReferenceTo<MorphSubtableHeader2> &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const;
};
struct ChainHeader2
......@@ -132,6 +135,7 @@ struct ChainHeader2
le_uint32 nSubtables;
FeatureTableEntry featureTable[ANY_NUMBER];
};
LE_VAR_ARRAY(ChainHeader2, featureTable)
struct MorphTableHeader2
{
......@@ -139,8 +143,9 @@ struct MorphTableHeader2
le_uint32 nChains;
ChainHeader2 chains[ANY_NUMBER];
void process(LEGlyphStorage &glyphStorage, le_int32 typoFlags) const;
void process(const LEReferenceTo<MorphTableHeader2> &base, LEGlyphStorage &glyphStorage, le_int32 typoFlags, LEErrorCode &success) const;
};
LE_VAR_ARRAY(MorphTableHeader2, chains)
/*
* AAT Font Features
......
......@@ -42,27 +42,40 @@
U_NAMESPACE_BEGIN
void MorphTableHeader2::process(LEGlyphStorage &glyphStorage, le_int32 typoFlags) const
void MorphTableHeader2::process(const LEReferenceTo<MorphTableHeader2> &base, LEGlyphStorage &glyphStorage,
le_int32 typoFlags, LEErrorCode &success) const
{
const ChainHeader2 *chainHeader = chains;
if(LE_FAILURE(success)) return;
le_uint32 chainCount = SWAPL(this->nChains);
LEReferenceTo<ChainHeader2> chainHeader(base, success, &chains[0]);
/* chainHeader and subtableHeader are implemented as a moving pointer rather than an array dereference
* to (slightly) reduce code churn. However, must be careful to preincrement them the 2nd time through.
* We don't want to increment them at the end of the loop, as that would attempt to dereference
* out of range memory.
*/
le_uint32 chain;
for (chain = 0; chain < chainCount; chain++) {
FeatureFlags flag = SWAPL(chainHeader->defaultFlags);
for (chain = 0; LE_SUCCESS(success) && (chain < chainCount); chain++) {
if (chain>0) {
le_uint32 chainLength = SWAPL(chainHeader->chainLength);
chainHeader.addOffset(chainLength, success); // Don't increment the first time
}
FeatureFlags flag = SWAPL(chainHeader->defaultFlags);
le_uint32 nFeatureEntries = SWAPL(chainHeader->nFeatureEntries);
le_uint32 nSubtables = SWAPL(chainHeader->nSubtables);
const MorphSubtableHeader2 *subtableHeader =
(const MorphSubtableHeader2 *)&chainHeader->featureTable[nFeatureEntries];
LEReferenceTo<MorphSubtableHeader2> subtableHeader(chainHeader,
success, (const MorphSubtableHeader2 *)&chainHeader->featureTable[nFeatureEntries]);
le_uint32 subtable;
if(LE_FAILURE(success)) break; // malformed table
if (typoFlags != 0) {
le_uint32 featureEntry;
LEReferenceToArrayOf<FeatureTableEntry> featureTableRef(chainHeader, success, &chainHeader->featureTable[0], nFeatureEntries);
if(LE_FAILURE(success)) break;
// Feature subtables
for (featureEntry = 0; featureEntry < nFeatureEntries; featureEntry++) {
FeatureTableEntry featureTableEntry = chains->featureTable[featureEntry];
const FeatureTableEntry &featureTableEntry = featureTableRef(featureEntry, success);
le_int16 featureType = SWAPW(featureTableEntry.featureType);
le_int16 featureSetting = SWAPW(featureTableEntry.featureSetting);
le_uint32 enableFlags = SWAPL(featureTableEntry.enableFlags);
......@@ -172,57 +185,63 @@ void MorphTableHeader2::process(LEGlyphStorage &glyphStorage, le_int32 typoFlags
}
}
for (subtable = 0; subtable < nSubtables; subtable++) {
for (subtable = 0; LE_SUCCESS(success) && subtable < nSubtables; subtable++) {
if(subtable>0) {
le_uint32 length = SWAPL(subtableHeader->length);
subtableHeader.addOffset(length, success); // Don't addOffset for the last entry.
}
le_uint32 coverage = SWAPL(subtableHeader->coverage);
FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures);
// should check coverage more carefully...
if (((coverage & scfIgnoreVt2) || !(coverage & scfVertical2)) && (subtableFeatures & flag) != 0) {
subtableHeader->process(glyphStorage);
subtableHeader->process(subtableHeader, glyphStorage, success);
}
subtableHeader = (const MorphSubtableHeader2 *) ((char *)subtableHeader + length);
}
chainHeader = (const ChainHeader2 *)((char *)chainHeader + chainLength);
}
}
void MorphSubtableHeader2::process(LEGlyphStorage &glyphStorage) const
void MorphSubtableHeader2::process(const LEReferenceTo<MorphSubtableHeader2> &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const
{
SubtableProcessor2 *processor = NULL;
switch (SWAPL(coverage) & scfTypeMask2)
{
case mstIndicRearrangement:
processor = new IndicRearrangementProcessor2(this);
processor = new IndicRearrangementProcessor2(base, success);
break;
case mstContextualGlyphSubstitution:
processor = new ContextualGlyphSubstitutionProcessor2(this);
processor = new ContextualGlyphSubstitutionProcessor2(base, success);
break;
case mstLigatureSubstitution:
processor = new LigatureSubstitutionProcessor2(this);
processor = new LigatureSubstitutionProcessor2(base, success);
break;
case mstReservedUnused:
break;
case mstNonContextualGlyphSubstitution:
processor = NonContextualGlyphSubstitutionProcessor2::createInstance(this);
processor = NonContextualGlyphSubstitutionProcessor2::createInstance(base, success);
break;
case mstContextualGlyphInsertion:
processor = new ContextualGlyphInsertionProcessor2(this);
processor = new ContextualGlyphInsertionProcessor2(base, success);
break;
default:
break;
return;
break; /*NOTREACHED*/
}
if (processor != NULL) {
processor->process(glyphStorage);
processor->process(glyphStorage, success);
delete processor;
} else {
if(LE_SUCCESS(success)) {
success = LE_MEMORY_ALLOCATION_ERROR; // because ptr is null and we didn't break out.
}
}
}
......
......@@ -39,7 +39,7 @@
U_NAMESPACE_BEGIN
le_uint32 MultipleSubstitutionSubtable::process(GlyphIterator *glyphIterator, LEErrorCode& success, const LEGlyphFilter *filter) const
le_uint32 MultipleSubstitutionSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, LEErrorCode& success, const LEGlyphFilter *filter) const
{
if (LE_FAILURE(success)) {
return 0;
......@@ -58,7 +58,7 @@ le_uint32 MultipleSubstitutionSubtable::process(GlyphIterator *glyphIterator, LE
return 0;
}
le_int32 coverageIndex = getGlyphCoverage(glyph);
le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
le_uint16 seqCount = SWAPW(sequenceCount);
if (coverageIndex >= 0 && coverageIndex < seqCount) {
......
......@@ -50,14 +50,16 @@ struct SequenceTable
le_uint16 glyphCount;
TTGlyphID substituteArray[ANY_NUMBER];
};
LE_VAR_ARRAY(SequenceTable, substituteArray)
struct MultipleSubstitutionSubtable : GlyphSubstitutionSubtable
{
le_uint16 sequenceCount;
Offset sequenceTableOffsetArray[ANY_NUMBER];
le_uint32 process(GlyphIterator *glyphIterator, LEErrorCode& success, const LEGlyphFilter *filter = NULL) const;
le_uint32 process(const LETableReference &base, GlyphIterator *glyphIterator, LEErrorCode& success, const LEGlyphFilter *filter = NULL) const;
};
LE_VAR_ARRAY(MultipleSubstitutionSubtable, sequenceTableOffsetArray)
U_NAMESPACE_END
#endif
......@@ -47,8 +47,8 @@ NonContextualGlyphSubstitutionProcessor::NonContextualGlyphSubstitutionProcessor
{
}
NonContextualGlyphSubstitutionProcessor::NonContextualGlyphSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader)
: SubtableProcessor(morphSubtableHeader)
NonContextualGlyphSubstitutionProcessor::NonContextualGlyphSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
: SubtableProcessor(morphSubtableHeader, success)
{
}
......@@ -56,26 +56,27 @@ NonContextualGlyphSubstitutionProcessor::~NonContextualGlyphSubstitutionProcesso
{
}
SubtableProcessor *NonContextualGlyphSubstitutionProcessor::createInstance(const MorphSubtableHeader *morphSubtableHeader)
SubtableProcessor *NonContextualGlyphSubstitutionProcessor::createInstance(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
{
const NonContextualGlyphSubstitutionHeader *header = (const NonContextualGlyphSubstitutionHeader *) morphSubtableHeader;
LEReferenceTo<NonContextualGlyphSubstitutionHeader> header(morphSubtableHeader, success);
switch (SWAPW(header->table.format))
{
if(LE_FAILURE(success)) return NULL;
switch (SWAPW(header->table.format)) {
case ltfSimpleArray:
return new SimpleArrayProcessor(morphSubtableHeader);
return new SimpleArrayProcessor(morphSubtableHeader, success);
case ltfSegmentSingle:
return new SegmentSingleProcessor(morphSubtableHeader);
return new SegmentSingleProcessor(morphSubtableHeader, success);
case ltfSegmentArray:
return new SegmentArrayProcessor(morphSubtableHeader);
return new SegmentArrayProcessor(morphSubtableHeader, success);
case ltfSingleTable:
return new SingleTableProcessor(morphSubtableHeader);
return new SingleTableProcessor(morphSubtableHeader, success);
case ltfTrimmedArray:
return new TrimmedArrayProcessor(morphSubtableHeader);
return new TrimmedArrayProcessor(morphSubtableHeader, success);
default:
return NULL;
......
......@@ -49,13 +49,13 @@ class LEGlyphStorage;
class NonContextualGlyphSubstitutionProcessor : public SubtableProcessor
{
public:
virtual void process(LEGlyphStorage &glyphStorage) = 0;
virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success) = 0;
static SubtableProcessor *createInstance(const MorphSubtableHeader *morphSubtableHeader);
static SubtableProcessor *createInstance(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
protected:
NonContextualGlyphSubstitutionProcessor();
NonContextualGlyphSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader);
NonContextualGlyphSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &status);
virtual ~NonContextualGlyphSubstitutionProcessor();
......
......@@ -47,8 +47,9 @@ NonContextualGlyphSubstitutionProcessor2::NonContextualGlyphSubstitutionProcesso
{
}
NonContextualGlyphSubstitutionProcessor2::NonContextualGlyphSubstitutionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader)
: SubtableProcessor2(morphSubtableHeader)
NonContextualGlyphSubstitutionProcessor2::NonContextualGlyphSubstitutionProcessor2(
const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
: SubtableProcessor2(morphSubtableHeader, success)
{
}
......@@ -56,26 +57,28 @@ NonContextualGlyphSubstitutionProcessor2::~NonContextualGlyphSubstitutionProcess
{
}
SubtableProcessor2 *NonContextualGlyphSubstitutionProcessor2::createInstance(const MorphSubtableHeader2 *morphSubtableHeader)
SubtableProcessor2 *NonContextualGlyphSubstitutionProcessor2::createInstance(
const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
{
const NonContextualGlyphSubstitutionHeader2 *header = (const NonContextualGlyphSubstitutionHeader2 *) morphSubtableHeader;
const LEReferenceTo<NonContextualGlyphSubstitutionHeader2> header(morphSubtableHeader, success);
if(LE_FAILURE(success)) return NULL;
switch (SWAPW(header->table.format))
{
case ltfSimpleArray:
return new SimpleArrayProcessor2(morphSubtableHeader);
return new SimpleArrayProcessor2(morphSubtableHeader, success);
case ltfSegmentSingle:
return new SegmentSingleProcessor2(morphSubtableHeader);
return new SegmentSingleProcessor2(morphSubtableHeader, success);
case ltfSegmentArray:
return new SegmentArrayProcessor2(morphSubtableHeader);
return new SegmentArrayProcessor2(morphSubtableHeader, success);
case ltfSingleTable:
return new SingleTableProcessor2(morphSubtableHeader);
return new SingleTableProcessor2(morphSubtableHeader, success);
case ltfTrimmedArray:
return new TrimmedArrayProcessor2(morphSubtableHeader);
return new TrimmedArrayProcessor2(morphSubtableHeader, success);
default:
return NULL;
......
......@@ -49,13 +49,13 @@ class LEGlyphStorage;
class NonContextualGlyphSubstitutionProcessor2 : public SubtableProcessor2
{
public:
virtual void process(LEGlyphStorage &glyphStorage) = 0;
virtual void process(LEGlyphStorage &glyphStorage, LEErrorCode &success) = 0;
static SubtableProcessor2 *createInstance(const MorphSubtableHeader2 *morphSubtableHeader);
static SubtableProcessor2 *createInstance(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
protected:
NonContextualGlyphSubstitutionProcessor2();
NonContextualGlyphSubstitutionProcessor2(const MorphSubtableHeader2 *morphSubtableHeader);
NonContextualGlyphSubstitutionProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
virtual ~NonContextualGlyphSubstitutionProcessor2();
......
......@@ -151,25 +151,21 @@ static const FeatureMap featureMap[] =
static const le_int32 featureMapCount = LE_ARRAY_SIZE(featureMap);
OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success)
: LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success), fFeatureMask(minimalFeatures),
fFeatureMap(featureMap), fFeatureMapCount(featureMapCount), fFeatureOrder(FALSE),
fGSUBTable(gsubTable), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL)
fGSUBTable(gsubTable),
fGDEFTable(fontInstance, LE_GDEF_TABLE_TAG, success),
fGPOSTable(fontInstance, LE_GPOS_TABLE_TAG, success), fSubstitutionFilter(NULL)
{
static const le_uint32 gdefTableTag = LE_GDEF_TABLE_TAG;
static const le_uint32 gposTableTag = LE_GPOS_TABLE_TAG;
const GlyphPositioningTableHeader *gposTable = (const GlyphPositioningTableHeader *) getFontTable(gposTableTag);
applyTypoFlags();
setScriptAndLanguageTags();
fGDEFTable = (const GlyphDefinitionTableHeader *) getFontTable(gdefTableTag);
// JK patch, 2008-05-30 - see Sinhala bug report and LKLUG font
// if (gposTable != NULL && gposTable->coversScriptAndLanguage(fScriptTag, fLangSysTag)) {
if (gposTable != NULL && gposTable->coversScript(fScriptTag)) {
fGPOSTable = gposTable;
if (!fGPOSTable.isEmpty()&& !fGPOSTable->coversScript(fGPOSTable, fScriptTag, success)) {
fGPOSTable.clear(); // already loaded
}
}
......@@ -252,7 +248,7 @@ void OpenTypeLayoutEngine::reset()
OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
le_int32 typoFlags, LEErrorCode &success)
: LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success), fFeatureOrder(FALSE),
fGSUBTable(NULL), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL)
fGSUBTable(), fGDEFTable(), fGPOSTable(), fSubstitutionFilter(NULL)
{
applyTypoFlags();
setScriptAndLanguageTags();
......@@ -375,13 +371,13 @@ le_int32 OpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_int32
return 0;
}
if (fGSUBTable != NULL) {
if (fScriptTagV2 != nullScriptTag && fGSUBTable->coversScriptAndLanguage(fScriptTagV2,fLangSysTag)) {
count = fGSUBTable->process(glyphStorage, rightToLeft, fScriptTagV2, fLangSysTag, fGDEFTable, fSubstitutionFilter,
if (fGSUBTable.isValid()) {
if (fScriptTagV2 != nullScriptTag && fGSUBTable->coversScriptAndLanguage(fGSUBTable, fScriptTagV2, fLangSysTag, success)) {
count = fGSUBTable->process(fGSUBTable, glyphStorage, rightToLeft, fScriptTagV2, fLangSysTag, fGDEFTable, fSubstitutionFilter,
fFeatureMap, fFeatureMapCount, fFeatureOrder, success);
} else {
count = fGSUBTable->process(glyphStorage, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter,
count = fGSUBTable->process(fGSUBTable, glyphStorage, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter,
fFeatureMap, fFeatureMapCount, fFeatureOrder, success);
}
}
......@@ -402,13 +398,13 @@ le_int32 OpenTypeLayoutEngine::glyphSubstitution(le_int32 count, le_int32 max, l
return 0;
}
if (fGSUBTable != NULL) {
if (fScriptTagV2 != nullScriptTag && fGSUBTable->coversScriptAndLanguage(fScriptTagV2,fLangSysTag)) {
count = fGSUBTable->process(glyphStorage, rightToLeft, fScriptTagV2, fLangSysTag, fGDEFTable, fSubstitutionFilter,
if (fGSUBTable.isValid()) {
if (fScriptTagV2 != nullScriptTag && fGSUBTable->coversScriptAndLanguage(fGSUBTable,fScriptTagV2,fLangSysTag,success)) {
count = fGSUBTable->process(fGSUBTable, glyphStorage, rightToLeft, fScriptTagV2, fLangSysTag, fGDEFTable, fSubstitutionFilter,
fFeatureMap, fFeatureMapCount, fFeatureOrder, success);
} else {
count = fGSUBTable->process(glyphStorage, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter,
count = fGSUBTable->process(fGSUBTable, glyphStorage, rightToLeft, fScriptTag, fLangSysTag, fGDEFTable, fSubstitutionFilter,
fFeatureMap, fFeatureMapCount, fFeatureOrder, success);
}
}
......@@ -488,7 +484,7 @@ void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int3
return;
}
if (fGPOSTable != NULL) {
if (!fGPOSTable.isEmpty()) {
GlyphPositionAdjustments *adjustments = new GlyphPositionAdjustments(glyphCount);
le_int32 i;
......@@ -511,19 +507,20 @@ void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int3
}
#endif
if (fGPOSTable != NULL) {
if (fScriptTagV2 != nullScriptTag && fGPOSTable->coversScriptAndLanguage(fScriptTagV2,fLangSysTag)) {
fGPOSTable->process(glyphStorage, adjustments, reverse, fScriptTagV2, fLangSysTag, fGDEFTable, success, fFontInstance,
fFeatureMap, fFeatureMapCount, fFeatureOrder);
if (!fGPOSTable.isEmpty()) {
if (fScriptTagV2 != nullScriptTag &&
fGPOSTable->coversScriptAndLanguage(fGPOSTable, fScriptTagV2,fLangSysTag,success)) {
fGPOSTable->process(fGPOSTable, glyphStorage, adjustments, reverse, fScriptTagV2, fLangSysTag,
fGDEFTable, success, fFontInstance, fFeatureMap, fFeatureMapCount, fFeatureOrder);
} else {
fGPOSTable->process(glyphStorage, adjustments, reverse, fScriptTag, fLangSysTag, fGDEFTable, success, fFontInstance,
fFeatureMap, fFeatureMapCount, fFeatureOrder);
fGPOSTable->process(fGPOSTable, glyphStorage, adjustments, reverse, fScriptTag, fLangSysTag,
fGDEFTable, success, fFontInstance, fFeatureMap, fFeatureMapCount, fFeatureOrder);
}
} else if ( fTypoFlags & 0x1 ) {
static const le_uint32 kernTableTag = LE_KERN_TABLE_TAG;
KernTable kt(fFontInstance, getFontTable(kernTableTag));
kt.process(glyphStorage);
} else if (fTypoFlags & LE_Kerning_FEATURE_FLAG) { /* kerning enabled */
LETableReference kernTable(fFontInstance, LE_KERN_TABLE_TAG, success);
KernTable kt(kernTable, success);
kt.process(glyphStorage, success);
}
float xAdjust = 0, yAdjust = 0;
......
......@@ -35,6 +35,7 @@
#include "LEGlyphFilter.h"
#include "LEFontInstance.h"
#include "LayoutEngine.h"
#include "LETableReference.h"
#include "GlyphSubstitutionTables.h"
#include "GlyphDefinitionTables.h"
......@@ -88,7 +89,7 @@ public:
* @internal
*/
OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success);
le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success);
/**
* This constructor is used when the font requires a "canned" GSUB table which can't be known
......@@ -228,21 +229,21 @@ protected:
*
* @internal
*/
const GlyphSubstitutionTableHeader *fGSUBTable;
LEReferenceTo<GlyphSubstitutionTableHeader> fGSUBTable;
/**
* The address of the GDEF table.
*
* @internal
*/
const GlyphDefinitionTableHeader *fGDEFTable;
LEReferenceTo<GlyphDefinitionTableHeader> fGDEFTable;
/**
* The address of the GPOS table.
*
* @internal
*/
const GlyphPositioningTableHeader *fGPOSTable;
LEReferenceTo<GlyphPositioningTableHeader> fGPOSTable;
/**
* An optional filter used to inhibit substitutions
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册