ReactOS 0.4.16-dev-2354-g16de117
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 (C) 2006-2020 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
20
21#include <freetype/ftlcdfil.h>
22#include <freetype/ftimage.h>
24
25
26#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
27
28/* define USE_LEGACY to implement the legacy filter */
29#define USE_LEGACY
30
31#define FT_SHIFTCLAMP( x ) ( x >>= 8, (FT_Byte)( x > 255 ? 255 : x ) )
32
33
34 /* add padding according to filter weights */
35 FT_BASE_DEF (void)
39 {
40 FT_Byte* lcd_weights;
41 FT_Bitmap_LcdFilterFunc lcd_filter_func;
42
43
44 /* Per-face LCD filtering takes priority if set up. */
45 if ( slot->face && slot->face->internal->lcd_filter_func )
46 {
47 lcd_weights = slot->face->internal->lcd_weights;
48 lcd_filter_func = slot->face->internal->lcd_filter_func;
49 }
50 else
51 {
52 lcd_weights = slot->library->lcd_weights;
53 lcd_filter_func = slot->library->lcd_filter_func;
54 }
55
56 if ( lcd_filter_func == ft_lcd_filter_fir )
57 {
58 if ( mode == FT_RENDER_MODE_LCD )
59 {
60 cbox->xMin -= lcd_weights[0] ? 43 :
61 lcd_weights[1] ? 22 : 0;
62 cbox->xMax += lcd_weights[4] ? 43 :
63 lcd_weights[3] ? 22 : 0;
64 }
65 else if ( mode == FT_RENDER_MODE_LCD_V )
66 {
67 cbox->yMin -= lcd_weights[0] ? 43 :
68 lcd_weights[1] ? 22 : 0;
69 cbox->yMax += lcd_weights[4] ? 43 :
70 lcd_weights[3] ? 22 : 0;
71 }
72 }
73 }
74
75
76 /* FIR filter used by the default and light filters */
77 FT_BASE_DEF( void )
78 ft_lcd_filter_fir( FT_Bitmap* bitmap,
80 {
83 FT_Int pitch = bitmap->pitch;
84 FT_Byte* origin = bitmap->buffer;
85 FT_Byte mode = bitmap->pixel_mode;
86
87
88 /* take care of bitmap flow */
89 if ( pitch > 0 && height > 0 )
90 origin += pitch * (FT_Int)( height - 1 );
91
92 /* horizontal in-place FIR filter */
93 if ( mode == FT_PIXEL_MODE_LCD && width >= 2 )
94 {
96
97
98 /* `fir' must be at least 32 bit wide, since the sum of */
99 /* the values in `weights' can exceed 0xFF */
100
101 for ( ; height > 0; height--, line -= pitch )
102 {
103 FT_UInt fir[5];
104 FT_UInt val, xx;
105
106
107 val = line[0];
108 fir[2] = weights[2] * val;
109 fir[3] = weights[3] * val;
110 fir[4] = weights[4] * val;
111
112 val = line[1];
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 for ( xx = 2; xx < width; xx++ )
119 {
120 val = line[xx];
121 fir[0] = fir[1] + weights[0] * val;
122 fir[1] = fir[2] + weights[1] * val;
123 fir[2] = fir[3] + weights[2] * val;
124 fir[3] = fir[4] + weights[3] * val;
125 fir[4] = weights[4] * val;
126
127 line[xx - 2] = FT_SHIFTCLAMP( fir[0] );
128 }
129
130 line[xx - 2] = FT_SHIFTCLAMP( fir[1] );
131 line[xx - 1] = FT_SHIFTCLAMP( fir[2] );
132 }
133 }
134
135 /* vertical in-place FIR filter */
136 else if ( mode == FT_PIXEL_MODE_LCD_V && height >= 2 )
137 {
139
140
141 for ( ; width > 0; width--, column++ )
142 {
143 FT_Byte* col = column;
144 FT_UInt fir[5];
145 FT_UInt val, yy;
146
147
148 val = col[0];
149 fir[2] = weights[2] * val;
150 fir[3] = weights[3] * val;
151 fir[4] = weights[4] * val;
152 col -= pitch;
153
154 val = col[0];
155 fir[1] = fir[2] + weights[1] * val;
156 fir[2] = fir[3] + weights[2] * val;
157 fir[3] = fir[4] + weights[3] * val;
158 fir[4] = weights[4] * val;
159 col -= pitch;
160
161 for ( yy = 2; yy < height; yy++, col -= pitch )
162 {
163 val = col[0];
164 fir[0] = fir[1] + weights[0] * val;
165 fir[1] = fir[2] + weights[1] * val;
166 fir[2] = fir[3] + weights[2] * val;
167 fir[3] = fir[4] + weights[3] * val;
168 fir[4] = weights[4] * val;
169
170 col[pitch * 2] = FT_SHIFTCLAMP( fir[0] );
171 }
172
173 col[pitch * 2] = FT_SHIFTCLAMP( fir[1] );
174 col[pitch] = FT_SHIFTCLAMP( fir[2] );
175 }
176 }
177 }
178
179
180#ifdef USE_LEGACY
181
182 /* intra-pixel filter used by the legacy filter */
183 static void
184 _ft_lcd_filter_legacy( FT_Bitmap* bitmap,
186 {
188 FT_UInt height = (FT_UInt)bitmap->rows;
189 FT_Int pitch = bitmap->pitch;
190 FT_Byte* origin = bitmap->buffer;
191 FT_Byte mode = bitmap->pixel_mode;
192
193 static const unsigned int filters[3][3] =
194 {
195 { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 },
196 { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 },
197 { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 }
198 };
199
201
202
203 /* take care of bitmap flow */
204 if ( pitch > 0 && height > 0 )
205 origin += pitch * (FT_Int)( height - 1 );
206
207 /* horizontal in-place intra-pixel filter */
208 if ( mode == FT_PIXEL_MODE_LCD && width >= 3 )
209 {
211
212
213 for ( ; height > 0; height--, line -= pitch )
214 {
215 FT_UInt xx;
216
217
218 for ( xx = 0; xx < width; xx += 3 )
219 {
220 FT_UInt r, g, b;
221 FT_UInt p;
222
223
224 p = line[xx];
225 r = filters[0][0] * p;
226 g = filters[0][1] * p;
227 b = filters[0][2] * p;
228
229 p = line[xx + 1];
230 r += filters[1][0] * p;
231 g += filters[1][1] * p;
232 b += filters[1][2] * p;
233
234 p = line[xx + 2];
235 r += filters[2][0] * p;
236 g += filters[2][1] * p;
237 b += filters[2][2] * p;
238
239 line[xx] = (FT_Byte)( r / 65536 );
240 line[xx + 1] = (FT_Byte)( g / 65536 );
241 line[xx + 2] = (FT_Byte)( b / 65536 );
242 }
243 }
244 }
245 else if ( mode == FT_PIXEL_MODE_LCD_V && height >= 3 )
246 {
248
249
250 for ( ; width > 0; width--, column++ )
251 {
252 FT_Byte* col = column - 2 * pitch;
253
254
255 for ( ; height > 0; height -= 3, col -= 3 * pitch )
256 {
257 FT_UInt r, g, b;
258 FT_UInt p;
259
260
261 p = col[0];
262 r = filters[0][0] * p;
263 g = filters[0][1] * p;
264 b = filters[0][2] * p;
265
266 p = col[pitch];
267 r += filters[1][0] * p;
268 g += filters[1][1] * p;
269 b += filters[1][2] * p;
270
271 p = col[pitch * 2];
272 r += filters[2][0] * p;
273 g += filters[2][1] * p;
274 b += filters[2][2] * p;
275
276 col[0] = (FT_Byte)( r / 65536 );
277 col[pitch] = (FT_Byte)( g / 65536 );
278 col[pitch * 2] = (FT_Byte)( b / 65536 );
279 }
280 }
281 }
282 }
283
284#endif /* USE_LEGACY */
285
286
287 /* documentation in ftlcdfil.h */
288
291 unsigned char *weights )
292 {
293 if ( !library )
294 return FT_THROW( Invalid_Library_Handle );
295
296 if ( !weights )
297 return FT_THROW( Invalid_Argument );
298
300 library->lcd_filter_func = ft_lcd_filter_fir;
301
302 return FT_Err_Ok;
303 }
304
305
306 /* documentation in ftlcdfil.h */
307
311 {
312 static const FT_LcdFiveTapFilter default_weights =
313 { 0x08, 0x4d, 0x56, 0x4d, 0x08 };
314 static const FT_LcdFiveTapFilter light_weights =
315 { 0x00, 0x55, 0x56, 0x55, 0x00 };
316
317
318 if ( !library )
319 return FT_THROW( Invalid_Library_Handle );
320
321 switch ( filter )
322 {
324 library->lcd_filter_func = NULL;
325 break;
326
328 ft_memcpy( library->lcd_weights,
329 default_weights,
331 library->lcd_filter_func = ft_lcd_filter_fir;
332 break;
333
335 ft_memcpy( library->lcd_weights,
336 light_weights,
338 library->lcd_filter_func = ft_lcd_filter_fir;
339 break;
340
341#ifdef USE_LEGACY
342
345 library->lcd_filter_func = _ft_lcd_filter_legacy;
346 break;
347
348#endif
349
350 default:
351 return FT_THROW( Invalid_Argument );
352 }
353
354 return FT_Err_Ok;
355 }
356
357
360 FT_Vector* sub )
361 {
363 FT_UNUSED( sub );
364
365 return FT_THROW( Unimplemented_Feature );
366 }
367
368#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
369
370 /* add padding to accommodate outline shifts */
371 FT_BASE_DEF (void)
375 {
376 FT_Vector* sub = slot->library->lcd_geometry;
377
378 if ( mode == FT_RENDER_MODE_LCD )
379 {
380 cbox->xMin -= FT_MAX( FT_MAX( sub[0].x, sub[1].x ), sub[2].x );
381 cbox->xMax -= FT_MIN( FT_MIN( sub[0].x, sub[1].x ), sub[2].x );
382 cbox->yMin -= FT_MAX( FT_MAX( sub[0].y, sub[1].y ), sub[2].y );
383 cbox->yMax -= FT_MIN( FT_MIN( sub[0].y, sub[1].y ), sub[2].y );
384 }
385 else if ( mode == FT_RENDER_MODE_LCD_V )
386 {
387 cbox->xMin -= FT_MAX( FT_MAX( sub[0].y, sub[1].y ), sub[2].y );
388 cbox->xMax -= FT_MIN( FT_MIN( sub[0].y, sub[1].y ), sub[2].y );
389 cbox->yMin += FT_MIN( FT_MIN( sub[0].x, sub[1].x ), sub[2].x );
390 cbox->yMax += FT_MAX( FT_MAX( sub[0].x, sub[1].x ), sub[2].x );
391 }
392 }
393
394
397 unsigned char *weights )
398 {
401
402 return FT_THROW( Unimplemented_Feature );
403 }
404
405
409 {
411 FT_UNUSED( filter );
412
413 return FT_THROW( Unimplemented_Feature );
414 }
415
416
417 /* documentation in ftlcdfil.h */
418
421 FT_Vector sub[3] )
422 {
423 if ( !library )
424 return FT_THROW( Invalid_Library_Handle );
425
426 if ( !sub )
427 return FT_THROW( Invalid_Argument );
428
429 ft_memcpy( library->lcd_geometry, sub, 3 * sizeof( FT_Vector ) );
430
431 return FT_THROW( Unimplemented_Feature );
432 }
433
434#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
435
436
437/* END */
FT_Library library
Definition: cffdrivr.c:660
#define FT_EXPORT_DEF(x)
#define FT_BASE_DEF(x)
#define NULL
Definition: types.h:112
enum FT_Render_Mode_ FT_Render_Mode
@ FT_RENDER_MODE_LCD_V
Definition: freetype.h:3253
@ FT_RENDER_MODE_LCD
Definition: freetype.h:3252
return FT_Err_Ok
Definition: ftbbox.c:526
#define FT_THROW(e)
Definition: ftdebug.h:243
@ FT_PIXEL_MODE_LCD_V
Definition: ftimage.h:188
@ FT_PIXEL_MODE_LCD
Definition: ftimage.h:187
FT_Library_SetLcdFilter(FT_Library library, FT_LcdFilter filter)
Definition: ftlcdfil.c:407
FT_Library_SetLcdGeometry(FT_Library library, FT_Vector sub[3])
Definition: ftlcdfil.c:420
FT_Library_SetLcdFilterWeights(FT_Library library, unsigned char *weights)
Definition: ftlcdfil.c:396
ft_lcd_padding(FT_BBox *cbox, FT_GlyphSlot slot, FT_Render_Mode mode)
Definition: ftlcdfil.c:372
@ FT_LCD_FILTER_LIGHT
Definition: ftlcdfil.h:164
@ FT_LCD_FILTER_LEGACY1
Definition: ftlcdfil.h:165
@ FT_LCD_FILTER_LEGACY
Definition: ftlcdfil.h:166
@ FT_LCD_FILTER_DEFAULT
Definition: ftlcdfil.h:163
@ FT_LCD_FILTER_NONE
Definition: ftlcdfil.h:162
#define FT_LCD_FILTER_FIVE_TAPS
Definition: ftlcdfil.h:264
FT_BEGIN_HEADER enum FT_LcdFilter_ FT_LcdFilter
FT_Byte FT_LcdFiveTapFilter[FT_LCD_FILTER_FIVE_TAPS]
Definition: ftlcdfil.h:266
#define FT_MIN(a, b)
Definition: ftobjs.h:70
#define FT_MAX(a, b)
Definition: ftobjs.h:71
#define ft_memcpy
Definition: ftstdlib.h:82
unsigned char FT_Byte
Definition: fttypes.h:154
int FT_Error
Definition: fttypes.h:299
unsigned int FT_UInt
Definition: fttypes.h:231
signed int FT_Int
Definition: fttypes.h:220
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
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
#define FT_UNUSED(arg)
FT_Pos xMin
Definition: ftimage.h:120
FT_Pos yMax
Definition: ftimage.h:121
FT_Pos yMin
Definition: ftimage.h:120
FT_Pos xMax
Definition: ftimage.h:121
FT_Vector lcd_geometry[3]
Definition: ftobjs.h:914
Definition: vfat.h:185
Definition: uimain.c:89
uint32 width
Definition: uimain.c:91
Definition: parser.c:49