ftobjs.c 133 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 (body).                            */
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
    {
Werner Lemberg's avatar
   
Werner Lemberg committed
268
269
270
      /* in this case, we do not need to allocate a new stream object */
      /* since the caller is responsible for closing it himself       */
      FREE( stream );
271
      stream = args->stream;
272
273
274
    }
    else
      error = FT_Err_Invalid_Argument;
275

Werner Lemberg's avatar
   
Werner Lemberg committed
276
277
    if ( error )
      FREE( stream );
278

279
    *astream = stream;
Werner Lemberg's avatar
   
Werner Lemberg committed
280

David Turner's avatar
David Turner committed
281
  Exit:
282
283
284
285
    return error;
  }


Werner Lemberg's avatar
   
Werner Lemberg committed
286
287
288
  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
David Turner's avatar
David Turner committed
289
  /*    FT_Done_Stream                                                     */
Werner Lemberg's avatar
   
Werner Lemberg committed
290
291
292
293
  /*                                                                       */
  /* <Description>                                                         */
  /*    Closes and destroys a stream object.                               */
  /*                                                                       */
Werner Lemberg's avatar
   
Werner Lemberg committed
294
295
296
297
  /* <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
298
  {
Werner Lemberg's avatar
   
Werner Lemberg committed
299
    if ( stream && stream->close )
300
    {
David Turner's avatar
David Turner committed
301
      stream->close( stream );
302
303
      stream->close = 0;
    }
David Turner's avatar
David Turner committed
304
305
306
  }


307
  static
Werner Lemberg's avatar
   
Werner Lemberg committed
308
309
  void  ft_done_stream( FT_Stream*  astream,
                        FT_Int      external )
310
311
  {
    FT_Stream  stream = *astream;
Werner Lemberg's avatar
   
Werner Lemberg committed
312

Werner Lemberg's avatar
   
Werner Lemberg committed
313

Werner Lemberg's avatar
   
Werner Lemberg committed
314
    if ( stream->close )
315
      stream->close( stream );
316

Werner Lemberg's avatar
   
Werner Lemberg committed
317
    if ( !external )
318
319
    {
      FT_Memory  memory = stream->memory;
Werner Lemberg's avatar
   
Werner Lemberg committed
320
321


322
323
      FREE( stream );
    }
324
325
326
    *astream = 0;
  }

Werner Lemberg's avatar
   
Werner Lemberg committed
327

David Turner's avatar
David Turner committed
328
329
330
#undef  FT_COMPONENT
#define FT_COMPONENT  trace_objs

Werner Lemberg's avatar
   
Werner Lemberg committed
331

David Turner's avatar
David Turner committed
332
333
334
335
336
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/
  /****                                                                 ****/
  /****                                                                 ****/
David Turner's avatar
David Turner committed
337
  /****                     G L Y P H   L O A D E R                     ****/
David Turner's avatar
David Turner committed
338
339
340
341
342
343
  /****                                                                 ****/
  /****                                                                 ****/
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/

Werner Lemberg's avatar
   
Werner Lemberg committed
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374

  /*************************************************************************/
  /*                                                                       */
  /* 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
375
376
377
  {
    FT_GlyphLoader*  loader;
    FT_Error         error;
Werner Lemberg's avatar
   
Werner Lemberg committed
378

Werner Lemberg's avatar
   
Werner Lemberg committed
379
380

    if ( !ALLOC( loader, sizeof ( *loader ) ) )
David Turner's avatar
David Turner committed
381
382
383
384
385
386
    {
      loader->memory = memory;
      *aloader       = loader;
    }
    return error;
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
387
388


Werner Lemberg's avatar
   
Werner Lemberg committed
389
390
  /* rewind the glyph loader - reset counters to 0 */
  BASE_FUNC( void )  FT_GlyphLoader_Rewind( FT_GlyphLoader*  loader )
Werner Lemberg's avatar
   
Werner Lemberg committed
391
  {
David Turner's avatar
David Turner committed
392
393
394
    FT_GlyphLoad*  base    = &loader->base;
    FT_GlyphLoad*  current = &loader->current;

Werner Lemberg's avatar
   
Werner Lemberg committed
395

David Turner's avatar
David Turner committed
396
397
398
399
400
    base->outline.n_points   = 0;
    base->outline.n_contours = 0;
    base->num_subglyphs      = 0;

    *current = *base;
Werner Lemberg's avatar
   
Werner Lemberg committed
401
  }
David Turner's avatar
David Turner committed
402
403


Werner Lemberg's avatar
   
Werner Lemberg committed
404
405
406
  /* 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
407
  {
David Turner's avatar
David Turner committed
408
    FT_Memory memory = loader->memory;
Werner Lemberg's avatar
   
Werner Lemberg committed
409

Werner Lemberg's avatar
   
Werner Lemberg committed
410

David Turner's avatar
David Turner committed
411
412
413
414
415
    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
416

David Turner's avatar
David Turner committed
417
418
419
    loader->max_points    = 0;
    loader->max_contours  = 0;
    loader->max_subglyphs = 0;
Werner Lemberg's avatar
   
Werner Lemberg committed
420

David Turner's avatar
David Turner committed
421
422
    FT_GlyphLoader_Rewind( loader );
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
423

424

Werner Lemberg's avatar
   
Werner Lemberg committed
425
426
  /* delete a glyph loader */
  BASE_FUNC( void )  FT_GlyphLoader_Done( FT_GlyphLoader*  loader )
David Turner's avatar
David Turner committed
427
  {
Werner Lemberg's avatar
   
Werner Lemberg committed
428
    if ( loader )
David Turner's avatar
David Turner committed
429
430
431
    {
      FT_Memory memory = loader->memory;

Werner Lemberg's avatar
   
Werner Lemberg committed
432

Werner Lemberg's avatar
   
Werner Lemberg committed
433
      FT_GlyphLoader_Reset( loader );
David Turner's avatar
David Turner committed
434
435
      FREE( loader );
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
436
  }
David Turner's avatar
David Turner committed
437
438


Werner Lemberg's avatar
   
Werner Lemberg committed
439
  /* re-adjust the `current' outline fields */
Werner Lemberg's avatar
   
Werner Lemberg committed
440
441
  static
  void  FT_GlyphLoader_Adjust_Points( FT_GlyphLoader*  loader )
David Turner's avatar
David Turner committed
442
  {
David Turner's avatar
David Turner committed
443
444
445
    FT_Outline*  base    = &loader->base.outline;
    FT_Outline*  current = &loader->current.outline;

Werner Lemberg's avatar
   
Werner Lemberg committed
446

David Turner's avatar
David Turner committed
447
448
449
    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
450

David Turner's avatar
David Turner committed
451
    /* handle extra points table - if any */
Werner Lemberg's avatar
   
Werner Lemberg committed
452
453
454
    if ( loader->use_extra )
      loader->current.extra_points =
        loader->base.extra_points + base->n_points;
David Turner's avatar
David Turner committed
455
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
456

David Turner's avatar
David Turner committed
457

Werner Lemberg's avatar
   
Werner Lemberg committed
458
459
  BASE_FUNC( FT_Error )  FT_GlyphLoader_Create_Extra(
                           FT_GlyphLoader*  loader )
David Turner's avatar
David Turner committed
460
461
462
  {
    FT_Error   error;
    FT_Memory  memory = loader->memory;
Werner Lemberg's avatar
   
Werner Lemberg committed
463

Werner Lemberg's avatar
   
Werner Lemberg committed
464

David Turner's avatar
David Turner committed
465
466
467
468
    if ( !ALLOC_ARRAY( loader->base.extra_points,
                       loader->max_points, FT_Vector ) )
    {
      loader->use_extra = 1;
Werner Lemberg's avatar
   
Werner Lemberg committed
469
      FT_GlyphLoader_Adjust_Points( loader );
David Turner's avatar
David Turner committed
470
471
472
    }
    return error;
  }
David Turner's avatar
David Turner committed
473
474


Werner Lemberg's avatar
   
Werner Lemberg committed
475
  /* re-adjust the `current' subglyphs field */
Werner Lemberg's avatar
   
Werner Lemberg committed
476
477
  static
  void  FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader*  loader )
David Turner's avatar
David Turner committed
478
  {
David Turner's avatar
David Turner committed
479
480
    FT_GlyphLoad* base    = &loader->base;
    FT_GlyphLoad* current = &loader->current;
481

Werner Lemberg's avatar
   
Werner Lemberg committed
482

David Turner's avatar
David Turner committed
483
484
    current->subglyphs = base->subglyphs + base->num_subglyphs;
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
485

Werner Lemberg's avatar
   
Werner Lemberg committed
486

Werner Lemberg's avatar
   
Werner Lemberg committed
487
488
489
  /* 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
490
  /*                                                                       */
Werner Lemberg's avatar
   
Werner Lemberg committed
491
492
493
494
  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
495
496
497
498
499
500
501
  {
    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
502
    FT_UInt      new_max;
David Turner's avatar
David Turner committed
503

Werner Lemberg's avatar
   
Werner Lemberg committed
504

David Turner's avatar
David Turner committed
505
506
    /* check points & tags */
    new_max = base->n_points + current->n_points + n_points;
Werner Lemberg's avatar
   
Werner Lemberg committed
507
    if ( new_max > loader->max_points )
David Turner's avatar
David Turner committed
508
    {
Werner Lemberg's avatar
   
Werner Lemberg committed
509
510
511
512
513
      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
514
515
516
       goto Exit;

      if ( loader->use_extra &&
Werner Lemberg's avatar
   
Werner Lemberg committed
517
518
           REALLOC_ARRAY( loader->base.extra_points, base->n_points,
                          new_max, FT_Vector ) )
David Turner's avatar
David Turner committed
519
520
521
522
523
       goto Exit;

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

David Turner's avatar
David Turner committed
525
526
527
    /* check contours */
    new_max = base->n_contours + current->n_contours +
              n_contours;
Werner Lemberg's avatar
   
Werner Lemberg committed
528
    if ( new_max > loader->max_contours )
David Turner's avatar
David Turner committed
529
    {
Werner Lemberg's avatar
   
Werner Lemberg committed
530
531
532
      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
533
        goto Exit;
Werner Lemberg's avatar
   
Werner Lemberg committed
534

David Turner's avatar
David Turner committed
535
536
      adjust = 1;
      loader->max_contours = new_max;
David Turner's avatar
David Turner committed
537
    }
David Turner's avatar
David Turner committed
538

Werner Lemberg's avatar
   
Werner Lemberg committed
539
    if ( adjust )
David Turner's avatar
David Turner committed
540
541
542
543
      FT_GlyphLoader_Adjust_Points( loader );

  Exit:
    return error;
David Turner's avatar
David Turner committed
544
545
  }

Werner Lemberg's avatar
   
Werner Lemberg committed
546

Werner Lemberg's avatar
   
Werner Lemberg committed
547
548
549
  /* 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
550
  /*                                                                  */
Werner Lemberg's avatar
   
Werner Lemberg committed
551
552
553
  BASE_FUNC( FT_Error )  FT_GlyphLoader_Check_Subglyphs(
                           FT_GlyphLoader*  loader,
                           FT_UInt          n_subs )
David Turner's avatar
David Turner committed
554
  {
David Turner's avatar
David Turner committed
555
556
557
    FT_Memory  memory = loader->memory;
    FT_Error   error  = FT_Err_Ok;
    FT_UInt    new_max;
558

David Turner's avatar
David Turner committed
559
560
    FT_GlyphLoad*  base    = &loader->base;
    FT_GlyphLoad*  current = &loader->current;
Werner Lemberg's avatar
   
Werner Lemberg committed
561

Werner Lemberg's avatar
   
Werner Lemberg committed
562

David Turner's avatar
David Turner committed
563
    new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
Werner Lemberg's avatar
   
Werner Lemberg committed
564
    if ( new_max > loader->max_subglyphs )
David Turner's avatar
David Turner committed
565
    {
Werner Lemberg's avatar
   
Werner Lemberg committed
566
567
568
      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
569
        goto Exit;
Werner Lemberg's avatar
   
Werner Lemberg committed
570

David Turner's avatar
David Turner committed
571
      loader->max_subglyphs = new_max;
Werner Lemberg's avatar
   
Werner Lemberg committed
572

David Turner's avatar
David Turner committed
573
574
      FT_GlyphLoader_Adjust_Subglyphs( loader );
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
575

David Turner's avatar
David Turner committed
576
577
578
  Exit:
    return error;
  }
579
580


Werner Lemberg's avatar
   
Werner Lemberg committed
581
582
  /* 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
583
584
  {
    FT_GlyphLoad*  current = &loader->current;
585

Werner Lemberg's avatar
   
Werner Lemberg committed
586

David Turner's avatar
David Turner committed
587
588
589
    current->outline.n_points   = 0;
    current->outline.n_contours = 0;
    current->num_subglyphs      = 0;
Werner Lemberg's avatar
   
Werner Lemberg committed
590

David Turner's avatar
David Turner committed
591
592
593
    FT_GlyphLoader_Adjust_Points   ( loader );
    FT_GlyphLoader_Adjust_Subglyphs( loader );
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
594

595

Werner Lemberg's avatar
   
Werner Lemberg committed
596
597
  /* 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
598
599
600
  {
    FT_GlyphLoad*  base    = &loader->base;
    FT_GlyphLoad*  current = &loader->current;
Werner Lemberg's avatar
   
Werner Lemberg committed
601

David Turner's avatar
David Turner committed
602
603
604
605
    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
606

David Turner's avatar
David Turner committed
607
608
609
610
611
612
613
614
615
616
617
618
619
    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
620
621
  BASE_FUNC( FT_Error )  FT_GlyphLoader_Copy_Points( FT_GlyphLoader*  target,
                                                     FT_GlyphLoader*  source )
David Turner's avatar
David Turner committed
622
623
624
625
  {
    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
626

Werner Lemberg's avatar
   
Werner Lemberg committed
627

David Turner's avatar
David Turner committed
628
    error = FT_GlyphLoader_Check_Points( target, num_points, num_contours );
Werner Lemberg's avatar
   
Werner Lemberg committed
629
    if ( !error )
David Turner's avatar
David Turner committed
630
    {
David Turner's avatar
David Turner committed
631
632
      FT_Outline*  out = &target->base.outline;
      FT_Outline*  in  = &source->base.outline;
Werner Lemberg's avatar
   
Werner Lemberg committed
633

Werner Lemberg's avatar
   
Werner Lemberg committed
634

Werner Lemberg's avatar
   
Werner Lemberg committed
635
636
637
638
639
640
      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
641

Werner Lemberg's avatar
   
Werner Lemberg committed
642
643
      /* do we need to copy the extra points? */
      if ( target->use_extra && source->use_extra )
David Turner's avatar
David Turner committed
644
        MEM_Copy( target->base.extra_points, source->base.extra_points,
Werner Lemberg's avatar
   
Werner Lemberg committed
645
                  num_points * sizeof ( FT_Vector ) );
Werner Lemberg's avatar
   
Werner Lemberg committed
646

David Turner's avatar
David Turner committed
647
648
      out->n_points   = num_points;
      out->n_contours = num_contours;
Werner Lemberg's avatar
   
Werner Lemberg committed
649

David Turner's avatar
David Turner committed
650
      FT_GlyphLoader_Adjust_Points( target );
David Turner's avatar
David Turner committed
651
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
652

Werner Lemberg's avatar
   
Werner Lemberg committed
653
654
    return error;
  }
Werner Lemberg's avatar
   
Werner Lemberg committed
655

David Turner's avatar
David Turner committed
656

David Turner's avatar
David Turner committed
657
658
659
660
661
662
663
664
665
666
667
668
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/
  /****                                                                 ****/
  /****                                                                 ****/
  /****               FACE, SIZE & GLYPH SLOT OBJECTS                   ****/
  /****                                                                 ****/
  /****                                                                 ****/
  /*************************************************************************/
  /*************************************************************************/
  /*************************************************************************/

Werner Lemberg's avatar
   
Werner Lemberg committed
669
670
671

  static
  FT_Error  ft_glyphslot_init( FT_GlyphSlot  slot )
David Turner's avatar
David Turner committed
672
673
674
675
676
677
  {
    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
678

679
    slot->library = driver->root.library;
Werner Lemberg's avatar
   
Werner Lemberg committed
680

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

Werner Lemberg's avatar
   
Werner Lemberg committed
684
    if ( !error && clazz->init_slot )
David Turner's avatar
David Turner committed
685
686
      error = clazz->init_slot( slot );

David Turner's avatar
David Turner committed
687
    return error;
David Turner's avatar
David Turner committed
688
  }
David Turner's avatar
David Turner committed
689

David Turner's avatar
David Turner committed
690

Werner Lemberg's avatar
   
Werner Lemberg committed
691
692
  static
  void  ft_glyphslot_clear( FT_GlyphSlot  slot )
David Turner's avatar
David Turner committed
693
  {
694
695
696
697
    /* 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
698
699


700
701
702
      FREE( slot->bitmap.buffer );
      slot->flags &= ~ft_glyph_own_bitmap;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
703

David Turner's avatar
David Turner committed
704
    /* clear all public fields in the glyph slot */
Werner Lemberg's avatar
   
Werner Lemberg committed
705
706
707
    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
708
709
710
711
712
713
714
715

    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
716
    slot->format        = ft_glyph_format_none;
David Turner's avatar
David Turner committed
717
718
719
720
721
722

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


Werner Lemberg's avatar
   
Werner Lemberg committed
723
724
  static
  void  ft_glyphslot_done( FT_GlyphSlot  slot )
David Turner's avatar
David Turner committed
725
726
727
728
729
  {
    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
730

David Turner's avatar
David Turner committed
731
732
733
734
735
    /* 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
736
    if ( FT_DRIVER_USES_OUTLINES( driver ) )
David Turner's avatar
David Turner committed
737
738
739
740
741
    {
      FT_GlyphLoader_Done( slot->loader );
      slot->loader = 0;
    }

Werner Lemberg's avatar
   
Werner Lemberg committed
742
    if ( clazz->done_slot )
David Turner's avatar
David Turner committed
743
      clazz->done_slot( slot );
744
  }
David Turner's avatar
David Turner committed
745

Werner Lemberg's avatar
   
Werner Lemberg committed
746

David Turner's avatar
David Turner committed
747
748
749
  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
David Turner's avatar
David Turner committed
750
  /*    FT_New_GlyphSlot                                                   */
David Turner's avatar
David Turner committed
751
752
  /*                                                                       */
  /* <Description>                                                         */
David Turner's avatar
David Turner committed
753
754
755
756
  /*    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
757
758
  /*                                                                       */
  /* <Input>                                                               */
David Turner's avatar
David Turner committed
759
  /*    face  :: A handle to a parent face object.                         */
Werner Lemberg's avatar
   
Werner Lemberg committed
760
  /*                                                                       */
David Turner's avatar
David Turner committed
761
762
  /* <Output>                                                              */
  /*    aslot :: A handle to a new glyph slot object.                      */
David Turner's avatar
David Turner committed
763
764
  /*                                                                       */
  /* <Return>                                                              */
Werner Lemberg's avatar
   
Werner Lemberg committed
765
  /*    FreeType error code.  0 means success.                             */
David Turner's avatar
David Turner committed
766
  /*                                                                       */
David Turner's avatar
David Turner committed
767
768
  BASE_FUNC( FT_Error )  FT_New_GlyphSlot( FT_Face        face,
                                           FT_GlyphSlot*  aslot )
David Turner's avatar
David Turner committed
769
  {
Werner Lemberg's avatar
   
Werner Lemberg committed
770
771
772
773
774
775
    FT_Error          error;
    FT_Driver         driver;
    FT_Driver_Class*  clazz;
    FT_Memory         memory;
    FT_GlyphSlot      slot;

Werner Lemberg's avatar
   
Werner Lemberg committed
776

David Turner's avatar
David Turner committed
777
778
    if ( !face || !aslot || !face->driver )
      return FT_Err_Invalid_Argument;
Werner Lemberg's avatar
   
Werner Lemberg committed
779

Werner Lemberg's avatar
   
Werner Lemberg committed
780
781
    *aslot = 0;

David Turner's avatar
David Turner committed
782
783
784
    driver = face->driver;
    clazz  = driver->clazz;
    memory = driver->root.memory;
Werner Lemberg's avatar
   
Werner Lemberg committed
785

David Turner's avatar
David Turner committed
786
787
    FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
    if ( !ALLOC( slot, clazz->slot_object_size ) )
David Turner's avatar
David Turner committed
788
    {
David Turner's avatar
David Turner committed
789
      slot->face = face;
Werner Lemberg's avatar
   
Werner Lemberg committed
790

David Turner's avatar
David Turner committed
791
      error = ft_glyphslot_init( slot );
Werner Lemberg's avatar
   
Werner Lemberg committed
792
      if ( error )
David Turner's avatar
David Turner committed
793
      {
David Turner's avatar
David Turner committed
794
795
796
        ft_glyphslot_done( slot );
        FREE( slot );
        goto Exit;
David Turner's avatar
David Turner committed
797
      }
David Turner's avatar
David Turner committed
798
799

      *aslot = slot;
David Turner's avatar
David Turner committed
800
801
802
    }

  Exit:
David Turner's avatar
David Turner committed
803
    FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
David Turner's avatar
David Turner committed
804
805
806
    return error;
  }

Werner Lemberg's avatar
   
Werner Lemberg committed
807

David Turner's avatar
David Turner committed
808
809
810
  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
David Turner's avatar
David Turner committed
811
  /*    FT_Done_GlyphSlot                                                  */
David Turner's avatar
David Turner committed
812
813
  /*                                                                       */
  /* <Description>                                                         */
David Turner's avatar
David Turner committed
814
815
816
  /*    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
817
818
  /*                                                                       */
  /* <Input>                                                               */
David Turner's avatar
David Turner committed
819
  /*    slot :: A handle to a target glyph slot.                           */
David Turner's avatar
David Turner committed
820
  /*                                                                       */
David Turner's avatar
David Turner committed
821
  BASE_FUNC( void )  FT_Done_GlyphSlot( FT_GlyphSlot  slot )
David Turner's avatar
David Turner committed
822
  {
David Turner's avatar
David Turner committed
823
824
825
826
827
828
829
    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
830

David Turner's avatar
David Turner committed
831
832
833
      /* Remove slot from its parent face's list */
      parent = &slot->face->glyph;
      cur    = *parent;
Werner Lemberg's avatar
   
Werner Lemberg committed
834

David Turner's avatar
David Turner committed
835
836
837
838
839
      while ( cur )
      {
        if ( cur == slot )
        {
          *parent = cur->next;
Werner Lemberg's avatar
   
Werner Lemberg committed
840
          ft_glyphslot_done( slot );
David Turner's avatar
David Turner committed
841
842
843
844
845
846
847
          FREE( slot );
          break;
        }
        cur = cur->next;
      }
    }
  }
848

Werner Lemberg's avatar
   
Werner Lemberg committed
849

Werner Lemberg's avatar
   
Werner Lemberg committed
850
851
852
  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
David Turner's avatar
David Turner committed
853
  /*    FT_Set_Transform                                                   */
Werner Lemberg's avatar
   
Werner Lemberg committed
854
855
  /*                                                                       */
  /* <Description>                                                         */
David Turner's avatar
David Turner committed
856
  /*    A function used to set the transformation that is applied to glyph */
Werner Lemberg's avatar
   
Werner Lemberg committed
857
858
  /*    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
859
  /*                                                                       */
David Turner's avatar
David Turner committed
860
861
  /* <InOut>                                                               */
  /*    face   :: A handle to the source face object.                      */
David Turner's avatar
David Turner committed
862
863
  /*                                                                       */
  /* <Input>                                                               */
David Turner's avatar
David Turner committed
864
865
866
867
  /*    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
868
  /*                                                                       */
David Turner's avatar
David Turner committed
869
  /* <Note>                                                                */
Werner Lemberg's avatar
   
Werner Lemberg committed
870
871
872
873
  /*    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
874
  /*                                                                       */
David Turner's avatar
David Turner committed
875
876
877
  FT_EXPORT_FUNC( void )  FT_Set_Transform( FT_Face     face,
                                            FT_Matrix*  matrix,
                                            FT_Vector*  delta )
David Turner's avatar
David Turner committed
878
  {
David Turner's avatar
David Turner committed
879
880
    if ( !face )
      return;
David Turner's avatar
David Turner committed
881

David Turner's avatar
David Turner committed
882
    face->transform_flags = 0;
Werner Lemberg's avatar
   
Werner Lemberg committed
883

David Turner's avatar
David Turner committed
884
885
886
    if ( !matrix )
    {
      face->transform_matrix.xx = 0x10000L;
Werner Lemberg's avatar
   
Werner Lemberg committed
887
888
      face->transform_matrix.xy = 0;
      face->transform_matrix.yx = 0;
David Turner's avatar
David Turner committed
889
890
891
892
893
      face->transform_matrix.yy = 0x10000L;
      matrix = &face->transform_matrix;
    }
    else
      face->transform_matrix = *matrix;
894

David Turner's avatar
David Turner committed
895
896
897
898
899
    /* 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
900

David Turner's avatar
David Turner committed
901
902
903
904
905
906
907
908
    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
909

David Turner's avatar
David Turner committed
910
911
912
    /* 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
913
914
915
  }


Werner Lemberg's avatar
   
Werner Lemberg committed
916
917
918
  static FT_Renderer  ft_lookup_glyph_renderer( FT_GlyphSlot  slot );


David Turner's avatar
David Turner committed
919
920
921
  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
David Turner's avatar
David Turner committed
922
  /*    FT_Load_Glyph                                                      */
David Turner's avatar
David Turner committed
923
924
  /*                                                                       */
  /* <Description>                                                         */
David Turner's avatar
David Turner committed
925
926
  /*    A function used to load a single glyph within a given glyph slot,  */
  /*    for a given size.                                                  */
David Turner's avatar
David Turner committed
927
928
  /*                                                                       */
  /* <Input>                                                               */
David Turner's avatar
David Turner committed
929
930
931
932
933
934
935
936
937
938
  /*    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
939
940
  /*                                                                       */
  /* <Return>                                                              */
Werner Lemberg's avatar
   
Werner Lemberg committed
941
  /*    FreeType error code.  0 means success.                             */
David Turner's avatar
David Turner committed
942
  /*                                                                       */
David Turner's avatar
David Turner committed
943
944
945
946
947
948
  /* <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
949
950
  /*    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
951
952
953
954
  /*                                                                       */
  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
955
  {
David Turner's avatar
David Turner committed
956
957
958
    FT_Error      error;
    FT_Driver     driver;
    FT_GlyphSlot  slot;
959
960
961
    FT_Library    library;
    FT_Bool       autohint;
    FT_Module     hinter;
David Turner's avatar
David Turner committed
962

Werner Lemberg's avatar
   
Werner Lemberg committed
963

David Turner's avatar
David Turner committed
964
965
    if ( !face || !face->size || !face->glyph )
      return FT_Err_Invalid_Face_Handle;
David Turner's avatar
David Turner committed
966

967
    if ( glyph_index >= (FT_UInt)face->num_glyphs )
David Turner's avatar
David Turner committed
968
      return FT_Err_Invalid_Argument;
David Turner's avatar
David Turner committed
969

David Turner's avatar
David Turner committed
970
971
    slot = face->glyph;
    ft_glyphslot_clear( slot );
David Turner's avatar
David Turner committed
972

David Turner's avatar
David Turner committed
973
    driver = face->driver;
David Turner's avatar
David Turner committed
974

David Turner's avatar
David Turner committed
975
976
    /* when the flag NO_RECURSE is set, we disable hinting and scaling */
    if ( load_flags & FT_LOAD_NO_RECURSE )
David Turner's avatar
David Turner committed
977
978
979
980
981
982
983
984
985
    {
      /* disable scaling, hinting and transform */
      load_flags |= FT_LOAD_NO_SCALE       |
                    FT_LOAD_NO_HINTING     |
                    FT_LOAD_IGNORE_TRANSFORM;
                    
      /* disable bitmap rendering */
      load_flags &= ~FT_LOAD_RENDER;                    
    }
David Turner's avatar
David Turner committed
986

Werner Lemberg's avatar
   
Werner Lemberg committed
987
    /* do we need to load the glyph through the auto-hinter? */
988
989
    library  = driver->root.library;
    hinter   = library->auto_hinter;
990
991
992
993
    autohint = hinter                                                      &&
               !( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) &&
               FT_DRIVER_IS_SCALABLE(driver) &&
               FT_DRIVER_USES_OUTLINES(driver);
Werner Lemberg's avatar
   
Werner Lemberg committed
994
    if ( autohint )
995
996
    {
      if ( FT_DRIVER_HAS_HINTER( driver ) &&
Werner Lemberg's avatar
   
Werner Lemberg committed
997
998
999
           !( load_flags & FT_LOAD_FORCE_AUTOHINT ) )
        autohint = 0;
    }
Werner Lemberg's avatar
   
Werner Lemberg committed
1000

For faster browsing, not all history is shown. View entire blame