[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