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