diff --git a/src/share/classes/sun/font/FileFontStrike.java b/src/share/classes/sun/font/FileFontStrike.java index c66bcaf7411fed0c3dbab7b08b74a93c8fe09824..d423feb3258a3a114eb0f7dbe9a20e062647a29f 100644 --- a/src/share/classes/sun/font/FileFontStrike.java +++ b/src/share/classes/sun/font/FileFontStrike.java @@ -328,7 +328,8 @@ public class FileFontStrike extends PhysicalStrike { int style, int size, int glyphCode, - boolean fracMetrics); + boolean fracMetrics, + int fontDataSize); long getGlyphImageFromWindows(int glyphCode) { String family = fileFont.getFamilyName(null); @@ -337,7 +338,8 @@ public class FileFontStrike extends PhysicalStrike { int size = intPtSize; long ptr = _getGlyphImageFromWindows (family, style, size, glyphCode, - desc.fmHint == INTVAL_FRACTIONALMETRICS_ON); + desc.fmHint == INTVAL_FRACTIONALMETRICS_ON, + ((TrueTypeFont)fileFont).fontDataSize); if (ptr != 0) { /* Get the advance from the JDK rasterizer. This is mostly * necessary for the fractional metrics case, but there are @@ -351,6 +353,12 @@ public class FileFontStrike extends PhysicalStrike { advance); return ptr; } else { + if (FontUtilities.isLogging()) { + FontUtilities.getLogger().warning( + "Failed to render glyph using GDI: code=" + glyphCode + + ", fontFamily=" + family + ", style=" + style + + ", size=" + size); + } return fileFont.getGlyphImage(pScalerContext, glyphCode); } } diff --git a/src/share/classes/sun/font/TrueTypeFont.java b/src/share/classes/sun/font/TrueTypeFont.java index 8724c161b970ef69985893aa7ebb7303d9fd6194..544f78d20fa8881bc20115223ce69e97c7b87668 100644 --- a/src/share/classes/sun/font/TrueTypeFont.java +++ b/src/share/classes/sun/font/TrueTypeFont.java @@ -172,6 +172,15 @@ public class TrueTypeFont extends FileFont { private String localeFamilyName; private String localeFullName; + /* + * Used on Windows to validate the font selected by GDI for (sub-pixel + * antialiased) rendering. For 'standalone' fonts it's equal to the font + * file size, for collection (TTC, OTC) members it's the number of bytes in + * the collection file from the start of this font's offset table till the + * end of the file. + */ + int fontDataSize; + public TrueTypeFont(String platname, Object nativeNames, int fIndex, boolean javaRasterizer) throws FontFormatException @@ -529,11 +538,13 @@ public class TrueTypeFont extends FileFont { fontIndex = fIndex; buffer = readBlock(TTCHEADERSIZE+4*fIndex, 4); headerOffset = buffer.getInt(); + fontDataSize = Math.max(0, fileSize - headerOffset); break; case v1ttTag: case trueTag: case ottoTag: + fontDataSize = fileSize; break; default: diff --git a/src/windows/native/sun/font/lcdglyph.c b/src/windows/native/sun/font/lcdglyph.c index d940e8cb468ff52174d975a19f92eb6839bd7e9c..c63d96c301cd451223f89dbf12a8dfc05678f7a8 100644 --- a/src/windows/native/sun/font/lcdglyph.c +++ b/src/windows/native/sun/font/lcdglyph.c @@ -172,7 +172,8 @@ JNIEXPORT jboolean JNICALL JNIEXPORT jlong JNICALL Java_sun_font_FileFontStrike__1getGlyphImageFromWindows (JNIEnv *env, jobject unused, - jstring fontFamily, jint style, jint size, jint glyphCode, jboolean fm) { + jstring fontFamily, jint style, jint size, jint glyphCode, jboolean fm, + jint fontDataSize) { GLYPHMETRICS glyphMetrics; LOGFONTW lf; @@ -188,6 +189,7 @@ Java_sun_font_FileFontStrike__1getGlyphImageFromWindows LPWSTR name; HFONT oldFont, hFont; MAT2 mat2; + DWORD actualFontDataSize; unsigned short width; unsigned short height; @@ -254,6 +256,17 @@ Java_sun_font_FileFontStrike__1getGlyphImageFromWindows } oldFont = SelectObject(hMemoryDC, hFont); + if (fontDataSize > 0) { + // GDI doesn't allow to select a specific font file for drawing, we can + // only check that it picks the file we need by validating font size. + // If it doesn't match, we cannot proceed, as the same glyph code can + // correspond to a completely different glyph in the selected font. + actualFontDataSize = GetFontData(hMemoryDC, 0, 0, NULL, 0); + if (actualFontDataSize != fontDataSize) { + FREE_AND_RETURN; + } + } + tmpBitmap = CreateCompatibleBitmap(hDesktopDC, 1, 1); if (tmpBitmap == NULL) { FREE_AND_RETURN;