Anti-Grain Geometry Tutorial
agg_renderer_outline_image.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_IMAGE_INCLUDED
16 #define AGG_RENDERER_OUTLINE_IMAGE_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_rendering_buffer.h"
24 #include "agg_clip_liang_barsky.h"
25 
26 
27 namespace agg
28 {
29  //========================================================line_image_scale
30  template<class Source> class line_image_scale
31  {
32  public:
33  typedef typename Source::color_type color_type;
34 
35  line_image_scale(const Source& src, double height) :
36  m_source(src),
37  m_height(height),
38  m_scale(src.height() / height),
39  m_scale_inv(height / src.height())
40  {
41  }
42 
43  double width() const { return m_source.width(); }
44  double height() const { return m_height; }
45 
46  color_type pixel(int x, int y) const
47  {
48  if (m_scale < 1.0)
49  {
50  // Interpolate between nearest source pixels.
51  double src_y = (y + 0.5) * m_scale - 0.5;
52  int h = m_source.height() - 1;
53  int y1 = ifloor(src_y);
54  int y2 = y1 + 1;
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);
58  }
59  else
60  {
61  // Average source pixels between y and y+1.
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;
69  while (++y1 < y2)
70  {
71  if (y1 <= h) c += m_source.pixel(x, y1);
72  }
73  if (y2 <= h) c += rgba(m_source.pixel(x, y2)) *= src_y2 - y2;
74  return c *= m_scale_inv;
75  }
76  }
77 
78  private:
80  const line_image_scale<Source>& operator = (const line_image_scale<Source>&);
81 
82  const Source& m_source;
83  double m_height;
84  double m_scale;
85  double m_scale_inv;
86  };
87 
88 
89 
90  //======================================================line_image_pattern
91  template<class Filter> class line_image_pattern
92  {
93  public:
94  typedef Filter filter_type;
95  typedef typename filter_type::color_type color_type;
96 
97  //--------------------------------------------------------------------
98  line_image_pattern(Filter& filter) :
99  m_filter(&filter),
100  m_dilation(filter.dilation() + 1),
101  m_dilation_hr(m_dilation << line_subpixel_shift),
102  m_data(),
103  m_width(0),
104  m_height(0),
105  m_width_hr(0),
106  m_half_height_hr(0),
107  m_offset_y_hr(0)
108  {
109  }
110 
111  // Create
112  //--------------------------------------------------------------------
113  template<class Source>
114  line_image_pattern(Filter& filter, const Source& src) :
115  m_filter(&filter),
116  m_dilation(filter.dilation() + 1),
117  m_dilation_hr(m_dilation << line_subpixel_shift),
118  m_data(),
119  m_width(0),
120  m_height(0),
121  m_width_hr(0),
122  m_half_height_hr(0),
123  m_offset_y_hr(0)
124  {
125  create(src);
126  }
127 
128  // Create
129  //--------------------------------------------------------------------
130  template<class Source> void create(const Source& src)
131  {
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;
138 
139  m_data.resize((m_width + m_dilation * 2) * (m_height + m_dilation * 2));
140 
141  m_buf.attach(&m_data[0], m_width + m_dilation * 2,
142  m_height + m_dilation * 2,
143  m_width + m_dilation * 2);
144  unsigned x, y;
145  color_type* d1;
146  color_type* d2;
147  for(y = 0; y < m_height; y++)
148  {
149  d1 = m_buf.row_ptr(y + m_dilation) + m_dilation;
150  for(x = 0; x < m_width; x++)
151  {
152  *d1++ = src.pixel(x, y);
153  }
154  }
155 
156  const color_type* s1;
157  const color_type* s2;
158  for(y = 0; y < m_dilation; y++)
159  {
160  //s1 = m_buf.row_ptr(m_height + m_dilation - 1) + m_dilation;
161  //s2 = m_buf.row_ptr(m_dilation) + m_dilation;
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++)
165  {
166  //*d1++ = color_type(*s1++, 0);
167  //*d2++ = color_type(*s2++, 0);
168  *d1++ = color_type::no_color();
169  *d2++ = color_type::no_color();
170  }
171  }
172 
173  unsigned h = m_height + m_dilation * 2;
174  for(y = 0; y < h; y++)
175  {
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;
180 
181  for(x = 0; x < m_dilation; x++)
182  {
183  *d1++ = *s1++;
184  *--d2 = *--s2;
185  }
186  }
187  }
188 
189  //--------------------------------------------------------------------
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; }
193 
194  //--------------------------------------------------------------------
195  void pixel(color_type* p, int x, int y) const
196  {
197  m_filter->pixel_high_res(m_buf.rows(),
198  p,
199  x % m_width_hr + m_dilation_hr,
200  y + m_offset_y_hr);
201  }
202 
203  //--------------------------------------------------------------------
204  const filter_type& filter() const { return *m_filter; }
205 
206  private:
209  operator = (const line_image_pattern<filter_type>&);
210 
211  protected:
213  const filter_type* m_filter;
214  unsigned m_dilation;
215  int m_dilation_hr;
216  pod_array<color_type> m_data;
217  unsigned m_width;
218  unsigned m_height;
219  int m_width_hr;
220  int m_half_height_hr;
221  int m_offset_y_hr;
222  };
223 
224 
225 
226 
227 
228 
229  //=================================================line_image_pattern_pow2
230  template<class Filter> class line_image_pattern_pow2 :
231  public line_image_pattern<Filter>
232  {
233  public:
234  typedef Filter filter_type;
235  typedef typename filter_type::color_type color_type;
237 
238  //--------------------------------------------------------------------
239  line_image_pattern_pow2(Filter& filter) :
240  line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) {}
241 
242  //--------------------------------------------------------------------
243  template<class Source>
244  line_image_pattern_pow2(Filter& filter, const Source& src) :
245  line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask)
246  {
247  create(src);
248  }
249 
250  //--------------------------------------------------------------------
251  template<class Source> void create(const Source& src)
252  {
254  m_mask = 1;
255  while(m_mask < base_type::m_width)
256  {
257  m_mask <<= 1;
258  m_mask |= 1;
259  }
260  m_mask <<= line_subpixel_shift - 1;
261  m_mask |= line_subpixel_mask;
262  base_type::m_width_hr = m_mask + 1;
263  }
264 
265  //--------------------------------------------------------------------
266  void pixel(color_type* p, int x, int y) const
267  {
268  base_type::m_filter->pixel_high_res(
269  base_type::m_buf.rows(),
270  p,
271  (x & m_mask) + base_type::m_dilation_hr,
272  y + base_type::m_offset_y_hr);
273  }
274  private:
275  unsigned m_mask;
276  };
277 
278 
279 
280 
281 
282 
283 
284  //===================================================distance_interpolator4
286  {
287  public:
288  //---------------------------------------------------------------------
290  distance_interpolator4(int x1, int y1, int x2, int y2,
291  int sx, int sy, int ex, int ey,
292  int len, double scale, int x, int y) :
293  m_dx(x2 - x1),
294  m_dy(y2 - y1),
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)),
299 
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))),
302 
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),
305 
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))
309  {
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);
313  m_dx_pict = -dy;
314  m_dy_pict = dx;
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) >>
317  line_subpixel_shift;
318 
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;
325  }
326 
327  //---------------------------------------------------------------------
328  void inc_x()
329  {
330  m_dist += m_dy;
331  m_dist_start += m_dy_start;
332  m_dist_pict += m_dy_pict;
333  m_dist_end += m_dy_end;
334  }
335 
336  //---------------------------------------------------------------------
337  void dec_x()
338  {
339  m_dist -= m_dy;
340  m_dist_start -= m_dy_start;
341  m_dist_pict -= m_dy_pict;
342  m_dist_end -= m_dy_end;
343  }
344 
345  //---------------------------------------------------------------------
346  void inc_y()
347  {
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;
352  }
353 
354  //---------------------------------------------------------------------
355  void dec_y()
356  {
357  m_dist += m_dx;
358  m_dist_start += m_dx_start;
359  m_dist_pict += m_dx_pict;
360  m_dist_end += m_dx_end;
361  }
362 
363  //---------------------------------------------------------------------
364  void inc_x(int dy)
365  {
366  m_dist += m_dy;
367  m_dist_start += m_dy_start;
368  m_dist_pict += m_dy_pict;
369  m_dist_end += m_dy_end;
370  if(dy > 0)
371  {
372  m_dist -= m_dx;
373  m_dist_start -= m_dx_start;
374  m_dist_pict -= m_dx_pict;
375  m_dist_end -= m_dx_end;
376  }
377  if(dy < 0)
378  {
379  m_dist += m_dx;
380  m_dist_start += m_dx_start;
381  m_dist_pict += m_dx_pict;
382  m_dist_end += m_dx_end;
383  }
384  }
385 
386  //---------------------------------------------------------------------
387  void dec_x(int dy)
388  {
389  m_dist -= m_dy;
390  m_dist_start -= m_dy_start;
391  m_dist_pict -= m_dy_pict;
392  m_dist_end -= m_dy_end;
393  if(dy > 0)
394  {
395  m_dist -= m_dx;
396  m_dist_start -= m_dx_start;
397  m_dist_pict -= m_dx_pict;
398  m_dist_end -= m_dx_end;
399  }
400  if(dy < 0)
401  {
402  m_dist += m_dx;
403  m_dist_start += m_dx_start;
404  m_dist_pict += m_dx_pict;
405  m_dist_end += m_dx_end;
406  }
407  }
408 
409  //---------------------------------------------------------------------
410  void inc_y(int dx)
411  {
412  m_dist -= m_dx;
413  m_dist_start -= m_dx_start;
414  m_dist_pict -= m_dx_pict;
415  m_dist_end -= m_dx_end;
416  if(dx > 0)
417  {
418  m_dist += m_dy;
419  m_dist_start += m_dy_start;
420  m_dist_pict += m_dy_pict;
421  m_dist_end += m_dy_end;
422  }
423  if(dx < 0)
424  {
425  m_dist -= m_dy;
426  m_dist_start -= m_dy_start;
427  m_dist_pict -= m_dy_pict;
428  m_dist_end -= m_dy_end;
429  }
430  }
431 
432  //---------------------------------------------------------------------
433  void dec_y(int dx)
434  {
435  m_dist += m_dx;
436  m_dist_start += m_dx_start;
437  m_dist_pict += m_dx_pict;
438  m_dist_end += m_dx_end;
439  if(dx > 0)
440  {
441  m_dist += m_dy;
442  m_dist_start += m_dy_start;
443  m_dist_pict += m_dy_pict;
444  m_dist_end += m_dy_end;
445  }
446  if(dx < 0)
447  {
448  m_dist -= m_dy;
449  m_dist_start -= m_dy_start;
450  m_dist_pict -= m_dy_pict;
451  m_dist_end -= m_dy_end;
452  }
453  }
454 
455  //---------------------------------------------------------------------
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; }
460 
461  //---------------------------------------------------------------------
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; }
471 
472  private:
473  //---------------------------------------------------------------------
474  int m_dx;
475  int m_dy;
476  int m_dx_start;
477  int m_dy_start;
478  int m_dx_pict;
479  int m_dy_pict;
480  int m_dx_end;
481  int m_dy_end;
482 
483  int m_dist;
484  int m_dist_start;
485  int m_dist_pict;
486  int m_dist_end;
487  int m_len;
488  };
489 
490 
491 
492 
493 
494  //==================================================line_interpolator_image
495  template<class Renderer> class line_interpolator_image
496  {
497  public:
498  typedef Renderer renderer_type;
499  typedef typename Renderer::color_type color_type;
500 
501  //---------------------------------------------------------------------
502  enum max_half_width_e
503  {
504  max_half_width = 64
505  };
506 
507  //---------------------------------------------------------------------
508  line_interpolator_image(renderer_type& ren, const line_parameters& lp,
509  int sx, int sy, int ex, int ey,
510  int pattern_start,
511  double scale_x) :
512  m_lp(lp),
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),
519  m_ren(ren),
520  m_x(lp.x1 >> line_subpixel_shift),
521  m_y(lp.y1 >> line_subpixel_shift),
522  m_old_x(m_x),
523  m_old_y(m_y),
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()),
527  //m_max_extent(m_width >> (line_subpixel_shift - 2)),
528  m_max_extent((m_width + line_subpixel_scale) >> line_subpixel_shift),
529  m_start(pattern_start + (m_max_extent + 2) * ren.pattern_width()),
530  m_step(0)
531  {
532  agg::dda2_line_interpolator li(0, lp.vertical ?
533  (lp.dy << agg::line_subpixel_shift) :
534  (lp.dx << agg::line_subpixel_shift),
535  lp.len);
536 
537  unsigned i;
538  int stop = m_width + line_subpixel_scale * 2;
539  for(i = 0; i < max_half_width; ++i)
540  {
541  m_dist_pos[i] = li.y();
542  if(m_dist_pos[i] >= stop) break;
543  ++li;
544  }
545  m_dist_pos[i] = 0x7FFF0000;
546 
547  int dist1_start;
548  int dist2_start;
549  int npix = 1;
550 
551  if(lp.vertical)
552  {
553  do
554  {
555  --m_li;
556  m_y -= lp.inc;
557  m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;
558 
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);
561 
562  m_old_x = m_x;
563 
564  dist1_start = dist2_start = m_di.dist_start();
565 
566  int dx = 0;
567  if(dist1_start < 0) ++npix;
568  do
569  {
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;
574  ++dx;
575  }
576  while(m_dist_pos[dx] <= m_width);
577  if(npix == 0) break;
578 
579  npix = 0;
580  }
581  while(--m_step >= -m_max_extent);
582  }
583  else
584  {
585  do
586  {
587  --m_li;
588 
589  m_x -= lp.inc;
590  m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;
591 
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);
594 
595  m_old_y = m_y;
596 
597  dist1_start = dist2_start = m_di.dist_start();
598 
599  int dy = 0;
600  if(dist1_start < 0) ++npix;
601  do
602  {
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;
607  ++dy;
608  }
609  while(m_dist_pos[dy] <= m_width);
610  if(npix == 0) break;
611 
612  npix = 0;
613  }
614  while(--m_step >= -m_max_extent);
615  }
616  m_li.adjust_forward();
617  m_step -= m_max_extent;
618  }
619 
620  //---------------------------------------------------------------------
621  bool step_hor()
622  {
623  ++m_li;
624  m_x += m_lp.inc;
625  m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;
626 
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);
629 
630  m_old_y = m_y;
631 
632  int s1 = m_di.dist() / m_lp.len;
633  int s2 = -s1;
634 
635  if(m_lp.inc < 0) s1 = -s1;
636 
637  int dist_start;
638  int dist_pict;
639  int dist_end;
640  int dy;
641  int dist;
642 
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;
647  color_type* p1 = p0;
648 
649  int npix = 0;
650  p1->clear();
651  if(dist_end > 0)
652  {
653  if(dist_start <= 0)
654  {
655  m_ren.pixel(p1, dist_pict, s2);
656  }
657  ++npix;
658  }
659  ++p1;
660 
661  dy = 1;
662  while((dist = m_dist_pos[dy]) - s1 <= m_width)
663  {
664  dist_start -= m_di.dx_start();
665  dist_pict -= m_di.dx_pict();
666  dist_end -= m_di.dx_end();
667  p1->clear();
668  if(dist_end > 0 && dist_start <= 0)
669  {
670  if(m_lp.inc > 0) dist = -dist;
671  m_ren.pixel(p1, dist_pict, s2 - dist);
672  ++npix;
673  }
674  ++p1;
675  ++dy;
676  }
677 
678  dy = 1;
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)
683  {
684  dist_start += m_di.dx_start();
685  dist_pict += m_di.dx_pict();
686  dist_end += m_di.dx_end();
687  --p0;
688  p0->clear();
689  if(dist_end > 0 && dist_start <= 0)
690  {
691  if(m_lp.inc > 0) dist = -dist;
692  m_ren.pixel(p0, dist_pict, s2 + dist);
693  ++npix;
694  }
695  ++dy;
696  }
697  m_ren.blend_color_vspan(m_x,
698  m_y - dy + 1,
699  unsigned(p1 - p0),
700  p0);
701  return npix && ++m_step < m_count;
702  }
703 
704 
705 
706  //---------------------------------------------------------------------
707  bool step_ver()
708  {
709  ++m_li;
710  m_y += m_lp.inc;
711  m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;
712 
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);
715 
716  m_old_x = m_x;
717 
718  int s1 = m_di.dist() / m_lp.len;
719  int s2 = -s1;
720 
721  if(m_lp.inc > 0) s1 = -s1;
722 
723  int dist_start;
724  int dist_pict;
725  int dist_end;
726  int dist;
727  int dx;
728 
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;
733  color_type* p1 = p0;
734 
735  int npix = 0;
736  p1->clear();
737  if(dist_end > 0)
738  {
739  if(dist_start <= 0)
740  {
741  m_ren.pixel(p1, dist_pict, s2);
742  }
743  ++npix;
744  }
745  ++p1;
746 
747  dx = 1;
748  while((dist = m_dist_pos[dx]) - s1 <= m_width)
749  {
750  dist_start += m_di.dy_start();
751  dist_pict += m_di.dy_pict();
752  dist_end += m_di.dy_end();
753  p1->clear();
754  if(dist_end > 0 && dist_start <= 0)
755  {
756  if(m_lp.inc > 0) dist = -dist;
757  m_ren.pixel(p1, dist_pict, s2 + dist);
758  ++npix;
759  }
760  ++p1;
761  ++dx;
762  }
763 
764  dx = 1;
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)
769  {
770  dist_start -= m_di.dy_start();
771  dist_pict -= m_di.dy_pict();
772  dist_end -= m_di.dy_end();
773  --p0;
774  p0->clear();
775  if(dist_end > 0 && dist_start <= 0)
776  {
777  if(m_lp.inc > 0) dist = -dist;
778  m_ren.pixel(p0, dist_pict, s2 - dist);
779  ++npix;
780  }
781  ++dx;
782  }
783  m_ren.blend_color_hspan(m_x - dx + 1,
784  m_y,
785  unsigned(p1 - p0),
786  p0);
787  return npix && ++m_step < m_count;
788  }
789 
790 
791  //---------------------------------------------------------------------
792  int pattern_end() const { return m_start + m_di.len(); }
793 
794  //---------------------------------------------------------------------
795  bool vertical() const { return m_lp.vertical; }
796  int width() const { return m_width; }
797  int count() const { return m_count; }
798 
799  private:
802  operator = (const line_interpolator_image<Renderer>&);
803 
804  protected:
805  const line_parameters& m_lp;
808  renderer_type& m_ren;
809  int m_plen;
810  int m_x;
811  int m_y;
812  int m_old_x;
813  int m_old_y;
814  int m_count;
815  int m_width;
816  int m_max_extent;
817  int m_start;
818  int m_step;
819  int m_dist_pos[max_half_width + 1];
820  color_type m_colors[max_half_width * 2 + 4];
821  };
822 
823 
824 
825 
826 
827 
828 
829 
830  //===================================================renderer_outline_image
831  template<class BaseRenderer, class ImagePattern>
833  {
834  public:
835  //---------------------------------------------------------------------
836  typedef BaseRenderer base_ren_type;
838  typedef typename base_ren_type::color_type color_type;
839  typedef ImagePattern pattern_type;
840 
841 
842  //---------------------------------------------------------------------
843  renderer_outline_image(base_ren_type& ren, pattern_type& patt) :
844  m_ren(&ren),
845  m_pattern(&patt),
846  m_start(0),
847  m_scale_x(1.0),
848  m_clip_box(0,0,0,0),
849  m_clipping(false)
850  {}
851  void attach(base_ren_type& ren) { m_ren = &ren; }
852 
853  //---------------------------------------------------------------------
854  void pattern(pattern_type& p) { m_pattern = &p; }
855  pattern_type& pattern() const { return *m_pattern; }
856 
857  //---------------------------------------------------------------------
858  void reset_clipping() { m_clipping = false; }
859  void clip_box(double x1, double y1, double x2, double y2)
860  {
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);
865  m_clipping = true;
866  }
867 
868  //---------------------------------------------------------------------
869  void scale_x(double s) { m_scale_x = s; }
870  double scale_x() const { return m_scale_x; }
871 
872  //---------------------------------------------------------------------
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; }
875 
876  //---------------------------------------------------------------------
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; }
880 
881  //-------------------------------------------------------------------------
882  void pixel(color_type* p, int x, int y) const
883  {
884  m_pattern->pixel(p, x, y);
885  }
886 
887  //-------------------------------------------------------------------------
888  void blend_color_hspan(int x, int y, unsigned len, const color_type* colors)
889  {
890  m_ren->blend_color_hspan(x, y, len, colors, 0);
891  }
892 
893  //-------------------------------------------------------------------------
894  void blend_color_vspan(int x, int y, unsigned len, const color_type* colors)
895  {
896  m_ren->blend_color_vspan(x, y, len, colors, 0);
897  }
898 
899  //-------------------------------------------------------------------------
900  static bool accurate_join_only() { return true; }
901 
902  //-------------------------------------------------------------------------
903  template<class Cmp>
904  void semidot(Cmp, int, int, int, int)
905  {
906  }
907 
908  //-------------------------------------------------------------------------
909  void pie(int, int, int, int, int, int)
910  {
911  }
912 
913  //-------------------------------------------------------------------------
914  void line0(const line_parameters&)
915  {
916  }
917 
918  //-------------------------------------------------------------------------
919  void line1(const line_parameters&, int, int)
920  {
921  }
922 
923  //-------------------------------------------------------------------------
924  void line2(const line_parameters&, int, int)
925  {
926  }
927 
928  //-------------------------------------------------------------------------
929  void line3_no_clip(const line_parameters& lp,
930  int sx, int sy, int ex, int ey)
931  {
932  if(lp.len > line_max_length)
933  {
934  line_parameters lp1, lp2;
935  lp.divide(lp1, lp2);
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);
940  return;
941  }
942 
943  fix_degenerate_bisectrix_start(lp, &sx, &sy);
944  fix_degenerate_bisectrix_end(lp, &ex, &ey);
946  sx, sy,
947  ex, ey,
948  m_start, m_scale_x);
949  if(li.vertical())
950  {
951  while(li.step_ver());
952  }
953  else
954  {
955  while(li.step_hor());
956  }
957  m_start += uround(lp.len / m_scale_x);
958  }
959 
960  //-------------------------------------------------------------------------
961  void line3(const line_parameters& lp,
962  int sx, int sy, int ex, int ey)
963  {
964  if(m_clipping)
965  {
966  int x1 = lp.x1;
967  int y1 = lp.y1;
968  int x2 = lp.x2;
969  int y2 = lp.y2;
970  unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box);
971  int start = m_start;
972  if((flags & 4) == 0)
973  {
974  if(flags)
975  {
976  line_parameters lp2(x1, y1, x2, y2,
977  uround(calc_distance(x1, y1, x2, y2)));
978  if(flags & 1)
979  {
980  m_start += uround(calc_distance(lp.x1, lp.y1, x1, y1) / m_scale_x);
981  sx = x1 + (y2 - y1);
982  sy = y1 - (x2 - x1);
983  }
984  else
985  {
986  while(std::abs(sx - lp.x1) + std::abs(sy - lp.y1) > lp2.len)
987  {
988  sx = (lp.x1 + sx) >> 1;
989  sy = (lp.y1 + sy) >> 1;
990  }
991  }
992  if(flags & 2)
993  {
994  ex = x2 + (y2 - y1);
995  ey = y2 - (x2 - x1);
996  }
997  else
998  {
999  while(std::abs(ex - lp.x2) + std::abs(ey - lp.y2) > lp2.len)
1000  {
1001  ex = (lp.x2 + ex) >> 1;
1002  ey = (lp.y2 + ey) >> 1;
1003  }
1004  }
1005  line3_no_clip(lp2, sx, sy, ex, ey);
1006  }
1007  else
1008  {
1009  line3_no_clip(lp, sx, sy, ex, ey);
1010  }
1011  }
1012  m_start = start + uround(lp.len / m_scale_x);
1013  }
1014  else
1015  {
1016  line3_no_clip(lp, sx, sy, ex, ey);
1017  }
1018  }
1019 
1020  private:
1021  base_ren_type* m_ren;
1022  pattern_type* m_pattern;
1023  int m_start;
1024  double m_scale_x;
1025  rect_i m_clip_box;
1026  bool m_clipping;
1027  };
1028 
1029 
1030 
1031 
1032 
1033 }
1034 
1035 
1036 
1037 #endif
Definition: agg_arc.cpp:24