OLD | NEW |
| (Empty) |
1 #if !defined(_FXFT_VERSION_) || _FXFT_VERSION_ == 2501 | |
2 /***************************************************************************/ | |
3 /* */ | |
4 /* ftlcdfil.c */ | |
5 /* */ | |
6 /* FreeType API for color filtering of subpixel bitmap glyphs (body). */ | |
7 /* */ | |
8 /* Copyright 2006, 2008-2010, 2013 by */ | |
9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ | |
10 /* */ | |
11 /* This file is part of the FreeType project, and may only be used, */ | |
12 /* modified, and distributed under the terms of the FreeType project */ | |
13 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ | |
14 /* this file you indicate that you have read the license and */ | |
15 /* understand and accept it fully. */ | |
16 /* */ | |
17 /***************************************************************************/ | |
18 | |
19 #define FT2_BUILD_LIBRARY | |
20 #include "../../include/ft2build.h" | |
21 #include "../../include/freetype/internal/ftdebug.h" | |
22 | |
23 #include "../../include/freetype/ftlcdfil.h" | |
24 #include "../../include/freetype/ftimage.h" | |
25 #include "../../include/freetype/internal/ftobjs.h" | |
26 | |
27 | |
28 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING | |
29 | |
30 /* define USE_LEGACY to implement the legacy filter */ | |
31 #define USE_LEGACY | |
32 | |
33 /* FIR filter used by the default and light filters */ | |
34 static void | |
35 _ft_lcd_filter_fir( FT_Bitmap* bitmap, | |
36 FT_Render_Mode mode, | |
37 FT_Library library ) | |
38 { | |
39 FT_Byte* weights = library->lcd_weights; | |
40 FT_UInt width = (FT_UInt)bitmap->width; | |
41 FT_UInt height = (FT_UInt)bitmap->rows; | |
42 | |
43 | |
44 /* horizontal in-place FIR filter */ | |
45 if ( mode == FT_RENDER_MODE_LCD && width >= 4 ) | |
46 { | |
47 FT_Byte* line = bitmap->buffer; | |
48 | |
49 | |
50 for ( ; height > 0; height--, line += bitmap->pitch ) | |
51 { | |
52 FT_UInt fir[5]; | |
53 FT_UInt val1, xx; | |
54 | |
55 | |
56 val1 = line[0]; | |
57 fir[0] = weights[2] * val1; | |
58 fir[1] = weights[3] * val1; | |
59 fir[2] = weights[4] * val1; | |
60 fir[3] = 0; | |
61 fir[4] = 0; | |
62 | |
63 val1 = line[1]; | |
64 fir[0] += weights[1] * val1; | |
65 fir[1] += weights[2] * val1; | |
66 fir[2] += weights[3] * val1; | |
67 fir[3] += weights[4] * val1; | |
68 | |
69 for ( xx = 2; xx < width; xx++ ) | |
70 { | |
71 FT_UInt val, pix; | |
72 | |
73 | |
74 val = line[xx]; | |
75 pix = fir[0] + weights[0] * val; | |
76 fir[0] = fir[1] + weights[1] * val; | |
77 fir[1] = fir[2] + weights[2] * val; | |
78 fir[2] = fir[3] + weights[3] * val; | |
79 fir[3] = weights[4] * val; | |
80 | |
81 pix >>= 8; | |
82 pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); | |
83 line[xx - 2] = (FT_Byte)pix; | |
84 } | |
85 | |
86 { | |
87 FT_UInt pix; | |
88 | |
89 | |
90 pix = fir[0] >> 8; | |
91 pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); | |
92 line[xx - 2] = (FT_Byte)pix; | |
93 | |
94 pix = fir[1] >> 8; | |
95 pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); | |
96 line[xx - 1] = (FT_Byte)pix; | |
97 } | |
98 } | |
99 } | |
100 | |
101 /* vertical in-place FIR filter */ | |
102 else if ( mode == FT_RENDER_MODE_LCD_V && height >= 4 ) | |
103 { | |
104 FT_Byte* column = bitmap->buffer; | |
105 FT_Int pitch = bitmap->pitch; | |
106 | |
107 | |
108 for ( ; width > 0; width--, column++ ) | |
109 { | |
110 FT_Byte* col = column; | |
111 FT_UInt fir[5]; | |
112 FT_UInt val1, yy; | |
113 | |
114 | |
115 val1 = col[0]; | |
116 fir[0] = weights[2] * val1; | |
117 fir[1] = weights[3] * val1; | |
118 fir[2] = weights[4] * val1; | |
119 fir[3] = 0; | |
120 fir[4] = 0; | |
121 col += pitch; | |
122 | |
123 val1 = col[0]; | |
124 fir[0] += weights[1] * val1; | |
125 fir[1] += weights[2] * val1; | |
126 fir[2] += weights[3] * val1; | |
127 fir[3] += weights[4] * val1; | |
128 col += pitch; | |
129 | |
130 for ( yy = 2; yy < height; yy++ ) | |
131 { | |
132 FT_UInt val, pix; | |
133 | |
134 | |
135 val = col[0]; | |
136 pix = fir[0] + weights[0] * val; | |
137 fir[0] = fir[1] + weights[1] * val; | |
138 fir[1] = fir[2] + weights[2] * val; | |
139 fir[2] = fir[3] + weights[3] * val; | |
140 fir[3] = weights[4] * val; | |
141 | |
142 pix >>= 8; | |
143 pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); | |
144 col[-2 * pitch] = (FT_Byte)pix; | |
145 col += pitch; | |
146 } | |
147 | |
148 { | |
149 FT_UInt pix; | |
150 | |
151 | |
152 pix = fir[0] >> 8; | |
153 pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); | |
154 col[-2 * pitch] = (FT_Byte)pix; | |
155 | |
156 pix = fir[1] >> 8; | |
157 pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); | |
158 col[-pitch] = (FT_Byte)pix; | |
159 } | |
160 } | |
161 } | |
162 } | |
163 | |
164 | |
165 #ifdef USE_LEGACY | |
166 | |
167 /* intra-pixel filter used by the legacy filter */ | |
168 static void | |
169 _ft_lcd_filter_legacy( FT_Bitmap* bitmap, | |
170 FT_Render_Mode mode, | |
171 FT_Library library ) | |
172 { | |
173 FT_UInt width = (FT_UInt)bitmap->width; | |
174 FT_UInt height = (FT_UInt)bitmap->rows; | |
175 FT_Int pitch = bitmap->pitch; | |
176 | |
177 static const int filters[3][3] = | |
178 { | |
179 { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 }, | |
180 { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 }, | |
181 { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 } | |
182 }; | |
183 | |
184 FT_UNUSED( library ); | |
185 | |
186 | |
187 /* horizontal in-place intra-pixel filter */ | |
188 if ( mode == FT_RENDER_MODE_LCD && width >= 3 ) | |
189 { | |
190 FT_Byte* line = bitmap->buffer; | |
191 | |
192 | |
193 for ( ; height > 0; height--, line += pitch ) | |
194 { | |
195 FT_UInt xx; | |
196 | |
197 | |
198 for ( xx = 0; xx < width; xx += 3 ) | |
199 { | |
200 FT_UInt r = 0; | |
201 FT_UInt g = 0; | |
202 FT_UInt b = 0; | |
203 FT_UInt p; | |
204 | |
205 | |
206 p = line[xx]; | |
207 r += filters[0][0] * p; | |
208 g += filters[0][1] * p; | |
209 b += filters[0][2] * p; | |
210 | |
211 p = line[xx + 1]; | |
212 r += filters[1][0] * p; | |
213 g += filters[1][1] * p; | |
214 b += filters[1][2] * p; | |
215 | |
216 p = line[xx + 2]; | |
217 r += filters[2][0] * p; | |
218 g += filters[2][1] * p; | |
219 b += filters[2][2] * p; | |
220 | |
221 line[xx] = (FT_Byte)( r / 65536 ); | |
222 line[xx + 1] = (FT_Byte)( g / 65536 ); | |
223 line[xx + 2] = (FT_Byte)( b / 65536 ); | |
224 } | |
225 } | |
226 } | |
227 else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 ) | |
228 { | |
229 FT_Byte* column = bitmap->buffer; | |
230 | |
231 | |
232 for ( ; width > 0; width--, column++ ) | |
233 { | |
234 FT_Byte* col = column; | |
235 FT_Byte* col_end = col + height * pitch; | |
236 | |
237 | |
238 for ( ; col < col_end; col += 3 * pitch ) | |
239 { | |
240 FT_UInt r = 0; | |
241 FT_UInt g = 0; | |
242 FT_UInt b = 0; | |
243 FT_UInt p; | |
244 | |
245 | |
246 p = col[0]; | |
247 r += filters[0][0] * p; | |
248 g += filters[0][1] * p; | |
249 b += filters[0][2] * p; | |
250 | |
251 p = col[pitch]; | |
252 r += filters[1][0] * p; | |
253 g += filters[1][1] * p; | |
254 b += filters[1][2] * p; | |
255 | |
256 p = col[pitch * 2]; | |
257 r += filters[2][0] * p; | |
258 g += filters[2][1] * p; | |
259 b += filters[2][2] * p; | |
260 | |
261 col[0] = (FT_Byte)( r / 65536 ); | |
262 col[pitch] = (FT_Byte)( g / 65536 ); | |
263 col[2 * pitch] = (FT_Byte)( b / 65536 ); | |
264 } | |
265 } | |
266 } | |
267 } | |
268 | |
269 #endif /* USE_LEGACY */ | |
270 | |
271 | |
272 FT_EXPORT_DEF( FT_Error ) | |
273 FT_Library_SetLcdFilterWeights( FT_Library library, | |
274 unsigned char *weights ) | |
275 { | |
276 if ( !library || !weights ) | |
277 return FT_THROW( Invalid_Argument ); | |
278 | |
279 ft_memcpy( library->lcd_weights, weights, 5 ); | |
280 | |
281 return FT_Err_Ok; | |
282 } | |
283 | |
284 | |
285 FT_EXPORT_DEF( FT_Error ) | |
286 FT_Library_SetLcdFilter( FT_Library library, | |
287 FT_LcdFilter filter ) | |
288 { | |
289 static const FT_Byte light_filter[5] = | |
290 { 0x00, 0x55, 0x56, 0x55, 0x00 }; | |
291 /* the values here sum up to a value larger than 256, */ | |
292 /* providing a cheap gamma correction */ | |
293 static const FT_Byte default_filter[5] = | |
294 { 0x10, 0x40, 0x70, 0x40, 0x10 }; | |
295 | |
296 | |
297 if ( !library ) | |
298 return FT_THROW( Invalid_Argument ); | |
299 | |
300 switch ( filter ) | |
301 { | |
302 case FT_LCD_FILTER_NONE: | |
303 library->lcd_filter_func = NULL; | |
304 library->lcd_extra = 0; | |
305 break; | |
306 | |
307 case FT_LCD_FILTER_DEFAULT: | |
308 #if defined( FT_FORCE_LEGACY_LCD_FILTER ) | |
309 | |
310 library->lcd_filter_func = _ft_lcd_filter_legacy; | |
311 library->lcd_extra = 0; | |
312 | |
313 #elif defined( FT_FORCE_LIGHT_LCD_FILTER ) | |
314 | |
315 ft_memcpy( library->lcd_weights, light_filter, 5 ); | |
316 library->lcd_filter_func = _ft_lcd_filter_fir; | |
317 library->lcd_extra = 2; | |
318 | |
319 #else | |
320 | |
321 ft_memcpy( library->lcd_weights, default_filter, 5 ); | |
322 library->lcd_filter_func = _ft_lcd_filter_fir; | |
323 library->lcd_extra = 2; | |
324 | |
325 #endif | |
326 | |
327 break; | |
328 | |
329 case FT_LCD_FILTER_LIGHT: | |
330 ft_memcpy( library->lcd_weights, light_filter, 5 ); | |
331 library->lcd_filter_func = _ft_lcd_filter_fir; | |
332 library->lcd_extra = 2; | |
333 break; | |
334 | |
335 #ifdef USE_LEGACY | |
336 | |
337 case FT_LCD_FILTER_LEGACY: | |
338 library->lcd_filter_func = _ft_lcd_filter_legacy; | |
339 library->lcd_extra = 0; | |
340 break; | |
341 | |
342 #endif | |
343 | |
344 default: | |
345 return FT_THROW( Invalid_Argument ); | |
346 } | |
347 | |
348 library->lcd_filter = filter; | |
349 | |
350 return FT_Err_Ok; | |
351 } | |
352 | |
353 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ | |
354 | |
355 FT_EXPORT_DEF( FT_Error ) | |
356 FT_Library_SetLcdFilterWeights( FT_Library library, | |
357 unsigned char *weights ) | |
358 { | |
359 FT_UNUSED( library ); | |
360 FT_UNUSED( weights ); | |
361 | |
362 return FT_THROW( Unimplemented_Feature ); | |
363 } | |
364 | |
365 | |
366 FT_EXPORT_DEF( FT_Error ) | |
367 FT_Library_SetLcdFilter( FT_Library library, | |
368 FT_LcdFilter filter ) | |
369 { | |
370 FT_UNUSED( library ); | |
371 FT_UNUSED( filter ); | |
372 | |
373 return FT_THROW( Unimplemented_Feature ); | |
374 } | |
375 | |
376 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ | |
377 | |
378 | |
379 /* END */ | |
380 #endif | |
381 | |
OLD | NEW |