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 // 03.02.2006-Milano: Complete unit port
25 // 02.02.2006-Milano: Unit port establishment
26 //
27 { agg_renderer_outline_image.pas }
28 unit
29  agg_renderer_outline_image ;
30 
31 INTERFACE
32 
33 {$I agg_mode.inc }
34 {$Q- }
35 {$R- }
36 
37 uses
38  Math ,
39  agg_basics ,
40  agg_color ,
41  agg_line_aa_basics ,
42  agg_dda_line ,
43  agg_rendering_buffer ,
44  agg_renderer_base ,
45  agg_renderer_outline_aa ,
46  agg_pattern_filters_rgba ;
47 
48 { TYPES DEFINITION }
49 type
50  pixel_source_ptr = ^pixel_source;
51  pixel_source = object
_widthnull52    function  _width : unsigned; virtual; abstract;
_heightnull53    function  _height : unsigned; virtual; abstract;
54 
_width_dnull55    function  _width_d : double; virtual;
_height_dnull56    function  _height_d : double; virtual;
57 
pixelnull58    function  pixel(x ,y : int ) : rgba8; virtual; abstract;
59 
60   end;
61 
62  line_image_scale = object(pixel_source )
63    m_source : pixel_source_ptr;
64    m_height ,
65    m_scale  : double;
66 
67    constructor Construct(src : pixel_source_ptr; height_ : double );
68 
_width_dnull69    function  _width_d : double; virtual;
_height_dnull70    function  _height_d : double; virtual;
71 
pixelnull72    function  pixel(x ,y : int ) : rgba8; virtual;
73 
74   end;
75 
76  line_image_pattern_ptr = ^line_image_pattern;
77  line_image_pattern = object
78    m_buf    : rendering_buffer;
79    m_filter : pattern_filter_ptr;
80 
81    m_dilation    : unsigned;
82    m_dilation_hr : int;
83 
84    m_data   : aggclr_ptr;
85    m_dt_sz  ,
86    m_width  ,
87    m_height : unsigned;
88 
89    m_width_hr       ,
90    m_half_height_hr ,
91    m_offset_y_hr    : int;
92 
93    constructor Construct(filter_ : pattern_filter_ptr ); overload;
94    constructor Construct(filter_ : pattern_filter_ptr; src : pixel_source_ptr ); overload;
95    destructor  Destruct;
96 
97    procedure create(src : pixel_source_ptr ); virtual;
98 
pattern_widthnull99    function  pattern_width : int;
line_widthnull100    function  line_width : int;
101 
102    procedure pixel(p : aggclr_ptr; x ,y : int ); virtual;
103 
104    procedure filter(filter_ : pattern_filter_ptr ); overload;
filternull105    function  filter : pattern_filter_ptr; overload;
106 
107   end;
108 
109  line_image_pattern_pow2 = object(line_image_pattern )
110    m_mask : unsigned;
111 
112    constructor Construct(filter_ : pattern_filter_ptr ); overload;
113    constructor Construct(filter_ : pattern_filter_ptr; src : pixel_source_ptr ); overload;
114 
115    procedure create(src : pixel_source_ptr ); virtual;
116    procedure pixel (p : aggclr_ptr; x ,y : int ); virtual;
117 
118   end;
119 
120  distance_interpolator4 = object(distance_interpolator )
121    m_dx ,
122    m_dy ,
123 
124    m_dx_start ,
125    m_dy_start ,
126    m_dx_pict  ,
127    m_dy_pict  ,
128    m_dx_end   ,
129    m_dy_end   ,
130 
131    m_dist       ,
132    m_dist_start ,
133    m_dist_pict  ,
134    m_dist_end   ,
135 
136    m_len : int;
137 
138    constructor Construct; overload;
139    constructor Construct(x1 ,y1 ,x2 ,y2 ,sx ,sy ,ex ,ey ,len_ : int; scale : double; x ,y : int ); overload;
140 
141    procedure inc_x_; virtual;
142    procedure dec_x_; virtual;
143    procedure inc_y_; virtual;
144    procedure dec_y_; virtual;
145 
146    procedure inc_x(dy_ : int ); virtual;
147    procedure dec_x(dy_ : int ); virtual;
148    procedure inc_y(dx_ : int ); virtual;
149    procedure dec_y(dx_ : int ); virtual;
150 
distnull151    function  dist : int; virtual;
dist_startnull152    function  dist_start : int; virtual;
dist_pictnull153    function  dist_pict : int;
dist_endnull154    function  dist_end : int; virtual;
155 
dxnull156    function  dx : int; virtual;
dynull157    function  dy : int; virtual;
dx_startnull158    function  dx_start : int; virtual;
dy_startnull159    function  dy_start : int; virtual;
dx_pictnull160    function  dx_pict : int;
dy_pictnull161    function  dy_pict : int;
dx_endnull162    function  dx_end : int; virtual;
dy_endnull163    function  dy_end : int; virtual;
lennull164    function  len : int;
165 
166   end;
167 
168  renderer_outline_image_ptr = ^renderer_outline_image;
169 
170  line_interpolator_image = object //(line_interpolator )
171    m_lp  : line_parameters_ptr;
172    m_li  : dda2_line_interpolator;
173    m_di  : distance_interpolator4;
174    m_ren : renderer_outline_image_ptr;
175 
176    m_plen ,
177    m_x    ,
178    m_y    ,
179 
180    m_old_x ,
181    m_old_y ,
182    m_count ,
183    m_width ,
184 
185    m_max_extent ,
186 
187    m_start ,
188    m_step  : int;
189 
190    m_dist_pos : array[0..max_half_width + 1 - 1 ] of int;
191    m_colors   : array[0..max_half_width * 2 + 4 - 1 ] of aggclr;
192 
193    constructor Construct(
194                 ren : renderer_outline_image_ptr;
195                 lp  : line_parameters_ptr;
196                 sx ,sy ,ex ,ey ,pattern_start : int;
197                 scale_x : double );
198 
step_hornull199    function  step_hor : boolean;
step_vernull200    function  step_ver : boolean;
201 
pattern_endnull202    function  pattern_end : int;
verticalnull203    function  vertical : boolean;
widthnull204    function  width : int;
countnull205    function  count : int;
206 
207   end;
208 
209  renderer_outline_image = object(renderer_outline )
210    m_ren     : renderer_base_ptr;
211    m_pattern : line_image_pattern_ptr;
212    m_start   : int;
213    m_scale_x : double;
214 
215    constructor Construct(ren : renderer_base_ptr; patt : line_image_pattern_ptr );
216 
217    procedure pattern_(p : line_image_pattern_ptr );
_patternnull218    function  _pattern : line_image_pattern_ptr;
219 
220    procedure scale_x_(s : double );
_scale_xnull221    function  _scale_x : double;
222 
223    procedure start_x_(s : double );
_start_xnull224    function  _start_x : double;
225 
subpixel_widthnull226    function  subpixel_width : int; virtual;
_pattern_widthnull227    function  _pattern_width : int;
228 
229    procedure pixel(p : aggclr_ptr; x ,y : int );
230 
231    procedure blend_color_hspan(x ,y : int; len : unsigned; colors : aggclr_ptr );
232    procedure blend_color_vspan(x ,y : int; len : unsigned; colors : aggclr_ptr );
233 
accurate_join_onlynull234    function  accurate_join_only : boolean; virtual;
235 
236    procedure semidot(cmp : cmp_function; xc1 ,yc1 ,xc2 ,yc2 : int ); virtual;
237 
238    procedure line0(lp : line_parameters_ptr ); virtual;
239    procedure line1(lp : line_parameters_ptr; sx ,sy : int ); virtual;
240    procedure line2(lp : line_parameters_ptr; ex ,ey : int ); virtual;
241    procedure line3(lp : line_parameters_ptr; sx ,sy ,ex ,ey : int ); virtual;
242 
243   end;
244 
245 { GLOBAL PROCEDURES }
246 
247 
248 IMPLEMENTATION
249 { LOCAL VARIABLES & CONSTANTS }
250 { UNIT IMPLEMENTATION }
251 { _WIDTH_D }
pixel_source._width_dnull252 function pixel_source._width_d;
253 begin
254  result:=_width;
255 
256 end;
257 
258 { _HEIGHT_D }
pixel_source._height_dnull259 function pixel_source._height_d;
260 begin
261  result:=_height;
262 
263 end;
264 
265 { CONSTRUCT }
266 constructor line_image_scale.Construct;
267 begin
268  m_source:=src;
269  m_height:=height_;
270 
271  if height_ <> 0 then
272   m_scale:=src._height / height_
273  else
274   m_scale:=0;
275 
276 end;
277 
278 { _WIDTH_D }
line_image_scale._width_dnull279 function line_image_scale._width_d;
280 begin
281  result:=m_source._width;
282 
283 end;
284 
285 { _HEIGHT_D }
line_image_scale._height_dnull286 function line_image_scale._height_d;
287 begin
288  result:=m_height;
289 
290 end;
291 
292 { PIXEL }
line_image_scale.pixelnull293 function line_image_scale.pixel;
294 var
295  src_y : double;
296 
297  h ,y1 ,y2 : int;
298 
299  pix1 ,pix2 : aggclr;
300 
301 begin
302  src_y:=(y + 0.5 ) * m_scale - 0.5;
303 
304  h :=trunc(m_source._height ) - 1;
305  y1:=trunc(src_y );
306  y2:=y1 + 1;
307 
308  if y1 < 0 then
309   pix1.Construct
310  else
311   pix1.Construct(m_source.pixel(x ,y1 ) );
312 
313  if y2 > h then
314   pix2.Construct
315  else
316   pix2.Construct(m_source.pixel(x ,y2 ) );
317 
318  result:=pix1.gradient8(@pix2 ,src_y - y1 );
319 
320 end;
321 
322 { CONSTRUCT }
323 constructor line_image_pattern.Construct(filter_ : pattern_filter_ptr );
324 begin
325  m_buf.Construct;
326 
327  m_filter:=filter_;
328 
329  m_dilation   :=filter_.dilation + 1;
330  m_dilation_hr:=m_dilation shl line_subpixel_shift;
331 
332  m_data  :=0;
333  m_dt_sz :=0;
334  m_width :=0;
335  m_height:=0;
336 
337  m_width_hr      :=0;
338  m_half_height_hr:=0;
339  m_offset_y_hr   :=0;
340 
341 end;
342 
343 { CONSTRUCT }
344 constructor line_image_pattern.Construct(filter_ : pattern_filter_ptr; src : pixel_source_ptr );
345 begin
346  m_buf.Construct;
347 
348  m_filter:=filter_;
349 
350  m_dilation   :=filter_.dilation + 1;
351  m_dilation_hr:=m_dilation shl line_subpixel_shift;
352 
353  m_data  :=0;
354  m_dt_sz :=0;
355  m_width :=0;
356  m_height:=0;
357 
358  m_width_hr      :=0;
359  m_half_height_hr:=0;
360  m_offset_y_hr   :=0;
361 
362  create(src );
363 
364 end;
365 
366 { DESTRUCT }
367 destructor line_image_pattern.Destruct;
368 begin
369  agg_freemem(pointer(m_data ) ,m_dt_sz );
370 
371  m_buf.Destruct;
372 
373 end;
374 
375 { CREATE }
376 procedure line_image_pattern.create;
377 var
378  x ,y ,h : unsigned;
379 
380  d1 ,d2 ,s1 ,s2 : rgba8_ptr;
381 
382 begin
383  m_height:=Ceil(src._height_d );
384  m_width :=Ceil(src._width_d );
385 
386  m_width_hr      :=trunc(src._width_d * line_subpixel_size );
387  m_half_height_hr:=trunc(src._height_d * line_subpixel_size / 2 );
388  m_offset_y_hr   :=m_dilation_hr + m_half_height_hr - line_subpixel_size div 2;
389 
390  inc(m_half_height_hr ,line_subpixel_size div 2 );
391 
392  agg_freemem(pointer(m_data ) ,m_dt_sz );
393 
394  m_dt_sz:=(m_width + m_dilation * 2 ) * (m_height + m_dilation * 2 ) * sizeof(rgba8 );
395 
396  agg_getmem(pointer(m_data ) ,m_dt_sz );
397 
398  m_buf.attach(
399   int8u_ptr(m_data ) ,
400   m_width + m_dilation * 2 ,
401   m_height + m_dilation * 2 ,
402   (m_width + m_dilation * 2 ) * sizeof(rgba8 ) );
403 
404  if m_height > 0 then
405   for y:=0 to m_height - 1 do
406    begin
407     d1:=rgba8_ptr(ptrcomp(m_buf.row(y + m_dilation ) ) + m_dilation * sizeof(rgba8 ) );
408 
409     for x:=0 to m_width - 1 do
410      begin
411       d1^:=src.pixel(x ,y );
412 
413       inc(ptrcomp(d1 ) ,sizeof(rgba8 ) );
414 
415      end;
416 
417    end;
418 
419  for y:=0 to m_dilation - 1 do
420   begin
421    d1:=rgba8_ptr(ptrcomp(m_buf.row(m_dilation + m_height + y ) ) + m_dilation * sizeof(rgba8 ) );
422    d2:=rgba8_ptr(ptrcomp(m_buf.row(m_dilation - y - 1 ) ) + m_dilation * sizeof(rgba8 ) );
423 
424    for x:=0 to m_width - 1 do
425     begin
426      d1^.no_color;
427      d2^.no_color;
428 
429      inc(ptrcomp(d1 ) ,sizeof(rgba8 ) );
430      inc(ptrcomp(d2 ) ,sizeof(rgba8 ) );
431 
432     end;
433 
434   end;
435 
436  h:=m_height + m_dilation * 2;
437 
438  for y:=0 to h - 1 do
439   begin
440    s1:=rgba8_ptr(ptrcomp(m_buf.row(y ) ) + m_dilation * sizeof(rgba8 ) );
441    s2:=rgba8_ptr(ptrcomp(m_buf.row(y ) ) + (m_dilation + m_width ) * sizeof(rgba8 ) );
442    d1:=rgba8_ptr(ptrcomp(m_buf.row(y ) ) + (m_dilation + m_width ) * sizeof(rgba8 ) );
443    d2:=rgba8_ptr(ptrcomp(m_buf.row(y ) ) + m_dilation * sizeof(rgba8 ) );
444 
445    for x:=0 to m_dilation - 1 do
446     begin
447      d1^:=s1^;
448 
449      inc(ptrcomp(d1 ) ,sizeof(rgba8 ) );
450      inc(ptrcomp(s1 ) ,sizeof(rgba8 ) );
451      dec(ptrcomp(d2 ) ,sizeof(rgba8 ) );
452      dec(ptrcomp(s2 ) ,sizeof(rgba8 ) );
453 
454      d2^:=s2^;
455 
456     end;
457 
458   end;
459 
460 end;
461 
462 { PATTERN_WIDTH }
line_image_pattern.pattern_widthnull463 function line_image_pattern.pattern_width;
464 begin
465  result:=m_width_hr;
466 
467 end;
468 
469 { LINE_WIDTH }
line_image_pattern.line_widthnull470 function line_image_pattern.line_width;
471 begin
472  result:=m_half_height_hr;
473 
474 end;
475 
476 { PIXEL }
477 procedure line_image_pattern.pixel;
478 begin
479  m_filter.pixel_high_res(
480   m_buf.rows ,
481   p ,
482   x mod m_width_hr + m_dilation_hr ,
483   y + m_offset_y_hr );
484 
485 end;
486 
487 { FILTER }
488 procedure line_image_pattern.filter(filter_ : pattern_filter_ptr );
489 begin
490  m_filter:=filter_;
491 
492 end;
493 
494 { FILTER }
line_image_pattern.filternull495 function line_image_pattern.filter : pattern_filter_ptr;
496 begin
497  result:=m_filter;
498 
499 end;
500 
501 { CONSTRUCT }
502 constructor line_image_pattern_pow2.Construct(filter_ : pattern_filter_ptr );
503 begin
504  inherited Construct(filter_ );
505 
506  m_mask:=0;
507 
508 end;
509 
510 { CONSTRUCT }
511 constructor line_image_pattern_pow2.Construct(filter_ : pattern_filter_ptr; src : pixel_source_ptr );
512 begin
513  inherited Construct(filter_ ,src );
514 
515  create(src );
516 
517 end;
518 
519 { CREATE }
520 procedure line_image_pattern_pow2.create;
521 begin
522  inherited create(src );
523 
524  m_mask:=1;
525 
526  while m_mask < m_width do
527   begin
528    m_mask:=m_mask shl 1;
529    m_mask:=m_mask or 1;
530 
531   end;
532 
533  m_mask:=m_mask shl (line_subpixel_shift - 1 );
534  m_mask:=m_mask or line_subpixel_mask;
535 
536  m_width_hr:=m_mask + 1;
537 
538 end;
539 
540 { PIXEL }
541 procedure line_image_pattern_pow2.pixel;
542 begin
543  m_filter.pixel_high_res(
544   m_buf.rows ,
545   p ,
546   (x and m_mask ) + m_dilation_hr ,
547   y + m_offset_y_hr );
548 
549 end;
550 
551 { CONSTRUCT }
552 constructor distance_interpolator4.Construct;
553 begin
554 end;
555 
556 { CONSTRUCT }
557 constructor distance_interpolator4.Construct(x1 ,y1 ,x2 ,y2 ,sx ,sy ,ex ,ey ,len_ : int; scale : double; x ,y : int );
558 var
559  d : double;
560 
561  dx_ ,dy_ : int;
562 
563 begin
564  m_dx:=x2 - x1;
565  m_dy:=y2 - y1;
566 
567  m_dx_start:=line_mr(sx ) - line_mr(x1 );
568  m_dy_start:=line_mr(sy ) - line_mr(y1 );
569  m_dx_end  :=line_mr(ex ) - line_mr(x2 );
570  m_dy_end  :=line_mr(ey ) - line_mr(y2 );
571 
572  m_dist:=
573   trunc(
574    (x + line_subpixel_size / 2 - x2 ) * m_dy -
575    (y + line_subpixel_size / 2 - y2 ) * m_dx );
576 
577  m_dist_start:=
578   (line_mr(x + line_subpixel_size div 2 ) - line_mr(sx ) ) * m_dy_start -
579   (line_mr(y + line_subpixel_size div 2 ) - line_mr(sy ) ) * m_dx_start;
580 
581  m_dist_end:=
582   (line_mr(x + line_subpixel_size div 2) - line_mr(ex ) ) * m_dy_end -
583   (line_mr(y + line_subpixel_size div 2) - line_mr(ey ) ) * m_dx_end;
584 
585  if scale <> 0 then
586   m_len:=trunc(len_ / scale )
587  else
588   m_len:=0;
589 
590  d:=len_ * scale;
591 
592  if d <> 0 then
593   begin
594    dx_:=trunc(((x2 - x1 ) shl line_subpixel_shift ) / d );
595    dy_:=trunc(((y2 - y1 ) shl line_subpixel_shift ) / d );
596 
597   end
598  else
599   begin
600    dx_:=0;
601    dy_:=0;
602 
603   end;
604 
605  m_dx_pict:=-dy_;
606  m_dy_pict:=dx_;
607 
608  m_dist_pict:=
609   shr_int32(
610    (x + line_subpixel_size div 2 - (x1 - dy_ ) ) * m_dy_pict -
611    (y + line_subpixel_size div 2 - (y1 + dx_ ) ) * m_dx_pict ,line_subpixel_shift );
612 
613  m_dx      :=m_dx shl line_subpixel_shift;
614  m_dy      :=m_dy shl line_subpixel_shift;
615  m_dx_start:=m_dx_start shl line_mr_subpixel_shift;
616  m_dy_start:=m_dy_start shl line_mr_subpixel_shift;
617  m_dx_end  :=m_dx_end shl line_mr_subpixel_shift;
618  m_dy_end  :=m_dy_end shl line_mr_subpixel_shift;
619 
620 end;
621 
622 { INC_X_ }
623 procedure distance_interpolator4.inc_x_;
624 begin
625  inc(m_dist ,m_dy );
626  inc(m_dist_start ,m_dy_start );
627  inc(m_dist_pict ,m_dy_pict );
628  inc(m_dist_end ,m_dy_end );
629 
630 end;
631 
632 { DEC_X_ }
633 procedure distance_interpolator4.dec_x_;
634 begin
635  dec(m_dist ,m_dy );
636  dec(m_dist_start ,m_dy_start );
637  dec(m_dist_pict ,m_dy_pict );
638  dec(m_dist_end ,m_dy_end );
639 
640 end;
641 
642 { INC_Y_ }
643 procedure distance_interpolator4.inc_y_;
644 begin
645  dec(m_dist ,m_dx );
646  dec(m_dist_start ,m_dx_start );
647  dec(m_dist_pict ,m_dx_pict );
648  dec(m_dist_end ,m_dx_end );
649 
650 end;
651 
652 { DEC_Y_ }
653 procedure distance_interpolator4.dec_y_;
654 begin
655  inc(m_dist ,m_dx );
656  inc(m_dist_start ,m_dx_start );
657  inc(m_dist_pict ,m_dx_pict );
658  inc(m_dist_end ,m_dx_end );
659 
660 end;
661 
662 { INC_X }
663 procedure distance_interpolator4.inc_x;
664 begin
665  inc(m_dist ,m_dy );
666  inc(m_dist_start ,m_dy_start );
667  inc(m_dist_pict ,m_dy_pict );
668  inc(m_dist_end ,m_dy_end );
669 
670  if dy_ > 0 then
671   begin
672    dec(m_dist ,m_dx );
673    dec(m_dist_start ,m_dx_start );
674    dec(m_dist_pict ,m_dx_pict );
675    dec(m_dist_end ,m_dx_end );
676 
677   end;
678 
679  if dy_ < 0 then
680   begin
681    inc(m_dist ,m_dx );
682    inc(m_dist_start ,m_dx_start );
683    inc(m_dist_pict ,m_dx_pict );
684    inc(m_dist_end ,m_dx_end );
685 
686   end;
687 
688 end;
689 
690 { DEC_X }
691 procedure distance_interpolator4.dec_x;
692 begin
693  dec(m_dist ,m_dy );
694  dec(m_dist_start ,m_dy_start );
695  dec(m_dist_pict ,m_dy_pict );
696  dec(m_dist_end ,m_dy_end );
697 
698  if dy_ > 0 then
699   begin
700    dec(m_dist ,m_dx );
701    dec(m_dist_start ,m_dx_start );
702    dec(m_dist_pict ,m_dx_pict );
703    dec(m_dist_end ,m_dx_end );
704 
705   end;
706 
707  if dy_ < 0 then
708   begin
709    inc(m_dist ,m_dx );
710    inc(m_dist_start ,m_dx_start );
711    inc(m_dist_pict ,m_dx_pict );
712    inc(m_dist_end ,m_dx_end );
713 
714   end;
715 
716 end;
717 
718 { INC_Y }
719 procedure distance_interpolator4.inc_y;
720 begin
721  dec(m_dist ,m_dx );
722  dec(m_dist_start ,m_dx_start );
723  dec(m_dist_pict ,m_dx_pict );
724  dec(m_dist_end ,m_dx_end );
725 
726  if dx_ > 0 then
727   begin
728    inc(m_dist ,m_dy );
729    inc(m_dist_start ,m_dy_start );
730    inc(m_dist_pict ,m_dy_pict );
731    inc(m_dist_end ,m_dy_end );
732 
733   end;
734 
735  if dx_ < 0 then
736   begin
737    dec(m_dist ,m_dy );
738    dec(m_dist_start ,m_dy_start );
739    dec(m_dist_pict ,m_dy_pict );
740    dec(m_dist_end ,m_dy_end );
741 
742   end;
743 
744 end;
745 
746 { DEC_Y }
747 procedure distance_interpolator4.dec_y;
748 begin
749  inc(m_dist ,m_dx );
750  inc(m_dist_start ,m_dx_start );
751  inc(m_dist_pict ,m_dx_pict );
752  inc(m_dist_end ,m_dx_end );
753 
754  if dx_ > 0 then
755   begin
756    inc(m_dist ,m_dy );
757    inc(m_dist_start ,m_dy_start );
758    inc(m_dist_pict ,m_dy_pict );
759    inc(m_dist_end ,m_dy_end );
760 
761   end;
762 
763  if dx_ < 0 then
764   begin
765    dec(m_dist ,m_dy );
766    dec(m_dist_start ,m_dy_start );
767    dec(m_dist_pict ,m_dy_pict );
768    dec(m_dist_end ,m_dy_end );
769 
770   end;
771 
772 end;
773 
774 { DIST }
distance_interpolator4.distnull775 function distance_interpolator4.dist;
776 begin
777  result:=m_dist;
778 
779 end;
780 
781 { DIST_START }
distance_interpolator4.dist_startnull782 function distance_interpolator4.dist_start;
783 begin
784  result:=m_dist_start;
785 
786 end;
787 
788 { DIST_PICT }
distance_interpolator4.dist_pictnull789 function distance_interpolator4.dist_pict;
790 begin
791  result:=m_dist_pict;
792 
793 end;
794 
795 { DIST_END }
distance_interpolator4.dist_endnull796 function distance_interpolator4.dist_end;
797 begin
798  result:=m_dist_end;
799 
800 end;
801 
802 { DX }
distance_interpolator4.dxnull803 function distance_interpolator4.dx;
804 begin
805  result:=m_dx;
806 
807 end;
808 
809 { DY }
distance_interpolator4.dynull810 function distance_interpolator4.dy;
811 begin
812  result:=m_dy;
813 
814 end;
815 
816 { DX_START }
distance_interpolator4.dx_startnull817 function distance_interpolator4.dx_start;
818 begin
819  result:=m_dx_start;
820 
821 end;
822 
823 { DY_START }
distance_interpolator4.dy_startnull824 function distance_interpolator4.dy_start;
825 begin
826  result:=m_dy_start;
827 
828 end;
829 
830 { DX_PICT }
distance_interpolator4.dx_pictnull831 function distance_interpolator4.dx_pict;
832 begin
833  result:=m_dx_pict;
834 
835 end;
836 
837 { DY_PICT }
distance_interpolator4.dy_pictnull838 function distance_interpolator4.dy_pict;
839 begin
840  result:=m_dy_pict;
841 
842 end;
843 
844 { DX_END }
distance_interpolator4.dx_endnull845 function distance_interpolator4.dx_end;
846 begin
847  result:=m_dx_end;
848 
849 end;
850 
851 { DY_END }
distance_interpolator4.dy_endnull852 function distance_interpolator4.dy_end;
853 begin
854  result:=m_dy_end;
855 
856 end;
857 
858 { LEN }
distance_interpolator4.lennull859 function distance_interpolator4.len;
860 begin
861  result:=m_len;
862 
863 end;
864 
865 { CONSTRUCT }
866 constructor line_interpolator_image.Construct;
867 var
868  i : unsigned;
869 
870  stop ,dist1_start ,dist2_start ,npix ,dx ,dy : int;
871 
872  li : dda2_line_interpolator;
873 
874 begin
875  m_lp:=lp;
876 
877  if lp.vertical then
878   m_li.Construct(line_dbl_hr(lp.x2 - lp.x1 ) ,Abs(lp.y2 - lp.y1 ) )
879  else
880   m_li.Construct(line_dbl_hr(lp.y2 - lp.y1 ) ,Abs(lp.x2 - lp.x1 ) + 1 );
881 
882  m_di.Construct(
883   lp.x1 ,lp.y1 ,lp.x2 ,lp.y2 ,sx ,sy ,ex ,ey ,lp.len ,scale_x ,
884   lp.x1 and not line_subpixel_mask ,
885   lp.y1 and not line_subpixel_mask );
886 
887  m_ren:=ren;
888 
889  m_x:=shr_int32(lp.x1 ,line_subpixel_shift );
890  m_y:=shr_int32(lp.y1 ,line_subpixel_shift );
891 
892  m_old_x:=m_x;
893  m_old_y:=m_y;
894 
895  if lp.vertical then
896   m_count:=Abs(shr_int32(lp.y2 ,line_subpixel_shift ) - m_y )
897  else
898   m_count:=Abs(shr_int32(lp.x2 ,line_subpixel_shift ) - m_x );
899 
900  m_width     :=ren.subpixel_width;
901  m_max_extent:=shr_int32(m_width ,line_subpixel_shift - 2 );
902 
903 try
904  m_start:=pattern_start + (m_max_extent + 2 ) * ren._pattern_width;
905 except
906  m_start:=0 + (m_max_extent + 2 ) * ren._pattern_width;
907 
908 end;
909 
910  m_step :=0;
911 
912  if lp.vertical then
913   li.Construct(0 ,lp.dy shl line_subpixel_shift ,lp.len )
914  else
915   li.Construct(0 ,lp.dx shl line_subpixel_shift ,lp.len );
916 
917  stop:=m_width + line_subpixel_size * 2;
918  i   :=0;
919 
920  while i < max_half_width do
921   begin
922    m_dist_pos[i ]:=li._y;
923 
924    if m_dist_pos[i ] >= stop then
925     break;
926 
927    li.plus_operator;
928 
929    inc(i );
930 
931   end;
932 
933  m_dist_pos[i ]:=$7FFF0000;
934 
935  npix:=1;
936 
937  if lp.vertical then
938   repeat
939    m_li.minus_operator;
940 
941    dec(m_y ,lp.inc_ );
942 
943    m_x:=shr_int32(m_lp.x1 + m_li._y ,line_subpixel_shift );
944 
945    if lp.inc_ > 0 then
946     m_di.dec_y(m_x - m_old_x )
947    else
948     m_di.inc_y(m_x - m_old_x );
949 
950    m_old_x:=m_x;
951 
952    dist1_start:=m_di.dist_start;
953    dist2_start:=dist1_start;
954 
955    dx:=0;
956 
957    if dist1_start < 0 then
958     inc(npix );
959 
960    repeat
961     inc(dist1_start ,m_di.dy_start );
962     dec(dist2_start ,m_di.dy_start );
963 
964     if dist1_start < 0 then
965      inc(npix );
966 
967     if dist2_start < 0 then
968      inc(npix );
969 
970     inc(dx );
971 
972    until m_dist_pos[dx ] > m_width;
973 
974    if npix = 0 then
975     break;
976 
977    npix:=0;
978 
979    dec(m_step );
980 
981   until m_step < -m_max_extent
982  else
983   repeat
984    m_li.minus_operator;
985 
986    dec(m_x ,lp.inc_ );
987 
988    m_y:=shr_int32(m_lp.y1 + m_li._y ,line_subpixel_shift );
989 
990    if lp.inc_ > 0 then
991     m_di.dec_x(m_y - m_old_y )
992    else
993     m_di.inc_x(m_y - m_old_y );
994 
995    m_old_y:=m_y;
996 
997    dist1_start:=m_di.dist_start;
998    dist2_start:=dist1_start;
999 
1000    dy:=0;
1001 
1002    if dist1_start < 0 then
1003     inc(npix );
1004 
1005    repeat
1006     dec(dist1_start ,m_di.dx_start );
1007     inc(dist2_start ,m_di.dx_start );
1008 
1009     if dist1_start < 0 then
1010      inc(npix );
1011 
1012     if dist2_start < 0 then
1013      inc(npix );
1014 
1015     inc(dy );
1016 
1017    until m_dist_pos[dy ] > m_width;
1018 
1019    if npix = 0 then
1020     break;
1021 
1022    npix:=0;
1023 
1024    dec(m_step );
1025 
1026   until m_step < -m_max_extent;
1027 
1028  m_li.adjust_forward;
1029 
1030  dec(m_step ,m_max_extent );
1031 
1032 end;
1033 
1034 { STEP_HOR }
line_interpolator_image.step_hornull1035 function line_interpolator_image.step_hor;
1036 var
1037  s1 ,s2 ,dist_start ,dist_pict ,dist_end ,dy ,dist ,npix : int;
1038 
1039  p0 ,p1 : aggclr_ptr;
1040 
1041 begin
1042  m_li.plus_operator;
1043 
1044  inc(m_x ,m_lp.inc_ );
1045 
1046  m_y:=shr_int32(m_lp.y1 + m_li._y ,line_subpixel_shift );
1047 
1048  if m_lp.inc_ > 0 then
1049   m_di.inc_x(m_y - m_old_y )
1050  else
1051   m_di.dec_x(m_y - m_old_y );
1052 
1053  m_old_y:=m_y;
1054 
1055  s1:=m_di.dist div m_lp.len;
1056  s2:=-s1;
1057 
1058  if m_lp.inc_ < 0 then
1059   s1:=-s1;
1060 
1061  dist_start:=m_di.dist_start;
1062  dist_pict :=m_di.dist_pict + m_start;
1063  dist_end  :=m_di.dist_end;
1064 
1065  p0:=aggclr_ptr(ptrcomp(@m_colors[0 ] ) + (max_half_width + 2 ) * sizeof(aggclr ) );
1066  p1:=p0;
1067 
1068  npix:=0;
1069 
1070  p1.clear;
1071 
1072  if dist_end > 0 then
1073   begin
1074    if dist_start <= 0 then
1075     m_ren.pixel(p1 ,dist_pict ,s2 );
1076 
1077    inc(npix );
1078 
1079   end;
1080 
1081  inc(ptrcomp(p1 ) ,sizeof(aggclr ) );
1082 
1083  dy  :=1;
1084  dist:=m_dist_pos[dy ];
1085 
1086  while dist - s1 <= m_width do
1087   begin
1088    dec(dist_start ,m_di.dx_start );
1089    dec(dist_pict ,m_di.dx_pict );
1090    dec(dist_end ,m_di.dx_end );
1091 
1092    p1.clear();
1093 
1094    if (dist_end > 0 ) and
1095       (dist_start <= 0 ) then
1096     begin
1097      if m_lp.inc_ > 0 then
1098       dist:=-dist;
1099 
1100      m_ren.pixel(p1 ,dist_pict ,s2 - dist );
1101 
1102      inc(npix );
1103 
1104     end;
1105 
1106    inc(ptrcomp(p1 ) ,sizeof(aggclr ) );
1107    inc(dy );
1108 
1109    dist:=m_dist_pos[dy ];
1110 
1111   end;
1112 
1113  dy:=1;
1114 
1115  dist_start:=m_di.dist_start;
1116  dist_pict :=m_di.dist_pict + m_start;
1117  dist_end  :=m_di.dist_end;
1118 
1119  dist:=m_dist_pos[dy ];
1120 
1121  while dist + s1 <= m_width do
1122   begin
1123    inc(dist_start ,m_di.dx_start );
1124    inc(dist_pict ,m_di.dx_pict );
1125    inc(dist_end ,m_di.dx_end );
1126 
1127    dec(ptrcomp(p0 ) ,sizeof(aggclr ) );
1128 
1129    p0.clear;
1130 
1131    if (dist_end > 0 ) and
1132       (dist_start <= 0 ) then
1133     begin
1134      if m_lp.inc_ > 0 then
1135       dist:=-dist;
1136 
1137      m_ren.pixel(p0 ,dist_pict ,s2 + dist );
1138 
1139      inc(npix );
1140 
1141     end;
1142 
1143    inc(dy );
1144 
1145    dist:=m_dist_pos[dy ];
1146 
1147   end;
1148 
1149  m_ren.blend_color_vspan(
1150   m_x ,m_y - dy + 1 ,
1151   unsigned((ptrcomp(p1 ) - ptrcomp(p0 ) ) div sizeof(aggclr ) ) ,
1152   p0 );
1153 
1154  inc(m_step );
1155 
1156  result:=
1157   (npix <> 0 ) and
1158   (m_step < m_count );
1159 
1160 end;
1161 
1162 { STEP_VER }
line_interpolator_image.step_vernull1163 function line_interpolator_image.step_ver;
1164 var
1165  s1 ,s2 ,dist_start ,dist_pict ,dist_end ,dx ,dist ,npix : int;
1166 
1167  p0 ,p1 : aggclr_ptr;
1168 
1169 begin
1170  m_li.plus_operator;
1171 
1172  inc(m_y ,m_lp.inc_ );
1173 
1174  m_x:=shr_int32(m_lp.x1 + m_li._y ,line_subpixel_shift );
1175 
1176  if m_lp.inc_ > 0 then
1177   m_di.inc_y(m_x - m_old_x )
1178  else
1179   m_di.dec_y(m_x - m_old_x );
1180 
1181  m_old_x:=m_x;
1182 
1183  s1:=m_di.dist div  m_lp.len;
1184  s2:=-s1;
1185 
1186  if m_lp.inc_ > 0 then
1187   s1:=-s1;
1188 
1189  dist_start:=m_di.dist_start;
1190  dist_pict :=m_di.dist_pict + m_start;
1191  dist_end  :=m_di.dist_end;
1192 
1193  p0:=aggclr_ptr(ptrcomp(@m_colors[0 ] ) + (max_half_width + 2 ) * sizeof(aggclr ) );
1194  p1:=p0;
1195 
1196  npix:=0;
1197 
1198  p1.clear;
1199 
1200  if dist_end > 0 then
1201   begin
1202    if dist_start <= 0 then
1203     m_ren.pixel(p1 ,dist_pict ,s2 );
1204 
1205    inc(npix );
1206 
1207   end;
1208 
1209  inc(ptrcomp(p1 ) ,sizeof(aggclr ) );
1210 
1211  dx  :=1;
1212  dist:=m_dist_pos[dx ];
1213 
1214  while dist - s1 <= m_width do
1215   begin
1216    inc(dist_start ,m_di.dy_start );
1217    inc(dist_pict ,m_di.dy_pict );
1218    inc(dist_end ,m_di.dy_end );
1219 
1220    p1.clear;
1221 
1222    if (dist_end > 0 ) and
1223       (dist_start <= 0 ) then
1224     begin
1225      if m_lp.inc_ > 0 then
1226       dist:=-dist;
1227 
1228      m_ren.pixel(p1 ,dist_pict ,s2 + dist );
1229 
1230      inc(npix );
1231 
1232     end;
1233 
1234    inc(ptrcomp(p1 ) ,sizeof(aggclr ) );
1235    inc(dx );
1236 
1237    dist:=m_dist_pos[dx ];
1238 
1239   end;
1240 
1241  dx:=1;
1242 
1243  dist_start:=m_di.dist_start;
1244  dist_pict :=m_di.dist_pict + m_start;
1245  dist_end  :=m_di.dist_end;
1246 
1247  dist:=m_dist_pos[dx ];
1248 
1249  while dist + s1 <= m_width do
1250   begin
1251    dec(dist_start ,m_di.dy_start );
1252    dec(dist_pict ,m_di.dy_pict );
1253    dec(dist_end ,m_di.dy_end );
1254 
1255    dec(ptrcomp(p0 ) ,sizeof(aggclr ) );
1256 
1257    p0.clear;
1258 
1259    if (dist_end > 0 ) and
1260       (dist_start <= 0 ) then
1261     begin
1262      if m_lp.inc_ > 0 then
1263       dist:=-dist;
1264 
1265      m_ren.pixel(p0 ,dist_pict ,s2 - dist );
1266 
1267      inc(npix );
1268 
1269     end;
1270 
1271    inc(dx );
1272 
1273    dist:=m_dist_pos[dx ];
1274 
1275   end;
1276 
1277  m_ren.blend_color_hspan(
1278   m_x - dx + 1 ,m_y ,
1279   unsigned((ptrcomp(p1 ) - ptrcomp(p0 ) ) div sizeof(aggclr ) ) ,
1280   p0 );
1281 
1282  inc(m_step );
1283 
1284  result:=
1285   (npix <> 0 ) and
1286   (m_step < m_count );
1287 
1288 end;
1289 
1290 { PATTERN_END }
line_interpolator_image.pattern_endnull1291 function line_interpolator_image.pattern_end;
1292 begin
1293  result:=m_start + m_di.len;
1294 
1295 end;
1296 
1297 { VERTICAL }
line_interpolator_image.verticalnull1298 function line_interpolator_image.vertical;
1299 begin
1300  result:=m_lp.vertical;
1301 
1302 end;
1303 
1304 { WIDTH }
line_interpolator_image.widthnull1305 function line_interpolator_image.width;
1306 begin
1307  result:=m_width;
1308 
1309 end;
1310 
1311 { COUNT }
line_interpolator_image.countnull1312 function line_interpolator_image.count;
1313 begin
1314  result:=m_count;
1315 
1316 end;
1317 
1318 { CONSTRUCT }
1319 constructor renderer_outline_image.Construct;
1320 begin
1321  m_ren    :=ren;
1322  m_pattern:=patt;
1323  m_start  :=0;
1324  m_scale_x:=1.0;
1325 
1326 end;
1327 
1328 { PATTERN_ }
1329 procedure renderer_outline_image.pattern_;
1330 begin
1331  m_pattern:=p;
1332 
1333 end;
1334 
1335 { _PATTERN }
renderer_outline_image._patternnull1336 function renderer_outline_image._pattern;
1337 begin
1338  result:=m_pattern;
1339 
1340 end;
1341 
1342 { SCALE_X_ }
1343 procedure renderer_outline_image.scale_x_;
1344 begin
1345  m_scale_x:=s;
1346 
1347 end;
1348 
1349 { _SCALE_X }
renderer_outline_image._scale_xnull1350 function renderer_outline_image._scale_x;
1351 begin
1352  result:=m_scale_x;
1353 
1354 end;
1355 
1356 { START_X_ }
1357 procedure renderer_outline_image.start_x_;
1358 begin
1359  m_start:=trunc(s * line_subpixel_size );
1360 
1361 end;
1362 
1363 { _START_X }
renderer_outline_image._start_xnull1364 function renderer_outline_image._start_x;
1365 begin
1366  result:=m_start / line_subpixel_size;
1367 
1368 end;
1369 
1370 { SUBPIXEL_WIDTH }
renderer_outline_image.subpixel_widthnull1371 function renderer_outline_image.subpixel_width;
1372 begin
1373  result:=m_pattern.line_width;
1374 
1375 end;
1376 
1377 { _PATTERN_WIDTH }
renderer_outline_image._pattern_widthnull1378 function renderer_outline_image._pattern_width;
1379 begin
1380  result:=m_pattern.pattern_width;
1381 
1382 end;
1383 
1384 { PIXEL }
1385 procedure renderer_outline_image.pixel;
1386 begin
1387  m_pattern.pixel(p ,x ,y );
1388 
1389 end;
1390 
1391 { BLEND_COLOR_HSPAN }
1392 procedure renderer_outline_image.blend_color_hspan;
1393 begin
1394  m_ren.blend_color_hspan(x ,y ,len ,colors ,NIL );
1395 
1396 end;
1397 
1398 { BLEND_COLOR_VSPAN }
1399 procedure renderer_outline_image.blend_color_vspan;
1400 begin
1401  m_ren.blend_color_vspan(x ,y ,len ,colors ,NIL );
1402 
1403 end;
1404 
1405 { ACCURATE_JOIN_ONLY }
renderer_outline_image.accurate_join_onlynull1406 function renderer_outline_image.accurate_join_only;
1407 begin
1408  result:=true;
1409 
1410 end;
1411 
1412 { SEMIDOT }
1413 procedure renderer_outline_image.semidot;
1414 begin
1415 end;
1416 
1417 { LINE0 }
1418 procedure renderer_outline_image.line0;
1419 begin
1420 end;
1421 
1422 { LINE1 }
1423 procedure renderer_outline_image.line1;
1424 begin
1425 end;
1426 
1427 { LINE2 }
1428 procedure renderer_outline_image.line2;
1429 begin
1430 end;
1431 
1432 { LINE3 }
1433 procedure renderer_outline_image.line3;
1434 var
1435  li : line_interpolator_image;
1436 
1437 begin
1438  fix_degenerate_bisectrix_start(lp ,@sx ,@sy );
1439  fix_degenerate_bisectrix_end  (lp ,@ex ,@ey );
1440 
1441  li.Construct(@self ,lp ,sx ,sy ,ex ,ey ,m_start ,m_scale_x );
1442 
1443  if li.vertical then
1444   while li.step_ver do
1445  else
1446   while li.step_hor do;
1447 
1448  m_start:=li.pattern_end;
1449 
1450 end;
1451 
1452 END.
1453 
1454