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
Showing with 130 additions and 20 deletions
+130 -20
......@@ -22,12 +22,14 @@ namespace SVGViewer
private void open_Click(object sender, EventArgs e)
{
if (openSvgFile.ShowDialog() == DialogResult.OK)
{
SvgDocument svgDoc = SvgDocument.Open(openSvgFile.FileName);
//if (openSvgFile.ShowDialog() == DialogResult.OK)
//{
//var path = openSvgFile.FileName;
var path = @"C:\Users\edomke\AppData\Local\Temp\map.svg";
SvgDocument svgDoc = SvgDocument.Open(path);
RenderSvg(svgDoc);
}
//}
}
private string FXML = "";
......
......@@ -10,6 +10,7 @@ namespace Svg
/// <summary>
/// Represents an orientation in an Scalable Vector Graphics document.
/// </summary>
[TypeConverter(typeof(SvgOrientConverter))]
public class SvgOrient
{
private bool _isAuto = true;
......@@ -102,6 +103,22 @@ namespace Svg
{
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
//so we have to determine the corosponding byte value
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;
}
......
......@@ -49,7 +49,7 @@ namespace Svg
if (value is string)
{
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;
else
return SvgPaintServerFactory.Create(s, (SvgDocument)context);
......
......@@ -8,6 +8,11 @@ namespace Svg.Pathing
{
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();
}
......
......@@ -143,25 +143,32 @@ namespace Svg
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)
{
var marker = this.OwnerDocument.GetElementById<SvgMarker>(this.MarkerStart.ToString());
var markerPath = marker.Path.Clone() as GraphicsPath;
var marker = this.OwnerDocument.GetElementById<SvgMarker>(this.MarkerStart.ToString());
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);
pen.CustomStartCap = new CustomLineCap(markerPath, null);
pen.CustomStartCap = new CustomLineCap(markerPath, 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 transMatrix = new Matrix();
transMatrix.Scale(.5f, .5f);
transMatrix.Rotate(90f);
transMatrix.Translate(-1 * marker.RefX.ToDeviceValue(), -1 * marker.RefY.ToDeviceValue());
markerPath.Transform(transMatrix);
pen.CustomEndCap = new CustomLineCap(markerPath, null);
pen.CustomEndCap = new CustomLineCap(markerPath, null);
}
renderer.DrawPath(pen, this.Path);
......
......@@ -16,7 +16,7 @@
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<SccProjectName>
</SccProjectName>
......@@ -106,6 +106,7 @@
<Compile Include="DataTypes\SvgElementStyle.cs" />
<Compile Include="DataTypes\SvgCoordinateUnits.cs" />
<Compile Include="DataTypes\SvgFontWeight.cs" />
<Compile Include="DataTypes\SvgOrientConverter.cs" />
<Compile Include="DataTypes\SvgOverflow.cs" />
<Compile Include="DataTypes\SvgUnitCollection.cs" />
<Compile Include="DataTypes\SvgViewBox.cs" />
......
......@@ -243,7 +243,7 @@ namespace Svg
element.Content = value.ToString();
// Reset content value for new element
value.Clear();
value.Length = 0;
}
break;
case XmlNodeType.CDATA:
......
......@@ -763,6 +763,7 @@ namespace Svg
onmouseout = "<anything>"
*/
#if Net4
/// <summary>
/// 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.
......@@ -804,6 +805,7 @@ namespace Svg
caller.UnregisterAction(rpcID + "onmouseout");
}
}
#endif
[SvgAttribute("onclick")]
public event EventHandler<MouseArg> Click;
......@@ -825,12 +827,14 @@ namespace Svg
[SvgAttribute("onmouseout")]
public event EventHandler<MouseArg> MouseOut;
#if Net4
protected Action<float, float, int, int, bool, bool, bool, string> CreateMouseEventAction(Action<object, MouseArg> eventRaiser)
{
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 });
}
#endif
//click
protected void RaiseMouseClick(object sender, MouseArg e)
......@@ -943,6 +947,7 @@ namespace Svg
public SvgElement BeforeSibling;
}
#if Net4
//deriving class registers event actions and calls the actions if the event occurs
public interface ISvgEventCaller
{
......@@ -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 UnregisterAction(string rpcID);
}
#endif
/// <summary>
/// Represents the state of the mouse at the moment the event occured.
......
......@@ -313,7 +313,7 @@ namespace Svg
{
// 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 (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;
//NOT SURE WHAT THIS IS ABOUT - Path gets created again anyway - WTF?
// When an empty string is passed to GraphicsPath, it rises an InvalidArgumentException...
......@@ -462,6 +462,7 @@ namespace Svg
}
}
#if Net4
public override void RegisterEvents(ISvgEventCaller caller)
{
//register basic events
......@@ -480,6 +481,7 @@ namespace Svg
caller.UnregisterAction(this.ID + "/onchange");
}
#endif
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