add color information to the operation context. create color classes for letters and paths to use

This commit is contained in:
Eliot Jones
2019-08-04 16:47:47 +01:00
parent 1d551d6de3
commit 0b9ae1db13
22 changed files with 323 additions and 25 deletions

View File

@@ -3,9 +3,10 @@
using System.Collections.Generic;
using PdfPig.Geometry;
using PdfPig.Graphics;
using PdfPig.Graphics.Colors;
using PdfPig.IO;
using PdfPig.Tokens;
using UglyToad.PdfPig.Core;
using PdfPig.Core;
internal class TestOperationContext : IOperationContext
{
@@ -17,14 +18,11 @@
public TextMatrices TextMatrices { get; set; }
= new TextMatrices();
public TransformationMatrix CurrentTransformationMatrix
{
get { return GetCurrentState().CurrentTransformationMatrix; }
}
public TransformationMatrix CurrentTransformationMatrix => GetCurrentState().CurrentTransformationMatrix;
public PdfPath CurrentPath { get; set; }
public IColorspaceContext ColorspaceContext { get; } = new ColorspaceContext();
public IColorSpaceContext ColorSpaceContext { get; } = new ColorSpaceContext();
public PdfPoint CurrentPosition { get; set; }
@@ -81,8 +79,16 @@
}
}
public class TestColorspaceContext : IColorspaceContext
public class TestColorSpaceContext : IColorSpaceContext
{
public ColorSpace CurrentStrokingColorSpace { get; } = ColorSpace.DeviceGray;
public ColorSpace CurrentNonStrokingColorSpace { get; } = ColorSpace.DeviceGray;
public IColor CurrentStrokingColor { get; } = GrayColor.Black;
public IColor CurrentNonStrokingColor { get; } = GrayColor.Black;
public void SetStrokingColorspace(NameToken colorspace)
{
}

View File

@@ -80,6 +80,7 @@
"UglyToad.PdfPig.Graphics.Colors.ColorSpace",
"UglyToad.PdfPig.Graphics.Colors.ColorSpaceExtensions",
"UglyToad.PdfPig.Graphics.Colors.ColorSpaceFamily",
"UglyToad.PdfPig.Graphics.Colors.IColor",
"UglyToad.PdfPig.Graphics.Core.LineCapStyle",
"UglyToad.PdfPig.Graphics.Core.LineDashPattern",
"UglyToad.PdfPig.Graphics.Core.LineJoinStyle",
@@ -87,7 +88,7 @@
"UglyToad.PdfPig.Graphics.Core.TextRenderingMode",
"UglyToad.PdfPig.Graphics.CurrentFontState",
"UglyToad.PdfPig.Graphics.CurrentGraphicsState",
"UglyToad.PdfPig.Graphics.IColorspaceContext",
"UglyToad.PdfPig.Graphics.IColorSpaceContext",
"UglyToad.PdfPig.Graphics.IOperationContext",
"UglyToad.PdfPig.Graphics.Operations.ClippingPaths.ModifyClippingByEvenOddIntersect",
"UglyToad.PdfPig.Graphics.Operations.ClippingPaths.ModifyClippingByNonZeroWindingIntersect",

View File

@@ -0,0 +1,53 @@
namespace UglyToad.PdfPig.Graphics.Colors
{
/// <summary>
/// A color with cyan, magenta, yellow and black (K) components.
/// </summary>
internal class CMYKColor : IColor
{
public static IColor Black { get; } = new CMYKColor(0, 0, 0, 1);
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 ((255 * (1 - C) * (1 - K)) / 255m,
(255 * (1 - M) * (1 - K)) / 255m,
(255 * (1 - Y) * (1 - K)) / 255m);
}
}
}

View File

@@ -0,0 +1,33 @@
namespace UglyToad.PdfPig.Graphics.Colors
{
/// <summary>
/// A grayscale color with a single gray component.
/// </summary>
internal class GrayColor : IColor
{
public static GrayColor Black { get; } = new GrayColor(0);
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);
}
}
}

View 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();
}
}

View File

@@ -0,0 +1,45 @@
namespace UglyToad.PdfPig.Graphics.Colors
{
/// <summary>
/// A color with red, green and blue components.
/// </summary>
internal class RGBColor : IColor
{
public static RGBColor Black = new RGBColor(0, 0, 0);
public static RGBColor White = new RGBColor(1, 1, 1);
/// <inheritdoc/>
public ColorSpace ColorSpace { get; } = ColorSpace.DeviceRGB;
/// <summary>
/// The red value.
/// </summary>
public decimal R { get; }
/// <summary>
/// The green value.
/// </summary>
public decimal G { get; }
/// <summary>
/// The blue value.
/// </summary>
public decimal B { get; }
/// <summary>
/// Create a new <see cref="RGBColor"/>.
/// </summary>
public RGBColor(decimal r, decimal g, decimal b)
{
R = r;
G = g;
B = b;
}
/// <inheritdoc/>
public (decimal r, decimal g, decimal b) ToRGBValues()
{
return (R, G, B);
}
}
}

View File

@@ -1,39 +1,106 @@
namespace UglyToad.PdfPig.Graphics
{
using Colors;
using Tokens;
internal class ColorspaceContext : IColorspaceContext
internal class ColorSpaceContext : IColorSpaceContext
{
public ColorSpace CurrentStrokingColorSpace { get; private set; } = ColorSpace.DeviceGray;
public ColorSpace CurrentNonStrokingColorSpace { get; private set; } = ColorSpace.DeviceGray;
public IColor CurrentStrokingColor { get; private set; } = GrayColor.Black;
public IColor CurrentNonStrokingColor { get; private set; } = GrayColor.Black;
public void SetStrokingColorspace(NameToken colorspace)
{
if (colorspace.TryMapToColorSpace(out var colorspaceActual))
{
CurrentStrokingColorSpace = colorspaceActual;
switch (colorspaceActual)
{
case ColorSpace.DeviceGray:
CurrentStrokingColor = GrayColor.Black;
break;
case ColorSpace.DeviceRGB:
CurrentStrokingColor = RGBColor.Black;
break;
case ColorSpace.DeviceCMYK:
CurrentStrokingColor = CMYKColor.Black;
break;
default:
CurrentStrokingColor = GrayColor.Black;
break;
}
}
else
{
CurrentStrokingColorSpace = ColorSpace.DeviceGray;
CurrentStrokingColor = GrayColor.Black;
}
}
public void SetNonStrokingColorspace(NameToken colorspace)
{
if (colorspace.TryMapToColorSpace(out var colorspaceActual))
{
CurrentNonStrokingColorSpace = colorspaceActual;
switch (colorspaceActual)
{
case ColorSpace.DeviceGray:
CurrentNonStrokingColor = GrayColor.Black;
break;
case ColorSpace.DeviceRGB:
CurrentNonStrokingColor = RGBColor.Black;
break;
case ColorSpace.DeviceCMYK:
CurrentNonStrokingColor = CMYKColor.Black;
break;
default:
CurrentNonStrokingColor = GrayColor.Black;
break;
}
}
else
{
CurrentNonStrokingColorSpace = ColorSpace.DeviceGray;
CurrentNonStrokingColor = GrayColor.Black;
}
}
public void SetStrokingColorGray(decimal gray)
{
CurrentStrokingColorSpace = ColorSpace.DeviceGray;
CurrentStrokingColor = new GrayColor(gray);
}
public void SetStrokingColorRgb(decimal r, decimal g, decimal b)
{
CurrentStrokingColorSpace = ColorSpace.DeviceRGB;
CurrentStrokingColor = new RGBColor(r, g, b);
}
public void SetStrokingColorCmyk(decimal c, decimal m, decimal y, decimal k)
{
CurrentStrokingColorSpace = ColorSpace.DeviceCMYK;
CurrentStrokingColor = new CMYKColor(c, m, y, k);
}
public void SetNonStrokingColorGray(decimal gray)
{
CurrentNonStrokingColorSpace = ColorSpace.DeviceGray;
CurrentNonStrokingColor = new GrayColor(gray);
}
public void SetNonStrokingColorRgb(decimal r, decimal g, decimal b)
{
CurrentNonStrokingColorSpace = ColorSpace.DeviceRGB;
CurrentNonStrokingColor = new RGBColor(r, g, b);
}
public void SetNonStrokingColorCmyk(decimal c, decimal m, decimal y, decimal k)
{
CurrentNonStrokingColorSpace = ColorSpace.DeviceCMYK;
CurrentNonStrokingColor = new CMYKColor(c, m, y, k);
}
}
}

View File

@@ -39,7 +39,7 @@
public PdfPath CurrentPath { get; private set; }
public IColorspaceContext ColorspaceContext { get; } = new ColorspaceContext();
public IColorSpaceContext ColorSpaceContext { get; } = new ColorSpaceContext();
public PdfPoint CurrentPosition { get; set; }

View File

@@ -1,12 +1,33 @@
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>
/// The <see cref="IColor"/> used for stroking operations.
/// </summary>
IColor CurrentStrokingColor { get; }
/// <summary>
/// The <see cref="IColor"/> used for non-stroking operations.
/// </summary>
IColor CurrentNonStrokingColor { get; }
/// <summary>
/// Set the current color space to use for stroking operations.
/// </summary>
@@ -39,7 +60,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>

View File

@@ -21,7 +21,7 @@
/// <summary>
/// The active colorspaces for this content stream.
/// </summary>
IColorspaceContext ColorspaceContext { get; }
IColorSpaceContext ColorSpaceContext { get; }
/// <summary>
/// The current position.

View File

@@ -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 />

View File

@@ -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 />

View File

@@ -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 />

View File

@@ -33,7 +33,7 @@
/// <inheritdoc />
public void Run(IOperationContext operationContext)
{
operationContext.ColorspaceContext.SetNonStrokingColorGray(Gray);
operationContext.ColorSpaceContext.SetNonStrokingColorGray(Gray);
}
/// <inheritdoc />

View File

@@ -47,7 +47,7 @@
/// <inheritdoc />
public void Run(IOperationContext operationContext)
{
operationContext.ColorspaceContext.SetNonStrokingColorRgb(R, G, B);
operationContext.ColorSpaceContext.SetNonStrokingColorRgb(R, G, B);
}
/// <inheritdoc />

View File

@@ -36,7 +36,7 @@
/// <inheritdoc />
public void Run(IOperationContext operationContext)
{
operationContext.ColorspaceContext.SetNonStrokingColorspace(Name);
operationContext.ColorSpaceContext.SetNonStrokingColorspace(Name);
}
/// <inheritdoc />

View File

@@ -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;

View File

@@ -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 />

View File

@@ -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 />

View File

@@ -33,7 +33,7 @@
/// <inheritdoc />
public void Run(IOperationContext operationContext)
{
operationContext.ColorspaceContext.SetStrokingColorGray(Gray);
operationContext.ColorSpaceContext.SetStrokingColorGray(Gray);
}
/// <inheritdoc />

View File

@@ -47,7 +47,7 @@
/// <inheritdoc />
public void Run(IOperationContext operationContext)
{
operationContext.ColorspaceContext.SetStrokingColorRgb(R, G, B);
operationContext.ColorSpaceContext.SetStrokingColorRgb(R, G, B);
}
/// <inheritdoc />

View File

@@ -36,7 +36,7 @@
/// <inheritdoc />
public void Run(IOperationContext operationContext)
{
operationContext.ColorspaceContext.SetStrokingColorspace(Name);
operationContext.ColorSpaceContext.SetStrokingColorspace(Name);
}
/// <inheritdoc />