Description: Problem ======= On OpenJDK JRE and using some TrueType font, JasperReports does not display text element which height is just the same as the font size eg. { height="8", size="8", font="IPA mincho" }. JasperReports checks the text size before drawing the text elements. If (ascent + descent) of text is greater than the height of text element, this text is not drawn. In above case, Sun Java returns the same height (ascent + descent = fontsize), but OpenJDK returns the text height greater than font size, so not drawn. Sample code (includes Japanese char) =================================== import java.awt.Font; import java.awt.font.FontRenderContext; import java.awt.font.TextLayout; public class JavaApplication1 { public static void main(String[] args) throws Exception { Font f = new Font("IPA明朝",Font.PLAIN, 8); TextLayout layout = new TextLayout("IPA明朝", f, new FontRenderContext(null, true, true)); System.out.println("Ascent: " + layout.getAscent()); System.out.println("Descent: " + layout.getDescent()); } } Result of this code =================== Sun Java 6 (sun-java6-jre 6.26-0squeeze1) > Ascent: 7.0390625 > Descent: 0.9609375 OpenJDK 6 (openjdk-6-jre 6b24~pre2-1) > Ascent: 7.046875 > Descent: 0.96875 OpenJDK 7 (openjdk-7-jre 7~b147-2.0-1) > Ascent: 7.046875 > Descent: 0.96875 Sun Java returns correct height, but OpenJDK returns greater value than Sun's. Analysis of Source code ======================= In OpenJDK6/7 native method sun.font.FreetypeFontScaler.getFontMetricsNative(): jdk/src/share/native/sun/font/freetypeScaler.c >JNIEXPORT jobject JNICALL >Java_sun_font_FreetypeFontScaler_getFontMetricsNative( > JNIEnv *env, jobject scaler, jobject font2D, > jlong pScalerContext, jlong pScaler) { (snip) > /* ascent */ > ax = 0; > ay = -(jfloat) FT26Dot6ToFloat(FT_MulFix( > ((jlong) scalerInfo->face->ascender + bmodifier/2), > (jlong) scalerInfo->face->size->metrics.y_scale)); > /* descent */ > dx = 0; > dy = -(jfloat) FT26Dot6ToFloat(FT_MulFix( > ((jlong) scalerInfo->face->descender + bmodifier/2), > (jlong) scalerInfo->face->size->metrics.y_scale)); (snip) > metrics = (*env)->NewObject(env, > sunFontIDs.strikeMetricsClass, > sunFontIDs.strikeMetricsCtr, > ax, ay, dx, dy, bx, by, lx, ly, mx, my); > > return metrics; >} This code uses FT_MulFix to convert size. But FT_MulFix sometimes rounds up and loses precision. In FreeType2's FT_MulFix: freetype-2.4.8/src/base/ftcalc.c > c = (FT_Long)( ( (FT_Int64)a * b + 0x8000L ) >> 16 ); If both ascent and descent are rounded up, (ascent + descent) is greater than original height. In the sample case (IPA mincho font), bmodifier = 0 scalerInfo->face->ascender = 1802L scalerInfo->face->descender = -246L scalerInfo->face->size->metrics.y_scale = 16384L In this case, 1802 mod 4 = 2 and 246 mod 4 = 2, so both are rounded up. This causes (ay + dy) > font-size. (Note: (Sun) 1802.0/256.0 = 7.0390625, (OpenJDK) 1804.0/256.0 = 7.046875) Suggested fix ============= Fix to keep the precision in the font metrics conversion in Java_sun_font_FreetypeFontScaler_getFontMetricsNative(). Author: Nobuhiro Ban Bug-Debian: http://bugs.debian.org/657854 --- openjdk/jdk/src/share/native/sun/font/freetypeScaler.c +++ openjdk/jdk/src/share/native/sun/font/freetypeScaler.c @@ -488,14 +488,15 @@ /**** Note: only some metrics are affected by styling ***/ +#define FT_MulFixFloatShift6(a, b) (((float) (a)) * ((float) (b)) / 65536.0 / 64.0) /* ascent */ ax = 0; - ay = -(jfloat) FT26Dot6ToFloat(FT_MulFix( + ay = -(jfloat) (FT_MulFixFloatShift6( ((jlong) scalerInfo->face->ascender + bmodifier/2), (jlong) scalerInfo->face->size->metrics.y_scale)); /* descent */ dx = 0; - dy = -(jfloat) FT26Dot6ToFloat(FT_MulFix( + dy = -(jfloat) (FT_MulFixFloatShift6( ((jlong) scalerInfo->face->descender + bmodifier/2), (jlong) scalerInfo->face->size->metrics.y_scale)); /* baseline */ @@ -503,7 +504,7 @@ /* leading */ lx = 0; - ly = (jfloat) FT26Dot6ToFloat(FT_MulFix( + ly = (jfloat) (FT_MulFixFloatShift6( (jlong) scalerInfo->face->height + bmodifier, (jlong) scalerInfo->face->size->metrics.y_scale)) + ay - dy;