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