Commit 14a3b6a9 authored by Eric Domke's avatar Eric Domke
Browse files

.Net 3.5 Support and Marker Fixes

- Implemented .Net 3.5 support mostly by removing ISvgEventCaller
functionality in .Net 3.5 build
- Added ability to parse orient="auto"
- Added ability to parse colors such as rgb(#%, #%, #%)
- Fixed marker rendering implementation
parent 2f2a1e02
...@@ -22,12 +22,14 @@ namespace SVGViewer ...@@ -22,12 +22,14 @@ namespace SVGViewer
private void open_Click(object sender, EventArgs e) private void open_Click(object sender, EventArgs e)
{ {
if (openSvgFile.ShowDialog() == DialogResult.OK) //if (openSvgFile.ShowDialog() == DialogResult.OK)
{ //{
SvgDocument svgDoc = SvgDocument.Open(openSvgFile.FileName); //var path = openSvgFile.FileName;
var path = @"C:\Users\edomke\AppData\Local\Temp\map.svg";
SvgDocument svgDoc = SvgDocument.Open(path);
RenderSvg(svgDoc); RenderSvg(svgDoc);
} //}
} }
private string FXML = ""; private string FXML = "";
......
...@@ -10,6 +10,7 @@ namespace Svg ...@@ -10,6 +10,7 @@ namespace Svg
/// <summary> /// <summary>
/// Represents an orientation in an Scalable Vector Graphics document. /// Represents an orientation in an Scalable Vector Graphics document.
/// </summary> /// </summary>
[TypeConverter(typeof(SvgOrientConverter))]
public class SvgOrient public class SvgOrient
{ {
private bool _isAuto = true; private bool _isAuto = true;
...@@ -102,6 +103,22 @@ namespace Svg ...@@ -102,6 +103,22 @@ namespace Svg
{ {
return new SvgOrient(value); return new SvgOrient(value);
} }
public static implicit operator SvgOrient(string value)
{
float angle;
if (value == "auto")
{
return new SvgOrient();
}
else if (float.TryParse(value, out angle))
{
return new SvgOrient(angle);
}
else
{
throw new ArgumentException("The value '" + value + "' cannot be converted to an SVG value.");
}
}
} }
......
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Globalization;
namespace Svg
{
public sealed class SvgOrientConverter : TypeConverter
{
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value == null || value.ToString() == string.Empty || value.ToString() == "auto")
{
return new SvgOrient();
}
else if (value is float)
{
return new SvgOrient((float)value);
}
else if (value is int)
{
return new SvgOrient((float)value);
}
throw new ArgumentException("The value '" + value.ToString() + "' cannot be converted to an SVG value.");
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string) || sourceType == typeof(float) || sourceType == typeof(int))
{
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 override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
return ((SvgOrient)value).ToString();
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
}
...@@ -50,7 +50,18 @@ namespace Svg ...@@ -50,7 +50,18 @@ namespace Svg
//so we have to determine the corosponding byte value //so we have to determine the corosponding byte value
alphaValue = (int)(decimal.Parse(values[3]) * 255); alphaValue = (int)(decimal.Parse(values[3]) * 255);
} }
Color colorpart = System.Drawing.Color.FromArgb(alphaValue, int.Parse(values[0]), int.Parse(values[1]), int.Parse(values[2]));
Color colorpart;
if (values[0].Trim().EndsWith("%"))
{
colorpart = System.Drawing.Color.FromArgb(alphaValue, (int)(255 * float.Parse(values[0].Trim().TrimEnd('%')) / 100f),
(int)(255 * float.Parse(values[1].Trim().TrimEnd('%')) / 100f),
(int)(255 * float.Parse(values[2].Trim().TrimEnd('%')) / 100f));
}
else
{
colorpart = System.Drawing.Color.FromArgb(alphaValue, int.Parse(values[0]), int.Parse(values[1]), int.Parse(values[2]));
}
return colorpart; return colorpart;
} }
......
...@@ -49,7 +49,7 @@ namespace Svg ...@@ -49,7 +49,7 @@ namespace Svg
if (value is string) if (value is string)
{ {
var s = (string) value; var s = (string) value;
if(String.Equals( s.Trim(), "none", StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(s)) if(String.Equals( s.Trim(), "none", StringComparison.OrdinalIgnoreCase) || string.IsNullOrEmpty(s) || s.Trim().Length < 1)
return SvgPaintServer.None; return SvgPaintServer.None;
else else
return SvgPaintServerFactory.Create(s, (SvgDocument)context); return SvgPaintServerFactory.Create(s, (SvgDocument)context);
......
...@@ -8,6 +8,11 @@ namespace Svg.Pathing ...@@ -8,6 +8,11 @@ namespace Svg.Pathing
{ {
public override void AddToPath(System.Drawing.Drawing2D.GraphicsPath graphicsPath) public override void AddToPath(System.Drawing.Drawing2D.GraphicsPath graphicsPath)
{ {
// Important for custom line caps. Force the path the close with an explicit line, not just an implicit close of the figure.
if (graphicsPath.PathPoints.Length > 1 && !graphicsPath.PathPoints[0].Equals(graphicsPath.PathPoints[graphicsPath.PathPoints.Length - 1]))
{
graphicsPath.AddLine(graphicsPath.PathPoints[graphicsPath.PathPoints.Length - 1], graphicsPath.PathPoints[0]);
}
graphicsPath.CloseFigure(); graphicsPath.CloseFigure();
} }
......
...@@ -143,25 +143,32 @@ namespace Svg ...@@ -143,25 +143,32 @@ namespace Svg
pen.DashPattern = this.StrokeDashArray.ConvertAll(u => u.Value / ((strokeWidth <= 0) ? 1 : strokeWidth)).ToArray(); pen.DashPattern = this.StrokeDashArray.ConvertAll(u => u.Value / ((strokeWidth <= 0) ? 1 : strokeWidth)).ToArray();
} }
//hardcoded transformation matrix. I am not sure why this is not in proportion or rotated correctly (something to do with how the endcaps are determined in GDI)
var transMatrix = new Matrix();
transMatrix.Rotate(-90f);
transMatrix.Scale(.6f, .6f);
if (this.MarkerStart != null) if (this.MarkerStart != null)
{ {
var marker = this.OwnerDocument.GetElementById<SvgMarker>(this.MarkerStart.ToString()); var marker = this.OwnerDocument.GetElementById<SvgMarker>(this.MarkerStart.ToString());
var markerPath = marker.Path.Clone() as GraphicsPath; var markerPath = marker.Path.Clone() as GraphicsPath;
var transMatrix = new Matrix();
transMatrix.Scale(.5f, .5f);
transMatrix.RotateAt(90f, new PointF(marker.RefX.ToDeviceValue(), marker.RefY.ToDeviceValue()));
transMatrix.Translate(-1 * marker.RefX.ToDeviceValue(), -1 * marker.RefY.ToDeviceValue());
markerPath.Transform(transMatrix); markerPath.Transform(transMatrix);
pen.CustomStartCap = new CustomLineCap(markerPath, null); pen.CustomStartCap = new CustomLineCap(markerPath, null);
} }
if (this.MarkerEnd != null) if (this.MarkerEnd != null)
{ {
var marker = this.OwnerDocument.GetElementById<SvgMarker>(this.MarkerEnd.ToString()); var marker = this.OwnerDocument.GetElementById<SvgMarker>(this.MarkerEnd.ToString());
var markerPath = marker.Path.Clone() as GraphicsPath; var markerPath = marker.Path.Clone() as GraphicsPath;
var transMatrix = new Matrix();
transMatrix.Scale(.5f, .5f);
transMatrix.Rotate(90f);
transMatrix.Translate(-1 * marker.RefX.ToDeviceValue(), -1 * marker.RefY.ToDeviceValue());
markerPath.Transform(transMatrix); markerPath.Transform(transMatrix);
pen.CustomEndCap = new CustomLineCap(markerPath, null); pen.CustomEndCap = new CustomLineCap(markerPath, null);
} }
renderer.DrawPath(pen, this.Path); renderer.DrawPath(pen, this.Path);
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<OldToolsVersion>3.5</OldToolsVersion> <OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation> <UpgradeBackupLocation>
</UpgradeBackupLocation> </UpgradeBackupLocation>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<IsWebBootstrapper>false</IsWebBootstrapper> <IsWebBootstrapper>false</IsWebBootstrapper>
<SccProjectName> <SccProjectName>
</SccProjectName> </SccProjectName>
...@@ -106,6 +106,7 @@ ...@@ -106,6 +106,7 @@
<Compile Include="DataTypes\SvgElementStyle.cs" /> <Compile Include="DataTypes\SvgElementStyle.cs" />
<Compile Include="DataTypes\SvgCoordinateUnits.cs" /> <Compile Include="DataTypes\SvgCoordinateUnits.cs" />
<Compile Include="DataTypes\SvgFontWeight.cs" /> <Compile Include="DataTypes\SvgFontWeight.cs" />
<Compile Include="DataTypes\SvgOrientConverter.cs" />
<Compile Include="DataTypes\SvgOverflow.cs" /> <Compile Include="DataTypes\SvgOverflow.cs" />
<Compile Include="DataTypes\SvgUnitCollection.cs" /> <Compile Include="DataTypes\SvgUnitCollection.cs" />
<Compile Include="DataTypes\SvgViewBox.cs" /> <Compile Include="DataTypes\SvgViewBox.cs" />
......
...@@ -243,7 +243,7 @@ namespace Svg ...@@ -243,7 +243,7 @@ namespace Svg
element.Content = value.ToString(); element.Content = value.ToString();
// Reset content value for new element // Reset content value for new element
value.Clear(); value.Length = 0;
} }
break; break;
case XmlNodeType.CDATA: case XmlNodeType.CDATA:
......
...@@ -763,6 +763,7 @@ namespace Svg ...@@ -763,6 +763,7 @@ namespace Svg
onmouseout = "<anything>" onmouseout = "<anything>"
*/ */
#if Net4
/// <summary> /// <summary>
/// Use this method to provide your implementation ISvgEventCaller which can register Actions /// Use this method to provide your implementation ISvgEventCaller which can register Actions
/// and call them if one of the events occurs. Make sure, that your SvgElement has a unique ID. /// and call them if one of the events occurs. Make sure, that your SvgElement has a unique ID.
...@@ -804,6 +805,7 @@ namespace Svg ...@@ -804,6 +805,7 @@ namespace Svg
caller.UnregisterAction(rpcID + "onmouseout"); caller.UnregisterAction(rpcID + "onmouseout");
} }
} }
#endif
[SvgAttribute("onclick")] [SvgAttribute("onclick")]
public event EventHandler<MouseArg> Click; public event EventHandler<MouseArg> Click;
...@@ -825,12 +827,14 @@ namespace Svg ...@@ -825,12 +827,14 @@ namespace Svg
[SvgAttribute("onmouseout")] [SvgAttribute("onmouseout")]
public event EventHandler<MouseArg> MouseOut; public event EventHandler<MouseArg> MouseOut;
#if Net4
protected Action<float, float, int, int, bool, bool, bool, string> CreateMouseEventAction(Action<object, MouseArg> eventRaiser) protected Action<float, float, int, int, bool, bool, bool, string> CreateMouseEventAction(Action<object, MouseArg> eventRaiser)
{ {
return (x, y, button, clickCount, altKey, shiftKey, ctrlKey, sessionID) => return (x, y, button, clickCount, altKey, shiftKey, ctrlKey, sessionID) =>
eventRaiser(this, new MouseArg { x = x, y = y, Button = button, ClickCount = clickCount, AltKey = altKey, ShiftKey = shiftKey, CtrlKey = ctrlKey, SessionID = sessionID }); eventRaiser(this, new MouseArg { x = x, y = y, Button = button, ClickCount = clickCount, AltKey = altKey, ShiftKey = shiftKey, CtrlKey = ctrlKey, SessionID = sessionID });
} }
#endif
//click //click
protected void RaiseMouseClick(object sender, MouseArg e) protected void RaiseMouseClick(object sender, MouseArg e)
...@@ -943,6 +947,7 @@ namespace Svg ...@@ -943,6 +947,7 @@ namespace Svg
public SvgElement BeforeSibling; public SvgElement BeforeSibling;
} }
#if Net4
//deriving class registers event actions and calls the actions if the event occurs //deriving class registers event actions and calls the actions if the event occurs
public interface ISvgEventCaller public interface ISvgEventCaller
{ {
...@@ -957,6 +962,7 @@ namespace Svg ...@@ -957,6 +962,7 @@ namespace Svg
void RegisterAction<T1, T2, T3, T4, T5, T6, T7, T8>(string rpcID, Action<T1, T2, T3, T4, T5, T6, T7, T8> action); void RegisterAction<T1, T2, T3, T4, T5, T6, T7, T8>(string rpcID, Action<T1, T2, T3, T4, T5, T6, T7, T8> action);
void UnregisterAction(string rpcID); void UnregisterAction(string rpcID);
} }
#endif
/// <summary> /// <summary>
/// Represents the state of the mouse at the moment the event occured. /// Represents the state of the mouse at the moment the event occured.
......
...@@ -313,7 +313,7 @@ namespace Svg ...@@ -313,7 +313,7 @@ namespace Svg
{ {
// Make sure the path is always null if there is no text // Make sure the path is always null if there is no text
//if there is a TSpan inside of this text element then path should not be null (even if this text is empty!) //if there is a TSpan inside of this text element then path should not be null (even if this text is empty!)
if (string.IsNullOrWhiteSpace(this.Text) && this.Children.Where(x => x is SvgTextSpan).Select(x => x as SvgTextSpan).Count() == 0) if ((string.IsNullOrEmpty(this.Text) || this.Text.Trim().Length < 1) && this.Children.Where(x => x is SvgTextSpan).Select(x => x as SvgTextSpan).Count() == 0)
return _path = null; return _path = null;
//NOT SURE WHAT THIS IS ABOUT - Path gets created again anyway - WTF? //NOT SURE WHAT THIS IS ABOUT - Path gets created again anyway - WTF?
// When an empty string is passed to GraphicsPath, it rises an InvalidArgumentException... // When an empty string is passed to GraphicsPath, it rises an InvalidArgumentException...
...@@ -462,6 +462,7 @@ namespace Svg ...@@ -462,6 +462,7 @@ namespace Svg
} }
} }
#if Net4
public override void RegisterEvents(ISvgEventCaller caller) public override void RegisterEvents(ISvgEventCaller caller)
{ {
//register basic events //register basic events
...@@ -480,6 +481,7 @@ namespace Svg ...@@ -480,6 +481,7 @@ namespace Svg
caller.UnregisterAction(this.ID + "/onchange"); caller.UnregisterAction(this.ID + "/onchange");
} }
#endif
public override SvgElement DeepCopy() public override SvgElement DeepCopy()
{ {
......
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