Commit 1fcb5709 authored by Tebjan Halm's avatar Tebjan Halm
Browse files

added custom attributes to svg elements, svg writing to XML is non verbose

parent 5d3b01aa
...@@ -21,12 +21,12 @@ namespace Svg ...@@ -21,12 +21,12 @@ namespace Svg
/// <summary> /// <summary>
/// Gets and empty <see cref="SvgUnit"/>. /// Gets and empty <see cref="SvgUnit"/>.
/// </summary> /// </summary>
public static readonly SvgUnit Empty = new SvgUnit(); public static readonly SvgUnit Empty = new SvgUnit(SvgUnitType.User, 0);
/// <summary> /// <summary>
/// Gets an <see cref="SvgUnit"/> with a value of none. /// Gets an <see cref="SvgUnit"/> with a value of none.
/// </summary> /// </summary>
public static readonly SvgUnit None = new SvgUnit(SvgUnitType.None,0f); public static readonly SvgUnit None = new SvgUnit(SvgUnitType.None, 0f);
/// <summary> /// <summary>
/// Gets a value to determine whether the unit is empty. /// Gets a value to determine whether the unit is empty.
......
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Globalization; using System.Globalization;
namespace Svg namespace Svg
{ {
//just overrrides canconvert and returns true //just overrrides canconvert and returns true
public class BaseConverter : TypeConverter public class BaseConverter : TypeConverter
{ {
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{ {
if (sourceType == typeof(string)) if (sourceType == typeof(string))
{ {
return true; return true;
} }
return base.CanConvertFrom(context, sourceType); return base.CanConvertFrom(context, sourceType);
} }
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{ {
if (destinationType == typeof(string)) if (destinationType == typeof(string))
{ {
return true; return true;
} }
return base.CanConvertTo(context, destinationType); return base.CanConvertTo(context, destinationType);
} }
} }
public sealed class SvgBoolConverter : BaseConverter public sealed class SvgBoolConverter : BaseConverter
{ {
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{ {
if (value == null) if (value == null)
{ {
return true; return true;
} }
if (!(value is string)) if (!(value is string))
{ {
throw new ArgumentOutOfRangeException("value must be a string."); throw new ArgumentOutOfRangeException("value must be a string.");
} }
return (string)value == "visible" ? true : false; return (string)value == "visible" ? true : false;
} }
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{ {
if (destinationType == typeof(string)) if (destinationType == typeof(string))
{ {
return ((bool)value) ? "visible" : "hidden"; return ((bool)value) ? "visible" : "hidden";
} }
return base.ConvertTo(context, culture, value, destinationType); return base.ConvertTo(context, culture, value, destinationType);
} }
} }
//converts enums to lower case strings //converts enums to lower case strings
public class EnumBaseConverter<T> : BaseConverter public class EnumBaseConverter<T> : BaseConverter
{ {
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{ {
if (value == null) if (value == null)
{ {
return Activator.CreateInstance(typeof(T)); return Activator.CreateInstance(typeof(T));
} }
if (!(value is string)) if (!(value is string))
{ {
throw new ArgumentOutOfRangeException("value must be a string."); throw new ArgumentOutOfRangeException("value must be a string.");
} }
return (T)Enum.Parse(typeof(T), (string)value, true); return (T)Enum.Parse(typeof(T), (string)value, true);
} }
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{ {
if (destinationType == typeof(string)) if (destinationType == typeof(string))
{ {
return ((T)value).ToString().ToLower(); return ((T)value).ToString().ToLower();
} }
return base.ConvertTo(context, culture, value, destinationType); return base.ConvertTo(context, culture, value, destinationType);
} }
} }
//implementation for fill-rule //implementation for fill-rule
public sealed class SvgFillRuleConverter : EnumBaseConverter<SvgFillRule> public sealed class SvgFillRuleConverter : EnumBaseConverter<SvgFillRule>
{ {
} }
//implementaton for clip rule //implementaton for clip rule
public sealed class SvgClipRuleConverter : EnumBaseConverter<SvgClipRule> public sealed class SvgClipRuleConverter : EnumBaseConverter<SvgClipRule>
{ {
} }
//implementaton for clip rule //implementaton for clip rule
public sealed class SvgTextAnchorConverter : EnumBaseConverter<SvgTextAnchor> public sealed class SvgTextAnchorConverter : EnumBaseConverter<SvgTextAnchor>
{ {
} }
//implementaton for preserve aspect ratio //implementaton for preserve aspect ratio
public sealed class SvgPreserverAspectRatioConverter : EnumBaseConverter<SvgPreserveAspectRatio> public sealed class SvgPreserverAspectRatioConverter : EnumBaseConverter<SvgPreserveAspectRatio>
{ {
} }
} public sealed class SvgStrokeLineCapConverter : EnumBaseConverter<SvgStrokeLineCap>
{
}
public sealed class SvgStrokeLineJoinConverter : EnumBaseConverter<SvgStrokeLineJoin>
{
}
}
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.ComponentModel;
namespace Svg namespace Svg
{ {
[TypeConverter(typeof(SvgStrokeLineCapConverter))]
public enum SvgStrokeLineCap public enum SvgStrokeLineCap
{ {
Butt, Butt,
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.ComponentModel;
namespace Svg namespace Svg
{ {
[TypeConverter(typeof(SvgStrokeLineJoinConverter))]
public enum SvgStrokeLineJoin public enum SvgStrokeLineJoin
{ {
Miter, Miter,
......
...@@ -18,7 +18,7 @@ namespace Svg ...@@ -18,7 +18,7 @@ namespace Svg
} }
} }
internal class SvgPathBuilder : TypeConverter public class SvgPathBuilder : TypeConverter
{ {
/// <summary> /// <summary>
/// Parses the specified string into a collection of path segments. /// Parses the specified string into a collection of path segments.
...@@ -46,6 +46,20 @@ namespace Svg ...@@ -46,6 +46,20 @@ namespace Svg
isRelative = char.IsLower(command); isRelative = char.IsLower(command);
// http://www.w3.org/TR/SVG11/paths.html#PathDataGeneralInformation // http://www.w3.org/TR/SVG11/paths.html#PathDataGeneralInformation
CreatePathSegment(command, segments, coords, isRelative);
}
}
catch (Exception exc)
{
Trace.TraceError("Error parsing path \"{0}\": {1}", path, exc.Message);
}
return segments;
}
public static void CreatePathSegment(char command, SvgPathSegmentList segments, List<float> coords, bool isRelative)
{
switch (command) switch (command)
{ {
case 'm': // relative moveto case 'm': // relative moveto
...@@ -148,14 +162,6 @@ namespace Svg ...@@ -148,14 +162,6 @@ namespace Svg
segments.Add(new SvgClosePathSegment()); segments.Add(new SvgClosePathSegment());
break; break;
} }
}
}
catch (Exception exc)
{
Trace.TraceError("Error parsing path \"{0}\": {1}", path, exc.Message);
}
return segments;
} }
private static PointF Reflect(PointF point, PointF mirror) private static PointF Reflect(PointF point, PointF mirror)
......
...@@ -121,6 +121,7 @@ ...@@ -121,6 +121,7 @@
<Compile Include="Filter Effects\feGaussianBlur\SvgGaussianBlur.cs" /> <Compile Include="Filter Effects\feGaussianBlur\SvgGaussianBlur.cs" />
<Compile Include="Filter Effects\feMerge\SvgMerge.cs" /> <Compile Include="Filter Effects\feMerge\SvgMerge.cs" />
<Compile Include="Painting\EnumConverters.cs" /> <Compile Include="Painting\EnumConverters.cs" />
<Compile Include="SvgDefinitionDefaults.cs" />
<Compile Include="SvgElementAttribute.cs" /> <Compile Include="SvgElementAttribute.cs" />
<Compile Include="SvgRenderer.cs" /> <Compile Include="SvgRenderer.cs" />
<Compile Include="Painting\SvgColourConverter.cs" /> <Compile Include="Painting\SvgColourConverter.cs" />
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Svg
{
/// <summary>
/// Holds a dictionary of the default values of the SVG specification
/// </summary>
public static class SvgDefaults
{
//internal dictionary for the defaults
private static readonly Dictionary<string, string> _defaults = new Dictionary<string, string>();
static SvgDefaults()
{
_defaults["viewBox"] = "0, 0, 0, 0";
_defaults["visibility"] = "visible";
_defaults["opacity"] = "1";
_defaults["clip-rule"] = "nonzero";
_defaults["transform"] = "";
_defaults["fill"] = "Black";
_defaults["fill-opacity"] = "1";
_defaults["fill-rule"] = "nonzero";
_defaults["stroke"] = "none";
_defaults["stroke-opacity"] = "1";
_defaults["stroke-width"] = "1";
_defaults["stroke-miterlimit"] = "4";
_defaults["stroke-linecap"] = "butt";
_defaults["stroke-linejoin"] = "miter";
_defaults["stroke-dasharray"] = "none";
_defaults["stroke-dashoffset"] = "0";
}
/// <summary>
/// Checks whether the property value is the default value of the svg definition.
/// </summary>
/// <param name="attributeName">Name of the svg attribute</param>
/// <param name="propertyValue">.NET value of the attribute</param>
public static bool IsDefault(string attributeName, string value)
{
if (_defaults.ContainsKey(attributeName))
{
if (_defaults[attributeName] == value) return true;
else if (attributeName == "fill") return value == "#000000";
}
return false;
}
}
}
...@@ -22,6 +22,7 @@ namespace Svg ...@@ -22,6 +22,7 @@ namespace Svg
private SvgElementCollection _children; private SvgElementCollection _children;
private static readonly object _loadEventKey = new object(); private static readonly object _loadEventKey = new object();
private Matrix _graphicsMatrix; private Matrix _graphicsMatrix;
private Dictionary<string, string> _customAttributes;
/// <summary> /// <summary>
/// Gets the name of the element. /// Gets the name of the element.
...@@ -137,6 +138,11 @@ namespace Svg ...@@ -137,6 +138,11 @@ namespace Svg
} }
} }
public Dictionary<string, string> CustomAttributes
{
get { return this._customAttributes; }
}
/// <summary> /// <summary>
/// Applies the required transforms to <see cref="SvgRenderer"/>. /// Applies the required transforms to <see cref="SvgRenderer"/>.
/// </summary> /// </summary>
...@@ -276,12 +282,13 @@ namespace Svg ...@@ -276,12 +282,13 @@ namespace Svg
this._children = new SvgElementCollection(this); this._children = new SvgElementCollection(this);
this._eventHandlers = new EventHandlerList(); this._eventHandlers = new EventHandlerList();
this._elementName = string.Empty; this._elementName = string.Empty;
this._customAttributes = new Dictionary<string, string>();
} }
public virtual void InitialiseFromXML(XmlTextReader reader, SvgDocument document) public virtual void InitialiseFromXML(XmlTextReader reader, SvgDocument document)
{ {
throw new NotImplementedException();
} }
...@@ -343,25 +350,27 @@ namespace Svg ...@@ -343,25 +350,27 @@ namespace Svg
if (propertyValue != null) if (propertyValue != null)
{ {
var type = propertyValue.GetType(); var type = propertyValue.GetType();
string value = (string)attr.Property.Converter.ConvertTo(propertyValue, typeof(string));
object defaultValue = null; if (!SvgDefaults.IsDefault(attr.Attribute.Name, value))
if(type.IsValueType)
defaultValue = Activator.CreateInstance(type);
if (!propertyValue.Equals(defaultValue) || type == typeof(float) || type == typeof(bool) || type == typeof(SvgColourServer))
{ {
string value = (string)attr.Property.Converter.ConvertTo(propertyValue, typeof(string));
writer.WriteAttributeString(attr.Attribute.NamespaceAndName, value); writer.WriteAttributeString(attr.Attribute.NamespaceAndName, value);
} }
} }
else if(attr.Attribute.Name == "fill") //if fill equals null, write 'none' else if(attr.Attribute.Name == "fill") //if fill equals null, write 'none'
{ {
string value = (string)attr.Property.Converter.ConvertTo(propertyValue, typeof(string)); string value = (string)attr.Property.Converter.ConvertTo(propertyValue, typeof(string));
writer.WriteAttributeString(attr.Attribute.NamespaceAndName, value); writer.WriteAttributeString(attr.Attribute.NamespaceAndName, value);
} }
} }
} }
//add the custom attributes
foreach (var item in this._customAttributes)
{
writer.WriteAttributeString(item.Key, item.Value);
}
} }
protected virtual void Write(XmlTextWriter writer) protected virtual void Write(XmlTextWriter writer)
......
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