Suggestion from "mgh".
[open-ps2-loader.git] / thirdparty / freetype-2.3.12 / src / smooth / ftsmooth.c
blobeed63531572b4798e7baec300a76c1aef6b409d3
1 /***************************************************************************/
2 /* */
3 /* ftsmooth.c */
4 /* */
5 /* Anti-aliasing renderer interface (body). */
6 /* */
7 /* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2009 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 /***************************************************************************/
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"
27 #include "ftsmerrs.h"
30 /* initialize renderer -- init its raster */
31 static FT_Error
32 ft_smooth_init( FT_Renderer render )
34 FT_Library library = FT_MODULE_LIBRARY( render );
37 render->clazz->raster_class->raster_reset( render->raster,
38 library->raster_pool,
39 library->raster_pool_size );
41 return 0;
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 )
51 /* we simply pass it to the raster */
52 return render->clazz->raster_class->raster_set_mode( render->raster,
53 mode_tag,
54 data );
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 )
64 FT_Error error = Smooth_Err_Ok;
67 if ( slot->format != render->glyph_format )
69 error = Smooth_Err_Invalid_Argument;
70 goto Exit;
73 if ( matrix )
74 FT_Outline_Transform( &slot->outline, matrix );
76 if ( delta )
77 FT_Outline_Translate( &slot->outline, delta->x, delta->y );
79 Exit:
80 return error;
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 )
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 */
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 )
105 FT_Error error;
106 FT_Outline* outline = NULL;
107 FT_BBox cbox;
108 FT_UInt width, height, height_org, width_org, pitch;
109 FT_Bitmap* bitmap;
110 FT_Memory memory;
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;
122 goto Exit;
125 /* check mode */
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 */
132 if ( origin )
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 width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
144 height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
145 bitmap = &slot->bitmap;
146 memory = render->root.memory;
148 width_org = width;
149 height_org = height;
151 /* release old bitmap buffer */
152 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
154 FT_FREE( bitmap->buffer );
155 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
158 /* allocate new one */
159 pitch = width;
160 if ( hmul )
162 width = width * 3;
163 pitch = FT_PAD_CEIL( width, 4 );
166 if ( vmul )
167 height *= 3;
169 x_shift = (FT_Int) cbox.xMin;
170 y_shift = (FT_Int) cbox.yMin;
171 x_left = (FT_Int)( cbox.xMin >> 6 );
172 y_top = (FT_Int)( cbox.yMax >> 6 );
174 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
176 if ( slot->library->lcd_filter_func )
178 FT_Int extra = slot->library->lcd_extra;
181 if ( hmul )
183 x_shift -= 64 * ( extra >> 1 );
184 width += 3 * extra;
185 pitch = FT_PAD_CEIL( width, 4 );
186 x_left -= extra >> 1;
189 if ( vmul )
191 y_shift -= 64 * ( extra >> 1 );
192 height += 3 * extra;
193 y_top += extra >> 1;
197 #endif
199 #if FT_UINT_MAX > 0xFFFFU
201 /* Required check is ( pitch * height < FT_ULONG_MAX ), */
202 /* but we care realistic cases only. Always pitch <= width. */
203 if ( width > 0xFFFFU || height > 0xFFFFU )
205 FT_ERROR(( "ft_smooth_render_generic: glyph too large: %d x %d\n",
206 width, height ));
207 return Smooth_Err_Raster_Overflow;
210 #endif
212 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
213 bitmap->num_grays = 256;
214 bitmap->width = width;
215 bitmap->rows = height;
216 bitmap->pitch = pitch;
218 /* translate outline to render it into the bitmap */
219 FT_Outline_Translate( outline, -x_shift, -y_shift );
221 if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
222 goto Exit;
224 slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
226 /* set up parameters */
227 params.target = bitmap;
228 params.source = outline;
229 params.flags = FT_RASTER_FLAG_AA;
231 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
233 /* implode outline if needed */
235 FT_Vector* points = outline->points;
236 FT_Vector* points_end = points + outline->n_points;
237 FT_Vector* vec;
240 if ( hmul )
241 for ( vec = points; vec < points_end; vec++ )
242 vec->x *= 3;
244 if ( vmul )
245 for ( vec = points; vec < points_end; vec++ )
246 vec->y *= 3;
249 /* render outline into the bitmap */
250 error = render->raster_render( render->raster, &params );
252 /* deflate outline if needed */
254 FT_Vector* points = outline->points;
255 FT_Vector* points_end = points + outline->n_points;
256 FT_Vector* vec;
259 if ( hmul )
260 for ( vec = points; vec < points_end; vec++ )
261 vec->x /= 3;
263 if ( vmul )
264 for ( vec = points; vec < points_end; vec++ )
265 vec->y /= 3;
268 if ( slot->library->lcd_filter_func )
269 slot->library->lcd_filter_func( bitmap, mode, slot->library );
271 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
273 /* render outline into bitmap */
274 error = render->raster_render( render->raster, &params );
276 /* expand it horizontally */
277 if ( hmul )
279 FT_Byte* line = bitmap->buffer;
280 FT_UInt hh;
283 for ( hh = height_org; hh > 0; hh--, line += pitch )
285 FT_UInt xx;
286 FT_Byte* end = line + width;
289 for ( xx = width_org; xx > 0; xx-- )
291 FT_UInt pixel = line[xx-1];
294 end[-3] = (FT_Byte)pixel;
295 end[-2] = (FT_Byte)pixel;
296 end[-1] = (FT_Byte)pixel;
297 end -= 3;
302 /* expand it vertically */
303 if ( vmul )
305 FT_Byte* read = bitmap->buffer + ( height - height_org ) * pitch;
306 FT_Byte* write = bitmap->buffer;
307 FT_UInt hh;
310 for ( hh = height_org; hh > 0; hh-- )
312 ft_memcpy( write, read, pitch );
313 write += pitch;
315 ft_memcpy( write, read, pitch );
316 write += pitch;
318 ft_memcpy( write, read, pitch );
319 write += pitch;
320 read += pitch;
324 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
326 FT_Outline_Translate( outline, x_shift, y_shift );
329 * XXX: on 16bit system, we return an error for huge bitmap
330 * to prevent an overflow.
332 if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )
333 return Smooth_Err_Invalid_Pixel_Size;
335 if ( error )
336 goto Exit;
338 slot->format = FT_GLYPH_FORMAT_BITMAP;
339 slot->bitmap_left = (FT_Int)x_left;
340 slot->bitmap_top = (FT_Int)y_top;
342 Exit:
343 if ( outline && origin )
344 FT_Outline_Translate( outline, -origin->x, -origin->y );
346 return error;
350 /* convert a slot's glyph image into a bitmap */
351 static FT_Error
352 ft_smooth_render( FT_Renderer render,
353 FT_GlyphSlot slot,
354 FT_Render_Mode mode,
355 const FT_Vector* origin )
357 if ( mode == FT_RENDER_MODE_LIGHT )
358 mode = FT_RENDER_MODE_NORMAL;
360 return ft_smooth_render_generic( render, slot, mode, origin,
361 FT_RENDER_MODE_NORMAL );
365 /* convert a slot's glyph image into a horizontal LCD bitmap */
366 static FT_Error
367 ft_smooth_render_lcd( FT_Renderer render,
368 FT_GlyphSlot slot,
369 FT_Render_Mode mode,
370 const FT_Vector* origin )
372 FT_Error error;
374 error = ft_smooth_render_generic( render, slot, mode, origin,
375 FT_RENDER_MODE_LCD );
376 if ( !error )
377 slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
379 return error;
383 /* convert a slot's glyph image into a vertical LCD bitmap */
384 static FT_Error
385 ft_smooth_render_lcd_v( FT_Renderer render,
386 FT_GlyphSlot slot,
387 FT_Render_Mode mode,
388 const FT_Vector* origin )
390 FT_Error error;
392 error = ft_smooth_render_generic( render, slot, mode, origin,
393 FT_RENDER_MODE_LCD_V );
394 if ( !error )
395 slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
397 return error;
401 FT_DEFINE_RENDERER(ft_smooth_renderer_class,
403 FT_MODULE_RENDERER,
404 sizeof( FT_RendererRec ),
406 "smooth",
407 0x10000L,
408 0x20000L,
410 0, /* module specific interface */
412 (FT_Module_Constructor)ft_smooth_init,
413 (FT_Module_Destructor) 0,
414 (FT_Module_Requester) 0
417 FT_GLYPH_FORMAT_OUTLINE,
419 (FT_Renderer_RenderFunc) ft_smooth_render,
420 (FT_Renderer_TransformFunc)ft_smooth_transform,
421 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
422 (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
424 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
428 FT_DEFINE_RENDERER(ft_smooth_lcd_renderer_class,
430 FT_MODULE_RENDERER,
431 sizeof( FT_RendererRec ),
433 "smooth-lcd",
434 0x10000L,
435 0x20000L,
437 0, /* module specific interface */
439 (FT_Module_Constructor)ft_smooth_init,
440 (FT_Module_Destructor) 0,
441 (FT_Module_Requester) 0
444 FT_GLYPH_FORMAT_OUTLINE,
446 (FT_Renderer_RenderFunc) ft_smooth_render_lcd,
447 (FT_Renderer_TransformFunc)ft_smooth_transform,
448 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
449 (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
451 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
454 FT_DEFINE_RENDERER(ft_smooth_lcdv_renderer_class,
456 FT_MODULE_RENDERER,
457 sizeof( FT_RendererRec ),
459 "smooth-lcdv",
460 0x10000L,
461 0x20000L,
463 0, /* module specific interface */
465 (FT_Module_Constructor)ft_smooth_init,
466 (FT_Module_Destructor) 0,
467 (FT_Module_Requester) 0
470 FT_GLYPH_FORMAT_OUTLINE,
472 (FT_Renderer_RenderFunc) ft_smooth_render_lcd_v,
473 (FT_Renderer_TransformFunc)ft_smooth_transform,
474 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
475 (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
477 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
481 /* END */