SvgRectangle.cs 6.97 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
29
30
31
32
            get { return new SvgPoint(X, Y); }
        }

        public override SvgPaintServer Fill
        {
            get { return (this.Attributes["Fill"] == null) ? new SvgColourServer(Color.Black) : (SvgPaintServer)this.Attributes["Fill"]; }
            set { this.Attributes["Fill"] = value; }
davescriven's avatar
davescriven committed
33
34
35
36
37
        }

        [SvgAttribute("x")]
        public SvgUnit X
        {
38
39
40
41
42
43
            get { return _x; }
            set
            {
                _x = value;
                IsPathDirty = true;
            }
davescriven's avatar
davescriven committed
44
45
46
47
48
        }

        [SvgAttribute("y")]
        public SvgUnit Y
        {
49
50
51
52
53
54
            get { return _y; }
            set
            {
                _y = value;
                IsPathDirty = true;
            }
davescriven's avatar
davescriven committed
55
56
57
58
59
        }

        [SvgAttribute("width")]
        public SvgUnit Width
        {
60
61
62
63
64
65
            get { return _width; }
            set
            {
                _width = value;
                IsPathDirty = true;
            }
davescriven's avatar
davescriven committed
66
67
68
69
70
        }

        [SvgAttribute("height")]
        public SvgUnit Height
        {
71
72
73
74
75
76
            get { return _height; }
            set
            {
                _height = value;
                IsPathDirty = true;
            }
davescriven's avatar
davescriven committed
77
78
79
80
81
82
83
84
        }

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

88
89
90
91
92
93
                return _cornerRadiusX;
            }
            set
            {
                _cornerRadiusX = value;
                IsPathDirty = true;
davescriven's avatar
davescriven committed
94
95
96
97
98
99
100
101
102
            }
        }

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

106
                return _cornerRadiusY;
davescriven's avatar
davescriven committed
107
108
109
            }
            set
            {
110
111
                _cornerRadiusY = value;
                IsPathDirty = true;
davescriven's avatar
davescriven committed
112
113
114
115
116
            }
        }

        protected override bool RequiresSmoothRendering
        {
117
            get { return (CornerRadiusX.Value > 0 || CornerRadiusY.Value > 0); }
davescriven's avatar
davescriven committed
118
119
120
121
        }

        public override RectangleF Bounds
        {
122
            get { return Path.GetBounds(); }
davescriven's avatar
davescriven committed
123
124
125
126
127
128
        }

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

                        _path = new GraphicsPath();
                        _path.StartFigure();
                        _path.AddRectangle(rectangle);
                        _path.CloseFigure();
                    }
                    else
                    {
                        _path = new GraphicsPath();
145
146
147
148
149
150
151
152
                        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
153
154
155
156
157
158
159
160
161
162
163

                        // Start
                        _path.StartFigure();

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

                        // Add first line
164
                        lineStart.X = location.X + rx;
davescriven's avatar
davescriven committed
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
200
201
202
203
204
205
                        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();
                    }
206
                    IsPathDirty = false;
davescriven's avatar
davescriven committed
207
208
209
210
211
212
213
                }
                return _path;
            }
        }

        protected override void Render(Graphics graphics)
        {
214
            if (Width.Value > 0.0f && Height.Value > 0.0f)
davescriven's avatar
davescriven committed
215
216
217
218
                base.Render(graphics);
        }
    }
}