Commit 7c70bd11 authored by Eric Domke's avatar Eric Domke
Browse files

Text on a Path & SVG Fonts

- Extraction interface for SvgRenderer
- Initial support for Text on a Path
- Initial support for Svg Fonts
- Support for symbol element
- Minor bug fixes with image pattern rendering
- Additional support for Text whitespace modes
parent 1a00f391
...@@ -98,7 +98,7 @@ namespace Svg ...@@ -98,7 +98,7 @@ namespace Svg
/// <summary> /// <summary>
/// Gets the <see cref="GraphicsPath"/> representing this element. /// Gets the <see cref="GraphicsPath"/> representing this element.
/// </summary> /// </summary>
public override GraphicsPath Path(SvgRenderer renderer) public override GraphicsPath Path(ISvgRenderer renderer)
{ {
if (this._path == null || this.IsPathDirty) if (this._path == null || this.IsPathDirty)
{ {
...@@ -117,7 +117,7 @@ namespace Svg ...@@ -117,7 +117,7 @@ namespace Svg
/// Renders the circle to the specified <see cref="Graphics"/> object. /// Renders the circle to the specified <see cref="Graphics"/> object.
/// </summary> /// </summary>
/// <param name="graphics">The graphics object.</param> /// <param name="graphics">The graphics object.</param>
protected override void Render(SvgRenderer renderer) protected override void Render(ISvgRenderer renderer)
{ {
// Don't draw if there is no radius set // Don't draw if there is no radius set
if (this.Radius.Value > 0.0f) if (this.Radius.Value > 0.0f)
......
...@@ -102,7 +102,7 @@ namespace Svg ...@@ -102,7 +102,7 @@ namespace Svg
/// Gets the <see cref="GraphicsPath"/> for this element. /// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary> /// </summary>
/// <value></value> /// <value></value>
public override GraphicsPath Path(SvgRenderer renderer) public override GraphicsPath Path(ISvgRenderer renderer)
{ {
if (this._path == null || this.IsPathDirty) if (this._path == null || this.IsPathDirty)
{ {
...@@ -122,7 +122,7 @@ namespace Svg ...@@ -122,7 +122,7 @@ namespace Svg
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object. /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object.
/// </summary> /// </summary>
/// <param name="graphics">The <see cref="Graphics"/> object to render to.</param> /// <param name="graphics">The <see cref="Graphics"/> object to render to.</param>
protected override void Render(SvgRenderer renderer) protected override void Render(ISvgRenderer renderer)
{ {
if (this._radiusX.Value > 0.0f && this._radiusY.Value > 0.0f) if (this._radiusX.Value > 0.0f && this._radiusY.Value > 0.0f)
{ {
......
...@@ -94,7 +94,7 @@ namespace Svg ...@@ -94,7 +94,7 @@ namespace Svg
/// <summary> /// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element. /// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary> /// </summary>
public override GraphicsPath Path(SvgRenderer renderer) public override GraphicsPath Path(ISvgRenderer renderer)
{ {
return null; return null;
} }
...@@ -102,7 +102,7 @@ namespace Svg ...@@ -102,7 +102,7 @@ namespace Svg
/// <summary> /// <summary>
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object. /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object.
/// </summary> /// </summary>
protected override void Render(SvgRenderer renderer) protected override void Render(ISvgRenderer renderer)
{ {
if (!Visible || !Displayable) if (!Visible || !Displayable)
return; return;
...@@ -120,7 +120,7 @@ namespace Svg ...@@ -120,7 +120,7 @@ namespace Svg
RectangleF destRect = destClip; RectangleF destRect = destClip;
this.PushTransforms(renderer); this.PushTransforms(renderer);
renderer.AddClip(new Region(destClip)); renderer.SetClip(new Region(destClip), CombineMode.Intersect);
this.SetClip(renderer); this.SetClip(renderer);
if (AspectRatio != null && AspectRatio.Align != SvgPreserveAspectRatio.none) if (AspectRatio != null && AspectRatio.Align != SvgPreserveAspectRatio.none)
...@@ -223,6 +223,7 @@ namespace Svg ...@@ -223,6 +223,7 @@ namespace Svg
if (uri.LocalPath.EndsWith(".svg", StringComparison.InvariantCultureIgnoreCase)) if (uri.LocalPath.EndsWith(".svg", StringComparison.InvariantCultureIgnoreCase))
{ {
var doc = SvgDocument.Open<SvgDocument>(ms); var doc = SvgDocument.Open<SvgDocument>(ms);
doc.BaseUri = uri;
return doc.Draw(); return doc.Draw();
} }
else else
......
...@@ -92,7 +92,7 @@ namespace Svg ...@@ -92,7 +92,7 @@ namespace Svg
{ {
} }
public override System.Drawing.Drawing2D.GraphicsPath Path(SvgRenderer renderer) public override System.Drawing.Drawing2D.GraphicsPath Path(ISvgRenderer renderer)
{ {
if (this._path == null || this.IsPathDirty) if (this._path == null || this.IsPathDirty)
{ {
......
...@@ -32,7 +32,7 @@ namespace Svg ...@@ -32,7 +32,7 @@ namespace Svg
get { return true; } get { return true; }
} }
public override GraphicsPath Path(SvgRenderer renderer) public override GraphicsPath Path(ISvgRenderer renderer)
{ {
if (this._path == null || this.IsPathDirty) if (this._path == null || this.IsPathDirty)
{ {
......
...@@ -14,7 +14,7 @@ namespace Svg ...@@ -14,7 +14,7 @@ namespace Svg
public class SvgPolyline : SvgPolygon public class SvgPolyline : SvgPolygon
{ {
private GraphicsPath _Path; private GraphicsPath _Path;
public override GraphicsPath Path(SvgRenderer renderer) public override GraphicsPath Path(ISvgRenderer renderer)
{ {
if (_Path == null || this.IsPathDirty) if (_Path == null || this.IsPathDirty)
{ {
......
...@@ -174,7 +174,7 @@ namespace Svg ...@@ -174,7 +174,7 @@ namespace Svg
/// <summary> /// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element. /// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary> /// </summary>
public override GraphicsPath Path(SvgRenderer renderer) public override GraphicsPath Path(ISvgRenderer renderer)
{ {
if (_path == null || IsPathDirty) if (_path == null || IsPathDirty)
{ {
...@@ -261,7 +261,7 @@ namespace Svg ...@@ -261,7 +261,7 @@ namespace Svg
/// <summary> /// <summary>
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object. /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object.
/// </summary> /// </summary>
protected override void Render(SvgRenderer renderer) protected override void Render(ISvgRenderer renderer)
{ {
if (Width.Value > 0.0f && Height.Value > 0.0f) if (Width.Value > 0.0f && Height.Value > 0.0f)
{ {
......
using System; using System;
using System.Drawing; using System.Drawing;
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
using System.Diagnostics;
namespace Svg namespace Svg
{ {
...@@ -16,7 +17,7 @@ namespace Svg ...@@ -16,7 +17,7 @@ namespace Svg
/// <summary> /// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element. /// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary> /// </summary>
public abstract GraphicsPath Path(SvgRenderer renderer); public abstract GraphicsPath Path(ISvgRenderer renderer);
PointF ISvgBoundable.Location PointF ISvgBoundable.Location
{ {
...@@ -104,13 +105,13 @@ namespace Svg ...@@ -104,13 +105,13 @@ namespace Svg
/// <summary> /// <summary>
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object. /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object.
/// </summary> /// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> object to render to.</param> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param>
protected override void Render(SvgRenderer renderer) protected override void Render(ISvgRenderer renderer)
{ {
this.Render(renderer, true); this.Render(renderer, true);
} }
private void Render(SvgRenderer renderer, bool renderFilter) private void Render(ISvgRenderer renderer, bool renderFilter)
{ {
if (this.Visible && this.Displayable && this.PushTransforms(renderer) && if (this.Visible && this.Displayable && this.PushTransforms(renderer) &&
(!Renderable || this.Path(renderer) != null)) (!Renderable || this.Path(renderer) != null))
...@@ -119,11 +120,20 @@ namespace Svg ...@@ -119,11 +120,20 @@ namespace Svg
if (renderFilter && this.Filter != null) if (renderFilter && this.Filter != null)
{ {
var filter = this.OwnerDocument.IdManager.GetElementById(this.Filter) as FilterEffects.SvgFilter; var filterPath = this.Filter;
if (filterPath.ToString().StartsWith("url("))
{
filterPath = new Uri(filterPath.ToString().Substring(4, filterPath.ToString().Length - 5), UriKind.RelativeOrAbsolute);
}
var filter = this.OwnerDocument.IdManager.GetElementById(filterPath) as FilterEffects.SvgFilter;
if (filter != null) if (filter != null)
{ {
this.PopTransforms(renderer); this.PopTransforms(renderer);
try
{
filter.ApplyFilter(this, renderer, (r) => this.Render(r, false)); filter.ApplyFilter(this, renderer, (r) => this.Render(r, false));
}
catch (Exception ex) { Debug.Print(ex.ToString()); }
renderNormal = false; renderNormal = false;
} }
} }
...@@ -163,10 +173,10 @@ namespace Svg ...@@ -163,10 +173,10 @@ namespace Svg
} }
/// <summary> /// <summary>
/// Renders the fill of the <see cref="SvgVisualElement"/> to the specified <see cref="SvgRenderer"/> /// Renders the fill of the <see cref="SvgVisualElement"/> to the specified <see cref="ISvgRenderer"/>
/// </summary> /// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> object to render to.</param> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param>
protected internal virtual void RenderFill(SvgRenderer renderer) protected internal virtual void RenderFill(ISvgRenderer renderer)
{ {
if (this.Fill != null) if (this.Fill != null)
{ {
...@@ -182,12 +192,12 @@ namespace Svg ...@@ -182,12 +192,12 @@ namespace Svg
} }
/// <summary> /// <summary>
/// Renders the stroke of the <see cref="SvgVisualElement"/> to the specified <see cref="SvgRenderer"/> /// Renders the stroke of the <see cref="SvgVisualElement"/> to the specified <see cref="ISvgRenderer"/>
/// </summary> /// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> object to render to.</param> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param>
protected internal virtual void RenderStroke(SvgRenderer renderer) protected internal virtual void RenderStroke(ISvgRenderer renderer)
{ {
if (this.Stroke != null) if (this.Stroke != null && this.Stroke != SvgColourServer.None)
{ {
float strokeWidth = this.StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this); float strokeWidth = this.StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this);
using (var pen = new Pen(this.Stroke.GetBrush(this, renderer, Math.Min(Math.Max(this.StrokeOpacity * this.Opacity, 0), 1)), strokeWidth)) using (var pen = new Pen(this.Stroke.GetBrush(this, renderer, Math.Min(Math.Max(this.StrokeOpacity * this.Opacity, 0), 1)), strokeWidth))
...@@ -204,50 +214,50 @@ namespace Svg ...@@ -204,50 +214,50 @@ namespace Svg
} }
/// <summary> /// <summary>
/// Sets the clipping region of the specified <see cref="SvgRenderer"/>. /// Sets the clipping region of the specified <see cref="ISvgRenderer"/>.
/// </summary> /// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> to have its clipping region set.</param> /// <param name="renderer">The <see cref="ISvgRenderer"/> to have its clipping region set.</param>
protected internal virtual void SetClip(SvgRenderer renderer) protected internal virtual void SetClip(ISvgRenderer renderer)
{ {
if (this.ClipPath != null) if (this.ClipPath != null)
{ {
SvgClipPath clipPath = this.OwnerDocument.GetElementById<SvgClipPath>(this.ClipPath.ToString()); SvgClipPath clipPath = this.OwnerDocument.GetElementById<SvgClipPath>(this.ClipPath.ToString());
this._previousClip = renderer.Clip; this._previousClip = renderer.GetClip();
if (clipPath != null) if (clipPath != null)
{ {
renderer.AddClip(clipPath.GetClipRegion(this)); renderer.SetClip(clipPath.GetClipRegion(this), CombineMode.Intersect);
} }
} }
} }
/// <summary> /// <summary>
/// Resets the clipping region of the specified <see cref="SvgRenderer"/> back to where it was before the <see cref="SetClip"/> method was called. /// Resets the clipping region of the specified <see cref="ISvgRenderer"/> back to where it was before the <see cref="SetClip"/> method was called.
/// </summary> /// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> to have its clipping region reset.</param> /// <param name="renderer">The <see cref="ISvgRenderer"/> to have its clipping region reset.</param>
protected internal virtual void ResetClip(SvgRenderer renderer) protected internal virtual void ResetClip(ISvgRenderer renderer)
{ {
if (this._previousClip != null) if (this._previousClip != null)
{ {
renderer.Clip = this._previousClip; renderer.SetClip(this._previousClip);
this._previousClip = null; this._previousClip = null;
} }
} }
/// <summary> /// <summary>
/// Sets the clipping region of the specified <see cref="SvgRenderer"/>. /// Sets the clipping region of the specified <see cref="ISvgRenderer"/>.
/// </summary> /// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> to have its clipping region set.</param> /// <param name="renderer">The <see cref="ISvgRenderer"/> to have its clipping region set.</param>
void ISvgClipable.SetClip(SvgRenderer renderer) void ISvgClipable.SetClip(ISvgRenderer renderer)
{ {
this.SetClip(renderer); this.SetClip(renderer);
} }
/// <summary> /// <summary>
/// Resets the clipping region of the specified <see cref="SvgRenderer"/> back to where it was before the <see cref="SetClip"/> method was called. /// Resets the clipping region of the specified <see cref="ISvgRenderer"/> back to where it was before the <see cref="SetClip"/> method was called.
/// </summary> /// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> to have its clipping region reset.</param> /// <param name="renderer">The <see cref="ISvgRenderer"/> to have its clipping region reset.</param>
void ISvgClipable.ResetClip(SvgRenderer renderer) void ISvgClipable.ResetClip(ISvgRenderer renderer)
{ {
this.ResetClip(renderer); this.ResetClip(renderer);
} }
......
...@@ -187,7 +187,7 @@ namespace Svg ...@@ -187,7 +187,7 @@ namespace Svg
} }
/// <summary> /// <summary>
/// Refers to the boldness of the font. /// Refers to the style of the font.
/// </summary> /// </summary>
[SvgAttribute("font-style")] [SvgAttribute("font-style")]
public virtual SvgFontStyle FontStyle public virtual SvgFontStyle FontStyle
...@@ -197,7 +197,7 @@ namespace Svg ...@@ -197,7 +197,7 @@ namespace Svg
} }
/// <summary> /// <summary>
/// Refers to the boldness of the font. /// Refers to the varient of the font.
/// </summary> /// </summary>
[SvgAttribute("font-variant")] [SvgAttribute("font-variant")]
public virtual SvgFontVariant FontVariant public virtual SvgFontVariant FontVariant
...@@ -323,7 +323,7 @@ namespace Svg ...@@ -323,7 +323,7 @@ namespace Svg
/// Get the font information based on data stored with the text object or inherited from the parent. /// Get the font information based on data stored with the text object or inherited from the parent.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
internal System.Drawing.Font GetFont(SvgRenderer renderer) internal IFontDefn GetFont(ISvgRenderer renderer)
{ {
// Get the font-size // Get the font-size
float fontSize; float fontSize;
...@@ -337,6 +337,11 @@ namespace Svg ...@@ -337,6 +337,11 @@ namespace Svg
fontSize = fontSizeUnit.ToDeviceValue(renderer, UnitRenderingType.Vertical, this); fontSize = fontSizeUnit.ToDeviceValue(renderer, UnitRenderingType.Vertical, this);
} }
var family = ValidateFontFamily(this.FontFamily, this.OwnerDocument);
var sFaces = family as IEnumerable<SvgFontFace>;
if (sFaces == null)
{
var fontStyle = System.Drawing.FontStyle.Regular; var fontStyle = System.Drawing.FontStyle.Regular;
// Get the font-weight // Get the font-weight
...@@ -372,27 +377,41 @@ namespace Svg ...@@ -372,27 +377,41 @@ namespace Svg
break; break;
} }
var family = ValidateFontFamily(this.FontFamily); var ff = family as FontFamily;
if (!family.IsStyleAvailable(fontStyle)) if (!ff.IsStyleAvailable(fontStyle))
{ {
// Do Something // Do Something
} }
// Get the font-family // Get the font-family
return new System.Drawing.Font(family, fontSize, fontStyle, System.Drawing.GraphicsUnit.Pixel); return new GdiFontDefn(new System.Drawing.Font(ff, fontSize, fontStyle, System.Drawing.GraphicsUnit.Pixel));
}
else
{
var font = sFaces.First().Parent as SvgFont;
if (font == null)
{
var uri = sFaces.First().Descendants().OfType<SvgFontFaceUri>().First().ReferencedElement;
font = OwnerDocument.IdManager.GetElementById(uri) as SvgFont;
}
return new SvgFontDefn(font, fontSize, OwnerDocument.Ppi);
}
} }
private static FontFamily ValidateFontFamily(string fontFamilyList) public static object ValidateFontFamily(string fontFamilyList, SvgDocument doc)
{ {
// Split font family list on "," and then trim start and end spaces and quotes. // Split font family list on "," and then trim start and end spaces and quotes.
var fontParts = (fontFamilyList ?? "").Split(new[] { ',' }).Select(fontName => fontName.Trim(new[] { '"', ' ', '\'' })); var fontParts = (fontFamilyList ?? "").Split(new[] { ',' }).Select(fontName => fontName.Trim(new[] { '"', ' ', '\'' }));
var families = System.Drawing.FontFamily.Families; var families = System.Drawing.FontFamily.Families;
FontFamily family; FontFamily family;
IEnumerable<SvgFontFace> sFaces;
// Find a the first font that exists in the list of installed font families. // Find a the first font that exists in the list of installed font families.
//styles from IE get sent through as lowercase. //styles from IE get sent through as lowercase.
foreach (var f in fontParts) foreach (var f in fontParts)
{ {
if (doc.FontDefns().TryGetValue(f, out sFaces)) return sFaces;
family = families.FirstOrDefault(ff => ff.Name.ToLower() == f.ToLower()); family = families.FirstOrDefault(ff => ff.Name.ToLower() == f.ToLower());
if (family != null) return family; if (family != null) return family;
......
...@@ -20,14 +20,14 @@ namespace Svg ...@@ -20,14 +20,14 @@ namespace Svg
/// </summary> /// </summary>
SvgClipRule ClipRule { get; set; } SvgClipRule ClipRule { get; set; }
/// <summary> /// <summary>
/// Sets the clipping region of the specified <see cref="SvgRenderer"/>. /// Sets the clipping region of the specified <see cref="ISvgRenderer"/>.
/// </summary> /// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> to have its clipping region set.</param> /// <param name="renderer">The <see cref="ISvgRenderer"/> to have its clipping region set.</param>
void SetClip(SvgRenderer renderer); void SetClip(ISvgRenderer renderer);
/// <summary> /// <summary>
/// Resets the clipping region of the specified <see cref="SvgRenderer"/> back to where it was before the <see cref="SetClip"/> method was called. /// Resets the clipping region of the specified <see cref="ISvgRenderer"/> back to where it was before the <see cref="SetClip"/> method was called.
/// </summary> /// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> to have its clipping region reset.</param> /// <param name="renderer">The <see cref="ISvgRenderer"/> to have its clipping region reset.</param>
void ResetClip(SvgRenderer renderer); void ResetClip(ISvgRenderer renderer);
} }
} }
\ No newline at end of file
...@@ -75,7 +75,7 @@ namespace Svg ...@@ -75,7 +75,7 @@ namespace Svg
} }
} }
path.AddPath(childPath, false); if (childPath.PointCount > 0) path.AddPath(childPath, false);
} }
foreach (SvgElement child in element.Children) foreach (SvgElement child in element.Children)
...@@ -108,10 +108,10 @@ namespace Svg ...@@ -108,10 +108,10 @@ namespace Svg
} }
/// <summary> /// <summary>
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="SvgRenderer"/> object. /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="ISvgRenderer"/> object.
/// </summary> /// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> object to render to.</param> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param>
protected override void Render(SvgRenderer renderer) protected override void Render(ISvgRenderer renderer)
{ {
// Do nothing // Do nothing
} }
......
...@@ -23,7 +23,7 @@ namespace Svg ...@@ -23,7 +23,7 @@ namespace Svg
set { this.y = value; } set { this.y = value; }
} }
public PointF ToDeviceValue(SvgRenderer renderer, SvgElement owner) public PointF ToDeviceValue(ISvgRenderer renderer, SvgElement owner)
{ {
return SvgUnit.GetDevicePoint(this.X, this.Y, renderer, owner); return SvgUnit.GetDevicePoint(this.X, this.Y, renderer, owner);
} }
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Svg
{
public enum SvgTextLengthAdjust
{
spacing,
spacingAndGlyphs
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Svg
{
public enum SvgTextPathMethod
{
align,
stretch
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Svg
{
public enum SvgTextPathSpacing
{
exact,
auto
}
}
...@@ -64,7 +64,7 @@ namespace Svg ...@@ -64,7 +64,7 @@ namespace Svg
/// </summary> /// </summary>
/// <param name="boundable">The container element used as the basis for calculations</param> /// <param name="boundable">The container element used as the basis for calculations</param>
/// <returns>The representation of the current unit in a device value (usually pixels).</returns> /// <returns>The representation of the current unit in a device value (usually pixels).</returns>
public float ToDeviceValue(SvgRenderer renderer, UnitRenderingType renderType, SvgElement owner) public float ToDeviceValue(ISvgRenderer renderer, UnitRenderingType renderType, SvgElement owner)
{ {
// If it's already been calculated // If it's already been calculated
if (this._deviceValue.HasValue) if (this._deviceValue.HasValue)
...@@ -107,7 +107,7 @@ namespace Svg ...@@ -107,7 +107,7 @@ namespace Svg
} }
float points; float points;
Font currFont; IFontDefn currFont;
switch (type) switch (type)
{ {
...@@ -158,7 +158,7 @@ namespace Svg ...@@ -158,7 +158,7 @@ namespace Svg
break; break;
case SvgUnitType.Percentage: case SvgUnitType.Percentage:
// Can't calculate if there is no style owner // Can't calculate if there is no style owner
var boundable = (renderer == null ? (owner == null ? null : owner.OwnerDocument) : renderer.Boundable()); var boundable = (renderer == null ? (owner == null ? null : owner.OwnerDocument) : renderer.GetBoundable());
if (boundable == null) if (boundable == null)
{ {
_deviceValue = value; _deviceValue = value;
...@@ -193,7 +193,7 @@ namespace Svg ...@@ -193,7 +193,7 @@ namespace Svg
return this._deviceValue.Value; return this._deviceValue.Value;
} }
private Font GetFont(SvgRenderer renderer, SvgElement owner) private IFontDefn GetFont(ISvgRenderer renderer, SvgElement owner)
{ {
if (owner == null) return null; if (owner == null) return null;
...@@ -335,18 +335,18 @@ namespace Svg ...@@ -335,18 +335,18 @@ namespace Svg
this._deviceValue = null; this._deviceValue = null;
} }
public static System.Drawing.PointF GetDevicePoint(SvgUnit x, SvgUnit y, SvgRenderer renderer, SvgElement owner) public static System.Drawing.PointF GetDevicePoint(SvgUnit x, SvgUnit y, ISvgRenderer renderer, SvgElement owner)
{ {
return new System.Drawing.PointF(x.ToDeviceValue(renderer, UnitRenderingType.Horizontal, owner), return new System.Drawing.PointF(x.ToDeviceValue(renderer, UnitRenderingType.Horizontal, owner),
y.ToDeviceValue(renderer, UnitRenderingType.Vertical, owner)); y.ToDeviceValue(renderer, UnitRenderingType.Vertical, owner));
} }
public static System.Drawing.PointF GetDevicePointOffset(SvgUnit x, SvgUnit y, SvgRenderer renderer, SvgElement owner) public static System.Drawing.PointF GetDevicePointOffset(SvgUnit x, SvgUnit y, ISvgRenderer renderer, SvgElement owner)
{ {
return new System.Drawing.PointF(x.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, owner), return new System.Drawing.PointF(x.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, owner),
y.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, owner)); y.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, owner));
} }
public static System.Drawing.SizeF GetDeviceSize(SvgUnit width, SvgUnit height, SvgRenderer renderer, SvgElement owner) public static System.Drawing.SizeF GetDeviceSize(SvgUnit width, SvgUnit height, ISvgRenderer renderer, SvgElement owner)
{ {
return new System.Drawing.SizeF(width.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, owner), return new System.Drawing.SizeF(width.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, owner),
height.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, owner)); height.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, owner));
......
...@@ -4,6 +4,7 @@ using System.ComponentModel; ...@@ -4,6 +4,7 @@ using System.ComponentModel;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Globalization; using System.Globalization;
using System.Drawing.Drawing2D;
namespace Svg namespace Svg
{ {
...@@ -123,6 +124,81 @@ namespace Svg ...@@ -123,6 +124,81 @@ namespace Svg
} }
#endregion #endregion
public void AddViewBoxTransform(SvgAspectRatio aspectRatio, ISvgRenderer renderer, SvgFragment frag)
{
if (this.Equals(SvgViewBox.Empty)) return;
var width = (frag == null ? this.Width : frag.Width.ToDeviceValue(renderer, UnitRenderingType.Horizontal, frag));
var height = (frag == null ? this.Height : frag.Height.ToDeviceValue(renderer, UnitRenderingType.Vertical, frag));
var fScaleX = width / this.Width;
var fScaleY = height / this.Height; //(this.MinY < 0 ? -1 : 1) *
var fMinX = this.MinX;
var fMinY = this.MinY;
if (aspectRatio == null) aspectRatio = new SvgAspectRatio(SvgPreserveAspectRatio.xMidYMid, false);
if (aspectRatio.Align != SvgPreserveAspectRatio.none)
{
if (aspectRatio.Slice)
{
fScaleX = Math.Max(fScaleX, fScaleY);
fScaleY = Math.Max(fScaleX, fScaleY);
}
else
{
fScaleX = Math.Min(fScaleX, fScaleY);
fScaleY = Math.Min(fScaleX, fScaleY);
}
float fViewMidX = (this.Width / 2) * fScaleX;
float fViewMidY = (this.Height / 2) * fScaleY;
float fMidX = width / 2;
float fMidY = height / 2;
switch (aspectRatio.Align)
{
case SvgPreserveAspectRatio.xMinYMin:
break;
case SvgPreserveAspectRatio.xMidYMin:
fMinX += fMidX - fViewMidX;
break;
case SvgPreserveAspectRatio.xMaxYMin:
fMinX += width - this.Width * fScaleX;
break;
case SvgPreserveAspectRatio.xMinYMid:
fMinY += fMidY - fViewMidY;
break;
case SvgPreserveAspectRatio.xMidYMid:
fMinX += fMidX - fViewMidX;
fMinY += fMidY - fViewMidY;
break;
case SvgPreserveAspectRatio.xMaxYMid:
fMinX += width - this.Width * fScaleX;
fMinY += fMidY - fViewMidY;
break;
case SvgPreserveAspectRatio.xMinYMax:
fMinY += height - this.Height * fScaleY;
break;
case SvgPreserveAspectRatio.xMidYMax:
fMinX += fMidX - fViewMidX;
fMinY += height - this.Height * fScaleY;
break;
case SvgPreserveAspectRatio.xMaxYMax:
fMinX += width - this.Width * fScaleX;
fMinY += height - this.Height * fScaleY;
break;
default:
break;
}
}
var x = (frag == null ? 0 : frag.X.ToDeviceValue(renderer, UnitRenderingType.Horizontal, frag));
var y = (frag == null ? 0 : frag.Y.ToDeviceValue(renderer, UnitRenderingType.Vertical, frag));
renderer.SetClip(new Region(new RectangleF(x, y, width, height)), CombineMode.Intersect);
renderer.ScaleTransform(fScaleX, fScaleY, MatrixOrder.Prepend);
renderer.TranslateTransform(x, y);
renderer.TranslateTransform(-fMinX, -fMinY);
}
} }
internal class SvgViewBoxConverter : TypeConverter internal class SvgViewBoxConverter : TypeConverter
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Svg
{
public enum XmlSpaceHandling
{
@default,
inherit,
preserve
}
}
...@@ -18,10 +18,10 @@ namespace Svg ...@@ -18,10 +18,10 @@ namespace Svg
} }
/// <summary> /// <summary>
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="SvgRenderer"/> object. /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="ISvgRenderer"/> object.
/// </summary> /// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> object to render to.</param> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param>
protected override void Render(SvgRenderer renderer) protected override void Render(ISvgRenderer renderer)
{ {
// Do nothing. Children should NOT be rendered. // Do nothing. Children should NOT be rendered.
} }
......
...@@ -31,10 +31,10 @@ namespace Svg ...@@ -31,10 +31,10 @@ namespace Svg
/// <summary> /// <summary>
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="SvgRenderer"/> object. /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="ISvgRenderer"/> object.
/// </summary> /// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> object to render to.</param> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param>
protected override void Render(SvgRenderer renderer) protected override void Render(ISvgRenderer renderer)
{ {
// Do nothing. Children should NOT be rendered. // Do nothing. Children should NOT be rendered.
} }
......
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