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_RASTERIZER_OUTLINE_AA_INCLUDED
16 #define AGG_RASTERIZER_OUTLINE_AA_INCLUDED
18 #include "agg_basics.h"
19 #include "agg_line_aa_basics.h"
20 #include "agg_vertex_sequence.h"
25 //-------------------------------------------------------------------------
26 inline bool cmp_dist_start(int d
) { return d
> 0; }
27 inline bool cmp_dist_end(int d
) { return d
<= 0; }
31 //-----------------------------------------------------------line_aa_vertex
32 // Vertex (x, y) with the distance to the next one. The last vertex has
33 // the distance between the last and the first points
41 line_aa_vertex(int x_
, int y_
) :
48 bool operator () (const line_aa_vertex
& val
)
50 double dx
= val
.x
- x
;
51 double dy
= val
.y
- y
;
52 return (len
= int(sqrt(dx
* dx
+ dy
* dy
))) >
53 (line_subpixel_size
+ line_subpixel_size
/ 2);
60 //=======================================================rasterizer_outline_aa
61 template<class Renderer
> class rasterizer_outline_aa
64 //------------------------------------------------------------------------
69 line_parameters curr
, next
;
71 int xb1
, yb1
, xb2
, yb2
;
75 void draw(draw_vars
& dv
, unsigned start
, unsigned end
);
78 typedef line_aa_vertex vertex_type
;
79 typedef vertex_sequence
<vertex_type
, 6> vertex_storage_type
;
81 rasterizer_outline_aa(Renderer
& ren
) :
83 m_accurate_join(m_ren
.accurate_join_only()),
90 //------------------------------------------------------------------------
91 void accurate_join(bool v
)
93 m_accurate_join
= m_ren
.accurate_join_only() ? true : v
;
95 bool accurate_join() const { return m_accurate_join
; }
97 //------------------------------------------------------------------------
98 void round_cap(bool v
) { m_round_cap
= v
; }
99 bool round_cap() const { return m_round_cap
; }
101 //------------------------------------------------------------------------
102 void move_to(int x
, int y
)
104 m_src_vertices
.modify_last(vertex_type(m_start_x
= x
, m_start_y
= y
));
107 //------------------------------------------------------------------------
108 void line_to(int x
, int y
)
110 m_src_vertices
.add(vertex_type(x
, y
));
113 //------------------------------------------------------------------------
114 void move_to_d(double x
, double y
)
116 move_to(line_coord(x
), line_coord(y
));
119 //------------------------------------------------------------------------
120 void line_to_d(double x
, double y
)
122 line_to(line_coord(x
), line_coord(y
));
125 //------------------------------------------------------------------------
126 void render(bool close_polygon
);
128 //------------------------------------------------------------------------
129 void add_vertex(double x
, double y
, unsigned cmd
)
140 render(is_closed(cmd
));
143 move_to(m_start_x
, m_start_y
);
153 //------------------------------------------------------------------------
154 template<class VertexSource
>
155 void add_path(VertexSource
& vs
, unsigned id
=0)
162 while(!is_stop(cmd
= vs
.vertex(&x
, &y
)))
164 add_vertex(x
, y
, cmd
);
170 //------------------------------------------------------------------------
171 template<class VertexSource
, class ColorStorage
, class PathId
>
172 void render_all_paths(VertexSource
& vs
,
173 const ColorStorage
& colors
,
177 for(unsigned i
= 0; i
< num_paths
; i
++)
179 m_ren
.color(colors
[i
]);
185 //------------------------------------------------------------------------
186 template<class Ctrl
> void render_ctrl(Ctrl
& c
)
189 for(i
= 0; i
< c
.num_paths(); i
++)
191 m_ren
.color(c
.color(i
));
197 rasterizer_outline_aa(const rasterizer_outline_aa
<Renderer
>&);
198 const rasterizer_outline_aa
<Renderer
>& operator =
199 (const rasterizer_outline_aa
<Renderer
>&);
202 vertex_storage_type m_src_vertices
;
203 bool m_accurate_join
;
216 //----------------------------------------------------------------------------
217 template<class Renderer
>
218 void rasterizer_outline_aa
<Renderer
>::draw(draw_vars
& dv
, unsigned start
, unsigned end
)
221 const vertex_storage_type::value_type
* v
;
223 for(i
= start
; i
< end
; i
++)
227 case 0: m_ren
.line3(dv
.curr
, dv
.xb1
, dv
.yb1
, dv
.xb2
, dv
.yb2
); break;
228 case 1: m_ren
.line2(dv
.curr
, dv
.xb2
, dv
.yb2
); break;
229 case 2: m_ren
.line1(dv
.curr
, dv
.xb1
, dv
.yb1
); break;
230 case 3: m_ren
.line0(dv
.curr
); break;
236 dv
.lnext
= m_src_vertices
[dv
.idx
].len
;
239 if(dv
.idx
>= m_src_vertices
.size()) dv
.idx
= 0;
241 v
= &m_src_vertices
[dv
.idx
];
246 dv
.next
= line_parameters(dv
.x1
, dv
.y1
, dv
.x2
, dv
.y2
, dv
.lnext
);
257 dv
.flags
|= ((dv
.curr
.diagonal_quadrant() ==
258 dv
.next
.diagonal_quadrant()) << 1);
261 if((dv
.flags
& 2) == 0)
263 bisectrix(dv
.curr
, dv
.next
, &dv
.xb2
, &dv
.yb2
);
271 //----------------------------------------------------------------------------
272 template<class Renderer
>
273 void rasterizer_outline_aa
<Renderer
>::render(bool close_polygon
)
275 m_src_vertices
.close(close_polygon
);
277 const vertex_storage_type::value_type
* v
;
286 if(m_src_vertices
.size() >= 3)
290 v
= &m_src_vertices
[m_src_vertices
.size() - 1];
295 v
= &m_src_vertices
[0];
299 line_parameters
prev(x1
, y1
, x2
, y2
, lprev
);
301 v
= &m_src_vertices
[1];
305 dv
.curr
= line_parameters(x2
, y2
, dv
.x1
, dv
.y1
, dv
.lcurr
);
307 v
= &m_src_vertices
[dv
.idx
];
310 dv
.next
= line_parameters(dv
.x1
, dv
.y1
, dv
.x2
, dv
.y2
, dv
.lnext
);
324 (prev
.diagonal_quadrant() == dv
.curr
.diagonal_quadrant()) |
325 ((dv
.curr
.diagonal_quadrant() == dv
.next
.diagonal_quadrant()) << 1);
328 if((dv
.flags
& 1) == 0)
330 bisectrix(prev
, dv
.curr
, &dv
.xb1
, &dv
.yb1
);
333 if((dv
.flags
& 2) == 0)
335 bisectrix(dv
.curr
, dv
.next
, &dv
.xb2
, &dv
.yb2
);
337 draw(dv
, 0, m_src_vertices
.size());
342 switch(m_src_vertices
.size())
350 v
= &m_src_vertices
[0];
354 v
= &m_src_vertices
[1];
357 line_parameters
lp(x1
, y1
, x2
, y2
, lprev
);
360 m_ren
.semidot(cmp_dist_start
, x1
, y1
, x1
+ (y2
- y1
), y1
- (x2
- x1
));
369 m_ren
.semidot(cmp_dist_end
, x2
, y2
, x2
+ (y2
- y1
), y2
- (x2
- x1
));
378 v
= &m_src_vertices
[0];
382 v
= &m_src_vertices
[1];
386 v
= &m_src_vertices
[2];
389 line_parameters
lp1(x1
, y1
, x2
, y2
, lprev
);
390 line_parameters
lp2(x2
, y2
, x3
, y3
, lnext
);
391 bisectrix(lp1
, lp2
, &dv
.xb1
, &dv
.yb1
);
395 m_ren
.semidot(cmp_dist_start
, x1
, y1
, x1
+ (y2
- y1
), y1
- (x2
- x1
));
410 m_ren
.semidot(cmp_dist_end
, x3
, y3
, x3
+ (y3
- y2
), y3
- (x3
- x2
));
419 v
= &m_src_vertices
[0];
424 v
= &m_src_vertices
[1];
428 line_parameters
prev(x1
, y1
, x2
, y2
, lprev
);
430 v
= &m_src_vertices
[2];
434 dv
.curr
= line_parameters(x2
, y2
, dv
.x1
, dv
.y1
, dv
.lcurr
);
436 v
= &m_src_vertices
[dv
.idx
];
439 dv
.next
= line_parameters(dv
.x1
, dv
.y1
, dv
.x2
, dv
.y2
, dv
.lnext
);
453 (prev
.diagonal_quadrant() == dv
.curr
.diagonal_quadrant()) |
454 ((dv
.curr
.diagonal_quadrant() == dv
.next
.diagonal_quadrant()) << 1);
457 if((dv
.flags
& 1) == 0)
459 bisectrix(prev
, dv
.curr
, &dv
.xb1
, &dv
.yb1
);
474 m_ren
.semidot(cmp_dist_start
, x1
, y1
, x1
+ (y2
- y1
), y1
- (x2
- x1
));
476 if((dv
.flags
& 2) == 0)
478 bisectrix(dv
.curr
, dv
.next
, &dv
.xb2
, &dv
.yb2
);
481 draw(dv
, 1, m_src_vertices
.size() - 2);
483 if((dv
.flags
& 1) == 0)
488 dv
.curr
.x2
+ (dv
.curr
.y2
- dv
.curr
.y1
),
489 dv
.curr
.y2
- (dv
.curr
.x2
- dv
.curr
.x1
));
494 dv
.curr
.x2
+ (dv
.curr
.y2
- dv
.curr
.y1
),
495 dv
.curr
.y2
- (dv
.curr
.x2
- dv
.curr
.x1
));
499 m_ren
.semidot(cmp_dist_end
, dv
.curr
.x2
, dv
.curr
.y2
,
500 dv
.curr
.x2
+ (dv
.curr
.y2
- dv
.curr
.y1
),
501 dv
.curr
.y2
- (dv
.curr
.x2
- dv
.curr
.x1
));
508 m_src_vertices
.remove_all();