Skip to content

Commit

Permalink
Enhanced default content drawing behavior, introduced Repeat() elemen…
Browse files Browse the repository at this point in the history
…t API
  • Loading branch information
MarcinZiabek committed May 16, 2024
1 parent 4172016 commit 484690a
Show file tree
Hide file tree
Showing 27 changed files with 199 additions and 85 deletions.
4 changes: 2 additions & 2 deletions Source/QuestPDF.UnitTests/ColumnTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ public void Draw_UsesEmpty_WhenFirstChildIsRendered()
}

[Test]
public void Draw_TogglesFirstRenderedFlag_WhenSecondFullyRenders()
public void Draw_DoesNotToggleFirstRenderedFlag_WhenSecondFullyRenders()
{
TestPlan
.For(CreateColumnWithTwoItemsWhereFirstIsFullyRendered)
Expand All @@ -185,7 +185,7 @@ public void Draw_TogglesFirstRenderedFlag_WhenSecondFullyRenders()
.ExpectChildDraw("second", new Size(400, 300))
.ExpectCanvasTranslate(0, 0)
.CheckDrawResult()
.CheckState<Column>(x => x.CurrentRenderingIndex == 0);
.CheckState<Column>(x => x.CurrentRenderingIndex == 2);
}

#endregion
Expand Down
26 changes: 12 additions & 14 deletions Source/QuestPDF.UnitTests/TestEngine/TestPlan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using NUnit.Framework.Legacy;
using QuestPDF.Drawing;
using QuestPDF.Elements;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine.Operations;
Expand Down Expand Up @@ -231,18 +232,13 @@ public TestPlan CheckState(Func<Element, bool> condition)

public static Element CreateUniqueElement()
{
return new Constrained
{
MinWidth = 90,
MinHeight = 60,

Child = new DynamicImage
{
CompressionQuality = ImageCompressionQuality.Medium,
TargetDpi = DocumentSettings.DefaultRasterDpi,
Source = paylaod => Placeholders.Image(paylaod.ImageSize)
}
};
var content = new Container();

content
.AspectRatio(4 / 3f)
.Image(Placeholders.Image);

return content;
}

public static void CompareOperations(Element value, Element expected, Size? availableSpace = null)
Expand All @@ -253,7 +249,7 @@ public static void CompareOperations(Element value, Element expected, Size? avai

private static void CompareMeasureOperations(Element value, Element expected, Size? availableSpace = null)
{
availableSpace ??= new Size(400, 300);
availableSpace ??= new Size(400, 900);

var canvas = new FreeCanvas();
value.InjectDependencies(null, canvas);
Expand All @@ -267,14 +263,16 @@ private static void CompareMeasureOperations(Element value, Element expected, Si

private static void CompareDrawOperations(Element value, Element expected, Size? availableSpace = null)
{
availableSpace ??= new Size(400, 300);
availableSpace ??= new Size(400, 1200);

var valueCanvas = new OperationRecordingCanvas();
value.InjectDependencies(null, valueCanvas);
value.ApplyDefaultImageConfiguration(144, ImageCompressionQuality.Medium, false);
value.Draw(availableSpace.Value);

var expectedCanvas = new OperationRecordingCanvas();
expected.InjectDependencies(null, expectedCanvas);
expected.ApplyDefaultImageConfiguration(144, ImageCompressionQuality.Medium, false);
expected.Draw(availableSpace.Value);

valueCanvas.Operations.Should().BeEquivalentTo(expectedCanvas.Operations);
Expand Down
2 changes: 1 addition & 1 deletion Source/QuestPDF/Drawing/DocumentGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ private static void RenderPass<TCanvas>(PageContext pageContext, TCanvas canvas,
where TCanvas : ICanvas, IRenderingCanvas
{
content.InjectDependencies(pageContext, canvas);
content.VisitChildren(x => (x as IStateResettable)?.ResetState());
content.VisitChildren(x => (x as IStateResettable)?.ResetState(hardReset: true));

while(true)
{
Expand Down
5 changes: 1 addition & 4 deletions Source/QuestPDF/Elements/Column.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ internal sealed class Column : Element, ICacheable, IStateResettable

internal int CurrentRenderingIndex { get; set; }

public void ResetState()
public void ResetState(bool hardReset)
{
CurrentRenderingIndex = 0;
}
Expand Down Expand Up @@ -79,9 +79,6 @@ internal override void Draw(Size availableSpace)

var fullyRenderedItems = renderingCommands.Count(x => x.Measurement.Type is SpacePlanType.FullRender);
CurrentRenderingIndex += fullyRenderedItems;

if (CurrentRenderingIndex == Items.Count)
ResetState();
}

private List<ColumnItemRenderingCommand> PlanLayout(Size availableSpace)
Expand Down
2 changes: 1 addition & 1 deletion Source/QuestPDF/Elements/DebugArea.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public void Compose(IContainer container)
.Layer()
.ShowIf(!string.IsNullOrWhiteSpace(Text))
.AlignCenter()
.MinimalBox()
.Shrink()
.Background(Colors.White)
.Padding(2)
.Text(Text)
Expand Down
18 changes: 14 additions & 4 deletions Source/QuestPDF/Elements/Dynamic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ namespace QuestPDF.Elements
{
internal sealed class DynamicHost : Element, IStateResettable, IContentDirectionAware
{
private bool IsRendered { get; set; }

private DynamicComponentProxy Child { get; }
private object InitialComponentState { get; set; }

Expand All @@ -25,14 +27,18 @@ public DynamicHost(DynamicComponentProxy child)
InitialComponentState = Child.GetState();
}

public void ResetState()
public void ResetState(bool hardReset)
{
IsRendered = false;
Child.SetState(InitialComponentState);
}

internal override SpacePlan Measure(Size availableSpace)
{
var result = GetContent(availableSpace, acceptNewState: false);
if (IsRendered)
return SpacePlan.FullRender(Size.Zero);

var result = ComposeContent(availableSpace, acceptNewState: false);
var content = result.Content as Element ?? Empty.Instance;
var measurement = content.Measure(availableSpace);

Expand All @@ -46,11 +52,15 @@ internal override SpacePlan Measure(Size availableSpace)

internal override void Draw(Size availableSpace)
{
var content = GetContent(availableSpace, acceptNewState: true).Content as Element;
var composeResult = ComposeContent(availableSpace, acceptNewState: true);
var content = composeResult.Content as Element;
content?.Draw(availableSpace);

if (!composeResult.HasMoreContent)
IsRendered = true;
}

private DynamicComponentComposeResult GetContent(Size availableSize, bool acceptNewState)
private DynamicComponentComposeResult ComposeContent(Size availableSize, bool acceptNewState)
{
var componentState = Child.GetState();

Expand Down
21 changes: 17 additions & 4 deletions Source/QuestPDF/Elements/DynamicImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,29 @@ public class GenerateDynamicImageDelegatePayload
/// <returns>An image in PNG, JPEG, or WEBP image format returned as byte array.</returns>
public delegate byte[]? GenerateDynamicImageDelegate(GenerateDynamicImageDelegatePayload payload);

internal sealed class DynamicImage : Element
internal sealed class DynamicImage : Element, IStateResettable
{
private bool IsRendered { get; set; }

internal int? TargetDpi { get; set; }
internal ImageCompressionQuality? CompressionQuality { get; set; }
internal bool UseOriginalImage { get; set; }
public GenerateDynamicImageDelegate? Source { get; set; }

public void ResetState(bool hardReset = false)
{
IsRendered = false;
}

internal override SpacePlan Measure(Size availableSpace)
{
return availableSpace.IsNegative()
? SpacePlan.Wrap()
: SpacePlan.FullRender(availableSpace);
if (IsRendered)
return SpacePlan.FullRender(Size.Zero);

if (availableSpace.IsNegative())
return SpacePlan.Wrap();

return SpacePlan.FullRender(availableSpace);
}

internal override void Draw(Size availableSpace)
Expand Down Expand Up @@ -63,6 +74,8 @@ internal override void Draw(Size availableSpace)

var targetImage = Helpers.Helpers.GetImageWithSmallerSize(originalImage, compressedImage);
Canvas.DrawImage(targetImage, availableSpace);

IsRendered = true;
}

private static ImageSize GetTargetResolution(Size availableSize, int targetDpi)
Expand Down
21 changes: 17 additions & 4 deletions Source/QuestPDF/Elements/DynamicSvgImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,26 @@

namespace QuestPDF.Elements;

internal class DynamicSvgImage : Element
internal class DynamicSvgImage : Element, IStateResettable
{
private bool IsRendered { get; set; }

public GenerateDynamicSvgDelegate SvgSource { get; set; }

public void ResetState(bool hardReset = false)
{
IsRendered = false;
}

internal override SpacePlan Measure(Size availableSpace)
{
return availableSpace.IsNegative()
? SpacePlan.Wrap()
: SpacePlan.FullRender(availableSpace);
if (IsRendered)
return SpacePlan.FullRender(Size.Zero);

if (availableSpace.IsNegative())
return SpacePlan.Wrap();

return SpacePlan.FullRender(availableSpace);
}

internal override void Draw(Size availableSpace)
Expand All @@ -26,5 +37,7 @@ internal override void Draw(Size availableSpace)

using var svgImage = new SkSvgImage(svg, FontManager.CurrentFontManager);
Canvas.DrawSvg(svgImage, availableSpace);

IsRendered = true;
}
}
2 changes: 1 addition & 1 deletion Source/QuestPDF/Elements/Empty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace QuestPDF.Elements
{
internal sealed class Empty : Element
{
internal static Empty Instance { get; } = new Empty();
internal static Empty Instance { get; } = new();

internal override SpacePlan Measure(Size availableSpace)
{
Expand Down
21 changes: 17 additions & 4 deletions Source/QuestPDF/Elements/Image.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,30 @@

namespace QuestPDF.Elements
{
internal sealed class Image : Element, ICacheable
internal sealed class Image : Element, ICacheable, IStateResettable
{
private bool IsRendered { get; set; }

public Infrastructure.Image? DocumentImage { get; set; }

internal bool UseOriginalImage { get; set; }
internal int? TargetDpi { get; set; }
internal ImageCompressionQuality? CompressionQuality { get; set; }

public void ResetState(bool hardReset = false)
{
IsRendered = false;
}

internal override SpacePlan Measure(Size availableSpace)
{
return availableSpace.IsNegative()
? SpacePlan.Wrap()
: SpacePlan.FullRender(Size.Zero);
if (IsRendered)
return SpacePlan.FullRender(Size.Zero);

if (availableSpace.IsNegative())
return SpacePlan.Wrap();

return SpacePlan.FullRender(Size.Zero);
}

internal override void Draw(Size availableSpace)
Expand All @@ -27,6 +38,8 @@ internal override void Draw(Size availableSpace)

var image = GetImageToDraw(availableSpace);
Canvas.DrawImage(image, availableSpace);

IsRendered = true;
}

private SkImage GetImageToDraw(Size availableSpace)
Expand Down
2 changes: 1 addition & 1 deletion Source/QuestPDF/Elements/Inlined.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ internal sealed class Inlined : Element, IContentDirectionAware, IStateResettabl
internal InlinedAlignment? ElementsAlignment { get; set; }
internal VerticalAlignment BaselineAlignment { get; set; }

public void ResetState()
public void ResetState(bool hardReset)
{
CurrentRenderingIndex = 0;
}
Expand Down
2 changes: 1 addition & 1 deletion Source/QuestPDF/Elements/Layers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ internal sealed class Layer : ContainerElement

internal sealed class Layers : Element, ICacheable
{
public List<Layer> Children { get; set; } = new List<Layer>();
public List<Layer> Children { get; set; } = new();

internal override IEnumerable<Element?> GetChildren()
{
Expand Down
24 changes: 18 additions & 6 deletions Source/QuestPDF/Elements/Line.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,31 @@ internal enum LineType
Horizontal
}

internal sealed class Line : Element, ILine, ICacheable
internal sealed class Line : Element, ILine, ICacheable, IStateResettable
{
private bool IsRendered { get; set; }

public LineType Type { get; set; } = LineType.Vertical;
public Color Color { get; set; } = Colors.Black;
public float Size { get; set; } = 1;
public float Thickness { get; set; } = 1;

public void ResetState(bool hardReset)
{
IsRendered = false;
}

internal override SpacePlan Measure(Size availableSpace)
{
if (IsRendered)
return SpacePlan.FullRender(Size.Zero);

if (availableSpace.IsNegative())
return SpacePlan.Wrap();

return Type switch
{
LineType.Vertical when availableSpace.Width + Infrastructure.Size.Epsilon >= Size => SpacePlan.FullRender(Size, 0),
LineType.Horizontal when availableSpace.Height + Infrastructure.Size.Epsilon >= Size => SpacePlan.FullRender(0, Size),
LineType.Vertical when availableSpace.Width + Infrastructure.Size.Epsilon >= Thickness => SpacePlan.FullRender(Thickness, 0),
LineType.Horizontal when availableSpace.Height + Infrastructure.Size.Epsilon >= Thickness => SpacePlan.FullRender(0, Thickness),
_ => SpacePlan.Wrap()
};
}
Expand All @@ -38,12 +48,14 @@ internal override void Draw(Size availableSpace)
{
if (Type == LineType.Vertical)
{
Canvas.DrawFilledRectangle(new Position(-Size/2, 0), new Size(Size, availableSpace.Height), Color);
Canvas.DrawFilledRectangle(new Position(-Thickness/2, 0), new Size(Thickness, availableSpace.Height), Color);
}
else if (Type == LineType.Horizontal)
{
Canvas.DrawFilledRectangle(new Position(0, -Size/2), new Size(availableSpace.Width, Size), Color);
Canvas.DrawFilledRectangle(new Position(0, -Thickness/2), new Size(availableSpace.Width, Thickness), Color);
}

IsRendered = true;
}
}
}
2 changes: 1 addition & 1 deletion Source/QuestPDF/Elements/PageBreak.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal sealed class PageBreak : Element, IStateResettable
{
private bool IsRendered { get; set; }

public void ResetState()
public void ResetState(bool hardReset)
{
IsRendered = false;
}
Expand Down

0 comments on commit 484690a

Please sign in to comment.