Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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