Home | History | Annotate | Download | only in smooth
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  ftsmooth.c                                                             */
      4 /*                                                                         */
      5 /*    Anti-aliasing renderer interface (body).                             */
      6 /*                                                                         */
      7 /*  Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 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 #include FT_INTERNAL_OBJECTS_H
     22 #include FT_OUTLINE_H
     23 #include "ftsmooth.h"
     24 #include "ftgrays.h"
     25 #include "ftspic.h"
     26 
     27 #include "ftsmerrs.h"
     28 
     29 
     30   /* initialize renderer -- init its raster */
     31   static FT_Error
     32   ft_smooth_init( FT_Renderer  render )
     33   {
     34     FT_Library  library = FT_MODULE_LIBRARY( render );
     35 
     36 
     37     render->clazz->raster_class->raster_reset( render->raster,
     38                                                library->raster_pool,
     39                                                library->raster_pool_size );
     40 
     41     return 0;
     42   }
     43 
     44 
     45   /* sets render-specific mode */
     46   static FT_Error
     47   ft_smooth_set_mode( FT_Renderer  render,
     48                       FT_ULong     mode_tag,
     49                       FT_Pointer   data )
     50   {
     51     /* we simply pass it to the raster */
     52     return render->clazz->raster_class->raster_set_mode( render->raster,
     53                                                          mode_tag,
     54                                                          data );
     55   }
     56 
     57   /* transform a given glyph image */
     58   static FT_Error
     59   ft_smooth_transform( FT_Renderer       render,
     60                        FT_GlyphSlot      slot,
     61                        const FT_Matrix*  matrix,
     62                        const FT_Vector*  delta )
     63   {
     64     FT_Error  error = Smooth_Err_Ok;
     65 
     66 
     67     if ( slot->format != render->glyph_format )
     68     {
     69       error = Smooth_Err_Invalid_Argument;
     70       goto Exit;
     71     }
     72 
     73     if ( matrix )
     74       FT_Outline_Transform( &slot->outline, matrix );
     75 
     76     if ( delta )
     77       FT_Outline_Translate( &slot->outline, delta->x, delta->y );
     78 
     79   Exit:
     80     return error;
     81   }
     82 
     83 
     84   /* return the glyph's control box */
     85   static void
     86   ft_smooth_get_cbox( FT_Renderer   render,
     87                       FT_GlyphSlot  slot,
     88                       FT_BBox*      cbox )
     89   {
     90     FT_MEM_ZERO( cbox, sizeof ( *cbox ) );
     91 
     92     if ( slot->format == render->glyph_format )
     93       FT_Outline_Get_CBox( &slot->outline, cbox );
     94   }
     95 
     96 
     97   /* convert a slot's glyph image into a bitmap */
     98   static FT_Error
     99   ft_smooth_render_generic( FT_Renderer       render,
    100                             FT_GlyphSlot      slot,
    101                             FT_Render_Mode    mode,
    102                             const FT_Vector*  origin,
    103                             FT_Render_Mode    required_mode )
    104   {
    105     FT_Error     error;
    106     FT_Outline*  outline = NULL;
    107     FT_BBox      cbox;
    108     FT_UInt      width, height, height_org, width_org, pitch;
    109     FT_Bitmap*   bitmap;
    110     FT_Memory    memory;
    111     FT_Int       hmul = mode == FT_RENDER_MODE_LCD;
    112     FT_Int       vmul = mode == FT_RENDER_MODE_LCD_V;
    113     FT_Pos       x_shift, y_shift, x_left, y_top;
    114 
    115     FT_Raster_Params  params;
    116 
    117 
    118     /* check glyph image format */
    119     if ( slot->format != render->glyph_format )
    120     {
    121       error = Smooth_Err_Invalid_Argument;
    122       goto Exit;
    123     }
    124 
    125     /* check mode */
    126     if ( mode != required_mode )
    127       return Smooth_Err_Cannot_Render_Glyph;
    128 
    129     outline = &slot->outline;
    130 
    131     /* translate the outline to the new origin if needed */
    132     if ( origin )
    133       FT_Outline_Translate( outline, origin->x, origin->y );
    134 
    135     /* compute the control box, and grid fit it */
    136     FT_Outline_Get_CBox( outline, &cbox );
    137 
    138     cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
    139     cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
    140     cbox.xMax = FT_PIX_CEIL( cbox.xMax );
    141     cbox.yMax = FT_PIX_CEIL( cbox.yMax );
    142 
    143     width  = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
    144     height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
    145     bitmap = &slot->bitmap;
    146     memory = render->root.memory;
    147 
    148     width_org  = width;
    149     height_org = height;
    150 
    151     /* release old bitmap buffer */
    152     if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
    153     {
    154       FT_FREE( bitmap->buffer );
    155       slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
    156     }
    157 
    158     /* allocate new one */
    159     pitch = width;
    160     if ( hmul )
    161     {
    162       width = width * 3;
    163       pitch = FT_PAD_CEIL( width, 4 );
    164     }
    165 
    166     if ( vmul )
    167       height *= 3;
    168 
    169     x_shift = (FT_Int) cbox.xMin;
    170     y_shift = (FT_Int) cbox.yMin;
    171     x_left  = (FT_Int)( cbox.xMin >> 6 );
    172     y_top   = (FT_Int)( cbox.yMax >> 6 );
    173 
    174 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
    175 
    176     if ( slot->library->lcd_filter_func )
    177     {
    178       FT_Int  extra = slot->library->lcd_extra;
    179 
    180 
    181       if ( hmul )
    182       {
    183         x_shift -= 64 * ( extra >> 1 );
    184         width   += 3 * extra;
    185         pitch    = FT_PAD_CEIL( width, 4 );
    186         x_left  -= extra >> 1;
    187       }
    188 
    189       if ( vmul )
    190       {
    191         y_shift -= 64 * ( extra >> 1 );
    192         height  += 3 * extra;
    193         y_top   += extra >> 1;
    194       }
    195     }
    196 
    197 #endif
    198 
    199 #if FT_UINT_MAX > 0xFFFFU
    200 
    201     /* Required check is ( pitch * height < FT_ULONG_MAX ),     */
    202     /* but we care realistic cases only. Always pitch <= width. */
    203     if ( width > 0x7FFFU || height > 0x7FFFU )
    204     {
    205       FT_ERROR(( "ft_smooth_render_generic: glyph too large: %d x %d\n",
    206                  width, height ));
    207       return Smooth_Err_Raster_Overflow;
    208     }
    209 
    210 #endif
    211 
    212     bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
    213     bitmap->num_grays  = 256;
    214     bitmap->width      = width;
    215     bitmap->rows       = height;
    216     bitmap->pitch      = pitch;
    217 
    218     /* translate outline to render it into the bitmap */
    219     FT_Outline_Translate( outline, -x_shift, -y_shift );
    220 
    221     if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
    222       goto Exit;
    223 
    224     slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
    225 
    226     /* set up parameters */
    227     params.target = bitmap;
    228     params.source = outline;
    229     params.flags  = FT_RASTER_FLAG_AA;
    230 
    231 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
    232 
    233     /* implode outline if needed */
    234     {
    235       FT_Vector*  points     = outline->points;
    236       FT_Vector*  points_end = points + outline->n_points;
    237       FT_Vector*  vec;
    238 
    239 
    240       if ( hmul )
    241         for ( vec = points; vec < points_end; vec++ )
    242           vec->x *= 3;
    243 
    244       if ( vmul )
    245         for ( vec = points; vec < points_end; vec++ )
    246           vec->y *= 3;
    247     }
    248 
    249     /* render outline into the bitmap */
    250     error = render->raster_render( render->raster, &params );
    251 
    252     /* deflate outline if needed */
    253     {
    254       FT_Vector*  points     = outline->points;
    255       FT_Vector*  points_end = points + outline->n_points;
    256       FT_Vector*  vec;
    257 
    258 
    259       if ( hmul )
    260         for ( vec = points; vec < points_end; vec++ )
    261           vec->x /= 3;
    262 
    263       if ( vmul )
    264         for ( vec = points; vec < points_end; vec++ )
    265           vec->y /= 3;
    266     }
    267 
    268     if ( slot->library->lcd_filter_func )
    269       slot->library->lcd_filter_func( bitmap, mode, slot->library );
    270 
    271 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
    272 
    273     /* render outline into bitmap */
    274     error = render->raster_render( render->raster, &params );
    275 
    276     /* expand it horizontally */
    277     if ( hmul )
    278     {
    279       FT_Byte*  line = bitmap->buffer;
    280       FT_UInt   hh;
    281 
    282 
    283       for ( hh = height_org; hh > 0; hh--, line += pitch )
    284       {
    285         FT_UInt   xx;
    286         FT_Byte*  end = line + width;
    287 
    288 
    289         for ( xx = width_org; xx > 0; xx-- )
    290         {
    291           FT_UInt  pixel = line[xx-1];
    292 
    293 
    294           end[-3] = (FT_Byte)pixel;
    295           end[-2] = (FT_Byte)pixel;
    296           end[-1] = (FT_Byte)pixel;
    297           end    -= 3;
    298         }
    299       }
    300     }
    301 
    302     /* expand it vertically */
    303     if ( vmul )
    304     {
    305       FT_Byte*  read  = bitmap->buffer + ( height - height_org ) * pitch;
    306       FT_Byte*  write = bitmap->buffer;
    307       FT_UInt   hh;
    308 
    309 
    310       for ( hh = height_org; hh > 0; hh-- )
    311       {
    312         ft_memcpy( write, read, pitch );
    313         write += pitch;
    314 
    315         ft_memcpy( write, read, pitch );
    316         write += pitch;
    317 
    318         ft_memcpy( write, read, pitch );
    319         write += pitch;
    320         read  += pitch;
    321       }
    322     }
    323 
    324 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
    325 
    326     FT_Outline_Translate( outline, x_shift, y_shift );
    327 
    328     /*
    329      * XXX: on 16bit system, we return an error for huge bitmap
    330      * to prevent an overflow.
    331      */
    332     if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )
    333       return Smooth_Err_Invalid_Pixel_Size;
    334 
    335     if ( error )
    336       goto Exit;
    337 
    338     slot->format      = FT_GLYPH_FORMAT_BITMAP;
    339     slot->bitmap_left = (FT_Int)x_left;
    340     slot->bitmap_top  = (FT_Int)y_top;
    341 
    342   Exit:
    343     if ( outline && origin )
    344       FT_Outline_Translate( outline, -origin->x, -origin->y );
    345 
    346     return error;
    347   }
    348 
    349 
    350   /* convert a slot's glyph image into a bitmap */
    351   static FT_Error
    352   ft_smooth_render( FT_Renderer       render,
    353                     FT_GlyphSlot      slot,
    354                     FT_Render_Mode    mode,
    355                     const FT_Vector*  origin )
    356   {
    357     if ( mode == FT_RENDER_MODE_LIGHT )
    358       mode = FT_RENDER_MODE_NORMAL;
    359 
    360     return ft_smooth_render_generic( render, slot, mode, origin,
    361                                      FT_RENDER_MODE_NORMAL );
    362   }
    363 
    364 
    365   /* convert a slot's glyph image into a horizontal LCD bitmap */
    366   static FT_Error
    367   ft_smooth_render_lcd( FT_Renderer       render,
    368                         FT_GlyphSlot      slot,
    369                         FT_Render_Mode    mode,
    370                         const FT_Vector*  origin )
    371   {
    372     FT_Error  error;
    373 
    374     error = ft_smooth_render_generic( render, slot, mode, origin,
    375                                       FT_RENDER_MODE_LCD );
    376     if ( !error )
    377       slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
    378 
    379     return error;
    380   }
    381 
    382 
    383   /* convert a slot's glyph image into a vertical LCD bitmap */
    384   static FT_Error
    385   ft_smooth_render_lcd_v( FT_Renderer       render,
    386                           FT_GlyphSlot      slot,
    387                           FT_Render_Mode    mode,
    388                           const FT_Vector*  origin )
    389   {
    390     FT_Error  error;
    391 
    392     error = ft_smooth_render_generic( render, slot, mode, origin,
    393                                       FT_RENDER_MODE_LCD_V );
    394     if ( !error )
    395       slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
    396 
    397     return error;
    398   }
    399 
    400 
    401   FT_DEFINE_RENDERER(ft_smooth_renderer_class,
    402 
    403       FT_MODULE_RENDERER,
    404       sizeof( FT_RendererRec ),
    405 
    406       "smooth",
    407       0x10000L,
    408       0x20000L,
    409 
    410       0,    /* module specific interface */
    411 
    412       (FT_Module_Constructor)ft_smooth_init,
    413       (FT_Module_Destructor) 0,
    414       (FT_Module_Requester)  0
    415     ,
    416 
    417     FT_GLYPH_FORMAT_OUTLINE,
    418 
    419     (FT_Renderer_RenderFunc)   ft_smooth_render,
    420     (FT_Renderer_TransformFunc)ft_smooth_transform,
    421     (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
    422     (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
    423 
    424     (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
    425   )
    426 
    427 
    428   FT_DEFINE_RENDERER(ft_smooth_lcd_renderer_class,
    429 
    430       FT_MODULE_RENDERER,
    431       sizeof( FT_RendererRec ),
    432 
    433       "smooth-lcd",
    434       0x10000L,
    435       0x20000L,
    436 
    437       0,    /* module specific interface */
    438 
    439       (FT_Module_Constructor)ft_smooth_init,
    440       (FT_Module_Destructor) 0,
    441       (FT_Module_Requester)  0
    442     ,
    443 
    444     FT_GLYPH_FORMAT_OUTLINE,
    445 
    446     (FT_Renderer_RenderFunc)   ft_smooth_render_lcd,
    447     (FT_Renderer_TransformFunc)ft_smooth_transform,
    448     (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
    449     (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
    450 
    451     (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
    452   )
    453 
    454   FT_DEFINE_RENDERER(ft_smooth_lcdv_renderer_class,
    455 
    456       FT_MODULE_RENDERER,
    457       sizeof( FT_RendererRec ),
    458 
    459       "smooth-lcdv",
    460       0x10000L,
    461       0x20000L,
    462 
    463       0,    /* module specific interface */
    464 
    465       (FT_Module_Constructor)ft_smooth_init,
    466       (FT_Module_Destructor) 0,
    467       (FT_Module_Requester)  0
    468     ,
    469 
    470     FT_GLYPH_FORMAT_OUTLINE,
    471 
    472     (FT_Renderer_RenderFunc)   ft_smooth_render_lcd_v,
    473     (FT_Renderer_TransformFunc)ft_smooth_transform,
    474     (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
    475     (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
    476 
    477     (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
    478   )
    479 
    480 
    481 /* END */
    482