1/****************************************************************************
2 *
3 * gxvmod.c
4 *
5 * FreeType's TrueTypeGX/AAT validation module implementation (body).
6 *
7 * Copyright (C) 2004-2023 by
8 * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
9 * David Turner, Robert Wilhelm, and Werner Lemberg.
10 *
11 * This file is part of the FreeType project, and may only be used,
12 * modified, and distributed under the terms of the FreeType project
13 * license, LICENSE.TXT. By continuing to use, modify, or distribute
14 * this file you indicate that you have read the license and
15 * understand and accept it fully.
16 *
17 */
18
19/****************************************************************************
20 *
21 * gxvalid is derived from both gxlayout module and otvalid module.
22 * Development of gxlayout is supported by the Information-technology
23 * Promotion Agency(IPA), Japan.
24 *
25 */
26
27
28#include <freetype/tttables.h>
29#include <freetype/tttags.h>
30#include <freetype/ftgxval.h>
31#include <freetype/internal/ftobjs.h>
32#include <freetype/internal/services/svgxval.h>
33
34#include "gxvmod.h"
35#include "gxvalid.h"
36#include "gxvcommn.h"
37
38
39 /**************************************************************************
40 *
41 * The macro FT_COMPONENT is used in trace mode. It is an implicit
42 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
43 * messages during execution.
44 */
45#undef FT_COMPONENT
46#define FT_COMPONENT gxvmodule
47
48
49 static FT_Error
50 gxv_load_table( FT_Face face,
51 FT_Tag tag,
52 FT_Byte* volatile* table,
53 FT_ULong* table_len )
54 {
55 FT_Error error;
56 FT_Memory memory = FT_FACE_MEMORY( face );
57
58
59 error = FT_Load_Sfnt_Table( face, tag, 0, NULL, table_len );
60 if ( FT_ERR_EQ( error, Table_Missing ) )
61 return FT_Err_Ok;
62 if ( error )
63 goto Exit;
64
65 if ( FT_QALLOC( *table, *table_len ) )
66 goto Exit;
67
68 error = FT_Load_Sfnt_Table( face, tag, 0, *table, table_len );
69
70 Exit:
71 return error;
72 }
73
74
75#define GXV_TABLE_DECL( _sfnt ) \
76 FT_Byte* volatile _sfnt = NULL; \
77 FT_ULong len_ ## _sfnt = 0
78
79#define GXV_TABLE_LOAD( _sfnt ) \
80 FT_BEGIN_STMNT \
81 if ( ( FT_VALIDATE_ ## _sfnt ## _INDEX < table_count ) && \
82 ( gx_flags & FT_VALIDATE_ ## _sfnt ) ) \
83 { \
84 error = gxv_load_table( face, TTAG_ ## _sfnt, \
85 &_sfnt, &len_ ## _sfnt ); \
86 if ( error ) \
87 goto Exit; \
88 } \
89 FT_END_STMNT
90
91#define GXV_TABLE_VALIDATE( _sfnt ) \
92 FT_BEGIN_STMNT \
93 if ( _sfnt ) \
94 { \
95 ft_validator_init( &valid, _sfnt, _sfnt + len_ ## _sfnt, \
96 FT_VALIDATE_DEFAULT ); \
97 if ( ft_setjmp( valid.jump_buffer ) == 0 ) \
98 gxv_ ## _sfnt ## _validate( _sfnt, face, &valid ); \
99 error = valid.error; \
100 if ( error ) \
101 goto Exit; \
102 } \
103 FT_END_STMNT
104
105#define GXV_TABLE_SET( _sfnt ) \
106 if ( FT_VALIDATE_ ## _sfnt ## _INDEX < table_count ) \
107 tables[FT_VALIDATE_ ## _sfnt ## _INDEX] = (FT_Bytes)_sfnt
108
109
110 static FT_Error
111 gxv_validate( FT_Face face,
112 FT_UInt gx_flags,
113 FT_Bytes tables[FT_VALIDATE_GX_LENGTH],
114 FT_UInt table_count )
115 {
116 FT_Memory volatile memory = FT_FACE_MEMORY( face );
117
118 FT_Error error = FT_Err_Ok;
119 FT_ValidatorRec volatile valid;
120
121 FT_UInt i;
122
123
124 GXV_TABLE_DECL( feat );
125 GXV_TABLE_DECL( bsln );
126 GXV_TABLE_DECL( trak );
127 GXV_TABLE_DECL( just );
128 GXV_TABLE_DECL( mort );
129 GXV_TABLE_DECL( morx );
130 GXV_TABLE_DECL( kern );
131 GXV_TABLE_DECL( opbd );
132 GXV_TABLE_DECL( prop );
133 GXV_TABLE_DECL( lcar );
134
135 for ( i = 0; i < table_count; i++ )
136 tables[i] = 0;
137
138 /* load tables */
139 GXV_TABLE_LOAD( feat );
140 GXV_TABLE_LOAD( bsln );
141 GXV_TABLE_LOAD( trak );
142 GXV_TABLE_LOAD( just );
143 GXV_TABLE_LOAD( mort );
144 GXV_TABLE_LOAD( morx );
145 GXV_TABLE_LOAD( kern );
146 GXV_TABLE_LOAD( opbd );
147 GXV_TABLE_LOAD( prop );
148 GXV_TABLE_LOAD( lcar );
149
150 /* validate tables */
151 GXV_TABLE_VALIDATE( feat );
152 GXV_TABLE_VALIDATE( bsln );
153 GXV_TABLE_VALIDATE( trak );
154 GXV_TABLE_VALIDATE( just );
155 GXV_TABLE_VALIDATE( mort );
156 GXV_TABLE_VALIDATE( morx );
157 GXV_TABLE_VALIDATE( kern );
158 GXV_TABLE_VALIDATE( opbd );
159 GXV_TABLE_VALIDATE( prop );
160 GXV_TABLE_VALIDATE( lcar );
161
162 /* Set results */
163 GXV_TABLE_SET( feat );
164 GXV_TABLE_SET( mort );
165 GXV_TABLE_SET( morx );
166 GXV_TABLE_SET( bsln );
167 GXV_TABLE_SET( just );
168 GXV_TABLE_SET( kern );
169 GXV_TABLE_SET( opbd );
170 GXV_TABLE_SET( trak );
171 GXV_TABLE_SET( prop );
172 GXV_TABLE_SET( lcar );
173
174 Exit:
175 if ( error )
176 {
177 FT_FREE( feat );
178 FT_FREE( bsln );
179 FT_FREE( trak );
180 FT_FREE( just );
181 FT_FREE( mort );
182 FT_FREE( morx );
183 FT_FREE( kern );
184 FT_FREE( opbd );
185 FT_FREE( prop );
186 FT_FREE( lcar );
187 }
188
189 return error;
190 }
191
192
193 static FT_Error
194 classic_kern_validate( FT_Face face,
195 FT_UInt ckern_flags,
196 FT_Bytes* ckern_table )
197 {
198 FT_Memory volatile memory = FT_FACE_MEMORY( face );
199
200 FT_Byte* volatile ckern = NULL;
201 FT_ULong len_ckern = 0;
202
203 /* without volatile on `error' GCC 4.1.1. emits: */
204 /* warning: variable 'error' might be clobbered by 'longjmp' or 'vfork' */
205 /* this warning seems spurious but --- */
206 FT_Error volatile error;
207 FT_ValidatorRec volatile valid;
208
209
210 *ckern_table = NULL;
211
212 error = gxv_load_table( face, TTAG_kern, &ckern, &len_ckern );
213 if ( error )
214 goto Exit;
215
216 if ( ckern )
217 {
218 ft_validator_init( &valid, ckern, ckern + len_ckern,
219 FT_VALIDATE_DEFAULT );
220 if ( ft_setjmp( valid.jump_buffer ) == 0 )
221 gxv_kern_validate_classic( ckern, face,
222 ckern_flags & FT_VALIDATE_CKERN, &valid );
223 error = valid.error;
224 if ( error )
225 goto Exit;
226 }
227
228 *ckern_table = ckern;
229
230 Exit:
231 if ( error )
232 FT_FREE( ckern );
233
234 return error;
235 }
236
237
238 static
239 const FT_Service_GXvalidateRec gxvalid_interface =
240 {
241 gxv_validate /* validate */
242 };
243
244
245 static
246 const FT_Service_CKERNvalidateRec ckernvalid_interface =
247 {
248 classic_kern_validate /* validate */
249 };
250
251
252 static
253 const FT_ServiceDescRec gxvalid_services[] =
254 {
255 { FT_SERVICE_ID_GX_VALIDATE, &gxvalid_interface },
256 { FT_SERVICE_ID_CLASSICKERN_VALIDATE, &ckernvalid_interface },
257 { NULL, NULL }
258 };
259
260
261 static FT_Pointer
262 gxvalid_get_service( FT_Module module,
263 const char* service_id )
264 {
265 FT_UNUSED( module );
266
267 return ft_service_list_lookup( gxvalid_services, service_id );
268 }
269
270
271 FT_CALLBACK_TABLE_DEF
272 const FT_Module_Class gxv_module_class =
273 {
274 0,
275 sizeof ( FT_ModuleRec ),
276 "gxvalid",
277 0x10000L,
278 0x20000L,
279
280 NULL, /* module-specific interface */
281
282 (FT_Module_Constructor)NULL, /* module_init */
283 (FT_Module_Destructor) NULL, /* module_done */
284 (FT_Module_Requester) gxvalid_get_service /* get_interface */
285 };
286
287
288/* END */
289