1 /***************************************************************************/
5 /* Anti-aliasing renderer interface (body). */
7 /* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
20 #include FT_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_OBJECTS_H
30 /* initialize renderer -- init its raster */
32 ft_smooth_init( FT_Renderer render
)
34 FT_Library library
= FT_MODULE_LIBRARY( render
);
37 render
->clazz
->raster_class
->raster_reset( render
->raster
,
39 library
->raster_pool_size
);
45 /* sets render-specific mode */
47 ft_smooth_set_mode( FT_Renderer render
,
51 /* we simply pass it to the raster */
52 return render
->clazz
->raster_class
->raster_set_mode( render
->raster
,
57 /* transform a given glyph image */
59 ft_smooth_transform( FT_Renderer render
,
61 const FT_Matrix
* matrix
,
62 const FT_Vector
* delta
)
64 FT_Error error
= Smooth_Err_Ok
;
67 if ( slot
->format
!= render
->glyph_format
)
69 error
= Smooth_Err_Invalid_Argument
;
74 FT_Outline_Transform( &slot
->outline
, matrix
);
77 FT_Outline_Translate( &slot
->outline
, delta
->x
, delta
->y
);
84 /* return the glyph's control box */
86 ft_smooth_get_cbox( FT_Renderer render
,
90 FT_MEM_ZERO( cbox
, sizeof ( *cbox
) );
92 if ( slot
->format
== render
->glyph_format
)
93 FT_Outline_Get_CBox( &slot
->outline
, cbox
);
97 /* convert a slot's glyph image into a bitmap */
99 ft_smooth_render_generic( FT_Renderer render
,
102 const FT_Vector
* origin
,
103 FT_Render_Mode required_mode
)
106 FT_Outline
* outline
= NULL
;
108 FT_UInt width
, height
, height_org
, width_org
, pitch
;
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
;
115 FT_Raster_Params params
;
118 /* check glyph image format */
119 if ( slot
->format
!= render
->glyph_format
)
121 error
= Smooth_Err_Invalid_Argument
;
126 if ( mode
!= required_mode
)
127 return Smooth_Err_Cannot_Render_Glyph
;
129 outline
= &slot
->outline
;
131 /* translate the outline to the new origin if needed */
133 FT_Outline_Translate( outline
, origin
->x
, origin
->y
);
135 /* compute the control box, and grid fit it */
136 FT_Outline_Get_CBox( outline
, &cbox
);
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
);
143 if ( cbox
.xMin
< 0 && cbox
.xMax
> FT_INT_MAX
+ cbox
.xMin
)
145 FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
146 " xMin = %d, xMax = %d\n",
147 cbox
.xMin
>> 6, cbox
.xMax
>> 6 ));
148 return Smooth_Err_Raster_Overflow
;
151 width
= (FT_UInt
)( ( cbox
.xMax
- cbox
.xMin
) >> 6 );
153 if ( cbox
.yMin
< 0 && cbox
.yMax
> FT_INT_MAX
+ cbox
.yMin
)
155 FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
156 " yMin = %d, yMax = %d\n",
157 cbox
.yMin
>> 6, cbox
.yMax
>> 6 ));
158 return Smooth_Err_Raster_Overflow
;
161 height
= (FT_UInt
)( ( cbox
.yMax
- cbox
.yMin
) >> 6 );
163 bitmap
= &slot
->bitmap
;
164 memory
= render
->root
.memory
;
169 /* release old bitmap buffer */
170 if ( slot
->internal
->flags
& FT_GLYPH_OWN_BITMAP
)
172 FT_FREE( bitmap
->buffer
);
173 slot
->internal
->flags
&= ~FT_GLYPH_OWN_BITMAP
;
176 /* allocate new one */
181 pitch
= FT_PAD_CEIL( width
, 4 );
187 x_shift
= (FT_Int
) cbox
.xMin
;
188 y_shift
= (FT_Int
) cbox
.yMin
;
189 x_left
= (FT_Int
)( cbox
.xMin
>> 6 );
190 y_top
= (FT_Int
)( cbox
.yMax
>> 6 );
192 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
194 if ( slot
->library
->lcd_filter_func
)
196 FT_Int extra
= slot
->library
->lcd_extra
;
201 x_shift
-= 64 * ( extra
>> 1 );
203 pitch
= FT_PAD_CEIL( width
, 4 );
204 x_left
-= extra
>> 1;
209 y_shift
-= 64 * ( extra
>> 1 );
217 #if FT_UINT_MAX > 0xFFFFU
219 /* Required check is ( pitch * height < FT_ULONG_MAX ), */
220 /* but we care realistic cases only. Always pitch <= width. */
221 if ( width
> 0x7FFFU
|| height
> 0x7FFFU
)
223 FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n",
225 return Smooth_Err_Raster_Overflow
;
230 bitmap
->pixel_mode
= FT_PIXEL_MODE_GRAY
;
231 bitmap
->num_grays
= 256;
232 bitmap
->width
= width
;
233 bitmap
->rows
= height
;
234 bitmap
->pitch
= pitch
;
236 /* translate outline to render it into the bitmap */
237 FT_Outline_Translate( outline
, -x_shift
, -y_shift
);
239 if ( FT_ALLOC( bitmap
->buffer
, (FT_ULong
)pitch
* height
) )
242 slot
->internal
->flags
|= FT_GLYPH_OWN_BITMAP
;
244 /* set up parameters */
245 params
.target
= bitmap
;
246 params
.source
= outline
;
247 params
.flags
= FT_RASTER_FLAG_AA
;
249 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
251 /* implode outline if needed */
253 FT_Vector
* points
= outline
->points
;
254 FT_Vector
* points_end
= points
+ outline
->n_points
;
259 for ( vec
= points
; vec
< points_end
; vec
++ )
263 for ( vec
= points
; vec
< points_end
; vec
++ )
267 /* render outline into the bitmap */
268 error
= render
->raster_render( render
->raster
, ¶ms
);
270 /* deflate outline if needed */
272 FT_Vector
* points
= outline
->points
;
273 FT_Vector
* points_end
= points
+ outline
->n_points
;
278 for ( vec
= points
; vec
< points_end
; vec
++ )
282 for ( vec
= points
; vec
< points_end
; vec
++ )
286 if ( slot
->library
->lcd_filter_func
)
287 slot
->library
->lcd_filter_func( bitmap
, mode
, slot
->library
);
289 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
291 /* render outline into bitmap */
292 error
= render
->raster_render( render
->raster
, ¶ms
);
294 /* expand it horizontally */
297 FT_Byte
* line
= bitmap
->buffer
;
301 for ( hh
= height_org
; hh
> 0; hh
--, line
+= pitch
)
304 FT_Byte
* end
= line
+ width
;
307 for ( xx
= width_org
; xx
> 0; xx
-- )
309 FT_UInt pixel
= line
[xx
-1];
312 end
[-3] = (FT_Byte
)pixel
;
313 end
[-2] = (FT_Byte
)pixel
;
314 end
[-1] = (FT_Byte
)pixel
;
320 /* expand it vertically */
323 FT_Byte
* read
= bitmap
->buffer
+ ( height
- height_org
) * pitch
;
324 FT_Byte
* write
= bitmap
->buffer
;
328 for ( hh
= height_org
; hh
> 0; hh
-- )
330 ft_memcpy( write
, read
, pitch
);
333 ft_memcpy( write
, read
, pitch
);
336 ft_memcpy( write
, read
, pitch
);
342 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
344 FT_Outline_Translate( outline
, x_shift
, y_shift
);
347 * XXX: on 16bit system, we return an error for huge bitmap
348 * to prevent an overflow.
350 if ( x_left
> FT_INT_MAX
|| y_top
> FT_INT_MAX
)
351 return Smooth_Err_Invalid_Pixel_Size
;
356 slot
->format
= FT_GLYPH_FORMAT_BITMAP
;
357 slot
->bitmap_left
= (FT_Int
)x_left
;
358 slot
->bitmap_top
= (FT_Int
)y_top
;
361 if ( outline
&& origin
)
362 FT_Outline_Translate( outline
, -origin
->x
, -origin
->y
);
368 /* convert a slot's glyph image into a bitmap */
370 ft_smooth_render( FT_Renderer render
,
373 const FT_Vector
* origin
)
375 if ( mode
== FT_RENDER_MODE_LIGHT
)
376 mode
= FT_RENDER_MODE_NORMAL
;
378 return ft_smooth_render_generic( render
, slot
, mode
, origin
,
379 FT_RENDER_MODE_NORMAL
);
383 /* convert a slot's glyph image into a horizontal LCD bitmap */
385 ft_smooth_render_lcd( FT_Renderer render
,
388 const FT_Vector
* origin
)
392 error
= ft_smooth_render_generic( render
, slot
, mode
, origin
,
393 FT_RENDER_MODE_LCD
);
395 slot
->bitmap
.pixel_mode
= FT_PIXEL_MODE_LCD
;
401 /* convert a slot's glyph image into a vertical LCD bitmap */
403 ft_smooth_render_lcd_v( FT_Renderer render
,
406 const FT_Vector
* origin
)
410 error
= ft_smooth_render_generic( render
, slot
, mode
, origin
,
411 FT_RENDER_MODE_LCD_V
);
413 slot
->bitmap
.pixel_mode
= FT_PIXEL_MODE_LCD_V
;
419 FT_DEFINE_RENDERER(ft_smooth_renderer_class
,
422 sizeof( FT_RendererRec
),
428 0, /* module specific interface */
430 (FT_Module_Constructor
)ft_smooth_init
,
431 (FT_Module_Destructor
) 0,
432 (FT_Module_Requester
) 0
435 FT_GLYPH_FORMAT_OUTLINE
,
437 (FT_Renderer_RenderFunc
) ft_smooth_render
,
438 (FT_Renderer_TransformFunc
)ft_smooth_transform
,
439 (FT_Renderer_GetCBoxFunc
) ft_smooth_get_cbox
,
440 (FT_Renderer_SetModeFunc
) ft_smooth_set_mode
,
442 (FT_Raster_Funcs
*) &FT_GRAYS_RASTER_GET
446 FT_DEFINE_RENDERER(ft_smooth_lcd_renderer_class
,
449 sizeof( FT_RendererRec
),
455 0, /* module specific interface */
457 (FT_Module_Constructor
)ft_smooth_init
,
458 (FT_Module_Destructor
) 0,
459 (FT_Module_Requester
) 0
462 FT_GLYPH_FORMAT_OUTLINE
,
464 (FT_Renderer_RenderFunc
) ft_smooth_render_lcd
,
465 (FT_Renderer_TransformFunc
)ft_smooth_transform
,
466 (FT_Renderer_GetCBoxFunc
) ft_smooth_get_cbox
,
467 (FT_Renderer_SetModeFunc
) ft_smooth_set_mode
,
469 (FT_Raster_Funcs
*) &FT_GRAYS_RASTER_GET
472 FT_DEFINE_RENDERER(ft_smooth_lcdv_renderer_class
,
475 sizeof( FT_RendererRec
),
481 0, /* module specific interface */
483 (FT_Module_Constructor
)ft_smooth_init
,
484 (FT_Module_Destructor
) 0,
485 (FT_Module_Requester
) 0
488 FT_GLYPH_FORMAT_OUTLINE
,
490 (FT_Renderer_RenderFunc
) ft_smooth_render_lcd_v
,
491 (FT_Renderer_TransformFunc
)ft_smooth_transform
,
492 (FT_Renderer_GetCBoxFunc
) ft_smooth_get_cbox
,
493 (FT_Renderer_SetModeFunc
) ft_smooth_set_mode
,
495 (FT_Raster_Funcs
*) &FT_GRAYS_RASTER_GET