1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
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
= uround(sqrt(dx
* dx
+ dy
* dy
))) >
53 (line_subpixel_scale
+ line_subpixel_scale
/ 2);
58 //----------------------------------------------------------outline_aa_join_e
59 enum outline_aa_join_e
61 outline_no_join
, //-----outline_no_join
62 outline_miter_join
, //-----outline_miter_join
63 outline_round_join
, //-----outline_round_join
64 outline_miter_accurate_join
//-----outline_accurate_join
67 //=======================================================rasterizer_outline_aa
68 template<class Renderer
, class Coord
=line_coord
> class rasterizer_outline_aa
71 //------------------------------------------------------------------------
76 line_parameters curr
, next
;
78 int xb1
, yb1
, xb2
, yb2
;
82 void draw(draw_vars
& dv
, unsigned start
, unsigned end
);
85 typedef line_aa_vertex vertex_type
;
86 typedef vertex_sequence
<vertex_type
, 6> vertex_storage_type
;
88 rasterizer_outline_aa(Renderer
& ren
) :
90 m_line_join(ren
.accurate_join_only() ?
91 outline_miter_accurate_join
:
97 void attach(Renderer
& ren
) { m_ren
= &ren
; }
99 //------------------------------------------------------------------------
100 void line_join(outline_aa_join_e join
)
102 m_line_join
= m_ren
->accurate_join_only() ?
103 outline_miter_accurate_join
:
106 bool line_join() const { return m_line_join
; }
108 //------------------------------------------------------------------------
109 void round_cap(bool v
) { m_round_cap
= v
; }
110 bool round_cap() const { return m_round_cap
; }
112 //------------------------------------------------------------------------
113 void move_to(int x
, int y
)
115 m_src_vertices
.modify_last(vertex_type(m_start_x
= x
, m_start_y
= y
));
118 //------------------------------------------------------------------------
119 void line_to(int x
, int y
)
121 m_src_vertices
.add(vertex_type(x
, y
));
124 //------------------------------------------------------------------------
125 void move_to_d(double x
, double y
)
127 move_to(Coord::conv(x
), Coord::conv(y
));
130 //------------------------------------------------------------------------
131 void line_to_d(double x
, double y
)
133 line_to(Coord::conv(x
), Coord::conv(y
));
136 //------------------------------------------------------------------------
137 void render(bool close_polygon
);
139 //------------------------------------------------------------------------
140 void add_vertex(double x
, double y
, unsigned cmd
)
151 render(is_closed(cmd
));
154 move_to(m_start_x
, m_start_y
);
164 //------------------------------------------------------------------------
165 template<class VertexSource
>
166 void add_path(VertexSource
& vs
, unsigned path_id
=0)
173 while(!is_stop(cmd
= vs
.vertex(&x
, &y
)))
175 add_vertex(x
, y
, cmd
);
181 //------------------------------------------------------------------------
182 template<class VertexSource
, class ColorStorage
, class PathId
>
183 void render_all_paths(VertexSource
& vs
,
184 const ColorStorage
& colors
,
185 const PathId
& path_id
,
188 for(unsigned i
= 0; i
< num_paths
; i
++)
190 m_ren
->color(colors
[i
]);
191 add_path(vs
, path_id
[i
]);
196 //------------------------------------------------------------------------
197 template<class Ctrl
> void render_ctrl(Ctrl
& c
)
200 for(i
= 0; i
< c
.num_paths(); i
++)
202 m_ren
->color(c
.color(i
));
208 rasterizer_outline_aa(const rasterizer_outline_aa
<Renderer
, Coord
>&);
209 const rasterizer_outline_aa
<Renderer
, Coord
>& operator =
210 (const rasterizer_outline_aa
<Renderer
, Coord
>&);
213 vertex_storage_type m_src_vertices
;
214 outline_aa_join_e m_line_join
;
227 //----------------------------------------------------------------------------
228 template<class Renderer
, class Coord
>
229 void rasterizer_outline_aa
<Renderer
, Coord
>::draw(draw_vars
& dv
,
234 const vertex_storage_type::value_type
* v
;
236 for(i
= start
; i
< end
; i
++)
238 if(m_line_join
== outline_round_join
)
240 dv
.xb1
= dv
.curr
.x1
+ (dv
.curr
.y2
- dv
.curr
.y1
);
241 dv
.yb1
= dv
.curr
.y1
- (dv
.curr
.x2
- dv
.curr
.x1
);
242 dv
.xb2
= dv
.curr
.x2
+ (dv
.curr
.y2
- dv
.curr
.y1
);
243 dv
.yb2
= dv
.curr
.y2
- (dv
.curr
.x2
- dv
.curr
.x1
);
248 case 0: m_ren
->line3(dv
.curr
, dv
.xb1
, dv
.yb1
, dv
.xb2
, dv
.yb2
); break;
249 case 1: m_ren
->line2(dv
.curr
, dv
.xb2
, dv
.yb2
); break;
250 case 2: m_ren
->line1(dv
.curr
, dv
.xb1
, dv
.yb1
); break;
251 case 3: m_ren
->line0(dv
.curr
); break;
254 if(m_line_join
== outline_round_join
&& (dv
.flags
& 2) == 0)
256 m_ren
->pie(dv
.curr
.x2
, dv
.curr
.y2
,
257 dv
.curr
.x2
+ (dv
.curr
.y2
- dv
.curr
.y1
),
258 dv
.curr
.y2
- (dv
.curr
.x2
- dv
.curr
.x1
),
259 dv
.curr
.x2
+ (dv
.next
.y2
- dv
.next
.y1
),
260 dv
.curr
.y2
- (dv
.next
.x2
- dv
.next
.x1
));
266 dv
.lnext
= m_src_vertices
[dv
.idx
].len
;
269 if(dv
.idx
>= m_src_vertices
.size()) dv
.idx
= 0;
271 v
= &m_src_vertices
[dv
.idx
];
276 dv
.next
= line_parameters(dv
.x1
, dv
.y1
, dv
.x2
, dv
.y2
, dv
.lnext
);
282 case outline_no_join
:
286 case outline_miter_join
:
288 dv
.flags
|= ((dv
.curr
.diagonal_quadrant() ==
289 dv
.next
.diagonal_quadrant()) << 1);
290 if((dv
.flags
& 2) == 0)
292 bisectrix(dv
.curr
, dv
.next
, &dv
.xb2
, &dv
.yb2
);
296 case outline_round_join
:
298 dv
.flags
|= ((dv
.curr
.diagonal_quadrant() ==
299 dv
.next
.diagonal_quadrant()) << 1);
302 case outline_miter_accurate_join
:
304 bisectrix(dv
.curr
, dv
.next
, &dv
.xb2
, &dv
.yb2
);
313 //----------------------------------------------------------------------------
314 template<class Renderer
, class Coord
>
315 void rasterizer_outline_aa
<Renderer
, Coord
>::render(bool close_polygon
)
317 m_src_vertices
.close(close_polygon
);
319 const vertex_storage_type::value_type
* v
;
328 if(m_src_vertices
.size() >= 3)
332 v
= &m_src_vertices
[m_src_vertices
.size() - 1];
337 v
= &m_src_vertices
[0];
341 line_parameters
prev(x1
, y1
, x2
, y2
, lprev
);
343 v
= &m_src_vertices
[1];
347 dv
.curr
= line_parameters(x2
, y2
, dv
.x1
, dv
.y1
, dv
.lcurr
);
349 v
= &m_src_vertices
[dv
.idx
];
352 dv
.next
= line_parameters(dv
.x1
, dv
.y1
, dv
.x2
, dv
.y2
, dv
.lnext
);
361 case outline_no_join
:
365 case outline_miter_join
:
366 case outline_round_join
:
368 (prev
.diagonal_quadrant() == dv
.curr
.diagonal_quadrant()) |
369 ((dv
.curr
.diagonal_quadrant() == dv
.next
.diagonal_quadrant()) << 1);
372 case outline_miter_accurate_join
:
377 if((dv
.flags
& 1) == 0 && m_line_join
!= outline_round_join
)
379 bisectrix(prev
, dv
.curr
, &dv
.xb1
, &dv
.yb1
);
382 if((dv
.flags
& 2) == 0 && m_line_join
!= outline_round_join
)
384 bisectrix(dv
.curr
, dv
.next
, &dv
.xb2
, &dv
.yb2
);
386 draw(dv
, 0, m_src_vertices
.size());
391 switch(m_src_vertices
.size())
399 v
= &m_src_vertices
[0];
403 v
= &m_src_vertices
[1];
406 line_parameters
lp(x1
, y1
, x2
, y2
, lprev
);
409 m_ren
->semidot(cmp_dist_start
, x1
, y1
, x1
+ (y2
- y1
), y1
- (x2
- x1
));
418 m_ren
->semidot(cmp_dist_end
, x2
, y2
, x2
+ (y2
- y1
), y2
- (x2
- x1
));
427 v
= &m_src_vertices
[0];
431 v
= &m_src_vertices
[1];
435 v
= &m_src_vertices
[2];
438 line_parameters
lp1(x1
, y1
, x2
, y2
, lprev
);
439 line_parameters
lp2(x2
, y2
, x3
, y3
, lnext
);
443 m_ren
->semidot(cmp_dist_start
, x1
, y1
, x1
+ (y2
- y1
), y1
- (x2
- x1
));
446 if(m_line_join
== outline_round_join
)
448 m_ren
->line3(lp1
, x1
+ (y2
- y1
), y1
- (x2
- x1
),
449 x2
+ (y2
- y1
), y2
- (x2
- x1
));
451 m_ren
->pie(x2
, y2
, x2
+ (y2
- y1
), y2
- (x2
- x1
),
452 x2
+ (y3
- y2
), y2
- (x3
- x2
));
454 m_ren
->line3(lp2
, x2
+ (y3
- y2
), y2
- (x3
- x2
),
455 x3
+ (y3
- y2
), y3
- (x3
- x2
));
459 bisectrix(lp1
, lp2
, &dv
.xb1
, &dv
.yb1
);
460 m_ren
->line3(lp1
, x1
+ (y2
- y1
), y1
- (x2
- x1
),
463 m_ren
->line3(lp2
, dv
.xb1
, dv
.yb1
,
464 x3
+ (y3
- y2
), y3
- (x3
- x2
));
468 m_ren
->semidot(cmp_dist_end
, x3
, y3
, x3
+ (y3
- y2
), y3
- (x3
- x2
));
477 v
= &m_src_vertices
[0];
482 v
= &m_src_vertices
[1];
486 line_parameters
prev(x1
, y1
, x2
, y2
, lprev
);
488 v
= &m_src_vertices
[2];
492 dv
.curr
= line_parameters(x2
, y2
, dv
.x1
, dv
.y1
, dv
.lcurr
);
494 v
= &m_src_vertices
[dv
.idx
];
497 dv
.next
= line_parameters(dv
.x1
, dv
.y1
, dv
.x2
, dv
.y2
, dv
.lnext
);
506 case outline_no_join
:
510 case outline_miter_join
:
511 case outline_round_join
:
513 (prev
.diagonal_quadrant() == dv
.curr
.diagonal_quadrant()) |
514 ((dv
.curr
.diagonal_quadrant() == dv
.next
.diagonal_quadrant()) << 1);
517 case outline_miter_accurate_join
:
524 m_ren
->semidot(cmp_dist_start
, x1
, y1
, x1
+ (y2
- y1
), y1
- (x2
- x1
));
526 if((dv
.flags
& 1) == 0)
528 if(m_line_join
== outline_round_join
)
530 m_ren
->line3(prev
, x1
+ (y2
- y1
), y1
- (x2
- x1
),
531 x2
+ (y2
- y1
), y2
- (x2
- x1
));
532 m_ren
->pie(prev
.x2
, prev
.y2
,
533 x2
+ (y2
- y1
), y2
- (x2
- x1
),
534 dv
.curr
.x1
+ (dv
.curr
.y2
- dv
.curr
.y1
),
535 dv
.curr
.y1
- (dv
.curr
.x2
- dv
.curr
.x1
));
539 bisectrix(prev
, dv
.curr
, &dv
.xb1
, &dv
.yb1
);
540 m_ren
->line3(prev
, x1
+ (y2
- y1
), y1
- (x2
- x1
),
550 if((dv
.flags
& 2) == 0 && m_line_join
!= outline_round_join
)
552 bisectrix(dv
.curr
, dv
.next
, &dv
.xb2
, &dv
.yb2
);
555 draw(dv
, 1, m_src_vertices
.size() - 2);
557 if((dv
.flags
& 1) == 0)
559 if(m_line_join
== outline_round_join
)
561 m_ren
->line3(dv
.curr
,
562 dv
.curr
.x1
+ (dv
.curr
.y2
- dv
.curr
.y1
),
563 dv
.curr
.y1
- (dv
.curr
.x2
- dv
.curr
.x1
),
564 dv
.curr
.x2
+ (dv
.curr
.y2
- dv
.curr
.y1
),
565 dv
.curr
.y2
- (dv
.curr
.x2
- dv
.curr
.x1
));
569 m_ren
->line3(dv
.curr
, dv
.xb1
, dv
.yb1
,
570 dv
.curr
.x2
+ (dv
.curr
.y2
- dv
.curr
.y1
),
571 dv
.curr
.y2
- (dv
.curr
.x2
- dv
.curr
.x1
));
576 m_ren
->line2(dv
.curr
,
577 dv
.curr
.x2
+ (dv
.curr
.y2
- dv
.curr
.y1
),
578 dv
.curr
.y2
- (dv
.curr
.x2
- dv
.curr
.x1
));
582 m_ren
->semidot(cmp_dist_end
, dv
.curr
.x2
, dv
.curr
.y2
,
583 dv
.curr
.x2
+ (dv
.curr
.y2
- dv
.curr
.y1
),
584 dv
.curr
.y2
- (dv
.curr
.x2
- dv
.curr
.x1
));
591 m_src_vertices
.remove_all();