diff --git a/source/X39.Solutions.PdfTemplate/DocumentOptions.cs b/source/X39.Solutions.PdfTemplate/DocumentOptions.cs
index 06ef29a..03f15a7 100644
--- a/source/X39.Solutions.PdfTemplate/DocumentOptions.cs
+++ b/source/X39.Solutions.PdfTemplate/DocumentOptions.cs
@@ -1,3 +1,5 @@
+using X39.Solutions.PdfTemplate.Data;
+
namespace X39.Solutions.PdfTemplate;
///
@@ -53,4 +55,14 @@ public float DotsPerMillimeter
/// The product that is converting this document to PDF.
///
public string Producer { get; set; } = "";
+
+ ///
+ /// The margin of the document.
+ ///
+ ///
+ /// Margin is removed from the page size, not added to it.
+ /// This implies that a margin of 100pt... or 10pt... will result in the same page size,
+ /// but the content will be moved by 100pt... or 10pt... respectively.
+ ///
+ public Thickness Margin { get; init; } = new(0, 0, 0, 0);
}
\ No newline at end of file
diff --git a/source/X39.Solutions.PdfTemplate/Generator.cs b/source/X39.Solutions.PdfTemplate/Generator.cs
index a625b53..7c9486a 100644
--- a/source/X39.Solutions.PdfTemplate/Generator.cs
+++ b/source/X39.Solutions.PdfTemplate/Generator.cs
@@ -165,18 +165,20 @@ public async Task> GenerateBitmapsAsync(
{
SKCanvas? canvas = null;
await GenerateAsync(
- () =>
- {
- var bitmap = new SKBitmap((int) Math.Ceiling(pageSize.Width), (int) Math.Ceiling(pageSize.Height));
- bitmaps.Add(bitmap);
- canvas = new SKCanvas(bitmap);
- canvas.Clear(SKColors.White);
- return canvas;
- },
- reader,
- cultureInfo,
- options,
- cancellationToken)
+ () =>
+ {
+ var bitmap = new SKBitmap(
+ (int) Math.Ceiling(pageSize.Width),
+ (int) Math.Ceiling(pageSize.Height));
+ bitmaps.Add(bitmap);
+ canvas = new SKCanvas(bitmap);
+ canvas.Clear(SKColors.White);
+ return canvas;
+ },
+ reader,
+ cultureInfo,
+ options,
+ cancellationToken)
.ConfigureAwait(false);
canvas?.Dispose();
return bitmaps.AsReadOnly();
@@ -206,6 +208,16 @@ private async Task GenerateAsync(
var pageSize = new Size(
options.DotsPerMillimeter * options.PageWidthInMillimeters,
options.DotsPerMillimeter * options.PageHeightInMillimeters);
+ var marginLeft = options.Margin.Left.ToPixels(pageSize.Width, options.DotsPerInch);
+ var marginTop = options.Margin.Top.ToPixels(pageSize.Height, options.DotsPerInch);
+ pageSize = new Size(
+ pageSize.Width
+ - marginLeft
+ - options.Margin.Right.ToPixels(pageSize.Width, options.DotsPerInch),
+ pageSize.Height
+ - marginTop
+ - options.Margin.Bottom.ToPixels(pageSize.Height, options.DotsPerInch)
+ );
#region Measure
@@ -234,7 +246,7 @@ private async Task GenerateAsync(
var footerPageSize = pageSize with {Height = pageSize.Height * 0.25F};
foreach (var control in template.FooterControls)
{
- var size = control.Arrange(options.DotsPerInch,pageSize, footerPageSize, footerPageSize, cultureInfo);
+ var size = control.Arrange(options.DotsPerInch, pageSize, footerPageSize, footerPageSize, cultureInfo);
footerSizes.Add(size);
}
@@ -247,7 +259,7 @@ private async Task GenerateAsync(
var bodyPageSize = pageSize with {Height = pageSize.Height - headerPageSize.Height - footerPageSize.Height};
foreach (var control in template.BodyControls)
{
- var size = control.Arrange(options.DotsPerInch,pageSize, bodyPageSize, bodyPageSize, cultureInfo);
+ var size = control.Arrange(options.DotsPerInch, pageSize, bodyPageSize, bodyPageSize, cultureInfo);
bodySizes.Add(size);
}
@@ -294,6 +306,8 @@ private async Task GenerateAsync(
for (var i = 0; i < pageCount; i++)
{
using var canvas = nextCanvas();
+ canvas.Save();
+ canvas.Translate(marginLeft, marginTop);
canvas.Save();
canvas.ClipRect(
@@ -316,6 +330,8 @@ private async Task GenerateAsync(
footerCanvasAbstraction.Render(canvas);
canvas.Restore();
currentHeight += bodyPageSize.Height;
+
+ canvas.Restore();
}
#endregion