Skip to content

Instantly share code, notes, and snippets.

@trustin
Last active November 30, 2015 15:47
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save trustin/2893461 to your computer and use it in GitHub Desktop.
OpenJDK 7 font rendering patch for Linux (cd openjdk/jdk; patch -p1 < fontfix.patch)
diff -r 19cc3b567644 make/sun/font/Makefile
--- a/make/sun/font/Makefile Wed Jan 22 12:34:24 2014 -0800
+++ b/make/sun/font/Makefile Fri Jan 24 21:41:23 2014 +0900
@@ -138,7 +138,7 @@
ifeq ($(USING_SYSTEM_FT_LIB), false)
FREETYPE_LIB = $(LIB_LOCATION)/$(LIB_PREFIX)freetype.$(LIBRARY_SUFFIX).6
endif
- OTHER_LDLIBS += -L$(FREETYPE_LIB_PATH) -lfreetype
+ OTHER_LDLIBS += -L$(FREETYPE_LIB_PATH) -lfreetype -lfontconfig
endif
library:: $(FREETYPE_LIB)
diff -r 19cc3b567644 src/share/native/sun/font/freetypeScaler.c
--- a/src/share/native/sun/font/freetypeScaler.c Wed Jan 22 12:34:24 2014 -0800
+++ b/src/share/native/sun/font/freetypeScaler.c Fri Jan 24 21:41:23 2014 +0900
@@ -38,6 +38,8 @@
#include FT_SIZES_H
#include FT_OUTLINE_H
#include FT_SYNTHESIS_H
+#include FT_LCD_FILTER_H
+#include <fontconfig/fontconfig.h>
#include "fontscaler.h"
@@ -692,6 +694,145 @@
}
}
+typedef struct {
+ FT_Render_Mode ftRenderMode;
+ int ftLoadFlags;
+ FT_LcdFilter ftLcdFilter;
+} RenderingProperties;
+
+static FcPattern* matchedPattern(const FcChar8* family, double ptSize) {
+ /*
+ we will create pattern to find our family and size in
+ fontconfig configuration, and then will return it's
+ properties:
+ */
+ FcPattern* fcPattern = 0;
+ fcPattern = FcPatternCreate();
+ FcValue fcValue;
+ fcValue.type = FcTypeString;
+ fcValue.u.s = family;
+ FcPatternAdd(fcPattern, FC_FAMILY, fcValue, FcTrue);
+ FcPatternAddBool(fcPattern, FC_SCALABLE, FcTrue);
+ FcPatternAddDouble(fcPattern, FC_SIZE, ptSize);
+ // TODO FcPatternAddInteger(pattern, FC_WEIGHT, weight_value);
+ // TODO FcPatternAddInteger(pattern, FC_SLANT, slant_value);
+ // TODO FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size_value);
+ // TODO FcPatternAddInteger(pattern, FC_WIDTH, stretch); 100 in most cases
+ FcConfigSubstitute(0, fcPattern, FcMatchPattern);
+ FcConfigSubstitute(0, fcPattern, FcMatchFont);
+ FcDefaultSubstitute(fcPattern);
+ FcResult res;
+
+ FcPattern *pattern = 0;
+ pattern = FcFontMatch(0, fcPattern, &res);
+ FcPatternDestroy(fcPattern);
+ return pattern;
+}
+
+static void readFontconfig(const FcChar8* family, double ptSize, jint aaType, RenderingProperties* rp) {
+
+ FcPattern *pattern = matchedPattern(family, ptSize);
+
+ int ftLoadFalgs = FT_LOAD_DEFAULT;
+ FT_Render_Mode ftRenderMode;
+ FT_LcdFilter ftLcdFilter;
+ char horizontal = 1;
+ FcBool b;
+
+ // subpixel order:
+ if (aaType == TEXT_AA_ON)
+ ftRenderMode = FT_RENDER_MODE_NORMAL;
+ else if (aaType == TEXT_AA_OFF)
+ ftRenderMode = FT_RENDER_MODE_MONO;
+ else if (FcPatternGetBool(pattern, FC_ANTIALIAS, 0, &b) == FcResultMatch)
+ if (b) {
+ int subpixel = FC_RGBA_UNKNOWN;
+ FcPatternGetInteger(pattern, FC_RGBA, 0, &subpixel);
+ if (subpixel == FC_RGBA_UNKNOWN)
+ subpixel = FC_RGBA_NONE;
+ switch (subpixel) {
+ case FC_RGBA_NONE:
+ ftRenderMode = FT_RENDER_MODE_NORMAL;
+ break;
+ case FC_RGBA_RGB:
+ case FC_RGBA_BGR:
+ ftRenderMode = FT_RENDER_MODE_LCD;
+ horizontal = 1;
+ break;
+ case FC_RGBA_VRGB:
+ case FC_RGBA_VBGR:
+ ftRenderMode = FT_RENDER_MODE_LCD_V;
+ horizontal = 0;
+ break;
+ default:
+ break;
+ }
+ } else {
+ ftRenderMode = FT_RENDER_MODE_NORMAL;
+ }
+
+ // loading mode:
+ if (aaType == TEXT_AA_OFF)
+ ftLoadFalgs |= FT_LOAD_TARGET_MONO;
+ else {
+ int hint_style = FC_HINT_NONE;
+ FcPatternGetInteger(pattern, FC_HINT_STYLE, 0, &hint_style);
+ switch (hint_style) {
+ case FC_HINT_NONE:
+ ftLoadFalgs |= FT_LOAD_NO_HINTING;
+ break;
+ case FC_HINT_SLIGHT:
+ ftLoadFalgs |= FT_LOAD_TARGET_LIGHT;
+ break;
+ case FC_HINT_MEDIUM:
+ ftLoadFalgs |= FT_LOAD_TARGET_NORMAL;
+ break;
+ case FC_HINT_FULL:
+ if (aaType == TEXT_AA_ON)
+ ftLoadFalgs |= FT_LOAD_TARGET_NORMAL;
+ else
+ ftLoadFalgs |= horizontal ? FT_LOAD_TARGET_LCD : FT_LOAD_TARGET_LCD_V;
+ break;
+ default:
+ // what else to use as default?
+ ftLoadFalgs |= FT_LOAD_TARGET_NORMAL;
+ break;
+ }
+ }
+
+ // autohinting:
+ if (FcPatternGetBool(pattern, FC_AUTOHINT, 0, &b) == FcResultMatch)
+ if (b)
+ ftLoadFalgs |= FT_LOAD_FORCE_AUTOHINT;
+
+ // LCD filter:
+ int filter = FC_LCD_DEFAULT;
+ FcPatternGetInteger(pattern, FC_LCD_FILTER, 0, &filter);
+ switch (filter) {
+ case FC_LCD_NONE:
+ ftLcdFilter = FT_LCD_FILTER_NONE;
+ break;
+ case FC_LCD_DEFAULT:
+ ftLcdFilter = FT_LCD_FILTER_DEFAULT;
+ break;
+ case FC_LCD_LIGHT:
+ ftLcdFilter = FT_LCD_FILTER_LIGHT;
+ break;
+ case FC_LCD_LEGACY:
+ ftLcdFilter = FT_LCD_FILTER_LEGACY;
+ break;
+ default:
+ // new unknown lcd filter type?! will use default one:
+ ftLcdFilter = FT_LCD_FILTER_DEFAULT;
+ break;
+ }
+
+ FcPatternDestroy(pattern);
+
+ rp->ftRenderMode = ftRenderMode;
+ rp->ftLoadFlags = ftLoadFalgs;
+ rp->ftLcdFilter = ftLcdFilter;
+}
/*
* Class: sun_font_FreetypeFontScaler
@@ -707,7 +848,6 @@
UInt16 width, height;
GlyphInfo *glyphInfo;
int glyph_index;
- int renderFlags = FT_LOAD_RENDER, target;
FT_GlyphSlot ftglyph;
FTScalerContext* context =
@@ -725,32 +865,15 @@
return ptr_to_jlong(getNullGlyphImage());
}
- /* if algorithmic styling is required then we do not request bitmap */
- if (context->doBold || context->doItalize) {
- renderFlags = FT_LOAD_DEFAULT;
- }
-
- /* NB: in case of non identity transform
- we might also prefer to disable transform before hinting,
- and apply it explicitly after hinting is performed.
- Or we can disable hinting. */
-
- /* select appropriate hinting mode */
- if (context->aaType == TEXT_AA_OFF) {
- target = FT_LOAD_TARGET_MONO;
- } else if (context->aaType == TEXT_AA_ON) {
- target = FT_LOAD_TARGET_NORMAL;
- } else if (context->aaType == TEXT_AA_LCD_HRGB ||
- context->aaType == TEXT_AA_LCD_HBGR) {
- target = FT_LOAD_TARGET_LCD;
- } else {
- target = FT_LOAD_TARGET_LCD_V;
- }
- renderFlags |= target;
+ RenderingProperties renderingProperties;
+ readFontconfig((const FcChar8 *) scalerInfo->face->family_name,
+ context->ptsz, context->aaType, &renderingProperties);
glyph_index = FT_Get_Char_Index(scalerInfo->face, glyphCode);
- error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags);
+ FT_Library_SetLcdFilter(scalerInfo->library, renderingProperties.ftLcdFilter);
+
+ error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderingProperties.ftLoadFlags);
if (error) {
//do not destroy scaler yet.
//this can be problem of particular context (e.g. with bad transform)
@@ -767,11 +890,7 @@
FT_GlyphSlot_Oblique(ftglyph);
}
- /* generate bitmap if it is not done yet
- e.g. if algorithmic styling is performed and style was added to outline */
- if (ftglyph->format == FT_GLYPH_FORMAT_OUTLINE) {
- FT_Render_Glyph(ftglyph, FT_LOAD_TARGET_MODE(target));
- }
+ FT_Render_Glyph(ftglyph, renderingProperties.ftRenderMode);
width = (UInt16) ftglyph->bitmap.width;
height = (UInt16) ftglyph->bitmap.rows;
@@ -984,7 +1103,6 @@
static FT_Outline* getFTOutline(JNIEnv* env, jobject font2D,
FTScalerContext *context, FTScalerInfo* scalerInfo,
jint glyphCode, jfloat xpos, jfloat ypos) {
- int renderFlags;
int glyph_index;
FT_Error error;
FT_GlyphSlot ftglyph;
@@ -999,11 +1117,13 @@
return NULL;
}
- renderFlags = FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP;
+ RenderingProperties renderingProperties;
+ readFontconfig((const FcChar8 *) scalerInfo->face->family_name,
+ context->ptsz, context->aaType, &renderingProperties);
glyph_index = FT_Get_Char_Index(scalerInfo->face, glyphCode);
- error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags);
+ error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderingProperties.ftLoadFlags);
if (error) {
return NULL;
}
@hgomez
Copy link

hgomez commented Jan 22, 2014

Hi Trustin

Very interesting patch, could I use it in https://github.com/hgomez/obuildfactory ?

Thanks

@trustin
Copy link
Author

trustin commented Jan 24, 2014

Sure.

@piotr-dobrogost
Copy link

Is there bug for this opened in OpenJDK?
Is there any chance it will be merged?
Is there a version for OpenJDK 8?

Copy link

ghost commented Dec 30, 2014

Hi,
I am using Fedora20 and vanil-openjdk7. What must I do with this file? where should i use it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment