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//
16// class renderer_primitives
17//
18//----------------------------------------------------------------------------
19
20#ifndef AGG_RENDERER_PRIMITIVES_INCLUDED
21#define AGG_RENDERER_PRIMITIVES_INCLUDED
22
23#include "agg_basics.h"
24#include "agg_renderer_base.h"
25#include "agg_dda_line.h"
26#include "agg_ellipse_bresenham.h"
27
28namespace agg
29{
30    //-----------------------------------------------------renderer_primitives
31    template<class BaseRenderer> class renderer_primitives
32    {
33    public:
34        typedef BaseRenderer base_ren_type;
35        typedef typename base_ren_type::color_type color_type;
36
37        //--------------------------------------------------------------------
38        renderer_primitives(base_ren_type& ren) :
39            m_ren(&ren),
40            m_fill_color(),
41            m_line_color(),
42            m_curr_x(0),
43            m_curr_y(0)
44        {}
45        void attach(base_ren_type& ren) { m_ren = &ren; }
46
47        //--------------------------------------------------------------------
48        static int coord(double c)
49        {
50            return iround(c * line_bresenham_interpolator::subpixel_scale);
51        }
52
53        //--------------------------------------------------------------------
54        void fill_color(const color_type& c) { m_fill_color = c; }
55        void line_color(const color_type& c) { m_line_color = c; }
56        const color_type& fill_color() const { return m_fill_color; }
57        const color_type& line_color() const { return m_line_color; }
58
59        //--------------------------------------------------------------------
60        void rectangle(int x1, int y1, int x2, int y2)
61        {
62            m_ren->blend_hline(x1,   y1,   x2-1, m_line_color, cover_full);
63            m_ren->blend_vline(x2,   y1,   y2-1, m_line_color, cover_full);
64            m_ren->blend_hline(x1+1, y2,   x2,   m_line_color, cover_full);
65            m_ren->blend_vline(x1,   y1+1, y2,   m_line_color, cover_full);
66        }
67
68        //--------------------------------------------------------------------
69        void solid_rectangle(int x1, int y1, int x2, int y2)
70        {
71            m_ren->blend_bar(x1, y1, x2, y2, m_fill_color, cover_full);
72        }
73
74        //--------------------------------------------------------------------
75        void outlined_rectangle(int x1, int y1, int x2, int y2)
76        {
77            rectangle(x1, y1, x2, y2);
78            m_ren->blend_bar(x1+1, y1+1, x2-1, y2-1, m_fill_color, cover_full);
79        }
80
81        //--------------------------------------------------------------------
82        void ellipse(int x, int y, int rx, int ry)
83        {
84            ellipse_bresenham_interpolator ei(rx, ry);
85            int dx = 0;
86            int dy = -ry;
87            do
88            {
89                dx += ei.dx();
90                dy += ei.dy();
91                m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full);
92                m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full);
93                m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full);
94                m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full);
95                ++ei;
96            }
97            while(dy < 0);
98        }
99
100        //--------------------------------------------------------------------
101        void solid_ellipse(int x, int y, int rx, int ry)
102        {
103            ellipse_bresenham_interpolator ei(rx, ry);
104            int dx = 0;
105            int dy = -ry;
106            int dy0 = dy;
107            int dx0 = dx;
108
109            do
110            {
111                dx += ei.dx();
112                dy += ei.dy();
113
114                if(dy != dy0)
115                {
116                    m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full);
117                    m_ren->blend_hline(x-dx0, y-dy0, x+dx0, m_fill_color, cover_full);
118                }
119                dx0 = dx;
120                dy0 = dy;
121                ++ei;
122            }
123            while(dy < 0);
124            m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full);
125        }
126
127        //--------------------------------------------------------------------
128        void outlined_ellipse(int x, int y, int rx, int ry)
129        {
130            ellipse_bresenham_interpolator ei(rx, ry);
131            int dx = 0;
132            int dy = -ry;
133
134            do
135            {
136                dx += ei.dx();
137                dy += ei.dy();
138
139                m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full);
140                m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full);
141                m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full);
142                m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full);
143
144                if(ei.dy() && dx)
145                {
146                   m_ren->blend_hline(x-dx+1, y+dy, x+dx-1, m_fill_color, cover_full);
147                   m_ren->blend_hline(x-dx+1, y-dy, x+dx-1, m_fill_color, cover_full);
148                }
149                ++ei;
150            }
151            while(dy < 0);
152        }
153
154        //--------------------------------------------------------------------
155        void line(int x1, int y1, int x2, int y2, bool last=false)
156        {
157            line_bresenham_interpolator li(x1, y1, x2, y2);
158
159            unsigned len = li.len();
160            if(len == 0)
161            {
162                if(last)
163                {
164                    m_ren->blend_pixel(li.line_lr(x1), li.line_lr(y1), m_line_color, cover_full);
165                }
166                return;
167            }
168
169            if(last) ++len;
170
171            if(li.is_ver())
172            {
173                do
174                {
175                    m_ren->blend_pixel(li.x2(), li.y1(), m_line_color, cover_full);
176                    li.vstep();
177                }
178                while(--len);
179            }
180            else
181            {
182                do
183                {
184                    m_ren->blend_pixel(li.x1(), li.y2(), m_line_color, cover_full);
185                    li.hstep();
186                }
187                while(--len);
188            }
189        }
190
191        //--------------------------------------------------------------------
192        void move_to(int x, int y)
193        {
194            m_curr_x = x;
195            m_curr_y = y;
196        }
197
198        //--------------------------------------------------------------------
199        void line_to(int x, int y, bool last=false)
200        {
201            line(m_curr_x, m_curr_y, x, y, last);
202            m_curr_x = x;
203            m_curr_y = y;
204        }
205
206        //--------------------------------------------------------------------
207        const base_ren_type& ren() const { return *m_ren; }
208        base_ren_type& ren() { return *m_ren; }
209
210        //--------------------------------------------------------------------
211        const rendering_buffer& rbuf() const { return m_ren->rbuf(); }
212        rendering_buffer& rbuf() { return m_ren->rbuf(); }
213
214    private:
215        base_ren_type* m_ren;
216        color_type m_fill_color;
217        color_type m_line_color;
218        int m_curr_x;
219        int m_curr_y;
220    };
221
222}
223
224#endif
225