ftsmooth.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ftsmooth.c                                                             */
00004 /*                                                                         */
00005 /*    Anti-aliasing renderer interface (body).                             */
00006 /*                                                                         */
00007 /*  Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2009 by             */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019 #include <ft2build.h>
00020 #include FT_INTERNAL_DEBUG_H
00021 #include FT_INTERNAL_OBJECTS_H
00022 #include FT_OUTLINE_H
00023 #include "ftsmooth.h"
00024 #include "ftgrays.h"
00025 #include "ftspic.h"
00026 
00027 #include "ftsmerrs.h"
00028 
00029 
00030   /* initialize renderer -- init its raster */
00031   static FT_Error
00032   ft_smooth_init( FT_Renderer  render )
00033   {
00034     FT_Library  library = FT_MODULE_LIBRARY( render );
00035 
00036 
00037     render->clazz->raster_class->raster_reset( render->raster,
00038                                                library->raster_pool,
00039                                                library->raster_pool_size );
00040 
00041     return 0;
00042   }
00043 
00044 
00045   /* sets render-specific mode */
00046   static FT_Error
00047   ft_smooth_set_mode( FT_Renderer  render,
00048                       FT_ULong     mode_tag,
00049                       FT_Pointer   data )
00050   {
00051     /* we simply pass it to the raster */
00052     return render->clazz->raster_class->raster_set_mode( render->raster,
00053                                                          mode_tag,
00054                                                          data );
00055   }
00056 
00057   /* transform a given glyph image */
00058   static FT_Error
00059   ft_smooth_transform( FT_Renderer       render,
00060                        FT_GlyphSlot      slot,
00061                        const FT_Matrix*  matrix,
00062                        const FT_Vector*  delta )
00063   {
00064     FT_Error  error = Smooth_Err_Ok;
00065 
00066 
00067     if ( slot->format != render->glyph_format )
00068     {
00069       error = Smooth_Err_Invalid_Argument;
00070       goto Exit;
00071     }
00072 
00073     if ( matrix )
00074       FT_Outline_Transform( &slot->outline, matrix );
00075 
00076     if ( delta )
00077       FT_Outline_Translate( &slot->outline, delta->x, delta->y );
00078 
00079   Exit:
00080     return error;
00081   }
00082 
00083 
00084   /* return the glyph's control box */
00085   static void
00086   ft_smooth_get_cbox( FT_Renderer   render,
00087                       FT_GlyphSlot  slot,
00088                       FT_BBox*      cbox )
00089   {
00090     FT_MEM_ZERO( cbox, sizeof ( *cbox ) );
00091 
00092     if ( slot->format == render->glyph_format )
00093       FT_Outline_Get_CBox( &slot->outline, cbox );
00094   }
00095 
00096 
00097   /* convert a slot's glyph image into a bitmap */
00098   static FT_Error
00099   ft_smooth_render_generic( FT_Renderer       render,
00100                             FT_GlyphSlot      slot,
00101                             FT_Render_Mode    mode,
00102                             const FT_Vector*  origin,
00103                             FT_Render_Mode    required_mode )
00104   {
00105     FT_Error     error;
00106     FT_Outline*  outline = NULL;
00107     FT_BBox      cbox;
00108     FT_UInt      width, height, height_org, width_org, pitch;
00109     FT_Bitmap*   bitmap;
00110     FT_Memory    memory;
00111     FT_Int       hmul = mode == FT_RENDER_MODE_LCD;
00112     FT_Int       vmul = mode == FT_RENDER_MODE_LCD_V;
00113     FT_Pos       x_shift, y_shift, x_left, y_top;
00114 
00115     FT_Raster_Params  params;
00116 
00117 
00118     /* check glyph image format */
00119     if ( slot->format != render->glyph_format )
00120     {
00121       error = Smooth_Err_Invalid_Argument;
00122       goto Exit;
00123     }
00124 
00125     /* check mode */
00126     if ( mode != required_mode )
00127       return Smooth_Err_Cannot_Render_Glyph;
00128 
00129     outline = &slot->outline;
00130 
00131     /* translate the outline to the new origin if needed */
00132     if ( origin )
00133       FT_Outline_Translate( outline, origin->x, origin->y );
00134 
00135     /* compute the control box, and grid fit it */
00136     FT_Outline_Get_CBox( outline, &cbox );
00137 
00138     cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
00139     cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
00140     cbox.xMax = FT_PIX_CEIL( cbox.xMax );
00141     cbox.yMax = FT_PIX_CEIL( cbox.yMax );
00142 
00143     width  = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
00144     height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
00145     bitmap = &slot->bitmap;
00146     memory = render->root.memory;
00147 
00148     width_org  = width;
00149     height_org = height;
00150 
00151     /* release old bitmap buffer */
00152     if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
00153     {
00154       FT_FREE( bitmap->buffer );
00155       slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
00156     }
00157 
00158     /* allocate new one */
00159     pitch = width;
00160     if ( hmul )
00161     {
00162       width = width * 3;
00163       pitch = FT_PAD_CEIL( width, 4 );
00164     }
00165 
00166     if ( vmul )
00167       height *= 3;
00168 
00169     x_shift = (FT_Int) cbox.xMin;
00170     y_shift = (FT_Int) cbox.yMin;
00171     x_left  = (FT_Int)( cbox.xMin >> 6 );
00172     y_top   = (FT_Int)( cbox.yMax >> 6 );
00173 
00174 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
00175 
00176     if ( slot->library->lcd_filter_func )
00177     {
00178       FT_Int  extra = slot->library->lcd_extra;
00179 
00180 
00181       if ( hmul )
00182       {
00183         x_shift -= 64 * ( extra >> 1 );
00184         width   += 3 * extra;
00185         pitch    = FT_PAD_CEIL( width, 4 );
00186         x_left  -= extra >> 1;
00187       }
00188 
00189       if ( vmul )
00190       {
00191         y_shift -= 64 * ( extra >> 1 );
00192         height  += 3 * extra;
00193         y_top   += extra >> 1;
00194       }
00195     }
00196 
00197 #endif
00198 
00199 #if FT_UINT_MAX > 0xFFFFU
00200 
00201     /* Required check is ( pitch * height < FT_ULONG_MAX ),     */
00202     /* but we care realistic cases only. Always pitch <= width. */
00203     if ( width > 0xFFFFU || height > 0xFFFFU )
00204     {
00205       FT_ERROR(( "ft_smooth_render_generic: glyph too large: %d x %d\n",
00206                  width, height ));
00207       return Smooth_Err_Raster_Overflow;
00208     }
00209 
00210 #endif
00211 
00212     bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
00213     bitmap->num_grays  = 256;
00214     bitmap->width      = width;
00215     bitmap->rows       = height;
00216     bitmap->pitch      = pitch;
00217 
00218     /* translate outline to render it into the bitmap */
00219     FT_Outline_Translate( outline, -x_shift, -y_shift );
00220 
00221     if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
00222       goto Exit;
00223 
00224     slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
00225 
00226     /* set up parameters */
00227     params.target = bitmap;
00228     params.source = outline;
00229     params.flags  = FT_RASTER_FLAG_AA;
00230 
00231 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
00232 
00233     /* implode outline if needed */
00234     {
00235       FT_Vector*  points     = outline->points;
00236       FT_Vector*  points_end = points + outline->n_points;
00237       FT_Vector*  vec;
00238 
00239 
00240       if ( hmul )
00241         for ( vec = points; vec < points_end; vec++ )
00242           vec->x *= 3;
00243 
00244       if ( vmul )
00245         for ( vec = points; vec < points_end; vec++ )
00246           vec->y *= 3;
00247     }
00248 
00249     /* render outline into the bitmap */
00250     error = render->raster_render( render->raster, &params );
00251 
00252     /* deflate outline if needed */
00253     {
00254       FT_Vector*  points     = outline->points;
00255       FT_Vector*  points_end = points + outline->n_points;
00256       FT_Vector*  vec;
00257 
00258 
00259       if ( hmul )
00260         for ( vec = points; vec < points_end; vec++ )
00261           vec->x /= 3;
00262 
00263       if ( vmul )
00264         for ( vec = points; vec < points_end; vec++ )
00265           vec->y /= 3;
00266     }
00267 
00268     if ( slot->library->lcd_filter_func )
00269       slot->library->lcd_filter_func( bitmap, mode, slot->library );
00270 
00271 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
00272 
00273     /* render outline into bitmap */
00274     error = render->raster_render( render->raster, &params );
00275 
00276     /* expand it horizontally */
00277     if ( hmul )
00278     {
00279       FT_Byte*  line = bitmap->buffer;
00280       FT_UInt   hh;
00281 
00282 
00283       for ( hh = height_org; hh > 0; hh--, line += pitch )
00284       {
00285         FT_UInt   xx;
00286         FT_Byte*  end = line + width;
00287 
00288 
00289         for ( xx = width_org; xx > 0; xx-- )
00290         {
00291           FT_UInt  pixel = line[xx-1];
00292 
00293 
00294           end[-3] = (FT_Byte)pixel;
00295           end[-2] = (FT_Byte)pixel;
00296           end[-1] = (FT_Byte)pixel;
00297           end    -= 3;
00298         }
00299       }
00300     }
00301 
00302     /* expand it vertically */
00303     if ( vmul )
00304     {
00305       FT_Byte*  read  = bitmap->buffer + ( height - height_org ) * pitch;
00306       FT_Byte*  write = bitmap->buffer;
00307       FT_UInt   hh;
00308 
00309 
00310       for ( hh = height_org; hh > 0; hh-- )
00311       {
00312         ft_memcpy( write, read, pitch );
00313         write += pitch;
00314 
00315         ft_memcpy( write, read, pitch );
00316         write += pitch;
00317 
00318         ft_memcpy( write, read, pitch );
00319         write += pitch;
00320         read  += pitch;
00321       }
00322     }
00323 
00324 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
00325 
00326     FT_Outline_Translate( outline, x_shift, y_shift );
00327 
00328     /*
00329      * XXX: on 16bit system, we return an error for huge bitmap
00330      * to prevent an overflow.
00331      */
00332     if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )
00333       return Smooth_Err_Invalid_Pixel_Size;
00334 
00335     if ( error )
00336       goto Exit;
00337 
00338     slot->format      = FT_GLYPH_FORMAT_BITMAP;
00339     slot->bitmap_left = (FT_Int)x_left;
00340     slot->bitmap_top  = (FT_Int)y_top;
00341 
00342   Exit:
00343     if ( outline && origin )
00344       FT_Outline_Translate( outline, -origin->x, -origin->y );
00345 
00346     return error;
00347   }
00348 
00349 
00350   /* convert a slot's glyph image into a bitmap */
00351   static FT_Error
00352   ft_smooth_render( FT_Renderer       render,
00353                     FT_GlyphSlot      slot,
00354                     FT_Render_Mode    mode,
00355                     const FT_Vector*  origin )
00356   {
00357     if ( mode == FT_RENDER_MODE_LIGHT )
00358       mode = FT_RENDER_MODE_NORMAL;
00359 
00360     return ft_smooth_render_generic( render, slot, mode, origin,
00361                                      FT_RENDER_MODE_NORMAL );
00362   }
00363 
00364 
00365   /* convert a slot's glyph image into a horizontal LCD bitmap */
00366   static FT_Error
00367   ft_smooth_render_lcd( FT_Renderer       render,
00368                         FT_GlyphSlot      slot,
00369                         FT_Render_Mode    mode,
00370                         const FT_Vector*  origin )
00371   {
00372     FT_Error  error;
00373 
00374     error = ft_smooth_render_generic( render, slot, mode, origin,
00375                                       FT_RENDER_MODE_LCD );
00376     if ( !error )
00377       slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
00378 
00379     return error;
00380   }
00381 
00382 
00383   /* convert a slot's glyph image into a vertical LCD bitmap */
00384   static FT_Error
00385   ft_smooth_render_lcd_v( FT_Renderer       render,
00386                           FT_GlyphSlot      slot,
00387                           FT_Render_Mode    mode,
00388                           const FT_Vector*  origin )
00389   {
00390     FT_Error  error;
00391 
00392     error = ft_smooth_render_generic( render, slot, mode, origin,
00393                                       FT_RENDER_MODE_LCD_V );
00394     if ( !error )
00395       slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
00396 
00397     return error;
00398   }
00399 
00400 
00401   FT_DEFINE_RENDERER(ft_smooth_renderer_class,
00402 
00403       FT_MODULE_RENDERER,
00404       sizeof( FT_RendererRec ),
00405 
00406       "smooth",
00407       0x10000L,
00408       0x20000L,
00409 
00410       0,    /* module specific interface */
00411 
00412       (FT_Module_Constructor)ft_smooth_init,
00413       (FT_Module_Destructor) 0,
00414       (FT_Module_Requester)  0
00415     ,
00416 
00417     FT_GLYPH_FORMAT_OUTLINE,
00418 
00419     (FT_Renderer_RenderFunc)   ft_smooth_render,
00420     (FT_Renderer_TransformFunc)ft_smooth_transform,
00421     (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
00422     (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
00423 
00424     (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
00425   )
00426 
00427 
00428   FT_DEFINE_RENDERER(ft_smooth_lcd_renderer_class,
00429   
00430       FT_MODULE_RENDERER,
00431       sizeof( FT_RendererRec ),
00432 
00433       "smooth-lcd",
00434       0x10000L,
00435       0x20000L,
00436 
00437       0,    /* module specific interface */
00438 
00439       (FT_Module_Constructor)ft_smooth_init,
00440       (FT_Module_Destructor) 0,
00441       (FT_Module_Requester)  0
00442     ,
00443 
00444     FT_GLYPH_FORMAT_OUTLINE,
00445 
00446     (FT_Renderer_RenderFunc)   ft_smooth_render_lcd,
00447     (FT_Renderer_TransformFunc)ft_smooth_transform,
00448     (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
00449     (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
00450 
00451     (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
00452   )
00453 
00454   FT_DEFINE_RENDERER(ft_smooth_lcdv_renderer_class,
00455 
00456       FT_MODULE_RENDERER,
00457       sizeof( FT_RendererRec ),
00458 
00459       "smooth-lcdv",
00460       0x10000L,
00461       0x20000L,
00462 
00463       0,    /* module specific interface */
00464 
00465       (FT_Module_Constructor)ft_smooth_init,
00466       (FT_Module_Destructor) 0,
00467       (FT_Module_Requester)  0
00468     ,
00469 
00470     FT_GLYPH_FORMAT_OUTLINE,
00471 
00472     (FT_Renderer_RenderFunc)   ft_smooth_render_lcd_v,
00473     (FT_Renderer_TransformFunc)ft_smooth_transform,
00474     (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
00475     (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
00476 
00477     (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
00478   )
00479 
00480 
00481 /* END */

Generated on Tue Jul 5 14:13:51 2011 for ROOT_528-00b_version by  doxygen 1.5.1