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