Anti-Grain Geometry Tutorial
agg_rasterizer_outline_aa.h
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
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.
9 //
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
17 
18 #include <cmath>
19 #include "agg_basics.h"
20 #include "agg_line_aa_basics.h"
21 #include "agg_vertex_sequence.h"
22 
23 namespace agg
24 {
25 
26  //-------------------------------------------------------------------------
27  inline bool cmp_dist_start(int d) { return d > 0; }
28  inline bool cmp_dist_end(int d) { return d <= 0; }
29 
30 
31 
32  //-----------------------------------------------------------line_aa_vertex
33  // Vertex (x, y) with the distance to the next one. The last vertex has
34  // the distance between the last and the first points
36  {
37  int x;
38  int y;
39  int len;
40 
41  line_aa_vertex() {}
42  line_aa_vertex(int x_, int y_) :
43  x(x_),
44  y(y_),
45  len(0)
46  {
47  }
48 
49  bool operator () (const line_aa_vertex& val)
50  {
51  double dx = val.x - x;
52  double dy = val.y - y;
53  return (len = uround(std::sqrt(dx * dx + dy * dy))) >
54  (line_subpixel_scale + line_subpixel_scale / 2);
55  }
56  };
57 
58 
59  //----------------------------------------------------------outline_aa_join_e
60  enum outline_aa_join_e
61  {
62  outline_no_join, //-----outline_no_join
63  outline_miter_join, //-----outline_miter_join
64  outline_round_join, //-----outline_round_join
65  outline_miter_accurate_join //-----outline_accurate_join
66  };
67 
68  //=======================================================rasterizer_outline_aa
69  template<class Renderer, class Coord=line_coord> class rasterizer_outline_aa
70  {
71  private:
72  //------------------------------------------------------------------------
73  struct draw_vars
74  {
75  unsigned idx;
76  int x1, y1, x2, y2;
77  line_parameters curr, next;
78  int lcurr, lnext;
79  int xb1, yb1, xb2, yb2;
80  unsigned flags;
81  };
82 
83  void draw(draw_vars& dv, unsigned start, unsigned end);
84 
85  public:
88 
89  explicit rasterizer_outline_aa(Renderer& ren) :
90  m_ren(&ren),
91  m_line_join(ren.accurate_join_only() ?
92  outline_miter_accurate_join :
93  outline_round_join),
94  m_round_cap(false),
95  m_start_x(0),
96  m_start_y(0)
97  {}
98  void attach(Renderer& ren) { m_ren = &ren; }
99 
100  //------------------------------------------------------------------------
101  void line_join(outline_aa_join_e join)
102  {
103  m_line_join = m_ren->accurate_join_only() ?
104  outline_miter_accurate_join :
105  join;
106  }
107  bool line_join() const { return m_line_join; }
108 
109  //------------------------------------------------------------------------
110  void round_cap(bool v) { m_round_cap = v; }
111  bool round_cap() const { return m_round_cap; }
112 
113  //------------------------------------------------------------------------
114  void move_to(int x, int y)
115  {
116  m_src_vertices.modify_last(vertex_type(m_start_x = x, m_start_y = y));
117  }
118 
119  //------------------------------------------------------------------------
120  void line_to(int x, int y)
121  {
122  m_src_vertices.add(vertex_type(x, y));
123  }
124 
125  //------------------------------------------------------------------------
126  void move_to_d(double x, double y)
127  {
128  move_to(Coord::conv(x), Coord::conv(y));
129  }
130 
131  //------------------------------------------------------------------------
132  void line_to_d(double x, double y)
133  {
134  line_to(Coord::conv(x), Coord::conv(y));
135  }
136 
137  //------------------------------------------------------------------------
138  void render(bool close_polygon);
139 
140  //------------------------------------------------------------------------
141  void add_vertex(double x, double y, unsigned cmd)
142  {
143  if(is_move_to(cmd))
144  {
145  render(false);
146  move_to_d(x, y);
147  }
148  else
149  {
150  if(is_end_poly(cmd))
151  {
152  render(is_closed(cmd));
153  if(is_closed(cmd))
154  {
155  move_to(m_start_x, m_start_y);
156  }
157  }
158  else
159  {
160  line_to_d(x, y);
161  }
162  }
163  }
164 
165  //------------------------------------------------------------------------
166  template<class VertexSource>
167  void add_path(VertexSource& vs, unsigned path_id=0)
168  {
169  double x;
170  double y;
171 
172  unsigned cmd;
173  vs.rewind(path_id);
174  while(!is_stop(cmd = vs.vertex(&x, &y)))
175  {
176  add_vertex(x, y, cmd);
177  }
178  render(false);
179  }
180 
181 
182  //------------------------------------------------------------------------
183  template<class VertexSource, class ColorStorage, class PathId>
184  void render_all_paths(VertexSource& vs,
185  const ColorStorage& colors,
186  const PathId& path_id,
187  unsigned num_paths)
188  {
189  for(unsigned i = 0; i < num_paths; i++)
190  {
191  m_ren->color(colors[i]);
192  add_path(vs, path_id[i]);
193  }
194  }
195 
196 
197  //------------------------------------------------------------------------
198  template<class Ctrl> void render_ctrl(Ctrl& c)
199  {
200  unsigned i;
201  for(i = 0; i < c.num_paths(); i++)
202  {
203  m_ren->color(c.color(i));
204  add_path(c, i);
205  }
206  }
207 
208  private:
210  const rasterizer_outline_aa<Renderer, Coord>& operator =
212 
213  Renderer* m_ren;
214  vertex_storage_type m_src_vertices;
215  outline_aa_join_e m_line_join;
216  bool m_round_cap;
217  int m_start_x;
218  int m_start_y;
219  };
220 
221 
222 
223 
224 
225 
226 
227 
228  //----------------------------------------------------------------------------
229  template<class Renderer, class Coord>
231  unsigned start,
232  unsigned end)
233  {
234  unsigned i;
235  const vertex_storage_type::value_type* v;
236 
237  for(i = start; i < end; i++)
238  {
239  if(m_line_join == outline_round_join)
240  {
241  dv.xb1 = dv.curr.x1 + (dv.curr.y2 - dv.curr.y1);
242  dv.yb1 = dv.curr.y1 - (dv.curr.x2 - dv.curr.x1);
243  dv.xb2 = dv.curr.x2 + (dv.curr.y2 - dv.curr.y1);
244  dv.yb2 = dv.curr.y2 - (dv.curr.x2 - dv.curr.x1);
245  }
246 
247  switch(dv.flags)
248  {
249  case 0: m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break;
250  case 1: m_ren->line2(dv.curr, dv.xb2, dv.yb2); break;
251  case 2: m_ren->line1(dv.curr, dv.xb1, dv.yb1); break;
252  case 3: m_ren->line0(dv.curr); break;
253  }
254 
255  if(m_line_join == outline_round_join && (dv.flags & 2) == 0)
256  {
257  m_ren->pie(dv.curr.x2, dv.curr.y2,
258  dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
259  dv.curr.y2 - (dv.curr.x2 - dv.curr.x1),
260  dv.curr.x2 + (dv.next.y2 - dv.next.y1),
261  dv.curr.y2 - (dv.next.x2 - dv.next.x1));
262  }
263 
264  dv.x1 = dv.x2;
265  dv.y1 = dv.y2;
266  dv.lcurr = dv.lnext;
267  dv.lnext = m_src_vertices[dv.idx].len;
268 
269  ++dv.idx;
270  if(dv.idx >= m_src_vertices.size()) dv.idx = 0;
271 
272  v = &m_src_vertices[dv.idx];
273  dv.x2 = v->x;
274  dv.y2 = v->y;
275 
276  dv.curr = dv.next;
277  dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
278  dv.xb1 = dv.xb2;
279  dv.yb1 = dv.yb2;
280 
281  switch(m_line_join)
282  {
283  case outline_no_join:
284  dv.flags = 3;
285  break;
286 
287  case outline_miter_join:
288  dv.flags >>= 1;
289  dv.flags |= ((dv.curr.diagonal_quadrant() ==
290  dv.next.diagonal_quadrant()) << 1);
291  if((dv.flags & 2) == 0)
292  {
293  bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
294  }
295  break;
296 
297  case outline_round_join:
298  dv.flags >>= 1;
299  dv.flags |= ((dv.curr.diagonal_quadrant() ==
300  dv.next.diagonal_quadrant()) << 1);
301  break;
302 
303  case outline_miter_accurate_join:
304  dv.flags = 0;
305  bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
306  break;
307  }
308  }
309  }
310 
311 
312 
313 
314  //----------------------------------------------------------------------------
315  template<class Renderer, class Coord>
316  void rasterizer_outline_aa<Renderer, Coord>::render(bool close_polygon)
317  {
318  m_src_vertices.close(close_polygon);
319  draw_vars dv;
320  const vertex_storage_type::value_type* v;
321  int x1;
322  int y1;
323  int x2;
324  int y2;
325  int lprev;
326 
327  if(close_polygon)
328  {
329  if(m_src_vertices.size() >= 3)
330  {
331  dv.idx = 2;
332 
333  v = &m_src_vertices[m_src_vertices.size() - 1];
334  x1 = v->x;
335  y1 = v->y;
336  lprev = v->len;
337 
338  v = &m_src_vertices[0];
339  x2 = v->x;
340  y2 = v->y;
341  dv.lcurr = v->len;
342  line_parameters prev(x1, y1, x2, y2, lprev);
343 
344  v = &m_src_vertices[1];
345  dv.x1 = v->x;
346  dv.y1 = v->y;
347  dv.lnext = v->len;
348  dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
349 
350  v = &m_src_vertices[dv.idx];
351  dv.x2 = v->x;
352  dv.y2 = v->y;
353  dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
354 
355  dv.xb1 = 0;
356  dv.yb1 = 0;
357  dv.xb2 = 0;
358  dv.yb2 = 0;
359 
360  switch(m_line_join)
361  {
362  case outline_no_join:
363  dv.flags = 3;
364  break;
365 
366  case outline_miter_join:
367  case outline_round_join:
368  dv.flags =
369  (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
370  ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
371  break;
372 
373  case outline_miter_accurate_join:
374  dv.flags = 0;
375  break;
376  }
377 
378  if((dv.flags & 1) == 0 && m_line_join != outline_round_join)
379  {
380  bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
381  }
382 
383  if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
384  {
385  bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
386  }
387  draw(dv, 0, m_src_vertices.size());
388  }
389  }
390  else
391  {
392  switch(m_src_vertices.size())
393  {
394  case 0:
395  case 1:
396  break;
397 
398  case 2:
399  {
400  v = &m_src_vertices[0];
401  x1 = v->x;
402  y1 = v->y;
403  lprev = v->len;
404  v = &m_src_vertices[1];
405  x2 = v->x;
406  y2 = v->y;
407  line_parameters lp(x1, y1, x2, y2, lprev);
408  if(m_round_cap)
409  {
410  m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
411  }
412  m_ren->line3(lp,
413  x1 + (y2 - y1),
414  y1 - (x2 - x1),
415  x2 + (y2 - y1),
416  y2 - (x2 - x1));
417  if(m_round_cap)
418  {
419  m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1));
420  }
421  }
422  break;
423 
424  case 3:
425  {
426  int x3, y3;
427  int lnext;
428  v = &m_src_vertices[0];
429  x1 = v->x;
430  y1 = v->y;
431  lprev = v->len;
432  v = &m_src_vertices[1];
433  x2 = v->x;
434  y2 = v->y;
435  lnext = v->len;
436  v = &m_src_vertices[2];
437  x3 = v->x;
438  y3 = v->y;
439  line_parameters lp1(x1, y1, x2, y2, lprev);
440  line_parameters lp2(x2, y2, x3, y3, lnext);
441 
442  if(m_round_cap)
443  {
444  m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
445  }
446 
447  if(m_line_join == outline_round_join)
448  {
449  m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
450  x2 + (y2 - y1), y2 - (x2 - x1));
451 
452  m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1),
453  x2 + (y3 - y2), y2 - (x3 - x2));
454 
455  m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2),
456  x3 + (y3 - y2), y3 - (x3 - x2));
457  }
458  else
459  {
460  bisectrix(lp1, lp2, &dv.xb1, &dv.yb1);
461  m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
462  dv.xb1, dv.yb1);
463 
464  m_ren->line3(lp2, dv.xb1, dv.yb1,
465  x3 + (y3 - y2), y3 - (x3 - x2));
466  }
467  if(m_round_cap)
468  {
469  m_ren->semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2));
470  }
471  }
472  break;
473 
474  default:
475  {
476  dv.idx = 3;
477 
478  v = &m_src_vertices[0];
479  x1 = v->x;
480  y1 = v->y;
481  lprev = v->len;
482 
483  v = &m_src_vertices[1];
484  x2 = v->x;
485  y2 = v->y;
486  dv.lcurr = v->len;
487  line_parameters prev(x1, y1, x2, y2, lprev);
488 
489  v = &m_src_vertices[2];
490  dv.x1 = v->x;
491  dv.y1 = v->y;
492  dv.lnext = v->len;
493  dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
494 
495  v = &m_src_vertices[dv.idx];
496  dv.x2 = v->x;
497  dv.y2 = v->y;
498  dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
499 
500  dv.xb1 = 0;
501  dv.yb1 = 0;
502  dv.xb2 = 0;
503  dv.yb2 = 0;
504 
505  switch(m_line_join)
506  {
507  case outline_no_join:
508  dv.flags = 3;
509  break;
510 
511  case outline_miter_join:
512  case outline_round_join:
513  dv.flags =
514  (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
515  ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
516  break;
517 
518  case outline_miter_accurate_join:
519  dv.flags = 0;
520  break;
521  }
522 
523  if(m_round_cap)
524  {
525  m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
526  }
527  if((dv.flags & 1) == 0)
528  {
529  if(m_line_join == outline_round_join)
530  {
531  m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
532  x2 + (y2 - y1), y2 - (x2 - x1));
533  m_ren->pie(prev.x2, prev.y2,
534  x2 + (y2 - y1), y2 - (x2 - x1),
535  dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
536  dv.curr.y1 - (dv.curr.x2 - dv.curr.x1));
537  }
538  else
539  {
540  bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
541  m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
542  dv.xb1, dv.yb1);
543  }
544  }
545  else
546  {
547  m_ren->line1(prev,
548  x1 + (y2 - y1),
549  y1 - (x2 - x1));
550  }
551  if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
552  {
553  bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
554  }
555 
556  draw(dv, 1, m_src_vertices.size() - 2);
557 
558  if((dv.flags & 1) == 0)
559  {
560  if(m_line_join == outline_round_join)
561  {
562  m_ren->line3(dv.curr,
563  dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
564  dv.curr.y1 - (dv.curr.x2 - dv.curr.x1),
565  dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
566  dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
567  }
568  else
569  {
570  m_ren->line3(dv.curr, dv.xb1, dv.yb1,
571  dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
572  dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
573  }
574  }
575  else
576  {
577  m_ren->line2(dv.curr,
578  dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
579  dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
580  }
581  if(m_round_cap)
582  {
583  m_ren->semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2,
584  dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
585  dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
586  }
587 
588  }
589  break;
590  }
591  }
592  m_src_vertices.remove_all();
593  }
594 
595 
596 }
597 
598 
599 #endif
600 
Definition: agg_arc.cpp:24