Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ftsmooth.c                                                             */
  4. /*                                                                         */
  5. /*    Anti-aliasing renderer interface (body).                             */
  6. /*                                                                         */
  7. /*  Copyright 2000-2006, 2009-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. #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 = FT_Err_Ok;
  65.  
  66.  
  67.     if ( slot->format != render->glyph_format )
  68.     {
  69.       error = FT_THROW( 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_Pos       width, height, pitch;
  109. #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  110.     FT_Pos       height_org, width_org;
  111. #endif
  112.     FT_Bitmap*   bitmap  = &slot->bitmap;
  113.     FT_Memory    memory  = render->root.memory;
  114.     FT_Int       hmul    = mode == FT_RENDER_MODE_LCD;
  115.     FT_Int       vmul    = mode == FT_RENDER_MODE_LCD_V;
  116.     FT_Pos       x_shift = 0;
  117.     FT_Pos       y_shift = 0;
  118.     FT_Pos       x_left, y_top;
  119.  
  120.     FT_Raster_Params  params;
  121.  
  122.     FT_Bool  have_translated_origin = FALSE;
  123.     FT_Bool  have_outline_shifted   = FALSE;
  124.     FT_Bool  have_buffer            = FALSE;
  125.  
  126.  
  127.     /* check glyph image format */
  128.     if ( slot->format != render->glyph_format )
  129.     {
  130.       error = FT_THROW( Invalid_Argument );
  131.       goto Exit;
  132.     }
  133.  
  134.     /* check mode */
  135.     if ( mode != required_mode )
  136.     {
  137.       error = FT_THROW( Cannot_Render_Glyph );
  138.       goto Exit;
  139.     }
  140.  
  141.     outline = &slot->outline;
  142.  
  143.     /* translate the outline to the new origin if needed */
  144.     if ( origin )
  145.     {
  146.       FT_Outline_Translate( outline, origin->x, origin->y );
  147.       have_translated_origin = TRUE;
  148.     }
  149.  
  150.     /* compute the control box, and grid fit it */
  151.     FT_Outline_Get_CBox( outline, &cbox );
  152.  
  153.     cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
  154.     cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
  155.     cbox.xMax = FT_PIX_CEIL( cbox.xMax );
  156.     cbox.yMax = FT_PIX_CEIL( cbox.yMax );
  157.  
  158.     if ( cbox.xMin < 0 && cbox.xMax > FT_INT_MAX + cbox.xMin )
  159.     {
  160.       FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
  161.                  " xMin = %d, xMax = %d\n",
  162.                  cbox.xMin >> 6, cbox.xMax >> 6 ));
  163.       error = FT_THROW( Raster_Overflow );
  164.       goto Exit;
  165.     }
  166.     else
  167.       width = ( cbox.xMax - cbox.xMin ) >> 6;
  168.  
  169.     if ( cbox.yMin < 0 && cbox.yMax > FT_INT_MAX + cbox.yMin )
  170.     {
  171.       FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
  172.                  " yMin = %d, yMax = %d\n",
  173.                  cbox.yMin >> 6, cbox.yMax >> 6 ));
  174.       error = FT_THROW( Raster_Overflow );
  175.       goto Exit;
  176.     }
  177.     else
  178.       height = ( cbox.yMax - cbox.yMin ) >> 6;
  179.  
  180. #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  181.     width_org  = width;
  182.     height_org = height;
  183. #endif
  184.  
  185.     /* release old bitmap buffer */
  186.     if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
  187.     {
  188.       FT_FREE( bitmap->buffer );
  189.       slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
  190.     }
  191.  
  192.     /* allocate new one */
  193.     pitch = width;
  194.     if ( hmul )
  195.     {
  196.       width = width * 3;
  197.       pitch = FT_PAD_CEIL( width, 4 );
  198.     }
  199.  
  200.     if ( vmul )
  201.       height *= 3;
  202.  
  203.     x_shift = (FT_Int) cbox.xMin;
  204.     y_shift = (FT_Int) cbox.yMin;
  205.     x_left  = (FT_Int)( cbox.xMin >> 6 );
  206.     y_top   = (FT_Int)( cbox.yMax >> 6 );
  207.  
  208. #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  209.  
  210.     if ( slot->library->lcd_filter_func )
  211.     {
  212.       FT_Int  extra = slot->library->lcd_extra;
  213.  
  214.  
  215.       if ( hmul )
  216.       {
  217.         x_shift -= 64 * ( extra >> 1 );
  218.         width   += 3 * extra;
  219.         pitch    = FT_PAD_CEIL( width, 4 );
  220.         x_left  -= extra >> 1;
  221.       }
  222.  
  223.       if ( vmul )
  224.       {
  225.         y_shift -= 64 * ( extra >> 1 );
  226.         height  += 3 * extra;
  227.         y_top   += extra >> 1;
  228.       }
  229.     }
  230.  
  231. #endif
  232.  
  233. #if FT_UINT_MAX > 0xFFFFU
  234.  
  235.     /* Required check is (pitch * height < FT_ULONG_MAX),        */
  236.     /* but we care realistic cases only.  Always pitch <= width. */
  237.     if ( width > 0x7FFF || height > 0x7FFF )
  238.     {
  239.       FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n",
  240.                  width, height ));
  241.       error = FT_THROW( Raster_Overflow );
  242.       goto Exit;
  243.     }
  244.  
  245. #endif
  246.  
  247.     bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
  248.     bitmap->num_grays  = 256;
  249.     bitmap->width      = width;
  250.     bitmap->rows       = height;
  251.     bitmap->pitch      = pitch;
  252.  
  253.     /* translate outline to render it into the bitmap */
  254.     FT_Outline_Translate( outline, -x_shift, -y_shift );
  255.     have_outline_shifted = TRUE;
  256.  
  257.     if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
  258.       goto Exit;
  259.     else
  260.       have_buffer = TRUE;
  261.  
  262.     slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
  263.  
  264.     /* set up parameters */
  265.     params.target = bitmap;
  266.     params.source = outline;
  267.     params.flags  = FT_RASTER_FLAG_AA;
  268.  
  269. #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  270.  
  271.     /* implode outline if needed */
  272.     {
  273.       FT_Vector*  points     = outline->points;
  274.       FT_Vector*  points_end = points + outline->n_points;
  275.       FT_Vector*  vec;
  276.  
  277.  
  278.       if ( hmul )
  279.         for ( vec = points; vec < points_end; vec++ )
  280.           vec->x *= 3;
  281.  
  282.       if ( vmul )
  283.         for ( vec = points; vec < points_end; vec++ )
  284.           vec->y *= 3;
  285.     }
  286.  
  287.     /* render outline into the bitmap */
  288.     error = render->raster_render( render->raster, &params );
  289.  
  290.     /* deflate outline if needed */
  291.     {
  292.       FT_Vector*  points     = outline->points;
  293.       FT_Vector*  points_end = points + outline->n_points;
  294.       FT_Vector*  vec;
  295.  
  296.  
  297.       if ( hmul )
  298.         for ( vec = points; vec < points_end; vec++ )
  299.           vec->x /= 3;
  300.  
  301.       if ( vmul )
  302.         for ( vec = points; vec < points_end; vec++ )
  303.           vec->y /= 3;
  304.     }
  305.  
  306.     if ( error )
  307.       goto Exit;
  308.  
  309.     if ( slot->library->lcd_filter_func )
  310.       slot->library->lcd_filter_func( bitmap, mode, slot->library );
  311.  
  312. #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
  313.  
  314.     /* render outline into bitmap */
  315.     error = render->raster_render( render->raster, &params );
  316.     if ( error )
  317.       goto Exit;
  318.  
  319.     /* expand it horizontally */
  320.     if ( hmul )
  321.     {
  322.       FT_Byte*  line = bitmap->buffer;
  323.       FT_UInt   hh;
  324.  
  325.  
  326.       for ( hh = height_org; hh > 0; hh--, line += pitch )
  327.       {
  328.         FT_UInt   xx;
  329.         FT_Byte*  end = line + width;
  330.  
  331.  
  332.         for ( xx = width_org; xx > 0; xx-- )
  333.         {
  334.           FT_UInt  pixel = line[xx-1];
  335.  
  336.  
  337.           end[-3] = (FT_Byte)pixel;
  338.           end[-2] = (FT_Byte)pixel;
  339.           end[-1] = (FT_Byte)pixel;
  340.           end    -= 3;
  341.         }
  342.       }
  343.     }
  344.  
  345.     /* expand it vertically */
  346.     if ( vmul )
  347.     {
  348.       FT_Byte*  read  = bitmap->buffer + ( height - height_org ) * pitch;
  349.       FT_Byte*  write = bitmap->buffer;
  350.       FT_UInt   hh;
  351.  
  352.  
  353.       for ( hh = height_org; hh > 0; hh-- )
  354.       {
  355.         ft_memcpy( write, read, pitch );
  356.         write += pitch;
  357.  
  358.         ft_memcpy( write, read, pitch );
  359.         write += pitch;
  360.  
  361.         ft_memcpy( write, read, pitch );
  362.         write += pitch;
  363.         read  += pitch;
  364.       }
  365.     }
  366.  
  367. #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
  368.  
  369.     /*
  370.      * XXX: on 16bit system, we return an error for huge bitmap
  371.      * to prevent an overflow.
  372.      */
  373.     if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )
  374.     {
  375.       error = FT_THROW( Invalid_Pixel_Size );
  376.       goto Exit;
  377.     }
  378.  
  379.     slot->format      = FT_GLYPH_FORMAT_BITMAP;
  380.     slot->bitmap_left = (FT_Int)x_left;
  381.     slot->bitmap_top  = (FT_Int)y_top;
  382.  
  383.     /* everything is fine; don't deallocate buffer */
  384.     have_buffer = FALSE;
  385.  
  386.     error = FT_Err_Ok;
  387.  
  388.   Exit:
  389.     if ( have_outline_shifted )
  390.       FT_Outline_Translate( outline, x_shift, y_shift );
  391.     if ( have_translated_origin )
  392.       FT_Outline_Translate( outline, -origin->x, -origin->y );
  393.     if ( have_buffer )
  394.     {
  395.       FT_FREE( bitmap->buffer );
  396.       slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
  397.     }
  398.  
  399.     return error;
  400.   }
  401.  
  402.  
  403.   /* convert a slot's glyph image into a bitmap */
  404.   static FT_Error
  405.   ft_smooth_render( FT_Renderer       render,
  406.                     FT_GlyphSlot      slot,
  407.                     FT_Render_Mode    mode,
  408.                     const FT_Vector*  origin )
  409.   {
  410.     if ( mode == FT_RENDER_MODE_LIGHT )
  411.       mode = FT_RENDER_MODE_NORMAL;
  412.  
  413.     return ft_smooth_render_generic( render, slot, mode, origin,
  414.                                      FT_RENDER_MODE_NORMAL );
  415.   }
  416.  
  417.  
  418.   /* convert a slot's glyph image into a horizontal LCD bitmap */
  419.   static FT_Error
  420.   ft_smooth_render_lcd( FT_Renderer       render,
  421.                         FT_GlyphSlot      slot,
  422.                         FT_Render_Mode    mode,
  423.                         const FT_Vector*  origin )
  424.   {
  425.     FT_Error  error;
  426.  
  427.     error = ft_smooth_render_generic( render, slot, mode, origin,
  428.                                       FT_RENDER_MODE_LCD );
  429.     if ( !error )
  430.       slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
  431.  
  432.     return error;
  433.   }
  434.  
  435.  
  436.   /* convert a slot's glyph image into a vertical LCD bitmap */
  437.   static FT_Error
  438.   ft_smooth_render_lcd_v( FT_Renderer       render,
  439.                           FT_GlyphSlot      slot,
  440.                           FT_Render_Mode    mode,
  441.                           const FT_Vector*  origin )
  442.   {
  443.     FT_Error  error;
  444.  
  445.     error = ft_smooth_render_generic( render, slot, mode, origin,
  446.                                       FT_RENDER_MODE_LCD_V );
  447.     if ( !error )
  448.       slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
  449.  
  450.     return error;
  451.   }
  452.  
  453.  
  454.   FT_DEFINE_RENDERER( ft_smooth_renderer_class,
  455.  
  456.       FT_MODULE_RENDERER,
  457.       sizeof ( FT_RendererRec ),
  458.  
  459.       "smooth",
  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,
  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.   FT_DEFINE_RENDERER( ft_smooth_lcd_renderer_class,
  482.  
  483.       FT_MODULE_RENDERER,
  484.       sizeof ( FT_RendererRec ),
  485.  
  486.       "smooth-lcd",
  487.       0x10000L,
  488.       0x20000L,
  489.  
  490.       0,    /* module specific interface */
  491.  
  492.       (FT_Module_Constructor)ft_smooth_init,
  493.       (FT_Module_Destructor) 0,
  494.       (FT_Module_Requester)  0
  495.     ,
  496.  
  497.     FT_GLYPH_FORMAT_OUTLINE,
  498.  
  499.     (FT_Renderer_RenderFunc)   ft_smooth_render_lcd,
  500.     (FT_Renderer_TransformFunc)ft_smooth_transform,
  501.     (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
  502.     (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
  503.  
  504.     (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
  505.   )
  506.  
  507.   FT_DEFINE_RENDERER( ft_smooth_lcdv_renderer_class,
  508.  
  509.       FT_MODULE_RENDERER,
  510.       sizeof ( FT_RendererRec ),
  511.  
  512.       "smooth-lcdv",
  513.       0x10000L,
  514.       0x20000L,
  515.  
  516.       0,    /* module specific interface */
  517.  
  518.       (FT_Module_Constructor)ft_smooth_init,
  519.       (FT_Module_Destructor) 0,
  520.       (FT_Module_Requester)  0
  521.     ,
  522.  
  523.     FT_GLYPH_FORMAT_OUTLINE,
  524.  
  525.     (FT_Renderer_RenderFunc)   ft_smooth_render_lcd_v,
  526.     (FT_Renderer_TransformFunc)ft_smooth_transform,
  527.     (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
  528.     (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
  529.  
  530.     (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
  531.   )
  532.  
  533.  
  534. /* END */
  535.