8004986: Better handling of glyph table
8004987: Improve font layout
8004994: Improve checking of glyph table
Reviewed-by: srl, jgodinez
--- a/jdk/src/share/native/sun/font/layout/ArabicLayoutEngine.cpp Fri Feb 15 13:07:17 2013 -0800
+++ b/jdk/src/share/native/sun/font/layout/ArabicLayoutEngine.cpp Tue Feb 26 10:07:26 2013 -0800
@@ -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 @@
}
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
--- a/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc2.cpp Fri Feb 15 13:07:17 2013 -0800
+++ b/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc2.cpp Tue Feb 26 10:07:26 2013 -0800
@@ -38,7 +38,6 @@
#include "ContextualGlyphSubstProc2.h"
#include "LEGlyphStorage.h"
#include "LESwaps.h"
-#include <stdio.h>
U_NAMESPACE_BEGIN
@@ -123,7 +122,7 @@
break;
}
case ltfSegmentArray: {
- printf("Context Lookup Table Format4: specific interpretation needed!\n");
+ //printf("Context Lookup Table Format4: specific interpretation needed!\n");
break;
}
case ltfSingleTable:
--- a/jdk/src/share/native/sun/font/layout/LETypes.h Fri Feb 15 13:07:17 2013 -0800
+++ b/jdk/src/share/native/sun/font/layout/LETypes.h Tue Feb 26 10:07:26 2013 -0800
@@ -339,6 +339,35 @@
#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 @@
*
* @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 @@
*
* @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 @@
#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.
*
--- a/jdk/src/share/native/sun/font/layout/LayoutEngine.cpp Fri Feb 15 13:07:17 2013 -0800
+++ b/jdk/src/share/native/sun/font/layout/LayoutEngine.cpp Tue Feb 26 10:07:26 2013 -0800
@@ -428,7 +428,7 @@
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 @@
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 @@
}
} 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) {
--- a/jdk/src/share/native/sun/font/layout/LigatureSubstProc.cpp Fri Feb 15 13:07:17 2013 -0800
+++ b/jdk/src/share/native/sun/font/layout/LigatureSubstProc.cpp Tue Feb 26 10:07:26 2013 -0800
@@ -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 @@
}
componentStack[m] = currGlyph;
+ } else if ( m == -1) {
+ // bad font- skip this glyph.
+ currGlyph++;
+ return newState;
}
ByteOffset actionOffset = flags & lsfActionOffsetMask;
@@ -102,7 +106,21 @@
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 @@
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) {
--- a/jdk/src/share/native/sun/font/layout/LigatureSubstProc2.cpp Fri Feb 15 13:07:17 2013 -0800
+++ b/jdk/src/share/native/sun/font/layout/LigatureSubstProc2.cpp Tue Feb 26 10:07:26 2013 -0800
@@ -79,6 +79,11 @@
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 @@
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 @@
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) {
--- a/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp Fri Feb 15 13:07:17 2013 -0800
+++ b/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp Tue Feb 26 10:07:26 2013 -0800
@@ -208,7 +208,7 @@
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 @@
// 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);
--- a/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.cpp Fri Feb 15 13:07:17 2013 -0800
+++ b/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.cpp Tue Feb 26 10:07:26 2013 -0800
@@ -123,7 +123,7 @@
{ccmpFeatureTag, ccmpFeatureMask},
{ligaFeatureTag, ligaFeatureMask},
{cligFeatureTag, cligFeatureMask},
- {kernFeatureTag, kernFeatureMask},
+ {kernFeatureTag, kernFeatureMask},
{paltFeatureTag, paltFeatureMask},
{markFeatureTag, markFeatureMask},
{mkmkFeatureTag, mkmkFeatureMask},
@@ -160,6 +160,23 @@
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 @@
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 @@
: 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();
--- a/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.h Fri Feb 15 13:07:17 2013 -0800
+++ b/jdk/src/share/native/sun/font/layout/OpenTypeLayoutEngine.h Tue Feb 26 10:07:26 2013 -0800
@@ -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 @@
*/
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
--- a/jdk/src/share/native/sun/font/layout/StateTableProcessor.cpp Fri Feb 15 13:07:17 2013 -0800
+++ b/jdk/src/share/native/sun/font/layout/StateTableProcessor.cpp Tue Feb 26 10:07:26 2013 -0800
@@ -65,6 +65,9 @@
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 @@
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 @@
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();
--- a/jdk/src/share/native/sun/font/layout/StateTableProcessor2.cpp Fri Feb 15 13:07:17 2013 -0800
+++ b/jdk/src/share/native/sun/font/layout/StateTableProcessor2.cpp Tue Feb 26 10:07:26 2013 -0800
@@ -38,7 +38,6 @@
#include "LEGlyphStorage.h"
#include "LESwaps.h"
#include "LookupTables.h"
-#include <stdio.h>
U_NAMESPACE_BEGIN
@@ -72,6 +71,8 @@
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 @@
#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 @@
}
}
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 @@
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 @@
}
}
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 @@
}
}
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 @@
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 @@
}
}
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;
}
--- a/jdk/src/share/native/sun/font/layout/StateTables.h Fri Feb 15 13:07:17 2013 -0800
+++ b/jdk/src/share/native/sun/font/layout/StateTables.h Tue Feb 26 10:07:26 2013 -0800
@@ -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;