Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 <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.   /* 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 */
  379.