btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / libs / agg / agg_rasterizer_sl_clip.h
blobe7ba065acce8d5b14cc78a9ec63e3230cc9cb71a
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
18 #include "agg_clip_liang_barsky.h"
20 namespace agg
22 //--------------------------------------------------------poly_max_coord_e
23 enum poly_max_coord_e
25 poly_max_coord = (1 << 30) - 1 //----poly_max_coord
28 //------------------------------------------------------------ras_conv_int
29 struct ras_conv_int
31 typedef int coord_type;
32 static AGG_INLINE int mul_div(double a, double b, double c)
34 return iround(a * b / c);
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; }
42 //--------------------------------------------------------ras_conv_int_sat
43 struct ras_conv_int_sat
45 typedef int coord_type;
46 static AGG_INLINE int mul_div(double a, double b, double c)
48 return saturation<poly_max_coord>::iround(a * b / c);
50 static int xi(int v) { return v; }
51 static int yi(int v) { return v; }
52 static int upscale(double v)
54 return saturation<poly_max_coord>::iround(v * poly_subpixel_scale);
56 static int downscale(int v) { return v; }
59 //---------------------------------------------------------ras_conv_int_3x
60 struct ras_conv_int_3x
62 typedef int coord_type;
63 static AGG_INLINE int mul_div(double a, double b, double c)
65 return iround(a * b / c);
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; }
73 //-----------------------------------------------------------ras_conv_dbl
74 struct ras_conv_dbl
76 typedef double coord_type;
77 static AGG_INLINE double mul_div(double a, double b, double c)
79 return a * b / c;
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); }
87 //--------------------------------------------------------ras_conv_dbl_3x
88 struct ras_conv_dbl_3x
90 typedef double coord_type;
91 static AGG_INLINE double mul_div(double a, double b, double c)
93 return a * b / c;
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); }
105 //------------------------------------------------------rasterizer_sl_clip
106 template<class Conv> class rasterizer_sl_clip
108 public:
109 typedef Conv conv_type;
110 typedef typename Conv::coord_type coord_type;
111 typedef rect_base<coord_type> rect_type;
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)
122 //--------------------------------------------------------------------
123 void reset_clipping()
125 m_clipping = false;
128 //--------------------------------------------------------------------
129 void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2)
131 m_clip_box = rect_type(x1, y1, x2, y2);
132 m_clip_box.normalize();
133 m_clipping = true;
136 //--------------------------------------------------------------------
137 void move_to(coord_type x1, coord_type y1)
139 m_x1 = x1;
140 m_y1 = y1;
141 if(m_clipping) m_f1 = clipping_flags(x1, y1, m_clip_box);
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
152 f1 &= 10;
153 f2 &= 10;
154 if((f1 | f2) == 0)
156 // Fully visible
157 ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2));
159 else
161 if(f1 == f2)
163 // Invisible by Y
164 return;
167 coord_type tx1 = x1;
168 coord_type ty1 = y1;
169 coord_type tx2 = x2;
170 coord_type ty2 = y2;
172 if(f1 & 8) // y1 < clip.y1
174 tx1 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
175 ty1 = m_clip_box.y1;
178 if(f1 & 2) // y1 > clip.y2
180 tx1 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
181 ty1 = m_clip_box.y2;
184 if(f2 & 8) // y2 < clip.y1
186 tx2 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
187 ty2 = m_clip_box.y1;
190 if(f2 & 2) // y2 > clip.y2
192 tx2 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
193 ty2 = m_clip_box.y2;
195 ras.line(Conv::xi(tx1), Conv::yi(ty1),
196 Conv::xi(tx2), Conv::yi(ty2));
201 public:
202 //--------------------------------------------------------------------
203 template<class Rasterizer>
204 void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
206 if(m_clipping)
208 unsigned f2 = clipping_flags(x2, y2, m_clip_box);
210 if((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0)
212 // Invisible by Y
213 m_x1 = x2;
214 m_y1 = y2;
215 m_f1 = f2;
216 return;
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;
225 switch(((f1 & 5) << 1) | (f2 & 5))
227 case 0: // Visible by X
228 line_clip_y(ras, x1, y1, x2, y2, f1, f2);
229 break;
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;
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;
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;
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;
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;
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;
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;
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;
287 m_f1 = f2;
289 else
291 ras.line(Conv::xi(m_x1), Conv::yi(m_y1),
292 Conv::xi(x2), Conv::yi(y2));
294 m_x1 = x2;
295 m_y1 = y2;
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;
310 //---------------------------------------------------rasterizer_sl_no_clip
311 class rasterizer_sl_no_clip
313 public:
314 typedef ras_conv_int conv_type;
315 typedef int coord_type;
317 rasterizer_sl_no_clip() : m_x1(0), m_y1(0) {}
319 void reset_clipping() {}
320 void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2) {}
321 void move_to(coord_type x1, coord_type y1) { m_x1 = x1; m_y1 = y1; }
323 template<class Rasterizer>
324 void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
326 ras.line(m_x1, m_y1, x2, y2);
327 m_x1 = x2;
328 m_y1 = y2;
331 private:
332 int m_x1, m_y1;
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 //------------------------------------------------------------------------
342 typedef rasterizer_sl_clip<ras_conv_int> rasterizer_sl_clip_int;
343 typedef rasterizer_sl_clip<ras_conv_int_sat> rasterizer_sl_clip_int_sat;
344 typedef rasterizer_sl_clip<ras_conv_int_3x> rasterizer_sl_clip_int_3x;
345 typedef rasterizer_sl_clip<ras_conv_dbl> rasterizer_sl_clip_dbl;
346 typedef rasterizer_sl_clip<ras_conv_dbl_3x> rasterizer_sl_clip_dbl_3x;
351 #endif