[FREETYPE] Update to v2.6.3. CORE-10964
[reactos.git] / reactos / lib / 3rdparty / freetype / src / base / ftlcdfil.c
1 /***************************************************************************/
2 /* */
3 /* ftlcdfil.c */
4 /* */
5 /* FreeType API for color filtering of subpixel bitmap glyphs (body). */
6 /* */
7 /* Copyright 2006-2016 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 /* FIR filter used by the default and light filters */
33 static void
34 _ft_lcd_filter_fir( FT_Bitmap* bitmap,
35 FT_Render_Mode mode,
36 FT_Library library )
37 {
38 FT_Byte* weights = library->lcd_weights;
39 FT_UInt width = (FT_UInt)bitmap->width;
40 FT_UInt height = (FT_UInt)bitmap->rows;
41
42
43 /* horizontal in-place FIR filter */
44 if ( mode == FT_RENDER_MODE_LCD && width >= 4 )
45 {
46 FT_Byte* line = bitmap->buffer;
47
48
49 /* take care of bitmap flow */
50 if ( bitmap->pitch < 0 )
51 line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
52
53 /* `fir' and `pix' must be at least 32 bit wide, since the sum of */
54 /* the values in `weights' can exceed 0xFF */
55
56 for ( ; height > 0; height--, line += bitmap->pitch )
57 {
58 FT_UInt fir[4]; /* below, `pix' is used as the 5th element */
59 FT_UInt val1, xx;
60
61
62 val1 = line[0];
63 fir[0] = weights[2] * val1;
64 fir[1] = weights[3] * val1;
65 fir[2] = weights[4] * val1;
66 fir[3] = 0;
67
68 val1 = line[1];
69 fir[0] += weights[1] * val1;
70 fir[1] += weights[2] * val1;
71 fir[2] += weights[3] * val1;
72 fir[3] += weights[4] * val1;
73
74 for ( xx = 2; xx < width; xx++ )
75 {
76 FT_UInt val, pix;
77
78
79 val = line[xx];
80 pix = fir[0] + weights[0] * val;
81 fir[0] = fir[1] + weights[1] * val;
82 fir[1] = fir[2] + weights[2] * val;
83 fir[2] = fir[3] + weights[3] * val;
84 fir[3] = weights[4] * val;
85
86 pix >>= 8;
87 pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
88 line[xx - 2] = (FT_Byte)pix;
89 }
90
91 {
92 FT_UInt pix;
93
94
95 pix = fir[0] >> 8;
96 pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
97 line[xx - 2] = (FT_Byte)pix;
98
99 pix = fir[1] >> 8;
100 pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
101 line[xx - 1] = (FT_Byte)pix;
102 }
103 }
104 }
105
106 /* vertical in-place FIR filter */
107 else if ( mode == FT_RENDER_MODE_LCD_V && height >= 4 )
108 {
109 FT_Byte* column = bitmap->buffer;
110 FT_Int pitch = bitmap->pitch;
111
112
113 /* take care of bitmap flow */
114 if ( bitmap->pitch < 0 )
115 column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
116
117 for ( ; width > 0; width--, column++ )
118 {
119 FT_Byte* col = column;
120 FT_UInt fir[4]; /* below, `pix' is used as the 5th element */
121 FT_UInt val1, yy;
122
123
124 val1 = col[0];
125 fir[0] = weights[2] * val1;
126 fir[1] = weights[3] * val1;
127 fir[2] = weights[4] * val1;
128 fir[3] = 0;
129 col += pitch;
130
131 val1 = col[0];
132 fir[0] += weights[1] * val1;
133 fir[1] += weights[2] * val1;
134 fir[2] += weights[3] * val1;
135 fir[3] += weights[4] * val1;
136 col += pitch;
137
138 for ( yy = 2; yy < height; yy++ )
139 {
140 FT_UInt val, pix;
141
142
143 val = col[0];
144 pix = fir[0] + weights[0] * val;
145 fir[0] = fir[1] + weights[1] * val;
146 fir[1] = fir[2] + weights[2] * val;
147 fir[2] = fir[3] + weights[3] * val;
148 fir[3] = weights[4] * val;
149
150 pix >>= 8;
151 pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
152 col[-2 * pitch] = (FT_Byte)pix;
153 col += pitch;
154 }
155
156 {
157 FT_UInt pix;
158
159
160 pix = fir[0] >> 8;
161 pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
162 col[-2 * pitch] = (FT_Byte)pix;
163
164 pix = fir[1] >> 8;
165 pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
166 col[-pitch] = (FT_Byte)pix;
167 }
168 }
169 }
170 }
171
172
173 #ifdef USE_LEGACY
174
175 /* intra-pixel filter used by the legacy filter */
176 static void
177 _ft_lcd_filter_legacy( FT_Bitmap* bitmap,
178 FT_Render_Mode mode,
179 FT_Library library )
180 {
181 FT_UInt width = (FT_UInt)bitmap->width;
182 FT_UInt height = (FT_UInt)bitmap->rows;
183 FT_Int pitch = bitmap->pitch;
184
185 static const unsigned int filters[3][3] =
186 {
187 { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 },
188 { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 },
189 { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 }
190 };
191
192 FT_UNUSED( library );
193
194
195 /* horizontal in-place intra-pixel filter */
196 if ( mode == FT_RENDER_MODE_LCD && width >= 3 )
197 {
198 FT_Byte* line = bitmap->buffer;
199
200
201 /* take care of bitmap flow */
202 if ( bitmap->pitch < 0 )
203 line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
204
205 for ( ; height > 0; height--, line += pitch )
206 {
207 FT_UInt xx;
208
209
210 for ( xx = 0; xx < width; xx += 3 )
211 {
212 FT_UInt r = 0;
213 FT_UInt g = 0;
214 FT_UInt b = 0;
215 FT_UInt p;
216
217
218 p = line[xx];
219 r += filters[0][0] * p;
220 g += filters[0][1] * p;
221 b += filters[0][2] * p;
222
223 p = line[xx + 1];
224 r += filters[1][0] * p;
225 g += filters[1][1] * p;
226 b += filters[1][2] * p;
227
228 p = line[xx + 2];
229 r += filters[2][0] * p;
230 g += filters[2][1] * p;
231 b += filters[2][2] * p;
232
233 line[xx] = (FT_Byte)( r / 65536 );
234 line[xx + 1] = (FT_Byte)( g / 65536 );
235 line[xx + 2] = (FT_Byte)( b / 65536 );
236 }
237 }
238 }
239 else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 )
240 {
241 FT_Byte* column = bitmap->buffer;
242
243
244 /* take care of bitmap flow */
245 if ( bitmap->pitch < 0 )
246 column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
247
248 for ( ; width > 0; width--, column++ )
249 {
250 FT_Byte* col = column;
251 FT_Byte* col_end = col + (FT_Int)height * pitch;
252
253
254 for ( ; col < col_end; col += 3 * pitch )
255 {
256 FT_UInt r = 0;
257 FT_UInt g = 0;
258 FT_UInt b = 0;
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[2 * pitch] = (FT_Byte)( b / 65536 );
280 }
281 }
282 }
283 }
284
285 #endif /* USE_LEGACY */
286
287
288 FT_EXPORT_DEF( FT_Error )
289 FT_Library_SetLcdFilterWeights( FT_Library library,
290 unsigned char *weights )
291 {
292 if ( !library )
293 return FT_THROW( Invalid_Library_Handle );
294
295 if ( !weights )
296 return FT_THROW( Invalid_Argument );
297
298 ft_memcpy( library->lcd_weights, weights, 5 );
299 library->lcd_filter_func = _ft_lcd_filter_fir;
300 library->lcd_extra = 2;
301
302 return FT_Err_Ok;
303 }
304
305
306 FT_EXPORT_DEF( FT_Error )
307 FT_Library_SetLcdFilter( FT_Library library,
308 FT_LcdFilter filter )
309 {
310 static const FT_Byte default_filter[5] =
311 { 0x08, 0x4d, 0x56, 0x4d, 0x08 };
312 static const FT_Byte light_filter[5] =
313 { 0x00, 0x55, 0x56, 0x55, 0x00 };
314
315
316 if ( !library )
317 return FT_THROW( Invalid_Library_Handle );
318
319 switch ( filter )
320 {
321 case FT_LCD_FILTER_NONE:
322 library->lcd_filter_func = NULL;
323 library->lcd_extra = 0;
324 break;
325
326 case FT_LCD_FILTER_DEFAULT:
327 ft_memcpy( library->lcd_weights, default_filter, 5 );
328 library->lcd_filter_func = _ft_lcd_filter_fir;
329 library->lcd_extra = 2;
330 break;
331
332 case FT_LCD_FILTER_LIGHT:
333 ft_memcpy( library->lcd_weights, light_filter, 5 );
334 library->lcd_filter_func = _ft_lcd_filter_fir;
335 library->lcd_extra = 2;
336 break;
337
338 #ifdef USE_LEGACY
339
340 case FT_LCD_FILTER_LEGACY:
341 case FT_LCD_FILTER_LEGACY1:
342 library->lcd_filter_func = _ft_lcd_filter_legacy;
343 library->lcd_extra = 0;
344 break;
345
346 #endif
347
348 default:
349 return FT_THROW( Invalid_Argument );
350 }
351
352 library->lcd_filter = filter;
353
354 return FT_Err_Ok;
355 }
356
357 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
358
359 FT_EXPORT_DEF( FT_Error )
360 FT_Library_SetLcdFilterWeights( FT_Library library,
361 unsigned char *weights )
362 {
363 FT_UNUSED( library );
364 FT_UNUSED( weights );
365
366 return FT_THROW( Unimplemented_Feature );
367 }
368
369
370 FT_EXPORT_DEF( FT_Error )
371 FT_Library_SetLcdFilter( FT_Library library,
372 FT_LcdFilter filter )
373 {
374 FT_UNUSED( library );
375 FT_UNUSED( filter );
376
377 return FT_THROW( Unimplemented_Feature );
378 }
379
380 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
381
382
383 /* END */