提交 5126da46 编写于 作者: P prr

8012617: ArrayIndexOutOfBoundsException with some fonts using LineBreakMeasurer

Reviewed-by: bae, srl
上级 7fa33389
...@@ -247,6 +247,10 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La ...@@ -247,6 +247,10 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La
float aw = 0f; float aw = 0f;
float ah = cm.ascent + cm.descent; float ah = cm.ascent + cm.descent;
if (charinfo == null || charinfo.length == 0) {
return new Rectangle2D.Float(al, at, aw, ah);
}
boolean lineIsLTR = (source.getLayoutFlags() & 0x8) == 0; boolean lineIsLTR = (source.getLayoutFlags() & 0x8) == 0;
int rn = info.length - numvals; int rn = info.length - numvals;
if (lineIsLTR) { if (lineIsLTR) {
...@@ -350,24 +354,42 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La ...@@ -350,24 +354,42 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La
public float getCharX(int index) { public float getCharX(int index) {
validate(index); validate(index);
return getCharinfo()[l2v(index) * numvals + posx]; float[] charinfo = getCharinfo();
int idx = l2v(index) * numvals + posx;
if (charinfo == null || idx >= charinfo.length) {
return 0f;
} else {
return charinfo[idx];
}
} }
public float getCharY(int index) { public float getCharY(int index) {
validate(index); validate(index);
return getCharinfo()[l2v(index) * numvals + posy]; float[] charinfo = getCharinfo();
int idx = l2v(index) * numvals + posy;
if (charinfo == null || idx >= charinfo.length) {
return 0f;
} else {
return charinfo[idx];
}
} }
public float getCharAdvance(int index) { public float getCharAdvance(int index) {
validate(index); validate(index);
return getCharinfo()[l2v(index) * numvals + advx]; float[] charinfo = getCharinfo();
int idx = l2v(index) * numvals + advx;
if (charinfo == null || idx >= charinfo.length) {
return 0f;
} else {
return charinfo[idx];
}
} }
public Rectangle2D handleGetCharVisualBounds(int index) { public Rectangle2D handleGetCharVisualBounds(int index) {
validate(index); validate(index);
float[] charinfo = getCharinfo(); float[] charinfo = getCharinfo();
index = l2v(index) * numvals; index = l2v(index) * numvals;
if ((index+vish) >= charinfo.length) { if (charinfo == null || (index+vish) >= charinfo.length) {
return new Rectangle2D.Float(); return new Rectangle2D.Float();
} }
return new Rectangle2D.Float( return new Rectangle2D.Float(
...@@ -463,7 +485,7 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La ...@@ -463,7 +485,7 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La
if (cidx >= charinfo.length) { if (cidx >= charinfo.length) {
break; // layout bailed for some reason break; // layout bailed for some reason
} }
float adv = charinfo[l2v(start) * numvals + advx]; float adv = charinfo[cidx];
width -= adv; width -= adv;
} }
...@@ -512,7 +534,13 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La ...@@ -512,7 +534,13 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La
// } // }
//} //}
return getCharinfo()[v * numvals + advx] != 0; int idx = v * numvals + advx;
float[] charinfo = getCharinfo();
if (charinfo == null || idx >= charinfo.length) {
return false;
} else {
return charinfo[idx] != 0;
}
} }
private final float[] getCharinfo() { private final float[] getCharinfo() {
...@@ -604,6 +632,9 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La ...@@ -604,6 +632,9 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La
*/ */
int numGlyphs = gv.getNumGlyphs(); int numGlyphs = gv.getNumGlyphs();
if (numGlyphs == 0) {
return glyphinfo;
}
int[] indices = gv.getGlyphCharIndices(0, numGlyphs, null); int[] indices = gv.getGlyphCharIndices(0, numGlyphs, null);
boolean DEBUG = false; boolean DEBUG = false;
......
...@@ -464,7 +464,12 @@ public final class GlyphLayout { ...@@ -464,7 +464,12 @@ public final class GlyphLayout {
break; break;
} }
catch (IndexOutOfBoundsException e) { catch (IndexOutOfBoundsException e) {
_gvdata.grow(); if (_gvdata._count >=0) {
_gvdata.grow();
}
}
if (_gvdata._count < 0) {
break;
} }
} }
} }
...@@ -473,7 +478,19 @@ public final class GlyphLayout { ...@@ -473,7 +478,19 @@ public final class GlyphLayout {
// _gvdata.adjustPositions(txinfo.invdtx); // _gvdata.adjustPositions(txinfo.invdtx);
// } // }
StandardGlyphVector gv = _gvdata.createGlyphVector(font, frc, result); // If layout fails (negative glyph count) create an un-laid out GV instead.
// ie default positions. This will be a lot better than the alternative of
// a complete blank layout.
StandardGlyphVector gv;
if (_gvdata._count < 0) {
gv = new StandardGlyphVector(font, text, offset, count, frc);
if (FontUtilities.debugFonts()) {
FontUtilities.getLogger().warning("OpenType layout failed on font: " +
font);
}
} else {
gv = _gvdata.createGlyphVector(font, frc, result);
}
// System.err.println("Layout returns: " + gv); // System.err.println("Layout returns: " + gv);
return gv; return gv;
} }
......
...@@ -218,6 +218,9 @@ le_uint32 ContextualSubstitutionFormat1Subtable::process(const LookupProcessor * ...@@ -218,6 +218,9 @@ le_uint32 ContextualSubstitutionFormat1Subtable::process(const LookupProcessor *
LEGlyphID glyph = glyphIterator->getCurrGlyphID(); LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success); le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
if (LE_FAILURE(success)) {
return 0;
}
if (coverageIndex >= 0) { if (coverageIndex >= 0) {
le_uint16 srSetCount = SWAPW(subRuleSetCount); le_uint16 srSetCount = SWAPW(subRuleSetCount);
...@@ -267,6 +270,9 @@ le_uint32 ContextualSubstitutionFormat2Subtable::process(const LookupProcessor * ...@@ -267,6 +270,9 @@ le_uint32 ContextualSubstitutionFormat2Subtable::process(const LookupProcessor *
LEGlyphID glyph = glyphIterator->getCurrGlyphID(); LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success); le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
if (LE_FAILURE(success)) {
return 0;
}
if (coverageIndex >= 0) { if (coverageIndex >= 0) {
const ClassDefinitionTable *classDefinitionTable = const ClassDefinitionTable *classDefinitionTable =
...@@ -395,6 +401,9 @@ le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupPro ...@@ -395,6 +401,9 @@ le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupPro
LEGlyphID glyph = glyphIterator->getCurrGlyphID(); LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success); le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
if (LE_FAILURE(success)) {
return 0;
}
if (coverageIndex >= 0) { if (coverageIndex >= 0) {
le_uint16 srSetCount = SWAPW(chainSubRuleSetCount); le_uint16 srSetCount = SWAPW(chainSubRuleSetCount);
...@@ -466,6 +475,9 @@ le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupPro ...@@ -466,6 +475,9 @@ le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupPro
LEGlyphID glyph = glyphIterator->getCurrGlyphID(); LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success); le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
if (LE_FAILURE(success)) {
return 0;
}
if (coverageIndex >= 0) { if (coverageIndex >= 0) {
const ClassDefinitionTable *backtrackClassDefinitionTable = const ClassDefinitionTable *backtrackClassDefinitionTable =
......
...@@ -45,7 +45,7 @@ le_uint32 CursiveAttachmentSubtable::process(const LEReferenceTo<CursiveAttachme ...@@ -45,7 +45,7 @@ le_uint32 CursiveAttachmentSubtable::process(const LEReferenceTo<CursiveAttachme
le_int32 coverageIndex = getGlyphCoverage(base, glyphID, success); le_int32 coverageIndex = getGlyphCoverage(base, glyphID, success);
le_uint16 eeCount = SWAPW(entryExitCount); le_uint16 eeCount = SWAPW(entryExitCount);
if (coverageIndex < 0 || coverageIndex >= eeCount) { if (coverageIndex < 0 || coverageIndex >= eeCount || LE_FAILURE(success)) {
glyphIterator->setCursiveGlyph(); glyphIterator->setCursiveGlyph();
return 0; return 0;
} }
......
...@@ -44,10 +44,10 @@ U_NAMESPACE_BEGIN ...@@ -44,10 +44,10 @@ U_NAMESPACE_BEGIN
#define READ_LONG(code) (le_uint32)((SWAPW(*(le_uint16*)&code) << 16) + SWAPW(*(((le_uint16*)&code) + 1))) #define READ_LONG(code) (le_uint32)((SWAPW(*(le_uint16*)&code) << 16) + SWAPW(*(((le_uint16*)&code) + 1)))
// FIXME: should look at the format too... maybe have a sub-class for it? // FIXME: should look at the format too... maybe have a sub-class for it?
le_uint32 ExtensionSubtable::process(const LookupProcessor *lookupProcessor, le_uint16 lookupType, le_uint32 ExtensionSubtable::process(const LEReferenceTo<ExtensionSubtable> &thisRef,
const LookupProcessor *lookupProcessor, le_uint16 lookupType,
GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const
{ {
const LEReferenceTo<ExtensionSubtable> thisRef(lookupProcessor->getReference(), success); // create a reference to this
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return 0; return 0;
...@@ -57,7 +57,7 @@ le_uint32 ExtensionSubtable::process(const LookupProcessor *lookupProcessor, le_ ...@@ -57,7 +57,7 @@ le_uint32 ExtensionSubtable::process(const LookupProcessor *lookupProcessor, le_
if (elt != lookupType) { if (elt != lookupType) {
le_uint32 extOffset = READ_LONG(extensionOffset); le_uint32 extOffset = READ_LONG(extensionOffset);
LEReferenceTo<LookupSubtable> subtable(thisRef, success, extOffset); LEReferenceTo<LookupSubtable> subtable(thisRef, success, extOffset);
if(LE_SUCCESS(success)) { if(LE_SUCCESS(success)) {
return lookupProcessor->applySubtable(subtable, elt, glyphIterator, fontInstance, success); return lookupProcessor->applySubtable(subtable, elt, glyphIterator, fontInstance, success);
......
...@@ -52,7 +52,8 @@ struct ExtensionSubtable //: GlyphSubstitutionSubtable ...@@ -52,7 +52,8 @@ struct ExtensionSubtable //: GlyphSubstitutionSubtable
le_uint16 extensionLookupType; le_uint16 extensionLookupType;
le_uint32 extensionOffset; le_uint32 extensionOffset;
le_uint32 process(const LookupProcessor *lookupProcessor, le_uint16 lookupType, le_uint32 process(const LEReferenceTo<ExtensionSubtable> &extRef,
const LookupProcessor *lookupProcessor, le_uint16 lookupType,
GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const; GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
}; };
......
...@@ -168,7 +168,7 @@ le_uint32 GlyphPositioningLookupProcessor::applySubtable(const LEReferenceTo<Loo ...@@ -168,7 +168,7 @@ le_uint32 GlyphPositioningLookupProcessor::applySubtable(const LEReferenceTo<Loo
{ {
LEReferenceTo<ExtensionSubtable> subtable(lookupSubtable, success); LEReferenceTo<ExtensionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, lookupType, glyphIterator, fontInstance, success); delta = subtable->process(subtable, this, lookupType, glyphIterator, fontInstance, success);
break; break;
} }
......
...@@ -139,7 +139,7 @@ le_uint32 GlyphSubstitutionLookupProcessor::applySubtable(const LEReferenceTo<Lo ...@@ -139,7 +139,7 @@ le_uint32 GlyphSubstitutionLookupProcessor::applySubtable(const LEReferenceTo<Lo
{ {
const LEReferenceTo<ExtensionSubtable> subtable(lookupSubtable, success); const LEReferenceTo<ExtensionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, lookupType, glyphIterator, fontInstance, success); delta = subtable->process(subtable, this, lookupType, glyphIterator, fontInstance, success);
break; break;
} }
......
...@@ -45,6 +45,10 @@ le_uint32 LigatureSubstitutionSubtable::process(const LETableReference &base, Gl ...@@ -45,6 +45,10 @@ le_uint32 LigatureSubstitutionSubtable::process(const LETableReference &base, Gl
LEGlyphID glyph = glyphIterator->getCurrGlyphID(); LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(base, glyph, success); le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
if (LE_FAILURE(success)) {
return 0;
}
if (coverageIndex >= 0) { if (coverageIndex >= 0) {
Offset ligSetTableOffset = SWAPW(ligSetTableOffsetArray[coverageIndex]); Offset ligSetTableOffset = SWAPW(ligSetTableOffsetArray[coverageIndex]);
const LigatureSetTable *ligSetTable = (const LigatureSetTable *) ((char *) this + ligSetTableOffset); const LigatureSetTable *ligSetTable = (const LigatureSetTable *) ((char *) this + ligSetTableOffset);
......
...@@ -56,6 +56,10 @@ le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, Gl ...@@ -56,6 +56,10 @@ le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, Gl
LEGlyphID markGlyph = glyphIterator->getCurrGlyphID(); LEGlyphID markGlyph = glyphIterator->getCurrGlyphID();
le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success); le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success);
if (LE_FAILURE(success)) {
return 0;
}
if (markCoverage < 0) { if (markCoverage < 0) {
// markGlyph isn't a covered mark glyph // markGlyph isn't a covered mark glyph
return 0; return 0;
......
...@@ -55,6 +55,10 @@ le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base ...@@ -55,6 +55,10 @@ le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base
LEGlyphID markGlyph = glyphIterator->getCurrGlyphID(); LEGlyphID markGlyph = glyphIterator->getCurrGlyphID();
le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success); le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success);
if (LE_FAILURE(success)) {
return 0;
}
if (markCoverage < 0) { if (markCoverage < 0) {
// markGlyph isn't a covered mark glyph // markGlyph isn't a covered mark glyph
return 0; return 0;
......
...@@ -56,6 +56,10 @@ le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, Gl ...@@ -56,6 +56,10 @@ le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, Gl
LEGlyphID markGlyph = glyphIterator->getCurrGlyphID(); LEGlyphID markGlyph = glyphIterator->getCurrGlyphID();
le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success); le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success);
if (LE_FAILURE(success)) {
return 0;
}
if (markCoverage < 0) { if (markCoverage < 0) {
// markGlyph isn't a covered mark glyph // markGlyph isn't a covered mark glyph
return 0; return 0;
......
...@@ -61,6 +61,10 @@ le_uint32 MultipleSubstitutionSubtable::process(const LETableReference &base, Gl ...@@ -61,6 +61,10 @@ le_uint32 MultipleSubstitutionSubtable::process(const LETableReference &base, Gl
le_int32 coverageIndex = getGlyphCoverage(base, glyph, success); le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
le_uint16 seqCount = SWAPW(sequenceCount); le_uint16 seqCount = SWAPW(sequenceCount);
if (LE_FAILURE(success)) {
return 0;
}
if (coverageIndex >= 0 && coverageIndex < seqCount) { if (coverageIndex >= 0 && coverageIndex < seqCount) {
Offset sequenceTableOffset = SWAPW(sequenceTableOffsetArray[coverageIndex]); Offset sequenceTableOffset = SWAPW(sequenceTableOffsetArray[coverageIndex]);
const SequenceTable *sequenceTable = (const SequenceTable *) ((char *) this + sequenceTableOffset); const SequenceTable *sequenceTable = (const SequenceTable *) ((char *) this + sequenceTableOffset);
......
...@@ -126,6 +126,11 @@ le_uint32 PairPositioningFormat2Subtable::process(const LEReferenceTo<PairPositi ...@@ -126,6 +126,11 @@ le_uint32 PairPositioningFormat2Subtable::process(const LEReferenceTo<PairPositi
{ {
LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID(); LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(base, firstGlyph, success); le_int32 coverageIndex = getGlyphCoverage(base, firstGlyph, success);
if (LE_FAILURE(success)) {
return 0;
}
GlyphIterator tempIterator(*glyphIterator); GlyphIterator tempIterator(*glyphIterator);
if (coverageIndex >= 0 && glyphIterator->next()) { if (coverageIndex >= 0 && glyphIterator->next()) {
......
...@@ -70,6 +70,9 @@ le_uint32 SinglePositioningFormat1Subtable::process(const LEReferenceTo<SinglePo ...@@ -70,6 +70,9 @@ le_uint32 SinglePositioningFormat1Subtable::process(const LEReferenceTo<SinglePo
{ {
LEGlyphID glyph = glyphIterator->getCurrGlyphID(); LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(base, glyph, success); le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
if (LE_FAILURE(success)) {
return 0;
}
if (coverageIndex >= 0) { if (coverageIndex >= 0) {
valueRecord.adjustPosition(SWAPW(valueFormat), (const char *) this, *glyphIterator, fontInstance); valueRecord.adjustPosition(SWAPW(valueFormat), (const char *) this, *glyphIterator, fontInstance);
...@@ -84,6 +87,9 @@ le_uint32 SinglePositioningFormat2Subtable::process(const LEReferenceTo<SinglePo ...@@ -84,6 +87,9 @@ le_uint32 SinglePositioningFormat2Subtable::process(const LEReferenceTo<SinglePo
{ {
LEGlyphID glyph = glyphIterator->getCurrGlyphID(); LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int16 coverageIndex = (le_int16) getGlyphCoverage(base, glyph, success); le_int16 coverageIndex = (le_int16) getGlyphCoverage(base, glyph, success);
if (LE_FAILURE(success)) {
return 0;
}
if (coverageIndex >= 0) { if (coverageIndex >= 0) {
valueRecordArray[0].adjustPosition(coverageIndex, SWAPW(valueFormat), (const char *) this, *glyphIterator, fontInstance); valueRecordArray[0].adjustPosition(coverageIndex, SWAPW(valueFormat), (const char *) this, *glyphIterator, fontInstance);
......
...@@ -69,6 +69,9 @@ le_uint32 SingleSubstitutionFormat1Subtable::process(const LEReferenceTo<SingleS ...@@ -69,6 +69,9 @@ le_uint32 SingleSubstitutionFormat1Subtable::process(const LEReferenceTo<SingleS
{ {
LEGlyphID glyph = glyphIterator->getCurrGlyphID(); LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(base, glyph, success); le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
if (LE_FAILURE(success)) {
return 0;
}
if (coverageIndex >= 0) { if (coverageIndex >= 0) {
TTGlyphID substitute = ((TTGlyphID) LE_GET_GLYPH(glyph)) + SWAPW(deltaGlyphID); TTGlyphID substitute = ((TTGlyphID) LE_GET_GLYPH(glyph)) + SWAPW(deltaGlyphID);
...@@ -87,6 +90,9 @@ le_uint32 SingleSubstitutionFormat2Subtable::process(const LEReferenceTo<SingleS ...@@ -87,6 +90,9 @@ le_uint32 SingleSubstitutionFormat2Subtable::process(const LEReferenceTo<SingleS
{ {
LEGlyphID glyph = glyphIterator->getCurrGlyphID(); LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(base, glyph, success); le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
if (LE_FAILURE(success)) {
return 0;
}
if (coverageIndex >= 0) { if (coverageIndex >= 0) {
TTGlyphID substitute = SWAPW(substituteArray[coverageIndex]); TTGlyphID substitute = SWAPW(substituteArray[coverageIndex]);
......
...@@ -203,16 +203,19 @@ JNIEXPORT void JNICALL Java_sun_font_SunLayoutEngine_nativeLayout ...@@ -203,16 +203,19 @@ JNIEXPORT void JNICALL Java_sun_font_SunLayoutEngine_nativeLayout
getFloat(env, pt, x, y); getFloat(env, pt, x, y);
jboolean rtl = (typo_flags & TYPO_RTL) != 0; jboolean rtl = (typo_flags & TYPO_RTL) != 0;
int glyphCount = engine->layoutChars(chars, start - min, limit - start, len, rtl, x, y, success); int glyphCount = engine->layoutChars(chars, start - min, limit - start, len, rtl, x, y, success);
// fprintf(stderr, "sle nl len %d -> gc: %d\n", len, glyphCount); fflush(stderr); // fprintf(stderr, "sle nl len %d -> gc: %d\n", len, glyphCount); fflush(stderr);
engine->getGlyphPosition(glyphCount, x, y, success); engine->getGlyphPosition(glyphCount, x, y, success);
// fprintf(stderr, "layout glyphs: %d x: %g y: %g\n", glyphCount, x, y); fflush(stderr); // fprintf(stderr, "layout glyphs: %d x: %g y: %g\n", glyphCount, x, y); fflush(stderr);
if (LE_FAILURE(success)) {
if (putGV(env, gmask, baseIndex, gvdata, engine, glyphCount)) { env->SetIntField(gvdata, gvdCountFID, -1); // flag failure
// !!! hmmm, could use current value in positions array of GVData... } else {
putFloat(env, pt, x, y); if (putGV(env, gmask, baseIndex, gvdata, engine, glyphCount)) {
} // !!! hmmm, could use current value in positions array of GVData...
putFloat(env, pt, x, y);
}
}
if (chars != buffer) { if (chars != buffer) {
free(chars); free(chars);
......
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* 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.
*
* 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.
*/
/*
* @test
* @bug 8012617
* @summary ArrayIndexOutOfBoundsException in LineBreakMeasurer
*/
import java.awt.*;
import java.awt.image.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.text.*;
import java.util.Hashtable;
public class AllFontsLBM {
public static void main(String[] args) {
Font[] allFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
for (int i=0;i<allFonts.length; i++) {
try {
Font f = allFonts[i].deriveFont(Font.PLAIN, 20);
if ( f.getFontName().startsWith("HiraKaku") ) {
continue;
}
System.out.println("Try : " + f.getFontName());
System.out.flush();
breakLines(f);
} catch (Exception e) {
System.out.println(allFonts[i]);
}
}
}
static void breakLines(Font font) {
AttributedString vanGogh = new AttributedString(
"Many people believe that Vincent van Gogh painted his best works " +
"during the two-year period he spent in Provence. Here is where he " +
"painted The Starry Night--which some consider to be his greatest " +
"work of all. However, as his artistic brilliance reached new " +
"heights in Provence, his physical and mental health plummeted. ",
new Hashtable());
vanGogh.addAttribute(TextAttribute.FONT, font);
BufferedImage bi = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bi.createGraphics();
AttributedCharacterIterator aci = vanGogh.getIterator();
FontRenderContext frc = new FontRenderContext(null, false, false);
LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc);
lbm.setPosition(aci.getBeginIndex());
while (lbm.getPosition() < aci.getEndIndex()) {
lbm.nextLayout(100f);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册