Line 0
Link Here
|
|
|
1 |
Based on original OpenJDK8 patches from Infinality project: |
2 |
http://www.infinality.net/forum/viewtopic.php?f=2&t=80#p395 |
3 |
and Fedora 21 OpenJDK8 patches by Steven Merrill: |
4 |
https://github.com/smerrill/fedora-21-openjdk8-infinality/blob/master/SOURCES/005_enable-infinality.patch |
5 |
--- jdk/src/share/native/sun/font/freetypeScaler.c.orig 2017-01-20 17:04:07 UTC |
6 |
+++ jdk/src/share/native/sun/font/freetypeScaler.c |
7 |
@@ -38,6 +38,8 @@ |
8 |
#include FT_SIZES_H |
9 |
#include FT_OUTLINE_H |
10 |
#include FT_SYNTHESIS_H |
11 |
+#include FT_LCD_FILTER_H |
12 |
+#include <fontconfig/fontconfig.h> |
13 |
|
14 |
#include "fontscaler.h" |
15 |
|
16 |
@@ -60,6 +62,7 @@ typedef struct { |
17 |
JNIEnv* env; |
18 |
FT_Library library; |
19 |
FT_Face face; |
20 |
+ FT_Stream faceStream; |
21 |
jobject font2D; |
22 |
jobject directBuffer; |
23 |
|
24 |
@@ -107,15 +110,10 @@ static void freeNativeResources(JNIEnv * |
25 |
if (scalerInfo == NULL) |
26 |
return; |
27 |
|
28 |
- //apparently Done_Face will only close the stream |
29 |
- // but will not relase the memory of stream structure. |
30 |
- // We need to free it explicitly to avoid leak. |
31 |
- //Direct access to the stream field might be not ideal solution as |
32 |
- // it is considred to be "private". |
33 |
- //Alternatively we could have stored pointer to the structure |
34 |
- // in the scalerInfo but this will increase size of the structure |
35 |
- // for no good reason |
36 |
- stream = scalerInfo->face->stream; |
37 |
+ // FT_Done_Face always closes the stream, but only frees the memory |
38 |
+ // of the data structure if it was internally allocated by FT. |
39 |
+ // We hold on to a pointer to the stream structure if we provide it |
40 |
+ // ourselves, so that we can free it here. |
41 |
|
42 |
FT_Done_Face(scalerInfo->face); |
43 |
FT_Done_FreeType(scalerInfo->library); |
44 |
@@ -128,8 +126,8 @@ static void freeNativeResources(JNIEnv * |
45 |
free(scalerInfo->fontData); |
46 |
} |
47 |
|
48 |
- if (stream != NULL) { |
49 |
- free(stream); |
50 |
+ if (scalerInfo->faceStream != NULL) { |
51 |
+ free(scalerInfo->faceStream); |
52 |
} |
53 |
|
54 |
free(scalerInfo); |
55 |
@@ -333,6 +331,10 @@ Java_sun_font_FreetypeFontScaler_initNat |
56 |
&ft_open_args, |
57 |
indexInCollection, |
58 |
&scalerInfo->face); |
59 |
+ |
60 |
+ if (!error) { |
61 |
+ scalerInfo->faceStream = ftstream; |
62 |
+ } |
63 |
} |
64 |
if (error || scalerInfo->directBuffer == NULL) { |
65 |
free(ftstream); |
66 |
@@ -693,6 +695,132 @@ static void CopyFTSubpixelVToSubpixel(co |
67 |
} |
68 |
} |
69 |
|
70 |
+typedef struct { |
71 |
+ FT_Render_Mode ftRenderMode; |
72 |
+ int ftLoadFlags; |
73 |
+ FT_LcdFilter ftLcdFilter; |
74 |
+} RenderingProperties; |
75 |
+ |
76 |
+static FcPattern* matchedPattern(const FcChar8* family, double ptSize) { |
77 |
+ FcPattern* pattern = FcPatternCreate(); |
78 |
+ if (!pattern) |
79 |
+ return 0; |
80 |
+ |
81 |
+ FcPatternAddString(pattern, FC_FAMILY, family); |
82 |
+ FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); |
83 |
+ FcPatternAddDouble(pattern, FC_SIZE, ptSize); |
84 |
+ |
85 |
+ FcConfigSubstitute(0, pattern, FcMatchPattern); |
86 |
+ FcDefaultSubstitute(pattern); |
87 |
+ |
88 |
+ FcResult res; |
89 |
+ FcPattern *match = FcFontMatch(0, pattern, &res); |
90 |
+ FcPatternDestroy(pattern); |
91 |
+ return (res == FcResultMatch) ? match : NULL; |
92 |
+} |
93 |
+ |
94 |
+static void readFontconfig(const FcChar8* family, double ptSize, jint aaType, RenderingProperties* rp) { |
95 |
+ FcPattern *pattern = matchedPattern(family, ptSize); |
96 |
+ |
97 |
+ FT_Render_Mode ftRenderMode = FT_RENDER_MODE_NORMAL; |
98 |
+ int ftLoadFlags = FT_LOAD_DEFAULT; |
99 |
+ FT_LcdFilter ftLcdFilter = FT_LCD_FILTER_DEFAULT; |
100 |
+ FcBool fcAntialias = 0; |
101 |
+ char horizontal = 1; |
102 |
+ |
103 |
+ // subpixel order |
104 |
+ if (aaType == TEXT_AA_ON) |
105 |
+ ftRenderMode = FT_RENDER_MODE_NORMAL; |
106 |
+ else if (aaType == TEXT_AA_OFF) |
107 |
+ ftRenderMode = FT_RENDER_MODE_MONO; |
108 |
+ else { |
109 |
+ int fcRGBA = FC_RGBA_UNKNOWN; |
110 |
+ if (pattern) |
111 |
+ FcPatternGetInteger(pattern, FC_RGBA, 0, &fcRGBA); |
112 |
+ switch (fcRGBA) { |
113 |
+ case FC_RGBA_NONE: |
114 |
+ ftRenderMode = FT_RENDER_MODE_NORMAL; |
115 |
+ break; |
116 |
+ case FC_RGBA_RGB: |
117 |
+ case FC_RGBA_BGR: |
118 |
+ ftRenderMode = FT_RENDER_MODE_LCD; |
119 |
+ horizontal = 1; |
120 |
+ break; |
121 |
+ case FC_RGBA_VRGB: |
122 |
+ case FC_RGBA_VBGR: |
123 |
+ ftRenderMode = FT_RENDER_MODE_LCD_V; |
124 |
+ horizontal = 0; |
125 |
+ break; |
126 |
+ default: |
127 |
+ ftRenderMode = FT_RENDER_MODE_NORMAL; |
128 |
+ break; |
129 |
+ } |
130 |
+ } |
131 |
+ |
132 |
+ // loading mode |
133 |
+ if (aaType == TEXT_AA_OFF) |
134 |
+ ftLoadFlags |= FT_LOAD_TARGET_MONO; |
135 |
+ else { |
136 |
+ int fcHintStyle = FC_HINT_NONE; |
137 |
+ if (pattern) |
138 |
+ FcPatternGetInteger(pattern, FC_HINT_STYLE, 0, &fcHintStyle); |
139 |
+ switch (fcHintStyle) { |
140 |
+ case FC_HINT_NONE: |
141 |
+ ftLoadFlags |= FT_LOAD_NO_HINTING; |
142 |
+ break; |
143 |
+ case FC_HINT_SLIGHT: |
144 |
+ ftLoadFlags |= FT_LOAD_TARGET_LIGHT; |
145 |
+ break; |
146 |
+ case FC_HINT_MEDIUM: |
147 |
+ ftLoadFlags |= FT_LOAD_TARGET_NORMAL; |
148 |
+ break; |
149 |
+ case FC_HINT_FULL: |
150 |
+ if (aaType == TEXT_AA_ON) |
151 |
+ ftLoadFlags |= FT_LOAD_TARGET_NORMAL; |
152 |
+ else |
153 |
+ ftLoadFlags |= horizontal ? FT_LOAD_TARGET_LCD : FT_LOAD_TARGET_LCD_V; |
154 |
+ break; |
155 |
+ default: |
156 |
+ ftLoadFlags |= FT_LOAD_TARGET_NORMAL; |
157 |
+ break; |
158 |
+ } |
159 |
+ } |
160 |
+ |
161 |
+ // autohinting |
162 |
+ FcBool fcAutohint = 0; |
163 |
+ if (pattern && FcPatternGetBool(pattern, FC_AUTOHINT, 0, &fcAutohint) == FcResultMatch) |
164 |
+ if (fcAutohint) |
165 |
+ ftLoadFlags |= FT_LOAD_FORCE_AUTOHINT; |
166 |
+ |
167 |
+ // LCD filter |
168 |
+ int fcLCDFilter = FC_LCD_DEFAULT; |
169 |
+ if (pattern) |
170 |
+ FcPatternGetInteger(pattern, FC_LCD_FILTER, 0, &fcLCDFilter); |
171 |
+ switch (fcLCDFilter) { |
172 |
+ case FC_LCD_NONE: |
173 |
+ ftLcdFilter = FT_LCD_FILTER_NONE; |
174 |
+ break; |
175 |
+ case FC_LCD_DEFAULT: |
176 |
+ ftLcdFilter = FT_LCD_FILTER_DEFAULT; |
177 |
+ break; |
178 |
+ case FC_LCD_LIGHT: |
179 |
+ ftLcdFilter = FT_LCD_FILTER_LIGHT; |
180 |
+ break; |
181 |
+ case FC_LCD_LEGACY: |
182 |
+ ftLcdFilter = FT_LCD_FILTER_LEGACY; |
183 |
+ break; |
184 |
+ default: |
185 |
+ ftLcdFilter = FT_LCD_FILTER_DEFAULT; |
186 |
+ break; |
187 |
+ } |
188 |
+ |
189 |
+ if (pattern) |
190 |
+ FcPatternDestroy(pattern); |
191 |
+ |
192 |
+ rp->ftRenderMode = ftRenderMode; |
193 |
+ rp->ftLoadFlags = ftLoadFlags; |
194 |
+ rp->ftLcdFilter = ftLcdFilter; |
195 |
+} |
196 |
|
197 |
/* |
198 |
* Class: sun_font_FreetypeFontScaler |
199 |
@@ -726,32 +850,15 @@ Java_sun_font_FreetypeFontScaler_getGlyp |
200 |
return ptr_to_jlong(getNullGlyphImage()); |
201 |
} |
202 |
|
203 |
- /* if algorithmic styling is required then we do not request bitmap */ |
204 |
- if (context->doBold || context->doItalize) { |
205 |
- renderFlags = FT_LOAD_DEFAULT; |
206 |
- } |
207 |
- |
208 |
- /* NB: in case of non identity transform |
209 |
- we might also prefer to disable transform before hinting, |
210 |
- and apply it explicitly after hinting is performed. |
211 |
- Or we can disable hinting. */ |
212 |
- |
213 |
- /* select appropriate hinting mode */ |
214 |
- if (context->aaType == TEXT_AA_OFF) { |
215 |
- target = FT_LOAD_TARGET_MONO; |
216 |
- } else if (context->aaType == TEXT_AA_ON) { |
217 |
- target = FT_LOAD_TARGET_NORMAL; |
218 |
- } else if (context->aaType == TEXT_AA_LCD_HRGB || |
219 |
- context->aaType == TEXT_AA_LCD_HBGR) { |
220 |
- target = FT_LOAD_TARGET_LCD; |
221 |
- } else { |
222 |
- target = FT_LOAD_TARGET_LCD_V; |
223 |
- } |
224 |
- renderFlags |= target; |
225 |
+ RenderingProperties renderingProperties; |
226 |
+ readFontconfig((const FcChar8 *) scalerInfo->face->family_name, |
227 |
+ context->ptsz, context->aaType, &renderingProperties); |
228 |
|
229 |
glyph_index = FT_Get_Char_Index(scalerInfo->face, glyphCode); |
230 |
|
231 |
- error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags); |
232 |
+ FT_Library_SetLcdFilter(scalerInfo->library, renderingProperties.ftLcdFilter); |
233 |
+ error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderingProperties.ftLoadFlags); |
234 |
+ |
235 |
if (error) { |
236 |
//do not destroy scaler yet. |
237 |
//this can be problem of particular context (e.g. with bad transform) |
238 |
@@ -770,9 +877,7 @@ Java_sun_font_FreetypeFontScaler_getGlyp |
239 |
|
240 |
/* generate bitmap if it is not done yet |
241 |
e.g. if algorithmic styling is performed and style was added to outline */ |
242 |
- if (ftglyph->format == FT_GLYPH_FORMAT_OUTLINE) { |
243 |
- FT_Render_Glyph(ftglyph, FT_LOAD_TARGET_MODE(target)); |
244 |
- } |
245 |
+ FT_Render_Glyph(ftglyph, renderingProperties.ftRenderMode); |
246 |
|
247 |
width = (UInt16) ftglyph->bitmap.width; |
248 |
height = (UInt16) ftglyph->bitmap.rows; |
249 |
@@ -1001,11 +1106,14 @@ static FT_Outline* getFTOutline(JNIEnv* |
250 |
return NULL; |
251 |
} |
252 |
|
253 |
- renderFlags = FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP; |
254 |
+ RenderingProperties renderingProperties; |
255 |
+ readFontconfig((const FcChar8 *) scalerInfo->face->family_name, |
256 |
+ context->ptsz, context->aaType, &renderingProperties); |
257 |
|
258 |
glyph_index = FT_Get_Char_Index(scalerInfo->face, glyphCode); |
259 |
|
260 |
- error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderFlags); |
261 |
+ error = FT_Load_Glyph(scalerInfo->face, glyphCode, renderingProperties.ftLoadFlags); |
262 |
+ |
263 |
if (error) { |
264 |
return NULL; |
265 |
} |