ftglue.c revision 2c393a42
1/* ftglue.c: Glue code for compiling the OpenType code from
2 *           FreeType 1 using only the public API of FreeType 2
3 *
4 * By David Turner, The FreeType Project (www.freetype.org)
5 *
6 * This code is explicitely put in the public domain
7 *
8 * See ftglue.h for more information.
9 */
10
11#include "ftglue.h"
12
13#if 0
14#include <stdio.h>
15#define  LOG(x)  ftglue_log x
16
17static void
18ftglue_log( const char*   format, ... )
19{
20  va_list  ap;
21
22  va_start( ap, format );
23  vfprintf( stderr, format, ap );
24  va_end( ap );
25}
26
27#else
28#define  LOG(x)  do {} while (0)
29#endif
30
31/* only used internally */
32static FT_Pointer
33ftglue_qalloc( FT_Memory  memory,
34               FT_ULong   size,
35               FT_Error  *perror )
36{
37  FT_Error    error = 0;
38  FT_Pointer  block = NULL;
39
40  if ( size > 0 )
41  {
42    block = memory->alloc( memory, size );
43    if ( !block )
44      error = FT_Err_Out_Of_Memory;
45  }
46
47  *perror = error;
48  return block;
49}
50
51#undef   QALLOC  /* just in case */
52#define  QALLOC(ptr,size)    ( (ptr) = ftglue_qalloc( memory, (size), &error ), error != 0 )
53#define  FREE(_ptr)                    \
54  do {                                 \
55    if ( (_ptr) )                      \
56    {                                  \
57      ftglue_free( memory, _ptr );     \
58      _ptr = NULL;                     \
59    }                                  \
60  } while (0)
61
62
63FTGLUE_APIDEF( FT_Pointer )
64ftglue_alloc( FT_Memory  memory,
65              FT_ULong   size,
66              FT_Error  *perror )
67{
68  FT_Error    error = 0;
69  FT_Pointer  block = NULL;
70
71  if ( size > 0 )
72  {
73    block = memory->alloc( memory, size );
74    if ( !block )
75      error = FT_Err_Out_Of_Memory;
76    else
77      memset( (char*)block, 0, (size_t)size );
78  }
79
80  *perror = error;
81  return block;
82}
83
84
85FTGLUE_APIDEF( FT_Pointer )
86ftglue_realloc( FT_Memory   memory,
87                FT_Pointer  block,
88                FT_ULong    old_size,
89                FT_ULong    new_size,
90                FT_Error   *perror )
91{
92  FT_Pointer  block2 = NULL;
93  FT_Error    error  = 0;
94
95  if ( old_size == 0 || block == NULL )
96  {
97    block2 = ftglue_alloc( memory, new_size, &error );
98  }
99  else if ( new_size == 0 )
100  {
101    ftglue_free( memory, block );
102  }
103  else
104  {
105    block2 = memory->realloc( memory, old_size, new_size, block );
106    if ( block2 == NULL )
107      error = FT_Err_Out_Of_Memory;
108    else if ( new_size > old_size )
109      memset( (char*)block2 + old_size, 0, (size_t)(new_size - old_size) );
110  }
111
112  if ( !error )
113    block = block2;
114
115  *perror = error;
116  return block;
117}
118
119
120FTGLUE_APIDEF( void )
121ftglue_free( FT_Memory   memory,
122             FT_Pointer  block )
123{
124  if ( block )
125    memory->free( memory, block );
126}
127
128
129FTGLUE_APIDEF( FT_Long )
130ftglue_stream_pos( FT_Stream   stream )
131{
132  LOG(( "ftglue:stream:pos() -> %ld\n", stream->pos ));
133  return stream->pos;
134}
135
136
137FTGLUE_APIDEF( FT_Error )
138ftglue_stream_seek( FT_Stream   stream,
139                    FT_Long     pos )
140{
141  FT_Error  error = 0;
142
143  stream->pos = pos;
144  if ( stream->read )
145  {
146    if ( stream->read( stream, pos, 0, 0 ) )
147      error = FT_Err_Invalid_Stream_Operation;
148  }
149  else if ( pos > stream->size )
150    error = FT_Err_Invalid_Stream_Operation;
151
152  LOG(( "ftglue:stream:seek(%ld) -> %d\n", pos, error ));
153  return error;
154}
155
156
157FTGLUE_APIDEF( FT_Error )
158ftglue_stream_frame_enter( FT_Stream   stream,
159                           FT_ULong    count )
160{
161  FT_Error  error = FT_Err_Ok;
162  FT_ULong  read_bytes;
163
164  if ( stream->read )
165  {
166    /* allocate the frame in memory */
167    FT_Memory  memory = stream->memory;
168
169
170    if ( QALLOC( stream->base, count ) )
171      goto Exit;
172
173    /* read it */
174    read_bytes = stream->read( stream, stream->pos,
175                               stream->base, count );
176    if ( read_bytes < count )
177    {
178      FREE( stream->base );
179      error = FT_Err_Invalid_Stream_Operation;
180    }
181    stream->cursor = stream->base;
182    stream->limit  = stream->cursor + count;
183    stream->pos   += read_bytes;
184  }
185  else
186  {
187    /* check current and new position */
188    if ( stream->pos >= stream->size        ||
189         stream->pos + count > stream->size )
190    {
191      error = FT_Err_Invalid_Stream_Operation;
192      goto Exit;
193    }
194
195    /* set cursor */
196    stream->cursor = stream->base + stream->pos;
197    stream->limit  = stream->cursor + count;
198    stream->pos   += count;
199  }
200
201Exit:
202  LOG(( "ftglue:stream:frame_enter(%ld) -> %d\n", count, error ));
203  return error;
204}
205
206
207FTGLUE_APIDEF( void )
208ftglue_stream_frame_exit( FT_Stream  stream )
209{
210  if ( stream->read )
211  {
212    FT_Memory  memory = stream->memory;
213
214    FREE( stream->base );
215  }
216  stream->cursor = 0;
217  stream->limit  = 0;
218
219  LOG(( "ftglue:stream:frame_exit()\n" ));
220}
221
222
223FTGLUE_APIDEF( FT_Error )
224ftglue_face_goto_table( FT_Face    face,
225                        FT_ULong   the_tag,
226                        FT_Stream  stream )
227{
228  FT_Error  error;
229
230  LOG(( "ftglue_face_goto_table( %p, %c%c%c%c, %p )\n",
231                face,
232                (int)((the_tag >> 24) & 0xFF),
233                (int)((the_tag >> 16) & 0xFF),
234                (int)((the_tag >> 8) & 0xFF),
235                (int)(the_tag & 0xFF),
236                stream ));
237
238  if ( !FT_IS_SFNT(face) )
239  {
240    LOG(( "not a SFNT face !!\n" ));
241    error = FT_Err_Invalid_Face_Handle;
242  }
243  else
244  {
245   /* parse the directory table directly, without using
246    * FreeType's built-in data structures
247    */
248    FT_ULong  offset = 0;
249    FT_UInt   count, nn;
250
251    if ( face->num_faces > 1 )
252    {
253      /* deal with TrueType collections */
254
255      LOG(( ">> This is a TrueType Collection\n" ));
256
257      if ( FILE_Seek( 12 + face->face_index*4 ) ||
258           ACCESS_Frame( 4 )                    )
259        goto Exit;
260
261      offset = GET_ULong();
262
263      FORGET_Frame();
264    }
265
266    LOG(( "TrueType offset = %ld\n", offset ));
267
268    if ( FILE_Seek( offset+4 ) ||
269         ACCESS_Frame( 2 )     )
270      goto Exit;
271
272    count = GET_UShort();
273
274    FORGET_Frame();
275
276    if ( FILE_Seek( offset+12 )   ||
277         ACCESS_Frame( count*16 ) )
278      goto Exit;
279
280    for ( nn = 0; nn < count; nn++ )
281    {
282      FT_ULong  tag      = GET_ULong();
283      FT_ULong  checksum = GET_ULong();
284      FT_ULong  start    = GET_ULong();
285      FT_ULong  size     = GET_ULong();
286
287      FT_UNUSED(checksum);
288      FT_UNUSED(size);
289
290      if ( tag == the_tag )
291      {
292        LOG(( "TrueType table (start: %ld) (size: %ld)\n", start, size ));
293        error = ftglue_stream_seek( stream, start );
294        goto FoundIt;
295      }
296    }
297    error = TT_Err_Table_Missing;
298
299  FoundIt:
300    FORGET_Frame();
301  }
302
303Exit:
304  LOG(( "TrueType error=%d\n", error ));
305
306  return error;
307}
308
309#undef QALLOC
310#define __ftglue__
311#include "fcaliastail.h"
312#undef __ftglue__
313