1
//----------------------------------------------------------------------------
2
// Anti-Grain Geometry - Version 2.4 (Public License)
3
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
5
// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
6
// Pascal Port By: Milan Marusinec alias Milano
8
// http://www.aggpas.org
9
// Copyright (c) 2005-2007
11
// Permission to copy, use, modify, sell and distribute this software
12
// is granted provided this copyright notice appears in all copies.
13
// This software is provided "as is" without express or implied
14
// warranty, and with no claim as to its suitability for any purpose.
16
//----------------------------------------------------------------------------
17
// Contact: mcseem@antigrain.com
18
// mcseemagg@yahoo.com
19
// http://www.antigrain.com
21
// [Pascal Port History] -----------------------------------------------------
23
// 17.09.2007-Milano: Porting & Finished OK
24
// 16.09.2007-Milano: Unit port establishment
26
{ agg_font_freetype.pas }
36
agg_font_freetype_lib ,
39
agg_font_cache_manager ,
42
agg_path_storage_integer ,
47
agg_rasterizer_scanline_aa ,
48
agg_renderer_scanline ,
49
agg_render_scanlines ,
52
{ GLOBAL VARIABLES & CONSTANTS }
55
face_name_ptr = ^face_name;
57
name : char_ptr; //PChar;
62
//-----------------------------------------------font_engine_freetype_base
63
font_engine_freetype_base = object(font_engine )
71
m_face_index : unsigned;
72
m_char_map : FT_Encoding;
73
m_signature : face_name;
80
m_library_initialized : boolean;
82
m_library : FT_Library_ptr; // handle to library
83
m_faces : FT_Face_ptr_ptr; // A pool of font faces
85
m_face_names : face_name_ptr;
87
m_max_faces : unsigned;
88
m_cur_face : FT_Face_ptr; // handle to the current face object
91
m_glyph_rendering : glyph_rendering;
94
m_data_type : unsigned;
96
m_bounds : agg_basics.rect;
99
m_affine : trans_affine;
101
m_path16 : path_storage_int16;
102
m_path32 : path_storage_int32;
104
m_curves32 : conv_curve;
106
m_scanline_aa : scanline_u8;
107
m_scanline_bin : scanline_bin;
108
m_scanlines_aa : scanlines_aa_type;
109
m_scanlines_bin : scanlines_bin_type;
110
m_rasterizer : rasterizer_scanline_aa;
112
constructor Construct(flag32_ : boolean; max_faces : unsigned = 32 );
115
// Set font parameters
116
procedure resolution_(dpi : unsigned );
119
font_name : PChar; face_index : unsigned; ren_type : glyph_rendering;
120
font_mem : PChar = NIL; font_mem_size : int = 0 ) : boolean;
122
function attach(file_name : PChar ) : boolean;
124
function char_map_ (map : FT_Encoding ) : boolean;
125
function height_ (h : double ) : boolean;
126
function width_ (w : double ) : boolean;
127
procedure hinting_ (h : boolean );
128
procedure flip_y_ (flip : boolean );
129
procedure transform_(affine : trans_affine_ptr );
132
procedure gamma_(f : vertex_source_ptr );
135
function _last_error : int;
136
function _resolution : unsigned;
137
function _name : PChar;
138
function _num_faces : unsigned;
139
function _char_map : FT_Encoding;
140
function _height : double;
141
function _width : double;
142
function _ascender : double;
143
function _descender : double;
144
function _hinting : boolean;
145
function _flip_y : boolean;
147
// Interface mandatory to implement for font_cache_manager
148
function font_signature : PChar; virtual;
149
function change_stamp : int; virtual;
151
function prepare_glyph(glyph_code : unsigned ) : boolean; virtual;
153
function glyph_index : unsigned; virtual;
154
function data_size : unsigned; virtual;
155
function data_type : unsigned; virtual;
156
function bounds : rect_ptr; virtual;
157
function advance_x : double; virtual;
158
function advance_y : double; virtual;
160
procedure write_glyph_to(data : int8u_ptr ); virtual;
161
function add_kerning (first ,second : unsigned; x ,y : double_ptr ) : boolean; virtual;
163
function flag32 : boolean; virtual;
166
procedure update_char_size;
167
procedure update_signature;
169
function find_face(name : PChar ) : int;
173
//------------------------------------------------font_engine_freetype_int16
174
// This class uses values of type int16 (10.6 format) for the vector cache.
175
// The vector cache is compact, but when rendering glyphs of height
176
// more that 200 there integer overflow can occur.
177
font_engine_freetype_int16 = object(font_engine_freetype_base )
178
constructor Construct(max_faces : unsigned = 32 );
182
//------------------------------------------------font_engine_freetype_int32
183
// This class uses values of type int32 (26.6 format) for the vector cache.
184
// The vector cache is twice larger than in font_engine_freetype_int16,
185
// but it allows you to render glyphs of very large sizes.
186
font_engine_freetype_int32 = object(font_engine_freetype_base )
187
constructor Construct(max_faces : unsigned = 32 );
191
{ GLOBAL PROCEDURES }
195
{ LOCAL VARIABLES & CONSTANTS }
196
//------------------------------------------------------------------------------
198
// This code implements the AUTODIN II polynomial
199
// The variable corresponding to the macro argument "crc" should
200
// be an unsigned long.
201
// Oroginal code by Spencer Garrett <srg@quick.com>
203
// generated using the AUTODIN II polynomial
204
// x^32 + x^26 + x^23 + x^22 + x^16 +
205
// x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
207
//------------------------------------------------------------------------------
209
crc32tab : array[0..255 ] of unsigned = (
210
$00000000, $77073096, $ee0e612c, $990951ba,
211
$076dc419, $706af48f, $e963a535, $9e6495a3,
212
$0edb8832, $79dcb8a4, $e0d5e91e, $97d2d988,
213
$09b64c2b, $7eb17cbd, $e7b82d07, $90bf1d91,
214
$1db71064, $6ab020f2, $f3b97148, $84be41de,
215
$1adad47d, $6ddde4eb, $f4d4b551, $83d385c7,
216
$136c9856, $646ba8c0, $fd62f97a, $8a65c9ec,
217
$14015c4f, $63066cd9, $fa0f3d63, $8d080df5,
218
$3b6e20c8, $4c69105e, $d56041e4, $a2677172,
219
$3c03e4d1, $4b04d447, $d20d85fd, $a50ab56b,
220
$35b5a8fa, $42b2986c, $dbbbc9d6, $acbcf940,
221
$32d86ce3, $45df5c75, $dcd60dcf, $abd13d59,
222
$26d930ac, $51de003a, $c8d75180, $bfd06116,
223
$21b4f4b5, $56b3c423, $cfba9599, $b8bda50f,
224
$2802b89e, $5f058808, $c60cd9b2, $b10be924,
225
$2f6f7c87, $58684c11, $c1611dab, $b6662d3d,
226
$76dc4190, $01db7106, $98d220bc, $efd5102a,
227
$71b18589, $06b6b51f, $9fbfe4a5, $e8b8d433,
228
$7807c9a2, $0f00f934, $9609a88e, $e10e9818,
229
$7f6a0dbb, $086d3d2d, $91646c97, $e6635c01,
230
$6b6b51f4, $1c6c6162, $856530d8, $f262004e,
231
$6c0695ed, $1b01a57b, $8208f4c1, $f50fc457,
232
$65b0d9c6, $12b7e950, $8bbeb8ea, $fcb9887c,
233
$62dd1ddf, $15da2d49, $8cd37cf3, $fbd44c65,
234
$4db26158, $3ab551ce, $a3bc0074, $d4bb30e2,
235
$4adfa541, $3dd895d7, $a4d1c46d, $d3d6f4fb,
236
$4369e96a, $346ed9fc, $ad678846, $da60b8d0,
237
$44042d73, $33031de5, $aa0a4c5f, $dd0d7cc9,
238
$5005713c, $270241aa, $be0b1010, $c90c2086,
239
$5768b525, $206f85b3, $b966d409, $ce61e49f,
240
$5edef90e, $29d9c998, $b0d09822, $c7d7a8b4,
241
$59b33d17, $2eb40d81, $b7bd5c3b, $c0ba6cad,
242
$edb88320, $9abfb3b6, $03b6e20c, $74b1d29a,
243
$ead54739, $9dd277af, $04db2615, $73dc1683,
244
$e3630b12, $94643b84, $0d6d6a3e, $7a6a5aa8,
245
$e40ecf0b, $9309ff9d, $0a00ae27, $7d079eb1,
246
$f00f9344, $8708a3d2, $1e01f268, $6906c2fe,
247
$f762575d, $806567cb, $196c3671, $6e6b06e7,
248
$fed41b76, $89d32be0, $10da7a5a, $67dd4acc,
249
$f9b9df6f, $8ebeeff9, $17b7be43, $60b08ed5,
250
$d6d6a3e8, $a1d1937e, $38d8c2c4, $4fdff252,
251
$d1bb67f1, $a6bc5767, $3fb506dd, $48b2364b,
252
$d80d2bda, $af0a1b4c, $36034af6, $41047a60,
253
$df60efc3, $a867df55, $316e8eef, $4669be79,
254
$cb61b38c, $bc66831a, $256fd2a0, $5268e236,
255
$cc0c7795, $bb0b4703, $220216b9, $5505262f,
256
$c5ba3bbe, $b2bd0b28, $2bb45a92, $5cb36a04,
257
$c2d7ffa7, $b5d0cf31, $2cd99e8b, $5bdeae1d,
258
$9b64c2b0, $ec63f226, $756aa39c, $026d930a,
259
$9c0906a9, $eb0e363f, $72076785, $05005713,
260
$95bf4a82, $e2b87a14, $7bb12bae, $0cb61b38,
261
$92d28e9b, $e5d5be0d, $7cdcefb7, $0bdbdf21,
262
$86d3d2d4, $f1d4e242, $68ddb3f8, $1fda836e,
263
$81be16cd, $f6b9265b, $6fb077e1, $18b74777,
264
$88085ae6, $ff0f6a70, $66063bca, $11010b5c,
265
$8f659eff, $f862ae69, $616bffd3, $166ccf45,
266
$a00ae278, $d70dd2ee, $4e048354, $3903b3c2,
267
$a7672661, $d06016f7, $4969474d, $3e6e77db,
268
$aed16a4a, $d9d65adc, $40df0b66, $37d83bf0,
269
$a9bcae53, $debb9ec5, $47b2cf7f, $30b5ffe9,
270
$bdbdf21c, $cabac28a, $53b39330, $24b4a3a6,
271
$bad03605, $cdd70693, $54de5729, $23d967bf,
272
$b3667a2e, $c4614ab8, $5d681b02, $2a6f2b94,
273
$b40bbe37, $c30c8ea1, $5a05df1b, $2d02ef8d );
275
{ UNIT IMPLEMENTATION }
277
function calc_crc32(buf : int8u_ptr; size : unsigned ) : unsigned;
279
crc ,len ,nr : unsigned;
284
crc:=unsigned(not 0 );
294
crc:=(crc shr 8 ) xor crc32tab[(crc xor p^ ) and $ff ];
296
inc(ptrcomp(p ) ,sizeof(int8u ) );
305
function dbl_to_plain_fx(d : double ) : int;
307
result:=Trunc(d * 65536.0 )
312
function int26p6_to_dbl(p : int ) : double;
319
function dbl_to_int26p6(p : double ) : int;
321
result:=Trunc(p * 64.0 + 0.5 );
325
{ decompose_ft_outline }
326
function decompose_ft_outline(
327
outline : FT_Outline_ptr;
329
mtx : trans_affine_ptr;
330
path : path_storage_integer_ptr ) : boolean;
332
v_last ,v_control ,v_start ,vec ,v_middle ,vec1 ,vec2 : FT_Vector;
334
x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double;
336
point ,limit : FT_Vector_ptr;
340
n , // index of contour in outline
341
first , // index of first point in contour
342
last : int; // index of last point in contour
344
tag : char; // current point's state
353
while n < outline.n_contours do
355
last :=FT_Short_ptr(ptrcomp(outline.contours ) + n * sizeof(FT_Short ) )^;
356
limit:=FT_Vector_ptr(ptrcomp(outline.points ) + last * sizeof(FT_Vector ) );
358
v_start:=FT_Vector_ptr(ptrcomp(outline.points ) + first * sizeof(FT_Vector) )^;
359
v_last :=FT_Vector_ptr(ptrcomp(outline.points ) + last * sizeof(FT_Vector) )^;
363
point:=FT_Vector_ptr(ptrcomp(outline.points ) + first * sizeof(FT_Vector ) );
364
tags :=char_ptr (ptrcomp(outline.tags ) + first * sizeof(char ) );
365
tag :=FT_CURVE_TAG (tags^ );
367
// A contour cannot start with a cubic control point!
368
if tag = char(FT_CURVE_TAG_CUBIC ) then
376
// check first point to determine origin
377
if tag = char(FT_CURVE_TAG_CONIC ) then
379
// first point is conic control. Yes, this happens.
380
if FT_CURVE_TAG(char_ptr(ptrcomp(outline.tags ) + last )^ ) = char(FT_CURVE_TAG_ON ) then
382
// start at last point if it is on the curve
390
// if both first and last points are conic,
391
// start at their middle and record its position
393
v_start.x:=(v_start.x + v_last.x ) div 2;
394
v_start.y:=(v_start.y + v_last.y ) div 2;
400
dec(ptrcomp(point ) ,sizeof(FT_Vector ) );
401
dec(ptrcomp(tags ) );
405
x1:=int26p6_to_dbl(v_start.x );
406
y1:=int26p6_to_dbl(v_start.y );
411
mtx.transform(mtx ,@x1 ,@y1 );
412
path.move_to (dbl_to_int26p6(x1 ) ,dbl_to_int26p6(y1 ) );
414
while ptrcomp(point ) < ptrcomp(limit ) do
416
inc(ptrcomp(point ) ,sizeof(FT_Vector ) );
417
inc(ptrcomp(tags ) );
419
tag:=FT_CURVE_TAG(tags^ );
422
// emit a single line_to
423
char(FT_CURVE_TAG_ON ) :
425
x1:=int26p6_to_dbl(point.x );
426
y1:=int26p6_to_dbl(point.y );
431
mtx.transform(mtx ,@x1 ,@y1 );
432
path.line_to (dbl_to_int26p6(x1 ) ,dbl_to_int26p6(y1 ) );
438
// consume conic arcs
439
char(FT_CURVE_TAG_CONIC ) :
441
v_control.x:=point.x;
442
v_control.y:=point.y;
445
if ptrcomp(point ) < ptrcomp(limit ) then
447
inc(ptrcomp(point ) ,sizeof(FT_Vector ) );
448
inc(ptrcomp(tags ) );
450
tag:=FT_CURVE_TAG(tags^ );
455
if tag = char(FT_CURVE_TAG_ON ) then
457
x1:=int26p6_to_dbl(v_control.x );
458
y1:=int26p6_to_dbl(v_control.y );
459
x2:=int26p6_to_dbl(vec.x );
460
y2:=int26p6_to_dbl(vec.y );
469
mtx.transform(mtx ,@x1 ,@y1 );
470
mtx.transform(mtx ,@x2 ,@y2 );
473
dbl_to_int26p6(x1 ) ,
474
dbl_to_int26p6(y1 ) ,
475
dbl_to_int26p6(x2 ) ,
476
dbl_to_int26p6(y2 ) );
482
if tag <> char(FT_CURVE_TAG_CONIC ) then
490
v_middle.x:=(v_control.x + vec.x ) div 2;
491
v_middle.y:=(v_control.y + vec.y ) div 2;
493
x1:=int26p6_to_dbl(v_control.x );
494
y1:=int26p6_to_dbl(v_control.y );
495
x2:=int26p6_to_dbl(v_middle.x );
496
y2:=int26p6_to_dbl(v_middle.y );
505
mtx.transform(mtx ,@x1 ,@y1 );
506
mtx.transform(mtx ,@x2 ,@y2 );
509
dbl_to_int26p6(x1 ) ,
510
dbl_to_int26p6(y1 ) ,
511
dbl_to_int26p6(x2 ) ,
512
dbl_to_int26p6(y2 ) );
520
x1:=int26p6_to_dbl(v_control.x );
521
y1:=int26p6_to_dbl(v_control.y );
522
x2:=int26p6_to_dbl(v_start.x );
523
y2:=int26p6_to_dbl(v_start.y );
532
mtx.transform(mtx ,@x1 ,@y1 );
533
mtx.transform(mtx ,@x2 ,@y2 );
536
dbl_to_int26p6(x1 ) ,
537
dbl_to_int26p6(y1 ) ,
538
dbl_to_int26p6(x2 ) ,
539
dbl_to_int26p6(y2 ) );
545
// FT_CURVE_TAG_CUBIC
548
if (ptrcomp(point ) + sizeof(FT_Vector ) > ptrcomp(limit ) ) or
549
(FT_CURVE_TAG(char_ptr(ptrcomp(tags ) + 1 )^ ) <> char(FT_CURVE_TAG_CUBIC ) ) then
559
vec2.x:=FT_Vector_ptr(ptrcomp(point ) + sizeof(FT_Vector ) ).x;
560
vec2.y:=FT_Vector_ptr(ptrcomp(point ) + sizeof(FT_Vector ) ).y;
562
inc(ptrcomp(point ) ,2 * sizeof(FT_Vector ) );
563
inc(ptrcomp(tags ) ,2 );
565
if ptrcomp(point ) <= ptrcomp(limit ) then
570
x1:=int26p6_to_dbl(vec1.x );
571
y1:=int26p6_to_dbl(vec1.y );
572
x2:=int26p6_to_dbl(vec2.x );
573
y2:=int26p6_to_dbl(vec2.y );
574
x3:=int26p6_to_dbl(vec.x );
575
y3:=int26p6_to_dbl(vec.y );
585
mtx.transform(mtx ,@x1 ,@y1 );
586
mtx.transform(mtx ,@x2 ,@y2 );
587
mtx.transform(mtx ,@x3 ,@y3 );
590
dbl_to_int26p6(x1 ) ,
591
dbl_to_int26p6(y1 ) ,
592
dbl_to_int26p6(x2 ) ,
593
dbl_to_int26p6(y2 ) ,
594
dbl_to_int26p6(x3 ) ,
595
dbl_to_int26p6(y3 ) );
601
x1:=int26p6_to_dbl(vec1.x );
602
y1:=int26p6_to_dbl(vec1.y );
603
x2:=int26p6_to_dbl(vec2.x );
604
y2:=int26p6_to_dbl(vec2.y );
605
x3:=int26p6_to_dbl(v_start.x );
606
y3:=int26p6_to_dbl(v_start.y );
616
mtx.transform(mtx ,@x1 ,@y1 );
617
mtx.transform(mtx ,@x2 ,@y2 );
618
mtx.transform(mtx ,@x3 ,@y3 );
626
dbl_to_int26p6(y3) );
649
{ decompose_ft_bitmap_mono }
650
procedure decompose_ft_bitmap_mono(
651
bitmap : FT_Bitmap_ptr;
655
storage : renderer_scanline_ptr );
660
bits : bitset_iterator;
663
buf :=int8u_ptr(bitmap.buffer );
666
sl.reset (x ,x + bitmap.width );
667
storage.prepare(bitmap.width + 2 );
671
inc(ptrcomp(buf ) ,bitmap.pitch * (bitmap.rows - 1 ) );
672
inc(y ,bitmap.rows );
680
while i < bitmap.rows do
684
bits.Construct(buf ,0 );
688
while j < bitmap.width do
690
if bits.bit <> 0 then
691
sl.add_cell(x + j ,cover_full );
699
inc(ptrcomp(buf ) ,pitch * sizeof(int8u ) );
701
if sl.num_spans <> 0 then
703
sl.finalize (y - i - 1 );
714
{ decompose_ft_bitmap_gray8 }
715
procedure decompose_ft_bitmap_gray8(
716
bitmap : FT_Bitmap_ptr;
719
ras : rasterizer_scanline_aa_ptr;
721
storage : renderer_scanline_ptr );
728
buf :=int8u_ptr(bitmap.buffer );
731
sl.reset (x ,x + bitmap.width );
732
storage.prepare(bitmap.width + 2 );
736
inc(ptrcomp(buf ) ,bitmap.pitch * (bitmap.rows - 1 ) );
737
inc(y ,bitmap.rows );
745
while i < bitmap.rows do
752
while j < bitmap.width do
755
sl.add_cell(x + j ,ras.apply_gamma(p^ ) );
757
inc(ptrcomp(p ) ,sizeof(int8u ) );
762
inc(ptrcomp(buf ) ,pitch * sizeof(int8u ) );
764
if sl.num_spans <> 0 then
766
sl.finalize (y - i - 1 );
778
constructor font_engine_freetype_base.Construct(flag32_ : boolean; max_faces : unsigned = 32 );
786
m_name_len :=256 - 16 - 1;
789
m_char_map:=FT_ENCODING_NONE;
791
m_signature.size:=256 + 256 - 16;
793
agg_getmem(pointer(m_signature.name ) ,m_signature.size );
800
m_library_initialized:=false;
804
agg_getmem(pointer(m_faces ) ,max_faces * sizeof(FT_Face_ptr ) );
805
agg_getmem(pointer(m_face_names ) ,max_faces * sizeof(face_name ) );
808
m_max_faces :=max_faces;
812
m_glyph_rendering:=glyph_ren_native_gray8;
815
m_data_type :=glyph_data_invalid;
817
m_bounds.Construct(1 ,1 ,0 ,0 );
826
m_curves16.Construct(@m_path16 );
827
m_curves32.Construct(@m_path32 );
828
m_scanline_aa.Construct;
829
m_scanline_bin.Construct;
830
m_scanlines_aa.Construct;
831
m_scanlines_bin.Construct;
832
m_rasterizer.Construct;
834
m_curves16.approximation_scale_(4.0 );
835
m_curves32.approximation_scale_(4.0 );
837
m_last_error:=FT_Init_FreeType(@m_library );
839
if m_last_error = 0 then
840
m_library_initialized:=true;
845
destructor font_engine_freetype_base.Destruct;
854
while i < m_num_faces do
856
agg_freemem (pointer(n.name ) ,n.size );
857
FT_Done_Face(FT_Face_ptr_ptr(ptrcomp(m_faces ) + i * sizeof(FT_Face_ptr ) )^ );
859
inc(ptrcomp(n ) ,sizeof(face_name ) );
864
agg_freemem(pointer(m_face_names ) ,m_max_faces * sizeof(face_name ) );
865
agg_freemem(pointer(m_faces ) ,m_max_faces * sizeof(FT_Face_ptr ) );
866
agg_freemem(pointer(m_signature.name ) ,m_signature.size );
868
if m_library_initialized then
869
FT_Done_FreeType(m_library );
875
m_scanline_aa.Destruct;
876
m_scanline_bin.Destruct;
877
m_scanlines_aa.Destruct;
878
m_scanlines_bin.Destruct;
879
m_rasterizer.Destruct;
884
procedure font_engine_freetype_base.resolution_(dpi : unsigned );
893
function font_engine_freetype_base.load_font(
894
font_name : PChar; face_index : unsigned; ren_type : glyph_rendering;
895
font_mem : PChar = NIL; font_mem_size : int = 0 ) : boolean;
902
if m_library_initialized then
906
idx:=find_face(font_name );
910
m_cur_face:=FT_Face_ptr_ptr(ptrcomp(m_faces ) + idx * sizeof(FT_Face_ptr ) )^;
911
m_name :=PChar(face_name_ptr(ptrcomp(m_face_names ) + idx * sizeof(face_name ) ).name );
916
if m_num_faces >= m_max_faces then
918
agg_freemem (pointer(m_face_names.name ) ,m_face_names.size );
919
FT_Done_Face(m_faces^ );
922
FT_Face_ptr_ptr(ptrcomp(m_faces ) + sizeof(FT_Face_ptr ) )^ ,
924
(m_max_faces - 1 ) * sizeof(FT_Face_ptr ) );
927
face_name_ptr(ptrcomp(m_face_names ) + sizeof(face_name ) )^ ,
929
(m_max_faces - 1 ) * sizeof(face_name ) );
935
if (font_mem <> NIL ) and
936
(font_mem_size > 0 ) then
940
FT_Byte_ptr(font_mem ) ,
943
FT_Face_ptr_ptr(ptrcomp(m_faces ) + m_num_faces * sizeof(FT_Face_ptr ) )^ )
950
FT_Face_ptr_ptr(ptrcomp(m_faces ) + m_num_faces * sizeof(FT_Face_ptr ) )^ );
952
if m_last_error = 0 then
954
face_name_ptr(ptrcomp(m_face_names ) + m_num_faces * sizeof(face_name ) ).size:=
955
StrLen(font_name ) + 1;
958
pointer(face_name_ptr(ptrcomp(m_face_names ) + m_num_faces * sizeof(face_name ) ).name ) ,
959
face_name_ptr(ptrcomp(m_face_names ) + m_num_faces * sizeof(face_name ) ).size );
962
PChar(face_name_ptr(ptrcomp(m_face_names ) + m_num_faces * sizeof(face_name ) ).name ) ,
965
m_cur_face:=FT_Face_ptr_ptr(ptrcomp(m_faces ) + m_num_faces * sizeof(FT_Face_ptr ) )^;
966
m_name :=PChar(face_name_ptr(ptrcomp(m_face_names ) + m_num_faces * sizeof(face_name ) ).name );
973
PChar(face_name_ptr(ptrcomp(m_face_names ) + m_num_faces * sizeof(face_name ) ).name ):=NIL;
982
if m_last_error = 0 then
987
glyph_ren_native_mono :
988
m_glyph_rendering:=glyph_ren_native_mono;
990
glyph_ren_native_gray8 :
991
m_glyph_rendering:=glyph_ren_native_gray8;
994
if FT_IS_SCALABLE(m_cur_face ) then
995
m_glyph_rendering:=glyph_ren_outline
997
m_glyph_rendering:=glyph_ren_native_gray8;
1000
if FT_IS_SCALABLE(m_cur_face ) then
1001
m_glyph_rendering:=glyph_ren_agg_mono
1003
m_glyph_rendering:=glyph_ren_native_mono;
1005
glyph_ren_agg_gray8 :
1006
if FT_IS_SCALABLE(m_cur_face ) then
1007
m_glyph_rendering:=glyph_ren_agg_gray8
1009
m_glyph_rendering:=glyph_ren_native_gray8;
1022
function font_engine_freetype_base.attach(file_name : PChar ) : boolean;
1026
if m_cur_face <> NIL then
1028
m_last_error:=FT_Attach_File(m_cur_face ,file_name );
1030
result:=m_last_error = 0;
1037
function font_engine_freetype_base.char_map_(map : FT_Encoding ) : boolean;
1041
if m_cur_face <> NIL then
1043
m_last_error:=FT_Select_Charmap(m_cur_face ,map );
1045
if m_last_error = 0 then
1060
function font_engine_freetype_base.height_(h : double ) : boolean;
1063
m_height:=Trunc(h * 64.0 );
1065
if m_cur_face <> NIL then
1076
function font_engine_freetype_base.width_(w : double ) : boolean;
1079
m_width:=Trunc(w * 64.0 );
1081
if m_cur_face <> NIL then
1092
procedure font_engine_freetype_base.hinting_(h : boolean );
1096
if m_cur_face <> NIL then
1102
procedure font_engine_freetype_base.flip_y_(flip : boolean );
1106
if m_cur_face <> NIL then
1112
procedure font_engine_freetype_base.transform_(affine : trans_affine_ptr );
1114
m_affine.assign_all(affine );
1116
if m_cur_face <> NIL then
1122
procedure font_engine_freetype_base.gamma_(f : vertex_source_ptr );
1124
m_rasterizer.gamma(f );
1129
function font_engine_freetype_base._last_error : int;
1131
result:=m_last_error;
1136
function font_engine_freetype_base._resolution : unsigned;
1138
result:=m_resolution;
1143
function font_engine_freetype_base._name : PChar;
1150
function font_engine_freetype_base._num_faces : unsigned;
1152
if m_cur_face <> NIL then
1153
result:=m_cur_face.num_faces
1160
function font_engine_freetype_base._char_map : FT_Encoding;
1167
function font_engine_freetype_base._height : double;
1169
result:=m_height / 64.0;
1174
function font_engine_freetype_base._width : double;
1176
result:=m_width / 64.0;
1181
function font_engine_freetype_base._ascender : double;
1183
if m_cur_face <> NIL then
1184
result:=m_cur_face.ascender * _height / m_cur_face.height
1191
function font_engine_freetype_base._descender : double;
1193
if m_cur_face <> NIL then
1194
result:=m_cur_face.descender * _height / m_cur_face.height
1201
function font_engine_freetype_base._hinting : boolean;
1208
function font_engine_freetype_base._flip_y : boolean;
1215
function font_engine_freetype_base.font_signature : PChar;
1217
result:=PChar(m_signature.name );
1222
function font_engine_freetype_base.change_stamp : int;
1224
result:=m_change_stamp;
1229
function font_engine_freetype_base.prepare_glyph(glyph_code : unsigned ) : boolean;
1238
m_glyph_index:=FT_Get_Char_Index(m_cur_face ,glyph_code );
1241
m_last_error:=FT_Load_Glyph(m_cur_face ,m_glyph_index ,FT_LOAD_DEFAULT{} {FT_LOAD_FORCE_AUTOHINT{} )
1243
m_last_error:=FT_Load_Glyph(m_cur_face ,m_glyph_index ,FT_LOAD_NO_HINTING );
1245
if m_last_error = 0 then
1246
case m_glyph_rendering of
1247
glyph_ren_native_mono :
1249
m_last_error:=FT_Render_Glyph(m_cur_face.glyph ,FT_RENDER_MODE_MONO );
1251
if m_last_error = 0 then
1254
fl:=-m_cur_face.glyph.bitmap_top
1256
fl:=m_cur_face.glyph.bitmap_top;
1258
decompose_ft_bitmap_mono(
1259
@m_cur_face.glyph.bitmap ,
1260
m_cur_face.glyph.bitmap_left ,
1266
m_bounds.x1:=m_scanlines_bin._min_x;
1267
m_bounds.y1:=m_scanlines_bin._min_y;
1268
m_bounds.x2:=m_scanlines_bin._max_x;
1269
m_bounds.y2:=m_scanlines_bin._max_y;
1270
m_data_size:=m_scanlines_bin.byte_size;
1271
m_data_type:=glyph_data_mono;
1272
m_advance_x:=int26p6_to_dbl(m_cur_face.glyph.advance.x );
1273
m_advance_y:=int26p6_to_dbl(m_cur_face.glyph.advance.y );
1281
glyph_ren_native_gray8 :
1283
m_last_error:=FT_Render_Glyph(m_cur_face.glyph ,FT_RENDER_MODE_NORMAL );
1285
if m_last_error = 0 then
1288
fl:=-m_cur_face.glyph.bitmap_top
1290
fl:=m_cur_face.glyph.bitmap_top;
1292
decompose_ft_bitmap_gray8(
1293
@m_cur_face.glyph.bitmap ,
1294
m_cur_face.glyph.bitmap_left ,
1301
m_bounds.x1:=m_scanlines_aa._min_x;
1302
m_bounds.y1:=m_scanlines_aa._min_y;
1303
m_bounds.x2:=m_scanlines_aa._max_x;
1304
m_bounds.y2:=m_scanlines_aa._max_y;
1305
m_data_size:=m_scanlines_aa.byte_size;
1306
m_data_type:=glyph_data_gray8;
1307
m_advance_x:=int26p6_to_dbl(m_cur_face.glyph.advance.x );
1308
m_advance_y:=int26p6_to_dbl(m_cur_face.glyph.advance.y );
1317
if m_last_error = 0 then
1320
m_path32.remove_all;
1322
if decompose_ft_outline(
1323
@m_cur_face.glyph.outline ,
1328
bnd:=m_path32.bounding_rect;
1330
m_data_size:=m_path32.byte_size;
1331
m_data_type:=glyph_data_outline;
1332
m_bounds.x1:=Floor(bnd.x1 );
1333
m_bounds.y1:=Floor(bnd.y1 );
1334
m_bounds.x2:=Ceil(bnd.x2 );
1335
m_bounds.y2:=Ceil(bnd.y2 );
1336
m_advance_x:=int26p6_to_dbl(m_cur_face.glyph.advance.x );
1337
m_advance_y:=int26p6_to_dbl(m_cur_face.glyph.advance.y );
1339
m_affine.transform(@m_affine ,@m_advance_x ,@m_advance_y );
1348
m_path16.remove_all;
1350
if decompose_ft_outline(
1351
@m_cur_face.glyph.outline ,
1356
bnd:=m_path16.bounding_rect;
1358
m_data_size:=m_path16.byte_size;
1359
m_data_type:=glyph_data_outline;
1360
m_bounds.x1:=Floor(bnd.x1 );
1361
m_bounds.y1:=Floor(bnd.y1 );
1362
m_bounds.x2:=Ceil(bnd.x2 );
1363
m_bounds.y2:=Ceil(bnd.y2 );
1364
m_advance_x:=int26p6_to_dbl(m_cur_face.glyph.advance.x );
1365
m_advance_y:=int26p6_to_dbl(m_cur_face.glyph.advance.y );
1367
m_affine.transform(@m_affine ,@m_advance_x ,@m_advance_y );
1375
glyph_ren_agg_mono :
1376
if m_last_error = 0 then
1382
m_path32.remove_all;
1384
decompose_ft_outline(
1385
@m_cur_face.glyph.outline ,
1390
m_rasterizer.add_path(@m_curves32 );
1395
m_path16.remove_all;
1397
decompose_ft_outline(
1398
@m_cur_face.glyph.outline ,
1403
m_rasterizer.add_path(@m_curves16 );
1407
m_scanlines_bin.prepare(1 ); // Remove all
1409
render_scanlines(@m_rasterizer ,@m_scanline_bin ,@m_scanlines_bin );
1411
m_bounds.x1:=m_scanlines_bin._min_x;
1412
m_bounds.y1:=m_scanlines_bin._min_y;
1413
m_bounds.x2:=m_scanlines_bin._max_x;
1414
m_bounds.y2:=m_scanlines_bin._max_y;
1415
m_data_size:=m_scanlines_bin.byte_size;
1416
m_data_type:=glyph_data_mono;
1417
m_advance_x:=int26p6_to_dbl(m_cur_face.glyph.advance.x );
1418
m_advance_y:=int26p6_to_dbl(m_cur_face.glyph.advance.y );
1420
m_affine.transform(@m_affine ,@m_advance_x ,@m_advance_y );
1426
glyph_ren_agg_gray8 :
1427
if m_last_error = 0 then
1433
m_path32.remove_all;
1435
decompose_ft_outline(
1436
@m_cur_face.glyph.outline ,
1441
m_rasterizer.add_path(@m_curves32 );
1446
m_path16.remove_all;
1448
decompose_ft_outline(
1449
@m_cur_face.glyph.outline ,
1454
m_rasterizer.add_path(@m_curves16 );
1458
m_scanlines_aa.prepare(1 ); // Remove all
1460
render_scanlines(@m_rasterizer ,@m_scanline_aa ,@m_scanlines_aa );
1462
m_bounds.x1:=m_scanlines_aa._min_x;
1463
m_bounds.y1:=m_scanlines_aa._min_y;
1464
m_bounds.x2:=m_scanlines_aa._max_x;
1465
m_bounds.y2:=m_scanlines_aa._max_y;
1466
m_data_size:=m_scanlines_aa.byte_size;
1467
m_data_type:=glyph_data_gray8;
1468
m_advance_x:=int26p6_to_dbl(m_cur_face.glyph.advance.x );
1469
m_advance_y:=int26p6_to_dbl(m_cur_face.glyph.advance.y );
1471
m_affine.transform(@m_affine ,@m_advance_x ,@m_advance_y );
1482
function font_engine_freetype_base.glyph_index : unsigned;
1484
result:=m_glyph_index;
1489
function font_engine_freetype_base.data_size : unsigned;
1491
result:=m_data_size;
1496
function font_engine_freetype_base.data_type : unsigned;
1498
result:=m_data_type;
1503
function font_engine_freetype_base.bounds : rect_ptr;
1510
function font_engine_freetype_base.advance_x : double;
1512
result:=m_advance_x;
1517
function font_engine_freetype_base.advance_y : double;
1519
result:=m_advance_y;
1524
procedure font_engine_freetype_base.write_glyph_to(data : int8u_ptr );
1526
if (data <> NIL ) and
1527
(m_data_size <> 0 ) then
1530
m_scanlines_bin.serialize(data );
1533
m_scanlines_aa.serialize(data );
1535
glyph_data_outline :
1537
m_path32.serialize(data )
1539
m_path16.serialize(data );
1546
function font_engine_freetype_base.add_kerning(first ,second : unsigned; x ,y : double_ptr ) : boolean;
1552
if (m_cur_face <> NIL ) and
1555
FT_HAS_KERNING(m_cur_face ) then
1557
FT_Get_Kerning(m_cur_face ,first ,second ,FT_KERNING_DEFAULT ,@delta );
1559
dx:=int26p6_to_dbl(delta.x );
1560
dy:=int26p6_to_dbl(delta.y );
1562
if (m_glyph_rendering = glyph_ren_outline ) or
1563
(m_glyph_rendering = glyph_ren_agg_mono ) or
1564
(m_glyph_rendering = glyph_ren_agg_gray8 ) then
1565
m_affine.transform_2x2(@m_affine ,@dx ,@dy );
1579
function font_engine_freetype_base.flag32;
1585
{ UPDATE_CHAR_SIZE }
1586
procedure font_engine_freetype_base.update_char_size;
1588
if m_cur_face <> NIL then
1590
if m_resolution <> 0 then
1593
m_width , // char_width in 1/64th of points
1594
m_height , // char_height in 1/64th of points
1595
m_resolution , // horizontal device resolution
1596
m_resolution ) // vertical device resolution
1600
m_width shr 6 , // pixel_width
1601
m_height shr 6 ); // pixel_height
1609
{ UPDATE_SIGNATURE }
1610
procedure font_engine_freetype_base.update_signature;
1612
name_len ,gamma_hash ,i : unsigned;
1614
gamma_table : array[0..aa_num - 1 ] of int8u;
1616
mtx : array[0..5 ] of double;
1617
buf : array[0..99 ] of char;
1621
if (m_cur_face <> NIL ) and
1622
(m_name <> NIL ) then
1624
name_len:=StrLen(m_name );
1626
if name_len > m_name_len then
1628
agg_freemem(pointer(m_signature.name ) ,m_signature.size );
1630
m_signature.size:=name_len + 32 + 256;
1632
agg_getmem(pointer(m_signature.name ) ,m_signature.size );
1634
m_name_len:=name_len + 32 - 1;
1640
if (m_glyph_rendering = glyph_ren_native_gray8 ) or
1641
(m_glyph_rendering = glyph_ren_agg_mono ) or
1642
(m_glyph_rendering = glyph_ren_agg_gray8 ) then
1644
for i:=0 to aa_num - 1 do
1645
gamma_table[i ]:=m_rasterizer.apply_gamma(i );
1647
gamma_hash:=calc_crc32(@gamma_table ,sizeof(gamma_table ) );
1651
str:=m_signature.name;
1653
sprintf(str ,'%s,' ,ptrcomp(m_name ) );
1654
sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%u,' ,int(m_char_map ) );
1655
sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,m_face_index );
1656
sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_glyph_rendering ) );
1657
sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d:' ,m_resolution );
1658
sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%dx' ,m_height );
1659
sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,m_width );
1660
sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_hinting ) );
1661
sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_flip_y ) );
1662
sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%08X' ,gamma_hash );
1664
if (m_glyph_rendering = glyph_ren_outline ) or
1665
(m_glyph_rendering = glyph_ren_agg_mono ) or
1666
(m_glyph_rendering = glyph_ren_agg_gray8 ) then
1668
m_affine.store_to(@mtx );
1670
sprintf(@buf[0 ] ,',%08X' ,dbl_to_plain_fx(mtx[0 ] ) );
1671
sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[1 ] ) );
1672
sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[2 ] ) );
1673
sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[3 ] ) );
1674
sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[4 ] ) );
1675
sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[5 ] ) );
1677
StrCat(PChar(m_signature.name ) ,buf );
1681
inc(m_change_stamp );
1688
function font_engine_freetype_base.find_face(name : PChar ) : int;
1699
while i < m_num_faces do
1701
if StrComp(name ,PChar(n.name ) ) = 0 then
1709
inc(ptrcomp(n ) ,sizeof(face_name ) );
1717
constructor font_engine_freetype_int16.Construct(max_faces : unsigned = 32 );
1719
inherited Construct(false ,max_faces );
1724
constructor font_engine_freetype_int32.Construct(max_faces : unsigned = 32 );
1726
inherited Construct(true ,max_faces );