1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 #ifndef AGG_RENDERER_OUTLINE_IMAGE_INCLUDED
16 #define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED
19 #include "agg_line_aa_basics.h"
20 #include "agg_dda_line.h"
21 #include "agg_rendering_buffer.h"
26 //========================================================line_image_scale
27 template<class Source
> class line_image_scale
30 typedef typename
Source::color_type color_type
;
32 line_image_scale(const Source
& src
, double height
) :
35 m_scale(src
.height() / height
)
39 double width() const { return m_source
.width(); }
40 double height() const { return m_height
; }
42 color_type
pixel(int x
, int y
) const
44 double src_y
= (y
+ 0.5) * m_scale
- 0.5;
45 int h
= int(m_source
.height()) - 1;
46 int y1
= int(floor(src_y
));
48 color_type pix1
= (y1
< 0) ? color_type::no_color() : m_source
.pixel(x
, y1
);
49 color_type pix2
= (y2
> h
) ? color_type::no_color() : m_source
.pixel(x
, y2
);
50 return pix1
.gradient(pix2
, src_y
- y1
);
54 line_image_scale(const line_image_scale
<Source
>&);
55 const line_image_scale
<Source
>& operator = (const line_image_scale
<Source
>&);
57 const Source
& m_source
;
64 //======================================================line_image_pattern
65 template<class Filter
> class line_image_pattern
68 typedef Filter filter_type
;
69 typedef typename
filter_type::color_type color_type
;
71 //--------------------------------------------------------------------
77 //--------------------------------------------------------------------
78 line_image_pattern(const Filter
& filter
) :
80 m_dilation(filter
.dilation() + 1),
81 m_dilation_hr(m_dilation
<< line_subpixel_shift
),
92 //--------------------------------------------------------------------
93 template<class Source
>
94 line_image_pattern(const Filter
& filter
, const Source
& src
) :
96 m_dilation(filter
.dilation() + 1),
97 m_dilation_hr(m_dilation
<< line_subpixel_shift
),
109 //--------------------------------------------------------------------
110 template<class Source
> void create(const Source
& src
)
112 m_height
= unsigned(ceil((double)src
.height()));
113 m_width
= unsigned(ceil((double)src
.width()));
114 m_width_hr
= int(src
.width() * line_subpixel_size
);
115 m_half_height_hr
= int(src
.height() * line_subpixel_size
/2);
116 m_offset_y_hr
= m_dilation_hr
+ m_half_height_hr
- line_subpixel_size
/2;
117 m_half_height_hr
+= line_subpixel_size
/2;
120 m_data
= new color_type
[(m_width
+ m_dilation
* 2) * (m_height
+ m_dilation
* 2)];
122 m_buf
.attach(m_data
, m_width
+ m_dilation
* 2,
123 m_height
+ m_dilation
* 2,
124 m_width
+ m_dilation
* 2);
128 for(y
= 0; y
< m_height
; y
++)
130 d1
= m_buf
.row(y
+ m_dilation
) + m_dilation
;
131 for(x
= 0; x
< m_width
; x
++)
133 *d1
++ = src
.pixel(x
, y
);
137 const color_type
* s1
;
138 const color_type
* s2
;
139 for(y
= 0; y
< m_dilation
; y
++)
141 //s1 = m_buf.row(m_height + m_dilation - 1) + m_dilation;
142 //s2 = m_buf.row(m_dilation) + m_dilation;
143 d1
= m_buf
.row(m_dilation
+ m_height
+ y
) + m_dilation
;
144 d2
= m_buf
.row(m_dilation
- y
- 1) + m_dilation
;
145 for(x
= 0; x
< m_width
; x
++)
147 //*d1++ = color_type(*s1++, 0);
148 //*d2++ = color_type(*s2++, 0);
149 *d1
++ = color_type::no_color();
150 *d2
++ = color_type::no_color();
154 unsigned h
= m_height
+ m_dilation
* 2;
155 for(y
= 0; y
< h
; y
++)
157 s1
= m_buf
.row(y
) + m_dilation
;
158 s2
= m_buf
.row(y
) + m_dilation
+ m_width
;
159 d1
= m_buf
.row(y
) + m_dilation
+ m_width
;
160 d2
= m_buf
.row(y
) + m_dilation
;
162 for(x
= 0; x
< m_dilation
; x
++)
170 //--------------------------------------------------------------------
171 int pattern_width() const { return m_width_hr
; }
172 int line_width() const { return m_half_height_hr
; }
174 //--------------------------------------------------------------------
175 void pixel(color_type
* p
, int x
, int y
) const
177 m_filter
->pixel_high_res(m_buf
.rows(),
179 x
% m_width_hr
+ m_dilation_hr
,
183 //--------------------------------------------------------------------
184 const filter_type
& filter() const { return *m_filter
; }
187 line_image_pattern(const line_image_pattern
<filter_type
>&);
188 const line_image_pattern
<filter_type
>&
189 operator = (const line_image_pattern
<filter_type
>&);
192 row_ptr_cache
<color_type
> m_buf
;
193 const filter_type
* m_filter
;
200 int m_half_height_hr
;
209 //=================================================line_image_pattern_pow2
210 template<class Filter
> class line_image_pattern_pow2
:
211 public line_image_pattern
<Filter
>
214 typedef Filter filter_type
;
215 typedef typename
filter_type::color_type color_type
;
216 typedef line_image_pattern
<Filter
> base_type
;
218 //--------------------------------------------------------------------
219 line_image_pattern_pow2(const Filter
& filter
) :
220 line_image_pattern
<Filter
>(filter
), m_mask(line_subpixel_mask
) {}
222 //--------------------------------------------------------------------
223 template<class Source
>
224 line_image_pattern_pow2(const Filter
& filter
, const Source
& src
) :
225 line_image_pattern
<Filter
>(filter
), m_mask(line_subpixel_mask
)
230 //--------------------------------------------------------------------
231 template<class Source
> void create(const Source
& src
)
233 line_image_pattern
<Filter
>::create(src
);
235 while(m_mask
< base_type::m_width
)
240 m_mask
<<= line_subpixel_shift
- 1;
241 m_mask
|= line_subpixel_mask
;
242 base_type::m_width_hr
= m_mask
+ 1;
245 //--------------------------------------------------------------------
246 void pixel(color_type
* p
, int x
, int y
) const
248 base_type::m_filter
->pixel_high_res(
249 base_type::m_buf
.rows(),
251 (x
& m_mask
) + base_type::m_dilation_hr
,
252 y
+ base_type::m_offset_y_hr
);
264 //===================================================distance_interpolator4
265 class distance_interpolator4
268 //---------------------------------------------------------------------
269 distance_interpolator4() {}
270 distance_interpolator4(int x1
, int y1
, int x2
, int y2
,
271 int sx
, int sy
, int ex
, int ey
,
272 int len
, double scale
, int x
, int y
) :
275 m_dx_start(line_mr(sx
) - line_mr(x1
)),
276 m_dy_start(line_mr(sy
) - line_mr(y1
)),
277 m_dx_end(line_mr(ex
) - line_mr(x2
)),
278 m_dy_end(line_mr(ey
) - line_mr(y2
)),
280 m_dist(int(double(x
+ line_subpixel_size
/2 - x2
) * double(m_dy
) -
281 double(y
+ line_subpixel_size
/2 - y2
) * double(m_dx
))),
283 m_dist_start((line_mr(x
+ line_subpixel_size
/2) - line_mr(sx
)) * m_dy_start
-
284 (line_mr(y
+ line_subpixel_size
/2) - line_mr(sy
)) * m_dx_start
),
286 m_dist_end((line_mr(x
+ line_subpixel_size
/2) - line_mr(ex
)) * m_dy_end
-
287 (line_mr(y
+ line_subpixel_size
/2) - line_mr(ey
)) * m_dx_end
),
288 m_len(int(len
/ scale
))
290 double d
= len
* scale
;
291 int dx
= int(((x2
- x1
) << line_subpixel_shift
) / d
);
292 int dy
= int(((y2
- y1
) << line_subpixel_shift
) / d
);
295 m_dist_pict
= ((x
+ line_subpixel_size
/2 - (x1
- dy
)) * m_dy_pict
-
296 (y
+ line_subpixel_size
/2 - (y1
+ dx
)) * m_dx_pict
) >>
299 m_dx
<<= line_subpixel_shift
;
300 m_dy
<<= line_subpixel_shift
;
301 m_dx_start
<<= line_mr_subpixel_shift
;
302 m_dy_start
<<= line_mr_subpixel_shift
;
303 m_dx_end
<<= line_mr_subpixel_shift
;
304 m_dy_end
<<= line_mr_subpixel_shift
;
307 //---------------------------------------------------------------------
311 m_dist_start
+= m_dy_start
;
312 m_dist_pict
+= m_dy_pict
;
313 m_dist_end
+= m_dy_end
;
316 //---------------------------------------------------------------------
320 m_dist_start
-= m_dy_start
;
321 m_dist_pict
-= m_dy_pict
;
322 m_dist_end
-= m_dy_end
;
325 //---------------------------------------------------------------------
329 m_dist_start
-= m_dx_start
;
330 m_dist_pict
-= m_dx_pict
;
331 m_dist_end
-= m_dx_end
;
334 //---------------------------------------------------------------------
338 m_dist_start
+= m_dx_start
;
339 m_dist_pict
+= m_dx_pict
;
340 m_dist_end
+= m_dx_end
;
343 //---------------------------------------------------------------------
347 m_dist_start
+= m_dy_start
;
348 m_dist_pict
+= m_dy_pict
;
349 m_dist_end
+= m_dy_end
;
353 m_dist_start
-= m_dx_start
;
354 m_dist_pict
-= m_dx_pict
;
355 m_dist_end
-= m_dx_end
;
360 m_dist_start
+= m_dx_start
;
361 m_dist_pict
+= m_dx_pict
;
362 m_dist_end
+= m_dx_end
;
366 //---------------------------------------------------------------------
370 m_dist_start
-= m_dy_start
;
371 m_dist_pict
-= m_dy_pict
;
372 m_dist_end
-= m_dy_end
;
376 m_dist_start
-= m_dx_start
;
377 m_dist_pict
-= m_dx_pict
;
378 m_dist_end
-= m_dx_end
;
383 m_dist_start
+= m_dx_start
;
384 m_dist_pict
+= m_dx_pict
;
385 m_dist_end
+= m_dx_end
;
389 //---------------------------------------------------------------------
393 m_dist_start
-= m_dx_start
;
394 m_dist_pict
-= m_dx_pict
;
395 m_dist_end
-= m_dx_end
;
399 m_dist_start
+= m_dy_start
;
400 m_dist_pict
+= m_dy_pict
;
401 m_dist_end
+= m_dy_end
;
406 m_dist_start
-= m_dy_start
;
407 m_dist_pict
-= m_dy_pict
;
408 m_dist_end
-= m_dy_end
;
412 //---------------------------------------------------------------------
416 m_dist_start
+= m_dx_start
;
417 m_dist_pict
+= m_dx_pict
;
418 m_dist_end
+= m_dx_end
;
422 m_dist_start
+= m_dy_start
;
423 m_dist_pict
+= m_dy_pict
;
424 m_dist_end
+= m_dy_end
;
429 m_dist_start
-= m_dy_start
;
430 m_dist_pict
-= m_dy_pict
;
431 m_dist_end
-= m_dy_end
;
435 //---------------------------------------------------------------------
436 int dist() const { return m_dist
; }
437 int dist_start() const { return m_dist_start
; }
438 int dist_pict() const { return m_dist_pict
; }
439 int dist_end() const { return m_dist_end
; }
441 //---------------------------------------------------------------------
442 int dx() const { return m_dx
; }
443 int dy() const { return m_dy
; }
444 int dx_start() const { return m_dx_start
; }
445 int dy_start() const { return m_dy_start
; }
446 int dx_pict() const { return m_dx_pict
; }
447 int dy_pict() const { return m_dy_pict
; }
448 int dx_end() const { return m_dx_end
; }
449 int dy_end() const { return m_dy_end
; }
450 int len() const { return m_len
; }
453 //---------------------------------------------------------------------
474 //==================================================line_interpolator_image
475 template<class Renderer
> class line_interpolator_image
478 typedef Renderer renderer_type
;
479 typedef typename
Renderer::color_type color_type
;
481 //---------------------------------------------------------------------
487 //---------------------------------------------------------------------
488 line_interpolator_image(renderer_type
& ren
, const line_parameters
& lp
,
489 int sx
, int sy
, int ex
, int ey
,
493 m_li(lp
.vertical
? line_dbl_hr(lp
.x2
- lp
.x1
) :
494 line_dbl_hr(lp
.y2
- lp
.y1
),
495 lp
.vertical
? abs(lp
.y2
- lp
.y1
) :
496 abs(lp
.x2
- lp
.x1
) + 1),
497 m_di(lp
.x1
, lp
.y1
, lp
.x2
, lp
.y2
, sx
, sy
, ex
, ey
, lp
.len
, scale_x
,
498 lp
.x1
& ~line_subpixel_mask
, lp
.y1
& ~line_subpixel_mask
),
500 m_x(lp
.x1
>> line_subpixel_shift
),
501 m_y(lp
.y1
>> line_subpixel_shift
),
504 m_count((lp
.vertical
? abs((lp
.y2
>> line_subpixel_shift
) - m_y
) :
505 abs((lp
.x2
>> line_subpixel_shift
) - m_x
))),
506 m_width(ren
.subpixel_width()),
507 m_max_extent(m_width
>> (line_subpixel_shift
- 2)),
508 m_start(pattern_start
+ (m_max_extent
+ 2) * ren
.pattern_width()),
511 agg::dda2_line_interpolator
li(0, lp
.vertical
?
512 (lp
.dy
<< agg::line_subpixel_shift
) :
513 (lp
.dx
<< agg::line_subpixel_shift
),
517 int stop
= m_width
+ line_subpixel_size
* 2;
518 for(i
= 0; i
< max_half_width
; ++i
)
520 m_dist_pos
[i
] = li
.y();
521 if(m_dist_pos
[i
] >= stop
) break;
524 m_dist_pos
[i
] = 0x7FFF0000;
536 m_x
= (m_lp
.x1
+ m_li
.y()) >> line_subpixel_shift
;
538 if(lp
.inc
> 0) m_di
.dec_y(m_x
- m_old_x
);
539 else m_di
.inc_y(m_x
- m_old_x
);
543 dist1_start
= dist2_start
= m_di
.dist_start();
546 if(dist1_start
< 0) ++npix
;
549 dist1_start
+= m_di
.dy_start();
550 dist2_start
-= m_di
.dy_start();
551 if(dist1_start
< 0) ++npix
;
552 if(dist2_start
< 0) ++npix
;
555 while(m_dist_pos
[dx
] <= m_width
);
560 while(--m_step
>= -m_max_extent
);
569 m_y
= (m_lp
.y1
+ m_li
.y()) >> line_subpixel_shift
;
571 if(lp
.inc
> 0) m_di
.dec_x(m_y
- m_old_y
);
572 else m_di
.inc_x(m_y
- m_old_y
);
576 dist1_start
= dist2_start
= m_di
.dist_start();
579 if(dist1_start
< 0) ++npix
;
582 dist1_start
-= m_di
.dx_start();
583 dist2_start
+= m_di
.dx_start();
584 if(dist1_start
< 0) ++npix
;
585 if(dist2_start
< 0) ++npix
;
588 while(m_dist_pos
[dy
] <= m_width
);
593 while(--m_step
>= -m_max_extent
);
595 m_li
.adjust_forward();
596 m_step
-= m_max_extent
;
599 //---------------------------------------------------------------------
604 m_y
= (m_lp
.y1
+ m_li
.y()) >> line_subpixel_shift
;
606 if(m_lp
.inc
> 0) m_di
.inc_x(m_y
- m_old_y
);
607 else m_di
.dec_x(m_y
- m_old_y
);
611 int s1
= m_di
.dist() / m_lp
.len
;
614 if(m_lp
.inc
< 0) s1
= -s1
;
622 dist_start
= m_di
.dist_start();
623 dist_pict
= m_di
.dist_pict() + m_start
;
624 dist_end
= m_di
.dist_end();
625 color_type
* p0
= m_colors
+ max_half_width
+ 2;
634 m_ren
.pixel(p1
, dist_pict
, s2
);
641 while((dist
= m_dist_pos
[dy
]) - s1
<= m_width
)
643 dist_start
-= m_di
.dx_start();
644 dist_pict
-= m_di
.dx_pict();
645 dist_end
-= m_di
.dx_end();
647 if(dist_end
> 0 && dist_start
<= 0)
649 if(m_lp
.inc
> 0) dist
= -dist
;
650 m_ren
.pixel(p1
, dist_pict
, s2
- dist
);
658 dist_start
= m_di
.dist_start();
659 dist_pict
= m_di
.dist_pict() + m_start
;
660 dist_end
= m_di
.dist_end();
661 while((dist
= m_dist_pos
[dy
]) + s1
<= m_width
)
663 dist_start
+= m_di
.dx_start();
664 dist_pict
+= m_di
.dx_pict();
665 dist_end
+= m_di
.dx_end();
668 if(dist_end
> 0 && dist_start
<= 0)
670 if(m_lp
.inc
> 0) dist
= -dist
;
671 m_ren
.pixel(p0
, dist_pict
, s2
+ dist
);
676 m_ren
.blend_color_vspan(m_x
,
680 return npix
&& ++m_step
< m_count
;
685 //---------------------------------------------------------------------
690 m_x
= (m_lp
.x1
+ m_li
.y()) >> line_subpixel_shift
;
692 if(m_lp
.inc
> 0) m_di
.inc_y(m_x
- m_old_x
);
693 else m_di
.dec_y(m_x
- m_old_x
);
697 int s1
= m_di
.dist() / m_lp
.len
;
700 if(m_lp
.inc
> 0) s1
= -s1
;
708 dist_start
= m_di
.dist_start();
709 dist_pict
= m_di
.dist_pict() + m_start
;
710 dist_end
= m_di
.dist_end();
711 color_type
* p0
= m_colors
+ max_half_width
+ 2;
720 m_ren
.pixel(p1
, dist_pict
, s2
);
727 while((dist
= m_dist_pos
[dx
]) - s1
<= m_width
)
729 dist_start
+= m_di
.dy_start();
730 dist_pict
+= m_di
.dy_pict();
731 dist_end
+= m_di
.dy_end();
733 if(dist_end
> 0 && dist_start
<= 0)
735 if(m_lp
.inc
> 0) dist
= -dist
;
736 m_ren
.pixel(p1
, dist_pict
, s2
+ dist
);
744 dist_start
= m_di
.dist_start();
745 dist_pict
= m_di
.dist_pict() + m_start
;
746 dist_end
= m_di
.dist_end();
747 while((dist
= m_dist_pos
[dx
]) + s1
<= m_width
)
749 dist_start
-= m_di
.dy_start();
750 dist_pict
-= m_di
.dy_pict();
751 dist_end
-= m_di
.dy_end();
754 if(dist_end
> 0 && dist_start
<= 0)
756 if(m_lp
.inc
> 0) dist
= -dist
;
757 m_ren
.pixel(p0
, dist_pict
, s2
- dist
);
762 m_ren
.blend_color_hspan(m_x
- dx
+ 1,
766 return npix
&& ++m_step
< m_count
;
770 //---------------------------------------------------------------------
771 int pattern_end() const { return m_start
+ m_di
.len(); }
773 //---------------------------------------------------------------------
774 bool vertical() const { return m_lp
.vertical
; }
775 int width() const { return m_width
; }
776 int count() const { return m_count
; }
779 line_interpolator_image(const line_interpolator_image
<Renderer
>&);
780 const line_interpolator_image
<Renderer
>&
781 operator = (const line_interpolator_image
<Renderer
>&);
784 const line_parameters
& m_lp
;
785 dda2_line_interpolator m_li
;
786 distance_interpolator4 m_di
;
787 renderer_type
& m_ren
;
798 int m_dist_pos
[max_half_width
+ 1];
799 color_type m_colors
[max_half_width
* 2 + 4];
809 //===================================================renderer_outline_image
810 template<class BaseRenderer
, class ImagePattern
>
811 class renderer_outline_image
814 //---------------------------------------------------------------------
815 typedef BaseRenderer base_ren_type
;
816 typedef renderer_outline_image
<BaseRenderer
, ImagePattern
> self_type
;
817 typedef typename
base_ren_type::color_type color_type
;
818 typedef ImagePattern pattern_type
;
821 //---------------------------------------------------------------------
822 renderer_outline_image(base_ren_type
& ren
, const pattern_type
& patt
) :
830 //---------------------------------------------------------------------
831 void pattern(const pattern_type
& p
) { m_pattern
= &p
; }
832 const pattern_type
& pattern() const { return *m_pattern
; }
834 //---------------------------------------------------------------------
835 void scale_x(double s
) { m_scale_x
= s
; }
836 double scale_x() const { return m_scale_x
; }
838 //---------------------------------------------------------------------
839 void start_x(double s
) { m_start
= int(s
* line_subpixel_size
); }
840 double start_x() const { return double(m_start
) / line_subpixel_size
; }
842 //---------------------------------------------------------------------
843 int subpixel_width() const { return m_pattern
->line_width(); }
844 int pattern_width() const { return m_pattern
->pattern_width(); }
846 //-------------------------------------------------------------------------
847 void pixel(color_type
* p
, int x
, int y
) const
849 m_pattern
->pixel(p
, x
, y
);
852 //-------------------------------------------------------------------------
853 void blend_color_hspan(int x
, int y
, unsigned len
, const color_type
* colors
)
855 m_ren
->blend_color_hspan(x
, y
, len
, colors
, 0);
858 //-------------------------------------------------------------------------
859 void blend_color_vspan(int x
, int y
, unsigned len
, const color_type
* colors
)
861 m_ren
->blend_color_vspan(x
, y
, len
, colors
, 0);
864 //-------------------------------------------------------------------------
865 static bool accurate_join_only() { return true; }
867 //-------------------------------------------------------------------------
869 void semidot(Cmp
, int, int, int, int)
873 //-------------------------------------------------------------------------
874 void line0(const line_parameters
&)
878 //-------------------------------------------------------------------------
879 void line1(const line_parameters
&, int, int)
883 //-------------------------------------------------------------------------
884 void line2(const line_parameters
&, int, int)
888 //-------------------------------------------------------------------------
889 void line3(const line_parameters
& lp
,
890 int sx
, int sy
, int ex
, int ey
)
892 fix_degenerate_bisectrix_start(lp
, &sx
, &sy
);
893 fix_degenerate_bisectrix_end(lp
, &ex
, &ey
);
894 line_interpolator_image
<self_type
> li(*this, lp
,
900 while(li
.step_ver());
904 while(li
.step_hor());
906 m_start
= li
.pattern_end();
910 base_ren_type
* m_ren
;
911 const pattern_type
* m_pattern
;