-
Bug
-
Resolution: Fixed
-
P3
-
1.4.0
-
beta3
-
x86
-
windows_98
Name: bsT130419 Date: 09/18/2001
java version "1.4.0-beta2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta2-b77)
Java HotSpot(TM) Client VM (build 1.4.0-beta2-b77, mixed mode)
Some interaction among font width measurements among different fonts
is provoking the following:
Assertion failed: (int)offset == offset1, file ../../../src/share/native/sun/awt
/font/fontmanager/fontobjects/fontObject.cpp, line 475
This started with JDK1.4beta2; the exact same code runs fine in 1.4beta1 and
earlier.
The problem comes with switching fonts, as the same methods
(create a font with Font.createFont(), query for Font.charWidth())
work fine in isolation. The problem is very sensitive to the exact
sequence. As shown in the source code below, slight changes to the
sequence prevents or provokes the crash. In general use displaying
documents with various fonts, such problematic sequences happen
regularly.
I have packaged source code and fonts that generate the failure
at http://www.cs.berkeley.edu/~phelps/fontObjFail.zip,
available until copied over by Sun. To generate the error,
unpack the .zip, and type "java -classpath . AssertFail".
A couple of the fonts in the .zip have been edited. Initially, they were
missing glyphs at a character code, but that character was available
at the wrong code, so it was copied over. Thus, perhaps some table
is not as regular as usual and the font handling code should handle
this less common but still correct case. On the other hand, the assertion
fails only after switching fonts, and the case works in isolation.
import java.awt.*;
import java.io.InputStream;
import java.io.FileInputStream;
public class AssertFail extends Frame {
public static void main(String[] argv) throws Exception {
AssertFail f = new AssertFail();
f.setBounds(100,100, 200,200);
f.setVisible(true);
}
public void paint(Graphics g) {
String[] fsc = {
"cmr12 16.0 175", // DELETE ANY TUPLE AND NO CRASH
"cmmi12 16.0 175",
//"cmr12 16.0 54", // INSERT THIS LINE AND NO CRASH
"cmmi8 10.666667 69",
"cmsy8 10.666667 163",
"cmr8 10.666667 50",
"cmex10 13.333333 32",
"cmr12 16.0 54",
"cmmi12 16.0 188" // goes BOOM here -- remove and no crash
};
Font f=null;
FontMetrics fm=null;
Font[] fcache=new Font[256]; int cachei=0;
FontMetrics[] fmcache=new FontMetrics[256];
int w = 0;
for (int ti=0,timax=fsc.length; ti<timax; ti++) {
String tuple = fsc[ti];
// 1. select font
int x1=tuple.indexOf(' '), x2=tuple.indexOf(' ', x1+1);
String family=tuple.substring(0,x1); float size =
Float.parseFloat(tuple.substring(x1+1,x2));
boolean fcached = false;
for (int i=0; i<cachei; i++) {
f = fcache[i];
if (family.equals(f.getFamily()) && Math.abs(size -
f.getSize2D()) < 0.01) {
fm = fmcache[i];
fcached = true;
break;
}
}
if (!fcached) try {
InputStream fin = new FileInputStream
(/*"d:/prj/Multivalent/www/jar/dvi/fonts/"+*/family+".ttf");
f = Font.createFont(Font.TRUETYPE_FONT, fin);
fin.close();
//f = new Font(f.getFamily(), Font.PLAIN, (int)
size); // doesn't matter if use constructor or deriveFont(size)
f = f.deriveFont(size); // doesn't matter if scale
font (and remove "size - f.getSize2D()" above)
fcache[cachei] = f; // HAVE TO CACHE FONT OR NO
CRASH -- if Font.createFont() every time, no crash
//fm = fmcache[cachei] = g.getFontMetrics(f); // can
cache FontMetrics or create below, doesn't matter to crashing
cachei++;
} catch (Exception e) { System.out.println("problem: "+e); }
fm = g.getFontMetrics(f); // uses deprecated method, but
same if use Graphics.getFontMetrics(Font)
// 2. take charWidth
int c = Integer.parseInt(tuple.substring(x2+1));
w += fm.charWidth((char)c); // crashes here after
*sequence* of fonts and characters
g.setColor(Color.BLACK);
g.setFont(f);
g.drawString(String.valueOf((char)c), 10+w, 20);
System.out.println(""+(char)c+"/"+c+" "+fm.charWidth(c)+" "+f.getFamily()
+"/"+f.getSize2D());
}
System.out.println("w="+w);
}
}
(Review ID: 131440)
======================================================================