Anti-Grain Geometry Tutorial
agg_rasterizer_sl_clip.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_RASTERIZER_SL_CLIP_INCLUDED
16 #define AGG_RASTERIZER_SL_CLIP_INCLUDED
17 
18 #include "agg_clip_liang_barsky.h"
19 
20 namespace agg
21 {
22  //--------------------------------------------------------poly_max_coord_e
23  enum poly_max_coord_e
24  {
25  poly_max_coord = (1 << 30) - 1 //----poly_max_coord
26  };
27 
28  //------------------------------------------------------------ras_conv_int
29  struct ras_conv_int
30  {
31  typedef int coord_type;
32  static AGG_INLINE int mul_div(double a, double b, double c)
33  {
34  return iround(a * b / c);
35  }
36  static int xi(int v) { return v; }
37  static int yi(int v) { return v; }
38  static int upscale(double v) { return iround(v * poly_subpixel_scale); }
39  static int downscale(int v) { return v; }
40  };
41 
42  //--------------------------------------------------------ras_conv_int_sat
44  {
45  typedef int coord_type;
46  static AGG_INLINE int mul_div(double a, double b, double c)
47  {
48  return saturation<poly_max_coord>::iround(a * b / c);
49  }
50  static int xi(int v) { return v; }
51  static int yi(int v) { return v; }
52  static int upscale(double v)
53  {
54  return saturation<poly_max_coord>::iround(v * poly_subpixel_scale);
55  }
56  static int downscale(int v) { return v; }
57  };
58 
59  //---------------------------------------------------------ras_conv_int_3x
61  {
62  typedef int coord_type;
63  static AGG_INLINE int mul_div(double a, double b, double c)
64  {
65  return iround(a * b / c);
66  }
67  static int xi(int v) { return v * 3; }
68  static int yi(int v) { return v; }
69  static int upscale(double v) { return iround(v * poly_subpixel_scale); }
70  static int downscale(int v) { return v; }
71  };
72 
73  //-----------------------------------------------------------ras_conv_dbl
74  struct ras_conv_dbl
75  {
76  typedef double coord_type;
77  static AGG_INLINE double mul_div(double a, double b, double c)
78  {
79  return a * b / c;
80  }
81  static int xi(double v) { return iround(v * poly_subpixel_scale); }
82  static int yi(double v) { return iround(v * poly_subpixel_scale); }
83  static double upscale(double v) { return v; }
84  static double downscale(int v) { return v / double(poly_subpixel_scale); }
85  };
86 
87  //--------------------------------------------------------ras_conv_dbl_3x
89  {
90  typedef double coord_type;
91  static AGG_INLINE double mul_div(double a, double b, double c)
92  {
93  return a * b / c;
94  }
95  static int xi(double v) { return iround(v * poly_subpixel_scale * 3); }
96  static int yi(double v) { return iround(v * poly_subpixel_scale); }
97  static double upscale(double v) { return v; }
98  static double downscale(int v) { return v / double(poly_subpixel_scale); }
99  };
100 
101 
102 
103 
104 
105  //------------------------------------------------------rasterizer_sl_clip
106  template<class Conv> class rasterizer_sl_clip
107  {
108  public:
109  typedef Conv conv_type;
110  typedef typename Conv::coord_type coord_type;
112 
113  //--------------------------------------------------------------------
114  rasterizer_sl_clip() :
115  m_clip_box(0,0,0,0),
116  m_x1(0),
117  m_y1(0),
118  m_f1(0),
119  m_clipping(false)
120  {}
121 
122  //--------------------------------------------------------------------
123  void reset_clipping()
124  {
125  m_clipping = false;
126  }
127 
128  //--------------------------------------------------------------------
129  void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2)
130  {
131  m_clip_box = rect_type(x1, y1, x2, y2);
132  m_clip_box.normalize();
133  m_clipping = true;
134  }
135 
136  //--------------------------------------------------------------------
137  void move_to(coord_type x1, coord_type y1)
138  {
139  m_x1 = x1;
140  m_y1 = y1;
141  if(m_clipping) m_f1 = clipping_flags(x1, y1, m_clip_box);
142  }
143 
144  private:
145  //------------------------------------------------------------------------
146  template<class Rasterizer>
147  AGG_INLINE void line_clip_y(Rasterizer& ras,
148  coord_type x1, coord_type y1,
149  coord_type x2, coord_type y2,
150  unsigned f1, unsigned f2) const
151  {
152  f1 &= 10;
153  f2 &= 10;
154  if((f1 | f2) == 0)
155  {
156  // Fully visible
157  ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2));
158  }
159  else
160  {
161  if(f1 == f2)
162  {
163  // Invisible by Y
164  return;
165  }
166 
167  coord_type tx1 = x1;
168  coord_type ty1 = y1;
169  coord_type tx2 = x2;
170  coord_type ty2 = y2;
171 
172  if(f1 & 8) // y1 < clip.y1
173  {
174  tx1 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
175  ty1 = m_clip_box.y1;
176  }
177 
178  if(f1 & 2) // y1 > clip.y2
179  {
180  tx1 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
181  ty1 = m_clip_box.y2;
182  }
183 
184  if(f2 & 8) // y2 < clip.y1
185  {
186  tx2 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
187  ty2 = m_clip_box.y1;
188  }
189 
190  if(f2 & 2) // y2 > clip.y2
191  {
192  tx2 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
193  ty2 = m_clip_box.y2;
194  }
195  ras.line(Conv::xi(tx1), Conv::yi(ty1),
196  Conv::xi(tx2), Conv::yi(ty2));
197  }
198  }
199 
200 
201  public:
202  //--------------------------------------------------------------------
203  template<class Rasterizer>
204  void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
205  {
206  if(m_clipping)
207  {
208  unsigned f2 = clipping_flags(x2, y2, m_clip_box);
209 
210  if((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0)
211  {
212  // Invisible by Y
213  m_x1 = x2;
214  m_y1 = y2;
215  m_f1 = f2;
216  return;
217  }
218 
219  coord_type x1 = m_x1;
220  coord_type y1 = m_y1;
221  unsigned f1 = m_f1;
222  coord_type y3, y4;
223  unsigned f3, f4;
224 
225  switch(((f1 & 5) << 1) | (f2 & 5))
226  {
227  case 0: // Visible by X
228  line_clip_y(ras, x1, y1, x2, y2, f1, f2);
229  break;
230 
231  case 1: // x2 > clip.x2
232  y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
233  f3 = clipping_flags_y(y3, m_clip_box);
234  line_clip_y(ras, x1, y1, m_clip_box.x2, y3, f1, f3);
235  line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x2, y2, f3, f2);
236  break;
237 
238  case 2: // x1 > clip.x2
239  y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
240  f3 = clipping_flags_y(y3, m_clip_box);
241  line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3);
242  line_clip_y(ras, m_clip_box.x2, y3, x2, y2, f3, f2);
243  break;
244 
245  case 3: // x1 > clip.x2 && x2 > clip.x2
246  line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y2, f1, f2);
247  break;
248 
249  case 4: // x2 < clip.x1
250  y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
251  f3 = clipping_flags_y(y3, m_clip_box);
252  line_clip_y(ras, x1, y1, m_clip_box.x1, y3, f1, f3);
253  line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x1, y2, f3, f2);
254  break;
255 
256  case 6: // x1 > clip.x2 && x2 < clip.x1
257  y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
258  y4 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
259  f3 = clipping_flags_y(y3, m_clip_box);
260  f4 = clipping_flags_y(y4, m_clip_box);
261  line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3);
262  line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x1, y4, f3, f4);
263  line_clip_y(ras, m_clip_box.x1, y4, m_clip_box.x1, y2, f4, f2);
264  break;
265 
266  case 8: // x1 < clip.x1
267  y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
268  f3 = clipping_flags_y(y3, m_clip_box);
269  line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3);
270  line_clip_y(ras, m_clip_box.x1, y3, x2, y2, f3, f2);
271  break;
272 
273  case 9: // x1 < clip.x1 && x2 > clip.x2
274  y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1);
275  y4 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1);
276  f3 = clipping_flags_y(y3, m_clip_box);
277  f4 = clipping_flags_y(y4, m_clip_box);
278  line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3);
279  line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x2, y4, f3, f4);
280  line_clip_y(ras, m_clip_box.x2, y4, m_clip_box.x2, y2, f4, f2);
281  break;
282 
283  case 12: // x1 < clip.x1 && x2 < clip.x1
284  line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y2, f1, f2);
285  break;
286  }
287  m_f1 = f2;
288  }
289  else
290  {
291  ras.line(Conv::xi(m_x1), Conv::yi(m_y1),
292  Conv::xi(x2), Conv::yi(y2));
293  }
294  m_x1 = x2;
295  m_y1 = y2;
296  }
297 
298 
299  private:
300  rect_type m_clip_box;
301  coord_type m_x1;
302  coord_type m_y1;
303  unsigned m_f1;
304  bool m_clipping;
305  };
306 
307 
308 
309 
310  //---------------------------------------------------rasterizer_sl_no_clip
312  {
313  public:
314  typedef ras_conv_int conv_type;
315  typedef int coord_type;
316 
317  rasterizer_sl_no_clip() : m_x1(0), m_y1(0) {}
318 
319  void reset_clipping() {}
320  void clip_box(coord_type, coord_type, coord_type, coord_type) {}
321  void move_to(coord_type x1, coord_type y1) { m_x1 = x1; m_y1 = y1; }
322 
323  template<class Rasterizer>
324  void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
325  {
326  ras.line(m_x1, m_y1, x2, y2);
327  m_x1 = x2;
328  m_y1 = y2;
329  }
330 
331  private:
332  int m_x1, m_y1;
333  };
334 
335 
336  // -----rasterizer_sl_clip_int
337  // -----rasterizer_sl_clip_int_sat
338  // -----rasterizer_sl_clip_int_3x
339  // -----rasterizer_sl_clip_dbl
340  // -----rasterizer_sl_clip_dbl_3x
341  //------------------------------------------------------------------------
347 
348 
349 }
350 
351 #endif
Definition: agg_arc.cpp:24