1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
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.
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"
22 //--------------------------------------------------------poly_max_coord_e
25 poly_max_coord
= (1 << 30) - 1 //----poly_max_coord
28 //------------------------------------------------------------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
76 typedef double coord_type
;
77 static AGG_INLINE
double mul_div(double a
, double b
, double 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
)
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
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() :
122 //--------------------------------------------------------------------
123 void reset_clipping()
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();
136 //--------------------------------------------------------------------
137 void move_to(coord_type x1
, coord_type y1
)
141 if(m_clipping
) m_f1
= clipping_flags(x1
, y1
, m_clip_box
);
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
157 ras
.line(Conv::xi(x1
), Conv::yi(y1
), Conv::xi(x2
), Conv::yi(y2
));
172 if(f1
& 8) // y1 < clip.y1
174 tx1
= x1
+ Conv::mul_div(m_clip_box
.y1
-y1
, x2
-x1
, y2
-y1
);
178 if(f1
& 2) // y1 > clip.y2
180 tx1
= x1
+ Conv::mul_div(m_clip_box
.y2
-y1
, x2
-x1
, y2
-y1
);
184 if(f2
& 8) // y2 < clip.y1
186 tx2
= x1
+ Conv::mul_div(m_clip_box
.y1
-y1
, x2
-x1
, y2
-y1
);
190 if(f2
& 2) // y2 > clip.y2
192 tx2
= x1
+ Conv::mul_div(m_clip_box
.y2
-y1
, x2
-x1
, y2
-y1
);
195 ras
.line(Conv::xi(tx1
), Conv::yi(ty1
),
196 Conv::xi(tx2
), Conv::yi(ty2
));
202 //--------------------------------------------------------------------
203 template<class Rasterizer
>
204 void line_to(Rasterizer
& ras
, coord_type x2
, coord_type y2
)
208 unsigned f2
= clipping_flags(x2
, y2
, m_clip_box
);
210 if((m_f1
& 10) == (f2
& 10) && (m_f1
& 10) != 0)
219 coord_type x1
= m_x1
;
220 coord_type y1
= m_y1
;
225 switch(((f1
& 5) << 1) | (f2
& 5))
227 case 0: // Visible by X
228 line_clip_y(ras
, x1
, y1
, x2
, y2
, f1
, f2
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
291 ras
.line(Conv::xi(m_x1
), Conv::yi(m_y1
),
292 Conv::xi(x2
), Conv::yi(y2
));
300 rect_type m_clip_box
;
310 //---------------------------------------------------rasterizer_sl_no_clip
311 class rasterizer_sl_no_clip
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
);
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
;