XFA: merge patch from CL 817753002
[pdfium.git] / core / src / fxge / fx_freetype / fxft2.5.01 / src / base / fxft_ftlcdfil.c
1 #if !defined(_FXFT_VERSION_) || _FXFT_VERSION_ == 2501
2 /***************************************************************************/
3 /*                                                                         */
4 /*  ftlcdfil.c                                                             */
5 /*                                                                         */
6 /*    FreeType API for color filtering of subpixel bitmap glyphs (body).   */
7 /*                                                                         */
8 /*  Copyright 2006, 2008-2010, 2013 by                                     */
9 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
10 /*                                                                         */
11 /*  This file is part of the FreeType project, and may only be used,       */
12 /*  modified, and distributed under the terms of the FreeType project      */
13 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
14 /*  this file you indicate that you have read the license and              */
15 /*  understand and accept it fully.                                        */
16 /*                                                                         */
17 /***************************************************************************/
18
19 #define FT2_BUILD_LIBRARY
20 #include "../../include/ft2build.h"
21 #include "../../include/freetype/internal/ftdebug.h"
22
23 #include "../../include/freetype/ftlcdfil.h"
24 #include "../../include/freetype/ftimage.h"
25 #include "../../include/freetype/internal/ftobjs.h"
26
27
28 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
29
30 /* define USE_LEGACY to implement the legacy filter */
31 #define  USE_LEGACY
32
33   /* FIR filter used by the default and light filters */
34   static void
35   _ft_lcd_filter_fir( FT_Bitmap*      bitmap,
36                       FT_Render_Mode  mode,
37                       FT_Library      library )
38   {
39     FT_Byte*  weights = library->lcd_weights;
40     FT_UInt   width   = (FT_UInt)bitmap->width;
41     FT_UInt   height  = (FT_UInt)bitmap->rows;
42
43
44     /* horizontal in-place FIR filter */
45     if ( mode == FT_RENDER_MODE_LCD && width >= 4 )
46     {
47       FT_Byte*  line = bitmap->buffer;
48
49
50       for ( ; height > 0; height--, line += bitmap->pitch )
51       {
52         FT_UInt  fir[5];
53         FT_UInt  val1, xx;
54
55
56         val1   = line[0];
57         fir[0] = weights[2] * val1;
58         fir[1] = weights[3] * val1;
59         fir[2] = weights[4] * val1;
60         fir[3] = 0;
61         fir[4] = 0;
62
63         val1    = line[1];
64         fir[0] += weights[1] * val1;
65         fir[1] += weights[2] * val1;
66         fir[2] += weights[3] * val1;
67         fir[3] += weights[4] * val1;
68
69         for ( xx = 2; xx < width; xx++ )
70         {
71           FT_UInt  val, pix;
72
73
74           val    = line[xx];
75           pix    = fir[0] + weights[0] * val;
76           fir[0] = fir[1] + weights[1] * val;
77           fir[1] = fir[2] + weights[2] * val;
78           fir[2] = fir[3] + weights[3] * val;
79           fir[3] =          weights[4] * val;
80
81           pix        >>= 8;
82           pix         |= (FT_UInt)-(FT_Int)( pix >> 8 );
83           line[xx - 2] = (FT_Byte)pix;
84         }
85
86         {
87           FT_UInt  pix;
88
89
90           pix          = fir[0] >> 8;
91           pix         |= (FT_UInt)-(FT_Int)( pix >> 8 );
92           line[xx - 2] = (FT_Byte)pix;
93
94           pix          = fir[1] >> 8;
95           pix         |= (FT_UInt)-(FT_Int)( pix >> 8 );
96           line[xx - 1] = (FT_Byte)pix;
97         }
98       }
99     }
100
101     /* vertical in-place FIR filter */
102     else if ( mode == FT_RENDER_MODE_LCD_V && height >= 4 )
103     {
104       FT_Byte*  column = bitmap->buffer;
105       FT_Int    pitch  = bitmap->pitch;
106
107
108       for ( ; width > 0; width--, column++ )
109       {
110         FT_Byte*  col = column;
111         FT_UInt   fir[5];
112         FT_UInt   val1, yy;
113
114
115         val1   = col[0];
116         fir[0] = weights[2] * val1;
117         fir[1] = weights[3] * val1;
118         fir[2] = weights[4] * val1;
119         fir[3] = 0;
120         fir[4] = 0;
121         col   += pitch;
122
123         val1    = col[0];
124         fir[0] += weights[1] * val1;
125         fir[1] += weights[2] * val1;
126         fir[2] += weights[3] * val1;
127         fir[3] += weights[4] * val1;
128         col    += pitch;
129
130         for ( yy = 2; yy < height; yy++ )
131         {
132           FT_UInt  val, pix;
133
134
135           val    = col[0];
136           pix    = fir[0] + weights[0] * val;
137           fir[0] = fir[1] + weights[1] * val;
138           fir[1] = fir[2] + weights[2] * val;
139           fir[2] = fir[3] + weights[3] * val;
140           fir[3] =          weights[4] * val;
141
142           pix           >>= 8;
143           pix            |= (FT_UInt)-(FT_Int)( pix >> 8 );
144           col[-2 * pitch] = (FT_Byte)pix;
145           col            += pitch;
146         }
147
148         {
149           FT_UInt  pix;
150
151
152           pix             = fir[0] >> 8;
153           pix            |= (FT_UInt)-(FT_Int)( pix >> 8 );
154           col[-2 * pitch] = (FT_Byte)pix;
155
156           pix         = fir[1] >> 8;
157           pix            |= (FT_UInt)-(FT_Int)( pix >> 8 );
158           col[-pitch] = (FT_Byte)pix;
159         }
160       }
161     }
162   }
163
164
165 #ifdef USE_LEGACY
166
167   /* intra-pixel filter used by the legacy filter */
168   static void
169   _ft_lcd_filter_legacy( FT_Bitmap*      bitmap,
170                          FT_Render_Mode  mode,
171                          FT_Library      library )
172   {
173     FT_UInt  width  = (FT_UInt)bitmap->width;
174     FT_UInt  height = (FT_UInt)bitmap->rows;
175     FT_Int   pitch  = bitmap->pitch;
176
177     static const int  filters[3][3] =
178     {
179       { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 },
180       { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 },
181       { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 }
182     };
183
184     FT_UNUSED( library );
185
186
187     /* horizontal in-place intra-pixel filter */
188     if ( mode == FT_RENDER_MODE_LCD && width >= 3 )
189     {
190       FT_Byte*  line = bitmap->buffer;
191
192
193       for ( ; height > 0; height--, line += pitch )
194       {
195         FT_UInt  xx;
196
197
198         for ( xx = 0; xx < width; xx += 3 )
199         {
200           FT_UInt  r = 0;
201           FT_UInt  g = 0;
202           FT_UInt  b = 0;
203           FT_UInt  p;
204
205
206           p  = line[xx];
207           r += filters[0][0] * p;
208           g += filters[0][1] * p;
209           b += filters[0][2] * p;
210
211           p  = line[xx + 1];
212           r += filters[1][0] * p;
213           g += filters[1][1] * p;
214           b += filters[1][2] * p;
215
216           p  = line[xx + 2];
217           r += filters[2][0] * p;
218           g += filters[2][1] * p;
219           b += filters[2][2] * p;
220
221           line[xx]     = (FT_Byte)( r / 65536 );
222           line[xx + 1] = (FT_Byte)( g / 65536 );
223           line[xx + 2] = (FT_Byte)( b / 65536 );
224         }
225       }
226     }
227     else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 )
228     {
229       FT_Byte*  column = bitmap->buffer;
230
231
232       for ( ; width > 0; width--, column++ )
233       {
234         FT_Byte*  col     = column;
235         FT_Byte*  col_end = col + height * pitch;
236
237
238         for ( ; col < col_end; col += 3 * pitch )
239         {
240           FT_UInt  r = 0;
241           FT_UInt  g = 0;
242           FT_UInt  b = 0;
243           FT_UInt  p;
244
245
246           p  = col[0];
247           r += filters[0][0] * p;
248           g += filters[0][1] * p;
249           b += filters[0][2] * p;
250
251           p  = col[pitch];
252           r += filters[1][0] * p;
253           g += filters[1][1] * p;
254           b += filters[1][2] * p;
255
256           p  = col[pitch * 2];
257           r += filters[2][0] * p;
258           g += filters[2][1] * p;
259           b += filters[2][2] * p;
260
261           col[0]         = (FT_Byte)( r / 65536 );
262           col[pitch]     = (FT_Byte)( g / 65536 );
263           col[2 * pitch] = (FT_Byte)( b / 65536 );
264         }
265       }
266     }
267   }
268
269 #endif /* USE_LEGACY */
270
271
272   FT_EXPORT_DEF( FT_Error )
273   FT_Library_SetLcdFilterWeights( FT_Library      library,
274                                   unsigned char  *weights )
275   {
276     if ( !library || !weights )
277       return FT_THROW( Invalid_Argument );
278
279     ft_memcpy( library->lcd_weights, weights, 5 );
280
281     return FT_Err_Ok;
282   }
283
284
285   FT_EXPORT_DEF( FT_Error )
286   FT_Library_SetLcdFilter( FT_Library    library,
287                            FT_LcdFilter  filter )
288   {
289     static const FT_Byte  light_filter[5] =
290                             { 0x00, 0x55, 0x56, 0x55, 0x00 };
291     /* the values here sum up to a value larger than 256, */
292     /* providing a cheap gamma correction                 */
293     static const FT_Byte  default_filter[5] =
294                             { 0x10, 0x40, 0x70, 0x40, 0x10 };
295
296
297     if ( !library )
298       return FT_THROW( Invalid_Argument );
299
300     switch ( filter )
301     {
302     case FT_LCD_FILTER_NONE:
303       library->lcd_filter_func = NULL;
304       library->lcd_extra       = 0;
305       break;
306
307     case FT_LCD_FILTER_DEFAULT:
308 #if defined( FT_FORCE_LEGACY_LCD_FILTER )
309
310       library->lcd_filter_func = _ft_lcd_filter_legacy;
311       library->lcd_extra       = 0;
312
313 #elif defined( FT_FORCE_LIGHT_LCD_FILTER )
314
315       ft_memcpy( library->lcd_weights, light_filter, 5 );
316       library->lcd_filter_func = _ft_lcd_filter_fir;
317       library->lcd_extra       = 2;
318
319 #else
320
321       ft_memcpy( library->lcd_weights, default_filter, 5 );
322       library->lcd_filter_func = _ft_lcd_filter_fir;
323       library->lcd_extra       = 2;
324
325 #endif
326
327       break;
328
329     case FT_LCD_FILTER_LIGHT:
330       ft_memcpy( library->lcd_weights, light_filter, 5 );
331       library->lcd_filter_func = _ft_lcd_filter_fir;
332       library->lcd_extra       = 2;
333       break;
334
335 #ifdef USE_LEGACY
336
337     case FT_LCD_FILTER_LEGACY:
338       library->lcd_filter_func = _ft_lcd_filter_legacy;
339       library->lcd_extra       = 0;
340       break;
341
342 #endif
343
344     default:
345       return FT_THROW( Invalid_Argument );
346     }
347
348     library->lcd_filter = filter;
349
350     return FT_Err_Ok;
351   }
352
353 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
354
355   FT_EXPORT_DEF( FT_Error )
356   FT_Library_SetLcdFilterWeights( FT_Library      library,
357                                   unsigned char  *weights )
358   {
359     FT_UNUSED( library );
360     FT_UNUSED( weights );
361
362     return FT_THROW( Unimplemented_Feature );
363   }
364
365
366   FT_EXPORT_DEF( FT_Error )
367   FT_Library_SetLcdFilter( FT_Library    library,
368                            FT_LcdFilter  filter )
369   {
370     FT_UNUSED( library );
371     FT_UNUSED( filter );
372
373     return FT_THROW( Unimplemented_Feature );
374   }
375
376 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
377
378
379 /* END */
380 #endif
381