1 /***************************************************************************/
2 /*                                                                         */
3 /*  otvgdef.c                                                              */
4 /*                                                                         */
5 /*    OpenType GDEF table validation (body).                               */
6 /*                                                                         */
7 /*  Copyright 2004, 2005, 2007 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 "otvalid.h"
20 #include "otvcommn.h"
21 
22 
23   /*************************************************************************/
24   /*                                                                       */
25   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
26   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
27   /* messages during execution.                                            */
28   /*                                                                       */
29 #undef  FT_COMPONENT
30 #define FT_COMPONENT  trace_otvgdef
31 
32 
33   /*************************************************************************/
34   /*************************************************************************/
35   /*****                                                               *****/
36   /*****                      UTILITY FUNCTIONS                        *****/
37   /*****                                                               *****/
38   /*************************************************************************/
39   /*************************************************************************/
40 
41 #define AttachListFunc    otv_O_x_Ox
42 #define LigCaretListFunc  otv_O_x_Ox
43 
44   /* sets valid->extra1 (0)           */
45 
46   static void
otv_O_x_Ox(FT_Bytes table,OTV_Validator valid)47   otv_O_x_Ox( FT_Bytes       table,
48               OTV_Validator  valid )
49   {
50     FT_Bytes           p = table;
51     FT_Bytes           Coverage;
52     FT_UInt            GlyphCount;
53     OTV_Validate_Func  func;
54 
55 
56     OTV_ENTER;
57 
58     OTV_LIMIT_CHECK( 4 );
59     Coverage   = table + FT_NEXT_USHORT( p );
60     GlyphCount = FT_NEXT_USHORT( p );
61 
62     OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
63 
64     otv_Coverage_validate( Coverage, valid, GlyphCount );
65     if ( GlyphCount != otv_Coverage_get_count( Coverage ) )
66       FT_INVALID_DATA;
67 
68     OTV_LIMIT_CHECK( GlyphCount * 2 );
69 
70     valid->nesting_level++;
71     func          = valid->func[valid->nesting_level];
72     valid->extra1 = 0;
73 
74     for ( ; GlyphCount > 0; GlyphCount-- )
75       func( table + FT_NEXT_USHORT( p ), valid );
76 
77     valid->nesting_level--;
78 
79     OTV_EXIT;
80   }
81 
82 
83   /*************************************************************************/
84   /*************************************************************************/
85   /*****                                                               *****/
86   /*****                       LIGATURE CARETS                         *****/
87   /*****                                                               *****/
88   /*************************************************************************/
89   /*************************************************************************/
90 
91 #define CaretValueFunc  otv_CaretValue_validate
92 
93   static void
otv_CaretValue_validate(FT_Bytes table,OTV_Validator valid)94   otv_CaretValue_validate( FT_Bytes       table,
95                            OTV_Validator  valid )
96   {
97     FT_Bytes  p = table;
98     FT_UInt   CaretValueFormat;
99 
100 
101     OTV_ENTER;
102 
103     OTV_LIMIT_CHECK( 4 );
104 
105     CaretValueFormat = FT_NEXT_USHORT( p );
106 
107     OTV_TRACE(( " (format = %d)\n", CaretValueFormat ));
108 
109     switch ( CaretValueFormat )
110     {
111     case 1:     /* CaretValueFormat1 */
112       /* skip Coordinate, no test */
113       break;
114 
115     case 2:     /* CaretValueFormat2 */
116       /* skip CaretValuePoint, no test */
117       break;
118 
119     case 3:     /* CaretValueFormat3 */
120       p += 2;   /* skip Coordinate */
121 
122       OTV_LIMIT_CHECK( 2 );
123 
124       /* DeviceTable */
125       otv_Device_validate( table + FT_NEXT_USHORT( p ), valid );
126       break;
127 
128     default:
129       FT_INVALID_FORMAT;
130     }
131 
132     OTV_EXIT;
133   }
134 
135 
136   /*************************************************************************/
137   /*************************************************************************/
138   /*****                                                               *****/
139   /*****                         GDEF TABLE                            *****/
140   /*****                                                               *****/
141   /*************************************************************************/
142   /*************************************************************************/
143 
144   /* sets valid->glyph_count */
145 
146   FT_LOCAL_DEF( void )
otv_GDEF_validate(FT_Bytes table,FT_Bytes gsub,FT_Bytes gpos,FT_UInt glyph_count,FT_Validator ftvalid)147   otv_GDEF_validate( FT_Bytes      table,
148                      FT_Bytes      gsub,
149                      FT_Bytes      gpos,
150                      FT_UInt       glyph_count,
151                      FT_Validator  ftvalid )
152   {
153     OTV_ValidatorRec  validrec;
154     OTV_Validator     valid = &validrec;
155     FT_Bytes          p     = table;
156     FT_UInt           table_size;
157     FT_Bool           need_MarkAttachClassDef;
158 
159     OTV_OPTIONAL_TABLE( GlyphClassDef );
160     OTV_OPTIONAL_TABLE( AttachListOffset );
161     OTV_OPTIONAL_TABLE( LigCaretListOffset );
162     OTV_OPTIONAL_TABLE( MarkAttachClassDef );
163 
164 
165     valid->root = ftvalid;
166 
167     FT_TRACE3(( "validating GDEF table\n" ));
168     OTV_INIT;
169 
170     OTV_LIMIT_CHECK( 12 );
171 
172     if ( FT_NEXT_ULONG( p ) != 0x10000UL )          /* Version */
173       FT_INVALID_FORMAT;
174 
175     /* MarkAttachClassDef has been added to the OpenType */
176     /* specification without increasing GDEF's version,  */
177     /* so we use this ugly hack to find out whether the  */
178     /* table is needed actually.                         */
179 
180     need_MarkAttachClassDef = FT_BOOL(
181       otv_GSUBGPOS_have_MarkAttachmentType_flag( gsub ) ||
182       otv_GSUBGPOS_have_MarkAttachmentType_flag( gpos ) );
183 
184     if ( need_MarkAttachClassDef )
185       table_size = 12;              /* OpenType >= 1.2 */
186     else
187       table_size = 10;              /* OpenType < 1.2  */
188 
189     valid->glyph_count = glyph_count;
190 
191     OTV_OPTIONAL_OFFSET( GlyphClassDef );
192     OTV_SIZE_CHECK( GlyphClassDef );
193     if ( GlyphClassDef )
194       otv_ClassDef_validate( table + GlyphClassDef, valid );
195 
196     OTV_OPTIONAL_OFFSET( AttachListOffset );
197     OTV_SIZE_CHECK( AttachListOffset );
198     if ( AttachListOffset )
199     {
200       OTV_NEST2( AttachList, AttachPoint );
201       OTV_RUN( table + AttachListOffset, valid );
202     }
203 
204     OTV_OPTIONAL_OFFSET( LigCaretListOffset );
205     OTV_SIZE_CHECK( LigCaretListOffset );
206     if ( LigCaretListOffset )
207     {
208       OTV_NEST3( LigCaretList, LigGlyph, CaretValue );
209       OTV_RUN( table + LigCaretListOffset, valid );
210     }
211 
212     if ( need_MarkAttachClassDef )
213     {
214       OTV_OPTIONAL_OFFSET( MarkAttachClassDef );
215       OTV_SIZE_CHECK( MarkAttachClassDef );
216       if ( MarkAttachClassDef )
217         otv_ClassDef_validate( table + MarkAttachClassDef, valid );
218     }
219 
220     FT_TRACE4(( "\n" ));
221   }
222 
223 
224 /* END */
225