Update: code tidy complete
This commit is contained in:
Родитель
6977b114e9
Коммит
3b4516b11e
|
@ -1,150 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Globalization;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a color in the CMYK color space
|
||||
/// </summary>
|
||||
public struct CmykColor : IEquatable<CmykColor>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a color with CMYK values of (0, 0, 0, 100)
|
||||
/// </summary>
|
||||
public static readonly CmykColor Black = new CmykColor(0, 0, 0, 100);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a color with CMYK values of (0, 0, 0, 0)
|
||||
/// </summary>
|
||||
public static readonly CmykColor White = new CmykColor(0, 0, 0, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a color with CMYK values of (100, 0, 0, 0)
|
||||
/// </summary>
|
||||
public static readonly CmykColor Cyan = new CmykColor(100, 0, 0, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a color with CMYK values of (0, 100, 0, 0)
|
||||
/// </summary>
|
||||
public static readonly CmykColor Magenta = new CmykColor(0, 100, 0, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a color with CMYK values of (0, 0, 100, 0)
|
||||
/// </summary>
|
||||
public static readonly CmykColor Yellow = new CmykColor(0, 0, 100, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Cyan component (0-100)
|
||||
/// </summary>
|
||||
public readonly byte C;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Magenta component (0-100)
|
||||
/// </summary>
|
||||
public readonly byte M;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Yellow component (0-100)
|
||||
/// </summary>
|
||||
public readonly byte Y;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Black component (0-100)
|
||||
/// </summary>
|
||||
public readonly byte K;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="CmykColor"/>
|
||||
/// </summary>
|
||||
/// <param name="c">cyan channel intensity between 0..100</param>
|
||||
/// <param name="m">magenta channel intensity between 0..100</param>
|
||||
/// <param name="y">yellow channel intensity between 0..100</param>
|
||||
/// <param name="k">black channel intensity between 0..100</param>
|
||||
public CmykColor(byte c, byte m, byte y, byte k)
|
||||
{
|
||||
C = EnsureValidIntensity(c);
|
||||
M = EnsureValidIntensity(m);
|
||||
Y = EnsureValidIntensity(y);
|
||||
K = EnsureValidIntensity(k);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="CmykColor"/> from the values in the specified string
|
||||
/// </summary>
|
||||
public CmykColor(string color)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(color)) throw new ArgumentException(nameof(color));
|
||||
if (color.StartsWith("#"))
|
||||
{
|
||||
C = byte.Parse(color.Substring(1, 2), NumberStyles.HexNumber);
|
||||
M = byte.Parse(color.Substring(3, 2), NumberStyles.HexNumber);
|
||||
Y = byte.Parse(color.Substring(5, 2), NumberStyles.HexNumber);
|
||||
K = byte.Parse(color.Substring(7, 2), NumberStyles.HexNumber);
|
||||
}
|
||||
else if (color.StartsWith("(") && color.EndsWith(")"))
|
||||
{
|
||||
var values = color.Substring(1, color.Length - 2).Split(',');
|
||||
if (values.Length != 4)
|
||||
{
|
||||
throw new ArgumentException($"Expected (C,M,Y,K) but got '{color}'", nameof(color));
|
||||
}
|
||||
C = byte.Parse(values[0]);
|
||||
M = byte.Parse(values[1]);
|
||||
Y = byte.Parse(values[2]);
|
||||
K = byte.Parse(values[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Invalid color, expected hex or value encoded (e.g. '#B8BDB900', '(72, 74, 73, 0)')", nameof(color));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hash code for the color structure
|
||||
/// </summary>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hashCode = C.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ M.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ Y.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ K.GetHashCode();
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the specified color is equal to the current color.
|
||||
/// </summary>
|
||||
public bool Equals(CmykColor other) => C == other.C && M == other.M && Y == other.Y && K == other.K;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the specified object is equal to the current color.
|
||||
/// </summary>
|
||||
public override bool Equals(object obj) => !ReferenceEquals(null, obj) && obj is CmykColor cmyk && Equals(cmyk);
|
||||
|
||||
/// <summary>
|
||||
/// Compares two colors for exact equality
|
||||
/// </summary>
|
||||
public static bool operator ==(CmykColor left, CmykColor right) => left.Equals(right);
|
||||
|
||||
/// <summary>
|
||||
/// Compares two colors for inequality
|
||||
/// </summary>
|
||||
public static bool operator !=(CmykColor left, CmykColor right) => !left.Equals(right);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the string representation of the color
|
||||
/// </summary>
|
||||
public override string ToString() => $"#{C:x2}{M:x2}{Y:x2}{K:x2}";
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static byte EnsureValidIntensity(byte value) => value <= 100 ? value : throw new ArgumentOutOfRangeException(nameof(value), $"channel intensity should be between 0..100 but got {value}");
|
||||
}
|
||||
}
|
|
@ -1,231 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a color in multiple color spaces
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public struct Color : IEquatable<Color>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the system defined No color
|
||||
/// </summary>
|
||||
public static readonly Color NoColor = new Color();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the system defined Black color
|
||||
/// </summary>
|
||||
public static readonly Color Black = new Color(EquinoxLabs.SVGSharpie.DynamicPDF.RgbColor.Black, EquinoxLabs.SVGSharpie.DynamicPDF.CmykColor.Black);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the system defined White color
|
||||
/// </summary>
|
||||
public static readonly Color White = new Color(EquinoxLabs.SVGSharpie.DynamicPDF.RgbColor.White, EquinoxLabs.SVGSharpie.DynamicPDF.CmykColor.White);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color in the RGB color space
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public RgbColor? RgbColor { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color in the CMYK color space
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public CmykColor? CmykColor { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color in the Spot color space
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public SpotColor? SpotColor { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current color is empty (no values specified)
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public bool IsNone => !RgbColor.HasValue && !CmykColor.HasValue && !SpotColor.HasValue;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance color with just an RGB representation
|
||||
/// </summary>
|
||||
public Color(RgbColor rgb)
|
||||
{
|
||||
RgbColor = rgb;
|
||||
CmykColor = null;
|
||||
SpotColor = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance color with just a CMYK representation
|
||||
/// </summary>
|
||||
public Color(CmykColor cmyk)
|
||||
{
|
||||
RgbColor = null;
|
||||
CmykColor = cmyk;
|
||||
SpotColor = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance color with RGB, CMYK and Spot representations
|
||||
/// </summary>
|
||||
public Color(RgbColor? rgb, CmykColor? cmyk = null, SpotColor? spot = null)
|
||||
{
|
||||
RgbColor = rgb;
|
||||
CmykColor = cmyk;
|
||||
SpotColor = spot;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance color from the specified string representation
|
||||
/// </summary>
|
||||
public Color(string color)
|
||||
{
|
||||
if (color == null) throw new ArgumentNullException(nameof(color));
|
||||
RgbColor = null;
|
||||
CmykColor = null;
|
||||
SpotColor = null;
|
||||
|
||||
if (color.StartsWith("#"))
|
||||
{
|
||||
RgbColor = new RgbColor(color);
|
||||
return;
|
||||
}
|
||||
|
||||
void ParseColorSpace(ref Color self, string space)
|
||||
{
|
||||
var pair = space.Split(ColorSpaceValueSplitChars, StringSplitOptions.RemoveEmptyEntries);
|
||||
var colorSpace = pair[0];
|
||||
var colorValue = pair.Length == 2 ? pair[1] : string.Empty;
|
||||
if (pair.Length != 2)
|
||||
{
|
||||
var index = space.IndexOf("(", StringComparison.OrdinalIgnoreCase);
|
||||
if (index < 0)
|
||||
{
|
||||
throw new Exception($"Invalid color space value '{space}'");
|
||||
}
|
||||
colorSpace = space.Substring(0, index);
|
||||
colorValue = space.Substring(index);
|
||||
}
|
||||
if (ColorSpaceInitializers.TryGetValue(colorSpace.ToLowerInvariant(), out var initializer))
|
||||
{
|
||||
initializer(ref self, colorValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Invalid color space prefix '{colorSpace}', expected one of [{RgbSpacePrefix}, {CmykSpacePrefix}, {SpotSpacePrefix}]");
|
||||
}
|
||||
}
|
||||
|
||||
var builder = new StringBuilder();
|
||||
var scope = 0;
|
||||
for (var i = 0; i < color.Length; i++)
|
||||
{
|
||||
var c = color[i];
|
||||
if (c == ColorSpaceSplitChar && scope == 0)
|
||||
{
|
||||
var space = builder.ToString();
|
||||
ParseColorSpace(ref this, space);
|
||||
builder.Clear();
|
||||
}
|
||||
else if (!char.IsWhiteSpace(c))
|
||||
{
|
||||
if (c == '(') scope++;
|
||||
else if (c == ')') scope--;
|
||||
builder.Append(c);
|
||||
}
|
||||
}
|
||||
if (builder.Length > 0)
|
||||
{
|
||||
ParseColorSpace(ref this, builder.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the string representation of the current color
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
if (RgbColor.HasValue && !CmykColor.HasValue && !SpotColor.HasValue)
|
||||
{
|
||||
return RgbColor.Value.ToString();
|
||||
}
|
||||
if (RgbColor.HasValue)
|
||||
{
|
||||
builder.Append(RgbSpacePrefix).Append(ColorSpaceValueSplitChar).Append(RgbColor.Value);
|
||||
}
|
||||
if (CmykColor.HasValue)
|
||||
{
|
||||
if (builder.Length > 0) builder.Append(ColorSpaceSplitChar);
|
||||
builder.Append(CmykSpacePrefix).Append(ColorSpaceValueSplitChar).Append(CmykColor.Value);
|
||||
}
|
||||
if (SpotColor.HasValue)
|
||||
{
|
||||
if (builder.Length > 0) builder.Append(ColorSpaceSplitChar);
|
||||
builder.Append(SpotSpacePrefix).Append(ColorSpaceValueSplitChar).Append(SpotColor.Value);
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the specified color is equal to the current color.
|
||||
/// </summary>
|
||||
public bool Equals(Color other) => RgbColor.Equals(other.RgbColor) && CmykColor.Equals(other.CmykColor) && SpotColor.Equals(other.SpotColor);
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the specified object is equal to the current color.
|
||||
/// </summary>
|
||||
public override bool Equals(object obj) => !ReferenceEquals(null, obj) && obj is Color color && Equals(color);
|
||||
|
||||
/// <summary>
|
||||
/// Compares two colors for exact equality
|
||||
/// </summary>
|
||||
public static bool operator ==(Color left, Color right) => left.Equals(right);
|
||||
|
||||
/// <summary>
|
||||
/// Compares two colors for inequality
|
||||
/// </summary>
|
||||
public static bool operator !=(Color left, Color right) => !left.Equals(right);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hash code for the color structure
|
||||
/// </summary>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
// ReSharper disable once NonReadonlyMemberInGetHashCode
|
||||
var hashCode = RgbColor.GetHashCode();
|
||||
// ReSharper disable once NonReadonlyMemberInGetHashCode
|
||||
hashCode = (hashCode * 397) ^ CmykColor.GetHashCode();
|
||||
// ReSharper disable once NonReadonlyMemberInGetHashCode
|
||||
hashCode = (hashCode * 397) ^ SpotColor.GetHashCode();
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
private const string RgbSpacePrefix = "rgb";
|
||||
private const string CmykSpacePrefix = "cmyk";
|
||||
private const string SpotSpacePrefix = "spot";
|
||||
|
||||
private const char ColorSpaceSplitChar = ',';
|
||||
private const char ColorSpaceValueSplitChar = ':';
|
||||
private static readonly char[] ColorSpaceValueSplitChars = { ColorSpaceValueSplitChar };
|
||||
|
||||
private delegate void ColorSpaceInitializerDelegate(ref Color self, string value);
|
||||
|
||||
private static readonly Dictionary<string, ColorSpaceInitializerDelegate> ColorSpaceInitializers = new Dictionary<string, ColorSpaceInitializerDelegate>
|
||||
{
|
||||
{ RgbSpacePrefix, (ref Color self, string value) => self.RgbColor = new RgbColor(value) },
|
||||
{ CmykSpacePrefix, (ref Color self, string value) => self.CmykColor = new CmykColor(value) },
|
||||
{ SpotSpacePrefix, (ref Color self, string value) => self.SpotColor = new SpotColor(value) }
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
using ceTe.DynamicPDF;
|
||||
using Color = EquinoxLabs.SVGSharpie.DynamicPDF.Color;
|
||||
using PdfColor = ceTe.DynamicPDF.Color;
|
||||
using PdfCmykColor = ceTe.DynamicPDF.CmykColor;
|
||||
using PdfSpotColor = ceTe.DynamicPDF.SpotColor;
|
||||
using PdfSpotkColorInk = ceTe.DynamicPDF.SpotColorInk;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF
|
||||
{
|
||||
internal static class ColorExtensions
|
||||
{
|
||||
public static PdfColor ToPdfColor(this Color color, PdfSpotColor spotColorInk)
|
||||
{
|
||||
return DynamicPdfColorConverter.ToPdfColor(color, spotColorInk);
|
||||
}
|
||||
|
||||
public static PdfColor ToPdfColor(this SvgColor color, PdfSpotColor spotColorOverride)
|
||||
{
|
||||
if (spotColorOverride != null)
|
||||
{
|
||||
return spotColorOverride;
|
||||
}
|
||||
return new ceTe.DynamicPDF.RgbColor(color.R, color.G, color.B);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
using ceTe.DynamicPDF;
|
||||
using ceTe.DynamicPDF.IO;
|
||||
using ceTe.DynamicPDF.PageElements;
|
||||
using Rectangle = EquinoxLabs.SVGSharpie.DynamicPDF.Rectangle;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Draws a rectangular clipping group around the child elements. All children will be clipped to the
|
||||
|
@ -18,8 +17,9 @@ namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements
|
|||
/// <param name="clippingRectangle">the clipping rectangle to which the child elements will be clipped</param>
|
||||
/// <param name="children">the child elements to add to the clipping group</param>
|
||||
public ClippingGroup(Rectangle clippingRectangle, params PageElement[] children)
|
||||
: this(clippingRectangle.X, clippingRectangle.Y, clippingRectangle.Right, clippingRectangle.Bottom, children)
|
||||
: this(clippingRectangle.X, clippingRectangle.Y, clippingRectangle.X + clippingRectangle.Width, clippingRectangle.Y + clippingRectangle.Height, children)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
|
@ -1,7 +1,7 @@
|
|||
using ceTe.DynamicPDF.IO;
|
||||
using ceTe.DynamicPDF.PageElements;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a 'closepath' sub path command and writes the PDF 'h' operator
|
|
@ -2,7 +2,7 @@
|
|||
using ceTe.DynamicPDF.IO;
|
||||
using ceTe.DynamicPDF.PageElements;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Customized PDF path renderer, the base <see cref="Path"/> doesn't support fill rules other than non-zero
|
|
@ -0,0 +1,25 @@
|
|||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes how a child element is horizontally positioned or stretched within a parent elements layout
|
||||
/// </summary>
|
||||
public enum HorizontalAlignment
|
||||
{
|
||||
/// <summary>
|
||||
/// An element aligned to the left of the layout slot for the parent element.
|
||||
/// </summary>
|
||||
Left,
|
||||
/// <summary>
|
||||
/// An element aligned to the center of the layout slot for the parent element.
|
||||
/// </summary>
|
||||
Center,
|
||||
/// <summary>
|
||||
/// An element aligned to the right of the layout slot for the parent element.
|
||||
/// </summary>
|
||||
Right,
|
||||
/// <summary>
|
||||
/// An element stretched to fill the entire layout slot of the parent element.
|
||||
/// </summary>
|
||||
Stretch
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
using ceTe.DynamicPDF.IO;
|
||||
using ceTe.DynamicPDF.PageElements;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a 'moveto' sub path command, when added to a <see cref="T:ceTe.DynamicPDF.PageElements.Path" />, is used to
|
|
@ -0,0 +1,46 @@
|
|||
using System.Runtime.Serialization;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the width, height and location of a rectangle
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public struct Rectangle
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the x-axis value of the left side of the rectangle.
|
||||
/// </summary>
|
||||
[DataMember(Name = "X")]
|
||||
public double X { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the y-axis value of the top side of the rectangle.
|
||||
/// </summary>
|
||||
[DataMember(Name = "Y")]
|
||||
public double Y { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width of the rectangle
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public double Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the height of the rectangle
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public double Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Rectangle structure that has the specified x-coordinate, y-coordinate, width, and height.
|
||||
/// </summary>
|
||||
public Rectangle(double x, double y, double width, double height)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements.Shading
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core.Shading
|
||||
{
|
||||
internal struct Circle : IEquatable<Circle>
|
||||
{
|
|
@ -2,7 +2,7 @@
|
|||
using ceTe.DynamicPDF;
|
||||
using PdfColor = ceTe.DynamicPDF.Color;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements.Shading
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core.Shading
|
||||
{
|
||||
internal struct GradientColorStop : IEquatable<GradientColorStop>
|
||||
{
|
|
@ -6,7 +6,7 @@ using ceTe.DynamicPDF;
|
|||
using ceTe.DynamicPDF.IO;
|
||||
using PdfColor = ceTe.DynamicPDF.Color;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements.Shading
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core.Shading
|
||||
{
|
||||
internal abstract class GradientShadingColor<T> : GradientShadingColor, IEquatable<T>
|
||||
where T : GradientShadingColor<T>
|
|
@ -2,7 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements.Shading
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core.Shading
|
||||
{
|
||||
internal sealed class LinearGradientShadingColor : GradientShadingColor<LinearGradientShadingColor>
|
||||
{
|
|
@ -2,7 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements.Shading
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core.Shading
|
||||
{
|
||||
internal sealed class RadialGradientShadingColor : GradientShadingColor<RadialGradientShadingColor>
|
||||
{
|
|
@ -1,4 +1,4 @@
|
|||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements.Shading
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core.Shading
|
||||
{
|
||||
internal enum ShadingType
|
||||
{
|
|
@ -1,12 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ceTe.DynamicPDF;
|
||||
using ceTe.DynamicPDF.IO;
|
||||
using EquinoxLabs.SVGSharpie;
|
||||
using PdfSpotColor = ceTe.DynamicPDF.SpotColor;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core
|
||||
{
|
||||
internal sealed class SvgClipPathMaskWriterVisitor : SvgElementVisitor
|
||||
{
|
|
@ -1,10 +1,9 @@
|
|||
using System;
|
||||
using ceTe.DynamicPDF;
|
||||
using ceTe.DynamicPDF.IO;
|
||||
using EquinoxLabs.SVGSharpie;
|
||||
using PdfSpotColor = ceTe.DynamicPDF.SpotColor;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core
|
||||
{
|
||||
internal sealed class SvgClipPathPageElement : PageElement
|
||||
{
|
|
@ -3,12 +3,10 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using ceTe.DynamicPDF;
|
||||
using ceTe.DynamicPDF.PageElements;
|
||||
using EquinoxLabs.SVGSharpie;
|
||||
using EquinoxLabs.SVGSharpie.DynamicPDF;
|
||||
using EquinoxLabs.SVGSharpie.DynamicPDF.Extensions;
|
||||
using PdfSpotColor = ceTe.DynamicPDF.SpotColor;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
|
@ -2,10 +2,9 @@
|
|||
using ceTe.DynamicPDF;
|
||||
using ceTe.DynamicPDF.IO;
|
||||
using ceTe.DynamicPDF.PageElements;
|
||||
using EquinoxLabs.SVGSharpie;
|
||||
using PdfSpotColor = ceTe.DynamicPDF.SpotColor;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a DynamicPdf graphical <see cref="PageElement"/> where the
|
||||
|
@ -29,7 +28,7 @@ namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements
|
|||
|
||||
public PdfSpotColor SpotColorOveride { get; set; }
|
||||
|
||||
public SvgPageElement(SvgDocument svgDocument, EquinoxLabs.SVGSharpie.DynamicPDF.Rectangle bounds, HorizontalAlignment horizontalAlignment = HorizontalAlignment.Center, VerticalAlignment verticalAlignment = VerticalAlignment.Center)
|
||||
public SvgPageElement(SvgDocument svgDocument, Rectangle bounds, HorizontalAlignment horizontalAlignment = HorizontalAlignment.Center, VerticalAlignment verticalAlignment = VerticalAlignment.Center)
|
||||
: this(svgDocument, (float)bounds.X, (float)bounds.Y, (float)bounds.Width, (float)bounds.Height, horizontalAlignment, verticalAlignment)
|
||||
{
|
||||
}
|
|
@ -2,15 +2,12 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
//using PNI.Apollo.Render.Services.DynamicPdf.Extensions;
|
||||
using PNI.Apollo.Render.Services.DynamicPdf.PageElements.Shading;
|
||||
using EquinoxLabs.SVGSharpie;
|
||||
using EquinoxLabs.SVGSharpie.DynamicPDF.Extensions;
|
||||
using Color = ceTe.DynamicPDF.Color;
|
||||
using EquinoxLabs.SVGSharpie.DynamicPDF;
|
||||
using ceTe.DynamicPDF;
|
||||
using EquinoxLabs.SVGSharpie.DynamicPDF.Core.Shading;
|
||||
using PdfSpotColor = ceTe.DynamicPDF.SpotColor;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core
|
||||
{
|
||||
internal sealed class SvgPaintServerToDynamicPdfColorConverter
|
||||
{
|
|
@ -3,12 +3,10 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using ceTe.DynamicPDF;
|
||||
using ceTe.DynamicPDF.PageElements;
|
||||
//using PNI.Apollo.Render.Services.DynamicPdf.Extensions;
|
||||
using EquinoxLabs.SVGSharpie;
|
||||
using EquinoxLabs.SVGSharpie.DynamicPDF;
|
||||
using PdfSpotColor = ceTe.DynamicPDF.SpotColor;
|
||||
using EquinoxLabs.SVGSharpie.DynamicPDF.Extensions;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Transforms path segments composed only of <see cref="SvgPathSegCurvetoCubicAbs"/>, <see cref="SvgPathSegLinetoAbs"/>
|
|
@ -1,53 +1,8 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core
|
||||
{
|
||||
public enum VerticalAlignment
|
||||
{
|
||||
/// <summary>
|
||||
/// The child element is aligned to the top of the parent's layout slot.
|
||||
/// </summary>
|
||||
Top,
|
||||
/// <summary>
|
||||
/// The child element is aligned to the center of the parent's layout slot.
|
||||
/// </summary>
|
||||
Center,
|
||||
/// <summary>
|
||||
/// The child element is aligned to the bottom of the parent's layout slot.
|
||||
/// </summary>
|
||||
Bottom,
|
||||
/// <summary>
|
||||
/// The child element is stretched to fill the parent's layout slot.
|
||||
/// </summary>
|
||||
Stretch
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Describes how a child element is horizontally positioned or stretched within a parent elements layout
|
||||
/// </summary>
|
||||
public enum HorizontalAlignment
|
||||
{
|
||||
/// <summary>
|
||||
/// An element aligned to the left of the layout slot for the parent element.
|
||||
/// </summary>
|
||||
Left,
|
||||
/// <summary>
|
||||
/// An element aligned to the center of the layout slot for the parent element.
|
||||
/// </summary>
|
||||
Center,
|
||||
/// <summary>
|
||||
/// An element aligned to the right of the layout slot for the parent element.
|
||||
/// </summary>
|
||||
Right,
|
||||
/// <summary>
|
||||
/// An element stretched to fill the entire layout slot of the parent element.
|
||||
/// </summary>
|
||||
Stretch
|
||||
}
|
||||
|
||||
|
||||
internal sealed class VectorElementPdfPageViewport
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -80,11 +35,6 @@ namespace PNI.Apollo.Render.Services.DynamicPdf.PageElements
|
|||
/// </summary>
|
||||
public bool ClippingGroupRequired { get; }
|
||||
|
||||
//public VectorElementPdfPageViewport(float contentWidth, float contentHeight, VectorElement element)
|
||||
// : this(contentWidth, contentHeight, (float)element.Bounds.X, (float)element.Bounds.Y, (float)element.Bounds.Width, (float)element.Bounds.Height, element.HorizontalAlignment, element.VerticalAlignment)
|
||||
//{
|
||||
//}
|
||||
|
||||
public VectorElementPdfPageViewport(float contentWidth, float contentHeight, float x, float y, float width, float height, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment)
|
||||
{
|
||||
ScaleX = width / contentWidth;
|
|
@ -0,0 +1,22 @@
|
|||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Core
|
||||
{
|
||||
public enum VerticalAlignment
|
||||
{
|
||||
/// <summary>
|
||||
/// The child element is aligned to the top of the parent's layout slot.
|
||||
/// </summary>
|
||||
Top,
|
||||
/// <summary>
|
||||
/// The child element is aligned to the center of the parent's layout slot.
|
||||
/// </summary>
|
||||
Center,
|
||||
/// <summary>
|
||||
/// The child element is aligned to the bottom of the parent's layout slot.
|
||||
/// </summary>
|
||||
Bottom,
|
||||
/// <summary>
|
||||
/// The child element is stretched to fill the parent's layout slot.
|
||||
/// </summary>
|
||||
Stretch
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
using ceTe.DynamicPDF;
|
||||
using Color = EquinoxLabs.SVGSharpie.DynamicPDF.Color;
|
||||
using PdfColor = ceTe.DynamicPDF.Color;
|
||||
using PdfCmykColor = ceTe.DynamicPDF.CmykColor;
|
||||
using PdfSpotColor = ceTe.DynamicPDF.SpotColor;
|
||||
using PdfSpotkColorInk = ceTe.DynamicPDF.SpotColorInk;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides functionality to convert from the render langue color to the DynamicPdf color structure
|
||||
/// </summary>
|
||||
internal static class DynamicPdfColorConverter
|
||||
{
|
||||
public static PdfColor ToPdfColor(Color color, PdfSpotColor spotColorOverride)
|
||||
{
|
||||
if (spotColorOverride != null)
|
||||
{
|
||||
return spotColorOverride;
|
||||
}
|
||||
if (color.SpotColor != null)
|
||||
{
|
||||
var spotColorName = color.SpotColor.Value.InkName;
|
||||
var cmyk = color.CmykColor.GetValueOrDefault();
|
||||
var cmykAlternate = new PdfCmykColor(cmyk.C / 100f, cmyk.M / 100f, cmyk.Y / 100f, cmyk.K / 100f);
|
||||
return new PdfSpotColor(100, new PdfSpotkColorInk(spotColorName, cmykAlternate));
|
||||
}
|
||||
if (color.CmykColor != null)
|
||||
{
|
||||
var cmyk = color.CmykColor.GetValueOrDefault();
|
||||
return new PdfCmykColor(cmyk.C / 100f, cmyk.M / 100f, cmyk.Y / 100f, cmyk.K / 100f);
|
||||
}
|
||||
if (color.RgbColor != null)
|
||||
{
|
||||
var rgb = color.RgbColor.Value;
|
||||
return new ceTe.DynamicPDF.RgbColor(rgb.R, rgb.G, rgb.B);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -31,6 +31,16 @@
|
|||
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="CmykColor.cs" />
|
||||
<Compile Remove="Color.cs" />
|
||||
<Compile Remove="DynamicPdfColorConverter.cs" />
|
||||
<Compile Remove="Point.cs" />
|
||||
<Compile Remove="RgbColor.cs" />
|
||||
<Compile Remove="Size.cs" />
|
||||
<Compile Remove="SpotColor.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EquinoxLabs.SVGSharpie\EquinoxLabs.SVGSharpie.csproj" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Extensions
|
||||
{
|
|
@ -0,0 +1,18 @@
|
|||
using PdfColor = ceTe.DynamicPDF.Color;
|
||||
using PdfRgbColor = ceTe.DynamicPDF.RgbColor;
|
||||
using PdfSpotColor = ceTe.DynamicPDF.SpotColor;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Extensions
|
||||
{
|
||||
internal static class ColorExtensions
|
||||
{
|
||||
public static PdfColor ToPdfColor(this SvgColor color, PdfSpotColor spotColorOverride)
|
||||
{
|
||||
if (spotColorOverride != null)
|
||||
{
|
||||
return spotColorOverride;
|
||||
}
|
||||
return new PdfRgbColor(color.R, color.G, color.B);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ceTe.DynamicPDF;
|
||||
using ceTe.DynamicPDF.PageElements;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Extensions
|
||||
{
|
||||
internal static class DynamicPdfPageElementExtensions
|
||||
{
|
|
@ -1,12 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ceTe.DynamicPDF;
|
||||
using EquinoxLabs.SVGSharpie;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Extensions
|
||||
{
|
||||
internal static class SvgEnumConversionExtensions
|
||||
{
|
|
@ -1,89 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a point in a two-dimensional plane using a pair of x- and y- coordinates.
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public struct Point : IEquatable<Point>
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a Point that has <see cref="X"/> and <see cref="Y"/> values set to zero.
|
||||
/// </summary>
|
||||
public static readonly Point Empty = new Point();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the x-coordinate of this Point.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public double X { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the y-coordinate of this Point.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public double Y { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this Point is empty (both X and Y are 0, otherwise false)
|
||||
/// </summary>
|
||||
public bool IsEmpty =>
|
||||
Math.Abs(X) < double.Epsilon &&
|
||||
Math.Abs(Y) < double.Epsilon;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether both the x- and y- axis coordinates are the same
|
||||
/// </summary>
|
||||
public bool IsUniform =>
|
||||
Math.Abs(X - Y) < double.Epsilon;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Point class with the specified coordinates.
|
||||
/// </summary>
|
||||
/// <param name="x">The horizontal position of the point.</param>
|
||||
/// <param name="y">The vertical position of the point.</param>
|
||||
public Point(double x, double y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether this instance and the specified object represent the same value.
|
||||
/// </summary>
|
||||
public bool Equals(Point other) => X.Equals(other.X) && Y.Equals(other.Y);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether this instance and the specified object represent the same value.
|
||||
/// </summary>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
return obj is Point && Equals((Point)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (X.GetHashCode() * 397) ^ Y.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether the two specified points represent the same value.
|
||||
/// </summary>
|
||||
public static bool operator ==(Point left, Point right) => left.Equals(right);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether the two specified points do not represent the same value.
|
||||
/// </summary>
|
||||
public static bool operator !=(Point left, Point right) => !left.Equals(right);
|
||||
}
|
||||
}
|
|
@ -1,154 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the width, height and location of a rectangle
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public struct Rectangle
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a special value that represents a rectangle with no position or area.
|
||||
/// </summary>
|
||||
public static Rectangle Empty { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the x-axis value of the left side of the rectangle.
|
||||
/// </summary>
|
||||
[DataMember(Name = "Left")]
|
||||
public double X { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the y-axis value of the top side of the rectangle.
|
||||
/// </summary>
|
||||
[DataMember(Name = "Top")]
|
||||
public double Y { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width of the rectangle
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public double Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the height of the rectangle
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public double Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size of the rectangle
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public Size Size
|
||||
{
|
||||
get => new Size(Width, Height);
|
||||
set
|
||||
{
|
||||
Width = value.Width;
|
||||
Height = value.Height;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current rectangle is the <see cref="Empty"/> rectangle
|
||||
/// </summary>
|
||||
public bool IsEmpty =>
|
||||
double.IsPositiveInfinity(X) &&
|
||||
double.IsPositiveInfinity(Y) &&
|
||||
double.IsNegativeInfinity(Width) &&
|
||||
double.IsNegativeInfinity(Height);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the x-axis value of the left side of the rectangle.
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public double Left => X;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the y-axis value of the top side of the rectangle.
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public double Top => Y;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the x-axis value of the right side of the rectangle.
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public double Right => X + Width;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the y-axis value of the bottom of the rectangle.
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public double Bottom => Y + Height;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the top left point of the rectangle.
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public Point TopLeft => new Point(Left, Top);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the top right point of the rectangle.
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public Point TopRight => new Point(Right, Top);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bottom left point of the rectangle.
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public Point BottomLeft => new Point(Left, Bottom);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bottom right point of the rectangle.
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
public Point BottomRight => new Point(Right, Bottom);
|
||||
|
||||
static Rectangle()
|
||||
{
|
||||
Empty = new Rectangle
|
||||
{
|
||||
X = double.PositiveInfinity,
|
||||
Y = double.PositiveInfinity,
|
||||
Width = double.NegativeInfinity,
|
||||
Height = double.NegativeInfinity
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Rectangle structure that has the specified x-coordinate, y-coordinate, width, and height.
|
||||
/// </summary>
|
||||
public Rectangle(double x, double y, double width, double height)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Rectangle structure that has the specified width, and height and is located at (0,0).
|
||||
/// </summary>
|
||||
public Rectangle(double width, double height)
|
||||
: this(0, 0, width, height)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Rectangle structure that has the specified size and is located at (0,0).
|
||||
/// </summary>
|
||||
public Rectangle(Size size)
|
||||
: this(size.Width, size.Height)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ceTe.DynamicPDF;
|
||||
using PNI.Apollo.Render.Services.DynamicPdf.PageElements;
|
||||
using ceTe.DynamicPDF;
|
||||
using EquinoxLabs.SVGSharpie.DynamicPDF.Core;
|
||||
using PdfSpotColor = ceTe.DynamicPDF.SpotColor;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF
|
||||
{
|
||||
public static class SvgImageRenderer
|
||||
public static class Renderer
|
||||
{
|
||||
|
||||
public static PageElement CreateSvgImagePageElement(SvgDocument document, Rectangle bounds, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment, PdfSpotColor spotColorInk)
|
|
@ -1,142 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a color in the RGB color space
|
||||
/// </summary>
|
||||
public struct RgbColor : IEquatable<RgbColor>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a color with the RGB value of #000000
|
||||
/// </summary>
|
||||
public static readonly RgbColor Black = new RgbColor(0, 0, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a color with the RGB value of #FFFFFF
|
||||
/// </summary>
|
||||
public static readonly RgbColor White = new RgbColor(255, 255, 255);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a color with the RGB value of #FF0000
|
||||
/// </summary>
|
||||
public static readonly RgbColor Red = new RgbColor(255, 0, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a color with the RGB value of #00FF00
|
||||
/// </summary>
|
||||
public static readonly RgbColor Green = new RgbColor(0, 255, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a color with the RGB value of #0000FF
|
||||
/// </summary>
|
||||
public static readonly RgbColor Blue = new RgbColor(0, 0, 255);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Red component
|
||||
/// </summary>
|
||||
public readonly byte R;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Green component
|
||||
/// </summary>
|
||||
public readonly byte G;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Blue component
|
||||
/// </summary>
|
||||
public readonly byte B;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RgbColor"/> with the specified channel intensities
|
||||
/// </summary>
|
||||
public RgbColor(byte r, byte g, byte b)
|
||||
{
|
||||
R = r;
|
||||
G = g;
|
||||
B = b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RgbColor"/> from the specified string value
|
||||
/// </summary>
|
||||
public RgbColor(string color)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(color)) throw new ArgumentException(nameof(color));
|
||||
if (color.StartsWith("#"))
|
||||
{
|
||||
int HexCharToNumber(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||||
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
|
||||
throw new Exception($"Invalid character '{c}' in color '{color}'");
|
||||
}
|
||||
|
||||
byte HexStrToByte(string str, int index) => (byte)(HexCharToNumber(str[index]) * 16 + HexCharToNumber(str[index + 1]));
|
||||
|
||||
R = HexStrToByte(color, 1);
|
||||
G = HexStrToByte(color, 3);
|
||||
B = HexStrToByte(color, 5);
|
||||
}
|
||||
else if (color.StartsWith("(") && color.EndsWith(")"))
|
||||
{
|
||||
var values = color.Substring(1, color.Length - 2).Split(',');
|
||||
if (values.Length != 3)
|
||||
{
|
||||
throw new ArgumentException($"Expected (R,G,B) but got '{color}'", nameof(color));
|
||||
}
|
||||
R = byte.Parse(values[0]);
|
||||
G = byte.Parse(values[1]);
|
||||
B = byte.Parse(values[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Invalid color, expected hex or value encoded (e.g. '#7248BD', '(114, 72,189)') got '{color}'", nameof(color));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hash code for the color structure
|
||||
/// </summary>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hashCode = R.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ G.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ B.GetHashCode();
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the specified color is equal to the current color.
|
||||
/// </summary>
|
||||
public bool Equals(RgbColor other) => R == other.R && G == other.G && B == other.B;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the specified object is equal to the current color.
|
||||
/// </summary>
|
||||
public override bool Equals(object obj) => !ReferenceEquals(null, obj) && obj is RgbColor rgb && Equals(rgb);
|
||||
|
||||
/// <summary>
|
||||
/// Compares two colors for exact equality
|
||||
/// </summary>
|
||||
public static bool operator ==(RgbColor left, RgbColor right) => left.Equals(right);
|
||||
|
||||
/// <summary>
|
||||
/// Compares two colors for inequality
|
||||
/// </summary>
|
||||
public static bool operator !=(RgbColor left, RgbColor right) => !left.Equals(right);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the color encoded as a hex string (e.g. '#ccffa0')
|
||||
/// </summary>
|
||||
public override string ToString() => $"#{R:x2}{G:x2}{B:x2}";
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the size of an object
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public struct Size
|
||||
{
|
||||
private double _width;
|
||||
private double _height;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a special size that represents a size with no area
|
||||
/// </summary>
|
||||
public static Size Empty { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current size is the <see cref="Empty"/> size
|
||||
/// </summary>
|
||||
public bool IsEmpty => double.IsNegativeInfinity(_width) && double.IsNegativeInfinity(_height);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width of the current size
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public double Width
|
||||
{
|
||||
get => _width;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
_width = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the height of the current size
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public double Height
|
||||
{
|
||||
get => _height;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
_height = value;
|
||||
}
|
||||
}
|
||||
|
||||
static Size()
|
||||
{
|
||||
Empty = new Size
|
||||
{
|
||||
_width = double.NegativeInfinity,
|
||||
_height = double.NegativeInfinity
|
||||
};
|
||||
}
|
||||
|
||||
public Size(double width, double height)
|
||||
{
|
||||
if (width < 0) {
|
||||
throw new ArgumentOutOfRangeException(nameof(width));
|
||||
}
|
||||
if (height < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(height));
|
||||
}
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the type of spot color
|
||||
/// </summary>
|
||||
public enum SpotColorType
|
||||
{
|
||||
/// <summary>
|
||||
/// Pantone proprietary color space
|
||||
/// </summary>
|
||||
Pantone,
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
Generic
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a spot color, composed of a type and a descriptor specific to that type
|
||||
/// </summary>
|
||||
public struct SpotColor : IEquatable<SpotColor>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the type of the spot color
|
||||
/// </summary>
|
||||
public readonly SpotColorType SpotColorType;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ink name of the spot color
|
||||
/// </summary>
|
||||
public readonly string InkName;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of spot color of a specific type and descriptor
|
||||
/// </summary>
|
||||
public SpotColor(SpotColorType spotColorType, string inkName)
|
||||
{
|
||||
SpotColorType = spotColorType;
|
||||
InkName = inkName ?? throw new ArgumentNullException(nameof(inkName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of spot color by parsing the specified color string
|
||||
/// </summary>
|
||||
/// <param name="color">string representation to parse the type and descriptor from</param>
|
||||
public SpotColor(string color)
|
||||
{
|
||||
if (color == null) throw new ArgumentNullException(nameof(color));
|
||||
if (color.StartsWith("(") && color.EndsWith(")"))
|
||||
{
|
||||
color = color.Substring(1, color.Length - 2);
|
||||
}
|
||||
var splitIndex = color.IndexOf('-');
|
||||
if (splitIndex < 0)
|
||||
{
|
||||
throw new ArgumentException(nameof(color));
|
||||
}
|
||||
var spotColorTypeStr = color.Substring(0, splitIndex);
|
||||
if (!Enum.TryParse(spotColorTypeStr, true, out SpotColorType))
|
||||
{
|
||||
throw new ArgumentException($"Invalid spot color type '{spotColorTypeStr}'", nameof(color));
|
||||
}
|
||||
InkName = color.Substring(splitIndex + 1);
|
||||
if (string.IsNullOrWhiteSpace(InkName))
|
||||
{
|
||||
throw new ArgumentException("Missing spot color value", nameof(color));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the string representation of the color
|
||||
/// </summary>
|
||||
public override string ToString() => $"{SpotColorType}-{InkName}";
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the specified color is equal to the current color.
|
||||
/// </summary>
|
||||
public bool Equals(SpotColor other) => SpotColorType == other.SpotColorType && string.Equals(InkName, other.InkName);
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the specified object is equal to the current color.
|
||||
/// </summary>
|
||||
public override bool Equals(object obj) => !ReferenceEquals(null, obj) && obj is SpotColor spot && Equals(spot);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hash code for the color structure
|
||||
/// </summary>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return ((int)SpotColorType * 397) ^ (InkName != null ? InkName.GetHashCode() : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares two colors for exact equality
|
||||
/// </summary>
|
||||
public static bool operator ==(SpotColor left, SpotColor right) => left.Equals(right);
|
||||
|
||||
/// <summary>
|
||||
/// Compares two colors for inequality
|
||||
/// </summary>
|
||||
public static bool operator !=(SpotColor left, SpotColor right) => !left.Equals(right);
|
||||
}
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using ceTe.DynamicPDF;
|
||||
using ceTe.DynamicPDF.PageElements;
|
||||
using Xunit;
|
||||
using PdfSpotColorInk = ceTe.DynamicPDF.SpotColorInk;
|
||||
using PdfSpotColor = ceTe.DynamicPDF.SpotColor;
|
||||
using EquinoxLabs.SVGSharpie.DynamicPDF.Core;
|
||||
using Rectangle = EquinoxLabs.SVGSharpie.DynamicPDF.Core.Rectangle;
|
||||
|
||||
namespace EquinoxLabs.SVGSharpie.DynamicPDF.Tests
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ namespace EquinoxLabs.SVGSharpie.DynamicPDF.Tests
|
|||
var spotColor = new PdfSpotColor(1, spotColorInk);
|
||||
Page page = new Page( PageSize.Letter, PageOrientation.Portrait, 54.0f );
|
||||
var svgDocument = SvgDocument.Parse(File.ReadAllText(svgFilePath));
|
||||
var pageElement = SvgImageRenderer.CreateSvgImagePageElement(svgDocument, new Rectangle(0, 0, 300, 300), PNI.Apollo.Render.Services.DynamicPdf.PageElements.HorizontalAlignment.Center, PNI.Apollo.Render.Services.DynamicPdf.PageElements.VerticalAlignment.Center, spotColor);
|
||||
var pageElement = Renderer.CreateSvgImagePageElement(svgDocument, new Rectangle(0, 0, 300, 300), HorizontalAlignment.Center, VerticalAlignment.Center, spotColor);
|
||||
page.Elements.Add(pageElement);
|
||||
document.Pages.Add(page);
|
||||
document.Draw(System.IO.Path.Combine(System.IO.Path.GetDirectoryName(svgFilePath), System.IO.Path.GetFileNameWithoutExtension(svgFilePath) + ".pdf"));
|
||||
|
|
Загрузка…
Ссылка в новой задаче