1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  ftlcdfil.c                                                             */
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*    FreeType API for color filtering of subpixel bitmap glyphs (body).   */
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
7ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki/*  Copyright 2006-2015 by                                                 */
8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  This file is part of the FreeType project, and may only be used,       */
11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  modified, and distributed under the terms of the FreeType project      */
12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  this file you indicate that you have read the license and              */
14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  understand and accept it fully.                                        */
15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
19049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <ft2build.h>
20727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include FT_INTERNAL_DEBUG_H
21727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_LCD_FILTER_H
23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_IMAGE_H
24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_OBJECTS_H
25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
26049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
27049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
28049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* define USE_LEGACY to implement the legacy filter */
30049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define  USE_LEGACY
31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* FIR filter used by the default and light filters */
33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
34049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  _ft_lcd_filter_fir( FT_Bitmap*      bitmap,
35049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Render_Mode  mode,
36049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Library      library )
37049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
38049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Byte*  weights = library->lcd_weights;
39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   width   = (FT_UInt)bitmap->width;
40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   height  = (FT_UInt)bitmap->rows;
41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* horizontal in-place FIR filter */
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_LCD && width >= 4 )
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  line = bitmap->buffer;
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
49ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      /* take care of bitmap flow */
50ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      if ( bitmap->pitch < 0 )
51ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki        line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
52ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
539c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      /* `fir' and `pix' must be at least 32 bit wide, since the sum of */
549c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      /* the values in `weights' can exceed 0xFF                        */
559c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; height > 0; height--, line += bitmap->pitch )
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
589c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        FT_UInt  fir[4];        /* below, `pix' is used as the 5th element */
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt  val1, xx;
60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        val1   = line[0];
63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[0] = weights[2] * val1;
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[1] = weights[3] * val1;
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[2] = weights[4] * val1;
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[3] = 0;
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        val1    = line[1];
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[0] += weights[1] * val1;
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[1] += weights[2] * val1;
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[2] += weights[3] * val1;
72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[3] += weights[4] * val1;
73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( xx = 2; xx < width; xx++ )
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  val, pix;
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          val    = line[xx];
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pix    = fir[0] + weights[0] * val;
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          fir[0] = fir[1] + weights[1] * val;
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          fir[1] = fir[2] + weights[2] * val;
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          fir[2] = fir[3] + weights[3] * val;
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          fir[3] =          weights[4] * val;
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pix        >>= 8;
879c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          pix         |= (FT_UInt)-(FT_Int)( pix >> 8 );
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          line[xx - 2] = (FT_Byte)pix;
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  pix;
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pix          = fir[0] >> 8;
969c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          pix         |= (FT_UInt)-(FT_Int)( pix >> 8 );
97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          line[xx - 2] = (FT_Byte)pix;
98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pix          = fir[1] >> 8;
1009c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          pix         |= (FT_UInt)-(FT_Int)( pix >> 8 );
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          line[xx - 1] = (FT_Byte)pix;
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* vertical in-place FIR filter */
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else if ( mode == FT_RENDER_MODE_LCD_V && height >= 4 )
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  column = bitmap->buffer;
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Int    pitch  = bitmap->pitch;
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
113ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      /* take care of bitmap flow */
114ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      if ( bitmap->pitch < 0 )
115ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki        column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
116ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; width > 0; width--, column++ )
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Byte*  col = column;
1209c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        FT_UInt   fir[4];       /* below, `pix' is used as the 5th element */
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt   val1, yy;
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        val1   = col[0];
125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[0] = weights[2] * val1;
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[1] = weights[3] * val1;
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[2] = weights[4] * val1;
128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[3] = 0;
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        col   += pitch;
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        val1    = col[0];
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[0] += weights[1] * val1;
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[1] += weights[2] * val1;
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[2] += weights[3] * val1;
135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fir[3] += weights[4] * val1;
136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        col    += pitch;
137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( yy = 2; yy < height; yy++ )
139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  val, pix;
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          val    = col[0];
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pix    = fir[0] + weights[0] * val;
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          fir[0] = fir[1] + weights[1] * val;
146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          fir[1] = fir[2] + weights[2] * val;
147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          fir[2] = fir[3] + weights[3] * val;
148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          fir[3] =          weights[4] * val;
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pix           >>= 8;
1519c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          pix            |= (FT_UInt)-(FT_Int)( pix >> 8 );
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          col[-2 * pitch] = (FT_Byte)pix;
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          col            += pitch;
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  pix;
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pix             = fir[0] >> 8;
1619c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          pix            |= (FT_UInt)-(FT_Int)( pix >> 8 );
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          col[-2 * pitch] = (FT_Byte)pix;
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          pix         = fir[1] >> 8;
1659c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          pix        |= (FT_UInt)-(FT_Int)( pix >> 8 );
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          col[-pitch] = (FT_Byte)pix;
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef USE_LEGACY
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* intra-pixel filter used by the legacy filter */
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  _ft_lcd_filter_legacy( FT_Bitmap*      bitmap,
178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         FT_Render_Mode  mode,
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         FT_Library      library )
180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt  width  = (FT_UInt)bitmap->width;
182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt  height = (FT_UInt)bitmap->rows;
183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int   pitch  = bitmap->pitch;
184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
185ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    static const unsigned int  filters[3][3] =
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 },
188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 },
189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 }
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    };
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( library );
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* horizontal in-place intra-pixel filter */
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mode == FT_RENDER_MODE_LCD && width >= 3 )
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  line = bitmap->buffer;
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
201ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      /* take care of bitmap flow */
202ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      if ( bitmap->pitch < 0 )
203ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki        line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
204ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; height > 0; height--, line += pitch )
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_UInt  xx;
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( xx = 0; xx < width; xx += 3 )
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  r = 0;
213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  g = 0;
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  b = 0;
215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  p;
216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p  = line[xx];
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          r += filters[0][0] * p;
220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          g += filters[0][1] * p;
221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          b += filters[0][2] * p;
222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p  = line[xx + 1];
224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          r += filters[1][0] * p;
225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          g += filters[1][1] * p;
226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          b += filters[1][2] * p;
227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p  = line[xx + 2];
229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          r += filters[2][0] * p;
230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          g += filters[2][1] * p;
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          b += filters[2][2] * p;
232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          line[xx]     = (FT_Byte)( r / 65536 );
234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          line[xx + 1] = (FT_Byte)( g / 65536 );
235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          line[xx + 2] = (FT_Byte)( b / 65536 );
236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 )
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Byte*  column = bitmap->buffer;
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
244ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      /* take care of bitmap flow */
245ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      if ( bitmap->pitch < 0 )
246ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki        column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
247ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; width > 0; width--, column++ )
249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Byte*  col     = column;
251ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki        FT_Byte*  col_end = col + (FT_Int)height * pitch;
252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( ; col < col_end; col += 3 * pitch )
255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  r = 0;
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  g = 0;
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  b = 0;
259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_UInt  p;
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p  = col[0];
263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          r += filters[0][0] * p;
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          g += filters[0][1] * p;
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          b += filters[0][2] * p;
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p  = col[pitch];
268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          r += filters[1][0] * p;
269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          g += filters[1][1] * p;
270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          b += filters[1][2] * p;
271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          p  = col[pitch * 2];
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          r += filters[2][0] * p;
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          g += filters[2][1] * p;
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          b += filters[2][2] * p;
276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          col[0]         = (FT_Byte)( r / 65536 );
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          col[pitch]     = (FT_Byte)( g / 65536 );
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          col[2 * pitch] = (FT_Byte)( b / 65536 );
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* USE_LEGACY */
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2880a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
289aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich  FT_Library_SetLcdFilterWeights( FT_Library      library,
290aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich                                  unsigned char  *weights )
291aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich  {
292ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    if ( !library )
293ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      return FT_THROW( Invalid_Library_Handle );
294ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
295ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    if ( !weights )
296727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Argument );
297aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
298aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    ft_memcpy( library->lcd_weights, weights, 5 );
299aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
300aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    return FT_Err_Ok;
301aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich  }
302aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
303aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
304aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich  FT_EXPORT_DEF( FT_Error )
305aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich  FT_Library_SetLcdFilter( FT_Library    library,
306aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich                           FT_LcdFilter  filter )
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    static const FT_Byte  light_filter[5] =
309aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich                            { 0x00, 0x55, 0x56, 0x55, 0x00 };
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* the values here sum up to a value larger than 256, */
311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* providing a cheap gamma correction                 */
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    static const FT_Byte  default_filter[5] =
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            { 0x10, 0x40, 0x70, 0x40, 0x10 };
314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
316aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    if ( !library )
317ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      return FT_THROW( Invalid_Library_Handle );
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    switch ( filter )
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case FT_LCD_FILTER_NONE:
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      library->lcd_filter_func = NULL;
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      library->lcd_extra       = 0;
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case FT_LCD_FILTER_DEFAULT:
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if defined( FT_FORCE_LEGACY_LCD_FILTER )
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      library->lcd_filter_func = _ft_lcd_filter_legacy;
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      library->lcd_extra       = 0;
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#elif defined( FT_FORCE_LIGHT_LCD_FILTER )
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3340a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      ft_memcpy( library->lcd_weights, light_filter, 5 );
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      library->lcd_filter_func = _ft_lcd_filter_fir;
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      library->lcd_extra       = 2;
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3400a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      ft_memcpy( library->lcd_weights, default_filter, 5 );
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      library->lcd_filter_func = _ft_lcd_filter_fir;
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      library->lcd_extra       = 2;
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case FT_LCD_FILTER_LIGHT:
3490a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      ft_memcpy( library->lcd_weights, light_filter, 5 );
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      library->lcd_filter_func = _ft_lcd_filter_fir;
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      library->lcd_extra       = 2;
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef USE_LEGACY
355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    case FT_LCD_FILTER_LEGACY:
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      library->lcd_filter_func = _ft_lcd_filter_legacy;
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      library->lcd_extra       = 0;
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      break;
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    default:
364727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Argument );
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    library->lcd_filter = filter;
368aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
369aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    return FT_Err_Ok;
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3740a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  FT_EXPORT_DEF( FT_Error )
375aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich  FT_Library_SetLcdFilterWeights( FT_Library      library,
376aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich                                  unsigned char  *weights )
377aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich  {
378aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    FT_UNUSED( library );
379aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    FT_UNUSED( weights );
380aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
381727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_THROW( Unimplemented_Feature );
382aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich  }
383aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
384aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
385aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich  FT_EXPORT_DEF( FT_Error )
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Library_SetLcdFilter( FT_Library    library,
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_LcdFilter  filter )
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( library );
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( filter );
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
392727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_THROW( Unimplemented_Feature );
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
399