From ec2c8d4e7685d8350688bead3cb96146292b5b3e Mon Sep 17 00:00:00 2001 From: X39 Date: Sat, 25 Nov 2023 15:26:18 +0100 Subject: [PATCH] adding points (pt) to Length [major][add] With dpi properly taken into account for text now, lines (and other things relying on length) now also required a way to properly define the size in points (aka: in relation to DPI). This is now concluded with Length having support for `pt` size (eg. 72pt ~ 1inch). --- .../Controls/Base/Control.cs | 12 +++++----- .../Controls/BorderControl.cs | 6 ++--- .../Controls/LineControl.cs | 24 ++++++++++--------- .../Data/ELengthMode.cs | 8 +++++++ .../X39.Solutions.PdfTemplate/Data/Length.cs | 7 +++++- .../Data/Thickness.cs | 22 +++++++++-------- .../Controls/LineControlTests.cs | 12 ++++++---- 7 files changed, 56 insertions(+), 35 deletions(-) diff --git a/source/X39.Solutions.PdfTemplate/Controls/Base/Control.cs b/source/X39.Solutions.PdfTemplate/Controls/Base/Control.cs index bc937bc..8c387ac 100644 --- a/source/X39.Solutions.PdfTemplate/Controls/Base/Control.cs +++ b/source/X39.Solutions.PdfTemplate/Controls/Base/Control.cs @@ -168,8 +168,8 @@ public virtual Size Measure( in Size remainingSize, CultureInfo cultureInfo) { - var padding = Padding.ToRectangle(fullPageSize); - var margin = Margin.ToRectangle(fullPageSize); + var padding = Padding.ToRectangle(fullPageSize, dpi); + var margin = Margin.ToRectangle(fullPageSize, dpi); var measureResult = DoMeasure( dpi, ToSize(fullPageSize, margin), @@ -219,8 +219,8 @@ public virtual Size Arrange( { FramedSize = framedPageSize; RemainingSize = framedPageSize; - var padding = Padding.ToRectangle(remainingSize); - var margin = Margin.ToRectangle(remainingSize); + var padding = Padding.ToRectangle(remainingSize, dpi); + var margin = Margin.ToRectangle(remainingSize, dpi); var measureResult = DoArrange( dpi, ToSize(fullPageSize, margin), @@ -260,8 +260,8 @@ public virtual void Render( in Size parentSize, CultureInfo cultureInfo) { - var padding = Padding.ToRectangle(parentSize); - var margin = Margin.ToRectangle(parentSize); + var padding = Padding.ToRectangle(parentSize, dpi); + var margin = Margin.ToRectangle(parentSize, dpi); canvas.PushState(); try { diff --git a/source/X39.Solutions.PdfTemplate/Controls/BorderControl.cs b/source/X39.Solutions.PdfTemplate/Controls/BorderControl.cs index 2e4942a..0d2ea06 100644 --- a/source/X39.Solutions.PdfTemplate/Controls/BorderControl.cs +++ b/source/X39.Solutions.PdfTemplate/Controls/BorderControl.cs @@ -40,7 +40,7 @@ protected override Size DoMeasure( in Size remainingSize, CultureInfo cultureInfo) { - var thickness = Thickness.ToRectangle(fullPageSize); + var thickness = Thickness.ToRectangle(fullPageSize, dpi); var size = Size.Zero; foreach (var child in Children) { @@ -65,7 +65,7 @@ protected override Size DoArrange( in Size remainingSize, CultureInfo cultureInfo) { - var thickness = Thickness.ToRectangle(fullPageSize); + var thickness = Thickness.ToRectangle(fullPageSize, dpi); var size = Size.Zero; foreach (var child in Children) { @@ -89,7 +89,7 @@ protected override void DoRender(ICanvas canvas, float dpi, in Size parentSize, using var state = canvas.CreateState(); canvas.Translate(-ArrangementInner); canvas.Translate(Arrangement); - var thickness = Thickness.ToRectangle(parentSize); + var thickness = Thickness.ToRectangle(parentSize, dpi); if (Background != Colors.Transparent) canvas.DrawRect(Arrangement with {Left = 0, Top = 0}, Background); if (thickness.Left > 0) diff --git a/source/X39.Solutions.PdfTemplate/Controls/LineControl.cs b/source/X39.Solutions.PdfTemplate/Controls/LineControl.cs index 275d244..23fe1fc 100644 --- a/source/X39.Solutions.PdfTemplate/Controls/LineControl.cs +++ b/source/X39.Solutions.PdfTemplate/Controls/LineControl.cs @@ -39,7 +39,7 @@ public sealed class LineControl : AlignableControl /// protected override Size DoMeasure( - float pageSize, + float dpi, in Size fullPageSize, in Size framedPageSize, in Size remainingSize, @@ -48,11 +48,11 @@ protected override Size DoMeasure( return Orientation switch { EOrientation.Horizontal => new Size( - Length.ToPixels(remainingSize.Width), - Thickness.ToPixels(remainingSize.Height)), + Length.ToPixels(remainingSize.Width, dpi), + Thickness.ToPixels(remainingSize.Height, dpi)), EOrientation.Vertical => new Size( - Thickness.ToPixels(remainingSize.Width), - Length.ToPixels(remainingSize.Height)), + Thickness.ToPixels(remainingSize.Width, dpi), + Length.ToPixels(remainingSize.Height, dpi)), _ => throw new InvalidEnumArgumentException(nameof(Orientation), (int) Orientation, typeof(EOrientation)), }; } @@ -68,11 +68,11 @@ protected override Size DoArrange( return Orientation switch { EOrientation.Horizontal => new Size( - Length.ToPixels(remainingSize.Width), - Thickness.ToPixels(remainingSize.Height)), + Length.ToPixels(remainingSize.Width, dpi), + Thickness.ToPixels(remainingSize.Height, dpi)), EOrientation.Vertical => new Size( - Thickness.ToPixels(remainingSize.Width), - Length.ToPixels(remainingSize.Height)), + Thickness.ToPixels(remainingSize.Width, dpi), + Length.ToPixels(remainingSize.Height, dpi)), _ => throw new InvalidEnumArgumentException(nameof(Orientation), (int) Orientation, typeof(EOrientation)), }; } @@ -88,11 +88,13 @@ protected override void DoRender( var length = Length.ToPixels( Orientation is EOrientation.Horizontal ? parentSize.Width - : parentSize.Height); + : parentSize.Height, + dpi); var thickness = Thickness.ToPixels( Orientation is EOrientation.Horizontal ? parentSize.Height - : parentSize.Width); + : parentSize.Width, + dpi); switch (Orientation) { case EOrientation.Horizontal: diff --git a/source/X39.Solutions.PdfTemplate/Data/ELengthMode.cs b/source/X39.Solutions.PdfTemplate/Data/ELengthMode.cs index 3eb171a..ae4ecc6 100644 --- a/source/X39.Solutions.PdfTemplate/Data/ELengthMode.cs +++ b/source/X39.Solutions.PdfTemplate/Data/ELengthMode.cs @@ -14,4 +14,12 @@ public enum ELengthMode /// The size is in percent of the available space. /// Percent, + + /// + /// The size is in points. + /// + /// + /// 1 point = 1/72.272 inch + /// + Points, } \ No newline at end of file diff --git a/source/X39.Solutions.PdfTemplate/Data/Length.cs b/source/X39.Solutions.PdfTemplate/Data/Length.cs index 21f6621..64df6ff 100644 --- a/source/X39.Solutions.PdfTemplate/Data/Length.cs +++ b/source/X39.Solutions.PdfTemplate/Data/Length.cs @@ -56,14 +56,16 @@ public void Deconstruct(out float value, out ELengthMode lengthMode) /// Translates the into a based on the given bounds and . /// /// The bounds to use for the calculation in case of in pixels + /// The DPI to use for the calculation in case of in pixels /// The pixel value of the /// Thrown when is not a valid - public float ToPixels(float bounds) + public float ToPixels(float bounds, float dpi) { return LengthMode switch { ELengthMode.Pixel => Value, ELengthMode.Percent => Value * bounds, + ELengthMode.Points => Value * dpi / 72.272F, _ => throw new InvalidEnumArgumentException(nameof(LengthMode), (int)LengthMode, typeof(ELengthMode)), }; } @@ -91,6 +93,7 @@ public static Length Parse(ReadOnlySpan s, IFormatProvider? provider) "" => ELengthMode.Pixel, "px" => ELengthMode.Pixel, "%" => ELengthMode.Percent, + "pt" => ELengthMode.Points, _ => throw new NotSupportedException($"The unit '{unit}' is not supported.") }; if (sizeMode is ELengthMode.Percent) @@ -115,6 +118,7 @@ public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, out "" => ELengthMode.Pixel, "px" => ELengthMode.Pixel, "%" => ELengthMode.Percent, + "pt" => ELengthMode.Points, _ => default(ELengthMode?), }; if (sizeMode is null) @@ -141,6 +145,7 @@ public string ToString(IFormatProvider? provider) { ELengthMode.Pixel => "px", ELengthMode.Percent => "%", + ELengthMode.Points => "pt", _ => throw new NotSupportedException($"The size mode '{sizeMode}' is not supported."), }; return string.Concat(sizeValue.ToString(provider), sizeUnit); diff --git a/source/X39.Solutions.PdfTemplate/Data/Thickness.cs b/source/X39.Solutions.PdfTemplate/Data/Thickness.cs index 4a66a99..ab2bccb 100644 --- a/source/X39.Solutions.PdfTemplate/Data/Thickness.cs +++ b/source/X39.Solutions.PdfTemplate/Data/Thickness.cs @@ -34,13 +34,14 @@ public Thickness(Length horizontal, Length vertical) : this(horizontal, vertical /// Translates the thickness to a pixels rectangle. /// /// The bounds of the rectangle + /// The DPI to use for the calculation in case of in pixels /// The translated rectangle - public Rectangle ToRectangle(Rectangle bounds) + public Rectangle ToRectangle(Rectangle bounds, float dpi) { - var left = Left.ToPixels(bounds.Width); - var top = Top.ToPixels(bounds.Height); - var right = Right.ToPixels(bounds.Width); - var bottom = Bottom.ToPixels(bounds.Height); + var left = Left.ToPixels(bounds.Width, dpi); + var top = Top.ToPixels(bounds.Height, dpi); + var right = Right.ToPixels(bounds.Width, dpi); + var bottom = Bottom.ToPixels(bounds.Height, dpi); return new Rectangle( left, top, @@ -52,13 +53,14 @@ public Rectangle ToRectangle(Rectangle bounds) /// Translates the thickness to a pixels rectangle. /// /// The bounds of the rectangle + /// The DPI to use for the calculation in case of in pixels /// The translated rectangle - public Rectangle ToRectangle(Size bounds) + public Rectangle ToRectangle(Size bounds, float dpi) { - var left = Left.ToPixels(bounds.Width); - var top = Top.ToPixels(bounds.Height); - var width = Right.ToPixels(bounds.Width); - var height = Bottom.ToPixels(bounds.Height); + var left = Left.ToPixels(bounds.Width, dpi); + var top = Top.ToPixels(bounds.Height, dpi); + var width = Right.ToPixels(bounds.Width, dpi); + var height = Bottom.ToPixels(bounds.Height, dpi); return new Rectangle( left, top, diff --git a/test/X39.Solutions.PdfTemplate.Test/Controls/LineControlTests.cs b/test/X39.Solutions.PdfTemplate.Test/Controls/LineControlTests.cs index 4aed23a..e2d2100 100644 --- a/test/X39.Solutions.PdfTemplate.Test/Controls/LineControlTests.cs +++ b/test/X39.Solutions.PdfTemplate.Test/Controls/LineControlTests.cs @@ -66,7 +66,8 @@ public void DrawLineTests( mock.AssertDrawLine( Colors.Green, lineControl.Thickness.ToPixels( - orientation == EOrientation.Horizontal ? pageBounds.Height : pageBounds.Width), + orientation == EOrientation.Horizontal ? pageBounds.Height : pageBounds.Width, + 90), expectedStartX, expectedStartY, expectedEndX, @@ -111,7 +112,8 @@ public void PaddingIsApplied(EOrientation orientation) lineControl.Thickness.ToPixels( orientation == EOrientation.Horizontal ? pageBounds.Height - : pageBounds.Width), + : pageBounds.Width, + 90), orientation == EOrientation.Horizontal ? 10F : 10.5F, orientation == EOrientation.Horizontal ? 10.5F : 10F, orientation == EOrientation.Horizontal ? 990F : 10.5F, @@ -152,7 +154,8 @@ public void MarginIsApplied(EOrientation orientation) lineControl.Thickness.ToPixels( orientation == EOrientation.Horizontal ? pageBounds.Height - : pageBounds.Width), + : pageBounds.Width, + 90), orientation == EOrientation.Horizontal ? 10F : 10.5F, orientation == EOrientation.Horizontal ? 10.5F : 10F, orientation == EOrientation.Horizontal ? 990F : 10.5F, @@ -193,7 +196,8 @@ public void MarginAndPaddingBothAreApplied(EOrientation orientation) lineControl.Thickness.ToPixels( orientation == EOrientation.Horizontal ? pageBounds.Height - : pageBounds.Width), + : pageBounds.Width, + 90), orientation == EOrientation.Horizontal ? 20F : 20.5F, orientation == EOrientation.Horizontal ? 20.5F : 20F, orientation == EOrientation.Horizontal ? 980F : 20.5F,