Skip to content

Commit 1972355

Browse files
committed
Add support for overprinting by way of extended graphics states
1 parent ad15301 commit 1972355

15 files changed

+149
-16
lines changed

Directory.Build.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Update="SixLabors.ImageSharp" Version="3.0.*" />
10+
<PackageReference Update="SixLabors.ImageSharp" Version="3.1.*" />
1111
</ItemGroup>
1212

1313
<!-- Disable auto imports/usings from ImageSharp -->
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace Synercoding.FileFormats.Pdf;
2+
3+
/// <summary>
4+
/// Class representing an ExtGState dictionary.
5+
/// </summary>
6+
public sealed record class ExtendedGraphicsState
7+
{
8+
/// <summary>
9+
/// A flag specifying whether to apply overprint.
10+
/// There are two separate overprint parameters: one for stroking and one for all other painting operations.
11+
/// Specifying an <see cref="Overprint"/> entry sets both parameters
12+
/// unless there is also an <see cref="OverprintNonStroking"/> entry in the same graphics state parameter dictionary,
13+
/// in which case the <see cref="Overprint"/> entry sets only the overprint parameter for stroking.
14+
/// </summary>
15+
public bool? Overprint { get; set; }
16+
17+
/// <summary>
18+
/// A flag specifying whether to apply overprint for painting operations other than stroking.
19+
/// If this entry is absent, the <see cref="Overprint"/> entry, if any, sets this parameter.
20+
/// </summary>
21+
public bool? OverprintNonStroking { get; set; }
22+
}
23+

src/Synercoding.FileFormats.Pdf/GraphicState.cs renamed to src/Synercoding.FileFormats.Pdf/GraphicsState.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ namespace Synercoding.FileFormats.Pdf;
77
/// <summary>
88
/// Class representing the grahpic state of a PDF at a certain moment in time.
99
/// </summary>
10-
public sealed class GraphicState
10+
public sealed class GraphicsState
1111
{
12-
internal GraphicState()
12+
internal GraphicsState()
1313
{
1414
CTM = Matrix.Identity;
1515
Fill = PredefinedColors.Black;
@@ -111,9 +111,9 @@ internal GraphicState()
111111
/// </summary>
112112
public double TextRise { get; internal set; }
113113

114-
internal GraphicState Clone()
114+
internal GraphicsState Clone()
115115
{
116-
return new GraphicState()
116+
return new GraphicsState()
117117
{
118118
CTM = CTM,
119119
Fill = Fill,

src/Synercoding.FileFormats.Pdf/IContentContext.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public interface IContentContext<TSelf>
1919
/// <summary>
2020
/// Represents the current graphic state
2121
/// </summary>
22-
GraphicState GraphicState { get; }
22+
GraphicsState GraphicState { get; }
2323

2424
/// <summary>
2525
/// Wrap the <paramref name="contentOperations"/> in save and restore state operators
@@ -40,7 +40,7 @@ public interface IContentContext<TSelf>
4040
Task<TSelf> WrapInStateAsync<T>(T data, Func<T, TSelf, Task> contentOperations);
4141

4242
/// <summary>
43-
/// Concatenate a matrix to <see cref="GraphicState.CTM"/>
43+
/// Concatenate a matrix to <see cref="GraphicsState.CTM"/>
4444
/// </summary>
4545
/// <param name="matrix">The matrix to concat</param>
4646
/// <returns>This <see cref="IContentContext{TSelf}"/> to enable chaining operations</returns>
@@ -94,5 +94,12 @@ public interface IContentContext<TSelf>
9494
/// <param name="dashPattern">The dash pattern to set</param>
9595
/// <returns>This <see cref="IContentContext{TSelf}"/> to enable chaining operations</returns>
9696
TSelf SetDashPattern(Dash dashPattern);
97+
98+
/// <summary>
99+
/// Set an extended graphics state (ExtGState) dictionary.
100+
/// </summary>
101+
/// <param name="extendedGraphicsState">The state to apply.</param>
102+
/// <returns>This <see cref="IContentContext{TSelf}"/> to enable chaining operations</returns>
103+
TSelf SetExtendedGraphicsState(ExtendedGraphicsState extendedGraphicsState);
97104
}
98105

src/Synercoding.FileFormats.Pdf/ITextContentContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public interface ITextContentContext : IContentContext<ITextContentContext>
101101
ITextContentContext ShowTextOnNextLine(string text);
102102

103103
/// <summary>
104-
/// Operation to show text on the next line and setting the <see cref="GraphicState.WordSpacing"/> and <see cref="GraphicState.CharacterSpacing"/>
104+
/// Operation to show text on the next line and setting the <see cref="GraphicsState.WordSpacing"/> and <see cref="GraphicsState.CharacterSpacing"/>
105105
/// </summary>
106106
/// <param name="text">The text to show</param>
107107
/// <param name="wordSpacing">The word spacing to set</param>

src/Synercoding.FileFormats.Pdf/Internals/PageContentContext.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ namespace Synercoding.FileFormats.Pdf.Internals;
66

77
internal class PageContentContext : IPageContentContext
88
{
9-
public PageContentContext(ContentStream contentStream, GraphicState graphicState)
9+
public PageContentContext(ContentStream contentStream, GraphicsState graphicState)
1010
{
1111
RawContentStream = contentStream;
1212
GraphicState = graphicState;
1313
}
1414

1515
public ContentStream RawContentStream { get; }
1616

17-
public GraphicState GraphicState { get; }
17+
public GraphicsState GraphicState { get; }
1818

1919
public IPageContentContext AddImage(Image image)
2020
{
@@ -155,4 +155,11 @@ public async Task<IPageContentContext> AddShapesAsync<T>(T data, Func<T, IShapeC
155155

156156
return this;
157157
}
158+
159+
public IPageContentContext SetExtendedGraphicsState(ExtendedGraphicsState extendedGraphicsState)
160+
{
161+
RawContentStream.SetExtendedGraphicsState(extendedGraphicsState);
162+
163+
return this;
164+
}
158165
}

src/Synercoding.FileFormats.Pdf/Internals/ShapesContentContext.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ namespace Synercoding.FileFormats.Pdf.Internals;
66

77
internal class ShapesContentContext : IShapeContentContext
88
{
9-
public ShapesContentContext(ContentStream contentStream, GraphicState graphicState)
9+
public ShapesContentContext(ContentStream contentStream, GraphicsState graphicState)
1010
{
1111
RawContentStream = contentStream;
1212
GraphicState = graphicState;
1313
}
1414

1515
public ContentStream RawContentStream { get; }
1616

17-
public GraphicState GraphicState { get; }
17+
public GraphicsState GraphicState { get; }
1818

1919
public IShapeContentContext ConcatenateMatrix(Matrix matrix)
2020
{
@@ -204,4 +204,11 @@ public IShapeContentContext EndPathNoStrokeNoFill()
204204

205205
return this;
206206
}
207+
208+
public IShapeContentContext SetExtendedGraphicsState(ExtendedGraphicsState extendedGraphicsState)
209+
{
210+
RawContentStream.SetExtendedGraphicsState(extendedGraphicsState);
211+
212+
return this;
213+
}
207214
}

src/Synercoding.FileFormats.Pdf/Internals/TextContentContext.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ namespace Synercoding.FileFormats.Pdf.Internals;
77

88
internal class TextContentContext : ITextContentContext
99
{
10-
public TextContentContext(ContentStream contentStream, GraphicState graphicState)
10+
public TextContentContext(ContentStream contentStream, GraphicsState graphicState)
1111
{
1212
RawContentStream = contentStream;
1313
GraphicState = graphicState;
1414
}
1515

1616
public ContentStream RawContentStream { get; }
1717

18-
public GraphicState GraphicState { get; }
18+
public GraphicsState GraphicState { get; }
1919

2020
public ITextContentContext ConcatenateMatrix(Matrix matrix)
2121
{
@@ -225,4 +225,11 @@ public ITextContentContext ShowTextOnNextLine(string text, double wordSpacing, d
225225

226226
return this;
227227
}
228+
229+
public ITextContentContext SetExtendedGraphicsState(ExtendedGraphicsState extendedGraphicsState)
230+
{
231+
RawContentStream.SetExtendedGraphicsState(extendedGraphicsState);
232+
233+
return this;
234+
}
228235
}

src/Synercoding.FileFormats.Pdf/LowLevel/ContentStream.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,20 @@ public ContentStream Paint(PdfName resource)
387387
return this;
388388
}
389389

390+
/// <summary>
391+
/// Set an extended graphics state (ExtGState) dictionary using a gs operator..
392+
/// </summary>
393+
/// <param name="state">The state to apply.</param>
394+
/// <returns>The <see cref="ContentStream"/> to support chaining operations.</returns>
395+
public ContentStream SetExtendedGraphicsState(ExtendedGraphicsState state)
396+
{
397+
var name = Resources.AddExtendedGraphicsState(state);
398+
399+
InnerStream.Write(name).Space().Write("gs").NewLine();
400+
401+
return this;
402+
}
403+
390404
/// <summary>
391405
/// Write the operator (m) to the stream
392406
/// </summary>

src/Synercoding.FileFormats.Pdf/LowLevel/Graphics/LineJoinStyle.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public enum LineJoinStyle
99
/// The outer edges of the strokes for the two segments shall be extended until they meet at an angle.
1010
/// </summary>
1111
/// <remarks>
12-
/// If the segments meet at too sharp an angle (see <see cref="GraphicState.MiterLimit"/>), a bevel join shall be used instead.
12+
/// If the segments meet at too sharp an angle (see <see cref="GraphicsState.MiterLimit"/>), a bevel join shall be used instead.
1313
/// </remarks>
1414
MiterJoin = 0,
1515
/// <summary>

0 commit comments

Comments
 (0)