Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: third_party/freetype/src/truetype/ttgxvar.c

Issue 1413673003: Update bundled freetype to 2.6.1 (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: DEPS for corpus Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /***************************************************************************/ 1 /***************************************************************************/
2 /* */ 2 /* */
3 /* ttgxvar.c */ 3 /* ttgxvar.c */
4 /* */ 4 /* */
5 /* TrueType GX Font Variation loader */ 5 /* TrueType GX Font Variation loader */
6 /* */ 6 /* */
7 /* Copyright 2004-2014 by */ 7 /* Copyright 2004-2015 by */
8 /* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */ 8 /* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */
9 /* */ 9 /* */
10 /* This file is part of the FreeType project, and may only be used, */ 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 */ 11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */ 13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */ 14 /* understand and accept it fully. */
15 /* */ 15 /* */
16 /***************************************************************************/ 16 /***************************************************************************/
17 17
18 18
19 /*************************************************************************/ 19 /*************************************************************************/
20 /* */ 20 /* */
21 /* Apple documents the `fvar', `gvar', `cvar', and `avar' tables at */ 21 /* Apple documents the `fvar', `gvar', `cvar', and `avar' tables at */
22 /* */ 22 /* */
23 /* http://developer.apple.com/fonts/TTRefMan/RM06/Chap6[fgca]var.html */ 23 /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6[fg ca]var.html */
24 /* */ 24 /* */
25 /* The documentation for `fvar' is inconsistent. At one point it says */ 25 /* The documentation for `fvar' is inconsistent. At one point it says */
26 /* that `countSizePairs' should be 3, at another point 2. It should */ 26 /* that `countSizePairs' should be 3, at another point 2. It should */
27 /* be 2. */ 27 /* be 2. */
28 /* */ 28 /* */
29 /* The documentation for `gvar' is not intelligible; `cvar' refers you */ 29 /* The documentation for `gvar' is not intelligible; `cvar' refers you */
30 /* to `gvar' and is thus also incomprehensible. */ 30 /* to `gvar' and is thus also incomprehensible. */
31 /* */ 31 /* */
32 /* The documentation for `avar' appears correct, but Apple has no fonts */ 32 /* The documentation for `avar' appears correct, but Apple has no fonts */
33 /* with an `avar' table, so it is hard to test. */ 33 /* with an `avar' table, so it is hard to test. */
(...skipping 19 matching lines...) Expand all
53 53
54 #include "ttpload.h" 54 #include "ttpload.h"
55 #include "ttgxvar.h" 55 #include "ttgxvar.h"
56 56
57 #include "tterrors.h" 57 #include "tterrors.h"
58 58
59 59
60 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 60 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
61 61
62 62
63 #define FT_Stream_FTell( stream ) \ 63 #define FT_Stream_FTell( stream ) \
64 (FT_ULong)( (stream)->cursor - (stream)->base ) 64 (FT_ULong)( (stream)->cursor - (stream)->base )
65 #define FT_Stream_SeekSet( stream, off ) \ 65 #define FT_Stream_SeekSet( stream, off ) \
66 ( (stream)->cursor = (stream)->base + (off) ) 66 ( (stream)->cursor = (stream)->base + (off) )
67 67
68 68
69 /*************************************************************************/ 69 /*************************************************************************/
70 /* */ 70 /* */
71 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 71 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
72 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 72 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
73 /* messages during execution. */ 73 /* messages during execution. */
74 /* */ 74 /* */
75 #undef FT_COMPONENT 75 #undef FT_COMPONENT
(...skipping 13 matching lines...) Expand all
89 /* */ 89 /* */
90 /* The macro ALL_POINTS is used in `ft_var_readpackedpoints'. It */ 90 /* The macro ALL_POINTS is used in `ft_var_readpackedpoints'. It */
91 /* indicates that there is a delta for every point without needing to */ 91 /* indicates that there is a delta for every point without needing to */
92 /* enumerate all of them. */ 92 /* enumerate all of them. */
93 /* */ 93 /* */
94 94
95 /* ensure that value `0' has the same width as a pointer */ 95 /* ensure that value `0' has the same width as a pointer */
96 #define ALL_POINTS (FT_UShort*)~(FT_PtrDist)0 96 #define ALL_POINTS (FT_UShort*)~(FT_PtrDist)0
97 97
98 98
99 #define GX_PT_POINTS_ARE_WORDS 0x80 99 #define GX_PT_POINTS_ARE_WORDS 0x80U
100 #define GX_PT_POINT_RUN_COUNT_MASK 0x7F 100 #define GX_PT_POINT_RUN_COUNT_MASK 0x7FU
101 101
102 102
103 /*************************************************************************/ 103 /*************************************************************************/
104 /* */ 104 /* */
105 /* <Function> */ 105 /* <Function> */
106 /* ft_var_readpackedpoints */ 106 /* ft_var_readpackedpoints */
107 /* */ 107 /* */
108 /* <Description> */ 108 /* <Description> */
109 /* Read a set of points to which the following deltas will apply. */ 109 /* Read a set of points to which the following deltas will apply. */
110 /* Points are packed with a run length encoding. */ 110 /* Points are packed with a run length encoding. */
111 /* */ 111 /* */
112 /* <Input> */ 112 /* <Input> */
113 /* stream :: The data stream. */ 113 /* stream :: The data stream. */
114 /* */ 114 /* */
115 /* <Output> */ 115 /* <Output> */
116 /* point_cnt :: The number of points read. A zero value means that */ 116 /* point_cnt :: The number of points read. A zero value means that */
117 /* all points in the glyph will be affected, without */ 117 /* all points in the glyph will be affected, without */
118 /* enumerating them individually. */ 118 /* enumerating them individually. */
119 /* */ 119 /* */
120 /* <Return> */ 120 /* <Return> */
121 /* An array of FT_UShort containing the affected points or the */ 121 /* An array of FT_UShort containing the affected points or the */
122 /* special value ALL_POINTS. */ 122 /* special value ALL_POINTS. */
123 /* */ 123 /* */
124 static FT_UShort* 124 static FT_UShort*
125 ft_var_readpackedpoints( FT_Stream stream, 125 ft_var_readpackedpoints( FT_Stream stream,
126 FT_UInt *point_cnt ) 126 FT_UInt *point_cnt )
127 { 127 {
128 FT_UShort *points = NULL; 128 FT_UShort *points = NULL;
129 FT_Int n; 129 FT_UInt n;
130 FT_Int runcnt; 130 FT_UInt runcnt;
131 FT_Int i; 131 FT_UInt i, j;
132 FT_Int j; 132 FT_UShort first;
133 FT_Int first;
134 FT_Memory memory = stream->memory; 133 FT_Memory memory = stream->memory;
135 FT_Error error = FT_Err_Ok; 134 FT_Error error = FT_Err_Ok;
136 135
137 FT_UNUSED( error ); 136 FT_UNUSED( error );
138 137
139 138
140 *point_cnt = n = FT_GET_BYTE(); 139 *point_cnt = 0;
140
141 n = FT_GET_BYTE();
141 if ( n == 0 ) 142 if ( n == 0 )
142 return ALL_POINTS; 143 return ALL_POINTS;
143 144
144 if ( n & GX_PT_POINTS_ARE_WORDS ) 145 if ( n & GX_PT_POINTS_ARE_WORDS )
145 n = FT_GET_BYTE() | ( ( n & GX_PT_POINT_RUN_COUNT_MASK ) << 8 ); 146 {
147 n &= GX_PT_POINT_RUN_COUNT_MASK;
148 n <<= 8;
149 n |= FT_GET_BYTE();
150 }
146 151
147 if ( FT_NEW_ARRAY( points, n ) ) 152 if ( FT_NEW_ARRAY( points, n ) )
148 return NULL; 153 return NULL;
149 154
155 *point_cnt = n;
156
150 i = 0; 157 i = 0;
151 while ( i < n ) 158 while ( i < n )
152 { 159 {
153 runcnt = FT_GET_BYTE(); 160 runcnt = FT_GET_BYTE();
154 if ( runcnt & GX_PT_POINTS_ARE_WORDS ) 161 if ( runcnt & GX_PT_POINTS_ARE_WORDS )
155 { 162 {
156 runcnt = runcnt & GX_PT_POINT_RUN_COUNT_MASK; 163 runcnt &= GX_PT_POINT_RUN_COUNT_MASK;
157 first = points[i++] = FT_GET_USHORT(); 164 first = FT_GET_USHORT();
165 points[i++] = first;
158 166
159 if ( runcnt < 1 || i + runcnt >= n ) 167 if ( runcnt < 1 || i + runcnt > n )
160 goto Exit; 168 goto Exit;
161 169
162 /* first point not included in runcount */ 170 /* first point not included in run count */
163 for ( j = 0; j < runcnt; ++j ) 171 for ( j = 0; j < runcnt; j++ )
164 points[i++] = (FT_UShort)( first += FT_GET_USHORT() ); 172 {
173 first += FT_GET_USHORT();
174 points[i++] = first;
175 }
165 } 176 }
166 else 177 else
167 { 178 {
168 first = points[i++] = FT_GET_BYTE(); 179 first = FT_GET_BYTE();
180 points[i++] = first;
169 181
170 if ( runcnt < 1 || i + runcnt >= n ) 182 if ( runcnt < 1 || i + runcnt > n )
171 goto Exit; 183 goto Exit;
172 184
173 for ( j = 0; j < runcnt; ++j ) 185 for ( j = 0; j < runcnt; j++ )
174 points[i++] = (FT_UShort)( first += FT_GET_BYTE() ); 186 {
187 first += FT_GET_BYTE();
188 points[i++] = first;
189 }
175 } 190 }
176 } 191 }
177 192
178 Exit: 193 Exit:
179 return points; 194 return points;
180 } 195 }
181 196
182 197
183 enum 198 #define GX_DT_DELTAS_ARE_ZERO 0x80U
184 { 199 #define GX_DT_DELTAS_ARE_WORDS 0x40U
185 GX_DT_DELTAS_ARE_ZERO = 0x80, 200 #define GX_DT_DELTA_RUN_COUNT_MASK 0x3FU
186 GX_DT_DELTAS_ARE_WORDS = 0x40,
187 GX_DT_DELTA_RUN_COUNT_MASK = 0x3F
188 };
189 201
190 202
191 /*************************************************************************/ 203 /*************************************************************************/
192 /* */ 204 /* */
193 /* <Function> */ 205 /* <Function> */
194 /* ft_var_readpackeddeltas */ 206 /* ft_var_readpackeddeltas */
195 /* */ 207 /* */
196 /* <Description> */ 208 /* <Description> */
197 /* Read a set of deltas. These are packed slightly differently than */ 209 /* Read a set of deltas. These are packed slightly differently than */
198 /* points. In particular there is no overall count. */ 210 /* points. In particular there is no overall count. */
199 /* */ 211 /* */
200 /* <Input> */ 212 /* <Input> */
201 /* stream :: The data stream. */ 213 /* stream :: The data stream. */
202 /* */ 214 /* */
203 /* delta_cnt :: The number of to be read. */ 215 /* delta_cnt :: The number of deltas to be read. */
204 /* */ 216 /* */
205 /* <Return> */ 217 /* <Return> */
206 /* An array of FT_Short containing the deltas for the affected */ 218 /* An array of FT_Short containing the deltas for the affected */
207 /* points. (This only gets the deltas for one dimension. It will */ 219 /* points. (This only gets the deltas for one dimension. It will */
208 /* generally be called twice, once for x, once for y. When used in */ 220 /* generally be called twice, once for x, once for y. When used in */
209 /* cvt table, it will only be called once.) */ 221 /* cvt table, it will only be called once.) */
210 /* */ 222 /* */
211 static FT_Short* 223 static FT_Short*
212 ft_var_readpackeddeltas( FT_Stream stream, 224 ft_var_readpackeddeltas( FT_Stream stream,
213 FT_Offset delta_cnt ) 225 FT_UInt delta_cnt )
214 { 226 {
215 FT_Short *deltas = NULL; 227 FT_Short *deltas = NULL;
216 FT_UInt runcnt; 228 FT_UInt runcnt, cnt;
217 FT_Offset i; 229 FT_UInt i, j;
218 FT_UInt j;
219 FT_Memory memory = stream->memory; 230 FT_Memory memory = stream->memory;
220 FT_Error error = FT_Err_Ok; 231 FT_Error error = FT_Err_Ok;
221 232
222 FT_UNUSED( error ); 233 FT_UNUSED( error );
223 234
224 235
225 if ( FT_NEW_ARRAY( deltas, delta_cnt ) ) 236 if ( FT_NEW_ARRAY( deltas, delta_cnt ) )
226 return NULL; 237 return NULL;
227 238
228 i = 0; 239 i = 0;
229 while ( i < delta_cnt ) 240 while ( i < delta_cnt )
230 { 241 {
231 runcnt = FT_GET_BYTE(); 242 runcnt = FT_GET_BYTE();
243 cnt = runcnt & GX_DT_DELTA_RUN_COUNT_MASK;
244
232 if ( runcnt & GX_DT_DELTAS_ARE_ZERO ) 245 if ( runcnt & GX_DT_DELTAS_ARE_ZERO )
233 { 246 {
234 /* runcnt zeroes get added */ 247 /* `runcnt' zeroes get added */
235 for ( j = 0; 248 for ( j = 0; j <= cnt && i < delta_cnt; j++ )
236 j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
237 ++j )
238 deltas[i++] = 0; 249 deltas[i++] = 0;
239 } 250 }
240 else if ( runcnt & GX_DT_DELTAS_ARE_WORDS ) 251 else if ( runcnt & GX_DT_DELTAS_ARE_WORDS )
241 { 252 {
242 /* runcnt shorts from the stack */ 253 /* `runcnt' shorts from the stack */
243 for ( j = 0; 254 for ( j = 0; j <= cnt && i < delta_cnt; j++ )
244 j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
245 ++j )
246 deltas[i++] = FT_GET_SHORT(); 255 deltas[i++] = FT_GET_SHORT();
247 } 256 }
248 else 257 else
249 { 258 {
250 /* runcnt signed bytes from the stack */ 259 /* `runcnt' signed bytes from the stack */
251 for ( j = 0; 260 for ( j = 0; j <= cnt && i < delta_cnt; j++ )
252 j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
253 ++j )
254 deltas[i++] = FT_GET_CHAR(); 261 deltas[i++] = FT_GET_CHAR();
255 } 262 }
256 263
257 if ( j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) ) 264 if ( j <= cnt )
258 { 265 {
259 /* Bad format */ 266 /* bad format */
260 FT_FREE( deltas ); 267 FT_FREE( deltas );
261 return NULL; 268 return NULL;
262 } 269 }
263 } 270 }
264 271
265 return deltas; 272 return deltas;
266 } 273 }
267 274
268 275
269 /*************************************************************************/ 276 /*************************************************************************/
270 /* */ 277 /* */
271 /* <Function> */ 278 /* <Function> */
272 /* ft_var_load_avar */ 279 /* ft_var_load_avar */
273 /* */ 280 /* */
274 /* <Description> */ 281 /* <Description> */
275 /* Parse the `avar' table if present. It need not be, so we return */ 282 /* Parse the `avar' table if present. It need not be, so we return */
276 /* nothing. */ 283 /* nothing. */
277 /* */ 284 /* */
278 /* <InOut> */ 285 /* <InOut> */
279 /* face :: The font face. */ 286 /* face :: The font face. */
280 /* */ 287 /* */
281 static void 288 static void
282 ft_var_load_avar( TT_Face face ) 289 ft_var_load_avar( TT_Face face )
283 { 290 {
284 FT_Stream stream = FT_FACE_STREAM(face); 291 FT_Stream stream = FT_FACE_STREAM( face );
285 FT_Memory memory = stream->memory; 292 FT_Memory memory = stream->memory;
286 GX_Blend blend = face->blend; 293 GX_Blend blend = face->blend;
287 GX_AVarSegment segment; 294 GX_AVarSegment segment;
288 FT_Error error = FT_Err_Ok; 295 FT_Error error = FT_Err_Ok;
289 FT_ULong version; 296 FT_Long version;
290 FT_Long axisCount; 297 FT_Long axisCount;
291 FT_Int i, j; 298 FT_Int i, j;
292 FT_ULong table_len; 299 FT_ULong table_len;
293 300
294 FT_UNUSED( error ); 301 FT_UNUSED( error );
295 302
296 303
304 FT_TRACE2(( "AVAR " ));
305
297 blend->avar_checked = TRUE; 306 blend->avar_checked = TRUE;
298 if ( (error = face->goto_table( face, TTAG_avar, stream, &table_len )) != 0 ) 307 error = face->goto_table( face, TTAG_avar, stream, &table_len );
308 if ( error )
309 {
310 FT_TRACE2(( "is missing\n" ));
299 return; 311 return;
312 }
300 313
301 if ( FT_FRAME_ENTER( table_len ) ) 314 if ( FT_FRAME_ENTER( table_len ) )
302 return; 315 return;
303 316
304 version = FT_GET_LONG(); 317 version = FT_GET_LONG();
305 axisCount = FT_GET_LONG(); 318 axisCount = FT_GET_LONG();
306 319
307 if ( version != 0x00010000L || 320 if ( version != 0x00010000L )
308 axisCount != (FT_Long)blend->mmvar->num_axis ) 321 {
322 FT_TRACE2(( "bad table version\n" ));
309 goto Exit; 323 goto Exit;
324 }
325
326 FT_TRACE2(( "loaded\n" ));
327
328 if ( axisCount != (FT_Long)blend->mmvar->num_axis )
329 {
330 FT_TRACE2(( "ft_var_load_avar: number of axes in `avar' and `cvar'\n"
331 " table are different\n" ));
332 goto Exit;
333 }
310 334
311 if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) ) 335 if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) )
312 goto Exit; 336 goto Exit;
313 337
314 segment = &blend->avar_segment[0]; 338 segment = &blend->avar_segment[0];
315 for ( i = 0; i < axisCount; ++i, ++segment ) 339 for ( i = 0; i < axisCount; i++, segment++ )
316 { 340 {
341 FT_TRACE5(( " axis %d:\n", i ));
342
317 segment->pairCount = FT_GET_USHORT(); 343 segment->pairCount = FT_GET_USHORT();
318 if ( FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) ) 344 if ( FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) )
319 { 345 {
320 /* Failure. Free everything we have done so far. We must do */ 346 /* Failure. Free everything we have done so far. We must do */
321 /* it right now since loading the `avar' table is optional. */ 347 /* it right now since loading the `avar' table is optional. */
322 348
323 for ( j = i - 1; j >= 0; --j ) 349 for ( j = i - 1; j >= 0; j-- )
324 FT_FREE( blend->avar_segment[j].correspondence ); 350 FT_FREE( blend->avar_segment[j].correspondence );
325 351
326 FT_FREE( blend->avar_segment ); 352 FT_FREE( blend->avar_segment );
327 blend->avar_segment = NULL; 353 blend->avar_segment = NULL;
328 goto Exit; 354 goto Exit;
329 } 355 }
330 356
331 for ( j = 0; j < segment->pairCount; ++j ) 357 for ( j = 0; j < segment->pairCount; j++ )
332 { 358 {
333 segment->correspondence[j].fromCoord = 359 /* convert to Fixed */
334 FT_GET_SHORT() << 2; /* convert to Fixed */ 360 segment->correspondence[j].fromCoord = FT_GET_SHORT() * 4;
335 segment->correspondence[j].toCoord = 361 segment->correspondence[j].toCoord = FT_GET_SHORT() * 4;
336 FT_GET_SHORT()<<2; /* convert to Fixed */ 362
363 FT_TRACE5(( " mapping %.4f to %.4f\n",
364 segment->correspondence[j].fromCoord / 65536.0,
365 segment->correspondence[j].toCoord / 65536.0 ));
337 } 366 }
367
368 FT_TRACE5(( "\n" ));
338 } 369 }
339 370
340 Exit: 371 Exit:
341 FT_FRAME_EXIT(); 372 FT_FRAME_EXIT();
342 } 373 }
343 374
344 375
345 typedef struct GX_GVar_Head_ 376 typedef struct GX_GVar_Head_
346 { 377 {
347 FT_Long version; 378 FT_Long version;
348 FT_UShort axisCount; 379 FT_UShort axisCount;
349 FT_UShort globalCoordCount; 380 FT_UShort globalCoordCount;
350 FT_ULong offsetToCoord; 381 FT_ULong offsetToCoord;
351 FT_UShort glyphCount; 382 FT_UShort glyphCount;
352 FT_UShort flags; 383 FT_UShort flags;
353 FT_ULong offsetToData; 384 FT_ULong offsetToData;
354 385
355 } GX_GVar_Head; 386 } GX_GVar_Head;
356 387
357 388
358 /*************************************************************************/ 389 /*************************************************************************/
359 /* */ 390 /* */
360 /* <Function> */ 391 /* <Function> */
361 /* ft_var_load_gvar */ 392 /* ft_var_load_gvar */
362 /* */ 393 /* */
363 /* <Description> */ 394 /* <Description> */
364 /* Parses the `gvar' table if present. If `fvar' is there, `gvar' */ 395 /* Parse the `gvar' table if present. If `fvar' is there, `gvar' had */
365 /* had better be there too. */ 396 /* better be there too. */
366 /* */ 397 /* */
367 /* <InOut> */ 398 /* <InOut> */
368 /* face :: The font face. */ 399 /* face :: The font face. */
369 /* */ 400 /* */
370 /* <Return> */ 401 /* <Return> */
371 /* FreeType error code. 0 means success. */ 402 /* FreeType error code. 0 means success. */
372 /* */ 403 /* */
373 static FT_Error 404 static FT_Error
374 ft_var_load_gvar( TT_Face face ) 405 ft_var_load_gvar( TT_Face face )
375 { 406 {
376 FT_Stream stream = FT_FACE_STREAM(face); 407 FT_Stream stream = FT_FACE_STREAM( face );
377 FT_Memory memory = stream->memory; 408 FT_Memory memory = stream->memory;
378 GX_Blend blend = face->blend; 409 GX_Blend blend = face->blend;
379 FT_Error error; 410 FT_Error error;
380 FT_UInt i, j; 411 FT_UInt i, j;
381 FT_ULong table_len; 412 FT_ULong table_len;
382 FT_ULong gvar_start; 413 FT_ULong gvar_start;
383 FT_ULong offsetToData; 414 FT_ULong offsetToData;
384 GX_GVar_Head gvar_head; 415 GX_GVar_Head gvar_head;
385 416
386 static const FT_Frame_Field gvar_fields[] = 417 static const FT_Frame_Field gvar_fields[] =
387 { 418 {
388 419
389 #undef FT_STRUCTURE 420 #undef FT_STRUCTURE
390 #define FT_STRUCTURE GX_GVar_Head 421 #define FT_STRUCTURE GX_GVar_Head
391 422
392 FT_FRAME_START( 20 ), 423 FT_FRAME_START( 20 ),
393 FT_FRAME_LONG ( version ), 424 FT_FRAME_LONG ( version ),
394 FT_FRAME_USHORT( axisCount ), 425 FT_FRAME_USHORT( axisCount ),
395 FT_FRAME_USHORT( globalCoordCount ), 426 FT_FRAME_USHORT( globalCoordCount ),
396 FT_FRAME_ULONG ( offsetToCoord ), 427 FT_FRAME_ULONG ( offsetToCoord ),
397 FT_FRAME_USHORT( glyphCount ), 428 FT_FRAME_USHORT( glyphCount ),
398 FT_FRAME_USHORT( flags ), 429 FT_FRAME_USHORT( flags ),
399 FT_FRAME_ULONG ( offsetToData ), 430 FT_FRAME_ULONG ( offsetToData ),
400 FT_FRAME_END 431 FT_FRAME_END
401 }; 432 };
402 433
403 if ( (error = face->goto_table( face, TTAG_gvar, stream, &table_len )) != 0 ) 434
435 FT_TRACE2(( "GVAR " ));
436
437 if ( ( error = face->goto_table( face,
438 TTAG_gvar,
439 stream,
440 &table_len ) ) != 0 )
441 {
442 FT_TRACE2(( "is missing\n" ));
404 goto Exit; 443 goto Exit;
444 }
405 445
406 gvar_start = FT_STREAM_POS( ); 446 gvar_start = FT_STREAM_POS( );
407 if ( FT_STREAM_READ_FIELDS( gvar_fields, &gvar_head ) ) 447 if ( FT_STREAM_READ_FIELDS( gvar_fields, &gvar_head ) )
408 goto Exit; 448 goto Exit;
409 449
410 blend->tuplecount = gvar_head.globalCoordCount; 450 blend->tuplecount = gvar_head.globalCoordCount;
411 blend->gv_glyphcnt = gvar_head.glyphCount; 451 blend->gv_glyphcnt = gvar_head.glyphCount;
412 offsetToData = gvar_start + gvar_head.offsetToData; 452 offsetToData = gvar_start + gvar_head.offsetToData;
413 453
414 if ( gvar_head.version != (FT_Long)0x00010000L || 454 if ( gvar_head.version != 0x00010000L )
415 gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
416 { 455 {
456 FT_TRACE1(( "bad table version\n" ));
417 error = FT_THROW( Invalid_Table ); 457 error = FT_THROW( Invalid_Table );
418 goto Exit; 458 goto Exit;
419 } 459 }
420 460
461 FT_TRACE2(( "loaded\n" ));
462
463 if ( gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
464 {
465 FT_TRACE1(( "ft_var_load_gvar: number of axes in `gvar' and `cvar'\n"
466 " table are different\n" ));
467 error = FT_THROW( Invalid_Table );
468 goto Exit;
469 }
470
471 FT_TRACE5(( "gvar: there are %d shared coordinates:\n",
472 blend->tuplecount ));
473
421 if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) ) 474 if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) )
422 goto Exit; 475 goto Exit;
423 476
424 if ( gvar_head.flags & 1 ) 477 if ( gvar_head.flags & 1 )
425 { 478 {
426 /* long offsets (one more offset than glyphs, to mark size of last) */ 479 /* long offsets (one more offset than glyphs, to mark size of last) */
427 if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 4L ) ) 480 if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 4L ) )
428 goto Exit; 481 goto Exit;
429 482
430 for ( i = 0; i <= blend->gv_glyphcnt; ++i ) 483 for ( i = 0; i <= blend->gv_glyphcnt; i++ )
431 blend->glyphoffsets[i] = offsetToData + FT_GET_LONG(); 484 blend->glyphoffsets[i] = offsetToData + FT_GET_ULONG();
432 485
433 FT_FRAME_EXIT(); 486 FT_FRAME_EXIT();
434 } 487 }
435 else 488 else
436 { 489 {
437 /* short offsets (one more offset than glyphs, to mark size of last) */ 490 /* short offsets (one more offset than glyphs, to mark size of last) */
438 if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 2L ) ) 491 if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 2L ) )
439 goto Exit; 492 goto Exit;
440 493
441 for ( i = 0; i <= blend->gv_glyphcnt; ++i ) 494 for ( i = 0; i <= blend->gv_glyphcnt; i++ )
442 blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2; 495 blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2;
443 /* XXX: Undocumented: `*2'! */ 496 /* XXX: Undocumented: `*2'! */
444 497
445 FT_FRAME_EXIT(); 498 FT_FRAME_EXIT();
446 } 499 }
447 500
448 if ( blend->tuplecount != 0 ) 501 if ( blend->tuplecount != 0 )
449 { 502 {
450 if ( FT_NEW_ARRAY( blend->tuplecoords, 503 if ( FT_NEW_ARRAY( blend->tuplecoords,
451 gvar_head.axisCount * blend->tuplecount ) ) 504 gvar_head.axisCount * blend->tuplecount ) )
452 goto Exit; 505 goto Exit;
453 506
454 if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord ) || 507 if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord ) ||
455 FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L ) ) 508 FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L ) )
456 goto Exit; 509 goto Exit;
457 510
458 for ( i = 0; i < blend->tuplecount; ++i ) 511 for ( i = 0; i < blend->tuplecount; i++ )
459 for ( j = 0 ; j < (FT_UInt)gvar_head.axisCount; ++j ) 512 {
513 FT_TRACE5(( " [ " ));
514 for ( j = 0 ; j < (FT_UInt)gvar_head.axisCount; j++ )
515 {
460 blend->tuplecoords[i * gvar_head.axisCount + j] = 516 blend->tuplecoords[i * gvar_head.axisCount + j] =
461 FT_GET_SHORT() << 2; /* convert to FT_Fixed */ 517 FT_GET_SHORT() * 4; /* convert to FT_Fixed */
518 FT_TRACE5(( "%.4f ",
519 blend->tuplecoords[i * gvar_head.axisCount + j] / 65536.0 ));
520 }
521 FT_TRACE5(( "]\n" ));
522 }
523
524 FT_TRACE5(( "\n" ));
462 525
463 FT_FRAME_EXIT(); 526 FT_FRAME_EXIT();
464 } 527 }
465 528
466 Exit: 529 Exit:
467 return error; 530 return error;
468 } 531 }
469 532
470 533
471 /*************************************************************************/ 534 /*************************************************************************/
(...skipping 27 matching lines...) Expand all
499 ft_var_apply_tuple( GX_Blend blend, 562 ft_var_apply_tuple( GX_Blend blend,
500 FT_UShort tupleIndex, 563 FT_UShort tupleIndex,
501 FT_Fixed* tuple_coords, 564 FT_Fixed* tuple_coords,
502 FT_Fixed* im_start_coords, 565 FT_Fixed* im_start_coords,
503 FT_Fixed* im_end_coords ) 566 FT_Fixed* im_end_coords )
504 { 567 {
505 FT_UInt i; 568 FT_UInt i;
506 FT_Fixed apply = 0x10000L; 569 FT_Fixed apply = 0x10000L;
507 570
508 571
509 for ( i = 0; i < blend->num_axis; ++i ) 572 for ( i = 0; i < blend->num_axis; i++ )
510 { 573 {
574 FT_TRACE6(( " axis coordinate %d (%.4f):\n",
575 i, blend->normalizedcoords[i] / 65536.0 ));
576
577 /* It's not clear why (for intermediate tuples) we don't need */
578 /* to check against start/end -- the documentation says we don't. */
579 /* Similarly, it's unclear why we don't need to scale along the */
580 /* axis. */
581
511 if ( tuple_coords[i] == 0 ) 582 if ( tuple_coords[i] == 0 )
512 /* It's not clear why (for intermediate tuples) we don't need */ 583 {
513 /* to check against start/end -- the documentation says we don't. */ 584 FT_TRACE6(( " tuple coordinate is zero, ignored\n", i ));
514 /* Similarly, it's unclear why we don't need to scale along the */
515 /* axis. */
516 continue; 585 continue;
586 }
517 587
518 else if ( blend->normalizedcoords[i] == 0 || 588 else if ( blend->normalizedcoords[i] == 0 )
519 ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) || 589 {
590 FT_TRACE6(( " axis coordinate is zero, stop\n" ));
591 apply = 0;
592 break;
593 }
594
595 else if ( ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) ||
520 ( blend->normalizedcoords[i] > 0 && tuple_coords[i] < 0 ) ) 596 ( blend->normalizedcoords[i] > 0 && tuple_coords[i] < 0 ) )
521 { 597 {
598 FT_TRACE6(( " tuple coordinate value %.4f is exceeded, stop\n",
599 tuple_coords[i] / 65536.0 ));
522 apply = 0; 600 apply = 0;
523 break; 601 break;
524 } 602 }
525 603
526 else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) ) 604 else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
605 {
606 FT_TRACE6(( " tuple coordinate value %.4f fits\n",
607 tuple_coords[i] / 65536.0 ));
527 /* not an intermediate tuple */ 608 /* not an intermediate tuple */
528 apply = FT_MulFix( apply, 609 apply = FT_MulFix( apply,
529 blend->normalizedcoords[i] > 0 610 blend->normalizedcoords[i] > 0
530 ? blend->normalizedcoords[i] 611 ? blend->normalizedcoords[i]
531 : -blend->normalizedcoords[i] ); 612 : -blend->normalizedcoords[i] );
613 }
532 614
533 else if ( blend->normalizedcoords[i] <= im_start_coords[i] || 615 else if ( blend->normalizedcoords[i] < im_start_coords[i] ||
534 blend->normalizedcoords[i] >= im_end_coords[i] ) 616 blend->normalizedcoords[i] > im_end_coords[i] )
535 { 617 {
618 FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] is exceeded,"
619 " stop\n",
620 im_start_coords[i] / 65536.0,
621 im_end_coords[i] / 65536.0 ));
536 apply = 0; 622 apply = 0;
537 break; 623 break;
538 } 624 }
539 625
540 else if ( blend->normalizedcoords[i] < tuple_coords[i] ) 626 else if ( blend->normalizedcoords[i] < tuple_coords[i] )
627 {
628 FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] fits\n",
629 im_start_coords[i] / 65536.0,
630 im_end_coords[i] / 65536.0 ));
541 apply = FT_MulDiv( apply, 631 apply = FT_MulDiv( apply,
542 blend->normalizedcoords[i] - im_start_coords[i], 632 blend->normalizedcoords[i] - im_start_coords[i],
543 tuple_coords[i] - im_start_coords[i] ); 633 tuple_coords[i] - im_start_coords[i] );
634 }
544 635
545 else 636 else
637 {
638 FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] fits\n",
639 im_start_coords[i] / 65536.0,
640 im_end_coords[i] / 65536.0 ));
546 apply = FT_MulDiv( apply, 641 apply = FT_MulDiv( apply,
547 im_end_coords[i] - blend->normalizedcoords[i], 642 im_end_coords[i] - blend->normalizedcoords[i],
548 im_end_coords[i] - tuple_coords[i] ); 643 im_end_coords[i] - tuple_coords[i] );
644 }
549 } 645 }
550 646
647 FT_TRACE6(( " apply factor is %.4f\n", apply / 65536.0 ));
648
551 return apply; 649 return apply;
552 } 650 }
553 651
554 652
555 /*************************************************************************/ 653 /*************************************************************************/
556 /*************************************************************************/ 654 /*************************************************************************/
557 /***** *****/ 655 /***** *****/
558 /***** MULTIPLE MASTERS SERVICE FUNCTIONS *****/ 656 /***** MULTIPLE MASTERS SERVICE FUNCTIONS *****/
559 /***** *****/ 657 /***** *****/
560 /*************************************************************************/ 658 /*************************************************************************/
561 /*************************************************************************/ 659 /*************************************************************************/
562 660
563 661
564 typedef struct GX_FVar_Head_ 662 typedef struct GX_FVar_Head_
565 { 663 {
566 FT_Long version; 664 FT_Long version;
567 FT_UShort offsetToData; 665 FT_UShort offsetToData;
568 FT_UShort countSizePairs; 666 FT_UShort countSizePairs;
569 FT_UShort axisCount; 667 FT_UShort axisCount;
570 FT_UShort axisSize; 668 FT_UShort axisSize;
571 FT_UShort instanceCount; 669 FT_UShort instanceCount;
572 FT_UShort instanceSize; 670 FT_UShort instanceSize;
573 671
574 } GX_FVar_Head; 672 } GX_FVar_Head;
575 673
576 674
577 typedef struct fvar_axis_ 675 typedef struct fvar_axis_
578 { 676 {
579 FT_ULong axisTag; 677 FT_ULong axisTag;
580 FT_ULong minValue; 678 FT_Fixed minValue;
581 FT_ULong defaultValue; 679 FT_Fixed defaultValue;
582 FT_ULong maxValue; 680 FT_Fixed maxValue;
583 FT_UShort flags; 681 FT_UShort flags;
584 FT_UShort nameID; 682 FT_UShort nameID;
585 683
586 } GX_FVar_Axis; 684 } GX_FVar_Axis;
587 685
588 686
589 /*************************************************************************/ 687 /*************************************************************************/
590 /* */ 688 /* */
591 /* <Function> */ 689 /* <Function> */
592 /* TT_Get_MM_Var */ 690 /* TT_Get_MM_Var */
593 /* */ 691 /* */
594 /* <Description> */ 692 /* <Description> */
595 /* Check that the font's `fvar' table is valid, parse it, and return */ 693 /* Check that the font's `fvar' table is valid, parse it, and return */
596 /* those data. */ 694 /* those data. */
597 /* */ 695 /* */
598 /* <InOut> */ 696 /* <InOut> */
599 /* face :: The font face. */ 697 /* face :: The font face. */
600 /* TT_Get_MM_Var initializes the blend structure. */ 698 /* TT_Get_MM_Var initializes the blend structure. */
601 /* */ 699 /* */
602 /* <Output> */ 700 /* <Output> */
603 /* master :: The `fvar' data (must be freed by caller). */ 701 /* master :: The `fvar' data (must be freed by caller). Can be NULL, */
702 /* which makes this function simply load MM support. */
604 /* */ 703 /* */
605 /* <Return> */ 704 /* <Return> */
606 /* FreeType error code. 0 means success. */ 705 /* FreeType error code. 0 means success. */
607 /* */ 706 /* */
608 FT_LOCAL_DEF( FT_Error ) 707 FT_LOCAL_DEF( FT_Error )
609 TT_Get_MM_Var( TT_Face face, 708 TT_Get_MM_Var( TT_Face face,
610 FT_MM_Var* *master ) 709 FT_MM_Var* *master )
611 { 710 {
612 FT_Stream stream = face->root.stream; 711 FT_Stream stream = face->root.stream;
613 FT_Memory memory = face->root.memory; 712 FT_Memory memory = face->root.memory;
(...skipping 26 matching lines...) Expand all
640 }; 739 };
641 740
642 static const FT_Frame_Field fvaraxis_fields[] = 741 static const FT_Frame_Field fvaraxis_fields[] =
643 { 742 {
644 743
645 #undef FT_STRUCTURE 744 #undef FT_STRUCTURE
646 #define FT_STRUCTURE GX_FVar_Axis 745 #define FT_STRUCTURE GX_FVar_Axis
647 746
648 FT_FRAME_START( 20 ), 747 FT_FRAME_START( 20 ),
649 FT_FRAME_ULONG ( axisTag ), 748 FT_FRAME_ULONG ( axisTag ),
650 FT_FRAME_ULONG ( minValue ), 749 FT_FRAME_LONG ( minValue ),
651 FT_FRAME_ULONG ( defaultValue ), 750 FT_FRAME_LONG ( defaultValue ),
652 FT_FRAME_ULONG ( maxValue ), 751 FT_FRAME_LONG ( maxValue ),
653 FT_FRAME_USHORT( flags ), 752 FT_FRAME_USHORT( flags ),
654 FT_FRAME_USHORT( nameID ), 753 FT_FRAME_USHORT( nameID ),
655 FT_FRAME_END 754 FT_FRAME_END
656 }; 755 };
657 756
658 757
758 /* read the font data and set up the internal representation */
759 /* if not already done */
760
659 if ( face->blend == NULL ) 761 if ( face->blend == NULL )
660 { 762 {
763 FT_TRACE2(( "FVAR " ));
764
661 /* both `fvar' and `gvar' must be present */ 765 /* both `fvar' and `gvar' must be present */
662 if ( (error = face->goto_table( face, TTAG_gvar, 766 if ( ( error = face->goto_table( face, TTAG_gvar,
663 stream, &table_len )) != 0 ) 767 stream, &table_len ) ) != 0 )
768 {
769 FT_TRACE1(( "\n"
770 "TT_Get_MM_Var: `gvar' table is missing\n" ));
664 goto Exit; 771 goto Exit;
772 }
665 773
666 if ( (error = face->goto_table( face, TTAG_fvar, 774 if ( ( error = face->goto_table( face, TTAG_fvar,
667 stream, &table_len )) != 0 ) 775 stream, &table_len ) ) != 0 )
776 {
777 FT_TRACE1(( "is missing\n" ));
668 goto Exit; 778 goto Exit;
779 }
669 780
670 fvar_start = FT_STREAM_POS( ); 781 fvar_start = FT_STREAM_POS( );
671 782
672 if ( FT_STREAM_READ_FIELDS( fvar_fields, &fvar_head ) ) 783 if ( FT_STREAM_READ_FIELDS( fvar_fields, &fvar_head ) )
673 goto Exit; 784 goto Exit;
674 785
675 if ( fvar_head.version != (FT_Long)0x00010000L || 786 if ( fvar_head.version != (FT_Long)0x00010000L ||
787 #if 0
788 /* fonts like `JamRegular.ttf' have an incorrect value for */
789 /* `countSizePairs'; since value 2 is hard-coded in `fvar' */
790 /* version 1.0, we simply ignore it */
676 fvar_head.countSizePairs != 2 || 791 fvar_head.countSizePairs != 2 ||
792 #endif
677 fvar_head.axisSize != 20 || 793 fvar_head.axisSize != 20 ||
678 /* axisCount limit implied by 16-bit instanceSize */ 794 /* axisCount limit implied by 16-bit instanceSize */
679 fvar_head.axisCount > 0x3FFE || 795 fvar_head.axisCount > 0x3FFE ||
680 fvar_head.instanceSize != 4 + 4 * fvar_head.axisCount || 796 fvar_head.instanceSize != 4 + 4 * fvar_head.axisCount ||
681 /* instanceCount limit implied by limited range of name IDs */ 797 /* instanceCount limit implied by limited range of name IDs */
682 fvar_head.instanceCount > 0x7EFF || 798 fvar_head.instanceCount > 0x7EFF ||
683 fvar_head.offsetToData + fvar_head.axisCount * 20U + 799 fvar_head.offsetToData + fvar_head.axisCount * 20U +
684 fvar_head.instanceCount * fvar_head.instanceSize > table_len ) 800 fvar_head.instanceCount * fvar_head.instanceSize > table_len )
685 { 801 {
802 FT_TRACE1(( "\n"
803 "TT_Get_MM_Var: invalid `fvar' header\n" ));
686 error = FT_THROW( Invalid_Table ); 804 error = FT_THROW( Invalid_Table );
687 goto Exit; 805 goto Exit;
688 } 806 }
689 807
808 FT_TRACE2(( "loaded\n" ));
809
810 FT_TRACE5(( "number of GX style axes: %d\n", fvar_head.axisCount ));
811
690 if ( FT_NEW( face->blend ) ) 812 if ( FT_NEW( face->blend ) )
691 goto Exit; 813 goto Exit;
692 814
693 /* cannot overflow 32-bit arithmetic because of limits above */ 815 /* cannot overflow 32-bit arithmetic because of limits above */
694 face->blend->mmvar_len = 816 face->blend->mmvar_len =
695 sizeof ( FT_MM_Var ) + 817 sizeof ( FT_MM_Var ) +
696 fvar_head.axisCount * sizeof ( FT_Var_Axis ) + 818 fvar_head.axisCount * sizeof ( FT_Var_Axis ) +
697 fvar_head.instanceCount * sizeof ( FT_Var_Named_Style ) + 819 fvar_head.instanceCount * sizeof ( FT_Var_Named_Style ) +
698 fvar_head.instanceCount * fvar_head.axisCount * sizeof ( FT_Fixed ) + 820 fvar_head.instanceCount * fvar_head.axisCount * sizeof ( FT_Fixed ) +
699 5 * fvar_head.axisCount; 821 5 * fvar_head.axisCount;
700 822
701 if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) 823 if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) )
702 goto Exit; 824 goto Exit;
703 face->blend->mmvar = mmvar; 825 face->blend->mmvar = mmvar;
704 826
827 /* set up pointers and offsets into the `mmvar' array; */
828 /* the data gets filled in later on */
829
705 mmvar->num_axis = 830 mmvar->num_axis =
706 fvar_head.axisCount; 831 fvar_head.axisCount;
707 mmvar->num_designs = 832 mmvar->num_designs =
708 ~0U; /* meaningless in this context; each glyph */ 833 ~0U; /* meaningless in this context; each glyph */
709 /* may have a different number of designs */ 834 /* may have a different number of designs */
710 /* (or tuples, as called by Apple) */ 835 /* (or tuples, as called by Apple) */
711 mmvar->num_namedstyles = 836 mmvar->num_namedstyles =
712 fvar_head.instanceCount; 837 fvar_head.instanceCount;
713 mmvar->axis = 838 mmvar->axis =
714 (FT_Var_Axis*)&(mmvar[1]); 839 (FT_Var_Axis*)&( mmvar[1] );
715 mmvar->namedstyle = 840 mmvar->namedstyle =
716 (FT_Var_Named_Style*)&(mmvar->axis[fvar_head.axisCount]); 841 (FT_Var_Named_Style*)&( mmvar->axis[fvar_head.axisCount] );
717 842
718 next_coords = 843 next_coords =
719 (FT_Fixed*)&(mmvar->namedstyle[fvar_head.instanceCount]); 844 (FT_Fixed*)&( mmvar->namedstyle[fvar_head.instanceCount] );
720 for ( i = 0; i < fvar_head.instanceCount; ++i ) 845 for ( i = 0; i < fvar_head.instanceCount; i++ )
721 { 846 {
722 mmvar->namedstyle[i].coords = next_coords; 847 mmvar->namedstyle[i].coords = next_coords;
723 next_coords += fvar_head.axisCount; 848 next_coords += fvar_head.axisCount;
724 } 849 }
725 850
726 next_name = (FT_String*)next_coords; 851 next_name = (FT_String*)next_coords;
727 for ( i = 0; i < fvar_head.axisCount; ++i ) 852 for ( i = 0; i < fvar_head.axisCount; i++ )
728 { 853 {
729 mmvar->axis[i].name = next_name; 854 mmvar->axis[i].name = next_name;
730 next_name += 5; 855 next_name += 5;
731 } 856 }
732 857
858 /* now fill in the data */
859
733 if ( FT_STREAM_SEEK( fvar_start + fvar_head.offsetToData ) ) 860 if ( FT_STREAM_SEEK( fvar_start + fvar_head.offsetToData ) )
734 goto Exit; 861 goto Exit;
735 862
736 a = mmvar->axis; 863 a = mmvar->axis;
737 for ( i = 0; i < fvar_head.axisCount; ++i ) 864 for ( i = 0; i < fvar_head.axisCount; i++ )
738 { 865 {
739 GX_FVar_Axis axis_rec; 866 GX_FVar_Axis axis_rec;
740 867
741 868
742 if ( FT_STREAM_READ_FIELDS( fvaraxis_fields, &axis_rec ) ) 869 if ( FT_STREAM_READ_FIELDS( fvaraxis_fields, &axis_rec ) )
743 goto Exit; 870 goto Exit;
744 a->tag = axis_rec.axisTag; 871 a->tag = axis_rec.axisTag;
745 a->minimum = axis_rec.minValue; /* A Fixed */ 872 a->minimum = axis_rec.minValue;
746 a->def = axis_rec.defaultValue; /* A Fixed */ 873 a->def = axis_rec.defaultValue;
747 a->maximum = axis_rec.maxValue; /* A Fixed */ 874 a->maximum = axis_rec.maxValue;
748 a->strid = axis_rec.nameID; 875 a->strid = axis_rec.nameID;
749 876
750 a->name[0] = (FT_String)( a->tag >> 24 ); 877 a->name[0] = (FT_String)( a->tag >> 24 );
751 a->name[1] = (FT_String)( ( a->tag >> 16 ) & 0xFF ); 878 a->name[1] = (FT_String)( ( a->tag >> 16 ) & 0xFF );
752 a->name[2] = (FT_String)( ( a->tag >> 8 ) & 0xFF ); 879 a->name[2] = (FT_String)( ( a->tag >> 8 ) & 0xFF );
753 a->name[3] = (FT_String)( ( a->tag ) & 0xFF ); 880 a->name[3] = (FT_String)( ( a->tag ) & 0xFF );
754 a->name[4] = 0; 881 a->name[4] = '\0';
755 882
756 ++a; 883 FT_TRACE5(( " \"%s\": minimum=%.4f, default=%.4f, maximum=%.4f\n",
884 a->name,
885 a->minimum / 65536.0,
886 a->def / 65536.0,
887 a->maximum / 65536.0 ));
888
889 a++;
757 } 890 }
758 891
892 FT_TRACE5(( "\n" ));
893
759 ns = mmvar->namedstyle; 894 ns = mmvar->namedstyle;
760 for ( i = 0; i < fvar_head.instanceCount; ++i, ++ns ) 895 for ( i = 0; i < fvar_head.instanceCount; i++, ns++ )
761 { 896 {
762 if ( FT_FRAME_ENTER( 4L + 4L * fvar_head.axisCount ) ) 897 if ( FT_FRAME_ENTER( 4L + 4L * fvar_head.axisCount ) )
763 goto Exit; 898 goto Exit;
764 899
765 ns->strid = FT_GET_USHORT(); 900 ns->strid = FT_GET_USHORT();
766 (void) /* flags = */ FT_GET_USHORT(); 901 (void) /* flags = */ FT_GET_USHORT();
767 902
768 for ( j = 0; j < fvar_head.axisCount; ++j ) 903 for ( j = 0; j < fvar_head.axisCount; j++ )
769 ns->coords[j] = FT_GET_ULONG(); /* A Fixed */ 904 ns->coords[j] = FT_GET_LONG();
770 905
771 FT_FRAME_EXIT(); 906 FT_FRAME_EXIT();
772 } 907 }
773 } 908 }
774 909
910 /* fill the output array if requested */
911
775 if ( master != NULL ) 912 if ( master != NULL )
776 { 913 {
777 FT_UInt n; 914 FT_UInt n;
778 915
779 916
780 if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) 917 if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) )
781 goto Exit; 918 goto Exit;
782 FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len ); 919 FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len );
783 920
784 mmvar->axis = 921 mmvar->axis =
785 (FT_Var_Axis*)&(mmvar[1]); 922 (FT_Var_Axis*)&( mmvar[1] );
786 mmvar->namedstyle = 923 mmvar->namedstyle =
787 (FT_Var_Named_Style*)&(mmvar->axis[mmvar->num_axis]); 924 (FT_Var_Named_Style*)&( mmvar->axis[mmvar->num_axis] );
788 next_coords = 925 next_coords =
789 (FT_Fixed*)&(mmvar->namedstyle[mmvar->num_namedstyles]); 926 (FT_Fixed*)&( mmvar->namedstyle[mmvar->num_namedstyles] );
790 927
791 for ( n = 0; n < mmvar->num_namedstyles; ++n ) 928 for ( n = 0; n < mmvar->num_namedstyles; n++ )
792 { 929 {
793 mmvar->namedstyle[n].coords = next_coords; 930 mmvar->namedstyle[n].coords = next_coords;
794 next_coords += mmvar->num_axis; 931 next_coords += mmvar->num_axis;
795 } 932 }
796 933
797 a = mmvar->axis; 934 a = mmvar->axis;
798 next_name = (FT_String*)next_coords; 935 next_name = (FT_String*)next_coords;
799 for ( n = 0; n < mmvar->num_axis; ++n ) 936 for ( n = 0; n < mmvar->num_axis; n++ )
800 { 937 {
801 a->name = next_name; 938 a->name = next_name;
802 939
803 /* standard PostScript names for some standard apple tags */ 940 /* standard PostScript names for some standard apple tags */
804 if ( a->tag == TTAG_wght ) 941 if ( a->tag == TTAG_wght )
805 a->name = (char *)"Weight"; 942 a->name = (char*)"Weight";
806 else if ( a->tag == TTAG_wdth ) 943 else if ( a->tag == TTAG_wdth )
807 a->name = (char *)"Width"; 944 a->name = (char*)"Width";
808 else if ( a->tag == TTAG_opsz ) 945 else if ( a->tag == TTAG_opsz )
809 a->name = (char *)"OpticalSize"; 946 a->name = (char*)"OpticalSize";
810 else if ( a->tag == TTAG_slnt ) 947 else if ( a->tag == TTAG_slnt )
811 a->name = (char *)"Slant"; 948 a->name = (char*)"Slant";
812 949
813 next_name += 5; 950 next_name += 5;
814 ++a; 951 a++;
815 } 952 }
816 953
817 *master = mmvar; 954 *master = mmvar;
818 } 955 }
819 956
820 Exit: 957 Exit:
821 return error; 958 return error;
822 } 959 }
823 960
824 961
825 /*************************************************************************/ 962 /*************************************************************************/
826 /* */ 963 /* */
827 /* <Function> */ 964 /* <Function> */
828 /* TT_Set_MM_Blend */ 965 /* TT_Set_MM_Blend */
829 /* */ 966 /* */
830 /* <Description> */ 967 /* <Description> */
831 /* Set the blend (normalized) coordinates for this instance of the */ 968 /* Set the blend (normalized) coordinates for this instance of the */
832 /* font. Check that the `gvar' table is reasonable and does some */ 969 /* font. Check that the `gvar' table is reasonable and does some */
833 /* initial preparation. */ 970 /* initial preparation. */
834 /* */ 971 /* */
835 /* <InOut> */ 972 /* <InOut> */
836 /* face :: The font. */ 973 /* face :: The font. */
837 /* Initialize the blend structure with `gvar' data. */ 974 /* Initialize the blend structure with `gvar' data. */
838 /* */ 975 /* */
839 /* <Input> */ 976 /* <Input> */
840 /* num_coords :: Must be the axis count of the font. */ 977 /* num_coords :: The number of available coordinates. If it is */
978 /* larger than the number of axes, ignore the excess */
979 /* values. If it is smaller than the number of axes, */
980 /* use the default value (0) for the remaining axes. */
841 /* */ 981 /* */
842 /* coords :: An array of num_coords, each between [-1,1]. */ 982 /* coords :: An array of `num_coords', each between [-1,1]. */
843 /* */ 983 /* */
844 /* <Return> */ 984 /* <Return> */
845 /* FreeType error code. 0 means success. */ 985 /* FreeType error code. 0 means success. */
846 /* */ 986 /* */
847 FT_LOCAL_DEF( FT_Error ) 987 FT_LOCAL_DEF( FT_Error )
848 TT_Set_MM_Blend( TT_Face face, 988 TT_Set_MM_Blend( TT_Face face,
849 FT_UInt num_coords, 989 FT_UInt num_coords,
850 FT_Fixed* coords ) 990 FT_Fixed* coords )
851 { 991 {
852 FT_Error error = FT_Err_Ok; 992 FT_Error error = FT_Err_Ok;
853 GX_Blend blend; 993 GX_Blend blend;
854 FT_MM_Var* mmvar; 994 FT_MM_Var* mmvar;
855 FT_UInt i; 995 FT_UInt i;
856 FT_Memory memory = face->root.memory; 996 FT_Memory memory = face->root.memory;
857 997
858 enum 998 enum
859 { 999 {
860 mcvt_retain, 1000 mcvt_retain,
861 mcvt_modify, 1001 mcvt_modify,
862 mcvt_load 1002 mcvt_load
863 1003
864 } manageCvt; 1004 } manageCvt;
865 1005
866 1006
867 face->doblend = FALSE; 1007 face->doblend = FALSE;
868 1008
869 if ( face->blend == NULL ) 1009 if ( face->blend == NULL )
870 { 1010 {
871 if ( (error = TT_Get_MM_Var( face, NULL)) != 0 ) 1011 if ( ( error = TT_Get_MM_Var( face, NULL ) ) != 0 )
872 goto Exit; 1012 goto Exit;
873 } 1013 }
874 1014
875 blend = face->blend; 1015 blend = face->blend;
876 mmvar = blend->mmvar; 1016 mmvar = blend->mmvar;
877 1017
878 if ( num_coords != mmvar->num_axis ) 1018 if ( num_coords > mmvar->num_axis )
879 { 1019 {
880 error = FT_THROW( Invalid_Argument ); 1020 FT_TRACE2(( "TT_Set_MM_Blend: only using first %d of %d coordinates\n",
881 goto Exit; 1021 mmvar->num_axis, num_coords ));
1022 num_coords = mmvar->num_axis;
882 } 1023 }
883 1024
884 for ( i = 0; i < num_coords; ++i ) 1025 FT_TRACE5(( "normalized design coordinates:\n" ));
1026
1027 for ( i = 0; i < num_coords; i++ )
1028 {
1029 FT_TRACE5(( " %.4f\n", coords[i] / 65536.0 ));
885 if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L ) 1030 if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L )
886 { 1031 {
1032 FT_TRACE1(( "TT_Set_MM_Blend: normalized design coordinate %.4f\n"
1033 " is out of range [-1;1]\n",
1034 coords[i] / 65536.0 ));
887 error = FT_THROW( Invalid_Argument ); 1035 error = FT_THROW( Invalid_Argument );
888 goto Exit; 1036 goto Exit;
889 } 1037 }
1038 }
1039
1040 FT_TRACE5(( "\n" ));
890 1041
891 if ( blend->glyphoffsets == NULL ) 1042 if ( blend->glyphoffsets == NULL )
892 if ( (error = ft_var_load_gvar( face )) != 0 ) 1043 if ( ( error = ft_var_load_gvar( face ) ) != 0 )
893 goto Exit; 1044 goto Exit;
894 1045
895 if ( blend->normalizedcoords == NULL ) 1046 if ( blend->normalizedcoords == NULL )
896 { 1047 {
897 if ( FT_NEW_ARRAY( blend->normalizedcoords, num_coords ) ) 1048 if ( FT_NEW_ARRAY( blend->normalizedcoords, mmvar->num_axis ) )
898 goto Exit; 1049 goto Exit;
899 1050
900 manageCvt = mcvt_modify; 1051 manageCvt = mcvt_modify;
901 1052
902 /* If we have not set the blend coordinates before this, then the */ 1053 /* If we have not set the blend coordinates before this, then the */
903 /* cvt table will still be what we read from the `cvt ' table and */ 1054 /* cvt table will still be what we read from the `cvt ' table and */
904 /* we don't need to reload it. We may need to change it though... */ 1055 /* we don't need to reload it. We may need to change it though... */
905 } 1056 }
906 else 1057 else
907 { 1058 {
908 manageCvt = mcvt_retain; 1059 manageCvt = mcvt_retain;
909 for ( i = 0; i < num_coords; ++i ) 1060
1061 for ( i = 0; i < num_coords; i++ )
910 { 1062 {
911 if ( blend->normalizedcoords[i] != coords[i] ) 1063 if ( blend->normalizedcoords[i] != coords[i] )
912 { 1064 {
913 manageCvt = mcvt_load; 1065 manageCvt = mcvt_load;
914 break; 1066 break;
915 } 1067 }
916 } 1068 }
917 1069
1070 for ( ; i < mmvar->num_axis; i++ )
1071 {
1072 if ( blend->normalizedcoords[i] != 0 )
1073 {
1074 manageCvt = mcvt_load;
1075 break;
1076 }
1077 }
1078
918 /* If we don't change the blend coords then we don't need to do */ 1079 /* If we don't change the blend coords then we don't need to do */
919 /* anything to the cvt table. It will be correct. Otherwise we */ 1080 /* anything to the cvt table. It will be correct. Otherwise we */
920 /* no longer have the original cvt (it was modified when we set */ 1081 /* no longer have the original cvt (it was modified when we set */
921 /* the blend last time), so we must reload and then modify it. */ 1082 /* the blend last time), so we must reload and then modify it. */
922 } 1083 }
923 1084
924 blend->num_axis = num_coords; 1085 blend->num_axis = mmvar->num_axis;
925 FT_MEM_COPY( blend->normalizedcoords, 1086 FT_MEM_COPY( blend->normalizedcoords,
926 coords, 1087 coords,
927 num_coords * sizeof ( FT_Fixed ) ); 1088 num_coords * sizeof ( FT_Fixed ) );
928 1089
929 face->doblend = TRUE; 1090 face->doblend = TRUE;
930 1091
931 if ( face->cvt != NULL ) 1092 if ( face->cvt != NULL )
932 { 1093 {
933 switch ( manageCvt ) 1094 switch ( manageCvt )
934 { 1095 {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
966 /* <Description> */ 1127 /* <Description> */
967 /* Set the coordinates for the instance, measured in the user */ 1128 /* Set the coordinates for the instance, measured in the user */
968 /* coordinate system. Parse the `avar' table (if present) to convert */ 1129 /* coordinate system. Parse the `avar' table (if present) to convert */
969 /* from user to normalized coordinates. */ 1130 /* from user to normalized coordinates. */
970 /* */ 1131 /* */
971 /* <InOut> */ 1132 /* <InOut> */
972 /* face :: The font face. */ 1133 /* face :: The font face. */
973 /* Initialize the blend struct with `gvar' data. */ 1134 /* Initialize the blend struct with `gvar' data. */
974 /* */ 1135 /* */
975 /* <Input> */ 1136 /* <Input> */
976 /* num_coords :: This must be the axis count of the font. */ 1137 /* num_coords :: The number of available coordinates. If it is */
1138 /* larger than the number of axes, ignore the excess */
1139 /* values. If it is smaller than the number of axes, */
1140 /* use the default values for the remaining axes. */
977 /* */ 1141 /* */
978 /* coords :: A coordinate array with `num_coords' elements. */ 1142 /* coords :: A coordinate array with `num_coords' elements. */
979 /* */ 1143 /* */
980 /* <Return> */ 1144 /* <Return> */
981 /* FreeType error code. 0 means success. */ 1145 /* FreeType error code. 0 means success. */
982 /* */ 1146 /* */
983 FT_LOCAL_DEF( FT_Error ) 1147 FT_LOCAL_DEF( FT_Error )
984 TT_Set_Var_Design( TT_Face face, 1148 TT_Set_Var_Design( TT_Face face,
985 FT_UInt num_coords, 1149 FT_UInt num_coords,
986 FT_Fixed* coords ) 1150 FT_Fixed* coords )
987 { 1151 {
988 FT_Error error = FT_Err_Ok; 1152 FT_Error error = FT_Err_Ok;
989 FT_Fixed* normalized = NULL; 1153 FT_Fixed* normalized = NULL;
990 GX_Blend blend; 1154 GX_Blend blend;
991 FT_MM_Var* mmvar; 1155 FT_MM_Var* mmvar;
992 FT_UInt i, j; 1156 FT_UInt i, j;
993 FT_Var_Axis* a; 1157 FT_Var_Axis* a;
994 GX_AVarSegment av; 1158 GX_AVarSegment av;
995 FT_Memory memory = face->root.memory; 1159 FT_Memory memory = face->root.memory;
996 1160
997 1161
998 if ( face->blend == NULL ) 1162 if ( face->blend == NULL )
999 { 1163 {
1000 if ( (error = TT_Get_MM_Var( face, NULL )) != 0 ) 1164 if ( ( error = TT_Get_MM_Var( face, NULL ) ) != 0 )
1001 goto Exit; 1165 goto Exit;
1002 } 1166 }
1003 1167
1004 blend = face->blend; 1168 blend = face->blend;
1005 mmvar = blend->mmvar; 1169 mmvar = blend->mmvar;
1006 1170
1007 if ( num_coords != mmvar->num_axis ) 1171 if ( num_coords > mmvar->num_axis )
1008 { 1172 {
1009 error = FT_THROW( Invalid_Argument ); 1173 FT_TRACE2(( "TT_Set_Var_Design:"
1010 goto Exit; 1174 " only using first %d of %d coordinates\n",
1175 mmvar->num_axis, num_coords ));
1176 num_coords = mmvar->num_axis;
1011 } 1177 }
1012 1178
1013 /* Axis normalization is a two stage process. First we normalize */ 1179 /* Axis normalization is a two stage process. First we normalize */
1014 /* based on the [min,def,max] values for the axis to be [-1,0,1]. */ 1180 /* based on the [min,def,max] values for the axis to be [-1,0,1]. */
1015 /* Then, if there's an `avar' table, we renormalize this range. */ 1181 /* Then, if there's an `avar' table, we renormalize this range. */
1016 1182
1017 if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) ) 1183 if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) )
1018 goto Exit; 1184 goto Exit;
1019 1185
1186 FT_TRACE5(( "design coordinates:\n" ));
1187
1020 a = mmvar->axis; 1188 a = mmvar->axis;
1021 for ( i = 0; i < mmvar->num_axis; ++i, ++a ) 1189 for ( i = 0; i < num_coords; i++, a++ )
1022 { 1190 {
1191 FT_TRACE5(( " %.4f\n", coords[i] / 65536.0 ));
1023 if ( coords[i] > a->maximum || coords[i] < a->minimum ) 1192 if ( coords[i] > a->maximum || coords[i] < a->minimum )
1024 { 1193 {
1194 FT_TRACE1(( "TT_Set_Var_Design: normalized design coordinate %.4f\n"
1195 " is out of range [%.4f;%.4f]\n",
1196 coords[i] / 65536.0,
1197 a->minimum / 65536.0,
1198 a->maximum / 65536.0 ));
1025 error = FT_THROW( Invalid_Argument ); 1199 error = FT_THROW( Invalid_Argument );
1026 goto Exit; 1200 goto Exit;
1027 } 1201 }
1028 1202
1029 if ( coords[i] < a->def ) 1203 if ( coords[i] < a->def )
1030 normalized[i] = -FT_DivFix( coords[i] - a->def, a->minimum - a->def ); 1204 normalized[i] = -FT_DivFix( coords[i] - a->def,
1205 a->minimum - a->def );
1031 else if ( a->maximum == a->def ) 1206 else if ( a->maximum == a->def )
1032 normalized[i] = 0; 1207 normalized[i] = 0;
1033 else 1208 else
1034 normalized[i] = FT_DivFix( coords[i] - a->def, a->maximum - a->def ); 1209 normalized[i] = FT_DivFix( coords[i] - a->def,
1210 a->maximum - a->def );
1035 } 1211 }
1036 1212
1213 FT_TRACE5(( "\n" ));
1214
1215 for ( ; i < mmvar->num_axis; i++ )
1216 normalized[i] = 0;
1217
1037 if ( !blend->avar_checked ) 1218 if ( !blend->avar_checked )
1038 ft_var_load_avar( face ); 1219 ft_var_load_avar( face );
1039 1220
1040 if ( blend->avar_segment != NULL ) 1221 if ( blend->avar_segment != NULL )
1041 { 1222 {
1223 FT_TRACE5(( "normalized design coordinates"
1224 " before applying `avar' data:\n" ));
1225
1042 av = blend->avar_segment; 1226 av = blend->avar_segment;
1043 for ( i = 0; i < mmvar->num_axis; ++i, ++av ) 1227 for ( i = 0; i < mmvar->num_axis; i++, av++ )
1044 { 1228 {
1045 for ( j = 1; j < (FT_UInt)av->pairCount; ++j ) 1229 for ( j = 1; j < (FT_UInt)av->pairCount; j++ )
1230 {
1231 FT_TRACE5(( " %.4f\n", normalized[i] / 65536.0 ));
1046 if ( normalized[i] < av->correspondence[j].fromCoord ) 1232 if ( normalized[i] < av->correspondence[j].fromCoord )
1047 { 1233 {
1048 normalized[i] = 1234 normalized[i] =
1049 FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord, 1235 FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord,
1050 av->correspondence[j].toCoord - 1236 av->correspondence[j].toCoord -
1051 av->correspondence[j - 1].toCoord, 1237 av->correspondence[j - 1].toCoord,
1052 av->correspondence[j].fromCoord - 1238 av->correspondence[j].fromCoord -
1053 av->correspondence[j - 1].fromCoord ) + 1239 av->correspondence[j - 1].fromCoord ) +
1054 av->correspondence[j - 1].toCoord; 1240 av->correspondence[j - 1].toCoord;
1055 break; 1241 break;
1056 } 1242 }
1243 }
1057 } 1244 }
1058 } 1245 }
1059 1246
1060 error = TT_Set_MM_Blend( face, num_coords, normalized ); 1247 error = TT_Set_MM_Blend( face, mmvar->num_axis, normalized );
1061 1248
1062 Exit: 1249 Exit:
1063 FT_FREE( normalized ); 1250 FT_FREE( normalized );
1064 return error; 1251 return error;
1065 } 1252 }
1066 1253
1067 1254
1068 /*************************************************************************/ 1255 /*************************************************************************/
1069 /*************************************************************************/ 1256 /*************************************************************************/
1070 /***** *****/ 1257 /***** *****/
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1113 GX_Blend blend = face->blend; 1300 GX_Blend blend = face->blend;
1114 FT_UInt point_count; 1301 FT_UInt point_count;
1115 FT_UShort* localpoints; 1302 FT_UShort* localpoints;
1116 FT_Short* deltas; 1303 FT_Short* deltas;
1117 1304
1118 1305
1119 FT_TRACE2(( "CVAR " )); 1306 FT_TRACE2(( "CVAR " ));
1120 1307
1121 if ( blend == NULL ) 1308 if ( blend == NULL )
1122 { 1309 {
1123 FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" )); 1310 FT_TRACE2(( "\n"
1124 1311 "tt_face_vary_cvt: no blend specified\n" ));
1125 error = FT_Err_Ok; 1312 error = FT_Err_Ok;
1126 goto Exit; 1313 goto Exit;
1127 } 1314 }
1128 1315
1129 if ( face->cvt == NULL ) 1316 if ( face->cvt == NULL )
1130 { 1317 {
1131 FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" )); 1318 FT_TRACE2(( "\n"
1132 1319 "tt_face_vary_cvt: no `cvt ' table\n" ));
1133 error = FT_Err_Ok; 1320 error = FT_Err_Ok;
1134 goto Exit; 1321 goto Exit;
1135 } 1322 }
1136 1323
1137 error = face->goto_table( face, TTAG_cvar, stream, &table_len ); 1324 error = face->goto_table( face, TTAG_cvar, stream, &table_len );
1138 if ( error ) 1325 if ( error )
1139 { 1326 {
1140 FT_TRACE2(( "is missing\n" )); 1327 FT_TRACE2(( "is missing\n" ));
1141 1328
1142 error = FT_Err_Ok; 1329 error = FT_Err_Ok;
1143 goto Exit; 1330 goto Exit;
1144 } 1331 }
1145 1332
1146 if ( FT_FRAME_ENTER( table_len ) ) 1333 if ( FT_FRAME_ENTER( table_len ) )
1147 { 1334 {
1148 error = FT_Err_Ok; 1335 error = FT_Err_Ok;
1149 goto Exit; 1336 goto Exit;
1150 } 1337 }
1151 1338
1152 table_start = FT_Stream_FTell( stream ); 1339 table_start = FT_Stream_FTell( stream );
1153 if ( FT_GET_LONG() != 0x00010000L ) 1340 if ( FT_GET_LONG() != 0x00010000L )
1154 { 1341 {
1155 FT_TRACE2(( "bad table version\n" )); 1342 FT_TRACE2(( "bad table version\n" ));
1156 1343
1157 error = FT_Err_Ok; 1344 error = FT_Err_Ok;
1158 goto FExit; 1345 goto FExit;
1159 } 1346 }
1160 1347
1348 FT_TRACE2(( "loaded\n" ));
1349
1161 if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) || 1350 if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||
1162 FT_NEW_ARRAY( im_start_coords, blend->num_axis ) || 1351 FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
1163 FT_NEW_ARRAY( im_end_coords, blend->num_axis ) ) 1352 FT_NEW_ARRAY( im_end_coords, blend->num_axis ) )
1164 goto FExit; 1353 goto FExit;
1165 1354
1166 tupleCount = FT_GET_USHORT(); 1355 tupleCount = FT_GET_USHORT();
1167 offsetToData = table_start + FT_GET_USHORT(); 1356 offsetToData = table_start + FT_GET_USHORT();
1168 1357
1169 /* The documentation implies there are flags packed into the */ 1358 /* The documentation implies there are flags packed into the */
1170 /* tuplecount, but John Jenkins says that shared points don't apply */ 1359 /* tuplecount, but John Jenkins says that shared points don't apply */
1171 /* to `cvar', and no other flags are defined. */ 1360 /* to `cvar', and no other flags are defined. */
1172 1361
1173 for ( i = 0; i < ( tupleCount & 0xFFF ); ++i ) 1362 FT_TRACE5(( "cvar: there are %d tuples:\n", tupleCount ));
1363
1364 for ( i = 0; i < ( tupleCount & 0xFFF ); i++ )
1174 { 1365 {
1175 FT_UInt tupleDataSize; 1366 FT_UInt tupleDataSize;
1176 FT_UInt tupleIndex; 1367 FT_UInt tupleIndex;
1177 FT_Fixed apply; 1368 FT_Fixed apply;
1178 1369
1179 1370
1371 FT_TRACE6(( " tuple %d:\n", i ));
1372
1180 tupleDataSize = FT_GET_USHORT(); 1373 tupleDataSize = FT_GET_USHORT();
1181 tupleIndex = FT_GET_USHORT(); 1374 tupleIndex = FT_GET_USHORT();
1182 1375
1183 /* There is no provision here for a global tuple coordinate section, */ 1376 /* There is no provision here for a global tuple coordinate section, */
1184 /* so John says. There are no tuple indices, just embedded tuples. */ 1377 /* so John says. There are no tuple indices, just embedded tuples. */
1185 1378
1186 if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD ) 1379 if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
1187 { 1380 {
1188 for ( j = 0; j < blend->num_axis; ++j ) 1381 for ( j = 0; j < blend->num_axis; j++ )
1189 tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */ 1382 tuple_coords[j] = FT_GET_SHORT() * 4; /* convert from */
1190 /* short frac to fixed */ 1383 /* short frac to fixed */
1191 } 1384 }
1192 else 1385 else
1193 { 1386 {
1194 /* skip this tuple; it makes no sense */ 1387 /* skip this tuple; it makes no sense */
1195 1388
1196 if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) 1389 if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
1197 for ( j = 0; j < 2 * blend->num_axis; ++j ) 1390 for ( j = 0; j < 2 * blend->num_axis; j++ )
1198 (void)FT_GET_SHORT(); 1391 (void)FT_GET_SHORT();
1199 1392
1200 offsetToData += tupleDataSize; 1393 offsetToData += tupleDataSize;
1201 continue; 1394 continue;
1202 } 1395 }
1203 1396
1204 if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) 1397 if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
1205 { 1398 {
1206 for ( j = 0; j < blend->num_axis; ++j ) 1399 for ( j = 0; j < blend->num_axis; j++ )
1207 im_start_coords[j] = FT_GET_SHORT() << 2; 1400 im_start_coords[j] = FT_GET_SHORT() * 4;
1208 for ( j = 0; j < blend->num_axis; ++j ) 1401 for ( j = 0; j < blend->num_axis; j++ )
1209 im_end_coords[j] = FT_GET_SHORT() << 2; 1402 im_end_coords[j] = FT_GET_SHORT() * 4;
1210 } 1403 }
1211 1404
1212 apply = ft_var_apply_tuple( blend, 1405 apply = ft_var_apply_tuple( blend,
1213 (FT_UShort)tupleIndex, 1406 (FT_UShort)tupleIndex,
1214 tuple_coords, 1407 tuple_coords,
1215 im_start_coords, 1408 im_start_coords,
1216 im_end_coords ); 1409 im_end_coords );
1217 if ( /* tuple isn't active for our blend */ 1410 if ( /* tuple isn't active for our blend */
1218 apply == 0 || 1411 apply == 0 ||
1219 /* global points not allowed, */ 1412 /* global points not allowed, */
1220 /* if they aren't local, makes no sense */ 1413 /* if they aren't local, makes no sense */
1221 !( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) ) 1414 !( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) )
1222 { 1415 {
1223 offsetToData += tupleDataSize; 1416 offsetToData += tupleDataSize;
1224 continue; 1417 continue;
1225 } 1418 }
1226 1419
1227 here = FT_Stream_FTell( stream ); 1420 here = FT_Stream_FTell( stream );
1228 1421
1229 FT_Stream_SeekSet( stream, offsetToData ); 1422 FT_Stream_SeekSet( stream, offsetToData );
1230 1423
1231 localpoints = ft_var_readpackedpoints( stream, &point_count ); 1424 localpoints = ft_var_readpackedpoints( stream, &point_count );
1232 deltas = ft_var_readpackeddeltas( stream, 1425 deltas = ft_var_readpackeddeltas( stream,
1233 point_count == 0 ? face->cvt_size 1426 point_count == 0 ? face->cvt_size
1234 : point_count ); 1427 : point_count );
1235 if ( localpoints == NULL || deltas == NULL ) 1428 if ( localpoints == NULL || deltas == NULL )
1236 /* failure, ignore it */; 1429 ; /* failure, ignore it */
1237 1430
1238 else if ( localpoints == ALL_POINTS ) 1431 else if ( localpoints == ALL_POINTS )
1239 { 1432 {
1433 #ifdef FT_DEBUG_LEVEL_TRACE
1434 int count = 0;
1435 #endif
1436
1437
1438 FT_TRACE7(( " CVT deltas:\n" ));
1439
1240 /* this means that there are deltas for every entry in cvt */ 1440 /* this means that there are deltas for every entry in cvt */
1241 for ( j = 0; j < face->cvt_size; ++j ) 1441 for ( j = 0; j < face->cvt_size; j++ )
1242 face->cvt[j] = (FT_Short)( face->cvt[j] + 1442 {
1443 FT_Long orig_cvt = face->cvt[j];
1444
1445
1446 face->cvt[j] = (FT_Short)( orig_cvt +
1243 FT_MulFix( deltas[j], apply ) ); 1447 FT_MulFix( deltas[j], apply ) );
1448
1449 #ifdef FT_DEBUG_LEVEL_TRACE
1450 if ( orig_cvt != face->cvt[j] )
1451 {
1452 FT_TRACE7(( " %d: %d -> %d\n",
1453 j, orig_cvt, face->cvt[j] ));
1454 count++;
1455 }
1456 #endif
1457 }
1458
1459 #ifdef FT_DEBUG_LEVEL_TRACE
1460 if ( !count )
1461 FT_TRACE7(( " none\n" ));
1462 #endif
1244 } 1463 }
1245 1464
1246 else 1465 else
1247 { 1466 {
1248 for ( j = 0; j < point_count; ++j ) 1467 #ifdef FT_DEBUG_LEVEL_TRACE
1468 int count = 0;
1469 #endif
1470
1471
1472 FT_TRACE7(( " CVT deltas:\n" ));
1473
1474 for ( j = 0; j < point_count; j++ )
1249 { 1475 {
1250 int pindex = localpoints[j]; 1476 int pindex = localpoints[j];
1477 FT_Long orig_cvt = face->cvt[pindex];
1251 1478
1252 face->cvt[pindex] = (FT_Short)( face->cvt[pindex] + 1479
1480 face->cvt[pindex] = (FT_Short)( orig_cvt +
1253 FT_MulFix( deltas[j], apply ) ); 1481 FT_MulFix( deltas[j], apply ) );
1482
1483 #ifdef FT_DEBUG_LEVEL_TRACE
1484 if ( orig_cvt != face->cvt[pindex] )
1485 {
1486 FT_TRACE7(( " %d: %d -> %d\n",
1487 pindex, orig_cvt, face->cvt[pindex] ));
1488 count++;
1489 }
1490 #endif
1254 } 1491 }
1492
1493 #ifdef FT_DEBUG_LEVEL_TRACE
1494 if ( !count )
1495 FT_TRACE7(( " none\n" ));
1496 #endif
1255 } 1497 }
1256 1498
1257 if ( localpoints != ALL_POINTS ) 1499 if ( localpoints != ALL_POINTS )
1258 FT_FREE( localpoints ); 1500 FT_FREE( localpoints );
1259 FT_FREE( deltas ); 1501 FT_FREE( deltas );
1260 1502
1261 offsetToData += tupleDataSize; 1503 offsetToData += tupleDataSize;
1262 1504
1263 FT_Stream_SeekSet( stream, here ); 1505 FT_Stream_SeekSet( stream, here );
1264 } 1506 }
1265 1507
1508 FT_TRACE5(( "\n" ));
1509
1266 FExit: 1510 FExit:
1267 FT_FRAME_EXIT(); 1511 FT_FRAME_EXIT();
1268 1512
1269 Exit: 1513 Exit:
1270 FT_FREE( tuple_coords ); 1514 FT_FREE( tuple_coords );
1271 FT_FREE( im_start_coords ); 1515 FT_FREE( im_start_coords );
1272 FT_FREE( im_end_coords ); 1516 FT_FREE( im_end_coords );
1273 1517
1274 return error; 1518 return error;
1275 } 1519 }
1276 1520
1277 1521
1522 /* Shift the original coordinates of all points between indices `p1' */
1523 /* and `p2', using the same difference as given by index `ref'. */
1524
1525 /* modeled after `af_iup_shift' */
1526
1527 static void
1528 tt_delta_shift( int p1,
1529 int p2,
1530 int ref,
1531 FT_Vector* in_points,
1532 FT_Vector* out_points )
1533 {
1534 int p;
1535 FT_Vector delta;
1536
1537
1538 delta.x = out_points[ref].x - in_points[ref].x;
1539 delta.y = out_points[ref].y - in_points[ref].y;
1540
1541 if ( delta.x == 0 && delta.y == 0 )
1542 return;
1543
1544 for ( p = p1; p < ref; p++ )
1545 {
1546 out_points[p].x += delta.x;
1547 out_points[p].y += delta.y;
1548 }
1549
1550 for ( p = ref + 1; p <= p2; p++ )
1551 {
1552 out_points[p].x += delta.x;
1553 out_points[p].y += delta.y;
1554 }
1555 }
1556
1557
1558 /* Interpolate the original coordinates of all points with indices */
1559 /* between `p1' and `p2', using `ref1' and `ref2' as the reference */
1560 /* point indices. */
1561
1562 /* modeled after `af_iup_interp', `_iup_worker_interpolate', and */
1563 /* `Ins_IUP' */
1564
1565 static void
1566 tt_delta_interpolate( int p1,
1567 int p2,
1568 int ref1,
1569 int ref2,
1570 FT_Vector* in_points,
1571 FT_Vector* out_points )
1572 {
1573 int p, i;
1574
1575 FT_Pos out, in1, in2, out1, out2, d1, d2;
1576
1577
1578 if ( p1 > p2 )
1579 return;
1580
1581 /* handle both horizontal and vertical coordinates */
1582 for ( i = 0; i <= 1; i++ )
1583 {
1584 /* shift array pointers so that we can access `foo.y' as `foo.x' */
1585 in_points = (FT_Vector*)( (FT_Pos*)in_points + i );
1586 out_points = (FT_Vector*)( (FT_Pos*)out_points + i );
1587
1588 if ( in_points[ref1].x > in_points[ref2].x )
1589 {
1590 p = ref1;
1591 ref1 = ref2;
1592 ref2 = p;
1593 }
1594
1595 in1 = in_points[ref1].x;
1596 in2 = in_points[ref2].x;
1597 out1 = out_points[ref1].x;
1598 out2 = out_points[ref2].x;
1599 d1 = out1 - in1;
1600 d2 = out2 - in2;
1601
1602 if ( out1 == out2 || in1 == in2 )
1603 {
1604 for ( p = p1; p <= p2; p++ )
1605 {
1606 out = in_points[p].x;
1607
1608 if ( out <= in1 )
1609 out += d1;
1610 else if ( out >= in2 )
1611 out += d2;
1612 else
1613 out = out1;
1614
1615 out_points[p].x = out;
1616 }
1617 }
1618 else
1619 {
1620 FT_Fixed scale = FT_DivFix( out2 - out1, in2 - in1 );
1621
1622
1623 for ( p = p1; p <= p2; p++ )
1624 {
1625 out = in_points[p].x;
1626
1627 if ( out <= in1 )
1628 out += d1;
1629 else if ( out >= in2 )
1630 out += d2;
1631 else
1632 out = out1 + FT_MulFix( out - in1, scale );
1633
1634 out_points[p].x = out;
1635 }
1636 }
1637 }
1638 }
1639
1640
1641 /* Interpolate points without delta values, similar to */
1642 /* the `IUP' hinting instruction. */
1643
1644 /* modeled after `Ins_IUP */
1645
1646 static void
1647 tt_handle_deltas( FT_Outline* outline,
1648 FT_Vector* in_points,
1649 FT_Bool* has_delta )
1650 {
1651 FT_Vector* out_points;
1652
1653 FT_Int first_point;
1654 FT_Int end_point;
1655
1656 FT_Int first_delta;
1657 FT_Int cur_delta;
1658
1659 FT_Int point;
1660 FT_Short contour;
1661
1662
1663 /* ignore empty outlines */
1664 if ( !outline->n_contours )
1665 return;
1666
1667 out_points = outline->points;
1668
1669 contour = 0;
1670 point = 0;
1671
1672 do
1673 {
1674 end_point = outline->contours[contour];
1675 first_point = point;
1676
1677 /* search first point that has a delta */
1678 while ( point <= end_point && !has_delta[point] )
1679 point++;
1680
1681 if ( point <= end_point )
1682 {
1683 first_delta = point;
1684 cur_delta = point;
1685
1686 point++;
1687
1688 while ( point <= end_point )
1689 {
1690 /* search next point that has a delta */
1691 /* and interpolate intermediate points */
1692 if ( has_delta[point] )
1693 {
1694 tt_delta_interpolate( cur_delta + 1,
1695 point - 1,
1696 cur_delta,
1697 point,
1698 in_points,
1699 out_points );
1700 cur_delta = point;
1701 }
1702
1703 point++;
1704 }
1705
1706 /* shift contour if we only have a single delta */
1707 if ( cur_delta == first_delta )
1708 tt_delta_shift( first_point,
1709 end_point,
1710 cur_delta,
1711 in_points,
1712 out_points );
1713 else
1714 {
1715 /* otherwise handle remaining points */
1716 /* at the end and beginning of the contour */
1717 tt_delta_interpolate( cur_delta + 1,
1718 end_point,
1719 cur_delta,
1720 first_delta,
1721 in_points,
1722 out_points );
1723
1724 if ( first_delta > 0 )
1725 tt_delta_interpolate( first_point,
1726 first_delta - 1,
1727 cur_delta,
1728 first_delta,
1729 in_points,
1730 out_points );
1731 }
1732 }
1733 contour++;
1734
1735 } while ( contour < outline->n_contours );
1736 }
1737
1738
1278 /*************************************************************************/ 1739 /*************************************************************************/
1279 /* */ 1740 /* */
1280 /* <Function> */ 1741 /* <Function> */
1281 /* TT_Vary_Get_Glyph_Deltas */ 1742 /* TT_Vary_Apply_Glyph_Deltas */
1282 /* */ 1743 /* */
1283 /* <Description> */ 1744 /* <Description> */
1284 /* Load the appropriate deltas for the current glyph. */ 1745 /* Apply the appropriate deltas to the current glyph. */
1285 /* */ 1746 /* */
1286 /* <Input> */ 1747 /* <Input> */
1287 /* face :: A handle to the target face object. */ 1748 /* face :: A handle to the target face object. */
1288 /* */ 1749 /* */
1289 /* glyph_index :: The index of the glyph being modified. */ 1750 /* glyph_index :: The index of the glyph being modified. */
1290 /* */ 1751 /* */
1291 /* n_points :: The number of the points in the glyph, including */ 1752 /* n_points :: The number of the points in the glyph, including */
1292 /* phantom points. */ 1753 /* phantom points. */
1293 /* */ 1754 /* */
1294 /* <Output> */ 1755 /* <InOut> */
1295 /* deltas :: The array of points to change. */ 1756 /* outline :: The outline to change. */
1296 /* */ 1757 /* */
1297 /* <Return> */ 1758 /* <Return> */
1298 /* FreeType error code. 0 means success. */ 1759 /* FreeType error code. 0 means success. */
1299 /* */ 1760 /* */
1300 FT_LOCAL_DEF( FT_Error ) 1761 FT_LOCAL_DEF( FT_Error )
1301 TT_Vary_Get_Glyph_Deltas( TT_Face face, 1762 TT_Vary_Apply_Glyph_Deltas( TT_Face face,
1302 FT_UInt glyph_index, 1763 FT_UInt glyph_index,
1303 FT_Vector* *deltas, 1764 FT_Outline* outline,
1304 FT_UInt n_points ) 1765 FT_UInt n_points )
1305 { 1766 {
1306 FT_Stream stream = face->root.stream; 1767 FT_Stream stream = face->root.stream;
1307 FT_Memory memory = stream->memory; 1768 FT_Memory memory = stream->memory;
1308 GX_Blend blend = face->blend; 1769 GX_Blend blend = face->blend;
1309 FT_Vector* delta_xy = NULL; 1770
1771 FT_Vector* points_org = NULL;
1772 FT_Bool* has_delta = NULL;
1310 1773
1311 FT_Error error; 1774 FT_Error error;
1312 FT_ULong glyph_start; 1775 FT_ULong glyph_start;
1313 FT_UInt tupleCount; 1776 FT_UInt tupleCount;
1314 FT_ULong offsetToData; 1777 FT_ULong offsetToData;
1315 FT_ULong here; 1778 FT_ULong here;
1316 FT_UInt i, j; 1779 FT_UInt i, j;
1317 FT_Fixed* tuple_coords = NULL; 1780 FT_Fixed* tuple_coords = NULL;
1318 FT_Fixed* im_start_coords = NULL; 1781 FT_Fixed* im_start_coords = NULL;
1319 FT_Fixed* im_end_coords = NULL; 1782 FT_Fixed* im_end_coords = NULL;
1320 FT_UInt point_count, spoint_count = 0; 1783 FT_UInt point_count, spoint_count = 0;
1321 FT_UShort* sharedpoints = NULL; 1784 FT_UShort* sharedpoints = NULL;
1322 FT_UShort* localpoints = NULL; 1785 FT_UShort* localpoints = NULL;
1323 FT_UShort* points; 1786 FT_UShort* points;
1324 FT_Short *deltas_x, *deltas_y; 1787 FT_Short *deltas_x, *deltas_y;
1325 1788
1326 1789
1327 if ( !face->doblend || blend == NULL ) 1790 if ( !face->doblend || blend == NULL )
1328 return FT_THROW( Invalid_Argument ); 1791 return FT_THROW( Invalid_Argument );
1329 1792
1330 /* to be freed by the caller */
1331 if ( FT_NEW_ARRAY( delta_xy, n_points ) )
1332 goto Exit;
1333 *deltas = delta_xy;
1334
1335 if ( glyph_index >= blend->gv_glyphcnt || 1793 if ( glyph_index >= blend->gv_glyphcnt ||
1336 blend->glyphoffsets[glyph_index] == 1794 blend->glyphoffsets[glyph_index] ==
1337 blend->glyphoffsets[glyph_index + 1] ) 1795 blend->glyphoffsets[glyph_index + 1] )
1338 return FT_Err_Ok; /* no variation data for this glyph */ 1796 {
1797 FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
1798 " no variation data for this glyph\n" ));
1799 return FT_Err_Ok;
1800 }
1801
1802 if ( FT_NEW_ARRAY( points_org, n_points ) ||
1803 FT_NEW_ARRAY( has_delta, n_points ) )
1804 goto Fail1;
1339 1805
1340 if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) || 1806 if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) ||
1341 FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] - 1807 FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] -
1342 blend->glyphoffsets[glyph_index] ) ) 1808 blend->glyphoffsets[glyph_index] ) )
1343 goto Fail1; 1809 goto Fail1;
1344 1810
1345 glyph_start = FT_Stream_FTell( stream ); 1811 glyph_start = FT_Stream_FTell( stream );
1346 1812
1347 /* each set of glyph variation data is formatted similarly to `cvar' */ 1813 /* each set of glyph variation data is formatted similarly to `cvar' */
1348 /* (except we get shared points and global tuples) */ 1814 /* (except we get shared points and global tuples) */
(...skipping 11 matching lines...) Expand all
1360 here = FT_Stream_FTell( stream ); 1826 here = FT_Stream_FTell( stream );
1361 1827
1362 FT_Stream_SeekSet( stream, offsetToData ); 1828 FT_Stream_SeekSet( stream, offsetToData );
1363 1829
1364 sharedpoints = ft_var_readpackedpoints( stream, &spoint_count ); 1830 sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
1365 offsetToData = FT_Stream_FTell( stream ); 1831 offsetToData = FT_Stream_FTell( stream );
1366 1832
1367 FT_Stream_SeekSet( stream, here ); 1833 FT_Stream_SeekSet( stream, here );
1368 } 1834 }
1369 1835
1370 for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); ++i ) 1836 FT_TRACE5(( "gvar: there are %d tuples:\n", tupleCount ));
1837
1838 for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ )
1371 { 1839 {
1372 FT_UInt tupleDataSize; 1840 FT_UInt tupleDataSize;
1373 FT_UInt tupleIndex; 1841 FT_UInt tupleIndex;
1374 FT_Fixed apply; 1842 FT_Fixed apply;
1375 1843
1376 1844
1845 FT_TRACE6(( " tuple %d:\n", i ));
1846
1377 tupleDataSize = FT_GET_USHORT(); 1847 tupleDataSize = FT_GET_USHORT();
1378 tupleIndex = FT_GET_USHORT(); 1848 tupleIndex = FT_GET_USHORT();
1379 1849
1380 if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD ) 1850 if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
1381 { 1851 {
1382 for ( j = 0; j < blend->num_axis; ++j ) 1852 for ( j = 0; j < blend->num_axis; j++ )
1383 tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */ 1853 tuple_coords[j] = FT_GET_SHORT() * 4; /* convert from */
1384 /* short frac to fixed */ 1854 /* short frac to fixed */
1385 } 1855 }
1386 else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount ) 1856 else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
1387 { 1857 {
1388 error = FT_THROW( Invalid_Table ); 1858 error = FT_THROW( Invalid_Table );
1389 goto Fail3; 1859 goto Fail2;
1390 } 1860 }
1391 else 1861 else
1392 {
1393 FT_MEM_COPY( 1862 FT_MEM_COPY(
1394 tuple_coords, 1863 tuple_coords,
1395 &blend->tuplecoords[(tupleIndex & 0xFFF) * blend->num_axis], 1864 &blend->tuplecoords[( tupleIndex & 0xFFF ) * blend->num_axis],
1396 blend->num_axis * sizeof ( FT_Fixed ) ); 1865 blend->num_axis * sizeof ( FT_Fixed ) );
1397 }
1398 1866
1399 if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) 1867 if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
1400 { 1868 {
1401 for ( j = 0; j < blend->num_axis; ++j ) 1869 for ( j = 0; j < blend->num_axis; j++ )
1402 im_start_coords[j] = FT_GET_SHORT() << 2; 1870 im_start_coords[j] = FT_GET_SHORT() * 4;
1403 for ( j = 0; j < blend->num_axis; ++j ) 1871 for ( j = 0; j < blend->num_axis; j++ )
1404 im_end_coords[j] = FT_GET_SHORT() << 2; 1872 im_end_coords[j] = FT_GET_SHORT() * 4;
1405 } 1873 }
1406 1874
1407 apply = ft_var_apply_tuple( blend, 1875 apply = ft_var_apply_tuple( blend,
1408 (FT_UShort)tupleIndex, 1876 (FT_UShort)tupleIndex,
1409 tuple_coords, 1877 tuple_coords,
1410 im_start_coords, 1878 im_start_coords,
1411 im_end_coords ); 1879 im_end_coords );
1412 1880
1413 if ( apply == 0 ) /* tuple isn't active for our blend */ 1881 if ( apply == 0 ) /* tuple isn't active for our blend */
1414 { 1882 {
(...skipping 21 matching lines...) Expand all
1436 : point_count ); 1904 : point_count );
1437 deltas_y = ft_var_readpackeddeltas( stream, 1905 deltas_y = ft_var_readpackeddeltas( stream,
1438 point_count == 0 ? n_points 1906 point_count == 0 ? n_points
1439 : point_count ); 1907 : point_count );
1440 1908
1441 if ( points == NULL || deltas_y == NULL || deltas_x == NULL ) 1909 if ( points == NULL || deltas_y == NULL || deltas_x == NULL )
1442 ; /* failure, ignore it */ 1910 ; /* failure, ignore it */
1443 1911
1444 else if ( points == ALL_POINTS ) 1912 else if ( points == ALL_POINTS )
1445 { 1913 {
1914 #ifdef FT_DEBUG_LEVEL_TRACE
1915 int count = 0;
1916 #endif
1917
1918
1919 FT_TRACE7(( " point deltas:\n" ));
1920
1446 /* this means that there are deltas for every point in the glyph */ 1921 /* this means that there are deltas for every point in the glyph */
1447 for ( j = 0; j < n_points; ++j ) 1922 for ( j = 0; j < n_points; j++ )
1448 { 1923 {
1449 delta_xy[j].x += FT_MulFix( deltas_x[j], apply ); 1924 #ifdef FT_DEBUG_LEVEL_TRACE
1450 delta_xy[j].y += FT_MulFix( deltas_y[j], apply ); 1925 FT_Vector point_org = outline->points[j];
1926 #endif
1927
1928
1929 outline->points[j].x += FT_MulFix( deltas_x[j], apply );
1930 outline->points[j].y += FT_MulFix( deltas_y[j], apply );
1931
1932 #ifdef FT_DEBUG_LEVEL_TRACE
1933 if ( ( point_org.x != outline->points[j].x ) ||
1934 ( point_org.y != outline->points[j].y ) )
1935 {
1936 FT_TRACE7(( " %d: (%d, %d) -> (%d, %d)\n",
1937 j,
1938 point_org.x,
1939 point_org.y,
1940 outline->points[j].x,
1941 outline->points[j].y ));
1942 count++;
1943 }
1944 #endif
1451 } 1945 }
1946
1947 #ifdef FT_DEBUG_LEVEL_TRACE
1948 if ( !count )
1949 FT_TRACE7(( " none\n" ));
1950 #endif
1452 } 1951 }
1453 1952
1454 else 1953 else
1455 { 1954 {
1456 for ( j = 0; j < point_count; ++j ) 1955 #ifdef FT_DEBUG_LEVEL_TRACE
1956 int count = 0;
1957 #endif
1958
1959
1960 /* we have to interpolate the missing deltas similar to the */
1961 /* IUP bytecode instruction */
1962 for ( j = 0; j < n_points; j++ )
1457 { 1963 {
1458 if ( localpoints[j] >= n_points ) 1964 points_org[j] = outline->points[j];
1965 has_delta[j] = FALSE;
1966 }
1967
1968 for ( j = 0; j < point_count; j++ )
1969 {
1970 FT_UShort idx = localpoints[j];
1971
1972
1973 if ( idx >= n_points )
1459 continue; 1974 continue;
1460 1975
1461 delta_xy[localpoints[j]].x += FT_MulFix( deltas_x[j], apply ); 1976 has_delta[idx] = TRUE;
1462 delta_xy[localpoints[j]].y += FT_MulFix( deltas_y[j], apply ); 1977
1978 outline->points[idx].x += FT_MulFix( deltas_x[j], apply );
1979 outline->points[idx].y += FT_MulFix( deltas_y[j], apply );
1463 } 1980 }
1981
1982 /* no need to handle phantom points here, */
1983 /* since solitary points can't be interpolated */
1984 tt_handle_deltas( outline,
1985 points_org,
1986 has_delta );
1987
1988 #ifdef FT_DEBUG_LEVEL_TRACE
1989 FT_TRACE7(( " point deltas:\n" ));
1990
1991 for ( j = 0; j < n_points; j++)
1992 {
1993 if ( ( points_org[j].x != outline->points[j].x ) ||
1994 ( points_org[j].y != outline->points[j].y ) )
1995 {
1996 FT_TRACE7(( " %d: (%d, %d) -> (%d, %d)\n",
1997 j,
1998 points_org[j].x,
1999 points_org[j].y,
2000 outline->points[j].x,
2001 outline->points[j].y ));
2002 count++;
2003 }
2004 }
2005
2006 if ( !count )
2007 FT_TRACE7(( " none\n" ));
2008 #endif
1464 } 2009 }
1465 2010
1466 if ( localpoints != ALL_POINTS ) 2011 if ( localpoints != ALL_POINTS )
1467 FT_FREE( localpoints ); 2012 FT_FREE( localpoints );
1468 FT_FREE( deltas_x ); 2013 FT_FREE( deltas_x );
1469 FT_FREE( deltas_y ); 2014 FT_FREE( deltas_y );
1470 2015
1471 offsetToData += tupleDataSize; 2016 offsetToData += tupleDataSize;
1472 2017
1473 FT_Stream_SeekSet( stream, here ); 2018 FT_Stream_SeekSet( stream, here );
1474 } 2019 }
1475 2020
1476 Fail3: 2021 FT_TRACE5(( "\n" ));
2022
2023 Fail2:
1477 FT_FREE( tuple_coords ); 2024 FT_FREE( tuple_coords );
1478 FT_FREE( im_start_coords ); 2025 FT_FREE( im_start_coords );
1479 FT_FREE( im_end_coords ); 2026 FT_FREE( im_end_coords );
1480 2027
1481 Fail2:
1482 FT_FRAME_EXIT(); 2028 FT_FRAME_EXIT();
1483 2029
1484 Fail1: 2030 Fail1:
1485 if ( error ) 2031 FT_FREE( points_org );
1486 { 2032 FT_FREE( has_delta );
1487 FT_FREE( delta_xy );
1488 *deltas = NULL;
1489 }
1490 2033
1491 Exit:
1492 return error; 2034 return error;
1493 } 2035 }
1494 2036
1495 2037
1496 /*************************************************************************/ 2038 /*************************************************************************/
1497 /* */ 2039 /* */
1498 /* <Function> */ 2040 /* <Function> */
1499 /* tt_done_blend */ 2041 /* tt_done_blend */
1500 /* */ 2042 /* */
1501 /* <Description> */ 2043 /* <Description> */
1502 /* Frees the blend internal data structure. */ 2044 /* Free the blend internal data structure. */
1503 /* */ 2045 /* */
1504 FT_LOCAL_DEF( void ) 2046 FT_LOCAL_DEF( void )
1505 tt_done_blend( FT_Memory memory, 2047 tt_done_blend( FT_Memory memory,
1506 GX_Blend blend ) 2048 GX_Blend blend )
1507 { 2049 {
1508 if ( blend != NULL ) 2050 if ( blend != NULL )
1509 { 2051 {
1510 FT_UInt i; 2052 FT_UInt i;
1511 2053
1512 2054
1513 FT_FREE( blend->normalizedcoords ); 2055 FT_FREE( blend->normalizedcoords );
1514 FT_FREE( blend->mmvar ); 2056 FT_FREE( blend->mmvar );
1515 2057
1516 if ( blend->avar_segment != NULL ) 2058 if ( blend->avar_segment != NULL )
1517 { 2059 {
1518 for ( i = 0; i < blend->num_axis; ++i ) 2060 for ( i = 0; i < blend->num_axis; i++ )
1519 FT_FREE( blend->avar_segment[i].correspondence ); 2061 FT_FREE( blend->avar_segment[i].correspondence );
1520 FT_FREE( blend->avar_segment ); 2062 FT_FREE( blend->avar_segment );
1521 } 2063 }
1522 2064
1523 FT_FREE( blend->tuplecoords ); 2065 FT_FREE( blend->tuplecoords );
1524 FT_FREE( blend->glyphoffsets ); 2066 FT_FREE( blend->glyphoffsets );
1525 FT_FREE( blend ); 2067 FT_FREE( blend );
1526 } 2068 }
1527 } 2069 }
1528 2070
1529 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 2071 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1530 2072
1531 2073
1532 /* END */ 2074 /* END */
OLDNEW
« no previous file with comments | « third_party/freetype/src/truetype/ttgxvar.h ('k') | third_party/freetype/src/truetype/ttinterp.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698