OpenJDK / amber / amber
changeset 60001:82fe2f667c29
8236996: Incorrect Roboto font rendering on Windows with subpixel antialiasing
Reviewed-by: prr, serb
author | dbatrak |
---|---|
date | Mon, 27 Jan 2020 13:02:54 -0800 |
parents | ffcc3bd2b5da |
children | 2777408b8281 |
files | src/java.desktop/share/classes/sun/font/FileFontStrike.java src/java.desktop/share/classes/sun/font/TrueTypeFont.java src/java.desktop/windows/native/libfontmanager/lcdglyph.c |
diffstat | 3 files changed, 35 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/src/java.desktop/share/classes/sun/font/FileFontStrike.java Fri Jan 24 18:39:51 2020 -0800 +++ b/src/java.desktop/share/classes/sun/font/FileFontStrike.java Mon Jan 27 13:02:54 2020 -0800 @@ -328,7 +328,8 @@ 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 @@ 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 @@ 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); } }
--- a/src/java.desktop/share/classes/sun/font/TrueTypeFont.java Fri Jan 24 18:39:51 2020 -0800 +++ b/src/java.desktop/share/classes/sun/font/TrueTypeFont.java Mon Jan 27 13:02:54 2020 -0800 @@ -180,6 +180,15 @@ 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 @@ -537,11 +546,13 @@ 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:
--- a/src/java.desktop/windows/native/libfontmanager/lcdglyph.c Fri Jan 24 18:39:51 2020 -0800 +++ b/src/java.desktop/windows/native/libfontmanager/lcdglyph.c Mon Jan 27 13:02:54 2020 -0800 @@ -172,7 +172,8 @@ 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 @@ LPWSTR name; HFONT oldFont, hFont; MAT2 mat2; + DWORD actualFontDataSize; unsigned short width; unsigned short height; @@ -254,6 +256,17 @@ } 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;