8004986: Better handling of glyph table
8004987: Improve font layout 8004994: Improve checking of glyph table Reviewed-by: srl, jgodinez
This commit is contained in:
parent
ae5b3c9310
commit
ae2454b3e5
@ -26,7 +26,7 @@
|
||||
|
||||
/*
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved
|
||||
* (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
@ -152,17 +152,16 @@ void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], l
|
||||
}
|
||||
|
||||
UnicodeArabicOpenTypeLayoutEngine::UnicodeArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
|
||||
: ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success)
|
||||
: ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags | LE_CHAR_FILTER_FEATURE_FLAG, success)
|
||||
{
|
||||
fGSUBTable = (const GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
|
||||
fGDEFTable = (const GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
|
||||
|
||||
fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
|
||||
/* OpenTypeLayoutEngine will allocate a substitution filter */
|
||||
}
|
||||
|
||||
UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
|
||||
{
|
||||
delete fSubstitutionFilter;
|
||||
/* OpenTypeLayoutEngine will cleanup the substitution filter */
|
||||
}
|
||||
|
||||
// "glyphs", "indices" -> glyphs, indices
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include "ContextualGlyphSubstProc2.h"
|
||||
#include "LEGlyphStorage.h"
|
||||
#include "LESwaps.h"
|
||||
#include <stdio.h>
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
@ -123,7 +122,7 @@ TTGlyphID ContextualGlyphSubstitutionProcessor2::lookup(le_uint32 offset, LEGlyp
|
||||
break;
|
||||
}
|
||||
case ltfSegmentArray: {
|
||||
printf("Context Lookup Table Format4: specific interpretation needed!\n");
|
||||
//printf("Context Lookup Table Format4: specific interpretation needed!\n");
|
||||
break;
|
||||
}
|
||||
case ltfSingleTable:
|
||||
|
@ -339,6 +339,35 @@ typedef struct LEPoint LEPoint;
|
||||
|
||||
|
||||
#ifndef U_HIDE_INTERNAL_API
|
||||
|
||||
#ifndef LE_ASSERT_BAD_FONT
|
||||
#define LE_ASSERT_BAD_FONT 0
|
||||
#endif
|
||||
|
||||
#if LE_ASSERT_BAD_FONT
|
||||
#include <stdio.h>
|
||||
#define LE_DEBUG_BAD_FONT(x) fprintf(stderr,"%s:%d: BAD FONT: %s\n", __FILE__, __LINE__, (x));
|
||||
#else
|
||||
#define LE_DEBUG_BAD_FONT(x)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Max value representable by a uintptr
|
||||
*/
|
||||
#ifndef UINTPTR_MAX
|
||||
#ifndef UINT32_MAX
|
||||
#define LE_UINTPTR_MAX 0xFFFFFFFFU
|
||||
#else
|
||||
#define LE_UINTPTR_MAX UINT32_MAX
|
||||
#endif
|
||||
#else
|
||||
#define LE_UINTPTR_MAX UINTPTR_MAX
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Range check for overflow
|
||||
*/
|
||||
#define LE_RANGE_CHECK(type, count, ptrfn) (( (LE_UINTPTR_MAX / sizeof(type)) < count ) ? NULL : (ptrfn))
|
||||
/**
|
||||
* A convenience macro to get the length of an array.
|
||||
*
|
||||
@ -360,7 +389,7 @@ typedef struct LEPoint LEPoint;
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
#define LE_NEW_ARRAY(type, count) (type *) uprv_malloc((count) * sizeof(type))
|
||||
#define LE_NEW_ARRAY(type, count) (type *) LE_RANGE_CHECK(type,count,uprv_malloc((count) * sizeof(type)))
|
||||
|
||||
/**
|
||||
* Re-allocate an array of basic types. This is used to isolate the rest of
|
||||
@ -403,7 +432,7 @@ typedef struct LEPoint LEPoint;
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
#define LE_NEW_ARRAY(type, count) (type *) malloc((count) * sizeof(type))
|
||||
#define LE_NEW_ARRAY(type, count) LE_RANGE_CHECK(type,count,(type *) malloc((count) * sizeof(type)))
|
||||
|
||||
/**
|
||||
* Re-allocate an array of basic types. This is used to isolate the rest of
|
||||
@ -696,6 +725,8 @@ enum LEFeatureENUMs {
|
||||
|
||||
#define LE_CHAR_FILTER_FEATURE_FLAG (1 << LE_CHAR_FILTER_FEATURE_ENUM)
|
||||
|
||||
#define LE_DEFAULT_FEATURE_FLAG (LE_Kerning_FEATURE_FLAG | LE_Ligatures_FEATURE_FLAG) /**< default features */
|
||||
|
||||
/**
|
||||
* Error codes returned by the LayoutEngine.
|
||||
*
|
||||
|
@ -428,7 +428,7 @@ void LayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset
|
||||
|
||||
adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
|
||||
|
||||
if (fTypoFlags & 0x1) { /* kerning enabled */
|
||||
if (fTypoFlags & LE_Kerning_FEATURE_FLAG) { /* kerning enabled */
|
||||
static const le_uint32 kernTableTag = LE_KERN_TABLE_TAG;
|
||||
|
||||
KernTable kt(fFontInstance, getFontTable(kernTableTag));
|
||||
@ -571,8 +571,8 @@ void LayoutEngine::reset()
|
||||
|
||||
LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, LEErrorCode &success)
|
||||
{
|
||||
// 3 -> kerning and ligatures
|
||||
return LayoutEngine::layoutEngineFactory(fontInstance, scriptCode, languageCode, 3, success);
|
||||
//kerning and ligatures - by default
|
||||
return LayoutEngine::layoutEngineFactory(fontInstance, scriptCode, languageCode, LE_DEFAULT_FEATURE_FLAG, success);
|
||||
}
|
||||
|
||||
LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
|
||||
@ -660,11 +660,11 @@ LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstan
|
||||
}
|
||||
} else {
|
||||
MorphTableHeader2 *morxTable = (MorphTableHeader2 *)fontInstance->getFontTable(morxTableTag);
|
||||
if (morxTable != NULL) {
|
||||
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) { // mort
|
||||
if (mortTable != NULL && SWAPL(mortTable->version)==0x00010000) { // mort
|
||||
result = new GXLayoutEngine(fontInstance, scriptCode, languageCode, mortTable, success);
|
||||
} else {
|
||||
switch (scriptCode) {
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
/*
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
|
||||
* (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
@ -79,6 +79,10 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp
|
||||
}
|
||||
|
||||
componentStack[m] = currGlyph;
|
||||
} else if ( m == -1) {
|
||||
// bad font- skip this glyph.
|
||||
currGlyph++;
|
||||
return newState;
|
||||
}
|
||||
|
||||
ByteOffset actionOffset = flags & lsfActionOffsetMask;
|
||||
@ -102,7 +106,21 @@ 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));
|
||||
|
||||
// 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?
|
||||
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])]);
|
||||
|
||||
if (action & (lafLast | lafStore)) {
|
||||
@ -110,13 +128,22 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp
|
||||
TTGlyphID ligatureGlyph = SWAPW(*ligatureOffset);
|
||||
|
||||
glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph);
|
||||
if(mm==nComponents) {
|
||||
LE_DEBUG_BAD_FONT("exceeded nComponents");
|
||||
mm--; // don't overrun the stack.
|
||||
}
|
||||
stack[++mm] = componentGlyph;
|
||||
i = 0;
|
||||
} else {
|
||||
glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], 0xFFFF);
|
||||
}
|
||||
}
|
||||
} while (!(action & lafLast));
|
||||
#if LE_ASSERT_BAD_FONT
|
||||
if(m<0) {
|
||||
LE_DEBUG_BAD_FONT("m<0")
|
||||
}
|
||||
#endif
|
||||
} while (!(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items
|
||||
|
||||
while (mm >= 0) {
|
||||
if (++m >= nComponents) {
|
||||
|
@ -79,6 +79,11 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp
|
||||
m = 0;
|
||||
}
|
||||
componentStack[m] = currGlyph;
|
||||
} else if ( m == -1) {
|
||||
// bad font- skip this glyph.
|
||||
LE_DEBUG_BAD_FONT("m==-1")
|
||||
currGlyph+= dir;
|
||||
return nextStateIndex;
|
||||
}
|
||||
|
||||
ByteOffset actionOffset = flags & lsfPerformAction;
|
||||
@ -93,6 +98,16 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp
|
||||
|
||||
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?
|
||||
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
|
||||
|
||||
@ -104,19 +119,32 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp
|
||||
|
||||
offset = action & lafComponentOffsetMask;
|
||||
if (offset != 0) {
|
||||
|
||||
if(componentGlyph > glyphStorage.getGlyphCount()) {
|
||||
LE_DEBUG_BAD_FONT("preposterous componentGlyph");
|
||||
currGlyph+= dir;
|
||||
return nextStateIndex; // get out! bad font
|
||||
}
|
||||
i += SWAPW(componentTable[LE_GET_GLYPH(glyphStorage[componentGlyph]) + (SignExtend(offset, lafComponentOffsetMask))]);
|
||||
|
||||
if (action & (lafLast | lafStore)) {
|
||||
TTGlyphID ligatureGlyph = SWAPW(ligatureTable[i]);
|
||||
glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph);
|
||||
if(mm==nComponents) {
|
||||
LE_DEBUG_BAD_FONT("exceeded nComponents");
|
||||
mm--; // don't overrun the stack.
|
||||
}
|
||||
stack[++mm] = componentGlyph;
|
||||
i = 0;
|
||||
} else {
|
||||
glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], 0xFFFF);
|
||||
}
|
||||
}
|
||||
} while (!(action & lafLast));
|
||||
#if LE_ASSERT_BAD_FONT
|
||||
if(m<0) {
|
||||
LE_DEBUG_BAD_FONT("m<0")
|
||||
}
|
||||
#endif
|
||||
} while (!(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items
|
||||
|
||||
while (mm >= 0) {
|
||||
if (++m >= nComponents) {
|
||||
|
@ -208,7 +208,7 @@ LookupProcessor::LookupProcessor(const char *baseAddress,
|
||||
lookupSelectCount = lookupListCount;
|
||||
|
||||
le_int32 count, order = 0;
|
||||
le_int32 featureReferences = 0;
|
||||
le_uint32 featureReferences = 0;
|
||||
const FeatureTable *featureTable = NULL;
|
||||
LETag featureTag;
|
||||
|
||||
@ -219,7 +219,7 @@ LookupProcessor::LookupProcessor(const char *baseAddress,
|
||||
// be the maximum number of entries in the lookupOrderArray. We can't use
|
||||
// lookupListCount because some lookups might be referenced by more than
|
||||
// one feature.
|
||||
for (le_int32 feature = 0; feature < featureCount; feature += 1) {
|
||||
for (le_uint32 feature = 0; feature < featureCount; feature += 1) {
|
||||
le_uint16 featureIndex = SWAPW(langSysTable->featureIndexArray[feature]);
|
||||
|
||||
featureTable = featureListTable->getFeatureTable(featureIndex, &featureTag);
|
||||
|
@ -123,7 +123,7 @@ static const FeatureMap featureMap[] =
|
||||
{ccmpFeatureTag, ccmpFeatureMask},
|
||||
{ligaFeatureTag, ligaFeatureMask},
|
||||
{cligFeatureTag, cligFeatureMask},
|
||||
{kernFeatureTag, kernFeatureMask},
|
||||
{kernFeatureTag, kernFeatureMask},
|
||||
{paltFeatureTag, paltFeatureMask},
|
||||
{markFeatureTag, markFeatureMask},
|
||||
{mkmkFeatureTag, mkmkFeatureMask},
|
||||
@ -160,6 +160,23 @@ OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, l
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenTypeLayoutEngine::applyTypoFlags() {
|
||||
const le_int32& typoFlags = fTypoFlags;
|
||||
const LEFontInstance *fontInstance = fFontInstance;
|
||||
|
||||
switch (typoFlags & (LE_SS01_FEATURE_FLAG
|
||||
| LE_SS02_FEATURE_FLAG
|
||||
| LE_SS03_FEATURE_FLAG
|
||||
@ -221,15 +238,6 @@ OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, l
|
||||
fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenTypeLayoutEngine::reset()
|
||||
@ -246,13 +254,15 @@ OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, l
|
||||
: LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success), fFeatureOrder(FALSE),
|
||||
fGSUBTable(NULL), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL)
|
||||
{
|
||||
setScriptAndLanguageTags();
|
||||
applyTypoFlags();
|
||||
setScriptAndLanguageTags();
|
||||
}
|
||||
|
||||
OpenTypeLayoutEngine::~OpenTypeLayoutEngine()
|
||||
{
|
||||
if (fTypoFlags & 0x80000000L) {
|
||||
if (fTypoFlags & LE_CHAR_FILTER_FEATURE_FLAG) {
|
||||
delete fSubstitutionFilter;
|
||||
fSubstitutionFilter = NULL;
|
||||
}
|
||||
|
||||
reset();
|
||||
|
@ -24,7 +24,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* (C) Copyright IBM Corp. 1998-2010 - All Rights Reserved
|
||||
* (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
@ -184,6 +184,11 @@ private:
|
||||
*/
|
||||
static const LETag scriptTags[];
|
||||
|
||||
/**
|
||||
* apply the typoflags. Only called by the c'tors.
|
||||
*/
|
||||
void applyTypoFlags();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* A set of "default" features. The default characterProcessing method
|
||||
|
@ -65,6 +65,9 @@ StateTableProcessor::~StateTableProcessor()
|
||||
|
||||
void StateTableProcessor::process(LEGlyphStorage &glyphStorage)
|
||||
{
|
||||
|
||||
LE_STATE_PATIENCE_INIT();
|
||||
|
||||
// Start at state 0
|
||||
// XXX: How do we know when to start at state 1?
|
||||
ByteOffset currentState = stateArrayOffset;
|
||||
@ -76,6 +79,7 @@ void StateTableProcessor::process(LEGlyphStorage &glyphStorage)
|
||||
beginStateTable();
|
||||
|
||||
while (currGlyph <= glyphCount) {
|
||||
if(LE_STATE_PATIENCE_DECR()) break; // patience exceeded.
|
||||
ClassCode classCode = classCodeOOB;
|
||||
if (currGlyph == glyphCount) {
|
||||
// XXX: How do we handle EOT vs. EOL?
|
||||
@ -92,8 +96,9 @@ void StateTableProcessor::process(LEGlyphStorage &glyphStorage)
|
||||
|
||||
const EntryTableIndex *stateArray = (const EntryTableIndex *) ((char *) &stateTableHeader->stHeader + currentState);
|
||||
EntryTableIndex entryTableIndex = stateArray[(le_uint8)classCode];
|
||||
|
||||
LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
|
||||
currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
|
||||
LE_STATE_PATIENCE_INCR(currGlyph);
|
||||
}
|
||||
|
||||
endStateTable();
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include "LEGlyphStorage.h"
|
||||
#include "LESwaps.h"
|
||||
#include "LookupTables.h"
|
||||
#include <stdio.h>
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
@ -72,6 +71,8 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
|
||||
le_uint16 currentState = 0;
|
||||
le_int32 glyphCount = glyphStorage.getGlyphCount();
|
||||
|
||||
LE_STATE_PATIENCE_INIT();
|
||||
|
||||
le_int32 currGlyph = 0;
|
||||
if ((coverage & scfReverse2) != 0) { // process glyphs in descending order
|
||||
currGlyph = glyphCount - 1;
|
||||
@ -86,6 +87,10 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
|
||||
#ifdef TEST_FORMAT
|
||||
SimpleArrayLookupTable *lookupTable0 = (SimpleArrayLookupTable *) classTable;
|
||||
while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
|
||||
if(LE_STATE_PATIENCE_DECR()) {
|
||||
LE_DEBUG_BAD_FONT("patience exceeded - state table not moving")
|
||||
break; // patience exceeded.
|
||||
}
|
||||
LookupValue classCode = classCodeOOB;
|
||||
if (currGlyph == glyphCount || currGlyph == -1) {
|
||||
// XXX: How do we handle EOT vs. EOL?
|
||||
@ -101,7 +106,9 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
|
||||
}
|
||||
}
|
||||
EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);
|
||||
LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
|
||||
currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex); // return a zero-based index instead of a byte offset
|
||||
LE_STATE_PATIENCE_INCR(currGlyph);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
@ -109,6 +116,10 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
|
||||
case ltfSegmentSingle: {
|
||||
SegmentSingleLookupTable *lookupTable2 = (SegmentSingleLookupTable *) classTable;
|
||||
while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
|
||||
if(LE_STATE_PATIENCE_DECR()) {
|
||||
LE_DEBUG_BAD_FONT("patience exceeded - state table not moving")
|
||||
break; // patience exceeded.
|
||||
}
|
||||
LookupValue classCode = classCodeOOB;
|
||||
if (currGlyph == glyphCount || currGlyph == -1) {
|
||||
// XXX: How do we handle EOT vs. EOL?
|
||||
@ -127,21 +138,31 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
|
||||
}
|
||||
}
|
||||
EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);
|
||||
LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
|
||||
currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
|
||||
LE_STATE_PATIENCE_INCR(currGlyph);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ltfSegmentArray: {
|
||||
printf("Lookup Table Format4: specific interpretation needed!\n");
|
||||
//printf("Lookup Table Format4: specific interpretation needed!\n");
|
||||
break;
|
||||
}
|
||||
case ltfSingleTable: {
|
||||
SingleTableLookupTable *lookupTable6 = (SingleTableLookupTable *) classTable;
|
||||
while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
|
||||
if(LE_STATE_PATIENCE_DECR()) {
|
||||
LE_DEBUG_BAD_FONT("patience exceeded - state table not moving")
|
||||
break; // patience exceeded.
|
||||
}
|
||||
LookupValue classCode = classCodeOOB;
|
||||
if (currGlyph == glyphCount || currGlyph == -1) {
|
||||
// XXX: How do we handle EOT vs. EOL?
|
||||
classCode = classCodeEOT;
|
||||
} else if(currGlyph > glyphCount) {
|
||||
// note if > glyphCount, we've run off the end (bad font)
|
||||
currGlyph = glyphCount;
|
||||
classCode = classCodeEOT;
|
||||
} else {
|
||||
LEGlyphID gid = glyphStorage[currGlyph];
|
||||
TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
|
||||
@ -156,7 +177,9 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
|
||||
}
|
||||
}
|
||||
EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);
|
||||
LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
|
||||
currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
|
||||
LE_STATE_PATIENCE_INCR(currGlyph);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -166,6 +189,11 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
|
||||
TTGlyphID lastGlyph = firstGlyph + SWAPW(lookupTable8->glyphCount);
|
||||
|
||||
while ((dir == 1 && currGlyph <= glyphCount) || (dir == -1 && currGlyph >= -1)) {
|
||||
if(LE_STATE_PATIENCE_DECR()) {
|
||||
LE_DEBUG_BAD_FONT("patience exceeded - state table not moving")
|
||||
break; // patience exceeded.
|
||||
}
|
||||
|
||||
LookupValue classCode = classCodeOOB;
|
||||
if (currGlyph == glyphCount || currGlyph == -1) {
|
||||
// XXX: How do we handle EOT vs. EOL?
|
||||
@ -179,7 +207,9 @@ void StateTableProcessor2::process(LEGlyphStorage &glyphStorage)
|
||||
}
|
||||
}
|
||||
EntryTableIndex2 entryTableIndex = SWAPW(stateArray[classCode + currentState * nClasses]);
|
||||
LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
|
||||
currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
|
||||
LE_STATE_PATIENCE_INCR(currGlyph);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -42,6 +42,41 @@
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* State table loop detection.
|
||||
* Detects if too many ( LE_STATE_PATIENCE_COUNT ) state changes occur without moving the glyph index 'g'.
|
||||
*
|
||||
* Usage (pseudocode):
|
||||
*
|
||||
* {
|
||||
* LE_STATE_PATIENCE_INIT();
|
||||
*
|
||||
* int g=0; // the glyph index - expect it to be moving
|
||||
*
|
||||
* for(;;) {
|
||||
* if(LE_STATE_PATIENCE_DECR()) { // decrements the patience counter
|
||||
* // ran out of patience, get out.
|
||||
* break;
|
||||
* }
|
||||
*
|
||||
* LE_STATE_PATIENCE_CURR(int, g); // store the 'current'
|
||||
* state = newState(state,g);
|
||||
* g+= <something, could be zero>;
|
||||
* LE_STATE_PATIENCE_INCR(g); // if g has moved, increment the patience counter. Otherwise leave it.
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
#define LE_STATE_PATIENCE_COUNT 4096 /**< give up if a state table doesn't move the glyph after this many iterations */
|
||||
#define LE_STATE_PATIENCE_INIT() le_uint32 le_patience_count = LE_STATE_PATIENCE_COUNT
|
||||
#define LE_STATE_PATIENCE_DECR() --le_patience_count==0
|
||||
#define LE_STATE_PATIENCE_CURR(type,x) type le_patience_curr=(x)
|
||||
#define LE_STATE_PATIENCE_INCR(x) if((x)!=le_patience_curr) ++le_patience_count;
|
||||
|
||||
|
||||
struct StateTableHeader
|
||||
{
|
||||
le_int16 stateSize;
|
||||
|
Loading…
x
Reference in New Issue
Block a user