Line 0
Link Here
|
|
|
1 |
Patch FreeType scaler to obtain per-family FreeType rendering/loading flags |
2 |
from fontconfig instead of using OpenJDK heuristics. |
3 |
Based on original OpenJDK Infinality patches from |
4 |
http://www.infinality.net/forum/viewtopic.php?f=2&t=80#p395 (now gone) and Fedora 21 |
5 |
https://github.com/smerrill/fedora-21-openjdk8-infinality/blob/master/SOURCES/005_enable-infinality.patch |
6 |
|
7 |
--- jdk/src/share/native/sun/font/freetypeScaler.c.orig 2016-12-27 15:42:38.958414000 -0500 |
8 |
+++ jdk/src/share/native/sun/font/freetypeScaler.c 2016-12-27 15:57:22.816455000 -0500 |
9 |
@@ -38,6 +38,8 @@ |
10 |
#include FT_SIZES_H |
11 |
#include FT_OUTLINE_H |
12 |
#include FT_SYNTHESIS_H |
13 |
+#include FT_LCD_FILTER_H |
14 |
+#include <fontconfig/fontconfig.h> |
15 |
|
16 |
#include "fontscaler.h" |
17 |
|
18 |
@@ -656,6 +658,128 @@ |
19 |
} |
20 |
} |
21 |
|
22 |
+typedef struct { |
23 |
+ FT_Render_Mode ftRenderMode; |
24 |
+ int ftLoadFlags; |
25 |
+ FT_LcdFilter ftLcdFilter; |
26 |
+} RenderingProperties; |
27 |
+ |
28 |
+static FcPattern* matchedPattern(const FcChar8* family, double ptSize) { |
29 |
+ FcPattern* pattern = FcPatternCreate(); |
30 |
+ if (!pattern) |
31 |
+ return 0; |
32 |
+ |
33 |
+ FcPatternAddString(pattern, FC_FAMILY, family); |
34 |
+ FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); |
35 |
+ FcPatternAddDouble(pattern, FC_SIZE, ptSize); |
36 |
+ |
37 |
+ FcConfigSubstitute(0, pattern, FcMatchPattern); |
38 |
+ FcDefaultSubstitute(pattern); |
39 |
+ |
40 |
+ FcResult res; |
41 |
+ FcPattern *match = FcFontMatch(0, pattern, &res); |
42 |
+ FcPatternDestroy(pattern); |
43 |
+ return match; |
44 |
+} |
45 |
+ |
46 |
+static void readFontconfig(const FcChar8* family, double ptSize, jint aaType, RenderingProperties* rp) { |
47 |
+ FcPattern *pattern = matchedPattern(family, ptSize); |
48 |
+ |
49 |
+ FT_Render_Mode ftRenderMode = FT_RENDER_MODE_NORMAL; |
50 |
+ int ftLoadFlags = FT_LOAD_DEFAULT; |
51 |
+ FT_LcdFilter ftLcdFilter = FT_LCD_FILTER_DEFAULT; |
52 |
+ FcBool fcAntialias = 0; |
53 |
+ char horizontal = 1; |
54 |
+ |
55 |
+ // subpixel order |
56 |
+ if (aaType == TEXT_AA_ON) |
57 |
+ ftRenderMode = FT_RENDER_MODE_NORMAL; |
58 |
+ else if (aaType == TEXT_AA_OFF) |
59 |
+ ftRenderMode = FT_RENDER_MODE_MONO; |
60 |
+ else { |
61 |
+ int fcRGBA = FC_RGBA_UNKNOWN; |
62 |
+ FcPatternGetInteger(pattern, FC_RGBA, 0, &fcRGBA); |
63 |
+ switch (fcRGBA) { |
64 |
+ case FC_RGBA_NONE: |
65 |
+ ftRenderMode = FT_RENDER_MODE_NORMAL; |
66 |
+ break; |
67 |
+ case FC_RGBA_RGB: |
68 |
+ case FC_RGBA_BGR: |
69 |
+ ftRenderMode = FT_RENDER_MODE_LCD; |
70 |
+ horizontal = 1; |
71 |
+ break; |
72 |
+ case FC_RGBA_VRGB: |
73 |
+ case FC_RGBA_VBGR: |
74 |
+ ftRenderMode = FT_RENDER_MODE_LCD_V; |
75 |
+ horizontal = 0; |
76 |
+ break; |
77 |
+ default: |
78 |
+ ftRenderMode = FT_RENDER_MODE_NORMAL; |
79 |
+ break; |
80 |
+ } |
81 |
+ } |
82 |
+ |
83 |
+ // loading mode |
84 |
+ if (aaType == TEXT_AA_OFF) |
85 |
+ ftLoadFlags |= FT_LOAD_TARGET_MONO; |
86 |
+ else { |
87 |
+ int fcHintStyle = FC_HINT_NONE; |
88 |
+ FcPatternGetInteger(pattern, FC_HINT_STYLE, 0, &fcHintStyle); |
89 |
+ switch (fcHintStyle) { |
90 |
+ case FC_HINT_NONE: |
91 |
+ ftLoadFlags |= FT_LOAD_NO_HINTING; |
92 |
+ break; |
93 |
+ case FC_HINT_SLIGHT: |
94 |
+ ftLoadFlags |= FT_LOAD_TARGET_LIGHT; |
95 |
+ break; |
96 |
+ case FC_HINT_MEDIUM: |
97 |
+ ftLoadFlags |= FT_LOAD_TARGET_NORMAL; |
98 |
+ break; |
99 |
+ case FC_HINT_FULL: |
100 |
+ if (aaType == TEXT_AA_ON) |
101 |
+ ftLoadFlags |= FT_LOAD_TARGET_NORMAL; |
102 |
+ else |
103 |
+ ftLoadFlags |= horizontal ? FT_LOAD_TARGET_LCD : FT_LOAD_TARGET_LCD_V; |
104 |
+ break; |
105 |
+ default: |
106 |
+ ftLoadFlags |= FT_LOAD_TARGET_NORMAL; |
107 |
+ break; |
108 |
+ } |
109 |
+ } |
110 |
+ |
111 |
+ // autohinting |
112 |
+ FcBool fcAutohint = 0; |
113 |
+ if (FcPatternGetBool(pattern, FC_AUTOHINT, 0, &fcAutohint) == FcResultMatch) |
114 |
+ if (fcAutohint) |
115 |
+ ftLoadFlags |= FT_LOAD_FORCE_AUTOHINT; |
116 |
+ |
117 |
+ // LCD filter |
118 |
+ int fcLCDFilter = FC_LCD_DEFAULT; |
119 |
+ FcPatternGetInteger(pattern, FC_LCD_FILTER, 0, &fcLCDFilter); |
120 |
+ switch (fcLCDFilter) { |
121 |
+ case FC_LCD_NONE: |
122 |
+ ftLcdFilter = FT_LCD_FILTER_NONE; |
123 |
+ break; |
124 |
+ case FC_LCD_DEFAULT: |
125 |
+ ftLcdFilter = FT_LCD_FILTER_DEFAULT; |
126 |
+ break; |
127 |
+ case FC_LCD_LIGHT: |
128 |
+ ftLcdFilter = FT_LCD_FILTER_LIGHT; |
129 |
+ break; |
130 |
+ case FC_LCD_LEGACY: |
131 |
+ ftLcdFilter = FT_LCD_FILTER_LEGACY; |
132 |
+ break; |
133 |
+ default: |
134 |
+ ftLcdFilter = FT_LCD_FILTER_DEFAULT; |
135 |
+ break; |
136 |
+ } |
137 |
+ |
138 |
+ FcPatternDestroy(pattern); |
139 |
+ |
140 |
+ rp->ftRenderMode = ftRenderMode; |
141 |
+ rp->ftLoadFlags = ftLoadFlags; |
142 |
+ rp->ftLcdFilter = ftLcdFilter; |
143 |
+} |
144 |
|
145 |
/* |
146 |
* Class: sun_font_FreetypeFontScaler |
147 |
@@ -689,32 +813,15 @@ |
148 |
return ptr_to_jlong(getNullGlyphImage()); |
149 |
} |
150 |
|
151 |
- /* if algorithmic styling is required then we do not request bitmap */ |
152 |
- if (context->doBold || context->doItalize) { |
153 |
- renderFlags = FT_LOAD_DEFAULT; |
154 |
- } |
155 |
- |
156 |
- /* NB: in case of non identity transform |
157 |
- we might also prefer to disable transform before hinting, |
158 |
- and apply it explicitly after hinting is performed. |
159 |
- Or we can disable hinting. */ |
160 |
- |
161 |
- /* select appropriate hinting mode */ |
162 |
- if (context->aaType == TEXT_AA_OFF) { |
163 |
- target = FT_LOAD_TARGET_MONO; |
164 |
- } else if (context->aaType == TEXT_AA_ON) { |
165 |
- target = FT_LOAD_TARGET_NORMAL; |
166 |
- } else if (context->aaType == TEXT_AA_LCD_HRGB || |
167 |
- context->aaType == TEXT_AA_LCD_HBGR) { |
168 |
- target = FT_LOAD_TARGET_LCD; |
169 |
- } else { |
170 |
- target = FT_LOAD_TARGET_LCD_V; |
171 |
- } |
172 |
- renderFlags |= target; |
173 |
+ RenderingProperties renderingProperties; |
174 |
+ readFontconfig((const FcChar8 *) scalerInfo->face->family_name, |
175 |
+ context->ptsz, context->aaType, &renderingProperties); |
176 |
|
177 |
glyph_index = FT_Get_Char_Index(scalerInfo->face, glyphCode); |
178 |
|
179 |
- error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags); |
180 |
+ FT_Library_SetLcdFilter(scalerInfo->library, renderingProperties.ftLcdFilter); |
181 |
+ error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderingProperties.ftLoadFlags); |
182 |
+ |
183 |
if (error) { |
184 |
//do not destroy scaler yet. |
185 |
//this can be problem of particular context (e.g. with bad transform) |
186 |
@@ -733,9 +840,7 @@ |
187 |
|
188 |
/* generate bitmap if it is not done yet |
189 |
e.g. if algorithmic styling is performed and style was added to outline */ |
190 |
- if (ftglyph->format == FT_GLYPH_FORMAT_OUTLINE) { |
191 |
- FT_Render_Glyph(ftglyph, FT_LOAD_TARGET_MODE(target)); |
192 |
- } |
193 |
+ FT_Render_Glyph(ftglyph, renderingProperties.ftRenderMode); |
194 |
|
195 |
width = (UInt16) ftglyph->bitmap.width; |
196 |
height = (UInt16) ftglyph->bitmap.rows; |
197 |
@@ -964,11 +1069,14 @@ |
198 |
return NULL; |
199 |
} |
200 |
|
201 |
- renderFlags = FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP; |
202 |
+ RenderingProperties renderingProperties; |
203 |
+ readFontconfig((const FcChar8 *) scalerInfo->face->family_name, |
204 |
+ context->ptsz, context->aaType, &renderingProperties); |
205 |
|
206 |
glyph_index = FT_Get_Char_Index(scalerInfo->face, glyphCode); |
207 |
|
208 |
- error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags); |
209 |
+ error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderingProperties.ftLoadFlags); |
210 |
+ |
211 |
if (error) { |
212 |
return NULL; |
213 |
} |