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