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 ...@@ -79,14 +79,6 @@ namespace Svg
} }
} }
/// <summary>
/// Gets the name of the element.
/// </summary>
protected override string ElementName
{
get { return "circle"; }
}
/// <summary> /// <summary>
/// Gets the bounds of the circle. /// Gets the bounds of the circle.
/// </summary> /// </summary>
...@@ -130,12 +122,12 @@ namespace Svg ...@@ -130,12 +122,12 @@ namespace Svg
/// Renders the circle to the specified <see cref="Graphics"/> object. /// Renders the circle to the specified <see cref="Graphics"/> object.
/// </summary> /// </summary>
/// <param name="graphics">The graphics object.</param> /// <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 // Don't draw if there is no radius set
if (this.Radius.Value > 0.0f) if (this.Radius.Value > 0.0f)
{ {
base.Render(graphics); base.Render(renderer);
} }
} }
......
...@@ -8,6 +8,9 @@ using System.ComponentModel; ...@@ -8,6 +8,9 @@ using System.ComponentModel;
namespace Svg namespace Svg
{ {
/// <summary>
/// Represents and SVG ellipse element.
/// </summary>
public class SvgEllipse : SvgGraphicsElement public class SvgEllipse : SvgGraphicsElement
{ {
private SvgUnit _radiusX; private SvgUnit _radiusX;
...@@ -97,11 +100,11 @@ namespace Svg ...@@ -97,11 +100,11 @@ namespace Svg
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object. /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object.
/// </summary> /// </summary>
/// <param name="graphics">The <see cref="Graphics"/> object to render to.</param> /// <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) if (this._radiusX.Value > 0.0f && this._radiusY.Value > 0.0f)
{ {
base.Render(graphics); base.Render(renderer);
} }
} }
......
...@@ -61,50 +61,50 @@ namespace Svg ...@@ -61,50 +61,50 @@ namespace Svg
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object. /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object.
/// </summary> /// </summary>
/// <param name="graphics">The <see cref="Graphics"/> object to render to.</param> /// <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) if (this.Path != null && this.Visible)
{ {
this.PushTransforms(graphics); this.PushTransforms(renderer);
// If this element needs smoothing enabled turn anti aliasing on // If this element needs smoothing enabled turn anti aliasing on
if (this.RequiresSmoothRendering) if (this.RequiresSmoothRendering)
{ {
graphics.SmoothingMode = SmoothingMode.AntiAlias; renderer.SmoothingMode = SmoothingMode.AntiAlias;
} }
// Fill first so that the stroke can overlay // 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)) using (Brush brush = this.Fill.GetBrush(this, this.FillOpacity))
{ {
if (brush != null) if (brush != null)
{ {
graphics.FillPath(brush, this.Path); renderer.FillPath(brush, this.Path);
} }
} }
} }
// Stroke is the last thing to do // Stroke is the last thing to do
if (!SvgPaintServer.IsNullOrEmpty(this.Stroke)) if (this.Stroke != null)
{ {
float strokeWidth = this.StrokeWidth.ToDeviceValue(this); float strokeWidth = this.StrokeWidth.ToDeviceValue(this);
using (Pen pen = new Pen(this.Stroke.GetBrush(this, this.StrokeOpacity), strokeWidth)) using (Pen pen = new Pen(this.Stroke.GetBrush(this, this.StrokeOpacity), strokeWidth))
{ {
if (pen != null) if (pen != null)
{ {
graphics.DrawPath(pen, this.Path); renderer.DrawPath(pen, this.Path);
} }
} }
} }
// Reset the smoothing mode // 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 ...@@ -31,7 +31,7 @@ namespace Svg
[SvgAttribute("fill")] [SvgAttribute("fill")]
public virtual SvgPaintServer 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; } set { this.Attributes["Fill"] = value; }
} }
...@@ -41,7 +41,7 @@ namespace Svg ...@@ -41,7 +41,7 @@ namespace Svg
[SvgAttribute("stroke")] [SvgAttribute("stroke")]
public virtual SvgPaintServer 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; } set { this.Attributes["Stroke"] = value; }
} }
......
...@@ -7,6 +7,9 @@ using System.Drawing.Drawing2D; ...@@ -7,6 +7,9 @@ using System.Drawing.Drawing2D;
namespace Svg namespace Svg
{ {
/// <summary>
/// Represents and SVG line element.
/// </summary>
public class SvgLine : SvgGraphicsElement public class SvgLine : SvgGraphicsElement
{ {
private SvgUnit _startX; private SvgUnit _startX;
......
...@@ -4,7 +4,9 @@ using System.Drawing.Drawing2D; ...@@ -4,7 +4,9 @@ using System.Drawing.Drawing2D;
namespace Svg namespace Svg
{ {
[Serializable] /// <summary>
/// Represents and SVG rectangle that could also have reounded edges.
/// </summary>
public class SvgRectangle : SvgGraphicsElement public class SvgRectangle : SvgGraphicsElement
{ {
private SvgUnit _cornerRadiusX; private SvgUnit _cornerRadiusX;
...@@ -15,17 +17,26 @@ namespace Svg ...@@ -15,17 +17,26 @@ namespace Svg
private SvgUnit _x; private SvgUnit _x;
private SvgUnit _y; private SvgUnit _y;
/// <summary>
/// Initializes a new instance of the <see cref="SvgRectangle"/> class.
/// </summary>
public SvgRectangle() public SvgRectangle()
{ {
_width = new SvgUnit(0.0f); _width = new SvgUnit(0.0f);
_height = 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 public SvgPoint Location
{ {
get { return new SvgPoint(X, Y); } get { return new SvgPoint(X, Y); }
} }
/// <summary>
/// Gets or sets the position where the left point of the rectangle should start.
/// </summary>
[SvgAttribute("x")] [SvgAttribute("x")]
public SvgUnit X public SvgUnit X
{ {
...@@ -37,6 +48,9 @@ namespace Svg ...@@ -37,6 +48,9 @@ namespace Svg
} }
} }
/// <summary>
/// Gets or sets the position where the top point of the rectangle should start.
/// </summary>
[SvgAttribute("y")] [SvgAttribute("y")]
public SvgUnit Y public SvgUnit Y
{ {
...@@ -48,6 +62,9 @@ namespace Svg ...@@ -48,6 +62,9 @@ namespace Svg
} }
} }
/// <summary>
/// Gets or sets the width of the rectangle.
/// </summary>
[SvgAttribute("width")] [SvgAttribute("width")]
public SvgUnit Width public SvgUnit Width
{ {
...@@ -59,6 +76,9 @@ namespace Svg ...@@ -59,6 +76,9 @@ namespace Svg
} }
} }
/// <summary>
/// Gets or sets the height of the rectangle.
/// </summary>
[SvgAttribute("height")] [SvgAttribute("height")]
public SvgUnit Height public SvgUnit Height
{ {
...@@ -70,6 +90,9 @@ namespace Svg ...@@ -70,6 +90,9 @@ namespace Svg
} }
} }
/// <summary>
/// Gets or sets the X-radius of the rounded edges of this rectangle.
/// </summary>
[SvgAttribute("rx")] [SvgAttribute("rx")]
public SvgUnit CornerRadiusX public SvgUnit CornerRadiusX
{ {
...@@ -88,6 +111,9 @@ namespace Svg ...@@ -88,6 +111,9 @@ namespace Svg
} }
} }
/// <summary>
/// Gets or sets the Y-radius of the rounded edges of this rectangle.
/// </summary>
[SvgAttribute("ry")] [SvgAttribute("ry")]
public SvgUnit CornerRadiusY public SvgUnit CornerRadiusY
{ {
...@@ -106,16 +132,26 @@ namespace Svg ...@@ -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 protected override bool RequiresSmoothRendering
{ {
get { return (CornerRadiusX.Value > 0 || CornerRadiusY.Value > 0); } get { return (CornerRadiusX.Value > 0 || CornerRadiusY.Value > 0); }
} }
/// <summary>
/// Gets the bounds of the element.
/// </summary>
/// <value>The bounds.</value>
public override RectangleF Bounds public override RectangleF Bounds
{ {
get { return Path.GetBounds(); } get { return Path.GetBounds(); }
} }
/// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
public override GraphicsPath Path public override GraphicsPath Path
{ {
get get
...@@ -203,10 +239,15 @@ namespace Svg ...@@ -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) 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 ...@@ -27,14 +27,6 @@ namespace Svg
this._clipPathUnits = SvgCoordinateUnits.ObjectBoundingBox; this._clipPathUnits = SvgCoordinateUnits.ObjectBoundingBox;
} }
/// <summary>
/// Gets the name of the element.
/// </summary>
protected override string ElementName
{
get { return "clipPath"; }
}
private Region GetClipRegion() private Region GetClipRegion()
{ {
if (_region == null || _pathDirty) if (_region == null || _pathDirty)
...@@ -67,19 +59,19 @@ namespace Svg ...@@ -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; this._pathDirty = true;
} }
protected override void ElementRemoved(SvgElement child) protected override void RemoveElement(SvgElement child)
{ {
base.ElementRemoved(child); base.RemoveElement(child);
this._pathDirty = true; this._pathDirty = true;
} }
protected override void Render(System.Drawing.Graphics graphics) protected override void Render(SvgRenderer renderer)
{ {
// Do nothing // Do nothing
} }
......
...@@ -17,6 +17,9 @@ namespace Svg ...@@ -17,6 +17,9 @@ namespace Svg
private bool _isEmpty; private bool _isEmpty;
private float? _deviceValue; private float? _deviceValue;
/// <summary>
/// Gets and empty <see cref="SvgUnit"/>.
/// </summary>
public static readonly SvgUnit Empty = new SvgUnit(); public static readonly SvgUnit Empty = new SvgUnit();
/// <summary> /// <summary>
...@@ -35,21 +38,36 @@ namespace Svg ...@@ -35,21 +38,36 @@ namespace Svg
get { return this._value; } get { return this._value; }
} }
/// <summary>
/// Gets the <see cref="SvgUnitType"/> of unit.
/// </summary>
public SvgUnitType Type public SvgUnitType Type
{ {
get { return this._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() public float ToDeviceValue()
{ {
return this.ToDeviceValue(null); 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) public float ToDeviceValue(ISvgStylable styleOwner)
{ {
return this.ToDeviceValue(styleOwner, false); 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) public float ToDeviceValue(ISvgStylable styleOwner, bool vertical)
{ {
// If it's already been calculated // If it's already been calculated
...@@ -111,6 +129,10 @@ namespace Svg ...@@ -111,6 +129,10 @@ namespace Svg
return this._deviceValue.Value; 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() public SvgUnit ToPercentage()
{ {
switch (this.Type) switch (this.Type)
...@@ -127,6 +149,13 @@ namespace Svg ...@@ -127,6 +149,13 @@ namespace Svg
return this; 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) public override bool Equals(object obj)
{ {
if (obj == null) if (obj == null)
...@@ -143,6 +172,12 @@ namespace Svg ...@@ -143,6 +172,12 @@ namespace Svg
return (unit.Value == this.Value && unit.Type == this.Type); 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() public override string ToString()
{ {
string type = string.Empty; string type = string.Empty;
...@@ -175,16 +210,31 @@ namespace Svg ...@@ -175,16 +210,31 @@ namespace Svg
return string.Concat(this.Value.ToString(), type); 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) public static implicit operator float(SvgUnit value)
{ {
return value.ToDeviceValue(); 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) public static implicit operator SvgUnit(float value)
{ {
return new SvgUnit(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) public SvgUnit(SvgUnitType type, float value)
{ {
this._type = type; this._type = type;
...@@ -193,6 +243,10 @@ namespace Svg ...@@ -193,6 +243,10 @@ namespace Svg
this._deviceValue = null; 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) public SvgUnit(float value)
{ {
this._value = value; this._value = value;
......
...@@ -53,7 +53,7 @@ namespace Svg ...@@ -53,7 +53,7 @@ namespace Svg
case "cm": case "cm":
return new SvgUnit(SvgUnitType.Centimeter, val); return new SvgUnit(SvgUnitType.Centimeter, val);
case "in": case "in":
return new SvgUnit(SvgUnitType.Millimeter, val); return new SvgUnit(SvgUnitType.Inch, val);
case "px": case "px":
return new SvgUnit(SvgUnitType.Pixel, val); return new SvgUnit(SvgUnitType.Pixel, val);
case "pt": case "pt":
...@@ -62,11 +62,11 @@ namespace Svg ...@@ -62,11 +62,11 @@ namespace Svg
return new SvgUnit(SvgUnitType.Pica, val); return new SvgUnit(SvgUnitType.Pica, val);
case "%": case "%":
return new SvgUnit(SvgUnitType.Percentage, val); return new SvgUnit(SvgUnitType.Percentage, val);
case "em":
return new SvgUnit(SvgUnitType.Em, val);
default: default:
throw new FormatException("Unit is in an invalid format '" + unit + "'."); throw new FormatException("Unit is in an invalid format '" + unit + "'.");
} }
return new SvgUnit(0.0f);
} }
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
......
...@@ -4,20 +4,25 @@ using System.Text; ...@@ -4,20 +4,25 @@ using System.Text;
namespace Svg namespace Svg
{ {
/// <summary>
/// Represents a list of re-usable SVG components.
/// </summary>
public class SvgDefinitionList : SvgElement public class SvgDefinitionList : SvgElement
{ {
/// <summary>
/// Initializes a new instance of the <see cref="SvgDefinitionList"/> class.
/// </summary>
public SvgDefinitionList() 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. // 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 ...@@ -25,6 +25,9 @@ namespace Svg
private SvgElementIdManager _idManager; private SvgElementIdManager _idManager;
/// <summary>
/// Initializes a new instance of the <see cref="SvgDocument"/> class.
/// </summary>
public SvgDocument() public SvgDocument()
{ {
Ppi = 96; Ppi = 96;
...@@ -101,24 +104,36 @@ namespace Svg ...@@ -101,24 +104,36 @@ namespace Svg
return Open(path, null); 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) public static SvgDocument Open(string path, Dictionary<string, string> entities)
{ {
if (!File.Exists(path)) if (!File.Exists(path))
{
throw new FileNotFoundException("The specified document cannot be found.", path); throw new FileNotFoundException("The specified document cannot be found.", path);
}
return Open(File.OpenRead(path), entities); 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) public static SvgDocument Open(Stream stream)
{ {
return Open(stream, null); return Open(stream, null);
} }
public static SvgDocument OpenRender(Stream stream, Graphics graphics) /// <summary>
{ /// Attempts to open an SVG document from the specified <see cref="Stream"/> and adds the specified entities.
return null; /// </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) public static SvgDocument Open(Stream stream, Dictionary<string, string> entities)
{ {
Trace.TraceInformation("Begin Read"); Trace.TraceInformation("Begin Read");
...@@ -145,15 +160,19 @@ namespace Svg ...@@ -145,15 +160,19 @@ namespace Svg
bool isEmpty = reader.IsEmptyElement; bool isEmpty = reader.IsEmptyElement;
// Create element // Create element
if (elementStack.Count > 0) if (elementStack.Count > 0)
{
element = SvgElementFactory.CreateElement(reader, svgDocument); element = SvgElementFactory.CreateElement(reader, svgDocument);
}
else else
{ {
element = SvgElementFactory.CreateDocument(reader); element = SvgElementFactory.CreateDocument(reader);
svgDocument = (SvgDocument) element; svgDocument = (SvgDocument)element;
} }
if (element == null) if (element == null)
{
continue; continue;
}
// Add to the parents children // Add to the parents children
if (elementStack.Count > 0) if (elementStack.Count > 0)
...@@ -167,13 +186,18 @@ namespace Svg ...@@ -167,13 +186,18 @@ namespace Svg
// Need to process if the element is empty // Need to process if the element is empty
if (isEmpty) if (isEmpty)
{
goto case XmlNodeType.EndElement; goto case XmlNodeType.EndElement;
}
break; break;
case XmlNodeType.EndElement: case XmlNodeType.EndElement:
// Skip if no element was created // Skip if no element was created and is not the closing tag for the last
if (element == null) // known element
if (element == null && reader.LocalName != elementStack.Peek().ElementName)
{
continue; continue;
}
// Pop the element out of the stack // Pop the element out of the stack
element = elementStack.Pop(); element = elementStack.Pop();
...@@ -221,28 +245,35 @@ namespace Svg ...@@ -221,28 +245,35 @@ namespace Svg
return new RectangleF(0, 0, Width.ToDeviceValue(), Height.ToDeviceValue()); 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() public virtual Bitmap Draw()
{ {
Trace.TraceInformation("Begin Render"); Trace.TraceInformation("Begin Render");
var size = GetDimensions(); 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 try
{ {
using (var g = Graphics.FromImage(bitmap)) using (var renderer = SvgRenderer.FromImage(bitmap))
{ {
g.TextRenderingHint = TextRenderingHint.AntiAlias; renderer.TextRenderingHint = TextRenderingHint.AntiAlias;
g.TextContrast = 1; renderer.TextContrast = 1;
g.PixelOffsetMode = PixelOffsetMode.Half; renderer.PixelOffsetMode = PixelOffsetMode.Half;
Render(g); this.Render(renderer);
g.Save(); renderer.Save();
} }
} }
catch catch
...@@ -257,14 +288,12 @@ namespace Svg ...@@ -257,14 +288,12 @@ namespace Svg
public void Write(Stream stream) public void Write(Stream stream)
{ {
using (new XmlTextWriter(stream, Encoding.UTF8))
{
}
} }
public void Write(string path) public void Write(string path)
{ {
Write(File.Create(path));
} }
} }
} }
\ No newline at end of file
...@@ -23,7 +23,7 @@ namespace Svg ...@@ -23,7 +23,7 @@ namespace Svg
public static readonly Uri Namespace = new Uri("http://www.w3.org/2000/svg"); public static readonly Uri Namespace = new Uri("http://www.w3.org/2000/svg");
/// <summary> /// <summary>
/// Gets or sets the width. /// Gets or sets the width of the fragment.
/// </summary> /// </summary>
/// <value>The width.</value> /// <value>The width.</value>
[SvgAttribute("width")] [SvgAttribute("width")]
...@@ -34,7 +34,7 @@ namespace Svg ...@@ -34,7 +34,7 @@ namespace Svg
} }
/// <summary> /// <summary>
/// Gets or sets the height. /// Gets or sets the height of the fragment.
/// </summary> /// </summary>
/// <value>The height.</value> /// <value>The height.</value>
[SvgAttribute("height")] [SvgAttribute("height")]
...@@ -56,30 +56,21 @@ namespace Svg ...@@ -56,30 +56,21 @@ namespace Svg
} }
/// <summary> /// <summary>
/// Gets the name of the element. /// Applies the required transforms to <see cref="SvgRenderer"/>.
/// </summary> /// </summary>
/// <value></value> /// <param name="renderer">The <see cref="SvgRenderer"/> to be transformed.</param>
protected override string ElementName protected internal override void PushTransforms(SvgRenderer renderer)
{
get { return "svg"; }
}
/// <summary>
/// Pushes the transforms.
/// </summary>
/// <param name="graphics">The graphics.</param>
protected internal override void PushTransforms(Graphics graphics)
{ {
base.PushTransforms(graphics); base.PushTransforms(renderer);
if (!this.ViewBox.Equals(SvgViewBox.Empty)) if (!this.ViewBox.Equals(SvgViewBox.Empty))
{ {
if (this.ViewBox.MinX > 0 || this.ViewBox.MinY > 0) 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 ...@@ -48,11 +48,11 @@ namespace Svg
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object. /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object.
/// </summary> /// </summary>
/// <param name="graphics">The <see cref="Graphics"/> object to render to.</param> /// <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); this.PushTransforms(renderer);
base.RenderContents(graphics); base.RenderChildren(renderer);
this.PopTransforms(graphics); this.PopTransforms(renderer);
} }
} }
} }
\ No newline at end of file
...@@ -33,10 +33,10 @@ namespace Svg ...@@ -33,10 +33,10 @@ namespace Svg
set { this.Attributes["y"] = value; } set { this.Attributes["y"] = value; }
} }
protected internal override void PushTransforms(System.Drawing.Graphics graphics) protected internal override void PushTransforms(SvgRenderer renderer)
{ {
base.PushTransforms(graphics); base.PushTransforms(renderer);
graphics.TranslateTransform(this.X.ToDeviceValue(this), this.Y.ToDeviceValue(this, true)); renderer.TranslateTransform(this.X.ToDeviceValue(this), this.Y.ToDeviceValue(this, true));
} }
public SvgUse() public SvgUse()
...@@ -54,24 +54,19 @@ namespace Svg ...@@ -54,24 +54,19 @@ namespace Svg
get { return new System.Drawing.RectangleF(); } get { return new System.Drawing.RectangleF(); }
} }
protected override string ElementName protected override void Render(SvgRenderer renderer)
{ {
get { return "use"; } this.PushTransforms(renderer);
}
protected override void Render(System.Drawing.Graphics graphics)
{
this.PushTransforms(graphics);
SvgGraphicsElement element = (SvgGraphicsElement)this.OwnerDocument.IdManager.GetElementById(this.ReferencedElement); SvgGraphicsElement element = (SvgGraphicsElement)this.OwnerDocument.IdManager.GetElementById(this.ReferencedElement);
// For the time of rendering we want the referenced element to inherit // For the time of rendering we want the referenced element to inherit
// this elements transforms // this elements transforms
SvgElement parent = element._parent; SvgElement parent = element._parent;
element._parent = this; element._parent = this;
element.RenderElement(graphics); element.RenderElement(renderer);
element._parent = parent; element._parent = parent;
this.PopTransforms(graphics); this.PopTransforms(renderer);
} }
} }
} }
\ No newline at end of file
...@@ -44,7 +44,7 @@ namespace Svg.FilterEffects ...@@ -44,7 +44,7 @@ namespace Svg.FilterEffects
this._results = new Dictionary<string, Bitmap>(); this._results = new Dictionary<string, Bitmap>();
} }
protected override void Render(Graphics graphics) protected override void Render(SvgRenderer renderer)
{ {
// Do nothing // 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 ...@@ -20,18 +20,18 @@ namespace Svg
this._stops = new List<SvgGradientStop>(); 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) if (child is SvgGradientStop)
this.Stops.Add((SvgGradientStop)child); 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) if (child is SvgGradientStop)
this.Stops.Add((SvgGradientStop)child); this.Stops.Add((SvgGradientStop)child);
base.ElementRemoved(child); base.RemoveElement(child);
} }
public List<SvgGradientStop> Stops public List<SvgGradientStop> Stops
......
...@@ -6,12 +6,18 @@ using System.ComponentModel; ...@@ -6,12 +6,18 @@ using System.ComponentModel;
namespace Svg namespace Svg
{ {
/// <summary>
/// Represents a colour stop in a gradient.
/// </summary>
public class SvgGradientStop : SvgElement public class SvgGradientStop : SvgElement
{ {
private SvgUnit _offset; private SvgUnit _offset;
private Color _colour; private Color _colour;
private float _opacity; 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")] [SvgAttribute("offset")]
public SvgUnit Offset public SvgUnit Offset
{ {
...@@ -22,6 +28,9 @@ namespace Svg ...@@ -22,6 +28,9 @@ namespace Svg
} }
} }
/// <summary>
/// Gets or sets the colour of the gradient stop.
/// </summary>
[SvgAttribute("stop-color")] [SvgAttribute("stop-color")]
[TypeConverter(typeof(SvgColourConverter))] [TypeConverter(typeof(SvgColourConverter))]
public Color Colour public Color Colour
...@@ -30,6 +39,9 @@ namespace Svg ...@@ -30,6 +39,9 @@ namespace Svg
set { this._colour = value; } set { this._colour = value; }
} }
/// <summary>
/// Gets or sets the opacity of the gradient stop (0-1).
/// </summary>
[SvgAttribute("stop-opacity")] [SvgAttribute("stop-opacity")]
public float Opacity public float Opacity
{ {
...@@ -37,11 +49,9 @@ namespace Svg ...@@ -37,11 +49,9 @@ namespace Svg
set { this._opacity = value; } set { this._opacity = value; }
} }
protected override string ElementName /// <summary>
{ /// Initializes a new instance of the <see cref="SvgGradientStop"/> class.
get { return "stop"; } /// </summary>
}
public SvgGradientStop() public SvgGradientStop()
{ {
this._offset = new SvgUnit(0.0f); this._offset = new SvgUnit(0.0f);
...@@ -49,6 +59,11 @@ namespace Svg ...@@ -49,6 +59,11 @@ namespace Svg
this._opacity = 1.0f; 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) public SvgGradientStop(SvgUnit offset, Color colour)
{ {
this._offset = offset; this._offset = offset;
......
...@@ -72,14 +72,6 @@ namespace Svg ...@@ -72,14 +72,6 @@ namespace Svg
get { return new SvgPoint(this.X2, this.Y2); } 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) public override Brush GetBrush(SvgGraphicsElement owner, float opacity)
{ {
// Need at least 2 colours to do the gradient fill // Need at least 2 colours to do the gradient fill
......
...@@ -17,18 +17,13 @@ namespace Svg ...@@ -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 // Never render paint servers or their children
} }
public abstract Brush GetBrush(SvgGraphicsElement styleOwner, float opacity); public abstract Brush GetBrush(SvgGraphicsElement styleOwner, float opacity);
public static bool IsNullOrEmpty(SvgPaintServer server)
{
return (server == null || server == SvgPaintServer.None);
}
public override string ToString() public override string ToString()
{ {
return String.Format("url(#{0})", this.ID); 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