1 /***************************************************************************/
5 /* Anti-aliasing renderer interface (body). */
7 /* Copyright 2000-2006, 2009-2012 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_Pos width, height, pitch;
109 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
110 FT_Pos height_org, width_org;
114 FT_Int hmul = mode == FT_RENDER_MODE_LCD;
115 FT_Int vmul = mode == FT_RENDER_MODE_LCD_V;
116 FT_Pos x_shift, y_shift, x_left, y_top;
118 FT_Raster_Params params;
121 /* check glyph image format */
122 if ( slot->format != render->glyph_format )
124 error = Smooth_Err_Invalid_Argument;
129 if ( mode != required_mode )
130 return Smooth_Err_Cannot_Render_Glyph;
132 outline = &slot->outline;
134 /* translate the outline to the new origin if needed */
136 FT_Outline_Translate( outline, origin->x, origin->y );
138 /* compute the control box, and grid fit it */
139 FT_Outline_Get_CBox( outline, &cbox );
141 cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
142 cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
143 cbox.xMax = FT_PIX_CEIL( cbox.xMax );
144 cbox.yMax = FT_PIX_CEIL( cbox.yMax );
146 if ( cbox.xMin < 0 && cbox.xMax > FT_INT_MAX + cbox.xMin )
148 FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
149 " xMin = %d, xMax = %d\n",
150 cbox.xMin >> 6, cbox.xMax >> 6 ));
151 return Smooth_Err_Raster_Overflow;
154 width = ( cbox.xMax - cbox.xMin ) >> 6;
156 if ( cbox.yMin < 0 && cbox.yMax > FT_INT_MAX + cbox.yMin )
158 FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
159 " yMin = %d, yMax = %d\n",
160 cbox.yMin >> 6, cbox.yMax >> 6 ));
161 return Smooth_Err_Raster_Overflow;
164 height = ( cbox.yMax - cbox.yMin ) >> 6;
166 bitmap = &slot->bitmap;
167 memory = render->root.memory;
169 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
174 /* release old bitmap buffer */
175 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
177 FT_FREE( bitmap->buffer );
178 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
181 /* allocate new one */
186 pitch = FT_PAD_CEIL( width, 4 );
192 x_shift = (FT_Int) cbox.xMin;
193 y_shift = (FT_Int) cbox.yMin;
194 x_left = (FT_Int)( cbox.xMin >> 6 );
195 y_top = (FT_Int)( cbox.yMax >> 6 );
197 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
199 if ( slot->library->lcd_filter_func )
201 FT_Int extra = slot->library->lcd_extra;
206 x_shift -= 64 * ( extra >> 1 );
208 pitch = FT_PAD_CEIL( width, 4 );
209 x_left -= extra >> 1;
214 y_shift -= 64 * ( extra >> 1 );
222 #if FT_UINT_MAX > 0xFFFFU
224 /* Required check is ( pitch * height < FT_ULONG_MAX ), */
225 /* but we care realistic cases only. Always pitch <= width. */
226 if ( width > 0x7FFF || height > 0x7FFF )
228 FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n",
230 return Smooth_Err_Raster_Overflow;
235 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
236 bitmap->num_grays = 256;
237 bitmap->width = width;
238 bitmap->rows = height;
239 bitmap->pitch = pitch;
241 /* translate outline to render it into the bitmap */
242 FT_Outline_Translate( outline, -x_shift, -y_shift );
244 if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
247 slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
249 /* set up parameters */
250 params.target = bitmap;
251 params.source = outline;
252 params.flags = FT_RASTER_FLAG_AA;
254 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
256 /* implode outline if needed */
258 FT_Vector* points = outline->points;
259 FT_Vector* points_end = points + outline->n_points;
264 for ( vec = points; vec < points_end; vec++ )
268 for ( vec = points; vec < points_end; vec++ )
272 /* render outline into the bitmap */
273 error = render->raster_render( render->raster, ¶ms );
275 /* deflate outline if needed */
277 FT_Vector* points = outline->points;
278 FT_Vector* points_end = points + outline->n_points;
283 for ( vec = points; vec < points_end; vec++ )
287 for ( vec = points; vec < points_end; vec++ )
291 if ( slot->library->lcd_filter_func )
292 slot->library->lcd_filter_func( bitmap, mode, slot->library );
294 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
296 /* render outline into bitmap */
297 error = render->raster_render( render->raster, ¶ms );
299 /* expand it horizontally */
302 FT_Byte* line = bitmap->buffer;
306 for ( hh = height_org; hh > 0; hh--, line += pitch )
309 FT_Byte* end = line + width;
312 for ( xx = width_org; xx > 0; xx-- )
314 FT_UInt pixel = line[xx-1];
317 end[-3] = (FT_Byte)pixel;
318 end[-2] = (FT_Byte)pixel;
319 end[-1] = (FT_Byte)pixel;
325 /* expand it vertically */
328 FT_Byte* read = bitmap->buffer + ( height - height_org ) * pitch;
329 FT_Byte* write = bitmap->buffer;
333 for ( hh = height_org; hh > 0; hh-- )
335 ft_memcpy( write, read, pitch );
338 ft_memcpy( write, read, pitch );
341 ft_memcpy( write, read, pitch );
347 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
349 FT_Outline_Translate( outline, x_shift, y_shift );
352 * XXX: on 16bit system, we return an error for huge bitmap
353 * to prevent an overflow.
355 if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )
356 return Smooth_Err_Invalid_Pixel_Size;
361 slot->format = FT_GLYPH_FORMAT_BITMAP;
362 slot->bitmap_left = (FT_Int)x_left;
363 slot->bitmap_top = (FT_Int)y_top;
366 if ( outline && origin )
367 FT_Outline_Translate( outline, -origin->x, -origin->y );
373 /* convert a slot's glyph image into a bitmap */
375 ft_smooth_render( FT_Renderer render,
378 const FT_Vector* origin )
380 if ( mode == FT_RENDER_MODE_LIGHT )
381 mode = FT_RENDER_MODE_NORMAL;
383 return ft_smooth_render_generic( render, slot, mode, origin,
384 FT_RENDER_MODE_NORMAL );
388 /* convert a slot's glyph image into a horizontal LCD bitmap */
390 ft_smooth_render_lcd( FT_Renderer render,
393 const FT_Vector* origin )
397 error = ft_smooth_render_generic( render, slot, mode, origin,
398 FT_RENDER_MODE_LCD );
400 slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
406 /* convert a slot's glyph image into a vertical LCD bitmap */
408 ft_smooth_render_lcd_v( FT_Renderer render,
411 const FT_Vector* origin )
415 error = ft_smooth_render_generic( render, slot, mode, origin,
416 FT_RENDER_MODE_LCD_V );
418 slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
424 FT_DEFINE_RENDERER( ft_smooth_renderer_class,
427 sizeof ( FT_RendererRec ),
433 0, /* module specific interface */
435 (FT_Module_Constructor)ft_smooth_init,
436 (FT_Module_Destructor) 0,
437 (FT_Module_Requester) 0
440 FT_GLYPH_FORMAT_OUTLINE,
442 (FT_Renderer_RenderFunc) ft_smooth_render,
443 (FT_Renderer_TransformFunc)ft_smooth_transform,
444 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
445 (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
447 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
451 FT_DEFINE_RENDERER( ft_smooth_lcd_renderer_class,
454 sizeof ( FT_RendererRec ),
460 0, /* module specific interface */
462 (FT_Module_Constructor)ft_smooth_init,
463 (FT_Module_Destructor) 0,
464 (FT_Module_Requester) 0
467 FT_GLYPH_FORMAT_OUTLINE,
469 (FT_Renderer_RenderFunc) ft_smooth_render_lcd,
470 (FT_Renderer_TransformFunc)ft_smooth_transform,
471 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
472 (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
474 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
477 FT_DEFINE_RENDERER( ft_smooth_lcdv_renderer_class,
480 sizeof ( FT_RendererRec ),
486 0, /* module specific interface */
488 (FT_Module_Constructor)ft_smooth_init,
489 (FT_Module_Destructor) 0,
490 (FT_Module_Requester) 0
493 FT_GLYPH_FORMAT_OUTLINE,
495 (FT_Renderer_RenderFunc) ft_smooth_render_lcd_v,
496 (FT_Renderer_TransformFunc)ft_smooth_transform,
497 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
498 (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
500 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET