1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4 (Public License)
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
6 // Pascal Port By: Milan Marusinec alias Milano
7 // milan@marusinec.sk
8 // http://www.aggpas.org
9 // Copyright (c) 2005-2006
10 //
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.
15 //
16 //----------------------------------------------------------------------------
17 // Contact: mcseem@antigrain.com
18 // mcseemagg@yahoo.com
19 // http://www.antigrain.com
20 //
21 // [Pascal Port History] -----------------------------------------------------
22 //
23 // 23.06.2006-Milano: ptrcomp adjustments
24 // 18.02.2006-Milano: Complete unit port
25 // 17.02.2006-Milano: Unit port establishment
26 //
27 { agg_font_win32_tt.pas }
28 unit
29 agg_font_win32_tt ;
30
31 INTERFACE
32
33 {$I agg_mode.inc }
34
35 uses
36 Windows ,SysUtils ,Math ,
37 agg_basics ,
38 agg_array ,
39 agg_bitset_iterator ,
40 agg_scanline_storage_aa ,
41 agg_scanline_storage_bin ,
42 agg_scanline ,
43 agg_scanline_u ,
44 agg_scanline_bin ,
45 agg_renderer_scanline ,
46 agg_render_scanlines ,
47 agg_path_storage_integer ,
48 agg_rasterizer_scanline_aa ,
49 agg_conv_curve ,
50 agg_trans_affine ,
51 agg_font_cache_manager ,
52 agg_font_engine ,
53 agg_vertex_source ;
54
55 { TYPES DEFINITION }
56 const
57 buf_size = 32768 - 32;
58
59 type
60 winapi_GetGlyphOutlineX = function (DC: HDC; p2, p3: UINT; const p4: TGlyphMetrics; p5: DWORD; p6: Pointer; const p7: TMat2): DWORD; stdcall;
61
62 HFONT_ptr = ^HFONT;
63 PChar_ptr = ^PChar;
64
65 KERNINGPAIR_ptr = ^KERNINGPAIR;
66
67 FIXED_ptr = ^FIXED;
68
69 TTPOLYGONHEADER_ptr = ^TTPOLYGONHEADER;
70
71 TTPOLYCURVE_ptr = ^TTPOLYCURVE;
72
73 POINTFX_ptr = ^POINTFX;
74
75 font_name_ptr = ^font_name;
76 font_name = record
77 name : char_ptr; //PChar;
78 size : unsigned;
79
80 end;
81
82 //-----------------------------------------------font_engine_win32_tt_base
83 font_engine_win32_tt_base = object(font_engine )
84 m_flag32 : boolean;
85 m_dc : HDC;
86
87 m_old_font : HFONT;
88 m_fonts : HFONT_ptr;
89
90 m_num_fonts ,
91 m_max_fonts : unsigned;
92 m_font_names : font_name_ptr;
93 m_cur_font : HFONT;
94
95 m_change_stamp : int;
96 m_typeface : font_name;
97 m_typeface_len : unsigned;
98 m_signature : font_name;
99
100 m_height ,
101 m_width : unsigned;
102 m_weight : int;
103 m_italic : boolean;
104 m_char_set : DWORD;
105
106 m_pitch_and_family : DWORD;
107
108 m_hinting ,
109 m_flip_y : boolean;
110
111 m_font_created : boolean;
112 m_resolution : unsigned;
113 m_glyph_rendering : glyph_rendering;
114 m_glyph_index : unsigned;
115
116 m_data_size ,
117 m_data_type : unsigned;
118 m_bounds : rect;
119 m_advance_x ,
120 m_advance_y : double;
121
122 m_matrix : TMAT2;
123 m_gbuf : int8u_ptr;
124
125 m_kerning_pairs : KERNINGPAIR_ptr;
126 m_num_kerning_pairs ,
127 m_max_kerning_pairs : unsigned;
128
129 m_affine : trans_affine;
130
131 m_path16 : path_storage_int16;
132 m_path32 : path_storage_int32;
133 m_curves16 ,
134 m_curves32 : conv_curve;
135
136 m_scanline_aa : scanline_u8;
137 m_scanline_bin : scanline_bin;
138 m_scanlines_aa : scanlines_aa_type;
139 m_scanlines_bin : scanlines_bin_type;
140 m_rasterizer : rasterizer_scanline_aa;
141
142 constructor Construct(flag32_ : boolean; dc : HDC; max_fonts : unsigned = 32 );
143 destructor Destruct;
144
145 // Set font parameters
146 procedure resolution_(dpi : unsigned );
147 procedure height_ (h : double );
148 procedure width_ (w : double );
149 procedure weight_ (w : int );
150 procedure italic_ (it : boolean );
151 procedure char_set_ (c : DWORD );
152
153 procedure pitch_and_family_(p : DWORD );
154
155 procedure flip_y_ (flip : boolean );
156 procedure hinting_(h : boolean );
157
create_fontnull158 function create_font (typeface_ : PChar; ren_type : glyph_rendering ) : boolean;
create_font_null159 function create_font_(
160 typeface : PChar;
161 ren_type : glyph_rendering;
162 height : double;
163 width : double = 0.0;
164 weight : int = FW_REGULAR;
165 italic : boolean = false;
166 char_set : DWORD = ANSI_CHARSET;
167 pitch_and_family : DWORD = FF_DONTCARE ) : boolean;
168
169 // Set Gamma
170 procedure gamma_ (f : vertex_source_ptr );
171 procedure transform_(mtx : trans_affine_ptr );
172
173 // Accessors
_resolutionnull174 function _resolution : unsigned;
_typefacenull175 function _typeface : PChar;
_heightnull176 function _height : double;
_widthnull177 function _width : double;
_weightnull178 function _weight : int;
_italicnull179 function _italic : boolean;
_char_setnull180 function _char_set : DWORD;
_pitch_and_familynull181 function _pitch_and_family : DWORD;
_hintingnull182 function _hinting : boolean;
_flip_ynull183 function _flip_y : boolean;
184
185 // Interface mandatory to implement for font_cache_manager
font_signaturenull186 function font_signature : PChar; virtual;
change_stampnull187 function change_stamp : int; virtual;
188
prepare_glyphnull189 function prepare_glyph(glyph_code : unsigned ) : boolean; virtual;
190
glyph_indexnull191 function glyph_index : unsigned; virtual;
data_sizenull192 function data_size : unsigned; virtual;
data_typenull193 function data_type : unsigned; virtual;
boundsnull194 function bounds : rect_ptr; virtual;
advance_xnull195 function advance_x : double; virtual;
advance_ynull196 function advance_y : double; virtual;
197
198 procedure write_glyph_to(data : int8u_ptr ); virtual;
add_kerningnull199 function add_kerning (first ,second : unsigned; x ,y : double_ptr ) : boolean; virtual;
200
flag32null201 function flag32 : boolean; virtual;
202
203 // Private
204 procedure update_signature;
pair_lessnull205 function pair_less(v1 ,v2 : KERNINGPAIR_ptr ) : boolean;
206
207 procedure load_kerning_pairs;
208 procedure sort_kerning_pairs;
209
find_fontnull210 function find_font(name : PChar ) : int;
211
212 end;
213
214 //------------------------------------------------font_engine_win32_tt_int16
215 // This class uses values of type int16 (10.6 format) for the vector cache.
216 // The vector cache is compact, but when rendering glyphs of height
217 // more that 200 there integer overflow can occur.
218 font_engine_win32_tt_int16 = object(font_engine_win32_tt_base )
219 constructor Construct(dc : HDC; max_fonts : unsigned = 32 );
220
221 end;
222
223
224 //------------------------------------------------font_engine_win32_tt_int32
225 // This class uses values of type int32 (26.6 format) for the vector cache.
226 // The vector cache is twice larger than in font_engine_win32_tt_int16,
227 // but it allows you to render glyphs of very large sizes.
228 font_engine_win32_tt_int32 = object(font_engine_win32_tt_base )
229 constructor Construct(dc : HDC; max_fonts : unsigned = 32 );
230
231 end;
232
233 var
234 GetGlyphOutlineX : winapi_GetGlyphOutlineX;
235
236 { GLOBAL PROCEDURES }
237
238
239 IMPLEMENTATION
240 { LOCAL VARIABLES & CONSTANTS }
241 //------------------------------------------------------------------------------
242 //
243 // This code implements the AUTODIN II polynomial
244 // The variable corresponding to the macro argument "crc" should
245 // be an unsigned long.
246 // Oroginal code by Spencer Garrett <srg@quick.com>
247 //
248 // generated using the AUTODIN II polynomial
249 // x^32 + x^26 + x^23 + x^22 + x^16 +
250 // x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
251 //
252 //------------------------------------------------------------------------------
253 const
254 crc32tab : array[0..255 ] of unsigned = (
255 $00000000, $77073096, $ee0e612c, $990951ba,
256 $076dc419, $706af48f, $e963a535, $9e6495a3,
257 $0edb8832, $79dcb8a4, $e0d5e91e, $97d2d988,
258 $09b64c2b, $7eb17cbd, $e7b82d07, $90bf1d91,
259 $1db71064, $6ab020f2, $f3b97148, $84be41de,
260 $1adad47d, $6ddde4eb, $f4d4b551, $83d385c7,
261 $136c9856, $646ba8c0, $fd62f97a, $8a65c9ec,
262 $14015c4f, $63066cd9, $fa0f3d63, $8d080df5,
263 $3b6e20c8, $4c69105e, $d56041e4, $a2677172,
264 $3c03e4d1, $4b04d447, $d20d85fd, $a50ab56b,
265 $35b5a8fa, $42b2986c, $dbbbc9d6, $acbcf940,
266 $32d86ce3, $45df5c75, $dcd60dcf, $abd13d59,
267 $26d930ac, $51de003a, $c8d75180, $bfd06116,
268 $21b4f4b5, $56b3c423, $cfba9599, $b8bda50f,
269 $2802b89e, $5f058808, $c60cd9b2, $b10be924,
270 $2f6f7c87, $58684c11, $c1611dab, $b6662d3d,
271 $76dc4190, $01db7106, $98d220bc, $efd5102a,
272 $71b18589, $06b6b51f, $9fbfe4a5, $e8b8d433,
273 $7807c9a2, $0f00f934, $9609a88e, $e10e9818,
274 $7f6a0dbb, $086d3d2d, $91646c97, $e6635c01,
275 $6b6b51f4, $1c6c6162, $856530d8, $f262004e,
276 $6c0695ed, $1b01a57b, $8208f4c1, $f50fc457,
277 $65b0d9c6, $12b7e950, $8bbeb8ea, $fcb9887c,
278 $62dd1ddf, $15da2d49, $8cd37cf3, $fbd44c65,
279 $4db26158, $3ab551ce, $a3bc0074, $d4bb30e2,
280 $4adfa541, $3dd895d7, $a4d1c46d, $d3d6f4fb,
281 $4369e96a, $346ed9fc, $ad678846, $da60b8d0,
282 $44042d73, $33031de5, $aa0a4c5f, $dd0d7cc9,
283 $5005713c, $270241aa, $be0b1010, $c90c2086,
284 $5768b525, $206f85b3, $b966d409, $ce61e49f,
285 $5edef90e, $29d9c998, $b0d09822, $c7d7a8b4,
286 $59b33d17, $2eb40d81, $b7bd5c3b, $c0ba6cad,
287 $edb88320, $9abfb3b6, $03b6e20c, $74b1d29a,
288 $ead54739, $9dd277af, $04db2615, $73dc1683,
289 $e3630b12, $94643b84, $0d6d6a3e, $7a6a5aa8,
290 $e40ecf0b, $9309ff9d, $0a00ae27, $7d079eb1,
291 $f00f9344, $8708a3d2, $1e01f268, $6906c2fe,
292 $f762575d, $806567cb, $196c3671, $6e6b06e7,
293 $fed41b76, $89d32be0, $10da7a5a, $67dd4acc,
294 $f9b9df6f, $8ebeeff9, $17b7be43, $60b08ed5,
295 $d6d6a3e8, $a1d1937e, $38d8c2c4, $4fdff252,
296 $d1bb67f1, $a6bc5767, $3fb506dd, $48b2364b,
297 $d80d2bda, $af0a1b4c, $36034af6, $41047a60,
298 $df60efc3, $a867df55, $316e8eef, $4669be79,
299 $cb61b38c, $bc66831a, $256fd2a0, $5268e236,
300 $cc0c7795, $bb0b4703, $220216b9, $5505262f,
301 $c5ba3bbe, $b2bd0b28, $2bb45a92, $5cb36a04,
302 $c2d7ffa7, $b5d0cf31, $2cd99e8b, $5bdeae1d,
303 $9b64c2b0, $ec63f226, $756aa39c, $026d930a,
304 $9c0906a9, $eb0e363f, $72076785, $05005713,
305 $95bf4a82, $e2b87a14, $7bb12bae, $0cb61b38,
306 $92d28e9b, $e5d5be0d, $7cdcefb7, $0bdbdf21,
307 $86d3d2d4, $f1d4e242, $68ddb3f8, $1fda836e,
308 $81be16cd, $f6b9265b, $6fb077e1, $18b74777,
309 $88085ae6, $ff0f6a70, $66063bca, $11010b5c,
310 $8f659eff, $f862ae69, $616bffd3, $166ccf45,
311 $a00ae278, $d70dd2ee, $4e048354, $3903b3c2,
312 $a7672661, $d06016f7, $4969474d, $3e6e77db,
313 $aed16a4a, $d9d65adc, $40df0b66, $37d83bf0,
314 $a9bcae53, $debb9ec5, $47b2cf7f, $30b5ffe9,
315 $bdbdf21c, $cabac28a, $53b39330, $24b4a3a6,
316 $bad03605, $cdd70693, $54de5729, $23d967bf,
317 $b3667a2e, $c4614ab8, $5d681b02, $2a6f2b94,
318 $b40bbe37, $c30c8ea1, $5a05df1b, $2d02ef8d );
319
320 { UNIT IMPLEMENTATION }
321 { calc_crc32 }
calc_crc32null322 function calc_crc32(buf : int8u_ptr; size : unsigned ) : unsigned;
323 var
324 crc ,len ,nr : unsigned;
325
326 p : int8u_ptr;
327
328 begin
329 crc:=unsigned(not 0 );
330 len:=0;
331 nr :=size;
332 len:=len + nr;
333 p :=buf;
334
335 while nr <> 0 do
336 begin
337 dec(nr );
338
339 crc:=(crc shr 8 ) xor crc32tab[(crc xor p^ ) and $ff ];
340
341 inc(ptrcomp(p ) ,sizeof(int8u ) );
342
343 end;
344
345 result:=not crc;
346
347 end;
348
349 { dbl_to_fx }
dbl_to_fxnull350 function dbl_to_fx(d : double ) : FIXED;
351 var
352 l : int;
353
354 begin
355 l:=trunc(d * 65536.0 );
356
357 move(l ,result ,sizeof(int ) );
358
359 end;
360
361 { dbl_to_plain_fx }
dbl_to_plain_fxnull362 function dbl_to_plain_fx(d : double ) : int;
363 begin
364 result:=trunc(d * 65536.0 );
365
366 end;
367
368 { negate_fx }
negate_fxnull369 function negate_fx(fx : FIXED_ptr ) : FIXED;
370 var
371 l : int;
372
373 begin
374 l:=-int(fx );
375
376 move(l ,result ,sizeof(int ) );
377
378 end;
379
380 { fx_to_dbl }
fx_to_dblnull381 function fx_to_dbl(p : FIXED_ptr ) : double;
382 begin
383 result:=p.value + p.fract * (1.0 / 65536.0 );
384
385 end;
386
387 { fx_to_plain_int }
fx_to_plain_intnull388 function fx_to_plain_int(fx : FIXED_ptr ) : int;
389 begin
390 result:=int(fx );
391
392 end;
393
394 { fx_to_int26p6 }
fx_to_int26p6null395 function fx_to_int26p6(p : FIXED_ptr ) : int;
396 begin
397 result:=(int(p.value ) shl 6 ) + (shr_int32(int(p.fract ) ,10 ) );
398
399 end;
400
401 { dbl_to_int26p6 }
dbl_to_int26p6null402 function dbl_to_int26p6(p : double ) : int;
403 begin
404 result:=trunc(p * 64.0 + 0.5 );
405
406 end;
407
408 { decompose_win32_glyph_bitmap_mono }
409 procedure decompose_win32_glyph_bitmap_mono(
410 gbuf : int8u_ptr;
411 w ,h ,x ,y : int;
412 flip_y : boolean;
413 sl : scanline_ptr;
414 storage : renderer_scanline_ptr );
415 var
416 i ,pitch ,j : int;
417
418 buf : int8u_ptr;
419 bits : bitset_iterator;
420
421 begin
422 pitch:=shr_int32(w + 31 ,5 ) shl 2;
423 buf :=gbuf;
424
425 sl.reset (x ,x + w );
426 storage.prepare(w + 2 );
427
428 if flip_y then
429 begin
430 inc(ptrcomp(buf ) ,(pitch * (h - 1 ) ) * sizeof(int8u ) );
431 inc(y ,h );
432
433 pitch:=-pitch;
434
435 end;
436
437 i:=0;
438
439 while i < h do
440 begin
441 sl.reset_spans;
442
443 bits.Construct(buf ,0 );
444
445 j:=0;
446
447 while j < w do
448 begin
449 if bits.bit <> 0 then
450 sl.add_cell(x + j ,cover_full );
451
452 bits.inc_operator;
453
454 inc(j );
455
456 end;
457
458 inc(ptrcomp(buf ) ,pitch * sizeof(int8u ) );
459
460 if sl.num_spans <> 0 then
461 begin
462 sl.finalize (y - i - 1 );
463 storage.render(sl );
464
465 end;
466
467 inc(i );
468
469 end;
470
471 end;
472
473 { decompose_win32_glyph_bitmap_gray8 }
474 procedure decompose_win32_glyph_bitmap_gray8(
475 gbuf : int8u_ptr;
476 w ,h ,x ,y : int;
477 flip_y : boolean;
478 ras : rasterizer_scanline_aa_ptr;
479 sl : scanline_ptr;
480 storage : renderer_scanline_ptr );
481 var
482 i ,j ,pitch : int;
483
484 buf ,p : int8u_ptr;
485
486 v : unsigned;
487
488 begin
489 pitch:=shr_int32(w + 3 ,2 ) shl 2;
490 buf :=gbuf;
491
492 sl.reset (x ,x + w );
493 storage.prepare(w + 2 );
494
495 if flip_y then
496 begin
497 inc(ptrcomp(buf ) ,(pitch * (h - 1 ) ) * sizeof(int8u ) );
498 inc(y ,h );
499
500 pitch:=-pitch;
501
502 end;
503
504 i:=0;
505
506 while i < h do
507 begin
508 sl.reset_spans;
509
510 p:=buf;
511 j:=0;
512
513 while j < w do
514 begin
515 if p^ <> 0 then
516 begin
517 v:=p^;
518
519 if v = 64 then
520 v:=255
521 else
522 v:=v shl 2;
523
524 sl.add_cell(x + j ,ras.apply_gamma(v ) );
525
526 end;
527
528 inc(ptrcomp(p ) ,sizeof(int8u ) );
529 inc(j );
530
531 end;
532
533 inc(ptrcomp(buf ) ,pitch * sizeof(int8u ) );
534
535 if sl.num_spans <> 0 then
536 begin
537 sl.finalize (y - i - 1 );
538 storage.render(sl );
539
540 end;
541
542 inc(i );
543
544 end;
545
546 end;
547
548 { decompose_win32_glyph_outline }
decompose_win32_glyph_outlinenull549 function decompose_win32_glyph_outline(
550 gbuf : int8u_ptr;
551 total_size : unsigned;
552 flip_y : boolean;
553 mtx : trans_affine_ptr;
554 path : path_storage_integer_ptr ) : boolean;
555 var
556 cur_glyph ,end_glyph ,end_poly ,cur_poly : int8u_ptr;
557
558 x ,y ,x2 ,y2 : double;
559
560 i ,u : int;
561
562 th : TTPOLYGONHEADER_ptr;
563 pc : TTPOLYCURVE_ptr;
564
565 pnt_b ,pnt_c : POINTFX;
566
567 cx ,cy ,bx ,by : int;
568
569 begin
570 cur_glyph:=gbuf;
571 end_glyph:=int8u_ptr(ptrcomp(gbuf ) + total_size * sizeof(int8u ) );
572
573 while ptrcomp(cur_glyph ) < ptrcomp(end_glyph ) do
574 begin
575 th:=TTPOLYGONHEADER_ptr(cur_glyph );
576
577 end_poly:=int8u_ptr(ptrcomp(cur_glyph ) + th.cb );
578 cur_poly:=int8u_ptr(ptrcomp(cur_glyph ) + sizeof(TTPOLYGONHEADER ) );
579
580 x:=fx_to_dbl(@th.pfxStart.x );
581 y:=fx_to_dbl(@th.pfxStart.y );
582
583 if flip_y then
584 y:=-y;
585
586 mtx.transform(mtx ,@x ,@y );
587 path.move_to (dbl_to_int26p6(x ) ,dbl_to_int26p6(y ) );
588
589 while ptrcomp(cur_poly ) < ptrcomp(end_poly ) do
590 begin
591 pc:=TTPOLYCURVE_ptr(cur_poly );
592
593 if pc.wType = TT_PRIM_LINE then
594 begin
595 i:=0;
596
597 while i < pc.cpfx do
598 begin
599 x:=fx_to_dbl(@POINTFX_ptr(ptrcomp(@pc.apfx ) + i * sizeof(POINTFX ) ).x );
600 y:=fx_to_dbl(@POINTFX_ptr(ptrcomp(@pc.apfx ) + i * sizeof(POINTFX ) ).y );
601
602 if flip_y then
603 y:=-y;
604
605 mtx.transform(mtx ,@x ,@y );
606 path.line_to (dbl_to_int26p6(x ) ,dbl_to_int26p6(y ) );
607
608 inc(i );
609
610 end;
611
612 end;
613
614 if pc.wType = TT_PRIM_QSPLINE then
615 begin
616 u:=0;
617
618 while u < pc.cpfx - 1 do // Walk through points in spline
619 begin
620 // B is always the current point
621 pnt_b:=POINTFX_ptr(ptrcomp(@pc.apfx ) + u * sizeof(POINTFX ) )^;
622 pnt_c:=POINTFX_ptr(ptrcomp(@pc.apfx ) + (u + 1 ) * sizeof(POINTFX ) )^;
623
624 if u < pc.cpfx - 2 then // If not on last spline, compute C
625 begin
626 // midpoint (x,y)
627 // int(pnt_c.x ):=int(pnt_b.x ) + int(pnt_c.x ) div 2;
628 // int(pnt_c.y ):=int(pnt_b.y ) + int(pnt_c.y ) div 2;
629 move(pnt_b.x ,bx ,sizeof(int ) );
630 move(pnt_b.y ,by ,sizeof(int ) );
631 move(pnt_c.x ,cx ,sizeof(int ) );
632 move(pnt_c.y ,cy ,sizeof(int ) );
633
634 cx:=(bx + cx ) div 2;
635 cy:=(by + cy ) div 2;
636
637 move(cx ,pnt_c.x ,sizeof(int ) );
638 move(cy ,pnt_c.y ,sizeof(int ) );
639
640 end;
641
642 x :=fx_to_dbl(@pnt_b.x );
643 y :=fx_to_dbl(@pnt_b.y );
644 x2:=fx_to_dbl(@pnt_c.x );
645 y2:=fx_to_dbl(@pnt_c.y );
646
647 if flip_y then
648 begin
649 y :=-y;
650 y2:=-y2;
651
652 end;
653
654 mtx.transform(mtx ,@x ,@y );
655 mtx.transform(mtx ,@x2 ,@y2 );
656
657 path.curve3(
658 dbl_to_int26p6(x ) ,dbl_to_int26p6(y ) ,
659 dbl_to_int26p6(x2 ) ,dbl_to_int26p6(y2 ) );
660
661 inc(u );
662
663 end;
664
665 end;
666
667 inc(ptrcomp(cur_poly ) ,sizeof(WORD ) * 2 + sizeof(POINTFX ) * pc.cpfx );
668
669 end;
670
671 inc(ptrcomp(cur_glyph ) ,th.cb );
672
673 end;
674
675 result:=true;
676
677 end;
678
679 { CONSTRUCT }
680 constructor font_engine_win32_tt_base.Construct;
681 begin
682 m_flag32:=flag32_;
683 m_dc :=dc;
684
685 if m_dc <> 0 then
686 m_old_font:=GetCurrentObject(m_dc ,OBJ_FONT )
687 else
688 m_old_font:=0;
689
690 agg_getmem(pointer(m_fonts ) ,sizeof(HFONT ) * max_fonts );
691
692 m_num_fonts:=0;
693 m_max_fonts:=max_fonts;
694
695 agg_getmem(pointer(m_font_names ) ,sizeof(font_name ) * max_fonts );
696
697 m_cur_font :=0;
698 m_change_stamp:=0;
699
700 m_typeface.size:=sizeof(char ) * (256 - 16 );
701
702 agg_getmem(pointer(m_typeface.name ) ,m_typeface.size );
703
704 m_typeface_len:=256 - 16 - 1;
705
706 m_signature.size:=sizeof(char ) * (256 + 256 - 16 );
707
708 agg_getmem(pointer(m_signature.name ) ,m_signature.size );
709
710 m_height :=0;
711 m_width :=0;
712 m_weight :=FW_REGULAR;
713 m_italic :=false;
714 m_char_set:=DEFAULT_CHARSET;
715
716 m_pitch_and_family:=FF_DONTCARE;
717
718 m_hinting:=true;
719 m_flip_y :=false;
720
721 m_font_created :=false;
722 m_resolution :=0;
723 m_glyph_rendering:=glyph_ren_native_gray8;
724
725 m_glyph_index:=0;
726 m_data_size :=0;
727 m_data_type :=glyph_data_invalid;
728
729 m_bounds.Construct(1 ,1 ,0 ,0 );
730
731 m_advance_x:=0.0;
732 m_advance_y:=0.0;
733
734 agg_getmem(pointer(m_gbuf ) ,sizeof(int8u ) * buf_size );
735
736 m_kerning_pairs :=NIL;
737 m_num_kerning_pairs:=0;
738 m_max_kerning_pairs:=0;
739
740 m_affine.Construct;
741
742 m_path16.Construct;
743 m_path32.Construct;
744 m_curves16.Construct(@m_path16 );
745 m_curves32.Construct(@m_path32 );
746 m_scanline_aa.Construct;
747 m_scanline_bin.Construct;
748 m_scanlines_aa.Construct;
749 m_scanlines_bin.Construct;
750 m_rasterizer.Construct;
751
752 m_curves16.approximation_scale_(4.0 );
753 m_curves32.approximation_scale_(4.0 );
754
755 fillchar(m_matrix ,sizeof(m_matrix ) ,0 );
756
757 m_matrix.eM11.value:=1;
758 m_matrix.eM22.value:=1;
759
760 end;
761
762 { DESTRUCT }
763 destructor font_engine_win32_tt_base.Destruct;
764 var
765 i : unsigned;
766 f : HFONT_ptr;
767 n : font_name_ptr;
768
769 begin
770 agg_freemem(pointer(m_kerning_pairs ) ,m_max_kerning_pairs * sizeof(KERNINGPAIR ) );
771 agg_freemem(pointer(m_gbuf ) ,sizeof(int8u ) * buf_size );
772 agg_freemem(pointer(m_signature.name ) ,m_signature.size );
773 agg_freemem(pointer(m_typeface.name ) ,m_typeface.size );
774
775 if (m_dc <> 0 ) and
776 (m_old_font <> 0 ) then
777 SelectObject(m_dc ,m_old_font );
778
779 i:=0;
780 f:=m_fonts;
781 n:=m_font_names;
782
783 while i < m_num_fonts do
784 begin
785 agg_freemem (pointer(n.name ) ,n.size );
786 DeleteObject(f^ );
787
788 inc(ptrcomp(n ) ,sizeof(font_name ) );
789 inc(ptrcomp(f ) ,sizeof(HFONT ) );
790 inc(i );
791
792 end;
793
794 agg_freemem(pointer(m_font_names ) ,sizeof(font_name ) * m_max_fonts );
795 agg_freemem(pointer(m_fonts ) ,sizeof(HFONT ) * m_max_fonts );
796
797 m_path16.Destruct;
798 m_path32.Destruct;
799 m_curves16.Destruct;
800 m_curves32.Destruct;
801 m_scanline_aa.Destruct;
802 m_scanline_bin.Destruct;
803 m_scanlines_aa.Destruct;
804 m_scanlines_bin.Destruct;
805 m_rasterizer.Destruct;
806
807 end;
808
809 { RESOLUTION_ }
810 procedure font_engine_win32_tt_base.resolution_;
811 begin
812 m_resolution:=dpi;
813
814 end;
815
816 { HEIGHT_ }
817 procedure font_engine_win32_tt_base.height_;
818 begin
819 m_height:=trunc(h );
820
821 end;
822
823 { WIDTH_ }
824 procedure font_engine_win32_tt_base.width_;
825 begin
826 m_width:=trunc(w );
827
828 end;
829
830 { WEIGHT_ }
831 procedure font_engine_win32_tt_base.weight_;
832 begin
833 m_weight:=w;
834
835 end;
836
837 { ITALIC_ }
838 procedure font_engine_win32_tt_base.italic_;
839 begin
840 m_italic:=it;
841
842 end;
843
844 { CHAR_SET_ }
845 procedure font_engine_win32_tt_base.char_set_;
846 begin
847 m_char_set:=c;
848
849 end;
850
851 { PITCH_AND_FAMILY_ }
852 procedure font_engine_win32_tt_base.pitch_and_family_;
853 begin
854 m_pitch_and_family:=p;
855
856 end;
857
858 { FLIP_Y_ }
859 procedure font_engine_win32_tt_base.flip_y_;
860 begin
861 m_flip_y:=flip;
862
863 end;
864
865 { HINTING_ }
866 procedure font_engine_win32_tt_base.hinting_;
867 begin
868 m_hinting:=h;
869
870 end;
871
872 { CREATE_FONT }
font_engine_win32_tt_base.create_fontnull873 function font_engine_win32_tt_base.create_font;
874 var
875 len : unsigned;
876
877 h ,w ,idx : int;
878
879 f : HFONT_ptr;
880 n : font_name_ptr;
881
882 begin
883 if m_dc <> 0 then
884 begin
885 len:=StrLen(typeface_ );
886
887 if len > m_typeface_len then
888 begin
889 agg_freemem(pointer(m_signature.name ) ,m_signature.size );
890 agg_freemem(pointer(m_typeface.name ) ,m_typeface.size );
891
892 m_typeface.size :=sizeof(char ) * (len + 32 );
893 m_signature.size:=sizeof(char ) * (len + 32 + 256 );
894
895 agg_getmem(pointer(m_typeface.name ) ,m_typeface.size );
896 agg_getmem(pointer(m_signature.name ) ,m_signature.size );
897
898 m_typeface_len:=len + 32 - 1;
899
900 end;
901
902 StrCopy(PChar(m_typeface.name ) ,typeface_ );
903
904 h:=m_height;
905 w:=m_width;
906
907 if m_resolution <> 0 then
908 begin
909 h:=MulDiv(m_height ,m_resolution ,72 );
910 w:=MulDiv(m_width ,m_resolution ,72 );
911
912 end;
913
914 m_glyph_rendering:=ren_type;
915
916 update_signature;
917
918 idx:=find_font(PChar(m_signature.name ) );
919
920 if idx >= 0 then
921 begin
922 m_cur_font:=HFONT_ptr(ptrcomp(m_fonts ) + idx * sizeof(HFONT ) )^;
923
924 SelectObject(m_dc ,m_cur_font );
925
926 m_num_kerning_pairs:=0;
927
928 result:=true;
929
930 exit;
931
932 end
933 else
934 begin
935 m_cur_font:=
936 CreateFont(
937 -h , // height of font
938 w , // average character width
939 0 , // angle of escapement
940 0 , // base-line orientation angle
941 m_weight , // font weight
942 unsigned(m_italic ) , // italic attribute option
943 0 , // underline attribute option
944 0 , // strikeout attribute option
945 m_char_set , // character set identifier
946 OUT_DEFAULT_PRECIS , // output precision
947 CLIP_DEFAULT_PRECIS , // clipping precision
948 ANTIALIASED_QUALITY , // output quality
949 m_pitch_and_family , // pitch and family
950 PChar(m_typeface.name ) // typeface name
951 );
952
953 if m_cur_font <> 0 then
954 begin
955 if m_num_fonts >= m_max_fonts then
956 begin
957 agg_freemem(pointer(m_font_names.name ) ,m_font_names.size );
958
959 if m_old_font <> 0 then
960 SelectObject(m_dc ,m_old_font );
961
962 DeleteObject(m_fonts^ );
963
964 move(
965 HFONT_ptr(ptrcomp(m_fonts ) + 1 * sizeof(HFONT ) )^ ,
966 m_fonts^ ,
967 (m_max_fonts - 1 ) * sizeof(HFONT ) );
968
969 move(
970 font_name_ptr(ptrcomp(m_font_names ) + 1 * sizeof(font_name ) )^ ,
971 m_font_names^ ,
972 (m_max_fonts - 1 ) * sizeof(font_name ) );
973
974 m_num_fonts:=m_max_fonts - 1;
975
976 end;
977
978 update_signature;
979
980 n:=font_name_ptr(ptrcomp(m_font_names ) + m_num_fonts * sizeof(font_name ) );
981 f:=HFONT_ptr(ptrcomp(m_fonts ) + m_num_fonts * sizeof(HFONT ) );
982
983 n.size:=sizeof(char ) * (StrLen(PChar(m_signature.name ) ) + 1 );
984
985 agg_getmem(pointer(n.name ) ,n.size );
986 StrCopy (PChar(n.name ) ,PChar(m_signature.name ) );
987
988 f^:=m_cur_font;
989
990 inc(m_num_fonts );
991
992 SelectObject(m_dc ,m_cur_font );
993
994 m_num_kerning_pairs:=0;
995
996 result:=true;
997
998 exit;
999
1000 end;
1001
1002 end;
1003
1004 end;
1005
1006 result:=false;
1007
1008 end;
1009
1010 { CREATE_FONT_ }
font_engine_win32_tt_base.create_font_null1011 function font_engine_win32_tt_base.create_font_;
1012 begin
1013 height_ (height );
1014 width_ (width );
1015 weight_ (weight );
1016 italic_ (italic );
1017 char_set_(char_set );
1018
1019 pitch_and_family_(pitch_and_family );
1020
1021 result:=create_font(typeface ,ren_type );
1022
1023 end;
1024
1025 { GAMMA_ }
1026 procedure font_engine_win32_tt_base.gamma_;
1027 begin
1028 m_rasterizer.gamma(f );
1029
1030 end;
1031
1032 { TRANSFORM_ }
1033 procedure font_engine_win32_tt_base.transform_;
1034 begin
1035 m_affine.assign_all(mtx );
1036
1037 end;
1038
1039 { _RESOLUTION }
font_engine_win32_tt_base._resolutionnull1040 function font_engine_win32_tt_base._resolution;
1041 begin
1042 result:=m_resolution;
1043
1044 end;
1045
1046 { _TYPEFACE }
font_engine_win32_tt_base._typefacenull1047 function font_engine_win32_tt_base._typeface;
1048 begin
1049 result:=PChar(m_typeface.name );
1050
1051 end;
1052
1053 { _HEIGHT }
font_engine_win32_tt_base._heightnull1054 function font_engine_win32_tt_base._height;
1055 begin
1056 result:=m_height;
1057
1058 end;
1059
1060 { _WIDTH }
font_engine_win32_tt_base._widthnull1061 function font_engine_win32_tt_base._width;
1062 begin
1063 result:=m_width;
1064
1065 end;
1066
1067 { _WEIGHT }
font_engine_win32_tt_base._weightnull1068 function font_engine_win32_tt_base._weight;
1069 begin
1070 result:=m_weight;
1071
1072 end;
1073
1074 { _ITALIC }
font_engine_win32_tt_base._italicnull1075 function font_engine_win32_tt_base._italic;
1076 begin
1077 result:=m_italic;
1078
1079 end;
1080
1081 { _CHAR_SET }
font_engine_win32_tt_base._char_setnull1082 function font_engine_win32_tt_base._char_set;
1083 begin
1084 result:=m_char_set;
1085
1086 end;
1087
1088 { _PITCH_AND_FAMILY }
font_engine_win32_tt_base._pitch_and_familynull1089 function font_engine_win32_tt_base._pitch_and_family;
1090 begin
1091 result:=m_pitch_and_family;
1092
1093 end;
1094
1095 { _HINTING }
font_engine_win32_tt_base._hintingnull1096 function font_engine_win32_tt_base._hinting;
1097 begin
1098 result:=m_hinting;
1099
1100 end;
1101
1102 { _FLIP_Y }
font_engine_win32_tt_base._flip_ynull1103 function font_engine_win32_tt_base._flip_y;
1104 begin
1105 result:=m_flip_y;
1106
1107 end;
1108
1109 { FONT_SIGNATURE }
font_engine_win32_tt_base.font_signaturenull1110 function font_engine_win32_tt_base.font_signature;
1111 begin
1112 result:=PChar(m_signature.name );
1113
1114 end;
1115
1116 { CHANGE_STAMP }
font_engine_win32_tt_base.change_stampnull1117 function font_engine_win32_tt_base.change_stamp;
1118 begin
1119 result:=m_change_stamp;
1120
1121 end;
1122
1123 { PREPARE_GLYPH }
font_engine_win32_tt_base.prepare_glyphnull1124 function font_engine_win32_tt_base.prepare_glyph;
1125 const
1126 GGO_UNHINTED = $0100; // For compatibility with old SDKs.
1127
1128 var
1129 format ,total_size : int;
1130
1131 gm : TGLYPHMETRICS;
1132 fl : longint;
1133 ts : DWORD;
1134
1135 bnd : rect_d;
1136
1137 begin
1138 if (m_dc <> 0 ) and
1139 (m_cur_font <> 0 ) then
1140 begin
1141 format:=GGO_BITMAP;
1142
1143 case m_glyph_rendering of
1144 glyph_ren_native_gray8 :
1145 format:=GGO_GRAY8_BITMAP;
1146
1147 glyph_ren_outline ,
1148 glyph_ren_agg_mono ,
1149 glyph_ren_agg_gray8 :
1150 format:=GGO_NATIVE;
1151
1152 end;
1153
1154 if not m_hinting then
1155 format:=format or GGO_UNHINTED;
1156
1157 ts:=
1158 GetGlyphOutlineX(
1159 m_dc ,
1160 glyph_code ,
1161 format ,
1162 gm ,
1163 buf_size ,
1164 m_gbuf ,
1165 m_matrix );
1166
1167 move(ts ,total_size ,sizeof(int ) );
1168
1169 if total_size < 0 then
1170 begin
1171 // GetGlyphOutline() fails when being called for
1172 // GGO_GRAY8_BITMAP and white space (stupid Microsoft).
1173 // It doesn't even initialize the glyph metrics
1174 // structure. So, we have to query the metrics
1175 // separately (basically we need gmCellIncX).
1176 ts:=
1177 GetGlyphOutlineX(
1178 m_dc ,
1179 glyph_code ,
1180 GGO_METRICS ,
1181 gm ,
1182 buf_size ,
1183 m_gbuf ,
1184 m_matrix );
1185
1186 move(ts ,total_size ,sizeof(int ) );
1187
1188 if total_size < 0 then
1189 begin
1190 result:=false;
1191
1192 exit;
1193
1194 end;
1195
1196 gm.gmBlackBoxX:=0;
1197 gm.gmBlackBoxY:=0;
1198
1199 total_size:=0;
1200
1201 end;
1202
1203 m_glyph_index:=glyph_code;
1204 m_advance_x :=gm.gmCellIncX;
1205 m_advance_y :=-gm.gmCellIncY;
1206
1207 case m_glyph_rendering of
1208 glyph_ren_native_mono :
1209 begin
1210 if m_flip_y then
1211 fl:=-gm.gmptGlyphOrigin.y
1212 else
1213 fl:=gm.gmptGlyphOrigin.y;
1214
1215 decompose_win32_glyph_bitmap_mono(
1216 m_gbuf ,
1217 gm.gmBlackBoxX ,
1218 gm.gmBlackBoxY ,
1219 gm.gmptGlyphOrigin.x ,
1220 fl ,
1221 m_flip_y ,
1222 @m_scanline_bin ,
1223 @m_scanlines_bin );
1224
1225 m_bounds.x1:=m_scanlines_bin._min_x;
1226 m_bounds.y1:=m_scanlines_bin._min_y;
1227 m_bounds.x2:=m_scanlines_bin._max_x;
1228 m_bounds.y2:=m_scanlines_bin._max_y;
1229 m_data_size:=m_scanlines_bin.byte_size;
1230 m_data_type:=glyph_data_mono;
1231
1232 result:=true;
1233
1234 exit;
1235
1236 end;
1237
1238 glyph_ren_native_gray8 :
1239 begin
1240 if m_flip_y then
1241 fl:=-gm.gmptGlyphOrigin.y
1242 else
1243 fl:=gm.gmptGlyphOrigin.y;
1244
1245 decompose_win32_glyph_bitmap_gray8(
1246 m_gbuf ,
1247 gm.gmBlackBoxX ,
1248 gm.gmBlackBoxY ,
1249 gm.gmptGlyphOrigin.x ,
1250 fl ,
1251 m_flip_y ,
1252 @m_rasterizer ,
1253 @m_scanline_aa ,
1254 @m_scanlines_aa );
1255
1256 m_bounds.x1:=m_scanlines_aa._min_x;
1257 m_bounds.y1:=m_scanlines_aa._min_y;
1258 m_bounds.x2:=m_scanlines_aa._max_x;
1259 m_bounds.y2:=m_scanlines_aa._max_y;
1260 m_data_size:=m_scanlines_aa.byte_size;
1261 m_data_type:=glyph_data_gray8;
1262
1263 result:=true;
1264
1265 exit;
1266
1267 end;
1268
1269 glyph_ren_outline :
1270 begin
1271 m_affine.transform(@m_affine ,@m_advance_x ,@m_advance_y );
1272
1273 if m_flag32 then
1274 begin
1275 m_path32.remove_all;
1276
1277 if decompose_win32_glyph_outline(
1278 m_gbuf ,
1279 total_size ,
1280 m_flip_y ,
1281 @m_affine ,
1282 @m_path32 ) then
1283 begin
1284 bnd:=m_path32.bounding_rect;
1285
1286 m_data_size:=m_path32.byte_size;
1287 m_data_type:=glyph_data_outline;
1288 m_bounds.x1:=Floor(bnd.x1 );
1289 m_bounds.y1:=Floor(bnd.y1 );
1290 m_bounds.x2:=Ceil(bnd.x2 );
1291 m_bounds.y2:=Ceil(bnd.y2 );
1292
1293 result:=true;
1294
1295 exit;
1296
1297 end;
1298
1299 end
1300 else
1301 begin
1302 m_path16.remove_all;
1303
1304 if decompose_win32_glyph_outline(
1305 m_gbuf ,
1306 total_size ,
1307 m_flip_y ,
1308 @m_affine ,
1309 @m_path16 ) then
1310 begin
1311 bnd:=m_path16.bounding_rect;
1312
1313 m_data_size:=m_path16.byte_size;
1314 m_data_type:=glyph_data_outline;
1315 m_bounds.x1:=Floor(bnd.x1 );
1316 m_bounds.y1:=Floor(bnd.y1 );
1317 m_bounds.x2:=Ceil(bnd.x2 );
1318 m_bounds.y2:=Ceil(bnd.y2 );
1319
1320 result:=true;
1321
1322 exit;
1323
1324 end;
1325
1326 end;
1327
1328 end;
1329
1330 glyph_ren_agg_mono :
1331 begin
1332 m_rasterizer.reset;
1333 m_affine.transform(@m_affine ,@m_advance_x ,@m_advance_y );
1334
1335 if m_flag32 then
1336 begin
1337 m_path32.remove_all;
1338
1339 decompose_win32_glyph_outline(
1340 m_gbuf ,
1341 total_size ,
1342 m_flip_y ,
1343 @m_affine ,
1344 @m_path32 );
1345
1346 m_rasterizer.add_path(@m_curves32 );
1347
1348 end
1349 else
1350 begin
1351 m_path16.remove_all;
1352
1353 decompose_win32_glyph_outline(
1354 m_gbuf ,
1355 total_size ,
1356 m_flip_y ,
1357 @m_affine ,
1358 @m_path16 );
1359
1360 m_rasterizer.add_path(@m_curves16 );
1361
1362 end;
1363
1364 m_scanlines_bin.prepare(1 ); // Remove all
1365
1366 render_scanlines(@m_rasterizer ,@m_scanline_bin ,@m_scanlines_bin );
1367
1368 m_bounds.x1:=m_scanlines_bin._min_x;
1369 m_bounds.y1:=m_scanlines_bin._min_y;
1370 m_bounds.x2:=m_scanlines_bin._max_x;
1371 m_bounds.y2:=m_scanlines_bin._max_y;
1372 m_data_size:=m_scanlines_bin.byte_size;
1373 m_data_type:=glyph_data_mono;
1374
1375 result:=true;
1376
1377 exit;
1378
1379 end;
1380
1381 glyph_ren_agg_gray8 :
1382 begin
1383 m_rasterizer.reset;
1384 m_affine.transform(@m_affine ,@m_advance_x ,@m_advance_y );
1385
1386 if m_flag32 then
1387 begin
1388 m_path32.remove_all;
1389
1390 decompose_win32_glyph_outline(
1391 m_gbuf ,
1392 total_size ,
1393 m_flip_y ,
1394 @m_affine ,
1395 @m_path32 );
1396
1397 m_rasterizer.add_path(@m_curves32 );
1398
1399 end
1400 else
1401 begin
1402 m_path16.remove_all;
1403
1404 decompose_win32_glyph_outline(
1405 m_gbuf ,
1406 total_size,
1407 m_flip_y ,
1408 @m_affine ,
1409 @m_path16 );
1410
1411 m_rasterizer.add_path(@m_curves16 );
1412
1413 end;
1414
1415 m_scanlines_aa.prepare(1 ); // Remove all
1416
1417 render_scanlines(@m_rasterizer ,@m_scanline_aa ,@m_scanlines_aa );
1418
1419 m_bounds.x1:=m_scanlines_aa._min_x;
1420 m_bounds.y1:=m_scanlines_aa._min_y;
1421 m_bounds.x2:=m_scanlines_aa._max_x;
1422 m_bounds.y2:=m_scanlines_aa._max_y;
1423 m_data_size:=m_scanlines_aa.byte_size;
1424 m_data_type:=glyph_data_gray8;
1425
1426 result:=true;
1427
1428 exit;
1429
1430 end;
1431
1432 end;
1433
1434 end;
1435
1436 result:=false;
1437
1438 end;
1439
1440 { GLYPH_INDEX }
1441 function font_engine_win32_tt_base.glyph_index;
1442 begin
1443 result:=m_glyph_index;
1444
1445 end;
1446
1447 { DATA_SIZE }
1448 function font_engine_win32_tt_base.data_size;
1449 begin
1450 result:=m_data_size;
1451
1452 end;
1453
1454 { DATA_TYPE }
1455 function font_engine_win32_tt_base.data_type;
1456 begin
1457 result:=m_data_type;
1458
1459 end;
1460
1461 { BOUNDS }
1462 function font_engine_win32_tt_base.bounds;
1463 begin
1464 result:=@m_bounds;
1465
1466 end;
1467
1468 { ADVANCE_X }
1469 function font_engine_win32_tt_base.advance_x;
1470 begin
1471 result:=m_advance_x;
1472
1473 end;
1474
1475 { ADVANCE_Y }
1476 function font_engine_win32_tt_base.advance_y;
1477 begin
1478 result:=m_advance_y;
1479
1480 end;
1481
1482 { WRITE_GLYPH_TO }
1483 procedure font_engine_win32_tt_base.write_glyph_to;
1484 begin
1485 if (data <> NIL ) and
1486 (m_data_size <> 0 ) then
1487 case m_data_type of
1488 glyph_data_mono :
1489 m_scanlines_bin.serialize(data );
1490
1491 glyph_data_gray8 :
1492 m_scanlines_aa.serialize(data );
1493
1494 glyph_data_outline :
1495 if m_flag32 then
1496 m_path32.serialize(data )
1497 else
1498 m_path16.serialize(data );
1499
1500 end;
1501
1502 end;
1503
1504 { ADD_KERNING }
1505 function font_engine_win32_tt_base.add_kerning;
1506 var
1507 end_ ,beg_ ,mid : int;
1508
1509 dx ,dy : double;
1510
1511 t : KERNINGPAIR;
1512 kp : KERNINGPAIR_ptr;
1513
1514 begin
1515 if (m_dc <> 0 ) and
1516 (m_cur_font <> 0 ) then
1517 begin
1518 if m_num_kerning_pairs = 0 then
1519 load_kerning_pairs;
1520
1521 end_:=m_num_kerning_pairs; dec(end_ );
1522 beg_:=0;
1523
1524 t.wFirst :=WORD(first );
1525 t.wSecond:=WORD(second );
1526
1527 while beg_ <= end_ do
1528 begin
1529 mid:=(end_ + beg_ ) div 2;
1530 kp :=KERNINGPAIR_ptr(ptrcomp(m_kerning_pairs ) + mid * sizeof(KERNINGPAIR ) );
1531
1532 if (kp.wFirst = t.wFirst ) and
1533 (kp.wSecond = t.wSecond ) then
1534 begin
1535 dx:=kp.iKernAmount;
1536 dy:=0.0;
1537
1538 if (m_glyph_rendering = glyph_ren_outline ) or
1539 (m_glyph_rendering = glyph_ren_agg_mono ) or
1540 (m_glyph_rendering = glyph_ren_agg_gray8 ) then
1541 m_affine.transform_2x2(@m_affine ,@dx ,@dy );
1542
1543 x^:=x^ + dx;
1544 y^:=y^ + dy;
1545
1546 result:=true;
1547
1548 exit;
1549
1550 end
1551 else
1552 if pair_less(@t ,kp ) then
1553 end_:=mid - 1
1554 else
1555 beg_:=mid + 1;
1556
1557 end;
1558
1559 end;
1560
1561 result:=false;
1562
1563 end;
1564
1565 { FLAG32 }
1566 function font_engine_win32_tt_base.flag32;
1567 begin
1568 result:=m_flag32;
1569
1570 end;
1571
1572 { UPDATE_SIGNATURE }
1573 procedure font_engine_win32_tt_base.update_signature;
1574 var
1575 gamma_hash ,i : unsigned;
1576
1577 gamma_table : array[0..aa_num - 1 ] of int8u;
1578
1579 mtx : array[0..5 ] of double;
1580 buf : array[0..99 ] of char;
1581 str : char_ptr;
1582
1583 begin
1584 m_signature.name^:=#0;
1585
1586 if (m_dc <> 0 ) and
1587 (m_cur_font <> 0 ) then
1588 begin
1589 gamma_hash:=0;
1590
1591 if (m_glyph_rendering = glyph_ren_native_gray8 ) or
1592 (m_glyph_rendering = glyph_ren_agg_mono ) or
1593 (m_glyph_rendering = glyph_ren_agg_gray8 ) then
1594 begin
1595 for i:=0 to aa_num - 1 do
1596 gamma_table[i ]:=m_rasterizer.apply_gamma(i );
1597
1598 gamma_hash:=calc_crc32(@gamma_table ,sizeof(gamma_table ) );
1599
1600 end;
1601
1602 str:=m_signature.name;
1603
1604 sprintf(str ,'%s,' ,ptrcomp(m_typeface.name ) );
1605 sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%u,' ,m_char_set );
1606 sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_glyph_rendering ) );
1607 sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d:' ,m_resolution );
1608 sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%dx' ,m_height );
1609 sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,m_width );
1610 sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,m_weight );
1611 sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_italic ) );
1612 sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_hinting) );
1613 sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_flip_y ) );
1614 sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%d,' ,int(m_pitch_and_family ) );
1615 sprintf(char_ptr(ptrcomp(str ) + StrLen(PChar(str ) ) ) ,'%08X' ,gamma_hash );
1616
1617 if (m_glyph_rendering = glyph_ren_outline ) or
1618 (m_glyph_rendering = glyph_ren_agg_mono ) or
1619 (m_glyph_rendering = glyph_ren_agg_gray8 ) then
1620 begin
1621 m_affine.store_to(@mtx );
1622
1623 sprintf(@buf[0 ] ,',%08X' ,dbl_to_plain_fx(mtx[0 ] ) );
1624 sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[1 ] ) );
1625 sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[2 ] ) );
1626 sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[3 ] ) );
1627 sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[4 ] ) );
1628 sprintf(@buf[StrLen(@buf[0 ] ) ] ,'%08X' ,dbl_to_plain_fx(mtx[5 ] ) );
1629
1630 StrCat(PChar(m_signature.name ) ,buf );
1631
1632 end;
1633
1634 inc(m_change_stamp );
1635
1636 end;
1637
1638 end;
1639
1640 { PAIR_LESS }
1641 function font_engine_win32_tt_base.pair_less;
1642 begin
1643 if v1.wFirst <> v2.wFirst then
1644 result:=v1.wFirst < v2.wFirst
1645 else
1646 result:=v1.wSecond < v2.wSecond;
1647
1648 end;
1649
1650 { LOAD_KERNING_PAIRS }
1651 procedure font_engine_win32_tt_base.load_kerning_pairs;
1652 var
1653 i : unsigned;
1654
1655 begin
1656 if (m_dc <> 0 ) and
1657 (m_cur_font <> 0 ) then
1658 begin
1659 if m_kerning_pairs = NIL then
1660 begin
1661 m_max_kerning_pairs:=16384 - 16;
1662
1663 agg_getmem(pointer(m_kerning_pairs ) ,m_max_kerning_pairs * sizeof(KERNINGPAIR ) );
1664
1665 end;
1666
1667 m_num_kerning_pairs:=
1668 GetKerningPairs(m_dc ,m_max_kerning_pairs ,m_kerning_pairs^ );
1669
1670 if m_num_kerning_pairs <> 0 then
1671 begin
1672 // Check to see if the kerning pairs are sorted and
1673 // sort them if they are not.
1674 i:=1;
1675
1676 while i < m_num_kerning_pairs do
1677 begin
1678 if not pair_less(
1679 KERNINGPAIR_ptr(ptrcomp(m_kerning_pairs ) + (i - 1 ) * sizeof(KERNINGPAIR ) ) ,
1680 KERNINGPAIR_ptr(ptrcomp(m_kerning_pairs ) + i * sizeof(KERNINGPAIR ) ) ) then
1681 begin
1682 sort_kerning_pairs;
1683
1684 break;
1685
1686 end;
1687
1688 inc(i );
1689
1690 end;
1691
1692 end;
1693
1694 end;
1695
1696 end;
1697
1698 { _pair_less }
1699 function _pair_less(v1 ,v2 : KERNINGPAIR_ptr ) : boolean;
1700 begin
1701 if v1.wFirst <> v2.wFirst then
1702 result:=v1.wFirst < v2.wFirst
1703 else
1704 result:=v1.wSecond < v2.wSecond;
1705
1706 end;
1707
1708 { SORT_KERNING_PAIRS }
1709 procedure font_engine_win32_tt_base.sort_kerning_pairs;
1710 var
1711 pairs : pod_array_adaptor;
1712
1713 begin
1714 pairs.Construct(m_kerning_pairs ,m_num_kerning_pairs ,sizeof(KERNINGPAIR ) );
1715
1716 quick_sort(@pairs ,@_pair_less );
1717
1718 end;
1719
1720 { FIND_FONT }
1721 function font_engine_win32_tt_base.find_font;
1722 var
1723 i : unsigned;
1724 n : font_name_ptr;
1725
1726 begin
1727 n:=m_font_names;
1728 i:=0;
1729
1730 while i < m_num_fonts do
1731 begin
1732 if StrComp(name ,PChar(n.name ) ) = 0 then
1733 begin
1734 result:=i;
1735
1736 exit;
1737
1738 end;
1739
1740 inc(ptrcomp(n ) ,sizeof(font_name ) );
1741 inc(i );
1742
1743 end;
1744
1745 result:=-1;
1746
1747 end;
1748
1749 { CONSTRUCT }
1750 constructor font_engine_win32_tt_int16.Construct;
1751 begin
1752 inherited Construct(false ,dc ,max_fonts );
1753
1754 end;
1755
1756 { CONSTRUCT }
1757 constructor font_engine_win32_tt_int32.Construct;
1758 begin
1759 inherited Construct(true ,dc ,max_fonts );
1760
1761 end;
1762
1763 { UNIT CONSTRUCTOR }
1764 INITIALIZATION
1765 {$IFDEF AGG_WIN9X_COMPLIANT }
1766 GetGlyphOutlineX:=@GetGlyphOutline;
1767
1768 {$ELSE }
1769 GetGlyphOutlineX:=@GetGlyphOutlineW;
1770
1771 {$ENDIF }
1772
1773 END.
1774
1775