vfs: check userland buffers before reading them.
[haiku.git] / headers / libs / agg / agg_curves.h
blob1ef02e87834ebbea47b95af32b714a264341d389
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 // Copyright (C) 2005 Tony Juricic (tonygeek@yahoo.com)
5 //
6 // Permission to copy, use, modify, sell and distribute this software
7 // is granted provided this copyright notice appears in all copies.
8 // This software is provided "as is" without express or implied
9 // warranty, and with no claim as to its suitability for any purpose.
11 //----------------------------------------------------------------------------
12 // Contact: mcseem@antigrain.com
13 // mcseemagg@yahoo.com
14 // http://www.antigrain.com
15 //----------------------------------------------------------------------------
17 #ifndef AGG_CURVES_INCLUDED
18 #define AGG_CURVES_INCLUDED
20 #include "agg_array.h"
22 namespace agg
25 // See Implementation agg_curves.cpp
27 //--------------------------------------------curve_approximation_method_e
28 enum curve_approximation_method_e
30 curve_inc,
31 curve_div
34 //--------------------------------------------------------------curve3_inc
35 class curve3_inc
37 public:
38 curve3_inc() :
39 m_num_steps(0), m_step(0), m_scale(1.0) { }
41 curve3_inc(double x1, double y1,
42 double x2, double y2,
43 double x3, double y3) :
44 m_num_steps(0), m_step(0), m_scale(1.0)
46 init(x1, y1, x2, y2, x3, y3);
49 void reset() { m_num_steps = 0; m_step = -1; }
50 void init(double x1, double y1,
51 double x2, double y2,
52 double x3, double y3);
54 void approximation_method(curve_approximation_method_e) {}
55 curve_approximation_method_e approximation_method() const { return curve_inc; }
57 void approximation_scale(double s);
58 double approximation_scale() const;
60 void angle_tolerance(double) {}
61 double angle_tolerance() const { return 0.0; }
63 void cusp_limit(double) {}
64 double cusp_limit() const { return 0.0; }
66 void rewind(unsigned path_id);
67 unsigned vertex(double* x, double* y);
69 private:
70 int m_num_steps;
71 int m_step;
72 double m_scale;
73 double m_start_x;
74 double m_start_y;
75 double m_end_x;
76 double m_end_y;
77 double m_fx;
78 double m_fy;
79 double m_dfx;
80 double m_dfy;
81 double m_ddfx;
82 double m_ddfy;
83 double m_saved_fx;
84 double m_saved_fy;
85 double m_saved_dfx;
86 double m_saved_dfy;
93 //-------------------------------------------------------------curve3_div
94 class curve3_div
96 public:
97 curve3_div() :
98 m_approximation_scale(1.0),
99 m_angle_tolerance(0.0),
100 m_count(0)
103 curve3_div(double x1, double y1,
104 double x2, double y2,
105 double x3, double y3) :
106 m_approximation_scale(1.0),
107 m_angle_tolerance(0.0),
108 m_count(0)
110 init(x1, y1, x2, y2, x3, y3);
113 void reset() { m_points.remove_all(); m_count = 0; }
114 void init(double x1, double y1,
115 double x2, double y2,
116 double x3, double y3);
118 void approximation_method(curve_approximation_method_e) {}
119 curve_approximation_method_e approximation_method() const { return curve_div; }
121 void approximation_scale(double s) { m_approximation_scale = s; }
122 double approximation_scale() const { return m_approximation_scale; }
124 void angle_tolerance(double a) { m_angle_tolerance = a; }
125 double angle_tolerance() const { return m_angle_tolerance; }
127 void cusp_limit(double) {}
128 double cusp_limit() const { return 0.0; }
130 void rewind(unsigned)
132 m_count = 0;
135 unsigned vertex(double* x, double* y)
137 if(m_count >= m_points.size()) return path_cmd_stop;
138 const point_d& p = m_points[m_count++];
139 *x = p.x;
140 *y = p.y;
141 return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to;
144 private:
145 void bezier(double x1, double y1,
146 double x2, double y2,
147 double x3, double y3);
148 void recursive_bezier(double x1, double y1,
149 double x2, double y2,
150 double x3, double y3,
151 unsigned level);
153 double m_approximation_scale;
154 double m_distance_tolerance_square;
155 double m_angle_tolerance;
156 unsigned m_count;
157 pod_bvector<point_d> m_points;
166 //-------------------------------------------------------------curve4_points
167 struct curve4_points
169 double cp[8];
170 curve4_points() {}
171 curve4_points(double x1, double y1,
172 double x2, double y2,
173 double x3, double y3,
174 double x4, double y4)
176 cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2;
177 cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4;
179 void init(double x1, double y1,
180 double x2, double y2,
181 double x3, double y3,
182 double x4, double y4)
184 cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2;
185 cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4;
187 double operator [] (unsigned i) const { return cp[i]; }
188 double& operator [] (unsigned i) { return cp[i]; }
193 //-------------------------------------------------------------curve4_inc
194 class curve4_inc
196 public:
197 curve4_inc() :
198 m_num_steps(0), m_step(0), m_scale(1.0) { }
200 curve4_inc(double x1, double y1,
201 double x2, double y2,
202 double x3, double y3,
203 double x4, double y4) :
204 m_num_steps(0), m_step(0), m_scale(1.0)
206 init(x1, y1, x2, y2, x3, y3, x4, y4);
209 curve4_inc(const curve4_points& cp) :
210 m_num_steps(0), m_step(0), m_scale(1.0)
212 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
215 void reset() { m_num_steps = 0; m_step = -1; }
216 void init(double x1, double y1,
217 double x2, double y2,
218 double x3, double y3,
219 double x4, double y4);
221 void init(const curve4_points& cp)
223 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
226 void approximation_method(curve_approximation_method_e) {}
227 curve_approximation_method_e approximation_method() const { return curve_inc; }
229 void approximation_scale(double s);
230 double approximation_scale() const;
232 void angle_tolerance(double) {}
233 double angle_tolerance() const { return 0.0; }
235 void cusp_limit(double) {}
236 double cusp_limit() const { return 0.0; }
238 void rewind(unsigned path_id);
239 unsigned vertex(double* x, double* y);
241 private:
242 int m_num_steps;
243 int m_step;
244 double m_scale;
245 double m_start_x;
246 double m_start_y;
247 double m_end_x;
248 double m_end_y;
249 double m_fx;
250 double m_fy;
251 double m_dfx;
252 double m_dfy;
253 double m_ddfx;
254 double m_ddfy;
255 double m_dddfx;
256 double m_dddfy;
257 double m_saved_fx;
258 double m_saved_fy;
259 double m_saved_dfx;
260 double m_saved_dfy;
261 double m_saved_ddfx;
262 double m_saved_ddfy;
267 //-------------------------------------------------------catrom_to_bezier
268 inline curve4_points catrom_to_bezier(double x1, double y1,
269 double x2, double y2,
270 double x3, double y3,
271 double x4, double y4)
273 // Trans. matrix Catmull-Rom to Bezier
275 // 0 1 0 0
276 // -1/6 1 1/6 0
277 // 0 1/6 1 -1/6
278 // 0 0 1 0
280 return curve4_points(
283 (-x1 + 6*x2 + x3) / 6,
284 (-y1 + 6*y2 + y3) / 6,
285 ( x2 + 6*x3 - x4) / 6,
286 ( y2 + 6*y3 - y4) / 6,
288 y3);
292 //-----------------------------------------------------------------------
293 inline curve4_points
294 catrom_to_bezier(const curve4_points& cp)
296 return catrom_to_bezier(cp[0], cp[1], cp[2], cp[3],
297 cp[4], cp[5], cp[6], cp[7]);
302 //-----------------------------------------------------ubspline_to_bezier
303 inline curve4_points ubspline_to_bezier(double x1, double y1,
304 double x2, double y2,
305 double x3, double y3,
306 double x4, double y4)
308 // Trans. matrix Uniform BSpline to Bezier
310 // 1/6 4/6 1/6 0
311 // 0 4/6 2/6 0
312 // 0 2/6 4/6 0
313 // 0 1/6 4/6 1/6
315 return curve4_points(
316 (x1 + 4*x2 + x3) / 6,
317 (y1 + 4*y2 + y3) / 6,
318 (4*x2 + 2*x3) / 6,
319 (4*y2 + 2*y3) / 6,
320 (2*x2 + 4*x3) / 6,
321 (2*y2 + 4*y3) / 6,
322 (x2 + 4*x3 + x4) / 6,
323 (y2 + 4*y3 + y4) / 6);
327 //-----------------------------------------------------------------------
328 inline curve4_points
329 ubspline_to_bezier(const curve4_points& cp)
331 return ubspline_to_bezier(cp[0], cp[1], cp[2], cp[3],
332 cp[4], cp[5], cp[6], cp[7]);
338 //------------------------------------------------------hermite_to_bezier
339 inline curve4_points hermite_to_bezier(double x1, double y1,
340 double x2, double y2,
341 double x3, double y3,
342 double x4, double y4)
344 // Trans. matrix Hermite to Bezier
346 // 1 0 0 0
347 // 1 0 1/3 0
348 // 0 1 0 -1/3
349 // 0 1 0 0
351 return curve4_points(
354 (3*x1 + x3) / 3,
355 (3*y1 + y3) / 3,
356 (3*x2 - x4) / 3,
357 (3*y2 - y4) / 3,
359 y2);
364 //-----------------------------------------------------------------------
365 inline curve4_points
366 hermite_to_bezier(const curve4_points& cp)
368 return hermite_to_bezier(cp[0], cp[1], cp[2], cp[3],
369 cp[4], cp[5], cp[6], cp[7]);
373 //-------------------------------------------------------------curve4_div
374 class curve4_div
376 public:
377 curve4_div() :
378 m_approximation_scale(1.0),
379 m_angle_tolerance(0.0),
380 m_cusp_limit(0.0),
381 m_count(0)
384 curve4_div(double x1, double y1,
385 double x2, double y2,
386 double x3, double y3,
387 double x4, double y4) :
388 m_approximation_scale(1.0),
389 m_angle_tolerance(0.0),
390 m_cusp_limit(0.0),
391 m_count(0)
393 init(x1, y1, x2, y2, x3, y3, x4, y4);
396 curve4_div(const curve4_points& cp) :
397 m_approximation_scale(1.0),
398 m_angle_tolerance(0.0),
399 m_count(0)
401 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
404 void reset() { m_points.remove_all(); m_count = 0; }
405 void init(double x1, double y1,
406 double x2, double y2,
407 double x3, double y3,
408 double x4, double y4);
410 void init(const curve4_points& cp)
412 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
415 void approximation_method(curve_approximation_method_e) {}
417 curve_approximation_method_e approximation_method() const
419 return curve_div;
422 void approximation_scale(double s) { m_approximation_scale = s; }
423 double approximation_scale() const { return m_approximation_scale; }
425 void angle_tolerance(double a) { m_angle_tolerance = a; }
426 double angle_tolerance() const { return m_angle_tolerance; }
428 void cusp_limit(double v)
430 m_cusp_limit = (v == 0.0) ? 0.0 : pi - v;
433 double cusp_limit() const
435 return (m_cusp_limit == 0.0) ? 0.0 : pi - m_cusp_limit;
438 void rewind(unsigned)
440 m_count = 0;
443 unsigned vertex(double* x, double* y)
445 if(m_count >= m_points.size()) return path_cmd_stop;
446 const point_d& p = m_points[m_count++];
447 *x = p.x;
448 *y = p.y;
449 return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to;
452 private:
453 void bezier(double x1, double y1,
454 double x2, double y2,
455 double x3, double y3,
456 double x4, double y4);
458 void recursive_bezier(double x1, double y1,
459 double x2, double y2,
460 double x3, double y3,
461 double x4, double y4,
462 unsigned level);
464 double m_approximation_scale;
465 double m_distance_tolerance_square;
466 double m_angle_tolerance;
467 double m_cusp_limit;
468 unsigned m_count;
469 pod_bvector<point_d> m_points;
473 //-----------------------------------------------------------------curve3
474 class curve3
476 public:
477 curve3() : m_approximation_method(curve_div) {}
478 curve3(double x1, double y1,
479 double x2, double y2,
480 double x3, double y3) :
481 m_approximation_method(curve_div)
483 init(x1, y1, x2, y2, x3, y3);
486 void reset()
488 m_curve_inc.reset();
489 m_curve_div.reset();
492 void init(double x1, double y1,
493 double x2, double y2,
494 double x3, double y3)
496 if(m_approximation_method == curve_inc)
498 m_curve_inc.init(x1, y1, x2, y2, x3, y3);
500 else
502 m_curve_div.init(x1, y1, x2, y2, x3, y3);
506 void approximation_method(curve_approximation_method_e v)
508 m_approximation_method = v;
511 curve_approximation_method_e approximation_method() const
513 return m_approximation_method;
516 void approximation_scale(double s)
518 m_curve_inc.approximation_scale(s);
519 m_curve_div.approximation_scale(s);
522 double approximation_scale() const
524 return m_curve_inc.approximation_scale();
527 void angle_tolerance(double a)
529 m_curve_div.angle_tolerance(a);
532 double angle_tolerance() const
534 return m_curve_div.angle_tolerance();
537 void cusp_limit(double v)
539 m_curve_div.cusp_limit(v);
542 double cusp_limit() const
544 return m_curve_div.cusp_limit();
547 void rewind(unsigned path_id)
549 if(m_approximation_method == curve_inc)
551 m_curve_inc.rewind(path_id);
553 else
555 m_curve_div.rewind(path_id);
559 unsigned vertex(double* x, double* y)
561 if(m_approximation_method == curve_inc)
563 return m_curve_inc.vertex(x, y);
565 return m_curve_div.vertex(x, y);
568 private:
569 curve3_inc m_curve_inc;
570 curve3_div m_curve_div;
571 curve_approximation_method_e m_approximation_method;
578 //-----------------------------------------------------------------curve4
579 class curve4
581 public:
582 curve4() : m_approximation_method(curve_div) {}
583 curve4(double x1, double y1,
584 double x2, double y2,
585 double x3, double y3,
586 double x4, double y4) :
587 m_approximation_method(curve_div)
589 init(x1, y1, x2, y2, x3, y3, x4, y4);
592 curve4(const curve4_points& cp) :
593 m_approximation_method(curve_div)
595 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
598 void reset()
600 m_curve_inc.reset();
601 m_curve_div.reset();
604 void init(double x1, double y1,
605 double x2, double y2,
606 double x3, double y3,
607 double x4, double y4)
609 if(m_approximation_method == curve_inc)
611 m_curve_inc.init(x1, y1, x2, y2, x3, y3, x4, y4);
613 else
615 m_curve_div.init(x1, y1, x2, y2, x3, y3, x4, y4);
619 void init(const curve4_points& cp)
621 init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
624 void approximation_method(curve_approximation_method_e v)
626 m_approximation_method = v;
629 curve_approximation_method_e approximation_method() const
631 return m_approximation_method;
634 void approximation_scale(double s)
636 m_curve_inc.approximation_scale(s);
637 m_curve_div.approximation_scale(s);
639 double approximation_scale() const { return m_curve_inc.approximation_scale(); }
641 void angle_tolerance(double v)
643 m_curve_div.angle_tolerance(v);
646 double angle_tolerance() const
648 return m_curve_div.angle_tolerance();
651 void cusp_limit(double v)
653 m_curve_div.cusp_limit(v);
656 double cusp_limit() const
658 return m_curve_div.cusp_limit();
661 void rewind(unsigned path_id)
663 if(m_approximation_method == curve_inc)
665 m_curve_inc.rewind(path_id);
667 else
669 m_curve_div.rewind(path_id);
673 unsigned vertex(double* x, double* y)
675 if(m_approximation_method == curve_inc)
677 return m_curve_inc.vertex(x, y);
679 return m_curve_div.vertex(x, y);
682 private:
683 curve4_inc m_curve_inc;
684 curve4_div m_curve_div;
685 curve_approximation_method_e m_approximation_method;
693 #endif