1 /*******************************************************************
5 * TrueType Glyph Loader.
7 * Copyright 1996-1999 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
10 * This file is part of the FreeType project, and may only be used
11 * modified and distributed under the terms of the FreeType project
12 * license, LICENSE.TXT. By continuing to use, modify, or distribute
13 * this file you indicate that you have read the license and
14 * understand and accept it fully.
16 ******************************************************************/
31 /* required by the tracing mode */
33 #define TT_COMPONENT trace_gload
36 /* composite font flags */
38 #define ARGS_ARE_WORDS 0x001
39 #define ARGS_ARE_XY_VALUES 0x002
40 #define ROUND_XY_TO_GRID 0x004
41 #define WE_HAVE_A_SCALE 0x008
43 #define MORE_COMPONENTS 0x020
44 #define WE_HAVE_AN_XY_SCALE 0x040
45 #define WE_HAVE_A_2X2 0x080
46 #define WE_HAVE_INSTR 0x100
47 #define USE_MY_METRICS 0x200
50 /********************************************************/
51 /* Return horizontal or vertical metrics in font units */
52 /* for a given glyph. The metrics are the left side */
53 /* bearing (resp. top side bearing) and advance width */
54 /* (resp. advance height). */
56 /* This function will much probably move to another */
57 /* component in the short future, but I haven't decided */
61 void TT_Get_Metrics( TT_Horizontal_Header
* header
,
68 UShort k
= header
->number_Of_HMetrics
;
73 longs_m
= (PLongMetrics
)header
->long_metrics
+ index
;
74 *bearing
= longs_m
->bearing
;
75 *advance
= longs_m
->advance
;
79 *bearing
= ((PShortMetrics
)header
->short_metrics
)[index
- k
];
80 *advance
= ((PLongMetrics
)header
->long_metrics
)[k
- 1].advance
;
85 /********************************************************/
86 /* Return horizontal metrics in font units for a given */
87 /* glyph. If `check' is true, take care of mono-spaced */
88 /* fonts by returning the advance width max. */
90 static void Get_HMetrics( PFace face
,
96 TT_Get_Metrics( &face
->horizontalHeader
, index
, lsb
, aw
);
98 if ( check
&& face
->postscript
.isFixedPitch
)
99 *aw
= face
->horizontalHeader
.advance_Width_Max
;
103 /********************************************************/
104 /* Return advance width table for a given pixel size */
105 /* if it is found in the font's `hdmx' table (if any). */
107 static PByte
Get_Advance_Widths( PFace face
,
113 for ( n
= 0; n
< face
->hdmx
.num_records
; n
++ )
114 if ( face
->hdmx
.records
[n
].ppem
== ppem
)
115 return face
->hdmx
.records
[n
].widths
;
121 /********************************************************/
122 /* Copy current glyph into original one. */
124 #define cur_to_org( n, zone ) \
125 MEM_Copy( (zone)->org, (zone)->cur, (n) * sizeof ( TT_Vector ) )
127 /********************************************************/
128 /* copy original glyph into current one */
130 #define org_to_cur( n, zone ) \
131 MEM_Copy( (zone)->cur, (zone)->org, (n) * sizeof ( TT_Vector ) )
133 /********************************************************/
134 /* translate an array of coordinates */
136 static void translate_array( UShort n
,
145 for ( k
= 0; k
< n
; k
++ )
146 coords
[k
].x
+= delta_x
;
149 for ( k
= 0; k
< n
; k
++ )
150 coords
[k
].y
+= delta_y
;
154 /********************************************************/
155 /* mount one zone on top of another */
157 static void mount_zone( PGlyph_Zone source
,
163 np
= source
->n_points
;
164 nc
= source
->n_contours
;
166 target
->org
= source
->org
+ np
;
167 target
->cur
= source
->cur
+ np
;
168 target
->touch
= source
->touch
+ np
;
170 target
->contours
= source
->contours
+ nc
;
172 target
->n_points
= 0;
173 target
->n_contours
= 0;
177 /*******************************************************************
179 * Function: Load_Simple_Glyph
181 ******************************************************************/
183 static TT_Error
Load_Simple_Glyph( PExecution_Context exec
,
189 PSubglyph_Record subg
)
191 DEFINE_LOAD_LOCALS( input
);
196 UShort n_points
, n_ins
;
206 if ( n_contours
> left_contours
)
208 PTRACE0(( "ERROR: Glyph index %ld has %d contours > left %d\n",
209 subg
->index
, n_contours
, left_contours
));
210 return TT_Err_Too_Many_Contours
;
214 /* preparing the execution context */
215 mount_zone( &subg
->zone
, &exec
->pts
);
217 /* reading the contours endpoints */
218 if ( ACCESS_Frame( (n_contours
+ 1) * 2L ) )
221 PTRACE4(( " Contour endpoints:" ));
223 for ( k
= 0; k
< n_contours
; k
++ )
225 exec
->pts
.contours
[k
] = GET_UShort();
226 PTRACE4(( " %d", exec
->pts
.contours
[k
] ));
230 if ( n_contours
> 0 )
231 n_points
= exec
->pts
.contours
[n_contours
- 1] + 1;
235 n_ins
= GET_UShort();
239 if ( n_points
> left_points
)
241 PTRACE0(( "ERROR: Too many points in glyph %ld\n", subg
->index
));
242 return TT_Err_Too_Many_Points
;
245 /* loading instructions */
247 PTRACE4(( " Instructions size: %d\n", n_ins
));
249 if ( n_ins
> face
->maxProfile
.maxSizeOfInstructions
)
251 PTRACE0(( "ERROR: Too many instructions!\n" ));
252 return TT_Err_Too_Many_Ins
;
255 if ( FILE_Read( exec
->glyphIns
, n_ins
) )
258 if ( (error
= Set_CodeRange( exec
,
261 n_ins
)) != TT_Err_Ok
)
267 if ( CHECK_ACCESS_Frame( n_points
* 5L ) )
271 flag
= exec
->pts
.touch
;
273 while ( j
< n_points
)
277 flag
[j
] = c
= GET_Byte();
296 for ( j
= 0; j
< n_points
; j
++ )
307 if ( (flag
[j
] & 16) == 0 )
319 for ( j
= 0; j
< n_points
; j
++ )
330 if ( (flag
[j
] & 32) == 0 )
339 /* Now add the two shadow points at n and n + 1. */
340 /* We need the left side bearing and advance width. */
342 /* pp1 = xMin - lsb */
343 vec
[n_points
].x
= subg
->metrics
.bbox
.xMin
- subg
->metrics
.horiBearingX
;
347 vec
[n_points
+1].x
= vec
[n_points
].x
+ subg
->metrics
.horiAdvance
;
348 vec
[n_points
+1].y
= 0;
350 /* clear the touch flags */
352 for ( j
= 0; j
< n_points
; j
++ )
353 exec
->pts
.touch
[j
] &= TT_Flag_On_Curve
;
355 exec
->pts
.touch
[n_points
] = 0;
356 exec
->pts
.touch
[n_points
+ 1] = 0;
358 /* Note that we return two more points that are not */
359 /* part of the glyph outline. */
363 /* now eventually scale and hint the glyph */
366 pts
->n_points
= n_points
;
367 pts
->n_contours
= n_contours
;
369 if ( (load_flags
& TTLOAD_SCALE_GLYPH
) == 0 )
371 /* no scaling, just copy the orig arrays into the cur ones */
372 org_to_cur( n_points
, pts
);
376 /* first scale the glyph points */
378 for ( j
= 0; j
< n_points
; j
++ )
380 pts
->org
[j
].x
= Scale_X( &exec
->metrics
, pts
->org
[j
].x
);
381 pts
->org
[j
].y
= Scale_Y( &exec
->metrics
, pts
->org
[j
].y
);
384 /* if hinting, round pp1, and shift the glyph accordingly */
385 if ( subg
->is_hinted
)
387 x
= pts
->org
[n_points
- 2].x
;
388 x
= ((x
+32) & -64) - x
;
389 translate_array( n_points
, pts
->org
, x
, 0 );
391 org_to_cur( n_points
, pts
);
393 pts
->cur
[n_points
- 1].x
= (pts
->cur
[n_points
- 1].x
+ 32) & -64;
395 /* now consider hinting */
398 exec
->is_composite
= FALSE
;
399 exec
->pedantic_hinting
= load_flags
& TTLOAD_PEDANTIC
;
401 error
= Context_Run( exec
, FALSE
);
402 if (error
&& exec
->pedantic_hinting
)
407 org_to_cur( n_points
, pts
);
410 /* save glyph phantom points */
411 if (!subg
->preserve_pps
)
413 subg
->pp1
= pts
->cur
[n_points
- 2];
414 subg
->pp2
= pts
->cur
[n_points
- 1];
421 /*******************************************************************
423 * Function : Load_Composite_End
425 ******************************************************************/
428 TT_Error
Load_Composite_End( UShort n_points
,
430 PExecution_Context exec
,
431 PSubglyph_Record subg
,
435 DEFINE_LOAD_LOCALS( input
);
441 if ( subg
->is_hinted
&&
442 subg
->element_flag
& WE_HAVE_INSTR
)
444 if ( ACCESS_Frame( 2L ) )
447 n_ins
= GET_UShort(); /* read size of instructions */
450 PTRACE4(( " Instructions size: %d\n", n_ins
));
452 if ( n_ins
> exec
->face
->maxProfile
.maxSizeOfInstructions
)
454 PTRACE0(( "ERROR: Too many instructions in composite glyph %ld\n",
456 return TT_Err_Too_Many_Ins
;
459 if ( FILE_Read( exec
->glyphIns
, n_ins
) )
462 error
= Set_CodeRange( exec
,
474 /* prepare the execution context */
476 exec
->pts
= subg
->zone
;
479 pts
->n_points
= n_points
;
480 pts
->n_contours
= n_contours
;
482 /* add phantom points */
483 pts
->cur
[n_points
- 2] = subg
->pp1
;
484 pts
->cur
[n_points
- 1] = subg
->pp2
;
486 pts
->touch
[n_points
- 1] = 0;
487 pts
->touch
[n_points
- 2] = 0;
489 /* if hinting, round the phantom points */
490 if ( subg
->is_hinted
)
492 pts
->cur
[n_points
- 2].x
= (subg
->pp1
.x
+ 32) & -64;
493 pts
->cur
[n_points
- 1].x
= (subg
->pp2
.x
+ 32) & -64;
496 for ( k
= 0; k
< n_points
; k
++ )
497 pts
->touch
[k
] &= TT_Flag_On_Curve
;
499 cur_to_org( n_points
, pts
);
501 /* now consider hinting */
502 if ( subg
->is_hinted
&& n_ins
> 0 )
504 exec
->is_composite
= TRUE
;
505 exec
->pedantic_hinting
= load_flags
& TTLOAD_PEDANTIC
;
507 error
= Context_Run( exec
, FALSE
);
508 if (error
&& exec
->pedantic_hinting
)
512 /* save glyph origin and advance points */
513 subg
->pp1
= pts
->cur
[n_points
- 2];
514 subg
->pp2
= pts
->cur
[n_points
- 1];
520 /*******************************************************************
522 * Function : Init_Glyph_Component
524 ******************************************************************/
527 void Init_Glyph_Component( PSubglyph_Record element
,
528 PSubglyph_Record original
,
529 PExecution_Context exec
)
532 element
->is_scaled
= FALSE
;
533 element
->is_hinted
= FALSE
;
536 mount_zone( &original
->zone
, &element
->zone
);
538 element
->zone
= exec
->pts
;
540 element
->zone
.n_contours
= 0;
541 element
->zone
.n_points
= 0;
546 element
->element_flag
= 0;
547 element
->preserve_pps
= FALSE
;
549 element
->transform
.xx
= 1L << 16;
550 element
->transform
.xy
= 0;
551 element
->transform
.yx
= 0;
552 element
->transform
.yy
= 1L << 16;
554 element
->transform
.ox
= 0;
555 element
->transform
.oy
= 0;
557 element
->metrics
.horiBearingX
= 0;
558 element
->metrics
.horiAdvance
= 0;
564 TT_Error
Load_TrueType_Glyph( PInstance instance
,
579 typedef enum TPhases_ TPhases
;
589 UShort num_elem_points
;
598 Long glyph_offset
, offset
;
600 TT_F26Dot6 x
, y
, nx
, ny
;
602 Fixed xx
, xy
, yx
, yy
;
604 PExecution_Context exec
;
606 PSubglyph_Record subglyph
, subglyph2
;
608 TGlyph_Zone base_pts
;
613 /* TT_Glyph_Loader_Callback cacheCb; */
614 /* TT_Outline cached_outline; */
617 /* first of all, check arguments */
619 return TT_Err_Invalid_Glyph_Handle
;
623 return TT_Err_Invalid_Glyph_Handle
;
625 if ( glyph_index
>= face
->numGlyphs
)
626 return TT_Err_Invalid_Glyph_Index
;
628 if ( instance
&& (load_flags
& TTLOAD_SCALE_GLYPH
) == 0 )
631 load_flags
&= ~( TTLOAD_SCALE_GLYPH
| TTLOAD_HINT_GLYPH
);
634 table
= TT_LookUp_Table( face
, TTAG_glyf
);
637 PTRACE0(( "ERROR: There is no glyph table in this font file!\n" ));
638 return TT_Err_Glyf_Table_Missing
;
641 glyph_offset
= face
->dirTables
[table
].Offset
;
643 /* query new execution context */
645 if ( instance
&& instance
->debug
)
646 exec
= instance
->context
;
648 exec
= New_Context( face
);
651 return TT_Err_Could_Not_Find_Context
;
653 Context_Load( exec
, face
, instance
);
657 if ( instance
->GS
.instruct_control
& 2 )
658 exec
->GS
= Default_GraphicsState
;
660 exec
->GS
= instance
->GS
;
661 /* load default graphics state */
663 glyph
->outline
.high_precision
= ( instance
->metrics
.y_ppem
< 24 );
666 /* save its critical pointers, as they'll be modified during load */
667 base_pts
= exec
->pts
;
670 left_points
= face
->maxPoints
;
671 left_contours
= face
->maxContours
;
677 subglyph
= exec
->loadStack
;
679 Init_Glyph_Component( subglyph
, NULL
, exec
);
681 subglyph
->index
= glyph_index
;
682 subglyph
->is_hinted
= load_flags
& TTLOAD_HINT_GLYPH
;
684 /* when the cvt program has disabled hinting, the argument */
686 if ( instance
&& instance
->GS
.instruct_control
& 1 )
687 subglyph
->is_hinted
= FALSE
;
690 /* now access stream */
692 if ( USE_Stream( face
->stream
, stream
) )
695 /* Main loading loop */
700 while ( phase
!= Load_Exit
)
702 subglyph
= exec
->loadStack
+ load_top
;
706 /************************************************************/
708 /* Load_Glyph state */
710 /* reading a glyph's generic header to determine */
711 /* whether it's simple or composite */
713 /* exit states: Load_Header and Load_End */
716 /* check glyph index and table */
718 index
= subglyph
->index
;
719 if ( index
< 0 || index
>= face
->numGlyphs
)
721 error
= TT_Err_Invalid_Glyph_Index
;
725 /* get horizontal metrics */
729 UShort advance_width
;
732 Get_HMetrics( face
, (UShort
)index
,
733 !(load_flags
& TTLOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
),
737 subglyph
->metrics
.horiBearingX
= left_bearing
;
738 subglyph
->metrics
.horiAdvance
= advance_width
;
744 /* The cache callback isn't part of the FreeType release yet */
745 /* It is discarded for the moment.. */
750 /* is the glyph in an outline cache ? */
751 cacheCb
= instance
->owner
->engine
->glCallback
;
752 if ( cacheCb
&& 0 ) /* disabled */
754 /* we have a callback */
755 error
= cacheCb( instance
->generic
,
756 index
, &cached_outline
, &x
, &y
);
759 /* no error, then append the outline to the current subglyph */
760 /* error = Append_Outline( subglyph,
763 &cached_outline ); */
772 /************************************************************/
774 /* Load_Header state */
776 /* reading a glyph's generic header to determine */
777 /* wether it's simple or composite */
779 /* exit states: Load_Simple and Load_Composite */
782 case Load_Header
: /* load glyph */
784 if ( index
+ 1 < face
->numLocations
&&
785 face
->glyphLocations
[index
] == face
->glyphLocations
[index
+ 1] )
787 /* as described by Frederic Loyer, these are spaces, and */
788 /* not the unknown glyph. */
793 subglyph
->metrics
.bbox
.xMin
= 0;
794 subglyph
->metrics
.bbox
.xMax
= 0;
795 subglyph
->metrics
.bbox
.yMin
= 0;
796 subglyph
->metrics
.bbox
.yMax
= 0;
799 subglyph
->pp2
.x
= subglyph
->metrics
.horiAdvance
;
800 if (load_flags
& TTLOAD_SCALE_GLYPH
)
801 subglyph
->pp2
.x
= Scale_X( &exec
->metrics
, subglyph
->pp2
.x
);
808 offset
= glyph_offset
+ face
->glyphLocations
[index
];
810 /* read first glyph header */
811 if ( FILE_Seek( offset
) ||
812 ACCESS_Frame( 10L ) )
815 num_contours
= GET_Short();
817 subglyph
->metrics
.bbox
.xMin
= GET_Short();
818 subglyph
->metrics
.bbox
.yMin
= GET_Short();
819 subglyph
->metrics
.bbox
.xMax
= GET_Short();
820 subglyph
->metrics
.bbox
.yMax
= GET_Short();
824 PTRACE6(( "Glyph %ld:\n", index
));
825 PTRACE6(( " # of contours: %d\n", num_contours
));
826 PTRACE6(( " xMin: %4d xMax: %4d\n",
827 subglyph
->metrics
.bbox
.xMin
,
828 subglyph
->metrics
.bbox
.xMax
));
829 PTRACE6(( " yMin: %4d yMax: %4d\n",
830 subglyph
->metrics
.bbox
.yMin
,
831 subglyph
->metrics
.bbox
.yMax
));
833 if ( num_contours
> left_contours
)
835 PTRACE0(( "ERROR: Too many contours for glyph %ld\n", index
));
836 error
= TT_Err_Too_Many_Contours
;
840 subglyph
->pp1
.x
= subglyph
->metrics
.bbox
.xMin
-
841 subglyph
->metrics
.horiBearingX
;
843 subglyph
->pp2
.x
= subglyph
->pp1
.x
+ subglyph
->metrics
.horiAdvance
;
844 if (load_flags
& TTLOAD_SCALE_GLYPH
)
846 subglyph
->pp1
.x
= Scale_X( &exec
->metrics
, subglyph
->pp1
.x
);
847 subglyph
->pp2
.x
= Scale_X( &exec
->metrics
, subglyph
->pp2
.x
);
850 /* is it a simple glyph ? */
851 if ( num_contours
> 0 )
854 phase
= Load_Composite
;
859 /************************************************************/
861 /* Load_Simple state */
863 /* reading a simple glyph (num_contours must be set to */
864 /* the glyph's number of contours.) */
866 /* exit states : Load_End */
870 new_flags
= load_flags
;
872 /* disable hinting when scaling */
873 if ( !subglyph
->is_hinted
)
874 new_flags
&= ~TTLOAD_HINT_GLYPH
;
876 error
= Load_Simple_Glyph( exec
,
886 /* Note: We could have put the simple loader source there */
887 /* but the code is fat enough already :-) */
889 num_points
= exec
->pts
.n_points
- 2;
896 /************************************************************/
898 /* Load_Composite state */
900 /* reading a composite glyph header a pushing a new */
901 /* load element on the stack. */
903 /* exit states: Load_Glyph */
908 /* create a new element on the stack */
911 if ( load_top
> face
->maxComponents
)
913 error
= TT_Err_Invalid_Composite
;
917 subglyph2
= exec
->loadStack
+ load_top
;
919 Init_Glyph_Component( subglyph2
, subglyph
, NULL
);
920 subglyph2
->is_hinted
= subglyph
->is_hinted
;
922 /* now read composite header */
924 if ( ACCESS_Frame( 4L ) )
927 subglyph
->element_flag
= new_flags
= GET_UShort();
929 subglyph2
->index
= GET_UShort();
935 if ( new_flags
& ARGS_ARE_WORDS
)
938 if ( new_flags
& WE_HAVE_A_SCALE
)
941 else if ( new_flags
& WE_HAVE_AN_XY_SCALE
)
944 else if ( new_flags
& WE_HAVE_A_2X2
)
947 if ( ACCESS_Frame( k
) )
950 if ( new_flags
& ARGS_ARE_WORDS
)
964 if ( new_flags
& ARGS_ARE_XY_VALUES
)
966 subglyph
->transform
.ox
= k
;
967 subglyph
->transform
.oy
= l
;
975 if ( new_flags
& WE_HAVE_A_SCALE
)
977 xx
= (Fixed
)GET_Short() << 2;
979 subglyph2
->is_scaled
= TRUE
;
981 else if ( new_flags
& WE_HAVE_AN_XY_SCALE
)
983 xx
= (Fixed
)GET_Short() << 2;
984 yy
= (Fixed
)GET_Short() << 2;
985 subglyph2
->is_scaled
= TRUE
;
987 else if ( new_flags
& WE_HAVE_A_2X2
)
989 xx
= (Fixed
)GET_Short() << 2;
990 xy
= (Fixed
)GET_Short() << 2;
991 yx
= (Fixed
)GET_Short() << 2;
992 yy
= (Fixed
)GET_Short() << 2;
993 subglyph2
->is_scaled
= TRUE
;
998 subglyph
->transform
.xx
= xx
;
999 subglyph
->transform
.xy
= xy
;
1000 subglyph
->transform
.yx
= yx
;
1001 subglyph
->transform
.yy
= yy
;
1003 k
= TT_MulFix( xx
, yy
) - TT_MulFix( xy
, yx
);
1005 /* disable hinting in case of scaling/slanting */
1006 if ( ABS( k
) != (1L << 16) )
1007 subglyph2
->is_hinted
= FALSE
;
1009 subglyph
->file_offset
= FILE_Pos();
1016 /************************************************************/
1018 /* Load_End state */
1020 /* after loading a glyph, apply transformation and offset */
1021 /* where necessary, pops element and continue or */
1024 /* exit states : Load_Composite and Load_Exit */
1030 subglyph2
= subglyph
;
1033 subglyph
= exec
->loadStack
+ load_top
;
1035 /* check advance width and left side bearing */
1037 if ( !subglyph
->preserve_pps
&&
1038 subglyph
->element_flag
& USE_MY_METRICS
)
1040 subglyph
->metrics
.horiBearingX
= subglyph2
->metrics
.horiBearingX
;
1041 subglyph
->metrics
.horiAdvance
= subglyph2
->metrics
.horiAdvance
;
1043 subglyph
->pp1
= subglyph2
->pp1
;
1044 subglyph
->pp2
= subglyph2
->pp2
;
1046 subglyph
->preserve_pps
= TRUE
;
1051 if ( subglyph2
->is_scaled
)
1053 TT_Vector
* cur
= subglyph2
->zone
.cur
;
1054 TT_Vector
* org
= subglyph2
->zone
.org
;
1056 for ( u
= 0; u
< num_points
; u
++ )
1058 nx
= TT_MulFix( cur
->x
, subglyph
->transform
.xx
) +
1059 TT_MulFix( cur
->y
, subglyph
->transform
.yx
);
1061 ny
= TT_MulFix( cur
->x
, subglyph
->transform
.xy
) +
1062 TT_MulFix( cur
->y
, subglyph
->transform
.yy
);
1067 nx
= TT_MulFix( org
->x
, subglyph
->transform
.xx
) +
1068 TT_MulFix( org
->y
, subglyph
->transform
.yx
);
1070 ny
= TT_MulFix( org
->x
, subglyph
->transform
.xy
) +
1071 TT_MulFix( org
->y
, subglyph
->transform
.yy
);
1083 num_elem_points
= subglyph
->zone
.n_points
;
1085 for ( k
= 0; k
< num_contours
; k
++ )
1086 subglyph2
->zone
.contours
[k
] += num_elem_points
;
1088 subglyph
->zone
.n_points
+= num_points
;
1089 subglyph
->zone
.n_contours
+= num_contours
;
1091 left_points
-= num_points
;
1092 left_contours
-= num_contours
;
1094 if ( !(subglyph
->element_flag
& ARGS_ARE_XY_VALUES
) )
1096 /* move second glyph according to control points */
1097 /* the attach points are relative to the specific component */
1099 u
= (UShort
)subglyph
->arg1
;
1100 v
= (UShort
)subglyph
->arg2
;
1102 if ( u
>= num_elem_points
||
1105 error
= TT_Err_Invalid_Composite
;
1110 v
+= num_elem_points
;
1112 x
= subglyph
->zone
.cur
[u
].x
- subglyph
->zone
.cur
[v
].x
;
1113 y
= subglyph
->zone
.cur
[u
].y
- subglyph
->zone
.cur
[v
].y
;
1119 x
= subglyph
->transform
.ox
;
1120 y
= subglyph
->transform
.oy
;
1122 if ( load_flags
& TTLOAD_SCALE_GLYPH
)
1124 x
= Scale_X( &exec
->metrics
, x
);
1125 y
= Scale_Y( &exec
->metrics
, y
);
1127 if ( subglyph
->element_flag
& ROUND_XY_TO_GRID
)
1135 translate_array( num_points
, subglyph2
->zone
.cur
, x
, y
);
1137 cur_to_org( num_points
, &subglyph2
->zone
);
1139 num_points
= subglyph
->zone
.n_points
;
1140 num_contours
= subglyph
->zone
.n_contours
;
1142 /* check for last component */
1144 if ( FILE_Seek( subglyph
->file_offset
) )
1147 if ( subglyph
->element_flag
& MORE_COMPONENTS
)
1148 phase
= Load_Composite
;
1151 error
= Load_Composite_End( num_points
,
1174 /* finally, copy the points arrays to the glyph object */
1176 exec
->pts
= base_pts
;
1178 for ( u
= 0; u
< num_points
+ 2; u
++ )
1180 glyph
->outline
.points
[u
] = exec
->pts
.cur
[u
];
1181 glyph
->outline
.flags
[u
] = exec
->pts
.touch
[u
];
1184 for ( k
= 0; k
< num_contours
; k
++ )
1185 glyph
->outline
.contours
[k
] = exec
->pts
.contours
[k
];
1187 glyph
->outline
.n_points
= num_points
;
1188 glyph
->outline
.n_contours
= num_contours
;
1189 glyph
->outline
.second_pass
= TRUE
;
1191 /* translate array so that (0,0) is the glyph's origin */
1192 translate_array( num_points
+ 2,
1193 glyph
->outline
.points
,
1197 TT_Get_Outline_BBox( &glyph
->outline
, &glyph
->metrics
.bbox
);
1199 if ( subglyph
->is_hinted
)
1201 /* grid-fit the bounding box */
1202 glyph
->metrics
.bbox
.xMin
&= -64;
1203 glyph
->metrics
.bbox
.yMin
&= -64;
1204 glyph
->metrics
.bbox
.xMax
= (glyph
->metrics
.bbox
.xMax
+63) & -64;
1205 glyph
->metrics
.bbox
.yMax
= (glyph
->metrics
.bbox
.yMax
+63) & -64;
1208 /* get the device-independent scaled horizontal metrics */
1209 /* take care of fixed-pitch fonts... */
1211 TT_Pos left_bearing
;
1215 left_bearing
= subglyph
->metrics
.horiBearingX
;
1216 advance
= subglyph
->metrics
.horiAdvance
;
1218 if ( face
->postscript
.isFixedPitch
)
1219 advance
= face
->horizontalHeader
.advance_Width_Max
;
1221 if ( load_flags
& TTLOAD_SCALE_GLYPH
)
1223 left_bearing
= Scale_X( &exec
->metrics
, left_bearing
);
1224 advance
= Scale_X( &exec
->metrics
, advance
);
1227 glyph
->metrics
.linearHoriBearingX
= left_bearing
;
1228 glyph
->metrics
.linearHoriAdvance
= advance
;
1231 glyph
->metrics
.horiBearingX
= glyph
->metrics
.bbox
.xMin
;
1232 glyph
->metrics
.horiBearingY
= glyph
->metrics
.bbox
.yMax
;
1233 glyph
->metrics
.horiAdvance
= subglyph
->pp2
.x
- subglyph
->pp1
.x
;
1235 /* Now take care of vertical metrics. In the case where there is */
1236 /* no vertical information within the font (relatively common), make */
1237 /* up some metrics `by hand' ... */
1240 Short top_bearing
; /* vertical top side bearing (EM units) */
1241 UShort advance_height
; /* vertical advance height (EM units) */
1243 TT_Pos left
; /* scaled vertical left side bearing */
1244 TT_Pos Top
; /* scaled original vertical top side bearing */
1245 TT_Pos top
; /* scaled vertical top side bearing */
1246 TT_Pos advance
; /* scaled vertical advance height */
1249 /* Get the unscaled `tsb' and `ah' values */
1250 if ( face
->verticalInfo
&&
1251 face
->verticalHeader
.number_Of_VMetrics
> 0 )
1253 /* Don't assume that both the vertical header and vertical */
1254 /* metrics are present in the same font :-) */
1256 TT_Get_Metrics( (TT_Horizontal_Header
*)&face
->verticalHeader
,
1263 /* Make up the distances from the horizontal header.. */
1265 /* NOTE: The OS/2 values are the only `portable' ones, */
1266 /* which is why we use them... */
1268 /* NOTE2: The sTypoDescender is negative, which is why */
1269 /* we compute the baseline-to-baseline distance */
1271 /* ascender - descender + linegap */
1273 top_bearing
= (Short
) (face
->os2
.sTypoLineGap
/ 2);
1274 advance_height
= (UShort
)(face
->os2
.sTypoAscender
-
1275 face
->os2
.sTypoDescender
+
1276 face
->os2
.sTypoLineGap
);
1279 /* We must adjust the top_bearing value from the bounding box given
1280 in the glyph header to te bounding box calculated with
1281 TT_Get_Outline_BBox() */
1283 /* scale the metrics */
1284 if ( load_flags
& TTLOAD_SCALE_GLYPH
)
1286 Top
= Scale_Y( &exec
->metrics
, top_bearing
);
1287 top
= Scale_Y( &exec
->metrics
,
1288 top_bearing
+ subglyph
->metrics
.bbox
.yMax
) -
1289 glyph
->metrics
.bbox
.yMax
;
1290 advance
= Scale_Y( &exec
->metrics
, advance_height
);
1295 top
= top_bearing
+ subglyph
->metrics
.bbox
.yMax
-
1296 glyph
->metrics
.bbox
.yMax
;
1297 advance
= advance_height
;
1300 glyph
->metrics
.linearVertBearingY
= Top
;
1301 glyph
->metrics
.linearVertAdvance
= advance
;
1303 /* XXX : for now, we have no better algo for the lsb, but it should */
1306 left
= ( glyph
->metrics
.bbox
.xMin
- glyph
->metrics
.bbox
.xMax
) / 2;
1308 /* grid-fit them if necessary */
1309 if ( subglyph
->is_hinted
)
1312 top
= (top
+ 63) & -64;
1313 advance
= (advance
+ 32) & -64;
1316 glyph
->metrics
.vertBearingX
= left
;
1317 glyph
->metrics
.vertBearingY
= top
;
1318 glyph
->metrics
.vertAdvance
= advance
;
1321 /* Adjust advance width to the value contained in the hdmx table. */
1322 if ( !exec
->face
->postscript
.isFixedPitch
&& instance
&&
1323 subglyph
->is_hinted
)
1325 widths
= Get_Advance_Widths( exec
->face
,
1326 exec
->instance
->metrics
.x_ppem
);
1328 glyph
->metrics
.horiAdvance
= widths
[glyph_index
] << 6;
1331 glyph
->outline
.dropout_mode
= (Char
)exec
->GS
.scan_type
;
1337 DONE_Stream( stream
);
1341 /* reset the execution context */
1342 exec
->pts
= base_pts
;
1344 if ( !instance
|| !instance
->debug
)
1345 Done_Context( exec
);