ftobjs.c 129 KB
Newer Older
David Turner's avatar
David Turner committed
1
2
3
4
/***************************************************************************/
/*                                                                         */
/*  ftobjs.c                                                               */
/*                                                                         */
Werner Lemberg's avatar
   
Werner Lemberg committed
5
/*    The FreeType private base classes (base).                            */
David Turner's avatar
David Turner committed
6
/*                                                                         */
Werner Lemberg's avatar
   
Werner Lemberg committed
7
/*  Copyright 1996-2000 by                                                 */
Werner Lemberg's avatar
   
Werner Lemberg committed
8
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
David Turner's avatar
David Turner committed
9
/*                                                                         */
Werner Lemberg's avatar
   
Werner Lemberg committed
10
11
/*  This file is part of the FreeType project, and may only be used,       */
/*  modified, and distributed under the terms of the FreeType project      */
David Turner's avatar
David Turner committed
12
13
14
15
16
17
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
/*  this file you indicate that you have read the license and              */
/*  understand and accept it fully.                                        */
/*                                                                         */
/***************************************************************************/

Werner Lemberg's avatar
   
Werner Lemberg committed
18

19
20
21
22
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftlist.h>
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftstream.h>
David Turner's avatar
David Turner committed
23

24
#include <freetype/tttables.h>
Werner Lemberg's avatar
   
Werner Lemberg committed
25

Werner Lemberg's avatar
   
Werner Lemberg committed
26
27
#include <string.h>     /* for strcmp() */

Werner Lemberg's avatar
   
Werner Lemberg committed
28

David Turner's avatar
David Turner committed
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/
  /****                                                                 ****/
  /****                                                                 ****/
  /****                           M E M O R Y                           ****/
  /****                                                                 ****/
  /****                                                                 ****/
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/

  /*************************************************************************/
  /*                                                                       */
  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
Werner Lemberg's avatar
   
Werner Lemberg committed
44
  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
David Turner's avatar
David Turner committed
45
46
47
48
49
50
51
52
53
54
55
56
57
  /* messages during execution.                                            */
  /*                                                                       */
#undef  FT_COMPONENT
#define FT_COMPONENT  trace_memory


  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
  /*    FT_Alloc                                                           */
  /*                                                                       */
  /* <Description>                                                         */
  /*    Allocates a new block of memory.  The returned area is always      */
Werner Lemberg's avatar
   
Werner Lemberg committed
58
  /*    zero-filled; this is a strong convention in many FreeType parts.   */
David Turner's avatar
David Turner committed
59
60
  /*                                                                       */
  /* <Input>                                                               */
Werner Lemberg's avatar
   
Werner Lemberg committed
61
62
  /*    memory :: A handle to a given `memory object' which handles        */
  /*              allocation.                                              */
David Turner's avatar
David Turner committed
63
64
65
66
67
68
69
70
71
72
  /*                                                                       */
  /*    size   :: The size in bytes of the block to allocate.              */
  /*                                                                       */
  /* <Output>                                                              */
  /*    P      :: A pointer to the fresh new block.  It should be set to   */
  /*              NULL if `size' is 0, or in case of error.                */
  /*                                                                       */
  /* <Return>                                                              */
  /*    FreeType error code.  0 means success.                             */
  /*                                                                       */
Werner Lemberg's avatar
   
Werner Lemberg committed
73
74
75
  BASE_FUNC( FT_Error )  FT_Alloc( FT_Memory  memory,
                                   FT_Long    size,
                                   void**     P )
David Turner's avatar
David Turner committed
76
77
78
  {
    FT_Assert( P != 0 );

Werner Lemberg's avatar
   
Werner Lemberg committed
79
    if ( size > 0 )
David Turner's avatar
David Turner committed
80
81
    {
      *P = memory->alloc( memory, size );
Werner Lemberg's avatar
   
Werner Lemberg committed
82
      if ( !*P )
David Turner's avatar
David Turner committed
83
      {
Werner Lemberg's avatar
   
Werner Lemberg committed
84
        FT_ERROR(( "FT_Alloc:" ));
Werner Lemberg's avatar
   
Werner Lemberg committed
85
        FT_ERROR(( " Out of memory? (%ld requested)\n",
David Turner's avatar
David Turner committed
86
87
88
89
90
91
92
93
94
                   size ));

        return FT_Err_Out_Of_Memory;
      }
      MEM_Set( *P, 0, size );
    }
    else
      *P = NULL;

Werner Lemberg's avatar
   
Werner Lemberg committed
95
96
    FT_TRACE7(( "FT_Alloc:" ));
    FT_TRACE7(( " size = %ld, block = 0x%08p, ref = 0x%08p\n",
97
                size, *P, P ));
David Turner's avatar
David Turner committed
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

    return FT_Err_Ok;
  }


  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
  /*    FT_Realloc                                                         */
  /*                                                                       */
  /* <Description>                                                         */
  /*    Reallocates a block of memory pointed to by `*P' to `Size' bytes   */
  /*    from the heap, possibly changing `*P'.                             */
  /*                                                                       */
  /* <Input>                                                               */
Werner Lemberg's avatar
   
Werner Lemberg committed
113
114
  /*    memory  :: A handle to a given `memory object' which handles       */
  /*               reallocation.                                           */
David Turner's avatar
David Turner committed
115
  /*                                                                       */
Werner Lemberg's avatar
   
Werner Lemberg committed
116
  /*    current :: The current block size in bytes.                        */
Werner Lemberg's avatar
   
Werner Lemberg committed
117
  /*                                                                       */
Werner Lemberg's avatar
   
Werner Lemberg committed
118
  /*    size    :: The new block size in bytes.                            */
David Turner's avatar
David Turner committed
119
120
  /*                                                                       */
  /* <InOut>                                                               */
Werner Lemberg's avatar
   
Werner Lemberg committed
121
122
  /*    P       :: A pointer to the fresh new block.  It should be set to  */
  /*               NULL if `size' is 0, or in case of error.               */
David Turner's avatar
David Turner committed
123
124
125
126
127
  /*                                                                       */
  /* <Return>                                                              */
  /*    FreeType error code.  0 means success.                             */
  /*                                                                       */
  /* <Note>                                                                */
Werner Lemberg's avatar
   
Werner Lemberg committed
128
  /*    All callers of FT_Realloc() _must_ provide the current block size  */
David Turner's avatar
David Turner committed
129
130
  /*    as well as the new one.                                            */
  /*                                                                       */
Werner Lemberg's avatar
   
Werner Lemberg committed
131
132
133
134
  BASE_FUNC( FT_Error )  FT_Realloc( FT_Memory  memory,
                                     FT_Long    current,
                                     FT_Long    size,
                                     void**     P )
David Turner's avatar
David Turner committed
135
136
137
  {
    void*  Q;

Werner Lemberg's avatar
   
Werner Lemberg committed
138

David Turner's avatar
David Turner committed
139
140
141
142
143
144
145
146
147
148
149
150
151
152
    FT_Assert( P != 0 );

    /* if the original pointer is NULL, call FT_Alloc() */
    if ( !*P )
      return FT_Alloc( memory, size, P );

    /* if the new block if zero-sized, clear the current one */
    if ( size <= 0 )
    {
      FT_Free( memory, P );
      return FT_Err_Ok;
    }

    Q = memory->realloc( memory, current, size, *P );
Werner Lemberg's avatar
   
Werner Lemberg committed
153
154
    if ( !Q )
      goto Fail;
David Turner's avatar
David Turner committed
155
156
157
158
159

    *P = Q;
    return FT_Err_Ok;

  Fail:
Werner Lemberg's avatar
   
Werner Lemberg committed
160
    FT_ERROR(( "FT_Realloc:" ));
Werner Lemberg's avatar
   
Werner Lemberg committed
161
    FT_ERROR(( " Failed (current %ld, requested %ld)\n",
David Turner's avatar
David Turner committed
162
163
164
165
166
167
168
169
170
171
172
173
174
175
               current, size ));
    return FT_Err_Out_Of_Memory;
  }


  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
  /*    FT_Free                                                            */
  /*                                                                       */
  /* <Description>                                                         */
  /*    Releases a given block of memory allocated through FT_Alloc().     */
  /*                                                                       */
  /* <Input>                                                               */
Werner Lemberg's avatar
   
Werner Lemberg committed
176
177
  /*    memory :: A handle to a given `memory object' which handles        */
  /*              memory deallocation                                      */
David Turner's avatar
David Turner committed
178
179
180
181
182
183
184
185
186
187
188
189
  /*                                                                       */
  /*    P      :: This is the _address_ of a _pointer_ which points to the */
  /*              allocated block.  It is always set to NULL on exit.      */
  /*                                                                       */
  /* <Return>                                                              */
  /*    FreeType error code.  0 means success.                             */
  /*                                                                       */
  /* <Note>                                                                */
  /*    If P or *P are NULL, this function should return successfully.     */
  /*    This is a strong convention within all of FreeType and its         */
  /*    drivers.                                                           */
  /*                                                                       */
Werner Lemberg's avatar
   
Werner Lemberg committed
190
191
  BASE_FUNC( void )  FT_Free( FT_Memory  memory,
                              void**     P )
David Turner's avatar
David Turner committed
192
  {
Werner Lemberg's avatar
   
Werner Lemberg committed
193
194
    FT_TRACE7(( "FT_Free:" ));
    FT_TRACE7(( " Freeing block 0x%08p, ref 0x%08p\n",
Werner Lemberg's avatar
   
Werner Lemberg committed
195
                P, P ? *P : (void*)0 ));
David Turner's avatar
David Turner committed
196

Werner Lemberg's avatar
   
Werner Lemberg committed
197
    if ( P && *P )
David Turner's avatar
David Turner committed
198
199
200
201
202
203
    {
      memory->free( memory, *P );
      *P = 0;
    }
  }

Werner Lemberg's avatar
   
Werner Lemberg committed
204

David Turner's avatar
David Turner committed
205
206
207
208
209
210
211
212
213
214
215
216
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/
  /****                                                                 ****/
  /****                                                                 ****/
  /****                           S T R E A M                           ****/
  /****                                                                 ****/
  /****                                                                 ****/
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/

Werner Lemberg's avatar
   
Werner Lemberg committed
217

Werner Lemberg's avatar
   
Werner Lemberg committed
218
219
220
221
222
223
224
225
  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
  /*    ft_new_input_stream                                                */
  /*                                                                       */
  /* <Description>                                                         */
  /*    Creates a new input stream object from an FT_Open_Args structure.  */
  /*                                                                       */
Werner Lemberg's avatar
   
Werner Lemberg committed
226
227
  /* <Note>                                                                */
  /*    The function expects a valid `astream' parameter.                  */
Werner Lemberg's avatar
   
Werner Lemberg committed
228
  /*                                                                       */
229
  static
Werner Lemberg's avatar
   
Werner Lemberg committed
230
231
  FT_Error  ft_new_input_stream( FT_Library     library,
                                 FT_Open_Args*  args,
Werner Lemberg's avatar
   
Werner Lemberg committed
232
                                 FT_Stream*     astream )
233
  {
Werner Lemberg's avatar
   
Werner Lemberg committed
234
235
236
237
    FT_Error   error;
    FT_Memory  memory;
    FT_Stream  stream;

Werner Lemberg's avatar
   
Werner Lemberg committed
238

Werner Lemberg's avatar
   
Werner Lemberg committed
239
240
241
242
243
244
    if ( !library )
      return FT_Err_Invalid_Library_Handle;

    if ( !args )
      return FT_Err_Invalid_Argument;

David Turner's avatar
David Turner committed
245
246
    *astream = 0;
    memory   = library->memory;
Werner Lemberg's avatar
   
Werner Lemberg committed
247
    if ( ALLOC( stream, sizeof ( *stream ) ) )
David Turner's avatar
David Turner committed
248
      goto Exit;
249

250
    stream->memory = memory;
251

252
253
    /* now, look at the stream flags */
    if ( args->flags & ft_open_memory )
254
    {
255
256
257
258
259
260
      error = 0;
      FT_New_Memory_Stream( library,
                            args->memory_base,
                            args->memory_size,
                            stream );
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
261
    else if ( args->flags & ft_open_pathname )
262
263
264
265
    {
      error = FT_New_Stream( args->pathname, stream );
      stream->pathname.pointer = args->pathname;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
266
    else if ( args->flags & ft_open_stream && args->stream )
267
268
269
270
271
272
    {
      *stream        = *(args->stream);
      stream->memory = memory;
    }
    else
      error = FT_Err_Invalid_Argument;
273

Werner Lemberg's avatar
   
Werner Lemberg committed
274
275
    if ( error )
      FREE( stream );
276

277
    *astream = stream;
Werner Lemberg's avatar
   
Werner Lemberg committed
278

David Turner's avatar
David Turner committed
279
  Exit:
280
281
282
283
    return error;
  }


Werner Lemberg's avatar
   
Werner Lemberg committed
284
285
286
  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
David Turner's avatar
David Turner committed
287
  /*    FT_Done_Stream                                                     */
Werner Lemberg's avatar
   
Werner Lemberg committed
288
289
290
291
  /*                                                                       */
  /* <Description>                                                         */
  /*    Closes and destroys a stream object.                               */
  /*                                                                       */
Werner Lemberg's avatar
   
Werner Lemberg committed
292
293
294
295
  /* <Input>                                                               */
  /*    stream :: The stream to be closed and destroyed.                   */
  /*                                                                       */
  FT_EXPORT_FUNC( void )  FT_Done_Stream( FT_Stream  stream )
David Turner's avatar
David Turner committed
296
  {
Werner Lemberg's avatar
   
Werner Lemberg committed
297
    if ( stream && stream->close )
David Turner's avatar
David Turner committed
298
299
300
301
      stream->close( stream );
  }


302
  static
Werner Lemberg's avatar
   
Werner Lemberg committed
303
  void  ft_done_stream( FT_Stream*  astream )
304
305
306
  {
    FT_Stream  stream = *astream;
    FT_Memory  memory = stream->memory;
Werner Lemberg's avatar
   
Werner Lemberg committed
307

Werner Lemberg's avatar
   
Werner Lemberg committed
308

Werner Lemberg's avatar
   
Werner Lemberg committed
309
    if ( stream->close )
310
      stream->close( stream );
311

312
313
314
315
    FREE( stream );
    *astream = 0;
  }

Werner Lemberg's avatar
   
Werner Lemberg committed
316

David Turner's avatar
David Turner committed
317
318
319
#undef  FT_COMPONENT
#define FT_COMPONENT  trace_objs

Werner Lemberg's avatar
   
Werner Lemberg committed
320

David Turner's avatar
David Turner committed
321
322
323
324
325
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/
  /****                                                                 ****/
  /****                                                                 ****/
David Turner's avatar
David Turner committed
326
  /****                     G L Y P H   L O A D E R                     ****/
David Turner's avatar
David Turner committed
327
328
329
330
331
332
  /****                                                                 ****/
  /****                                                                 ****/
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/

Werner Lemberg's avatar
   
Werner Lemberg committed
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363

  /*************************************************************************/
  /*                                                                       */
  /* The glyph loader is a simple object which is used to load a set of    */
  /* glyphs easily.  It is critical for the correct loading of composites. */
  /*                                                                       */
  /* Ideally, one can see it as a stack of abstract `glyph' objects.       */
  /*                                                                       */
  /*   loader.base     Is really the bottom of the stack.  It describes a  */
  /*                   single glyph image made of the juxtaposition of     */
  /*                   several glyphs (those `in the stack').              */
  /*                                                                       */
  /*   loader.current  Describes the top of the stack, on which a new      */
  /*                   glyph can be loaded.                                */
  /*                                                                       */
  /*   Rewind          Clears the stack.                                   */
  /*   Prepare         Set up `loader.current' for addition of a new glyph */
  /*                   image.                                              */
  /*   Add             Add the `current' glyph image to the `base' one,    */
  /*                   and prepare for another one.                        */
  /*                                                                       */
  /* The glyph loader is now a base object.  Each driver used to           */
  /* re-implement it in one way or the other, which wasted code and        */
  /* energy.                                                               */
  /*                                                                       */
  /*************************************************************************/


  /* create a new glyph loader */
  BASE_FUNC( FT_Error )  FT_GlyphLoader_New( FT_Memory         memory,
                                             FT_GlyphLoader**  aloader )
David Turner's avatar
David Turner committed
364
365
366
  {
    FT_GlyphLoader*  loader;
    FT_Error         error;
Werner Lemberg's avatar
   
Werner Lemberg committed
367

Werner Lemberg's avatar
   
Werner Lemberg committed
368
369

    if ( !ALLOC( loader, sizeof ( *loader ) ) )
David Turner's avatar
David Turner committed
370
371
372
373
374
375
    {
      loader->memory = memory;
      *aloader       = loader;
    }
    return error;
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
376
377


Werner Lemberg's avatar
   
Werner Lemberg committed
378
379
  /* rewind the glyph loader - reset counters to 0 */
  BASE_FUNC( void )  FT_GlyphLoader_Rewind( FT_GlyphLoader*  loader )
Werner Lemberg's avatar
   
Werner Lemberg committed
380
  {
David Turner's avatar
David Turner committed
381
382
383
    FT_GlyphLoad*  base    = &loader->base;
    FT_GlyphLoad*  current = &loader->current;

Werner Lemberg's avatar
   
Werner Lemberg committed
384

David Turner's avatar
David Turner committed
385
386
387
388
389
    base->outline.n_points   = 0;
    base->outline.n_contours = 0;
    base->num_subglyphs      = 0;

    *current = *base;
Werner Lemberg's avatar
   
Werner Lemberg committed
390
  }
David Turner's avatar
David Turner committed
391
392


Werner Lemberg's avatar
   
Werner Lemberg committed
393
394
395
  /* reset the glyph loader, frees all allocated tables */
  /* and starts from zero                               */
  BASE_FUNC( void )  FT_GlyphLoader_Reset( FT_GlyphLoader*  loader )
Werner Lemberg's avatar
   
Werner Lemberg committed
396
  {
David Turner's avatar
David Turner committed
397
    FT_Memory memory = loader->memory;
Werner Lemberg's avatar
   
Werner Lemberg committed
398

Werner Lemberg's avatar
   
Werner Lemberg committed
399

David Turner's avatar
David Turner committed
400
401
402
403
404
    FREE( loader->base.outline.points );
    FREE( loader->base.outline.tags );
    FREE( loader->base.outline.contours );
    FREE( loader->base.extra_points );
    FREE( loader->base.subglyphs );
Werner Lemberg's avatar
   
Werner Lemberg committed
405

David Turner's avatar
David Turner committed
406
407
408
    loader->max_points    = 0;
    loader->max_contours  = 0;
    loader->max_subglyphs = 0;
Werner Lemberg's avatar
   
Werner Lemberg committed
409

David Turner's avatar
David Turner committed
410
411
    FT_GlyphLoader_Rewind( loader );
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
412

413

Werner Lemberg's avatar
   
Werner Lemberg committed
414
415
  /* delete a glyph loader */
  BASE_FUNC( void )  FT_GlyphLoader_Done( FT_GlyphLoader*  loader )
David Turner's avatar
David Turner committed
416
  {
Werner Lemberg's avatar
   
Werner Lemberg committed
417
    if ( loader )
David Turner's avatar
David Turner committed
418
419
420
    {
      FT_Memory memory = loader->memory;

Werner Lemberg's avatar
   
Werner Lemberg committed
421

Werner Lemberg's avatar
   
Werner Lemberg committed
422
      FT_GlyphLoader_Reset( loader );
David Turner's avatar
David Turner committed
423
424
      FREE( loader );
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
425
  }
David Turner's avatar
David Turner committed
426
427


Werner Lemberg's avatar
   
Werner Lemberg committed
428
  /* re-adjust the `current' outline fields */
Werner Lemberg's avatar
   
Werner Lemberg committed
429
430
  static
  void  FT_GlyphLoader_Adjust_Points( FT_GlyphLoader*  loader )
David Turner's avatar
David Turner committed
431
  {
David Turner's avatar
David Turner committed
432
433
434
    FT_Outline*  base    = &loader->base.outline;
    FT_Outline*  current = &loader->current.outline;

Werner Lemberg's avatar
   
Werner Lemberg committed
435

David Turner's avatar
David Turner committed
436
437
438
    current->points   = base->points   + base->n_points;
    current->tags     = base->tags     + base->n_points;
    current->contours = base->contours + base->n_contours;
Werner Lemberg's avatar
   
Werner Lemberg committed
439

David Turner's avatar
David Turner committed
440
    /* handle extra points table - if any */
Werner Lemberg's avatar
   
Werner Lemberg committed
441
442
443
    if ( loader->use_extra )
      loader->current.extra_points =
        loader->base.extra_points + base->n_points;
David Turner's avatar
David Turner committed
444
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
445

David Turner's avatar
David Turner committed
446

Werner Lemberg's avatar
   
Werner Lemberg committed
447
448
  BASE_FUNC( FT_Error )  FT_GlyphLoader_Create_Extra(
                           FT_GlyphLoader*  loader )
David Turner's avatar
David Turner committed
449
450
451
  {
    FT_Error   error;
    FT_Memory  memory = loader->memory;
Werner Lemberg's avatar
   
Werner Lemberg committed
452

Werner Lemberg's avatar
   
Werner Lemberg committed
453

David Turner's avatar
David Turner committed
454
455
456
457
    if ( !ALLOC_ARRAY( loader->base.extra_points,
                       loader->max_points, FT_Vector ) )
    {
      loader->use_extra = 1;
Werner Lemberg's avatar
   
Werner Lemberg committed
458
      FT_GlyphLoader_Adjust_Points( loader );
David Turner's avatar
David Turner committed
459
460
461
    }
    return error;
  }
David Turner's avatar
David Turner committed
462
463


Werner Lemberg's avatar
   
Werner Lemberg committed
464
  /* re-adjust the `current' subglyphs field */
Werner Lemberg's avatar
   
Werner Lemberg committed
465
466
  static
  void  FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader*  loader )
David Turner's avatar
David Turner committed
467
  {
David Turner's avatar
David Turner committed
468
469
    FT_GlyphLoad* base    = &loader->base;
    FT_GlyphLoad* current = &loader->current;
470

Werner Lemberg's avatar
   
Werner Lemberg committed
471

David Turner's avatar
David Turner committed
472
473
    current->subglyphs = base->subglyphs + base->num_subglyphs;
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
474

Werner Lemberg's avatar
   
Werner Lemberg committed
475

Werner Lemberg's avatar
   
Werner Lemberg committed
476
477
478
  /* Ensure that we can add `n_points' and `n_contours' to our glyph. this */
  /* function reallocates its outline tables if necessary.  Note that it   */
  /* DOESN'T change the number of points within the loader!                */
Werner Lemberg's avatar
   
Werner Lemberg committed
479
  /*                                                                       */
Werner Lemberg's avatar
   
Werner Lemberg committed
480
481
482
483
  BASE_FUNC( FT_Error ) FT_GlyphLoader_Check_Points(
                          FT_GlyphLoader*  loader,
                          FT_UInt          n_points,
                          FT_UInt          n_contours )
David Turner's avatar
David Turner committed
484
485
486
487
488
489
490
  {
    FT_Memory    memory  = loader->memory;
    FT_Error     error   = FT_Err_Ok;
    FT_Outline*  base    = &loader->base.outline;
    FT_Outline*  current = &loader->current.outline;
    FT_Bool      adjust  = 1;

Werner Lemberg's avatar
   
Werner Lemberg committed
491
    FT_UInt      new_max;
David Turner's avatar
David Turner committed
492

Werner Lemberg's avatar
   
Werner Lemberg committed
493

David Turner's avatar
David Turner committed
494
495
    /* check points & tags */
    new_max = base->n_points + current->n_points + n_points;
Werner Lemberg's avatar
   
Werner Lemberg committed
496
    if ( new_max > loader->max_points )
David Turner's avatar
David Turner committed
497
    {
Werner Lemberg's avatar
   
Werner Lemberg committed
498
499
500
501
502
      new_max = ( new_max + 7 ) & -8;
      if ( REALLOC_ARRAY( base->points, base->n_points,
                          new_max, FT_Vector )          ||
           REALLOC_ARRAY( base->tags, base->n_points,
                          new_max, FT_Byte   )          )
David Turner's avatar
David Turner committed
503
504
505
       goto Exit;

      if ( loader->use_extra &&
Werner Lemberg's avatar
   
Werner Lemberg committed
506
507
           REALLOC_ARRAY( loader->base.extra_points, base->n_points,
                          new_max, FT_Vector ) )
David Turner's avatar
David Turner committed
508
509
510
511
512
       goto Exit;

      adjust = 1;
      loader->max_points = new_max;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
513

David Turner's avatar
David Turner committed
514
515
516
    /* check contours */
    new_max = base->n_contours + current->n_contours +
              n_contours;
Werner Lemberg's avatar
   
Werner Lemberg committed
517
    if ( new_max > loader->max_contours )
David Turner's avatar
David Turner committed
518
    {
Werner Lemberg's avatar
   
Werner Lemberg committed
519
520
521
      new_max = ( new_max + 3 ) & -4;
      if ( REALLOC_ARRAY( base->contours, base->n_contours,
                          new_max, FT_Short ) )
David Turner's avatar
David Turner committed
522
        goto Exit;
Werner Lemberg's avatar
   
Werner Lemberg committed
523

David Turner's avatar
David Turner committed
524
525
      adjust = 1;
      loader->max_contours = new_max;
David Turner's avatar
David Turner committed
526
    }
David Turner's avatar
David Turner committed
527

Werner Lemberg's avatar
   
Werner Lemberg committed
528
    if ( adjust )
David Turner's avatar
David Turner committed
529
530
531
532
      FT_GlyphLoader_Adjust_Points( loader );

  Exit:
    return error;
David Turner's avatar
David Turner committed
533
534
  }

Werner Lemberg's avatar
   
Werner Lemberg committed
535

Werner Lemberg's avatar
   
Werner Lemberg committed
536
537
538
  /* Ensure that we can add `n_subglyphs' to our glyph. this function */
  /* reallocates its subglyphs table if necessary.  Note that it DOES */
  /* NOT change the number of subglyphs within the loader!            */
Werner Lemberg's avatar
   
Werner Lemberg committed
539
  /*                                                                  */
Werner Lemberg's avatar
   
Werner Lemberg committed
540
541
542
  BASE_FUNC( FT_Error )  FT_GlyphLoader_Check_Subglyphs(
                           FT_GlyphLoader*  loader,
                           FT_UInt          n_subs )
David Turner's avatar
David Turner committed
543
  {
David Turner's avatar
David Turner committed
544
545
546
    FT_Memory  memory = loader->memory;
    FT_Error   error  = FT_Err_Ok;
    FT_UInt    new_max;
547

David Turner's avatar
David Turner committed
548
549
    FT_GlyphLoad*  base    = &loader->base;
    FT_GlyphLoad*  current = &loader->current;
Werner Lemberg's avatar
   
Werner Lemberg committed
550

Werner Lemberg's avatar
   
Werner Lemberg committed
551

David Turner's avatar
David Turner committed
552
    new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
Werner Lemberg's avatar
   
Werner Lemberg committed
553
    if ( new_max > loader->max_subglyphs )
David Turner's avatar
David Turner committed
554
    {
Werner Lemberg's avatar
   
Werner Lemberg committed
555
556
557
      new_max = ( new_max + 1 ) & -2;
      if ( REALLOC_ARRAY( base->subglyphs, base->num_subglyphs,
                          new_max, FT_SubGlyph ) )
David Turner's avatar
David Turner committed
558
        goto Exit;
Werner Lemberg's avatar
   
Werner Lemberg committed
559

David Turner's avatar
David Turner committed
560
      loader->max_subglyphs = new_max;
Werner Lemberg's avatar
   
Werner Lemberg committed
561

David Turner's avatar
David Turner committed
562
563
      FT_GlyphLoader_Adjust_Subglyphs( loader );
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
564

David Turner's avatar
David Turner committed
565
566
567
  Exit:
    return error;
  }
568
569


Werner Lemberg's avatar
   
Werner Lemberg committed
570
571
  /* prepare loader for the addition of a new glyph on top of the base one */
  BASE_FUNC( void )  FT_GlyphLoader_Prepare( FT_GlyphLoader*  loader )
David Turner's avatar
David Turner committed
572
573
  {
    FT_GlyphLoad*  current = &loader->current;
574

Werner Lemberg's avatar
   
Werner Lemberg committed
575

David Turner's avatar
David Turner committed
576
577
578
    current->outline.n_points   = 0;
    current->outline.n_contours = 0;
    current->num_subglyphs      = 0;
Werner Lemberg's avatar
   
Werner Lemberg committed
579

David Turner's avatar
David Turner committed
580
581
582
    FT_GlyphLoader_Adjust_Points   ( loader );
    FT_GlyphLoader_Adjust_Subglyphs( loader );
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
583

584

Werner Lemberg's avatar
   
Werner Lemberg committed
585
586
  /* add current glyph to the base image - and prepare for another */
  BASE_FUNC( void )  FT_GlyphLoader_Add( FT_GlyphLoader*  loader )
David Turner's avatar
David Turner committed
587
588
589
  {
    FT_GlyphLoad*  base    = &loader->base;
    FT_GlyphLoad*  current = &loader->current;
Werner Lemberg's avatar
   
Werner Lemberg committed
590

David Turner's avatar
David Turner committed
591
592
593
594
    FT_UInt        n_curr_contours = current->outline.n_contours;
    FT_UInt        n_base_points   = base->outline.n_points;
    FT_UInt        n;

Werner Lemberg's avatar
   
Werner Lemberg committed
595

David Turner's avatar
David Turner committed
596
597
598
599
600
601
602
603
604
605
606
607
608
    base->outline.n_points   += current->outline.n_points;
    base->outline.n_contours += current->outline.n_contours;
    base->num_subglyphs      += current->num_subglyphs;

    /* adjust contours count in newest outline */
    for ( n = 0; n < n_curr_contours; n++ )
      current->outline.contours[n] += n_base_points;

    /* prepare for another new glyph image */
    FT_GlyphLoader_Prepare( loader );
  }


Werner Lemberg's avatar
   
Werner Lemberg committed
609
610
  BASE_FUNC( FT_Error )  FT_GlyphLoader_Copy_Points( FT_GlyphLoader*  target,
                                                     FT_GlyphLoader*  source )
David Turner's avatar
David Turner committed
611
612
613
614
  {
    FT_Error  error;
    FT_UInt   num_points   = source->base.outline.n_points;
    FT_UInt   num_contours = source->base.outline.n_contours;
Werner Lemberg's avatar
   
Werner Lemberg committed
615

Werner Lemberg's avatar
   
Werner Lemberg committed
616

David Turner's avatar
David Turner committed
617
    error = FT_GlyphLoader_Check_Points( target, num_points, num_contours );
Werner Lemberg's avatar
   
Werner Lemberg committed
618
    if ( !error )
David Turner's avatar
David Turner committed
619
    {
David Turner's avatar
David Turner committed
620
621
      FT_Outline*  out = &target->base.outline;
      FT_Outline*  in  = &source->base.outline;
Werner Lemberg's avatar
   
Werner Lemberg committed
622

Werner Lemberg's avatar
   
Werner Lemberg committed
623

Werner Lemberg's avatar
   
Werner Lemberg committed
624
625
626
627
628
629
      MEM_Copy( out->points, in->points,
                num_points * sizeof ( FT_Vector ) );
      MEM_Copy( out->tags, in->tags,
                num_points * sizeof ( char ) );
      MEM_Copy( out->contours, in->contours,
                num_contours * sizeof ( short ) );
Werner Lemberg's avatar
   
Werner Lemberg committed
630

Werner Lemberg's avatar
   
Werner Lemberg committed
631
632
      /* do we need to copy the extra points? */
      if ( target->use_extra && source->use_extra )
David Turner's avatar
David Turner committed
633
        MEM_Copy( target->base.extra_points, source->base.extra_points,
Werner Lemberg's avatar
   
Werner Lemberg committed
634
                  num_points * sizeof ( FT_Vector ) );
Werner Lemberg's avatar
   
Werner Lemberg committed
635

David Turner's avatar
David Turner committed
636
637
      out->n_points   = num_points;
      out->n_contours = num_contours;
Werner Lemberg's avatar
   
Werner Lemberg committed
638

David Turner's avatar
David Turner committed
639
      FT_GlyphLoader_Adjust_Points( target );
David Turner's avatar
David Turner committed
640
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
641

Werner Lemberg's avatar
   
Werner Lemberg committed
642
643
    return error;
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
644

David Turner's avatar
David Turner committed
645

David Turner's avatar
David Turner committed
646
647
648
649
650
651
652
653
654
655
656
657
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/
  /****                                                                 ****/
  /****                                                                 ****/
  /****               FACE, SIZE & GLYPH SLOT OBJECTS                   ****/
  /****                                                                 ****/
  /****                                                                 ****/
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/

Werner Lemberg's avatar
   
Werner Lemberg committed
658
659
660

  static
  FT_Error  ft_glyphslot_init( FT_GlyphSlot  slot )
David Turner's avatar
David Turner committed
661
662
663
664
665
666
  {
    FT_Driver         driver = slot->face->driver;
    FT_Driver_Class*  clazz  = driver->clazz;
    FT_Memory         memory = driver->root.memory;
    FT_Error          error  = FT_Err_Ok;

Werner Lemberg's avatar
   
Werner Lemberg committed
667

668
    slot->library = driver->root.library;
Werner Lemberg's avatar
   
Werner Lemberg committed
669

Werner Lemberg's avatar
   
Werner Lemberg committed
670
    if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turner's avatar
David Turner committed
671
672
      error = FT_GlyphLoader_New( memory, &slot->loader );

Werner Lemberg's avatar
   
Werner Lemberg committed
673
    if ( !error && clazz->init_slot )
David Turner's avatar
David Turner committed
674
675
      error = clazz->init_slot( slot );

David Turner's avatar
David Turner committed
676
    return error;
David Turner's avatar
David Turner committed
677
  }
David Turner's avatar
David Turner committed
678

David Turner's avatar
David Turner committed
679

Werner Lemberg's avatar
   
Werner Lemberg committed
680
681
  static
  void  ft_glyphslot_clear( FT_GlyphSlot  slot )
David Turner's avatar
David Turner committed
682
  {
683
684
685
686
    /* free bitmap if needed */
    if ( slot->flags & ft_glyph_own_bitmap )
    {
      FT_Memory  memory = FT_FACE_MEMORY( slot->face );
Werner Lemberg's avatar
   
Werner Lemberg committed
687
688


689
690
691
      FREE( slot->bitmap.buffer );
      slot->flags &= ~ft_glyph_own_bitmap;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
692

David Turner's avatar
David Turner committed
693
    /* clear all public fields in the glyph slot */
Werner Lemberg's avatar
   
Werner Lemberg committed
694
695
696
    MEM_Set( &slot->metrics, 0, sizeof ( slot->metrics ) );
    MEM_Set( &slot->outline, 0, sizeof ( slot->outline ) );
    MEM_Set( &slot->bitmap,  0, sizeof ( slot->bitmap )  );
David Turner's avatar
David Turner committed
697
698
699
700
701
702
703
704

    slot->bitmap_left   = 0;
    slot->bitmap_top    = 0;
    slot->num_subglyphs = 0;
    slot->subglyphs     = 0;
    slot->control_data  = 0;
    slot->control_len   = 0;
    slot->other         = 0;
Werner Lemberg's avatar
   
Werner Lemberg committed
705
    slot->format        = ft_glyph_format_none;
David Turner's avatar
David Turner committed
706
707
708
709
710
711

    slot->linearHoriAdvance = 0;
    slot->linearVertAdvance = 0;
  }


Werner Lemberg's avatar
   
Werner Lemberg committed
712
713
  static
  void  ft_glyphslot_done( FT_GlyphSlot  slot )
David Turner's avatar
David Turner committed
714
715
716
717
718
  {
    FT_Driver         driver = slot->face->driver;
    FT_Driver_Class*  clazz  = driver->clazz;
    FT_Memory         memory = driver->root.memory;

Werner Lemberg's avatar
   
Werner Lemberg committed
719

David Turner's avatar
David Turner committed
720
721
722
723
724
    /* free bitmap buffer if needed */
    if ( slot->flags & ft_glyph_own_bitmap )
      FREE( slot->bitmap.buffer );

    /* free glyph loader */
Werner Lemberg's avatar
   
Werner Lemberg committed
725
    if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turner's avatar
David Turner committed
726
727
728
729
730
    {
      FT_GlyphLoader_Done( slot->loader );
      slot->loader = 0;
    }

Werner Lemberg's avatar
   
Werner Lemberg committed
731
    if ( clazz->done_slot )
David Turner's avatar
David Turner committed
732
      clazz->done_slot( slot );
733
  }
David Turner's avatar
David Turner committed
734

Werner Lemberg's avatar
   
Werner Lemberg committed
735

David Turner's avatar
David Turner committed
736
737
738
  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
David Turner's avatar
David Turner committed
739
  /*    FT_New_GlyphSlot                                                   */
David Turner's avatar
David Turner committed
740
741
  /*                                                                       */
  /* <Description>                                                         */
David Turner's avatar
David Turner committed
742
743
744
745
  /*    It is sometimes useful to have more than one glyph slot for a      */
  /*    given face object.  This function is used to create additional     */
  /*    slots.  All of them are automatically discarded when the face is   */
  /*    destroyed.                                                         */
David Turner's avatar
David Turner committed
746
747
  /*                                                                       */
  /* <Input>                                                               */
David Turner's avatar
David Turner committed
748
  /*    face  :: A handle to a parent face object.                         */
Werner Lemberg's avatar
   
Werner Lemberg committed
749
  /*                                                                       */
David Turner's avatar
David Turner committed
750
751
  /* <Output>                                                              */
  /*    aslot :: A handle to a new glyph slot object.                      */
David Turner's avatar
David Turner committed
752
753
  /*                                                                       */
  /* <Return>                                                              */
Werner Lemberg's avatar
   
Werner Lemberg committed
754
  /*    FreeType error code.  0 means success.                             */
David Turner's avatar
David Turner committed
755
  /*                                                                       */
David Turner's avatar
David Turner committed
756
757
758
  FT_EXPORT_FUNC( FT_Error )  FT_New_GlyphSlot( FT_Face        face,
                                                FT_GlyphSlot*  aslot )
  {
Werner Lemberg's avatar
   
Werner Lemberg committed
759
760
761
762
763
764
    FT_Error          error;
    FT_Driver         driver;
    FT_Driver_Class*  clazz;
    FT_Memory         memory;
    FT_GlyphSlot      slot;

Werner Lemberg's avatar
   
Werner Lemberg committed
765

David Turner's avatar
David Turner committed
766
767
    if ( !face || !aslot || !face->driver )
      return FT_Err_Invalid_Argument;
Werner Lemberg's avatar
   
Werner Lemberg committed
768

Werner Lemberg's avatar
   
Werner Lemberg committed
769
770
    *aslot = 0;

David Turner's avatar
David Turner committed
771
772
773
    driver = face->driver;
    clazz  = driver->clazz;
    memory = driver->root.memory;
Werner Lemberg's avatar
   
Werner Lemberg committed
774

David Turner's avatar
David Turner committed
775
776
    FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
    if ( !ALLOC( slot, clazz->slot_object_size ) )
David Turner's avatar
David Turner committed
777
    {
David Turner's avatar
David Turner committed
778
      slot->face = face;
Werner Lemberg's avatar
   
Werner Lemberg committed
779

David Turner's avatar
David Turner committed
780
      error = ft_glyphslot_init( slot );
Werner Lemberg's avatar
   
Werner Lemberg committed
781
      if ( error )
David Turner's avatar
David Turner committed
782
      {
David Turner's avatar
David Turner committed
783
784
785
        ft_glyphslot_done( slot );
        FREE( slot );
        goto Exit;
David Turner's avatar
David Turner committed
786
      }
David Turner's avatar
David Turner committed
787
788

      *aslot = slot;
David Turner's avatar
David Turner committed
789
790
791
    }

  Exit:
David Turner's avatar
David Turner committed
792
    FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
David Turner's avatar
David Turner committed
793
794
795
    return error;
  }

Werner Lemberg's avatar
   
Werner Lemberg committed
796

David Turner's avatar
David Turner committed
797
798
799
  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
David Turner's avatar
David Turner committed
800
  /*    FT_Done_GlyphSlot                                                  */
David Turner's avatar
David Turner committed
801
802
  /*                                                                       */
  /* <Description>                                                         */
David Turner's avatar
David Turner committed
803
804
805
  /*    Destroys a given glyph slot.  Remember however that all slots are  */
  /*    automatically destroyed with its parent.  Using this function is   */
  /*    not always mandatory.                                              */
Werner Lemberg's avatar
   
Werner Lemberg committed
806
807
  /*                                                                       */
  /* <Input>                                                               */
David Turner's avatar
David Turner committed
808
  /*    slot :: A handle to a target glyph slot.                           */
David Turner's avatar
David Turner committed
809
  /*                                                                       */
David Turner's avatar
David Turner committed
810
  FT_EXPORT_FUNC( void )  FT_Done_GlyphSlot( FT_GlyphSlot  slot )
David Turner's avatar
David Turner committed
811
  {
David Turner's avatar
David Turner committed
812
813
814
815
816
817
818
    if ( slot )
    {
      FT_Driver         driver = slot->face->driver;
      FT_Memory         memory = driver->root.memory;
      FT_GlyphSlot*     parent;
      FT_GlyphSlot      cur;

Werner Lemberg's avatar
   
Werner Lemberg committed
819

David Turner's avatar
David Turner committed
820
821
822
      /* Remove slot from its parent face's list */
      parent = &slot->face->glyph;
      cur    = *parent;
Werner Lemberg's avatar
   
Werner Lemberg committed
823

David Turner's avatar
David Turner committed
824
825
826
827
828
      while ( cur )
      {
        if ( cur == slot )
        {
          *parent = cur->next;
Werner Lemberg's avatar
   
Werner Lemberg committed
829
          ft_glyphslot_done( slot );
David Turner's avatar
David Turner committed
830
831
832
833
834
835
836
          FREE( slot );
          break;
        }
        cur = cur->next;
      }
    }
  }
837

Werner Lemberg's avatar
   
Werner Lemberg committed
838

Werner Lemberg's avatar
   
Werner Lemberg committed
839
840
841
  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
David Turner's avatar
David Turner committed
842
  /*    FT_Set_Transform                                                   */
Werner Lemberg's avatar
   
Werner Lemberg committed
843
844
  /*                                                                       */
  /* <Description>                                                         */
David Turner's avatar
David Turner committed
845
  /*    A function used to set the transformation that is applied to glyph */
Werner Lemberg's avatar
   
Werner Lemberg committed
846
847
  /*    images just before they are converted to bitmaps in a glyph slot   */
  /*    when FT_Render_Glyph() is called.                                  */
Werner Lemberg's avatar
   
Werner Lemberg committed
848
  /*                                                                       */
David Turner's avatar
David Turner committed
849
850
  /* <InOut>                                                               */
  /*    face   :: A handle to the source face object.                      */
David Turner's avatar
David Turner committed
851
852
  /*                                                                       */
  /* <Input>                                                               */
David Turner's avatar
David Turner committed
853
854
855
856
  /*    matrix :: A pointer to the transformation's 2x2 matrix.  Use 0 for */
  /*              the identity matrix.                                     */
  /*    delta  :: A pointer to the translation vector.  Use 0 for the null */
  /*              vector.                                                  */
David Turner's avatar
David Turner committed
857
  /*                                                                       */
David Turner's avatar
David Turner committed
858
  /* <Note>                                                                */
Werner Lemberg's avatar
   
Werner Lemberg committed
859
860
861
862
  /*    The transformation is only applied to scalable image formats after */
  /*    the glyph has been loaded.  It means that hinting is unaltered by  */
  /*    the transformation and is performed on the character size given in */
  /*    the last call to FT_Set_Char_Sizes() or FT_Set_Pixel_Sizes().      */
David Turner's avatar
David Turner committed
863
  /*                                                                       */
David Turner's avatar
David Turner committed
864
865
866
  FT_EXPORT_FUNC( void )  FT_Set_Transform( FT_Face     face,
                                            FT_Matrix*  matrix,
                                            FT_Vector*  delta )
David Turner's avatar
David Turner committed
867
  {
David Turner's avatar
David Turner committed
868
869
    if ( !face )
      return;
David Turner's avatar
David Turner committed
870

David Turner's avatar
David Turner committed
871
    face->transform_flags = 0;
Werner Lemberg's avatar
   
Werner Lemberg committed
872

David Turner's avatar
David Turner committed
873
874
875
    if ( !matrix )
    {
      face->transform_matrix.xx = 0x10000L;
Werner Lemberg's avatar
   
Werner Lemberg committed
876
877
      face->transform_matrix.xy = 0;
      face->transform_matrix.yx = 0;
David Turner's avatar
David Turner committed
878
879
880
881
882
      face->transform_matrix.yy = 0x10000L;
      matrix = &face->transform_matrix;
    }
    else
      face->transform_matrix = *matrix;
883

David Turner's avatar
David Turner committed
884
885
886
887
888
    /* set transform_flags bit flag 0 if `matrix' isn't the identity */
    if ( ( matrix->xy | matrix->yx ) ||
         matrix->xx != 0x10000L      ||
         matrix->yy != 0x10000L      )
      face->transform_flags |= 1;
David Turner's avatar
David Turner committed
889

David Turner's avatar
David Turner committed
890
891
892
893
894
895
896
897
    if ( !delta )
    {
      face->transform_delta.x = 0;
      face->transform_delta.y = 0;
      delta = &face->transform_delta;
    }
    else
      face->transform_delta = *delta;
Werner Lemberg's avatar
   
Werner Lemberg committed
898

David Turner's avatar
David Turner committed
899
900
901
    /* set transform_flags bit flag 1 if `delta' isn't the null vector */
    if ( delta->x | delta->y )
      face->transform_flags |= 2;
David Turner's avatar
David Turner committed
902
903
904
  }


Werner Lemberg's avatar
   
Werner Lemberg committed
905
906
907
  static FT_Renderer  ft_lookup_glyph_renderer( FT_GlyphSlot  slot );


David Turner's avatar
David Turner committed
908
909
910
  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
David Turner's avatar
David Turner committed
911
  /*    FT_Load_Glyph                                                      */
David Turner's avatar
David Turner committed
912
913
  /*                                                                       */
  /* <Description>                                                         */
David Turner's avatar
David Turner committed
914
915
  /*    A function used to load a single glyph within a given glyph slot,  */
  /*    for a given size.                                                  */
David Turner's avatar
David Turner committed
916
917
  /*                                                                       */
  /* <Input>                                                               */
David Turner's avatar
David Turner committed
918
919
920
921
922
923
924
925
926
927
  /*    face        :: A handle to the target face object where the glyph  */
  /*                   will be loaded.                                     */
  /*                                                                       */
  /*    glyph_index :: The index of the glyph in the font file.            */
  /*                                                                       */
  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
  /*                   FT_LOAD_XXX constants can be used to control the    */
  /*                   glyph loading process (e.g., whether the outline    */
  /*                   should be scaled, whether to load bitmaps or not,   */
  /*                   whether to hint the outline, etc).                  */
David Turner's avatar
David Turner committed
928
929
  /*                                                                       */
  /* <Return>                                                              */
Werner Lemberg's avatar
   
Werner Lemberg committed
930
  /*    FreeType error code.  0 means success.                             */
David Turner's avatar
David Turner committed
931
  /*                                                                       */
David Turner's avatar
David Turner committed
932
933
934
935
936
937
  /* <Note>                                                                */
  /*    If the glyph image is not a bitmap, and if the bit flag            */
  /*    FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be         */
  /*    transformed with the information passed to a previous call to      */
  /*    FT_Set_Transform.                                                  */
  /*                                                                       */
Werner Lemberg's avatar
   
Werner Lemberg committed
938
939
  /*    Note that this also transforms the `face.glyph.advance' field, but */
  /*    *not* the values in `face.glyph.metrics'.                          */
David Turner's avatar
David Turner committed
940
941
942
943
  /*                                                                       */
  FT_EXPORT_FUNC( FT_Error )  FT_Load_Glyph( FT_Face  face,
                                             FT_UInt  glyph_index,
                                             FT_Int   load_flags )
David Turner's avatar
David Turner committed
944
  {
David Turner's avatar
David Turner committed
945
946
947
    FT_Error      error;
    FT_Driver     driver;
    FT_GlyphSlot  slot;
948
949
950
    FT_Library    library;
    FT_Bool       autohint;
    FT_Module     hinter;
David Turner's avatar
David Turner committed
951

Werner Lemberg's avatar
   
Werner Lemberg committed
952

David Turner's avatar
David Turner committed
953
954
    if ( !face || !face->size || !face->glyph )
      return FT_Err_Invalid_Face_Handle;
David Turner's avatar
David Turner committed
955

956
    if ( glyph_index >= (FT_UInt)face->num_glyphs )
David Turner's avatar
David Turner committed
957
      return FT_Err_Invalid_Argument;
David Turner's avatar
David Turner committed
958

David Turner's avatar
David Turner committed
959
960
    slot = face->glyph;
    ft_glyphslot_clear( slot );
David Turner's avatar
David Turner committed
961

David Turner's avatar
David Turner committed
962
    driver = face->driver;
David Turner's avatar
David Turner committed
963

David Turner's avatar
David Turner committed
964
965
966
    /* when the flag NO_RECURSE is set, we disable hinting and scaling */
    if ( load_flags & FT_LOAD_NO_RECURSE )
      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
David Turner's avatar
David Turner committed
967

Werner Lemberg's avatar
   
Werner Lemberg committed
968
    /* do we need to load the glyph through the auto-hinter? */
969
970
971
    library  = driver->root.library;
    hinter   = library->auto_hinter;
    autohint = hinter &&
Werner Lemberg's avatar
   
Werner Lemberg committed
972
973
               !( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) );
    if ( autohint )
974
975
    {
      if ( FT_DRIVER_HAS_HINTER( driver ) &&
Werner Lemberg's avatar
   
Werner Lemberg committed
976
977
978
           !( load_flags & FT_LOAD_FORCE_AUTOHINT ) )
        autohint = 0;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
979

Werner Lemberg's avatar
   
Werner Lemberg committed
980
    if ( autohint )
981
982
    {
      FT_AutoHinter_Interface*  hinting;
Werner Lemberg's avatar
   
Werner Lemberg committed
983

Werner Lemberg's avatar
   
Werner Lemberg committed
984

985
      hinting = (FT_AutoHinter_Interface*)hinter->clazz->module_interface;
Werner Lemberg's avatar
   
Werner Lemberg committed
986
      error = hinting->load_glyph( (FT_AutoHinter)hinter, slot, face->size,
987
988
989
990
991
                                   glyph_index, load_flags );
    }
    else
      error = driver->clazz->load_glyph( slot,
                                         face->size,
Werner Lemberg's avatar
   
Werner Lemberg committed
992
993
                                         glyph_index,
                                         load_flags );
Werner Lemberg's avatar
   
Werner Lemberg committed
994
995
    if ( error )
      goto Exit;
Werner Lemberg's avatar
   
Werner Lemberg committed
996

David Turner's avatar
David Turner committed
997
    /* compute the advance */
Werner Lemberg's avatar
   
Werner Lemberg committed
998
    if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
David Turner's avatar
David Turner committed
999
1000
    {
      slot->advance.x = 0;
For faster browsing, not all history is shown. View entire blame