btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / libs / agg / agg_clip_liang_barsky.h
blob4b5fedbab5f6149a4881b863b9f26ccaabf9a2cc
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 //----------------------------------------------------------------------------
16 // Liang-Barsky clipping
18 //----------------------------------------------------------------------------
19 #ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED
20 #define AGG_CLIP_LIANG_BARSKY_INCLUDED
22 #include "agg_basics.h"
24 namespace agg
27 //------------------------------------------------------------------------
28 enum clipping_flags_e
30 clipping_flags_x1_clipped = 4,
31 clipping_flags_x2_clipped = 1,
32 clipping_flags_y1_clipped = 8,
33 clipping_flags_y2_clipped = 2,
34 clipping_flags_x_clipped = clipping_flags_x1_clipped | clipping_flags_x2_clipped,
35 clipping_flags_y_clipped = clipping_flags_y1_clipped | clipping_flags_y2_clipped
38 //----------------------------------------------------------clipping_flags
39 // Determine the clipping code of the vertex according to the
40 // Cyrus-Beck line clipping algorithm
42 // | |
43 // 0110 | 0010 | 0011
44 // | |
45 // -------+--------+-------- clip_box.y2
46 // | |
47 // 0100 | 0000 | 0001
48 // | |
49 // -------+--------+-------- clip_box.y1
50 // | |
51 // 1100 | 1000 | 1001
52 // | |
53 // clip_box.x1 clip_box.x2
55 //
56 template<class T>
57 inline unsigned clipping_flags(T x, T y, const rect_base<T>& clip_box)
59 return (x > clip_box.x2) |
60 ((y > clip_box.y2) << 1) |
61 ((x < clip_box.x1) << 2) |
62 ((y < clip_box.y1) << 3);
65 //--------------------------------------------------------clipping_flags_x
66 template<class T>
67 inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box)
69 return (x > clip_box.x2) | ((x < clip_box.x1) << 2);
73 //--------------------------------------------------------clipping_flags_y
74 template<class T>
75 inline unsigned clipping_flags_y(T y, const rect_base<T>& clip_box)
77 return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3);
81 //-------------------------------------------------------clip_liang_barsky
82 template<class T>
83 inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2,
84 const rect_base<T>& clip_box,
85 T* x, T* y)
87 const double nearzero = 1e-30;
89 double deltax = x2 - x1;
90 double deltay = y2 - y1;
91 double xin;
92 double xout;
93 double yin;
94 double yout;
95 double tinx;
96 double tiny;
97 double toutx;
98 double touty;
99 double tin1;
100 double tin2;
101 double tout1;
102 unsigned np = 0;
104 if(deltax == 0.0)
106 // bump off of the vertical
107 deltax = (x1 > clip_box.x1) ? -nearzero : nearzero;
110 if(deltay == 0.0)
112 // bump off of the horizontal
113 deltay = (y1 > clip_box.y1) ? -nearzero : nearzero;
116 if(deltax > 0.0)
118 // points to right
119 xin = clip_box.x1;
120 xout = clip_box.x2;
122 else
124 xin = clip_box.x2;
125 xout = clip_box.x1;
128 if(deltay > 0.0)
130 // points up
131 yin = clip_box.y1;
132 yout = clip_box.y2;
134 else
136 yin = clip_box.y2;
137 yout = clip_box.y1;
140 tinx = (xin - x1) / deltax;
141 tiny = (yin - y1) / deltay;
143 if (tinx < tiny)
145 // hits x first
146 tin1 = tinx;
147 tin2 = tiny;
149 else
151 // hits y first
152 tin1 = tiny;
153 tin2 = tinx;
156 if(tin1 <= 1.0)
158 if(0.0 < tin1)
160 *x++ = (T)xin;
161 *y++ = (T)yin;
162 ++np;
165 if(tin2 <= 1.0)
167 toutx = (xout - x1) / deltax;
168 touty = (yout - y1) / deltay;
170 tout1 = (toutx < touty) ? toutx : touty;
172 if(tin2 > 0.0 || tout1 > 0.0)
174 if(tin2 <= tout1)
176 if(tin2 > 0.0)
178 if(tinx > tiny)
180 *x++ = (T)xin;
181 *y++ = (T)(y1 + tinx * deltay);
183 else
185 *x++ = (T)(x1 + tiny * deltax);
186 *y++ = (T)yin;
188 ++np;
191 if(tout1 < 1.0)
193 if(toutx < touty)
195 *x++ = (T)xout;
196 *y++ = (T)(y1 + toutx * deltay);
198 else
200 *x++ = (T)(x1 + touty * deltax);
201 *y++ = (T)yout;
204 else
206 *x++ = x2;
207 *y++ = y2;
209 ++np;
211 else
213 if(tinx > tiny)
215 *x++ = (T)xin;
216 *y++ = (T)yout;
218 else
220 *x++ = (T)xout;
221 *y++ = (T)yin;
223 ++np;
228 return np;
232 //----------------------------------------------------------------------------
233 template<class T>
234 bool clip_move_point(T x1, T y1, T x2, T y2,
235 const rect_base<T>& clip_box,
236 T* x, T* y, unsigned flags)
238 T bound;
240 if(flags & clipping_flags_x_clipped)
242 if(x1 == x2)
244 return false;
246 bound = (flags & clipping_flags_x1_clipped) ? clip_box.x1 : clip_box.x2;
247 *y = (T)(double(bound - x1) * (y2 - y1) / (x2 - x1) + y1);
248 *x = bound;
251 flags = clipping_flags_y(*y, clip_box);
252 if(flags & clipping_flags_y_clipped)
254 if(y1 == y2)
256 return false;
258 bound = (flags & clipping_flags_y1_clipped) ? clip_box.y1 : clip_box.y2;
259 *x = (T)(double(bound - y1) * (x2 - x1) / (y2 - y1) + x1);
260 *y = bound;
262 return true;
265 //-------------------------------------------------------clip_line_segment
266 // Returns: ret >= 4 - Fully clipped
267 // (ret & 1) != 0 - First point has been moved
268 // (ret & 2) != 0 - Second point has been moved
270 template<class T>
271 unsigned clip_line_segment(T* x1, T* y1, T* x2, T* y2,
272 const rect_base<T>& clip_box)
274 unsigned f1 = clipping_flags(*x1, *y1, clip_box);
275 unsigned f2 = clipping_flags(*x2, *y2, clip_box);
276 unsigned ret = 0;
278 if((f2 | f1) == 0)
280 // Fully visible
281 return 0;
284 if((f1 & clipping_flags_x_clipped) != 0 &&
285 (f1 & clipping_flags_x_clipped) == (f2 & clipping_flags_x_clipped))
287 // Fully clipped
288 return 4;
291 if((f1 & clipping_flags_y_clipped) != 0 &&
292 (f1 & clipping_flags_y_clipped) == (f2 & clipping_flags_y_clipped))
294 // Fully clipped
295 return 4;
298 T tx1 = *x1;
299 T ty1 = *y1;
300 T tx2 = *x2;
301 T ty2 = *y2;
302 if(f1)
304 if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x1, y1, f1))
306 return 4;
308 if(*x1 == *x2 && *y1 == *y2)
310 return 4;
312 ret |= 1;
314 if(f2)
316 if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x2, y2, f2))
318 return 4;
320 if(*x1 == *x2 && *y1 == *y2)
322 return 4;
324 ret |= 2;
326 return ret;
333 #endif