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 //----------------------------------------------------------------------------
22 //
23 // Stroke generator
24 //
25 // [Pascal Port History] -----------------------------------------------------
26 //
27 // 18.10.2007-Milano: vcgen_stroke_math
28 // 21.12.2005-Milano: Unit port establishment
29 //
30 { agg_vcgen_stroke.pas }
31 unit
32 agg_vcgen_stroke ;
33
34 INTERFACE
35
36 {$I agg_mode.inc }
37
38 uses
39 agg_basics ,
40 agg_array ,
41 agg_vertex_source ,
42 agg_vertex_sequence ,
43 agg_math_stroke ,
44 agg_shorten_path ;
45
46 { TYPES DEFINITION }
47 type
48 status_e = (
49 initial ,
50 ready ,
51 cap1 ,
52 cap2 ,
53 outline1 ,
54 close_first ,
55 outline2 ,
56 out_vertices ,
57 end_poly1 ,
58 end_poly2 ,
59 stop );
60
61 vcgen_stroke_ptr = ^vcgen_stroke;
62 vcgen_stroke = object(vertex_source )
63 m_src_vertices : vertex_sequence;
64 m_out_vertices : pod_deque;
65 m_width ,
66 m_miter_limit ,
67 m_inner_miter_limit ,
68 m_approx_scale ,
69 m_shorten : double;
70 m_line_cap ,
71 m_line_join ,
72 m_inner_join ,
73 m_closed : unsigned;
74 m_status ,
75 m_prev_status : status_e;
76 m_src_vertex ,
77 m_out_vertex : unsigned;
78
79 constructor Construct;
80 destructor Destruct; virtual;
81
82 procedure line_cap_ (lc : unsigned );
83 procedure line_join_ (lj : unsigned );
84 procedure inner_join_(ij : unsigned );
85
_line_capnull86 function _line_cap : unsigned;
_line_joinnull87 function _line_join : unsigned;
_inner_joinnull88 function _inner_join : unsigned;
89
90 procedure width_ (w : double );
91 procedure miter_limit_ (ml : double );
92 procedure miter_limit_theta_ (t : double );
93 procedure inner_miter_limit_ (ml : double );
94 procedure approximation_scale_(as_ : double );
95
_widthnull96 function _width : double;
_miter_limitnull97 function _miter_limit : double;
_inner_miter_limitnull98 function _inner_miter_limit : double;
_approximation_scalenull99 function _approximation_scale : double;
100
101 procedure shorten_(s : double );
_shortennull102 function _shorten : double;
103
104 // Vertex Generator Interface
105 procedure remove_all; virtual;
106 procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
107
108 // Vertex Source Interface
109 procedure rewind(path_id : unsigned ); virtual;
vertexnull110 function vertex(x ,y : double_ptr ) : unsigned; virtual;
111
112 end;
113
114 vcgen_stroke_math_ptr = ^vcgen_stroke_math;
115 vcgen_stroke_math = object(vertex_source )
116 m_stroker : math_stroke;
117 m_src_vertices : vertex_sequence;
118 m_out_vertices : pod_deque;
119
120 m_shorten : double;
121 m_closed : unsigned;
122
123 m_status ,
124 m_prev_status : status_e;
125
126 m_src_vertex ,
127 m_out_vertex : unsigned;
128
129 constructor Construct;
130 destructor Destruct; virtual;
131
132 procedure line_cap_ (lc : unsigned );
133 procedure line_join_ (lj : unsigned );
134 procedure inner_join_(ij : unsigned );
135
_line_capnull136 function _line_cap : unsigned;
_line_joinnull137 function _line_join : unsigned;
_inner_joinnull138 function _inner_join : unsigned;
139
140 procedure width_ (w : double );
141 procedure miter_limit_ (ml : double );
142 procedure miter_limit_theta_ (t : double );
143 procedure inner_miter_limit_ (ml : double );
144 procedure approximation_scale_(as_ : double );
145
_widthnull146 function _width : double;
_miter_limitnull147 function _miter_limit : double;
_inner_miter_limitnull148 function _inner_miter_limit : double;
_approximation_scalenull149 function _approximation_scale : double;
150
151 procedure shorten_(s : double );
_shortennull152 function _shorten : double;
153
154 // Vertex Generator Interface
155 procedure remove_all; virtual;
156 procedure add_vertex(x ,y : double; cmd : unsigned ); virtual;
157
158 // Vertex Source Interface
159 procedure rewind(path_id : unsigned ); virtual;
vertexnull160 function vertex(x ,y : double_ptr ) : unsigned; virtual;
161
162 end;
163
164 { GLOBAL PROCEDURES }
165
166
167 IMPLEMENTATION
168 { LOCAL VARIABLES & CONSTANTS }
169 { UNIT IMPLEMENTATION }
170 { CONSTRUCT }
171 constructor vcgen_stroke.Construct;
172 begin
173 m_src_vertices.Construct(sizeof(vertex_dist ) );
174 m_out_vertices.Construct(sizeof(point_type ) );
175
176 m_width :=0.5;
177 m_miter_limit :=4.0;
178 m_inner_miter_limit:=1.01;
179 m_approx_scale :=1.0;
180 m_shorten :=0.0;
181 m_line_cap :=butt_cap;
182 m_line_join :=miter_join;
183 m_inner_join :=inner_miter;
184 m_closed :=0;
185 m_status :=initial;
186 m_src_vertex :=0;
187 m_out_vertex :=0;
188
189 end;
190
191 { DESTRUCT }
192 destructor vcgen_stroke.Destruct;
193 begin
194 m_src_vertices.Destruct;
195 m_out_vertices.Destruct;
196
197 end;
198
199 { LINE_CAP_ }
200 procedure vcgen_stroke.line_cap_;
201 begin
202 m_line_cap:=lc;
203
204 end;
205
206 { LINE_JOIN_ }
207 procedure vcgen_stroke.line_join_;
208 begin
209 m_line_join:=lj;
210
211 end;
212
213 { INNER_JOIN_ }
214 procedure vcgen_stroke.inner_join_;
215 begin
216 m_inner_join:=ij;
217
218 end;
219
220 { _LINE_CAP }
vcgen_stroke._line_capnull221 function vcgen_stroke._line_cap;
222 begin
223 result:=m_line_cap;
224
225 end;
226
227 { _LINE_JOIN }
vcgen_stroke._line_joinnull228 function vcgen_stroke._line_join;
229 begin
230 result:=m_line_join;
231
232 end;
233
234 { _INNER_JOIN }
vcgen_stroke._inner_joinnull235 function vcgen_stroke._inner_join;
236 begin
237 result:=m_inner_join;
238
239 end;
240
241 { WIDTH_ }
242 procedure vcgen_stroke.width_(w : double );
243 begin
244 m_width:=w * 0.5;
245
246 end;
247
248 { MITER_LIMIT_ }
249 procedure vcgen_stroke.miter_limit_(ml : double );
250 begin
251 m_miter_limit:=ml;
252
253 end;
254
255 { MITER_LIMIT_THETA_ }
256 procedure vcgen_stroke.miter_limit_theta_(t : double );
257 begin
258 m_miter_limit:=1.0 / Sin(t * 0.5 );
259
260 end;
261
262 { INNER_MITER_LIMIT_ }
263 procedure vcgen_stroke.inner_miter_limit_(ml : double );
264 begin
265 m_inner_miter_limit:=ml;
266
267 end;
268
269 { APPROXIMATION_SCALE_ }
270 procedure vcgen_stroke.approximation_scale_(as_ : double );
271 begin
272 m_approx_scale:=as_;
273
274 end;
275
276 { _WIDTH }
vcgen_stroke._widthnull277 function vcgen_stroke._width;
278 begin
279 result:=m_width * 2.0;
280
281 end;
282
283 { _MITER_LIMIT }
vcgen_stroke._miter_limitnull284 function vcgen_stroke._miter_limit;
285 begin
286 result:=m_miter_limit;
287
288 end;
289
290 { _INNER_MITER_LIMIT }
vcgen_stroke._inner_miter_limitnull291 function vcgen_stroke._inner_miter_limit;
292 begin
293 result:=m_inner_miter_limit;
294
295 end;
296
297 { _APPROXIMATION_SCALE }
vcgen_stroke._approximation_scalenull298 function vcgen_stroke._approximation_scale;
299 begin
300 result:=m_approx_scale;
301
302 end;
303
304 { SHORTEN_ }
305 procedure vcgen_stroke.shorten_;
306 begin
307 m_shorten:=s;
308
309 end;
310
311 { _SHORTEN }
vcgen_stroke._shortennull312 function vcgen_stroke._shorten;
313 begin
314 result:=m_shorten;
315
316 end;
317
318 { REMOVE_ALL }
319 procedure vcgen_stroke.remove_all;
320 begin
321 m_src_vertices.remove_all;
322
323 m_closed:=0;
324 m_status:=initial;
325
326 end;
327
328 { ADD_VERTEX }
329 procedure vcgen_stroke.add_vertex(x ,y : double; cmd : unsigned );
330 var
331 vd : vertex_dist;
332
333 begin
334 m_status:=initial;
335
336 vd.x:=x;
337 vd.y:=y;
338
339 vd.dist:=0;
340
341 if is_move_to(cmd ) then
342 m_src_vertices.modify_last(@vd )
343 else
344 if is_vertex(cmd ) then
345 m_src_vertices.add(@vd )
346 else
347 m_closed:=get_close_flag(cmd );
348
349 end;
350
351 { calc_butt_cap }
352 procedure calc_butt_cap(cap : double_00_ptr; v0 ,v1 : vertex_dist_ptr; len ,width : double );
353 var
354 dx ,dy : double;
355
356 begin
357 dx:=(v1.y - v0.y ) * width / len;
358 dy:=(v1.x - v0.x ) * width / len;
359
360 cap^[0 ]:=v0.x - dx;
361 cap^[1 ]:=v0.y + dy;
362 cap^[2 ]:=v0.x + dx;
363 cap^[3 ]:=v0.y - dy;
364
365 end;
366
367 { REWIND }
368 procedure vcgen_stroke.rewind(path_id : unsigned );
369 begin
370 if m_status = initial then
371 begin
372 m_src_vertices.close(boolean(m_closed <> 0 ) );
373
374 shorten_path(@m_src_vertices ,m_shorten ,m_closed );
375
376 if m_src_vertices.size < 3 then
377 m_closed:=0;
378
379 end;
380
381 m_status:=ready;
382
383 m_src_vertex:=0;
384 m_out_vertex:=0;
385
386 end;
387
388 { VERTEX }
vcgen_stroke.vertexnull389 function vcgen_stroke.vertex(x ,y : double_ptr ) : unsigned;
390 var
391 c : point_type_ptr;
392
393 cmd : unsigned;
394
395 label
396 _rdy ,_out2 ,_end ;
397
398 begin
399 cmd:=path_cmd_line_to;
400
401 while not is_stop(cmd ) do
402 begin
403 case m_status of
404 initial :
405 begin
406 rewind(0 );
407
408 goto _rdy;
409
410 end;
411
412 ready :
413 begin
414 _rdy:
415 if m_src_vertices.size < 2 + unsigned(m_closed <> 0 ) then
416 begin
417 cmd:=path_cmd_stop;
418
419 goto _end;
420
421 end;
422
423 if (m_closed <> 0 ) then
424 m_status:=outline1
425 else
426 m_status:=cap1;
427
428 cmd:=path_cmd_move_to;
429
430 m_src_vertex:=0;
431 m_out_vertex:=0;
432
433 end;
434
435 cap1 :
436 begin
437 stroke_calc_cap(
438 @m_out_vertices ,
439 m_src_vertices.array_operator(0 ) ,
440 m_src_vertices.array_operator(1 ) ,
441 vertex_dist_ptr(m_src_vertices.array_operator(0 ) )^.dist ,
442 m_line_cap ,
443 m_width ,
444 m_approx_scale );
445
446 m_src_vertex :=1;
447 m_prev_status:=outline1;
448 m_status :=out_vertices;
449 m_out_vertex :=0;
450
451 end;
452
453 cap2 :
454 begin
455 stroke_calc_cap(
456 @m_out_vertices ,
457 m_src_vertices.array_operator(m_src_vertices.size - 1 ) ,
458 m_src_vertices.array_operator(m_src_vertices.size - 2 ) ,
459 vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertices.size - 2 ) )^.dist ,
460 m_line_cap ,
461 m_width ,
462 m_approx_scale );
463
464 m_prev_status:=outline2;
465 m_status :=out_vertices;
466 m_out_vertex :=0;
467
468 end;
469
470 outline1 :
471 begin
472 if m_closed <> 0 then
473 if m_src_vertex >= m_src_vertices.size then
474 begin
475 m_prev_status:=close_first;
476 m_status :=end_poly1;
477
478 goto _end;
479
480 end
481 else
482 else
483 if m_src_vertex >= m_src_vertices.size - 1 then
484 begin
485 m_status:=cap2;
486
487 goto _end;
488
489 end;
490
491 stroke_calc_join(
492 @m_out_vertices ,
493 m_src_vertices.prev(m_src_vertex ) ,
494 m_src_vertices.curr(m_src_vertex ) ,
495 m_src_vertices.next(m_src_vertex ) ,
496 vertex_dist_ptr(m_src_vertices.prev(m_src_vertex ) )^.dist ,
497 vertex_dist_ptr(m_src_vertices.curr(m_src_vertex ) )^.dist ,
498 m_width ,
499 m_line_join ,
500 m_inner_join ,
501 m_miter_limit ,
502 m_inner_miter_limit ,
503 m_approx_scale );
504
505 inc(m_src_vertex );
506
507 m_prev_status:=m_status;
508 m_status :=out_vertices;
509 m_out_vertex :=0;
510
511 end;
512
513 close_first :
514 begin
515 m_status:=outline2;
516
517 cmd:=path_cmd_move_to;
518
519 goto _out2;
520
521 end;
522
523 outline2 :
524 begin
525 _out2:
526 if m_src_vertex <= unsigned(m_closed = 0 ) then
527 begin
528 m_status :=end_poly2;
529 m_prev_status:=stop;
530
531 goto _end;
532
533 end;
534
535 dec(m_src_vertex );
536
537 stroke_calc_join(
538 @m_out_vertices ,
539 m_src_vertices.next(m_src_vertex ) ,
540 m_src_vertices.curr(m_src_vertex ) ,
541 m_src_vertices.prev(m_src_vertex ) ,
542 vertex_dist_ptr(m_src_vertices.curr(m_src_vertex ) )^.dist ,
543 vertex_dist_ptr(m_src_vertices.prev(m_src_vertex ) )^.dist ,
544 m_width ,
545 m_line_join ,
546 m_inner_join ,
547 m_miter_limit ,
548 m_inner_miter_limit ,
549 m_approx_scale );
550
551 m_prev_status:=m_status;
552 m_status :=out_vertices;
553 m_out_vertex :=0;
554
555 end;
556
557 out_vertices :
558 if m_out_vertex >= m_out_vertices.size then
559 m_status:=m_prev_status
560
561 else
562 begin
563 c:=m_out_vertices.array_operator(m_out_vertex );
564
565 inc(m_out_vertex );
566
567 x^:=c.x;
568 y^:=c.y;
569
570 result:=cmd;
571
572 exit;
573
574 end;
575
576 end_poly1 :
577 begin
578 m_status:=m_prev_status;
579
580 result:=path_cmd_end_poly or path_flags_close or path_flags_ccw;
581
582 exit;
583
584 end;
585
586 end_poly2 :
587 begin
588 m_status:=m_prev_status;
589
590 result:=path_cmd_end_poly or path_flags_close or path_flags_cw;
591
592 exit;
593
594 end;
595
596 stop :
597 cmd:=path_cmd_stop;
598
599 end;
600
601 _end:
602 end;
603
604 result:=cmd;
605
606 end;
607
608 { CONSTRUCT }
609 constructor vcgen_stroke_math.Construct;
610 begin
611 m_stroker.Construct;
612 m_src_vertices.Construct(sizeof(vertex_dist ) );
613 m_out_vertices.Construct(sizeof(point_type ) );
614
615 m_shorten:=0.0;
616 m_closed :=0;
617 m_status :=initial;
618
619 m_src_vertex:=0;
620 m_out_vertex:=0;
621
622 end;
623
624 { DESTRUCT }
625 destructor vcgen_stroke_math.Destruct;
626 begin
627 m_src_vertices.Destruct;
628 m_out_vertices.Destruct;
629
630 end;
631
632 { LINE_CAP_ }
633 procedure vcgen_stroke_math.line_cap_(lc : unsigned );
634 begin
635 m_stroker.line_cap_(lc );
636
637 end;
638
639 { LINE_JOIN_ }
640 procedure vcgen_stroke_math.line_join_(lj : unsigned );
641 begin
642 m_stroker.line_join_(lj );
643
644 end;
645
646 { INNER_JOIN_ }
647 procedure vcgen_stroke_math.inner_join_(ij : unsigned );
648 begin
649 m_stroker.inner_join_(ij );
650
651 end;
652
653 { _LINE_CAP }
vcgen_stroke_math._line_capnull654 function vcgen_stroke_math._line_cap : unsigned;
655 begin
656 result:=m_stroker._line_cap;
657
658 end;
659
660 { _LINE_JOIN }
vcgen_stroke_math._line_joinnull661 function vcgen_stroke_math._line_join : unsigned;
662 begin
663 result:=m_stroker._line_join;
664
665 end;
666
667 { _INNER_JOIN }
vcgen_stroke_math._inner_joinnull668 function vcgen_stroke_math._inner_join : unsigned;
669 begin
670 result:=m_stroker._inner_join;
671
672 end;
673
674 { WIDTH_ }
675 procedure vcgen_stroke_math.width_(w : double );
676 begin
677 m_stroker.width_(w );
678
679 end;
680
681 { MITER_LIMIT_ }
682 procedure vcgen_stroke_math.miter_limit_(ml : double );
683 begin
684 m_stroker.miter_limit_(ml );
685
686 end;
687
688 { MITER_LIMIT_THETA_ }
689 procedure vcgen_stroke_math.miter_limit_theta_(t : double );
690 begin
691 m_stroker.miter_limit_theta_(t );
692
693 end;
694
695 { INNER_MITER_LIMIT_ }
696 procedure vcgen_stroke_math.inner_miter_limit_(ml : double );
697 begin
698 m_stroker.inner_miter_limit_(ml );
699
700 end;
701
702 { APPROXIMATION_SCALE_ }
703 procedure vcgen_stroke_math.approximation_scale_(as_ : double );
704 begin
705 m_stroker.approximation_scale_(as_ );
706
707 end;
708
709 { _WIDTH }
vcgen_stroke_math._widthnull710 function vcgen_stroke_math._width : double;
711 begin
712 result:=m_stroker._width;
713
714 end;
715
716 { _MITER_LIMIT }
vcgen_stroke_math._miter_limitnull717 function vcgen_stroke_math._miter_limit : double;
718 begin
719 result:=m_stroker._miter_limit;
720
721 end;
722
723 { _INNER_MITER_LIMIT }
vcgen_stroke_math._inner_miter_limitnull724 function vcgen_stroke_math._inner_miter_limit : double;
725 begin
726 result:=m_stroker._inner_miter_limit;
727
728 end;
729
730 { _APPROXIMATION_SCALE }
vcgen_stroke_math._approximation_scalenull731 function vcgen_stroke_math._approximation_scale : double;
732 begin
733 result:=m_stroker._approximation_scale;
734
735 end;
736
737 { SHORTEN_ }
738 procedure vcgen_stroke_math.shorten_(s : double );
739 begin
740 m_shorten:=s;
741
742 end;
743
744 { _SHORTEN }
vcgen_stroke_math._shortennull745 function vcgen_stroke_math._shorten : double;
746 begin
747 result:=m_shorten;
748
749 end;
750
751 { REMOVE_ALL }
752 procedure vcgen_stroke_math.remove_all;
753 begin
754 m_src_vertices.remove_all;
755
756 m_closed:=0;
757 m_status:=initial;
758
759 end;
760
761 { ADD_VERTEX }
762 procedure vcgen_stroke_math.add_vertex(x ,y : double; cmd : unsigned );
763 var
764 vd : vertex_dist;
765
766 begin
767 m_status:=initial;
768
769 vd.x:=x;
770 vd.y:=y;
771
772 vd.dist:=0;
773
774 if is_move_to(cmd ) then
775 m_src_vertices.modify_last(@vd )
776 else
777 if is_vertex(cmd ) then
778 m_src_vertices.add(@vd )
779 else
780 m_closed:=get_close_flag(cmd );
781
782 end;
783
784 { REWIND }
785 procedure vcgen_stroke_math.rewind(path_id : unsigned );
786 begin
787 if m_status = initial then
788 begin
789 m_src_vertices.close(boolean(m_closed <> 0 ) );
790
791 shorten_path(@m_src_vertices ,m_shorten ,m_closed );
792
793 if m_src_vertices.size < 3 then
794 m_closed:=0;
795
796 end;
797
798 m_status:=ready;
799
800 m_src_vertex:=0;
801 m_out_vertex:=0;
802
803 end;
804
805 { VERTEX }
vcgen_stroke_math.vertexnull806 function vcgen_stroke_math.vertex(x ,y : double_ptr ) : unsigned;
807 var
808 cmd : unsigned;
809
810 c : point_type_ptr;
811
812 label
813 _rdy ,_out2 ,_end ;
814
815 begin
816 cmd:=path_cmd_line_to;
817
818 while not is_stop(cmd ) do
819 begin
820 case m_status of
821 initial :
822 begin
823 rewind(0 );
824
825 goto _rdy;
826
827 end;
828
829 ready :
830 begin
831 _rdy:
832 if m_src_vertices.size < 2 + unsigned(m_closed <> 0 ) then
833 begin
834 cmd:=path_cmd_stop;
835
836 goto _end;
837
838 end;
839
840 if (m_closed <> 0 ) then
841 m_status:=outline1
842 else
843 m_status:=cap1;
844
845 cmd:=path_cmd_move_to;
846
847 m_src_vertex:=0;
848 m_out_vertex:=0;
849
850 end;
851
852 cap1 :
853 begin
854 m_stroker.calc_cap(
855 @m_out_vertices ,
856 m_src_vertices.array_operator(0 ) ,
857 m_src_vertices.array_operator(1 ) ,
858 vertex_dist_ptr(m_src_vertices.array_operator(0 ) )^.dist );
859
860 m_src_vertex :=1;
861 m_prev_status:=outline1;
862 m_status :=out_vertices;
863 m_out_vertex :=0;
864
865 end;
866
867 cap2 :
868 begin
869 m_stroker.calc_cap(
870 @m_out_vertices ,
871 m_src_vertices.array_operator(m_src_vertices.size - 1 ) ,
872 m_src_vertices.array_operator(m_src_vertices.size - 2 ) ,
873 vertex_dist_ptr(m_src_vertices.array_operator(m_src_vertices.size - 2 ) )^.dist );
874
875 m_prev_status:=outline2;
876 m_status :=out_vertices;
877 m_out_vertex :=0;
878
879 end;
880
881 outline1 :
882 begin
883 if m_closed <> 0 then
884 if m_src_vertex >= m_src_vertices.size then
885 begin
886 m_prev_status:=close_first;
887 m_status :=end_poly1;
888
889 goto _end;
890
891 end
892 else
893 else
894 if m_src_vertex >= m_src_vertices.size - 1 then
895 begin
896 m_status:=cap2;
897
898 goto _end;
899
900 end;
901
902 m_stroker.calc_join(
903 @m_out_vertices ,
904 m_src_vertices.prev(m_src_vertex ) ,
905 m_src_vertices.curr(m_src_vertex ) ,
906 m_src_vertices.next(m_src_vertex ) ,
907 vertex_dist_ptr(m_src_vertices.prev(m_src_vertex ) )^.dist ,
908 vertex_dist_ptr(m_src_vertices.curr(m_src_vertex ) )^.dist );
909
910 inc(m_src_vertex );
911
912 m_prev_status:=m_status;
913 m_status :=out_vertices;
914 m_out_vertex :=0;
915
916 end;
917
918 close_first :
919 begin
920 m_status:=outline2;
921
922 cmd:=path_cmd_move_to;
923
924 goto _out2;
925
926 end;
927
928 outline2 :
929 begin
930 _out2:
931 if m_src_vertex <= unsigned(m_closed = 0 ) then
932 begin
933 m_status :=end_poly2;
934 m_prev_status:=stop;
935
936 goto _end;
937
938 end;
939
940 dec(m_src_vertex );
941
942 m_stroker.calc_join(
943 @m_out_vertices ,
944 m_src_vertices.next(m_src_vertex ) ,
945 m_src_vertices.curr(m_src_vertex ) ,
946 m_src_vertices.prev(m_src_vertex ) ,
947 vertex_dist_ptr(m_src_vertices.curr(m_src_vertex ) )^.dist ,
948 vertex_dist_ptr(m_src_vertices.prev(m_src_vertex ) )^.dist );
949
950 m_prev_status:=m_status;
951 m_status :=out_vertices;
952 m_out_vertex :=0;
953
954 end;
955
956 out_vertices :
957 if m_out_vertex >= m_out_vertices.size then
958 m_status:=m_prev_status
959
960 else
961 begin
962 c:=m_out_vertices.array_operator(m_out_vertex );
963
964 inc(m_out_vertex );
965
966 x^:=c.x;
967 y^:=c.y;
968
969 result:=cmd;
970
971 exit;
972
973 end;
974
975 end_poly1 :
976 begin
977 m_status:=m_prev_status;
978
979 result:=path_cmd_end_poly or path_flags_close or path_flags_ccw;
980
981 exit;
982
983 end;
984
985 end_poly2 :
986 begin
987 m_status:=m_prev_status;
988
989 result:=path_cmd_end_poly or path_flags_close or path_flags_cw;
990
991 exit;
992
993 end;
994
995 stop :
996 cmd:=path_cmd_stop;
997
998 end;
999
1000 _end:
1001 end;
1002
1003 result:=cmd;
1004
1005 end;
1006
1007 END.
1008
1009