SvgRectangle.cs 6.71 KB
Newer Older
davescriven's avatar
davescriven committed
1
2
3
4
5
6
using System;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace Svg
{
7
    [Serializable]
davescriven's avatar
davescriven committed
8
9
10
11
    public class SvgRectangle : SvgGraphicsElement
    {
        private SvgUnit _cornerRadiusX;
        private SvgUnit _cornerRadiusY;
12
        private SvgUnit _height;
davescriven's avatar
davescriven committed
13
        private GraphicsPath _path;
14
15
16
17
18
19
20
21
22
        private SvgUnit _width;
        private SvgUnit _x;
        private SvgUnit _y;

        public SvgRectangle()
        {
            _width = new SvgUnit(0.0f);
            _height = new SvgUnit(0.0f);
        }
davescriven's avatar
davescriven committed
23
24
25

        public SvgPoint Location
        {
26
27
28
            get { return new SvgPoint(X, Y); }
        }

davescriven's avatar
davescriven committed
29
30
31
        [SvgAttribute("x")]
        public SvgUnit X
        {
32
33
34
35
36
37
            get { return _x; }
            set
            {
                _x = value;
                IsPathDirty = true;
            }
davescriven's avatar
davescriven committed
38
39
40
41
42
        }

        [SvgAttribute("y")]
        public SvgUnit Y
        {
43
44
45
46
47
48
            get { return _y; }
            set
            {
                _y = value;
                IsPathDirty = true;
            }
davescriven's avatar
davescriven committed
49
50
51
52
53
        }

        [SvgAttribute("width")]
        public SvgUnit Width
        {
54
55
56
57
58
59
            get { return _width; }
            set
            {
                _width = value;
                IsPathDirty = true;
            }
davescriven's avatar
davescriven committed
60
61
62
63
64
        }

        [SvgAttribute("height")]
        public SvgUnit Height
        {
65
66
67
68
69
70
            get { return _height; }
            set
            {
                _height = value;
                IsPathDirty = true;
            }
davescriven's avatar
davescriven committed
71
72
73
74
75
76
77
78
        }

        [SvgAttribute("rx")]
        public SvgUnit CornerRadiusX
        {
            get
            {
                // If ry has been set and rx hasn't, use it's value
79
80
                if (_cornerRadiusX.Value == 0.0f && _cornerRadiusY.Value > 0.0f)
                    return _cornerRadiusY;
davescriven's avatar
davescriven committed
81

82
83
84
85
86
87
                return _cornerRadiusX;
            }
            set
            {
                _cornerRadiusX = value;
                IsPathDirty = true;
davescriven's avatar
davescriven committed
88
89
90
91
92
93
94
95
96
            }
        }

        [SvgAttribute("ry")]
        public SvgUnit CornerRadiusY
        {
            get
            {
                // If rx has been set and ry hasn't, use it's value
97
98
                if (_cornerRadiusY.Value == 0.0f && _cornerRadiusX.Value > 0.0f)
                    return _cornerRadiusX;
davescriven's avatar
davescriven committed
99

100
                return _cornerRadiusY;
davescriven's avatar
davescriven committed
101
102
103
            }
            set
            {
104
105
                _cornerRadiusY = value;
                IsPathDirty = true;
davescriven's avatar
davescriven committed
106
107
108
109
110
            }
        }

        protected override bool RequiresSmoothRendering
        {
111
            get { return (CornerRadiusX.Value > 0 || CornerRadiusY.Value > 0); }
davescriven's avatar
davescriven committed
112
113
114
115
        }

        public override RectangleF Bounds
        {
116
            get { return Path.GetBounds(); }
davescriven's avatar
davescriven committed
117
118
119
120
121
122
        }

        public override GraphicsPath Path
        {
            get
            {
123
                if (_path == null || IsPathDirty)
davescriven's avatar
davescriven committed
124
125
                {
                    // If the corners aren't to be rounded just create a rectangle
126
                    if (CornerRadiusX.Value == 0.0f && CornerRadiusY.Value == 0.0f)
davescriven's avatar
davescriven committed
127
                    {
128
129
                        var rectangle = new RectangleF(Location.ToDeviceValue(),
                            new SizeF(Width.ToDeviceValue(), Height.ToDeviceValue()));
davescriven's avatar
davescriven committed
130
131
132
133
134
135
136
137
138

                        _path = new GraphicsPath();
                        _path.StartFigure();
                        _path.AddRectangle(rectangle);
                        _path.CloseFigure();
                    }
                    else
                    {
                        _path = new GraphicsPath();
139
140
141
142
143
144
145
146
                        var arcBounds = new RectangleF();
                        var lineStart = new PointF();
                        var lineEnd = new PointF();
                        var width = Width.ToDeviceValue();
                        var height = Height.ToDeviceValue();
                        var rx = CornerRadiusX.ToDeviceValue();
                        var ry = CornerRadiusY.ToDeviceValue();
                        var location = Location.ToDeviceValue();
davescriven's avatar
davescriven committed
147
148
149
150
151
152
153
154
155
156
157

                        // Start
                        _path.StartFigure();

                        // Add first arc
                        arcBounds.Location = location;
                        arcBounds.Width = rx;
                        arcBounds.Height = ry;
                        _path.AddArc(arcBounds, 180, 90);

                        // Add first line
158
                        lineStart.X = location.X + rx;
davescriven's avatar
davescriven committed
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
                        lineStart.Y = location.Y;
                        lineEnd.X = location.X + width - rx;
                        lineEnd.Y = lineStart.Y;
                        _path.AddLine(lineStart, lineEnd);

                        // Add second arc
                        arcBounds.Location = new PointF(location.X + width - rx, location.Y);
                        _path.AddArc(arcBounds, 270, 90);

                        // Add second line
                        lineStart.X = location.X + width;
                        lineStart.Y = location.Y + ry;
                        lineEnd.X = lineStart.X;
                        lineEnd.Y = location.Y + height - ry;
                        _path.AddLine(lineStart, lineEnd);

                        // Add third arc
                        arcBounds.Location = new PointF(location.X + width - rx, location.Y + height - ry);
                        _path.AddArc(arcBounds, 0, 90);

                        // Add third line
                        lineStart.X = location.X + width - rx;
                        lineStart.Y = location.Y + height;
                        lineEnd.X = location.X + rx;
                        lineEnd.Y = lineStart.Y;
                        _path.AddLine(lineStart, lineEnd);

                        // Add third arc
                        arcBounds.Location = new PointF(location.X, location.Y + height - ry);
                        _path.AddArc(arcBounds, 90, 90);

                        // Add fourth line
                        lineStart.X = location.X;
                        lineStart.Y = location.Y + height - ry;
                        lineEnd.X = lineStart.X;
                        lineEnd.Y = location.Y + ry;
                        _path.AddLine(lineStart, lineEnd);

                        // Close
                        _path.CloseFigure();
                    }
200
                    IsPathDirty = false;
davescriven's avatar
davescriven committed
201
202
203
204
205
206
207
                }
                return _path;
            }
        }

        protected override void Render(Graphics graphics)
        {
208
            if (Width.Value > 0.0f && Height.Value > 0.0f)
davescriven's avatar
davescriven committed
209
210
211
212
                base.Render(graphics);
        }
    }
}