1 /***************************************************************************/
5 /* Anti-aliasing renderer interface (body). */
7 /* Copyright 2000-2016 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 = FT_Err_Ok;
67 if ( slot->format != render->glyph_format )
69 error = FT_THROW( 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 = &slot->outline;
107 FT_Bitmap* bitmap = &slot->bitmap;
108 FT_Memory memory = render->root.memory;
112 FT_Pos x_left, y_top;
113 FT_Pos width, height, pitch;
114 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
115 FT_Pos height_org, width_org;
117 FT_Int hmul = mode == FT_RENDER_MODE_LCD;
118 FT_Int vmul = mode == FT_RENDER_MODE_LCD_V;
120 FT_Raster_Params params;
122 FT_Bool have_outline_shifted = FALSE;
123 FT_Bool have_buffer = FALSE;
126 /* check glyph image format */
127 if ( slot->format != render->glyph_format )
129 error = FT_THROW( Invalid_Argument );
134 if ( mode != required_mode )
136 error = FT_THROW( Cannot_Render_Glyph );
146 /* compute the control box, and grid fit it */
147 /* taking into account the origin shift */
148 FT_Outline_Get_CBox( outline, &cbox );
150 cbox.xMin = FT_PIX_FLOOR( cbox.xMin + x_shift );
151 cbox.yMin = FT_PIX_FLOOR( cbox.yMin + y_shift );
152 cbox.xMax = FT_PIX_CEIL( cbox.xMax + x_shift );
153 cbox.yMax = FT_PIX_CEIL( cbox.yMax + y_shift );
155 x_shift -= cbox.xMin;
156 y_shift -= cbox.yMin;
158 x_left = cbox.xMin >> 6;
159 y_top = cbox.yMax >> 6;
161 width = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6;
162 height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6;
164 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
173 pitch = FT_PAD_CEIL( width, 4 );
179 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
181 if ( slot->library->lcd_filter_func )
183 FT_Int extra = slot->library->lcd_extra;
188 x_shift += 64 * ( extra >> 1 );
189 x_left -= extra >> 1;
191 pitch = FT_PAD_CEIL( width, 4 );
196 y_shift += 64 * ( extra >> 1 );
205 * XXX: on 16bit system, we return an error for huge bitmap
206 * to prevent an overflow.
208 if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX ||
209 x_left < FT_INT_MIN || y_top < FT_INT_MIN )
211 error = FT_THROW( Invalid_Pixel_Size );
215 /* Required check is (pitch * height < FT_ULONG_MAX), */
216 /* but we care realistic cases only. Always pitch <= width. */
217 if ( width > 0x7FFF || height > 0x7FFF )
219 FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n",
221 error = FT_THROW( Raster_Overflow );
225 /* release old bitmap buffer */
226 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
228 FT_FREE( bitmap->buffer );
229 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
232 /* allocate new one */
233 if ( FT_ALLOC( bitmap->buffer, (FT_ULong)( pitch * height ) ) )
238 slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
240 slot->format = FT_GLYPH_FORMAT_BITMAP;
241 slot->bitmap_left = (FT_Int)x_left;
242 slot->bitmap_top = (FT_Int)y_top;
244 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
245 bitmap->num_grays = 256;
246 bitmap->width = (unsigned int)width;
247 bitmap->rows = (unsigned int)height;
248 bitmap->pitch = pitch;
250 /* translate outline to render it into the bitmap */
251 if ( x_shift || y_shift )
253 FT_Outline_Translate( outline, x_shift, y_shift );
254 have_outline_shifted = TRUE;
257 /* set up parameters */
258 params.target = bitmap;
259 params.source = outline;
260 params.flags = FT_RASTER_FLAG_AA;
262 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
264 /* implode outline if needed */
266 FT_Vector* points = outline->points;
267 FT_Vector* points_end = points + outline->n_points;
272 for ( vec = points; vec < points_end; vec++ )
276 for ( vec = points; vec < points_end; vec++ )
280 /* render outline into the bitmap */
281 error = render->raster_render( render->raster, ¶ms );
283 /* deflate outline if needed */
285 FT_Vector* points = outline->points;
286 FT_Vector* points_end = points + outline->n_points;
291 for ( vec = points; vec < points_end; vec++ )
295 for ( vec = points; vec < points_end; vec++ )
302 if ( slot->library->lcd_filter_func )
303 slot->library->lcd_filter_func( bitmap, mode, slot->library );
305 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
307 /* render outline into bitmap */
308 error = render->raster_render( render->raster, ¶ms );
312 /* expand it horizontally */
315 FT_Byte* line = bitmap->buffer;
319 for ( hh = height_org; hh > 0; hh--, line += pitch )
322 FT_Byte* end = line + width;
325 for ( xx = width_org; xx > 0; xx-- )
327 FT_UInt pixel = line[xx-1];
330 end[-3] = (FT_Byte)pixel;
331 end[-2] = (FT_Byte)pixel;
332 end[-1] = (FT_Byte)pixel;
338 /* expand it vertically */
341 FT_Byte* read = bitmap->buffer + ( height - height_org ) * pitch;
342 FT_Byte* write = bitmap->buffer;
346 for ( hh = height_org; hh > 0; hh-- )
348 ft_memcpy( write, read, pitch );
351 ft_memcpy( write, read, pitch );
354 ft_memcpy( write, read, pitch );
360 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
362 /* everything is fine; don't deallocate buffer */
368 if ( have_outline_shifted )
369 FT_Outline_Translate( outline, -x_shift, -y_shift );
372 FT_FREE( bitmap->buffer );
373 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
380 /* convert a slot's glyph image into a bitmap */
382 ft_smooth_render( FT_Renderer render,
385 const FT_Vector* origin )
387 if ( mode == FT_RENDER_MODE_LIGHT )
388 mode = FT_RENDER_MODE_NORMAL;
390 return ft_smooth_render_generic( render, slot, mode, origin,
391 FT_RENDER_MODE_NORMAL );
395 /* convert a slot's glyph image into a horizontal LCD bitmap */
397 ft_smooth_render_lcd( FT_Renderer render,
400 const FT_Vector* origin )
404 error = ft_smooth_render_generic( render, slot, mode, origin,
405 FT_RENDER_MODE_LCD );
407 slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
413 /* convert a slot's glyph image into a vertical LCD bitmap */
415 ft_smooth_render_lcd_v( FT_Renderer render,
418 const FT_Vector* origin )
422 error = ft_smooth_render_generic( render, slot, mode, origin,
423 FT_RENDER_MODE_LCD_V );
425 slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
431 FT_DEFINE_RENDERER( ft_smooth_renderer_class,
434 sizeof ( FT_RendererRec ),
440 0, /* module specific interface */
442 (FT_Module_Constructor)ft_smooth_init,
443 (FT_Module_Destructor) 0,
444 (FT_Module_Requester) 0
447 FT_GLYPH_FORMAT_OUTLINE,
449 (FT_Renderer_RenderFunc) ft_smooth_render,
450 (FT_Renderer_TransformFunc)ft_smooth_transform,
451 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
452 (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
454 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
458 FT_DEFINE_RENDERER( ft_smooth_lcd_renderer_class,
461 sizeof ( FT_RendererRec ),
467 0, /* module specific interface */
469 (FT_Module_Constructor)ft_smooth_init,
470 (FT_Module_Destructor) 0,
471 (FT_Module_Requester) 0
474 FT_GLYPH_FORMAT_OUTLINE,
476 (FT_Renderer_RenderFunc) ft_smooth_render_lcd,
477 (FT_Renderer_TransformFunc)ft_smooth_transform,
478 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
479 (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
481 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
484 FT_DEFINE_RENDERER( ft_smooth_lcdv_renderer_class,
487 sizeof ( FT_RendererRec ),
493 0, /* module specific interface */
495 (FT_Module_Constructor)ft_smooth_init,
496 (FT_Module_Destructor) 0,
497 (FT_Module_Requester) 0
500 FT_GLYPH_FORMAT_OUTLINE,
502 (FT_Renderer_RenderFunc) ft_smooth_render_lcd_v,
503 (FT_Renderer_TransformFunc)ft_smooth_transform,
504 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
505 (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
507 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET