btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / libs / agg / agg_rasterizer_outline_aa.h
blob6ce3c3102205b314499ac4bcd51ff6a230bf75db
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_OUTLINE_AA_INCLUDED
16 #define AGG_RASTERIZER_OUTLINE_AA_INCLUDED
18 #include "agg_basics.h"
19 #include "agg_line_aa_basics.h"
20 #include "agg_vertex_sequence.h"
22 namespace agg
25 //-------------------------------------------------------------------------
26 inline bool cmp_dist_start(int d) { return d > 0; }
27 inline bool cmp_dist_end(int d) { return d <= 0; }
31 //-----------------------------------------------------------line_aa_vertex
32 // Vertex (x, y) with the distance to the next one. The last vertex has
33 // the distance between the last and the first points
34 struct line_aa_vertex
36 int x;
37 int y;
38 int len;
40 line_aa_vertex() {}
41 line_aa_vertex(int x_, int y_) :
42 x(x_),
43 y(y_),
44 len(0)
48 bool operator () (const line_aa_vertex& val)
50 double dx = val.x - x;
51 double dy = val.y - y;
52 return (len = uround(sqrt(dx * dx + dy * dy))) >
53 (line_subpixel_scale + line_subpixel_scale / 2);
58 //----------------------------------------------------------outline_aa_join_e
59 enum outline_aa_join_e
61 outline_no_join, //-----outline_no_join
62 outline_miter_join, //-----outline_miter_join
63 outline_round_join, //-----outline_round_join
64 outline_miter_accurate_join //-----outline_accurate_join
67 //=======================================================rasterizer_outline_aa
68 template<class Renderer, class Coord=line_coord> class rasterizer_outline_aa
70 private:
71 //------------------------------------------------------------------------
72 struct draw_vars
74 unsigned idx;
75 int x1, y1, x2, y2;
76 line_parameters curr, next;
77 int lcurr, lnext;
78 int xb1, yb1, xb2, yb2;
79 unsigned flags;
82 void draw(draw_vars& dv, unsigned start, unsigned end);
84 public:
85 typedef line_aa_vertex vertex_type;
86 typedef vertex_sequence<vertex_type, 6> vertex_storage_type;
88 rasterizer_outline_aa(Renderer& ren) :
89 m_ren(&ren),
90 m_line_join(ren.accurate_join_only() ?
91 outline_miter_accurate_join :
92 outline_round_join),
93 m_round_cap(false),
94 m_start_x(0),
95 m_start_y(0)
97 void attach(Renderer& ren) { m_ren = &ren; }
99 //------------------------------------------------------------------------
100 void line_join(outline_aa_join_e join)
102 m_line_join = m_ren->accurate_join_only() ?
103 outline_miter_accurate_join :
104 join;
106 bool line_join() const { return m_line_join; }
108 //------------------------------------------------------------------------
109 void round_cap(bool v) { m_round_cap = v; }
110 bool round_cap() const { return m_round_cap; }
112 //------------------------------------------------------------------------
113 void move_to(int x, int y)
115 m_src_vertices.modify_last(vertex_type(m_start_x = x, m_start_y = y));
118 //------------------------------------------------------------------------
119 void line_to(int x, int y)
121 m_src_vertices.add(vertex_type(x, y));
124 //------------------------------------------------------------------------
125 void move_to_d(double x, double y)
127 move_to(Coord::conv(x), Coord::conv(y));
130 //------------------------------------------------------------------------
131 void line_to_d(double x, double y)
133 line_to(Coord::conv(x), Coord::conv(y));
136 //------------------------------------------------------------------------
137 void render(bool close_polygon);
139 //------------------------------------------------------------------------
140 void add_vertex(double x, double y, unsigned cmd)
142 if(is_move_to(cmd))
144 render(false);
145 move_to_d(x, y);
147 else
149 if(is_end_poly(cmd))
151 render(is_closed(cmd));
152 if(is_closed(cmd))
154 move_to(m_start_x, m_start_y);
157 else
159 line_to_d(x, y);
164 //------------------------------------------------------------------------
165 template<class VertexSource>
166 void add_path(VertexSource& vs, unsigned path_id=0)
168 double x;
169 double y;
171 unsigned cmd;
172 vs.rewind(path_id);
173 while(!is_stop(cmd = vs.vertex(&x, &y)))
175 add_vertex(x, y, cmd);
177 render(false);
181 //------------------------------------------------------------------------
182 template<class VertexSource, class ColorStorage, class PathId>
183 void render_all_paths(VertexSource& vs,
184 const ColorStorage& colors,
185 const PathId& path_id,
186 unsigned num_paths)
188 for(unsigned i = 0; i < num_paths; i++)
190 m_ren->color(colors[i]);
191 add_path(vs, path_id[i]);
196 //------------------------------------------------------------------------
197 template<class Ctrl> void render_ctrl(Ctrl& c)
199 unsigned i;
200 for(i = 0; i < c.num_paths(); i++)
202 m_ren->color(c.color(i));
203 add_path(c, i);
207 private:
208 rasterizer_outline_aa(const rasterizer_outline_aa<Renderer, Coord>&);
209 const rasterizer_outline_aa<Renderer, Coord>& operator =
210 (const rasterizer_outline_aa<Renderer, Coord>&);
212 Renderer* m_ren;
213 vertex_storage_type m_src_vertices;
214 outline_aa_join_e m_line_join;
215 bool m_round_cap;
216 int m_start_x;
217 int m_start_y;
227 //----------------------------------------------------------------------------
228 template<class Renderer, class Coord>
229 void rasterizer_outline_aa<Renderer, Coord>::draw(draw_vars& dv,
230 unsigned start,
231 unsigned end)
233 unsigned i;
234 const vertex_storage_type::value_type* v;
236 for(i = start; i < end; i++)
238 if(m_line_join == outline_round_join)
240 dv.xb1 = dv.curr.x1 + (dv.curr.y2 - dv.curr.y1);
241 dv.yb1 = dv.curr.y1 - (dv.curr.x2 - dv.curr.x1);
242 dv.xb2 = dv.curr.x2 + (dv.curr.y2 - dv.curr.y1);
243 dv.yb2 = dv.curr.y2 - (dv.curr.x2 - dv.curr.x1);
246 switch(dv.flags)
248 case 0: m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break;
249 case 1: m_ren->line2(dv.curr, dv.xb2, dv.yb2); break;
250 case 2: m_ren->line1(dv.curr, dv.xb1, dv.yb1); break;
251 case 3: m_ren->line0(dv.curr); break;
254 if(m_line_join == outline_round_join && (dv.flags & 2) == 0)
256 m_ren->pie(dv.curr.x2, dv.curr.y2,
257 dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
258 dv.curr.y2 - (dv.curr.x2 - dv.curr.x1),
259 dv.curr.x2 + (dv.next.y2 - dv.next.y1),
260 dv.curr.y2 - (dv.next.x2 - dv.next.x1));
263 dv.x1 = dv.x2;
264 dv.y1 = dv.y2;
265 dv.lcurr = dv.lnext;
266 dv.lnext = m_src_vertices[dv.idx].len;
268 ++dv.idx;
269 if(dv.idx >= m_src_vertices.size()) dv.idx = 0;
271 v = &m_src_vertices[dv.idx];
272 dv.x2 = v->x;
273 dv.y2 = v->y;
275 dv.curr = dv.next;
276 dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
277 dv.xb1 = dv.xb2;
278 dv.yb1 = dv.yb2;
280 switch(m_line_join)
282 case outline_no_join:
283 dv.flags = 3;
284 break;
286 case outline_miter_join:
287 dv.flags >>= 1;
288 dv.flags |= ((dv.curr.diagonal_quadrant() ==
289 dv.next.diagonal_quadrant()) << 1);
290 if((dv.flags & 2) == 0)
292 bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
294 break;
296 case outline_round_join:
297 dv.flags >>= 1;
298 dv.flags |= ((dv.curr.diagonal_quadrant() ==
299 dv.next.diagonal_quadrant()) << 1);
300 break;
302 case outline_miter_accurate_join:
303 dv.flags = 0;
304 bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
305 break;
313 //----------------------------------------------------------------------------
314 template<class Renderer, class Coord>
315 void rasterizer_outline_aa<Renderer, Coord>::render(bool close_polygon)
317 m_src_vertices.close(close_polygon);
318 draw_vars dv;
319 const vertex_storage_type::value_type* v;
320 int x1;
321 int y1;
322 int x2;
323 int y2;
324 int lprev;
326 if(close_polygon)
328 if(m_src_vertices.size() >= 3)
330 dv.idx = 2;
332 v = &m_src_vertices[m_src_vertices.size() - 1];
333 x1 = v->x;
334 y1 = v->y;
335 lprev = v->len;
337 v = &m_src_vertices[0];
338 x2 = v->x;
339 y2 = v->y;
340 dv.lcurr = v->len;
341 line_parameters prev(x1, y1, x2, y2, lprev);
343 v = &m_src_vertices[1];
344 dv.x1 = v->x;
345 dv.y1 = v->y;
346 dv.lnext = v->len;
347 dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
349 v = &m_src_vertices[dv.idx];
350 dv.x2 = v->x;
351 dv.y2 = v->y;
352 dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
354 dv.xb1 = 0;
355 dv.yb1 = 0;
356 dv.xb2 = 0;
357 dv.yb2 = 0;
359 switch(m_line_join)
361 case outline_no_join:
362 dv.flags = 3;
363 break;
365 case outline_miter_join:
366 case outline_round_join:
367 dv.flags =
368 (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
369 ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
370 break;
372 case outline_miter_accurate_join:
373 dv.flags = 0;
374 break;
377 if((dv.flags & 1) == 0 && m_line_join != outline_round_join)
379 bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
382 if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
384 bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
386 draw(dv, 0, m_src_vertices.size());
389 else
391 switch(m_src_vertices.size())
393 case 0:
394 case 1:
395 break;
397 case 2:
399 v = &m_src_vertices[0];
400 x1 = v->x;
401 y1 = v->y;
402 lprev = v->len;
403 v = &m_src_vertices[1];
404 x2 = v->x;
405 y2 = v->y;
406 line_parameters lp(x1, y1, x2, y2, lprev);
407 if(m_round_cap)
409 m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
411 m_ren->line3(lp,
412 x1 + (y2 - y1),
413 y1 - (x2 - x1),
414 x2 + (y2 - y1),
415 y2 - (x2 - x1));
416 if(m_round_cap)
418 m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1));
421 break;
423 case 3:
425 int x3, y3;
426 int lnext;
427 v = &m_src_vertices[0];
428 x1 = v->x;
429 y1 = v->y;
430 lprev = v->len;
431 v = &m_src_vertices[1];
432 x2 = v->x;
433 y2 = v->y;
434 lnext = v->len;
435 v = &m_src_vertices[2];
436 x3 = v->x;
437 y3 = v->y;
438 line_parameters lp1(x1, y1, x2, y2, lprev);
439 line_parameters lp2(x2, y2, x3, y3, lnext);
441 if(m_round_cap)
443 m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
446 if(m_line_join == outline_round_join)
448 m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
449 x2 + (y2 - y1), y2 - (x2 - x1));
451 m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1),
452 x2 + (y3 - y2), y2 - (x3 - x2));
454 m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2),
455 x3 + (y3 - y2), y3 - (x3 - x2));
457 else
459 bisectrix(lp1, lp2, &dv.xb1, &dv.yb1);
460 m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
461 dv.xb1, dv.yb1);
463 m_ren->line3(lp2, dv.xb1, dv.yb1,
464 x3 + (y3 - y2), y3 - (x3 - x2));
466 if(m_round_cap)
468 m_ren->semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2));
471 break;
473 default:
475 dv.idx = 3;
477 v = &m_src_vertices[0];
478 x1 = v->x;
479 y1 = v->y;
480 lprev = v->len;
482 v = &m_src_vertices[1];
483 x2 = v->x;
484 y2 = v->y;
485 dv.lcurr = v->len;
486 line_parameters prev(x1, y1, x2, y2, lprev);
488 v = &m_src_vertices[2];
489 dv.x1 = v->x;
490 dv.y1 = v->y;
491 dv.lnext = v->len;
492 dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
494 v = &m_src_vertices[dv.idx];
495 dv.x2 = v->x;
496 dv.y2 = v->y;
497 dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
499 dv.xb1 = 0;
500 dv.yb1 = 0;
501 dv.xb2 = 0;
502 dv.yb2 = 0;
504 switch(m_line_join)
506 case outline_no_join:
507 dv.flags = 3;
508 break;
510 case outline_miter_join:
511 case outline_round_join:
512 dv.flags =
513 (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
514 ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
515 break;
517 case outline_miter_accurate_join:
518 dv.flags = 0;
519 break;
522 if(m_round_cap)
524 m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
526 if((dv.flags & 1) == 0)
528 if(m_line_join == outline_round_join)
530 m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
531 x2 + (y2 - y1), y2 - (x2 - x1));
532 m_ren->pie(prev.x2, prev.y2,
533 x2 + (y2 - y1), y2 - (x2 - x1),
534 dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
535 dv.curr.y1 - (dv.curr.x2 - dv.curr.x1));
537 else
539 bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
540 m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
541 dv.xb1, dv.yb1);
544 else
546 m_ren->line1(prev,
547 x1 + (y2 - y1),
548 y1 - (x2 - x1));
550 if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
552 bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
555 draw(dv, 1, m_src_vertices.size() - 2);
557 if((dv.flags & 1) == 0)
559 if(m_line_join == outline_round_join)
561 m_ren->line3(dv.curr,
562 dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
563 dv.curr.y1 - (dv.curr.x2 - dv.curr.x1),
564 dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
565 dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
567 else
569 m_ren->line3(dv.curr, dv.xb1, dv.yb1,
570 dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
571 dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
574 else
576 m_ren->line2(dv.curr,
577 dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
578 dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
580 if(m_round_cap)
582 m_ren->semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2,
583 dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
584 dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
588 break;
591 m_src_vertices.remove_all();
598 #endif