Commit 4cd65121 authored by Tebjan Halm's avatar Tebjan Halm
Browse files

Merge pull request #105 from erdomke/master

Serialization Bug Fixes
Showing with 174 additions and 62 deletions
+174 -62
......@@ -86,6 +86,13 @@ namespace Svg
if (objColor == null)
return false;
if ((this == SvgPaintServer.None && obj != SvgPaintServer.None) ||
(this != SvgPaintServer.None && obj == SvgPaintServer.None) ||
(this == SvgColourServer.NotSet && obj != SvgColourServer.NotSet) ||
(this != SvgColourServer.NotSet && obj == SvgColourServer.NotSet) ||
(this == SvgColourServer.Inherit && obj != SvgColourServer.Inherit) ||
(this != SvgColourServer.Inherit && obj == SvgColourServer.Inherit)) return false;
return this.GetHashCode() == objColor.GetHashCode();
}
......
......@@ -81,7 +81,14 @@ namespace Svg
public override string ToString()
{
return (_serverLoaded ? _serverLoaded.ToString() : string.Format("deferred: {0}", this.DeferredId));
if (this.DeferredId == "currentColor")
{
return this.DeferredId;
}
else
{
return string.Format("url({0})", this.DeferredId);
}
}
public static T TryGet<T>(SvgPaintServer server, SvgElement parent) where T : SvgPaintServer
......
......@@ -135,15 +135,22 @@ namespace Svg
if (destinationType == typeof(string))
{
//check for none
if (value == SvgPaintServer.None) return "none";
if (value == SvgPaintServer.None || value == SvgColourServer.None) return "none";
if (value == SvgColourServer.Inherit) return "inherit";
if (value == SvgColourServer.NotSet) return "";
var colourServer = value as SvgColourServer;
if (colourServer != null)
{
return new SvgColourConverter().ConvertTo(colourServer.Colour, typeof(string));
}
var deferred = value as SvgDeferredPaintServer;
if (deferred != null)
{
return deferred.ToString();
}
if (value != null)
{
return string.Format(CultureInfo.InvariantCulture, "url(#{0})", ((SvgPaintServer)value).ID);
......
......@@ -22,7 +22,7 @@ namespace Svg
/// <summary>
/// Gets or sets a <see cref="SvgPathSegmentList"/> of path data.
/// </summary>
[SvgAttribute("d")]
[SvgAttribute("d", true)]
public SvgPathSegmentList PathData
{
get { return this.Attributes.GetAttribute<SvgPathSegmentList>("d"); }
......@@ -37,7 +37,7 @@ namespace Svg
/// <summary>
/// Gets or sets the length of the path.
/// </summary>
[SvgAttribute("pathLength")]
[SvgAttribute("pathLength", true)]
public float PathLength
{
get { return this.Attributes.GetAttribute<float>("pathLength"); }
......@@ -48,7 +48,7 @@ namespace Svg
/// <summary>
/// Gets or sets the marker (end cap) of the path.
/// </summary>
[SvgAttribute("marker-end")]
[SvgAttribute("marker-end", true)]
public Uri MarkerEnd
{
get { return this.Attributes.GetAttribute<Uri>("marker-end"); }
......@@ -59,7 +59,7 @@ namespace Svg
/// <summary>
/// Gets or sets the marker (start cap) of the path.
/// </summary>
[SvgAttribute("marker-mid")]
[SvgAttribute("marker-mid", true)]
public Uri MarkerMid
{
get { return this.Attributes.GetAttribute<Uri>("marker-mid"); }
......@@ -70,7 +70,7 @@ namespace Svg
/// <summary>
/// Gets or sets the marker (start cap) of the path.
/// </summary>
[SvgAttribute("marker-start")]
[SvgAttribute("marker-start", true)]
public Uri MarkerStart
{
get { return this.Attributes.GetAttribute<Uri>("marker-start"); }
......
......@@ -26,6 +26,7 @@ namespace Svg
new KeyValuePair<string, string>(XLinkPrefix, XLinkNamespace),
new KeyValuePair<string, string>("xml", XmlNamespace)
};
private bool _inAttrDictionary;
private string _name;
private string _namespace;
......@@ -80,6 +81,11 @@ namespace Svg
get { return this._namespace; }
}
public bool InAttributeDictionary
{
get { return this._inAttrDictionary; }
}
/// <summary>
/// Initializes a new instance of the <see cref="SvgAttributeAttribute"/> class.
/// </summary>
......@@ -98,6 +104,13 @@ namespace Svg
this._namespace = SvgNamespace;
}
internal SvgAttributeAttribute(string name, bool inAttrDictionary)
{
this._name = name;
this._namespace = SvgNamespace;
this._inAttrDictionary = inAttrDictionary;
}
/// <summary>
/// Initializes a new instance of the <see cref="SvgAttributeAttribute"/> class with the specified SVG attribute name and namespace.
/// </summary>
......
......@@ -15,6 +15,8 @@ namespace Svg
static SvgDefaults()
{
_defaults["d"] = "";
_defaults["viewBox"] = "0, 0, 0, 0";
_defaults["visibility"] = "visible";
......
......@@ -123,7 +123,7 @@ namespace Svg
/// <summary>
/// Gets or sets the color <see cref="SvgPaintServer"/> of this element which drives the currentColor property.
/// </summary>
[SvgAttribute("color")]
[SvgAttribute("color", true)]
public virtual SvgPaintServer Color
{
get { return (this.Attributes["color"] == null) ? SvgColourServer.NotSet : (SvgPaintServer)this.Attributes["color"]; }
......@@ -559,17 +559,22 @@ namespace Svg
writer.WriteEndElement();
}
}
protected virtual void WriteAttributes(XmlTextWriter writer)
{
var styles = new Dictionary<string, string>();
bool writeStyle;
bool forceWrite;
//properties
foreach (var attr in _svgPropertyAttributes)
{
if (attr.Property.Converter.CanConvertTo(typeof(string)))
if (attr.Property.Converter.CanConvertTo(typeof(string)) &&
(!attr.Attribute.InAttributeDictionary || _attributes.ContainsKey(attr.Attribute.Name)))
{
object propertyValue = attr.Property.GetValue(this);
var forceWrite = false;
forceWrite = false;
writeStyle = (attr.Attribute.Name == "fill");
if ((attr.Attribute.Name == "fill") && (Parent != null))
{
if(propertyValue == SvgColourServer.NotSet) continue;
......@@ -592,18 +597,31 @@ namespace Svg
if (!SvgDefaults.IsDefault(attr.Attribute.Name, value) || forceWrite)
{
writer.WriteAttributeString(attr.Attribute.NamespaceAndName, value);
if (writeStyle)
{
styles[attr.Attribute.Name] = value;
}
else
{
writer.WriteAttributeString(attr.Attribute.NamespaceAndName, value);
}
}
}
else if(attr.Attribute.Name == "fill") //if fill equals null, write 'none'
{
string value = (string)attr.Property.Converter.ConvertTo(propertyValue, typeof(string));
writer.WriteAttributeString(attr.Attribute.NamespaceAndName, value);
if (writeStyle)
{
styles[attr.Attribute.Name] = value;
}
else
{
writer.WriteAttributeString(attr.Attribute.NamespaceAndName, value);
}
}
}
}
//events
if(AutoPublishEvents)
{
......@@ -624,6 +642,13 @@ namespace Svg
{
writer.WriteAttributeString(item.Key, item.Value);
}
//write the style property
if (styles.Any())
{
writer.WriteAttributeString("style", (from s in styles
select s.Key + ":" + s.Value + ";").Aggregate((p,c) => p + c));
}
}
public bool AutoPublishEvents = true;
......@@ -663,14 +688,33 @@ namespace Svg
protected virtual void WriteChildren(XmlTextWriter writer)
{
//write the content
if(!String.IsNullOrEmpty(this.Content))
writer.WriteString(this.Content);
//write all children
foreach (SvgElement child in this.Children)
if (this.Nodes.Any())
{
SvgContentNode content;
foreach (var node in this.Nodes)
{
content = node as SvgContentNode;
if (content == null)
{
((SvgElement)node).Write(writer);
}
else if (!string.IsNullOrEmpty(content.Content))
{
writer.WriteString(content.Content);
}
}
}
else
{
child.Write(writer);
//write the content
if(!String.IsNullOrEmpty(this.Content))
writer.WriteString(this.Content);
//write all children
foreach (SvgElement child in this.Children)
{
child.Write(writer);
}
}
}
......
......@@ -36,7 +36,7 @@ namespace Svg
/// <summary>
/// Gets or sets the fill <see cref="SvgPaintServer"/> of this element.
/// </summary>
[SvgAttribute("fill")]
[SvgAttribute("fill", true)]
public virtual SvgPaintServer Fill
{
get { return (this.Attributes["fill"] == null) ? SvgColourServer.NotSet : (SvgPaintServer)this.Attributes["fill"]; }
......@@ -46,14 +46,14 @@ namespace Svg
/// <summary>
/// Gets or sets the <see cref="SvgPaintServer"/> to be used when rendering a stroke around this element.
/// </summary>
[SvgAttribute("stroke")]
[SvgAttribute("stroke", true)]
public virtual SvgPaintServer Stroke
{
get { return (this.Attributes["stroke"] == null) ? null : (SvgPaintServer)this.Attributes["stroke"]; }
set { this.Attributes["stroke"] = value; }
}
[SvgAttribute("fill-rule")]
[SvgAttribute("fill-rule", true)]
public virtual SvgFillRule FillRule
{
get { return (this.Attributes["fill-rule"] == null) ? SvgFillRule.NonZero : (SvgFillRule)this.Attributes["fill-rule"]; }
......@@ -63,7 +63,7 @@ namespace Svg
/// <summary>
/// Gets or sets the opacity of this element's <see cref="Fill"/>.
/// </summary>
[SvgAttribute("fill-opacity")]
[SvgAttribute("fill-opacity", true)]
public virtual float FillOpacity
{
get { return (this.Attributes["fill-opacity"] == null) ? this.Opacity : (float)this.Attributes["fill-opacity"]; }
......@@ -73,42 +73,42 @@ namespace Svg
/// <summary>
/// Gets or sets the width of the stroke (if the <see cref="Stroke"/> property has a valid value specified.
/// </summary>
[SvgAttribute("stroke-width")]
[SvgAttribute("stroke-width", true)]
public virtual SvgUnit StrokeWidth
{
get { return (this.Attributes["stroke-width"] == null) ? new SvgUnit(1.0f) : (SvgUnit)this.Attributes["stroke-width"]; }
set { this.Attributes["stroke-width"] = value; }
}
[SvgAttribute("stroke-linecap")]
[SvgAttribute("stroke-linecap", true)]
public virtual SvgStrokeLineCap StrokeLineCap
{
get { return (this.Attributes["stroke-linecap"] == null) ? SvgStrokeLineCap.Butt : (SvgStrokeLineCap)this.Attributes["stroke-linecap"]; }
set { this.Attributes["stroke-linecap"] = value; }
}
[SvgAttribute("stroke-linejoin")]
[SvgAttribute("stroke-linejoin", true)]
public virtual SvgStrokeLineJoin StrokeLineJoin
{
get { return (this.Attributes["stroke-linejoin"] == null) ? SvgStrokeLineJoin.Miter : (SvgStrokeLineJoin)this.Attributes["stroke-linejoin"]; }
set { this.Attributes["stroke-linejoin"] = value; }
}
[SvgAttribute("stroke-miterlimit")]
[SvgAttribute("stroke-miterlimit", true)]
public virtual float StrokeMiterLimit
{
get { return (this.Attributes["stroke-miterlimit"] == null) ? 4f : (float)this.Attributes["stroke-miterlimit"]; }
set { this.Attributes["stroke-miterlimit"] = value; }
}
[SvgAttribute("stroke-dasharray")]
[SvgAttribute("stroke-dasharray", true)]
public virtual SvgUnitCollection StrokeDashArray
{
get { return this.Attributes["stroke-dasharray"] as SvgUnitCollection; }
set { this.Attributes["stroke-dasharray"] = value; }
}
[SvgAttribute("stroke-dashoffset")]
[SvgAttribute("stroke-dashoffset", true)]
public virtual SvgUnit StrokeDashOffset
{
get { return (this.Attributes["stroke-dashoffset"] == null) ? SvgUnit.Empty : (SvgUnit)this.Attributes["stroke-dashoffset"]; }
......@@ -118,7 +118,7 @@ namespace Svg
/// <summary>
/// Gets or sets the opacity of the stroke, if the <see cref="Stroke"/> property has been specified. 1.0 is fully opaque; 0.0 is transparent.
/// </summary>
[SvgAttribute("stroke-opacity")]
[SvgAttribute("stroke-opacity", true)]
public virtual float StrokeOpacity
{
get { return (this.Attributes["stroke-opacity"] == null) ? this.Opacity : (float)this.Attributes["stroke-opacity"]; }
......@@ -129,7 +129,7 @@ namespace Svg
/// Gets or sets the colour of the gradient stop.
/// </summary>
/// <remarks>Apparently this can be set on non-sensical elements. Don't ask; just check the tests.</remarks>
[SvgAttribute("stop-color")]
[SvgAttribute("stop-color", true)]
[TypeConverter(typeof(SvgPaintServerFactory))]
public SvgPaintServer StopColor
{
......@@ -140,7 +140,7 @@ namespace Svg
/// <summary>
/// Gets or sets the opacity of the element. 1.0 is fully opaque; 0.0 is transparent.
/// </summary>
[SvgAttribute("opacity")]
[SvgAttribute("opacity", true)]
public virtual float Opacity
{
get { return (this.Attributes["opacity"] == null) ? 1.0f : (float)this.Attributes["opacity"]; }
......@@ -150,7 +150,7 @@ namespace Svg
/// <summary>
/// Indicates which font family is to be used to render the text.
/// </summary>
[SvgAttribute("font-family")]
[SvgAttribute("font-family", true)]
public virtual string FontFamily
{
get { return this.Attributes["font-family"] as string; }
......@@ -160,7 +160,7 @@ namespace Svg
/// <summary>
/// Refers to the size of the font from baseline to baseline when multiple lines of text are set solid in a multiline layout environment.
/// </summary>
[SvgAttribute("font-size")]
[SvgAttribute("font-size", true)]
public virtual SvgUnit FontSize
{
get { return (this.Attributes["font-size"] == null) ? SvgUnit.Empty : (SvgUnit)this.Attributes["font-size"]; }
......@@ -170,7 +170,7 @@ namespace Svg
/// <summary>
/// Refers to the style of the font.
/// </summary>
[SvgAttribute("font-style")]
[SvgAttribute("font-style", true)]
public virtual SvgFontStyle FontStyle
{
get { return (this.Attributes["font-style"] == null) ? SvgFontStyle.inherit : (SvgFontStyle)this.Attributes["font-style"]; }
......@@ -180,7 +180,7 @@ namespace Svg
/// <summary>
/// Refers to the varient of the font.
/// </summary>
[SvgAttribute("font-variant")]
[SvgAttribute("font-variant", true)]
public virtual SvgFontVariant FontVariant
{
get { return (this.Attributes["font-variant"] == null) ? SvgFontVariant.inherit : (SvgFontVariant)this.Attributes["font-variant"]; }
......@@ -190,7 +190,7 @@ namespace Svg
/// <summary>
/// Refers to the boldness of the font.
/// </summary>
[SvgAttribute("text-decoration")]
[SvgAttribute("text-decoration", true)]
public virtual SvgTextDecoration TextDecoration
{
get { return (this.Attributes["text-decoration"] == null) ? SvgTextDecoration.inherit : (SvgTextDecoration)this.Attributes["text-decoration"]; }
......@@ -200,7 +200,7 @@ namespace Svg
/// <summary>
/// Refers to the boldness of the font.
/// </summary>
[SvgAttribute("font-weight")]
[SvgAttribute("font-weight", true)]
public virtual SvgFontWeight FontWeight
{
get { return (this.Attributes["font-weight"] == null) ? SvgFontWeight.inherit : (SvgFontWeight)this.Attributes["font-weight"]; }
......@@ -220,7 +220,7 @@ namespace Svg
/// <summary>
/// Set all font information.
/// </summary>
[SvgAttribute("font")]
[SvgAttribute("font", true)]
public virtual string Font
{
get { return (this.Attributes["font"] == null ? "" : this.Attributes["font"] as string); }
......
......@@ -18,7 +18,18 @@ namespace Svg
[SvgAttribute("ascent")]
public float Ascent
{
get { return (this.Attributes["ascent"] == null ? this.UnitsPerEm : (float)this.Attributes["ascent"]); }
get
{
if (this.Attributes["ascent"] == null)
{
var font = this.Parent as SvgFont;
return (font == null ? 0 : this.UnitsPerEm - font.VertOriginY);
}
else
{
return (float)this.Attributes["ascent"];
}
}
set { this.Attributes["ascent"] = value; }
}
......@@ -32,7 +43,18 @@ namespace Svg
[SvgAttribute("descent")]
public float Descent
{
get { return (this.Attributes["descent"] == null ? 0 : (float)this.Attributes["descent"]); }
get
{
if (this.Attributes["descent"] == null)
{
var font = this.Parent as SvgFont;
return (font == null ? 0 : font.VertOriginY);
}
else
{
return (float)this.Attributes["descent"];
}
}
set { this.Attributes["descent"] = value; }
}
......
......@@ -15,44 +15,44 @@ namespace Svg
/// <summary>
/// Gets or sets a <see cref="SvgPathSegmentList"/> of path data.
/// </summary>
[SvgAttribute("d")]
[SvgAttribute("d", true)]
public SvgPathSegmentList PathData
{
get { return this.Attributes.GetAttribute<SvgPathSegmentList>("d"); }
set { this.Attributes["d"] = value; }
}
[SvgAttribute("glyph-name")]
[SvgAttribute("glyph-name", true)]
public virtual string GlyphName
{
get { return this.Attributes["glyph-name"] as string; }
set { this.Attributes["glyph-name"] = value; }
}
[SvgAttribute("horiz-adv-x")]
[SvgAttribute("horiz-adv-x", true)]
public float HorizAdvX
{
get { return (this.Attributes["horiz-adv-x"] == null ? this.Parents.OfType<SvgFont>().First().HorizAdvX : (float)this.Attributes["horiz-adv-x"]); }
set { this.Attributes["horiz-adv-x"] = value; }
}
[SvgAttribute("unicode")]
[SvgAttribute("unicode", true)]
public string Unicode
{
get { return this.Attributes["unicode"] as string; }
set { this.Attributes["unicode"] = value; }
}
[SvgAttribute("vert-adv-y")]
[SvgAttribute("vert-adv-y", true)]
public float VertAdvY
{
get { return (this.Attributes["vert-adv-y"] == null ? this.Parents.OfType<SvgFont>().First().VertAdvY : (float)this.Attributes["vert-adv-y"]); }
set { this.Attributes["vert-adv-y"] = value; }
}
[SvgAttribute("vert-origin-x")]
[SvgAttribute("vert-origin-x", true)]
public float VertOriginX
{
get { return (this.Attributes["vert-origin-x"] == null ? this.Parents.OfType<SvgFont>().First().VertOriginX : (float)this.Attributes["vert-origin-x"]); }
set { this.Attributes["vert-origin-x"] = value; }
}
[SvgAttribute("vert-origin-y")]
[SvgAttribute("vert-origin-y", true)]
public float VertOriginY
{
get { return (this.Attributes["vert-origin-y"] == null ? this.Parents.OfType<SvgFont>().First().VertOriginY : (float)this.Attributes["vert-origin-y"]); }
......
......@@ -33,14 +33,14 @@ namespace Svg
/// Gets or sets the text anchor.
/// </summary>
/// <value>The text anchor.</value>
[SvgAttribute("text-anchor")]
[SvgAttribute("text-anchor", true)]
public virtual SvgTextAnchor TextAnchor
{
get { return (this.Attributes["text-anchor"] == null) ? SvgTextAnchor.inherit : (SvgTextAnchor)this.Attributes["text-anchor"]; }
set { this.Attributes["text-anchor"] = value; this.IsPathDirty = true; }
}
[SvgAttribute("baseline-shift")]
[SvgAttribute("baseline-shift", true)]
public virtual string BaselineShift
{
get { return this.Attributes["baseline-shift"] as string; }
......@@ -153,7 +153,7 @@ namespace Svg
/// <summary>
/// The pre-calculated length of the text
/// </summary>
[SvgAttribute("textLength")]
[SvgAttribute("textLength", true)]
public virtual SvgUnit TextLength
{
get { return (this.Attributes["textLength"] == null ? SvgUnit.None : (SvgUnit)this.Attributes["textLength"]); }
......@@ -164,7 +164,7 @@ namespace Svg
/// Gets or sets the text anchor.
/// </summary>
/// <value>The text anchor.</value>
[SvgAttribute("lengthAdjust")]
[SvgAttribute("lengthAdjust", true)]
public virtual SvgTextLengthAdjust LengthAdjust
{
get { return (this.Attributes["lengthAdjust"] == null) ? SvgTextLengthAdjust.spacing : (SvgTextLengthAdjust)this.Attributes["lengthAdjust"]; }
......@@ -174,7 +174,7 @@ namespace Svg
/// <summary>
/// Specifies spacing behavior between text characters.
/// </summary>
[SvgAttribute("letter-spacing")]
[SvgAttribute("letter-spacing", true)]
public virtual SvgUnit LetterSpacing
{
get { return (this.Attributes["letter-spacing"] == null ? SvgUnit.None : (SvgUnit)this.Attributes["letter-spacing"]); }
......@@ -184,7 +184,7 @@ namespace Svg
/// <summary>
/// Specifies spacing behavior between words.
/// </summary>
[SvgAttribute("word-spacing")]
[SvgAttribute("word-spacing", true)]
public virtual SvgUnit WordSpacing
{
get { return (this.Attributes["word-spacing"] == null ? SvgUnit.None : (SvgUnit)this.Attributes["word-spacing"]); }
......
......@@ -27,7 +27,14 @@ namespace Svg.Transforms
public override string WriteToString()
{
return string.Format(CultureInfo.InvariantCulture, "skew({0}, {1})", this.AngleX, this.AngleY);
if (this.AngleY == 0)
{
return string.Format(CultureInfo.InvariantCulture, "skewX({0})", this.AngleX);
}
else
{
return string.Format(CultureInfo.InvariantCulture, "skewY({0})", this.AngleY);
}
}
public SvgSkew(float x, float y)
......
......@@ -71,9 +71,14 @@ namespace SvgW3CTestRunner
{
using(var memStream = new MemoryStream())
{
doc.Write(memStream);
doc.Write(memStream);
memStream.Position = 0;
var reader = new StreamReader(memStream);
System.IO.File.WriteAllText(@"C:\test.svg", reader.ReadToEnd());
memStream.Position = 0;
doc = SvgDocument.Open<SvgDocument>(memStream);
var baseUri = doc.BaseUri;
doc = SvgDocument.Open<SvgDocument>(memStream);
doc.BaseUri = baseUri;
if (fileName.StartsWith("__"))
{
......
color-prof-01-f.svg
color-prop-01-b.svg
color-prop-02-f.svg
color-prop-03-t.svg
......@@ -52,7 +51,6 @@ pservers-grad-14-b.svg
pservers-grad-15-b.svg
pservers-grad-16-b.svg
pservers-grad-17-b.svg
pservers-grad-18-b.svg
pservers-grad-20-b.svg
pservers-grad-22-b.svg
pservers-grad-23-f.svg
......
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