зеркало из https://github.com/wieslawsoltes/SVG.git
257 строки
9.2 KiB
C#
257 строки
9.2 KiB
C#
#if !NO_SDC
|
|
using System;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Xml;
|
|
using Svg.Exceptions;
|
|
|
|
namespace Svg
|
|
{
|
|
public partial class SvgDocument : SvgFragment, ITypeDescriptorContext
|
|
{
|
|
/// <summary>
|
|
/// Skip check whether the GDI+ can be loaded.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Set to true on systems that do not support GDI+ like UWP.
|
|
/// </remarks>
|
|
public static bool SkipGdiPlusCapabilityCheck { get; set; }
|
|
|
|
internal SvgFontManager FontManager { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Validate whether the system has GDI+ capabilities (non Windows related).
|
|
/// </summary>
|
|
/// <returns>Boolean whether the system is capable of using GDI+</returns>
|
|
public static bool SystemIsGdiPlusCapable()
|
|
{
|
|
try
|
|
{
|
|
EnsureSystemIsGdiPlusCapable();
|
|
}
|
|
catch (SvgGdiPlusCannotBeLoadedException)
|
|
{
|
|
return false;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// If somehow another type of exception is raised by the ensure function we will let it bubble up, since that might indicate other issues/problems
|
|
throw;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ensure that the running system is GDI capable, if not this will yield a
|
|
/// SvgGdiPlusCannotBeLoadedException exception.
|
|
/// </summary>
|
|
public static void EnsureSystemIsGdiPlusCapable()
|
|
{
|
|
try
|
|
{
|
|
using (var matrix = new Matrix(0f, 0f, 0f, 0f, 0f, 0f)) { }
|
|
}
|
|
// GDI+ loading errors will result in TypeInitializationExceptions,
|
|
// for readability we will catch and wrap the error
|
|
catch (Exception e)
|
|
{
|
|
if (ExceptionCaughtIsGdiPlusRelated(e))
|
|
{
|
|
// Throw only the customized exception if we are sure GDI+ is causing the problem
|
|
throw new SvgGdiPlusCannotBeLoadedException(e);
|
|
}
|
|
// If the Matrix creation is causing another type of exception we should just raise that one
|
|
throw;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if the current exception or one of its children is the targeted GDI+ exception.
|
|
/// It can be hidden in one of the InnerExceptions, so we need to iterate over them.
|
|
/// </summary>
|
|
/// <param name="e">The exception to validate against the GDI+ check</param>
|
|
private static bool ExceptionCaughtIsGdiPlusRelated(Exception e)
|
|
{
|
|
var currE = e;
|
|
int cnt = 0; // Keep track of depth to prevent endless-loops
|
|
while (currE != null && cnt < 10)
|
|
{
|
|
var typeException = currE as DllNotFoundException;
|
|
if (typeException?.Message?.LastIndexOf("libgdiplus", StringComparison.OrdinalIgnoreCase) > -1)
|
|
{
|
|
return true;
|
|
}
|
|
currE = currE.InnerException;
|
|
cnt++;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static Bitmap OpenAsBitmap(string path)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
public static Bitmap OpenAsBitmap(XmlDocument document)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
private void Draw(ISvgRenderer renderer, ISvgBoundable boundable)
|
|
{
|
|
using (FontManager = new SvgFontManager())
|
|
{
|
|
renderer.SetBoundable(boundable);
|
|
Render(renderer);
|
|
FontManager = null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Renders the <see cref="SvgDocument"/> to the specified <see cref="ISvgRenderer"/>.
|
|
/// </summary>
|
|
/// <param name="renderer">The <see cref="ISvgRenderer"/> to render the document with.</param>
|
|
/// <exception cref="ArgumentNullException">The <paramref name="renderer"/> parameter cannot be <c>null</c>.</exception>
|
|
public void Draw(ISvgRenderer renderer)
|
|
{
|
|
if (renderer == null)
|
|
{
|
|
throw new ArgumentNullException("renderer");
|
|
}
|
|
|
|
this.Draw(renderer, this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Renders the <see cref="SvgDocument"/> to the specified <see cref="Graphics"/>.
|
|
/// </summary>
|
|
/// <param name="graphics">The <see cref="Graphics"/> to be rendered to.</param>
|
|
/// <exception cref="ArgumentNullException">The <paramref name="graphics"/> parameter cannot be <c>null</c>.</exception>
|
|
public void Draw(Graphics graphics)
|
|
{
|
|
this.Draw(graphics, null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Renders the <see cref="SvgDocument"/> to the specified <see cref="Graphics"/>.
|
|
/// </summary>
|
|
/// <param name="graphics">The <see cref="Graphics"/> to be rendered to.</param>
|
|
/// <param name="size">The <see cref="SizeF"/> to render the document. If <c>null</c> document is rendered at the default document size.</param>
|
|
/// <exception cref="ArgumentNullException">The <paramref name="graphics"/> parameter cannot be <c>null</c>.</exception>
|
|
public void Draw(Graphics graphics, SizeF? size)
|
|
{
|
|
if (graphics == null)
|
|
throw new ArgumentNullException("graphics");
|
|
|
|
using (var renderer = SvgRenderer.FromGraphics(graphics))
|
|
{
|
|
var docSize = size ?? GetDimensions(renderer);
|
|
var boundable = new GenericBoundable(0, 0, docSize.Width, docSize.Height);
|
|
this.Draw(renderer, boundable);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Renders the <see cref="SvgDocument"/> and returns the image as a <see cref="Bitmap"/>.
|
|
/// </summary>
|
|
/// <returns>A <see cref="Bitmap"/> containing the rendered document.</returns>
|
|
public virtual Bitmap Draw()
|
|
{
|
|
//Trace.TraceInformation("Begin Render");
|
|
|
|
var size = Size.Round(GetDimensions());
|
|
if (size.Width <= 0 || size.Height <= 0)
|
|
return null;
|
|
|
|
Bitmap bitmap = null;
|
|
try
|
|
{
|
|
try
|
|
{
|
|
bitmap = new Bitmap(size.Width, size.Height);
|
|
}
|
|
catch (ArgumentException e)
|
|
{
|
|
// When processing too many files at one the system can run out of memory
|
|
throw new SvgMemoryException("Cannot process SVG file, cannot allocate the required memory", e);
|
|
}
|
|
|
|
//bitmap.SetResolution(300, 300);
|
|
|
|
this.Draw(bitmap);
|
|
}
|
|
catch
|
|
{
|
|
bitmap?.Dispose();
|
|
throw;
|
|
}
|
|
|
|
//Trace.TraceInformation("End Render");
|
|
return bitmap;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Renders the <see cref="SvgDocument"/> into a given Bitmap <see cref="Bitmap"/>.
|
|
/// </summary>
|
|
public virtual void Draw(Bitmap bitmap)
|
|
{
|
|
//Trace.TraceInformation("Begin Render");
|
|
|
|
using (var renderer = SvgRenderer.FromImage(bitmap))
|
|
{
|
|
var boundable = new GenericBoundable(0, 0, bitmap.Width, bitmap.Height);
|
|
this.Draw(renderer, boundable);
|
|
}
|
|
|
|
//Trace.TraceInformation("End Render");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Renders the <see cref="SvgDocument"/> in given size and returns the image as a <see cref="Bitmap"/>.
|
|
/// If one of rasterWidth and rasterHeight is zero, the image is scaled preserving aspect ratio,
|
|
/// otherwise the aspect ratio is ignored.
|
|
/// </summary>
|
|
/// <returns>A <see cref="Bitmap"/> containing the rendered document.</returns>
|
|
public virtual Bitmap Draw(int rasterWidth, int rasterHeight)
|
|
{
|
|
var svgSize = GetDimensions();
|
|
var imageSize = svgSize;
|
|
this.RasterizeDimensions(ref imageSize, rasterWidth, rasterHeight);
|
|
|
|
var bitmapSize = Size.Round(imageSize);
|
|
if (bitmapSize.Width <= 0 || bitmapSize.Height <= 0)
|
|
return null;
|
|
|
|
Bitmap bitmap = null;
|
|
try
|
|
{
|
|
try
|
|
{
|
|
bitmap = new Bitmap(bitmapSize.Width, bitmapSize.Height);
|
|
}
|
|
catch (ArgumentException e)
|
|
{
|
|
// When processing too many files at one the system can run out of memory
|
|
throw new SvgMemoryException("Cannot process SVG file, cannot allocate the required memory", e);
|
|
}
|
|
|
|
using (var renderer = SvgRenderer.FromImage(bitmap))
|
|
{
|
|
renderer.ScaleTransform(imageSize.Width / svgSize.Width, imageSize.Height / svgSize.Height);
|
|
var boundable = new GenericBoundable(0, 0, svgSize.Width, svgSize.Height);
|
|
this.Draw(renderer, boundable);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
bitmap?.Dispose();
|
|
throw;
|
|
}
|
|
|
|
return bitmap;
|
|
}
|
|
}
|
|
}
|
|
#endif
|