[CMAKE]
[reactos.git] / lib / 3rdparty / freetype / src / smooth / ftsmooth.c
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 /***************************************************************************/
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 = Smooth_Err_Ok;
65
66
67 if ( slot->format != render->glyph_format )
68 {
69 error = Smooth_Err_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_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;
114
115 FT_Raster_Params params;
116
117
118 /* check glyph image format */
119 if ( slot->format != render->glyph_format )
120 {
121 error = Smooth_Err_Invalid_Argument;
122 goto Exit;
123 }
124
125 /* check mode */
126 if ( mode != required_mode )
127 return Smooth_Err_Cannot_Render_Glyph;
128
129 outline = &slot->outline;
130
131 /* translate the outline to the new origin if needed */
132 if ( origin )
133 FT_Outline_Translate( outline, origin->x, origin->y );
134
135 /* compute the control box, and grid fit it */
136 FT_Outline_Get_CBox( outline, &cbox );
137
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 );
142
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;
147
148 width_org = width;
149 height_org = height;
150
151 /* release old bitmap buffer */
152 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
153 {
154 FT_FREE( bitmap->buffer );
155 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
156 }
157
158 /* allocate new one */
159 pitch = width;
160 if ( hmul )
161 {
162 width = width * 3;
163 pitch = FT_PAD_CEIL( width, 4 );
164 }
165
166 if ( vmul )
167 height *= 3;
168
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 );
173
174 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
175
176 if ( slot->library->lcd_filter_func )
177 {
178 FT_Int extra = slot->library->lcd_extra;
179
180
181 if ( hmul )
182 {
183 x_shift -= 64 * ( extra >> 1 );
184 width += 3 * extra;
185 pitch = FT_PAD_CEIL( width, 4 );
186 x_left -= extra >> 1;
187 }
188
189 if ( vmul )
190 {
191 y_shift -= 64 * ( extra >> 1 );
192 height += 3 * extra;
193 y_top += extra >> 1;
194 }
195 }
196
197 #endif
198
199 #if FT_UINT_MAX > 0xFFFFU
200
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 )
204 {
205 FT_ERROR(( "ft_smooth_render_generic: glyph too large: %d x %d\n",
206 width, height ));
207 return Smooth_Err_Raster_Overflow;
208 }
209
210 #endif
211
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;
217
218 /* translate outline to render it into the bitmap */
219 FT_Outline_Translate( outline, -x_shift, -y_shift );
220
221 if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
222 goto Exit;
223
224 slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
225
226 /* set up parameters */
227 params.target = bitmap;
228 params.source = outline;
229 params.flags = FT_RASTER_FLAG_AA;
230
231 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
232
233 /* implode outline if needed */
234 {
235 FT_Vector* points = outline->points;
236 FT_Vector* points_end = points + outline->n_points;
237 FT_Vector* vec;
238
239
240 if ( hmul )
241 for ( vec = points; vec < points_end; vec++ )
242 vec->x *= 3;
243
244 if ( vmul )
245 for ( vec = points; vec < points_end; vec++ )
246 vec->y *= 3;
247 }
248
249 /* render outline into the bitmap */
250 error = render->raster_render( render->raster, &params );
251
252 /* deflate outline if needed */
253 {
254 FT_Vector* points = outline->points;
255 FT_Vector* points_end = points + outline->n_points;
256 FT_Vector* vec;
257
258
259 if ( hmul )
260 for ( vec = points; vec < points_end; vec++ )
261 vec->x /= 3;
262
263 if ( vmul )
264 for ( vec = points; vec < points_end; vec++ )
265 vec->y /= 3;
266 }
267
268 if ( slot->library->lcd_filter_func )
269 slot->library->lcd_filter_func( bitmap, mode, slot->library );
270
271 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
272
273 /* render outline into bitmap */
274 error = render->raster_render( render->raster, &params );
275
276 /* expand it horizontally */
277 if ( hmul )
278 {
279 FT_Byte* line = bitmap->buffer;
280 FT_UInt hh;
281
282
283 for ( hh = height_org; hh > 0; hh--, line += pitch )
284 {
285 FT_UInt xx;
286 FT_Byte* end = line + width;
287
288
289 for ( xx = width_org; xx > 0; xx-- )
290 {
291 FT_UInt pixel = line[xx-1];
292
293
294 end[-3] = (FT_Byte)pixel;
295 end[-2] = (FT_Byte)pixel;
296 end[-1] = (FT_Byte)pixel;
297 end -= 3;
298 }
299 }
300 }
301
302 /* expand it vertically */
303 if ( vmul )
304 {
305 FT_Byte* read = bitmap->buffer + ( height - height_org ) * pitch;
306 FT_Byte* write = bitmap->buffer;
307 FT_UInt hh;
308
309
310 for ( hh = height_org; hh > 0; hh-- )
311 {
312 ft_memcpy( write, read, pitch );
313 write += pitch;
314
315 ft_memcpy( write, read, pitch );
316 write += pitch;
317
318 ft_memcpy( write, read, pitch );
319 write += pitch;
320 read += pitch;
321 }
322 }
323
324 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
325
326 FT_Outline_Translate( outline, x_shift, y_shift );
327
328 /*
329 * XXX: on 16bit system, we return an error for huge bitmap
330 * to prevent an overflow.
331 */
332 if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )
333 return Smooth_Err_Invalid_Pixel_Size;
334
335 if ( error )
336 goto Exit;
337
338 slot->format = FT_GLYPH_FORMAT_BITMAP;
339 slot->bitmap_left = (FT_Int)x_left;
340 slot->bitmap_top = (FT_Int)y_top;
341
342 Exit:
343 if ( outline && origin )
344 FT_Outline_Translate( outline, -origin->x, -origin->y );
345
346 return error;
347 }
348
349
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 )
356 {
357 if ( mode == FT_RENDER_MODE_LIGHT )
358 mode = FT_RENDER_MODE_NORMAL;
359
360 return ft_smooth_render_generic( render, slot, mode, origin,
361 FT_RENDER_MODE_NORMAL );
362 }
363
364
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 )
371 {
372 FT_Error error;
373
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;
378
379 return error;
380 }
381
382
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 )
389 {
390 FT_Error error;
391
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;
396
397 return error;
398 }
399
400
401 FT_DEFINE_RENDERER(ft_smooth_renderer_class,
402
403 FT_MODULE_RENDERER,
404 sizeof( FT_RendererRec ),
405
406 "smooth",
407 0x10000L,
408 0x20000L,
409
410 0, /* module specific interface */
411
412 (FT_Module_Constructor)ft_smooth_init,
413 (FT_Module_Destructor) 0,
414 (FT_Module_Requester) 0
415 ,
416
417 FT_GLYPH_FORMAT_OUTLINE,
418
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,
423
424 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
425 )
426
427
428 FT_DEFINE_RENDERER(ft_smooth_lcd_renderer_class,
429
430 FT_MODULE_RENDERER,
431 sizeof( FT_RendererRec ),
432
433 "smooth-lcd",
434 0x10000L,
435 0x20000L,
436
437 0, /* module specific interface */
438
439 (FT_Module_Constructor)ft_smooth_init,
440 (FT_Module_Destructor) 0,
441 (FT_Module_Requester) 0
442 ,
443
444 FT_GLYPH_FORMAT_OUTLINE,
445
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,
450
451 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
452 )
453
454 FT_DEFINE_RENDERER(ft_smooth_lcdv_renderer_class,
455
456 FT_MODULE_RENDERER,
457 sizeof( FT_RendererRec ),
458
459 "smooth-lcdv",
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_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,
476
477 (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
478 )
479
480
481 /* END */