00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00028 #define USE_LEGACY
00029
00030
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
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
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
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
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
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
00276
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
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
00349
00350
00351