1 /***************************************************************************/
5 /* FreeType API for color filtering of subpixel bitmap glyphs (body). */
7 /* Copyright 2006, 2008, 2009 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
16 /***************************************************************************/
20 #include FT_LCD_FILTER_H
22 #include FT_INTERNAL_OBJECTS_H
25 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
27 /* define USE_LEGACY to implement the legacy filter */
30 /* FIR filter used by the default and light filters */
32 _ft_lcd_filter_fir( FT_Bitmap
* bitmap
,
36 FT_Byte
* weights
= library
->lcd_weights
;
37 FT_UInt width
= (FT_UInt
)bitmap
->width
;
38 FT_UInt height
= (FT_UInt
)bitmap
->rows
;
41 /* horizontal in-place FIR filter */
42 if ( mode
== FT_RENDER_MODE_LCD
&& width
>= 4 )
44 FT_Byte
* line
= bitmap
->buffer
;
47 for ( ; height
> 0; height
--, line
+= bitmap
->pitch
)
54 fir
[0] = weights
[2] * val1
;
55 fir
[1] = weights
[3] * val1
;
56 fir
[2] = weights
[4] * val1
;
61 fir
[0] += weights
[1] * val1
;
62 fir
[1] += weights
[2] * val1
;
63 fir
[2] += weights
[3] * val1
;
64 fir
[3] += weights
[4] * val1
;
66 for ( xx
= 2; xx
< width
; xx
++ )
72 pix
= fir
[0] + weights
[0] * val
;
73 fir
[0] = fir
[1] + weights
[1] * val
;
74 fir
[1] = fir
[2] + weights
[2] * val
;
75 fir
[2] = fir
[3] + weights
[3] * val
;
76 fir
[3] = weights
[4] * val
;
80 line
[xx
- 2] = (FT_Byte
)pix
;
89 line
[xx
- 2] = (FT_Byte
)pix
;
93 line
[xx
- 1] = (FT_Byte
)pix
;
98 /* vertical in-place FIR filter */
99 else if ( mode
== FT_RENDER_MODE_LCD_V
&& height
>= 4 )
101 FT_Byte
* column
= bitmap
->buffer
;
102 FT_Int pitch
= bitmap
->pitch
;
105 for ( ; width
> 0; width
--, column
++ )
107 FT_Byte
* col
= column
;
113 fir
[0] = weights
[2] * val1
;
114 fir
[1] = weights
[3] * val1
;
115 fir
[2] = weights
[4] * val1
;
121 fir
[0] += weights
[1] * val1
;
122 fir
[1] += weights
[2] * val1
;
123 fir
[2] += weights
[3] * val1
;
124 fir
[3] += weights
[4] * val1
;
127 for ( yy
= 2; yy
< height
; yy
++ )
133 pix
= fir
[0] + weights
[0] * val
;
134 fir
[0] = fir
[1] + weights
[1] * val
;
135 fir
[1] = fir
[2] + weights
[2] * val
;
136 fir
[2] = fir
[3] + weights
[3] * val
;
137 fir
[3] = weights
[4] * val
;
140 pix
|= -( pix
>> 8 );
141 col
[-2 * pitch
] = (FT_Byte
)pix
;
150 pix
|= -( pix
>> 8 );
151 col
[-2 * pitch
] = (FT_Byte
)pix
;
154 pix
|= -( pix
>> 8 );
155 col
[-pitch
] = (FT_Byte
)pix
;
164 /* intra-pixel filter used by the legacy filter */
166 _ft_lcd_filter_legacy( FT_Bitmap
* bitmap
,
170 FT_UInt width
= (FT_UInt
)bitmap
->width
;
171 FT_UInt height
= (FT_UInt
)bitmap
->rows
;
172 FT_Int pitch
= bitmap
->pitch
;
174 static const int filters
[3][3] =
176 { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 },
177 { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 },
178 { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 }
181 FT_UNUSED( library
);
184 /* horizontal in-place intra-pixel filter */
185 if ( mode
== FT_RENDER_MODE_LCD
&& width
>= 3 )
187 FT_Byte
* line
= bitmap
->buffer
;
190 for ( ; height
> 0; height
--, line
+= pitch
)
195 for ( xx
= 0; xx
< width
; xx
+= 3 )
204 r
+= filters
[0][0] * p
;
205 g
+= filters
[0][1] * p
;
206 b
+= filters
[0][2] * p
;
209 r
+= filters
[1][0] * p
;
210 g
+= filters
[1][1] * p
;
211 b
+= filters
[1][2] * p
;
214 r
+= filters
[2][0] * p
;
215 g
+= filters
[2][1] * p
;
216 b
+= filters
[2][2] * p
;
218 line
[xx
] = (FT_Byte
)( r
/ 65536 );
219 line
[xx
+ 1] = (FT_Byte
)( g
/ 65536 );
220 line
[xx
+ 2] = (FT_Byte
)( b
/ 65536 );
224 else if ( mode
== FT_RENDER_MODE_LCD_V
&& height
>= 3 )
226 FT_Byte
* column
= bitmap
->buffer
;
229 for ( ; width
> 0; width
--, column
++ )
231 FT_Byte
* col
= column
;
232 FT_Byte
* col_end
= col
+ height
* pitch
;
235 for ( ; col
< col_end
; col
+= 3 * pitch
)
244 r
+= filters
[0][0] * p
;
245 g
+= filters
[0][1] * p
;
246 b
+= filters
[0][2] * p
;
249 r
+= filters
[1][0] * p
;
250 g
+= filters
[1][1] * p
;
251 b
+= filters
[1][2] * p
;
254 r
+= filters
[2][0] * p
;
255 g
+= filters
[2][1] * p
;
256 b
+= filters
[2][2] * p
;
258 col
[0] = (FT_Byte
)( r
/ 65536 );
259 col
[pitch
] = (FT_Byte
)( g
/ 65536 );
260 col
[2 * pitch
] = (FT_Byte
)( b
/ 65536 );
266 #endif /* USE_LEGACY */
269 FT_EXPORT_DEF( FT_Error
)
270 FT_Library_SetLcdFilter( FT_Library library
,
271 FT_LcdFilter filter
)
273 static const FT_Byte light_filter
[5] =
274 { 0, 85, 86, 85, 0 };
275 /* the values here sum up to a value larger than 256, */
276 /* providing a cheap gamma correction */
277 static const FT_Byte default_filter
[5] =
278 { 0x10, 0x40, 0x70, 0x40, 0x10 };
281 if ( library
== NULL
)
282 return FT_Err_Invalid_Argument
;
286 case FT_LCD_FILTER_NONE
:
287 library
->lcd_filter_func
= NULL
;
288 library
->lcd_extra
= 0;
291 case FT_LCD_FILTER_DEFAULT
:
292 #if defined( FT_FORCE_LEGACY_LCD_FILTER )
294 library
->lcd_filter_func
= _ft_lcd_filter_legacy
;
295 library
->lcd_extra
= 0;
297 #elif defined( FT_FORCE_LIGHT_LCD_FILTER )
299 ft_memcpy( library
->lcd_weights
, light_filter
, 5 );
300 library
->lcd_filter_func
= _ft_lcd_filter_fir
;
301 library
->lcd_extra
= 2;
305 ft_memcpy( library
->lcd_weights
, default_filter
, 5 );
306 library
->lcd_filter_func
= _ft_lcd_filter_fir
;
307 library
->lcd_extra
= 2;
313 case FT_LCD_FILTER_LIGHT
:
314 ft_memcpy( library
->lcd_weights
, light_filter
, 5 );
315 library
->lcd_filter_func
= _ft_lcd_filter_fir
;
316 library
->lcd_extra
= 2;
321 case FT_LCD_FILTER_LEGACY
:
322 library
->lcd_filter_func
= _ft_lcd_filter_legacy
;
323 library
->lcd_extra
= 0;
329 return FT_Err_Invalid_Argument
;
332 library
->lcd_filter
= filter
;
336 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
338 FT_EXPORT_DEF( FT_Error
)
339 FT_Library_SetLcdFilter( FT_Library library
,
340 FT_LcdFilter filter
)
342 FT_UNUSED( library
);
345 return FT_Err_Unimplemented_Feature
;
348 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */