[OpenJDK 2D-Dev] Setting the FreeType LCD filter
John Neffenger
john at status6.com
Thu Oct 11 19:08:07 UTC 2018
On 10/11/2018 11:41 AM, Laurent Bourgès wrote:
> Maybe just send text and your diff only and keep images as link on github.
Right again. Here's just the text, no attachments, formatted in plain
text as best I can. Thank you again for your help, Laurent.
The symptoms of the problem are the same as in the link below, but they
appear in AWT and Swing applications instead of JavaFX applications.
JDK-8188810: Fonts are blurry on Ubuntu 16.04 and Debian 9
https://bugs.openjdk.java.net/browse/JDK-8188810
The description of the problem on the Java side follows.
Synopsis: Reduce color fringes in FreeType subpixel rendering
The text in Java applications often has severe color fringes when using
OpenJDK on Ubuntu and other Debian-based distributions because the JDK
fails to set the LCD filter. Adding two lines of code to the file
freetypeScaler.c fixed the problem in my tests, without any regression
errors for other Linux distributions. The patch is included at the very
end of this message.
There are some alternatives to setting the filter:
• Bundle the FreeType library by default and always use the new
Harmony subpixel rendering technique. This option removes the
uncertainty in the library at the expense of an additional 4.6 megabytes
to the installed size — an increase of less than one percent. OpenJDK 12
even includes the latest FreeType 2.9.1, a newer version than the one
found on most systems.
• Wait another year and see what changes are made to FreeType, if
any, when the ClearType patents expire. This option, though, doesn’t
solve the problem that users of Ubuntu and other Debian-based
distributions have now.
The problem originates in decisions made by the developers of FreeType,
Debian, Fedora, and OpenJDK concerning the Microsoft ClearType patents [1].
• In 2007, FreeType 2.3.0 added a compiler configuration macro to the
file ftoption.h named FT_CONFIG_OPTION_SUBPIXEL_RENDERING. If defined,
the FreeType library includes patented ClearType techniques in its
subpixel rendering.
But there’s a catch. When the ClearType methods are enabled, the
subpixel rendering is not filtered, which results in severe color
fringes. Clients of the FreeType library must make an explicit call to
the function FT_Library_SetLcdFilter to apply color filtering. The
filter was disabled by default, explained one of its authors, “to avoid
major surprises to existing clients, including libXft and Cairo which
already perform some wacky color filtering on top of FreeType.”
• In 2009, Debian created a patch to FreeType 2.3.9, named
enable-subpixel-rendering.patch, that defines the macro and enables
ClearType-style rendering. The change log states, “This is considered no
more or less evil than the bytecode interpreter which we also enable.”
Ubuntu, based on Debian, applies the patch as well. Fedora created the
same patch in 2007, named freetype-2.3.0-enable-spr.patch, but does not
apply the patch by default.
• In 2017, FreeType 2.8.1 included a new subpixel rendering
technique, called Harmony, that is nearly identical in output to the
ClearType technique but uses a different algorithm, avoiding the
patents. FreeType now uses Harmony subpixel rendering when the ClearType
methods are disabled, with no need for clients to set the LCD filter.
(This would have been a good time for Debian to remove its subpixel
rendering patch.) The latest Fedora Workstation 28 runs FreeType 2.8.0,
which does not include Harmony.
• In 2019, the Microsoft ClearType patents expire.
So now we have two variants of the FreeType library: one that requires a
function call to set the LCD filter in Ubuntu and other distributions
based on Debian, and another that doesn’t require the function call in
Red Hat Enterprise Linux, Oracle Linux, and other distributions based on
Fedora.
To demonstrate the problem, I built four versions of the JDK from the
latest OpenJDK sources. I built a version that uses the system FreeType
library and another that uses the bundled FreeType library. Then I
changed the OpenJDK code to set the default LCD filter and built the two
versions again. The four builds were named:
jdk-12-system-lcdnone
jdk-12-system-lcddefault
jdk-12-bundled-lcdnone
jdk-12-bundled-lcddefault
The system library is FreeType 2.8.1 in Ubuntu 18.04.1 LTS, which has
the Debian patch applied (ClearType methods enabled), while the bundled
library is FreeType 2.9.1 in OpenJDK 12, which uses the library default
(ClearType methods disabled). I wrote a simple Java Swing application
called FontDemo [2] that displays two text areas with the Adobe Source
Code Pro font [3] in TTF and OTF formats (the latest non-variable download).
The results are shown in the two images below:
fontdemo.png
https://raw.githubusercontent.com/jgneff/openjdk-freetype/master/files/fontdemo.png
fontdemo-detail.png
https://raw.githubusercontent.com/jgneff/openjdk-freetype/master/files/fontdemo-detail.png
When using the Ubuntu system FreeType library, setting the LCD filter is
critical. The screenshots show the ClearType-style rendering without
setting the LCD filter, and after adding the change to set the filter.
The ClearType configuration macro is defined in the Ubuntu build of
FreeType, so the function to set the filter returns success (0) when
called and applies color filtering.
When using the OpenJDK bundled FreeType library, setting the LCD filter
does nothing. The screenshot shows the FreeType Harmony subpixel
rendering, which is the same whether or not the LCD filter is set. The
ClearType configuration macro is not defined in the OpenJDK build of
FreeType, so the function to set the filter returns
FT_Err_Unimplemented_Feature (7) when called and does nothing.
The test system I used is a QEMU/KVM guest virtual machine running
Ubuntu 18.04.1 LTS (Bionic Beaver) with the details shown below. The
display is a 27-inch Dell UltraSharp U2717D monitor with a resolution of
2560 × 1440 pixels at 109 pixels per inch.
ubuntu at bionic:~$ uname -a
Linux bionic 4.15.0-36-generic #39-Ubuntu SMP
Mon Sep 24 16:19:09 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
ubuntu at bionic:~$ ldd --version
ldd (Ubuntu GLIBC 2.27-3ubuntu1) 2.27
ubuntu at bionic:~$ getconf GNU_LIBPTHREAD_VERSION
NPTL 2.27
ubuntu at bionic:~$ $HOME/opt/jdk-12-system-lcdnone/bin/java -version
openjdk version "12-internal" 2019-03-19
OpenJDK Runtime Environment (build 12-internal+0-adhoc.ubuntu.jdk)
OpenJDK 64-Bit Server VM (build 12-internal+0-adhoc.ubuntu.jdk, mixed mode)
Below are the full test results using five versions of FreeType built
first with the ClearType methods disabled (the default) and then again
with them enabled. I ran all 10 libraries under OpenJDK 12, first with
no LCD filter and then again after adding the code to set the default
LCD filter.
No LCD Filter
2008 FreeType 2.3.5 (libfreetype.so.6.3.16) in Ubuntu 8.04 LTS
ClearType Off: Grayscale, ClearType On: Mild fringes
2014 FreeType 2.5.2 (libfreetype.so.6.11.1) in Ubuntu 14.04 LTS
ClearType Off: Grayscale, ClearType On: Severe fringes
2016 FreeType 2.6.1 (libfreetype.so.6.12.1) in Ubuntu 16.04 LTS
ClearType Off: Grayscale, ClearType On: Severe fringes
2018 FreeType 2.8.1 (libfreetype.so.6.15.0) in Ubuntu 18.04 LTS
ClearType Off: Harmony, ClearType On: Severe fringes
2019 FreeType 2.9.1 (libfreetype.so.6.16.1) in OpenJDK 12
ClearType Off: Harmony, ClearType On: Severe fringes
The OpenJDK does not set the FreeType LCD filter, so there are severe
color fringes when using a FreeType library built with the ClearType
methods enabled. The only reason the older FreeType 2.3.5 shows mild
color fringes is because it uses full hinting, so the glyphs are simply
too skinny to see their colors.
Default LCD Filter
2008 FreeType 2.3.5 (libfreetype.so.6.3.16) in Ubuntu 8.04 LTS
ClearType Off: Grayscale, ClearType On: ClearType filtered
2014 FreeType 2.5.2 (libfreetype.so.6.11.1) in Ubuntu 14.04 LTS
ClearType Off: Grayscale, ClearType On: ClearType filtered
2016 FreeType 2.6.1 (libfreetype.so.6.12.1) in Ubuntu 16.04 LTS
ClearType Off: Grayscale, ClearType On: ClearType filtered
2018 FreeType 2.8.1 (libfreetype.so.6.15.0) in Ubuntu 18.04 LTS
ClearType Off: Harmony, ClearType On: ClearType filtered
2019 FreeType 2.9.1 (libfreetype.so.6.16.1) in OpenJDK 12
ClearType Off: Harmony, ClearType On: ClearType filtered
After changing the OpenJDK to set the default LCD filter, there is no
version of the FreeType library that shows the severe color fringes.
Note that Fedora Workstation 28 includes FreeType 2.8.0 with the
ClearType methods disabled, so it displays grayscale anti-aliasing for
the OpenJDK whether it sets the LCD filter or not. (FreeType 2.8.0 does
not include Harmony.)
For background information on LCD filters see Section 2.2.1 [4] of The
Raster Tragedy at Low-Resolution, which has an interactive demonstration
of the filters used in ClearType (Microsoft), CoolType (Adobe), FreeType
(open source), and Quartz 2D (Apple). Hover your mouse over each of the
samples in the illustration to remove the filter.
Below is the relevant section of the file ftoption.h in FreeType 2.9.1
bundled with OpenJDK 12, edited for formatting:
java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h
/*
Uncomment the line below if you want to activate LCD rendering
technology similar to ClearType in this build of the library. This
technology triples the resolution in the direction color subpixels.
To mitigate color fringes inherent to this technology, you also need
to explicitly set up LCD filtering.
Note that this feature is covered by several Microsoft patents
and should not be activated in any default build of the library.
When this macro is not defined, FreeType offers alternative LCD
rendering technology that produces excellent output without LCD
filtering.
*/
/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
Links
[1] http://david.freetype.org/cleartype-patents.html
[2]
https://github.com/jgneff/openjdk-freetype/blob/master/src/org/status6/FontDemo.java
[3] https://github.com/adobe-fonts/source-code-pro
[4] http://rastertragedy.com/RTRCh2.htm#Sec21
Patch
diff -r 1aa9beac610e
src/java.desktop/share/native/libfontmanager/freetypeScaler.c
--- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c Thu
Oct 04 16:39:07 2018 +0200
+++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c Thu
Oct 11 08:30:00 2018 -0700
@@ -38,6 +38,7 @@
#include FT_SIZES_H
#include FT_OUTLINE_H
#include FT_SYNTHESIS_H
+#include FT_LCD_FILTER_H
#include "fontscaler.h"
@@ -397,6 +398,8 @@
if (errCode == 0) {
errCode = FT_Activate_Size(scalerInfo->face->size);
}
+
+ FT_Library_SetLcdFilter(scalerInfo->library,
FT_LCD_FILTER_DEFAULT);
}
return errCode;
More information about the 2d-dev
mailing list