Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3918 Serge 1
/***************************************************************************/
2
/*                                                                         */
3
/*  ftglyph.c                                                              */
4
/*                                                                         */
5
/*    FreeType convenience functions to handle glyphs (body).              */
6
/*                                                                         */
7
/*  Copyright 1996-2005, 2007, 2008, 2010, 2012, 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
  /*                                                                       */
20
  /*  This file contains the definition of several convenience functions   */
21
  /*  that can be used by client applications to easily retrieve glyph     */
22
  /*  bitmaps and outlines from a given face.                              */
23
  /*                                                                       */
24
  /*  These functions should be optional if you are writing a font server  */
25
  /*  or text layout engine on top of FreeType.  However, they are pretty  */
26
  /*  handy for many other simple uses of the library.                     */
27
  /*                                                                       */
28
  /*************************************************************************/
29
 
30
 
31
#include 
32
#include FT_INTERNAL_DEBUG_H
33
 
34
#include FT_GLYPH_H
35
#include FT_OUTLINE_H
36
#include FT_BITMAP_H
37
#include FT_INTERNAL_OBJECTS_H
38
 
39
#include "basepic.h"
40
 
41
  /*************************************************************************/
42
  /*                                                                       */
43
  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
44
  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
45
  /* messages during execution.                                            */
46
  /*                                                                       */
47
#undef  FT_COMPONENT
48
#define FT_COMPONENT  trace_glyph
49
 
50
 
51
  /*************************************************************************/
52
  /*************************************************************************/
53
  /****                                                                 ****/
54
  /****   FT_BitmapGlyph support                                        ****/
55
  /****                                                                 ****/
56
  /*************************************************************************/
57
  /*************************************************************************/
58
 
59
  FT_CALLBACK_DEF( FT_Error )
60
  ft_bitmap_glyph_init( FT_Glyph      bitmap_glyph,
61
                        FT_GlyphSlot  slot )
62
  {
63
    FT_BitmapGlyph  glyph   = (FT_BitmapGlyph)bitmap_glyph;
64
    FT_Error        error   = FT_Err_Ok;
65
    FT_Library      library = FT_GLYPH( glyph )->library;
66
 
67
 
68
    if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
69
    {
70
      error = FT_THROW( Invalid_Glyph_Format );
71
      goto Exit;
72
    }
73
 
74
    glyph->left = slot->bitmap_left;
75
    glyph->top  = slot->bitmap_top;
76
 
77
    /* do lazy copying whenever possible */
78
    if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
79
    {
80
      glyph->bitmap = slot->bitmap;
81
      slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
82
    }
83
    else
84
    {
85
      FT_Bitmap_New( &glyph->bitmap );
86
      error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap );
87
    }
88
 
89
  Exit:
90
    return error;
91
  }
92
 
93
 
94
  FT_CALLBACK_DEF( FT_Error )
95
  ft_bitmap_glyph_copy( FT_Glyph  bitmap_source,
96
                        FT_Glyph  bitmap_target )
97
  {
98
    FT_Library      library = bitmap_source->library;
99
    FT_BitmapGlyph  source  = (FT_BitmapGlyph)bitmap_source;
100
    FT_BitmapGlyph  target  = (FT_BitmapGlyph)bitmap_target;
101
 
102
 
103
    target->left = source->left;
104
    target->top  = source->top;
105
 
106
    return FT_Bitmap_Copy( library, &source->bitmap, &target->bitmap );
107
  }
108
 
109
 
110
  FT_CALLBACK_DEF( void )
111
  ft_bitmap_glyph_done( FT_Glyph  bitmap_glyph )
112
  {
113
    FT_BitmapGlyph  glyph   = (FT_BitmapGlyph)bitmap_glyph;
114
    FT_Library      library = FT_GLYPH( glyph )->library;
115
 
116
 
117
    FT_Bitmap_Done( library, &glyph->bitmap );
118
  }
119
 
120
 
121
  FT_CALLBACK_DEF( void )
122
  ft_bitmap_glyph_bbox( FT_Glyph  bitmap_glyph,
123
                        FT_BBox*  cbox )
124
  {
125
    FT_BitmapGlyph  glyph = (FT_BitmapGlyph)bitmap_glyph;
126
 
127
 
128
    cbox->xMin = glyph->left << 6;
129
    cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 );
130
    cbox->yMax = glyph->top << 6;
131
    cbox->yMin = cbox->yMax - ( glyph->bitmap.rows << 6 );
132
  }
133
 
134
 
135
  FT_DEFINE_GLYPH(ft_bitmap_glyph_class,
136
    sizeof ( FT_BitmapGlyphRec ),
137
    FT_GLYPH_FORMAT_BITMAP,
138
 
139
    ft_bitmap_glyph_init,
140
    ft_bitmap_glyph_done,
141
    ft_bitmap_glyph_copy,
142
    0,                          /* FT_Glyph_TransformFunc */
143
    ft_bitmap_glyph_bbox,
144
 
145
  )
146
 
147
 
148
  /*************************************************************************/
149
  /*************************************************************************/
150
  /****                                                                 ****/
151
  /****   FT_OutlineGlyph support                                       ****/
152
  /****                                                                 ****/
153
  /*************************************************************************/
154
  /*************************************************************************/
155
 
156
 
157
  FT_CALLBACK_DEF( FT_Error )
158
  ft_outline_glyph_init( FT_Glyph      outline_glyph,
159
                         FT_GlyphSlot  slot )
160
  {
161
    FT_OutlineGlyph  glyph   = (FT_OutlineGlyph)outline_glyph;
162
    FT_Error         error   = FT_Err_Ok;
163
    FT_Library       library = FT_GLYPH( glyph )->library;
164
    FT_Outline*      source  = &slot->outline;
165
    FT_Outline*      target  = &glyph->outline;
166
 
167
 
168
    /* check format in glyph slot */
169
    if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
170
    {
171
      error = FT_THROW( Invalid_Glyph_Format );
172
      goto Exit;
173
    }
174
 
175
    /* allocate new outline */
176
    error = FT_Outline_New( library, source->n_points, source->n_contours,
177
                            &glyph->outline );
178
    if ( error )
179
      goto Exit;
180
 
181
    FT_Outline_Copy( source, target );
182
 
183
  Exit:
184
    return error;
185
  }
186
 
187
 
188
  FT_CALLBACK_DEF( void )
189
  ft_outline_glyph_done( FT_Glyph  outline_glyph )
190
  {
191
    FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
192
 
193
 
194
    FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );
195
  }
196
 
197
 
198
  FT_CALLBACK_DEF( FT_Error )
199
  ft_outline_glyph_copy( FT_Glyph  outline_source,
200
                         FT_Glyph  outline_target )
201
  {
202
    FT_OutlineGlyph  source  = (FT_OutlineGlyph)outline_source;
203
    FT_OutlineGlyph  target  = (FT_OutlineGlyph)outline_target;
204
    FT_Error         error;
205
    FT_Library       library = FT_GLYPH( source )->library;
206
 
207
 
208
    error = FT_Outline_New( library, source->outline.n_points,
209
                            source->outline.n_contours, &target->outline );
210
    if ( !error )
211
      FT_Outline_Copy( &source->outline, &target->outline );
212
 
213
    return error;
214
  }
215
 
216
 
217
  FT_CALLBACK_DEF( void )
218
  ft_outline_glyph_transform( FT_Glyph          outline_glyph,
219
                              const FT_Matrix*  matrix,
220
                              const FT_Vector*  delta )
221
  {
222
    FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
223
 
224
 
225
    if ( matrix )
226
      FT_Outline_Transform( &glyph->outline, matrix );
227
 
228
    if ( delta )
229
      FT_Outline_Translate( &glyph->outline, delta->x, delta->y );
230
  }
231
 
232
 
233
  FT_CALLBACK_DEF( void )
234
  ft_outline_glyph_bbox( FT_Glyph  outline_glyph,
235
                         FT_BBox*  bbox )
236
  {
237
    FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
238
 
239
 
240
    FT_Outline_Get_CBox( &glyph->outline, bbox );
241
  }
242
 
243
 
244
  FT_CALLBACK_DEF( FT_Error )
245
  ft_outline_glyph_prepare( FT_Glyph      outline_glyph,
246
                            FT_GlyphSlot  slot )
247
  {
248
    FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
249
 
250
 
251
    slot->format         = FT_GLYPH_FORMAT_OUTLINE;
252
    slot->outline        = glyph->outline;
253
    slot->outline.flags &= ~FT_OUTLINE_OWNER;
254
 
255
    return FT_Err_Ok;
256
  }
257
 
258
 
259
  FT_DEFINE_GLYPH( ft_outline_glyph_class,
260
    sizeof ( FT_OutlineGlyphRec ),
261
    FT_GLYPH_FORMAT_OUTLINE,
262
 
263
    ft_outline_glyph_init,
264
    ft_outline_glyph_done,
265
    ft_outline_glyph_copy,
266
    ft_outline_glyph_transform,
267
    ft_outline_glyph_bbox,
268
    ft_outline_glyph_prepare
269
  )
270
 
271
 
272
  /*************************************************************************/
273
  /*************************************************************************/
274
  /****                                                                 ****/
275
  /****   FT_Glyph class and API                                        ****/
276
  /****                                                                 ****/
277
  /*************************************************************************/
278
  /*************************************************************************/
279
 
280
   static FT_Error
281
   ft_new_glyph( FT_Library             library,
282
                 const FT_Glyph_Class*  clazz,
283
                 FT_Glyph*              aglyph )
284
   {
285
     FT_Memory  memory = library->memory;
286
     FT_Error   error;
287
     FT_Glyph   glyph  = NULL;
288
 
289
 
290
     *aglyph = 0;
291
 
292
     if ( !FT_ALLOC( glyph, clazz->glyph_size ) )
293
     {
294
       glyph->library = library;
295
       glyph->clazz   = clazz;
296
       glyph->format  = clazz->glyph_format;
297
 
298
       *aglyph = glyph;
299
     }
300
 
301
     return error;
302
   }
303
 
304
 
305
  /* documentation is in ftglyph.h */
306
 
307
  FT_EXPORT_DEF( FT_Error )
308
  FT_Glyph_Copy( FT_Glyph   source,
309
                 FT_Glyph  *target )
310
  {
311
    FT_Glyph               copy;
312
    FT_Error               error;
313
    const FT_Glyph_Class*  clazz;
314
 
315
 
316
    /* check arguments */
317
    if ( !target )
318
    {
319
      error = FT_THROW( Invalid_Argument );
320
      goto Exit;
321
    }
322
 
323
    *target = 0;
324
 
325
    if ( !source || !source->clazz )
326
    {
327
      error = FT_THROW( Invalid_Argument );
328
      goto Exit;
329
    }
330
 
331
    clazz = source->clazz;
332
    error = ft_new_glyph( source->library, clazz, © );
333
    if ( error )
334
      goto Exit;
335
 
336
    copy->advance = source->advance;
337
    copy->format  = source->format;
338
 
339
    if ( clazz->glyph_copy )
340
      error = clazz->glyph_copy( source, copy );
341
 
342
    if ( error )
343
      FT_Done_Glyph( copy );
344
    else
345
      *target = copy;
346
 
347
  Exit:
348
    return error;
349
  }
350
 
351
 
352
  /* documentation is in ftglyph.h */
353
 
354
  FT_EXPORT_DEF( FT_Error )
355
  FT_Get_Glyph( FT_GlyphSlot  slot,
356
                FT_Glyph     *aglyph )
357
  {
358
    FT_Library  library;
359
    FT_Error    error;
360
    FT_Glyph    glyph;
361
 
362
    const FT_Glyph_Class*  clazz = 0;
363
 
364
 
365
    if ( !slot )
366
      return FT_THROW( Invalid_Slot_Handle );
367
 
368
    library = slot->library;
369
 
370
    if ( !aglyph )
371
      return FT_THROW( Invalid_Argument );
372
 
373
    /* if it is a bitmap, that's easy :-) */
374
    if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
375
      clazz = FT_BITMAP_GLYPH_CLASS_GET;
376
 
377
    /* if it is an outline */
378
    else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
379
      clazz = FT_OUTLINE_GLYPH_CLASS_GET;
380
 
381
    else
382
    {
383
      /* try to find a renderer that supports the glyph image format */
384
      FT_Renderer  render = FT_Lookup_Renderer( library, slot->format, 0 );
385
 
386
 
387
      if ( render )
388
        clazz = &render->glyph_class;
389
    }
390
 
391
    if ( !clazz )
392
    {
393
      error = FT_THROW( Invalid_Glyph_Format );
394
      goto Exit;
395
    }
396
 
397
    /* create FT_Glyph object */
398
    error = ft_new_glyph( library, clazz, &glyph );
399
    if ( error )
400
      goto Exit;
401
 
402
    /* copy advance while converting it to 16.16 format */
403
    glyph->advance.x = slot->advance.x << 10;
404
    glyph->advance.y = slot->advance.y << 10;
405
 
406
    /* now import the image from the glyph slot */
407
    error = clazz->glyph_init( glyph, slot );
408
 
409
    /* if an error occurred, destroy the glyph */
410
    if ( error )
411
      FT_Done_Glyph( glyph );
412
    else
413
      *aglyph = glyph;
414
 
415
  Exit:
416
    return error;
417
  }
418
 
419
 
420
  /* documentation is in ftglyph.h */
421
 
422
  FT_EXPORT_DEF( FT_Error )
423
  FT_Glyph_Transform( FT_Glyph    glyph,
424
                      FT_Matrix*  matrix,
425
                      FT_Vector*  delta )
426
  {
427
    const FT_Glyph_Class*  clazz;
428
    FT_Error               error = FT_Err_Ok;
429
 
430
 
431
    if ( !glyph || !glyph->clazz )
432
      error = FT_THROW( Invalid_Argument );
433
    else
434
    {
435
      clazz = glyph->clazz;
436
      if ( clazz->glyph_transform )
437
      {
438
        /* transform glyph image */
439
        clazz->glyph_transform( glyph, matrix, delta );
440
 
441
        /* transform advance vector */
442
        if ( matrix )
443
          FT_Vector_Transform( &glyph->advance, matrix );
444
      }
445
      else
446
        error = FT_THROW( Invalid_Glyph_Format );
447
    }
448
    return error;
449
  }
450
 
451
 
452
  /* documentation is in ftglyph.h */
453
 
454
  FT_EXPORT_DEF( void )
455
  FT_Glyph_Get_CBox( FT_Glyph  glyph,
456
                     FT_UInt   bbox_mode,
457
                     FT_BBox  *acbox )
458
  {
459
    const FT_Glyph_Class*  clazz;
460
 
461
 
462
    if ( !acbox )
463
      return;
464
 
465
    acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0;
466
 
467
    if ( !glyph || !glyph->clazz )
468
      return;
469
    else
470
    {
471
      clazz = glyph->clazz;
472
      if ( !clazz->glyph_bbox )
473
        return;
474
      else
475
      {
476
        /* retrieve bbox in 26.6 coordinates */
477
        clazz->glyph_bbox( glyph, acbox );
478
 
479
        /* perform grid fitting if needed */
480
        if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
481
             bbox_mode == FT_GLYPH_BBOX_PIXELS  )
482
        {
483
          acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
484
          acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
485
          acbox->xMax = FT_PIX_CEIL( acbox->xMax );
486
          acbox->yMax = FT_PIX_CEIL( acbox->yMax );
487
        }
488
 
489
        /* convert to integer pixels if needed */
490
        if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
491
             bbox_mode == FT_GLYPH_BBOX_PIXELS   )
492
        {
493
          acbox->xMin >>= 6;
494
          acbox->yMin >>= 6;
495
          acbox->xMax >>= 6;
496
          acbox->yMax >>= 6;
497
        }
498
      }
499
    }
500
    return;
501
  }
502
 
503
 
504
  /* documentation is in ftglyph.h */
505
 
506
  FT_EXPORT_DEF( FT_Error )
507
  FT_Glyph_To_Bitmap( FT_Glyph*       the_glyph,
508
                      FT_Render_Mode  render_mode,
509
                      FT_Vector*      origin,
510
                      FT_Bool         destroy )
511
  {
512
    FT_GlyphSlotRec           dummy;
513
    FT_GlyphSlot_InternalRec  dummy_internal;
514
    FT_Error                  error = FT_Err_Ok;
515
    FT_Glyph                  b, glyph;
516
    FT_BitmapGlyph            bitmap = NULL;
517
    const FT_Glyph_Class*     clazz;
518
 
519
    /* FT_BITMAP_GLYPH_CLASS_GET derefers `library' in PIC mode */
520
    FT_Library                library;
521
 
522
 
523
    /* check argument */
524
    if ( !the_glyph )
525
      goto Bad;
526
    glyph = *the_glyph;
527
    if ( !glyph )
528
      goto Bad;
529
 
530
    clazz   = glyph->clazz;
531
    library = glyph->library;
532
    if ( !library || !clazz )
533
      goto Bad;
534
 
535
    /* when called with a bitmap glyph, do nothing and return successfully */
536
    if ( clazz == FT_BITMAP_GLYPH_CLASS_GET )
537
      goto Exit;
538
 
539
    if ( !clazz->glyph_prepare )
540
      goto Bad;
541
 
542
    /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
543
    /* then calling FT_Render_Glyph_Internal()                            */
544
 
545
    FT_MEM_ZERO( &dummy, sizeof ( dummy ) );
546
    FT_MEM_ZERO( &dummy_internal, sizeof ( dummy_internal ) );
547
    dummy.internal = &dummy_internal;
548
    dummy.library  = library;
549
    dummy.format   = clazz->glyph_format;
550
 
551
    /* create result bitmap glyph */
552
    error = ft_new_glyph( library, FT_BITMAP_GLYPH_CLASS_GET, &b );
553
    if ( error )
554
      goto Exit;
555
    bitmap = (FT_BitmapGlyph)b;
556
 
557
#if 1
558
    /* if `origin' is set, translate the glyph image */
559
    if ( origin )
560
      FT_Glyph_Transform( glyph, 0, origin );
561
#else
562
    FT_UNUSED( origin );
563
#endif
564
 
565
    /* prepare dummy slot for rendering */
566
    error = clazz->glyph_prepare( glyph, &dummy );
567
    if ( !error )
568
      error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
569
 
570
#if 1
571
    if ( !destroy && origin )
572
    {
573
      FT_Vector  v;
574
 
575
 
576
      v.x = -origin->x;
577
      v.y = -origin->y;
578
      FT_Glyph_Transform( glyph, 0, &v );
579
    }
580
#endif
581
 
582
    if ( error )
583
      goto Exit;
584
 
585
    /* in case of success, copy the bitmap to the glyph bitmap */
586
    error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy );
587
    if ( error )
588
      goto Exit;
589
 
590
    /* copy advance */
591
    bitmap->root.advance = glyph->advance;
592
 
593
    if ( destroy )
594
      FT_Done_Glyph( glyph );
595
 
596
    *the_glyph = FT_GLYPH( bitmap );
597
 
598
  Exit:
599
    if ( error && bitmap )
600
      FT_Done_Glyph( FT_GLYPH( bitmap ) );
601
 
602
    return error;
603
 
604
  Bad:
605
    error = FT_THROW( Invalid_Argument );
606
    goto Exit;
607
  }
608
 
609
 
610
  /* documentation is in ftglyph.h */
611
 
612
  FT_EXPORT_DEF( void )
613
  FT_Done_Glyph( FT_Glyph  glyph )
614
  {
615
    if ( glyph )
616
    {
617
      FT_Memory              memory = glyph->library->memory;
618
      const FT_Glyph_Class*  clazz  = glyph->clazz;
619
 
620
 
621
      if ( clazz->glyph_done )
622
        clazz->glyph_done( glyph );
623
 
624
      FT_FREE( glyph );
625
    }
626
  }
627
 
628
 
629
/* END */