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
......@@ -148,86 +148,13 @@ namespace Svg
}
/// <summary>
/// Applies the required transforms to <see cref="SvgRenderer"/>.
/// Applies the required transforms to <see cref="ISvgRenderer"/>.
/// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> to be transformed.</param>
protected internal override bool PushTransforms(SvgRenderer renderer)
/// <param name="renderer">The <see cref="ISvgRenderer"/> to be transformed.</param>
protected internal override bool PushTransforms(ISvgRenderer renderer)
{
if (!base.PushTransforms(renderer)) return false;
if (!this.ViewBox.Equals(SvgViewBox.Empty))
{
var width = this.Width.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this);
var height = this.Height.ToDeviceValue(renderer, UnitRenderingType.Vertical, this);
var fScaleX = width / this.ViewBox.Width;
var fScaleY = height / this.ViewBox.Height;
var fMinX = -this.ViewBox.MinX;
var fMinY = -this.ViewBox.MinY;
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.ViewBox.Width / 2) * fScaleX;
float fViewMidY = (this.ViewBox.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.ViewBox.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.ViewBox.Width * fScaleX;
fMinY += fMidY - fViewMidY;
break;
case SvgPreserveAspectRatio.xMinYMax:
fMinY += height - this.ViewBox.Height * fScaleY;
break;
case SvgPreserveAspectRatio.xMidYMax:
fMinX += fMidX - fViewMidX;
fMinY += height - this.ViewBox.Height * fScaleY;
break;
case SvgPreserveAspectRatio.xMaxYMax:
fMinX += width - this.ViewBox.Width * fScaleX;
fMinY += height - this.ViewBox.Height * fScaleY;
break;
default:
break;
}
}
var x = _x.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this);
var y = _y.ToDeviceValue(renderer, UnitRenderingType.Vertical, this);
renderer.AddClip(new Region(new RectangleF(x, y, width, height)));
renderer.ScaleTransform(fScaleX, fScaleY, MatrixOrder.Prepend);
renderer.TranslateTransform(x,y);
renderer.TranslateTransform(fMinX, fMinY);
}
this.ViewBox.AddViewBoxTransform(this.AspectRatio, renderer, this);
return true;
}
......
......@@ -9,15 +9,11 @@ namespace Svg
[SvgElement("g")]
public class SvgGroup : SvgVisualElement
{
public SvgGroup()
{
}
/// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
/// <value></value>
public override System.Drawing.Drawing2D.GraphicsPath Path(SvgRenderer renderer)
public override System.Drawing.Drawing2D.GraphicsPath Path(ISvgRenderer renderer)
{
return GetPaths(this, renderer);
}
......@@ -58,25 +54,6 @@ namespace Svg
protected override bool Renderable { get { return false; } }
///// <summary>
///// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object.
///// </summary>
///// <param name="graphics">The <see cref="Graphics"/> object to render to.</param>
//protected override void Render(SvgRenderer renderer)
//{
// if (!Visible || !Displayable)
// return;
// if (this.PushTransforms(renderer))
// {
// this.SetClip(renderer);
// base.RenderChildren(renderer);
// this.ResetClip(renderer);
// this.PopTransforms(renderer);
// }
//}
public override SvgElement DeepCopy()
{
return DeepCopy<SvgGroup>();
......
......@@ -17,7 +17,7 @@ namespace Svg
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
/// <value></value>
public override System.Drawing.Drawing2D.GraphicsPath Path(SvgRenderer renderer)
public override System.Drawing.Drawing2D.GraphicsPath Path(ISvgRenderer renderer)
{
return GetPaths(this, renderer);
}
......@@ -60,7 +60,7 @@ namespace Svg
/// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object.
/// </summary>
/// <param name="renderer">The <see cref="Graphics"/> object to render to.</param>
protected override void Render(SvgRenderer renderer)
protected override void Render(ISvgRenderer renderer)
{
if (!Visible || !Displayable)
return;
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace Svg.Document_Structure
{
/// <summary>
/// An element used to group SVG shapes.
/// </summary>
[SvgElement("symbol")]
public class SvgSymbol : SvgVisualElement
{
/// <summary>
/// Gets or sets the viewport of the element.
/// </summary>
/// <value></value>
[SvgAttribute("viewBox")]
public SvgViewBox ViewBox
{
get { return this.Attributes.GetAttribute<SvgViewBox>("viewBox"); }
set { this.Attributes["viewBox"] = value; }
}
/// <summary>
/// Gets or sets the aspect of the viewport.
/// </summary>
/// <value></value>
[SvgAttribute("preserveAspectRatio")]
public SvgAspectRatio AspectRatio
{
get { return this.Attributes.GetAttribute<SvgAspectRatio>("preserveAspectRatio"); }
set { this.Attributes["preserveAspectRatio"] = value; }
}
/// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
/// <value></value>
public override System.Drawing.Drawing2D.GraphicsPath Path(ISvgRenderer renderer)
{
return GetPaths(this, renderer);
}
/// <summary>
/// Gets the bounds of the element.
/// </summary>
/// <value>The bounds.</value>
public override System.Drawing.RectangleF Bounds
{
get
{
var r = new RectangleF();
foreach (var c in this.Children)
{
if (c is SvgVisualElement)
{
// First it should check if rectangle is empty or it will return the wrong Bounds.
// This is because when the Rectangle is Empty, the Union method adds as if the first values where X=0, Y=0
if (r.IsEmpty)
{
r = ((SvgVisualElement)c).Bounds;
}
else
{
var childBounds = ((SvgVisualElement)c).Bounds;
if (!childBounds.IsEmpty)
{
r = RectangleF.Union(r, childBounds);
}
}
}
}
return r;
}
}
protected override bool Renderable { get { return false; } }
/// <summary>
/// Applies the required transforms to <see cref="ISvgRenderer"/>.
/// </summary>
/// <param name="renderer">The <see cref="ISvgRenderer"/> to be transformed.</param>
protected internal override bool PushTransforms(ISvgRenderer renderer)
{
if (!base.PushTransforms(renderer)) return false;
this.ViewBox.AddViewBoxTransform(this.AspectRatio, renderer, null);
return true;
}
public override SvgElement DeepCopy()
{
return DeepCopy<SvgSymbol>();
}
public override SvgElement DeepCopy<T>()
{
var newObj = base.DeepCopy<T>() as SvgSymbol;
if (this.Fill != null)
newObj.Fill = this.Fill.DeepCopy() as SvgPaintServer;
return newObj;
}
}
}
......@@ -35,10 +35,10 @@ namespace Svg
}
/// <summary>
/// Applies the required transforms to <see cref="SvgRenderer"/>.
/// Applies the required transforms to <see cref="ISvgRenderer"/>.
/// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> to be transformed.</param>
protected internal override bool PushTransforms(SvgRenderer renderer)
/// <param name="renderer">The <see cref="ISvgRenderer"/> to be transformed.</param>
protected internal override bool PushTransforms(ISvgRenderer renderer)
{
if (!base.PushTransforms(renderer)) return false;
renderer.TranslateTransform(this.X.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this),
......@@ -55,7 +55,7 @@ namespace Svg
this.Y = 0;
}
public override System.Drawing.Drawing2D.GraphicsPath Path(SvgRenderer renderer)
public override System.Drawing.Drawing2D.GraphicsPath Path(ISvgRenderer renderer)
{
SvgVisualElement element = (SvgVisualElement)this.OwnerDocument.IdManager.GetElementById(this.ReferencedElement);
return (element != null) ? element.Path(renderer) : null;
......@@ -66,20 +66,9 @@ namespace Svg
get { return new System.Drawing.RectangleF(); }
}
// public override SvgElementCollection Children
// {
// get
// {
// SvgElement element = this.OwnerDocument.IdManager.GetElementById(this.ReferencedElement);
// SvgElementCollection elements = new SvgElementCollection(this, true);
// elements.Add(element);
// return elements;
// }
// }
protected override bool Renderable { get { return false; } }
protected override void Render(SvgRenderer renderer)
protected override void Render(ISvgRenderer renderer)
{
if (!Visible || !Displayable)
return;
......
......@@ -17,7 +17,7 @@ namespace Svg
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
/// <value></value>
public override System.Drawing.Drawing2D.GraphicsPath Path(SvgRenderer renderer)
public override System.Drawing.Drawing2D.GraphicsPath Path(ISvgRenderer renderer)
{
return GetPaths(this, renderer);
}
......
......@@ -14,8 +14,8 @@ namespace Svg.FilterEffects
private Dictionary<string, Bitmap> _images;
private RectangleF _bounds;
private SvgRenderer _renderer;
private Action<SvgRenderer> _renderMethod;
private ISvgRenderer _renderer;
private Action<ISvgRenderer> _renderMethod;
private float _inflate;
public Matrix Transform { get; set; }
......@@ -41,7 +41,7 @@ namespace Svg.FilterEffects
}
}
public ImageBuffer(RectangleF bounds, float inflate, SvgRenderer renderer, Action<SvgRenderer> renderMethod)
public ImageBuffer(RectangleF bounds, float inflate, ISvgRenderer renderer, Action<ISvgRenderer> renderMethod)
{
_bounds = bounds;
_inflate = inflate;
......@@ -124,7 +124,7 @@ namespace Svg.FilterEffects
}
private string ProcessKey(string key)
{
if (string.IsNullOrEmpty(key)) return BufferKey;
if (string.IsNullOrEmpty(key)) return _images.ContainsKey(BufferKey) ? BufferKey : SvgFilterPrimitive.SourceGraphic;
return key;
}
......@@ -136,7 +136,7 @@ namespace Svg.FilterEffects
(int)(_bounds.Height + 2 * _inflate * _bounds.Height + _bounds.Y));
using (var renderer = SvgRenderer.FromImage(graphic))
{
renderer.Boundable(_renderer.Boundable());
renderer.SetBoundable(_renderer.GetBoundable());
var transform = new Matrix();
transform.Translate(_bounds.Width * _inflate, _bounds.Height * _inflate);
renderer.Transform = transform;
......
......@@ -80,10 +80,10 @@ namespace Svg.FilterEffects
}
/// <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>
/// <param name="renderer">The <see cref="SvgRenderer"/> object to render to.</param>
protected override void Render(SvgRenderer renderer)
/// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param>
protected override void Render(ISvgRenderer renderer)
{
base.RenderChildren(renderer);
}
......@@ -109,7 +109,7 @@ namespace Svg.FilterEffects
return transformMatrix;
}
private RectangleF GetPathBounds(SvgVisualElement element, SvgRenderer renderer, Matrix transform)
private RectangleF GetPathBounds(SvgVisualElement element, ISvgRenderer renderer, Matrix transform)
{
var bounds = element.Path(renderer).GetBounds();
var pts = new PointF[] { bounds.Location, new PointF(bounds.Right, bounds.Bottom) };
......@@ -119,7 +119,7 @@ namespace Svg.FilterEffects
Math.Abs(pts[0].X - pts[1].X), Math.Abs(pts[0].Y - pts[1].Y));
}
public void ApplyFilter(SvgVisualElement element, SvgRenderer renderer, Action<SvgRenderer> renderMethod)
public void ApplyFilter(SvgVisualElement element, ISvgRenderer renderer, Action<ISvgRenderer> renderMethod)
{
var inflate = 0.5f;
var transform = GetTransform(element);
......@@ -139,11 +139,10 @@ namespace Svg.FilterEffects
var bufferImg = buffer.Buffer;
bufferImg.Save(@"C:\test.png");
var imgDraw = RectangleF.Inflate(bounds, inflate * bounds.Width, inflate * bounds.Height);
var prevClip = renderer.Clip;
renderer.Clip = new Region(imgDraw);
var prevClip = renderer.GetClip();
renderer.SetClip(new Region(imgDraw));
renderer.DrawImage(bufferImg, imgDraw, new RectangleF(bounds.X, bounds.Y, imgDraw.Width, imgDraw.Height), GraphicsUnit.Pixel);
renderer.Clip = prevClip;
//renderer.DrawImage(bufferImg, bounds, bounds, GraphicsUnit.Pixel);
renderer.SetClip(prevClip);
}
}
......
......@@ -19,6 +19,6 @@ namespace Svg
float StrokeMiterLimit { get; set; }
SvgUnitCollection StrokeDashArray { get; set; }
SvgUnit StrokeDashOffset { get; set; }
GraphicsPath Path(SvgRenderer renderer);
GraphicsPath Path(ISvgRenderer renderer);
}
}
\ No newline at end of file
......@@ -35,7 +35,7 @@ namespace Svg
set { this._colour = value; }
}
public override Brush GetBrush(SvgVisualElement styleOwner, SvgRenderer renderer, float opacity)
public override Brush GetBrush(SvgVisualElement styleOwner, ISvgRenderer renderer, float opacity)
{
//is none?
if (this == SvgPaintServer.None) return new SolidBrush(System.Drawing.Color.Transparent);
......
......@@ -44,7 +44,7 @@ namespace Svg
}
}
public override System.Drawing.Brush GetBrush(SvgVisualElement styleOwner, SvgRenderer renderer, float opacity)
public override System.Drawing.Brush GetBrush(SvgVisualElement styleOwner, ISvgRenderer renderer, float opacity)
{
EnsureServer(styleOwner);
return _concreteServer.GetBrush(styleOwner, renderer, opacity);
......
......@@ -130,7 +130,7 @@ namespace Svg
/// </summary>
/// <param name="owner">The parent <see cref="SvgVisualElement"/>.</param>
/// <param name="opacity">The opacity of the colour blend.</param>
protected ColorBlend GetColorBlend(SvgRenderer renderer, float opacity, bool radial)
protected ColorBlend GetColorBlend(ISvgRenderer renderer, float opacity, bool radial)
{
int colourBlends = this.Stops.Count;
bool insertStart = false;
......@@ -184,7 +184,7 @@ namespace Svg
for (int i = 0; i < colourBlends; i++)
{
var currentStop = this.Stops[radial ? this.Stops.Count - 1 - actualStops : actualStops];
var boundWidth = renderer.Boundable().Bounds.Width;
var boundWidth = renderer.GetBoundable().Bounds.Width;
mergedOpacity = opacity * currentStop.Opacity;
position =
......
......@@ -79,7 +79,7 @@ namespace Svg
Y2 = new SvgUnit(SvgUnitType.Percentage, 0F);
}
public override Brush GetBrush(SvgVisualElement renderingElement, SvgRenderer renderer, float opacity)
public override Brush GetBrush(SvgVisualElement renderingElement, ISvgRenderer renderer, float opacity)
{
LoadStops(renderingElement);
if (IsInvalid)
......@@ -89,7 +89,7 @@ namespace Svg
try
{
if (this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) renderer.Boundable(renderingElement);
if (this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) renderer.SetBoundable(renderingElement);
var specifiedStart = CalculateStart(renderer);
var specifiedEnd = CalculateEnd(renderer);
......@@ -116,12 +116,12 @@ namespace Svg
}
}
private PointF CalculateStart(SvgRenderer renderer)
private PointF CalculateStart(ISvgRenderer renderer)
{
return TransformPoint(SvgUnit.GetDevicePointOffset(this.X1, this.Y1, renderer, this));
}
private PointF CalculateEnd(SvgRenderer renderer)
private PointF CalculateEnd(ISvgRenderer renderer)
{
return TransformPoint(SvgUnit.GetDevicePointOffset(this.X2, this.Y2, renderer, this));
}
......@@ -181,7 +181,7 @@ namespace Svg
return new GradientPoints(effectiveStart, effectiveEnd);
}
private ColorBlend CalculateColorBlend(SvgRenderer renderer, float opacity, PointF specifiedStart, PointF effectiveStart, PointF specifiedEnd, PointF effectiveEnd)
private ColorBlend CalculateColorBlend(ISvgRenderer renderer, float opacity, PointF specifiedStart, PointF effectiveStart, PointF specifiedEnd, PointF effectiveEnd)
{
var colorBlend = GetColorBlend(renderer, opacity, false);
......
......@@ -87,7 +87,7 @@ namespace Svg
Overflow = SvgOverflow.hidden;
}
public override System.Drawing.Drawing2D.GraphicsPath Path(SvgRenderer renderer)
public override System.Drawing.Drawing2D.GraphicsPath Path(ISvgRenderer renderer)
{
var path = this.Children.FirstOrDefault(x => x is SvgPath);
if (path != null)
......@@ -131,7 +131,7 @@ namespace Svg
/// <param name="pOwner"></param>
/// <param name="pMarkerPoint1"></param>
/// <param name="pMarkerPoint2"></param>
public void RenderMarker(SvgRenderer pRenderer, SvgPath pOwner, PointF pRefPoint, PointF pMarkerPoint1, PointF pMarkerPoint2)
public void RenderMarker(ISvgRenderer pRenderer, SvgPath pOwner, PointF pRefPoint, PointF pMarkerPoint1, PointF pMarkerPoint2)
{
float xDiff = pMarkerPoint2.X - pMarkerPoint1.X;
float yDiff = pMarkerPoint2.Y - pMarkerPoint1.Y;
......@@ -148,7 +148,7 @@ namespace Svg
/// <param name="pMarkerPoint1"></param>
/// <param name="pMarkerPoint2"></param>
/// <param name="pMarkerPoint3"></param>
public void RenderMarker(SvgRenderer pRenderer, SvgPath pOwner, PointF pRefPoint, PointF pMarkerPoint1, PointF pMarkerPoint2, PointF pMarkerPoint3)
public void RenderMarker(ISvgRenderer pRenderer, SvgPath pOwner, PointF pRefPoint, PointF pMarkerPoint1, PointF pMarkerPoint2, PointF pMarkerPoint3)
{
float xDiff = pMarkerPoint2.X - pMarkerPoint1.X;
float yDiff = pMarkerPoint2.Y - pMarkerPoint1.Y;
......@@ -168,7 +168,7 @@ namespace Svg
/// <param name="pRenderer"></param>
/// <param name="pOwner"></param>
/// <param name="pMarkerPoint"></param>
private void RenderPart2(float fAngle, SvgRenderer pRenderer, SvgPath pOwner, PointF pMarkerPoint)
private void RenderPart2(float fAngle, ISvgRenderer pRenderer, SvgPath pOwner, PointF pMarkerPoint)
{
Pen pRenderPen = CreatePen(pOwner, pRenderer);
......@@ -216,7 +216,7 @@ namespace Svg
/// </summary>
/// <param name="pStroke"></param>
/// <returns></returns>
private Pen CreatePen(SvgPath pPath, SvgRenderer renderer)
private Pen CreatePen(SvgPath pPath, ISvgRenderer renderer)
{
Brush pBrush = pPath.Stroke.GetBrush(this, renderer, Opacity);
switch (MarkerUnits)
......
......@@ -26,10 +26,10 @@ namespace Svg
}
/// <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>
/// <param name="renderer">The <see cref="SvgRenderer"/> object to render to.</param>
protected override void Render(SvgRenderer renderer)
/// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param>
protected override void Render(ISvgRenderer renderer)
{
// Never render paint servers or their children
}
......@@ -39,7 +39,7 @@ namespace Svg
/// </summary>
/// <param name="styleOwner">The owner <see cref="SvgVisualElement"/>.</param>
/// <param name="opacity">The opacity of the brush.</param>
public abstract Brush GetBrush(SvgVisualElement styleOwner, SvgRenderer renderer, float opacity);
public abstract Brush GetBrush(SvgVisualElement styleOwner, ISvgRenderer renderer, float opacity);
/// <summary>
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
......
......@@ -20,8 +20,8 @@ namespace Svg
private SvgUnit _x;
private SvgUnit _y;
private SvgViewBox _viewBox;
private SvgCoordinateUnits _patternUnits;
private SvgCoordinateUnits _patternContentUnits;
private SvgCoordinateUnits _patternUnits = SvgCoordinateUnits.ObjectBoundingBox;
private SvgCoordinateUnits _patternContentUnits = SvgCoordinateUnits.UserSpaceOnUse;
[SvgAttribute("overflow")]
public SvgOverflow Overflow
......@@ -129,7 +129,7 @@ namespace Svg
/// </summary>
/// <param name="renderingElement">The owner <see cref="SvgVisualElement"/>.</param>
/// <param name="opacity">The opacity of the brush.</param>
public override Brush GetBrush(SvgVisualElement renderingElement, SvgRenderer renderer, float opacity)
public override Brush GetBrush(SvgVisualElement renderingElement, ISvgRenderer renderer, float opacity)
{
// If there aren't any children, return null
if (this.Children.Count == 0)
......@@ -141,7 +141,7 @@ namespace Svg
try
{
if (this.PatternUnits == SvgCoordinateUnits.ObjectBoundingBox) renderer.Boundable(renderingElement);
if (this.PatternUnits == SvgCoordinateUnits.ObjectBoundingBox) renderer.SetBoundable(renderingElement);
float width = this._width.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this);
float height = this._height.ToDeviceValue(renderer, UnitRenderingType.Vertical, this);
......@@ -153,11 +153,7 @@ namespace Svg
float x = this._x.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, this);
float y = this._y.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, this);
patternMatrix.Translate(x + -1.0f, y + -1.0f);
}
else
{
patternMatrix.Translate(-1, -1);
patternMatrix.Translate(x, y);
}
if (this.ViewBox.Height > 0 || this.ViewBox.Width > 0)
......@@ -167,20 +163,16 @@ namespace Svg
}
Bitmap image = new Bitmap((int)width, (int)height);
using (SvgRenderer iRenderer = SvgRenderer.FromImage(image))
using (var iRenderer = SvgRenderer.FromImage(image))
{
iRenderer.Boundable((_patternContentUnits == SvgCoordinateUnits.ObjectBoundingBox) ? new GenericBoundable(0, 0, width, height) : renderer.Boundable());
iRenderer.SetBoundable((_patternContentUnits == SvgCoordinateUnits.ObjectBoundingBox) ? new GenericBoundable(0, 0, width, height) : renderer.GetBoundable());
iRenderer.Transform = patternMatrix;
iRenderer.CompositingQuality = CompositingQuality.HighQuality;
iRenderer.SmoothingMode = SmoothingMode.AntiAlias;
iRenderer.PixelOffsetMode = PixelOffsetMode.Half;
foreach (SvgElement child in this.Children)
{
child.RenderElement(iRenderer);
}
iRenderer.Save();
}
image.Save(string.Format(@"C:\test{0:D3}.png", imgNumber++));
......
......@@ -98,16 +98,16 @@ namespace Svg
private object _lockObj = new Object();
public override Brush GetBrush(SvgVisualElement renderingElement, SvgRenderer renderer, float opacity)
public override Brush GetBrush(SvgVisualElement renderingElement, ISvgRenderer renderer, float opacity)
{
LoadStops(renderingElement);
try
{
if (this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) renderer.Boundable(renderingElement);
if (this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) renderer.SetBoundable(renderingElement);
// Calculate the path and transform it appropriately
var origin = renderer.Boundable().Location;
var origin = renderer.GetBoundable().Location;
var center = new PointF(origin.X + CenterX.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, this),
origin.Y + CenterY.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, this));
var specifiedRadius = Radius.ToDeviceValue(renderer, UnitRenderingType.Other, this);
......@@ -181,7 +181,7 @@ namespace Svg
return bounds.Height / (points[2].Y - points[1].Y);
}
private PointF CalculateFocalPoint(SvgRenderer renderer, PointF origin)
private PointF CalculateFocalPoint(ISvgRenderer renderer, PointF origin)
{
var deviceFocalX = origin.X + FocalX.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, this);
var deviceFocalY = origin.Y + FocalY.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, this);
......@@ -203,7 +203,7 @@ namespace Svg
return path;
}
private ColorBlend CalculateColorBlend(SvgRenderer renderer, float opacity, float scale, out float outScale)
private ColorBlend CalculateColorBlend(ISvgRenderer renderer, float opacity, float scale, out float outScale)
{
var colorBlend = GetColorBlend(renderer, opacity, true);
float newScale;
......
......@@ -38,9 +38,9 @@ namespace Svg
/// Gets or sets the length of the path.
/// </summary>
[SvgAttribute("pathLength")]
public int PathLength
public float PathLength
{
get { return this.Attributes.GetAttribute<int>("pathLength"); }
get { return this.Attributes.GetAttribute<float>("pathLength"); }
set { this.Attributes["pathLength"] = value; }
}
......@@ -81,7 +81,7 @@ namespace Svg
/// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
public override GraphicsPath Path(SvgRenderer renderer)
public override GraphicsPath Path(ISvgRenderer renderer)
{
if (this._path == null || this.IsPathDirty)
{
......@@ -131,15 +131,15 @@ namespace Svg
}
/// <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>
/// <param name="renderer">The <see cref="SvgRenderer"/> object to render to.</param>
protected internal override void RenderStroke(SvgRenderer renderer)
/// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param>
protected internal override 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);
using (Pen pen = new Pen(this.Stroke.GetBrush(this, renderer, this.StrokeOpacity), strokeWidth))
using (Pen pen = new Pen(this.Stroke.GetBrush(this, renderer, this.StrokeOpacity * this.Opacity), strokeWidth))
{
if (this.StrokeDashArray != null && this.StrokeDashArray.Count > 0)
{
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace Svg
{
public interface IGraphicsProvider
{
Graphics GetGraphics();
}
}
using System;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.Collections.Generic;
namespace Svg
{
public interface ISvgRenderer : IDisposable
{
float DpiY { get; }
void DrawImage(Image image, RectangleF destRect, RectangleF srcRect, GraphicsUnit graphicsUnit);
void DrawImageUnscaled(Image image, Point location);
void DrawPath(Pen pen, GraphicsPath path);
void FillPath(Brush brush, GraphicsPath path);
float FontBaselineOffset(IFontDefn font);
ISvgBoundable GetBoundable();
Region GetClip();
IList<RectangleF> MeasureCharacters(string text, IFontDefn font);
SizeF MeasureString(string text, IFontDefn font);
ISvgBoundable PopBoundable();
void RotateTransform(float fAngle, MatrixOrder order = MatrixOrder.Append);
void ScaleTransform(float sx, float sy, MatrixOrder order = MatrixOrder.Append);
void SetBoundable(ISvgBoundable boundable);
void SetClip(Region region, CombineMode combineMode = CombineMode.Replace);
SmoothingMode SmoothingMode { get; set; }
Matrix Transform { get; set; }
void TranslateTransform(float dx, float dy, MatrixOrder order = MatrixOrder.Append);
}
}
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