15 #ifndef AGG_RENDERER_OUTLINE_IMAGE_INCLUDED 16 #define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED 19 #include "agg_array.h" 21 #include "agg_line_aa_basics.h" 22 #include "agg_dda_line.h" 23 #include "agg_rendering_buffer.h" 24 #include "agg_clip_liang_barsky.h" 33 typedef typename Source::color_type color_type;
38 m_scale(src.height() / height),
39 m_scale_inv(height / src.height())
43 double width()
const {
return m_source.width(); }
44 double height()
const {
return m_height; }
46 color_type pixel(
int x,
int y)
const 51 double src_y = (y + 0.5) * m_scale - 0.5;
52 int h = m_source.height() - 1;
53 int y1 = ifloor(src_y);
55 rgba pix1 = (y1 < 0) ? rgba::no_color() :
rgba(m_source.pixel(x, y1));
56 rgba pix2 = (y2 > h) ? rgba::no_color() :
rgba(m_source.pixel(x, y2));
57 return pix1.gradient(pix2, src_y - y1);
62 double src_y1 = (y + 0.5) * m_scale - 0.5;
63 double src_y2 = src_y1 + m_scale;
64 int h = m_source.height() - 1;
65 int y1 = ifloor(src_y1);
66 int y2 = ifloor(src_y2);
67 rgba c = rgba::no_color();
68 if (y1 >= 0) c +=
rgba(m_source.pixel(x, y1)) *= y1 + 1 - src_y1;
71 if (y1 <= h) c += m_source.pixel(x, y1);
73 if (y2 <= h) c +=
rgba(m_source.pixel(x, y2)) *= src_y2 - y2;
74 return c *= m_scale_inv;
82 const Source& m_source;
94 typedef Filter filter_type;
95 typedef typename filter_type::color_type color_type;
100 m_dilation(filter.dilation() + 1),
101 m_dilation_hr(m_dilation << line_subpixel_shift),
113 template<
class Source>
116 m_dilation(filter.dilation() + 1),
117 m_dilation_hr(m_dilation << line_subpixel_shift),
130 template<
class Source>
void create(
const Source& src)
132 m_height = uceil(src.height());
133 m_width = uceil(src.width());
134 m_width_hr = uround(src.width() * line_subpixel_scale);
135 m_half_height_hr = uround(src.height() * line_subpixel_scale/2);
136 m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_scale/2;
137 m_half_height_hr += line_subpixel_scale/2;
139 m_data.resize((m_width + m_dilation * 2) * (m_height + m_dilation * 2));
141 m_buf.attach(&m_data[0], m_width + m_dilation * 2,
142 m_height + m_dilation * 2,
143 m_width + m_dilation * 2);
147 for(y = 0; y < m_height; y++)
149 d1 = m_buf.row_ptr(y + m_dilation) + m_dilation;
150 for(x = 0; x < m_width; x++)
152 *d1++ = src.pixel(x, y);
156 const color_type* s1;
157 const color_type* s2;
158 for(y = 0; y < m_dilation; y++)
162 d1 = m_buf.row_ptr(m_dilation + m_height + y) + m_dilation;
163 d2 = m_buf.row_ptr(m_dilation - y - 1) + m_dilation;
164 for(x = 0; x < m_width; x++)
168 *d1++ = color_type::no_color();
169 *d2++ = color_type::no_color();
173 unsigned h = m_height + m_dilation * 2;
174 for(y = 0; y < h; y++)
176 s1 = m_buf.row_ptr(y) + m_dilation;
177 s2 = m_buf.row_ptr(y) + m_dilation + m_width;
178 d1 = m_buf.row_ptr(y) + m_dilation + m_width;
179 d2 = m_buf.row_ptr(y) + m_dilation;
181 for(x = 0; x < m_dilation; x++)
190 int pattern_width()
const {
return m_width_hr; }
191 int line_width()
const {
return m_half_height_hr; }
192 double width()
const {
return m_height; }
195 void pixel(color_type* p,
int x,
int y)
const 197 m_filter->pixel_high_res(m_buf.rows(),
199 x % m_width_hr + m_dilation_hr,
204 const filter_type& filter()
const {
return *m_filter; }
213 const filter_type* m_filter;
220 int m_half_height_hr;
234 typedef Filter filter_type;
235 typedef typename filter_type::color_type color_type;
243 template<
class Source>
251 template<
class Source>
void create(
const Source& src)
255 while(m_mask < base_type::m_width)
260 m_mask <<= line_subpixel_shift - 1;
261 m_mask |= line_subpixel_mask;
262 base_type::m_width_hr = m_mask + 1;
266 void pixel(color_type* p,
int x,
int y)
const 268 base_type::m_filter->pixel_high_res(
269 base_type::m_buf.rows(),
271 (x & m_mask) + base_type::m_dilation_hr,
272 y + base_type::m_offset_y_hr);
291 int sx,
int sy,
int ex,
int ey,
292 int len,
double scale,
int x,
int y) :
295 m_dx_start(line_mr(sx) - line_mr(x1)),
296 m_dy_start(line_mr(sy) - line_mr(y1)),
297 m_dx_end(line_mr(ex) - line_mr(x2)),
298 m_dy_end(line_mr(ey) - line_mr(y2)),
300 m_dist(iround(
double(x + line_subpixel_scale/2 - x2) *
double(m_dy) -
301 double(y + line_subpixel_scale/2 - y2) *
double(m_dx))),
303 m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start -
304 (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start),
306 m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end -
307 (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end),
308 m_len(uround(len / scale))
310 double d = len * scale;
311 int dx = iround(((x2 - x1) << line_subpixel_shift) / d);
312 int dy = iround(((y2 - y1) << line_subpixel_shift) / d);
315 m_dist_pict = ((x + line_subpixel_scale/2 - (x1 - dy)) * m_dy_pict -
316 (y + line_subpixel_scale/2 - (y1 + dx)) * m_dx_pict) >>
319 m_dx <<= line_subpixel_shift;
320 m_dy <<= line_subpixel_shift;
321 m_dx_start <<= line_mr_subpixel_shift;
322 m_dy_start <<= line_mr_subpixel_shift;
323 m_dx_end <<= line_mr_subpixel_shift;
324 m_dy_end <<= line_mr_subpixel_shift;
331 m_dist_start += m_dy_start;
332 m_dist_pict += m_dy_pict;
333 m_dist_end += m_dy_end;
340 m_dist_start -= m_dy_start;
341 m_dist_pict -= m_dy_pict;
342 m_dist_end -= m_dy_end;
349 m_dist_start -= m_dx_start;
350 m_dist_pict -= m_dx_pict;
351 m_dist_end -= m_dx_end;
358 m_dist_start += m_dx_start;
359 m_dist_pict += m_dx_pict;
360 m_dist_end += m_dx_end;
367 m_dist_start += m_dy_start;
368 m_dist_pict += m_dy_pict;
369 m_dist_end += m_dy_end;
373 m_dist_start -= m_dx_start;
374 m_dist_pict -= m_dx_pict;
375 m_dist_end -= m_dx_end;
380 m_dist_start += m_dx_start;
381 m_dist_pict += m_dx_pict;
382 m_dist_end += m_dx_end;
390 m_dist_start -= m_dy_start;
391 m_dist_pict -= m_dy_pict;
392 m_dist_end -= m_dy_end;
396 m_dist_start -= m_dx_start;
397 m_dist_pict -= m_dx_pict;
398 m_dist_end -= m_dx_end;
403 m_dist_start += m_dx_start;
404 m_dist_pict += m_dx_pict;
405 m_dist_end += m_dx_end;
413 m_dist_start -= m_dx_start;
414 m_dist_pict -= m_dx_pict;
415 m_dist_end -= m_dx_end;
419 m_dist_start += m_dy_start;
420 m_dist_pict += m_dy_pict;
421 m_dist_end += m_dy_end;
426 m_dist_start -= m_dy_start;
427 m_dist_pict -= m_dy_pict;
428 m_dist_end -= m_dy_end;
436 m_dist_start += m_dx_start;
437 m_dist_pict += m_dx_pict;
438 m_dist_end += m_dx_end;
442 m_dist_start += m_dy_start;
443 m_dist_pict += m_dy_pict;
444 m_dist_end += m_dy_end;
449 m_dist_start -= m_dy_start;
450 m_dist_pict -= m_dy_pict;
451 m_dist_end -= m_dy_end;
456 int dist()
const {
return m_dist; }
457 int dist_start()
const {
return m_dist_start; }
458 int dist_pict()
const {
return m_dist_pict; }
459 int dist_end()
const {
return m_dist_end; }
462 int dx()
const {
return m_dx; }
463 int dy()
const {
return m_dy; }
464 int dx_start()
const {
return m_dx_start; }
465 int dy_start()
const {
return m_dy_start; }
466 int dx_pict()
const {
return m_dx_pict; }
467 int dy_pict()
const {
return m_dy_pict; }
468 int dx_end()
const {
return m_dx_end; }
469 int dy_end()
const {
return m_dy_end; }
470 int len()
const {
return m_len; }
498 typedef Renderer renderer_type;
499 typedef typename Renderer::color_type color_type;
502 enum max_half_width_e
509 int sx,
int sy,
int ex,
int ey,
513 m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) :
514 line_dbl_hr(lp.y2 - lp.y1),
515 lp.vertical ? std::abs(lp.y2 - lp.y1) :
516 std::abs(lp.x2 - lp.x1) + 1),
517 m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x,
518 lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask),
520 m_x(lp.x1 >> line_subpixel_shift),
521 m_y(lp.y1 >> line_subpixel_shift),
524 m_count((lp.vertical ? std::abs((lp.y2 >> line_subpixel_shift) - m_y) :
525 std::abs((lp.x2 >> line_subpixel_shift) - m_x))),
526 m_width(ren.subpixel_width()),
528 m_max_extent((m_width + line_subpixel_scale) >> line_subpixel_shift),
529 m_start(pattern_start + (m_max_extent + 2) * ren.pattern_width()),
533 (lp.dy << agg::line_subpixel_shift) :
534 (lp.dx << agg::line_subpixel_shift),
538 int stop = m_width + line_subpixel_scale * 2;
539 for(i = 0; i < max_half_width; ++i)
541 m_dist_pos[i] = li.y();
542 if(m_dist_pos[i] >= stop)
break;
545 m_dist_pos[i] = 0x7FFF0000;
557 m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;
559 if(lp.inc > 0) m_di.dec_y(m_x - m_old_x);
560 else m_di.inc_y(m_x - m_old_x);
564 dist1_start = dist2_start = m_di.dist_start();
567 if(dist1_start < 0) ++npix;
570 dist1_start += m_di.dy_start();
571 dist2_start -= m_di.dy_start();
572 if(dist1_start < 0) ++npix;
573 if(dist2_start < 0) ++npix;
576 while(m_dist_pos[dx] <= m_width);
581 while(--m_step >= -m_max_extent);
590 m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;
592 if(lp.inc > 0) m_di.dec_x(m_y - m_old_y);
593 else m_di.inc_x(m_y - m_old_y);
597 dist1_start = dist2_start = m_di.dist_start();
600 if(dist1_start < 0) ++npix;
603 dist1_start -= m_di.dx_start();
604 dist2_start += m_di.dx_start();
605 if(dist1_start < 0) ++npix;
606 if(dist2_start < 0) ++npix;
609 while(m_dist_pos[dy] <= m_width);
614 while(--m_step >= -m_max_extent);
616 m_li.adjust_forward();
617 m_step -= m_max_extent;
625 m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;
627 if(m_lp.inc > 0) m_di.inc_x(m_y - m_old_y);
628 else m_di.dec_x(m_y - m_old_y);
632 int s1 = m_di.dist() / m_lp.len;
635 if(m_lp.inc < 0) s1 = -s1;
643 dist_start = m_di.dist_start();
644 dist_pict = m_di.dist_pict() + m_start;
645 dist_end = m_di.dist_end();
646 color_type* p0 = m_colors + max_half_width + 2;
655 m_ren.pixel(p1, dist_pict, s2);
662 while((dist = m_dist_pos[dy]) - s1 <= m_width)
664 dist_start -= m_di.dx_start();
665 dist_pict -= m_di.dx_pict();
666 dist_end -= m_di.dx_end();
668 if(dist_end > 0 && dist_start <= 0)
670 if(m_lp.inc > 0) dist = -dist;
671 m_ren.pixel(p1, dist_pict, s2 - dist);
679 dist_start = m_di.dist_start();
680 dist_pict = m_di.dist_pict() + m_start;
681 dist_end = m_di.dist_end();
682 while((dist = m_dist_pos[dy]) + s1 <= m_width)
684 dist_start += m_di.dx_start();
685 dist_pict += m_di.dx_pict();
686 dist_end += m_di.dx_end();
689 if(dist_end > 0 && dist_start <= 0)
691 if(m_lp.inc > 0) dist = -dist;
692 m_ren.pixel(p0, dist_pict, s2 + dist);
697 m_ren.blend_color_vspan(m_x,
701 return npix && ++m_step < m_count;
711 m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;
713 if(m_lp.inc > 0) m_di.inc_y(m_x - m_old_x);
714 else m_di.dec_y(m_x - m_old_x);
718 int s1 = m_di.dist() / m_lp.len;
721 if(m_lp.inc > 0) s1 = -s1;
729 dist_start = m_di.dist_start();
730 dist_pict = m_di.dist_pict() + m_start;
731 dist_end = m_di.dist_end();
732 color_type* p0 = m_colors + max_half_width + 2;
741 m_ren.pixel(p1, dist_pict, s2);
748 while((dist = m_dist_pos[dx]) - s1 <= m_width)
750 dist_start += m_di.dy_start();
751 dist_pict += m_di.dy_pict();
752 dist_end += m_di.dy_end();
754 if(dist_end > 0 && dist_start <= 0)
756 if(m_lp.inc > 0) dist = -dist;
757 m_ren.pixel(p1, dist_pict, s2 + dist);
765 dist_start = m_di.dist_start();
766 dist_pict = m_di.dist_pict() + m_start;
767 dist_end = m_di.dist_end();
768 while((dist = m_dist_pos[dx]) + s1 <= m_width)
770 dist_start -= m_di.dy_start();
771 dist_pict -= m_di.dy_pict();
772 dist_end -= m_di.dy_end();
775 if(dist_end > 0 && dist_start <= 0)
777 if(m_lp.inc > 0) dist = -dist;
778 m_ren.pixel(p0, dist_pict, s2 - dist);
783 m_ren.blend_color_hspan(m_x - dx + 1,
787 return npix && ++m_step < m_count;
792 int pattern_end()
const {
return m_start + m_di.len(); }
795 bool vertical()
const {
return m_lp.vertical; }
796 int width()
const {
return m_width; }
797 int count()
const {
return m_count; }
808 renderer_type& m_ren;
819 int m_dist_pos[max_half_width + 1];
820 color_type m_colors[max_half_width * 2 + 4];
831 template<
class BaseRenderer,
class ImagePattern>
836 typedef BaseRenderer base_ren_type;
838 typedef typename base_ren_type::color_type color_type;
839 typedef ImagePattern pattern_type;
851 void attach(base_ren_type& ren) { m_ren = &ren; }
854 void pattern(pattern_type& p) { m_pattern = &p; }
855 pattern_type& pattern()
const {
return *m_pattern; }
858 void reset_clipping() { m_clipping =
false; }
859 void clip_box(
double x1,
double y1,
double x2,
double y2)
861 m_clip_box.x1 = line_coord_sat::conv(x1);
862 m_clip_box.y1 = line_coord_sat::conv(y1);
863 m_clip_box.x2 = line_coord_sat::conv(x2);
864 m_clip_box.y2 = line_coord_sat::conv(y2);
869 void scale_x(
double s) { m_scale_x = s; }
870 double scale_x()
const {
return m_scale_x; }
873 void start_x(
double s) { m_start = iround(s * line_subpixel_scale); }
874 double start_x()
const {
return double(m_start) / line_subpixel_scale; }
877 int subpixel_width()
const {
return m_pattern->line_width(); }
878 int pattern_width()
const {
return m_pattern->pattern_width(); }
879 double width()
const {
return double(subpixel_width()) / line_subpixel_scale; }
882 void pixel(color_type* p,
int x,
int y)
const 884 m_pattern->pixel(p, x, y);
888 void blend_color_hspan(
int x,
int y,
unsigned len,
const color_type* colors)
890 m_ren->blend_color_hspan(x, y, len, colors, 0);
894 void blend_color_vspan(
int x,
int y,
unsigned len,
const color_type* colors)
896 m_ren->blend_color_vspan(x, y, len, colors, 0);
900 static bool accurate_join_only() {
return true; }
904 void semidot(Cmp,
int,
int,
int,
int)
909 void pie(
int,
int,
int,
int,
int,
int)
930 int sx,
int sy,
int ex,
int ey)
932 if(lp.len > line_max_length)
936 int mx = lp1.x2 + (lp1.y2 - lp1.y1);
937 int my = lp1.y2 - (lp1.x2 - lp1.x1);
938 line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my);
939 line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1);
943 fix_degenerate_bisectrix_start(lp, &sx, &sy);
944 fix_degenerate_bisectrix_end(lp, &ex, &ey);
951 while(li.step_ver());
955 while(li.step_hor());
957 m_start += uround(lp.len / m_scale_x);
962 int sx,
int sy,
int ex,
int ey)
970 unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
977 uround(calc_distance(x1, y1, x2, y2)));
980 m_start += uround(calc_distance(lp.x1, lp.y1, x1, y1) / m_scale_x);
986 while(std::abs(sx - lp.x1) + std::abs(sy - lp.y1) > lp2.len)
988 sx = (lp.x1 + sx) >> 1;
989 sy = (lp.y1 + sy) >> 1;
999 while(std::abs(ex - lp.x2) + std::abs(ey - lp.y2) > lp2.len)
1001 ex = (lp.x2 + ex) >> 1;
1002 ey = (lp.y2 + ey) >> 1;
1005 line3_no_clip(lp2, sx, sy, ex, ey);
1009 line3_no_clip(lp, sx, sy, ex, ey);
1012 m_start = start + uround(lp.len / m_scale_x);
1016 line3_no_clip(lp, sx, sy, ex, ey);
1021 base_ren_type* m_ren;
1022 pattern_type* m_pattern;