changeset 54876 | da3834261f0c |
parent 50479 | 70e706c85f1d |
54875:bcfedddcf4ce | 54876:da3834261f0c |
---|---|
1 /***************************************************************************/ |
1 /**************************************************************************** |
2 /* */ |
2 * |
3 /* t1load.c */ |
3 * t1load.c |
4 /* */ |
4 * |
5 /* Type 1 font loader (body). */ |
5 * Type 1 font loader (body). |
6 /* */ |
6 * |
7 /* Copyright 1996-2018 by */ |
7 * Copyright (C) 1996-2019 by |
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
8 * David Turner, Robert Wilhelm, and Werner Lemberg. |
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 /* This is the new and improved Type 1 data loader for FreeType 2. The */ |
21 * This is the new and improved Type 1 data loader for FreeType 2. The |
22 /* old loader has several problems: it is slow, complex, difficult to */ |
22 * old loader has several problems: it is slow, complex, difficult to |
23 /* maintain, and contains incredible hacks to make it accept some */ |
23 * maintain, and contains incredible hacks to make it accept some |
24 /* ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of */ |
24 * ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of |
25 /* the Type 1 fonts on my machine still aren't loaded correctly by it. */ |
25 * the Type 1 fonts on my machine still aren't loaded correctly by it. |
26 /* */ |
26 * |
27 /* This version is much simpler, much faster and also easier to read and */ |
27 * This version is much simpler, much faster and also easier to read and |
28 /* maintain by a great order of magnitude. The idea behind it is to */ |
28 * maintain by a great order of magnitude. The idea behind it is to |
29 /* _not_ try to read the Type 1 token stream with a state machine (i.e. */ |
29 * _not_ try to read the Type 1 token stream with a state machine (i.e. |
30 /* a Postscript-like interpreter) but rather to perform simple pattern */ |
30 * a Postscript-like interpreter) but rather to perform simple pattern |
31 /* matching. */ |
31 * matching. |
32 /* */ |
32 * |
33 /* Indeed, nearly all data definitions follow a simple pattern like */ |
33 * Indeed, nearly all data definitions follow a simple pattern like |
34 /* */ |
34 * |
35 /* ... /Field <data> ... */ |
35 * ... /Field <data> ... |
36 /* */ |
36 * |
37 /* where <data> can be a number, a boolean, a string, or an array of */ |
37 * where <data> can be a number, a boolean, a string, or an array of |
38 /* numbers. There are a few exceptions, namely the encoding, font name, */ |
38 * numbers. There are a few exceptions, namely the encoding, font name, |
39 /* charstrings, and subrs; they are handled with a special pattern */ |
39 * charstrings, and subrs; they are handled with a special pattern |
40 /* matching routine. */ |
40 * matching routine. |
41 /* */ |
41 * |
42 /* All other common cases are handled very simply. The matching rules */ |
42 * All other common cases are handled very simply. The matching rules |
43 /* are defined in the file `t1tokens.h' through the use of several */ |
43 * are defined in the file `t1tokens.h' through the use of several |
44 /* macros calls PARSE_XXX. This file is included twice here; the first */ |
44 * macros calls PARSE_XXX. This file is included twice here; the first |
45 /* time to generate parsing callback functions, the second time to */ |
45 * time to generate parsing callback functions, the second time to |
46 /* generate a table of keywords (with pointers to the associated */ |
46 * generate a table of keywords (with pointers to the associated |
47 /* callback functions). */ |
47 * callback functions). |
48 /* */ |
48 * |
49 /* The function `parse_dict' simply scans *linearly* a given dictionary */ |
49 * The function `parse_dict' simply scans *linearly* a given dictionary |
50 /* (either the top-level or private one) and calls the appropriate */ |
50 * (either the top-level or private one) and calls the appropriate |
51 /* callback when it encounters an immediate keyword. */ |
51 * callback when it encounters an immediate keyword. |
52 /* */ |
52 * |
53 /* This is by far the fastest way one can find to parse and read all */ |
53 * This is by far the fastest way one can find to parse and read all |
54 /* data. */ |
54 * data. |
55 /* */ |
55 * |
56 /* This led to tremendous code size reduction. Note that later, the */ |
56 * This led to tremendous code size reduction. Note that later, the |
57 /* glyph loader will also be _greatly_ simplified, and the automatic */ |
57 * glyph loader will also be _greatly_ simplified, and the automatic |
58 /* hinter will replace the clumsy `t1hinter'. */ |
58 * hinter will replace the clumsy `t1hinter'. |
59 /* */ |
59 * |
60 /*************************************************************************/ |
60 */ |
61 |
61 |
62 |
62 |
63 #include <ft2build.h> |
63 #include <ft2build.h> |
64 #include FT_INTERNAL_DEBUG_H |
64 #include FT_INTERNAL_DEBUG_H |
65 #include FT_CONFIG_CONFIG_H |
65 #include FT_CONFIG_CONFIG_H |
71 #include "t1load.h" |
71 #include "t1load.h" |
72 #include "t1errors.h" |
72 #include "t1errors.h" |
73 |
73 |
74 |
74 |
75 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
75 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
76 #define IS_INCREMENTAL (FT_Bool)( face->root.internal->incremental_interface != 0 ) |
76 #define IS_INCREMENTAL FT_BOOL( face->root.internal->incremental_interface ) |
77 #else |
77 #else |
78 #define IS_INCREMENTAL 0 |
78 #define IS_INCREMENTAL 0 |
79 #endif |
79 #endif |
80 |
80 |
81 |
81 |
82 /*************************************************************************/ |
82 /************************************************************************** |
83 /* */ |
83 * |
84 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
84 * The macro FT_COMPONENT is used in trace mode. It is an implicit |
85 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
85 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log |
86 /* messages during execution. */ |
86 * messages during execution. |
87 /* */ |
87 */ |
88 #undef FT_COMPONENT |
88 #undef FT_COMPONENT |
89 #define FT_COMPONENT trace_t1load |
89 #define FT_COMPONENT t1load |
90 |
90 |
91 |
91 |
92 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT |
92 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT |
93 |
93 |
94 |
94 |
220 |
220 |
221 return error; |
221 return error; |
222 } |
222 } |
223 |
223 |
224 |
224 |
225 /*************************************************************************/ |
225 /************************************************************************** |
226 /* */ |
226 * |
227 /* Given a normalized (blend) coordinate, figure out the design */ |
227 * Given a normalized (blend) coordinate, figure out the design |
228 /* coordinate appropriate for that value. */ |
228 * coordinate appropriate for that value. |
229 /* */ |
229 */ |
230 static FT_Fixed |
230 static FT_Fixed |
231 mm_axis_unmap( PS_DesignMap axismap, |
231 mm_axis_unmap( PS_DesignMap axismap, |
232 FT_Fixed ncv ) |
232 FT_Fixed ncv ) |
233 { |
233 { |
234 int j; |
234 int j; |
249 |
249 |
250 return INT_TO_FIXED( axismap->design_points[axismap->num_points - 1] ); |
250 return INT_TO_FIXED( axismap->design_points[axismap->num_points - 1] ); |
251 } |
251 } |
252 |
252 |
253 |
253 |
254 /*************************************************************************/ |
254 /************************************************************************** |
255 /* */ |
255 * |
256 /* Given a vector of weights, one for each design, figure out the */ |
256 * Given a vector of weights, one for each design, figure out the |
257 /* normalized axis coordinates which gave rise to those weights. */ |
257 * normalized axis coordinates which gave rise to those weights. |
258 /* */ |
258 */ |
259 static void |
259 static void |
260 mm_weights_unmap( FT_Fixed* weights, |
260 mm_weights_unmap( FT_Fixed* weights, |
261 FT_Fixed* axiscoords, |
261 FT_Fixed* axiscoords, |
262 FT_UInt axis_count ) |
262 FT_UInt axis_count ) |
263 { |
263 { |
291 weights[11] + weights[10] + weights[9] + weights[8]; |
291 weights[11] + weights[10] + weights[9] + weights[8]; |
292 } |
292 } |
293 } |
293 } |
294 |
294 |
295 |
295 |
296 /*************************************************************************/ |
296 /************************************************************************** |
297 /* */ |
297 * |
298 /* Just a wrapper around T1_Get_Multi_Master to support the different */ |
298 * Just a wrapper around T1_Get_Multi_Master to support the different |
299 /* arguments needed by the GX var distortable fonts. */ |
299 * arguments needed by the GX var distortable fonts. |
300 /* */ |
300 */ |
301 FT_LOCAL_DEF( FT_Error ) |
301 FT_LOCAL_DEF( FT_Error ) |
302 T1_Get_MM_Var( T1_Face face, |
302 T1_Get_MM_Var( T1_Face face, |
303 FT_MM_Var* *master ) |
303 FT_MM_Var* *master ) |
304 { |
304 { |
305 FT_Memory memory = face->root.memory; |
305 FT_Memory memory = face->root.memory; |
346 mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'd', 't', 'h' ); |
346 mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'd', 't', 'h' ); |
347 else if ( ft_strcmp( mmvar->axis[i].name, "OpticalSize" ) == 0 ) |
347 else if ( ft_strcmp( mmvar->axis[i].name, "OpticalSize" ) == 0 ) |
348 mmvar->axis[i].tag = FT_MAKE_TAG( 'o', 'p', 's', 'z' ); |
348 mmvar->axis[i].tag = FT_MAKE_TAG( 'o', 'p', 's', 'z' ); |
349 } |
349 } |
350 |
350 |
351 if ( blend->num_designs == ( 1U << blend->num_axis ) ) |
351 mm_weights_unmap( blend->default_weight_vector, |
352 { |
352 axiscoords, |
353 mm_weights_unmap( blend->default_weight_vector, |
353 blend->num_axis ); |
354 axiscoords, |
354 |
355 blend->num_axis ); |
355 for ( i = 0; i < mmaster.num_axis; i++ ) |
356 |
356 mmvar->axis[i].def = mm_axis_unmap( &blend->design_map[i], |
357 for ( i = 0; i < mmaster.num_axis; i++ ) |
357 axiscoords[i] ); |
358 mmvar->axis[i].def = mm_axis_unmap( &blend->design_map[i], |
|
359 axiscoords[i] ); |
|
360 } |
|
361 |
358 |
362 *master = mmvar; |
359 *master = mmvar; |
363 |
360 |
364 Exit: |
361 Exit: |
365 return error; |
362 return error; |
385 |
382 |
386 /* recompute the weight vector from the blend coordinates */ |
383 /* recompute the weight vector from the blend coordinates */ |
387 for ( n = 0; n < blend->num_designs; n++ ) |
384 for ( n = 0; n < blend->num_designs; n++ ) |
388 { |
385 { |
389 FT_Fixed result = 0x10000L; /* 1.0 fixed */ |
386 FT_Fixed result = 0x10000L; /* 1.0 fixed */ |
387 FT_Fixed factor; |
|
390 |
388 |
391 |
389 |
392 for ( m = 0; m < blend->num_axis; m++ ) |
390 for ( m = 0; m < blend->num_axis; m++ ) |
393 { |
391 { |
394 FT_Fixed factor; |
|
395 |
|
396 |
|
397 /* get current blend axis position; */ |
|
398 /* use a default value if we don't have a coordinate */ |
392 /* use a default value if we don't have a coordinate */ |
399 factor = m < num_coords ? coords[m] : 0x8000; |
393 if ( m >= num_coords ) |
400 if ( factor < 0 ) |
394 { |
401 factor = 0; |
395 result >>= 1; |
402 if ( factor > 0x10000L ) |
396 continue; |
403 factor = 0x10000L; |
397 } |
404 |
398 |
399 /* get current blend axis position */ |
|
400 factor = coords[m]; |
|
405 if ( ( n & ( 1 << m ) ) == 0 ) |
401 if ( ( n & ( 1 << m ) ) == 0 ) |
406 factor = 0x10000L - factor; |
402 factor = 0x10000L - factor; |
403 |
|
404 if ( factor <= 0 ) |
|
405 { |
|
406 result = 0; |
|
407 break; |
|
408 } |
|
409 else if ( factor >= 0x10000L ) |
|
410 continue; |
|
407 |
411 |
408 result = FT_MulFix( result, factor ); |
412 result = FT_MulFix( result, factor ); |
409 } |
413 } |
410 |
414 |
411 if ( blend->weight_vector[n] != result ) |
415 if ( blend->weight_vector[n] != result ) |
469 |
473 |
470 for ( i = 0; i < nc; i++ ) |
474 for ( i = 0; i < nc; i++ ) |
471 coords[i] = axiscoords[i]; |
475 coords[i] = axiscoords[i]; |
472 for ( ; i < num_coords; i++ ) |
476 for ( ; i < num_coords; i++ ) |
473 coords[i] = 0x8000; |
477 coords[i] = 0x8000; |
478 |
|
479 return FT_Err_Ok; |
|
480 } |
|
481 |
|
482 |
|
483 FT_LOCAL_DEF( FT_Error ) |
|
484 T1_Set_MM_WeightVector( T1_Face face, |
|
485 FT_UInt len, |
|
486 FT_Fixed* weightvector ) |
|
487 { |
|
488 PS_Blend blend = face->blend; |
|
489 FT_UInt i, n; |
|
490 |
|
491 |
|
492 if ( !blend ) |
|
493 return FT_THROW( Invalid_Argument ); |
|
494 |
|
495 if ( !len && !weightvector ) |
|
496 { |
|
497 for ( i = 0; i < blend->num_designs; i++ ) |
|
498 blend->weight_vector[i] = blend->default_weight_vector[i]; |
|
499 } |
|
500 else |
|
501 { |
|
502 if ( !weightvector ) |
|
503 return FT_THROW( Invalid_Argument ); |
|
504 |
|
505 n = len < blend->num_designs ? len : blend->num_designs; |
|
506 |
|
507 for ( i = 0; i < n; i++ ) |
|
508 blend->weight_vector[i] = weightvector[i]; |
|
509 |
|
510 for ( ; i < blend->num_designs; i++ ) |
|
511 blend->weight_vector[i] = (FT_Fixed)0; |
|
512 |
|
513 if ( len ) |
|
514 face->root.face_flags |= FT_FACE_FLAG_VARIATION; |
|
515 else |
|
516 face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; |
|
517 } |
|
518 |
|
519 return FT_Err_Ok; |
|
520 } |
|
521 |
|
522 |
|
523 FT_LOCAL_DEF( FT_Error ) |
|
524 T1_Get_MM_WeightVector( T1_Face face, |
|
525 FT_UInt* len, |
|
526 FT_Fixed* weightvector ) |
|
527 { |
|
528 PS_Blend blend = face->blend; |
|
529 FT_UInt i; |
|
530 |
|
531 |
|
532 if ( !blend ) |
|
533 return FT_THROW( Invalid_Argument ); |
|
534 |
|
535 if ( *len < blend->num_designs ) |
|
536 { |
|
537 *len = blend->num_designs; |
|
538 return FT_THROW( Invalid_Argument ); |
|
539 } |
|
540 |
|
541 for ( i = 0; i < blend->num_designs; i++ ) |
|
542 weightvector[i] = blend->weight_vector[i]; |
|
543 for ( ; i < *len; i++ ) |
|
544 weightvector[i] = (FT_Fixed)0; |
|
545 |
|
546 *len = blend->num_designs; |
|
474 |
547 |
475 return FT_Err_Ok; |
548 return FT_Err_Ok; |
476 } |
549 } |
477 |
550 |
478 |
551 |
571 |
644 |
572 return T1_Set_MM_Blend( face, 0, NULL ); |
645 return T1_Set_MM_Blend( face, 0, NULL ); |
573 } |
646 } |
574 |
647 |
575 |
648 |
576 /*************************************************************************/ |
649 /************************************************************************** |
577 /* */ |
650 * |
578 /* Just a wrapper around T1_Set_MM_Design to support the different */ |
651 * Just a wrapper around T1_Set_MM_Design to support the different |
579 /* arguments needed by the GX var distortable fonts. */ |
652 * arguments needed by the GX var distortable fonts. |
580 /* */ |
653 */ |
581 FT_LOCAL_DEF( FT_Error ) |
654 FT_LOCAL_DEF( FT_Error ) |
582 T1_Set_Var_Design( T1_Face face, |
655 T1_Set_Var_Design( T1_Face face, |
583 FT_UInt num_coords, |
656 FT_UInt num_coords, |
584 FT_Fixed* coords ) |
657 FT_Fixed* coords ) |
585 { |
658 { |
717 /* allocate blend if necessary */ |
790 /* allocate blend if necessary */ |
718 error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); |
791 error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); |
719 if ( error ) |
792 if ( error ) |
720 goto Exit; |
793 goto Exit; |
721 |
794 |
795 FT_TRACE4(( " [" )); |
|
796 |
|
722 blend = face->blend; |
797 blend = face->blend; |
723 memory = face->root.memory; |
798 memory = face->root.memory; |
724 |
799 |
725 /* each token is an immediate containing the name of the axis */ |
800 /* each token is an immediate containing the name of the axis */ |
726 for ( n = 0; n < num_axis; n++ ) |
801 for ( n = 0; n < num_axis; n++ ) |
739 { |
814 { |
740 error = FT_THROW( Invalid_File_Format ); |
815 error = FT_THROW( Invalid_File_Format ); |
741 goto Exit; |
816 goto Exit; |
742 } |
817 } |
743 |
818 |
819 FT_TRACE4(( " /%.*s", len, token->start )); |
|
820 |
|
744 name = (FT_Byte*)blend->axis_names[n]; |
821 name = (FT_Byte*)blend->axis_names[n]; |
745 if ( name ) |
822 if ( name ) |
746 { |
823 { |
747 FT_TRACE0(( "parse_blend_axis_types:" |
824 FT_TRACE0(( "parse_blend_axis_types:" |
748 " overwriting axis name `%s' with `%*.s'\n", |
825 " overwriting axis name `%s' with `%.*s'\n", |
749 name, len, token->start )); |
826 name, len, token->start )); |
750 FT_FREE( name ); |
827 FT_FREE( name ); |
751 } |
828 } |
752 |
829 |
753 if ( FT_ALLOC( blend->axis_names[n], len + 1 ) ) |
830 if ( FT_ALLOC( blend->axis_names[n], len + 1 ) ) |
755 |
832 |
756 name = (FT_Byte*)blend->axis_names[n]; |
833 name = (FT_Byte*)blend->axis_names[n]; |
757 FT_MEM_COPY( name, token->start, len ); |
834 FT_MEM_COPY( name, token->start, len ); |
758 name[len] = '\0'; |
835 name[len] = '\0'; |
759 } |
836 } |
837 |
|
838 FT_TRACE4(( "]\n" )); |
|
760 |
839 |
761 Exit: |
840 Exit: |
762 loader->parser.root.error = error; |
841 loader->parser.root.error = error; |
763 } |
842 } |
764 |
843 |
799 FT_Int n; |
878 FT_Int n; |
800 |
879 |
801 |
880 |
802 blend = face->blend; |
881 blend = face->blend; |
803 num_axis = 0; /* make compiler happy */ |
882 num_axis = 0; /* make compiler happy */ |
883 |
|
884 FT_TRACE4(( " [" )); |
|
804 |
885 |
805 for ( n = 0; n < num_designs; n++ ) |
886 for ( n = 0; n < num_designs; n++ ) |
806 { |
887 { |
807 T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; |
888 T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; |
808 T1_Token token; |
889 T1_Token token; |
840 error = FT_THROW( Invalid_File_Format ); |
921 error = FT_THROW( Invalid_File_Format ); |
841 goto Exit; |
922 goto Exit; |
842 } |
923 } |
843 |
924 |
844 /* now read each axis token into the design position */ |
925 /* now read each axis token into the design position */ |
926 FT_TRACE4(( " [" )) ; |
|
845 for ( axis = 0; axis < n_axis; axis++ ) |
927 for ( axis = 0; axis < n_axis; axis++ ) |
846 { |
928 { |
847 T1_Token token2 = axis_tokens + axis; |
929 T1_Token token2 = axis_tokens + axis; |
848 |
930 |
849 |
931 |
850 parser->root.cursor = token2->start; |
932 parser->root.cursor = token2->start; |
851 parser->root.limit = token2->limit; |
933 parser->root.limit = token2->limit; |
852 blend->design_pos[n][axis] = T1_ToFixed( parser, 0 ); |
934 blend->design_pos[n][axis] = T1_ToFixed( parser, 0 ); |
935 FT_TRACE4(( " %f", (double)blend->design_pos[n][axis] / 65536 )); |
|
853 } |
936 } |
854 } |
937 FT_TRACE4(( "]" )) ; |
938 } |
|
939 |
|
940 FT_TRACE4(( "]\n" )); |
|
855 |
941 |
856 loader->parser.root.cursor = old_cursor; |
942 loader->parser.root.cursor = old_cursor; |
857 loader->parser.root.limit = old_limit; |
943 loader->parser.root.limit = old_limit; |
858 } |
944 } |
859 |
945 |
897 error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); |
983 error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); |
898 if ( error ) |
984 if ( error ) |
899 goto Exit; |
985 goto Exit; |
900 blend = face->blend; |
986 blend = face->blend; |
901 |
987 |
988 FT_TRACE4(( " [" )); |
|
989 |
|
902 /* now read each axis design map */ |
990 /* now read each axis design map */ |
903 for ( n = 0; n < num_axis; n++ ) |
991 for ( n = 0; n < num_axis; n++ ) |
904 { |
992 { |
905 PS_DesignMap map = blend->design_map + n; |
993 PS_DesignMap map = blend->design_map + n; |
906 T1_Token axis_token; |
994 T1_Token axis_token; |
912 |
1000 |
913 parser->root.cursor = axis_token->start; |
1001 parser->root.cursor = axis_token->start; |
914 parser->root.limit = axis_token->limit; |
1002 parser->root.limit = axis_token->limit; |
915 T1_ToTokenArray( parser, point_tokens, |
1003 T1_ToTokenArray( parser, point_tokens, |
916 T1_MAX_MM_MAP_POINTS, &num_points ); |
1004 T1_MAX_MM_MAP_POINTS, &num_points ); |
1005 |
|
1006 FT_TRACE4(( " [" )); |
|
917 |
1007 |
918 if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS ) |
1008 if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS ) |
919 { |
1009 { |
920 FT_ERROR(( "parse_blend_design_map: incorrect table\n" )); |
1010 FT_ERROR(( "parse_blend_design_map: incorrect table\n" )); |
921 error = FT_THROW( Invalid_File_Format ); |
1011 error = FT_THROW( Invalid_File_Format ); |
946 parser->root.cursor = point_token->start + 1; |
1036 parser->root.cursor = point_token->start + 1; |
947 parser->root.limit = point_token->limit - 1; |
1037 parser->root.limit = point_token->limit - 1; |
948 |
1038 |
949 map->design_points[p] = T1_ToInt( parser ); |
1039 map->design_points[p] = T1_ToInt( parser ); |
950 map->blend_points [p] = T1_ToFixed( parser, 0 ); |
1040 map->blend_points [p] = T1_ToFixed( parser, 0 ); |
951 } |
1041 |
952 } |
1042 FT_TRACE4(( " [%d %f]", |
1043 map->design_points[p], |
|
1044 (double)map->blend_points[p] / 65536 )); |
|
1045 } |
|
1046 |
|
1047 FT_TRACE4(( "]" )); |
|
1048 } |
|
1049 |
|
1050 FT_TRACE4(( "]\n" )); |
|
953 |
1051 |
954 parser->root.cursor = old_cursor; |
1052 parser->root.cursor = old_cursor; |
955 parser->root.limit = old_limit; |
1053 parser->root.limit = old_limit; |
956 |
1054 |
957 Exit: |
1055 Exit: |
1008 } |
1106 } |
1009 |
1107 |
1010 old_cursor = parser->root.cursor; |
1108 old_cursor = parser->root.cursor; |
1011 old_limit = parser->root.limit; |
1109 old_limit = parser->root.limit; |
1012 |
1110 |
1111 FT_TRACE4(( "[" )); |
|
1112 |
|
1013 for ( n = 0; n < num_designs; n++ ) |
1113 for ( n = 0; n < num_designs; n++ ) |
1014 { |
1114 { |
1015 token = design_tokens + n; |
1115 token = design_tokens + n; |
1016 parser->root.cursor = token->start; |
1116 parser->root.cursor = token->start; |
1017 parser->root.limit = token->limit; |
1117 parser->root.limit = token->limit; |
1018 |
1118 |
1019 blend->default_weight_vector[n] = |
1119 blend->default_weight_vector[n] = |
1020 blend->weight_vector[n] = T1_ToFixed( parser, 0 ); |
1120 blend->weight_vector[n] = T1_ToFixed( parser, 0 ); |
1021 } |
1121 |
1122 FT_TRACE4(( " %f", (double)blend->weight_vector[n] / 65536 )); |
|
1123 } |
|
1124 |
|
1125 FT_TRACE4(( "]\n" )); |
|
1022 |
1126 |
1023 parser->root.cursor = old_cursor; |
1127 parser->root.cursor = old_cursor; |
1024 parser->root.limit = old_limit; |
1128 parser->root.limit = old_limit; |
1025 |
1129 |
1026 Exit: |
1130 Exit: |
1034 parse_buildchar( T1_Face face, |
1138 parse_buildchar( T1_Face face, |
1035 T1_Loader loader ) |
1139 T1_Loader loader ) |
1036 { |
1140 { |
1037 face->len_buildchar = (FT_UInt)T1_ToFixedArray( &loader->parser, |
1141 face->len_buildchar = (FT_UInt)T1_ToFixedArray( &loader->parser, |
1038 0, NULL, 0 ); |
1142 0, NULL, 0 ); |
1143 |
|
1144 #ifdef FT_DEBUG_LEVEL_TRACE |
|
1145 { |
|
1146 FT_UInt i; |
|
1147 |
|
1148 |
|
1149 FT_TRACE4(( " [" )); |
|
1150 for ( i = 0; i < face->len_buildchar; i++ ) |
|
1151 FT_TRACE4(( " 0" )); |
|
1152 |
|
1153 FT_TRACE4(( "]\n" )); |
|
1154 } |
|
1155 #endif |
|
1156 |
|
1039 return; |
1157 return; |
1040 } |
1158 } |
1041 |
1159 |
1042 |
1160 |
1043 #endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */ |
1161 #endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */ |
1069 blend = NULL; |
1187 blend = NULL; |
1070 |
1188 |
1071 /* if the keyword has a dedicated callback, call it */ |
1189 /* if the keyword has a dedicated callback, call it */ |
1072 if ( field->type == T1_FIELD_TYPE_CALLBACK ) |
1190 if ( field->type == T1_FIELD_TYPE_CALLBACK ) |
1073 { |
1191 { |
1192 FT_TRACE4(( " %s", field->ident )); |
|
1193 |
|
1074 field->reader( (FT_Face)face, loader ); |
1194 field->reader( (FT_Face)face, loader ); |
1075 error = loader->parser.root.error; |
1195 error = loader->parser.root.error; |
1076 goto Exit; |
1196 goto Exit; |
1077 } |
1197 } |
1078 |
1198 |
1146 dummy_object = &face->type1; |
1266 dummy_object = &face->type1; |
1147 objects = &dummy_object; |
1267 objects = &dummy_object; |
1148 max_objects = 0; |
1268 max_objects = 0; |
1149 } |
1269 } |
1150 |
1270 |
1271 FT_TRACE4(( " %s", field->ident )); |
|
1272 |
|
1151 if ( *objects ) |
1273 if ( *objects ) |
1152 { |
1274 { |
1153 if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY || |
1275 if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY || |
1154 field->type == T1_FIELD_TYPE_FIXED_ARRAY ) |
1276 field->type == T1_FIELD_TYPE_FIXED_ARRAY ) |
1155 error = T1_Load_Field_Table( &loader->parser, field, |
1277 error = T1_Load_Field_Table( &loader->parser, field, |
1165 " (probably due to missing keywords)\n", |
1287 " (probably due to missing keywords)\n", |
1166 field->ident )); |
1288 field->ident )); |
1167 error = FT_Err_Ok; |
1289 error = FT_Err_Ok; |
1168 } |
1290 } |
1169 |
1291 |
1292 FT_TRACE4(( "\n" )); |
|
1293 |
|
1170 Exit: |
1294 Exit: |
1171 return error; |
1295 return error; |
1172 } |
1296 } |
1173 |
1297 |
1174 |
1298 |
1177 T1_Loader loader ) |
1301 T1_Loader loader ) |
1178 { |
1302 { |
1179 FT_UNUSED( face ); |
1303 FT_UNUSED( face ); |
1180 |
1304 |
1181 loader->keywords_encountered |= T1_PRIVATE; |
1305 loader->keywords_encountered |= T1_PRIVATE; |
1306 |
|
1307 FT_TRACE4(( "\n" )); |
|
1182 } |
1308 } |
1183 |
1309 |
1184 |
1310 |
1185 /* return 1 in case of success */ |
1311 /* return 1 in case of success */ |
1186 |
1312 |
1256 { |
1382 { |
1257 parser->root.error = FT_THROW( Invalid_File_Format ); |
1383 parser->root.error = FT_THROW( Invalid_File_Format ); |
1258 return; |
1384 return; |
1259 } |
1385 } |
1260 |
1386 |
1387 FT_TRACE4(( " [%f %f %f %f %f %f]\n", |
|
1388 (double)temp[0] / 65536 / 1000, |
|
1389 (double)temp[1] / 65536 / 1000, |
|
1390 (double)temp[2] / 65536 / 1000, |
|
1391 (double)temp[3] / 65536 / 1000, |
|
1392 (double)temp[4] / 65536 / 1000, |
|
1393 (double)temp[5] / 65536 / 1000 )); |
|
1394 |
|
1261 temp_scale = FT_ABS( temp[3] ); |
1395 temp_scale = FT_ABS( temp[3] ); |
1262 |
1396 |
1263 if ( temp_scale == 0 ) |
1397 if ( temp_scale == 0 ) |
1264 { |
1398 { |
1265 FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" )); |
1399 FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" )); |
1278 temp[2] = FT_DivFix( temp[2], temp_scale ); |
1412 temp[2] = FT_DivFix( temp[2], temp_scale ); |
1279 temp[4] = FT_DivFix( temp[4], temp_scale ); |
1413 temp[4] = FT_DivFix( temp[4], temp_scale ); |
1280 temp[5] = FT_DivFix( temp[5], temp_scale ); |
1414 temp[5] = FT_DivFix( temp[5], temp_scale ); |
1281 temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L; |
1415 temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L; |
1282 } |
1416 } |
1283 |
|
1284 matrix->xx = temp[0]; |
1417 matrix->xx = temp[0]; |
1285 matrix->yx = temp[1]; |
1418 matrix->yx = temp[1]; |
1286 matrix->xy = temp[2]; |
1419 matrix->xy = temp[2]; |
1287 matrix->yy = temp[3]; |
1420 matrix->yy = temp[3]; |
1421 |
|
1422 if ( !FT_Matrix_Check( matrix ) ) |
|
1423 { |
|
1424 FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" )); |
|
1425 parser->root.error = FT_THROW( Invalid_File_Format ); |
|
1426 return; |
|
1427 } |
|
1288 |
1428 |
1289 /* note that the offsets must be expressed in integer font units */ |
1429 /* note that the offsets must be expressed in integer font units */ |
1290 offset->x = temp[4] >> 16; |
1430 offset->x = temp[4] >> 16; |
1291 offset->y = temp[5] >> 16; |
1431 offset->y = temp[5] >> 16; |
1292 } |
1432 } |
1492 } |
1632 } |
1493 |
1633 |
1494 T1_Skip_Spaces( parser ); |
1634 T1_Skip_Spaces( parser ); |
1495 } |
1635 } |
1496 |
1636 |
1637 #ifdef FT_DEBUG_LEVEL_TRACE |
|
1638 FT_TRACE4(( " [" )); |
|
1639 |
|
1640 /* XXX show encoding vector */ |
|
1641 FT_TRACE4(( "..." )); |
|
1642 |
|
1643 FT_TRACE4(( "]\n" )); |
|
1644 #endif |
|
1645 |
|
1497 face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; |
1646 face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; |
1498 parser->root.cursor = cur; |
1647 parser->root.cursor = cur; |
1499 } |
1648 } |
1500 |
1649 |
1501 /* Otherwise, we should have either `StandardEncoding', */ |
1650 /* Otherwise, we should have either `StandardEncoding', */ |
1502 /* `ExpertEncoding', or `ISOLatin1Encoding' */ |
1651 /* `ExpertEncoding', or `ISOLatin1Encoding' */ |
1503 else |
1652 else |
1504 { |
1653 { |
1505 if ( cur + 17 < limit && |
1654 if ( cur + 17 < limit && |
1506 ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) |
1655 ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) |
1656 { |
|
1507 face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; |
1657 face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; |
1658 FT_TRACE4(( " StandardEncoding\n" )); |
|
1659 } |
|
1508 |
1660 |
1509 else if ( cur + 15 < limit && |
1661 else if ( cur + 15 < limit && |
1510 ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) |
1662 ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) |
1663 { |
|
1511 face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; |
1664 face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; |
1665 FT_TRACE4(( " ExpertEncoding\n" )); |
|
1666 } |
|
1512 |
1667 |
1513 else if ( cur + 18 < limit && |
1668 else if ( cur + 18 < limit && |
1514 ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) |
1669 ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) |
1670 { |
|
1515 face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; |
1671 face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; |
1672 FT_TRACE4(( " ISOLatin1Encoding\n" )); |
|
1673 } |
|
1516 |
1674 |
1517 else |
1675 else |
1676 { |
|
1518 parser->root.error = FT_ERR( Ignore ); |
1677 parser->root.error = FT_ERR( Ignore ); |
1678 FT_TRACE4(( "<unknown>\n" )); |
|
1679 } |
|
1519 } |
1680 } |
1520 } |
1681 } |
1521 |
1682 |
1522 |
1683 |
1523 static void |
1684 static void |
1693 goto Fail; |
1854 goto Fail; |
1694 } |
1855 } |
1695 |
1856 |
1696 if ( !loader->num_subrs ) |
1857 if ( !loader->num_subrs ) |
1697 loader->num_subrs = num_subrs; |
1858 loader->num_subrs = num_subrs; |
1859 |
|
1860 #ifdef FT_DEBUG_LEVEL_TRACE |
|
1861 FT_TRACE4(( " <" )); |
|
1862 |
|
1863 /* XXX show subrs? */ |
|
1864 FT_TRACE4(( "%d elements", num_subrs )); |
|
1865 |
|
1866 FT_TRACE4(( ">\n" )); |
|
1867 #endif |
|
1698 |
1868 |
1699 return; |
1869 return; |
1700 |
1870 |
1701 Fail: |
1871 Fail: |
1702 parser->root.error = error; |
1872 parser->root.error = error; |
2015 |
2185 |
2016 /* we added a glyph. */ |
2186 /* we added a glyph. */ |
2017 loader->num_glyphs += 1; |
2187 loader->num_glyphs += 1; |
2018 } |
2188 } |
2019 |
2189 |
2190 #ifdef FT_DEBUG_LEVEL_TRACE |
|
2191 FT_TRACE4(( " <" )); |
|
2192 |
|
2193 /* XXX show charstrings? */ |
|
2194 FT_TRACE4(( "%d elements", loader->num_glyphs )); |
|
2195 |
|
2196 FT_TRACE4(( ">\n" )); |
|
2197 #endif |
|
2198 |
|
2020 return; |
2199 return; |
2021 |
2200 |
2022 Fail: |
2201 Fail: |
2023 parser->root.error = error; |
2202 parser->root.error = error; |
2024 } |
2203 } |
2025 |
2204 |
2026 |
2205 |
2027 /*************************************************************************/ |
2206 /************************************************************************** |
2028 /* */ |
2207 * |
2029 /* Define the token field static variables. This is a set of */ |
2208 * Define the token field static variables. This is a set of |
2030 /* T1_FieldRec variables. */ |
2209 * T1_FieldRec variables. |
2031 /* */ |
2210 * |
2032 /*************************************************************************/ |
2211 */ |
2033 |
2212 |
2034 |
2213 |
2035 static |
2214 static |
2036 const T1_FieldRec t1_keywords[] = |
2215 const T1_FieldRec t1_keywords[] = |
2037 { |
2216 { |
2213 |
2392 |
2214 const FT_UInt dict = |
2393 const FT_UInt dict = |
2215 ( loader->keywords_encountered & T1_PRIVATE ) |
2394 ( loader->keywords_encountered & T1_PRIVATE ) |
2216 ? T1_FIELD_DICT_PRIVATE |
2395 ? T1_FIELD_DICT_PRIVATE |
2217 : T1_FIELD_DICT_FONTDICT; |
2396 : T1_FIELD_DICT_FONTDICT; |
2397 |
|
2218 |
2398 |
2219 if ( !( dict & keyword->dict ) ) |
2399 if ( !( dict & keyword->dict ) ) |
2220 { |
2400 { |
2221 FT_TRACE1(( "parse_dict: found `%s' but ignoring it" |
2401 FT_TRACE1(( "parse_dict: found `%s' but ignoring it" |
2222 " since it is in the wrong dictionary\n", |
2402 " since it is in the wrong dictionary\n", |
2328 face->root.memory, |
2508 face->root.memory, |
2329 psaux ); |
2509 psaux ); |
2330 if ( error ) |
2510 if ( error ) |
2331 goto Exit; |
2511 goto Exit; |
2332 |
2512 |
2513 FT_TRACE4(( " top dictionary:\n" )); |
|
2333 error = parse_dict( face, &loader, |
2514 error = parse_dict( face, &loader, |
2334 parser->base_dict, parser->base_len ); |
2515 parser->base_dict, parser->base_len ); |
2335 if ( error ) |
2516 if ( error ) |
2336 goto Exit; |
2517 goto Exit; |
2337 |
2518 |
2338 error = T1_Get_Private_Dict( parser, psaux ); |
2519 error = T1_Get_Private_Dict( parser, psaux ); |
2339 if ( error ) |
2520 if ( error ) |
2340 goto Exit; |
2521 goto Exit; |
2341 |
2522 |
2523 FT_TRACE4(( " private dictionary:\n" )); |
|
2342 error = parse_dict( face, &loader, |
2524 error = parse_dict( face, &loader, |
2343 parser->private_dict, parser->private_len ); |
2525 parser->private_dict, parser->private_len ); |
2344 if ( error ) |
2526 if ( error ) |
2345 goto Exit; |
2527 goto Exit; |
2346 |
2528 |
2347 /* ensure even-ness of `num_blue_values' */ |
2529 /* ensure even-ness of `num_blue_values' */ |
2348 priv->num_blue_values &= ~1; |
2530 priv->num_blue_values &= ~1; |
2349 |
2531 |
2350 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT |
2532 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT |
2533 |
|
2534 /* we don't support Multiple Master fonts with intermediate designs; */ |
|
2535 /* this implies that `num_designs' must be equal to `2^^num_axis' */ |
|
2536 if ( face->blend && |
|
2537 face->blend->num_designs != ( 1U << face->blend->num_axis ) ) |
|
2538 { |
|
2539 FT_ERROR(( "T1_Open_Face:" |
|
2540 " number-of-designs != 2 ^^ number-of-axes\n" )); |
|
2541 T1_Done_Blend( face ); |
|
2542 } |
|
2351 |
2543 |
2352 if ( face->blend && |
2544 if ( face->blend && |
2353 face->blend->num_default_design_vector != 0 && |
2545 face->blend->num_default_design_vector != 0 && |
2354 face->blend->num_default_design_vector != face->blend->num_axis ) |
2546 face->blend->num_default_design_vector != face->blend->num_axis ) |
2355 { |
2547 { |