-
HeinrichAD authored
Fix: Now the application make sure to set back the old culture even an error occurred. SvgColourConverter.ConvertFrom SvgPathBuilder.ConvertTo SvgDocument.Write SvgExtentions.GetXML Add: Attribute: "shape-rendering" Change: - Many other properties were unknowingly overloaded. I changed them to override. - Some methods or structures need the [CLSCompliant(false)] Attribute. For example the Enums.TryParse extension. This extension has the where condition IConvertible. IConvertible is [CLSCompliant(false)] and that the reason why it is correct to mark the Enums.TryParse extension also as [CLSCompliant(false)]. - Property "float Opacity" in SvgElement was unknowingly overloaded in SvgGradientStop as string [stop-opacity]. In the end this property was only used as float. I changed the SvgGradientStop.Opacity property from string to float and to override.
7894ea9e
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using Svg.Transforms;
namespace Svg
{
/// <summary>
/// Represents an SVG rectangle that could also have rounded edges.
/// </summary>
[SvgElement("rect")]
public class SvgRectangle : SvgVisualElement
{
private SvgUnit _cornerRadiusX;
private SvgUnit _cornerRadiusY;
private SvgUnit _height;
private GraphicsPath _path;
private SvgUnit _width;
private SvgUnit _x;
private SvgUnit _y;
/// <summary>
/// Initializes a new instance of the <see cref="SvgRectangle"/> class.
/// </summary>
public SvgRectangle()
{
_width = new SvgUnit(0.0f);
_height = new SvgUnit(0.0f);
_cornerRadiusX = new SvgUnit(0.0f);
_cornerRadiusY = new SvgUnit(0.0f);
_x = new SvgUnit(0.0f);
_y = new SvgUnit(0.0f);
}
/// <summary>
/// Gets an <see cref="SvgPoint"/> representing the top left point of the rectangle.
/// </summary>
public SvgPoint Location
{
get { return new SvgPoint(X, Y); }
}
/// <summary>
/// Gets or sets the position where the left point of the rectangle should start.
/// </summary>
[SvgAttribute("x")]
public SvgUnit X
{
get { return _x; }
set
{
if(_x != value)
{
_x = value;
OnAttributeChanged(new AttributeEventArgs{ Attribute = "x", Value = value });
IsPathDirty = true;
}
}
}
/// <summary>
/// Gets or sets the position where the top point of the rectangle should start.
/// </summary>
[SvgAttribute("y")]
public SvgUnit Y
{
get { return _y; }
set
{
if(_y != value)
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
{
_y = value;
OnAttributeChanged(new AttributeEventArgs{ Attribute = "y", Value = value });
IsPathDirty = true;
}
}
}
/// <summary>
/// Gets or sets the width of the rectangle.
/// </summary>
[SvgAttribute("width")]
public SvgUnit Width
{
get { return _width; }
set
{
if(_width != value)
{
_width = value;
OnAttributeChanged(new AttributeEventArgs{ Attribute = "width", Value = value });
IsPathDirty = true;
}
}
}
/// <summary>
/// Gets or sets the height of the rectangle.
/// </summary>
[SvgAttribute("height")]
public SvgUnit Height
{
get { return _height; }
set
{
if(_height != value)
{
_height = value;
OnAttributeChanged(new AttributeEventArgs{ Attribute = "height", Value = value });
IsPathDirty = true;
}
}
}
/// <summary>
/// Gets or sets the X-radius of the rounded edges of this rectangle.
/// </summary>
[SvgAttribute("rx")]
public SvgUnit CornerRadiusX
{
get
{
// If ry has been set and rx hasn't, use it's value
if (_cornerRadiusX.Value == 0.0f && _cornerRadiusY.Value > 0.0f)
return _cornerRadiusY;
return _cornerRadiusX;
}
set
{
_cornerRadiusX = value;
IsPathDirty = true;
}
}
/// <summary>
/// Gets or sets the Y-radius of the rounded edges of this rectangle.
/// </summary>
[SvgAttribute("ry")]
public SvgUnit CornerRadiusY
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
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
200
201
202
203
204
205
206
207
208
209
210
{
get
{
// If rx has been set and ry hasn't, use it's value
if (_cornerRadiusY.Value == 0.0f && _cornerRadiusX.Value > 0.0f)
return _cornerRadiusX;
return _cornerRadiusY;
}
set
{
_cornerRadiusY = value;
IsPathDirty = true;
}
}
/// <summary>
/// Gets or sets a value to determine if anti-aliasing should occur when the element is being rendered.
/// </summary>
protected override bool RequiresSmoothRendering
{
get { return (CornerRadiusX.Value > 0 || CornerRadiusY.Value > 0); }
}
/// <summary>
/// Gets the bounds of the element.
/// </summary>
/// <value>The bounds.</value>
public override RectangleF Bounds
{
get { return Path(null).GetBounds(); }
}
/// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
public override GraphicsPath Path(ISvgRenderer renderer)
{
if ((_path == null || IsPathDirty) && base.StrokeWidth > 0)
{
float halfStrokeWidth = base.StrokeWidth / 2;
// If it is to render, don't need to consider stroke
if (renderer != null)
{
halfStrokeWidth = 0;
this.IsPathDirty = false;
}
// If the corners aren't to be rounded just create a rectangle
if (CornerRadiusX.Value == 0.0f && CornerRadiusY.Value == 0.0f)
{
// Starting location which take consideration of stroke width
SvgPoint strokedLocation = new SvgPoint(Location.X - halfStrokeWidth, Location.Y - halfStrokeWidth);
var rectangle = new RectangleF(strokedLocation.ToDeviceValue(renderer, this),
SvgUnit.GetDeviceSize(this.Width + halfStrokeWidth * 2, this.Height + halfStrokeWidth * 2, renderer, this));
_path = new GraphicsPath();
_path.StartFigure();
_path.AddRectangle(rectangle);
_path.CloseFigure();
}
else
{
_path = new GraphicsPath();
var arcBounds = new RectangleF();
var lineStart = new PointF();
var lineEnd = new PointF();
var width = Width.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this);
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
var height = Height.ToDeviceValue(renderer, UnitRenderingType.Vertical, this);
var rx = Math.Min(CornerRadiusX.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this) * 2, width);
var ry = Math.Min(CornerRadiusY.ToDeviceValue(renderer, UnitRenderingType.Vertical, this) * 2, height);
var location = Location.ToDeviceValue(renderer, this);
// Start
_path.StartFigure();
// Add first arc
arcBounds.Location = location;
arcBounds.Width = rx;
arcBounds.Height = ry;
_path.AddArc(arcBounds, 180, 90);
// Add first line
lineStart.X = Math.Min(location.X + rx, location.X + width * 0.5f);
lineStart.Y = location.Y;
lineEnd.X = Math.Max(location.X + width - rx, location.X + width * 0.5f);
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 = Math.Min(location.Y + ry, location.Y + height * 0.5f);
lineEnd.X = lineStart.X;
lineEnd.Y = Math.Max(location.Y + height - ry, location.Y + height * 0.5f);
_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 = Math.Max(location.X + width - rx, location.X + width * 0.5f);
lineStart.Y = location.Y + height;
lineEnd.X = Math.Min(location.X + rx, location.X + width * 0.5f);
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 = Math.Max(location.Y + height - ry, location.Y + height * 0.5f);
lineEnd.X = lineStart.X;
lineEnd.Y = Math.Min(location.Y + ry, location.Y + height * 0.5f);
_path.AddLine(lineStart, lineEnd);
// Close
_path.CloseFigure();
}
}
return _path;
}
/// <summary>
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object.
/// </summary>
protected override void Render(ISvgRenderer renderer)
{
if (Width.Value > 0.0f && Height.Value > 0.0f)
{
base.Render(renderer);
}
}
public override SvgElement DeepCopy()
{
return DeepCopy<SvgRectangle>();
}
public override SvgElement DeepCopy<T>()
{
var newObj = base.DeepCopy<T>() as SvgRectangle;
newObj.CornerRadiusX = this.CornerRadiusX;
newObj.CornerRadiusY = this.CornerRadiusY;
newObj.Height = this.Height;
newObj.Width = this.Width;
newObj.X = this.X;
newObj.Y = this.Y;
return newObj;
}
}
}