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: added ptrcomp type + ptrcomp adjustments
24 // 26.09.2005-Milano: Complete unit port
25 //
26 { agg_basics.pas }
27 unit
28  agg_basics ;
29 
30 INTERFACE
31 
32 {$I agg_mode.inc }
33 {$Q- }
34 {$R- }
35 
36 uses
37  Math ;
38 
39 { TYPES DEFINITION }
40 type
41  agg_types = (
42 
43   int8_type ,
44   int8u_type ,
45   int16_type ,
46   int16u_type ,
47   int32_type ,
48   int32u_type ,
49   int64_type ,
50   int64u_type
51 
52   );
53 
54  agg_type = (agg_int ,agg_unsigned ,agg_double );
55 
56  AGG_INT8  = shortint;
57  AGG_INT8U = byte;
58 
59  AGG_INT16  = smallint;
60  AGG_INT16U = word;
61 
62  AGG_INT32  = longint;
63  AGG_INT32U = longword;
64 
65  AGG_INT64  = int64;
66 {$IFDEF FPC }
67  AGG_INT64U = qword;
68 {$ELSE }
69  AGG_INT64U = int64;
70 {$ENDIF }
71 
72  int8   = AGG_INT8;
73  int8u  = AGG_INT8U;
74  int16  = AGG_INT16;
75  int16u = AGG_INT16U;
76  int32  = AGG_INT32;
77  int32u = AGG_INT32U;
78  int64  = AGG_INT64;
79  int64u = AGG_INT64U;
80 
81  int8_ptr   = ^int8;
82  int8u_ptr  = ^int8u;
83  int16_ptr  = ^int16;
84  int16u_ptr = ^int16u;
85  int32_ptr  = ^int32;
86  int32u_ptr = ^int32u;
87  int64_ptr  = ^int64;
88  int64u_ptr = ^int64u;
89 
90  int8u_ptr_ptr = ^int8u_ptr;
91 
92  cover_type_ptr = ^cover_type;
93  cover_type = byte;
94 
95  int_ptr = ^int;
96  int = int32;
97 
98  unsigned_ptr = ^unsigned;
99  unsigned = int32u;
100 
101  int8u_01_ptr = ^int8u_01;
102  int8u_01 = array[0..1 ] of int8u;
103 
104  int16u_ = record
105    low  ,
106    high : int8u;
107 
108   end;
109 
110  int32_ = record
111    low  ,
112    high : int16;
113 
114   end;
115 
116  int32_int8u = record
117    _0 ,_1 ,_2 ,_3 : int8u;
118 
119   end;
120 
121  int32u_ = record
122    low  ,
123    high : int16u;
124 
125   end;
126 
127 { To achive maximum compatiblity with older code, FPC doesn't change the size
128   of predefined data types like integer, longint or word when changing from
129   32 to 64 Bit. However, the size of a pointer is 8 bytes on a 64 bit
130   architecture so constructs like longint(pointer(p)) are doomed to crash on
131   64 bit architectures. However, to allow you to write portable code, the
132   FPC system unit introduces the types PtrInt and PtrUInt which are signed
133   and unsigned integer data types with the same size as a pointer.
134 
135   Keep in mind that the size change of the "pointer" type also affects record
136   sizes. If you allocate records with fixed sizes, and not with new or with
137   getmem (<x>,sizeof(<x>)), this will have to be fixed. }
138 // Pascal Pointer Computation Type
139 {$IFDEF CPU64 }
140  ptrcomp = system.int64;
141 
142 {$ELSE }
143  ptrcomp = integer;
144 
145 {$ENDIF }
146 
147 // Pascal's pointer-in-an-array-access helper structures
148  p32_ptr = ^p32;
149  p32 = record
150    case integer of
151     1 : (ptr : pointer );
152     2 : (int : ptrcomp );
153   end;
154 
155  double_ptr_ptr = ^double_ptr;
156  double_ptr = ^double;
157 
158  double_2_ptr = ^double_2;
159  double_2     = array[0..1 ] of double;
160 
161  double_8_ptr = ^double_8;
162  double_8     = array[0..7 ] of double;
163 
164  double_42_ptr = ^double_42;
165  double_42     = array[0..3 ,0..1 ] of double;
166 
167  double_44_ptr = ^double_44;
168  double_44     = array[0..3 ,0..3 ] of double;
169 
170  double_81_ptr = ^double_81;
171  double_81     = array[0..7 ,0..0 ] of double;
172 
173  double_88_ptr = ^double_88;
174  double_88     = array[0..7 ,0..7 ] of double;
175 
176  double_26_ptr = ^double_26;
177  double_26     = array[0..25 ] of double;
178 
179  double_00_ptr = ^double_00;
180  double_00     = array of double;
181 
182  char_ptr_ptr = ^char_ptr;
183  char_ptr     = ^char;
184  pointer_ptr  = ^pointer;
185 
186  gamma_ptr = ^gamma;
187  gamma = object
188    function dir(v : unsigned ) : unsigned; virtual; abstract;
189    function inv(v : unsigned ) : unsigned; virtual; abstract;
190 
191   end;
192 
193  poly_subpixel_scale_e = int;
194 
195  filling_rule_e = (fill_non_zero ,fill_even_odd );
196 
197 const
198 // cover_scale_e
199  cover_shift = 8;
200  cover_size  = 1 shl cover_shift;
201  cover_mask  = cover_size - 1;
202  cover_none  = 0;
203  cover_full  = cover_mask;
204 
205  pi : double = 3.14159265358979323846;
206 
207 // These constants determine the subpixel accuracy, to be more precise,
208 // the number of bits of the fractional part of the coordinates.
209 // The possible coordinate capacity in bits can be calculated by formula:
210 // sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and
211 // 8-bits fractional part the capacity is 24 bits.
212  poly_subpixel_shift = 8;                         //----poly_subpixel_shift
213  poly_subpixel_scale = 1 shl poly_subpixel_shift; //----poly_subpixel_scale
214  poly_subpixel_mask  = poly_subpixel_scale-1;     //----poly_subpixel_mask
215 
216 // path_commands_e
217  path_cmd_stop     = 0;
218  path_cmd_move_to  = 1;
219  path_cmd_line_to  = 2;
220  path_cmd_curve3   = 3;
221  path_cmd_curve4   = 4;
222  path_cmd_curveN   = 5;
223  path_cmd_catrom   = 6;
224  path_cmd_ubspline = 7;
225  path_cmd_end_poly = $0F;
226  path_cmd_mask     = $0F;
227 
228 // path_flags_e
229  path_flags_none  = 0;
230  path_flags_ccw   = $10;
231  path_flags_cw    = $20;
232  path_flags_close = $40;
233  path_flags_mask  = $F0;
234 
235 type
236  rect_ptr = ^rect;
237  rect = object
238    x1 ,y1 ,x2 ,y2 : int;
239 
240    constructor Construct; overload;
241    constructor Construct(x1_ ,y1_ ,x2_ ,y2_ : int ); overload;
242    constructor Construct(r : rect_ptr ); overload;
243 
244    function  normalize : rect_ptr;
245    function  clip(r : rect_ptr ) : boolean;
246    function  is_valid : boolean;
247 
248   end;
249 
250  rect_d_ptr = ^rect_d;
251  rect_d = object
252    x1 ,y1 ,x2 ,y2 : double;
253 
254    constructor Construct; overload;
255    constructor Construct(x1_ ,y1_ ,x2_ ,y2_ : double ); overload;
256 
257    function  normalize : rect_d_ptr;
258    function  clip(r : rect_d_ptr ) : boolean;
259    function  is_valid : boolean;
260 
261   end;
262 
263  rect_i_ptr = ^rect_i;
264  rect_i = object
265    x1 ,y1 ,x2 ,y2 : int;
266 
267    constructor Construct; overload;
268    constructor Construct(x1_ ,y1_ ,x2_ ,y2_ : int ); overload;
269 
270    function  clip(r : rect_i_ptr ) : boolean;
271 
272   end;
273 
274  point_type_ptr = ^point_type;
275  point_type = record
276    x ,y : double;
277 
278   end;
279 
280  vertex_type = object
281    x ,y : double;
282    cmd  : byte;
283 
284    constructor Construct; overload;
285    constructor Construct(x_ ,y_ : double; cmd_ : byte ); overload;
286 
287   end;
288 
289  unsigned_list_ptr = ^unsigned_list;
290  unsigned_list = object
291    function  array_operator(idx : unsigned ) : unsigned; virtual; abstract;
292 
293   end;
294 
295 { GLOBAL PROCEDURES }
296  function  agg_getmem (var buf : pointer; sz : unsigned ) : boolean;
297  function  agg_freemem(var buf : pointer; sz : unsigned ) : boolean;
298 
299  function  deg2rad(deg : double ) : double;
300  function  rad2deg(rad : double ) : double;
301 
302  procedure normalize_rect  (var this : rect );
303  procedure normalize_rect_d(var this : rect_d );
304 
305  function  clip_rect  (var this : rect; r : rect_ptr ) : boolean;
306  function  clip_rect_d(var this : rect_d; r : rect_d_ptr ) : boolean;
307 
308  function  is_valid_rect (var this : rect ) : boolean;
309  function  is_valid_rect_d(var this : rect_d ) : boolean;
310 
311  function  intersect_rectangles (r1 ,r2 : rect_ptr ) : rect;
312  function  intersect_rectangles_d(r1 ,r2 : rect_d_ptr ) : rect_d;
313 
314  function  unite_rectangles (r1 ,r2 : rect_ptr ) : rect;
315  function  unite_rectangles_d(r1 ,r2 : rect_d_ptr ) : rect_d;
316 
317  function  is_vertex   (c : unsigned ) : boolean;
318  function  is_drawing  (c : unsigned ) : boolean;
319  function  is_stop     (c : unsigned ) : boolean;
320  function  is_move     (c : unsigned ) : boolean;
321  function  is_line_to  (c : unsigned ) : boolean;
322  function  is_move_to  (c : unsigned ) : boolean;
323  function  is_curve    (c : unsigned ) : boolean;
324  function  is_curve3   (c : unsigned ) : boolean;
325  function  is_curve4   (c : unsigned ) : boolean;
326  function  is_end_poly (c : unsigned ) : boolean;
327  function  is_close    (c : unsigned ) : boolean;
328  function  is_next_poly(c : unsigned ) : boolean;
329  function  is_cw       (c : unsigned ) : boolean;
330  function  is_ccw      (c : unsigned ) : boolean;
331  function  is_oriented (c : unsigned ) : boolean;
332  function  is_closed   (c : unsigned ) : boolean;
333 
334  function  get_close_flag   (c : unsigned ) : unsigned;
335  function  clear_orientation(c : unsigned ) : unsigned;
336  function  get_orientation  (c : unsigned ) : unsigned;
337  function  set_orientation  (c ,o : unsigned ) : unsigned;
338 
339  procedure swap_ptrs(a ,b : pointer );
340  procedure sprintf  (dst : char_ptr; src : PChar; val : double );
341  function  intdbl   (i : int ) : double;
342 
343  procedure srand_(seed : int );
344  function  rand_ : int;
345 
346  procedure srand(seed : int );
347  function  rand : int;
348 
349  function  uround(v : double ) : int;
350  function  iround(v : double ) : int;
351 
352  function  saturation_iround(Limit : int; v : double ) : int;
353 
whosenull354 // NoP = No Operation. It's the empty function, whose purpose is only for the
355 // debugging, or for the piece of code where intentionaly nothing is planned
356 // to be.
357  procedure NoP;
358 
359 { These implementations have changed to use FPC's Sar*() functions, so should
360   now support all platforms without the need for ASM code. At a later date these
361   functions could be removed completely. }
shr_int8null362  function  shr_int8 (i ,shift : int8 ) : int8; inline;
shr_int16null363  function  shr_int16(i ,shift : int16 ) : int16; inline;
shr_int32null364  function  shr_int32(i ,shift : int ) : int; inline;
365 
366 IMPLEMENTATION
367 { UNIT IMPLEMENTATION }
368 { agg_getmem }
agg_getmemnull369 function agg_getmem;
370 begin
371  result:=false;
372 
373  try
374   getmem(buf ,sz );
375 
376   result:=true;
377 
378  except
379   buf:=NIL;
380 
381  end;
382 
383 end;
384 
385 { agg_freemem }
agg_freememnull386 function agg_freemem;
387 begin
388  if buf = NIL then
389   result:=true
390 
391  else
392   try
393    freemem(buf ,sz );
394 
395    buf:=NIL;
396 
397    result:=true;
398 
399   except
400    result:=false;
401 
402   end;
403 
404 end;
405 
406 { deg2rad }
deg2radnull407 function deg2rad;
408 begin
409  result:=deg * pi / 180;
410 
411 end;
412 
413 { rad2deg }
rad2degnull414 function rad2deg;
415 begin
416  result:=rad * 180 / pi;
417 
418 end;
419 
420 { CONSTRUCT }
421 constructor rect.Construct;
422 begin
423  x1:=0;
424  y1:=0;
425  x2:=0;
426  y2:=0;
427 
428 end;
429 
430 { CONSTRUCT }
431 constructor rect.Construct(x1_ ,y1_ ,x2_ ,y2_ : int );
432 begin
433  x1:=x1_;
434  y1:=y1_;
435  x2:=x2_;
436  y2:=y2_;
437 
438 end;
439 
440 { CONSTRUCT }
441 constructor rect.Construct(r : rect_ptr );
442 begin
443  x1:=r.x1;
444  y1:=r.y1;
445  x2:=r.x2;
446  y2:=r.y2;
447 
448 end;
449 
450 { NORMALIZE }
rect.normalizenull451 function rect.normalize: rect_ptr;
452 var
453  t : int;
454 
455 begin
456  if x1 > x2 then
457   begin
458    t :=x1;
459    x1:=x2;
460    x2:=t;
461 
462   end;
463 
464  if y1 > y2 then
465   begin
466    t :=y1;
467    y1:=y2;
468    y2:=t;
469 
470   end;
471 
472  result:=@self;
473 
474 end;
475 
476 { CLIP }
rect.clipnull477 function rect.clip(r: rect_ptr): boolean;
478 begin
479  if x2 > r.x2 then
480   x2:=r.x2;
481 
482  if y2 > r.y2 then
483   y2:=r.y2;
484 
485  if x1 < r.x1 then
486   x1:=r.x1;
487 
488  if y1 < r.y1 then
489   y1:=r.y1;
490 
491  result:=(x1 <= x2 ) and (y1 <= y2 );
492 
493 end;
494 
495 { IS_VALID }
rect.is_validnull496 function rect.is_valid: boolean;
497 begin
498  result:=(x1 <= x2 ) and (y1 <= y2 );
499 
500 end;
501 
502 { CONSTRUCT }
503 constructor rect_d.Construct;
504 begin
505  x1:=0;
506  y1:=0;
507  x2:=0;
508  y2:=0;
509 
510 end;
511 
512 { CONSTRUCT }
513 constructor rect_d.Construct(x1_ ,y1_ ,x2_ ,y2_ : double );
514 begin
515  x1:=x1_;
516  y1:=y1_;
517  x2:=x2_;
518  y2:=y2_;
519 
520 end;
521 
522 { NORMALIZE }
rect_d.normalizenull523 function rect_d.normalize;
524 var
525  t : double;
526 
527 begin
528  if x1 > x2 then
529   begin
530    t :=x1;
531    x1:=x2;
532    x2:=t;
533 
534   end;
535 
536  if y1 > y2 then
537   begin
538    t :=y1;
539    y1:=y2;
540    y2:=t;
541 
542   end;
543 
544  result:=@self;
545 
546 end;
547 
548 { CLIP }
rect_d.clipnull549 function rect_d.clip;
550 begin
551  if x2 > r.x2 then
552   x2:=r.x2;
553 
554  if y2 > r.y2 then
555   y2:=r.y2;
556 
557  if x1 < r.x1 then
558   x1:=r.x1;
559 
560  if y1 < r.y1 then
561   y1:=r.y1;
562 
563  result:=(x1 <= x2 ) and (y1 <= y2 );
564 
565 end;
566 
567 { IS_VALID }
rect_d.is_validnull568 function rect_d.is_valid;
569 begin
570  result:=(x1 <= x2 ) and (y1 <= y2 );
571 
572 end;
573 
574 { CONSTRUCT }
575 constructor rect_i.Construct;
576 begin
577  x1:=0;
578  y1:=0;
579  x2:=0;
580  y2:=0;
581 
582 end;
583 
584 { CONSTRUCT }
585 constructor rect_i.Construct(x1_ ,y1_ ,x2_ ,y2_ : int );
586 begin
587  x1:=x1_;
588  y1:=y1_;
589  x2:=x2_;
590  y2:=y2_;
591 
592 end;
593 
594 { CLIP }
rect_i.clipnull595 function rect_i.clip(r : rect_i_ptr ) : boolean;
596 begin
597  if x2 > r.x2 then
598   x2:=r.x2;
599 
600  if y2 > r.y2 then
601   y2:=r.y2;
602 
603  if x1 < r.x1 then
604   x1:=r.x1;
605 
606  if y1 < r.y1 then
607   y1:=r.y1;
608 
609  result:=(x1 <= x2 ) and (y1 <= y2 );
610 
611 end;
612 
613 { CONSTRUCT }
614 constructor vertex_type.Construct;
615 begin
616  x:=0;
617  y:=0;
618 
619  cmd:=0;
620 
621 end;
622 
623 { CONSTRUCT }
624 constructor vertex_type.Construct(x_ ,y_ : double; cmd_ : byte );
625 begin
626  x:=x_;
627  y:=y_;
628 
629  cmd:=cmd_;
630 
631 end;
632 
633 { normalize_rect }
634 procedure normalize_rect(var this : rect );
635 var
636  t : int;
637 
638 begin
639  if this.x1 > this.x2 then
640   begin
641    t      :=this.x1;
642    this.x1:=this.x2;
643    this.x2:=t;
644 
645   end;
646 
647  if this.y1 > this.y2 then
648   begin
649    t      :=this.y1;
650    this.y1:=this.y2;
651    this.y2:=t;
652 
653   end;
654 
655 end;
656 
657 { normalize_rect_d }
658 procedure normalize_rect_d(var this : rect_d );
659 var
660  t : double;
661 
662 begin
663  if this.x1 > this.x2 then
664   begin
665    t      :=this.x1;
666    this.x1:=this.x2;
667    this.x2:=t;
668 
669   end;
670 
671  if this.y1 > this.y2 then
672   begin
673    t      :=this.y1;
674    this.y1:=this.y2;
675    this.y2:=t;
676 
677   end;
678 
679 end;
680 
681 { clip_rect }
clip_rectnull682 function clip_rect(var this : rect; r : rect_ptr ) : boolean;
683 begin
684  if this.x2 > r.x2 then
685   this.x2:=r.x2;
686 
687  if this.y2 > r.y2 then
688   this.y2:=r.y2;
689 
690  if this.x1 < r.x1 then
691   this.x1:=r.x1;
692 
693  if this.y1 < r.y1 then
694   this.y1:=r.y1;
695 
696  result:=(this.x1 <= this.x2 ) and (this.y1 <= this.y2 );
697 
698 end;
699 
700 { clip_rect_d }
clip_rect_dnull701 function clip_rect_d(var this : rect_d; r : rect_d_ptr ) : boolean;
702 begin
703  if this.x2 > r.x2 then
704   this.x2:=r.x2;
705 
706  if this.y2 > r.y2 then
707   this.y2:=r.y2;
708 
709  if this.x1 < r.x1 then
710   this.x1:=r.x1;
711 
712  if this.y1 < r.y1 then
713   this.y1:=r.y1;
714 
715  result:=(this.x1 <= this.x2 ) and (this.y1 <= this.y2 );
716 
717 end;
718 
719 { is_valid_rect }
is_valid_rectnull720 function is_valid_rect(var this : rect ) : boolean;
721 begin
722  result:=(this.x1 <= this.x2 ) and (this.y1 <= this.y2 );
723 
724 end;
725 
726 { is_valid_rect_d }
is_valid_rect_dnull727 function is_valid_rect_d(var this : rect_d ) : boolean;
728 begin
729  result:=(this.x1 <= this.x2 ) and (this.y1 <= this.y2 );
730 
731 end;
732 
733 { intersect_rectangles }
intersect_rectanglesnull734 function intersect_rectangles(r1 ,r2 : rect_ptr ) : rect;
735 begin
736  result:=r1^;
737 
738  if result.x2 > r2.x2 then
739   result.x2:=r2.x2;
740 
741  if result.y2 > r2.y2 then
742   result.y2:=r2.y2;
743 
744  if result.x1 < r2.x1 then
745   result.x1:=r2.x1;
746 
747  if result.y1 < r2.y1 then
748   result.y1:=r2.y1;
749 
750 end;
751 
752 { intersect_rectangles_d }
intersect_rectangles_dnull753 function intersect_rectangles_d(r1 ,r2 : rect_d_ptr ) : rect_d;
754 begin
755  result:=r1^;
756 
757  if result.x2 > r2.x2 then
758   result.x2:=r2.x2;
759 
760  if result.y2 > r2.y2 then
761   result.y2:=r2.y2;
762 
763  if result.x1 < r2.x1 then
764   result.x1:=r2.x1;
765 
766  if result.y1 < r2.y1 then
767   result.y1:=r2.y1;
768 
769 end;
770 
771 { unite_rectangles }
unite_rectanglesnull772 function unite_rectangles(r1 ,r2 : rect_ptr ) : rect;
773 begin
774  result:=r1^;
775 
776  if result.x2 < r2.x2 then
777   result.x2:=r2.x2;
778 
779  if result.y2 < r2.y2 then
780   result.y2:=r2.y2;
781 
782  if result.x1 > r2.x1 then
783   result.x1:=r2.x1;
784 
785  if result.y1 > r2.y1 then
786   result.y1:=r2.y1;
787 
788 end;
789 
790 { unite_rectangles_d }
unite_rectangles_dnull791 function unite_rectangles_d(r1 ,r2 : rect_d_ptr ) : rect_d;
792 begin
793  result:=r1^;
794 
795  if result.x2 < r2.x2 then
796   result.x2:=r2.x2;
797 
798  if result.y2 < r2.y2 then
799   result.y2:=r2.y2;
800 
801  if result.x1 > r2.x1 then
802   result.x1:=r2.x1;
803 
804  if result.y1 > r2.y1 then
805   result.y1:=r2.y1;
806 
807 end;
808 
809 { is_vertex }
is_vertexnull810 function is_vertex;
811 begin
812  result:=(c >= path_cmd_move_to ) and (c < path_cmd_end_poly );
813 
814 end;
815 
816 { is_drawing }
is_drawingnull817 function is_drawing;
818 begin
819  result:=(c >= path_cmd_line_to ) and (c < path_cmd_end_poly );
820 
821 end;
822 
823 { is_stop }
is_stopnull824 function is_stop;
825 begin
826  result:=(c = path_cmd_stop );
827 
828 end;
829 
830 { is_move }
is_movenull831 function is_move;
832 begin
833  result:=(c = path_cmd_move_to );
834 
835 end;
836 
837 { is_line_to }
is_line_tonull838 function is_line_to;
839 begin
840  result:=(c = path_cmd_line_to );
841 
842 end;
843 
844 { is_move_to }
is_move_tonull845 function is_move_to;
846 begin
847  result:=(c = path_cmd_move_to );
848 
849 end;
850 
851 { is_curve }
is_curvenull852 function is_curve;
853 begin
854  result:=(c = path_cmd_curve3 ) or (c = path_cmd_curve4 );
855 
856 end;
857 
858 { is_curve3 }
is_curve3null859 function is_curve3;
860 begin
861  result:=(c = path_cmd_curve3 );
862 
863 end;
864 
865 { is_curve4 }
is_curve4null866 function is_curve4;
867 begin
868  result:=(c = path_cmd_curve4 );
869 
870 end;
871 
872 { is_end_poly }
is_end_polynull873 function is_end_poly;
874 begin
875  result:=((c and path_cmd_mask ) = path_cmd_end_poly );
876 
877 end;
878 
879 { is_close }
is_closenull880 function is_close;
881 begin
882  result:=
883   (c and not(path_flags_cw or path_flags_ccw ) ) =
884   (path_cmd_end_poly or path_flags_close )
885 
886 end;
887 
888 { is_next_poly }
is_next_polynull889 function is_next_poly;
890 begin
891  result:=is_stop(c ) or is_move_to(c ) or is_end_poly(c );
892 
893 end;
894 
895 { is_cw }
is_cwnull896 function is_cw;
897 begin
898  result:=not((c and path_flags_cw ) = 0 );
899 
900 end;
901 
902 { is_ccw }
is_ccwnull903 function is_ccw;
904 begin
905  result:=not((c and path_flags_ccw ) = 0 );
906 
907 end;
908 
909 { is_oriented }
is_orientednull910 function is_oriented;
911 begin
912  result:=not((c and (path_flags_cw or path_flags_ccw ) ) = 0 );
913 
914 end;
915 
916 { is_closed }
is_closednull917 function is_closed;
918 begin
919  result:=not((c and path_flags_close ) = 0 );
920 
921 end;
922 
923 { get_close_flag }
get_close_flagnull924 function get_close_flag;
925 begin
926  result:=c and path_flags_close;
927 
928 end;
929 
930 { clear_orientation }
clear_orientationnull931 function clear_orientation;
932 begin
933  result:=c and not(path_flags_cw or path_flags_ccw );
934 
935 end;
936 
937 { get_orientation }
get_orientationnull938 function get_orientation;
939 begin
940  result:=c and (path_flags_cw or path_flags_ccw );
941 
942 end;
943 
944 { set_orientation }
set_orientationnull945 function set_orientation;
946 begin
947  result:=clear_orientation(c ) or o;
948 
949 end;
950 
951 { swap_ptrs }
952 procedure swap_ptrs;
953 var
954  temp : pointer;
955 
956 begin
957  temp:=p32_ptr(a ).ptr;
958 
959  p32_ptr(a ).ptr:=p32_ptr(b ).ptr;
960  p32_ptr(b ).ptr:=temp;
961 
962 end;
963 
964 { MAKESTR }
MakeStrnull965 function MakeStr(ch : char; sz : byte ) : shortstring;
966 begin
967  result[0 ]:=char(sz );
968 
969  fillchar(result[1 ] ,sz ,ch );
970 
971 end;
972 
973 { BACKLEN }
BackLennull974 function BackLen(s : shortstring; sz : byte ) : shortstring;
975 type
976  tSCAN = (
977 
978   SCAN_0 ,
979   SCAN_1 ,SCAN_2 ,SCAN_3 ,SCAN_4 ,SCAN_5 ,SCAN_6 ,SCAN_7 ,SCAN_8 ,SCAN_9 ,
980   SCAN_A ,SCAN_B ,SCAN_C ,SCAN_D ,SCAN_E ,SCAN_F ,SCAN_G ,SCAN_H ,SCAN_I ,
981   SCAN_J ,SCAN_K ,SCAN_L ,SCAN_M ,SCAN_N ,SCAN_O ,SCAN_P ,SCAN_Q ,SCAN_R ,
982   SCAN_S ,SCAN_T ,SCAN_U ,SCAN_V ,SCAN_W ,SCAN_X ,SCAN_Y ,SCAN_Z
983 
984   );
985 
986 var
987  pos ,
988  wcb : byte;
989  scn : tSCAN;
990 
991 begin
992  result:='';
993 
994  wcb:=sz;
995  pos:=length(s );
996  scn:=SCAN_1;
997 
998  while wcb > 0 do
999   begin
1000    case scn of
1001     SCAN_1 :
1002      if pos > 0 then
1003       begin
1004        result:=s[pos ] + result;
1005 
1006        dec(pos );
1007 
1008       end
1009      else
1010       begin
1011        scn:=SCAN_2;
1012 
1013        result:=' ' + result;
1014 
1015       end;
1016 
1017     SCAN_2 :
1018      result:=' ' + result;
1019 
1020    end;
1021 
1022    dec(wcb );
1023 
1024   end;
1025 
1026 end;
1027 
1028 { INTHEX }
IntHexnull1029 function IntHex(i : int64; max : byte = 0; do_low : boolean = false ) : shortstring;
1030 type
1031  tITEM = (
1032 
1033   ITEM_0 ,
1034   ITEM_1 ,ITEM_2 ,ITEM_3 ,ITEM_4 ,ITEM_5 ,ITEM_6 ,ITEM_7 ,ITEM_8 ,ITEM_9 ,
1035   ITEM_A ,ITEM_B ,ITEM_C ,ITEM_D ,ITEM_E ,ITEM_F ,ITEM_G ,ITEM_H ,ITEM_I ,
1036   ITEM_J ,ITEM_K ,ITEM_L ,ITEM_M ,ITEM_N ,ITEM_O ,ITEM_P ,ITEM_Q ,ITEM_R ,
1037   ITEM_S ,ITEM_T ,ITEM_U ,ITEM_V ,ITEM_W ,ITEM_X ,ITEM_Y ,ITEM_Z
1038 
1039   );
1040 
1041 var
1042  str : shortstring;
1043  itm : tITEM;
1044  fcb : byte;
1045 
1046 const
1047  low : array[0..$f ] of char = '0123456789abcdef';
1048  hex : array[0..$f ] of char = '0123456789ABCDEF';
1049 
1050 begin
1051  if do_low then
1052   str:=
1053    low[i shr 60 and 15 ] +
1054    low[i shr 56 and 15 ] +
1055    low[i shr 52 and 15 ] +
1056    low[i shr 48 and 15 ] +
1057    low[i shr 44 and 15 ] +
1058    low[i shr 40 and 15 ] +
1059    low[i shr 36 and 15 ] +
1060    low[i shr 32 and 15 ] +
1061 
1062    low[i shr 28 and 15 ] +
1063    low[i shr 24 and 15 ] +
1064    low[i shr 20 and 15 ] +
1065    low[i shr 16 and 15 ] +
1066    low[i shr 12 and 15 ] +
1067    low[i shr 8 and 15 ] +
1068    low[i shr 4 and 15 ] +
1069    low[i and 15 ]
1070  else
1071   str:=
1072    hex[i shr 60 and 15 ] +
1073    hex[i shr 56 and 15 ] +
1074    hex[i shr 52 and 15 ] +
1075    hex[i shr 48 and 15 ] +
1076    hex[i shr 44 and 15 ] +
1077    hex[i shr 40 and 15 ] +
1078    hex[i shr 36 and 15 ] +
1079    hex[i shr 32 and 15 ] +
1080 
1081    hex[i shr 28 and 15 ] +
1082    hex[i shr 24 and 15 ] +
1083    hex[i shr 20 and 15 ] +
1084    hex[i shr 16 and 15 ] +
1085    hex[i shr 12 and 15 ] +
1086    hex[i shr 8 and 15 ] +
1087    hex[i shr 4 and 15 ] +
1088    hex[i and 15 ];
1089 
1090  if max > 0 then
1091   if length(str ) > max then
1092    result:=BackLen(str ,max )
1093   else
1094    if length(str ) < max then
1095     result:=MakeStr('0' ,max - length(str ) ) + str
1096    else
1097     result:=str
1098 
1099  else
1100   begin
1101    result:='';
1102 
1103    itm:=ITEM_1;
1104 
1105    for fcb:=1 to length(str ) do
1106     case itm of
1107      ITEM_1 :
1108       case str[fcb ] of
1109        '0' :
1110        else
1111         begin
1112          result:=str[fcb ];
1113 
1114          itm:=ITEM_2;
1115 
1116         end;
1117 
1118       end;
1119 
1120      ITEM_2 :
1121       result:=result + str[fcb ];
1122 
1123     end;
1124 
1125    if result = '' then
1126     result:='0';
1127 
1128   end;
1129 
1130 end;
1131 
1132 { SPRINTF }
1133 procedure sprintf;
1134 type
1135  scan = (_string ,_flags ,_width ,_precision ,_prefix ,_type );
1136 
1137 var
1138  sc : scan;
1139  nt ,
1140  fr : integer;
1141 
1142  get : shortstring;
1143  flg : char;
1144  dth ,
1145  prc ,
1146  err : integer;
1147  prf : array[0..3 ] of char;
1148  typ : char;
1149 
1150 { apply }
1151 procedure apply;
1152 var
1153  i ,x : int;
1154 
1155  add : shortstring;
1156 
1157 begin
1158  add:='';
1159 
1160  case typ of
1161   'X' :
1162    begin
1163     if dth = 1 then
1164      dth:=0;
1165 
1166     add:=IntHex(trunc(val ) ,dth ,false );
1167 
1168    end;
1169 
1170   'x' :
1171    begin
1172     if dth = 1 then
1173      dth:=0;
1174 
1175     add:=IntHex(trunc(val ) ,dth ,true );
1176 
1177    end;
1178 
1179   's' :
1180    add:=PChar(trunc(val ) );
1181 
1182   'u' ,'d' :
1183    begin
1184     str(nt ,get );
1185 
1186     while length(get ) < dth do
1187      get:='0' + get;
1188 
1189     add:=get;
1190 
1191    end;
1192 
1193   'f' :
1194    begin
1195     str(nt ,get );
1196 
1197     while length(get ) < dth do
1198      get:=' ' + get;
1199 
1200     add:=get;
1201 
1202     if prc > 0 then
1203      begin
1204       x:=1;
1205 
1206       for i:=1 to prc do
1207        x:=x * 10;
1208 
1209       fr:=Abs(trunc(system.frac(val ) * x ) );
1210 
1211       str(fr ,get );
1212 
1213       while length(get ) < prc do
1214        get:='0' + get;
1215 
1216       add:=add + '.' + get;
1217 
1218      end;
1219 
1220     if (val < 0 ) and
1221        (add[1 ] <> '-' ) then
1222      add:='-' + add;
1223 
1224    end;
1225 
1226  end;
1227 
1228  err:=0;
1229 
1230  while err < length(add ) do
1231   begin
1232    dst^:=add[err + 1 ];
1233 
1234    inc(ptrcomp(dst ) );
1235    inc(err );
1236 
1237   end;
1238 
1239  sc:=_string;
1240 
1241 end;
1242 
1243 begin
1244  nt:=trunc(system.int (val ) );
1245  fr:=trunc(system.frac(val ) );
1246  sc:=_string;
1247 
1248  flg:=#0;
1249  dth:=1;
1250  prc:=0;
1251  prf:=#0;
1252  typ:='s';
1253 
1254  while src^ <> #0 do
1255   begin
1256    case sc of
1257    { Copy Text or expect % }
1258     _string :
1259      case src^ of
1260       '%' :
1261        sc:=_flags;
1262 
1263       else
1264        begin
1265         dst^:=src^;
1266 
1267         inc(ptrcomp(dst ) );
1268 
1269        end;
1270 
1271      end;
1272 
1273    { Flags }
1274     _flags :
1275      case src^ of
1276       '-' ,'+' ,'0' ,' ' ,'#' :
1277        begin
1278          flg:=src^;
1279          if flg=#0 then ; // ToDo
1280        end;
1281 
1282       '1'..'9' :
1283        begin
1284         get:=src^;
1285         sc :=_width;
1286 
1287        end;
1288 
1289       '.' :
1290        begin
1291         get:='';
1292         sc :=_precision;
1293 
1294        end;
1295 
1296       'h' ,'l' :
1297        begin
1298         prf[0 ]:=src^;
1299         prf[3 ]:=#1;
1300 
1301         sc:=_type;
1302 
1303        end;
1304 
1305       'I' :
1306        begin
1307         prf[0 ]:=src^;
1308         prf[3 ]:=#1;
1309 
1310         sc:=_prefix;
1311 
1312        end;
1313 
1314       'c' ,'C' ,'d' ,'i' ,'o' ,'u' ,'x' ,'X' ,'e' ,'E' ,'f' ,'g' ,'G' ,'n' ,'p' ,'s' ,'S' :
1315        begin
1316         typ:=src^;
1317 
1318         apply;
1319 
1320        end;
1321 
1322       else
1323        begin
1324         dst^:=src^;
1325 
1326         inc(ptrcomp(dst ) );
1327 
1328         sc:=_string;
1329 
1330        end;
1331 
1332      end;
1333 
1334    { Width }
1335     _width :
1336      case src^ of
1337       '0' ,'1'..'9' :
1338        get:=get + src^;
1339 
1340       else
1341        begin
1342         system.val(get ,dth ,err );
1343 
1344         case src^ of
1345          '.' :
1346           begin
1347            get:='';
1348            sc :=_precision;
1349 
1350           end;
1351 
1352          'h' ,'l' :
1353           begin
1354            prf[0 ]:=src^;
1355            prf[3 ]:=#1;
1356 
1357            sc:=_type;
1358 
1359           end;
1360 
1361          'I' :
1362           begin
1363            prf[0 ]:=src^;
1364            prf[3 ]:=#1;
1365 
1366            sc:=_prefix;
1367 
1368           end;
1369 
1370          'c' ,'C' ,'d' ,'i' ,'o' ,'u' ,'x' ,'X' ,'e' ,'E' ,'f' ,'g' ,'G' ,'n' ,'p' ,'s' ,'S' :
1371           begin
1372            typ:=src^;
1373 
1374            apply;
1375 
1376           end;
1377 
1378          else
1379           sc:=_string;
1380 
1381         end;
1382 
1383        end;
1384 
1385      end;
1386 
1387    { Precision }
1388     _precision :
1389      case src^ of
1390       '0' ,'1'..'9' :
1391        get:=get + src^;
1392 
1393       else
1394        begin
1395         system.val(get ,prc ,err );
1396 
1397         case src^ of
1398          'h' ,'l' :
1399           begin
1400            prf[0 ]:=src^;
1401            prf[3 ]:=#1;
1402 
1403            sc:=_type;
1404 
1405           end;
1406 
1407          'I' :
1408           begin
1409            prf[0 ]:=src^;
1410            prf[3 ]:=#1;
1411 
1412            sc:=_prefix;
1413 
1414           end;
1415 
1416          'c' ,'C' ,'d' ,'i' ,'o' ,'u' ,'x' ,'X' ,'e' ,'E' ,'f' ,'g' ,'G' ,'n' ,'p' ,'s' ,'S' :
1417           begin
1418            typ:=src^;
1419 
1420            apply;
1421 
1422           end;
1423 
1424          else
1425           sc:=_string;
1426 
1427         end;
1428 
1429        end;
1430 
1431      end;
1432 
1433    { Prefix }
1434     _prefix :
1435      if prf[3 ] = #1 then
1436       case src^ of
1437        '3' ,'6' :
1438         begin
1439          prf[1 ]:=src^;
1440          prf[3 ]:=#2;
1441 
1442         end;
1443 
1444        'c' ,'C' ,'d' ,'i' ,'o' ,'u' ,'x' ,'X' ,'e' ,'E' ,'f' ,'g' ,'G' ,'n' ,'p' ,'s' ,'S' :
1445         begin
1446          typ:=src^;
1447 
1448          apply;
1449 
1450         end;
1451 
1452        else
1453         sc:=_string;
1454 
1455       end
1456      else
1457       if prf[3 ] = #2 then
1458        case src^ of
1459         '2' ,'4' :
1460          begin
1461           prf[2 ]:=src^;
1462           prf[3 ]:=#3;
1463 
1464           sc:=_type;
1465 
1466          end;
1467 
1468         'c' ,'C' ,'d' ,'i' ,'o' ,'u' ,'x' ,'X' ,'e' ,'E' ,'f' ,'g' ,'G' ,'n' ,'p' ,'s' ,'S' :
1469          begin
1470           typ:=src^;
1471 
1472           apply;
1473 
1474          end;
1475 
1476         else
1477          sc:=_string;
1478 
1479        end
1480       else
1481        sc:=_string;
1482 
1483    { Type }
1484     _type :
1485      case src^ of
1486       'c' ,'C' ,'d' ,'i' ,'o' ,'u' ,'x' ,'X' ,'e' ,'E' ,'f' ,'g' ,'G' ,'n' ,'p' ,'s' ,'S' :
1487        begin
1488         typ:=src^;
1489 
1490         apply;
1491 
1492        end;
1493 
1494       else
1495        sc:=_string;
1496 
1497      end;
1498 
1499    end;
1500 
1501    inc(ptrcomp(src ) );
1502 
1503   end;
1504 
1505  dst^:=#0;
1506 
1507 end;
1508 
1509 { INTDBL }
intdblnull1510 function intdbl;
1511 begin
1512  result:=i;
1513 
1514 end;
1515 
1516 { SRAND_ }
1517 procedure srand_(seed : int );
1518 begin
1519  system.RandSeed:=seed;
1520 
1521 end;
1522 
1523 { RAND_ }
1524 // Generates a pseudorandom number
rand_null1525 function rand_ : int;
1526 begin
1527  result:=system.Random($7fff )
1528 
1529 end;
1530 
1531 var
1532  g_holdrand : int = 1;
1533 
1534 { SRAND }
1535 procedure srand(seed : int );
1536 begin
1537  g_holdrand:=seed;
1538 
1539 end;
1540 
1541 { RAND }
randnull1542 function rand : int;
1543 begin
1544  g_holdrand:=g_holdrand * 214013 + 2531011;
1545 
1546  result:=(shr_int32(g_holdrand ,16 ) and $7fff );
1547 
1548 end;
1549 
1550 { UROUND }
uroundnull1551 function uround(v : double ) : int;
1552 begin
1553  result:=unsigned(Trunc(v + 0.5 ) );
1554 
1555 end;
1556 
1557 { IROUND }
iroundnull1558 function iround(v : double ) : int;
1559 begin
1560  if v < 0.0 then
1561   result:=int(Trunc(v - 0.5 ) )
1562  else
1563   result:=int(Trunc(v + 0.5 ) );
1564 
1565 end;
1566 
1567 { SATURATION_IROUND }
saturation_iroundnull1568 function saturation_iround(Limit : int; v : double ) : int;
1569 begin
1570  if v < -Limit then
1571   result:=-Limit
1572  else
1573   if v > Limit then
1574    result:=Limit
1575   else
1576    result:=iround(v );
1577 
1578 end;
1579 
1580 { NoP }
1581 procedure NoP;
1582 begin
1583 end;
1584 
1585 { SHR_INT8 }
shr_int8null1586 function shr_int8(i ,shift : int8 ) : int8;
1587 begin
1588   Result := SarShortint(i, shift);
1589 end;
1590 
1591 { SHR_INT16 }
shr_int16null1592 function shr_int16(i ,shift : int16 ) : int16;
1593 begin
1594   Result := SarSmallint(i, shift);
1595 end;
1596 
1597 { SHR_INT32 }
shr_int32null1598 function shr_int32(i, shift: int): int;
1599 begin
1600   Result := SarLongint(i, shift);
1601 end;
1602 
1603 end.
1604 
1605