Skip to content

Commit 835806c

Browse files
committed
Combined shapes, images and text into single api
1 parent d175363 commit 835806c

File tree

81 files changed

+2130
-1842
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+2130
-1842
lines changed

samples/Synercoding.FileFormats.Pdf.ConsoleTester/Program.cs

Lines changed: 79 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using Synercoding.FileFormats.Pdf.Extensions;
2-
using Synercoding.FileFormats.Pdf.LowLevel.Graphics;
3-
using Synercoding.FileFormats.Pdf.LowLevel.Graphics.Colors;
4-
using Synercoding.FileFormats.Pdf.LowLevel.Graphics.Colors.ColorSpaces;
2+
using Synercoding.FileFormats.Pdf.LowLevel.Colors;
3+
using Synercoding.FileFormats.Pdf.LowLevel.Colors.ColorSpaces;
54
using Synercoding.FileFormats.Pdf.LowLevel.Text;
65
using Synercoding.Primitives;
76
using Synercoding.Primitives.Extensions;
@@ -23,7 +22,7 @@ public static void Main(string[] args)
2322
using (var fs = File.OpenWrite(fileName))
2423
using (var writer = new PdfWriter(fs))
2524
{
26-
var bleed = new Spacing(3, Unit.Millimeters);
25+
var bleed = Mm(3);
2726
var mediaBox = Sizes.A4.Expand(bleed).AsRectangle();
2827
var trimBox = mediaBox.Contract(bleed);
2928

@@ -44,11 +43,42 @@ public static void Main(string[] args)
4443

4544
using (var blurStream = File.OpenRead("Pexels_com/4k-wallpaper-blur-bokeh-1484253.jpg"))
4645
{
47-
var addedImage = writer.AddJpgImageUnsafe(blurStream, 7000, 4672);
46+
var addedImage = writer.AddJpgUnsafe(blurStream, 7000, 4672, DeviceRGB.Instance);
4847
var scale = (double)addedImage.Width / addedImage.Height;
49-
page.AddImage(addedImage, new Rectangle(0, 0, scale * 303, 303, Unit.Millimeters));
48+
page.Content.AddImage(addedImage, new Rectangle(0, 0, scale * 303, 303, Unit.Millimeters));
5049
}
5150
})
51+
// Add text to page and use it as the clipping path
52+
.AddPage(page =>
53+
{
54+
page.MediaBox = mediaBox;
55+
page.TrimBox = trimBox;
56+
57+
page.Content.WrapInState(content =>
58+
{
59+
content.AddText(textOp =>
60+
{
61+
textOp.SetTextRenderingMode(TextRenderingMode.AddClippingPath)
62+
.SetFontAndSize(StandardFonts.Helvetica, 160)
63+
.SetTextLeading(500)
64+
.MoveToStartNextLine(Mm(10).AsRaw(Unit.Points), Mm(200).AsRaw(Unit.Points))
65+
.ShowText("Clipped")
66+
.SetFontAndSize(StandardFonts.HelveticaBold, 650)
67+
.ShowTextOnNextLine("it!");
68+
});
69+
70+
using (var forestStream = File.OpenRead("Pexels_com/android-wallpaper-art-backlit-1114897.jpg"))
71+
using (var forestImage = SixLabors.ImageSharp.Image.Load(forestStream))
72+
{
73+
var scale = (double)forestImage.Width / forestImage.Height;
74+
75+
var matrix = Matrix.CreateScaleMatrix(new Value(scale * 303, Unit.Millimeters).AsRaw(Unit.Points), new Value(303, Unit.Millimeters).AsRaw(Unit.Points))
76+
.Translate(new Value(-100, Unit.Millimeters).AsRaw(Unit.Points), new Value(0, Unit.Millimeters).AsRaw(Unit.Points));
77+
78+
page.Content.AddImage(forestImage, matrix);
79+
}
80+
});
81+
})
5282
// Test placement using rectangle
5383
.AddPage(page =>
5484
{
@@ -60,7 +90,7 @@ public static void Main(string[] args)
6090
{
6191
var scale = (double)barrenImage.Width / barrenImage.Height;
6292

63-
page.AddImage(barrenImage, new Rectangle(0, 0, scale * 303, 303, Unit.Millimeters));
93+
page.Content.AddImage(barrenImage, new Rectangle(0, 0, scale * 303, 303, Unit.Millimeters));
6494
}
6595

6696
using (var eyeStream = File.OpenRead("Pexels_com/adult-blue-blue-eyes-865711.jpg"))
@@ -71,7 +101,7 @@ public static void Main(string[] args)
71101
var height = 100 * scale;
72102

73103
var offSet = 6;
74-
page.AddImage(eyeStream, new Rectangle(offSet, offSet, width + offSet, height + offSet, Unit.Millimeters));
104+
page.Content.AddImage(eyeStream, new Rectangle(offSet, offSet, width + offSet, height + offSet, Unit.Millimeters));
75105
}
76106
})
77107
// Test shape graphics
@@ -80,40 +110,39 @@ public static void Main(string[] args)
80110
page.MediaBox = mediaBox;
81111
page.TrimBox = trimBox;
82112

83-
page.AddShapes(ctx =>
113+
page.Content.AddShapes(ctx =>
84114
{
85-
ctx.DefaultState(g =>
86-
{
87-
g.LineWidth = 1;
88-
g.Fill = null;
89-
g.Stroke = null;
90-
g.Dash = new Dash()
91-
{
92-
Array = Array.Empty<double>(),
93-
Phase = 0
94-
};
95-
g.MiterLimit = 10;
96-
g.LineCap = LineCapStyle.ButtCap;
97-
g.LineJoin = LineJoinStyle.MiterJoin;
98-
});
115+
ctx.SetMiterLimit(10)
116+
.SetLineCap(LowLevel.Graphics.LineCapStyle.ButtCap)
117+
.SetLineJoin(LowLevel.Graphics.LineJoinStyle.MiterJoin);
99118

100-
ctx.NewPath(g => { g.Fill = PredefinedColors.Red; g.Stroke = PredefinedColors.Black; g.LineWidth = 5; })
101-
.Move(100, 100)
119+
ctx.Move(100, 100)
102120
.LineTo(200, 100)
103121
.LineTo(200, 200)
104-
.LineTo(100, 200);
105-
ctx.NewPath(g => { g.Fill = PredefinedColors.Blue; g.Stroke = null; })
106-
.Move(50, 50)
122+
.LineTo(100, 200)
123+
.SetLineWidth(5)
124+
.SetStroke(PredefinedColors.Black)
125+
.SetFill(PredefinedColors.Red)
126+
.FillThenStroke(LowLevel.FillRule.NonZeroWindingNumber);
127+
128+
ctx.Move(50, 50)
107129
.LineTo(150, 50)
108130
.LineTo(150, 150)
109131
.LineTo(50, 150)
110-
.Close();
111-
ctx.NewPath(g => { g.Fill = null; g.Stroke = PredefinedColors.Yellow; g.LineWidth = 3; g.Dash = new Dash() { Array = new[] { 5d } }; })
112-
.Move(150, 150)
132+
.SetLineWidth(1)
133+
.SetFill(PredefinedColors.Blue)
134+
.CloseSubPath()
135+
.Fill(LowLevel.FillRule.NonZeroWindingNumber);
136+
137+
ctx.Move(150, 150)
113138
.LineTo(250, 150)
114139
.LineTo(250, 250)
115140
.LineTo(150, 250)
116-
.Close();
141+
.SetLineWidth(3)
142+
.SetStroke(PredefinedColors.Yellow)
143+
.SetDashPattern(new LowLevel.Graphics.Dash() { Array = new[] { 5d } })
144+
.CloseSubPath()
145+
.Stroke();
117146
});
118147
})
119148
// Test pages with text
@@ -122,23 +151,26 @@ public static void Main(string[] args)
122151
page.MediaBox = mediaBox;
123152
page.TrimBox = trimBox;
124153

125-
page.AddText("The quick brown fox jumps over the lazy dog.", new Point(Mm(10), Mm(10)), new TextState(StandardFonts.Helvetica, 12)
154+
page.Content.AddText(ops =>
126155
{
127-
Fill = PredefinedColors.Blue
156+
ops.MoveToStartNextLine(Mm(10).AsRaw(Unit.Points), Mm(10).AsRaw(Unit.Points))
157+
.SetFontAndSize(StandardFonts.Helvetica, 12)
158+
.SetFill(PredefinedColors.Blue)
159+
.ShowText("The quick brown fox jumps over the lazy dog.");
128160
});
129-
page.AddText("Text with a newline" + Environment.NewLine + "in it.", new Point(Mm(10), Mm(20)));
161+
162+
page.Content.AddText("Text with a newline" + Environment.NewLine + "in it.", StandardFonts.Helvetica, 12, new Point(Mm(10), Mm(20)));
130163
})
131164
.AddPage(page =>
132165
{
133166
page.MediaBox = mediaBox;
134167
page.TrimBox = trimBox;
135168

136-
page.AddText("This page also used Helvetica", new Point(Mm(10), Mm(10)), state =>
169+
page.Content.AddText("This page also used Helvetica", StandardFonts.Helvetica, 32, textContext =>
137170
{
138-
state.FontSize = 32;
139-
state.Font = StandardFonts.Helvetica;
140-
state.RenderingMode = TextRenderingMode.Stroke;
141-
state.Stroke = PredefinedColors.Red;
171+
textContext.MoveToStartNextLine(Mm(10).AsRaw(Unit.Points), Mm(10).AsRaw(Unit.Points))
172+
.SetTextRenderingMode(TextRenderingMode.Stroke)
173+
.SetStroke(PredefinedColors.Red);
142174
});
143175
})
144176
// Test placement using matrix
@@ -155,7 +187,7 @@ public static void Main(string[] args)
155187
var matrix = Matrix.CreateScaleMatrix(new Value(scale * 303, Unit.Millimeters).AsRaw(Unit.Points), new Value(303, Unit.Millimeters).AsRaw(Unit.Points))
156188
.Translate(new Value(-100, Unit.Millimeters).AsRaw(Unit.Points), new Value(0, Unit.Millimeters).AsRaw(Unit.Points));
157189

158-
page.AddImage(forestImage, matrix);
190+
page.Content.AddImage(forestImage, matrix);
159191
}
160192
});
161193

@@ -173,7 +205,7 @@ public static void Main(string[] args)
173205

174206
var scale = (double)blurImage.Width / blurImage.Height;
175207

176-
page.AddImage(reusedImage, new Rectangle(0, 0, scale * 303, 303, Unit.Millimeters));
208+
page.Content.AddImage(reusedImage, new Rectangle(0, 0, scale * 303, 303, Unit.Millimeters));
177209
});
178210
}
179211

@@ -185,15 +217,13 @@ public static void Main(string[] args)
185217

186218
var scale = (double)blurImage.Width / blurImage.Height;
187219

188-
page.AddImage(reusedImage, new Rectangle(0, 0, scale * 303, 303, Unit.Millimeters));
220+
page.Content.AddImage(reusedImage, new Rectangle(0, 0, scale * 303, 303, Unit.Millimeters));
189221

190-
page.AddShapes(trimBox, static (trim, context) =>
222+
page.Content.AddShapes(trimBox, static (trim, context) =>
191223
{
192-
context.DefaultState(state =>
193-
{
194-
state.Stroke = new SpotColor(new Separation(LowLevel.PdfName.Get("CutContour"), PredefinedColors.Magenta), 1);
195-
});
196-
context.NewPath().Rectangle(trim);
224+
context.SetStroke(new SpotColor(new Separation(LowLevel.PdfName.Get("CutContour"), PredefinedColors.Magenta), 1));
225+
context.Rectangle(trim);
226+
context.Stroke();
197227
});
198228
});
199229
}

src/Directory.Build.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<Project>
33

44
<PropertyGroup>
5-
<TargetFrameworks>net7.0;net6.0;netstandard2.1</TargetFrameworks>
5+
<TargetFrameworks>net7.0;net6.0</TargetFrameworks>
66
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileDirectory)..\Directory.Build.props</MSBuildAllProjects>
77
<SynercodingProjectCategory>src</SynercodingProjectCategory>
88
</PropertyGroup>
@@ -17,4 +17,4 @@
1717
<WarningsNotAsErrors>CS1591</WarningsNotAsErrors>
1818
</PropertyGroup>
1919

20-
</Project>
20+
</Project>

src/Synercoding.FileFormats.Pdf/DocumentInformation.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace Synercoding.FileFormats.Pdf
77
/// <summary>
88
/// This class contains information about the document
99
/// </summary>
10-
public class DocumentInformation : IPdfObject
10+
public class DocumentInformation
1111
{
1212
internal DocumentInformation(PdfReference id)
1313
{
@@ -54,7 +54,9 @@ internal DocumentInformation(PdfReference id)
5454
/// </summary>
5555
public DateTime? ModDate { get; set; }
5656

57-
/// <inheritdoc />
57+
/// <summary>
58+
/// A pdf reference object that can be used to reference to this object
59+
/// </summary>
5860
public PdfReference Reference { get; }
5961

6062
/// <summary>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
4+
namespace Synercoding.FileFormats.Pdf.Extensions;
5+
public static class IContentContextExtensions
6+
{
7+
public static TContext WrapInState<TContext>(this TContext context, Action<TContext> contentOperations)
8+
where TContext : IContentContext<TContext>
9+
=> context.WrapInState(contentOperations, static (operations, context) => operations(context));
10+
11+
public static Task<TContext> WrapInStateAsync<TContext>(this TContext context, Func<TContext, Task> contentOperations)
12+
where TContext: IContentContext<TContext>
13+
=> context.WrapInStateAsync(contentOperations, static (operations, context) => operations(context));
14+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
using Synercoding.FileFormats.Pdf.Internals;
2+
using Synercoding.FileFormats.Pdf.LowLevel.Colors.ColorSpaces;
3+
using Synercoding.FileFormats.Pdf.LowLevel.Text;
4+
using Synercoding.Primitives;
5+
using Synercoding.Primitives.Extensions;
6+
using System;
7+
using System.Linq;
8+
using System.Threading.Tasks;
9+
10+
namespace Synercoding.FileFormats.Pdf.Extensions;
11+
public static class IPageContentContextExtensions
12+
{
13+
public static IPageContentContext AddJpgUnsafe(this IPageContentContext context, System.IO.Stream jpgStream, int originalWidth, int originalHeight, ColorSpace colorSpace)
14+
{
15+
var name = context.RawContentStream.Resources.AddJpgUnsafe(jpgStream, originalWidth, originalHeight, colorSpace);
16+
17+
context.RawContentStream.Paint(name);
18+
19+
return context;
20+
}
21+
22+
public static IPageContentContext AddImage(this IPageContentContext context, System.IO.Stream stream, Matrix matrix)
23+
{
24+
return context.WrapInState((stream, matrix), static (tuple, context) =>
25+
{
26+
context.ConcatenateMatrix(tuple.matrix);
27+
context.AddImage(tuple.stream);
28+
});
29+
}
30+
31+
public static IPageContentContext AddImage(this IPageContentContext context, System.IO.Stream stream, Rectangle rectangle)
32+
=> context.AddImage(stream, rectangle.AsPlacementMatrix());
33+
34+
public static IPageContentContext AddImage(this IPageContentContext context, System.IO.Stream stream)
35+
{
36+
using var image = SixLabors.ImageSharp.Image.Load(stream);
37+
38+
return context.AddImage(image);
39+
}
40+
41+
public static IPageContentContext AddImage(this IPageContentContext context, SixLabors.ImageSharp.Image image, Matrix matrix)
42+
{
43+
return context.WrapInState((image, matrix), static (tuple, context) =>
44+
{
45+
context.ConcatenateMatrix(tuple.matrix);
46+
context.AddImage(tuple.image);
47+
});
48+
}
49+
50+
public static IPageContentContext AddImage(this IPageContentContext context, SixLabors.ImageSharp.Image image, Rectangle rectangle)
51+
=> context.AddImage(image, rectangle.AsPlacementMatrix());
52+
53+
public static IPageContentContext AddImage(this IPageContentContext context, SixLabors.ImageSharp.Image image)
54+
{
55+
var name = context.RawContentStream.Resources.AddImage(image);
56+
57+
context.RawContentStream.Paint(name);
58+
59+
return context;
60+
}
61+
62+
public static IPageContentContext AddImage(this IPageContentContext context, Image image, Rectangle rectangle)
63+
=> context.AddImage(image, rectangle.AsPlacementMatrix());
64+
65+
public static IPageContentContext AddImage(this IPageContentContext context, Image image, Matrix matrix)
66+
{
67+
return context.WrapInState((image, matrix), static (tuple, context) =>
68+
{
69+
context.ConcatenateMatrix(tuple.matrix);
70+
context.AddImage(tuple.image);
71+
});
72+
}
73+
74+
public static IPageContentContext AddShapes(this IPageContentContext context, Action<IShapeContext> shapeOperations)
75+
=> context.AddShapes(shapeOperations, static (operations, context) => operations(context));
76+
77+
public static Task<IPageContentContext> AddShapesAsync(this IPageContentContext context, Func<IShapeContext, Task> shapeOperations)
78+
=> context.AddShapesAsync(shapeOperations, static (operations, context) => operations(context));
79+
80+
public static IPageContentContext AddText(this IPageContentContext context, Action<ITextContentContext> textOperations)
81+
=> context.AddText(textOperations, static (operations, context) => operations(context));
82+
83+
public static Task<IPageContentContext> AddTextAsync(this IPageContentContext context, Func<ITextContentContext, Task> textOperations)
84+
=> context.AddTextAsync(textOperations, static (operations, context) => operations(context));
85+
86+
public static IPageContentContext AddText(this IPageContentContext context, string text, Font font, double size)
87+
=> context.AddText(text, font, size, ops => { });
88+
89+
public static IPageContentContext AddText(this IPageContentContext context, string text, Font font, double size, Point location)
90+
=> context.AddText(text, font, size, location, static (location, ops) =>
91+
{
92+
ops.MoveToStartNextLine(location.X.AsRaw(Unit.Points), location.Y.AsRaw(Unit.Points));
93+
});
94+
95+
public static IPageContentContext AddText(this IPageContentContext context, string text, Font font, double size, Action<ITextContentContext> extraOperations)
96+
=> context.AddText(text, font, size, extraOperations, static (extraOperations, context) => extraOperations(context));
97+
98+
public static IPageContentContext AddText<T>(this IPageContentContext context, string text, Font font, double size, T data, Action<T, ITextContentContext> extraOperations)
99+
{
100+
return context.AddText((text, font, size, data, extraOperations), static (quintuple, context) =>
101+
{
102+
var (text, font, size, data, extraOperations) = quintuple;
103+
context.SetFontAndSize(font, size);
104+
105+
extraOperations(data, context);
106+
107+
var lines = StringHelper.SplitOnNewLines(text).ToArray();
108+
109+
// if no leading parameter is set, and the text spans multiple lines, set textleading to the font size.
110+
if (lines.Length > 1 && context.TextLeading == default)
111+
context.SetTextLeading(size);
112+
113+
for (int i = 0; i < lines.Length; i++)
114+
{
115+
if (i == 0)
116+
{
117+
context.ShowText(lines[i]);
118+
}
119+
else
120+
{
121+
context.ShowTextOnNextLine(lines[i]);
122+
}
123+
}
124+
});
125+
}
126+
}

0 commit comments

Comments
 (0)