btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / libs / agg / agg_renderer_outline_aa.h
blobf9c7674cb91ad3d8887b65cd2e364b9d528fe687
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
18 #include "agg_array.h"
19 #include "agg_math.h"
20 #include "agg_line_aa_basics.h"
21 #include "agg_dda_line.h"
22 #include "agg_ellipse_bresenham.h"
23 #include "agg_renderer_base.h"
24 #include "agg_gamma_functions.h"
25 #include "agg_clip_liang_barsky.h"
27 namespace agg
30 //===================================================distance_interpolator0
31 class distance_interpolator0
33 public:
34 //---------------------------------------------------------------------
35 distance_interpolator0() {}
36 distance_interpolator0(int x1, int y1, int x2, int y2, int x, int y) :
37 m_dx(line_mr(x2) - line_mr(x1)),
38 m_dy(line_mr(y2) - line_mr(y1)),
39 m_dist((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy -
40 (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx)
42 m_dx <<= line_mr_subpixel_shift;
43 m_dy <<= line_mr_subpixel_shift;
46 //---------------------------------------------------------------------
47 void inc_x() { m_dist += m_dy; }
48 int dist() const { return m_dist; }
50 private:
51 //---------------------------------------------------------------------
52 int m_dx;
53 int m_dy;
54 int m_dist;
57 //==================================================distance_interpolator00
58 class distance_interpolator00
60 public:
61 //---------------------------------------------------------------------
62 distance_interpolator00() {}
63 distance_interpolator00(int xc, int yc,
64 int x1, int y1, int x2, int y2,
65 int x, int y) :
66 m_dx1(line_mr(x1) - line_mr(xc)),
67 m_dy1(line_mr(y1) - line_mr(yc)),
68 m_dx2(line_mr(x2) - line_mr(xc)),
69 m_dy2(line_mr(y2) - line_mr(yc)),
70 m_dist1((line_mr(x + line_subpixel_scale/2) - line_mr(x1)) * m_dy1 -
71 (line_mr(y + line_subpixel_scale/2) - line_mr(y1)) * m_dx1),
72 m_dist2((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy2 -
73 (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx2)
75 m_dx1 <<= line_mr_subpixel_shift;
76 m_dy1 <<= line_mr_subpixel_shift;
77 m_dx2 <<= line_mr_subpixel_shift;
78 m_dy2 <<= line_mr_subpixel_shift;
81 //---------------------------------------------------------------------
82 void inc_x() { m_dist1 += m_dy1; m_dist2 += m_dy2; }
83 int dist1() const { return m_dist1; }
84 int dist2() const { return m_dist2; }
86 private:
87 //---------------------------------------------------------------------
88 int m_dx1;
89 int m_dy1;
90 int m_dx2;
91 int m_dy2;
92 int m_dist1;
93 int m_dist2;
96 //===================================================distance_interpolator1
97 class distance_interpolator1
99 public:
100 //---------------------------------------------------------------------
101 distance_interpolator1() {}
102 distance_interpolator1(int x1, int y1, int x2, int y2, int x, int y) :
103 m_dx(x2 - x1),
104 m_dy(y2 - y1),
105 m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) -
106 double(y + line_subpixel_scale/2 - y2) * double(m_dx)))
108 m_dx <<= line_subpixel_shift;
109 m_dy <<= line_subpixel_shift;
112 //---------------------------------------------------------------------
113 void inc_x() { m_dist += m_dy; }
114 void dec_x() { m_dist -= m_dy; }
115 void inc_y() { m_dist -= m_dx; }
116 void dec_y() { m_dist += m_dx; }
118 //---------------------------------------------------------------------
119 void inc_x(int dy)
121 m_dist += m_dy;
122 if(dy > 0) m_dist -= m_dx;
123 if(dy < 0) m_dist += m_dx;
126 //---------------------------------------------------------------------
127 void dec_x(int dy)
129 m_dist -= m_dy;
130 if(dy > 0) m_dist -= m_dx;
131 if(dy < 0) m_dist += m_dx;
134 //---------------------------------------------------------------------
135 void inc_y(int dx)
137 m_dist -= m_dx;
138 if(dx > 0) m_dist += m_dy;
139 if(dx < 0) m_dist -= m_dy;
142 void dec_y(int dx)
143 //---------------------------------------------------------------------
145 m_dist += m_dx;
146 if(dx > 0) m_dist += m_dy;
147 if(dx < 0) m_dist -= m_dy;
150 //---------------------------------------------------------------------
151 int dist() const { return m_dist; }
152 int dx() const { return m_dx; }
153 int dy() const { return m_dy; }
155 private:
156 //---------------------------------------------------------------------
157 int m_dx;
158 int m_dy;
159 int m_dist;
166 //===================================================distance_interpolator2
167 class distance_interpolator2
169 public:
170 //---------------------------------------------------------------------
171 distance_interpolator2() {}
172 distance_interpolator2(int x1, int y1, int x2, int y2,
173 int sx, int sy, int x, int y) :
174 m_dx(x2 - x1),
175 m_dy(y2 - y1),
176 m_dx_start(line_mr(sx) - line_mr(x1)),
177 m_dy_start(line_mr(sy) - line_mr(y1)),
179 m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) -
180 double(y + line_subpixel_scale/2 - y2) * double(m_dx))),
182 m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start -
183 (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start)
185 m_dx <<= line_subpixel_shift;
186 m_dy <<= line_subpixel_shift;
187 m_dx_start <<= line_mr_subpixel_shift;
188 m_dy_start <<= line_mr_subpixel_shift;
191 distance_interpolator2(int x1, int y1, int x2, int y2,
192 int ex, int ey, int x, int y, int) :
193 m_dx(x2 - x1),
194 m_dy(y2 - y1),
195 m_dx_start(line_mr(ex) - line_mr(x2)),
196 m_dy_start(line_mr(ey) - line_mr(y2)),
198 m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) -
199 double(y + line_subpixel_scale/2 - y2) * double(m_dx))),
201 m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_start -
202 (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_start)
204 m_dx <<= line_subpixel_shift;
205 m_dy <<= line_subpixel_shift;
206 m_dx_start <<= line_mr_subpixel_shift;
207 m_dy_start <<= line_mr_subpixel_shift;
211 //---------------------------------------------------------------------
212 void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; }
213 void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; }
214 void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; }
215 void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; }
217 //---------------------------------------------------------------------
218 void inc_x(int dy)
220 m_dist += m_dy;
221 m_dist_start += m_dy_start;
222 if(dy > 0)
224 m_dist -= m_dx;
225 m_dist_start -= m_dx_start;
227 if(dy < 0)
229 m_dist += m_dx;
230 m_dist_start += m_dx_start;
234 //---------------------------------------------------------------------
235 void dec_x(int dy)
237 m_dist -= m_dy;
238 m_dist_start -= m_dy_start;
239 if(dy > 0)
241 m_dist -= m_dx;
242 m_dist_start -= m_dx_start;
244 if(dy < 0)
246 m_dist += m_dx;
247 m_dist_start += m_dx_start;
251 //---------------------------------------------------------------------
252 void inc_y(int dx)
254 m_dist -= m_dx;
255 m_dist_start -= m_dx_start;
256 if(dx > 0)
258 m_dist += m_dy;
259 m_dist_start += m_dy_start;
261 if(dx < 0)
263 m_dist -= m_dy;
264 m_dist_start -= m_dy_start;
268 //---------------------------------------------------------------------
269 void dec_y(int dx)
271 m_dist += m_dx;
272 m_dist_start += m_dx_start;
273 if(dx > 0)
275 m_dist += m_dy;
276 m_dist_start += m_dy_start;
278 if(dx < 0)
280 m_dist -= m_dy;
281 m_dist_start -= m_dy_start;
285 //---------------------------------------------------------------------
286 int dist() const { return m_dist; }
287 int dist_start() const { return m_dist_start; }
288 int dist_end() const { return m_dist_start; }
290 //---------------------------------------------------------------------
291 int dx() const { return m_dx; }
292 int dy() const { return m_dy; }
293 int dx_start() const { return m_dx_start; }
294 int dy_start() const { return m_dy_start; }
295 int dx_end() const { return m_dx_start; }
296 int dy_end() const { return m_dy_start; }
298 private:
299 //---------------------------------------------------------------------
300 int m_dx;
301 int m_dy;
302 int m_dx_start;
303 int m_dy_start;
305 int m_dist;
306 int m_dist_start;
313 //===================================================distance_interpolator3
314 class distance_interpolator3
316 public:
317 //---------------------------------------------------------------------
318 distance_interpolator3() {}
319 distance_interpolator3(int x1, int y1, int x2, int y2,
320 int sx, int sy, int ex, int ey,
321 int x, int y) :
322 m_dx(x2 - x1),
323 m_dy(y2 - y1),
324 m_dx_start(line_mr(sx) - line_mr(x1)),
325 m_dy_start(line_mr(sy) - line_mr(y1)),
326 m_dx_end(line_mr(ex) - line_mr(x2)),
327 m_dy_end(line_mr(ey) - line_mr(y2)),
329 m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) -
330 double(y + line_subpixel_scale/2 - y2) * double(m_dx))),
332 m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start -
333 (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start),
335 m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end -
336 (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end)
338 m_dx <<= line_subpixel_shift;
339 m_dy <<= line_subpixel_shift;
340 m_dx_start <<= line_mr_subpixel_shift;
341 m_dy_start <<= line_mr_subpixel_shift;
342 m_dx_end <<= line_mr_subpixel_shift;
343 m_dy_end <<= line_mr_subpixel_shift;
346 //---------------------------------------------------------------------
347 void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; }
348 void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; }
349 void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; }
350 void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; }
352 //---------------------------------------------------------------------
353 void inc_x(int dy)
355 m_dist += m_dy;
356 m_dist_start += m_dy_start;
357 m_dist_end += m_dy_end;
358 if(dy > 0)
360 m_dist -= m_dx;
361 m_dist_start -= m_dx_start;
362 m_dist_end -= m_dx_end;
364 if(dy < 0)
366 m_dist += m_dx;
367 m_dist_start += m_dx_start;
368 m_dist_end += m_dx_end;
372 //---------------------------------------------------------------------
373 void dec_x(int dy)
375 m_dist -= m_dy;
376 m_dist_start -= m_dy_start;
377 m_dist_end -= m_dy_end;
378 if(dy > 0)
380 m_dist -= m_dx;
381 m_dist_start -= m_dx_start;
382 m_dist_end -= m_dx_end;
384 if(dy < 0)
386 m_dist += m_dx;
387 m_dist_start += m_dx_start;
388 m_dist_end += m_dx_end;
392 //---------------------------------------------------------------------
393 void inc_y(int dx)
395 m_dist -= m_dx;
396 m_dist_start -= m_dx_start;
397 m_dist_end -= m_dx_end;
398 if(dx > 0)
400 m_dist += m_dy;
401 m_dist_start += m_dy_start;
402 m_dist_end += m_dy_end;
404 if(dx < 0)
406 m_dist -= m_dy;
407 m_dist_start -= m_dy_start;
408 m_dist_end -= m_dy_end;
412 //---------------------------------------------------------------------
413 void dec_y(int dx)
415 m_dist += m_dx;
416 m_dist_start += m_dx_start;
417 m_dist_end += m_dx_end;
418 if(dx > 0)
420 m_dist += m_dy;
421 m_dist_start += m_dy_start;
422 m_dist_end += m_dy_end;
424 if(dx < 0)
426 m_dist -= m_dy;
427 m_dist_start -= m_dy_start;
428 m_dist_end -= m_dy_end;
432 //---------------------------------------------------------------------
433 int dist() const { return m_dist; }
434 int dist_start() const { return m_dist_start; }
435 int dist_end() const { return m_dist_end; }
437 //---------------------------------------------------------------------
438 int dx() const { return m_dx; }
439 int dy() const { return m_dy; }
440 int dx_start() const { return m_dx_start; }
441 int dy_start() const { return m_dy_start; }
442 int dx_end() const { return m_dx_end; }
443 int dy_end() const { return m_dy_end; }
445 private:
446 //---------------------------------------------------------------------
447 int m_dx;
448 int m_dy;
449 int m_dx_start;
450 int m_dy_start;
451 int m_dx_end;
452 int m_dy_end;
454 int m_dist;
455 int m_dist_start;
456 int m_dist_end;
463 //================================================line_interpolator_aa_base
464 template<class Renderer> class line_interpolator_aa_base
466 public:
467 typedef Renderer renderer_type;
468 typedef typename Renderer::color_type color_type;
470 //---------------------------------------------------------------------
471 enum max_half_width_e
473 max_half_width = 64
476 //---------------------------------------------------------------------
477 line_interpolator_aa_base(renderer_type& ren, const line_parameters& lp) :
478 m_lp(&lp),
479 m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) :
480 line_dbl_hr(lp.y2 - lp.y1),
481 lp.vertical ? abs(lp.y2 - lp.y1) :
482 abs(lp.x2 - lp.x1) + 1),
483 m_ren(ren),
484 m_len((lp.vertical == (lp.inc > 0)) ? -lp.len : lp.len),
485 m_x(lp.x1 >> line_subpixel_shift),
486 m_y(lp.y1 >> line_subpixel_shift),
487 m_old_x(m_x),
488 m_old_y(m_y),
489 m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) :
490 abs((lp.x2 >> line_subpixel_shift) - m_x))),
491 m_width(ren.subpixel_width()),
492 //m_max_extent(m_width >> (line_subpixel_shift - 2)),
493 m_max_extent((m_width + line_subpixel_mask) >> line_subpixel_shift),
494 m_step(0)
496 agg::dda2_line_interpolator li(0, lp.vertical ?
497 (lp.dy << agg::line_subpixel_shift) :
498 (lp.dx << agg::line_subpixel_shift),
499 lp.len);
501 unsigned i;
502 int stop = m_width + line_subpixel_scale * 2;
503 for(i = 0; i < max_half_width; ++i)
505 m_dist[i] = li.y();
506 if(m_dist[i] >= stop) break;
507 ++li;
509 m_dist[i++] = 0x7FFF0000;
512 //---------------------------------------------------------------------
513 template<class DI> int step_hor_base(DI& di)
515 ++m_li;
516 m_x += m_lp->inc;
517 m_y = (m_lp->y1 + m_li.y()) >> line_subpixel_shift;
519 if(m_lp->inc > 0) di.inc_x(m_y - m_old_y);
520 else di.dec_x(m_y - m_old_y);
522 m_old_y = m_y;
524 return di.dist() / m_len;
527 //---------------------------------------------------------------------
528 template<class DI> int step_ver_base(DI& di)
530 ++m_li;
531 m_y += m_lp->inc;
532 m_x = (m_lp->x1 + m_li.y()) >> line_subpixel_shift;
534 if(m_lp->inc > 0) di.inc_y(m_x - m_old_x);
535 else di.dec_y(m_x - m_old_x);
537 m_old_x = m_x;
539 return di.dist() / m_len;
542 //---------------------------------------------------------------------
543 bool vertical() const { return m_lp->vertical; }
544 int width() const { return m_width; }
545 int count() const { return m_count; }
547 private:
548 line_interpolator_aa_base(const line_interpolator_aa_base<Renderer>&);
549 const line_interpolator_aa_base<Renderer>&
550 operator = (const line_interpolator_aa_base<Renderer>&);
552 protected:
553 const line_parameters* m_lp;
554 dda2_line_interpolator m_li;
555 renderer_type& m_ren;
556 int m_len;
557 int m_x;
558 int m_y;
559 int m_old_x;
560 int m_old_y;
561 int m_count;
562 int m_width;
563 int m_max_extent;
564 int m_step;
565 int m_dist[max_half_width + 1];
566 cover_type m_covers[max_half_width * 2 + 4];
575 //====================================================line_interpolator_aa0
576 template<class Renderer> class line_interpolator_aa0 :
577 public line_interpolator_aa_base<Renderer>
579 public:
580 typedef Renderer renderer_type;
581 typedef typename Renderer::color_type color_type;
582 typedef line_interpolator_aa_base<Renderer> base_type;
584 //---------------------------------------------------------------------
585 line_interpolator_aa0(renderer_type& ren, const line_parameters& lp) :
586 line_interpolator_aa_base<Renderer>(ren, lp),
587 m_di(lp.x1, lp.y1, lp.x2, lp.y2,
588 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask)
590 base_type::m_li.adjust_forward();
593 //---------------------------------------------------------------------
594 bool step_hor()
596 int dist;
597 int dy;
598 int s1 = base_type::step_hor_base(m_di);
599 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
600 cover_type* p1 = p0;
602 *p1++ = (cover_type)base_type::m_ren.cover(s1);
604 dy = 1;
605 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
607 *p1++ = (cover_type)base_type::m_ren.cover(dist);
608 ++dy;
611 dy = 1;
612 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
614 *--p0 = (cover_type)base_type::m_ren.cover(dist);
615 ++dy;
617 base_type::m_ren.blend_solid_vspan(base_type::m_x,
618 base_type::m_y - dy + 1,
619 unsigned(p1 - p0),
620 p0);
621 return ++base_type::m_step < base_type::m_count;
624 //---------------------------------------------------------------------
625 bool step_ver()
627 int dist;
628 int dx;
629 int s1 = base_type::step_ver_base(m_di);
630 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
631 cover_type* p1 = p0;
633 *p1++ = (cover_type)base_type::m_ren.cover(s1);
635 dx = 1;
636 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
638 *p1++ = (cover_type)base_type::m_ren.cover(dist);
639 ++dx;
642 dx = 1;
643 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
645 *--p0 = (cover_type)base_type::m_ren.cover(dist);
646 ++dx;
648 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
649 base_type::m_y,
650 unsigned(p1 - p0),
651 p0);
652 return ++base_type::m_step < base_type::m_count;
655 private:
656 line_interpolator_aa0(const line_interpolator_aa0<Renderer>&);
657 const line_interpolator_aa0<Renderer>&
658 operator = (const line_interpolator_aa0<Renderer>&);
660 //---------------------------------------------------------------------
661 distance_interpolator1 m_di;
669 //====================================================line_interpolator_aa1
670 template<class Renderer> class line_interpolator_aa1 :
671 public line_interpolator_aa_base<Renderer>
673 public:
674 typedef Renderer renderer_type;
675 typedef typename Renderer::color_type color_type;
676 typedef line_interpolator_aa_base<Renderer> base_type;
678 //---------------------------------------------------------------------
679 line_interpolator_aa1(renderer_type& ren, const line_parameters& lp,
680 int sx, int sy) :
681 line_interpolator_aa_base<Renderer>(ren, lp),
682 m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy,
683 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask)
685 int dist1_start;
686 int dist2_start;
688 int npix = 1;
690 if(lp.vertical)
694 --base_type::m_li;
695 base_type::m_y -= lp.inc;
696 base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift;
698 if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x);
699 else m_di.inc_y(base_type::m_x - base_type::m_old_x);
701 base_type::m_old_x = base_type::m_x;
703 dist1_start = dist2_start = m_di.dist_start();
705 int dx = 0;
706 if(dist1_start < 0) ++npix;
709 dist1_start += m_di.dy_start();
710 dist2_start -= m_di.dy_start();
711 if(dist1_start < 0) ++npix;
712 if(dist2_start < 0) ++npix;
713 ++dx;
715 while(base_type::m_dist[dx] <= base_type::m_width);
716 --base_type::m_step;
717 if(npix == 0) break;
718 npix = 0;
720 while(base_type::m_step >= -base_type::m_max_extent);
722 else
726 --base_type::m_li;
727 base_type::m_x -= lp.inc;
728 base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift;
730 if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y);
731 else m_di.inc_x(base_type::m_y - base_type::m_old_y);
733 base_type::m_old_y = base_type::m_y;
735 dist1_start = dist2_start = m_di.dist_start();
737 int dy = 0;
738 if(dist1_start < 0) ++npix;
741 dist1_start -= m_di.dx_start();
742 dist2_start += m_di.dx_start();
743 if(dist1_start < 0) ++npix;
744 if(dist2_start < 0) ++npix;
745 ++dy;
747 while(base_type::m_dist[dy] <= base_type::m_width);
748 --base_type::m_step;
749 if(npix == 0) break;
750 npix = 0;
752 while(base_type::m_step >= -base_type::m_max_extent);
754 base_type::m_li.adjust_forward();
757 //---------------------------------------------------------------------
758 bool step_hor()
760 int dist_start;
761 int dist;
762 int dy;
763 int s1 = base_type::step_hor_base(m_di);
765 dist_start = m_di.dist_start();
766 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
767 cover_type* p1 = p0;
769 *p1 = 0;
770 if(dist_start <= 0)
772 *p1 = (cover_type)base_type::m_ren.cover(s1);
774 ++p1;
776 dy = 1;
777 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
779 dist_start -= m_di.dx_start();
780 *p1 = 0;
781 if(dist_start <= 0)
783 *p1 = (cover_type)base_type::m_ren.cover(dist);
785 ++p1;
786 ++dy;
789 dy = 1;
790 dist_start = m_di.dist_start();
791 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
793 dist_start += m_di.dx_start();
794 *--p0 = 0;
795 if(dist_start <= 0)
797 *p0 = (cover_type)base_type::m_ren.cover(dist);
799 ++dy;
802 base_type::m_ren.blend_solid_vspan(base_type::m_x,
803 base_type::m_y - dy + 1,
804 unsigned(p1 - p0),
805 p0);
806 return ++base_type::m_step < base_type::m_count;
809 //---------------------------------------------------------------------
810 bool step_ver()
812 int dist_start;
813 int dist;
814 int dx;
815 int s1 = base_type::step_ver_base(m_di);
816 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
817 cover_type* p1 = p0;
819 dist_start = m_di.dist_start();
821 *p1 = 0;
822 if(dist_start <= 0)
824 *p1 = (cover_type)base_type::m_ren.cover(s1);
826 ++p1;
828 dx = 1;
829 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
831 dist_start += m_di.dy_start();
832 *p1 = 0;
833 if(dist_start <= 0)
835 *p1 = (cover_type)base_type::m_ren.cover(dist);
837 ++p1;
838 ++dx;
841 dx = 1;
842 dist_start = m_di.dist_start();
843 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
845 dist_start -= m_di.dy_start();
846 *--p0 = 0;
847 if(dist_start <= 0)
849 *p0 = (cover_type)base_type::m_ren.cover(dist);
851 ++dx;
853 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
854 base_type::m_y,
855 unsigned(p1 - p0),
856 p0);
857 return ++base_type::m_step < base_type::m_count;
860 private:
861 line_interpolator_aa1(const line_interpolator_aa1<Renderer>&);
862 const line_interpolator_aa1<Renderer>&
863 operator = (const line_interpolator_aa1<Renderer>&);
865 //---------------------------------------------------------------------
866 distance_interpolator2 m_di;
880 //====================================================line_interpolator_aa2
881 template<class Renderer> class line_interpolator_aa2 :
882 public line_interpolator_aa_base<Renderer>
884 public:
885 typedef Renderer renderer_type;
886 typedef typename Renderer::color_type color_type;
887 typedef line_interpolator_aa_base<Renderer> base_type;
889 //---------------------------------------------------------------------
890 line_interpolator_aa2(renderer_type& ren, const line_parameters& lp,
891 int ex, int ey) :
892 line_interpolator_aa_base<Renderer>(ren, lp),
893 m_di(lp.x1, lp.y1, lp.x2, lp.y2, ex, ey,
894 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask,
897 base_type::m_li.adjust_forward();
898 base_type::m_step -= base_type::m_max_extent;
901 //---------------------------------------------------------------------
902 bool step_hor()
904 int dist_end;
905 int dist;
906 int dy;
907 int s1 = base_type::step_hor_base(m_di);
908 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
909 cover_type* p1 = p0;
911 dist_end = m_di.dist_end();
913 int npix = 0;
914 *p1 = 0;
915 if(dist_end > 0)
917 *p1 = (cover_type)base_type::m_ren.cover(s1);
918 ++npix;
920 ++p1;
922 dy = 1;
923 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
925 dist_end -= m_di.dx_end();
926 *p1 = 0;
927 if(dist_end > 0)
929 *p1 = (cover_type)base_type::m_ren.cover(dist);
930 ++npix;
932 ++p1;
933 ++dy;
936 dy = 1;
937 dist_end = m_di.dist_end();
938 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
940 dist_end += m_di.dx_end();
941 *--p0 = 0;
942 if(dist_end > 0)
944 *p0 = (cover_type)base_type::m_ren.cover(dist);
945 ++npix;
947 ++dy;
949 base_type::m_ren.blend_solid_vspan(base_type::m_x,
950 base_type::m_y - dy + 1,
951 unsigned(p1 - p0),
952 p0);
953 return npix && ++base_type::m_step < base_type::m_count;
956 //---------------------------------------------------------------------
957 bool step_ver()
959 int dist_end;
960 int dist;
961 int dx;
962 int s1 = base_type::step_ver_base(m_di);
963 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
964 cover_type* p1 = p0;
966 dist_end = m_di.dist_end();
968 int npix = 0;
969 *p1 = 0;
970 if(dist_end > 0)
972 *p1 = (cover_type)base_type::m_ren.cover(s1);
973 ++npix;
975 ++p1;
977 dx = 1;
978 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
980 dist_end += m_di.dy_end();
981 *p1 = 0;
982 if(dist_end > 0)
984 *p1 = (cover_type)base_type::m_ren.cover(dist);
985 ++npix;
987 ++p1;
988 ++dx;
991 dx = 1;
992 dist_end = m_di.dist_end();
993 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
995 dist_end -= m_di.dy_end();
996 *--p0 = 0;
997 if(dist_end > 0)
999 *p0 = (cover_type)base_type::m_ren.cover(dist);
1000 ++npix;
1002 ++dx;
1004 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
1005 base_type::m_y,
1006 unsigned(p1 - p0),
1007 p0);
1008 return npix && ++base_type::m_step < base_type::m_count;
1011 private:
1012 line_interpolator_aa2(const line_interpolator_aa2<Renderer>&);
1013 const line_interpolator_aa2<Renderer>&
1014 operator = (const line_interpolator_aa2<Renderer>&);
1016 //---------------------------------------------------------------------
1017 distance_interpolator2 m_di;
1029 //====================================================line_interpolator_aa3
1030 template<class Renderer> class line_interpolator_aa3 :
1031 public line_interpolator_aa_base<Renderer>
1033 public:
1034 typedef Renderer renderer_type;
1035 typedef typename Renderer::color_type color_type;
1036 typedef line_interpolator_aa_base<Renderer> base_type;
1038 //---------------------------------------------------------------------
1039 line_interpolator_aa3(renderer_type& ren, const line_parameters& lp,
1040 int sx, int sy, int ex, int ey) :
1041 line_interpolator_aa_base<Renderer>(ren, lp),
1042 m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey,
1043 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask)
1045 int dist1_start;
1046 int dist2_start;
1047 int npix = 1;
1048 if(lp.vertical)
1052 --base_type::m_li;
1053 base_type::m_y -= lp.inc;
1054 base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift;
1056 if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x);
1057 else m_di.inc_y(base_type::m_x - base_type::m_old_x);
1059 base_type::m_old_x = base_type::m_x;
1061 dist1_start = dist2_start = m_di.dist_start();
1063 int dx = 0;
1064 if(dist1_start < 0) ++npix;
1067 dist1_start += m_di.dy_start();
1068 dist2_start -= m_di.dy_start();
1069 if(dist1_start < 0) ++npix;
1070 if(dist2_start < 0) ++npix;
1071 ++dx;
1073 while(base_type::m_dist[dx] <= base_type::m_width);
1074 if(npix == 0) break;
1075 npix = 0;
1077 while(--base_type::m_step >= -base_type::m_max_extent);
1079 else
1083 --base_type::m_li;
1084 base_type::m_x -= lp.inc;
1085 base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift;
1087 if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y);
1088 else m_di.inc_x(base_type::m_y - base_type::m_old_y);
1090 base_type::m_old_y = base_type::m_y;
1092 dist1_start = dist2_start = m_di.dist_start();
1094 int dy = 0;
1095 if(dist1_start < 0) ++npix;
1098 dist1_start -= m_di.dx_start();
1099 dist2_start += m_di.dx_start();
1100 if(dist1_start < 0) ++npix;
1101 if(dist2_start < 0) ++npix;
1102 ++dy;
1104 while(base_type::m_dist[dy] <= base_type::m_width);
1105 if(npix == 0) break;
1106 npix = 0;
1108 while(--base_type::m_step >= -base_type::m_max_extent);
1110 base_type::m_li.adjust_forward();
1111 base_type::m_step -= base_type::m_max_extent;
1115 //---------------------------------------------------------------------
1116 bool step_hor()
1118 int dist_start;
1119 int dist_end;
1120 int dist;
1121 int dy;
1122 int s1 = base_type::step_hor_base(m_di);
1123 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
1124 cover_type* p1 = p0;
1126 dist_start = m_di.dist_start();
1127 dist_end = m_di.dist_end();
1129 int npix = 0;
1130 *p1 = 0;
1131 if(dist_end > 0)
1133 if(dist_start <= 0)
1135 *p1 = (cover_type)base_type::m_ren.cover(s1);
1137 ++npix;
1139 ++p1;
1141 dy = 1;
1142 while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width)
1144 dist_start -= m_di.dx_start();
1145 dist_end -= m_di.dx_end();
1146 *p1 = 0;
1147 if(dist_end > 0 && dist_start <= 0)
1149 *p1 = (cover_type)base_type::m_ren.cover(dist);
1150 ++npix;
1152 ++p1;
1153 ++dy;
1156 dy = 1;
1157 dist_start = m_di.dist_start();
1158 dist_end = m_di.dist_end();
1159 while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width)
1161 dist_start += m_di.dx_start();
1162 dist_end += m_di.dx_end();
1163 *--p0 = 0;
1164 if(dist_end > 0 && dist_start <= 0)
1166 *p0 = (cover_type)base_type::m_ren.cover(dist);
1167 ++npix;
1169 ++dy;
1171 base_type::m_ren.blend_solid_vspan(base_type::m_x,
1172 base_type::m_y - dy + 1,
1173 unsigned(p1 - p0),
1174 p0);
1175 return npix && ++base_type::m_step < base_type::m_count;
1178 //---------------------------------------------------------------------
1179 bool step_ver()
1181 int dist_start;
1182 int dist_end;
1183 int dist;
1184 int dx;
1185 int s1 = base_type::step_ver_base(m_di);
1186 cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2;
1187 cover_type* p1 = p0;
1189 dist_start = m_di.dist_start();
1190 dist_end = m_di.dist_end();
1192 int npix = 0;
1193 *p1 = 0;
1194 if(dist_end > 0)
1196 if(dist_start <= 0)
1198 *p1 = (cover_type)base_type::m_ren.cover(s1);
1200 ++npix;
1202 ++p1;
1204 dx = 1;
1205 while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width)
1207 dist_start += m_di.dy_start();
1208 dist_end += m_di.dy_end();
1209 *p1 = 0;
1210 if(dist_end > 0 && dist_start <= 0)
1212 *p1 = (cover_type)base_type::m_ren.cover(dist);
1213 ++npix;
1215 ++p1;
1216 ++dx;
1219 dx = 1;
1220 dist_start = m_di.dist_start();
1221 dist_end = m_di.dist_end();
1222 while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width)
1224 dist_start -= m_di.dy_start();
1225 dist_end -= m_di.dy_end();
1226 *--p0 = 0;
1227 if(dist_end > 0 && dist_start <= 0)
1229 *p0 = (cover_type)base_type::m_ren.cover(dist);
1230 ++npix;
1232 ++dx;
1234 base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1,
1235 base_type::m_y,
1236 unsigned(p1 - p0),
1237 p0);
1238 return npix && ++base_type::m_step < base_type::m_count;
1241 private:
1242 line_interpolator_aa3(const line_interpolator_aa3<Renderer>&);
1243 const line_interpolator_aa3<Renderer>&
1244 operator = (const line_interpolator_aa3<Renderer>&);
1246 //---------------------------------------------------------------------
1247 distance_interpolator3 m_di;
1253 //==========================================================line_profile_aa
1255 // See Implementation agg_line_profile_aa.cpp
1257 class line_profile_aa
1259 public:
1260 //---------------------------------------------------------------------
1261 typedef int8u value_type;
1262 enum subpixel_scale_e
1264 subpixel_shift = line_subpixel_shift,
1265 subpixel_scale = 1 << subpixel_shift,
1266 subpixel_mask = subpixel_scale - 1
1269 enum aa_scale_e
1271 aa_shift = 8,
1272 aa_scale = 1 << aa_shift,
1273 aa_mask = aa_scale - 1
1276 //---------------------------------------------------------------------
1277 line_profile_aa() :
1278 m_subpixel_width(0),
1279 m_min_width(1.0),
1280 m_smoother_width(1.0)
1282 int i;
1283 for(i = 0; i < aa_scale; i++) m_gamma[i] = (value_type)i;
1286 //---------------------------------------------------------------------
1287 template<class GammaF>
1288 line_profile_aa(double w, const GammaF& gamma_function) :
1289 m_subpixel_width(0),
1290 m_min_width(1.0),
1291 m_smoother_width(1.0)
1293 gamma(gamma_function);
1294 width(w);
1297 //---------------------------------------------------------------------
1298 void min_width(double w) { m_min_width = w; }
1299 void smoother_width(double w) { m_smoother_width = w; }
1301 //---------------------------------------------------------------------
1302 template<class GammaF> void gamma(const GammaF& gamma_function)
1304 int i;
1305 for(i = 0; i < aa_scale; i++)
1307 m_gamma[i] = value_type(
1308 uround(gamma_function(double(i) / aa_mask) * aa_mask));
1312 void width(double w);
1314 unsigned profile_size() const { return m_profile.size(); }
1315 int subpixel_width() const { return m_subpixel_width; }
1317 //---------------------------------------------------------------------
1318 double min_width() const { return m_min_width; }
1319 double smoother_width() const { return m_smoother_width; }
1321 //---------------------------------------------------------------------
1322 value_type value(int dist) const
1324 return m_profile[dist + subpixel_scale*2];
1327 private:
1328 line_profile_aa(const line_profile_aa&);
1329 const line_profile_aa& operator = (const line_profile_aa&);
1331 value_type* profile(double w);
1332 void set(double center_width, double smoother_width);
1334 //---------------------------------------------------------------------
1335 pod_array<value_type> m_profile;
1336 value_type m_gamma[aa_scale];
1337 int m_subpixel_width;
1338 double m_min_width;
1339 double m_smoother_width;
1343 //======================================================renderer_outline_aa
1344 template<class BaseRenderer> class renderer_outline_aa
1346 public:
1347 //---------------------------------------------------------------------
1348 typedef BaseRenderer base_ren_type;
1349 typedef renderer_outline_aa<base_ren_type> self_type;
1350 typedef typename base_ren_type::color_type color_type;
1352 //---------------------------------------------------------------------
1353 renderer_outline_aa(base_ren_type& ren, const line_profile_aa& prof) :
1354 m_ren(&ren),
1355 m_profile(&prof),
1356 m_clip_box(0,0,0,0),
1357 m_clipping(false)
1359 void attach(base_ren_type& ren) { m_ren = &ren; }
1361 //---------------------------------------------------------------------
1362 void color(const color_type& c) { m_color = c; }
1363 const color_type& color() const { return m_color; }
1365 //---------------------------------------------------------------------
1366 void profile(const line_profile_aa& prof) { m_profile = &prof; }
1367 const line_profile_aa& profile() const { return *m_profile; }
1368 line_profile_aa& profile() { return *(line_profile_aa*)m_profile; }
1370 //---------------------------------------------------------------------
1371 int subpixel_width() const { return m_profile->subpixel_width(); }
1373 //---------------------------------------------------------------------
1374 void reset_clipping() { m_clipping = false; }
1375 void clip_box(double x1, double y1, double x2, double y2)
1377 m_clip_box.x1 = line_coord_sat::conv(x1);
1378 m_clip_box.y1 = line_coord_sat::conv(y1);
1379 m_clip_box.x2 = line_coord_sat::conv(x2);
1380 m_clip_box.y2 = line_coord_sat::conv(y2);
1381 m_clipping = true;
1384 //---------------------------------------------------------------------
1385 int cover(int d) const
1387 return m_profile->value(d);
1390 //-------------------------------------------------------------------------
1391 void blend_solid_hspan(int x, int y, unsigned len, const cover_type* covers)
1393 m_ren->blend_solid_hspan(x, y, len, m_color, covers);
1396 //-------------------------------------------------------------------------
1397 void blend_solid_vspan(int x, int y, unsigned len, const cover_type* covers)
1399 m_ren->blend_solid_vspan(x, y, len, m_color, covers);
1402 //-------------------------------------------------------------------------
1403 static bool accurate_join_only() { return false; }
1405 //-------------------------------------------------------------------------
1406 template<class Cmp>
1407 void semidot_hline(Cmp cmp,
1408 int xc1, int yc1, int xc2, int yc2,
1409 int x1, int y1, int x2)
1411 cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4];
1412 cover_type* p0 = covers;
1413 cover_type* p1 = covers;
1414 int x = x1 << line_subpixel_shift;
1415 int y = y1 << line_subpixel_shift;
1416 int w = subpixel_width();
1417 distance_interpolator0 di(xc1, yc1, xc2, yc2, x, y);
1418 x += line_subpixel_scale/2;
1419 y += line_subpixel_scale/2;
1421 int x0 = x1;
1422 int dx = x - xc1;
1423 int dy = y - yc1;
1426 int d = int(fast_sqrt(dx*dx + dy*dy));
1427 *p1 = 0;
1428 if(cmp(di.dist()) && d <= w)
1430 *p1 = (cover_type)cover(d);
1432 ++p1;
1433 dx += line_subpixel_scale;
1434 di.inc_x();
1436 while(++x1 <= x2);
1437 m_ren->blend_solid_hspan(x0, y1,
1438 unsigned(p1 - p0),
1439 color(),
1440 p0);
1443 //-------------------------------------------------------------------------
1444 template<class Cmp>
1445 void semidot(Cmp cmp, int xc1, int yc1, int xc2, int yc2)
1447 if(m_clipping && clipping_flags(xc1, yc1, m_clip_box)) return;
1449 int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift);
1450 if(r < 1) r = 1;
1451 ellipse_bresenham_interpolator ei(r, r);
1452 int dx = 0;
1453 int dy = -r;
1454 int dy0 = dy;
1455 int dx0 = dx;
1456 int x = xc1 >> line_subpixel_shift;
1457 int y = yc1 >> line_subpixel_shift;
1461 dx += ei.dx();
1462 dy += ei.dy();
1464 if(dy != dy0)
1466 semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0);
1467 semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y-dy0, x+dx0);
1469 dx0 = dx;
1470 dy0 = dy;
1471 ++ei;
1473 while(dy < 0);
1474 semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0);
1477 //-------------------------------------------------------------------------
1478 void pie_hline(int xc, int yc, int xp1, int yp1, int xp2, int yp2,
1479 int xh1, int yh1, int xh2)
1481 if(m_clipping && clipping_flags(xc, yc, m_clip_box)) return;
1483 cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4];
1484 cover_type* p0 = covers;
1485 cover_type* p1 = covers;
1486 int x = xh1 << line_subpixel_shift;
1487 int y = yh1 << line_subpixel_shift;
1488 int w = subpixel_width();
1490 distance_interpolator00 di(xc, yc, xp1, yp1, xp2, yp2, x, y);
1491 x += line_subpixel_scale/2;
1492 y += line_subpixel_scale/2;
1494 int xh0 = xh1;
1495 int dx = x - xc;
1496 int dy = y - yc;
1499 int d = int(fast_sqrt(dx*dx + dy*dy));
1500 *p1 = 0;
1501 if(di.dist1() <= 0 && di.dist2() > 0 && d <= w)
1503 *p1 = (cover_type)cover(d);
1505 ++p1;
1506 dx += line_subpixel_scale;
1507 di.inc_x();
1509 while(++xh1 <= xh2);
1510 m_ren->blend_solid_hspan(xh0, yh1,
1511 unsigned(p1 - p0),
1512 color(),
1513 p0);
1517 //-------------------------------------------------------------------------
1518 void pie(int xc, int yc, int x1, int y1, int x2, int y2)
1520 int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift);
1521 if(r < 1) r = 1;
1522 ellipse_bresenham_interpolator ei(r, r);
1523 int dx = 0;
1524 int dy = -r;
1525 int dy0 = dy;
1526 int dx0 = dx;
1527 int x = xc >> line_subpixel_shift;
1528 int y = yc >> line_subpixel_shift;
1532 dx += ei.dx();
1533 dy += ei.dy();
1535 if(dy != dy0)
1537 pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0);
1538 pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y-dy0, x+dx0);
1540 dx0 = dx;
1541 dy0 = dy;
1542 ++ei;
1544 while(dy < 0);
1545 pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0);
1548 //-------------------------------------------------------------------------
1549 void line0_no_clip(const line_parameters& lp)
1551 if(lp.len > line_max_length)
1553 line_parameters lp1, lp2;
1554 lp.divide(lp1, lp2);
1555 line0_no_clip(lp1);
1556 line0_no_clip(lp2);
1557 return;
1560 line_interpolator_aa0<self_type> li(*this, lp);
1561 if(li.count())
1563 if(li.vertical())
1565 while(li.step_ver());
1567 else
1569 while(li.step_hor());
1574 //-------------------------------------------------------------------------
1575 void line0(const line_parameters& lp)
1577 if(m_clipping)
1579 int x1 = lp.x1;
1580 int y1 = lp.y1;
1581 int x2 = lp.x2;
1582 int y2 = lp.y2;
1583 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1584 if((flags & 4) == 0)
1586 if(flags)
1588 line_parameters lp2(x1, y1, x2, y2,
1589 uround(calc_distance(x1, y1, x2, y2)));
1590 line0_no_clip(lp2);
1592 else
1594 line0_no_clip(lp);
1598 else
1600 line0_no_clip(lp);
1604 //-------------------------------------------------------------------------
1605 void line1_no_clip(const line_parameters& lp, int sx, int sy)
1607 if(lp.len > line_max_length)
1609 line_parameters lp1, lp2;
1610 lp.divide(lp1, lp2);
1611 line1_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1);
1612 line1_no_clip(lp2, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1));
1613 return;
1616 fix_degenerate_bisectrix_start(lp, &sx, &sy);
1617 line_interpolator_aa1<self_type> li(*this, lp, sx, sy);
1618 if(li.vertical())
1620 while(li.step_ver());
1622 else
1624 while(li.step_hor());
1629 //-------------------------------------------------------------------------
1630 void line1(const line_parameters& lp, int sx, int sy)
1632 if(m_clipping)
1634 int x1 = lp.x1;
1635 int y1 = lp.y1;
1636 int x2 = lp.x2;
1637 int y2 = lp.y2;
1638 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1639 if((flags & 4) == 0)
1641 if(flags)
1643 line_parameters lp2(x1, y1, x2, y2,
1644 uround(calc_distance(x1, y1, x2, y2)));
1645 if(flags & 1)
1647 sx = x1 + (y2 - y1);
1648 sy = y1 - (x2 - x1);
1650 else
1652 while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
1654 sx = (lp.x1 + sx) >> 1;
1655 sy = (lp.y1 + sy) >> 1;
1658 line1_no_clip(lp2, sx, sy);
1660 else
1662 line1_no_clip(lp, sx, sy);
1666 else
1668 line1_no_clip(lp, sx, sy);
1672 //-------------------------------------------------------------------------
1673 void line2_no_clip(const line_parameters& lp, int ex, int ey)
1675 if(lp.len > line_max_length)
1677 line_parameters lp1, lp2;
1678 lp.divide(lp1, lp2);
1679 line2_no_clip(lp1, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1));
1680 line2_no_clip(lp2, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
1681 return;
1684 fix_degenerate_bisectrix_end(lp, &ex, &ey);
1685 line_interpolator_aa2<self_type> li(*this, lp, ex, ey);
1686 if(li.vertical())
1688 while(li.step_ver());
1690 else
1692 while(li.step_hor());
1696 //-------------------------------------------------------------------------
1697 void line2(const line_parameters& lp, int ex, int ey)
1699 if(m_clipping)
1701 int x1 = lp.x1;
1702 int y1 = lp.y1;
1703 int x2 = lp.x2;
1704 int y2 = lp.y2;
1705 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1706 if((flags & 4) == 0)
1708 if(flags)
1710 line_parameters lp2(x1, y1, x2, y2,
1711 uround(calc_distance(x1, y1, x2, y2)));
1712 if(flags & 2)
1714 ex = x2 + (y2 - y1);
1715 ey = y2 - (x2 - x1);
1717 else
1719 while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
1721 ex = (lp.x2 + ex) >> 1;
1722 ey = (lp.y2 + ey) >> 1;
1725 line2_no_clip(lp2, ex, ey);
1727 else
1729 line2_no_clip(lp, ex, ey);
1733 else
1735 line2_no_clip(lp, ex, ey);
1739 //-------------------------------------------------------------------------
1740 void line3_no_clip(const line_parameters& lp,
1741 int sx, int sy, int ex, int ey)
1743 if(lp.len > line_max_length)
1745 line_parameters lp1, lp2;
1746 lp.divide(lp1, lp2);
1747 int mx = lp1.x2 + (lp1.y2 - lp1.y1);
1748 int my = lp1.y2 - (lp1.x2 - lp1.x1);
1749 line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my);
1750 line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
1751 return;
1754 fix_degenerate_bisectrix_start(lp, &sx, &sy);
1755 fix_degenerate_bisectrix_end(lp, &ex, &ey);
1756 line_interpolator_aa3<self_type> li(*this, lp, sx, sy, ex, ey);
1757 if(li.vertical())
1759 while(li.step_ver());
1761 else
1763 while(li.step_hor());
1767 //-------------------------------------------------------------------------
1768 void line3(const line_parameters& lp,
1769 int sx, int sy, int ex, int ey)
1771 if(m_clipping)
1773 int x1 = lp.x1;
1774 int y1 = lp.y1;
1775 int x2 = lp.x2;
1776 int y2 = lp.y2;
1777 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
1778 if((flags & 4) == 0)
1780 if(flags)
1782 line_parameters lp2(x1, y1, x2, y2,
1783 uround(calc_distance(x1, y1, x2, y2)));
1784 if(flags & 1)
1786 sx = x1 + (y2 - y1);
1787 sy = y1 - (x2 - x1);
1789 else
1791 while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
1793 sx = (lp.x1 + sx) >> 1;
1794 sy = (lp.y1 + sy) >> 1;
1797 if(flags & 2)
1799 ex = x2 + (y2 - y1);
1800 ey = y2 - (x2 - x1);
1802 else
1804 while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
1806 ex = (lp.x2 + ex) >> 1;
1807 ey = (lp.y2 + ey) >> 1;
1810 line3_no_clip(lp2, sx, sy, ex, ey);
1812 else
1814 line3_no_clip(lp, sx, sy, ex, ey);
1818 else
1820 line3_no_clip(lp, sx, sy, ex, ey);
1825 private:
1826 base_ren_type* m_ren;
1827 const line_profile_aa* m_profile;
1828 color_type m_color;
1829 rect_i m_clip_box;
1830 bool m_clipping;
1837 #endif