ReactOS 0.4.15-dev-7953-g1f49173
ftlcdfil.c
Go to the documentation of this file.
1/***************************************************************************/
2/* */
3/* ftlcdfil.c */
4/* */
5/* FreeType API for color filtering of subpixel bitmap glyphs (body). */
6/* */
7/* Copyright 2006-2018 by */
8/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
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. */
15/* */
16/***************************************************************************/
17
18
19#include <ft2build.h>
20#include FT_INTERNAL_DEBUG_H
21
22#include FT_LCD_FILTER_H
23#include FT_IMAGE_H
24#include FT_INTERNAL_OBJECTS_H
25
26
27#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
28
29/* define USE_LEGACY to implement the legacy filter */
30#define USE_LEGACY
31
32#define FT_SHIFTCLAMP( x ) ( x >>= 8, (FT_Byte)( x > 255 ? 255 : x ) )
33
34
35 /* add padding according to filter weights */
36 FT_BASE_DEF (void)
38 FT_Pos* Max,
40 {
41 FT_Byte* lcd_weights;
42 FT_Bitmap_LcdFilterFunc lcd_filter_func;
43
44
45 /* Per-face LCD filtering takes priority if set up. */
46 if ( slot->face && slot->face->internal->lcd_filter_func )
47 {
48 lcd_weights = slot->face->internal->lcd_weights;
49 lcd_filter_func = slot->face->internal->lcd_filter_func;
50 }
51 else
52 {
53 lcd_weights = slot->library->lcd_weights;
54 lcd_filter_func = slot->library->lcd_filter_func;
55 }
56
57 if ( lcd_filter_func == ft_lcd_filter_fir )
58 {
59 *Min -= lcd_weights[0] ? 43 :
60 lcd_weights[1] ? 22 : 0;
61 *Max += lcd_weights[4] ? 43 :
62 lcd_weights[3] ? 22 : 0;
63 }
64 }
65
66
67 /* FIR filter used by the default and light filters */
68 FT_BASE_DEF( void )
69 ft_lcd_filter_fir( FT_Bitmap* bitmap,
72 {
75 FT_Int pitch = bitmap->pitch;
76 FT_Byte* origin = bitmap->buffer;
77
78
79 /* take care of bitmap flow */
80 if ( pitch > 0 )
81 origin += pitch * (FT_Int)( height - 1 );
82
83 /* horizontal in-place FIR filter */
84 if ( mode == FT_RENDER_MODE_LCD && width >= 2 )
85 {
87
88
89 /* `fir' must be at least 32 bit wide, since the sum of */
90 /* the values in `weights' can exceed 0xFF */
91
92 for ( ; height > 0; height--, line -= pitch )
93 {
94 FT_UInt fir[5];
95 FT_UInt val, xx;
96
97
98 val = line[0];
99 fir[2] = weights[2] * val;
100 fir[3] = weights[3] * val;
101 fir[4] = weights[4] * val;
102
103 val = line[1];
104 fir[1] = fir[2] + weights[1] * val;
105 fir[2] = fir[3] + weights[2] * val;
106 fir[3] = fir[4] + weights[3] * val;
107 fir[4] = weights[4] * val;
108
109 for ( xx = 2; xx < width; xx++ )
110 {
111 val = line[xx];
112 fir[0] = fir[1] + weights[0] * val;
113 fir[1] = fir[2] + weights[1] * val;
114 fir[2] = fir[3] + weights[2] * val;
115 fir[3] = fir[4] + weights[3] * val;
116 fir[4] = weights[4] * val;
117
118 line[xx - 2] = FT_SHIFTCLAMP( fir[0] );
119 }
120
121 line[xx - 2] = FT_SHIFTCLAMP( fir[1] );
122 line[xx - 1] = FT_SHIFTCLAMP( fir[2] );
123 }
124 }
125
126 /* vertical in-place FIR filter */
127 else if ( mode == FT_RENDER_MODE_LCD_V && height >= 2 )
128 {
130
131
132 for ( ; width > 0; width--, column++ )
133 {
134 FT_Byte* col = column;
135 FT_UInt fir[5];
136 FT_UInt val, yy;
137
138
139 val = col[0];
140 fir[2] = weights[2] * val;
141 fir[3] = weights[3] * val;
142 fir[4] = weights[4] * val;
143 col -= pitch;
144
145 val = col[0];
146 fir[1] = fir[2] + weights[1] * val;
147 fir[2] = fir[3] + weights[2] * val;
148 fir[3] = fir[4] + weights[3] * val;
149 fir[4] = weights[4] * val;
150 col -= pitch;
151
152 for ( yy = 2; yy < height; yy++, col -= pitch )
153 {
154 val = col[0];
155 fir[0] = fir[1] + weights[0] * val;
156 fir[1] = fir[2] + weights[1] * val;
157 fir[2] = fir[3] + weights[2] * val;
158 fir[3] = fir[4] + weights[3] * val;
159 fir[4] = weights[4] * val;
160
161 col[pitch * 2] = FT_SHIFTCLAMP( fir[0] );
162 }
163
164 col[pitch * 2] = FT_SHIFTCLAMP( fir[1] );
165 col[pitch] = FT_SHIFTCLAMP( fir[2] );
166 }
167 }
168 }
169
170
171#ifdef USE_LEGACY
172
173 /* intra-pixel filter used by the legacy filter */
174 static void
175 _ft_lcd_filter_legacy( FT_Bitmap* bitmap,
178 {
180 FT_UInt height = (FT_UInt)bitmap->rows;
181 FT_Int pitch = bitmap->pitch;
182 FT_Byte* origin = bitmap->buffer;
183
184 static const unsigned int filters[3][3] =
185 {
186 { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 },
187 { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 },
188 { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 }
189 };
190
192
193
194 /* take care of bitmap flow */
195 if ( pitch > 0 )
196 origin += pitch * (FT_Int)( height - 1 );
197
198 /* horizontal in-place intra-pixel filter */
199 if ( mode == FT_RENDER_MODE_LCD && width >= 3 )
200 {
202
203
204 for ( ; height > 0; height--, line -= pitch )
205 {
206 FT_UInt xx;
207
208
209 for ( xx = 0; xx < width; xx += 3 )
210 {
211 FT_UInt r, g, b;
212 FT_UInt p;
213
214
215 p = line[xx];
216 r = filters[0][0] * p;
217 g = filters[0][1] * p;
218 b = filters[0][2] * p;
219
220 p = line[xx + 1];
221 r += filters[1][0] * p;
222 g += filters[1][1] * p;
223 b += filters[1][2] * p;
224
225 p = line[xx + 2];
226 r += filters[2][0] * p;
227 g += filters[2][1] * p;
228 b += filters[2][2] * p;
229
230 line[xx] = (FT_Byte)( r / 65536 );
231 line[xx + 1] = (FT_Byte)( g / 65536 );
232 line[xx + 2] = (FT_Byte)( b / 65536 );
233 }
234 }
235 }
236 else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 )
237 {
239
240
241 for ( ; width > 0; width--, column++ )
242 {
243 FT_Byte* col = column - 2 * pitch;
244
245
246 for ( ; height > 0; height -= 3, col -= 3 * pitch )
247 {
248 FT_UInt r, g, b;
249 FT_UInt p;
250
251
252 p = col[0];
253 r = filters[0][0] * p;
254 g = filters[0][1] * p;
255 b = filters[0][2] * p;
256
257 p = col[pitch];
258 r += filters[1][0] * p;
259 g += filters[1][1] * p;
260 b += filters[1][2] * p;
261
262 p = col[pitch * 2];
263 r += filters[2][0] * p;
264 g += filters[2][1] * p;
265 b += filters[2][2] * p;
266
267 col[0] = (FT_Byte)( r / 65536 );
268 col[pitch] = (FT_Byte)( g / 65536 );
269 col[pitch * 2] = (FT_Byte)( b / 65536 );
270 }
271 }
272 }
273 }
274
275#endif /* USE_LEGACY */
276
277
280 unsigned char *weights )
281 {
282 if ( !library )
283 return FT_THROW( Invalid_Library_Handle );
284
285 if ( !weights )
286 return FT_THROW( Invalid_Argument );
287
289 library->lcd_filter_func = ft_lcd_filter_fir;
290
291 return FT_Err_Ok;
292 }
293
294
298 {
299 static const FT_LcdFiveTapFilter default_weights =
300 { 0x08, 0x4d, 0x56, 0x4d, 0x08 };
301 static const FT_LcdFiveTapFilter light_weights =
302 { 0x00, 0x55, 0x56, 0x55, 0x00 };
303
304
305 if ( !library )
306 return FT_THROW( Invalid_Library_Handle );
307
308 switch ( filter )
309 {
311 library->lcd_filter_func = NULL;
312 break;
313
315 ft_memcpy( library->lcd_weights,
316 default_weights,
318 library->lcd_filter_func = ft_lcd_filter_fir;
319 break;
320
322 ft_memcpy( library->lcd_weights,
323 light_weights,
325 library->lcd_filter_func = ft_lcd_filter_fir;
326 break;
327
328#ifdef USE_LEGACY
329
332 library->lcd_filter_func = _ft_lcd_filter_legacy;
333 break;
334
335#endif
336
337 default:
338 return FT_THROW( Invalid_Argument );
339 }
340
341 return FT_Err_Ok;
342 }
343
344#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
345
346 /* add padding according to accommodate outline shifts */
347 FT_BASE_DEF (void)
349 FT_Pos* Max,
351 {
352 FT_UNUSED( slot );
353
354 *Min -= 21;
355 *Max += 21;
356 }
357
358
361 unsigned char *weights )
362 {
365
366 return FT_THROW( Unimplemented_Feature );
367 }
368
369
373 {
375 FT_UNUSED( filter );
376
377 return FT_THROW( Unimplemented_Feature );
378 }
379
380#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
381
382
383/* END */
#define Max(a, b)
Definition: cdprocs.h:78
#define Min(a, b)
Definition: cdprocs.h:74
FT_Library library
Definition: cffdrivr.c:654
#define NULL
Definition: types.h:112
enum FT_Render_Mode_ FT_Render_Mode
@ FT_RENDER_MODE_LCD_V
Definition: freetype.h:3238
@ FT_RENDER_MODE_LCD
Definition: freetype.h:3237
return FT_Err_Ok
Definition: ftbbox.c:511
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
#define FT_EXPORT_DEF(x)
Definition: ftconfig.h:483
#define FT_BASE_DEF(x)
Definition: ftconfig.h:419
#define FT_THROW(e)
Definition: ftdebug.h:213
FT_BEGIN_HEADER typedef signed long FT_Pos
Definition: ftimage.h:58
FT_Library_SetLcdFilter(FT_Library library, FT_LcdFilter filter)
Definition: ftlcdfil.c:371
FT_Library_SetLcdFilterWeights(FT_Library library, unsigned char *weights)
Definition: ftlcdfil.c:360
ft_lcd_padding(FT_Pos *Min, FT_Pos *Max, FT_GlyphSlot slot)
Definition: ftlcdfil.c:348
@ FT_LCD_FILTER_LIGHT
Definition: ftlcdfil.h:194
@ FT_LCD_FILTER_LEGACY1
Definition: ftlcdfil.h:195
@ FT_LCD_FILTER_LEGACY
Definition: ftlcdfil.h:196
@ FT_LCD_FILTER_DEFAULT
Definition: ftlcdfil.h:193
@ FT_LCD_FILTER_NONE
Definition: ftlcdfil.h:192
#define FT_LCD_FILTER_FIVE_TAPS
Definition: ftlcdfil.h:296
FT_BEGIN_HEADER enum FT_LcdFilter_ FT_LcdFilter
FT_Byte FT_LcdFiveTapFilter[FT_LCD_FILTER_FIVE_TAPS]
Definition: ftlcdfil.h:298
#define ft_memcpy
Definition: ftstdlib.h:82
unsigned char FT_Byte
Definition: fttypes.h:154
int FT_Error
Definition: fttypes.h:300
unsigned int FT_UInt
Definition: fttypes.h:231
signed int FT_Int
Definition: fttypes.h:220
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLint GLint GLsizei width
Definition: gl.h:1546
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum mode
Definition: glext.h:6217
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glext.h:7005
GLboolean GLboolean g
Definition: glext.h:6204
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
const GLbyte * weights
Definition: glext.h:6523
voidpf uLong int origin
Definition: ioapi.h:144
#define b
Definition: ke_i.h:79
int xx
Definition: npserver.c:29
Definition: vfat.h:185
Definition: uimain.c:89
uint32 width
Definition: uimain.c:91
Definition: parser.c:49