Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/***************************************************************************/
2
/*                                                                         */
3
/*  ftsmooth.c                                                             */
4
/*                                                                         */
5
/*    Anti-aliasing renderer interface (body).                             */
6
/*                                                                         */
7
/*  Copyright 2000-2006, 2009-2013 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 
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 = FT_Err_Ok;
65
 
66
 
67
    if ( slot->format != render->glyph_format )
68
    {
69
      error = FT_THROW( 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_Pos       width, height, pitch;
109
#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
110
    FT_Pos       height_org, width_org;
111
#endif
112
    FT_Bitmap*   bitmap  = &slot->bitmap;
113
    FT_Memory    memory  = render->root.memory;
114
    FT_Int       hmul    = mode == FT_RENDER_MODE_LCD;
115
    FT_Int       vmul    = mode == FT_RENDER_MODE_LCD_V;
116
    FT_Pos       x_shift = 0;
117
    FT_Pos       y_shift = 0;
118
    FT_Pos       x_left, y_top;
119
 
120
    FT_Raster_Params  params;
121
 
122
    FT_Bool  have_translated_origin = FALSE;
123
    FT_Bool  have_outline_shifted   = FALSE;
124
    FT_Bool  have_buffer            = FALSE;
125
 
126
 
127
    /* check glyph image format */
128
    if ( slot->format != render->glyph_format )
129
    {
130
      error = FT_THROW( Invalid_Argument );
131
      goto Exit;
132
    }
133
 
134
    /* check mode */
135
    if ( mode != required_mode )
136
    {
137
      error = FT_THROW( Cannot_Render_Glyph );
138
      goto Exit;
139
    }
140
 
141
    outline = &slot->outline;
142
 
143
    /* translate the outline to the new origin if needed */
144
    if ( origin )
145
    {
146
      FT_Outline_Translate( outline, origin->x, origin->y );
147
      have_translated_origin = TRUE;
148
    }
149
 
150
    /* compute the control box, and grid fit it */
151
    FT_Outline_Get_CBox( outline, &cbox );
152
 
153
    cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
154
    cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
155
    cbox.xMax = FT_PIX_CEIL( cbox.xMax );
156
    cbox.yMax = FT_PIX_CEIL( cbox.yMax );
157
 
158
    if ( cbox.xMin < 0 && cbox.xMax > FT_INT_MAX + cbox.xMin )
159
    {
160
      FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
161
                 " xMin = %d, xMax = %d\n",
162
                 cbox.xMin >> 6, cbox.xMax >> 6 ));
163
      error = FT_THROW( Raster_Overflow );
164
      goto Exit;
165
    }
166
    else
167
      width = ( cbox.xMax - cbox.xMin ) >> 6;
168
 
169
    if ( cbox.yMin < 0 && cbox.yMax > FT_INT_MAX + cbox.yMin )
170
    {
171
      FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
172
                 " yMin = %d, yMax = %d\n",
173
                 cbox.yMin >> 6, cbox.yMax >> 6 ));
174
      error = FT_THROW( Raster_Overflow );
175
      goto Exit;
176
    }
177
    else
178
      height = ( cbox.yMax - cbox.yMin ) >> 6;
179
 
180
#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
181
    width_org  = width;
182
    height_org = height;
183
#endif
184
 
185
    /* release old bitmap buffer */
186
    if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
187
    {
188
      FT_FREE( bitmap->buffer );
189
      slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
190
    }
191
 
192
    /* allocate new one */
193
    pitch = width;
194
    if ( hmul )
195
    {
196
      width = width * 3;
197
      pitch = FT_PAD_CEIL( width, 4 );
198
    }
199
 
200
    if ( vmul )
201
      height *= 3;
202
 
203
    x_shift = (FT_Int) cbox.xMin;
204
    y_shift = (FT_Int) cbox.yMin;
205
    x_left  = (FT_Int)( cbox.xMin >> 6 );
206
    y_top   = (FT_Int)( cbox.yMax >> 6 );
207
 
208
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
209
 
210
    if ( slot->library->lcd_filter_func )
211
    {
212
      FT_Int  extra = slot->library->lcd_extra;
213
 
214
 
215
      if ( hmul )
216
      {
217
        x_shift -= 64 * ( extra >> 1 );
218
        width   += 3 * extra;
219
        pitch    = FT_PAD_CEIL( width, 4 );
220
        x_left  -= extra >> 1;
221
      }
222
 
223
      if ( vmul )
224
      {
225
        y_shift -= 64 * ( extra >> 1 );
226
        height  += 3 * extra;
227
        y_top   += extra >> 1;
228
      }
229
    }
230
 
231
#endif
232
 
233
#if FT_UINT_MAX > 0xFFFFU
234
 
235
    /* Required check is (pitch * height < FT_ULONG_MAX),        */
236
    /* but we care realistic cases only.  Always pitch <= width. */
237
    if ( width > 0x7FFF || height > 0x7FFF )
238
    {
239
      FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n",
240
                 width, height ));
241
      error = FT_THROW( Raster_Overflow );
242
      goto Exit;
243
    }
244
 
245
#endif
246
 
247
    bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
248
    bitmap->num_grays  = 256;
249
    bitmap->width      = width;
250
    bitmap->rows       = height;
251
    bitmap->pitch      = pitch;
252
 
253
    /* translate outline to render it into the bitmap */
254
    FT_Outline_Translate( outline, -x_shift, -y_shift );
255
    have_outline_shifted = TRUE;
256
 
257
    if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
258
      goto Exit;
259
    else
260
      have_buffer = TRUE;
261
 
262
    slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
263
 
264
    /* set up parameters */
265
    params.target = bitmap;
266
    params.source = outline;
267
    params.flags  = FT_RASTER_FLAG_AA;
268
 
269
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
270
 
271
    /* implode outline if needed */
272
    {
273
      FT_Vector*  points     = outline->points;
274
      FT_Vector*  points_end = points + outline->n_points;
275
      FT_Vector*  vec;
276
 
277
 
278
      if ( hmul )
279
        for ( vec = points; vec < points_end; vec++ )
280
          vec->x *= 3;
281
 
282
      if ( vmul )
283
        for ( vec = points; vec < points_end; vec++ )
284
          vec->y *= 3;
285
    }
286
 
287
    /* render outline into the bitmap */
288
    error = render->raster_render( render->raster, ¶ms );
289
 
290
    /* deflate outline if needed */
291
    {
292
      FT_Vector*  points     = outline->points;
293
      FT_Vector*  points_end = points + outline->n_points;
294
      FT_Vector*  vec;
295
 
296
 
297
      if ( hmul )
298
        for ( vec = points; vec < points_end; vec++ )
299
          vec->x /= 3;
300
 
301
      if ( vmul )
302
        for ( vec = points; vec < points_end; vec++ )
303
          vec->y /= 3;
304
    }
305
 
306
    if ( error )
307
      goto Exit;
308
 
309
    if ( slot->library->lcd_filter_func )
310
      slot->library->lcd_filter_func( bitmap, mode, slot->library );
311
 
312
#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
313
 
314
    /* render outline into bitmap */
315
    error = render->raster_render( render->raster, ¶ms );
316
    if ( error )
317
      goto Exit;
318
 
319
    /* expand it horizontally */
320
    if ( hmul )
321
    {
322
      FT_Byte*  line = bitmap->buffer;
323
      FT_UInt   hh;
324
 
325
 
326
      for ( hh = height_org; hh > 0; hh--, line += pitch )
327
      {
328
        FT_UInt   xx;
329
        FT_Byte*  end = line + width;
330
 
331
 
332
        for ( xx = width_org; xx > 0; xx-- )
333
        {
334
          FT_UInt  pixel = line[xx-1];
335
 
336
 
337
          end[-3] = (FT_Byte)pixel;
338
          end[-2] = (FT_Byte)pixel;
339
          end[-1] = (FT_Byte)pixel;
340
          end    -= 3;
341
        }
342
      }
343
    }
344
 
345
    /* expand it vertically */
346
    if ( vmul )
347
    {
348
      FT_Byte*  read  = bitmap->buffer + ( height - height_org ) * pitch;
349
      FT_Byte*  write = bitmap->buffer;
350
      FT_UInt   hh;
351
 
352
 
353
      for ( hh = height_org; hh > 0; hh-- )
354
      {
355
        ft_memcpy( write, read, pitch );
356
        write += pitch;
357
 
358
        ft_memcpy( write, read, pitch );
359
        write += pitch;
360
 
361
        ft_memcpy( write, read, pitch );
362
        write += pitch;
363
        read  += pitch;
364
      }
365
    }
366
 
367
#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
368
 
369
    /*
370
     * XXX: on 16bit system, we return an error for huge bitmap
371
     * to prevent an overflow.
372
     */
373
    if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )
374
    {
375
      error = FT_THROW( Invalid_Pixel_Size );
376
      goto Exit;
377
    }
378
 
379
    slot->format      = FT_GLYPH_FORMAT_BITMAP;
380
    slot->bitmap_left = (FT_Int)x_left;
381
    slot->bitmap_top  = (FT_Int)y_top;
382
 
383
    /* everything is fine; don't deallocate buffer */
384
    have_buffer = FALSE;
385
 
386
    error = FT_Err_Ok;
387
 
388
  Exit:
389
    if ( have_outline_shifted )
390
      FT_Outline_Translate( outline, x_shift, y_shift );
391
    if ( have_translated_origin )
392
      FT_Outline_Translate( outline, -origin->x, -origin->y );
393
    if ( have_buffer )
394
    {
395
      FT_FREE( bitmap->buffer );
396
      slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
397
    }
398
 
399
    return error;
400
  }
401
 
402
 
403
  /* convert a slot's glyph image into a bitmap */
404
  static FT_Error
405
  ft_smooth_render( FT_Renderer       render,
406
                    FT_GlyphSlot      slot,
407
                    FT_Render_Mode    mode,
408
                    const FT_Vector*  origin )
409
  {
410
    if ( mode == FT_RENDER_MODE_LIGHT )
411
      mode = FT_RENDER_MODE_NORMAL;
412
 
413
    return ft_smooth_render_generic( render, slot, mode, origin,
414
                                     FT_RENDER_MODE_NORMAL );
415
  }
416
 
417
 
418
  /* convert a slot's glyph image into a horizontal LCD bitmap */
419
  static FT_Error
420
  ft_smooth_render_lcd( FT_Renderer       render,
421
                        FT_GlyphSlot      slot,
422
                        FT_Render_Mode    mode,
423
                        const FT_Vector*  origin )
424
  {
425
    FT_Error  error;
426
 
427
    error = ft_smooth_render_generic( render, slot, mode, origin,
428
                                      FT_RENDER_MODE_LCD );
429
    if ( !error )
430
      slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
431
 
432
    return error;
433
  }
434
 
435
 
436
  /* convert a slot's glyph image into a vertical LCD bitmap */
437
  static FT_Error
438
  ft_smooth_render_lcd_v( FT_Renderer       render,
439
                          FT_GlyphSlot      slot,
440
                          FT_Render_Mode    mode,
441
                          const FT_Vector*  origin )
442
  {
443
    FT_Error  error;
444
 
445
    error = ft_smooth_render_generic( render, slot, mode, origin,
446
                                      FT_RENDER_MODE_LCD_V );
447
    if ( !error )
448
      slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
449
 
450
    return error;
451
  }
452
 
453
 
454
  FT_DEFINE_RENDERER( ft_smooth_renderer_class,
455
 
456
      FT_MODULE_RENDERER,
457
      sizeof ( FT_RendererRec ),
458
 
459
      "smooth",
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,
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
  FT_DEFINE_RENDERER( ft_smooth_lcd_renderer_class,
482
 
483
      FT_MODULE_RENDERER,
484
      sizeof ( FT_RendererRec ),
485
 
486
      "smooth-lcd",
487
      0x10000L,
488
      0x20000L,
489
 
490
      0,    /* module specific interface */
491
 
492
      (FT_Module_Constructor)ft_smooth_init,
493
      (FT_Module_Destructor) 0,
494
      (FT_Module_Requester)  0
495
    ,
496
 
497
    FT_GLYPH_FORMAT_OUTLINE,
498
 
499
    (FT_Renderer_RenderFunc)   ft_smooth_render_lcd,
500
    (FT_Renderer_TransformFunc)ft_smooth_transform,
501
    (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
502
    (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
503
 
504
    (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
505
  )
506
 
507
  FT_DEFINE_RENDERER( ft_smooth_lcdv_renderer_class,
508
 
509
      FT_MODULE_RENDERER,
510
      sizeof ( FT_RendererRec ),
511
 
512
      "smooth-lcdv",
513
      0x10000L,
514
      0x20000L,
515
 
516
      0,    /* module specific interface */
517
 
518
      (FT_Module_Constructor)ft_smooth_init,
519
      (FT_Module_Destructor) 0,
520
      (FT_Module_Requester)  0
521
    ,
522
 
523
    FT_GLYPH_FORMAT_OUTLINE,
524
 
525
    (FT_Renderer_RenderFunc)   ft_smooth_render_lcd_v,
526
    (FT_Renderer_TransformFunc)ft_smooth_transform,
527
    (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
528
    (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
529
 
530
    (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
531
  )
532
 
533
 
534
/* END */