Commit bcf5b85c authored by Tebjan Halm's avatar Tebjan Halm
Browse files

Merge pull request #171 from ubbn/master

Added new Draw method
parents 2c3265fc caae2cce
...@@ -100,15 +100,24 @@ namespace Svg ...@@ -100,15 +100,24 @@ namespace Svg
/// </summary> /// </summary>
public override GraphicsPath Path(ISvgRenderer renderer) public override GraphicsPath Path(ISvgRenderer renderer)
{ {
if (this._path == null || this.IsPathDirty) if ((this._path == null || this.IsPathDirty) && base.StrokeWidth > 0)
{ {
float halfStrokeWidth = base.StrokeWidth / 2;
// If it is to render, don't need to consider stroke width.
// i.e stroke width only to be considered when calculating boundary
if (renderer != null)
{
halfStrokeWidth = 0;
this.IsPathDirty = false;
}
_path = new GraphicsPath(); _path = new GraphicsPath();
_path.StartFigure(); _path.StartFigure();
var center = this.Center.ToDeviceValue(renderer, this); var center = this.Center.ToDeviceValue(renderer, this);
var radius = this.Radius.ToDeviceValue(renderer, UnitRenderingType.Other, this); var radius = this.Radius.ToDeviceValue(renderer, UnitRenderingType.Other, this) + halfStrokeWidth;
_path.AddEllipse(center.X - radius, center.Y - radius, 2 * radius, 2 * radius); _path.AddEllipse(center.X - radius, center.Y - radius, 2 * radius, 2 * radius);
_path.CloseFigure(); _path.CloseFigure();
this.IsPathDirty = false;
} }
return _path; return _path;
} }
......
...@@ -104,16 +104,25 @@ namespace Svg ...@@ -104,16 +104,25 @@ namespace Svg
/// <value></value> /// <value></value>
public override GraphicsPath Path(ISvgRenderer renderer) public override GraphicsPath Path(ISvgRenderer renderer)
{ {
if (this._path == null || this.IsPathDirty) if ((this._path == null || this.IsPathDirty) && base.StrokeWidth > 0)
{ {
float halfStrokeWidth = base.StrokeWidth / 2;
// If it is to render, don't need to consider stroke width.
// i.e stroke width only to be considered when calculating boundary
if (renderer != null)
{
halfStrokeWidth = 0;
this.IsPathDirty = false;
}
var center = SvgUnit.GetDevicePoint(this._centerX, this._centerY, renderer, this); var center = SvgUnit.GetDevicePoint(this._centerX, this._centerY, renderer, this);
var radius = SvgUnit.GetDevicePoint(this._radiusX, this._radiusY, renderer, this); var radius = SvgUnit.GetDevicePoint(this._radiusX + halfStrokeWidth, this._radiusY + halfStrokeWidth, renderer, this);
this._path = new GraphicsPath(); this._path = new GraphicsPath();
_path.StartFigure(); _path.StartFigure();
_path.AddEllipse(center.X - radius.X, center.Y - radius.Y, 2 * radius.X, 2 * radius.Y); _path.AddEllipse(center.X - radius.X, center.Y - radius.Y, 2 * radius.X, 2 * radius.Y);
_path.CloseFigure(); _path.CloseFigure();
this.IsPathDirty = false;
} }
return _path; return _path;
} }
......
...@@ -23,6 +23,8 @@ namespace Svg ...@@ -23,6 +23,8 @@ namespace Svg
Height = new SvgUnit(0.0f); Height = new SvgUnit(0.0f);
} }
private GraphicsPath _path;
/// <summary> /// <summary>
/// Gets an <see cref="SvgPoint"/> representing the top left point of the rectangle. /// Gets an <see cref="SvgPoint"/> representing the top left point of the rectangle.
/// </summary> /// </summary>
...@@ -96,7 +98,19 @@ namespace Svg ...@@ -96,7 +98,19 @@ namespace Svg
/// </summary> /// </summary>
public override GraphicsPath Path(ISvgRenderer renderer) public override GraphicsPath Path(ISvgRenderer renderer)
{ {
return null; if (_path == null)
{
// Same size of rectangle can suffice to provide bounds of the image
var rectangle = new RectangleF(Location.ToDeviceValue(renderer, this),
SvgUnit.GetDeviceSize(Width, Height, renderer, this));
_path = new GraphicsPath();
_path.StartFigure();
_path.AddRectangle(rectangle);
_path.CloseFigure();
}
return _path;
} }
/// <summary> /// <summary>
......
...@@ -126,7 +126,7 @@ namespace Svg ...@@ -126,7 +126,7 @@ namespace Svg
public override System.Drawing.Drawing2D.GraphicsPath Path(ISvgRenderer renderer) public override System.Drawing.Drawing2D.GraphicsPath Path(ISvgRenderer renderer)
{ {
if (this._path == null || this.IsPathDirty) if ((this._path == null || this.IsPathDirty) && base.StrokeWidth > 0)
{ {
PointF start = new PointF(this.StartX.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this), PointF start = new PointF(this.StartX.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this),
this.StartY.ToDeviceValue(renderer, UnitRenderingType.Vertical, this)); this.StartY.ToDeviceValue(renderer, UnitRenderingType.Vertical, this));
...@@ -134,8 +134,22 @@ namespace Svg ...@@ -134,8 +134,22 @@ namespace Svg
this.EndY.ToDeviceValue(renderer, UnitRenderingType.Vertical, this)); this.EndY.ToDeviceValue(renderer, UnitRenderingType.Vertical, this));
this._path = new GraphicsPath(); this._path = new GraphicsPath();
this._path.AddLine(start, end);
this.IsPathDirty = false; // If it is to render, don't need to consider stroke width.
// i.e stroke width only to be considered when calculating boundary
if (renderer != null)
{
this._path.AddLine(start, end);
this.IsPathDirty = false;
}
else
{ // only when calculating boundary
_path.StartFigure();
var radius = base.StrokeWidth / 2;
_path.AddEllipse(start.X - radius, start.Y - radius, 2 * radius, 2 * radius);
_path.AddEllipse(end.X - radius, end.Y - radius, 2 * radius, 2 * radius);
_path.CloseFigure();
}
} }
return this._path; return this._path;
} }
......
...@@ -65,7 +65,7 @@ namespace Svg ...@@ -65,7 +65,7 @@ namespace Svg
public override GraphicsPath Path(ISvgRenderer renderer) public override GraphicsPath Path(ISvgRenderer renderer)
{ {
if (this._path == null || this.IsPathDirty) if ((this._path == null || this.IsPathDirty) && base.StrokeWidth > 0)
{ {
this._path = new GraphicsPath(); this._path = new GraphicsPath();
this._path.StartFigure(); this._path.StartFigure();
...@@ -77,6 +77,15 @@ namespace Svg ...@@ -77,6 +77,15 @@ namespace Svg
{ {
var endPoint = SvgUnit.GetDevicePoint(points[i], points[i + 1], renderer, this); var endPoint = SvgUnit.GetDevicePoint(points[i], points[i + 1], renderer, this);
// If it is to render, don't need to consider stroke width.
// i.e stroke width only to be considered when calculating boundary
if (renderer == null)
{
var radius = base.StrokeWidth / 2;
_path.AddEllipse(endPoint.X - radius, endPoint.Y - radius, 2 * radius, 2 * radius);
continue;
}
//first line //first line
if (_path.PointCount == 0) if (_path.PointCount == 0)
{ {
...@@ -94,7 +103,8 @@ namespace Svg ...@@ -94,7 +103,8 @@ namespace Svg
} }
this._path.CloseFigure(); this._path.CloseFigure();
this.IsPathDirty = false; if (renderer != null)
this.IsPathDirty = false;
} }
return this._path; return this._path;
} }
......
...@@ -48,7 +48,7 @@ namespace Svg ...@@ -48,7 +48,7 @@ namespace Svg
private GraphicsPath _Path; private GraphicsPath _Path;
public override GraphicsPath Path(ISvgRenderer renderer) public override GraphicsPath Path(ISvgRenderer renderer)
{ {
if (_Path == null || this.IsPathDirty) if ((_Path == null || this.IsPathDirty) && base.StrokeWidth > 0)
{ {
_Path = new GraphicsPath(); _Path = new GraphicsPath();
...@@ -59,6 +59,13 @@ namespace Svg ...@@ -59,6 +59,13 @@ namespace Svg
PointF endPoint = new PointF(Points[i].ToDeviceValue(renderer, UnitRenderingType.Horizontal, this), PointF endPoint = new PointF(Points[i].ToDeviceValue(renderer, UnitRenderingType.Horizontal, this),
Points[i + 1].ToDeviceValue(renderer, UnitRenderingType.Vertical, this)); Points[i + 1].ToDeviceValue(renderer, UnitRenderingType.Vertical, this));
if (renderer == null)
{
var radius = base.StrokeWidth / 2;
_Path.AddEllipse(endPoint.X - radius, endPoint.Y - radius, 2 * radius, 2 * radius);
continue;
}
// TODO: Remove unrequired first line // TODO: Remove unrequired first line
if (_Path.PointCount == 0) if (_Path.PointCount == 0)
{ {
...@@ -74,7 +81,8 @@ namespace Svg ...@@ -74,7 +81,8 @@ namespace Svg
{ {
Trace.TraceError("Error rendering points: " + exc.Message); Trace.TraceError("Error rendering points: " + exc.Message);
} }
this.IsPathDirty = false; if (renderer != null)
this.IsPathDirty = false;
} }
return _Path; return _Path;
} }
......
...@@ -176,13 +176,25 @@ namespace Svg ...@@ -176,13 +176,25 @@ namespace Svg
/// </summary> /// </summary>
public override GraphicsPath Path(ISvgRenderer renderer) public override GraphicsPath Path(ISvgRenderer renderer)
{ {
if (_path == null || IsPathDirty) if ((_path == null || IsPathDirty) && base.StrokeWidth > 0)
{ {
float halfStrokeWidth = base.StrokeWidth / 2;
// If it is to render, don't need to consider stroke
if (renderer != null)
{
halfStrokeWidth = 0;
this.IsPathDirty = false;
}
// If the corners aren't to be rounded just create a rectangle // If the corners aren't to be rounded just create a rectangle
if (CornerRadiusX.Value == 0.0f && CornerRadiusY.Value == 0.0f) if (CornerRadiusX.Value == 0.0f && CornerRadiusY.Value == 0.0f)
{ {
var rectangle = new RectangleF(Location.ToDeviceValue(renderer, this), // Starting location which take consideration of stroke width
SvgUnit.GetDeviceSize(this.Width, this.Height, renderer, this)); SvgPoint strokedLocation = new SvgPoint(Location.X - halfStrokeWidth, Location.Y - halfStrokeWidth);
var rectangle = new RectangleF(strokedLocation.ToDeviceValue(renderer, this),
SvgUnit.GetDeviceSize(this.Width + halfStrokeWidth * 2, this.Height + halfStrokeWidth * 2, renderer, this));
_path = new GraphicsPath(); _path = new GraphicsPath();
_path.StartFigure(); _path.StartFigure();
...@@ -253,7 +265,6 @@ namespace Svg ...@@ -253,7 +265,6 @@ namespace Svg
// Close // Close
_path.CloseFigure(); _path.CloseFigure();
} }
IsPathDirty = false;
} }
return _path; return _path;
} }
......
...@@ -244,12 +244,13 @@ namespace Svg ...@@ -244,12 +244,13 @@ namespace Svg
else else
{ {
bounds = this.Bounds; //do just one call to the recursive bounds property bounds = this.Bounds; //do just one call to the recursive bounds property
this.ViewBox = new SvgViewBox(bounds.X, bounds.Y, bounds.Width, bounds.Height);
} }
} }
if (isWidthperc) if (isWidthperc)
{ {
w = (bounds.Width + bounds.X) * (Width.Value * 0.01f); w = (bounds.Width) * (Width.Value * 0.01f);
} }
else else
{ {
...@@ -257,7 +258,7 @@ namespace Svg ...@@ -257,7 +258,7 @@ namespace Svg
} }
if (isHeightperc) if (isHeightperc)
{ {
h = (bounds.Height + bounds.Y) * (Height.Value * 0.01f); h = (bounds.Height) * (Height.Value * 0.01f);
} }
else else
{ {
......
...@@ -473,8 +473,10 @@ namespace Svg ...@@ -473,8 +473,10 @@ namespace Svg
//EO, 2014-12-05: Requested to ensure proper zooming (draw the svg in the bitmap size, ==> proper scaling) //EO, 2014-12-05: Requested to ensure proper zooming (draw the svg in the bitmap size, ==> proper scaling)
//EO, 2015-01-09, Added GetDimensions to use its returned size instead of this.Width and this.Height (request of Icarrere). //EO, 2015-01-09, Added GetDimensions to use its returned size instead of this.Width and this.Height (request of Icarrere).
SizeF size = this.GetDimensions();
renderer.ScaleTransform(bitmap.Width / size.Width, bitmap.Height / size.Height); //BBN, 2015-07-29, it is unnecassary to call again GetDimensions and transform to 1x1
//SizeF size = this.GetDimensions();
//renderer.ScaleTransform(bitmap.Width / size.Width, bitmap.Height / size.Height);
//EO, 2014-12-05: Requested to ensure proper zooming out (reduce size). Otherwise it clip the image. //EO, 2014-12-05: Requested to ensure proper zooming out (reduce size). Otherwise it clip the image.
this.Overflow = SvgOverflow.Auto; this.Overflow = SvgOverflow.Auto;
...@@ -490,6 +492,61 @@ namespace Svg ...@@ -490,6 +492,61 @@ namespace Svg
//Trace.TraceInformation("End Render"); //Trace.TraceInformation("End Render");
} }
/// <summary>
/// Renders the <see cref="SvgDocument"/> in given size and returns the image as a <see cref="Bitmap"/>.
/// </summary>
/// <returns>A <see cref="Bitmap"/> containing the rendered document.</returns>
public virtual Bitmap Draw(int rasterWidth, int rasterHeight)
{
var size = GetDimensions();
RasterizeDimensions(ref size, rasterWidth, rasterHeight);
if (size.Width == 0 || size.Height == 0)
return null;
var bitmap = new Bitmap((int)Math.Round(size.Width), (int)Math.Round(size.Height));
try
{
Draw(bitmap);
}
catch
{
bitmap.Dispose();
throw;
}
//Trace.TraceInformation("End Render");
return bitmap;
}
/// <summary>
/// If both or one of raster height and width is not given (0), calculate that missing value from original SVG size
/// while keeping original SVG size ratio
/// </summary>
/// <param name="size"></param>
/// <param name="rasterWidth"></param>
/// <param name="rasterHeight"></param>
public virtual void RasterizeDimensions(ref SizeF size, int rasterWidth, int rasterHeight)
{
if (size == null || size.Width == 0)
return;
// Ratio of height/width of the original SVG size, to be used for scaling transformation
float ratio = size.Height / size.Width;
size.Width = rasterWidth > 0 ? (float)rasterWidth : size.Width;
size.Height = rasterHeight > 0 ? (float)rasterHeight : size.Height;
if (rasterHeight == 0 && rasterWidth > 0)
{
size.Height = (int)(rasterWidth * ratio);
}
else if (rasterHeight > 0 && rasterWidth == 0)
{
size.Width = (int)(rasterHeight / ratio);
}
}
public override void Write(XmlTextWriter writer) public override void Write(XmlTextWriter writer)
{ {
//Save previous culture and switch to invariant for writing //Save previous culture and switch to invariant for writing
......
...@@ -745,6 +745,12 @@ namespace Svg ...@@ -745,6 +745,12 @@ namespace Svg
{ {
foreach(var child in elem.Children) foreach(var child in elem.Children)
{ {
// Skip to avoid double calculate Symbol element
// symbol element is only referenced by use element
// So here we need to skip when it is directly considered
if (child is Svg.Document_Structure.SvgSymbol)
continue;
if (child is SvgVisualElement) if (child is SvgVisualElement)
{ {
if(!(child is SvgGroup)) if(!(child is SvgGroup))
...@@ -783,7 +789,7 @@ namespace Svg ...@@ -783,7 +789,7 @@ namespace Svg
{ {
var childPath = ((SvgVisualElement)child).Path(renderer); var childPath = ((SvgVisualElement)child).Path(renderer);
if (childPath != null) if (childPath != null && childPath.PointCount > 0)
{ {
childPath = (GraphicsPath)childPath.Clone(); childPath = (GraphicsPath)childPath.Clone();
if(child.Transforms != null) if(child.Transforms != null)
......
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