diff --git a/Source/DataTypes/SvgUnit.cs b/Source/DataTypes/SvgUnit.cs index 3c437bd6008662f47bd7fc16909448ce562faa9d..86dd7e8a3ffee1ac2fb3371d399cc02eece52cd6 100644 --- a/Source/DataTypes/SvgUnit.cs +++ b/Source/DataTypes/SvgUnit.cs @@ -21,12 +21,12 @@ namespace Svg /// /// Gets and empty . /// - public static readonly SvgUnit Empty = new SvgUnit(); + public static readonly SvgUnit Empty = new SvgUnit(SvgUnitType.User, 0); /// /// Gets an with a value of none. /// - public static readonly SvgUnit None = new SvgUnit(SvgUnitType.None,0f); + public static readonly SvgUnit None = new SvgUnit(SvgUnitType.None, 0f); /// /// Gets a value to determine whether the unit is empty. diff --git a/Source/Painting/EnumConverters.cs b/Source/Painting/EnumConverters.cs index 3e4ab87f6f8c7852d43c94ad7680faadc424dc46..96b7ba7701b982b583d9ead2134d4c8c88fc9370 100644 --- a/Source/Painting/EnumConverters.cs +++ b/Source/Painting/EnumConverters.cs @@ -1,110 +1,118 @@ -using System; -using System.ComponentModel; -using System.Globalization; - -namespace Svg -{ - - //just overrrides canconvert and returns true - public class BaseConverter : TypeConverter - { - - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - if (sourceType == typeof(string)) - { - return true; - } - - return base.CanConvertFrom(context, sourceType); - } - - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) - { - if (destinationType == typeof(string)) - { - return true; - } - - return base.CanConvertTo(context, destinationType); - } - } - - public sealed class SvgBoolConverter : BaseConverter - { - public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - if (value == null) - { - return true; - } - - if (!(value is string)) - { - throw new ArgumentOutOfRangeException("value must be a string."); - } - - return (string)value == "visible" ? true : false; - } - - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) - { - if (destinationType == typeof(string)) - { - return ((bool)value) ? "visible" : "hidden"; - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - //converts enums to lower case strings - public class EnumBaseConverter : BaseConverter - { - public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - if (value == null) - { - return Activator.CreateInstance(typeof(T)); - } - - if (!(value is string)) - { - throw new ArgumentOutOfRangeException("value must be a string."); - } - - return (T)Enum.Parse(typeof(T), (string)value, true); - } - - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) - { - if (destinationType == typeof(string)) - { - return ((T)value).ToString().ToLower(); - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } - - //implementation for fill-rule - public sealed class SvgFillRuleConverter : EnumBaseConverter - { - } - - //implementaton for clip rule - public sealed class SvgClipRuleConverter : EnumBaseConverter - { - } - - //implementaton for clip rule - public sealed class SvgTextAnchorConverter : EnumBaseConverter - { - } - - //implementaton for preserve aspect ratio - public sealed class SvgPreserverAspectRatioConverter : EnumBaseConverter - { - } - -} +using System; +using System.ComponentModel; +using System.Globalization; + +namespace Svg +{ + + //just overrrides canconvert and returns true + public class BaseConverter : TypeConverter + { + + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == typeof(string)) + { + return true; + } + + return base.CanConvertFrom(context, sourceType); + } + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + if (destinationType == typeof(string)) + { + return true; + } + + return base.CanConvertTo(context, destinationType); + } + } + + public sealed class SvgBoolConverter : BaseConverter + { + public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + { + if (value == null) + { + return true; + } + + if (!(value is string)) + { + throw new ArgumentOutOfRangeException("value must be a string."); + } + + return (string)value == "visible" ? true : false; + } + + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (destinationType == typeof(string)) + { + return ((bool)value) ? "visible" : "hidden"; + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + //converts enums to lower case strings + public class EnumBaseConverter : BaseConverter + { + public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + { + if (value == null) + { + return Activator.CreateInstance(typeof(T)); + } + + if (!(value is string)) + { + throw new ArgumentOutOfRangeException("value must be a string."); + } + + return (T)Enum.Parse(typeof(T), (string)value, true); + } + + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (destinationType == typeof(string)) + { + return ((T)value).ToString().ToLower(); + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } + + //implementation for fill-rule + public sealed class SvgFillRuleConverter : EnumBaseConverter + { + } + + //implementaton for clip rule + public sealed class SvgClipRuleConverter : EnumBaseConverter + { + } + + //implementaton for clip rule + public sealed class SvgTextAnchorConverter : EnumBaseConverter + { + } + + //implementaton for preserve aspect ratio + public sealed class SvgPreserverAspectRatioConverter : EnumBaseConverter + { + } + + public sealed class SvgStrokeLineCapConverter : EnumBaseConverter + { + } + + public sealed class SvgStrokeLineJoinConverter : EnumBaseConverter + { + } + +} diff --git a/Source/Painting/SvgStrokeLineCap.cs b/Source/Painting/SvgStrokeLineCap.cs index 41a94e23a949773e204a9f0e9c206920e454339f..f937e7f778fe366a34cdb46e440c9a2c24f64421 100644 --- a/Source/Painting/SvgStrokeLineCap.cs +++ b/Source/Painting/SvgStrokeLineCap.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; using System.Text; +using System.ComponentModel; namespace Svg { + [TypeConverter(typeof(SvgStrokeLineCapConverter))] public enum SvgStrokeLineCap { Butt, diff --git a/Source/Painting/SvgStrokeLineJoin.cs b/Source/Painting/SvgStrokeLineJoin.cs index 7a81a2ee24cc6f7fd6af7c6897dd127e44cccca5..7af2288ae07950cce802fec03ab44d83fb2f59b0 100644 --- a/Source/Painting/SvgStrokeLineJoin.cs +++ b/Source/Painting/SvgStrokeLineJoin.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; using System.Text; +using System.ComponentModel; namespace Svg { + [TypeConverter(typeof(SvgStrokeLineJoinConverter))] public enum SvgStrokeLineJoin { Miter, diff --git a/Source/Paths/SvgPathBuilder.cs b/Source/Paths/SvgPathBuilder.cs index b290edcb49edc48fd6b9fcc298a0ea49e606128e..a08375074e671b70e8c5bb86d95abda31bf455da 100644 --- a/Source/Paths/SvgPathBuilder.cs +++ b/Source/Paths/SvgPathBuilder.cs @@ -18,7 +18,7 @@ namespace Svg } } - internal class SvgPathBuilder : TypeConverter + public class SvgPathBuilder : TypeConverter { /// /// Parses the specified string into a collection of path segments. @@ -46,6 +46,20 @@ namespace Svg isRelative = char.IsLower(command); // 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 coords, bool isRelative) + { + switch (command) { case 'm': // relative moveto @@ -148,14 +162,6 @@ namespace Svg segments.Add(new SvgClosePathSegment()); break; } - } - } - catch (Exception exc) - { - Trace.TraceError("Error parsing path \"{0}\": {1}", path, exc.Message); - } - - return segments; } private static PointF Reflect(PointF point, PointF mirror) diff --git a/Source/Svg.csproj b/Source/Svg.csproj index a365fd4a9e50efad77a606c930daf1fdb1e833c4..7704593b486c91a179066ce19b8e7f61c66f96e4 100644 --- a/Source/Svg.csproj +++ b/Source/Svg.csproj @@ -121,6 +121,7 @@ + diff --git a/Source/SvgDefinitionDefaults.cs b/Source/SvgDefinitionDefaults.cs new file mode 100644 index 0000000000000000000000000000000000000000..7896e4d276bed62944449cb70727ebb6fbfa1c1a --- /dev/null +++ b/Source/SvgDefinitionDefaults.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Svg +{ + /// + /// Holds a dictionary of the default values of the SVG specification + /// + public static class SvgDefaults + { + //internal dictionary for the defaults + private static readonly Dictionary _defaults = new Dictionary(); + + 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"; + } + + /// + /// Checks whether the property value is the default value of the svg definition. + /// + /// Name of the svg attribute + /// .NET value of the attribute + 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; + } + } +} diff --git a/Source/SvgElement.cs b/Source/SvgElement.cs index 6bb904315bb0de3c7bb0177289330322015fff78..1f299452e74b2f727559b601b150182f35561b1d 100644 --- a/Source/SvgElement.cs +++ b/Source/SvgElement.cs @@ -22,6 +22,7 @@ namespace Svg private SvgElementCollection _children; private static readonly object _loadEventKey = new object(); private Matrix _graphicsMatrix; + private Dictionary _customAttributes; /// /// Gets the name of the element. @@ -137,6 +138,11 @@ namespace Svg } } + public Dictionary CustomAttributes + { + get { return this._customAttributes; } + } + /// /// Applies the required transforms to . /// @@ -276,12 +282,13 @@ namespace Svg this._children = new SvgElementCollection(this); this._eventHandlers = new EventHandlerList(); this._elementName = string.Empty; + this._customAttributes = new Dictionary(); } public virtual void InitialiseFromXML(XmlTextReader reader, SvgDocument document) { - + throw new NotImplementedException(); } @@ -343,25 +350,27 @@ namespace Svg if (propertyValue != null) { var type = propertyValue.GetType(); + string value = (string)attr.Property.Converter.ConvertTo(propertyValue, typeof(string)); - object defaultValue = null; - if(type.IsValueType) - defaultValue = Activator.CreateInstance(type); - - if (!propertyValue.Equals(defaultValue) || type == typeof(float) || type == typeof(bool) || type == typeof(SvgColourServer)) + if (!SvgDefaults.IsDefault(attr.Attribute.Name, value)) { - string value = (string)attr.Property.Converter.ConvertTo(propertyValue, typeof(string)); - 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); + 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) diff --git a/Source/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/Source/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache index 341b11fa1d2075dabeb44ceb8a9ee60708224484..1867c4d45b05c10adbe13ba39fb031dbc657acf9 100644 Binary files a/Source/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache and b/Source/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ diff --git a/Source/obj/Release/ResolveAssemblyReference.cache b/Source/obj/Release/ResolveAssemblyReference.cache deleted file mode 100644 index b74b5ef69b54cde8674c69ea59c6b5f0592e900d..0000000000000000000000000000000000000000 Binary files a/Source/obj/Release/ResolveAssemblyReference.cache and /dev/null differ