btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / libs / agg / agg_renderer_outline_image.h
blobdd48450edbd4fb962c9535106f82bdb9385ffba9
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_IMAGE_INCLUDED
16 #define AGG_RENDERER_OUTLINE_IMAGE_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_rendering_buffer.h"
23 #include "agg_clip_liang_barsky.h"
26 namespace agg
28 //========================================================line_image_scale
29 template<class Source> class line_image_scale
31 public:
32 typedef typename Source::color_type color_type;
34 line_image_scale(const Source& src, double height) :
35 m_source(src),
36 m_height(height),
37 m_scale(src.height() / height)
41 double width() const { return m_source.width(); }
42 double height() const { return m_height; }
44 color_type pixel(int x, int y) const
46 double src_y = (y + 0.5) * m_scale - 0.5;
47 int h = m_source.height() - 1;
48 int y1 = ufloor(src_y);
49 int y2 = y1 + 1;
50 color_type pix1 = (y1 < 0) ? color_type::no_color() : m_source.pixel(x, y1);
51 color_type pix2 = (y2 > h) ? color_type::no_color() : m_source.pixel(x, y2);
52 return pix1.gradient(pix2, src_y - y1);
55 private:
56 line_image_scale(const line_image_scale<Source>&);
57 const line_image_scale<Source>& operator = (const line_image_scale<Source>&);
59 const Source& m_source;
60 double m_height;
61 double m_scale;
66 //======================================================line_image_pattern
67 template<class Filter> class line_image_pattern
69 public:
70 typedef Filter filter_type;
71 typedef typename filter_type::color_type color_type;
73 //--------------------------------------------------------------------
74 line_image_pattern(const Filter& filter) :
75 m_filter(&filter),
76 m_dilation(filter.dilation() + 1),
77 m_dilation_hr(m_dilation << line_subpixel_shift),
78 m_data(),
79 m_width(0),
80 m_height(0),
81 m_width_hr(0),
82 m_half_height_hr(0),
83 m_offset_y_hr(0)
87 // Create
88 //--------------------------------------------------------------------
89 template<class Source>
90 line_image_pattern(const Filter& filter, const Source& src) :
91 m_filter(&filter),
92 m_dilation(filter.dilation() + 1),
93 m_dilation_hr(m_dilation << line_subpixel_shift),
94 m_data(),
95 m_width(0),
96 m_height(0),
97 m_width_hr(0),
98 m_half_height_hr(0),
99 m_offset_y_hr(0)
101 create(src);
104 // Create
105 //--------------------------------------------------------------------
106 template<class Source> void create(const Source& src)
108 m_height = uceil(src.height());
109 m_width = uceil(src.width());
110 m_width_hr = uround(src.width() * line_subpixel_scale);
111 m_half_height_hr = uround(src.height() * line_subpixel_scale/2);
112 m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_scale/2;
113 m_half_height_hr += line_subpixel_scale/2;
115 m_data.resize((m_width + m_dilation * 2) * (m_height + m_dilation * 2));
117 m_buf.attach(&m_data[0], m_width + m_dilation * 2,
118 m_height + m_dilation * 2,
119 m_width + m_dilation * 2);
120 unsigned x, y;
121 color_type* d1;
122 color_type* d2;
123 for(y = 0; y < m_height; y++)
125 d1 = m_buf.row_ptr(y + m_dilation) + m_dilation;
126 for(x = 0; x < m_width; x++)
128 *d1++ = src.pixel(x, y);
132 const color_type* s1;
133 const color_type* s2;
134 for(y = 0; y < m_dilation; y++)
136 //s1 = m_buf.row_ptr(m_height + m_dilation - 1) + m_dilation;
137 //s2 = m_buf.row_ptr(m_dilation) + m_dilation;
138 d1 = m_buf.row_ptr(m_dilation + m_height + y) + m_dilation;
139 d2 = m_buf.row_ptr(m_dilation - y - 1) + m_dilation;
140 for(x = 0; x < m_width; x++)
142 //*d1++ = color_type(*s1++, 0);
143 //*d2++ = color_type(*s2++, 0);
144 *d1++ = color_type::no_color();
145 *d2++ = color_type::no_color();
149 unsigned h = m_height + m_dilation * 2;
150 for(y = 0; y < h; y++)
152 s1 = m_buf.row_ptr(y) + m_dilation;
153 s2 = m_buf.row_ptr(y) + m_dilation + m_width;
154 d1 = m_buf.row_ptr(y) + m_dilation + m_width;
155 d2 = m_buf.row_ptr(y) + m_dilation;
157 for(x = 0; x < m_dilation; x++)
159 *d1++ = *s1++;
160 *--d2 = *--s2;
165 //--------------------------------------------------------------------
166 int pattern_width() const { return m_width_hr; }
167 int line_width() const { return m_half_height_hr; }
168 double width() const { return m_height; }
170 //--------------------------------------------------------------------
171 void pixel(color_type* p, int x, int y) const
173 m_filter->pixel_high_res(m_buf.rows(),
175 x % m_width_hr + m_dilation_hr,
176 y + m_offset_y_hr);
179 //--------------------------------------------------------------------
180 const filter_type& filter() const { return *m_filter; }
182 private:
183 line_image_pattern(const line_image_pattern<filter_type>&);
184 const line_image_pattern<filter_type>&
185 operator = (const line_image_pattern<filter_type>&);
187 protected:
188 row_ptr_cache<color_type> m_buf;
189 const filter_type* m_filter;
190 unsigned m_dilation;
191 int m_dilation_hr;
192 pod_array<color_type> m_data;
193 unsigned m_width;
194 unsigned m_height;
195 int m_width_hr;
196 int m_half_height_hr;
197 int m_offset_y_hr;
205 //=================================================line_image_pattern_pow2
206 template<class Filter> class line_image_pattern_pow2 :
207 public line_image_pattern<Filter>
209 public:
210 typedef Filter filter_type;
211 typedef typename filter_type::color_type color_type;
212 typedef line_image_pattern<Filter> base_type;
214 //--------------------------------------------------------------------
215 line_image_pattern_pow2(const Filter& filter) :
216 line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) {}
218 //--------------------------------------------------------------------
219 template<class Source>
220 line_image_pattern_pow2(const Filter& filter, const Source& src) :
221 line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask)
223 create(src);
226 //--------------------------------------------------------------------
227 template<class Source> void create(const Source& src)
229 line_image_pattern<Filter>::create(src);
230 m_mask = 1;
231 while(m_mask < base_type::m_width)
233 m_mask <<= 1;
234 m_mask |= 1;
236 m_mask <<= line_subpixel_shift - 1;
237 m_mask |= line_subpixel_mask;
238 base_type::m_width_hr = m_mask + 1;
241 //--------------------------------------------------------------------
242 void pixel(color_type* p, int x, int y) const
244 base_type::m_filter->pixel_high_res(
245 base_type::m_buf.rows(),
247 (x & m_mask) + base_type::m_dilation_hr,
248 y + base_type::m_offset_y_hr);
250 private:
251 unsigned m_mask;
260 //===================================================distance_interpolator4
261 class distance_interpolator4
263 public:
264 //---------------------------------------------------------------------
265 distance_interpolator4() {}
266 distance_interpolator4(int x1, int y1, int x2, int y2,
267 int sx, int sy, int ex, int ey,
268 int len, double scale, int x, int y) :
269 m_dx(x2 - x1),
270 m_dy(y2 - y1),
271 m_dx_start(line_mr(sx) - line_mr(x1)),
272 m_dy_start(line_mr(sy) - line_mr(y1)),
273 m_dx_end(line_mr(ex) - line_mr(x2)),
274 m_dy_end(line_mr(ey) - line_mr(y2)),
276 m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) -
277 double(y + line_subpixel_scale/2 - y2) * double(m_dx))),
279 m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start -
280 (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start),
282 m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end -
283 (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end),
284 m_len(uround(len / scale))
286 double d = len * scale;
287 int dx = iround(((x2 - x1) << line_subpixel_shift) / d);
288 int dy = iround(((y2 - y1) << line_subpixel_shift) / d);
289 m_dx_pict = -dy;
290 m_dy_pict = dx;
291 m_dist_pict = ((x + line_subpixel_scale/2 - (x1 - dy)) * m_dy_pict -
292 (y + line_subpixel_scale/2 - (y1 + dx)) * m_dx_pict) >>
293 line_subpixel_shift;
295 m_dx <<= line_subpixel_shift;
296 m_dy <<= line_subpixel_shift;
297 m_dx_start <<= line_mr_subpixel_shift;
298 m_dy_start <<= line_mr_subpixel_shift;
299 m_dx_end <<= line_mr_subpixel_shift;
300 m_dy_end <<= line_mr_subpixel_shift;
303 //---------------------------------------------------------------------
304 void inc_x()
306 m_dist += m_dy;
307 m_dist_start += m_dy_start;
308 m_dist_pict += m_dy_pict;
309 m_dist_end += m_dy_end;
312 //---------------------------------------------------------------------
313 void dec_x()
315 m_dist -= m_dy;
316 m_dist_start -= m_dy_start;
317 m_dist_pict -= m_dy_pict;
318 m_dist_end -= m_dy_end;
321 //---------------------------------------------------------------------
322 void inc_y()
324 m_dist -= m_dx;
325 m_dist_start -= m_dx_start;
326 m_dist_pict -= m_dx_pict;
327 m_dist_end -= m_dx_end;
330 //---------------------------------------------------------------------
331 void dec_y()
333 m_dist += m_dx;
334 m_dist_start += m_dx_start;
335 m_dist_pict += m_dx_pict;
336 m_dist_end += m_dx_end;
339 //---------------------------------------------------------------------
340 void inc_x(int dy)
342 m_dist += m_dy;
343 m_dist_start += m_dy_start;
344 m_dist_pict += m_dy_pict;
345 m_dist_end += m_dy_end;
346 if(dy > 0)
348 m_dist -= m_dx;
349 m_dist_start -= m_dx_start;
350 m_dist_pict -= m_dx_pict;
351 m_dist_end -= m_dx_end;
353 if(dy < 0)
355 m_dist += m_dx;
356 m_dist_start += m_dx_start;
357 m_dist_pict += m_dx_pict;
358 m_dist_end += m_dx_end;
362 //---------------------------------------------------------------------
363 void dec_x(int dy)
365 m_dist -= m_dy;
366 m_dist_start -= m_dy_start;
367 m_dist_pict -= m_dy_pict;
368 m_dist_end -= m_dy_end;
369 if(dy > 0)
371 m_dist -= m_dx;
372 m_dist_start -= m_dx_start;
373 m_dist_pict -= m_dx_pict;
374 m_dist_end -= m_dx_end;
376 if(dy < 0)
378 m_dist += m_dx;
379 m_dist_start += m_dx_start;
380 m_dist_pict += m_dx_pict;
381 m_dist_end += m_dx_end;
385 //---------------------------------------------------------------------
386 void inc_y(int dx)
388 m_dist -= m_dx;
389 m_dist_start -= m_dx_start;
390 m_dist_pict -= m_dx_pict;
391 m_dist_end -= m_dx_end;
392 if(dx > 0)
394 m_dist += m_dy;
395 m_dist_start += m_dy_start;
396 m_dist_pict += m_dy_pict;
397 m_dist_end += m_dy_end;
399 if(dx < 0)
401 m_dist -= m_dy;
402 m_dist_start -= m_dy_start;
403 m_dist_pict -= m_dy_pict;
404 m_dist_end -= m_dy_end;
408 //---------------------------------------------------------------------
409 void dec_y(int dx)
411 m_dist += m_dx;
412 m_dist_start += m_dx_start;
413 m_dist_pict += m_dx_pict;
414 m_dist_end += m_dx_end;
415 if(dx > 0)
417 m_dist += m_dy;
418 m_dist_start += m_dy_start;
419 m_dist_pict += m_dy_pict;
420 m_dist_end += m_dy_end;
422 if(dx < 0)
424 m_dist -= m_dy;
425 m_dist_start -= m_dy_start;
426 m_dist_pict -= m_dy_pict;
427 m_dist_end -= m_dy_end;
431 //---------------------------------------------------------------------
432 int dist() const { return m_dist; }
433 int dist_start() const { return m_dist_start; }
434 int dist_pict() const { return m_dist_pict; }
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_pict() const { return m_dx_pict; }
443 int dy_pict() const { return m_dy_pict; }
444 int dx_end() const { return m_dx_end; }
445 int dy_end() const { return m_dy_end; }
446 int len() const { return m_len; }
448 private:
449 //---------------------------------------------------------------------
450 int m_dx;
451 int m_dy;
452 int m_dx_start;
453 int m_dy_start;
454 int m_dx_pict;
455 int m_dy_pict;
456 int m_dx_end;
457 int m_dy_end;
459 int m_dist;
460 int m_dist_start;
461 int m_dist_pict;
462 int m_dist_end;
463 int m_len;
470 //==================================================line_interpolator_image
471 template<class Renderer> class line_interpolator_image
473 public:
474 typedef Renderer renderer_type;
475 typedef typename Renderer::color_type color_type;
477 //---------------------------------------------------------------------
478 enum max_half_width_e
480 max_half_width = 64
483 //---------------------------------------------------------------------
484 line_interpolator_image(renderer_type& ren, const line_parameters& lp,
485 int sx, int sy, int ex, int ey,
486 int pattern_start,
487 double scale_x) :
488 m_lp(lp),
489 m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) :
490 line_dbl_hr(lp.y2 - lp.y1),
491 lp.vertical ? abs(lp.y2 - lp.y1) :
492 abs(lp.x2 - lp.x1) + 1),
493 m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x,
494 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask),
495 m_ren(ren),
496 m_x(lp.x1 >> line_subpixel_shift),
497 m_y(lp.y1 >> line_subpixel_shift),
498 m_old_x(m_x),
499 m_old_y(m_y),
500 m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) :
501 abs((lp.x2 >> line_subpixel_shift) - m_x))),
502 m_width(ren.subpixel_width()),
503 //m_max_extent(m_width >> (line_subpixel_shift - 2)),
504 m_max_extent((m_width + line_subpixel_scale) >> line_subpixel_shift),
505 m_start(pattern_start + (m_max_extent + 2) * ren.pattern_width()),
506 m_step(0)
508 agg::dda2_line_interpolator li(0, lp.vertical ?
509 (lp.dy << agg::line_subpixel_shift) :
510 (lp.dx << agg::line_subpixel_shift),
511 lp.len);
513 unsigned i;
514 int stop = m_width + line_subpixel_scale * 2;
515 for(i = 0; i < max_half_width; ++i)
517 m_dist_pos[i] = li.y();
518 if(m_dist_pos[i] >= stop) break;
519 ++li;
521 m_dist_pos[i] = 0x7FFF0000;
523 int dist1_start;
524 int dist2_start;
525 int npix = 1;
527 if(lp.vertical)
531 --m_li;
532 m_y -= lp.inc;
533 m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;
535 if(lp.inc > 0) m_di.dec_y(m_x - m_old_x);
536 else m_di.inc_y(m_x - m_old_x);
538 m_old_x = m_x;
540 dist1_start = dist2_start = m_di.dist_start();
542 int dx = 0;
543 if(dist1_start < 0) ++npix;
546 dist1_start += m_di.dy_start();
547 dist2_start -= m_di.dy_start();
548 if(dist1_start < 0) ++npix;
549 if(dist2_start < 0) ++npix;
550 ++dx;
552 while(m_dist_pos[dx] <= m_width);
553 if(npix == 0) break;
555 npix = 0;
557 while(--m_step >= -m_max_extent);
559 else
563 --m_li;
565 m_x -= lp.inc;
566 m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;
568 if(lp.inc > 0) m_di.dec_x(m_y - m_old_y);
569 else m_di.inc_x(m_y - m_old_y);
571 m_old_y = m_y;
573 dist1_start = dist2_start = m_di.dist_start();
575 int dy = 0;
576 if(dist1_start < 0) ++npix;
579 dist1_start -= m_di.dx_start();
580 dist2_start += m_di.dx_start();
581 if(dist1_start < 0) ++npix;
582 if(dist2_start < 0) ++npix;
583 ++dy;
585 while(m_dist_pos[dy] <= m_width);
586 if(npix == 0) break;
588 npix = 0;
590 while(--m_step >= -m_max_extent);
592 m_li.adjust_forward();
593 m_step -= m_max_extent;
596 //---------------------------------------------------------------------
597 bool step_hor()
599 ++m_li;
600 m_x += m_lp.inc;
601 m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;
603 if(m_lp.inc > 0) m_di.inc_x(m_y - m_old_y);
604 else m_di.dec_x(m_y - m_old_y);
606 m_old_y = m_y;
608 int s1 = m_di.dist() / m_lp.len;
609 int s2 = -s1;
611 if(m_lp.inc < 0) s1 = -s1;
613 int dist_start;
614 int dist_pict;
615 int dist_end;
616 int dy;
617 int dist;
619 dist_start = m_di.dist_start();
620 dist_pict = m_di.dist_pict() + m_start;
621 dist_end = m_di.dist_end();
622 color_type* p0 = m_colors + max_half_width + 2;
623 color_type* p1 = p0;
625 int npix = 0;
626 p1->clear();
627 if(dist_end > 0)
629 if(dist_start <= 0)
631 m_ren.pixel(p1, dist_pict, s2);
633 ++npix;
635 ++p1;
637 dy = 1;
638 while((dist = m_dist_pos[dy]) - s1 <= m_width)
640 dist_start -= m_di.dx_start();
641 dist_pict -= m_di.dx_pict();
642 dist_end -= m_di.dx_end();
643 p1->clear();
644 if(dist_end > 0 && dist_start <= 0)
646 if(m_lp.inc > 0) dist = -dist;
647 m_ren.pixel(p1, dist_pict, s2 - dist);
648 ++npix;
650 ++p1;
651 ++dy;
654 dy = 1;
655 dist_start = m_di.dist_start();
656 dist_pict = m_di.dist_pict() + m_start;
657 dist_end = m_di.dist_end();
658 while((dist = m_dist_pos[dy]) + s1 <= m_width)
660 dist_start += m_di.dx_start();
661 dist_pict += m_di.dx_pict();
662 dist_end += m_di.dx_end();
663 --p0;
664 p0->clear();
665 if(dist_end > 0 && dist_start <= 0)
667 if(m_lp.inc > 0) dist = -dist;
668 m_ren.pixel(p0, dist_pict, s2 + dist);
669 ++npix;
671 ++dy;
673 m_ren.blend_color_vspan(m_x,
674 m_y - dy + 1,
675 unsigned(p1 - p0),
676 p0);
677 return npix && ++m_step < m_count;
682 //---------------------------------------------------------------------
683 bool step_ver()
685 ++m_li;
686 m_y += m_lp.inc;
687 m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;
689 if(m_lp.inc > 0) m_di.inc_y(m_x - m_old_x);
690 else m_di.dec_y(m_x - m_old_x);
692 m_old_x = m_x;
694 int s1 = m_di.dist() / m_lp.len;
695 int s2 = -s1;
697 if(m_lp.inc > 0) s1 = -s1;
699 int dist_start;
700 int dist_pict;
701 int dist_end;
702 int dist;
703 int dx;
705 dist_start = m_di.dist_start();
706 dist_pict = m_di.dist_pict() + m_start;
707 dist_end = m_di.dist_end();
708 color_type* p0 = m_colors + max_half_width + 2;
709 color_type* p1 = p0;
711 int npix = 0;
712 p1->clear();
713 if(dist_end > 0)
715 if(dist_start <= 0)
717 m_ren.pixel(p1, dist_pict, s2);
719 ++npix;
721 ++p1;
723 dx = 1;
724 while((dist = m_dist_pos[dx]) - s1 <= m_width)
726 dist_start += m_di.dy_start();
727 dist_pict += m_di.dy_pict();
728 dist_end += m_di.dy_end();
729 p1->clear();
730 if(dist_end > 0 && dist_start <= 0)
732 if(m_lp.inc > 0) dist = -dist;
733 m_ren.pixel(p1, dist_pict, s2 + dist);
734 ++npix;
736 ++p1;
737 ++dx;
740 dx = 1;
741 dist_start = m_di.dist_start();
742 dist_pict = m_di.dist_pict() + m_start;
743 dist_end = m_di.dist_end();
744 while((dist = m_dist_pos[dx]) + s1 <= m_width)
746 dist_start -= m_di.dy_start();
747 dist_pict -= m_di.dy_pict();
748 dist_end -= m_di.dy_end();
749 --p0;
750 p0->clear();
751 if(dist_end > 0 && dist_start <= 0)
753 if(m_lp.inc > 0) dist = -dist;
754 m_ren.pixel(p0, dist_pict, s2 - dist);
755 ++npix;
757 ++dx;
759 m_ren.blend_color_hspan(m_x - dx + 1,
760 m_y,
761 unsigned(p1 - p0),
762 p0);
763 return npix && ++m_step < m_count;
767 //---------------------------------------------------------------------
768 int pattern_end() const { return m_start + m_di.len(); }
770 //---------------------------------------------------------------------
771 bool vertical() const { return m_lp.vertical; }
772 int width() const { return m_width; }
773 int count() const { return m_count; }
775 private:
776 line_interpolator_image(const line_interpolator_image<Renderer>&);
777 const line_interpolator_image<Renderer>&
778 operator = (const line_interpolator_image<Renderer>&);
780 protected:
781 const line_parameters& m_lp;
782 dda2_line_interpolator m_li;
783 distance_interpolator4 m_di;
784 renderer_type& m_ren;
785 int m_plen;
786 int m_x;
787 int m_y;
788 int m_old_x;
789 int m_old_y;
790 int m_count;
791 int m_width;
792 int m_max_extent;
793 int m_start;
794 int m_step;
795 int m_dist_pos[max_half_width + 1];
796 color_type m_colors[max_half_width * 2 + 4];
806 //===================================================renderer_outline_image
807 template<class BaseRenderer, class ImagePattern>
808 class renderer_outline_image
810 public:
811 //---------------------------------------------------------------------
812 typedef BaseRenderer base_ren_type;
813 typedef renderer_outline_image<BaseRenderer, ImagePattern> self_type;
814 typedef typename base_ren_type::color_type color_type;
815 typedef ImagePattern pattern_type;
818 //---------------------------------------------------------------------
819 renderer_outline_image(base_ren_type& ren, const pattern_type& patt) :
820 m_ren(&ren),
821 m_pattern(&patt),
822 m_start(0),
823 m_scale_x(1.0),
824 m_clip_box(0,0,0,0),
825 m_clipping(false)
827 void attach(base_ren_type& ren) { m_ren = &ren; }
829 //---------------------------------------------------------------------
830 void pattern(const pattern_type& p) { m_pattern = &p; }
831 const pattern_type& pattern() const { return *m_pattern; }
833 //---------------------------------------------------------------------
834 void reset_clipping() { m_clipping = false; }
835 void clip_box(double x1, double y1, double x2, double y2)
837 m_clip_box.x1 = line_coord_sat::conv(x1);
838 m_clip_box.y1 = line_coord_sat::conv(y1);
839 m_clip_box.x2 = line_coord_sat::conv(x2);
840 m_clip_box.y2 = line_coord_sat::conv(y2);
841 m_clipping = true;
844 //---------------------------------------------------------------------
845 void scale_x(double s) { m_scale_x = s; }
846 double scale_x() const { return m_scale_x; }
848 //---------------------------------------------------------------------
849 void start_x(double s) { m_start = iround(s * line_subpixel_scale); }
850 double start_x() const { return double(m_start) / line_subpixel_scale; }
852 //---------------------------------------------------------------------
853 int subpixel_width() const { return m_pattern->line_width(); }
854 int pattern_width() const { return m_pattern->pattern_width(); }
855 double width() const { return double(subpixel_width()) / line_subpixel_scale; }
857 //-------------------------------------------------------------------------
858 void pixel(color_type* p, int x, int y) const
860 m_pattern->pixel(p, x, y);
863 //-------------------------------------------------------------------------
864 void blend_color_hspan(int x, int y, unsigned len, const color_type* colors)
866 m_ren->blend_color_hspan(x, y, len, colors, 0);
869 //-------------------------------------------------------------------------
870 void blend_color_vspan(int x, int y, unsigned len, const color_type* colors)
872 m_ren->blend_color_vspan(x, y, len, colors, 0);
875 //-------------------------------------------------------------------------
876 static bool accurate_join_only() { return true; }
878 //-------------------------------------------------------------------------
879 template<class Cmp>
880 void semidot(Cmp, int, int, int, int)
884 //-------------------------------------------------------------------------
885 void pie(int, int, int, int, int, int)
889 //-------------------------------------------------------------------------
890 void line0(const line_parameters&)
894 //-------------------------------------------------------------------------
895 void line1(const line_parameters&, int, int)
899 //-------------------------------------------------------------------------
900 void line2(const line_parameters&, int, int)
904 //-------------------------------------------------------------------------
905 void line3_no_clip(const line_parameters& lp,
906 int sx, int sy, int ex, int ey)
908 if(lp.len > line_max_length)
910 line_parameters lp1, lp2;
911 lp.divide(lp1, lp2);
912 int mx = lp1.x2 + (lp1.y2 - lp1.y1);
913 int my = lp1.y2 - (lp1.x2 - lp1.x1);
914 line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my);
915 line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
916 return;
919 fix_degenerate_bisectrix_start(lp, &sx, &sy);
920 fix_degenerate_bisectrix_end(lp, &ex, &ey);
921 line_interpolator_image<self_type> li(*this, lp,
922 sx, sy,
923 ex, ey,
924 m_start, m_scale_x);
925 if(li.vertical())
927 while(li.step_ver());
929 else
931 while(li.step_hor());
933 m_start += uround(lp.len / m_scale_x);
936 //-------------------------------------------------------------------------
937 void line3(const line_parameters& lp,
938 int sx, int sy, int ex, int ey)
940 if(m_clipping)
942 int x1 = lp.x1;
943 int y1 = lp.y1;
944 int x2 = lp.x2;
945 int y2 = lp.y2;
946 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
947 int start = m_start;
948 if((flags & 4) == 0)
950 if(flags)
952 line_parameters lp2(x1, y1, x2, y2,
953 uround(calc_distance(x1, y1, x2, y2)));
954 if(flags & 1)
956 m_start += uround(calc_distance(lp.x1, lp.y1, x1, y1) / m_scale_x);
957 sx = x1 + (y2 - y1);
958 sy = y1 - (x2 - x1);
960 else
962 while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len)
964 sx = (lp.x1 + sx) >> 1;
965 sy = (lp.y1 + sy) >> 1;
968 if(flags & 2)
970 ex = x2 + (y2 - y1);
971 ey = y2 - (x2 - x1);
973 else
975 while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len)
977 ex = (lp.x2 + ex) >> 1;
978 ey = (lp.y2 + ey) >> 1;
981 line3_no_clip(lp2, sx, sy, ex, ey);
983 else
985 line3_no_clip(lp, sx, sy, ex, ey);
988 m_start = start + uround(lp.len / m_scale_x);
990 else
992 line3_no_clip(lp, sx, sy, ex, ey);
996 private:
997 base_ren_type* m_ren;
998 const pattern_type* m_pattern;
999 int m_start;
1000 double m_scale_x;
1001 rect_i m_clip_box;
1002 bool m_clipping;
1013 #endif