ReactOS 0.4.16-dev-1025-gd3456f5
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-2019 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)
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 if ( mode == FT_RENDER_MODE_LCD )
60 {
61 cbox->xMin -= lcd_weights[0] ? 43 :
62 lcd_weights[1] ? 22 : 0;
63 cbox->xMax += lcd_weights[4] ? 43 :
64 lcd_weights[3] ? 22 : 0;
65 }
66 else if ( mode == FT_RENDER_MODE_LCD_V )
67 {
68 cbox->yMin -= lcd_weights[0] ? 43 :
69 lcd_weights[1] ? 22 : 0;
70 cbox->yMax += lcd_weights[4] ? 43 :
71 lcd_weights[3] ? 22 : 0;
72 }
73 }
74 }
75
76
77 /* FIR filter used by the default and light filters */
78 FT_BASE_DEF( void )
79 ft_lcd_filter_fir( FT_Bitmap* bitmap,
82 {
85 FT_Int pitch = bitmap->pitch;
86 FT_Byte* origin = bitmap->buffer;
87
88
89 /* take care of bitmap flow */
90 if ( pitch > 0 && height > 0 )
91 origin += pitch * (FT_Int)( height - 1 );
92
93 /* horizontal in-place FIR filter */
94 if ( mode == FT_RENDER_MODE_LCD && width >= 2 )
95 {
97
98
99 /* `fir' must be at least 32 bit wide, since the sum of */
100 /* the values in `weights' can exceed 0xFF */
101
102 for ( ; height > 0; height--, line -= pitch )
103 {
104 FT_UInt fir[5];
105 FT_UInt val, xx;
106
107
108 val = line[0];
109 fir[2] = weights[2] * val;
110 fir[3] = weights[3] * val;
111 fir[4] = weights[4] * val;
112
113 val = line[1];
114 fir[1] = fir[2] + weights[1] * val;
115 fir[2] = fir[3] + weights[2] * val;
116 fir[3] = fir[4] + weights[3] * val;
117 fir[4] = weights[4] * val;
118
119 for ( xx = 2; xx < width; xx++ )
120 {
121 val = line[xx];
122 fir[0] = fir[1] + weights[0] * val;
123 fir[1] = fir[2] + weights[1] * val;
124 fir[2] = fir[3] + weights[2] * val;
125 fir[3] = fir[4] + weights[3] * val;
126 fir[4] = weights[4] * val;
127
128 line[xx - 2] = FT_SHIFTCLAMP( fir[0] );
129 }
130
131 line[xx - 2] = FT_SHIFTCLAMP( fir[1] );
132 line[xx - 1] = FT_SHIFTCLAMP( fir[2] );
133 }
134 }
135
136 /* vertical in-place FIR filter */
137 else if ( mode == FT_RENDER_MODE_LCD_V && height >= 2 )
138 {
140
141
142 for ( ; width > 0; width--, column++ )
143 {
144 FT_Byte* col = column;
145 FT_UInt fir[5];
146 FT_UInt val, yy;
147
148
149 val = col[0];
150 fir[2] = weights[2] * val;
151 fir[3] = weights[3] * val;
152 fir[4] = weights[4] * val;
153 col -= pitch;
154
155 val = col[0];
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 col -= pitch;
161
162 for ( yy = 2; yy < height; yy++, col -= pitch )
163 {
164 val = col[0];
165 fir[0] = fir[1] + weights[0] * val;
166 fir[1] = fir[2] + weights[1] * val;
167 fir[2] = fir[3] + weights[2] * val;
168 fir[3] = fir[4] + weights[3] * val;
169 fir[4] = weights[4] * val;
170
171 col[pitch * 2] = FT_SHIFTCLAMP( fir[0] );
172 }
173
174 col[pitch * 2] = FT_SHIFTCLAMP( fir[1] );
175 col[pitch] = FT_SHIFTCLAMP( fir[2] );
176 }
177 }
178 }
179
180
181#ifdef USE_LEGACY
182
183 /* intra-pixel filter used by the legacy filter */
184 static void
185 _ft_lcd_filter_legacy( FT_Bitmap* bitmap,
188 {
190 FT_UInt height = (FT_UInt)bitmap->rows;
191 FT_Int pitch = bitmap->pitch;
192 FT_Byte* origin = bitmap->buffer;
193
194 static const unsigned int filters[3][3] =
195 {
196 { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 },
197 { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 },
198 { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 }
199 };
200
202
203
204 /* take care of bitmap flow */
205 if ( pitch > 0 && height > 0 )
206 origin += pitch * (FT_Int)( height - 1 );
207
208 /* horizontal in-place intra-pixel filter */
209 if ( mode == FT_RENDER_MODE_LCD && width >= 3 )
210 {
212
213
214 for ( ; height > 0; height--, line -= pitch )
215 {
216 FT_UInt xx;
217
218
219 for ( xx = 0; xx < width; xx += 3 )
220 {
221 FT_UInt r, g, b;
222 FT_UInt p;
223
224
225 p = line[xx];
226 r = filters[0][0] * p;
227 g = filters[0][1] * p;
228 b = filters[0][2] * p;
229
230 p = line[xx + 1];
231 r += filters[1][0] * p;
232 g += filters[1][1] * p;
233 b += filters[1][2] * p;
234
235 p = line[xx + 2];
236 r += filters[2][0] * p;
237 g += filters[2][1] * p;
238 b += filters[2][2] * p;
239
240 line[xx] = (FT_Byte)( r / 65536 );
241 line[xx + 1] = (FT_Byte)( g / 65536 );
242 line[xx + 2] = (FT_Byte)( b / 65536 );
243 }
244 }
245 }
246 else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 )
247 {
249
250
251 for ( ; width > 0; width--, column++ )
252 {
253 FT_Byte* col = column - 2 * pitch;
254
255
256 for ( ; height > 0; height -= 3, col -= 3 * pitch )
257 {
258 FT_UInt r, g, b;
259 FT_UInt p;
260
261
262 p = col[0];
263 r = filters[0][0] * p;
264 g = filters[0][1] * p;
265 b = filters[0][2] * p;
266
267 p = col[pitch];
268 r += filters[1][0] * p;
269 g += filters[1][1] * p;
270 b += filters[1][2] * p;
271
272 p = col[pitch * 2];
273 r += filters[2][0] * p;
274 g += filters[2][1] * p;
275 b += filters[2][2] * p;
276
277 col[0] = (FT_Byte)( r / 65536 );
278 col[pitch] = (FT_Byte)( g / 65536 );
279 col[pitch * 2] = (FT_Byte)( b / 65536 );
280 }
281 }
282 }
283 }
284
285#endif /* USE_LEGACY */
286
287
288 /* documentation in ftlcdfil.h */
289
292 unsigned char *weights )
293 {
294 if ( !library )
295 return FT_THROW( Invalid_Library_Handle );
296
297 if ( !weights )
298 return FT_THROW( Invalid_Argument );
299
301 library->lcd_filter_func = ft_lcd_filter_fir;
302
303 return FT_Err_Ok;
304 }
305
306
307 /* documentation in ftlcdfil.h */
308
312 {
313 static const FT_LcdFiveTapFilter default_weights =
314 { 0x08, 0x4d, 0x56, 0x4d, 0x08 };
315 static const FT_LcdFiveTapFilter light_weights =
316 { 0x00, 0x55, 0x56, 0x55, 0x00 };
317
318
319 if ( !library )
320 return FT_THROW( Invalid_Library_Handle );
321
322 switch ( filter )
323 {
325 library->lcd_filter_func = NULL;
326 break;
327
329 ft_memcpy( library->lcd_weights,
330 default_weights,
332 library->lcd_filter_func = ft_lcd_filter_fir;
333 break;
334
336 ft_memcpy( library->lcd_weights,
337 light_weights,
339 library->lcd_filter_func = ft_lcd_filter_fir;
340 break;
341
342#ifdef USE_LEGACY
343
346 library->lcd_filter_func = _ft_lcd_filter_legacy;
347 break;
348
349#endif
350
351 default:
352 return FT_THROW( Invalid_Argument );
353 }
354
355 return FT_Err_Ok;
356 }
357
358
361 FT_Vector* sub )
362 {
364 FT_UNUSED( sub );
365
366 return FT_THROW( Unimplemented_Feature );
367 }
368
369#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
370
371 /* add padding to accommodate outline shifts */
372 FT_BASE_DEF (void)
376 {
377 FT_Vector* sub = slot->library->lcd_geometry;
378
379 if ( mode == FT_RENDER_MODE_LCD )
380 {
381 cbox->xMin -= FT_MAX( FT_MAX( sub[0].x, sub[1].x ), sub[2].x );
382 cbox->xMax -= FT_MIN( FT_MIN( sub[0].x, sub[1].x ), sub[2].x );
383 cbox->yMin -= FT_MAX( FT_MAX( sub[0].y, sub[1].y ), sub[2].y );
384 cbox->yMax -= FT_MIN( FT_MIN( sub[0].y, sub[1].y ), sub[2].y );
385 }
386 else if ( mode == FT_RENDER_MODE_LCD_V )
387 {
388 cbox->xMin -= FT_MAX( FT_MAX( sub[0].y, sub[1].y ), sub[2].y );
389 cbox->xMax -= FT_MIN( FT_MIN( sub[0].y, sub[1].y ), sub[2].y );
390 cbox->yMin += FT_MIN( FT_MIN( sub[0].x, sub[1].x ), sub[2].x );
391 cbox->yMax += FT_MAX( FT_MAX( sub[0].x, sub[1].x ), sub[2].x );
392 }
393 }
394
395
398 unsigned char *weights )
399 {
402
403 return FT_THROW( Unimplemented_Feature );
404 }
405
406
410 {
412 FT_UNUSED( filter );
413
414 return FT_THROW( Unimplemented_Feature );
415 }
416
417
418 /* documentation in ftlcdfil.h */
419
422 FT_Vector sub[3] )
423 {
424 if ( !library )
425 return FT_THROW( Invalid_Library_Handle );
426
427 if ( !sub )
428 return FT_THROW( Invalid_Argument );
429
430 ft_memcpy( library->lcd_geometry, sub, 3 * sizeof( FT_Vector ) );
431
432 return FT_THROW( Unimplemented_Feature );
433 }
434
435#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
436
437
438/* END */
FT_Library library
Definition: cffdrivr.c:661
#define NULL
Definition: types.h:112
enum FT_Render_Mode_ FT_Render_Mode
@ FT_RENDER_MODE_LCD_V
Definition: freetype.h:3260
@ FT_RENDER_MODE_LCD
Definition: freetype.h:3259
return FT_Err_Ok
Definition: ftbbox.c:527
#define FT_UNUSED(arg)
Definition: ftconfig.h:100
#define FT_EXPORT_DEF(x)
Definition: ftconfig.h:494
#define FT_BASE_DEF(x)
Definition: ftconfig.h:418
#define FT_THROW(e)
Definition: ftdebug.h:241
FT_Library_SetLcdFilter(FT_Library library, FT_LcdFilter filter)
Definition: ftlcdfil.c:408
FT_Library_SetLcdGeometry(FT_Library library, FT_Vector sub[3])
Definition: ftlcdfil.c:421
FT_Library_SetLcdFilterWeights(FT_Library library, unsigned char *weights)
Definition: ftlcdfil.c:397
ft_lcd_padding(FT_BBox *cbox, FT_GlyphSlot slot, FT_Render_Mode mode)
Definition: ftlcdfil.c:373
@ FT_LCD_FILTER_LIGHT
Definition: ftlcdfil.h:165
@ FT_LCD_FILTER_LEGACY1
Definition: ftlcdfil.h:166
@ FT_LCD_FILTER_LEGACY
Definition: ftlcdfil.h:167
@ FT_LCD_FILTER_DEFAULT
Definition: ftlcdfil.h:164
@ FT_LCD_FILTER_NONE
Definition: ftlcdfil.h:163
#define FT_LCD_FILTER_FIVE_TAPS
Definition: ftlcdfil.h:268
FT_BEGIN_HEADER enum FT_LcdFilter_ FT_LcdFilter
FT_Byte FT_LcdFiveTapFilter[FT_LCD_FILTER_FIVE_TAPS]
Definition: ftlcdfil.h:270
#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
FT_Pos xMin
Definition: ftimage.h:121
FT_Pos yMax
Definition: ftimage.h:122
FT_Pos yMin
Definition: ftimage.h:121
FT_Pos xMax
Definition: ftimage.h:122
FT_Vector lcd_geometry[3]
Definition: ftobjs.h:916
Definition: vfat.h:185
Definition: uimain.c:89
uint32 width
Definition: uimain.c:91
Definition: parser.c:49