-
Bug
-
Resolution: Unresolved
-
P4
-
13, 14, 15, 16
-
x86_64
-
linux
ADDITIONAL SYSTEM INFORMATION :
Tested using the Java 11 build distributed with ArchLinux, and using a Oracle OpenJDK 16
build (though this also appeared in ArchLinux's default OpenJDK 15 build):
IMPLEMENTOR="Oracle Corporation"
JAVA_VERSION="16"
JAVA_VERSION_DATE="2021-03-16"
LIBC="gnu"
MODULES="java.base java.compiler java.datatransfer java.xml java.prefs java.desktop java.instrument java.logging java.management java.security.sasl java.naming java.rmi java.management.rmi java.net.http java.scripting java.security.jgss java.transaction.xa java.sql java.sql.rowset java.xml.crypto java.se java.smartcardio jdk.accessibility jdk.internal.jvmstat jdk.attach jdk.charsets jdk.compiler jdk.crypto.ec jdk.crypto.cryptoki jdk.dynalink jdk.internal.ed jdk.editpad jdk.hotspot.agent jdk.httpserver jdk.incubator.foreign jdk.incubator.vector jdk.internal.le jdk.internal.opt jdk.internal.vm.ci jdk.jartool jdk.javadoc jdk.jcmd jdk.management jdk.management.agent jdk.jconsole jdk.jdeps jdk.jdwp.agent jdk.jdi jdk.jfr jdk.jlink jdk.jpackage jdk.jshell jdk.jsobject jdk.jstatd jdk.localedata jdk.management.jfr jdk.naming.dns jdk.naming.rmi jdk.net jdk.nio.mapmode jdk.sctp jdk.security.auth jdk.security.jgss jdk.unsupported jdk.unsupported.desktop jdk.xml.dom jdk.zipfs"
OS_ARCH="x86_64"
OS_NAME="Linux"
SOURCE=".:git:4de3a6be9e60"
A DESCRIPTION OF THE PROBLEM :
Text in Swing UIs using the Dialog.plain font are rendered using a mixture of two fonts - one for latin text and
one for numbers. Unfortunately as this appears to be the default font, the effects are quite widespread in the
tested applications that don't set the font themselves.
An example of this rendering can be found here (I coundn't see any way to post images in the bug
report form): <CAPTURE1.PNG><ATTACHED> - while the example is in a table, this appears everywhere and not
just tables.
I've gone through this in a debugger and think I've found the cause:
The system default font as reported by fc-match is: DejaVuSans.ttf: "DejaVu Sans" "Book"
This font has a subfamily of 'Book' but the full name is still only "DejaVu Sans" (for comparison, the
bold variant has a subfamily of 'Bold' and it's included in the full name: "DejaVu Sans Bold"). Apparently
as a result of the subfamily font-config is producing the full name "DejaVu Sans Book".
Running fc-cat | grep 'DejaVu Sans Book' thus presents:
"DejaVuSans.ttf" 0 "DejaVu Sans:familylang=en:style=Book:stylelang=en:fullname=DejaVu Sans Book:<other font rendering information>
This then appears to make it's way into Java's font cache: ~/.java/fonts/16-ea/fcinfo-1-gearbox-Arch-rolling-en-NZ.properties
sansserif.3.3.file=/usr/share/fonts/TTF/DejaVuSans.ttf
sansserif.3.3.fullName=DejaVu Sans Book
This causes a problem in CompositeFont.java:296 which checks the full name loaded from the TrueType file matches
the corresponding name in the array passed to it's constructor:
} else if (!componentNames[slot].equalsIgnoreCase(name)) {
/* If a component specifies the file with a bad font,
* the corresponding slot will be initialized by
* default physical font. In such case findFont2D may
* return composite font which cannot be casted to
* physical font.
*/
This makes it's way to getDefaultPhysicalFont. Unfortunately the font in question *is* the default physical
font, and that causes SunFontManager.java:1042 to run:
if (defaultPhysicalFont == null) {
/* Because of the findFont2D call above, if we reach here, we
* know all fonts have already been loaded, just accept any
* match at this point. If this fails we are in real trouble
* and I don't know how to recover from there being absolutely
* no fonts anywhere on the system.
*/
defaultPhysicalFont = physicalFonts.values().stream().findFirst()
.orElseThrow(()->new Error("Probable fatal error: No physical fonts found."));
}
This ends up using "Noto Sans Devanagari UI Thin" as the default font, which contains arabic numerals
but no latin characters. Since this is inside a CompositeFont those characters will fall through to the next
font, which is "DejaVu Sans Bold" - the combination of thin and bold text leads to the visually jarring text
shown above.
Running "otfinfo /usr/share/fonts/TTF/DejaVuSans.ttf --info" shows that the 'Book' subfamily is not part
of the full name:
Family: DejaVu Sans
Subfamily: Book
Full name: DejaVu Sans
PostScript name: DejaVuSans
Preferred family: DejaVu Sans
Preferred subfamily: Book
Version: Version 2.37
Unique ID: DejaVu Sans
Manufacturer: DejaVu fonts team
Vendor URL: http://dejavu.sourceforge.net
Copyright: Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved.
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
DejaVu changes are in public domain
The SHA256 hash of this file is 2fb91d8d18b8312659070e66001a863b82fb6758a21e37df2c94f1cae83683ed.
Testing shows the following values are showing up to the CompositeFont constructor:
Java 11:
CompositeFont.component{File}Names start withs "/usr/share/fonts/TTF/DejaVuSans.ttf" and "DejaVu Sans"
Java 16:
CompositeFont.component{File}Names start withs "/usr/share/fonts/TTF/DejaVuSans.ttf" and "DejaVu Sans Book"
CompositeFont.java:296 - componentNames[slot]="DejaVu Sans Book" while name="DejaVu Sans"
This appears to be caused byJDK-8219901, which uses the full names rather than the family names of fonts.
REGRESSION : Last worked in version 11
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Set DejaVu as the default system font on Linux - this is the default with ArchLinux and KDE.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Text should render using the selected default system font.
ACTUAL -
The characters are rendered using two different versions of the system fault: <CAPTURE2.PNG><ATTACHED>
---------- BEGIN SOURCE ----------
import javax.swing.*;
class Scratch {
public static void main(String[] args) {
JFrame frame = new JFrame("Hello World");
frame.setContentPane(new JTextArea("Testing 1234 test abc123"));
frame.pack();
frame.setVisible(true);
}
}
---------- END SOURCE ----------
FREQUENCY : always
Tested using the Java 11 build distributed with ArchLinux, and using a Oracle OpenJDK 16
build (though this also appeared in ArchLinux's default OpenJDK 15 build):
IMPLEMENTOR="Oracle Corporation"
JAVA_VERSION="16"
JAVA_VERSION_DATE="2021-03-16"
LIBC="gnu"
MODULES="java.base java.compiler java.datatransfer java.xml java.prefs java.desktop java.instrument java.logging java.management java.security.sasl java.naming java.rmi java.management.rmi java.net.http java.scripting java.security.jgss java.transaction.xa java.sql java.sql.rowset java.xml.crypto java.se java.smartcardio jdk.accessibility jdk.internal.jvmstat jdk.attach jdk.charsets jdk.compiler jdk.crypto.ec jdk.crypto.cryptoki jdk.dynalink jdk.internal.ed jdk.editpad jdk.hotspot.agent jdk.httpserver jdk.incubator.foreign jdk.incubator.vector jdk.internal.le jdk.internal.opt jdk.internal.vm.ci jdk.jartool jdk.javadoc jdk.jcmd jdk.management jdk.management.agent jdk.jconsole jdk.jdeps jdk.jdwp.agent jdk.jdi jdk.jfr jdk.jlink jdk.jpackage jdk.jshell jdk.jsobject jdk.jstatd jdk.localedata jdk.management.jfr jdk.naming.dns jdk.naming.rmi jdk.net jdk.nio.mapmode jdk.sctp jdk.security.auth jdk.security.jgss jdk.unsupported jdk.unsupported.desktop jdk.xml.dom jdk.zipfs"
OS_ARCH="x86_64"
OS_NAME="Linux"
SOURCE=".:git:4de3a6be9e60"
A DESCRIPTION OF THE PROBLEM :
Text in Swing UIs using the Dialog.plain font are rendered using a mixture of two fonts - one for latin text and
one for numbers. Unfortunately as this appears to be the default font, the effects are quite widespread in the
tested applications that don't set the font themselves.
An example of this rendering can be found here (I coundn't see any way to post images in the bug
report form): <CAPTURE1.PNG><ATTACHED> - while the example is in a table, this appears everywhere and not
just tables.
I've gone through this in a debugger and think I've found the cause:
The system default font as reported by fc-match is: DejaVuSans.ttf: "DejaVu Sans" "Book"
This font has a subfamily of 'Book' but the full name is still only "DejaVu Sans" (for comparison, the
bold variant has a subfamily of 'Bold' and it's included in the full name: "DejaVu Sans Bold"). Apparently
as a result of the subfamily font-config is producing the full name "DejaVu Sans Book".
Running fc-cat | grep 'DejaVu Sans Book' thus presents:
"DejaVuSans.ttf" 0 "DejaVu Sans:familylang=en:style=Book:stylelang=en:fullname=DejaVu Sans Book:<other font rendering information>
This then appears to make it's way into Java's font cache: ~/.java/fonts/16-ea/fcinfo-1-gearbox-Arch-rolling-en-NZ.properties
sansserif.3.3.file=/usr/share/fonts/TTF/DejaVuSans.ttf
sansserif.3.3.fullName=DejaVu Sans Book
This causes a problem in CompositeFont.java:296 which checks the full name loaded from the TrueType file matches
the corresponding name in the array passed to it's constructor:
} else if (!componentNames[slot].equalsIgnoreCase(name)) {
/* If a component specifies the file with a bad font,
* the corresponding slot will be initialized by
* default physical font. In such case findFont2D may
* return composite font which cannot be casted to
* physical font.
*/
This makes it's way to getDefaultPhysicalFont. Unfortunately the font in question *is* the default physical
font, and that causes SunFontManager.java:1042 to run:
if (defaultPhysicalFont == null) {
/* Because of the findFont2D call above, if we reach here, we
* know all fonts have already been loaded, just accept any
* match at this point. If this fails we are in real trouble
* and I don't know how to recover from there being absolutely
* no fonts anywhere on the system.
*/
defaultPhysicalFont = physicalFonts.values().stream().findFirst()
.orElseThrow(()->new Error("Probable fatal error: No physical fonts found."));
}
This ends up using "Noto Sans Devanagari UI Thin" as the default font, which contains arabic numerals
but no latin characters. Since this is inside a CompositeFont those characters will fall through to the next
font, which is "DejaVu Sans Bold" - the combination of thin and bold text leads to the visually jarring text
shown above.
Running "otfinfo /usr/share/fonts/TTF/DejaVuSans.ttf --info" shows that the 'Book' subfamily is not part
of the full name:
Family: DejaVu Sans
Subfamily: Book
Full name: DejaVu Sans
PostScript name: DejaVuSans
Preferred family: DejaVu Sans
Preferred subfamily: Book
Version: Version 2.37
Unique ID: DejaVu Sans
Manufacturer: DejaVu fonts team
Vendor URL: http://dejavu.sourceforge.net
Copyright: Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved.
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
DejaVu changes are in public domain
The SHA256 hash of this file is 2fb91d8d18b8312659070e66001a863b82fb6758a21e37df2c94f1cae83683ed.
Testing shows the following values are showing up to the CompositeFont constructor:
Java 11:
CompositeFont.component{File}Names start withs "/usr/share/fonts/TTF/DejaVuSans.ttf" and "DejaVu Sans"
Java 16:
CompositeFont.component{File}Names start withs "/usr/share/fonts/TTF/DejaVuSans.ttf" and "DejaVu Sans Book"
CompositeFont.java:296 - componentNames[slot]="DejaVu Sans Book" while name="DejaVu Sans"
This appears to be caused by
REGRESSION : Last worked in version 11
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Set DejaVu as the default system font on Linux - this is the default with ArchLinux and KDE.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Text should render using the selected default system font.
ACTUAL -
The characters are rendered using two different versions of the system fault: <CAPTURE2.PNG><ATTACHED>
---------- BEGIN SOURCE ----------
import javax.swing.*;
class Scratch {
public static void main(String[] args) {
JFrame frame = new JFrame("Hello World");
frame.setContentPane(new JTextArea("Testing 1234 test abc123"));
frame.pack();
frame.setVisible(true);
}
}
---------- END SOURCE ----------
FREQUENCY : always
- duplicates
-
JDK-8297119 Fallback to .otf font on linux not working
- Closed
-
JDK-8269224 Terribly broken font rendering with dejavu ttf
- Closed
- relates to
-
JDK-8219901 Noto fonts for East Asian countries cannot belong to CompositeFont
- Resolved