Commit 7a704170 authored by davescriven's avatar davescriven
Browse files

- Fixed #6324: SvgElement.PushTransforms and ViewBox - not necessarily related...

- Fixed #6324: SvgElement.PushTransforms and ViewBox - not necessarily related to ViewBox but every   element was 'resetting' the current graphics transform if the element contained it's own transform. This 
  was a very small fix for a large problem (SvgElement.PushTransforms Matrix transformMatrix = new   Matrix(); changed to Matrix transformMatrix = renderer.Transform; in order to inherit the current   transform.)
- Fixed #6344: Parsing document incorrectly parents elements when it encounters empty nodes which are   in a different namespace. Empty nodes are now ignored and current nodes are closed as required. We'll 
  see how this fix goes.
- Fixed #6381: Units in inches are incorrectly parsed as millimeters - problem was caused by some   copy/paste work.
- Graphics has been replaced by SvgRenderer. This is essentially a wrapper around graphics but will allow
  custom svg related properties in the future when needed.
- Removed ISvgRenderer: A concrete implementation is suitable.
- SvgElement.ElementName has been changed to non-virtual and is set by the parser instead of the   developer having to specify it when developing the class.
- Added more XML API documentation.
parent b12621e2
......@@ -79,14 +79,6 @@ namespace Svg
}
}
/// <summary>
/// Gets the name of the element.
/// </summary>
protected override string ElementName
{
get { return "circle"; }
}
/// <summary>
/// Gets the bounds of the circle.
/// </summary>
......@@ -130,12 +122,12 @@ namespace Svg
/// Renders the circle to the specified <see cref="Graphics"/> object.
/// </summary>
/// <param name="graphics">The graphics object.</param>
protected override void Render(Graphics graphics)
protected override void Render(SvgRenderer renderer)
{
// Don't draw if there is no radius set
if (this.Radius.Value > 0.0f)
{
base.Render(graphics);
base.Render(renderer);
}
}
......
......@@ -8,6 +8,9 @@ using System.ComponentModel;
namespace Svg
{
/// <summary>
/// Represents and SVG ellipse element.
/// </summary>
public class SvgEllipse : SvgGraphicsElement
{
private SvgUnit _radiusX;
......@@ -97,11 +100,11 @@ namespace Svg
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object.
/// </summary>
/// <param name="graphics">The <see cref="Graphics"/> object to render to.</param>
protected override void Render(Graphics graphics)
protected override void Render(SvgRenderer renderer)
{
if (this._radiusX.Value > 0.0f && this._radiusY.Value > 0.0f)
{
base.Render(graphics);
base.Render(renderer);
}
}
......
......@@ -61,50 +61,50 @@ namespace Svg
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object.
/// </summary>
/// <param name="graphics">The <see cref="Graphics"/> object to render to.</param>
protected override void Render(Graphics graphics)
protected override void Render(SvgRenderer renderer)
{
if (this.Path != null && this.Visible)
{
this.PushTransforms(graphics);
this.PushTransforms(renderer);
// If this element needs smoothing enabled turn anti aliasing on
if (this.RequiresSmoothRendering)
{
graphics.SmoothingMode = SmoothingMode.AntiAlias;
renderer.SmoothingMode = SmoothingMode.AntiAlias;
}
// Fill first so that the stroke can overlay
if (!SvgPaintServer.IsNullOrEmpty(this.Fill))
if (this.Fill != null)
{
using (Brush brush = this.Fill.GetBrush(this, this.FillOpacity))
{
if (brush != null)
{
graphics.FillPath(brush, this.Path);
renderer.FillPath(brush, this.Path);
}
}
}
// Stroke is the last thing to do
if (!SvgPaintServer.IsNullOrEmpty(this.Stroke))
if (this.Stroke != null)
{
float strokeWidth = this.StrokeWidth.ToDeviceValue(this);
using (Pen pen = new Pen(this.Stroke.GetBrush(this, this.StrokeOpacity), strokeWidth))
{
if (pen != null)
{
graphics.DrawPath(pen, this.Path);
renderer.DrawPath(pen, this.Path);
}
}
}
// Reset the smoothing mode
if (this.RequiresSmoothRendering && graphics.SmoothingMode == SmoothingMode.AntiAlias)
if (this.RequiresSmoothRendering && renderer.SmoothingMode == SmoothingMode.AntiAlias)
{
graphics.SmoothingMode = SmoothingMode.Default;
renderer.SmoothingMode = SmoothingMode.Default;
}
this.PopTransforms(graphics);
this.PopTransforms(renderer);
}
}
}
......
......@@ -31,7 +31,7 @@ namespace Svg
[SvgAttribute("fill")]
public virtual SvgPaintServer Fill
{
get { return (this.Attributes["Fill"] == null) ? SvgPaintServer.None : (SvgPaintServer)this.Attributes["Fill"]; }
get { return (this.Attributes["Fill"] == null) ? new SvgColourServer() : (SvgPaintServer)this.Attributes["Fill"]; }
set { this.Attributes["Fill"] = value; }
}
......@@ -41,7 +41,7 @@ namespace Svg
[SvgAttribute("stroke")]
public virtual SvgPaintServer Stroke
{
get { return (this.Attributes["Stroke"] == null) ? SvgPaintServer.None : (SvgPaintServer)this.Attributes["Stroke"]; }
get { return (this.Attributes["Stroke"] == null) ? null : (SvgPaintServer)this.Attributes["Stroke"]; }
set { this.Attributes["Stroke"] = value; }
}
......
......@@ -7,6 +7,9 @@ using System.Drawing.Drawing2D;
namespace Svg
{
/// <summary>
/// Represents and SVG line element.
/// </summary>
public class SvgLine : SvgGraphicsElement
{
private SvgUnit _startX;
......
......@@ -4,7 +4,9 @@ using System.Drawing.Drawing2D;
namespace Svg
{
[Serializable]
/// <summary>
/// Represents and SVG rectangle that could also have reounded edges.
/// </summary>
public class SvgRectangle : SvgGraphicsElement
{
private SvgUnit _cornerRadiusX;
......@@ -15,17 +17,26 @@ namespace Svg
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);
}
/// <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
{
......@@ -37,6 +48,9 @@ namespace Svg
}
}
/// <summary>
/// Gets or sets the position where the top point of the rectangle should start.
/// </summary>
[SvgAttribute("y")]
public SvgUnit Y
{
......@@ -48,6 +62,9 @@ namespace Svg
}
}
/// <summary>
/// Gets or sets the width of the rectangle.
/// </summary>
[SvgAttribute("width")]
public SvgUnit Width
{
......@@ -59,6 +76,9 @@ namespace Svg
}
}
/// <summary>
/// Gets or sets the height of the rectangle.
/// </summary>
[SvgAttribute("height")]
public SvgUnit Height
{
......@@ -70,6 +90,9 @@ namespace Svg
}
}
/// <summary>
/// Gets or sets the X-radius of the rounded edges of this rectangle.
/// </summary>
[SvgAttribute("rx")]
public SvgUnit CornerRadiusX
{
......@@ -88,6 +111,9 @@ namespace Svg
}
}
/// <summary>
/// Gets or sets the Y-radius of the rounded edges of this rectangle.
/// </summary>
[SvgAttribute("ry")]
public SvgUnit CornerRadiusY
{
......@@ -106,16 +132,26 @@ namespace Svg
}
}
/// <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.GetBounds(); }
}
/// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
public override GraphicsPath Path
{
get
......@@ -203,10 +239,15 @@ namespace Svg
}
}
protected override void Render(Graphics graphics)
/// <summary>
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object.
/// </summary>
protected override void Render(SvgRenderer renderer)
{
if (Width.Value > 0.0f && Height.Value > 0.0f)
base.Render(graphics);
{
base.Render(renderer);
}
}
}
}
\ No newline at end of file
......@@ -27,14 +27,6 @@ namespace Svg
this._clipPathUnits = SvgCoordinateUnits.ObjectBoundingBox;
}
/// <summary>
/// Gets the name of the element.
/// </summary>
protected override string ElementName
{
get { return "clipPath"; }
}
private Region GetClipRegion()
{
if (_region == null || _pathDirty)
......@@ -67,19 +59,19 @@ namespace Svg
}
}
protected override void ElementAdded(SvgElement child, int index)
protected override void AddElement(SvgElement child, int index)
{
base.ElementAdded(child, index);
base.AddElement(child, index);
this._pathDirty = true;
}
protected override void ElementRemoved(SvgElement child)
protected override void RemoveElement(SvgElement child)
{
base.ElementRemoved(child);
base.RemoveElement(child);
this._pathDirty = true;
}
protected override void Render(System.Drawing.Graphics graphics)
protected override void Render(SvgRenderer renderer)
{
// Do nothing
}
......
......@@ -17,6 +17,9 @@ namespace Svg
private bool _isEmpty;
private float? _deviceValue;
/// <summary>
/// Gets and empty <see cref="SvgUnit"/>.
/// </summary>
public static readonly SvgUnit Empty = new SvgUnit();
/// <summary>
......@@ -35,21 +38,36 @@ namespace Svg
get { return this._value; }
}
/// <summary>
/// Gets the <see cref="SvgUnitType"/> of unit.
/// </summary>
public SvgUnitType Type
{
get { return this._type; }
}
/// <summary>
/// Converts the current unit to one that can be used at render time.
/// </summary>
/// <returns>The representation of the current unit in a device value (usually pixels).</returns>
public float ToDeviceValue()
{
return this.ToDeviceValue(null);
}
/// <summary>
/// Converts the current unit to one that can be used at render time.
/// </summary>
/// <returns>The representation of the current unit in a device value (usually pixels).</returns>
public float ToDeviceValue(ISvgStylable styleOwner)
{
return this.ToDeviceValue(styleOwner, false);
}
/// <summary>
/// Converts the current unit to one that can be used at render time.
/// </summary>
/// <returns>The representation of the current unit in a device value (usually pixels).</returns>
public float ToDeviceValue(ISvgStylable styleOwner, bool vertical)
{
// If it's already been calculated
......@@ -111,6 +129,10 @@ namespace Svg
return this._deviceValue.Value;
}
/// <summary>
/// Converts the current unit to a percentage, if applicable.
/// </summary>
/// <returns>An <see cref="SvgUnit"/> of type <see cref="SvgUnitType.Perscentage"/>.</returns>
public SvgUnit ToPercentage()
{
switch (this.Type)
......@@ -127,6 +149,13 @@ namespace Svg
return this;
}
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
/// <param name="obj">Another object to compare to.</param>
/// <returns>
/// true if <paramref name="obj"/> and this instance are the same type and represent the same value; otherwise, false.
/// </returns>
public override bool Equals(object obj)
{
if (obj == null)
......@@ -143,6 +172,12 @@ namespace Svg
return (unit.Value == this.Value && unit.Type == this.Type);
}
/// <summary>
/// Returns the fully qualified type name of this instance.
/// </summary>
/// <returns>
/// A <see cref="T:System.String"/> containing a fully qualified type name.
/// </returns>
public override string ToString()
{
string type = string.Empty;
......@@ -175,16 +210,31 @@ namespace Svg
return string.Concat(this.Value.ToString(), type);
}
/// <summary>
/// Performs an implicit conversion from <see cref="Svg.SvgUnit"/> to <see cref="System.Single"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator float(SvgUnit value)
{
return value.ToDeviceValue();
}
/// <summary>
/// Performs an implicit conversion from <see cref="System.Single"/> to <see cref="Svg.SvgUnit"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator SvgUnit(float value)
{
return new SvgUnit(value);
}
/// <summary>
/// Initializes a new instance of the <see cref="SvgUnit"/> struct.
/// </summary>
/// <param name="type">The type.</param>
/// <param name="value">The value.</param>
public SvgUnit(SvgUnitType type, float value)
{
this._type = type;
......@@ -193,6 +243,10 @@ namespace Svg
this._deviceValue = null;
}
/// <summary>
/// Initializes a new instance of the <see cref="SvgUnit"/> struct.
/// </summary>
/// <param name="value">The value.</param>
public SvgUnit(float value)
{
this._value = value;
......
......@@ -53,7 +53,7 @@ namespace Svg
case "cm":
return new SvgUnit(SvgUnitType.Centimeter, val);
case "in":
return new SvgUnit(SvgUnitType.Millimeter, val);
return new SvgUnit(SvgUnitType.Inch, val);
case "px":
return new SvgUnit(SvgUnitType.Pixel, val);
case "pt":
......@@ -62,11 +62,11 @@ namespace Svg
return new SvgUnit(SvgUnitType.Pica, val);
case "%":
return new SvgUnit(SvgUnitType.Percentage, val);
case "em":
return new SvgUnit(SvgUnitType.Em, val);
default:
throw new FormatException("Unit is in an invalid format '" + unit + "'.");
}
return new SvgUnit(0.0f);
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
......
......@@ -4,20 +4,25 @@ using System.Text;
namespace Svg
{
/// <summary>
/// Represents a list of re-usable SVG components.
/// </summary>
public class SvgDefinitionList : SvgElement
{
/// <summary>
/// Initializes a new instance of the <see cref="SvgDefinitionList"/> class.
/// </summary>
public SvgDefinitionList()
{
}
protected override void Render(System.Drawing.Graphics graphics)
/// <summary>
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="SvgRenderer"/> object.
/// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> object to render to.</param>
protected override void Render(SvgRenderer renderer)
{
// Do nothing. Children should NOT be rendered.
}
protected override string ElementName
{
get { return "defs"; }
}
}
}
\ No newline at end of file
......@@ -25,6 +25,9 @@ namespace Svg
private SvgElementIdManager _idManager;
/// <summary>
/// Initializes a new instance of the <see cref="SvgDocument"/> class.
/// </summary>
public SvgDocument()
{
Ppi = 96;
......@@ -101,24 +104,36 @@ namespace Svg
return Open(path, null);
}
/// <summary>
/// Opens the document at the specified path and loads the contents.
/// </summary>
/// <param name="path">A <see cref="string"/> containing the path of the file to open.</param>
/// <param name="entities">A dictionary of custom entity definitions to be used when resolving XML entities within the document.</param>
/// <returns>An <see cref="SvgDocument"/> with the contents loaded.</returns>
public static SvgDocument Open(string path, Dictionary<string, string> entities)
{
if (!File.Exists(path))
{
throw new FileNotFoundException("The specified document cannot be found.", path);
}
return Open(File.OpenRead(path), entities);
}
/// <summary>
/// Attempts to open an SVG document from the specified <see cref="Stream"/>.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> containing the SVG document to open.</param>
public static SvgDocument Open(Stream stream)
{
return Open(stream, null);
}
public static SvgDocument OpenRender(Stream stream, Graphics graphics)
{
return null;
}
/// <summary>
/// Attempts to open an SVG document from the specified <see cref="Stream"/> and adds the specified entities.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> containing the SVG document to open.</param>
/// <param name="entities">Custom entity definitions.</param>
public static SvgDocument Open(Stream stream, Dictionary<string, string> entities)
{
Trace.TraceInformation("Begin Read");
......@@ -145,15 +160,19 @@ namespace Svg
bool isEmpty = reader.IsEmptyElement;
// Create element
if (elementStack.Count > 0)
{
element = SvgElementFactory.CreateElement(reader, svgDocument);
}
else
{
element = SvgElementFactory.CreateDocument(reader);
svgDocument = (SvgDocument) element;
svgDocument = (SvgDocument)element;
}
if (element == null)
{
continue;
}
// Add to the parents children
if (elementStack.Count > 0)
......@@ -167,13 +186,18 @@ namespace Svg
// Need to process if the element is empty
if (isEmpty)
{
goto case XmlNodeType.EndElement;
}
break;
case XmlNodeType.EndElement:
// Skip if no element was created
if (element == null)
// Skip if no element was created and is not the closing tag for the last
// known element
if (element == null && reader.LocalName != elementStack.Peek().ElementName)
{
continue;
}
// Pop the element out of the stack
element = elementStack.Pop();
......@@ -221,28 +245,35 @@ namespace Svg
return new RectangleF(0, 0, Width.ToDeviceValue(), Height.ToDeviceValue());
}
public void Draw(Graphics graphics)
/// <summary>
/// Renders the <see cref="SvgDocument"/> to the specified <see cref="SvgRenderer"/>.
/// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> to render the document with.</param>
public void Draw(SvgRenderer renderer)
{
Render(graphics);
Render(renderer);
}
/// <summary>
/// Renders the <see cref="SvgDocument"/> and returns the image as a <see cref="Bitmap"/>.
/// </summary>
/// <returns>A <see cref="Bitmap"/> containing the rendered document.</returns>
public virtual Bitmap Draw()
{
Trace.TraceInformation("Begin Render");
var size = GetDimensions();
var bitmap = new Bitmap((int) Math.Ceiling(size.Width), (int) Math.Ceiling(size.Height));
var bitmap = new Bitmap((int)Math.Ceiling(size.Width), (int)Math.Ceiling(size.Height));
try
{
using (var g = Graphics.FromImage(bitmap))
using (var renderer = SvgRenderer.FromImage(bitmap))
{
g.TextRenderingHint = TextRenderingHint.AntiAlias;
g.TextContrast = 1;
g.PixelOffsetMode = PixelOffsetMode.Half;
Render(g);
g.Save();
renderer.TextRenderingHint = TextRenderingHint.AntiAlias;
renderer.TextContrast = 1;
renderer.PixelOffsetMode = PixelOffsetMode.Half;
this.Render(renderer);
renderer.Save();
}
}
catch
......@@ -257,14 +288,12 @@ namespace Svg
public void Write(Stream stream)
{
using (new XmlTextWriter(stream, Encoding.UTF8))
{
}
}
public void Write(string path)
{
Write(File.Create(path));
}
}
}
\ No newline at end of file
......@@ -23,7 +23,7 @@ namespace Svg
public static readonly Uri Namespace = new Uri("http://www.w3.org/2000/svg");
/// <summary>
/// Gets or sets the width.
/// Gets or sets the width of the fragment.
/// </summary>
/// <value>The width.</value>
[SvgAttribute("width")]
......@@ -34,7 +34,7 @@ namespace Svg
}
/// <summary>
/// Gets or sets the height.
/// Gets or sets the height of the fragment.
/// </summary>
/// <value>The height.</value>
[SvgAttribute("height")]
......@@ -56,30 +56,21 @@ namespace Svg
}
/// <summary>
/// Gets the name of the element.
/// Applies the required transforms to <see cref="SvgRenderer"/>.
/// </summary>
/// <value></value>
protected override string ElementName
{
get { return "svg"; }
}
/// <summary>
/// Pushes the transforms.
/// </summary>
/// <param name="graphics">The graphics.</param>
protected internal override void PushTransforms(Graphics graphics)
/// <param name="renderer">The <see cref="SvgRenderer"/> to be transformed.</param>
protected internal override void PushTransforms(SvgRenderer renderer)
{
base.PushTransforms(graphics);
base.PushTransforms(renderer);
if (!this.ViewBox.Equals(SvgViewBox.Empty))
{
if (this.ViewBox.MinX > 0 || this.ViewBox.MinY > 0)
{
graphics.TranslateTransform(this.ViewBox.MinX, this.ViewBox.MinY, MatrixOrder.Append);
renderer.TranslateTransform(this.ViewBox.MinX, this.ViewBox.MinY, MatrixOrder.Append);
}
graphics.ScaleTransform(this.Width.ToDeviceValue() / this.ViewBox.Width, this.Height.ToDeviceValue() / this.ViewBox.Height, MatrixOrder.Append);
renderer.ScaleTransform(this.Width.ToDeviceValue() / this.ViewBox.Width, this.Height.ToDeviceValue() / this.ViewBox.Height, MatrixOrder.Append);
}
}
......
......@@ -48,11 +48,11 @@ namespace Svg
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object.
/// </summary>
/// <param name="graphics">The <see cref="Graphics"/> object to render to.</param>
protected override void Render(System.Drawing.Graphics graphics)
protected override void Render(SvgRenderer renderer)
{
this.PushTransforms(graphics);
base.RenderContents(graphics);
this.PopTransforms(graphics);
this.PushTransforms(renderer);
base.RenderChildren(renderer);
this.PopTransforms(renderer);
}
}
}
\ No newline at end of file
......@@ -33,10 +33,10 @@ namespace Svg
set { this.Attributes["y"] = value; }
}
protected internal override void PushTransforms(System.Drawing.Graphics graphics)
protected internal override void PushTransforms(SvgRenderer renderer)
{
base.PushTransforms(graphics);
graphics.TranslateTransform(this.X.ToDeviceValue(this), this.Y.ToDeviceValue(this, true));
base.PushTransforms(renderer);
renderer.TranslateTransform(this.X.ToDeviceValue(this), this.Y.ToDeviceValue(this, true));
}
public SvgUse()
......@@ -54,24 +54,19 @@ namespace Svg
get { return new System.Drawing.RectangleF(); }
}
protected override string ElementName
protected override void Render(SvgRenderer renderer)
{
get { return "use"; }
}
protected override void Render(System.Drawing.Graphics graphics)
{
this.PushTransforms(graphics);
this.PushTransforms(renderer);
SvgGraphicsElement element = (SvgGraphicsElement)this.OwnerDocument.IdManager.GetElementById(this.ReferencedElement);
// For the time of rendering we want the referenced element to inherit
// this elements transforms
SvgElement parent = element._parent;
element._parent = this;
element.RenderElement(graphics);
element.RenderElement(renderer);
element._parent = parent;
this.PopTransforms(graphics);
this.PopTransforms(renderer);
}
}
}
\ No newline at end of file
......@@ -44,7 +44,7 @@ namespace Svg.FilterEffects
this._results = new Dictionary<string, Bitmap>();
}
protected override void Render(Graphics graphics)
protected override void Render(SvgRenderer renderer)
{
// Do nothing
}
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Svg
{
public interface ISvgRenderer
{
}
}
\ No newline at end of file
......@@ -20,18 +20,18 @@ namespace Svg
this._stops = new List<SvgGradientStop>();
}
protected override void ElementAdded(SvgElement child, int index)
protected override void AddElement(SvgElement child, int index)
{
if (child is SvgGradientStop)
this.Stops.Add((SvgGradientStop)child);
base.ElementAdded(child, index);
base.AddElement(child, index);
}
protected override void ElementRemoved(SvgElement child)
protected override void RemoveElement(SvgElement child)
{
if (child is SvgGradientStop)
this.Stops.Add((SvgGradientStop)child);
base.ElementRemoved(child);
base.RemoveElement(child);
}
public List<SvgGradientStop> Stops
......
......@@ -6,12 +6,18 @@ using System.ComponentModel;
namespace Svg
{
/// <summary>
/// Represents a colour stop in a gradient.
/// </summary>
public class SvgGradientStop : SvgElement
{
private SvgUnit _offset;
private Color _colour;
private float _opacity;
/// <summary>
/// Gets or sets the offset, i.e. where the stop begins from the beginning, of the gradient stop.
/// </summary>
[SvgAttribute("offset")]
public SvgUnit Offset
{
......@@ -22,6 +28,9 @@ namespace Svg
}
}
/// <summary>
/// Gets or sets the colour of the gradient stop.
/// </summary>
[SvgAttribute("stop-color")]
[TypeConverter(typeof(SvgColourConverter))]
public Color Colour
......@@ -30,6 +39,9 @@ namespace Svg
set { this._colour = value; }
}
/// <summary>
/// Gets or sets the opacity of the gradient stop (0-1).
/// </summary>
[SvgAttribute("stop-opacity")]
public float Opacity
{
......@@ -37,11 +49,9 @@ namespace Svg
set { this._opacity = value; }
}
protected override string ElementName
{
get { return "stop"; }
}
/// <summary>
/// Initializes a new instance of the <see cref="SvgGradientStop"/> class.
/// </summary>
public SvgGradientStop()
{
this._offset = new SvgUnit(0.0f);
......@@ -49,6 +59,11 @@ namespace Svg
this._opacity = 1.0f;
}
/// <summary>
/// Initializes a new instance of the <see cref="SvgGradientStop"/> class.
/// </summary>
/// <param name="offset">The offset.</param>
/// <param name="colour">The colour.</param>
public SvgGradientStop(SvgUnit offset, Color colour)
{
this._offset = offset;
......
......@@ -72,14 +72,6 @@ namespace Svg
get { return new SvgPoint(this.X2, this.Y2); }
}
/// <summary>
/// Gets the name of the element.
/// </summary>
protected override string ElementName
{
get { return "linearGradient"; }
}
public override Brush GetBrush(SvgGraphicsElement owner, float opacity)
{
// Need at least 2 colours to do the gradient fill
......
......@@ -17,18 +17,13 @@ namespace Svg
}
protected override void Render(Graphics graphics)
protected override void Render(SvgRenderer renderer)
{
// Never render paint servers or their children
}
public abstract Brush GetBrush(SvgGraphicsElement styleOwner, float opacity);
public static bool IsNullOrEmpty(SvgPaintServer server)
{
return (server == null || server == SvgPaintServer.None);
}
public override string ToString()
{
return String.Format("url(#{0})", this.ID);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment