1 /***************************************************************************/ 2 /* */ 3 /* ftlcdfil.c */ 4 /* */ 5 /* FreeType API for color filtering of subpixel bitmap glyphs (body). */ 6 /* */ 7 /* Copyright 2006-2018 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 #define FT_SHIFTCLAMP( x ) ( x >>= 8, (FT_Byte)( x > 255 ? 255 : x ) ) 33 34 35 /* add padding according to filter weights */ 36 FT_BASE_DEF (void) 37 ft_lcd_padding( FT_Pos* Min, 38 FT_Pos* Max, 39 FT_GlyphSlot slot ) 40 { 41 FT_Byte* lcd_weights; 42 FT_Bitmap_LcdFilterFunc lcd_filter_func; 43 44 45 /* Per-face LCD filtering takes priority if set up. */ 46 if ( slot->face && slot->face->internal->lcd_filter_func ) 47 { 48 lcd_weights = slot->face->internal->lcd_weights; 49 lcd_filter_func = slot->face->internal->lcd_filter_func; 50 } 51 else 52 { 53 lcd_weights = slot->library->lcd_weights; 54 lcd_filter_func = slot->library->lcd_filter_func; 55 } 56 57 if ( lcd_filter_func == ft_lcd_filter_fir ) 58 { 59 *Min -= lcd_weights[0] ? 43 : 60 lcd_weights[1] ? 22 : 0; 61 *Max += lcd_weights[4] ? 43 : 62 lcd_weights[3] ? 22 : 0; 63 } 64 } 65 66 67 /* FIR filter used by the default and light filters */ 68 FT_BASE_DEF( void ) 69 ft_lcd_filter_fir( FT_Bitmap* bitmap, 70 FT_Render_Mode mode, 71 FT_LcdFiveTapFilter weights ) 72 { 73 FT_UInt width = (FT_UInt)bitmap->width; 74 FT_UInt height = (FT_UInt)bitmap->rows; 75 FT_Int pitch = bitmap->pitch; 76 FT_Byte* origin = bitmap->buffer; 77 78 79 /* take care of bitmap flow */ 80 if ( pitch > 0 && height > 0 ) 81 origin += pitch * (FT_Int)( height - 1 ); 82 83 /* horizontal in-place FIR filter */ 84 if ( mode == FT_RENDER_MODE_LCD && width >= 2 ) 258 r += filters[1][0] * p; 259 g += filters[1][1] * p; 260 b += filters[1][2] * p; 261 262 p = col[pitch * 2]; 263 r += filters[2][0] * p; 264 g += filters[2][1] * p; 265 b += filters[2][2] * p; 266 267 col[0] = (FT_Byte)( r / 65536 ); 268 col[pitch] = (FT_Byte)( g / 65536 ); 269 col[pitch * 2] = (FT_Byte)( b / 65536 ); 270 } 271 } 272 } 273 } 274 275 #endif /* USE_LEGACY */ 276 277 278 FT_EXPORT_DEF( FT_Error ) 279 FT_Library_SetLcdFilterWeights( FT_Library library, 280 unsigned char *weights ) 281 { 282 if ( !library ) 283 return FT_THROW( Invalid_Library_Handle ); 284 285 if ( !weights ) 286 return FT_THROW( Invalid_Argument ); 287 288 ft_memcpy( library->lcd_weights, weights, FT_LCD_FILTER_FIVE_TAPS ); 289 library->lcd_filter_func = ft_lcd_filter_fir; 290 291 return FT_Err_Ok; 292 } 293 294 295 FT_EXPORT_DEF( FT_Error ) 296 FT_Library_SetLcdFilter( FT_Library library, 297 FT_LcdFilter filter ) 298 { 299 static const FT_LcdFiveTapFilter default_weights = 300 { 0x08, 0x4d, 0x56, 0x4d, 0x08 }; 301 static const FT_LcdFiveTapFilter light_weights = 302 { 0x00, 0x55, 0x56, 0x55, 0x00 }; 303 304 305 if ( !library ) 306 return FT_THROW( Invalid_Library_Handle ); 307 308 switch ( filter ) 309 { 310 case FT_LCD_FILTER_NONE: 311 library->lcd_filter_func = NULL; 312 break; 313 314 case FT_LCD_FILTER_DEFAULT: 324 FT_LCD_FILTER_FIVE_TAPS ); 325 library->lcd_filter_func = ft_lcd_filter_fir; 326 break; 327 328 #ifdef USE_LEGACY 329 330 case FT_LCD_FILTER_LEGACY: 331 case FT_LCD_FILTER_LEGACY1: 332 library->lcd_filter_func = _ft_lcd_filter_legacy; 333 break; 334 335 #endif 336 337 default: 338 return FT_THROW( Invalid_Argument ); 339 } 340 341 return FT_Err_Ok; 342 } 343 344 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ 345 346 /* add padding according to accommodate outline shifts */ 347 FT_BASE_DEF (void) 348 ft_lcd_padding( FT_Pos* Min, 349 FT_Pos* Max, 350 FT_GlyphSlot slot ) 351 { 352 FT_UNUSED( slot ); 353 354 *Min -= 21; 355 *Max += 21; 356 } 357 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 */ | 1 /**************************************************************************** 2 * 3 * ftlcdfil.c 4 * 5 * FreeType API for color filtering of subpixel bitmap glyphs (body). 6 * 7 * Copyright (C) 2006-2019 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 #define FT_SHIFTCLAMP( x ) ( x >>= 8, (FT_Byte)( x > 255 ? 255 : x ) ) 33 34 35 /* add padding according to filter weights */ 36 FT_BASE_DEF (void) 37 ft_lcd_padding( FT_BBox* cbox, 38 FT_GlyphSlot slot, 39 FT_Render_Mode mode ) 40 { 41 FT_Byte* lcd_weights; 42 FT_Bitmap_LcdFilterFunc lcd_filter_func; 43 44 45 /* Per-face LCD filtering takes priority if set up. */ 46 if ( slot->face && slot->face->internal->lcd_filter_func ) 47 { 48 lcd_weights = slot->face->internal->lcd_weights; 49 lcd_filter_func = slot->face->internal->lcd_filter_func; 50 } 51 else 52 { 53 lcd_weights = slot->library->lcd_weights; 54 lcd_filter_func = slot->library->lcd_filter_func; 55 } 56 57 if ( lcd_filter_func == ft_lcd_filter_fir ) 58 { 59 if ( mode == FT_RENDER_MODE_LCD ) 60 { 61 cbox->xMin -= lcd_weights[0] ? 43 : 62 lcd_weights[1] ? 22 : 0; 63 cbox->xMax += lcd_weights[4] ? 43 : 64 lcd_weights[3] ? 22 : 0; 65 } 66 else if ( mode == FT_RENDER_MODE_LCD_V ) 67 { 68 cbox->yMin -= lcd_weights[0] ? 43 : 69 lcd_weights[1] ? 22 : 0; 70 cbox->yMax += lcd_weights[4] ? 43 : 71 lcd_weights[3] ? 22 : 0; 72 } 73 } 74 } 75 76 77 /* FIR filter used by the default and light filters */ 78 FT_BASE_DEF( void ) 79 ft_lcd_filter_fir( FT_Bitmap* bitmap, 80 FT_Render_Mode mode, 81 FT_LcdFiveTapFilter weights ) 82 { 83 FT_UInt width = (FT_UInt)bitmap->width; 84 FT_UInt height = (FT_UInt)bitmap->rows; 85 FT_Int pitch = bitmap->pitch; 86 FT_Byte* origin = bitmap->buffer; 87 88 89 /* take care of bitmap flow */ 90 if ( pitch > 0 && height > 0 ) 91 origin += pitch * (FT_Int)( height - 1 ); 92 93 /* horizontal in-place FIR filter */ 94 if ( mode == FT_RENDER_MODE_LCD && width >= 2 ) 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[pitch * 2] = (FT_Byte)( b / 65536 ); 280 } 281 } 282 } 283 } 284 285 #endif /* USE_LEGACY */ 286 287 288 /* documentation in ftlcdfil.h */ 289 290 FT_EXPORT_DEF( FT_Error ) 291 FT_Library_SetLcdFilterWeights( FT_Library library, 292 unsigned char *weights ) 293 { 294 if ( !library ) 295 return FT_THROW( Invalid_Library_Handle ); 296 297 if ( !weights ) 298 return FT_THROW( Invalid_Argument ); 299 300 ft_memcpy( library->lcd_weights, weights, FT_LCD_FILTER_FIVE_TAPS ); 301 library->lcd_filter_func = ft_lcd_filter_fir; 302 303 return FT_Err_Ok; 304 } 305 306 307 /* documentation in ftlcdfil.h */ 308 309 FT_EXPORT_DEF( FT_Error ) 310 FT_Library_SetLcdFilter( FT_Library library, 311 FT_LcdFilter filter ) 312 { 313 static const FT_LcdFiveTapFilter default_weights = 314 { 0x08, 0x4d, 0x56, 0x4d, 0x08 }; 315 static const FT_LcdFiveTapFilter light_weights = 316 { 0x00, 0x55, 0x56, 0x55, 0x00 }; 317 318 319 if ( !library ) 320 return FT_THROW( Invalid_Library_Handle ); 321 322 switch ( filter ) 323 { 324 case FT_LCD_FILTER_NONE: 325 library->lcd_filter_func = NULL; 326 break; 327 328 case FT_LCD_FILTER_DEFAULT: 338 FT_LCD_FILTER_FIVE_TAPS ); 339 library->lcd_filter_func = ft_lcd_filter_fir; 340 break; 341 342 #ifdef USE_LEGACY 343 344 case FT_LCD_FILTER_LEGACY: 345 case FT_LCD_FILTER_LEGACY1: 346 library->lcd_filter_func = _ft_lcd_filter_legacy; 347 break; 348 349 #endif 350 351 default: 352 return FT_THROW( Invalid_Argument ); 353 } 354 355 return FT_Err_Ok; 356 } 357 358 359 FT_EXPORT_DEF( FT_Error ) 360 FT_Library_SetLcdGeometry( FT_Library library, 361 FT_Vector* sub ) 362 { 363 FT_UNUSED( library ); 364 FT_UNUSED( sub ); 365 366 return FT_THROW( Unimplemented_Feature ); 367 } 368 369 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ 370 371 /* add padding to accommodate outline shifts */ 372 FT_BASE_DEF (void) 373 ft_lcd_padding( FT_BBox* cbox, 374 FT_GlyphSlot slot, 375 FT_Render_Mode mode ) 376 { 377 FT_Vector* sub = slot->library->lcd_geometry; 378 379 if ( mode == FT_RENDER_MODE_LCD ) 380 { 381 cbox->xMin -= FT_MAX( FT_MAX( sub[0].x, sub[1].x ), sub[2].x ); 382 cbox->xMax -= FT_MIN( FT_MIN( sub[0].x, sub[1].x ), sub[2].x ); 383 cbox->yMin -= FT_MAX( FT_MAX( sub[0].y, sub[1].y ), sub[2].y ); 384 cbox->yMax -= FT_MIN( FT_MIN( sub[0].y, sub[1].y ), sub[2].y ); 385 } 386 else if ( mode == FT_RENDER_MODE_LCD_V ) 387 { 388 cbox->xMin -= FT_MAX( FT_MAX( sub[0].y, sub[1].y ), sub[2].y ); 389 cbox->xMax -= FT_MIN( FT_MIN( sub[0].y, sub[1].y ), sub[2].y ); 390 cbox->yMin += FT_MIN( FT_MIN( sub[0].x, sub[1].x ), sub[2].x ); 391 cbox->yMax += FT_MAX( FT_MAX( sub[0].x, sub[1].x ), sub[2].x ); 392 } 393 } 394 395 396 FT_EXPORT_DEF( FT_Error ) 397 FT_Library_SetLcdFilterWeights( FT_Library library, 398 unsigned char *weights ) 399 { 400 FT_UNUSED( library ); 401 FT_UNUSED( weights ); 402 403 return FT_THROW( Unimplemented_Feature ); 404 } 405 406 407 FT_EXPORT_DEF( FT_Error ) 408 FT_Library_SetLcdFilter( FT_Library library, 409 FT_LcdFilter filter ) 410 { 411 FT_UNUSED( library ); 412 FT_UNUSED( filter ); 413 414 return FT_THROW( Unimplemented_Feature ); 415 } 416 417 418 /* documentation in ftlcdfil.h */ 419 420 FT_EXPORT_DEF( FT_Error ) 421 FT_Library_SetLcdGeometry( FT_Library library, 422 FT_Vector sub[3] ) 423 { 424 if ( !library ) 425 return FT_THROW( Invalid_Library_Handle ); 426 427 if ( !sub ) 428 return FT_THROW( Invalid_Argument ); 429 430 ft_memcpy( library->lcd_geometry, sub, 3 * sizeof( FT_Vector ) ); 431 432 return FT_THROW( Unimplemented_Feature ); 433 } 434 435 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ 436 437 438 /* END */ |