Anti-Grain Geometry Tutorial
agg_renderer_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_RENDERER_OUTLINE_AA_INCLUDED
16 #define AGG_RENDERER_OUTLINE_AA_INCLUDED
17 
18 #include <cstdlib>
19 #include "agg_array.h"
20 #include "agg_math.h"
21 #include "agg_line_aa_basics.h"
22 #include "agg_dda_line.h"
23 #include "agg_ellipse_bresenham.h"
24 #include "agg_renderer_base.h"
25 #include "agg_gamma_functions.h"
26 #include "agg_clip_liang_barsky.h"
27 
28 namespace agg
29 {
30 
31  //===================================================distance_interpolator0
33  {
34  public:
35  //---------------------------------------------------------------------
37  distance_interpolator0(int x1, int y1, int x2, int y2, int x, int y) :
38  m_dx(line_mr(x2) - line_mr(x1)),
39  m_dy(line_mr(y2) - line_mr(y1)),
40  m_dist((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy -
41  (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx)
42  {
43  m_dx <<= line_mr_subpixel_shift;
44  m_dy <<= line_mr_subpixel_shift;
45  }
46 
47  //---------------------------------------------------------------------
48  void inc_x() { m_dist += m_dy; }
49  int dist() const { return m_dist; }
50 
51  private:
52  //---------------------------------------------------------------------
53  int m_dx;
54  int m_dy;
55  int m_dist;
56  };
57 
58  //==================================================distance_interpolator00
60  {
61  public:
62  //---------------------------------------------------------------------
64  distance_interpolator00(int xc, int yc,
65  int x1, int y1, int x2, int y2,
66  int x, int y) :
67  m_dx1(line_mr(x1) - line_mr(xc)),
68  m_dy1(line_mr(y1) - line_mr(yc)),
69  m_dx2(line_mr(x2) - line_mr(xc)),
70  m_dy2(line_mr(y2) - line_mr(yc)),
71  m_dist1((line_mr(x + line_subpixel_scale/2) - line_mr(x1)) * m_dy1 -
72  (line_mr(y + line_subpixel_scale/2) - line_mr(y1)) * m_dx1),
73  m_dist2((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy2 -
74  (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx2)
75  {
76  m_dx1 <<= line_mr_subpixel_shift;
77  m_dy1 <<= line_mr_subpixel_shift;
78  m_dx2 <<= line_mr_subpixel_shift;
79  m_dy2 <<= line_mr_subpixel_shift;
80  }
81 
82  //---------------------------------------------------------------------
83  void inc_x() { m_dist1 += m_dy1; m_dist2 += m_dy2; }
84  int dist1() const { return m_dist1; }
85  int dist2() const { return m_dist2; }
86 
87  private:
88  //---------------------------------------------------------------------
89  int m_dx1;
90  int m_dy1;
91  int m_dx2;
92  int m_dy2;
93  int m_dist1;
94  int m_dist2;
95  };
96 
97  //===================================================distance_interpolator1
99  {
100  public:
101  //---------------------------------------------------------------------
103  distance_interpolator1(int x1, int y1, int x2, int y2, int x, int y) :
104  m_dx(x2 - x1),
105  m_dy(y2 - y1),
106  m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) -
107  double(y + line_subpixel_scale/2 - y2) * double(m_dx)))
108  {
109  m_dx <<= line_subpixel_shift;
110  m_dy <<= line_subpixel_shift;
111  }
112 
113  //---------------------------------------------------------------------
114  void inc_x() { m_dist += m_dy; }
115  void dec_x() { m_dist -= m_dy; }
116  void inc_y() { m_dist -= m_dx; }
117  void dec_y() { m_dist += m_dx; }
118 
119  //---------------------------------------------------------------------
120  void inc_x(int dy)
121  {
122  m_dist += m_dy;
123  if(dy > 0) m_dist -= m_dx;
124  if(dy < 0) m_dist += m_dx;
125  }
126 
127  //---------------------------------------------------------------------
128  void dec_x(int dy)
129  {
130  m_dist -= m_dy;
131  if(dy > 0) m_dist -= m_dx;
132  if(dy < 0) m_dist += m_dx;
133  }
134 
135  //---------------------------------------------------------------------
136  void inc_y(int dx)
137  {
138  m_dist -= m_dx;
139  if(dx > 0) m_dist += m_dy;
140  if(dx < 0) m_dist -= m_dy;
141  }
142 
143  void dec_y(int dx)
144  //---------------------------------------------------------------------
145  {
146  m_dist += m_dx;
147  if(dx > 0) m_dist += m_dy;
148  if(dx < 0) m_dist -= m_dy;
149  }
150 
151  //---------------------------------------------------------------------
152  int dist() const { return m_dist; }
153  int dx() const { return m_dx; }
154  int dy() const { return m_dy; }
155 
156  private:
157  //---------------------------------------------------------------------
158  int m_dx;
159  int m_dy;
160  int m_dist;
161  };
162 
163 
164 
165 
166 
167  //===================================================distance_interpolator2
169  {
170  public:
171  //---------------------------------------------------------------------
173  distance_interpolator2(int x1, int y1, int x2, int y2,
174  int sx, int sy, int x, int y) :
175  m_dx(x2 - x1),
176  m_dy(y2 - y1),
177  m_dx_start(line_mr(sx) - line_mr(x1)),
178  m_dy_start(line_mr(sy) - line_mr(y1)),
179 
180  m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) -
181  double(y + line_subpixel_scale/2 - y2) * double(m_dx))),
182 
183  m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start -
184  (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start)
185  {
186  m_dx <<= line_subpixel_shift;
187  m_dy <<= line_subpixel_shift;
188  m_dx_start <<= line_mr_subpixel_shift;
189  m_dy_start <<= line_mr_subpixel_shift;
190  }
191 
192  distance_interpolator2(int x1, int y1, int x2, int y2,
193  int ex, int ey, int x, int y, int) :
194  m_dx(x2 - x1),
195  m_dy(y2 - y1),
196  m_dx_start(line_mr(ex) - line_mr(x2)),
197  m_dy_start(line_mr(ey) - line_mr(y2)),
198 
199  m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) -
200  double(y + line_subpixel_scale/2 - y2) * double(m_dx))),
201 
202  m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_start -
203  (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_start)
204  {
205  m_dx <<= line_subpixel_shift;
206  m_dy <<= line_subpixel_shift;
207  m_dx_start <<= line_mr_subpixel_shift;
208  m_dy_start <<= line_mr_subpixel_shift;
209  }
210 
211 
212  //---------------------------------------------------------------------
213  void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; }
214  void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; }
215  void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; }
216  void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; }
217 
218  //---------------------------------------------------------------------
219  void inc_x(int dy)
220  {
221  m_dist += m_dy;
222  m_dist_start += m_dy_start;
223  if(dy > 0)
224  {
225  m_dist -= m_dx;
226  m_dist_start -= m_dx_start;
227  }
228  if(dy < 0)
229  {
230  m_dist += m_dx;
231  m_dist_start += m_dx_start;
232  }
233  }
234 
235  //---------------------------------------------------------------------
236  void dec_x(int dy)
237  {
238  m_dist -= m_dy;
239  m_dist_start -= m_dy_start;
240  if(dy > 0)
241  {
242  m_dist -= m_dx;
243  m_dist_start -= m_dx_start;
244  }
245  if(dy < 0)
246  {
247  m_dist += m_dx;
248  m_dist_start += m_dx_start;
249  }
250  }
251 
252  //---------------------------------------------------------------------
253  void inc_y(int dx)
254  {
255  m_dist -= m_dx;
256  m_dist_start -= m_dx_start;
257  if(dx > 0)
258  {
259  m_dist += m_dy;
260  m_dist_start += m_dy_start;
261  }
262  if(dx < 0)
263  {
264  m_dist -= m_dy;
265  m_dist_start -= m_dy_start;
266  }
267  }
268 
269  //---------------------------------------------------------------------
270  void dec_y(int dx)
271  {
272  m_dist += m_dx;
273  m_dist_start += m_dx_start;
274  if(dx > 0)
275  {
276  m_dist += m_dy;
277  m_dist_start += m_dy_start;
278  }
279  if(dx < 0)
280  {
281  m_dist -= m_dy;
282  m_dist_start -= m_dy_start;
283  }
284  }
285 
286  //---------------------------------------------------------------------
287  int dist() const { return m_dist; }
288  int dist_start() const { return m_dist_start; }
289  int dist_end() const { return m_dist_start; }
290 
291  //---------------------------------------------------------------------
292  int dx() const { return m_dx; }
293  int dy() const { return m_dy; }
294  int dx_start() const { return m_dx_start; }
295  int dy_start() const { return m_dy_start; }
296  int dx_end() const { return m_dx_start; }
297  int dy_end() const { return m_dy_start; }
298 
299  private:
300  //---------------------------------------------------------------------
301  int m_dx;
302  int m_dy;
303  int m_dx_start;
304  int m_dy_start;
305 
306  int m_dist;
307  int m_dist_start;
308  };
309 
310 
311 
312 
313 
314  //===================================================distance_interpolator3
316  {
317  public:
318  //---------------------------------------------------------------------
320  distance_interpolator3(int x1, int y1, int x2, int y2,
321  int sx, int sy, int ex, int ey,
322  int x, int y) :
323  m_dx(x2 - x1),
324  m_dy(y2 - y1),
325  m_dx_start(line_mr(sx) - line_mr(x1)),
326  m_dy_start(line_mr(sy) - line_mr(y1)),
327  m_dx_end(line_mr(ex) - line_mr(x2)),
328  m_dy_end(line_mr(ey) - line_mr(y2)),
329 
330  m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) -
331  double(y + line_subpixel_scale/2 - y2) * double(m_dx))),
332 
333  m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start -
334  (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start),
335 
336  m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end -
337  (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end)
338  {
339  m_dx <<= line_subpixel_shift;
340  m_dy <<= line_subpixel_shift;
341  m_dx_start <<= line_mr_subpixel_shift;
342  m_dy_start <<= line_mr_subpixel_shift;
343  m_dx_end <<= line_mr_subpixel_shift;
344  m_dy_end <<= line_mr_subpixel_shift;
345  }
346 
347  //---------------------------------------------------------------------
348  void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; }
349  void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; }
350  void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; }
351  void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; }
352 
353  //---------------------------------------------------------------------
354  void inc_x(int dy)
355  {
356  m_dist += m_dy;
357  m_dist_start += m_dy_start;
358  m_dist_end += m_dy_end;
359  if(dy > 0)
360  {
361  m_dist -= m_dx;
362  m_dist_start -= m_dx_start;
363  m_dist_end -= m_dx_end;
364  }
365  if(dy < 0)
366  {
367  m_dist += m_dx;
368  m_dist_start += m_dx_start;
369  m_dist_end += m_dx_end;
370  }
371  }
372 
373  //---------------------------------------------------------------------
374  void dec_x(int dy)
375  {
376  m_dist -= m_dy;
377  m_dist_start -= m_dy_start;
378  m_dist_end -= m_dy_end;
379  if(dy > 0)
380  {
381  m_dist -= m_dx;
382  m_dist_start -= m_dx_start;
383  m_dist_end -= m_dx_end;
384  }
385  if(dy < 0)
386  {
387  m_dist += m_dx;
388  m_dist_start += m_dx_start;
389  m_dist_end += m_dx_end;
390  }
391  }
392 
393  //---------------------------------------------------------------------
394  void inc_y(int dx)
395  {
396  m_dist -= m_dx;
397  m_dist_start -= m_dx_start;
398  m_dist_end -= m_dx_end;
399  if(dx > 0)
400  {
401  m_dist += m_dy;
402  m_dist_start += m_dy_start;
403  m_dist_end += m_dy_end;
404  }
405  if(dx < 0)
406  {
407  m_dist -= m_dy;
408  m_dist_start -= m_dy_start;
409  m_dist_end -= m_dy_end;
410  }
411  }
412 
413  //---------------------------------------------------------------------
414  void dec_y(int dx)
415  {
416  m_dist += m_dx;
417  m_dist_start += m_dx_start;
418  m_dist_end += m_dx_end;
419  if(dx > 0)
420  {
421  m_dist += m_dy;
422  m_dist_start += m_dy_start;
423  m_dist_end += m_dy_end;
424  }
425  if(dx < 0)
426  {
427  m_dist -= m_dy;
428  m_dist_start -= m_dy_start;
429  m_dist_end -= m_dy_end;
430  }
431  }
432 
433  //---------------------------------------------------------------------
434  int dist() const { return m_dist; }
435  int dist_start() const { return m_dist_start; }
436  int dist_end() const { return m_dist_end; }
437 
438  //---------------------------------------------------------------------
439  int dx() const { return m_dx; }
440  int dy() const { return m_dy; }
441  int dx_start() const { return m_dx_start; }
442  int dy_start() const { return m_dy_start; }
443  int dx_end() const { return m_dx_end; }
444  int dy_end() const { return m_dy_end; }
445 
446  private:
447  //---------------------------------------------------------------------
448  int m_dx;
449  int m_dy;
450  int m_dx_start;
451  int m_dy_start;
452  int m_dx_end;
453  int m_dy_end;
454 
455  int m_dist;
456  int m_dist_start;
457  int m_dist_end;
458  };
459 
460 
461 
462 
463 
464  //================================================line_interpolator_aa_base
465  template<class Renderer> class line_interpolator_aa_base
466  {
467  public:
468  typedef Renderer renderer_type;
469  typedef typename Renderer::color_type color_type;
470 
471  //---------------------------------------------------------------------
472  enum max_half_width_e
473  {
474  max_half_width = 64
475  };
476 
477  //---------------------------------------------------------------------
478  line_interpolator_aa_base(renderer_type& ren, line_parameters& lp) :
479  m_lp(&lp),
480  m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) :
481  line_dbl_hr(lp.y2 - lp.y1),
482  lp.vertical ? std::abs(lp.y2 - lp.y1) :
483  std::abs(lp.x2 - lp.x1) + 1),
484  m_ren(ren),
485  m_len((lp.vertical == (lp.inc > 0)) ? -lp.len : lp.len),
486  m_x(lp.x1 >> line_subpixel_shift),
487  m_y(lp.y1 >> line_subpixel_shift),
488  m_old_x(m_x),
489  m_old_y(m_y),
490  m_count((lp.vertical ? std::abs((lp.y2 >> line_subpixel_shift) - m_y) :
491  std::abs((lp.x2 >> line_subpixel_shift) - m_x))),
492  m_width(ren.subpixel_width()),
493  //m_max_extent(m_width >> (line_subpixel_shift - 2)),
494  m_max_extent((m_width + line_subpixel_mask) >> line_subpixel_shift),
495  m_step(0)
496  {
497  agg::dda2_line_interpolator li(0, lp.vertical ?
498  (lp.dy << agg::line_subpixel_shift) :
499  (lp.dx << agg::line_subpixel_shift),
500  lp.len);
501 
502  unsigned i;
503  int stop = m_width + line_subpixel_scale * 2;
504  for(i = 0; i < max_half_width; ++i)
505  {
506  m_dist[i] = li.y();
507  if(m_dist[i] >= stop) break;
508  ++li;
509  }
510  m_dist[i++] = 0x7FFF0000;
511  }
512 
513  //---------------------------------------------------------------------
514  template<class DI> int step_hor_base(DI& di)
515  {
516  ++m_li;
517  m_x += m_lp->inc;
518  m_y = (m_lp->y1 + m_li.y()) >> line_subpixel_shift;
519 
520  if(m_lp->inc > 0) di.inc_x(m_y - m_old_y);
521  else di.dec_x(m_y - m_old_y);
522 
523  m_old_y = m_y;
524 
525  return di.dist() / m_len;
526  }
527 
528  //---------------------------------------------------------------------
529  template<class DI> int step_ver_base(DI& di)
530  {
531  ++m_li;
532  m_y += m_lp->inc;
533  m_x = (m_lp->x1 + m_li.y()) >> line_subpixel_shift;
534 
535  if(m_lp->inc > 0) di.inc_y(m_x - m_old_x);
536  else di.dec_y(m_x - m_old_x);
537 
538  m_old_x = m_x;
539 
540  return di.dist() / m_len;
541  }
542 
543  //---------------------------------------------------------------------
544  bool vertical() const { return m_lp->vertical; }
545  int width() const { return m_width; }
546  int count() const { return m_count; }
547 
548  private:
551  operator = (const line_interpolator_aa_base<Renderer>&);
552 
553  protected:
554  line_parameters* m_lp;
556  renderer_type& m_ren;
557  int m_len;
558  int m_x;
559  int m_y;
560  int m_old_x;
561  int m_old_y;
562  int m_count;
563  int m_width;
564  int m_max_extent;
565  int m_step;
566  int m_dist[max_half_width + 1];
567  cover_type m_covers[max_half_width * 2 + 4];
568  };
569 
570 
571 
572 
573 
574 
575 
576  //====================================================line_interpolator_aa0
577  template<class Renderer> class line_interpolator_aa0 :
578  public line_interpolator_aa_base<Renderer>
579  {
580  public:
581  typedef Renderer renderer_type;
582  typedef typename Renderer::color_type color_type;
584 
585  //---------------------------------------------------------------------
586  line_interpolator_aa0(renderer_type& ren, line_parameters& lp) :
588  m_di(lp.x1, lp.y1, lp.x2, lp.y2,
589  lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask)
590  {
591  base_type::m_li.adjust_forward();
592  }
593 
594  //---------------------------------------------------------------------
595  bool step_hor()
596  {
597  int dist;
598  int dy;
599  int s1 = base_type::step_hor_base(m_di);
600  cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
601  cover_type* p1 = p0;
602 
603  *p1++ = (cover_type)base_type::m_ren.cover(s1);
604 
605  dy = 1;
606  while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
607  {
608  *p1++ = (cover_type)base_type::m_ren.cover(dist);
609  ++dy;
610  }
611 
612  dy = 1;
613  while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
614  {
615  *--p0 = (cover_type)base_type::m_ren.cover(dist);
616  ++dy;
617  }
618  base_type::m_ren.blend_solid_vspan(base_type::m_x,
619  base_type::m_y - dy + 1,
620  unsigned(p1 - p0),
621  p0);
622  return ++base_type::m_step < base_type::m_count;
623  }
624 
625  //---------------------------------------------------------------------
626  bool step_ver()
627  {
628  int dist;
629  int dx;
630  int s1 = base_type::step_ver_base(m_di);
631  cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
632  cover_type* p1 = p0;
633 
634  *p1++ = (cover_type)base_type::m_ren.cover(s1);
635 
636  dx = 1;
637  while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
638  {
639  *p1++ = (cover_type)base_type::m_ren.cover(dist);
640  ++dx;
641  }
642 
643  dx = 1;
644  while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
645  {
646  *--p0 = (cover_type)base_type::m_ren.cover(dist);
647  ++dx;
648  }
649  base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
650  base_type::m_y,
651  unsigned(p1 - p0),
652  p0);
653  return ++base_type::m_step < base_type::m_count;
654  }
655 
656  private:
659  operator = (const line_interpolator_aa0<Renderer>&);
660 
661  //---------------------------------------------------------------------
663  };
664 
665 
666 
667 
668 
669 
670  //====================================================line_interpolator_aa1
671  template<class Renderer> class line_interpolator_aa1 :
672  public line_interpolator_aa_base<Renderer>
673  {
674  public:
675  typedef Renderer renderer_type;
676  typedef typename Renderer::color_type color_type;
678 
679  //---------------------------------------------------------------------
680  line_interpolator_aa1(renderer_type& ren, line_parameters& lp,
681  int sx, int sy) :
683  m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy,
684  lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask)
685  {
686  int dist1_start;
687  int dist2_start;
688 
689  int npix = 1;
690 
691  if(lp.vertical)
692  {
693  do
694  {
695  --base_type::m_li;
696  base_type::m_y -= lp.inc;
697  base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift;
698 
699  if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x);
700  else m_di.inc_y(base_type::m_x - base_type::m_old_x);
701 
702  base_type::m_old_x = base_type::m_x;
703 
704  dist1_start = dist2_start = m_di.dist_start();
705 
706  int dx = 0;
707  if(dist1_start < 0) ++npix;
708  do
709  {
710  dist1_start += m_di.dy_start();
711  dist2_start -= m_di.dy_start();
712  if(dist1_start < 0) ++npix;
713  if(dist2_start < 0) ++npix;
714  ++dx;
715  }
716  while(base_type::m_dist[dx] <= base_type::m_width);
717  --base_type::m_step;
718  if(npix == 0) break;
719  npix = 0;
720  }
721  while(base_type::m_step >= -base_type::m_max_extent);
722  }
723  else
724  {
725  do
726  {
727  --base_type::m_li;
728  base_type::m_x -= lp.inc;
729  base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift;
730 
731  if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y);
732  else m_di.inc_x(base_type::m_y - base_type::m_old_y);
733 
734  base_type::m_old_y = base_type::m_y;
735 
736  dist1_start = dist2_start = m_di.dist_start();
737 
738  int dy = 0;
739  if(dist1_start < 0) ++npix;
740  do
741  {
742  dist1_start -= m_di.dx_start();
743  dist2_start += m_di.dx_start();
744  if(dist1_start < 0) ++npix;
745  if(dist2_start < 0) ++npix;
746  ++dy;
747  }
748  while(base_type::m_dist[dy] <= base_type::m_width);
749  --base_type::m_step;
750  if(npix == 0) break;
751  npix = 0;
752  }
753  while(base_type::m_step >= -base_type::m_max_extent);
754  }
755  base_type::m_li.adjust_forward();
756  }
757 
758  //---------------------------------------------------------------------
759  bool step_hor()
760  {
761  int dist_start;
762  int dist;
763  int dy;
764  int s1 = base_type::step_hor_base(m_di);
765 
766  dist_start = m_di.dist_start();
767  cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
768  cover_type* p1 = p0;
769 
770  *p1 = 0;
771  if(dist_start <= 0)
772  {
773  *p1 = (cover_type)base_type::m_ren.cover(s1);
774  }
775  ++p1;
776 
777  dy = 1;
778  while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
779  {
780  dist_start -= m_di.dx_start();
781  *p1 = 0;
782  if(dist_start <= 0)
783  {
784  *p1 = (cover_type)base_type::m_ren.cover(dist);
785  }
786  ++p1;
787  ++dy;
788  }
789 
790  dy = 1;
791  dist_start = m_di.dist_start();
792  while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
793  {
794  dist_start += m_di.dx_start();
795  *--p0 = 0;
796  if(dist_start <= 0)
797  {
798  *p0 = (cover_type)base_type::m_ren.cover(dist);
799  }
800  ++dy;
801  }
802 
803  base_type::m_ren.blend_solid_vspan(base_type::m_x,
804  base_type::m_y - dy + 1,
805  unsigned(p1 - p0),
806  p0);
807  return ++base_type::m_step < base_type::m_count;
808  }
809 
810  //---------------------------------------------------------------------
811  bool step_ver()
812  {
813  int dist_start;
814  int dist;
815  int dx;
816  int s1 = base_type::step_ver_base(m_di);
817  cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
818  cover_type* p1 = p0;
819 
820  dist_start = m_di.dist_start();
821 
822  *p1 = 0;
823  if(dist_start <= 0)
824  {
825  *p1 = (cover_type)base_type::m_ren.cover(s1);
826  }
827  ++p1;
828 
829  dx = 1;
830  while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
831  {
832  dist_start += m_di.dy_start();
833  *p1 = 0;
834  if(dist_start <= 0)
835  {
836  *p1 = (cover_type)base_type::m_ren.cover(dist);
837  }
838  ++p1;
839  ++dx;
840  }
841 
842  dx = 1;
843  dist_start = m_di.dist_start();
844  while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
845  {
846  dist_start -= m_di.dy_start();
847  *--p0 = 0;
848  if(dist_start <= 0)
849  {
850  *p0 = (cover_type)base_type::m_ren.cover(dist);
851  }
852  ++dx;
853  }
854  base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
855  base_type::m_y,
856  unsigned(p1 - p0),
857  p0);
858  return ++base_type::m_step < base_type::m_count;
859  }
860 
861  private:
864  operator = (const line_interpolator_aa1<Renderer>&);
865 
866  //---------------------------------------------------------------------
868  };
869 
870 
871 
872 
873 
874 
875 
876 
877 
878 
879 
880 
881  //====================================================line_interpolator_aa2
882  template<class Renderer> class line_interpolator_aa2 :
883  public line_interpolator_aa_base<Renderer>
884  {
885  public:
886  typedef Renderer renderer_type;
887  typedef typename Renderer::color_type color_type;
889 
890  //---------------------------------------------------------------------
891  line_interpolator_aa2(renderer_type& ren, line_parameters& lp,
892  int ex, int ey) :
894  m_di(lp.x1, lp.y1, lp.x2, lp.y2, ex, ey,
895  lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask,
896  0)
897  {
898  base_type::m_li.adjust_forward();
899  base_type::m_step -= base_type::m_max_extent;
900  }
901 
902  //---------------------------------------------------------------------
903  bool step_hor()
904  {
905  int dist_end;
906  int dist;
907  int dy;
908  int s1 = base_type::step_hor_base(m_di);
909  cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
910  cover_type* p1 = p0;
911 
912  dist_end = m_di.dist_end();
913 
914  int npix = 0;
915  *p1 = 0;
916  if(dist_end > 0)
917  {
918  *p1 = (cover_type)base_type::m_ren.cover(s1);
919  ++npix;
920  }
921  ++p1;
922 
923  dy = 1;
924  while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
925  {
926  dist_end -= m_di.dx_end();
927  *p1 = 0;
928  if(dist_end > 0)
929  {
930  *p1 = (cover_type)base_type::m_ren.cover(dist);
931  ++npix;
932  }
933  ++p1;
934  ++dy;
935  }
936 
937  dy = 1;
938  dist_end = m_di.dist_end();
939  while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
940  {
941  dist_end += m_di.dx_end();
942  *--p0 = 0;
943  if(dist_end > 0)
944  {
945  *p0 = (cover_type)base_type::m_ren.cover(dist);
946  ++npix;
947  }
948  ++dy;
949  }
950  base_type::m_ren.blend_solid_vspan(base_type::m_x,
951  base_type::m_y - dy + 1,
952  unsigned(p1 - p0),
953  p0);
954  return npix && ++base_type::m_step < base_type::m_count;
955  }
956 
957  //---------------------------------------------------------------------
958  bool step_ver()
959  {
960  int dist_end;
961  int dist;
962  int dx;
963  int s1 = base_type::step_ver_base(m_di);
964  cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
965  cover_type* p1 = p0;
966 
967  dist_end = m_di.dist_end();
968 
969  int npix = 0;
970  *p1 = 0;
971  if(dist_end > 0)
972  {
973  *p1 = (cover_type)base_type::m_ren.cover(s1);
974  ++npix;
975  }
976  ++p1;
977 
978  dx = 1;
979  while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
980  {
981  dist_end += m_di.dy_end();
982  *p1 = 0;
983  if(dist_end > 0)
984  {
985  *p1 = (cover_type)base_type::m_ren.cover(dist);
986  ++npix;
987  }
988  ++p1;
989  ++dx;
990  }
991 
992  dx = 1;
993  dist_end = m_di.dist_end();
994  while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
995  {
996  dist_end -= m_di.dy_end();
997  *--p0 = 0;
998  if(dist_end > 0)
999  {
1000  *p0 = (cover_type)base_type::m_ren.cover(dist);
1001  ++npix;
1002  }
1003  ++dx;
1004  }
1005  base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
1006  base_type::m_y,
1007  unsigned(p1 - p0),
1008  p0);
1009  return npix && ++base_type::m_step < base_type::m_count;
1010  }
1011 
1012  private:
1015  operator = (const line_interpolator_aa2<Renderer>&);
1016 
1017  //---------------------------------------------------------------------
1018  distance_interpolator2 m_di;
1019  };
1020 
1021 
1022 
1023 
1024 
1025 
1026 
1027 
1028 
1029 
1030  //====================================================line_interpolator_aa3
1031  template<class Renderer> class line_interpolator_aa3 :
1032  public line_interpolator_aa_base<Renderer>
1033  {
1034  public:
1035  typedef Renderer renderer_type;
1036  typedef typename Renderer::color_type color_type;
1038 
1039  //---------------------------------------------------------------------
1040  line_interpolator_aa3(renderer_type& ren, line_parameters& lp,
1041  int sx, int sy, int ex, int ey) :
1043  m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey,
1044  lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask)
1045  {
1046  int dist1_start;
1047  int dist2_start;
1048  int npix = 1;
1049  if(lp.vertical)
1050  {
1051  do
1052  {
1053  --base_type::m_li;
1054  base_type::m_y -= lp.inc;
1055  base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift;
1056 
1057  if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x);
1058  else m_di.inc_y(base_type::m_x - base_type::m_old_x);
1059 
1060  base_type::m_old_x = base_type::m_x;
1061 
1062  dist1_start = dist2_start = m_di.dist_start();
1063 
1064  int dx = 0;
1065  if(dist1_start < 0) ++npix;
1066  do
1067  {
1068  dist1_start += m_di.dy_start();
1069  dist2_start -= m_di.dy_start();
1070  if(dist1_start < 0) ++npix;
1071  if(dist2_start < 0) ++npix;
1072  ++dx;
1073  }
1074  while(base_type::m_dist[dx] <= base_type::m_width);
1075  if(npix == 0) break;
1076  npix = 0;
1077  }
1078  while(--base_type::m_step >= -base_type::m_max_extent);
1079  }
1080  else
1081  {
1082  do
1083  {
1084  --base_type::m_li;
1085  base_type::m_x -= lp.inc;
1086  base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift;
1087 
1088  if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y);
1089  else m_di.inc_x(base_type::m_y - base_type::m_old_y);
1090 
1091  base_type::m_old_y = base_type::m_y;
1092 
1093  dist1_start = dist2_start = m_di.dist_start();
1094 
1095  int dy = 0;
1096  if(dist1_start < 0) ++npix;
1097  do
1098  {
1099  dist1_start -= m_di.dx_start();
1100  dist2_start += m_di.dx_start();
1101  if(dist1_start < 0) ++npix;
1102  if(dist2_start < 0) ++npix;
1103  ++dy;
1104  }
1105  while(base_type::m_dist[dy] <= base_type::m_width);
1106  if(npix == 0) break;
1107  npix = 0;
1108  }
1109  while(--base_type::m_step >= -base_type::m_max_extent);
1110  }
1111  base_type::m_li.adjust_forward();
1112  base_type::m_step -= base_type::m_max_extent;
1113  }
1114 
1115 
1116  //---------------------------------------------------------------------
1117  bool step_hor()
1118  {
1119  int dist_start;
1120  int dist_end;
1121  int dist;
1122  int dy;
1123  int s1 = base_type::step_hor_base(m_di);
1124  cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
1125  cover_type* p1 = p0;
1126 
1127  dist_start = m_di.dist_start();
1128  dist_end = m_di.dist_end();
1129 
1130  int npix = 0;
1131  *p1 = 0;
1132  if(dist_end > 0)
1133  {
1134  if(dist_start <= 0)
1135  {
1136  *p1 = (cover_type)base_type::m_ren.cover(s1);
1137  }
1138  ++npix;
1139  }
1140  ++p1;
1141 
1142  dy = 1;
1143  while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
1144  {
1145  dist_start -= m_di.dx_start();
1146  dist_end -= m_di.dx_end();
1147  *p1 = 0;
1148  if(dist_end > 0 && dist_start <= 0)
1149  {
1150  *p1 = (cover_type)base_type::m_ren.cover(dist);
1151  ++npix;
1152  }
1153  ++p1;
1154  ++dy;
1155  }
1156 
1157  dy = 1;
1158  dist_start = m_di.dist_start();
1159  dist_end = m_di.dist_end();
1160  while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
1161  {
1162  dist_start += m_di.dx_start();
1163  dist_end += m_di.dx_end();
1164  *--p0 = 0;
1165  if(dist_end > 0 && dist_start <= 0)
1166  {
1167  *p0 = (cover_type)base_type::m_ren.cover(dist);
1168  ++npix;
1169  }
1170  ++dy;
1171  }
1172  base_type::m_ren.blend_solid_vspan(base_type::m_x,
1173  base_type::m_y - dy + 1,
1174  unsigned(p1 - p0),
1175  p0);
1176  return npix && ++base_type::m_step < base_type::m_count;
1177  }
1178 
1179  //---------------------------------------------------------------------
1180  bool step_ver()
1181  {
1182  int dist_start;
1183  int dist_end;
1184  int dist;
1185  int dx;
1186  int s1 = base_type::step_ver_base(m_di);
1187  cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
1188  cover_type* p1 = p0;
1189 
1190  dist_start = m_di.dist_start();
1191  dist_end = m_di.dist_end();
1192 
1193  int npix = 0;
1194  *p1 = 0;
1195  if(dist_end > 0)
1196  {
1197  if(dist_start <= 0)
1198  {
1199  *p1 = (cover_type)base_type::m_ren.cover(s1);
1200  }
1201  ++npix;
1202  }
1203  ++p1;
1204 
1205  dx = 1;
1206  while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
1207  {
1208  dist_start += m_di.dy_start();
1209  dist_end += m_di.dy_end();
1210  *p1 = 0;
1211  if(dist_end > 0 && dist_start <= 0)
1212  {
1213  *p1 = (cover_type)base_type::m_ren.cover(dist);
1214  ++npix;
1215  }
1216  ++p1;
1217  ++dx;
1218  }
1219 
1220  dx = 1;
1221  dist_start = m_di.dist_start();
1222  dist_end = m_di.dist_end();
1223  while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
1224  {
1225  dist_start -= m_di.dy_start();
1226  dist_end -= m_di.dy_end();
1227  *--p0 = 0;
1228  if(dist_end > 0 && dist_start <= 0)
1229  {
1230  *p0 = (cover_type)base_type::m_ren.cover(dist);
1231  ++npix;
1232  }
1233  ++dx;
1234  }
1235  base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
1236  base_type::m_y,
1237  unsigned(p1 - p0),
1238  p0);
1239  return npix && ++base_type::m_step < base_type::m_count;
1240  }
1241 
1242  private:
1245  operator = (const line_interpolator_aa3<Renderer>&);
1246 
1247  //---------------------------------------------------------------------
1248  distance_interpolator3 m_di;
1249  };
1250 
1251 
1252 
1253 
1254  //==========================================================line_profile_aa
1255  //
1256  // See Implementation agg_line_profile_aa.cpp
1257  //
1259  {
1260  public:
1261  //---------------------------------------------------------------------
1262  typedef int8u value_type;
1263  enum subpixel_scale_e
1264  {
1265  subpixel_shift = line_subpixel_shift,
1266  subpixel_scale = 1 << subpixel_shift,
1267  subpixel_mask = subpixel_scale - 1
1268  };
1269 
1270  enum aa_scale_e
1271  {
1272  aa_shift = 8,
1273  aa_scale = 1 << aa_shift,
1274  aa_mask = aa_scale - 1
1275  };
1276 
1277  //---------------------------------------------------------------------
1278  line_profile_aa() :
1279  m_subpixel_width(0),
1280  m_min_width(1.0),
1281  m_smoother_width(1.0)
1282  {
1283  int i;
1284  for(i = 0; i < aa_scale; i++) m_gamma[i] = (value_type)i;
1285  }
1286 
1287  //---------------------------------------------------------------------
1288  template<class GammaF>
1289  line_profile_aa(double w, const GammaF& gamma_function) :
1290  m_subpixel_width(0),
1291  m_min_width(1.0),
1292  m_smoother_width(1.0)
1293  {
1294  gamma(gamma_function);
1295  width(w);
1296  }
1297 
1298  //---------------------------------------------------------------------
1299  void min_width(double w) { m_min_width = w; }
1300  void smoother_width(double w) { m_smoother_width = w; }
1301 
1302  //---------------------------------------------------------------------
1303  template<class GammaF> void gamma(const GammaF& gamma_function)
1304  {
1305  int i;
1306  for(i = 0; i < aa_scale; i++)
1307  {
1308  m_gamma[i] = value_type(
1309  uround(gamma_function(double(i) / aa_mask) * aa_mask));
1310  }
1311  }
1312 
1313  void width(double w);
1314 
1315  unsigned profile_size() const { return m_profile.size(); }
1316  int subpixel_width() const { return m_subpixel_width; }
1317 
1318  //---------------------------------------------------------------------
1319  double min_width() const { return m_min_width; }
1320  double smoother_width() const { return m_smoother_width; }
1321 
1322  //---------------------------------------------------------------------
1323  value_type value(int dist) const
1324  {
1325  return m_profile[dist + subpixel_scale*2];
1326  }
1327 
1328  private:
1330  const line_profile_aa& operator = (const line_profile_aa&);
1331 
1332  value_type* profile(double w);
1333  void set(double center_width, double smoother_width);
1334 
1335  //---------------------------------------------------------------------
1336  pod_array<value_type> m_profile;
1337  value_type m_gamma[aa_scale];
1338  int m_subpixel_width;
1339  double m_min_width;
1340  double m_smoother_width;
1341  };
1342 
1343 
1344  //======================================================renderer_outline_aa
1345  template<class BaseRenderer> class renderer_outline_aa
1346  {
1347  public:
1348  //---------------------------------------------------------------------
1349  typedef BaseRenderer base_ren_type;
1351  typedef typename base_ren_type::color_type color_type;
1352 
1353  //---------------------------------------------------------------------
1354  renderer_outline_aa(base_ren_type& ren, line_profile_aa& prof) :
1355  m_ren(&ren),
1356  m_profile(&prof),
1357  m_clip_box(0,0,0,0),
1358  m_clipping(false)
1359  {}
1360  void attach(base_ren_type& ren) { m_ren = &ren; }
1361 
1362  //---------------------------------------------------------------------
1363  void color(const color_type& c) { m_color = c; }
1364  const color_type& color() const { return m_color; }
1365 
1366  //---------------------------------------------------------------------
1367  void profile(line_profile_aa& prof) { m_profile = &prof; }
1368  const line_profile_aa& profile() const { return *m_profile; }
1369  line_profile_aa& profile() { return *m_profile; }
1370 
1371  //---------------------------------------------------------------------
1372  int subpixel_width() const { return m_profile->subpixel_width(); }
1373 
1374  //---------------------------------------------------------------------
1375  void reset_clipping() { m_clipping = false; }
1376  void clip_box(double x1, double y1, double x2, double y2)
1377  {
1378  m_clip_box.x1 = line_coord_sat::conv(x1);
1379  m_clip_box.y1 = line_coord_sat::conv(y1);
1380  m_clip_box.x2 = line_coord_sat::conv(x2);
1381  m_clip_box.y2 = line_coord_sat::conv(y2);
1382  m_clipping = true;
1383  }
1384 
1385  //---------------------------------------------------------------------
1386  int cover(int d) const
1387  {
1388  return m_profile->value(d);
1389  }
1390 
1391  //-------------------------------------------------------------------------
1392  void blend_solid_hspan(int x, int y, unsigned len, const cover_type* covers)
1393  {
1394  m_ren->blend_solid_hspan(x, y, len, m_color, covers);
1395  }
1396 
1397  //-------------------------------------------------------------------------
1398  void blend_solid_vspan(int x, int y, unsigned len, const cover_type* covers)
1399  {
1400  m_ren->blend_solid_vspan(x, y, len, m_color, covers);
1401  }
1402 
1403  //-------------------------------------------------------------------------
1404  static bool accurate_join_only() { return false; }
1405 
1406  //-------------------------------------------------------------------------
1407  template<class Cmp>
1408  void semidot_hline(Cmp cmp,
1409  int xc1, int yc1, int xc2, int yc2,
1410  int x1, int y1, int x2)
1411  {
1412  cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4];
1413  cover_type* p0 = covers;
1414  cover_type* p1 = covers;
1415  int x = x1 << line_subpixel_shift;
1416  int y = y1 << line_subpixel_shift;
1417  int w = subpixel_width();
1418  distance_interpolator0 di(xc1, yc1, xc2, yc2, x, y);
1419  x += line_subpixel_scale/2;
1420  y += line_subpixel_scale/2;
1421 
1422  int x0 = x1;
1423  int dx = x - xc1;
1424  int dy = y - yc1;
1425  do
1426  {
1427  int d = int(fast_sqrt(dx*dx + dy*dy));
1428  *p1 = 0;
1429  if(cmp(di.dist()) && d <= w)
1430  {
1431  *p1 = (cover_type)cover(d);
1432  }
1433  ++p1;
1434  dx += line_subpixel_scale;
1435  di.inc_x();
1436  }
1437  while(++x1 <= x2);
1438  m_ren->blend_solid_hspan(x0, y1,
1439  unsigned(p1 - p0),
1440  color(),
1441  p0);
1442  }
1443 
1444  //-------------------------------------------------------------------------
1445  template<class Cmp>
1446  void semidot(Cmp cmp, int xc1, int yc1, int xc2, int yc2)
1447  {
1448  if(m_clipping && clipping_flags(xc1, yc1, m_clip_box)) return;
1449 
1450  int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift);
1451  if(r < 1) r = 1;
1453  int dx = 0;
1454  int dy = -r;
1455  int dy0 = dy;
1456  int dx0 = dx;
1457  int x = xc1 >> line_subpixel_shift;
1458  int y = yc1 >> line_subpixel_shift;
1459 
1460  do
1461  {
1462  dx += ei.dx();
1463  dy += ei.dy();
1464 
1465  if(dy != dy0)
1466  {
1467  semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0);
1468  semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y-dy0, x+dx0);
1469  }
1470  dx0 = dx;
1471  dy0 = dy;
1472  ++ei;
1473  }
1474  while(dy < 0);
1475  semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0);
1476  }
1477 
1478  //-------------------------------------------------------------------------
1479  void pie_hline(int xc, int yc, int xp1, int yp1, int xp2, int yp2,
1480  int xh1, int yh1, int xh2)
1481  {
1482  if(m_clipping && clipping_flags(xc, yc, m_clip_box)) return;
1483 
1484  cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4];
1485  cover_type* p0 = covers;
1486  cover_type* p1 = covers;
1487  int x = xh1 << line_subpixel_shift;
1488  int y = yh1 << line_subpixel_shift;
1489  int w = subpixel_width();
1490 
1491  distance_interpolator00 di(xc, yc, xp1, yp1, xp2, yp2, x, y);
1492  x += line_subpixel_scale/2;
1493  y += line_subpixel_scale/2;
1494 
1495  int xh0 = xh1;
1496  int dx = x - xc;
1497  int dy = y - yc;
1498  do
1499  {
1500  int d = int(fast_sqrt(dx*dx + dy*dy));
1501  *p1 = 0;
1502  if(di.dist1() <= 0 && di.dist2() > 0 && d <= w)
1503  {
1504  *p1 = (cover_type)cover(d);
1505  }
1506  ++p1;
1507  dx += line_subpixel_scale;
1508  di.inc_x();
1509  }
1510  while(++xh1 <= xh2);
1511  m_ren->blend_solid_hspan(xh0, yh1,
1512  unsigned(p1 - p0),
1513  color(),
1514  p0);
1515  }
1516 
1517 
1518  //-------------------------------------------------------------------------
1519  void pie(int xc, int yc, int x1, int y1, int x2, int y2)
1520  {
1521  int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift);
1522  if(r < 1) r = 1;
1524  int dx = 0;
1525  int dy = -r;
1526  int dy0 = dy;
1527  int dx0 = dx;
1528  int x = xc >> line_subpixel_shift;
1529  int y = yc >> line_subpixel_shift;
1530 
1531  do
1532  {
1533  dx += ei.dx();
1534  dy += ei.dy();
1535 
1536  if(dy != dy0)
1537  {
1538  pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0);
1539  pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y-dy0, x+dx0);
1540  }
1541  dx0 = dx;
1542  dy0 = dy;
1543  ++ei;
1544  }
1545  while(dy < 0);
1546  pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0);
1547  }
1548 
1549  //-------------------------------------------------------------------------
1550  void line0_no_clip(line_parameters& lp)
1551  {
1552  if(lp.len > line_max_length)
1553  {
1554  line_parameters lp1, lp2;
1555  lp.divide(lp1, lp2);
1556  line0_no_clip(lp1);
1557  line0_no_clip(lp2);
1558  return;
1559  }
1560 
1561  line_interpolator_aa0<self_type> li(*this, lp);
1562  if(li.count())
1563  {
1564  if(li.vertical())
1565  {
1566  while(li.step_ver());
1567  }
1568  else
1569  {
1570  while(li.step_hor());
1571  }
1572  }
1573  }
1574 
1575  //-------------------------------------------------------------------------
1576  void line0(line_parameters& lp)
1577  {
1578  if(m_clipping)
1579  {
1580  int x1 = lp.x1;
1581  int y1 = lp.y1;
1582  int x2 = lp.x2;
1583  int y2 = lp.y2;
1584  unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1585  if((flags & 4) == 0)
1586  {
1587  if(flags)
1588  {
1589  line_parameters lp2(x1, y1, x2, y2,
1590  uround(calc_distance(x1, y1, x2, y2)));
1591  line0_no_clip(lp2);
1592  }
1593  else
1594  {
1595  line0_no_clip(lp);
1596  }
1597  }
1598  }
1599  else
1600  {
1601  line0_no_clip(lp);
1602  }
1603  }
1604 
1605  //-------------------------------------------------------------------------
1606  void line1_no_clip(line_parameters& lp, int sx, int sy)
1607  {
1608  if(lp.len > line_max_length)
1609  {
1610  line_parameters lp1, lp2;
1611  lp.divide(lp1, lp2);
1612  line1_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1);
1613  line1_no_clip(lp2, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1));
1614  return;
1615  }
1616 
1617  fix_degenerate_bisectrix_start(lp, &sx, &sy);
1618  line_interpolator_aa1<self_type> li(*this, lp, sx, sy);
1619  if(li.vertical())
1620  {
1621  while(li.step_ver());
1622  }
1623  else
1624  {
1625  while(li.step_hor());
1626  }
1627  }
1628 
1629 
1630  //-------------------------------------------------------------------------
1631  void line1(line_parameters& lp, int sx, int sy)
1632  {
1633  if(m_clipping)
1634  {
1635  int x1 = lp.x1;
1636  int y1 = lp.y1;
1637  int x2 = lp.x2;
1638  int y2 = lp.y2;
1639  unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1640  if((flags & 4) == 0)
1641  {
1642  if(flags)
1643  {
1644  line_parameters lp2(x1, y1, x2, y2,
1645  uround(calc_distance(x1, y1, x2, y2)));
1646  if(flags & 1)
1647  {
1648  sx = x1 + (y2 - y1);
1649  sy = y1 - (x2 - x1);
1650  }
1651  else
1652  {
1653  while(std::abs(sx - lp.x1) + std::abs(sy - lp.y1) > lp2.len)
1654  {
1655  sx = (lp.x1 + sx) >> 1;
1656  sy = (lp.y1 + sy) >> 1;
1657  }
1658  }
1659  line1_no_clip(lp2, sx, sy);
1660  }
1661  else
1662  {
1663  line1_no_clip(lp, sx, sy);
1664  }
1665  }
1666  }
1667  else
1668  {
1669  line1_no_clip(lp, sx, sy);
1670  }
1671  }
1672 
1673  //-------------------------------------------------------------------------
1674  void line2_no_clip(line_parameters& lp, int ex, int ey)
1675  {
1676  if(lp.len > line_max_length)
1677  {
1678  line_parameters lp1, lp2;
1679  lp.divide(lp1, lp2);
1680  line2_no_clip(lp1, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1));
1681  line2_no_clip(lp2, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
1682  return;
1683  }
1684 
1685  fix_degenerate_bisectrix_end(lp, &ex, &ey);
1686  line_interpolator_aa2<self_type> li(*this, lp, ex, ey);
1687  if(li.vertical())
1688  {
1689  while(li.step_ver());
1690  }
1691  else
1692  {
1693  while(li.step_hor());
1694  }
1695  }
1696 
1697  //-------------------------------------------------------------------------
1698  void line2(line_parameters& lp, int ex, int ey)
1699  {
1700  if(m_clipping)
1701  {
1702  int x1 = lp.x1;
1703  int y1 = lp.y1;
1704  int x2 = lp.x2;
1705  int y2 = lp.y2;
1706  unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1707  if((flags & 4) == 0)
1708  {
1709  if(flags)
1710  {
1711  line_parameters lp2(x1, y1, x2, y2,
1712  uround(calc_distance(x1, y1, x2, y2)));
1713  if(flags & 2)
1714  {
1715  ex = x2 + (y2 - y1);
1716  ey = y2 - (x2 - x1);
1717  }
1718  else
1719  {
1720  while(std::abs(ex - lp.x2) + std::abs(ey - lp.y2) > lp2.len)
1721  {
1722  ex = (lp.x2 + ex) >> 1;
1723  ey = (lp.y2 + ey) >> 1;
1724  }
1725  }
1726  line2_no_clip(lp2, ex, ey);
1727  }
1728  else
1729  {
1730  line2_no_clip(lp, ex, ey);
1731  }
1732  }
1733  }
1734  else
1735  {
1736  line2_no_clip(lp, ex, ey);
1737  }
1738  }
1739 
1740  //-------------------------------------------------------------------------
1741  void line3_no_clip(line_parameters& lp,
1742  int sx, int sy, int ex, int ey)
1743  {
1744  if(lp.len > line_max_length)
1745  {
1746  line_parameters lp1, lp2;
1747  lp.divide(lp1, lp2);
1748  int mx = lp1.x2 + (lp1.y2 - lp1.y1);
1749  int my = lp1.y2 - (lp1.x2 - lp1.x1);
1750  line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my);
1751  line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
1752  return;
1753  }
1754 
1755  fix_degenerate_bisectrix_start(lp, &sx, &sy);
1756  fix_degenerate_bisectrix_end(lp, &ex, &ey);
1757  line_interpolator_aa3<self_type> li(*this, lp, sx, sy, ex, ey);
1758  if(li.vertical())
1759  {
1760  while(li.step_ver());
1761  }
1762  else
1763  {
1764  while(li.step_hor());
1765  }
1766  }
1767 
1768  //-------------------------------------------------------------------------
1769  void line3(line_parameters& lp,
1770  int sx, int sy, int ex, int ey)
1771  {
1772  if(m_clipping)
1773  {
1774  int x1 = lp.x1;
1775  int y1 = lp.y1;
1776  int x2 = lp.x2;
1777  int y2 = lp.y2;
1778  unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1779  if((flags & 4) == 0)
1780  {
1781  if(flags)
1782  {
1783  line_parameters lp2(x1, y1, x2, y2,
1784  uround(calc_distance(x1, y1, x2, y2)));
1785  if(flags & 1)
1786  {
1787  sx = x1 + (y2 - y1);
1788  sy = y1 - (x2 - x1);
1789  }
1790  else
1791  {
1792  while(std::abs(sx - lp.x1) + std::abs(sy - lp.y1) > lp2.len)
1793  {
1794  sx = (lp.x1 + sx) >> 1;
1795  sy = (lp.y1 + sy) >> 1;
1796  }
1797  }
1798  if(flags & 2)
1799  {
1800  ex = x2 + (y2 - y1);
1801  ey = y2 - (x2 - x1);
1802  }
1803  else
1804  {
1805  while(std::abs(ex - lp.x2) + std::abs(ey - lp.y2) > lp2.len)
1806  {
1807  ex = (lp.x2 + ex) >> 1;
1808  ey = (lp.y2 + ey) >> 1;
1809  }
1810  }
1811  line3_no_clip(lp2, sx, sy, ex, ey);
1812  }
1813  else
1814  {
1815  line3_no_clip(lp, sx, sy, ex, ey);
1816  }
1817  }
1818  }
1819  else
1820  {
1821  line3_no_clip(lp, sx, sy, ex, ey);
1822  }
1823  }
1824 
1825 
1826  private:
1827  base_ren_type* m_ren;
1828  line_profile_aa* m_profile;
1829  color_type m_color;
1830  rect_i m_clip_box;
1831  bool m_clipping;
1832  };
1833 
1834 
1835 
1836 }
1837 
1838 #endif
Definition: agg_arc.cpp:24