1
(*******************************************************************
5
* TrueType glyph loader
7
* Copyright 1996, 1997 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
******************************************************************)
25
FreeType, TTError, TTTypes, TTObjs;
27
function Load_TrueType_Glyph( instance : PInstance;
30
load_flags : Int ) : TError;
31
(* loads a font glyph into a given glyph info. The instance and *)
32
(* glyph objects faces _must_ match. The load_flags indicates *)
33
(* what kind of values should be written to the glyph object *)
34
(* ( metrics, outline in EM coordinates, grid-fitted outline.. ) *)
36
(* by default ( i.e. with load_flags = 0 ), this function only *)
37
(* returns the unscaled glyph metrics and points in EM units. *)
39
(* Use the following flags to query scaling and hinting ops. *)
41
(********************************************************)
42
(* return horizontal or vertical metrics in font units *)
43
(* for a given glyph. The metrics are the left side *)
44
(* bearing [resp. top side bearing] and advance width *)
45
(* [resp. advance height]. *)
47
(* This function may move later to another component.. *)
49
procedure TT_Get_Metrics( var header : TT_Horizontal_Header;
52
var advance : TT_Pos );
54
function Get_Advance_Widths( face : PFace;
69
ARGS_ARE_XY_VALUES = $02;
70
ROUND_XY_TO_GRID = $04;
71
WE_HAVE_A_SCALE = $08;
73
MORE_COMPONENTS = $20;
74
WE_HAVE_AN_XY_SCALE = $40;
77
USE_MY_METRICS = $200;
80
(********************************************************)
81
(* return horizontal or vertical metrics in font units *)
82
(* for a given glyph. The metrics are the left side *)
83
(* bearing [resp. top side bearing] and advance width *)
84
(* [resp. advance height]. *)
86
(* This function may move later to another component.. *)
88
procedure TT_Get_Metrics( var header : TT_Horizontal_Header;
91
var advance : TT_Pos );
94
longs : PTableLongMetrics;
96
k := header.number_Of_HMetrics;
100
longs := PTableLongMetrics(header.long_metrics);
101
bearing := longs^[index].bearing;
102
advance := longs^[index].advance;
106
bearing := PTableShortMetrics(header.short_metrics)^[index-k];
107
advance := PTableLongMetrics(header.long_metrics)^[k-1].advance;
113
(********************************************************)
114
(* return horizontal metrics in font units for a *)
115
(* given glyph. if "check" is true, take care of *)
116
(* mono-spaced fonts by returning the aw max. *)
118
procedure Get_HMetrics( face : PFace;
124
left_bearing, advance : TT_Pos;
126
TT_Get_Metrics( face^.horizontalHeader, index, left_bearing, advance );
128
lsb := Int(left_bearing);
131
if check and (face^.postscript.isFixedPitch <> 0) then
132
aw := face^.horizontalHeader.advance_Width_Max;
137
(********************************************************)
138
(* return advance width table for a given pixel size *)
139
(* if it is found in the font's "hdmx" table (if any) *)
141
function Get_Advance_Widths( face : PFace;
142
ppem : Int ) : PByte;
147
for n := 0 to num_records-1 do
148
if records^[n].ppem = ppem then
150
Get_Advance_Widths := records^[n].widths;
154
Get_Advance_Widths := nil;
157
(********************************************************)
158
(* copy current glyph into original one *)
160
procedure cur_to_org( n : int;
165
for k := 0 to n-1 do with pts^ do
170
(********************************************************)
171
(* copy original glyph into current one *)
173
procedure org_to_cur( n : int;
178
for k := 0 to n-1 do with pts^ do
182
(********************************************************)
183
(* translate an array of coordinates *)
185
procedure translate_array( n : int;
192
for k := 0 to n-1 do inc( coords^[k].x, dx );
194
for k := 0 to n-1 do inc( coords^[k].y, dy );
197
(********************************************************)
198
(* mount one zone on top of another one *)
200
procedure mount_zone( var source : TGlyph_Zone;
201
var target : TGlyph_Zone );
205
np := source.n_points;
206
nc := source.n_contours;
208
target.org := @source.org^[np];
209
target.cur := @source.cur^[np];
210
target.flags := @source.flags^[np];
212
target.conEnds := @source.conEnds^[nc];
214
target.n_points := 0;
215
target.n_contours := 0;
218
(*******************************************************************
220
* Function : Load_Simple_Glyph
223
******************************************************************)
226
function Load_Simple_Glyph( exec : PExec_Context;
232
subg : PSubGlyph_Record ) : TError;
240
flag : TT_PTouchTable;
245
Fail, Fail_File, Fail_Exec;
247
Load_Simple_Glyph := Failure;
253
if ( n_contours > left_contours ) then
256
Writeln( 'ERROR: Glyph index ',i,' has ',Gl.numberOfContours );
257
Writeln( ' contours > left ', left_contours );
259
error := TT_Err_Too_Many_Contours;
263
(* preparing the execution context *)
264
mount_zone( subg^.zone, exec^.pts );
266
(* Reading the contours endpoints *)
268
if TT_Access_Frame( (n_contours+1)*2 ) then
273
for k := 0 to n_contours-1 do
275
{$IFDEF DEBUG} Write( n_points,' '); {$ENDIF}
276
n_points := GET_Short;
277
exec^.pts.conEnds^[k] := n_points;
281
if n_points > left_points then
283
{$IFDEF DEBUG} Writeln( 'ERROR: Too many points' ); {$ENDIF}
284
error := TT_Err_Too_Many_Points;
288
(* Loading instructions *)
295
if not subg^.is_hinted then
297
if TT_Skip_File( n_ins ) then
300
(* skip the instructions *)
305
{$IFDEF DEBUG} Writeln('Instructions size : ', n_ins); {$ENDIF}
307
if n_ins > face^.maxProfile.maxSizeOfInstructions then
309
{$IFDEF DEBUG} Writeln('Too many instructions'); {$ENDIF}
310
error := TT_Err_Too_Many_Ins;
316
if TT_Read_File( glyphIns^, n_ins ) then
321
if Set_CodeRange( exec,
331
if TT_Check_And_Access_Frame( n_points*5 )
335
flag := exec^.pts.flags;
337
while ( k < n_points ) do
359
coords := exec^.pts.org;
361
for k := 0 to n_points-1 do
363
if flag^[k] and 2 <> 0 then
365
if flag^[k] and 16 <> 0 then inc( x, GET_Byte )
366
else inc( x, -GET_Byte )
368
if flag^[k] and 16 = 0 then inc( x, GET_Short );
377
for k := 0 to n_points-1 do
379
if flag^[k] and 4 <> 0 then
381
if flag^[k] and 32 <> 0 then inc( y, GET_Byte )
382
else inc( y, -GET_Byte )
384
if flag^[k] and 32 = 0 then inc( y, GET_Short );
391
(* Now adds the two shadow points at n and n+1 *)
392
(* We need the left side bearing and advance width *)
394
(* pp1 = xMin - lsb == glyph origin *)
395
coords^[n_points].x := subg^.bbox.XMin-subg^.leftBearing;
396
coords^[n_points].y := 0;
398
(* pp2 = pp1 + aw == glyph next position *)
399
coords^[n_points+1].x := subg^.bbox.xMin-
400
subg^.leftBearing + subg^.advanceWidth;
401
coords^[n_points+1].y := 0;
403
for k := 0 to n_points-1 do
404
exec^.pts.flags^[k] := exec^.pts.flags^[k] and TT_Flag_On_Curve;
406
exec^.pts.flags^[n_points ] := 0;
407
exec^.pts.flags^[n_points+1] := 0;
409
(* Note that we now return two more points, that are not *)
410
(* part of the glyph outline *)
413
(* now eventually scale and hint the glyph *)
416
pts^.n_points := n_points;
418
exec^.pts.n_contours := n_contours;
420
if load_flags and TT_Load_Scale_Glyph = 0 then
422
(* no scaling, just copy the org arrays into the cur ones *)
423
org_to_cur( n_points, pts );
428
(* first scale the glyph points *)
429
for k := 0 to n_points-1 do with pts^ do
430
org^[k].x := Scale_X( exec^.metrics, org^[k].x );
432
for k := 0 to n_points-1 do with pts^ do
433
org^[k].y := Scale_Y( exec^.metrics, org^[k].y );
435
(* if hinting, round pp1, and shift the glyph accordingly *)
436
if subg^.is_hinted then
438
x := pts^.org^[n_points-2].x;
439
x := ((x+32) and -64) - x;
440
translate_array( n_points, pts^.org, x, 0 );
442
org_to_cur( n_points, pts );
444
(* set the advance width *)
446
x := (Scale_X( exec^.metrics, subg^.advanceWidth )+32) and -64;
448
cur_x^[n_points-1] := cur_x^[n_points-2]+x;
451
cur^[n_points-1].x := (cur^[n_points-1].x+32) and -64;
453
(* now consider hinting *)
454
if (exec^.glyphSize > 0) then
456
exec^.is_composite := False;
458
if Context_Run( exec, load_flags and TT_Load_Debug <> 0 ) then
463
org_to_cur( n_points, pts );
466
(* save glyph origin and advance points *)
467
if not subg^.preserve_pps then
469
subg^.pp1 := pts^.cur^[n_points-2];
470
subg^.pp2 := pts^.cur^[n_points-1];
473
Load_Simple_Glyph := Success;
479
error := TT_Err_File_Error;
483
error := exec^.error;
487
(*******************************************************************
489
* Function : Load_Composite_End
492
******************************************************************)
494
function Load_Composite_End( n_points : Int;
496
exec : PExec_Context;
497
subg : PSubglyph_Record;
498
debug : Boolean ) : TError;
509
Fail, Fail_File, Fail_Exec;
511
Load_Composite_End := Failure;
513
if subg^.is_hinted and
514
(subg^.element_flag and WE_HAVE_INSTR <> 0) then
516
if TT_Access_Frame(2) then goto Fail_File;
520
(* load the instructions *)
521
{$IFDEF DEBUG} Writeln('Instructions size : ', n_ins); {$ENDIF}
523
if n_ins > exec^.face^.maxProfile.maxSizeOfInstructions then
525
{$IFDEF DEBUG} Writeln('Too many instructions'); {$ENDIF}
526
error := TT_Err_Too_Many_Ins;
533
if n_ins > 0 then with exec^ do
535
if TT_Read_File( glyphIns^, n_ins ) then
540
if Set_CodeRange( exec,
543
glyphSize ) then goto Fail_File;
546
(* prepare the execution context *)
549
exec^.pts := subg^.zone;
551
pts^.n_points := n_points;
553
(* add phantom points *)
556
cur^[n_points-2] := subg^.pp1;
557
cur^[n_points-1] := subg^.pp2;
558
flags^[n_points-2] := 0;
559
flags^[n_points-1] := 0;
562
(* if hinting, round the phantom points *)
563
if subg^.is_hinted then
565
y := ((subg^.pp1.x+32) and -64);
566
pts^.cur^[n_points-2].y := y;
568
x := ((subg^.pp2.x+32) and -64);
569
pts^.cur^[n_points-1].x := x;
572
for k := 0 to n_points-1 do
573
pts^.flags^[k] := pts^.flags^[k] and TT_Flag_On_Curve;
575
cur_to_org( n_points, pts );
577
(* now consider hinting *)
578
if subg^.is_hinted and (n_ins > 0) then
580
exec^.is_composite := true;
582
if Context_Run( exec, debug ) then
586
(* save glyph origin and advance points *)
587
subg^.pp1 := pts^.cur^[n_points-2];
588
subg^.pp2 := pts^.cur^[n_points-1];
590
Load_Composite_End := Success;
597
error := TT_Err_File_Error;
601
error := exec^.error;
607
(*******************************************************************
609
* Function : Init_Glyph_Component
612
******************************************************************)
615
procedure Init_Glyph_Component( element : PSubGlyph_Record;
616
original : PSubGlyph_Record;
617
exec : PExec_Context );
627
if original <> nil then
628
mount_zone( original^.zone, zone )
632
zone.n_contours := 0;
639
preserve_pps := false;
641
transform.xx := 1 shl 16;
644
transform.yy := 1 shl 16;
655
function Load_TrueType_Glyph( instance : PInstance;
658
load_flags : Int ) : TError;
660
TPhases = ( Load_Exit,
665
(* the composite loader is a simple automata wich states *)
666
(* are defined by the TPhases enumeration *)
681
new_flags, k, l : Int;
683
glyph_offset, offset : Long;
687
vec, nvec : TT_Vector;
689
xmin, xmax, ymin, ymax : TT_F26Dot6;
691
xx, xy, yx, yy : TT_Fixed;
693
exec : PExec_Context;
696
subglyph, subglyph2 : PSubGlyph_Record;
698
base_pts : TGlyph_Zone;
704
leftSideBearing : TT_Pos;
705
advanceWidth : TT_Pos;
707
top_bearing : TT_Pos;
708
advance_height : TT_Pos;
713
horizontal : TT_Horizontal_Header;
723
Load_TrueType_Glyph := Failure;
727
if (instance = nil) or (instance^.owner = nil) then
729
error := TT_Err_Invalid_Face_Handle;
733
face := instance^.owner;
735
table := LookUp_TrueType_Table( face, 'glyf');
739
Trace1( 'TTApi.load_glyph : couldn''t find glyf table' );
741
error := TT_Err_Table_Missing;
745
glyph_offset := face^.dirTables^[table].Offset;
747
(* query new execution context *)
749
if instance^.debug then
750
exec := instance^.context (* if debugging, use the pre-alloced context *)
752
exec := New_Context(instance);
756
error := TT_Err_Out_Of_Memory;
760
Context_Load( exec, instance );
761
if instance^.GS.instruct_control and 2 <> 0 then
762
exec^.GS := Default_GraphicsState
764
exec^.GS := instance^.GS;
766
glyph^.outline.high_precision := ( instance^.metrics.y_ppem < 24 );
768
glyph^.is_composite := false;
770
(* save its critical pointers that will be modified *)
773
base_pts := exec^.pts;
777
left_points := face^.maxPoints;
778
left_contours := face^.maxContours;
784
subglyph := @exec^.loadStack^[0];
786
Init_Glyph_Component( subglyph, nil, exec );
788
subglyph^.index := glyph_index;
789
subglyph^.is_hinted := load_flags and TT_Load_Hint_Glyph <> 0;
791
if instance^.GS.instruct_control and 1 <> 0 then
792
subglyph^.is_hinted := False;
794
(* now access stream *)
796
if TT_Use_Stream( face^.stream, stream ) then
799
(* Main Loading Loop *)
803
while phase <> Load_Exit do
806
subglyph := @exec^.loadStack^[load_top];
810
(************************************************************)
812
(* Load_Glyph state *)
814
(* reading a glyph's generic header to determine *)
815
(* wether it's simple or composite *)
817
(* exit states : Load_Simple and Load_Composite *)
822
(* check glyph index and table *)
824
index := subglyph^.index;
825
if (index < 0) or (index >= face^.numGlyphs) then
827
error := TT_Err_Invalid_Glyph_Index;
831
(* load glyph metrics *)
832
Get_HMetrics( face, index, true,
833
subglyph^.leftBearing,
834
subglyph^.advanceWidth );
837
if (index+1 < face^.numLocations) and
838
(face^.glyphLocations^[index] = face^.glyphLocations^[index+1]) then
841
(* as noticed by Frederic Loyer, these are spaces, not *)
842
(* the 'unknown' glyph *)
846
subglyph^.bbox.xMin := 0;
847
subglyph^.bbox.xMax := 0;
848
subglyph^.bbox.yMin := 0;
849
subglyph^.bbox.yMax := 0;
851
subglyph^.pp1.x := 0;
852
subglyph^.pp2.x := subglyph^.advanceWidth;
853
if load_flags and TT_LOAD_Scale_Glyph <> 0 then
854
subglyph^.pp2.x := Scale_X( exec^.metrics, subglyph^.pp2.x );
856
exec^.glyphSize := 0;
861
offset := glyph_offset + face^.glyphLocations^[index];
863
(* read first glyph header *)
865
if TT_Seek_File( offset ) or
866
TT_Access_Frame( 5*sizeof(Short) ) then
869
num_contours := GET_Short;
870
subglyph^.bbox.xMin := GET_Short;
871
subglyph^.bbox.yMin := GET_Short;
872
subglyph^.bbox.xMax := GET_Short;
873
subglyph^.bbox.yMax := GET_Short;
878
Writeln('Glyph ', i );
880
Writeln(' # of Contours : ',num_contours );
881
Writeln(' xMin : ',subglyph^.xMin:4,' xMax : ',subglyph^.xMax);
882
Writeln(' yMin : ',subglyph^.yMin:4,' yMax : ',subglyph^.yMax);
886
if num_contours > left_contours then
889
Writeln( 'ERROR: Glyph index ', i, ' has ', num_contours );
890
Writeln(' contours > left ', left_contours );
892
error := TT_Err_Too_Many_Contours;
898
pp1.x := bbox.xMin - leftBearing;
900
pp2.x := pp1.x + advanceWidth;
903
if load_flags and TT_Load_Scale_Glyph <> 0 then
905
pp1.x := Scale_X( exec^.metrics, pp1.x );
906
pp2.x := Scale_X( exec^.metrics, pp2.x );
910
(* is it a simple glyph ? *)
911
if num_contours >= 0 then
914
phase := Load_Composite;
919
(************************************************************)
921
(* Load_Simple state *)
923
(* reading a simple glyph (num_contours must be set to *)
924
(* the glyph's number of contours..) *)
926
(* exit states : Load_End *)
931
new_flags := load_flags;
933
if not subglyph^.is_hinted then
934
new_flags := new_flags and not TT_Load_Hint_Glyph;
935
(* disable hinting when scaling *)
937
if new_flags and TT_Load_Debug <> 0 then
939
new_flags := new_flags and not TT_Load_Debug;
941
if Load_Simple_Glyph(
951
num_points := exec^.pts.n_points-2;
956
(************************************************************)
958
(* Load_Composite state *)
960
(* reading a composite glyph header a pushing a new *)
961
(* load element on the stack.. *)
963
(* exit states : Load_Glyph *)
969
glyph^.is_composite := true;
971
(* create a new element *)
975
if load_top > face^.maxComponents then
977
error := TT_Err_Invalid_Composite;
981
subglyph2 := @exec^.loadStack^[load_top];
983
Init_Glyph_Component( subglyph2, subglyph, nil );
985
subglyph2^.index := -1;
986
subglyph2^.is_hinted := subglyph^.is_hinted;
988
(* now read composite header *)
990
if TT_Access_Frame( 4 ) then
993
new_flags := Get_UShort;
995
subglyph^.element_flag := new_flags;
996
subglyph2^.index := Get_UShort;
1002
if new_flags and ARGS_ARE_WORDS <> 0 then
1005
if new_flags and WE_HAVE_A_SCALE <> 0 then
1008
if new_flags and WE_HAVE_AN_XY_SCALE <> 0 then
1011
if new_flags and WE_HAVE_A_2X2 <> 0 then
1014
if TT_Access_Frame( k ) then
1017
if new_flags and ARGS_ARE_WORDS <> 0 then
1028
subglyph^.arg1 := k;
1029
subglyph^.arg2 := l;
1031
if new_flags and ARGS_ARE_XY_VALUES <> 0 then
1033
subglyph^.transform.ox := k;
1034
subglyph^.transform.oy := l;
1042
if new_flags and WE_HAVE_A_SCALE <> 0 then
1044
xx := Long(Get_Short) shl 2;
1047
subglyph2^.is_scaled := true;
1049
else if new_flags and WE_HAVE_AN_XY_SCALE <> 0 then
1051
xx := Long(Get_Short) shl 2;
1052
yy := Long(Get_Short) shl 2;
1054
subglyph2^.is_scaled := true;
1056
else if new_flags and WE_HAVE_A_2X2 <> 0 then
1058
xx := Long(Get_Short) shl 2;
1059
xy := Long(Get_Short) shl 2;
1060
yx := Long(Get_Short) shl 2;
1061
yy := Long(Get_Short) shl 2;
1063
subglyph2^.is_scaled := true;
1066
subglyph^.transform.xx := xx;
1067
subglyph^.transform.xy := xy;
1068
subglyph^.transform.yx := yx;
1069
subglyph^.transform.yy := yy;
1071
delta := MulDiv_Round( xx, yy, 1 shl 16 ) -
1072
MulDiv_Round( xy, yx, 1 shl 16 );
1074
if abs(delta) <> 1 shl 16 then
1075
subglyph2^.is_hinted := false;
1079
subglyph^.file_offset := TT_File_Pos;
1081
phase := Load_Glyph;
1084
(************************************************************)
1086
(* Load_End state *)
1088
(* after loading a glyph, apply transform and offset *)
1089
(* where necessary, pops element and continue or *)
1090
(* stop process.. *)
1092
(* exit states : Load_Composite and Load_Exit *)
1096
if load_top > 0 then
1099
subglyph2 := subglyph;
1102
subglyph := @exec^.loadStack^[load_top];
1104
(* check advance width and left side bearing *)
1106
if not subglyph^.preserve_pps and
1107
(subglyph^.element_flag and USE_MY_METRICS <> 0) then
1110
subglyph^.leftBearing := subglyph2^.leftBearing;
1111
subglyph^.advanceWidth := subglyph2^.advanceWidth;
1113
subglyph^.pp1 := subglyph2^.pp1;
1114
subglyph^.pp2 := subglyph2^.pp2;
1116
subglyph^.preserve_pps := true;
1119
(* apply scale/symmetry/rotation/wathever *)
1121
for k := 0 to num_points-1 do with subglyph^ do
1123
vec := subglyph2^.zone.cur^[k];
1125
nvec.x := MulDiv_Round( vec.x, transform.xx, 1 shl 16 ) +
1126
MulDiv_Round( vec.y, transform.yx, 1 shl 16 );
1128
nvec.y := MulDiv_Round( vec.x, transform.xy, 1 shl 16 ) +
1129
MulDiv_Round( vec.y, transform.yy, 1 shl 16 );
1131
subglyph2^.zone.cur^[k] := nvec;
1133
vec := subglyph2^.zone.org^[k];
1135
nvec.x := MulDiv_Round( vec.x, transform.xx, 1 shl 16 ) +
1136
MulDiv_Round( vec.y, transform.yx, 1 shl 16 );
1138
nvec.y := MulDiv_Round( vec.x, transform.xy, 1 shl 16 ) +
1139
MulDiv_Round( vec.y, transform.yy, 1 shl 16 );
1141
subglyph2^.zone.org^[k] := nvec;
1145
for k := 0 to num_contours-1 do
1146
inc( subglyph2^.zone.conEnds^[k], subglyph^.zone.n_points );
1148
inc( subglyph^.zone.n_points, num_points );
1149
inc( subglyph^.zone.n_contours, num_contours );
1151
dec( left_points, num_points );
1152
dec( left_contours, num_contours );
1156
if subglyph^.element_flag and ARGS_ARE_XY_VALUES = 0 then
1158
k := subglyph^.arg1;
1159
l := subglyph^.arg2;
1161
if (k < 0) or (k >= subglyph^.zone.n_points ) or
1162
(l < 0) or (l >= num_points) then
1164
error := TT_Err_Invalid_Composite;
1168
inc( l, subglyph^.zone.n_points );
1170
vec.x := subglyph^.zone.cur^[k].x -
1171
subglyph^.zone.cur^[l].x;
1173
vec.y := subglyph^.zone.cur^[k].y -
1174
subglyph^.zone.cur^[l].y;
1178
vec.x := subglyph^.transform.ox;
1179
vec.y := subglyph^.transform.oy;
1181
if load_flags and TT_Load_Scale_Glyph <> 0 then
1183
vec.x := Scale_X( exec^.metrics, vec.x );
1184
vec.y := Scale_Y( exec^.metrics, vec.y );
1186
if subglyph^.element_flag and ROUND_XY_TO_GRID <> 0 then
1188
vec.x := (vec.x+32) and -64;
1189
vec.y := (vec.y+32) and -64;
1194
translate_array( num_points, subglyph2^.zone.cur, vec.x, vec.y );
1196
cur_to_org( num_points, @subglyph2^.zone );
1198
num_points := subglyph^.zone.n_points;
1199
num_contours := subglyph^.zone.n_contours;
1201
(* check for last component *)
1203
if TT_Seek_File( subglyph^.file_offset ) then
1206
if subglyph^.element_flag and MORE_COMPONENTS <> 0 then
1207
phase := Load_Composite
1210
debug := ( load_top = 0 ) and
1211
( load_flags and TT_Load_Debug <> 0 );
1213
if Load_Composite_End( num_points,
1217
debug ) then goto Fail;
1228
(* finally, copy the points arrays to the glyph object *)
1230
exec^.pts := base_pts;
1232
(* copy also the phantom points, the debugger needs them *)
1233
inc( num_points, 2 );
1235
for k := 0 to num_points-1 do with glyph^.outline do
1237
points^[k] := exec^.pts.cur^[k];
1238
flags ^[k] := exec^.pts.flags^[k];
1241
for k := 0 to num_contours-1 do with glyph^.outline do
1242
conEnds^[k] := exec^.pts.conEnds^[k];
1244
glyph^.outline.n_points := num_points;
1245
glyph^.outline.n_contours := num_contours;
1246
glyph^.outline.second_pass := true;
1248
TT_Get_Outline_BBox( glyph^.outline, glyph^.metrics.bbox );
1250
glyph^.metrics.horiBearingX := glyph^.metrics.bbox.xMin - subglyph^.pp1.x;
1251
glyph^.metrics.horiBearingY := glyph^.metrics.bbox.yMax;
1252
glyph^.metrics.horiAdvance := subglyph^.pp2.x - subglyph^.pp1.x;
1254
glyph^.computed_width := glyph^.metrics.horiAdvance;
1255
glyph^.precalc_width := -1;
1257
(* Now take care of vertical metrics. In the case where there is *)
1258
(* no vertical information within the font (which is relatively *)
1259
(* common), make up some metrics "by hand".. *)
1263
(* get the unscaled "tsb" and "ah" *)
1264
(* don't assume that both the vertical header and metrics are *)
1265
(* present in a font file... *)
1266
if face^.verticalInfo and
1267
( face^.verticalHeader.number_Of_VMetrics > 0 ) then
1269
(* apparently, the following line isn't accepted by the FreePascal *)
1270
(* compiler. It complains because the typecast occurs on a 'var' *)
1271
(* parameter. Don't know if this is compiler bug or not, but I *)
1272
(* changed the code with some stupid copy trick.. *)
1274
(* TT_Get_Metrics( TT_Horizontal_Header(face^.verticalHeader), *)
1277
(* advance_height ); *)
1279
horizontal := TT_Horizontal_Header(face^.verticalHeader);
1280
TT_Get_Metrics( horizontal,
1287
(* Make up the distances from the horizontal header.. *)
1289
(* The typographic values are the only portable ones, which *)
1290
(* is why we use them.. *)
1292
(* The sTypoDescender field is always negative, unlike the *)
1293
(* Windows Descender.. *)
1297
top_bearing := sTypoLineGap div 2;
1298
advance_height := sTypoAscender - sTypoDescender + sTypoLineGap;
1303
(* now scale the metrics *)
1304
if load_flags and TT_Load_Scale_Glyph <> 0 then
1306
top_bearing := Scale_Y( exec^.metrics, top_bearing );
1307
advance_height := Scale_Y( exec^.metrics, advance_height );
1310
with glyph^.metrics do
1312
vertBearingX := ( bbox.xMin - bbox.xMax ) div 2;
1313
vertBearingY := top_bearing;
1314
vertAdvance := advance_height;
1316
if load_flags and TT_Load_Hint_Glyph <> 0 then
1318
vertBearingX := vertBearingX and -64;
1319
vertBearingY := (vertBearingY + 63) and -64;
1320
vertAdvance := (vertAdvance+32) and -64;
1326
(* use hdmx table to adjust advance width as necessary *)
1327
if load_flags and TT_Load_Default = TT_Load_Default then
1329
widths := Get_Advance_Widths( exec^.face,
1330
exec^.instance^.metrics.x_ppem );
1331
if widths <> nil then
1333
glyph^.metrics.horiAdvance := widths^[glyph_index]*64;
1334
glyph^.precalc_width := glyph^.metrics.horiAdvance;
1338
(* in case of hinting, shift the glyph so that (0,0) corresponds *)
1339
(* to the glyph origin. *)
1340
if subglyph^.is_hinted then
1342
glyph^.metrics.horiBearingX := (glyph^.metrics.bbox.xMin and -64) -
1345
glyph^.metrics.horiAdvance := (glyph^.metrics.horiAdvance+32) and -64;
1346
glyph^.computed_width := (glyph^.computed_width+32) and -64;
1348
translate_array( num_points,
1349
glyph^.outline.points,
1354
glyph^.outline.dropout_mode := exec^.GS.scan_type;
1356
Load_TrueType_Glyph := Success;
1359
TT_Done_Stream( stream );
1363
(* reset the execution context *)
1364
exec^.pts := base_pts;
1366
if instance^.debug then
1368
exec^.pts.n_points := num_points;
1369
exec^.pts.n_contours := num_contours;
1372
Done_Context( exec);
1377
error := TT_Err_File_Error;
1381
error := TT_Err_Invalid_Instance_Handle;
1385
error := TT_Err_Invalid_Glyph_Index;