Hopefully create a branch and not destroy the svn repository.
[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 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_OBJECTS_H
21 #include FT_OUTLINE_H
22 #include "ftsmooth.h"
23 #include "ftgrays.h"
24
25 #include "ftsmerrs.h"
26
27
28 /* initialize renderer -- init its raster */
29 static FT_Error
30 ft_smooth_init( FT_Renderer render )
31 {
32 FT_Library library = FT_MODULE_LIBRARY( render );
33
34
35 render->clazz->raster_class->raster_reset( render->raster,
36 library->raster_pool,
37 library->raster_pool_size );
38
39 return 0;
40 }
41
42
43 /* sets render-specific mode */
44 static FT_Error
45 ft_smooth_set_mode( FT_Renderer render,
46 FT_ULong mode_tag,
47 FT_Pointer data )
48 {
49 /* we simply pass it to the raster */
50 return render->clazz->raster_class->raster_set_mode( render->raster,
51 mode_tag,
52 data );
53 }
54
55 /* transform a given glyph image */
56 static FT_Error
57 ft_smooth_transform( FT_Renderer render,
58 FT_GlyphSlot slot,
59 const FT_Matrix* matrix,
60 const FT_Vector* delta )
61 {
62 FT_Error error = Smooth_Err_Ok;
63
64
65 if ( slot->format != render->glyph_format )
66 {
67 error = Smooth_Err_Invalid_Argument;
68 goto Exit;
69 }
70
71 if ( matrix )
72 FT_Outline_Transform( &slot->outline, matrix );
73
74 if ( delta )
75 FT_Outline_Translate( &slot->outline, delta->x, delta->y );
76
77 Exit:
78 return error;
79 }
80
81
82 /* return the glyph's control box */
83 static void
84 ft_smooth_get_cbox( FT_Renderer render,
85 FT_GlyphSlot slot,
86 FT_BBox* cbox )
87 {
88 FT_MEM_ZERO( cbox, sizeof ( *cbox ) );
89
90 if ( slot->format == render->glyph_format )
91 FT_Outline_Get_CBox( &slot->outline, cbox );
92 }
93
94
95 /* convert a slot's glyph image into a bitmap */
96 static FT_Error
97 ft_smooth_render_generic( FT_Renderer render,
98 FT_GlyphSlot slot,
99 FT_Render_Mode mode,
100 const FT_Vector* origin,
101 FT_Render_Mode required_mode )
102 {
103 FT_Error error;
104 FT_Outline* outline = NULL;
105 FT_BBox cbox;
106 FT_UInt width, height, height_org, width_org, pitch;
107 FT_Bitmap* bitmap;
108 FT_Memory memory;
109 FT_Int hmul = mode == FT_RENDER_MODE_LCD;
110 FT_Int vmul = mode == FT_RENDER_MODE_LCD_V;
111 FT_Pos x_shift, y_shift, x_left, y_top;
112
113 FT_Raster_Params params;
114
115
116 /* check glyph image format */
117 if ( slot->format != render->glyph_format )
118 {
119 error = Smooth_Err_Invalid_Argument;
120 goto Exit;
121 }
122
123 /* check mode */
124 if ( mode != required_mode )
125 return Smooth_Err_Cannot_Render_Glyph;
126
127 outline = &slot->outline;
128
129 /* translate the outline to the new origin if needed */
130 if ( origin )
131 FT_Outline_Translate( outline, origin->x, origin->y );
132
133 /* compute the control box, and grid fit it */
134 FT_Outline_Get_CBox( outline, &cbox );
135
136 cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
137 cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
138 cbox.xMax = FT_PIX_CEIL( cbox.xMax );
139 cbox.yMax = FT_PIX_CEIL( cbox.yMax );
140
141 width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
142 height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
143 bitmap = &slot->bitmap;
144 memory = render->root.memory;
145
146 width_org = width;
147 height_org = height;
148
149 /* release old bitmap buffer */
150 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
151 {
152 FT_FREE( bitmap->buffer );
153 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
154 }
155
156 /* allocate new one, depends on pixel format */
157 pitch = width;
158 if ( hmul )
159 {
160 width = width * 3;
161 pitch = FT_PAD_CEIL( width, 4 );
162 }
163
164 if ( vmul )
165 height *= 3;
166
167 x_shift = (FT_Int) cbox.xMin;
168 y_shift = (FT_Int) cbox.yMin;
169 x_left = (FT_Int)( cbox.xMin >> 6 );
170 y_top = (FT_Int)( cbox.yMax >> 6 );
171
172 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
173
174 if ( slot->library->lcd_filter_func )
175 {
176 FT_Int extra = slot->library->lcd_extra;
177
178
179 if ( hmul )
180 {
181 x_shift -= 64 * ( extra >> 1 );
182 width += 3 * extra;
183 pitch = FT_PAD_CEIL( width, 4 );
184 x_left -= extra >> 1;
185 }
186
187 if ( vmul )
188 {
189 y_shift -= 64 * ( extra >> 1 );
190 height += 3 * extra;
191 y_top += extra >> 1;
192 }
193 }
194
195 #endif
196
197 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
198 bitmap->num_grays = 256;
199 bitmap->width = width;
200 bitmap->rows = height;
201 bitmap->pitch = pitch;
202
203 /* translate outline to render it into the bitmap */
204 FT_Outline_Translate( outline, -x_shift, -y_shift );
205
206 if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
207 goto Exit;
208
209 slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
210
211 /* set up parameters */
212 params.target = bitmap;
213 params.source = outline;
214 params.flags = FT_RASTER_FLAG_AA;
215
216 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
217
218 /* implode outline if needed */
219 {
220 FT_Vector* points = outline->points;
221 FT_Vector* points_end = points + outline->n_points;
222 FT_Vector* vec;
223
224
225 if ( hmul )
226 for ( vec = points; vec < points_end; vec++ )
227 vec->x *= 3;
228
229 if ( vmul )
230 for ( vec = points; vec < points_end; vec++ )
231 vec->y *= 3;
232 }
233
234 /* render outline into the bitmap */
235 error = render->raster_render( render->raster, &params );
236
237 /* deflate outline if needed */
238 {
239 FT_Vector* points = outline->points;
240 FT_Vector* points_end = points + outline->n_points;
241 FT_Vector* vec;
242
243
244 if ( hmul )
245 for ( vec = points; vec < points_end; vec++ )
246 vec->x /= 3;
247
248 if ( vmul )
249 for ( vec = points; vec < points_end; vec++ )
250 vec->y /= 3;
251 }
252
253 if ( slot->library->lcd_filter_func )
254 slot->library->lcd_filter_func( bitmap, mode, slot->library );
255
256 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
257
258 /* render outline into bitmap */
259 error = render->raster_render( render->raster, &params );
260
261 /* expand it horizontally */
262 if ( hmul )
263 {
264 FT_Byte* line = bitmap->buffer;
265 FT_UInt hh;
266
267
268 for ( hh = height_org; hh > 0; hh--, line += pitch )
269 {
270 FT_UInt xx;
271 FT_Byte* end = line + width;
272
273
274 for ( xx = width_org; xx > 0; xx-- )
275 {
276 FT_UInt pixel = line[xx-1];
277
278
279 end[-3] = (FT_Byte)pixel;
280 end[-2] = (FT_Byte)pixel;
281 end[-1] = (FT_Byte)pixel;
282 end -= 3;
283 }
284 }
285 }
286
287 /* expand it vertically */
288 if ( vmul )
289 {
290 FT_Byte* read = bitmap->buffer + ( height - height_org ) * pitch;
291 FT_Byte* write = bitmap->buffer;
292 FT_UInt hh;
293
294
295 for ( hh = height_org; hh > 0; hh-- )
296 {
297 memcpy( write, read, pitch );
298 write += pitch;
299
300 memcpy( write, read, pitch );
301 write += pitch;
302
303 memcpy( write, read, pitch );
304 write += pitch;
305 read += pitch;
306 }
307 }
308
309 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
310
311 FT_Outline_Translate( outline, x_shift, y_shift );
312
313 if ( error )
314 goto Exit;
315
316 slot->format = FT_GLYPH_FORMAT_BITMAP;
317 slot->bitmap_left = x_left;
318 slot->bitmap_top = y_top;
319
320 Exit:
321 if ( outline && origin )
322 FT_Outline_Translate( outline, -origin->x, -origin->y );
323
324 return error;
325 }
326
327
328 /* convert a slot's glyph image into a bitmap */
329 static FT_Error
330 ft_smooth_render( FT_Renderer render,
331 FT_GlyphSlot slot,
332 FT_Render_Mode mode,
333 const FT_Vector* origin )
334 {
335 if ( mode == FT_RENDER_MODE_LIGHT )
336 mode = FT_RENDER_MODE_NORMAL;
337
338 return ft_smooth_render_generic( render, slot, mode, origin,
339 FT_RENDER_MODE_NORMAL );
340 }
341
342
343 /* convert a slot's glyph image into a horizontal LCD bitmap */
344 static FT_Error
345 ft_smooth_render_lcd( FT_Renderer render,
346 FT_GlyphSlot slot,
347 FT_Render_Mode mode,
348 const FT_Vector* origin )
349 {
350 FT_Error error;
351
352 error = ft_smooth_render_generic( render, slot, mode, origin,
353 FT_RENDER_MODE_LCD );
354 if ( !error )
355 slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
356
357 return error;
358 }
359
360
361 /* convert a slot's glyph image into a vertical LCD bitmap */
362 static FT_Error
363 ft_smooth_render_lcd_v( FT_Renderer render,
364 FT_GlyphSlot slot,
365 FT_Render_Mode mode,
366 const FT_Vector* origin )
367 {
368 FT_Error error;
369
370 error = ft_smooth_render_generic( render, slot, mode, origin,
371 FT_RENDER_MODE_LCD_V );
372 if ( !error )
373 slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
374
375 return error;
376 }
377
378
379 FT_CALLBACK_TABLE_DEF
380 const FT_Renderer_Class ft_smooth_renderer_class =
381 {
382 {
383 FT_MODULE_RENDERER,
384 sizeof( FT_RendererRec ),
385
386 "smooth",
387 0x10000L,
388 0x20000L,
389
390 0, /* module specific interface */
391
392 (FT_Module_Constructor)ft_smooth_init,
393 (FT_Module_Destructor) 0,
394 (FT_Module_Requester) 0
395 },
396
397 FT_GLYPH_FORMAT_OUTLINE,
398
399 (FT_Renderer_RenderFunc) ft_smooth_render,
400 (FT_Renderer_TransformFunc)ft_smooth_transform,
401 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
402 (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
403
404 (FT_Raster_Funcs*) &ft_grays_raster
405 };
406
407
408 FT_CALLBACK_TABLE_DEF
409 const FT_Renderer_Class ft_smooth_lcd_renderer_class =
410 {
411 {
412 FT_MODULE_RENDERER,
413 sizeof( FT_RendererRec ),
414
415 "smooth-lcd",
416 0x10000L,
417 0x20000L,
418
419 0, /* module specific interface */
420
421 (FT_Module_Constructor)ft_smooth_init,
422 (FT_Module_Destructor) 0,
423 (FT_Module_Requester) 0
424 },
425
426 FT_GLYPH_FORMAT_OUTLINE,
427
428 (FT_Renderer_RenderFunc) ft_smooth_render_lcd,
429 (FT_Renderer_TransformFunc)ft_smooth_transform,
430 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
431 (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
432
433 (FT_Raster_Funcs*) &ft_grays_raster
434 };
435
436
437
438 FT_CALLBACK_TABLE_DEF
439 const FT_Renderer_Class ft_smooth_lcdv_renderer_class =
440 {
441 {
442 FT_MODULE_RENDERER,
443 sizeof( FT_RendererRec ),
444
445 "smooth-lcdv",
446 0x10000L,
447 0x20000L,
448
449 0, /* module specific interface */
450
451 (FT_Module_Constructor)ft_smooth_init,
452 (FT_Module_Destructor) 0,
453 (FT_Module_Requester) 0
454 },
455
456 FT_GLYPH_FORMAT_OUTLINE,
457
458 (FT_Renderer_RenderFunc) ft_smooth_render_lcd_v,
459 (FT_Renderer_TransformFunc)ft_smooth_transform,
460 (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
461 (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
462
463 (FT_Raster_Funcs*) &ft_grays_raster
464 };
465
466
467 /* END */