mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-10-15 19:54:52 +08:00
Merge branch 'master' into master
This commit is contained in:
160
src/UglyToad.PdfPig/Graphics/ColorSpaceContext.cs
Normal file
160
src/UglyToad.PdfPig/Graphics/ColorSpaceContext.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
namespace UglyToad.PdfPig.Graphics
|
||||
{
|
||||
using System;
|
||||
using Colors;
|
||||
using Tokens;
|
||||
|
||||
internal class ColorSpaceContext : IColorSpaceContext
|
||||
{
|
||||
private readonly Func<CurrentGraphicsState> currentStateFunc;
|
||||
|
||||
public ColorSpace CurrentStrokingColorSpace { get; private set; } = ColorSpace.DeviceGray;
|
||||
|
||||
public ColorSpace CurrentNonStrokingColorSpace { get; private set; } = ColorSpace.DeviceGray;
|
||||
|
||||
public ColorSpaceContext(Func<CurrentGraphicsState> currentStateFunc)
|
||||
{
|
||||
this.currentStateFunc = currentStateFunc ?? throw new ArgumentNullException(nameof(currentStateFunc));
|
||||
}
|
||||
|
||||
public void SetStrokingColorspace(NameToken colorspace)
|
||||
{
|
||||
if (colorspace.TryMapToColorSpace(out var colorspaceActual))
|
||||
{
|
||||
CurrentStrokingColorSpace = colorspaceActual;
|
||||
switch (colorspaceActual)
|
||||
{
|
||||
case ColorSpace.DeviceGray:
|
||||
currentStateFunc().CurrentStrokingColor = GrayColor.Black;
|
||||
break;
|
||||
case ColorSpace.DeviceRGB:
|
||||
currentStateFunc().CurrentStrokingColor = RGBColor.Black;
|
||||
break;
|
||||
case ColorSpace.DeviceCMYK:
|
||||
currentStateFunc().CurrentStrokingColor = CMYKColor.Black;
|
||||
break;
|
||||
default:
|
||||
currentStateFunc().CurrentStrokingColor = GrayColor.Black;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentStrokingColorSpace = ColorSpace.DeviceGray;
|
||||
currentStateFunc().CurrentStrokingColor = GrayColor.Black;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetNonStrokingColorspace(NameToken colorspace)
|
||||
{
|
||||
if (colorspace.TryMapToColorSpace(out var colorspaceActual))
|
||||
{
|
||||
CurrentNonStrokingColorSpace = colorspaceActual;
|
||||
switch (colorspaceActual)
|
||||
{
|
||||
case ColorSpace.DeviceGray:
|
||||
currentStateFunc().CurrentNonStrokingColor = GrayColor.Black;
|
||||
break;
|
||||
case ColorSpace.DeviceRGB:
|
||||
currentStateFunc().CurrentNonStrokingColor = RGBColor.Black;
|
||||
break;
|
||||
case ColorSpace.DeviceCMYK:
|
||||
currentStateFunc().CurrentNonStrokingColor = CMYKColor.Black;
|
||||
break;
|
||||
default:
|
||||
currentStateFunc().CurrentNonStrokingColor = GrayColor.Black;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentNonStrokingColorSpace = ColorSpace.DeviceGray;
|
||||
currentStateFunc().CurrentNonStrokingColor = GrayColor.Black;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetStrokingColorGray(decimal gray)
|
||||
{
|
||||
CurrentStrokingColorSpace = ColorSpace.DeviceGray;
|
||||
|
||||
if (gray == 0)
|
||||
{
|
||||
currentStateFunc().CurrentStrokingColor = GrayColor.Black;
|
||||
}
|
||||
else if (gray == 1)
|
||||
{
|
||||
currentStateFunc().CurrentStrokingColor = GrayColor.White;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentStateFunc().CurrentStrokingColor = new GrayColor(gray);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetStrokingColorRgb(decimal r, decimal g, decimal b)
|
||||
{
|
||||
CurrentStrokingColorSpace = ColorSpace.DeviceRGB;
|
||||
|
||||
if (r == 0 && g == 0 && b == 0)
|
||||
{
|
||||
currentStateFunc().CurrentStrokingColor = RGBColor.Black;
|
||||
}
|
||||
else if (r == 1 && g == 1 && b == 1)
|
||||
{
|
||||
currentStateFunc().CurrentStrokingColor = RGBColor.White;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentStateFunc().CurrentStrokingColor = new RGBColor(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetStrokingColorCmyk(decimal c, decimal m, decimal y, decimal k)
|
||||
{
|
||||
CurrentStrokingColorSpace = ColorSpace.DeviceCMYK;
|
||||
currentStateFunc().CurrentStrokingColor = new CMYKColor(c, m, y, k);
|
||||
}
|
||||
|
||||
public void SetNonStrokingColorGray(decimal gray)
|
||||
{
|
||||
CurrentNonStrokingColorSpace = ColorSpace.DeviceGray;
|
||||
|
||||
if (gray == 0)
|
||||
{
|
||||
currentStateFunc().CurrentNonStrokingColor = GrayColor.Black;
|
||||
}
|
||||
else if (gray == 1)
|
||||
{
|
||||
currentStateFunc().CurrentNonStrokingColor = GrayColor.White;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentStateFunc().CurrentNonStrokingColor = new GrayColor(gray);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetNonStrokingColorRgb(decimal r, decimal g, decimal b)
|
||||
{
|
||||
CurrentNonStrokingColorSpace = ColorSpace.DeviceRGB;
|
||||
|
||||
if (r == 0 && g == 0 && b == 0)
|
||||
{
|
||||
currentStateFunc().CurrentNonStrokingColor = RGBColor.Black;
|
||||
}
|
||||
else if (r == 1 && g == 1 && b == 1)
|
||||
{
|
||||
currentStateFunc().CurrentNonStrokingColor = RGBColor.White;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentStateFunc().CurrentNonStrokingColor = new RGBColor(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetNonStrokingColorCmyk(decimal c, decimal m, decimal y, decimal k)
|
||||
{
|
||||
CurrentNonStrokingColorSpace = ColorSpace.DeviceCMYK;
|
||||
currentStateFunc().CurrentNonStrokingColor = new CMYKColor(c, m, y, k);
|
||||
}
|
||||
}
|
||||
}
|
106
src/UglyToad.PdfPig/Graphics/Colors/CMYKColor.cs
Normal file
106
src/UglyToad.PdfPig/Graphics/Colors/CMYKColor.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UglyToad.PdfPig.Graphics.Colors
|
||||
{
|
||||
/// <summary>
|
||||
/// A color with cyan, magenta, yellow and black (K) components.
|
||||
/// </summary>
|
||||
public class CMYKColor : IColor, IEquatable<CMYKColor>
|
||||
{
|
||||
/// <summary>
|
||||
/// CMYK Black value (0, 0, 0, 1).
|
||||
/// </summary>
|
||||
public static IColor Black { get; } = new CMYKColor(0, 0, 0, 1);
|
||||
|
||||
/// <summary>
|
||||
/// CMYK White value (all 0).
|
||||
/// </summary>
|
||||
public static IColor White { get; } = new CMYKColor(0, 0, 0, 0);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ColorSpace ColorSpace { get; } = ColorSpace.DeviceCMYK;
|
||||
|
||||
/// <summary>
|
||||
/// The cyan value.
|
||||
/// </summary>
|
||||
public decimal C { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The magenta value.
|
||||
/// </summary>
|
||||
public decimal M { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The yellow value.
|
||||
/// </summary>
|
||||
public decimal Y { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The black value.
|
||||
/// </summary>
|
||||
public decimal K { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="CMYKColor"/>.
|
||||
/// </summary>
|
||||
public CMYKColor(decimal c, decimal m, decimal y, decimal k)
|
||||
{
|
||||
C = c;
|
||||
M = m;
|
||||
Y = y;
|
||||
K = k;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public (decimal r, decimal g, decimal b) ToRGBValues()
|
||||
{
|
||||
return ((1 - C) * (1 - K),
|
||||
(1 - M) * (1 - K),
|
||||
(1 - Y) * (1 - K));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as CMYKColor);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(CMYKColor other)
|
||||
{
|
||||
return other != null &&
|
||||
C == other.C &&
|
||||
M == other.M &&
|
||||
Y == other.Y &&
|
||||
K == other.K;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashCode = -492570696;
|
||||
hashCode = hashCode * -1521134295 + C.GetHashCode();
|
||||
hashCode = hashCode * -1521134295 + M.GetHashCode();
|
||||
hashCode = hashCode * -1521134295 + Y.GetHashCode();
|
||||
hashCode = hashCode * -1521134295 + K.GetHashCode();
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Equals.
|
||||
/// </summary>
|
||||
public static bool operator ==(CMYKColor color1, CMYKColor color2) => EqualityComparer<CMYKColor>.Default.Equals(color1, color2);
|
||||
|
||||
/// <summary>
|
||||
/// Not Equals.
|
||||
/// </summary>
|
||||
public static bool operator !=(CMYKColor color1, CMYKColor color2) => !(color1 == color2);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"CMYK: ({C}, {M}, {Y}, {K})";
|
||||
}
|
||||
}
|
||||
}
|
74
src/UglyToad.PdfPig/Graphics/Colors/ColorSpace.cs
Normal file
74
src/UglyToad.PdfPig/Graphics/Colors/ColorSpace.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Colors
|
||||
{
|
||||
/// <summary>
|
||||
/// Color values in a PDF are interpreted according to the current color space.
|
||||
/// Color spaces enable a PDF to specify abstract colors in a device independent way.
|
||||
/// </summary>
|
||||
public enum ColorSpace
|
||||
{
|
||||
/// <summary>
|
||||
/// Grayscale. Controls the intensity of achromatic light on a scale from black to white.
|
||||
/// </summary>
|
||||
DeviceGray = 0,
|
||||
/// <summary>
|
||||
/// RGB. Controls the intensities of red, green and blue light.
|
||||
/// </summary>
|
||||
DeviceRGB = 1,
|
||||
/// <summary>
|
||||
/// CMYK. Controls the concentrations of cyan, magenta, yellow and black (K) inks.
|
||||
/// </summary>
|
||||
DeviceCMYK = 2,
|
||||
/// <summary>
|
||||
/// CIE (Commission Internationale de l'Éclairage) colorspace.
|
||||
/// Specifies color related to human visual perception with the aim of producing consistent color on different output devices.
|
||||
/// CalGray - Special case of the CIE colorspace using a single channel (A) and a single transformation.
|
||||
/// A represents the gray component of a calibrated gray space in the range 0 to 1.
|
||||
/// </summary>
|
||||
CalGray = 3,
|
||||
/// <summary>
|
||||
/// CIE (Commission Internationale de l'Éclairage) colorspace.
|
||||
/// Specifies color related to human visual perception with the aim of producing consistent color on different output devices.
|
||||
/// CalRGB - A CIE ABC color space with a single transformation.
|
||||
/// A, B and C represent red, green and blue color values in the range 0 to 1.
|
||||
/// </summary>
|
||||
CalRGB = 4,
|
||||
/// <summary>
|
||||
/// CIE (Commission Internationale de l'Éclairage) colorspace.
|
||||
/// Specifies color related to human visual perception with the aim of producing consistent color on different output devices.
|
||||
/// Lab - A CIE ABC color space with two transforms. A, B and C represent the L*, a* and b*
|
||||
/// components of a CIE 1976 L*a*b* space. The range of A (L*) is 0 to 100.
|
||||
/// The range of B (a*) and C (b*) are defined by the Range of the color space.
|
||||
/// </summary>
|
||||
Lab = 5,
|
||||
/// <summary>
|
||||
/// ICC (International Color Consortium) colorspace.
|
||||
/// ICC - Colorspace specified by a sequence of bytes which are interpreted according to the
|
||||
/// ICC specification.
|
||||
/// </summary>
|
||||
ICCBased = 6,
|
||||
/// <summary>
|
||||
/// An Indexed color space allows a PDF content stream to use small integers as indices into a color map or color table of arbitrary colors in some other space.
|
||||
/// A PDF consumer application treats each sample value as an index into the color table and uses the color value it finds there.
|
||||
/// </summary>
|
||||
Indexed = 7,
|
||||
/// <summary>
|
||||
/// Enables a PDF content stream to paint an area with a pattern rather than a single color.
|
||||
/// The pattern may be either a tiling pattern (type 1) or a shading pattern (type 2).
|
||||
/// </summary>
|
||||
Pattern = 8,
|
||||
/// <summary>
|
||||
/// Provides a means for specifying the use of additional colorants or for isolating the control of individual color components of
|
||||
/// a device color space for a subtractive device.
|
||||
/// When such a space is the current color space, the current color is a single-component value, called a tint,
|
||||
/// that controls the application of the given colorant or color components only.
|
||||
/// </summary>
|
||||
Separation = 9,
|
||||
/// <summary>
|
||||
/// Can contain an arbitrary number of color components. They provide greater flexibility than is possible with standard device color
|
||||
/// spaces such as <see cref="DeviceCMYK"/> or with individual <see cref="Separation"/> color spaces.
|
||||
/// For example, it is possible to create a DeviceN color space consisting of only the cyan, magenta, and yellow color components,
|
||||
/// with the black component excluded.
|
||||
/// </summary>
|
||||
DeviceN = 10
|
||||
}
|
||||
}
|
130
src/UglyToad.PdfPig/Graphics/Colors/ColorSpaceExtensions.cs
Normal file
130
src/UglyToad.PdfPig/Graphics/Colors/ColorSpaceExtensions.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Colors
|
||||
{
|
||||
using System;
|
||||
using Tokens;
|
||||
|
||||
/// <summary>
|
||||
/// Provides utility extension methods for dealing with <see cref="ColorSpace"/>s.
|
||||
/// </summary>
|
||||
public static class ColorSpaceExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the corresponding <see cref="ColorSpaceFamily"/> for a given <see cref="ColorSpace"/>.
|
||||
/// </summary>
|
||||
public static ColorSpaceFamily GetFamily(this ColorSpace colorSpace)
|
||||
{
|
||||
switch (colorSpace)
|
||||
{
|
||||
case ColorSpace.DeviceGray:
|
||||
case ColorSpace.DeviceRGB:
|
||||
case ColorSpace.DeviceCMYK:
|
||||
return ColorSpaceFamily.Device;
|
||||
case ColorSpace.CalGray:
|
||||
case ColorSpace.CalRGB:
|
||||
case ColorSpace.Lab:
|
||||
case ColorSpace.ICCBased:
|
||||
return ColorSpaceFamily.CIEBased;
|
||||
case ColorSpace.Indexed:
|
||||
case ColorSpace.Pattern:
|
||||
case ColorSpace.Separation:
|
||||
case ColorSpace.DeviceN:
|
||||
return ColorSpaceFamily.Special;
|
||||
default:
|
||||
throw new ArgumentException($"Unrecognized colorspace: {colorSpace}.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps from a <see cref="NameToken"/> to the corresponding <see cref="ColorSpace"/> if one exists.
|
||||
/// </summary>
|
||||
public static bool TryMapToColorSpace(this NameToken name, out ColorSpace colorspace)
|
||||
{
|
||||
colorspace = ColorSpace.DeviceGray;
|
||||
|
||||
if (name.Data == NameToken.Devicegray.Data)
|
||||
{
|
||||
colorspace = ColorSpace.DeviceGray;
|
||||
}
|
||||
else if (name.Data == NameToken.Devicergb.Data)
|
||||
{
|
||||
colorspace = ColorSpace.DeviceRGB;
|
||||
}
|
||||
else if (name.Data == NameToken.Devicecmyk.Data)
|
||||
{
|
||||
colorspace = ColorSpace.DeviceCMYK;
|
||||
}
|
||||
else if (name.Data == NameToken.Calgray.Data)
|
||||
{
|
||||
colorspace = ColorSpace.CalGray;
|
||||
}
|
||||
else if (name.Data == NameToken.Calrgb.Data)
|
||||
{
|
||||
colorspace = ColorSpace.CalRGB;
|
||||
}
|
||||
else if (name.Data == NameToken.Lab.Data)
|
||||
{
|
||||
colorspace = ColorSpace.Lab;
|
||||
}
|
||||
else if (name.Data == NameToken.Iccbased.Data)
|
||||
{
|
||||
colorspace = ColorSpace.ICCBased;
|
||||
}
|
||||
else if (name.Data == NameToken.Indexed.Data)
|
||||
{
|
||||
colorspace = ColorSpace.Indexed;
|
||||
}
|
||||
else if (name.Data == NameToken.Pattern.Data)
|
||||
{
|
||||
colorspace = ColorSpace.Pattern;
|
||||
}
|
||||
else if (name.Data == NameToken.Separation.Data)
|
||||
{
|
||||
colorspace = ColorSpace.Separation;
|
||||
}
|
||||
else if (name.Data == NameToken.Devicen.Data)
|
||||
{
|
||||
colorspace = ColorSpace.DeviceN;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the corresponding <see cref="NameToken"/> for a given <see cref="ColorSpace"/>.
|
||||
/// </summary>
|
||||
public static NameToken ToNameToken(this ColorSpace colorSpace)
|
||||
{
|
||||
switch (colorSpace)
|
||||
{
|
||||
case ColorSpace.DeviceGray:
|
||||
return NameToken.Devicegray;
|
||||
case ColorSpace.DeviceRGB:
|
||||
return NameToken.Devicergb;
|
||||
case ColorSpace.DeviceCMYK:
|
||||
return NameToken.Devicecmyk;
|
||||
case ColorSpace.CalGray:
|
||||
return NameToken.Calgray;
|
||||
case ColorSpace.CalRGB:
|
||||
return NameToken.Calrgb;
|
||||
case ColorSpace.Lab:
|
||||
return NameToken.Lab;
|
||||
case ColorSpace.ICCBased:
|
||||
return NameToken.Iccbased;
|
||||
case ColorSpace.Indexed:
|
||||
return NameToken.Indexed;
|
||||
case ColorSpace.Pattern:
|
||||
return NameToken.Pattern;
|
||||
case ColorSpace.Separation:
|
||||
return NameToken.Separation;
|
||||
case ColorSpace.DeviceN:
|
||||
return NameToken.Devicen;
|
||||
default:
|
||||
throw new ArgumentException($"Unrecognized colorspace: {colorSpace}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
26
src/UglyToad.PdfPig/Graphics/Colors/ColorSpaceFamily.cs
Normal file
26
src/UglyToad.PdfPig/Graphics/Colors/ColorSpaceFamily.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Colors
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="ColorSpace"/>s can be classified into colorspace families.
|
||||
/// <see cref="ColorSpace"/>s within the same family share general characteristics.
|
||||
/// </summary>
|
||||
public enum ColorSpaceFamily
|
||||
{
|
||||
/// <summary>
|
||||
/// Device colorspaces directly specify colors or shades of gray that the output device
|
||||
/// should produce.
|
||||
/// </summary>
|
||||
Device,
|
||||
/// <summary>
|
||||
/// CIE-based color spaces are based on an international standard for color specification created by
|
||||
/// the Commission Internationale de l'Éclairage (International Commission on Illumination) (CIE).
|
||||
/// These spaces specify colors in a way that is independent of the characteristics of any particular output device.
|
||||
/// </summary>
|
||||
CIEBased,
|
||||
/// <summary>
|
||||
/// Special color spaces add features or properties to an underlying color space.
|
||||
/// They include facilities for patterns, color mapping, separations, and high-fidelity and multitone color.
|
||||
/// </summary>
|
||||
Special
|
||||
}
|
||||
}
|
75
src/UglyToad.PdfPig/Graphics/Colors/GrayColor.cs
Normal file
75
src/UglyToad.PdfPig/Graphics/Colors/GrayColor.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UglyToad.PdfPig.Graphics.Colors
|
||||
{
|
||||
/// <summary>
|
||||
/// A grayscale color with a single gray component.
|
||||
/// </summary>
|
||||
public class GrayColor : IColor, IEquatable<GrayColor>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gray Black value (0).
|
||||
/// </summary>
|
||||
public static GrayColor Black { get; } = new GrayColor(0);
|
||||
|
||||
/// <summary>
|
||||
/// Gray White value (1).
|
||||
/// </summary>
|
||||
public static GrayColor White { get; } = new GrayColor(1);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ColorSpace ColorSpace { get; } = ColorSpace.DeviceGray;
|
||||
|
||||
/// <summary>
|
||||
/// The gray value between 0 and 1.
|
||||
/// </summary>
|
||||
public decimal Gray { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="GrayColor"/>.
|
||||
/// </summary>
|
||||
public GrayColor(decimal gray)
|
||||
{
|
||||
Gray = gray;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public (decimal r, decimal g, decimal b) ToRGBValues()
|
||||
{
|
||||
return (Gray, Gray, Gray);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as GrayColor);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(GrayColor other)
|
||||
{
|
||||
return other != null &&
|
||||
Gray == other.Gray;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode() => Gray.GetHashCode();
|
||||
|
||||
/// <summary>
|
||||
/// Equals.
|
||||
/// </summary>
|
||||
public static bool operator ==(GrayColor color1, GrayColor color2) => EqualityComparer<GrayColor>.Default.Equals(color1, color2);
|
||||
|
||||
/// <summary>
|
||||
/// Not Equals.
|
||||
/// </summary>
|
||||
public static bool operator !=(GrayColor color1, GrayColor color2) => !(color1 == color2);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Gray: {Gray}";
|
||||
}
|
||||
}
|
||||
}
|
18
src/UglyToad.PdfPig/Graphics/Colors/IColor.cs
Normal file
18
src/UglyToad.PdfPig/Graphics/Colors/IColor.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Colors
|
||||
{
|
||||
/// <summary>
|
||||
/// A color used for text or paths in a PDF.
|
||||
/// </summary>
|
||||
public interface IColor
|
||||
{
|
||||
/// <summary>
|
||||
/// The colorspace used for this color.
|
||||
/// </summary>
|
||||
ColorSpace ColorSpace { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The color as RGB values (between 0 and 1).
|
||||
/// </summary>
|
||||
(decimal r, decimal g, decimal b) ToRGBValues();
|
||||
}
|
||||
}
|
98
src/UglyToad.PdfPig/Graphics/Colors/RGBColor.cs
Normal file
98
src/UglyToad.PdfPig/Graphics/Colors/RGBColor.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
namespace UglyToad.PdfPig.Graphics.Colors
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// A color with red, green and blue components.
|
||||
/// </summary>
|
||||
public class RGBColor : IColor, IEquatable<RGBColor>
|
||||
{
|
||||
/// <summary>
|
||||
/// RGB Black value (all 0).
|
||||
/// </summary>
|
||||
public static RGBColor Black = new RGBColor(0, 0, 0);
|
||||
|
||||
/// <summary>
|
||||
/// RGB White value (all 1).
|
||||
/// </summary>
|
||||
public static RGBColor White = new RGBColor(1, 1, 1);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ColorSpace ColorSpace { get; } = ColorSpace.DeviceRGB;
|
||||
|
||||
/// <summary>
|
||||
/// The red value between 0 and 1.
|
||||
/// </summary>
|
||||
public decimal R { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The green value between 0 and 1.
|
||||
/// </summary>
|
||||
public decimal G { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The blue value between 0 and 1.
|
||||
/// </summary>
|
||||
public decimal B { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="RGBColor"/>.
|
||||
/// </summary>
|
||||
/// <param name="r">The red value between 0 and 1.</param>
|
||||
/// <param name="g">The green value between 0 and 1.</param>
|
||||
/// <param name="b">The blue value between 0 and 1.</param>
|
||||
public RGBColor(decimal r, decimal g, decimal b)
|
||||
{
|
||||
R = r;
|
||||
G = g;
|
||||
B = b;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public (decimal r, decimal g, decimal b) ToRGBValues() => (R, G, B);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is RGBColor color)
|
||||
{
|
||||
return Equals(color);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Whether 2 RGB colors are equal across all channels.
|
||||
/// </summary>
|
||||
public bool Equals(RGBColor other)
|
||||
{
|
||||
return other != null &&
|
||||
R == other.R &&
|
||||
G == other.G &&
|
||||
B == other.B;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode() => (R, G, B).GetHashCode();
|
||||
|
||||
/// <summary>
|
||||
/// Equals.
|
||||
/// </summary>
|
||||
public static bool operator ==(RGBColor color1, RGBColor color2) =>
|
||||
EqualityComparer<RGBColor>.Default.Equals(color1, color2);
|
||||
|
||||
/// <summary>
|
||||
/// Not Equals.
|
||||
/// </summary>
|
||||
public static bool operator !=(RGBColor color1, RGBColor color2) => !(color1 == color2);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"RGB: ({R}, {G}, {B})";
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
namespace UglyToad.PdfPig.Graphics
|
||||
{
|
||||
using Tokens;
|
||||
|
||||
internal class ColorspaceContext : IColorspaceContext
|
||||
{
|
||||
public void SetStrokingColorspace(NameToken colorspace)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetNonStrokingColorspace(NameToken colorspace)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetStrokingColorGray(decimal gray)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetStrokingColorRgb(decimal r, decimal g, decimal b)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetStrokingColorCmyk(decimal c, decimal m, decimal y, decimal k)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetNonStrokingColorGray(decimal gray)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetNonStrokingColorRgb(decimal r, decimal g, decimal b)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetNonStrokingColorCmyk(decimal c, decimal m, decimal y, decimal k)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,6 +3,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Colors;
|
||||
using Content;
|
||||
using Core;
|
||||
using Fonts;
|
||||
@@ -42,7 +43,7 @@
|
||||
|
||||
public PdfPath CurrentPath { get; private set; }
|
||||
|
||||
public IColorspaceContext ColorspaceContext { get; } = new ColorspaceContext();
|
||||
public IColorSpaceContext ColorSpaceContext { get; }
|
||||
|
||||
public PdfPoint CurrentPosition { get; set; }
|
||||
|
||||
@@ -69,6 +70,7 @@
|
||||
this.xObjectFactory = xObjectFactory;
|
||||
this.log = log;
|
||||
graphicsStack.Push(new CurrentGraphicsState());
|
||||
ColorSpaceContext = new ColorSpaceContext(GetCurrentState);
|
||||
}
|
||||
|
||||
public PageContent Process(IReadOnlyList<IGraphicsStateOperation> operations)
|
||||
@@ -168,11 +170,28 @@
|
||||
.Transform(TextMatrices.TextMatrix
|
||||
.Transform(renderingMatrix
|
||||
.Transform(boundingBox.GlyphBounds)));
|
||||
|
||||
var transformedPdfBounds = rotation.Rotate(transformationMatrix)
|
||||
.Transform(TextMatrices.TextMatrix
|
||||
.Transform(renderingMatrix.Transform(new PdfRectangle(0, 0, boundingBox.Width, 0))));
|
||||
|
||||
ShowGlyph(font, transformedGlyphBounds, transformedPdfBounds.BottomLeft, transformedPdfBounds.BottomRight, transformedPdfBounds.Width, unicode, fontSize, pointSize, textSequence);
|
||||
// If the text rendering mode calls for filling, the current nonstroking color in the graphics state is used;
|
||||
// if it calls for stroking, the current stroking color is used.
|
||||
// In modes that perform both filling and stroking, the effect is as if each glyph outline were filled and then stroked in separate operations.
|
||||
// TODO: expose color as something more advanced
|
||||
var color = currentState.FontState.TextRenderingMode != TextRenderingMode.Stroke
|
||||
? currentState.CurrentNonStrokingColor
|
||||
: currentState.CurrentStrokingColor;
|
||||
|
||||
ShowGlyph(font, transformedGlyphBounds,
|
||||
transformedPdfBounds.BottomLeft,
|
||||
transformedPdfBounds.BottomRight,
|
||||
transformedPdfBounds.Width,
|
||||
unicode,
|
||||
fontSize,
|
||||
color,
|
||||
pointSize,
|
||||
textSequence);
|
||||
|
||||
decimal tx, ty;
|
||||
if (font.IsVertical)
|
||||
@@ -275,7 +294,7 @@
|
||||
|
||||
public void BeginSubpath()
|
||||
{
|
||||
CurrentPath = new PdfPath(CurrentTransformationMatrix);
|
||||
CurrentPath = new PdfPath();
|
||||
}
|
||||
|
||||
public void StrokePath(bool close)
|
||||
@@ -341,9 +360,25 @@
|
||||
TextMatrices.TextMatrix = newMatrix;
|
||||
}
|
||||
|
||||
private void ShowGlyph(IFont font, PdfRectangle glyphRectangle, PdfPoint startBaseLine, PdfPoint endBaseLine, decimal width, string unicode, decimal fontSize, decimal pointSize, int textSequence)
|
||||
private void ShowGlyph(IFont font, PdfRectangle glyphRectangle,
|
||||
PdfPoint startBaseLine,
|
||||
PdfPoint endBaseLine,
|
||||
decimal width,
|
||||
string unicode,
|
||||
decimal fontSize,
|
||||
IColor color,
|
||||
decimal pointSize,
|
||||
int textSequence)
|
||||
{
|
||||
var letter = new Letter(unicode, glyphRectangle, startBaseLine, endBaseLine, width, fontSize, font.Name.Data, pointSize, textSequence);
|
||||
var letter = new Letter(unicode, glyphRectangle,
|
||||
startBaseLine,
|
||||
endBaseLine,
|
||||
width,
|
||||
fontSize,
|
||||
font.Name.Data,
|
||||
color,
|
||||
pointSize,
|
||||
textSequence);
|
||||
|
||||
Letters.Add(letter);
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
// ReSharper disable RedundantDefaultMemberInitializer
|
||||
namespace UglyToad.PdfPig.Graphics
|
||||
{
|
||||
using Colors;
|
||||
using Core;
|
||||
using PdfPig.Core;
|
||||
|
||||
@@ -96,6 +97,16 @@ namespace UglyToad.PdfPig.Graphics
|
||||
/// </summary>
|
||||
public decimal Smoothness { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The current active stroking color for paths.
|
||||
/// </summary>
|
||||
public IColor CurrentStrokingColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current active non-stroking color for text and fill.
|
||||
/// </summary>
|
||||
public IColor CurrentNonStrokingColor { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -118,7 +129,9 @@ namespace UglyToad.PdfPig.Graphics
|
||||
NonStrokingOverprint = NonStrokingOverprint,
|
||||
OverprintMode = OverprintMode,
|
||||
Smoothness = Smoothness,
|
||||
StrokeAdjustment = StrokeAdjustment
|
||||
StrokeAdjustment = StrokeAdjustment,
|
||||
CurrentStrokingColor = CurrentStrokingColor,
|
||||
CurrentNonStrokingColor = CurrentNonStrokingColor
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -1,12 +1,23 @@
|
||||
namespace UglyToad.PdfPig.Graphics
|
||||
{
|
||||
using Colors;
|
||||
using Tokens;
|
||||
|
||||
/// <summary>
|
||||
/// Methods for manipulating and retrieving the current color state for a PDF content stream.
|
||||
/// </summary>
|
||||
public interface IColorspaceContext
|
||||
public interface IColorSpaceContext
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="ColorSpace"/> used for stroking operations.
|
||||
/// </summary>
|
||||
ColorSpace CurrentStrokingColorSpace { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ColorSpace"/> used for non-stroking operations.
|
||||
/// </summary>
|
||||
ColorSpace CurrentNonStrokingColorSpace { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the current color space to use for stroking operations.
|
||||
/// </summary>
|
||||
@@ -39,7 +50,7 @@
|
||||
/// <param name="y">Yellow - A number between 0 (minimum concentration) and 1 (maximum concentration).</param>
|
||||
/// <param name="k">Black - A number between 0 (minimum concentration) and 1 (maximum concentration).</param>
|
||||
void SetStrokingColorCmyk(decimal c, decimal m, decimal y, decimal k);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set the nonstroking color space to DeviceGray and set the gray level to use for nonstroking operations.
|
||||
/// </summary>
|
@@ -21,7 +21,7 @@
|
||||
/// <summary>
|
||||
/// The active colorspaces for this content stream.
|
||||
/// </summary>
|
||||
IColorspaceContext ColorspaceContext { get; }
|
||||
IColorSpaceContext ColorSpaceContext { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The current position.
|
||||
|
@@ -52,10 +52,13 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.CurrentPath.BezierCurveTo(ControlPoint1.X, ControlPoint1.Y,
|
||||
ControlPoint2.X, ControlPoint2.Y,
|
||||
End.X, End.Y);
|
||||
operationContext.CurrentPosition = End;
|
||||
var controlPoint1Transform = operationContext.CurrentTransformationMatrix.Transform(ControlPoint1);
|
||||
var controlPoint2Transform = operationContext.CurrentTransformationMatrix.Transform(ControlPoint2);
|
||||
var endTransform = operationContext.CurrentTransformationMatrix.Transform(End);
|
||||
operationContext.CurrentPath.BezierCurveTo(controlPoint1Transform.X, controlPoint1Transform.Y,
|
||||
controlPoint2Transform.X, controlPoint2Transform.Y,
|
||||
endTransform.X, endTransform.Y);
|
||||
operationContext.CurrentPosition = endTransform;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -44,12 +44,14 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.CurrentPath.BezierCurveTo(ControlPoint1.X, ControlPoint1.Y,
|
||||
End.X,
|
||||
End.Y,
|
||||
End.X,
|
||||
End.Y);
|
||||
operationContext.CurrentPosition = End;
|
||||
var controlPoint1Transform = operationContext.CurrentTransformationMatrix.Transform(ControlPoint1);
|
||||
var endTransform = operationContext.CurrentTransformationMatrix.Transform(End);
|
||||
operationContext.CurrentPath.BezierCurveTo(controlPoint1Transform.X, controlPoint1Transform.Y,
|
||||
endTransform.X,
|
||||
endTransform.Y,
|
||||
endTransform.X,
|
||||
endTransform.Y);
|
||||
operationContext.CurrentPosition = endTransform;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -51,7 +51,8 @@
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.BeginSubpath();
|
||||
operationContext.CurrentPath.Rectangle(LowerLeft.X, LowerLeft.Y, Width, Height);
|
||||
var lowerLeftTransform = operationContext.CurrentTransformationMatrix.Transform(LowerLeft);
|
||||
operationContext.CurrentPath.Rectangle(lowerLeftTransform.X, lowerLeftTransform.Y, Width, Height);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -44,13 +44,15 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
var controlPoint2Transform = operationContext.CurrentTransformationMatrix.Transform(ControlPoint2);
|
||||
var endTransform = operationContext.CurrentTransformationMatrix.Transform(End);
|
||||
operationContext.CurrentPath.BezierCurveTo(operationContext.CurrentPosition.X,
|
||||
operationContext.CurrentPosition.Y,
|
||||
ControlPoint2.X,
|
||||
ControlPoint2.Y,
|
||||
End.X,
|
||||
End.Y);
|
||||
operationContext.CurrentPosition = End;
|
||||
controlPoint2Transform.X,
|
||||
controlPoint2Transform.Y,
|
||||
endTransform.X,
|
||||
endTransform.Y);
|
||||
operationContext.CurrentPosition = endTransform;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -35,8 +35,9 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.CurrentPath.LineTo(End.X, End.Y);
|
||||
operationContext.CurrentPosition = End;
|
||||
var endPoint = operationContext.CurrentTransformationMatrix.Transform(new PdfPoint(End.X, End.Y));
|
||||
operationContext.CurrentPath.LineTo(endPoint.X, endPoint.Y);
|
||||
operationContext.CurrentPosition = endPoint;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -36,8 +36,9 @@
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.BeginSubpath();
|
||||
operationContext.CurrentPosition = Point;
|
||||
operationContext.CurrentPath.LineTo(Point.X, Point.Y);
|
||||
var pointTransform = operationContext.CurrentTransformationMatrix.Transform(Point);
|
||||
operationContext.CurrentPosition = pointTransform;
|
||||
operationContext.CurrentPath.MoveTo(pointTransform.X, pointTransform.Y);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -35,6 +35,20 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
switch (Operands.Count)
|
||||
{
|
||||
case 1:
|
||||
operationContext.ColorSpaceContext.SetNonStrokingColorGray(Operands[0]);
|
||||
break;
|
||||
case 3:
|
||||
operationContext.ColorSpaceContext.SetNonStrokingColorRgb(Operands[0], Operands[1], Operands[2]);
|
||||
break;
|
||||
case 4:
|
||||
operationContext.ColorSpaceContext.SetNonStrokingColorCmyk(Operands[0], Operands[1], Operands[2], Operands[3]);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -3,6 +3,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Colors;
|
||||
using Tokens;
|
||||
using Writer;
|
||||
|
||||
@@ -53,6 +54,25 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
if (operationContext.ColorSpaceContext.CurrentNonStrokingColorSpace.GetFamily() != ColorSpaceFamily.Device)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (Operands.Count)
|
||||
{
|
||||
case 1:
|
||||
operationContext.ColorSpaceContext.SetNonStrokingColorGray(Operands[0]);
|
||||
break;
|
||||
case 3:
|
||||
operationContext.ColorSpaceContext.SetNonStrokingColorRgb(Operands[0], Operands[1], Operands[2]);
|
||||
break;
|
||||
case 4:
|
||||
operationContext.ColorSpaceContext.SetNonStrokingColorCmyk(Operands[0], Operands[1], Operands[2], Operands[3]);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -54,7 +54,7 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.ColorspaceContext.SetNonStrokingColorCmyk(C, M, Y, K);
|
||||
operationContext.ColorSpaceContext.SetNonStrokingColorCmyk(C, M, Y, K);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -33,7 +33,7 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.ColorspaceContext.SetNonStrokingColorGray(Gray);
|
||||
operationContext.ColorSpaceContext.SetNonStrokingColorGray(Gray);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -47,7 +47,7 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.ColorspaceContext.SetNonStrokingColorRgb(R, G, B);
|
||||
operationContext.ColorSpaceContext.SetNonStrokingColorRgb(R, G, B);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -36,7 +36,7 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.ColorspaceContext.SetNonStrokingColorspace(Name);
|
||||
operationContext.ColorSpaceContext.SetNonStrokingColorspace(Name);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -38,13 +38,13 @@
|
||||
switch (Operands.Count)
|
||||
{
|
||||
case 1:
|
||||
operationContext.ColorspaceContext.SetStrokingColorGray(Operands[0]);
|
||||
operationContext.ColorSpaceContext.SetStrokingColorGray(Operands[0]);
|
||||
break;
|
||||
case 3:
|
||||
operationContext.ColorspaceContext.SetStrokingColorRgb(Operands[0], Operands[1], Operands[2]);
|
||||
operationContext.ColorSpaceContext.SetStrokingColorRgb(Operands[0], Operands[1], Operands[2]);
|
||||
break;
|
||||
case 4:
|
||||
operationContext.ColorspaceContext.SetStrokingColorCmyk(Operands[0], Operands[1], Operands[2], Operands[3]);
|
||||
operationContext.ColorSpaceContext.SetStrokingColorCmyk(Operands[0], Operands[1], Operands[2], Operands[3]);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
@@ -3,6 +3,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Colors;
|
||||
using Tokens;
|
||||
using Writer;
|
||||
|
||||
@@ -40,7 +41,7 @@
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SetStrokeColor"/>.
|
||||
/// Create a new <see cref="SetStrokeColorAdvanced"/>.
|
||||
/// </summary>
|
||||
/// <param name="operands">The color operands.</param>
|
||||
/// <param name="patternName">The pattern name.</param>
|
||||
@@ -53,6 +54,25 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
if (operationContext.ColorSpaceContext.CurrentStrokingColorSpace.GetFamily() != ColorSpaceFamily.Device)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (Operands.Count)
|
||||
{
|
||||
case 1:
|
||||
operationContext.ColorSpaceContext.SetStrokingColorGray(Operands[0]);
|
||||
break;
|
||||
case 3:
|
||||
operationContext.ColorSpaceContext.SetStrokingColorRgb(Operands[0], Operands[1], Operands[2]);
|
||||
break;
|
||||
case 4:
|
||||
operationContext.ColorSpaceContext.SetStrokingColorCmyk(Operands[0], Operands[1], Operands[2], Operands[3]);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -54,7 +54,7 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.ColorspaceContext.SetStrokingColorCmyk(C, M, Y, K);
|
||||
operationContext.ColorSpaceContext.SetStrokingColorCmyk(C, M, Y, K);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -33,7 +33,7 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.ColorspaceContext.SetStrokingColorGray(Gray);
|
||||
operationContext.ColorSpaceContext.SetStrokingColorGray(Gray);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -47,7 +47,7 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.ColorspaceContext.SetStrokingColorRgb(R, G, B);
|
||||
operationContext.ColorSpaceContext.SetStrokingColorRgb(R, G, B);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -36,7 +36,7 @@
|
||||
/// <inheritdoc />
|
||||
public void Run(IOperationContext operationContext)
|
||||
{
|
||||
operationContext.ColorspaceContext.SetStrokingColorspace(Name);
|
||||
operationContext.ColorSpaceContext.SetStrokingColorspace(Name);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@@ -126,11 +126,11 @@ namespace UglyToad.PdfPig.Graphics
|
||||
case SetNonStrokeColorAdvanced.Symbol:
|
||||
if (operands[operands.Count - 1] is NameToken scnLowerPatternName)
|
||||
{
|
||||
return new SetStrokeColorAdvanced(operands.Take(operands.Count - 1).Select(x => ((NumericToken)x).Data).ToList(), scnLowerPatternName);
|
||||
return new SetNonStrokeColorAdvanced(operands.Take(operands.Count - 1).Select(x => ((NumericToken)x).Data).ToList(), scnLowerPatternName);
|
||||
}
|
||||
else if (operands.All(x => x is NumericToken))
|
||||
{
|
||||
return new SetStrokeColorAdvanced(operands.Select(x => ((NumericToken)x).Data).ToList());
|
||||
return new SetNonStrokeColorAdvanced(operands.Select(x => ((NumericToken)x).Data).ToList());
|
||||
}
|
||||
|
||||
var errorMessageScnLower = string.Join(", ", operands.Select(x => x.ToString()));
|
||||
|
Reference in New Issue
Block a user