12c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/***************************************************************************/ 22c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/* */ 32c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/* ftlcdfil.c */ 42c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/* */ 52c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/* FreeType API for color filtering of subpixel bitmap glyphs (body). */ 62c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/* */ 70a0c22569deab933df21127e75db5c81f724f292Werner Lemberg/* Copyright 2006-2018 by */ 82c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 92c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/* */ 102c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/* This file is part of the FreeType project, and may only be used, */ 112c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/* modified, and distributed under the terms of the FreeType project */ 122c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 132c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/* this file you indicate that you have read the license and */ 142c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/* understand and accept it fully. */ 152c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/* */ 162c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/***************************************************************************/ 172c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg 182c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg 193cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner#include <ft2build.h> 20059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg#include FT_INTERNAL_DEBUG_H 21059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg 223cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner#include FT_LCD_FILTER_H 233cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner#include FT_IMAGE_H 243cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner#include FT_INTERNAL_OBJECTS_H 253cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 262c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg 273cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING 283cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 2929c191cd530ef3351a8f15aa86d8811e820e9fa1David Turner/* define USE_LEGACY to implement the legacy filter */ 308765c71b41625406fe87598645d842ca8451983cDavid Turner#define USE_LEGACY 318765c71b41625406fe87598645d842ca8451983cDavid Turner 32c56d8851ea987023cc73981a70d261b3f6427545Alexei Podtelezhnikov (Алексей Подтележников)#define FT_SHIFTCLAMP( x ) ( x >>= 8, (FT_Byte)( x > 255 ? 255 : x ) ) 33c56d8851ea987023cc73981a70d261b3f6427545Alexei Podtelezhnikov (Алексей Подтележников) 3461d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) 3561d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) /* add padding according to filter weights */ 3661d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) FT_BASE_DEF (void) 3761d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) ft_lcd_padding( FT_Pos* Min, 3861d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) FT_Pos* Max, 3961d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) FT_GlyphSlot slot ) 4061d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) { 4161d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) FT_Byte* lcd_weights; 4261d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) FT_Bitmap_LcdFilterFunc lcd_filter_func; 4361d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) 4461d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) 4561d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) /* Per-face LCD filtering takes priority if set up. */ 4661d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) if ( slot->face && slot->face->internal->lcd_filter_func ) 4761d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) { 4861d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) lcd_weights = slot->face->internal->lcd_weights; 4961d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) lcd_filter_func = slot->face->internal->lcd_filter_func; 5061d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) } 5161d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) else 5261d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) { 5361d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) lcd_weights = slot->library->lcd_weights; 5461d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) lcd_filter_func = slot->library->lcd_filter_func; 5561d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) } 5661d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) 5761d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) if ( lcd_filter_func == ft_lcd_filter_fir ) 5861d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) { 5961d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) *Min -= lcd_weights[0] ? 43 : 6061d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) lcd_weights[1] ? 22 : 0; 6161d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) *Max += lcd_weights[4] ? 43 : 6261d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) lcd_weights[3] ? 22 : 0; 6361d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) } 6461d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) } 6561d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) 6661d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) 678765c71b41625406fe87598645d842ca8451983cDavid Turner /* FIR filter used by the default and light filters */ 6802e80da6090c21d6e59ac955b7f56e1ad4a9850bAlexei Podtelezhnikov (Алексей Подтележников) FT_BASE_DEF( void ) 692e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler ft_lcd_filter_fir( FT_Bitmap* bitmap, 702e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler FT_Render_Mode mode, 712e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler FT_LcdFiveTapFilter weights ) 723cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner { 737b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_UInt width = (FT_UInt)bitmap->width; 747b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_UInt height = (FT_UInt)bitmap->rows; 757b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_Int pitch = bitmap->pitch; 767b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_Byte* origin = bitmap->buffer; 772c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg 783cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 797b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) /* take care of bitmap flow */ 807b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) if ( pitch > 0 ) 817b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) origin += pitch * (FT_Int)( height - 1 ); 827b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) 833cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner /* horizontal in-place FIR filter */ 847b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) if ( mode == FT_RENDER_MODE_LCD && width >= 2 ) 853cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner { 867b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_Byte* line = origin; 873cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 889154dab8155e7bb5865dd5041fc4ef7fc5450c98Werner Lemberg 897b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) /* `fir' must be at least 32 bit wide, since the sum of */ 907b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) /* the values in `weights' can exceed 0xFF */ 916497b9c5a599071a631664a55cf32b7d96ce3474Werner Lemberg 927b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) for ( ; height > 0; height--, line -= pitch ) 933cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner { 947b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_UInt fir[5]; 957b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_UInt val, xx; 962c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg 973cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 987b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) val = line[0]; 997b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[2] = weights[2] * val; 1007b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[3] = weights[3] * val; 1017b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[4] = weights[4] * val; 1023cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 1037b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) val = line[1]; 1047b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[1] = fir[2] + weights[1] * val; 1057b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[2] = fir[3] + weights[2] * val; 1067b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[3] = fir[4] + weights[3] * val; 1077b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[4] = weights[4] * val; 1083cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 1093cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner for ( xx = 2; xx < width; xx++ ) 1103cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner { 1113cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner val = line[xx]; 1127b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[0] = fir[1] + weights[0] * val; 1137b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[1] = fir[2] + weights[1] * val; 1147b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[2] = fir[3] + weights[2] * val; 1157b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[3] = fir[4] + weights[3] * val; 1167b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[4] = weights[4] * val; 1177b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) 118c56d8851ea987023cc73981a70d261b3f6427545Alexei Podtelezhnikov (Алексей Подтележников) line[xx - 2] = FT_SHIFTCLAMP( fir[0] ); 1193cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner } 1203cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 121c56d8851ea987023cc73981a70d261b3f6427545Alexei Podtelezhnikov (Алексей Подтележников) line[xx - 2] = FT_SHIFTCLAMP( fir[1] ); 122c56d8851ea987023cc73981a70d261b3f6427545Alexei Podtelezhnikov (Алексей Подтележников) line[xx - 1] = FT_SHIFTCLAMP( fir[2] ); 1233cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner } 1243cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner } 1252c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg 1263cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner /* vertical in-place FIR filter */ 1277b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) else if ( mode == FT_RENDER_MODE_LCD_V && height >= 2 ) 1283cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner { 1297b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_Byte* column = origin; 1303cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 1319154dab8155e7bb5865dd5041fc4ef7fc5450c98Werner Lemberg 1323cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner for ( ; width > 0; width--, column++ ) 1333cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner { 1343cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner FT_Byte* col = column; 1357b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_UInt fir[5]; 1367b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_UInt val, yy; 1373cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 1382c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg 1397b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) val = col[0]; 1407b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[2] = weights[2] * val; 1417b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[3] = weights[3] * val; 1427b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[4] = weights[4] * val; 1437b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) col -= pitch; 1443cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 1457b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) val = col[0]; 1467b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[1] = fir[2] + weights[1] * val; 1477b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[2] = fir[3] + weights[2] * val; 1487b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[3] = fir[4] + weights[3] * val; 1497b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[4] = weights[4] * val; 1507b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) col -= pitch; 1513cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 1527b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) for ( yy = 2; yy < height; yy++, col -= pitch ) 1533cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner { 1543cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner val = col[0]; 1557b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[0] = fir[1] + weights[0] * val; 1567b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[1] = fir[2] + weights[1] * val; 1577b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[2] = fir[3] + weights[2] * val; 1587b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[3] = fir[4] + weights[3] * val; 1597b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) fir[4] = weights[4] * val; 1607b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) 161c56d8851ea987023cc73981a70d261b3f6427545Alexei Podtelezhnikov (Алексей Подтележников) col[pitch * 2] = FT_SHIFTCLAMP( fir[0] ); 1623cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner } 1633cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 164c56d8851ea987023cc73981a70d261b3f6427545Alexei Podtelezhnikov (Алексей Подтележников) col[pitch * 2] = FT_SHIFTCLAMP( fir[1] ); 165c56d8851ea987023cc73981a70d261b3f6427545Alexei Podtelezhnikov (Алексей Подтележников) col[pitch] = FT_SHIFTCLAMP( fir[2] ); 1663cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner } 1673cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner } 1683cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner } 1693cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 1703cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 1718765c71b41625406fe87598645d842ca8451983cDavid Turner#ifdef USE_LEGACY 1720d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 1734c93399155e88c415df05a46a14625ebf95c5ddcWerner Lemberg /* intra-pixel filter used by the legacy filter */ 1748765c71b41625406fe87598645d842ca8451983cDavid Turner static void 1758765c71b41625406fe87598645d842ca8451983cDavid Turner _ft_lcd_filter_legacy( FT_Bitmap* bitmap, 1768765c71b41625406fe87598645d842ca8451983cDavid Turner FT_Render_Mode mode, 1772e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler FT_Byte* weights ) 1788765c71b41625406fe87598645d842ca8451983cDavid Turner { 1797b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_UInt width = (FT_UInt)bitmap->width; 1807b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_UInt height = (FT_UInt)bitmap->rows; 1817b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_Int pitch = bitmap->pitch; 1827b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_Byte* origin = bitmap->buffer; 1838765c71b41625406fe87598645d842ca8451983cDavid Turner 18476abc75c2637cffc692fee6b16396c8f56091252Werner Lemberg static const unsigned int filters[3][3] = 1858765c71b41625406fe87598645d842ca8451983cDavid Turner { 1860d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 }, 1870d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 }, 1880d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 } 1898765c71b41625406fe87598645d842ca8451983cDavid Turner }; 1908765c71b41625406fe87598645d842ca8451983cDavid Turner 1912e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler FT_UNUSED( weights ); 1920d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 1938765c71b41625406fe87598645d842ca8451983cDavid Turner 1947b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) /* take care of bitmap flow */ 1957b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) if ( pitch > 0 ) 1967b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) origin += pitch * (FT_Int)( height - 1 ); 1977b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) 1984c93399155e88c415df05a46a14625ebf95c5ddcWerner Lemberg /* horizontal in-place intra-pixel filter */ 1998765c71b41625406fe87598645d842ca8451983cDavid Turner if ( mode == FT_RENDER_MODE_LCD && width >= 3 ) 2008765c71b41625406fe87598645d842ca8451983cDavid Turner { 2017b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_Byte* line = origin; 2028765c71b41625406fe87598645d842ca8451983cDavid Turner 2038765c71b41625406fe87598645d842ca8451983cDavid Turner 2047b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) for ( ; height > 0; height--, line -= pitch ) 2058765c71b41625406fe87598645d842ca8451983cDavid Turner { 2068765c71b41625406fe87598645d842ca8451983cDavid Turner FT_UInt xx; 2078765c71b41625406fe87598645d842ca8451983cDavid Turner 2080d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 2098765c71b41625406fe87598645d842ca8451983cDavid Turner for ( xx = 0; xx < width; xx += 3 ) 2108765c71b41625406fe87598645d842ca8451983cDavid Turner { 2117b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_UInt r, g, b; 2128765c71b41625406fe87598645d842ca8451983cDavid Turner FT_UInt p; 2138765c71b41625406fe87598645d842ca8451983cDavid Turner 2140d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 2158765c71b41625406fe87598645d842ca8451983cDavid Turner p = line[xx]; 2167b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) r = filters[0][0] * p; 2177b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) g = filters[0][1] * p; 2187b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) b = filters[0][2] * p; 2190d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 2200d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg p = line[xx + 1]; 2210d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg r += filters[1][0] * p; 2220d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg g += filters[1][1] * p; 2230d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg b += filters[1][2] * p; 2240d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 2250d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg p = line[xx + 2]; 2260d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg r += filters[2][0] * p; 2270d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg g += filters[2][1] * p; 2280d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg b += filters[2][2] * p; 2290d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 2300d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg line[xx] = (FT_Byte)( r / 65536 ); 2310d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg line[xx + 1] = (FT_Byte)( g / 65536 ); 2320d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg line[xx + 2] = (FT_Byte)( b / 65536 ); 2338765c71b41625406fe87598645d842ca8451983cDavid Turner } 2348765c71b41625406fe87598645d842ca8451983cDavid Turner } 2358765c71b41625406fe87598645d842ca8451983cDavid Turner } 2368765c71b41625406fe87598645d842ca8451983cDavid Turner else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 ) 2378765c71b41625406fe87598645d842ca8451983cDavid Turner { 2387b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_Byte* column = origin; 2398765c71b41625406fe87598645d842ca8451983cDavid Turner 2409154dab8155e7bb5865dd5041fc4ef7fc5450c98Werner Lemberg 2418765c71b41625406fe87598645d842ca8451983cDavid Turner for ( ; width > 0; width--, column++ ) 2428765c71b41625406fe87598645d842ca8451983cDavid Turner { 2437b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_Byte* col = column - 2 * pitch; 2440d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 2458765c71b41625406fe87598645d842ca8451983cDavid Turner 2467b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) for ( ; height > 0; height -= 3, col -= 3 * pitch ) 2478765c71b41625406fe87598645d842ca8451983cDavid Turner { 2487b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) FT_UInt r, g, b; 2498765c71b41625406fe87598645d842ca8451983cDavid Turner FT_UInt p; 2508765c71b41625406fe87598645d842ca8451983cDavid Turner 2510d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 2528765c71b41625406fe87598645d842ca8451983cDavid Turner p = col[0]; 2537b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) r = filters[0][0] * p; 2547b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) g = filters[0][1] * p; 2557b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) b = filters[0][2] * p; 2560d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 2570d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg p = col[pitch]; 2580d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg r += filters[1][0] * p; 2590d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg g += filters[1][1] * p; 2600d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg b += filters[1][2] * p; 2610d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 2620d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg p = col[pitch * 2]; 2630d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg r += filters[2][0] * p; 2640d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg g += filters[2][1] * p; 2650d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg b += filters[2][2] * p; 2660d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 2670d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg col[0] = (FT_Byte)( r / 65536 ); 2680d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg col[pitch] = (FT_Byte)( g / 65536 ); 2697b7278334cf3da01bb955f8ec0a33259a03dbb38Alexei Podtelezhnikov (Алексей Подтележников) col[pitch * 2] = (FT_Byte)( b / 65536 ); 2708765c71b41625406fe87598645d842ca8451983cDavid Turner } 2718765c71b41625406fe87598645d842ca8451983cDavid Turner } 2728765c71b41625406fe87598645d842ca8451983cDavid Turner } 2738765c71b41625406fe87598645d842ca8451983cDavid Turner } 2740d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 2758765c71b41625406fe87598645d842ca8451983cDavid Turner#endif /* USE_LEGACY */ 2768765c71b41625406fe87598645d842ca8451983cDavid Turner 2770d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 27852cd0fc8b9a76b4bee8d4fab7aa0409a85900970Werner Lemberg FT_EXPORT_DEF( FT_Error ) 279460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg FT_Library_SetLcdFilterWeights( FT_Library library, 280460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg unsigned char *weights ) 281460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg { 282f4f9e6880036304912c9da39fa94a343131fdb82Werner Lemberg if ( !library ) 283f4f9e6880036304912c9da39fa94a343131fdb82Werner Lemberg return FT_THROW( Invalid_Library_Handle ); 284f4f9e6880036304912c9da39fa94a343131fdb82Werner Lemberg 285f4f9e6880036304912c9da39fa94a343131fdb82Werner Lemberg if ( !weights ) 286059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg return FT_THROW( Invalid_Argument ); 287460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg 2882e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler ft_memcpy( library->lcd_weights, weights, FT_LCD_FILTER_FIVE_TAPS ); 2892e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler library->lcd_filter_func = ft_lcd_filter_fir; 290460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg 291460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg return FT_Err_Ok; 292460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg } 293460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg 294460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg 295460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg FT_EXPORT_DEF( FT_Error ) 296460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg FT_Library_SetLcdFilter( FT_Library library, 297460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg FT_LcdFilter filter ) 2983cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner { 2992e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler static const FT_LcdFiveTapFilter default_weights = 3002e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler { 0x08, 0x4d, 0x56, 0x4d, 0x08 }; 3012e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler static const FT_LcdFiveTapFilter light_weights = 3022e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler { 0x00, 0x55, 0x56, 0x55, 0x00 }; 3030d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 3043cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 305460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg if ( !library ) 306f4f9e6880036304912c9da39fa94a343131fdb82Werner Lemberg return FT_THROW( Invalid_Library_Handle ); 3073cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 3088765c71b41625406fe87598645d842ca8451983cDavid Turner switch ( filter ) 3093cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner { 3100d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg case FT_LCD_FILTER_NONE: 3110d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg library->lcd_filter_func = NULL; 3120d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg break; 3130d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 3140d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg case FT_LCD_FILTER_DEFAULT: 3152e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler ft_memcpy( library->lcd_weights, 3162e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler default_weights, 3172e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler FT_LCD_FILTER_FIVE_TAPS ); 3182e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler library->lcd_filter_func = ft_lcd_filter_fir; 3190d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg break; 3200d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 3210d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg case FT_LCD_FILTER_LIGHT: 3222e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler ft_memcpy( library->lcd_weights, 3232e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler light_weights, 3242e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler FT_LCD_FILTER_FIVE_TAPS ); 3252e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler library->lcd_filter_func = ft_lcd_filter_fir; 3260d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg break; 3278765c71b41625406fe87598645d842ca8451983cDavid Turner 3288765c71b41625406fe87598645d842ca8451983cDavid Turner#ifdef USE_LEGACY 3290d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 3300d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg case FT_LCD_FILTER_LEGACY: 331b96af12eb646534ab4d112e25210bd88812ee420Werner Lemberg case FT_LCD_FILTER_LEGACY1: 3320d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg library->lcd_filter_func = _ft_lcd_filter_legacy; 3330d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg break; 3340d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 3358765c71b41625406fe87598645d842ca8451983cDavid Turner#endif 3360d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg 3370d0d78dadc9ae38aa0aafbddb5f08d381b7d27ccWerner Lemberg default: 338059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg return FT_THROW( Invalid_Argument ); 3393cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner } 3403cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 341460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg return FT_Err_Ok; 3423cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner } 3433cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 3442c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ 3453cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 34661d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) /* add padding according to accommodate outline shifts */ 34761d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) FT_BASE_DEF (void) 34861d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) ft_lcd_padding( FT_Pos* Min, 34961d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) FT_Pos* Max, 35061d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) FT_GlyphSlot slot ) 3512e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler { 35261d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) FT_UNUSED( slot ); 35361d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) 35461d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) *Min -= 21; 35561d1818b5ef4fd9b014c4577f07cf5580ba67eeeAlexei Podtelezhnikov (Алексей Подтележников) *Max += 21; 3562e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler } 3572e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler 3582e9519885b8e7e5fdc9d75b35992ef7bbf15e53aNikolaus Waxweiler 35952cd0fc8b9a76b4bee8d4fab7aa0409a85900970Werner Lemberg FT_EXPORT_DEF( FT_Error ) 360460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg FT_Library_SetLcdFilterWeights( FT_Library library, 361460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg unsigned char *weights ) 362460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg { 363460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg FT_UNUSED( library ); 364460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg FT_UNUSED( weights ); 365460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg 366059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg return FT_THROW( Unimplemented_Feature ); 367460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg } 368460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg 369460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg 370460d23f1689f14f5812bfe4b322fd3f2a449905eWerner Lemberg FT_EXPORT_DEF( FT_Error ) 3718765c71b41625406fe87598645d842ca8451983cDavid Turner FT_Library_SetLcdFilter( FT_Library library, 3728765c71b41625406fe87598645d842ca8451983cDavid Turner FT_LcdFilter filter ) 3733cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner { 3742c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg FT_UNUSED( library ); 3758765c71b41625406fe87598645d842ca8451983cDavid Turner FT_UNUSED( filter ); 3763cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 377059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg return FT_THROW( Unimplemented_Feature ); 3783cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner } 3793cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 3802c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ 3812c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg 3823cc7d630bdccc1f2ae4bbf97ba7fddcddeb470c5David Turner 3832c002e13a74ab89b2ad0305088ed18660d5952abWerner Lemberg/* END */ 384