-
-
![]()
+
+
} @else {
diff --git a/src/Turnierplan.PdfRendering/Extensions/QuestPdfContainerExtensions.cs b/src/Turnierplan.PdfRendering/Extensions/QuestPdfContainerExtensions.cs
index 935aff7a..e50e5583 100644
--- a/src/Turnierplan.PdfRendering/Extensions/QuestPdfContainerExtensions.cs
+++ b/src/Turnierplan.PdfRendering/Extensions/QuestPdfContainerExtensions.cs
@@ -9,39 +9,78 @@ namespace Turnierplan.PdfRendering.Extensions;
internal static class QuestPdfContainerExtensions
{
- extension(IContainer container)
+ ///
+ /// Displays an image at the current position with the specified size. This method overwrites properties of the specified
+ /// so you should always call this method with a fresh container. Most importantly, the
+ /// method is called to allow for the desired positioning.
+ ///
+ public static void LogoImage(this IContainer container, Image image, IImageStorage imageStorage, float size, Unit sizeUnit, bool alignRight = false)
{
- public void Image(Image image, IImageStorage imageStorage)
+ if (alignRight)
{
- // Waiting for the task to complete is not ideal. However, attempting to use async
- // inside the QuestPDF document structure is probably a much bigger nightmare...
- var task = imageStorage.GetImageAsync(image);
- task.Wait();
+ float translateX;
- var stream = task.Result;
- container.Image(stream);
+ if (image.Height > image.Width)
+ {
+ var imageDisplayWidth = (float)image.Width / image.Height * size;
+ translateX = -imageDisplayWidth;
+ }
+ else
+ {
+ translateX = -size;
+ }
- // Dispose the stream (at this point, QuestPDF has read the stream content into an internal buffer)
- stream.Dispose();
+ container = container.AlignRight().TranslateX(translateX, sizeUnit);
}
- ///
- /// This code is taken from , last viewed on 2025-09-26
- ///
- public void SkiaSharpSvgCanvas(Action
drawOnCanvas)
+ float translateY;
+
+ if (image.Width > image.Height)
{
- container.Svg(size =>
- {
- using var stream = new MemoryStream();
+ var imageDisplayHeight = (float)image.Height / image.Width * size;
+ translateY = 0.5f * (size - imageDisplayHeight);
+ }
+ else
+ {
+ translateY = 0.0f;
+ }
- using (var canvas = SKSvgCanvas.Create(new SKRect(0, 0, size.Width, size.Height), stream))
- {
- drawOnCanvas(canvas, size);
- }
+ container.TranslateY(translateY, sizeUnit).Unconstrained().Width(size, sizeUnit).Height(size, sizeUnit).Image(image, imageStorage);
+ }
- var svgData = stream.ToArray();
- return Encoding.UTF8.GetString(svgData);
- });
- }
+ ///
+ /// Pulls the specified image from the configured image storage and creates a QuestPDF image with the retrieved image data.
+ ///
+ public static void Image(this IContainer container, Image image, IImageStorage imageStorage)
+ {
+ // Waiting for the task to complete is not ideal. However, attempting to use async
+ // inside the QuestPDF document structure is probably a much bigger nightmare...
+ var task = imageStorage.GetImageAsync(image);
+ task.Wait();
+
+ var stream = task.Result;
+ container.Image(stream);
+
+ // Dispose the stream (at this point, QuestPDF has read the stream content into an internal buffer)
+ stream.Dispose();
+ }
+
+ ///
+ /// This code is taken from , last viewed on 2026-03-01
+ ///
+ public static void SkiaSharpSvgCanvas(this IContainer container, Action drawOnCanvas)
+ {
+ container.Svg(size =>
+ {
+ using var stream = new MemoryStream();
+
+ using (var canvas = SKSvgCanvas.Create(new SKRect(0, 0, size.Width, size.Height), stream))
+ {
+ drawOnCanvas(canvas, size);
+ }
+
+ var svgData = stream.ToArray();
+ return Encoding.UTF8.GetString(svgData);
+ });
}
}
diff --git a/src/Turnierplan.PdfRendering/Renderer/MatchPlanRenderer.cs b/src/Turnierplan.PdfRendering/Renderer/MatchPlanRenderer.cs
index 94587fb3..8c486b33 100644
--- a/src/Turnierplan.PdfRendering/Renderer/MatchPlanRenderer.cs
+++ b/src/Turnierplan.PdfRendering/Renderer/MatchPlanRenderer.cs
@@ -50,13 +50,13 @@ string GetSectionHeader(string key)
if (tournament.PrimaryLogo is not null)
{
using var _ = DocumentRendererActivitySource.LoadRemoteImage(CurrentActivity, tournament.PrimaryLogo, nameof(tournament.PrimaryLogo));
- column.Item().Unconstrained().Width(3, Unit.Centimetre).Image(tournament.PrimaryLogo, imageStorage);
+ column.Item().LogoImage(tournament.PrimaryLogo, imageStorage, 3.0f, Unit.Centimetre);
}
if (tournament.SecondaryLogo is not null)
{
using var _ = DocumentRendererActivitySource.LoadRemoteImage(CurrentActivity, tournament.SecondaryLogo, nameof(tournament.SecondaryLogo));
- column.Item().AlignRight().Unconstrained().TranslateX(-3, Unit.Centimetre).Width(3, Unit.Centimetre).Image(tournament.SecondaryLogo, imageStorage);
+ column.Item().LogoImage(tournament.SecondaryLogo, imageStorage, 3.0f, Unit.Centimetre, alignRight: true);
}
var organizerName = string.IsNullOrWhiteSpace(configuration.OrganizerNameOverride)
diff --git a/src/Turnierplan.PdfRendering/Renderer/ReceiptsRenderer.cs b/src/Turnierplan.PdfRendering/Renderer/ReceiptsRenderer.cs
index 7c64f055..4d5e2236 100644
--- a/src/Turnierplan.PdfRendering/Renderer/ReceiptsRenderer.cs
+++ b/src/Turnierplan.PdfRendering/Renderer/ReceiptsRenderer.cs
@@ -37,13 +37,13 @@ protected override Document Render(Tournament tournament, ReceiptsDocumentConfig
if (configuration.ShowPrimaryLogo && tournament.PrimaryLogo is not null)
{
using var _ = DocumentRendererActivitySource.LoadRemoteImage(CurrentActivity, tournament.PrimaryLogo, nameof(tournament.PrimaryLogo));
- column.Item().Unconstrained().Width(1.7f, Unit.Centimetre).Image(tournament.PrimaryLogo, imageStorage);
+ column.Item().LogoImage(tournament.PrimaryLogo, imageStorage, 1.7f, Unit.Centimetre);
}
if (configuration.ShowSecondaryLogo && tournament.SecondaryLogo is not null)
{
using var _ = DocumentRendererActivitySource.LoadRemoteImage(CurrentActivity, tournament.SecondaryLogo, nameof(tournament.SecondaryLogo));
- column.Item().AlignRight().Unconstrained().TranslateX(-1.7f, Unit.Centimetre).Width(1.7f, Unit.Centimetre).Image(tournament.SecondaryLogo, imageStorage);
+ column.Item().LogoImage(tournament.SecondaryLogo, imageStorage, 1.7f, Unit.Centimetre, alignRight: true);
}
column.Item().PaddingVertical(10).MinHeight(12, Unit.Millimetre).AlignMiddle().Column(headerColumn =>