• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************/
2 /*                                                                         */
3 /*  ttbdf.c                                                                */
4 /*                                                                         */
5 /*    TrueType and OpenType embedded BDF properties (body).                */
6 /*                                                                         */
7 /*  Copyright 2005, 2006 by                                                */
8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9 /*                                                                         */
10 /*  This file is part of the FreeType project, and may only be used,       */
11 /*  modified, and distributed under the terms of the FreeType project      */
12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13 /*  this file you indicate that you have read the license and              */
14 /*  understand and accept it fully.                                        */
15 /*                                                                         */
16 /***************************************************************************/
17 
18 
19 #include <ft2build.h>
20 #include FT_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_STREAM_H
22 #include FT_TRUETYPE_TAGS_H
23 #include "ttbdf.h"
24 
25 #include "sferrors.h"
26 
27 
28 #ifdef TT_CONFIG_OPTION_BDF
29 
30   /*************************************************************************/
31   /*                                                                       */
32   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
33   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
34   /* messages during execution.                                            */
35   /*                                                                       */
36 #undef  FT_COMPONENT
37 #define FT_COMPONENT  trace_ttbdf
38 
39 
40   FT_LOCAL_DEF( void )
tt_face_free_bdf_props(TT_Face face)41   tt_face_free_bdf_props( TT_Face  face )
42   {
43     TT_BDF  bdf = &face->bdf;
44 
45 
46     if ( bdf->loaded )
47     {
48       FT_Stream  stream = FT_FACE(face)->stream;
49 
50 
51       if ( bdf->table != NULL )
52         FT_FRAME_RELEASE( bdf->table );
53 
54       bdf->table_end    = NULL;
55       bdf->strings      = NULL;
56       bdf->strings_size = 0;
57     }
58   }
59 
60 
61   static FT_Error
tt_face_load_bdf_props(TT_Face face,FT_Stream stream)62   tt_face_load_bdf_props( TT_Face    face,
63                           FT_Stream  stream )
64   {
65     TT_BDF    bdf = &face->bdf;
66     FT_ULong  length;
67     FT_Error  error;
68 
69 
70     FT_ZERO( bdf );
71 
72     error = tt_face_goto_table( face, TTAG_BDF, stream, &length );
73     if ( error                                  ||
74          length < 8                             ||
75          FT_FRAME_EXTRACT( length, bdf->table ) )
76     {
77       error = FT_Err_Invalid_Table;
78       goto Exit;
79     }
80 
81     bdf->table_end = bdf->table + length;
82 
83     {
84       FT_Byte*   p           = bdf->table;
85       FT_UInt    version     = FT_NEXT_USHORT( p );
86       FT_UInt    num_strikes = FT_NEXT_USHORT( p );
87       FT_UInt32  strings     = FT_NEXT_ULONG ( p );
88       FT_UInt    count;
89       FT_Byte*   strike;
90 
91 
92       if ( version != 0x0001                 ||
93            strings < 8                       ||
94            ( strings - 8 ) / 4 < num_strikes ||
95            strings + 1 > length              )
96       {
97         goto BadTable;
98       }
99 
100       bdf->num_strikes  = num_strikes;
101       bdf->strings      = bdf->table + strings;
102       bdf->strings_size = length - strings;
103 
104       count  = bdf->num_strikes;
105       p      = bdf->table + 8;
106       strike = p + count * 4;
107 
108 
109       for ( ; count > 0; count-- )
110       {
111         FT_UInt  num_items = FT_PEEK_USHORT( p + 2 );
112 
113         /*
114          *  We don't need to check the value sets themselves, since this
115          *  is done later.
116          */
117         strike += 10 * num_items;
118 
119         p += 4;
120       }
121 
122       if ( strike > bdf->strings )
123         goto BadTable;
124     }
125 
126     bdf->loaded = 1;
127 
128   Exit:
129     return error;
130 
131   BadTable:
132     FT_FRAME_RELEASE( bdf->table );
133     FT_ZERO( bdf );
134     error = FT_Err_Invalid_Table;
135     goto Exit;
136   }
137 
138 
139   FT_LOCAL_DEF( FT_Error )
tt_face_find_bdf_prop(TT_Face face,const char * property_name,BDF_PropertyRec * aprop)140   tt_face_find_bdf_prop( TT_Face           face,
141                          const char*       property_name,
142                          BDF_PropertyRec  *aprop )
143   {
144     TT_BDF    bdf   = &face->bdf;
145     FT_Size   size  = FT_FACE(face)->size;
146     FT_Error  error = 0;
147     FT_Byte*  p;
148     FT_UInt   count;
149     FT_Byte*  strike;
150     FT_UInt   property_len;
151 
152 
153     aprop->type = BDF_PROPERTY_TYPE_NONE;
154 
155     if ( bdf->loaded == 0 )
156     {
157       error = tt_face_load_bdf_props( face, FT_FACE( face )->stream );
158       if ( error )
159         goto Exit;
160     }
161 
162     count  = bdf->num_strikes;
163     p      = bdf->table + 8;
164     strike = p + 4 * count;
165 
166     error = FT_Err_Invalid_Argument;
167 
168     if ( size == NULL || property_name == NULL )
169       goto Exit;
170 
171     property_len = ft_strlen( property_name );
172     if ( property_len == 0 )
173       goto Exit;
174 
175     for ( ; count > 0; count-- )
176     {
177       FT_UInt  _ppem  = FT_NEXT_USHORT( p );
178       FT_UInt  _count = FT_NEXT_USHORT( p );
179 
180       if ( _ppem == size->metrics.y_ppem )
181       {
182         count = _count;
183         goto FoundStrike;
184       }
185 
186       strike += 10 * _count;
187     }
188     goto Exit;
189 
190   FoundStrike:
191     p = strike;
192     for ( ; count > 0; count-- )
193     {
194       FT_UInt  type = FT_PEEK_USHORT( p + 4 );
195 
196       if ( ( type & 0x10 ) != 0 )
197       {
198         FT_UInt32  name_offset = FT_PEEK_ULONG( p     );
199         FT_UInt32  value       = FT_PEEK_ULONG( p + 6 );
200 
201         /* be a bit paranoid for invalid entries here */
202         if ( name_offset < bdf->strings_size                    &&
203              property_len < bdf->strings_size - name_offset     &&
204              ft_strncmp( property_name,
205                          (const char*)bdf->strings + name_offset,
206                          bdf->strings_size - name_offset ) == 0 )
207         {
208           switch ( type & 0x0F )
209           {
210           case 0x00:  /* string */
211           case 0x01:  /* atoms */
212             /* check that the content is really 0-terminated */
213             if ( value < bdf->strings_size &&
214                  ft_memchr( bdf->strings + value, 0, bdf->strings_size ) )
215             {
216               aprop->type   = BDF_PROPERTY_TYPE_ATOM;
217               aprop->u.atom = (const char*)bdf->strings + value;
218               error         = 0;
219               goto Exit;
220             }
221             break;
222 
223           case 0x02:
224             aprop->type      = BDF_PROPERTY_TYPE_INTEGER;
225             aprop->u.integer = (FT_Int32)value;
226             error            = 0;
227             goto Exit;
228 
229           case 0x03:
230             aprop->type       = BDF_PROPERTY_TYPE_CARDINAL;
231             aprop->u.cardinal = value;
232             error             = 0;
233             goto Exit;
234 
235           default:
236             ;
237           }
238         }
239       }
240       p += 10;
241     }
242 
243   Exit:
244     return error;
245   }
246 
247 #endif /* TT_CONFIG_OPTION_BDF */
248 
249 
250 /* END */
251