ftlcdfil.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ftlcdfil.c                                                             */
00004 /*                                                                         */
00005 /*    FreeType API for color filtering of subpixel bitmap glyphs (body).   */
00006 /*                                                                         */
00007 /*  Copyright 2006, 2008, 2009 by                                          */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019 #include <ft2build.h>
00020 #include FT_LCD_FILTER_H
00021 #include FT_IMAGE_H
00022 #include FT_INTERNAL_OBJECTS_H
00023 
00024 
00025 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
00026 
00027 /* define USE_LEGACY to implement the legacy filter */
00028 #define  USE_LEGACY
00029 
00030   /* FIR filter used by the default and light filters */
00031   static void
00032   _ft_lcd_filter_fir( FT_Bitmap*      bitmap,
00033                       FT_Render_Mode  mode,
00034                       FT_Library      library )
00035   {
00036     FT_Byte*  weights = library->lcd_weights;
00037     FT_UInt   width   = (FT_UInt)bitmap->width;
00038     FT_UInt   height  = (FT_UInt)bitmap->rows;
00039 
00040 
00041     /* horizontal in-place FIR filter */
00042     if ( mode == FT_RENDER_MODE_LCD && width >= 4 )
00043     {
00044       FT_Byte*  line = bitmap->buffer;
00045 
00046 
00047       for ( ; height > 0; height--, line += bitmap->pitch )
00048       {
00049         FT_UInt  fir[5];
00050         FT_UInt  val1, xx;
00051 
00052 
00053         val1   = line[0];
00054         fir[0] = weights[2] * val1;
00055         fir[1] = weights[3] * val1;
00056         fir[2] = weights[4] * val1;
00057         fir[3] = 0;
00058         fir[4] = 0;
00059 
00060         val1    = line[1];
00061         fir[0] += weights[1] * val1;
00062         fir[1] += weights[2] * val1;
00063         fir[2] += weights[3] * val1;
00064         fir[3] += weights[4] * val1;
00065 
00066         for ( xx = 2; xx < width; xx++ )
00067         {
00068           FT_UInt  val, pix;
00069 
00070 
00071           val    = line[xx];
00072           pix    = fir[0] + weights[0] * val;
00073           fir[0] = fir[1] + weights[1] * val;
00074           fir[1] = fir[2] + weights[2] * val;
00075           fir[2] = fir[3] + weights[3] * val;
00076           fir[3] =          weights[4] * val;
00077 
00078           pix        >>= 8;
00079           pix         |= -( pix >> 8 );
00080           line[xx - 2] = (FT_Byte)pix;
00081         }
00082 
00083         {
00084           FT_UInt  pix;
00085 
00086 
00087           pix          = fir[0] >> 8;
00088           pix         |= -( pix >> 8 );
00089           line[xx - 2] = (FT_Byte)pix;
00090 
00091           pix          = fir[1] >> 8;
00092           pix         |= -( pix >> 8 );
00093           line[xx - 1] = (FT_Byte)pix;
00094         }
00095       }
00096     }
00097 
00098     /* vertical in-place FIR filter */
00099     else if ( mode == FT_RENDER_MODE_LCD_V && height >= 4 )
00100     {
00101       FT_Byte*  column = bitmap->buffer;
00102       FT_Int    pitch  = bitmap->pitch;
00103 
00104 
00105       for ( ; width > 0; width--, column++ )
00106       {
00107         FT_Byte*  col = column;
00108         FT_UInt   fir[5];
00109         FT_UInt   val1, yy;
00110 
00111 
00112         val1   = col[0];
00113         fir[0] = weights[2] * val1;
00114         fir[1] = weights[3] * val1;
00115         fir[2] = weights[4] * val1;
00116         fir[3] = 0;
00117         fir[4] = 0;
00118         col   += pitch;
00119 
00120         val1    = col[0];
00121         fir[0] += weights[1] * val1;
00122         fir[1] += weights[2] * val1;
00123         fir[2] += weights[3] * val1;
00124         fir[3] += weights[4] * val1;
00125         col    += pitch;
00126 
00127         for ( yy = 2; yy < height; yy++ )
00128         {
00129           FT_UInt  val, pix;
00130 
00131 
00132           val    = col[0];
00133           pix    = fir[0] + weights[0] * val;
00134           fir[0] = fir[1] + weights[1] * val;
00135           fir[1] = fir[2] + weights[2] * val;
00136           fir[2] = fir[3] + weights[3] * val;
00137           fir[3] =          weights[4] * val;
00138 
00139           pix           >>= 8;
00140           pix            |= -( pix >> 8 );
00141           col[-2 * pitch] = (FT_Byte)pix;
00142           col            += pitch;
00143         }
00144 
00145         {
00146           FT_UInt  pix;
00147 
00148 
00149           pix             = fir[0] >> 8;
00150           pix            |= -( pix >> 8 );
00151           col[-2 * pitch] = (FT_Byte)pix;
00152 
00153           pix         = fir[1] >> 8;
00154           pix        |= -( pix >> 8 );
00155           col[-pitch] = (FT_Byte)pix;
00156         }
00157       }
00158     }
00159   }
00160 
00161 
00162 #ifdef USE_LEGACY
00163 
00164   /* intra-pixel filter used by the legacy filter */
00165   static void
00166   _ft_lcd_filter_legacy( FT_Bitmap*      bitmap,
00167                          FT_Render_Mode  mode,
00168                          FT_Library      library )
00169   {
00170     FT_UInt  width  = (FT_UInt)bitmap->width;
00171     FT_UInt  height = (FT_UInt)bitmap->rows;
00172     FT_Int   pitch  = bitmap->pitch;
00173 
00174     static const int  filters[3][3] =
00175     {
00176       { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 },
00177       { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 },
00178       { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 }
00179     };
00180 
00181     FT_UNUSED( library );
00182 
00183 
00184     /* horizontal in-place intra-pixel filter */
00185     if ( mode == FT_RENDER_MODE_LCD && width >= 3 )
00186     {
00187       FT_Byte*  line = bitmap->buffer;
00188 
00189 
00190       for ( ; height > 0; height--, line += pitch )
00191       {
00192         FT_UInt  xx;
00193 
00194 
00195         for ( xx = 0; xx < width; xx += 3 )
00196         {
00197           FT_UInt  r = 0;
00198           FT_UInt  g = 0;
00199           FT_UInt  b = 0;
00200           FT_UInt  p;
00201 
00202 
00203           p  = line[xx];
00204           r += filters[0][0] * p;
00205           g += filters[0][1] * p;
00206           b += filters[0][2] * p;
00207 
00208           p  = line[xx + 1];
00209           r += filters[1][0] * p;
00210           g += filters[1][1] * p;
00211           b += filters[1][2] * p;
00212 
00213           p  = line[xx + 2];
00214           r += filters[2][0] * p;
00215           g += filters[2][1] * p;
00216           b += filters[2][2] * p;
00217 
00218           line[xx]     = (FT_Byte)( r / 65536 );
00219           line[xx + 1] = (FT_Byte)( g / 65536 );
00220           line[xx + 2] = (FT_Byte)( b / 65536 );
00221         }
00222       }
00223     }
00224     else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 )
00225     {
00226       FT_Byte*  column = bitmap->buffer;
00227 
00228 
00229       for ( ; width > 0; width--, column++ )
00230       {
00231         FT_Byte*  col     = column;
00232         FT_Byte*  col_end = col + height * pitch;
00233 
00234 
00235         for ( ; col < col_end; col += 3 * pitch )
00236         {
00237           FT_UInt  r = 0;
00238           FT_UInt  g = 0;
00239           FT_UInt  b = 0;
00240           FT_UInt  p;
00241 
00242 
00243           p  = col[0];
00244           r += filters[0][0] * p;
00245           g += filters[0][1] * p;
00246           b += filters[0][2] * p;
00247 
00248           p  = col[pitch];
00249           r += filters[1][0] * p;
00250           g += filters[1][1] * p;
00251           b += filters[1][2] * p;
00252 
00253           p  = col[pitch * 2];
00254           r += filters[2][0] * p;
00255           g += filters[2][1] * p;
00256           b += filters[2][2] * p;
00257 
00258           col[0]         = (FT_Byte)( r / 65536 );
00259           col[pitch]     = (FT_Byte)( g / 65536 );
00260           col[2 * pitch] = (FT_Byte)( b / 65536 );
00261         }
00262       }
00263     }
00264   }
00265 
00266 #endif /* USE_LEGACY */
00267 
00268 
00269   FT_EXPORT_DEF( FT_Error )
00270   FT_Library_SetLcdFilter( FT_Library     library,
00271                            FT_LcdFilter   filter )
00272   {
00273     static const FT_Byte  light_filter[5] =
00274                             { 0, 85, 86, 85, 0 };
00275     /* the values here sum up to a value larger than 256, */
00276     /* providing a cheap gamma correction                 */
00277     static const FT_Byte  default_filter[5] =
00278                             { 0x10, 0x40, 0x70, 0x40, 0x10 };
00279 
00280 
00281     if ( library == NULL )
00282       return FT_Err_Invalid_Argument;
00283 
00284     switch ( filter )
00285     {
00286     case FT_LCD_FILTER_NONE:
00287       library->lcd_filter_func = NULL;
00288       library->lcd_extra       = 0;
00289       break;
00290 
00291     case FT_LCD_FILTER_DEFAULT:
00292 #if defined( FT_FORCE_LEGACY_LCD_FILTER )
00293 
00294       library->lcd_filter_func = _ft_lcd_filter_legacy;
00295       library->lcd_extra       = 0;
00296 
00297 #elif defined( FT_FORCE_LIGHT_LCD_FILTER )
00298 
00299       ft_memcpy( library->lcd_weights, light_filter, 5 );
00300       library->lcd_filter_func = _ft_lcd_filter_fir;
00301       library->lcd_extra       = 2;
00302 
00303 #else
00304 
00305       ft_memcpy( library->lcd_weights, default_filter, 5 );
00306       library->lcd_filter_func = _ft_lcd_filter_fir;
00307       library->lcd_extra       = 2;
00308 
00309 #endif
00310 
00311       break;
00312 
00313     case FT_LCD_FILTER_LIGHT:
00314       ft_memcpy( library->lcd_weights, light_filter, 5 );
00315       library->lcd_filter_func = _ft_lcd_filter_fir;
00316       library->lcd_extra       = 2;
00317       break;
00318 
00319 #ifdef USE_LEGACY
00320 
00321     case FT_LCD_FILTER_LEGACY:
00322       library->lcd_filter_func = _ft_lcd_filter_legacy;
00323       library->lcd_extra       = 0;
00324       break;
00325 
00326 #endif
00327 
00328     default:
00329       return FT_Err_Invalid_Argument;
00330     }
00331 
00332     library->lcd_filter = filter;
00333     return 0;
00334   }
00335 
00336 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
00337 
00338   FT_EXPORT_DEF( FT_Error )
00339   FT_Library_SetLcdFilter( FT_Library    library,
00340                            FT_LcdFilter  filter )
00341   {
00342     FT_UNUSED( library );
00343     FT_UNUSED( filter );
00344 
00345     return FT_Err_Unimplemented_Feature;
00346   }
00347 
00348 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
00349 
00350 
00351 /* END */

Generated on Tue Jul 5 14:13:42 2011 for ROOT_528-00b_version by  doxygen 1.5.1