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

Merge pull request #89 from erdomke/master

Rendering Improvements and .Net 3.5 Support
parents ba3bc5fc ce8f2a64
...@@ -28,74 +28,79 @@ ...@@ -28,74 +28,79 @@
/// </summary> /// </summary>
private void InitializeComponent() private void InitializeComponent()
{ {
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SVGViewer)); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SVGViewer));
this.toolStrip1 = new System.Windows.Forms.ToolStrip(); this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.open = new System.Windows.Forms.ToolStripButton(); this.open = new System.Windows.Forms.ToolStripButton();
this.svgImage = new System.Windows.Forms.PictureBox(); this.svgImage = new System.Windows.Forms.PictureBox();
this.openSvgFile = new System.Windows.Forms.OpenFileDialog(); this.openSvgFile = new System.Windows.Forms.OpenFileDialog();
this.textBox1 = new System.Windows.Forms.TextBox(); this.textBox1 = new System.Windows.Forms.TextBox();
this.toolStrip1.SuspendLayout(); this.toolStrip1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.svgImage)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.svgImage)).BeginInit();
this.SuspendLayout(); this.SuspendLayout();
// //
// toolStrip1 // toolStrip1
// //
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.open}); this.open});
this.toolStrip1.Location = new System.Drawing.Point(0, 0); this.toolStrip1.Location = new System.Drawing.Point(0, 0);
this.toolStrip1.Name = "toolStrip1"; this.toolStrip1.Name = "toolStrip1";
this.toolStrip1.Size = new System.Drawing.Size(1060, 25); this.toolStrip1.Size = new System.Drawing.Size(1060, 25);
this.toolStrip1.TabIndex = 0; this.toolStrip1.TabIndex = 0;
this.toolStrip1.Text = "toolStrip1"; this.toolStrip1.Text = "toolStrip1";
// //
// open // open
// //
this.open.Image = ((System.Drawing.Image)(resources.GetObject("open.Image"))); this.open.Image = ((System.Drawing.Image)(resources.GetObject("open.Image")));
this.open.ImageTransparentColor = System.Drawing.Color.Magenta; this.open.ImageTransparentColor = System.Drawing.Color.Magenta;
this.open.Name = "open"; this.open.Name = "open";
this.open.Size = new System.Drawing.Size(53, 22); this.open.Size = new System.Drawing.Size(56, 22);
this.open.Text = "Open"; this.open.Text = "Open";
this.open.Click += new System.EventHandler(this.open_Click); this.open.Click += new System.EventHandler(this.open_Click);
// //
// svgImage // svgImage
// //
this.svgImage.Dock = System.Windows.Forms.DockStyle.Left; this.svgImage.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
this.svgImage.Location = new System.Drawing.Point(0, 25); | System.Windows.Forms.AnchorStyles.Left)
this.svgImage.Name = "svgImage"; | System.Windows.Forms.AnchorStyles.Right)));
this.svgImage.Size = new System.Drawing.Size(565, 449); this.svgImage.Location = new System.Drawing.Point(0, 25);
this.svgImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.svgImage.Name = "svgImage";
this.svgImage.TabIndex = 1; this.svgImage.Size = new System.Drawing.Size(735, 449);
this.svgImage.TabStop = false; this.svgImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
// this.svgImage.TabIndex = 1;
// openSvgFile this.svgImage.TabStop = false;
// //
this.openSvgFile.Filter = "Vector Graphics (*.svg)|*.svg"; // openSvgFile
// //
// textBox1 this.openSvgFile.Filter = "Vector Graphics (*.svg)|*.svg";
// //
this.textBox1.Location = new System.Drawing.Point(571, 25); // textBox1
this.textBox1.MaxLength = 327670; //
this.textBox1.Multiline = true; this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
this.textBox1.Name = "textBox1"; | System.Windows.Forms.AnchorStyles.Right)));
this.textBox1.Size = new System.Drawing.Size(477, 446); this.textBox1.Location = new System.Drawing.Point(741, 25);
this.textBox1.TabIndex = 2; this.textBox1.MaxLength = 327670;
this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged); this.textBox1.Multiline = true;
// this.textBox1.Name = "textBox1";
// SVGViewer this.textBox1.Size = new System.Drawing.Size(307, 446);
// this.textBox1.TabIndex = 2;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; //
this.ClientSize = new System.Drawing.Size(1060, 474); // SVGViewer
this.Controls.Add(this.textBox1); //
this.Controls.Add(this.svgImage); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.Controls.Add(this.toolStrip1); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "SVGViewer"; this.ClientSize = new System.Drawing.Size(1060, 474);
this.Text = "SVG Viewer"; this.Controls.Add(this.textBox1);
this.toolStrip1.ResumeLayout(false); this.Controls.Add(this.svgImage);
this.toolStrip1.PerformLayout(); this.Controls.Add(this.toolStrip1);
((System.ComponentModel.ISupportInitialize)(this.svgImage)).EndInit(); this.Name = "SVGViewer";
this.ResumeLayout(false); this.Text = "SVG Viewer";
this.PerformLayout(); this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.svgImage)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
} }
#endregion #endregion
......
This diff is collapsed.
...@@ -3,6 +3,9 @@ using System.Collections.Generic; ...@@ -3,6 +3,9 @@ using System.Collections.Generic;
using System.Text; using System.Text;
using System.Reflection; using System.Reflection;
using System.ComponentModel; using System.ComponentModel;
using Svg.DataTypes;
using System.Text.RegularExpressions;
using System.Linq;
namespace Svg namespace Svg
{ {
...@@ -151,5 +154,159 @@ namespace Svg ...@@ -151,5 +154,159 @@ namespace Svg
get { return (this.Attributes["opacity"] == null) ? 1.0f : (float)this.Attributes["opacity"]; } get { return (this.Attributes["opacity"] == null) ? 1.0f : (float)this.Attributes["opacity"]; }
set { this.Attributes["opacity"] = FixOpacityValue(value); } set { this.Attributes["opacity"] = FixOpacityValue(value); }
} }
/// <summary>
/// Indicates which font family is to be used to render the text.
/// </summary>
[SvgAttribute("font-family")]
public virtual string FontFamily
{
get { return this.Attributes["font-family"] as string; }
set
{
this.Attributes["font-family"] = value;
this.IsPathDirty = true;
}
}
/// <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")]
public virtual SvgUnit FontSize
{
get { return (this.Attributes["font-size"] == null) ? SvgUnit.Empty : (SvgUnit)this.Attributes["font-size"]; }
set { this.Attributes["font-size"] = value; this.IsPathDirty = true; }
}
public SvgUnit GetInheritedFontSize()
{
var fontSizeElement = (from e in this.ParentsAndSelf.OfType<SvgVisualElement>()
where e.FontSize != SvgUnit.Empty && e.FontSize != SvgUnit.None
select e).FirstOrDefault();
return (fontSizeElement == null ? SvgUnit.None : fontSizeElement.FontSize);
}
/// <summary>
/// Refers to the boldness of the font.
/// </summary>
[SvgAttribute("font-style")]
public virtual SvgFontStyle FontStyle
{
get { return (this.Attributes["font-style"] == null) ? SvgFontStyle.inherit : (SvgFontStyle)this.Attributes["font-style"]; }
set { this.Attributes["font-style"] = value; this.IsPathDirty = true; }
}
/// <summary>
/// Refers to the boldness of the font.
/// </summary>
[SvgAttribute("font-variant")]
public virtual SvgFontVariant FontVariant
{
get { return (this.Attributes["font-variant"] == null) ? SvgFontVariant.inherit : (SvgFontVariant)this.Attributes["font-variant"]; }
set { this.Attributes["font-variant"] = value; this.IsPathDirty = true; }
}
/// <summary>
/// Refers to the boldness of the font.
/// </summary>
[SvgAttribute("font-weight")]
public virtual SvgFontWeight FontWeight
{
get { return (this.Attributes["font-weight"] == null) ? SvgFontWeight.inherit : (SvgFontWeight)this.Attributes["font-weight"]; }
set { this.Attributes["font-weight"] = value; this.IsPathDirty = true; }
}
private enum FontParseState
{
fontStyle,
fontVariant,
fontWeight,
fontSize,
fontFamilyNext,
fontFamilyCurr
}
/// <summary>
/// Set all font information.
/// </summary>
[SvgAttribute("font")]
public virtual string Font
{
get { return (this.Attributes["font"] == null ? "" : this.Attributes["font"] as string); }
set
{
var state = FontParseState.fontStyle;
var parts = value.Split(' ');
SvgFontStyle fontStyle;
SvgFontVariant fontVariant;
SvgFontWeight fontWeight;
SvgUnit fontSize;
bool success;
string[] sizes;
string part;
for (int i = 0; i < parts.Length; i++)
{
part = parts[i];
success = false;
while (!success)
{
switch (state)
{
case FontParseState.fontStyle:
success = Enums.TryParse<SvgFontStyle>(part, out fontStyle);
if (success) this.FontStyle = fontStyle;
state++;
break;
case FontParseState.fontVariant:
success = Enums.TryParse<SvgFontVariant>(part, out fontVariant);
if (success) this.FontVariant = fontVariant;
state++;
break;
case FontParseState.fontWeight:
success = Enums.TryParse<SvgFontWeight>(part, out fontWeight);
if (success) this.FontWeight = fontWeight;
state++;
break;
case FontParseState.fontSize:
sizes = part.Split('/');
try
{
fontSize = (SvgUnit)(new SvgUnitConverter().ConvertFromInvariantString(sizes[0]));
success = true;
this.FontSize = fontSize;
}
catch { }
state++;
break;
case FontParseState.fontFamilyNext:
state++;
success = true;
break;
}
}
switch (state)
{
case FontParseState.fontFamilyNext:
this.FontFamily = string.Join(" ", parts, i + 1, parts.Length - (i + 1));
i = int.MaxValue - 2;
break;
case FontParseState.fontFamilyCurr:
this.FontFamily = string.Join(" ", parts, i, parts.Length - (i));
i = int.MaxValue - 2;
break;
}
}
this.Attributes["font"] = value;
this.IsPathDirty = true;
}
}
} }
} }
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Svg
{
public enum SvgFontStyle
{
normal,
italic,
oblique,
inherit
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace Svg.DataTypes
{
[TypeConverter(typeof(SvgFontVariantConverter))]
public enum SvgFontVariant
{
normal,
smallcaps,
inherit
}
}
...@@ -2,14 +2,26 @@ ...@@ -2,14 +2,26 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.ComponentModel;
namespace Svg.DataTypes namespace Svg
{ {
public enum SvgFontWeight [TypeConverter(typeof(SvgFontWeightConverter))]
{ public enum SvgFontWeight
normal, {
bold inherit,
} normal,
bold,
bolder,
lighter,
w100,
w200,
w300,
w400, // same as normal
w500,
w600,
w700, // same as bold
w800,
w900
}
} }
...@@ -102,8 +102,16 @@ namespace Svg ...@@ -102,8 +102,16 @@ namespace Svg
switch (this.Type) switch (this.Type)
{ {
case SvgUnitType.Em: case SvgUnitType.Em:
float points = (float)(this.Value * 9); var visualElem = boundable as SvgVisualElement;
_deviceValue = (points / 72) * ppi; if (visualElem == null)
{
float points = (float)(this.Value * 9);
_deviceValue = (points / 72) * ppi;
}
else
{
_deviceValue = this.Value * visualElem.GetInheritedFontSize().ToDeviceValue(boundable);
}
break; break;
case SvgUnitType.Centimeter: case SvgUnitType.Centimeter:
_deviceValue = (float)((this.Value / cmInInch) * ppi); _deviceValue = (float)((this.Value / cmInInch) * ppi);
......
...@@ -45,6 +45,7 @@ namespace Svg ...@@ -45,6 +45,7 @@ namespace Svg
{ {
if (value is string) if (value is string)
{ {
if (string.Compare(((string)value).Trim(), "none", StringComparison.InvariantCultureIgnoreCase) == 0) return null;
string[] points = ((string)value).Trim().Split(new char[] { ',', ' ', '\r', '\n', '\t' }, StringSplitOptions.RemoveEmptyEntries); string[] points = ((string)value).Trim().Split(new char[] { ',', ' ', '\r', '\n', '\t' }, StringSplitOptions.RemoveEmptyEntries);
SvgUnitCollection units = new SvgUnitCollection(); SvgUnitCollection units = new SvgUnitCollection();
......
...@@ -23,13 +23,6 @@ namespace Svg ...@@ -23,13 +23,6 @@ namespace Svg
throw new ArgumentOutOfRangeException("value must be a string."); throw new ArgumentOutOfRangeException("value must be a string.");
} }
//support exponents (the SVG that comes back from IE may be an exponent ugh!!!)
if ((value as string).Contains("e"))
{
var d = Decimal.Parse((string)value, System.Globalization.NumberStyles.Float);
value = d.ToString();
}
// http://www.w3.org/TR/CSS21/syndata.html#values // http://www.w3.org/TR/CSS21/syndata.html#values
// http://www.w3.org/TR/SVG11/coords.html#Units // http://www.w3.org/TR/SVG11/coords.html#Units
...@@ -41,7 +34,8 @@ namespace Svg ...@@ -41,7 +34,8 @@ namespace Svg
for (int i = 0; i < unit.Length; i++) for (int i = 0; i < unit.Length; i++)
{ {
if (char.IsLetter(unit[i]) || unit[i] == '%') // If the character is a percent sign or a letter which is not an exponent 'e'
if (unit[i] == '%' || (char.IsLetter(unit[i]) && !(unit[i] == 'e' && i < unit.Length - 1 && !char.IsLetter(unit[i + 1]))))
{ {
identifierIndex = i; identifierIndex = i;
break; break;
......
...@@ -9,31 +9,20 @@ namespace Svg ...@@ -9,31 +9,20 @@ namespace Svg
[SvgElement("desc")] [SvgElement("desc")]
public class SvgDescription : SvgElement public class SvgDescription : SvgElement
{ {
private string _text; public override string ToString()
public string Text
{ {
get { return this._text; } return this.Content;
set { this._text = value; }
} }
public override string ToString() public override SvgElement DeepCopy()
{ {
return this.Text; return DeepCopy<SvgDescription>();
} }
public override SvgElement DeepCopy<T>()
public override SvgElement DeepCopy() {
{ var newObj = base.DeepCopy<T>() as SvgDescription;
return DeepCopy<SvgDescription>(); return newObj;
} }
public override SvgElement DeepCopy<T>()
{
var newObj = base.DeepCopy<T>() as SvgDescription;
newObj.Text = this.Text;
return newObj;
}
} }
} }
\ No newline at end of file
...@@ -7,17 +7,22 @@ namespace Svg ...@@ -7,17 +7,22 @@ namespace Svg
{ {
[SvgElement("title")] [SvgElement("title")]
public class SvgTitle : SvgElement public class SvgTitle : SvgElement
{ {
public override SvgElement DeepCopy() public override string ToString()
{ {
return this.Content;
}
public override SvgElement DeepCopy()
{
return DeepCopy<SvgTitle>(); return DeepCopy<SvgTitle>();
} }
public override SvgElement DeepCopy<T>() public override SvgElement DeepCopy<T>()
{ {
var newObj = base.DeepCopy<T>() as SvgTitle; var newObj = base.DeepCopy<T>() as SvgTitle;
return newObj; return newObj;
} }
} }
} }
\ No newline at end of file
...@@ -13,7 +13,7 @@ namespace Svg ...@@ -13,7 +13,7 @@ namespace Svg
{ {
private Uri _referencedElement; private Uri _referencedElement;
[SvgAttribute("xlink:href")] [SvgAttribute("href", SvgAttributeAttribute.XLinkNamespace)]
public virtual Uri ReferencedElement public virtual Uri ReferencedElement
{ {
get { return this._referencedElement; } get { return this._referencedElement; }
...@@ -49,8 +49,8 @@ namespace Svg ...@@ -49,8 +49,8 @@ namespace Svg
/// </summary> /// </summary>
public SvgUse() public SvgUse()
{ {
this.X = 0; this.X = 0;
this.Y = 0; this.Y = 0;
} }
public override System.Drawing.Drawing2D.GraphicsPath Path public override System.Drawing.Drawing2D.GraphicsPath Path
...@@ -69,16 +69,16 @@ namespace Svg ...@@ -69,16 +69,16 @@ namespace Svg
get { return new System.Drawing.RectangleF(); } get { return new System.Drawing.RectangleF(); }
} }
// public override SvgElementCollection Children // public override SvgElementCollection Children
// { // {
// get // get
// { // {
// SvgElement element = this.OwnerDocument.IdManager.GetElementById(this.ReferencedElement); // SvgElement element = this.OwnerDocument.IdManager.GetElementById(this.ReferencedElement);
// SvgElementCollection elements = new SvgElementCollection(this, true); // SvgElementCollection elements = new SvgElementCollection(this, true);
// elements.Add(element); // elements.Add(element);
// return elements; // return elements;
// } // }
// } // }
protected override void Render(SvgRenderer renderer) protected override void Render(SvgRenderer renderer)
{ {
...@@ -99,20 +99,20 @@ namespace Svg ...@@ -99,20 +99,20 @@ namespace Svg
} }
public override SvgElement DeepCopy() public override SvgElement DeepCopy()
{ {
return DeepCopy<SvgUse>(); return DeepCopy<SvgUse>();
} }
public override SvgElement DeepCopy<T>() public override SvgElement DeepCopy<T>()
{ {
var newObj = base.DeepCopy<T>() as SvgUse; var newObj = base.DeepCopy<T>() as SvgUse;
newObj.ReferencedElement = this.ReferencedElement; newObj.ReferencedElement = this.ReferencedElement;
newObj.X = this.X; newObj.X = this.X;
newObj.Y = this.Y; newObj.Y = this.Y;
return newObj; return newObj;
} }
} }
} }
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace Svg
{
public static class Extensions
{
public static IEnumerable<SvgElement> Descendants<T>(this IEnumerable<T> source) where T : SvgElement
{
if (source == null) throw new ArgumentNullException("source");
return GetDescendants<T>(source, false);
}
private static IEnumerable<SvgElement> GetAncestors<T>(IEnumerable<T> source, bool self) where T : SvgElement
{
foreach (var start in source)
{
if (start != null)
{
for (var elem = (self ? start : start.Parent) as SvgElement; elem != null; elem = (elem.Parent as SvgElement))
{
yield return elem;
}
}
}
yield break;
}
private static IEnumerable<SvgElement> GetDescendants<T>(IEnumerable<T> source, bool self) where T : SvgElement
{
var positons = new Stack<int>();
int currPos;
SvgElement currParent;
foreach (var start in source)
{
if (start != null)
{
if (self) yield return start;
positons.Push(0);
currParent = start;
while (positons.Count > 0)
{
currPos = positons.Pop();
if (currPos < currParent.Children.Count)
{
yield return currParent.Children[currPos];
currParent = currParent.Children[currPos];
positons.Push(currPos + 1);
positons.Push(0);
}
else
{
currParent = currParent.Parent;
}
}
}
}
yield break;
}
}
}
\ No newline at end of file
...@@ -14,10 +14,10 @@ namespace Svg.FilterEffects ...@@ -14,10 +14,10 @@ namespace Svg.FilterEffects
[SvgElement("feGaussianBlur")] [SvgElement("feGaussianBlur")]
public class SvgGaussianBlur : SvgFilterPrimitive public class SvgGaussianBlur : SvgFilterPrimitive
{ {
private int _stdDeviation; private float _stdDeviation;
private BlurType _blurType; private BlurType _blurType;
private int[] _kernel; private int[] _kernel;
private int _kernelSum; private int _kernelSum;
private int[,] _multable; private int[,] _multable;
...@@ -26,12 +26,13 @@ namespace Svg.FilterEffects ...@@ -26,12 +26,13 @@ namespace Svg.FilterEffects
{ {
} }
public SvgGaussianBlur(int stdDeviation) public SvgGaussianBlur(float stdDeviation)
: this(stdDeviation, BlurType.Both) : this(stdDeviation, BlurType.Both)
{ {
} }
public SvgGaussianBlur(int stdDeviation, BlurType blurType) : base() public SvgGaussianBlur(float stdDeviation, BlurType blurType)
: base()
{ {
_stdDeviation = stdDeviation; _stdDeviation = stdDeviation;
_blurType = blurType; _blurType = blurType;
...@@ -42,13 +43,13 @@ namespace Svg.FilterEffects ...@@ -42,13 +43,13 @@ namespace Svg.FilterEffects
private void PreCalculate() private void PreCalculate()
{ {
int sz = _stdDeviation * 2 + 1; int sz = (int)(_stdDeviation * 2 + 1);
_kernel = new int[sz]; _kernel = new int[sz];
_multable = new int[sz, 256]; _multable = new int[sz, 256];
for (int i = 1; i <= _stdDeviation; i++) for (int i = 1; i <= _stdDeviation; i++)
{ {
int szi = _stdDeviation - i; int szi = (int)(_stdDeviation - i);
int szj = _stdDeviation + i; int szj = (int)(_stdDeviation + i);
_kernel[szj] = _kernel[szi] = (szi + 1) * (szi + 1); _kernel[szj] = _kernel[szi] = (szi + 1) * (szi + 1);
_kernelSum += (_kernel[szj] + _kernel[szi]); _kernelSum += (_kernel[szj] + _kernel[szi]);
for (int j = 0; j < 256; j++) for (int j = 0; j < 256; j++)
...@@ -56,11 +57,11 @@ namespace Svg.FilterEffects ...@@ -56,11 +57,11 @@ namespace Svg.FilterEffects
_multable[szj, j] = _multable[szi, j] = _kernel[szj] * j; _multable[szj, j] = _multable[szi, j] = _kernel[szj] * j;
} }
} }
_kernel[_stdDeviation] = (_stdDeviation + 1) * (_stdDeviation + 1); _kernel[(int)_stdDeviation] = (int)((_stdDeviation + 1) * (_stdDeviation + 1));
_kernelSum += _kernel[_stdDeviation]; _kernelSum += _kernel[(int)_stdDeviation];
for (int j = 0; j < 256; j++) for (int j = 0; j < 256; j++)
{ {
_multable[_stdDeviation, j] = _kernel[_stdDeviation] * j; _multable[(int)_stdDeviation, j] = _kernel[(int)_stdDeviation] * j;
} }
} }
...@@ -104,7 +105,7 @@ namespace Svg.FilterEffects ...@@ -104,7 +105,7 @@ namespace Svg.FilterEffects
for (int i = 0; i < pixelCount; i++) for (int i = 0; i < pixelCount; i++)
{ {
bsum = gsum = rsum = asum = 0; bsum = gsum = rsum = asum = 0;
read = i - _stdDeviation; read = (int)(i - _stdDeviation);
for (int z = 0; z < _kernel.Length; z++) for (int z = 0; z < _kernel.Length; z++)
{ {
if (read < start) if (read < start)
...@@ -156,7 +157,7 @@ namespace Svg.FilterEffects ...@@ -156,7 +157,7 @@ namespace Svg.FilterEffects
index = 0; index = 0;
for (int i = 0; i < src.Height; i++) for (int i = 0; i < src.Height; i++)
{ {
int y = i - _stdDeviation; int y = (int)(i - _stdDeviation);
start = y * src.Width; start = y * src.Width;
for (int j = 0; j < src.Width; j++) for (int j = 0; j < src.Width; j++)
{ {
...@@ -219,16 +220,16 @@ namespace Svg.FilterEffects ...@@ -219,16 +220,16 @@ namespace Svg.FilterEffects
} }
} }
/// <summary> /// <summary>
/// Gets or sets the radius of the blur (only allows for one value - not the two specified in the SVG Spec) /// Gets or sets the radius of the blur (only allows for one value - not the two specified in the SVG Spec)
/// </summary> /// </summary>
[SvgAttribute("stdDeviation")] [SvgAttribute("stdDeviation")]
public int StdDeviation public float StdDeviation
{ {
get { return _stdDeviation; } get { return _stdDeviation; }
set set
{ {
if (value < 1) if (value <= 0)
{ {
throw new InvalidOperationException("Radius must be greater then 0"); throw new InvalidOperationException("Radius must be greater then 0");
} }
...@@ -248,27 +249,27 @@ namespace Svg.FilterEffects ...@@ -248,27 +249,27 @@ namespace Svg.FilterEffects
} }
public override Bitmap Process()
{
//Todo
return null; public override Bitmap Process()
} {
//Todo
return null;
}
public override SvgElement DeepCopy() public override SvgElement DeepCopy()
{ {
return DeepCopy<SvgGaussianBlur>(); return DeepCopy<SvgGaussianBlur>();
} }
public override SvgElement DeepCopy<T>() public override SvgElement DeepCopy<T>()
{ {
var newObj = base.DeepCopy<T>() as SvgGaussianBlur; var newObj = base.DeepCopy<T>() as SvgGaussianBlur;
newObj.StdDeviation = this.StdDeviation; newObj.StdDeviation = this.StdDeviation;
newObj.BlurType = this.BlurType; newObj.BlurType = this.BlurType;
return newObj; return newObj;
} }
} }
} }
\ No newline at end of file
...@@ -5,7 +5,6 @@ using System.Globalization; ...@@ -5,7 +5,6 @@ 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
{ {
...@@ -120,4 +119,77 @@ namespace Svg ...@@ -120,4 +119,77 @@ namespace Svg
public sealed class SvgMarkerUnitsConverter : EnumBaseConverter<SvgMarkerUnits> public sealed class SvgMarkerUnitsConverter : EnumBaseConverter<SvgMarkerUnits>
{ {
} }
public sealed class SvgFontVariantConverter : EnumBaseConverter<SvgFontVariant>
{
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value == "small-caps") return SvgFontVariant.smallcaps;
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string) && value is SvgFontVariant && (SvgFontVariant)value == SvgFontVariant.smallcaps)
{
return "small-caps";
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
public sealed class SvgFontWeightConverter : EnumBaseConverter<SvgFontWeight>
{
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string)
{
switch ((string)value)
{
case "100": return SvgFontWeight.w100;
case "200": return SvgFontWeight.w200;
case "300": return SvgFontWeight.w300;
case "400": return SvgFontWeight.w400;
case "500": return SvgFontWeight.w500;
case "600": return SvgFontWeight.w600;
case "700": return SvgFontWeight.w700;
case "800": return SvgFontWeight.w800;
case "900": return SvgFontWeight.w900;
}
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string) && value is SvgFontWeight)
{
switch ((SvgFontWeight)value)
{
case SvgFontWeight.w100: return "100";
case SvgFontWeight.w200: return "200";
case SvgFontWeight.w300: return "300";
case SvgFontWeight.w400: return "400";
case SvgFontWeight.w500: return "500";
case SvgFontWeight.w600: return "600";
case SvgFontWeight.w700: return "700";
case SvgFontWeight.w800: return "800";
case SvgFontWeight.w900: return "900";
}
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
public static class Enums
{
public static bool TryParse<TEnum>(string value, out TEnum result) where TEnum : struct, IConvertible
{
var retValue = value == null ?
false :
Enum.IsDefined(typeof(TEnum), value);
result = retValue ?
(TEnum)Enum.Parse(typeof(TEnum), value) :
default(TEnum);
return retValue;
}
}
} }
...@@ -57,9 +57,9 @@ namespace Svg ...@@ -57,9 +57,9 @@ namespace Svg
{ {
alphastring = "0" + alphastring; alphastring = "0" + alphastring;
} }
var alphaDecimal = decimal.Parse(alphastring); var alphaDecimal = decimal.Parse(alphastring);
if(alphaDecimal <= 1) if(alphaDecimal <= 1)
{ {
alphaValue = (int)(alphaDecimal * 255); alphaValue = (int)(alphaDecimal * 255);
...@@ -69,7 +69,18 @@ namespace Svg ...@@ -69,7 +69,18 @@ namespace Svg
alphaValue = (int)alphaDecimal; alphaValue = (int)alphaDecimal;
} }
} }
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;
} }
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Svg
{
/// <summary>
/// A wrapper for a paint server which isn't defined currently in the parse process, but
/// should be defined by the time the image needs to render.
/// </summary>
public class SvgDeferredPaintServer : SvgPaintServer
{
private bool _serverLoaded = false;
private SvgPaintServer _concreteServer;
public SvgDocument Document { get; set; }
public string DeferredId { get; set; }
public SvgDeferredPaintServer() { }
public SvgDeferredPaintServer(SvgDocument document, string id)
{
this.Document = document;
this.DeferredId = id;
}
private void EnsureServer()
{
if (!_serverLoaded)
{
_concreteServer = this.Document.IdManager.GetElementById(this.DeferredId) as SvgPaintServer;
_serverLoaded = true;
}
}
public override System.Drawing.Brush GetBrush(SvgVisualElement styleOwner, float opacity)
{
EnsureServer();
return _concreteServer.GetBrush(styleOwner, opacity);
}
public override SvgElement DeepCopy()
{
return DeepCopy<SvgDeferredPaintServer>();
}
public override SvgElement DeepCopy<T>()
{
var newObj = base.DeepCopy<T>() as SvgDeferredPaintServer;
newObj.Document = this.Document;
newObj.DeferredId = this.DeferredId;
return newObj;
}
public override bool Equals(object obj)
{
var other = obj as SvgDeferredPaintServer;
if (other == null)
return false;
return this.Document == other.Document && this.DeferredId == other.DeferredId;
}
public override int GetHashCode()
{
if (this.Document == null || this.DeferredId == null) return 0;
return this.Document.GetHashCode() ^ this.DeferredId.GetHashCode();
}
public override string ToString()
{
return (_serverLoaded ? _serverLoaded.ToString() : string.Format("deferred: {0}", this.DeferredId));
}
public static T TryGet<T>(SvgPaintServer server) where T : SvgPaintServer
{
var deferred = server as SvgDeferredPaintServer;
if (deferred == null)
{
return server as T;
}
else
{
return deferred._concreteServer as T;
}
}
}
}
\ No newline at end of file
...@@ -13,7 +13,7 @@ namespace Svg ...@@ -13,7 +13,7 @@ namespace Svg
{ {
private SvgCoordinateUnits _gradientUnits; private SvgCoordinateUnits _gradientUnits;
private SvgGradientSpreadMethod _spreadMethod; private SvgGradientSpreadMethod _spreadMethod;
private SvgGradientServer _inheritGradient; private SvgPaintServer _inheritGradient;
private List<SvgGradientStop> _stops; private List<SvgGradientStop> _stops;
/// <summary> /// <summary>
...@@ -89,13 +89,12 @@ namespace Svg ...@@ -89,13 +89,12 @@ namespace Svg
/// Gets or sets another gradient fill from which to inherit the stops from. /// Gets or sets another gradient fill from which to inherit the stops from.
/// </summary> /// </summary>
[SvgAttribute("href")] [SvgAttribute("href")]
public SvgGradientServer InheritGradient public SvgPaintServer InheritGradient
{ {
get { return this._inheritGradient; } get { return this._inheritGradient; }
set set
{ {
this._inheritGradient = value; this._inheritGradient = value;
this.InheritStops();
} }
} }
...@@ -220,14 +219,12 @@ namespace Svg ...@@ -220,14 +219,12 @@ namespace Svg
return blend; return blend;
} }
/// <summary> protected void LoadStops()
// If this gradient contains no stops then it will search any inherited gradients for stops.
/// </summary>
protected virtual void InheritStops()
{ {
if (this.Stops.Count == 0 && this.InheritGradient != null) var core = SvgDeferredPaintServer.TryGet<SvgGradientServer>(_inheritGradient);
if (this.Stops.Count == 0 && core != null)
{ {
_stops.AddRange(this.InheritGradient.Stops); _stops.AddRange(core.Stops);
} }
} }
......
...@@ -81,6 +81,7 @@ namespace Svg ...@@ -81,6 +81,7 @@ namespace Svg
public override Brush GetBrush(SvgVisualElement renderingElement, float opacity) public override Brush GetBrush(SvgVisualElement renderingElement, float opacity)
{ {
LoadStops();
if (IsInvalid) if (IsInvalid)
{ {
return null; return null;
...@@ -97,8 +98,8 @@ namespace Svg ...@@ -97,8 +98,8 @@ namespace Svg
if (NeedToExpandGradient(renderingElement, specifiedStart, specifiedEnd)) if (NeedToExpandGradient(renderingElement, specifiedStart, specifiedEnd))
{ {
var expansion = ExpandGradient(renderingElement, specifiedStart, specifiedEnd); var expansion = ExpandGradient(renderingElement, specifiedStart, specifiedEnd);
effectiveStart = expansion.Item1; effectiveStart = expansion.StartPoint;
effectiveEnd = expansion.Item2; effectiveEnd = expansion.EndPoint;
} }
return new LinearGradientBrush(effectiveStart, effectiveEnd, Color.Transparent, Color.Transparent) return new LinearGradientBrush(effectiveStart, effectiveEnd, Color.Transparent, Color.Transparent)
...@@ -123,12 +124,24 @@ namespace Svg ...@@ -123,12 +124,24 @@ namespace Svg
return SpreadMethod == SvgGradientSpreadMethod.Pad && (boundable.Bounds.Contains(specifiedStart) || boundable.Bounds.Contains(specifiedEnd)); return SpreadMethod == SvgGradientSpreadMethod.Pad && (boundable.Bounds.Contains(specifiedStart) || boundable.Bounds.Contains(specifiedEnd));
} }
private Tuple<PointF, PointF> ExpandGradient(ISvgBoundable boundable, PointF specifiedStart, PointF specifiedEnd) public struct GradientPoints
{
public PointF StartPoint;
public PointF EndPoint;
public GradientPoints(PointF startPoint, PointF endPoint)
{
this.StartPoint = startPoint;
this.EndPoint = endPoint;
}
}
private GradientPoints ExpandGradient(ISvgBoundable boundable, PointF specifiedStart, PointF specifiedEnd)
{ {
if (!NeedToExpandGradient(boundable, specifiedStart, specifiedEnd)) if (!NeedToExpandGradient(boundable, specifiedStart, specifiedEnd))
{ {
Debug.Fail("Unexpectedly expanding gradient when not needed!"); Debug.Fail("Unexpectedly expanding gradient when not needed!");
return new Tuple<PointF, PointF>(specifiedStart, specifiedEnd); return new GradientPoints(specifiedStart, specifiedEnd);
} }
var specifiedLength = CalculateDistance(specifiedStart, specifiedEnd); var specifiedLength = CalculateDistance(specifiedStart, specifiedEnd);
...@@ -158,7 +171,7 @@ namespace Svg ...@@ -158,7 +171,7 @@ namespace Svg
effectiveEnd = MovePointAlongVector(effectiveEnd, specifiedUnitVector, 1); effectiveEnd = MovePointAlongVector(effectiveEnd, specifiedUnitVector, 1);
} }
return new Tuple<PointF, PointF>(effectiveStart, effectiveEnd); return new GradientPoints(effectiveStart, effectiveEnd);
} }
private ColorBlend CalculateColorBlend(SvgVisualElement owner, float opacity, PointF specifiedStart, PointF effectiveStart, PointF specifiedEnd, PointF effectiveEnd) private ColorBlend CalculateColorBlend(SvgVisualElement owner, float opacity, PointF specifiedStart, PointF effectiveStart, PointF specifiedEnd, PointF effectiveEnd)
...@@ -180,11 +193,11 @@ namespace Svg ...@@ -180,11 +193,11 @@ namespace Svg
for (var i = 0; i < colorBlend.Positions.Length; i++) for (var i = 0; i < colorBlend.Positions.Length; i++)
{ {
var originalPoint = MovePointAlongVector(specifiedStart, specifiedUnitVector, (float) specifiedLength * colorBlend.Positions[i]); var originalPoint = MovePointAlongVector(specifiedStart, specifiedUnitVector, (float)specifiedLength * colorBlend.Positions[i]);
var distanceFromEffectiveStart = CalculateDistance(effectiveStart, originalPoint); var distanceFromEffectiveStart = CalculateDistance(effectiveStart, originalPoint);
colorBlend.Positions[i] = (float) Math.Max(0F, Math.Min((distanceFromEffectiveStart / effectiveLength), 1.0F)); colorBlend.Positions[i] = (float)Math.Round(Math.Max(0F, Math.Min((distanceFromEffectiveStart / effectiveLength), 1.0F)), 5);
} }
if (startDelta > 0) if (startDelta > 0)
...@@ -240,7 +253,7 @@ namespace Svg ...@@ -240,7 +253,7 @@ namespace Svg
private float Y1 private float Y1
{ {
get; get;
set; set;
} }
......
...@@ -38,7 +38,18 @@ namespace Svg ...@@ -38,7 +38,18 @@ namespace Svg
{ {
return (SvgPaintServer)document.IdManager.GetElementById(value); return (SvgPaintServer)document.IdManager.GetElementById(value);
} }
else // Otherwise try and parse as colour else if (value.StartsWith("#")) // Otherwise try and parse as colour
{
try
{
return new SvgColourServer((Color)_colourConverter.ConvertFrom(value.Trim()));
}
catch
{
return new SvgDeferredPaintServer(document, value);
}
}
else
{ {
return new SvgColourServer((Color)_colourConverter.ConvertFrom(value.Trim())); return new SvgColourServer((Color)_colourConverter.ConvertFrom(value.Trim()));
} }
...@@ -49,7 +60,7 @@ namespace Svg ...@@ -49,7 +60,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);
...@@ -105,4 +116,4 @@ namespace Svg ...@@ -105,4 +116,4 @@ namespace Svg
return base.ConvertTo(context, culture, value, destinationType); return base.ConvertTo(context, culture, value, destinationType);
} }
} }
} }
\ No newline at end of file
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