Compare commits

..

3 Commits

Author SHA1 Message Date
Marcin Ziąbek 2772b5b4a4 Size component cleanup 2021-09-12 20:25:50 +02:00
Marcin Ziąbek 3dfe7a59e0 Fixed space removal 2021-09-12 20:15:41 +02:00
Marcin Ziąbek df5c5524ee Fixed text alignment 2021-09-12 20:10:52 +02:00
143 changed files with 1105 additions and 3332 deletions
-33
View File
@@ -1,33 +0,0 @@
using System.IO;
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
public class BarCode
{
[Test]
public void Example()
{
FontManager.RegisterFontType("LibreBarcode39", File.OpenRead("LibreBarcode39-Regular.ttf"));
RenderingTest
.Create()
.PageSize(400, 100)
.FileName()
.ShowResults()
.Render(container =>
{
container
.Background(Colors.White)
.AlignCenter()
.AlignMiddle()
.Text("*QuestPDF*", TextStyle.Default.FontType("LibreBarcode39").Size(64));
});
}
}
}
-46
View File
@@ -1,46 +0,0 @@
using System.Diagnostics;
using System.Linq;
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
public class ContinuousPageDocument : IDocument
{
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container.Page(page =>
{
page.Margin(20);
page.ContinuousSize(150);
page.Header().Text("Header");
page.Content().PaddingVertical(10).Border(1).Padding(10).Stack(stack =>
{
foreach (var index in Enumerable.Range(1, 100))
stack.Item().Text($"Line {index}", TextStyle.Default.Color(Placeholders.Color()));
});
page.Footer().Text("Footer");
});
}
}
public class ContinuousPageExamples
{
[Test]
public void ContinuousPage()
{
var path = "example.pdf";
new ContinuousPageDocument().GeneratePdf(path);
Process.Start("explorer", path);
}
}
}
-33
View File
@@ -1,33 +0,0 @@
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
namespace QuestPDF.Examples
{
public class DebuggingTesting
{
[Test]
public void Stack()
{
RenderingTest
.Create()
.PageSize(500, 360)
.FileName()
.Render(container =>
{
container
.Background(Colors.White)
.Padding(15)
.Grid(grid =>
{
grid.Spacing(15);
grid.Item().Background(Colors.Grey.Medium).Text(Placeholders.LoremIpsum());
grid.Item().DebugPointer("Test").Background(Colors.Grey.Lighten1).Height(1000); // <-- problem
grid.Item().Background(Colors.Grey.Lighten2).Height(150);
});
});
}
}
}
-170
View File
@@ -1,170 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using QuestPDF.Elements;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
public class OrderItem
{
public string ItemName { get; set; } = Placeholders.Label();
public int Price { get; set; } = Placeholders.Random.Next(1, 11) * 10;
public int Count { get; set; } = Placeholders.Random.Next(1, 11);
}
public class OrdersTable : IDynamicComponent
{
private ICollection<OrderItem> Items { get; }
private ICollection<OrderItem> ItemsLeft { get; set; }
public OrdersTable(ICollection<OrderItem> items)
{
Items = items;
}
public void Compose(DynamicContext context, IDynamicContainer container)
{
if (context.Operation == DynamicLayoutOperation.Reset)
{
ItemsLeft = new List<OrderItem>(Items);
return;
}
var header = ComposeHeader(context);
var sampleFooter = ComposeFooter(context, Enumerable.Empty<OrderItem>());
var decorationHeight = header.Size.Height + sampleFooter.Size.Height;
var rows = GetItemsForPage(context, decorationHeight).ToList();
var footer = ComposeFooter(context, rows.Select(x => x.Item));
if (ItemsLeft.Count > rows.Count)
container.HasMoreContent();
if (context.Operation == DynamicLayoutOperation.Draw)
ItemsLeft = ItemsLeft.Skip(rows.Count).ToList();
container.Box().Decoration(decoration =>
{
decoration.Header().Element(header);
decoration.Content().Box().Stack(stack =>
{
foreach (var row in rows)
stack.Item().Element(row.Element);
});
decoration.Footer().Element(footer);
});
}
private IDynamicElement ComposeHeader(DynamicContext context)
{
return context.CreateElement(element =>
{
element
.BorderBottom(1)
.BorderColor(Colors.Grey.Darken2)
.Padding(5)
.Row(row =>
{
var textStyle = TextStyle.Default.SemiBold();
row.ConstantColumn(30).Text("#", textStyle);
row.RelativeColumn().Text("Item name", textStyle);
row.ConstantColumn(50).AlignRight().Text("Count", textStyle);
row.ConstantColumn(50).AlignRight().Text("Price", textStyle);
row.ConstantColumn(50).AlignRight().Text("Total", textStyle);
});
});
}
private IDynamicElement ComposeFooter(DynamicContext context, IEnumerable<OrderItem> items)
{
var total = items.Sum(x => x.Count * x.Price);
return context.CreateElement(element =>
{
element
.Padding(5)
.AlignRight()
.Text($"Subtotal: {total}$", TextStyle.Default.Size(14).SemiBold());
});
}
private IEnumerable<(OrderItem Item, IDynamicElement Element)> GetItemsForPage(DynamicContext context, float decorationHeight)
{
var totalHeight = decorationHeight;
var counter = Items.Count - ItemsLeft.Count + 1;
foreach (var orderItem in ItemsLeft)
{
var element = context.CreateElement(content =>
{
content
.BorderBottom(1)
.BorderColor(Colors.Grey.Lighten2)
.Padding(5)
.Row(row =>
{
row.ConstantColumn(30).Text(counter++);
row.RelativeColumn().Text(orderItem.ItemName);
row.ConstantColumn(50).AlignRight().Text(orderItem.Count);
row.ConstantColumn(50).AlignRight().Text($"{orderItem.Price}$");
row.ConstantColumn(50).AlignRight().Text($"{orderItem.Count*orderItem.Price}$");
});
});
var elementHeight = element.Size.Height;
if (totalHeight + elementHeight > context.AvailableSize.Height)
break;
totalHeight += elementHeight;
yield return (orderItem, element);
}
}
}
public static class DynamicExamples
{
[Test]
public static void Dynamic()
{
RenderingTest
.Create()
.PageSize(PageSizes.A5)
.FileName()
.ShowResults()
.Render(container =>
{
var items = Enumerable.Range(0, 25).Select(x => new OrderItem()).ToList();
container
.Background(Colors.White)
.Padding(25)
.Decoration(decoration =>
{
decoration
.Header()
.PaddingBottom(5)
.Text(text =>
{
text.DefaultTextStyle(TextStyle.Default.SemiBold().Color(Colors.Blue.Darken2).Size(16));
text.Span("Page ");
text.CurrentPageNumber();
text.Span(" of ");
text.TotalPages();
});
decoration
.Content()
.Dynamic(new OrdersTable(items));
});
});
}
}
}
+4 -82
View File
@@ -154,7 +154,7 @@ namespace QuestPDF.Examples
{
container
.Padding(25)
.DebugArea("Grid example", Colors.Blue.Medium)
.Debug("Grid example", Colors.Blue.Medium)
.Grid(grid =>
{
grid.Columns(3);
@@ -581,7 +581,7 @@ namespace QuestPDF.Examples
{
RenderingTest
.Create()
.PageSize(650, 450)
.PageSize(350, 350)
.FileName()
.Render(container =>
{
@@ -595,8 +595,8 @@ namespace QuestPDF.Examples
foreach (var turns in Enumerable.Range(0, 4))
{
grid.Item()
.Width(300)
.Height(200)
.Width(150)
.Height(150)
.Background(Colors.Grey.Lighten2)
.Padding(10)
.Element(element =>
@@ -778,83 +778,5 @@ namespace QuestPDF.Examples
});
});
}
[Test]
public void ComplexLayout()
{
RenderingTest
.Create()
.PageSize(500, 225)
.FileName()
.Render(container =>
{
container
.Padding(25)
.Stack(stack =>
{
stack.Item().Row(row =>
{
row.RelativeColumn().LabelCell("Label 1");
row.RelativeColumn(3).Grid(grid =>
{
grid.Columns(3);
grid.Item(2).LabelCell("Label 2");
grid.Item().LabelCell("Label 3");
grid.Item(2).ValueCell().Text("Value 2");
grid.Item().ValueCell().Text("Value 3");
});
});
stack.Item().Row(row =>
{
row.RelativeColumn().ValueCell().Text("Value 1");
row.RelativeColumn(3).Grid(grid =>
{
grid.Columns(3);
grid.Item().LabelCell("Label 4");
grid.Item(2).LabelCell("Label 5");
grid.Item().ValueCell().Text("Value 4");
grid.Item(2).ValueCell().Text("Value 5");
});
});
stack.Item().Row(row =>
{
row.RelativeColumn().LabelCell("Label 6");
row.RelativeColumn().ValueCell().Text("Value 6");
});
});
});
}
[Test]
public void DomainSpecificLanguage()
{
RenderingTest
.Create()
.PageSize(600, 310)
.FileName()
.Render(container =>
{
container
.Padding(25)
.Grid(grid =>
{
grid.Columns(10);
for(var i=1; i<=4; i++)
{
grid.Item(2).LabelCell(Placeholders.Label());
grid.Item(3).ValueCell().Image(Placeholders.Image(200, 150));
}
});
});
}
}
}
+4 -5
View File
@@ -12,24 +12,23 @@ namespace QuestPDF.Examples
{
return container
.Border(1)
.Background(dark ? Colors.Grey.Lighten2 : Colors.White)
.Background(dark ? "#EEE" : "#FFF")
.Padding(10);
}
public static void LabelCell(this IContainer container, string text) => container.Cell(true).Text(text, TextStyle.Default.Medium());
public static IContainer LabelCell(this IContainer container) => container.Cell(true);
public static IContainer ValueCell(this IContainer container) => container.Cell(false);
}
public class FrameExample
{
[Test]
public void Frame()
public void Frame(IContainer container)
{
RenderingTest
.Create()
.PageSize(550, 400)
.FileName()
.ShowResults()
.Render(container =>
{
container
@@ -41,7 +40,7 @@ namespace QuestPDF.Examples
{
stack.Item().Row(row =>
{
row.RelativeColumn(2).LabelCell(Placeholders.Label());
row.RelativeColumn(2).LabelCell().Text(Placeholders.Label());
row.RelativeColumn(3).ValueCell().Text(Placeholders.Paragraph());
});
}
Binary file not shown.
+1 -2
View File
@@ -12,9 +12,8 @@ namespace QuestPDF.Examples
{
RenderingTest
.Create()
.PageSize(300, 300)
.PageSize(200, 150)
.FileName()
.ShowResults()
.Render(container =>
{
container
+3 -6
View File
@@ -6,10 +6,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="nunit" Version="3.13.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
<PackageReference Include="nunit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="SkiaSharp" Version="2.80.3" />
<PackageReference Include="SkiaSharp" Version="2.80.2" />
</ItemGroup>
<ItemGroup>
@@ -20,9 +20,6 @@
<None Update="quo-vadis.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="LibreBarcode39-Regular.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
+1 -1
View File
@@ -200,7 +200,7 @@ namespace QuestPDF.Examples
text.DefaultTextStyle(normalStyle);
text.Span("Ten dokument został wygenerowany na podstawie książki w formacie TXT opublikowanej w serwisie ");
text.ExternalLocation("wolnelektury.pl", "https://wolnelektury.pl/", normalStyle.Color(Colors.Blue.Medium).Underline());
text.ExternalLocation("wolnelektury.pl", "https://wolnelektury.pl/", normalStyle.Color(Colors.Blue.Medium).Underlined());
text.Span(". Dziękuję za wspieranie polskiego czytelnictwa!");
});
});
+58 -213
View File
@@ -1,6 +1,5 @@
using System;
using System.Linq;
using System.Text;
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
@@ -11,140 +10,21 @@ namespace QuestPDF.Examples
{
public class TextExamples
{
[Test]
public void SimpleTextBlock()
{
RenderingTest
.Create()
.PageSize(500, 300)
.FileName()
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Padding(5)
.Box()
.Border(1)
.Padding(10)
.Text(text =>
{
text.DefaultTextStyle(TextStyle.Default.Size(20));
text.Span("This is a normal text, followed by an ");
text.Span("underlined red text.", TextStyle.Default.Size(20).Color(Colors.Red.Medium).Underline());
});
});
}
[Test]
public void ParagraphSpacing()
{
RenderingTest
.Create()
.PageSize(500, 300)
.FileName()
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Padding(5)
.Box()
.Border(1)
.Padding(10)
.Text(text =>
{
text.ParagraphSpacing(10);
foreach (var i in Enumerable.Range(1, 3))
{
text.Span($"Paragraph {i}: ", TextStyle.Default.SemiBold());
text.Line(Placeholders.Paragraph());
}
});
});
}
[Test]
public void CustomElement()
{
RenderingTest
.Create()
.PageSize(500, 200)
.FileName()
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Padding(5)
.Box()
.Border(1)
.Padding(10)
.Text(text =>
{
text.DefaultTextStyle(TextStyle.Default.Size(20));
text.Span("This is a random image aligned to the baseline: ");
text.Element()
.PaddingBottom(-6)
.Height(24)
.Width(48)
.Image(Placeholders.Image);
text.Span(".");
});
});
}
[Test]
public void TextElements()
{
RenderingTest
.Create()
.PageSize(PageSizes.A4)
.PageSize(500, 400)
.FileName()
.ProducePdf()
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Padding(20)
.Padding(10)
.Box()
.Border(1)
.Padding(5)
.Padding(10)
.Text(text =>
{
text.DefaultTextStyle(TextStyle.Default);
text.AlignLeft();
text.ParagraphSpacing(10);
text.Line(Placeholders.LoremIpsum());
text.Span($"This is target text that should show up. {DateTime.UtcNow:T} > This is a short sentence that will be wrapped into second line hopefully, right? <", TextStyle.Default.Underline());
});
});
}
[Test]
public void TextStack()
{
RenderingTest
.Create()
.PageSize(PageSizes.A4)
.FileName()
.ProducePdf()
.ShowResults()
.Render(container =>
{
container
.Padding(20)
.Padding(10)
.Box()
.Border(1)
.Padding(5)
.Padding(10)
.Text(text =>
{
@@ -152,29 +32,78 @@ namespace QuestPDF.Examples
text.AlignLeft();
text.ParagraphSpacing(10);
foreach (var i in Enumerable.Range(1, 100))
text.Line($"{i}: {Placeholders.Paragraph()}");
text.Span(Placeholders.LoremIpsum());
text.NewLine();
text.Span("This text is a normal text, ");
text.Span("this is a bold text, ", TextStyle.Default.Bold());
text.Span("this is a red and underlined text, ", TextStyle.Default.Color(Colors.Red.Medium).Underlined());
text.Span("and this is slightly bigger text.", TextStyle.Default.Size(16));
text.NewLine();
text.Span("The new text element also supports injecting custom content between words: ");
text.Element().PaddingBottom(-10).Height(16).Width(32).Image(Placeholders.Image);
text.Span(".");
text.NewLine();
text.Span("This is page number ");
text.CurrentPageNumber();
text.Span(" out of ");
text.TotalPages();
text.NewLine();
text.ExternalLocation("Please visit QuestPDF website", "https://www.questpdf.com");
text.NewLine();
/*
text.Span("Let's start with bold text. ", TextStyle.Default.Bold().BackgroundColor(Colors.Grey.Lighten3).Size(16));
text.Span("Then something bigger. ", TextStyle.Default.Size(28).Color(Colors.DeepOrange.Darken2).BackgroundColor(Colors.Yellow.Lighten3).Underlined());
text.Span("And tiny \r\n teeny-tiny. ", TextStyle.Default.Size(6));
text.Span("Stroked text also works fine. ", TextStyle.Default.Size(14).Stroked().BackgroundColor(Colors.Grey.Lighten4));
text.Span("0123456789-0123456789-0123456789-0123456789-0123456789-0123456789-0123456789", TextStyle.Default.Size(18));
text.NewLine();
text.NewLine();
text.NewLine();
text.Span("Is it time for lorem ipsum? ", TextStyle.Default.Size(12).Underlined().BackgroundColor(Colors.Grey.Lighten3));
text.Span(Placeholders.LoremIpsum(), TextStyle.Default.Size(12));
text.Span("Before element - ");
text.Element().PaddingBottom(-10).Background(Colors.Red.Lighten4).Height(20).PaddingHorizontal(5).AlignMiddle().Text("Text inside text", TextStyle.Default.Size(8));
text.Span(" - end of element.");
text.NewLine();
// text.Span("And now some colors: ", TextStyle.Default.Size(16).Color(Colors.Green.Medium));
//
// foreach (var i in Enumerable.Range(1, 100))
// {
// text.Span($"{i}: {Placeholders.Sentence()} ", TextStyle.Default.Size(12 + i / 5).LineHeight(2.75f - i / 50f).Color(Placeholders.Color()).BackgroundColor(Placeholders.BackgroundColor()));
// }*/
});
});
}
[Test]
public void SpaceIssue()
public void PageNumber()
{
RenderingTest
.Create()
.PageSize(PageSizes.A4)
.PageSize(500, 400)
.FileName()
.ProducePdf()
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Padding(20)
.Padding(10)
.Box()
.Border(1)
.Padding(5)
.Padding(10)
.Text(text =>
{
@@ -182,94 +111,10 @@ namespace QuestPDF.Examples
text.AlignLeft();
text.ParagraphSpacing(10);
text.Span(Placeholders.LoremIpsum());
text.EmptyLine();
text.Span("This text is a normal text, ");
text.Span("this is a bold text, ", TextStyle.Default.Bold());
text.Span("this is a red and underlined text, ", TextStyle.Default.Color(Colors.Red.Medium).Underline());
text.Span("and this is slightly bigger text.", TextStyle.Default.Size(16));
text.EmptyLine();
text.Span("The new text element also supports injecting custom content between words: ");
text.Element().PaddingBottom(-10).Height(16).Width(32).Image(Placeholders.Image);
text.Span(".");
text.EmptyLine();
text.Span("This is page number ");
text.CurrentPageNumber();
text.Span(" out of ");
text.TotalPages();
text.EmptyLine();
text.ExternalLocation("Please visit QuestPDF website", "https://www.questpdf.com");
text.EmptyLine();
text.Span(Placeholders.Paragraphs());
text.EmptyLine();
text.Span(Placeholders.Paragraphs(), TextStyle.Default.Italic());
text.Line("This is target text that does not show up. " + Placeholders.Paragraph());
});
});
}
[Test]
public void HugeList()
{
RenderingTest
.Create()
.PageSize(PageSizes.A4)
.FileName()
.ProducePdf()
.ShowResults()
.Render(container =>
{
container
.Padding(20)
.Padding(10)
.Box()
.Border(1)
.Padding(5)
.Padding(10)
.Text(text =>
{
text.DefaultTextStyle(TextStyle.Default);
text.AlignLeft();
text.ParagraphSpacing(10);
text.Span("This text is a normal text, ");
text.Span("this is a bold text, ", TextStyle.Default.Bold());
text.Span("this is a red and underlined text, ", TextStyle.Default.Color(Colors.Red.Medium).Underline());
text.Span("and this is slightly bigger text.", TextStyle.Default.Size(16));
text.Span("The new text element also supports injecting custom content between words: ");
text.Element().PaddingBottom(-10).Height(16).Width(32).Image(Placeholders.Image);
text.Span(".");
text.EmptyLine();
foreach (var i in Enumerable.Range(1, 100))
{
text.Line($"{i}: {Placeholders.Paragraph()}");
text.ExternalLocation("Please visit QuestPDF website", "https://www.questpdf.com");
text.Span("This is page number ");
text.CurrentPageNumber();
text.Span(" out of ");
text.TotalPages();
text.EmptyLine();
}
});
});
}
+1 -1
View File
@@ -6,7 +6,7 @@ namespace QuestPDF.ReportSample
{
public static class Helpers
{
public static Random Random { get; } = new Random(1);
public static Random Random { get; } = new Random();
public static string GetTestItem(string path) => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources", path);
@@ -30,14 +30,14 @@ namespace QuestPDF.ReportSample.Layouts
container
.Row(row =>
{
row.RelativeColumn(2).AspectRatio(4 / 3f).Background(Colors.Grey.Lighten3);
row.RelativeColumn(2).AspectRatio(4 / 3f).Image(Placeholders.Image);
row.RelativeColumn().PaddingLeft(5).Stack(stack =>
{
stack.Spacing(7f);
stack.Item().AspectRatio(4 / 3f).Background(Colors.Grey.Lighten3);
stack.Item().AspectRatio(4 / 3f).Background(Colors.Grey.Lighten3);
stack.Item().AspectRatio(4 / 3f).Image(Placeholders.Image);
stack.Item().AspectRatio(4 / 3f).Image(Placeholders.Image);
});
});
}
@@ -59,25 +59,25 @@ namespace QuestPDF.ReportSample.Layouts
{
stack.Spacing(5);
stack.Item().MaxWidth(250).AspectRatio(4 / 3f).Background(Colors.Grey.Lighten3);
stack.Item().MaxWidth(250).AspectRatio(4 / 3f).Image(Placeholders.Image);
stack.Item().Text(model.Location.Format(), Typography.Normal);
});
}
void PhotosElement(IContainer container, ReportSectionPhotos model)
{
if (model.Photos.Count == 0)
if (model.Photos.Count == 0)
{
container.Text("No photos", Typography.Normal);
return;
}
container.DebugArea("Photos").Grid(grid =>
container.Debug("Photos").Grid(grid =>
{
grid.Spacing(5);
grid.Columns(3);
model.Photos.ForEach(x => grid.Item().AspectRatio(4 / 3f).Background(Colors.Grey.Lighten3));
model.Photos.ForEach(x => grid.Item().AspectRatio(4 / 3f).Image(Placeholders.Image));
});
}
}
@@ -55,7 +55,7 @@ namespace QuestPDF.ReportSample.Layouts
row.Spacing(50);
row.RelativeColumn().PaddingTop(-10).Text(Model.Title, Typography.Title);
row.ConstantColumn(150).ExternalLink("https://www.questpdf.com").Background(Colors.Grey.Lighten3);
row.ConstantColumn(150).ExternalLink("https://www.questpdf.com").Image(Model.LogoData);
});
stack.Item().ShowOnce().PaddingVertical(15).Border(1f).BorderColor(Colors.Grey.Lighten1).ExtendHorizontal();
-70
View File
@@ -1,70 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Engines;
using BenchmarkDotNet.Running;
using Microsoft.VisualStudio.TestPlatform.TestHost;
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.Proxy;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.ReportSample.Layouts;
namespace QuestPDF.ReportSample
{
[SimpleJob(RunStrategy.Monitoring, launchCount: 0, warmupCount: 1, targetCount: 100)]
[MinColumn, MaxColumn, MeanColumn, MedianColumn]
public class PerformanceTests
{
private PageContext PageContext { get; set; }
private DocumentMetadata Metadata { get; set; }
private Container Content { get; set; }
[Test]
public void Run()
{
var configuration = ManualConfig
.Create(DefaultConfig.Instance)
.WithOptions(ConfigOptions.DisableOptimizationsValidator);
BenchmarkRunner.Run<PerformanceTests>(configuration);
}
[IterationSetup]
public void GenerateReportData()
{
var model = DataSource.GetReport();
var report = new StandardReport(model);
Metadata = report.GetMetadata();
var documentContainer = new DocumentContainer();
report.Compose(documentContainer);
Content = documentContainer.Compose();
PageContext = new PageContext();
DocumentGenerator.RenderPass(PageContext, new FreeCanvas(), Content, Metadata, null);
var sw = new Stopwatch();
sw.Start();
Content.HandleVisitor(x =>
{
if (x is ICacheable)
x.CreateProxy(y => new CacheProxy(y));
});
sw.Stop();
Console.WriteLine($"Creating cache took: {sw.ElapsedMilliseconds}");
}
[Benchmark]
public void GenerationTest()
{
DocumentGenerator.RenderPass(PageContext, new FreeCanvas(), Content, Metadata, null);
}
}
}
@@ -8,11 +8,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
<PackageReference Include="nunit" Version="3.13.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="SkiaSharp" Version="2.80.3" />
<PackageReference Include="DeepCloner" Version="0.10.2" />
<PackageReference Include="nunit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="SkiaSharp" Version="2.80.2" />
</ItemGroup>
<ItemGroup>
+41 -24
View File
@@ -3,45 +3,62 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
using QuestPDF.ReportSample.Layouts;
namespace QuestPDF.ReportSample
{
public class ReportGeneration
{
private StandardReport Report { get; set; }
[SetUp]
public void SetUp()
{
var model = DataSource.GetReport();
Report = new StandardReport(model);
}
[Test]
public void GenerateAndShow()
{
var reportModel = DataSource.GetReport();
var report = new StandardReport(reportModel);
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"test_result.pdf");
Report.GeneratePdf(path);
report.GeneratePdf(path);
Process.Start("explorer.exe", path);
}
[Test]
public void Profile()
{
var container = new DocumentContainer();
Report.Compose(container);
var content = container.Compose();
var metadata = Report.GetMetadata();
var pageContext = new PageContext();
DocumentGenerator.RenderPass(pageContext, new FreeCanvas(), content, metadata, null);
DocumentGenerator.RenderPass(pageContext, new FreeCanvas(), content, metadata, null);
[Test]
public void PerformanceBenchmark()
{
// target document length should be around 100 pages
// test size
const int testSize = 10;
const decimal performanceTarget = 1; // documents per second
// create report models
var reports = Enumerable
.Range(0, testSize)
.Select(x =>
{
var reportModel = DataSource.GetReport();
return new StandardReport(reportModel);
})
.ToList();
// generate documents
var sw = new Stopwatch();
sw.Start();
var totalSize = reports.Select(x => x.GeneratePdf()).Sum(x => (long)x.Length);
sw.Stop();
// show summary
Console.WriteLine($"Total size: {totalSize:N0} bytes");
var performance = sw.ElapsedMilliseconds / (decimal)testSize;
var speed = 1000M / performance;
Console.WriteLine($"Test time: {sw.ElapsedMilliseconds} ms");
Console.WriteLine($"Time per document: {performance:N} ms");
Console.WriteLine($"Documents per second: {speed:N} d/s");
//if (speed < performanceTarget)
// throw new Exception("Rendering algorithm is too slow.");
}
}
}
+10 -6
View File
@@ -1,5 +1,5 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
@@ -10,7 +10,11 @@ namespace QuestPDF.UnitTests
public class AlignmentTests
{
[Test]
public void Measure() => SimpleContainerTests.Measure<Alignment>();
public void Measure_ShouldHandleNullChild() => new Alignment().MeasureWithoutChild();
[Test]
public void Draw_ShouldHandleNullChild() => new Alignment().DrawWithoutChild();
[Test]
public void Draw_HorizontalCenter_VerticalCenter()
{
@@ -23,7 +27,7 @@ namespace QuestPDF.UnitTests
Child = x.CreateChild()
})
.DrawElement(new Size(1000, 500))
.ExpectChildMeasure(expectedInput: new Size(1000, 500), returns: SpacePlan.PartialRender(new Size(400, 200)))
.ExpectChildMeasure(expectedInput: new Size(1000, 500), returns: new PartialRender(new Size(400, 200)))
.ExpectCanvasTranslate(new Position(300, 150))
.ExpectChildDraw(new Size(400, 200))
.ExpectCanvasTranslate(new Position(-300, -150))
@@ -42,7 +46,7 @@ namespace QuestPDF.UnitTests
Child = x.CreateChild()
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: SpacePlan.FullRender(new Size(100, 50)))
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: new FullRender(new Size(100, 50)))
.ExpectCanvasTranslate(new Position(0, 125))
.ExpectChildDraw(new Size(100, 50))
.ExpectCanvasTranslate(new Position(0, -125))
@@ -61,7 +65,7 @@ namespace QuestPDF.UnitTests
Child = x.CreateChild()
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: SpacePlan.FullRender(new Size(100, 50)))
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: new FullRender(new Size(100, 50)))
.ExpectCanvasTranslate(new Position(150, 250))
.ExpectChildDraw(new Size(100, 50))
.ExpectCanvasTranslate(new Position(-150, -250))
@@ -80,7 +84,7 @@ namespace QuestPDF.UnitTests
Child = x.CreateChild()
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: SpacePlan.FullRender(new Size(100, 50)))
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: new FullRender(new Size(100, 50)))
.ExpectCanvasTranslate(new Position(300, 0))
.ExpectChildDraw(new Size(100, 50))
.ExpectCanvasTranslate(new Position(-300, 0))
+23 -17
View File
@@ -1,5 +1,5 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
@@ -9,6 +9,12 @@ namespace QuestPDF.UnitTests
[TestFixture]
public class AspectRatioTests
{
[Test]
public void Measure_ShouldHandleNullChild() => new AspectRatio().MeasureWithoutChild();
[Test]
public void Draw_ShouldHandleNullChild() => new AspectRatio().DrawWithoutChild();
[Test]
public void Measure_FitWidth_EnoughSpace_FullRender()
{
@@ -20,8 +26,8 @@ namespace QuestPDF.UnitTests
Ratio = 2f
})
.MeasureElement(new Size(400, 201))
.ExpectChildMeasure(new Size(400, 200), SpacePlan.FullRender(100, 50))
.CheckMeasureResult(SpacePlan.FullRender(400, 200));
.ExpectChildMeasure(new Size(400, 200), new FullRender(100, 50))
.CheckMeasureResult(new FullRender(400, 200));
}
[Test]
@@ -35,8 +41,8 @@ namespace QuestPDF.UnitTests
Ratio = 2f
})
.MeasureElement(new Size(400, 201))
.ExpectChildMeasure(new Size(400, 200), SpacePlan.PartialRender(100, 50))
.CheckMeasureResult(SpacePlan.PartialRender(400, 200));
.ExpectChildMeasure(new Size(400, 200), new PartialRender(100, 50))
.CheckMeasureResult(new PartialRender(400, 200));
}
[Test]
@@ -50,8 +56,8 @@ namespace QuestPDF.UnitTests
Ratio = 2f
})
.MeasureElement(new Size(400, 201))
.ExpectChildMeasure(new Size(400, 200), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
.ExpectChildMeasure(new Size(400, 200), new Wrap())
.CheckMeasureResult(new Wrap());
}
[Test]
@@ -65,8 +71,8 @@ namespace QuestPDF.UnitTests
Ratio = 2f
})
.MeasureElement(new Size(400, 201))
.ExpectChildMeasure(new Size(400, 200), SpacePlan.FullRender(100, 50))
.CheckMeasureResult(SpacePlan.FullRender(400, 200));
.ExpectChildMeasure(new Size(400, 200), new FullRender(100, 50))
.CheckMeasureResult(new FullRender(400, 200));
}
[Test]
@@ -80,7 +86,7 @@ namespace QuestPDF.UnitTests
Ratio = 2f
})
.MeasureElement(new Size(400, 199))
.CheckMeasureResult(SpacePlan.Wrap());
.CheckMeasureResult(new Wrap());
}
[Test]
@@ -94,8 +100,8 @@ namespace QuestPDF.UnitTests
Ratio = 2f
})
.MeasureElement(new Size(401, 200))
.ExpectChildMeasure(new Size(400, 200), SpacePlan.FullRender(100, 50))
.CheckMeasureResult(SpacePlan.FullRender(400, 200));
.ExpectChildMeasure(new Size(400, 200), new FullRender(100, 50))
.CheckMeasureResult(new FullRender(400, 200));
}
[Test]
@@ -109,7 +115,7 @@ namespace QuestPDF.UnitTests
Ratio = 2f
})
.MeasureElement(new Size(399, 200))
.CheckMeasureResult(SpacePlan.Wrap());
.CheckMeasureResult(new Wrap());
}
[Test]
@@ -123,8 +129,8 @@ namespace QuestPDF.UnitTests
Ratio = 2f
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(400, 200), SpacePlan.FullRender(100, 50))
.CheckMeasureResult(SpacePlan.FullRender(400, 200));
.ExpectChildMeasure(new Size(400, 200), new FullRender(100, 50))
.CheckMeasureResult(new FullRender(400, 200));
}
[Test]
@@ -138,8 +144,8 @@ namespace QuestPDF.UnitTests
Ratio = 2f
})
.MeasureElement(new Size(500, 200))
.ExpectChildMeasure(new Size(400, 200), SpacePlan.FullRender(100, 50))
.CheckMeasureResult(SpacePlan.FullRender(400, 200));
.ExpectChildMeasure(new Size(400, 200), new FullRender(100, 50))
.CheckMeasureResult(new FullRender(400, 200));
}
[Test]
+2 -2
View File
@@ -10,8 +10,8 @@ namespace QuestPDF.UnitTests
public class BackgroundTests
{
[Test]
public void Measure() => SimpleContainerTests.Measure<Background>();
public void Measure_ShouldHandleNullChild() => new Background().MeasureWithoutChild();
[Test]
public void Draw_ShouldHandleNullChild()
{
+5 -5
View File
@@ -1,5 +1,5 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
@@ -11,8 +11,8 @@ namespace QuestPDF.UnitTests
public class BorderTests
{
[Test]
public void Measure() => SimpleContainerTests.Measure<Border>();
public void Measure_ShouldHandleNullChild() => new Border().MeasureWithoutChild();
[Test]
public void ComponentShouldNotAffectLayout()
{
@@ -27,8 +27,8 @@ namespace QuestPDF.UnitTests
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: SpacePlan.FullRender(new Size(100, 50)))
.CheckMeasureResult( SpacePlan.FullRender(new Size(100, 50)));
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: new FullRender(new Size(100, 50)))
.CheckMeasureResult( new FullRender(new Size(100, 50)));
}
[Test]
-56
View File
@@ -1,56 +0,0 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class BoxTests
{
[Test]
public void Measure() => SimpleContainerTests.Measure<Box>();
[Test]
public void Draw_Wrap()
{
TestPlan
.For(x => new Box
{
Child = x.CreateChild()
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: SpacePlan.Wrap())
.CheckDrawResult();
}
[Test]
public void Measure_PartialRender()
{
TestPlan
.For(x => new Box
{
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: SpacePlan.PartialRender(200, 100))
.ExpectChildDraw(new Size(200, 100))
.CheckDrawResult();
}
[Test]
public void Measure_FullRender()
{
TestPlan
.For(x => new Box
{
Child = x.CreateChild()
})
.MeasureElement(new Size(500, 400))
.ExpectChildMeasure(expectedInput: new Size(500, 400), returns: SpacePlan.FullRender(300, 200))
.ExpectChildDraw(new Size(300, 200))
.CheckDrawResult();
}
}
}
+17 -11
View File
@@ -1,5 +1,5 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
@@ -9,6 +9,12 @@ namespace QuestPDF.UnitTests
[TestFixture]
public class ConstrainedTests
{
[Test]
public void Measure_ShouldHandleNullChild() => new Constrained().MeasureWithoutChild();
[Test]
public void Draw_ShouldHandleNullChild() => new Constrained().DrawWithoutChild();
[Test]
public void Measure_MinHeight_ExpectWrap()
{
@@ -18,7 +24,7 @@ namespace QuestPDF.UnitTests
MinHeight = 100
})
.MeasureElement(new Size(400, 50))
.CheckMeasureResult(SpacePlan.Wrap());
.CheckMeasureResult(new Wrap());
}
[Test]
@@ -31,8 +37,8 @@ namespace QuestPDF.UnitTests
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 200))
.ExpectChildMeasure(new Size(400, 200), SpacePlan.FullRender(400, 50))
.CheckMeasureResult(SpacePlan.FullRender(400, 100));
.ExpectChildMeasure(new Size(400, 200), new FullRender(400, 50))
.CheckMeasureResult(new FullRender(400, 100));
}
[Test]
@@ -45,8 +51,8 @@ namespace QuestPDF.UnitTests
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 200))
.ExpectChildMeasure(new Size(400, 200), SpacePlan.FullRender(400, 150))
.CheckMeasureResult(SpacePlan.FullRender(400, 150));
.ExpectChildMeasure(new Size(400, 200), new FullRender(400, 150))
.CheckMeasureResult(new FullRender(400, 150));
}
[Test]
@@ -58,7 +64,7 @@ namespace QuestPDF.UnitTests
MaxHeight = 100
})
.MeasureElement(new Size(400, 150))
.CheckMeasureResult(SpacePlan.FullRender(0, 0));
.CheckMeasureResult(new FullRender(0, 0));
}
[Test]
@@ -71,8 +77,8 @@ namespace QuestPDF.UnitTests
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 200))
.ExpectChildMeasure(new Size(400, 100), SpacePlan.PartialRender(400, 75))
.CheckMeasureResult(SpacePlan.PartialRender(400, 75));
.ExpectChildMeasure(new Size(400, 100), new PartialRender(400, 75))
.CheckMeasureResult(new PartialRender(400, 75));
}
[Test]
@@ -85,8 +91,8 @@ namespace QuestPDF.UnitTests
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 200))
.ExpectChildMeasure(new Size(400, 100), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
.ExpectChildMeasure(new Size(400, 100), new Wrap())
.CheckMeasureResult(new Wrap());
}
}
}
+10
View File
@@ -0,0 +1,10 @@
using NUnit.Framework;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class DebugTests
{
}
}
+23 -23
View File
@@ -1,5 +1,5 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
@@ -15,78 +15,78 @@ namespace QuestPDF.UnitTests
public void Measure_ReturnsWrap_WhenDecorationReturnsWrap()
{
TestPlan
.For(x => new BinaryDecoration
.For(x => new SimpleDecoration
{
Type = DecorationType.Append,
DecorationElement = x.CreateChild("decoration"),
ContentElement = x.CreateChild("content")
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
.ExpectChildMeasure("decoration", new Size(400, 300), new Wrap())
.CheckMeasureResult(new Wrap());
}
[Test]
public void Measure_ReturnsWrap_WhenDecorationReturnsPartialRender()
{
TestPlan
.For(x => new BinaryDecoration
.For(x => new SimpleDecoration
{
Type = DecorationType.Append,
DecorationElement = x.CreateChild("decoration"),
ContentElement = x.CreateChild("content")
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.PartialRender(300, 200))
.CheckMeasureResult(SpacePlan.Wrap());
.ExpectChildMeasure("decoration", new Size(400, 300), new PartialRender(300, 200))
.CheckMeasureResult(new Wrap());
}
[Test]
public void Measure_ReturnsWrap_WhenContentReturnsWrap()
{
TestPlan
.For(x => new BinaryDecoration
.For(x => new SimpleDecoration
{
Type = DecorationType.Append,
DecorationElement = x.CreateChild("decoration"),
ContentElement = x.CreateChild("content")
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
.ExpectChildMeasure("content", new Size(400, 200), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
.ExpectChildMeasure("decoration", new Size(400, 300), new FullRender(300, 100))
.ExpectChildMeasure("content", new Size(400, 200), new Wrap())
.CheckMeasureResult(new Wrap());
}
[Test]
public void Measure_ReturnsPartialRender_WhenContentReturnsPartialRender()
{
TestPlan
.For(x => new BinaryDecoration
.For(x => new SimpleDecoration
{
Type = DecorationType.Append,
DecorationElement = x.CreateChild("decoration"),
ContentElement = x.CreateChild("content")
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
.ExpectChildMeasure("content", new Size(400, 200), SpacePlan.PartialRender(200, 150))
.CheckMeasureResult(SpacePlan.PartialRender(400, 250));
.ExpectChildMeasure("decoration", new Size(400, 300), new FullRender(300, 100))
.ExpectChildMeasure("content", new Size(400, 200), new PartialRender(200, 150))
.CheckMeasureResult(new PartialRender(400, 250));
}
[Test]
public void Measure_ReturnsFullRender_WhenContentReturnsFullRender()
{
TestPlan
.For(x => new BinaryDecoration
.For(x => new SimpleDecoration
{
Type = DecorationType.Append,
DecorationElement = x.CreateChild("decoration"),
ContentElement = x.CreateChild("content")
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
.ExpectChildMeasure("content", new Size(400, 200), SpacePlan.FullRender(200, 150))
.CheckMeasureResult(SpacePlan.FullRender(400, 250));
.ExpectChildMeasure("decoration", new Size(400, 300), new FullRender(300, 100))
.ExpectChildMeasure("content", new Size(400, 200), new FullRender(200, 150))
.CheckMeasureResult(new FullRender(400, 250));
}
#endregion
@@ -97,14 +97,14 @@ namespace QuestPDF.UnitTests
public void Draw_Prepend()
{
TestPlan
.For(x => new BinaryDecoration
.For(x => new SimpleDecoration
{
Type = DecorationType.Prepend,
DecorationElement = x.CreateChild("decoration"),
ContentElement = x.CreateChild("content")
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
.ExpectChildMeasure("decoration", new Size(400, 300), new FullRender(300, 100))
.ExpectChildDraw("decoration", new Size(400, 100))
.ExpectCanvasTranslate(0, 100)
.ExpectChildDraw("content", new Size(400, 200))
@@ -116,14 +116,14 @@ namespace QuestPDF.UnitTests
public void Draw_Append()
{
TestPlan
.For(x => new BinaryDecoration
.For(x => new SimpleDecoration
{
Type = DecorationType.Append,
DecorationElement = x.CreateChild("decoration"),
ContentElement = x.CreateChild("content")
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
.ExpectChildMeasure("decoration", new Size(400, 300), new FullRender(300, 100))
.ExpectChildDraw("content", new Size(400, 200))
.ExpectCanvasTranslate(0, 200)
.ExpectChildDraw("decoration", new Size(400, 100))
+3 -3
View File
@@ -1,6 +1,6 @@
using FluentAssertions;
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
@@ -20,7 +20,7 @@ namespace QuestPDF.UnitTests
Source = GenerateImage
})
.MeasureElement(new Size(300, 200))
.CheckMeasureResult(SpacePlan.FullRender(300, 200));
.CheckMeasureResult(new FullRender(300, 200));
}
[Test]
@@ -51,7 +51,7 @@ namespace QuestPDF.UnitTests
[Test]
public void Draw_PassesCorrectSizeToSource()
{
Size passedSize = default;
Size passedSize = null;
TestPlan
.For(x => new DynamicImage
+11 -14
View File
@@ -1,5 +1,5 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
@@ -19,8 +19,8 @@ namespace QuestPDF.UnitTests
MinHeight = 200
})
.MeasureElement(new Size(400, 100))
.ExpectChildMeasure(new Size(400, 100), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
.ExpectChildMeasure(new Size(400, 100), new Wrap())
.CheckMeasureResult(new Wrap());
}
[Test]
@@ -33,8 +33,8 @@ namespace QuestPDF.UnitTests
MinHeight = 200
})
.MeasureElement(new Size(400, 100))
.ExpectChildMeasure(new Size(400, 100), SpacePlan.PartialRender(300, 50))
.CheckMeasureResult(SpacePlan.Wrap());
.ExpectChildMeasure(new Size(400, 100), new PartialRender(300, 50))
.CheckMeasureResult(new Wrap());
}
[Test]
@@ -47,8 +47,8 @@ namespace QuestPDF.UnitTests
MinHeight = 200
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(400, 300), SpacePlan.PartialRender(300, 250))
.CheckMeasureResult(SpacePlan.PartialRender(300, 250));
.ExpectChildMeasure(new Size(400, 300), new PartialRender(300, 250))
.CheckMeasureResult(new PartialRender(300, 250));
}
[Test]
@@ -61,8 +61,8 @@ namespace QuestPDF.UnitTests
MinHeight = 200
})
.MeasureElement(new Size(400, 100))
.ExpectChildMeasure(new Size(400, 100), SpacePlan.FullRender(300, 50))
.CheckMeasureResult(SpacePlan.FullRender(300, 50));
.ExpectChildMeasure(new Size(400, 100), new FullRender(300, 50))
.CheckMeasureResult(new FullRender(300, 50));
}
[Test]
@@ -75,11 +75,8 @@ namespace QuestPDF.UnitTests
MinHeight = 200
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(400, 300), SpacePlan.FullRender(300, 250))
.CheckMeasureResult(SpacePlan.FullRender(300, 250));
.ExpectChildMeasure(new Size(400, 300), new FullRender(300, 250))
.CheckMeasureResult(new FullRender(300, 250));
}
[Test]
public void Draw() => SimpleContainerTests.Draw<EnsureSpace>();
}
}
+17 -14
View File
@@ -1,5 +1,5 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
@@ -9,6 +9,12 @@ namespace QuestPDF.UnitTests
[TestFixture]
public class ExtendTests
{
[Test]
public void Measure_ShouldHandleNullChild() => new Extend().MeasureWithoutChild();
[Test]
public void Draw_ShouldHandleNullChild() => new Extend().DrawWithoutChild();
[Test]
public void Measure_ReturnsWrap_WhenChildReturnsWrap()
{
@@ -18,8 +24,8 @@ namespace QuestPDF.UnitTests
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 200))
.ExpectChildMeasure(new Size(400, 200), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
.ExpectChildMeasure(new Size(400, 200), new Wrap())
.CheckMeasureResult(new Wrap());
}
[Test]
@@ -33,8 +39,8 @@ namespace QuestPDF.UnitTests
ExtendVertical = true
})
.MeasureElement(new Size(400, 200))
.ExpectChildMeasure(new Size(400, 200), SpacePlan.PartialRender(300, 100))
.CheckMeasureResult(SpacePlan.PartialRender(400, 200));
.ExpectChildMeasure(new Size(400, 200), new PartialRender(300, 100))
.CheckMeasureResult(new PartialRender(400, 200));
}
[Test]
@@ -48,8 +54,8 @@ namespace QuestPDF.UnitTests
ExtendVertical = true
})
.MeasureElement(new Size(400, 200))
.ExpectChildMeasure(new Size(400, 200), SpacePlan.FullRender(300, 100))
.CheckMeasureResult(SpacePlan.FullRender(400, 200));
.ExpectChildMeasure(new Size(400, 200), new FullRender(300, 100))
.CheckMeasureResult(new FullRender(400, 200));
}
[Test]
@@ -63,8 +69,8 @@ namespace QuestPDF.UnitTests
ExtendVertical = false
})
.MeasureElement(new Size(400, 200))
.ExpectChildMeasure(new Size(400, 200), SpacePlan.FullRender(100, 100))
.CheckMeasureResult(SpacePlan.FullRender(400, 100));
.ExpectChildMeasure(new Size(400, 200), new FullRender(100, 100))
.CheckMeasureResult(new FullRender(400, 100));
}
[Test]
@@ -78,11 +84,8 @@ namespace QuestPDF.UnitTests
ExtendVertical = true
})
.MeasureElement(new Size(400, 200))
.ExpectChildMeasure(new Size(400, 200), SpacePlan.FullRender(100, 100))
.CheckMeasureResult(SpacePlan.FullRender(100, 200));
.ExpectChildMeasure(new Size(400, 200), new FullRender(100, 100))
.CheckMeasureResult(new FullRender(100, 200));
}
[Test]
public void Draw() => SimpleContainerTests.Draw<Extend>();
}
}
-15
View File
@@ -1,15 +0,0 @@
using NUnit.Framework;
using QuestPDF.Elements;
using QuestPDF.UnitTests.TestEngine;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class ExternalLinkTests
{
[Test]
public void Measure() => SimpleContainerTests.Measure<ExternalLink>();
// TODO: consider tests for the Draw method
}
}
+27 -27
View File
@@ -39,30 +39,30 @@ namespace QuestPDF.UnitTests
// assert
var expected = new Container();
expected.Stack(stack =>
expected.Container().Stack(stack =>
{
stack.Item().Row(row =>
{
row.RelativeColumn(6).Element(childA);
row.RelativeColumn(4).Element(childB);
row.RelativeColumn(6).Container().Element(childA);
row.RelativeColumn(4).Container().Element(childB);
row.RelativeColumn(2);
});
stack.Item().Row(row =>
{
row.RelativeColumn(4).Element(childC);
row.RelativeColumn(2).Element(childD);
row.RelativeColumn(4).Container().Element(childC);
row.RelativeColumn(2).Container().Element(childD);
row.RelativeColumn(6);
});
stack.Item().Row(row =>
{
row.RelativeColumn(8).Element(childE);
row.RelativeColumn(8).Container().Element(childE);
row.RelativeColumn(4);
});
});
TestPlan.CompareOperations(structure, expected);
structure.Should().BeEquivalentTo(expected, o => o.WithTracing().WithAutoConversion().WithStrictOrdering().IncludingAllRuntimeProperties());
}
[Test]
@@ -93,33 +93,33 @@ namespace QuestPDF.UnitTests
// assert
var expected = new Container();
expected.Stack(stack =>
expected.Container().Stack(stack =>
{
stack.Item().Row(row =>
{
row.RelativeColumn(1);
row.RelativeColumn(6).Element(childA);
row.RelativeColumn(4).Element(childB);
row.RelativeColumn(6).Container().Element(childA);
row.RelativeColumn(4).Container().Element(childB);
row.RelativeColumn(1);
});
stack.Item().Row(row =>
{
row.RelativeColumn(3);
row.RelativeColumn(4).Element(childC);
row.RelativeColumn(2).Element(childD);
row.RelativeColumn(4).Container().Element(childC);
row.RelativeColumn(2).Container().Element(childD);
row.RelativeColumn(3);
});
stack.Item().Row(row =>
{
row.RelativeColumn(2);
row.RelativeColumn(8).Element(childE);
row.RelativeColumn(8).Container().Element(childE);
row.RelativeColumn(2);
});
});
TestPlan.CompareOperations(structure, expected);
structure.Should().BeEquivalentTo(expected, o => o.WithTracing().WithAutoConversion().WithStrictOrdering().IncludingAllRuntimeProperties());
}
[Test]
@@ -150,30 +150,30 @@ namespace QuestPDF.UnitTests
// assert
var expected = new Container();
expected.Stack(stack =>
expected.Container().Stack(stack =>
{
stack.Item().Row(row =>
{
row.RelativeColumn(2);
row.RelativeColumn(6).Element(childA);
row.RelativeColumn(4).Element(childB);
row.RelativeColumn(6).Container().Element(childA);
row.RelativeColumn(4).Container().Element(childB);
});
stack.Item().Row(row =>
{
row.RelativeColumn(6);
row.RelativeColumn(4).Element(childC);
row.RelativeColumn(2).Element(childD);
row.RelativeColumn(4).Container().Element(childC);
row.RelativeColumn(2).Container().Element(childD);
});
stack.Item().Row(row =>
{
row.RelativeColumn(4);
row.RelativeColumn(8).Element(childE);
row.RelativeColumn(8).Container().Element(childE);
});
});
TestPlan.CompareOperations(structure, expected);
structure.Should().BeEquivalentTo(expected, o => o.WithTracing().WithAutoConversion().WithStrictOrdering().IncludingAllRuntimeProperties());
}
#endregion
@@ -210,7 +210,7 @@ namespace QuestPDF.UnitTests
// assert
var expected = new Container();
expected.Stack(stack =>
expected.Container().Stack(stack =>
{
stack.Spacing(20);
@@ -219,8 +219,8 @@ namespace QuestPDF.UnitTests
row.Spacing(30);
row.RelativeColumn(3);
row.RelativeColumn(5).Element(childA);
row.RelativeColumn(5).Element(childB);
row.RelativeColumn(5).Container().Element(childA);
row.RelativeColumn(5).Container().Element(childB);
row.RelativeColumn(3);
});
@@ -229,7 +229,7 @@ namespace QuestPDF.UnitTests
row.Spacing(30);
row.RelativeColumn(3);
row.RelativeColumn(10).Element(childC);
row.RelativeColumn(10).Container().Element(childC);
row.RelativeColumn(3);
});
@@ -238,12 +238,12 @@ namespace QuestPDF.UnitTests
row.Spacing(30);
row.RelativeColumn(2);
row.RelativeColumn(12).Element(childD);
row.RelativeColumn(12).Container().Element(childD);
row.RelativeColumn(2);
});
});
TestPlan.CompareOperations(structure, expected);
structure.Should().BeEquivalentTo(expected, o => o.WithTracing().WithAutoConversion().WithStrictOrdering().IncludingAllRuntimeProperties().AllowingInfiniteRecursion());
}
#endregion
+30
View File
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
namespace QuestPDF.UnitTests
{
public static class Helpers
{
public static Random Random = new Random();
public static Size RandomSize => new Size(Random.Next(200, 400), Random.Next(100, 200));
public static void ShouldEqual(this IEnumerable<OperationBase> commands, IEnumerable<OperationBase> expected)
{
commands.Should().HaveSameCount(expected);
commands
.Zip(expected)
.ToList()
.ForEach(x =>
{
x.First.Should().BeOfType(x.Second.GetType());
x.First.Should().BeEquivalentTo(x.Second, y => y.RespectingRuntimeTypes());
});
}
}
}
+9 -3
View File
@@ -1,5 +1,5 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
@@ -11,6 +11,12 @@ namespace QuestPDF.UnitTests
[TestFixture]
public class ImageTests
{
[Test]
public void Measure_ShouldHandleNullChild() => new AspectRatio().MeasureWithoutChild();
[Test]
public void Draw_ShouldHandleNullChild() => new AspectRatio().DrawWithoutChild();
[Test]
public void Measure_TakesAvailableSpaceRegardlessOfSize()
{
@@ -20,7 +26,7 @@ namespace QuestPDF.UnitTests
InternalImage = GenerateImage(400, 300)
})
.MeasureElement(new Size(300, 200))
.CheckMeasureResult(SpacePlan.FullRender(300, 200));
.CheckMeasureResult(new FullRender(300, 200));
}
[Test]
@@ -49,7 +55,7 @@ namespace QuestPDF.UnitTests
return container;
})
.MeasureElement(new Size(300, 200))
.CheckMeasureResult(SpacePlan.FullRender(300, 100));;
.CheckMeasureResult(new FullRender(300, 100));;
}
SKImage GenerateImage(int width, int height)
-15
View File
@@ -1,15 +0,0 @@
using NUnit.Framework;
using QuestPDF.Elements;
using QuestPDF.UnitTests.TestEngine;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class InternalLinkTests
{
[Test]
public void Measure() => SimpleContainerTests.Measure<InternalLink>();
// TODO: consider tests for the Draw method
}
}
@@ -1,15 +0,0 @@
using NUnit.Framework;
using QuestPDF.Elements;
using QuestPDF.UnitTests.TestEngine;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class InternalLocationTests
{
[Test]
public void Measure() => SimpleContainerTests.Measure<InternalLink>();
// TODO: consider tests for the Draw method
}
}
-131
View File
@@ -1,131 +0,0 @@
using System.Collections.Generic;
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class LayersTests
{
private const string BackgroundLayer = "background";
private const string MainLayer = "main";
private const string ForegroundLayer = "foreground";
private static Layers GetLayers(TestPlan x)
{
return new Layers
{
Children = new List<Layer>
{
new Layer
{
Child = x.CreateChild(BackgroundLayer)
},
new Layer
{
Child = x.CreateChild(MainLayer),
IsPrimary = true
},
new Layer
{
Child = x.CreateChild(ForegroundLayer)
}
}
};
}
#region measure
[Test]
public void Measure_Wrap()
{
TestPlan
.For(GetLayers)
.MeasureElement(new Size(800, 600))
.ExpectChildMeasure(MainLayer, new Size(800, 600), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
}
[Test]
public void Measure_PartialRender()
{
TestPlan
.For(GetLayers)
.MeasureElement(new Size(800, 600))
.ExpectChildMeasure(MainLayer, new Size(800, 600), SpacePlan.PartialRender(700, 500))
.CheckMeasureResult(SpacePlan.PartialRender(700, 500));
}
[Test]
public void Measure_FullRender()
{
TestPlan
.For(GetLayers)
.MeasureElement(new Size(800, 600))
.ExpectChildMeasure(MainLayer, new Size(800, 600), SpacePlan.FullRender(500, 400))
.CheckMeasureResult(SpacePlan.FullRender(500, 400));
}
#endregion
#region draw
[Test]
public void Draw_Simple()
{
TestPlan
.For(GetLayers)
.MeasureElement(new Size(800, 600))
.ExpectChildMeasure(BackgroundLayer, new Size(800, 600), SpacePlan.FullRender(100, 200))
.ExpectChildMeasure(MainLayer, new Size(800, 600), SpacePlan.PartialRender(200, 300))
.ExpectChildMeasure(ForegroundLayer, new Size(800, 600), SpacePlan.FullRender(300, 400))
.ExpectChildDraw(BackgroundLayer, new Size(800, 600))
.ExpectChildDraw(MainLayer, new Size(800, 600))
.ExpectChildDraw(ForegroundLayer, new Size(800, 600))
.CheckDrawResult();
}
[Test]
public void Draw_WhenSecondaryLayerReturnsWrap_SkipThatLayer_1()
{
TestPlan
.For(GetLayers)
.MeasureElement(new Size(800, 600))
.ExpectChildMeasure(BackgroundLayer, new Size(800, 600), SpacePlan.PartialRender(100, 200))
.ExpectChildMeasure(MainLayer, new Size(800, 600), SpacePlan.PartialRender(200, 300))
.ExpectChildMeasure(ForegroundLayer, new Size(800, 600), SpacePlan.Wrap())
.ExpectChildDraw(BackgroundLayer, new Size(800, 600))
.ExpectChildDraw(MainLayer, new Size(800, 600))
.CheckDrawResult();
}
[Test]
public void Draw_WhenSecondaryLayerReturnsWrap_SkipThatLayer_2()
{
TestPlan
.For(GetLayers)
.MeasureElement(new Size(800, 600))
.ExpectChildMeasure(BackgroundLayer, new Size(800, 600), SpacePlan.Wrap())
.ExpectChildMeasure(MainLayer, new Size(800, 600), SpacePlan.PartialRender(200, 300))
.ExpectChildMeasure(ForegroundLayer, new Size(800, 600), SpacePlan.PartialRender(300, 400))
.ExpectChildDraw(MainLayer, new Size(800, 600))
.ExpectChildDraw(ForegroundLayer, new Size(800, 600))
.CheckDrawResult();
}
#endregion
}
}
+15 -9
View File
@@ -1,5 +1,5 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
@@ -9,6 +9,12 @@ namespace QuestPDF.UnitTests
[TestFixture]
public class PaddingTests
{
[Test]
public void Measure_ShouldHandleNullChild() => new Padding().MeasureWithoutChild();
[Test]
public void Draw_ShouldHandleNullChild() => new Padding().DrawWithoutChild();
private Padding GetPadding(TestPlan plan)
{
return new Padding()
@@ -28,8 +34,8 @@ namespace QuestPDF.UnitTests
TestPlan
.For(GetPadding)
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(340, 260), SpacePlan.FullRender(140, 60))
.CheckMeasureResult(SpacePlan.FullRender(200, 100));
.ExpectChildMeasure(new Size(340, 260), new FullRender(140, 60))
.CheckMeasureResult(new FullRender(200, 100));
}
[Test]
@@ -38,7 +44,7 @@ namespace QuestPDF.UnitTests
TestPlan
.For(GetPadding)
.MeasureElement(new Size(50, 300))
.CheckMeasureResult(SpacePlan.Wrap());
.CheckMeasureResult(new Wrap());
}
[Test]
@@ -47,7 +53,7 @@ namespace QuestPDF.UnitTests
TestPlan
.For(GetPadding)
.MeasureElement(new Size(20, 300))
.CheckMeasureResult(SpacePlan.Wrap());
.CheckMeasureResult(new Wrap());
}
[Test]
@@ -56,8 +62,8 @@ namespace QuestPDF.UnitTests
TestPlan
.For(GetPadding)
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(340, 260), SpacePlan.PartialRender(40, 160))
.CheckMeasureResult(SpacePlan.PartialRender(100, 200));
.ExpectChildMeasure(new Size(340, 260), new PartialRender(40, 160))
.CheckMeasureResult(new PartialRender(100, 200));
}
[Test]
@@ -66,8 +72,8 @@ namespace QuestPDF.UnitTests
TestPlan
.For(GetPadding)
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(340, 260), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
.ExpectChildMeasure(new Size(340, 260), new Wrap())
.CheckMeasureResult(new Wrap());
}
[Test]
+3 -3
View File
@@ -1,5 +1,5 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
@@ -16,13 +16,13 @@ namespace QuestPDF.UnitTests
.For(x => new PageBreak())
.MeasureElement(new Size(400, 300))
.CheckMeasureResult(SpacePlan.PartialRender(Size.Zero))
.CheckMeasureResult(new PartialRender(Size.Zero))
.DrawElement(new Size(400, 300))
.CheckDrawResult()
.MeasureElement(new Size(500, 400))
.CheckMeasureResult(SpacePlan.FullRender(0, 0));
.CheckMeasureResult(new FullRender(Size.Zero));
}
}
}
+10
View File
@@ -0,0 +1,10 @@
using NUnit.Framework;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class PageNumberTests
{
}
}
+5 -4
View File
@@ -6,11 +6,12 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.1.0" />
<PackageReference Include="nunit" Version="3.13.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="Moq" Version="4.13.1" />
<PackageReference Include="nunit" Version="3.13.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.0" />
<PackageReference Include="SkiaSharp" Version="2.80.3" />
<PackageReference Include="SkiaSharp" Version="2.80.2" />
</ItemGroup>
<ItemGroup>
-30
View File
@@ -1,30 +0,0 @@
using NUnit.Framework;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class RotateTests
{
[Test]
public void Measure() => SimpleContainerTests.Measure<Rotate>();
[Test]
public void Draw()
{
TestPlan
.For(x => new Rotate
{
Child = x.CreateChild(),
Angle = 123
})
.DrawElement(new Size(400, 300))
.ExpectCanvasRotate(123)
.ExpectChildDraw(new Size(400, 300))
.ExpectCanvasRotate(-123)
.CheckDrawResult();
}
}
}
+25 -176
View File
@@ -1,7 +1,6 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
@@ -16,74 +15,74 @@ namespace QuestPDF.UnitTests
public void Measure_ReturnsWrap_WhenLeftChildReturnsWrap()
{
TestPlan
.For(x => new BinaryRow
.For(x => new SimpleRow
{
Left = x.CreateChild("left"),
Right = x.CreateChild("right")
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("left", new Size(400, 300), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
.ExpectChildMeasure("left", new Size(400, 300), new Wrap())
.CheckMeasureResult(new Wrap());
}
[Test]
public void Measure_ReturnsWrap_WhenRightChildReturnsWrap()
{
TestPlan
.For(x => new BinaryRow
.For(x => new SimpleRow
{
Left = x.CreateChild("left"),
Right = x.CreateChild("right")
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("left", new Size(400, 300), SpacePlan.FullRender(250, 150))
.ExpectChildMeasure("right", new Size(150, 300), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
.ExpectChildMeasure("left", new Size(400, 300), new FullRender(250, 150))
.ExpectChildMeasure("right", new Size(150, 300), new Wrap())
.CheckMeasureResult(new Wrap());
}
[Test]
public void Measure_ReturnsPartialRender_WhenLeftChildReturnsPartialRender()
{
TestPlan
.For(x => new BinaryRow
.For(x => new SimpleRow
{
Left = x.CreateChild("left"),
Right = x.CreateChild("right")
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("left", new Size(400, 300), SpacePlan.PartialRender(250, 150))
.ExpectChildMeasure("right", new Size(150, 300), SpacePlan.FullRender(100, 100))
.CheckMeasureResult(SpacePlan.PartialRender(350, 150));
.ExpectChildMeasure("left", new Size(400, 300), new PartialRender(250, 150))
.ExpectChildMeasure("right", new Size(150, 300), new FullRender(100, 100))
.CheckMeasureResult(new PartialRender(350, 150));
}
[Test]
public void Measure_ReturnsPartialRender_WhenRightChildReturnsPartialRender()
{
TestPlan
.For(x => new BinaryRow
.For(x => new SimpleRow
{
Left = x.CreateChild("left"),
Right = x.CreateChild("right")
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("left", new Size(400, 300), SpacePlan.FullRender(250, 150))
.ExpectChildMeasure("right", new Size(150, 300), SpacePlan.PartialRender(100, 100))
.CheckMeasureResult(SpacePlan.PartialRender(350, 150));
.ExpectChildMeasure("left", new Size(400, 300), new FullRender(250, 150))
.ExpectChildMeasure("right", new Size(150, 300), new PartialRender(100, 100))
.CheckMeasureResult(new PartialRender(350, 150));
}
[Test]
public void Measure_ReturnsFullRender_WhenBothChildrenReturnFullRender()
{
TestPlan
.For(x => new BinaryRow
.For(x => new SimpleRow
{
Left = x.CreateChild("left"),
Right = x.CreateChild("right")
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("left", new Size(400, 300), SpacePlan.FullRender(200, 150))
.ExpectChildMeasure("right", new Size(200, 300), SpacePlan.FullRender(100, 100))
.CheckMeasureResult(SpacePlan.FullRender(300, 150));
.ExpectChildMeasure("left", new Size(400, 300), new FullRender(200, 150))
.ExpectChildMeasure("right", new Size(200, 300), new FullRender(100, 100))
.CheckMeasureResult(new FullRender(300, 150));
}
#endregion
@@ -94,13 +93,13 @@ namespace QuestPDF.UnitTests
public void Draw()
{
TestPlan
.For(x => new BinaryRow
.For(x => new SimpleRow
{
Left = x.CreateChild("left"),
Right = x.CreateChild("right")
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure("left", new Size(400, 300), SpacePlan.FullRender(250, 150))
.ExpectChildMeasure("left", new Size(400, 300), new FullRender(250, 150))
.ExpectChildDraw("left", new Size(250, 300))
.ExpectCanvasTranslate(250, 0)
.ExpectChildDraw("right", new Size(150, 300))
@@ -110,158 +109,8 @@ namespace QuestPDF.UnitTests
#endregion
#region Structure
[Test]
public void Structure_RelativeColumnsHandling()
{
// arrange
var childA = TestPlan.CreateUniqueElement();
var childB = TestPlan.CreateUniqueElement();
var childC = TestPlan.CreateUniqueElement();
var childD = TestPlan.CreateUniqueElement();
var childE = TestPlan.CreateUniqueElement();
const int spacing = 25;
var availableSpace = new Size(1100, 400);
// act
var value = new Container();
value.Row(row =>
{
row.Spacing(spacing);
row.ConstantColumn(150).Element(childA);
row.ConstantColumn(250).Element(childB);
row.RelativeColumn(1).Element(childC);
row.RelativeColumn(2).Element(childD);
row.RelativeColumn(3).Element(childE);
});
// assert
var expected = new Container();
expected.Row(row =>
{
row.Spacing(spacing);
row.ConstantColumn(150).Element(childA);
row.ConstantColumn(250).Element(childB);
row.ConstantColumn(100).Element(childC);
row.ConstantColumn(200).Element(childD);
row.ConstantColumn(300).Element(childE);
});
TestPlan.CompareOperations(value, expected, availableSpace);
}
[Test]
public void Structure_Tree()
{
// arrange
var childA = TestPlan.CreateUniqueElement();
var childB = TestPlan.CreateUniqueElement();
var childC = TestPlan.CreateUniqueElement();
var childD = TestPlan.CreateUniqueElement();
var childE = TestPlan.CreateUniqueElement();
const int spacing = 25;
var availableSpace = new Size(1200, 400);
// act
var value = new Container();
value.Row(row =>
{
row.Spacing(spacing);
row.ConstantColumn(150).Element(childA);
row.ConstantColumn(200).Element(childB);
row.ConstantColumn(250).Element(childC);
row.RelativeColumn(2).Element(childD);
row.RelativeColumn(3).Element(childE);
});
// assert
var expected = new BinaryRow
{
Left = new BinaryRow
{
Left = new BinaryRow
{
Left = new Constrained
{
MinWidth = 150,
MaxWidth = 150,
Child = childA
},
Right = new Constrained
{
MinWidth = 25,
MaxWidth = 25
}
},
Right = new BinaryRow
{
Left = new Constrained
{
MinWidth = 200,
MaxWidth = 200,
Child = childB
},
Right = new Constrained
{
MinWidth = 25,
MaxWidth = 25
}
}
},
Right = new BinaryRow
{
Left = new BinaryRow
{
Left = new Constrained
{
MinWidth = 250,
MaxWidth = 250,
Child = childC
},
Right = new Constrained
{
MinWidth = 25,
MaxWidth = 25
}
},
Right = new BinaryRow
{
Left = new Constrained
{
MinWidth = 200,
MaxWidth = 200,
Child = childD
},
Right = new BinaryRow
{
Left = new Constrained
{
MinWidth = 25,
MaxWidth = 25
},
Right = new Constrained
{
MinWidth = 300,
MaxWidth = 300,
Child = childE
}
}
}
}
};
TestPlan.CompareOperations(value, expected, availableSpace);
}
#endregion
// TODO: add tests for the spacing property
// TODO: add tests for the tree builder method
// TODO: add tests for relative column
}
}
-152
View File
@@ -1,152 +0,0 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class ScaleTests
{
#region measure
[Test]
public void Measure_Wrap()
{
TestPlan
.For(x => new Scale
{
Child = x.CreateChild(),
ScaleX = 3,
ScaleY = 2
})
.MeasureElement(new Size(900, 800))
.ExpectChildMeasure(new Size(300, 400), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
}
[Test]
public void Measure_PartialRender()
{
TestPlan
.For(x => new Scale
{
Child = x.CreateChild(),
ScaleX = 3,
ScaleY = 2
})
.MeasureElement(new Size(900, 800))
.ExpectChildMeasure(new Size(300, 400), SpacePlan.PartialRender(200, 350))
.CheckMeasureResult(SpacePlan.PartialRender(600, 700));
}
[Test]
public void Measure_FullRender()
{
TestPlan
.For(x => new Scale
{
Child = x.CreateChild(),
ScaleX = 3,
ScaleY = 2
})
.MeasureElement(new Size(900, 800))
.ExpectChildMeasure(new Size(300, 400), SpacePlan.FullRender(250, 300))
.CheckMeasureResult(SpacePlan.FullRender(750, 600));
}
[Test]
public void Measure_NegativeScaleX()
{
TestPlan
.For(x => new Scale
{
Child = x.CreateChild(),
ScaleX = -2,
ScaleY = 1
})
.MeasureElement(new Size(800, 600))
.ExpectChildMeasure(new Size(400, 600), SpacePlan.FullRender(300, 500))
.CheckMeasureResult(SpacePlan.FullRender(600, 500));
}
[Test]
public void Measure_NegativeScaleY()
{
TestPlan
.For(x => new Scale
{
Child = x.CreateChild(),
ScaleX = 1,
ScaleY = -3
})
.MeasureElement(new Size(800, 600))
.ExpectChildMeasure(new Size(800, 200), SpacePlan.FullRender(800, 100))
.CheckMeasureResult(SpacePlan.FullRender(800, 300));
}
#endregion
#region draw
[Test]
public void Draw_Simple()
{
TestPlan
.For(x => new Scale
{
Child = x.CreateChild(),
ScaleX = 3,
ScaleY = 2
})
.DrawElement(new Size(900, 800))
.ExpectCanvasTranslate(0, 0)
.ExpectCanvasScale(3, 2)
.ExpectChildDraw(new Size(300, 400))
.ExpectCanvasScale(1/3f, 1/2f)
.ExpectCanvasTranslate(0, 0)
.CheckDrawResult();
}
[Test]
public void Draw_NegativeScaleX()
{
TestPlan
.For(x => new Scale
{
Child = x.CreateChild(),
ScaleX = -3,
ScaleY = 2
})
.DrawElement(new Size(900, 800))
.ExpectCanvasTranslate(900, 0)
.ExpectCanvasScale(-3, 2)
.ExpectChildDraw(new Size(300, 400))
.ExpectCanvasScale(-1/3f, 1/2f)
.ExpectCanvasTranslate(-900, 0)
.CheckDrawResult();
}
[Test]
public void Draw_NegativeScaleY()
{
TestPlan
.For(x => new Scale
{
Child = x.CreateChild(),
ScaleX = 3,
ScaleY = -2
})
.DrawElement(new Size(900, 800))
.ExpectCanvasTranslate(0, 800)
.ExpectCanvasScale(3, -2)
.ExpectChildDraw(new Size(300, 400))
.ExpectCanvasScale(1/3f, -1/2f)
.ExpectCanvasTranslate(0, -800)
.CheckDrawResult();
}
#endregion
}
}
+7 -10
View File
@@ -1,5 +1,5 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
@@ -18,8 +18,8 @@ namespace QuestPDF.UnitTests
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(400, 300), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
.ExpectChildMeasure(new Size(400, 300), new Wrap())
.CheckMeasureResult(new Wrap());
}
[Test]
@@ -31,8 +31,8 @@ namespace QuestPDF.UnitTests
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(400, 300), SpacePlan.PartialRender(300, 200))
.CheckMeasureResult(SpacePlan.Wrap());
.ExpectChildMeasure(new Size(400, 300), new PartialRender(300, 200))
.CheckMeasureResult(new Wrap());
}
[Test]
@@ -44,11 +44,8 @@ namespace QuestPDF.UnitTests
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(400, 300), SpacePlan.FullRender(300, 200))
.CheckMeasureResult(SpacePlan.FullRender(300, 200));
.ExpectChildMeasure(new Size(400, 300), new FullRender(300, 200))
.CheckMeasureResult(new FullRender(300, 200));
}
[Test]
public void Draw() => SimpleContainerTests.Draw<ShowEntire>();
}
}
+37 -10
View File
@@ -1,5 +1,6 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using Moq;
using NUnit.Framework;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
@@ -10,7 +11,33 @@ namespace QuestPDF.UnitTests
public class ShowOnceTest
{
[Test]
public void Draw()
public void Measure_ShouldHandleNullChild() => new ShowOnce().MeasureWithoutChild();
[Test]
public void Draw_ShouldHandleNullChild() => new ShowOnce().DrawWithoutChild();
[Test]
public void ShouldRenderOnce_WhenRenderingCalledMultipleTimes()
{
var child = new Mock<Element>();
child
.Setup(x => x.Measure(It.IsAny<Size>()))
.Returns(() => new FullRender(Size.Zero));
var element = new ShowOnce()
{
Child = child.Object
};
element.Draw(Size.Zero);
element.Draw(Size.Zero);
child.Verify(x => x.Draw(It.IsAny<Size>()), Times.Once);
}
[Test]
public void Draw_HorizontalRight_VerticalTop()
{
TestPlan
.For(x => new ShowOnce()
@@ -20,31 +47,31 @@ namespace QuestPDF.UnitTests
// Measure the element and return result
.MeasureElement(new Size(300, 200))
.ExpectChildMeasure("child", new Size(300, 200), SpacePlan.PartialRender(new Size(200, 200)))
.CheckMeasureResult(SpacePlan.PartialRender(new Size(200, 200)))
.ExpectChildMeasure("child", new Size(300, 200), new PartialRender(new Size(200, 200)))
.CheckMeasureResult(new PartialRender(new Size(200, 200)))
// Draw element partially
.DrawElement(new Size(200, 200))
.ExpectChildMeasure(new Size(200, 200), SpacePlan.PartialRender(new Size(200, 200)))
.ExpectChildMeasure(new Size(200, 200), new PartialRender(new Size(200, 200)))
.ExpectChildDraw(new Size(200, 200))
.CheckDrawResult()
// Element was not fully drawn
// It should be measured again for rendering on next page
.MeasureElement(new Size(800, 200))
.ExpectChildMeasure(new Size(800, 200), SpacePlan.FullRender(new Size(400, 200)))
.CheckMeasureResult(SpacePlan.FullRender(new Size(400, 200)))
.ExpectChildMeasure(new Size(800, 200), new FullRender(new Size(400, 200)))
.CheckMeasureResult(new FullRender(new Size(400, 200)))
// Draw element on next page
// Element was fully drawn at this point
.DrawElement(new Size(400, 200))
.ExpectChildMeasure(new Size(400, 200), SpacePlan.FullRender(new Size(400, 200)))
.ExpectChildMeasure(new Size(400, 200), new FullRender(new Size(400, 200)))
.ExpectChildDraw(new Size(400, 200))
.CheckDrawResult()
// In the next attempt of measuring element, it should behave like empty parent.
.MeasureElement(new Size(600, 200))
.CheckMeasureResult(SpacePlan.FullRender(0, 0))
.CheckMeasureResult(new FullRender(Size.Zero))
// In the next attempt of measuring element, it should not draw its child
.DrawElement(new Size(600, 200))
-162
View File
@@ -1,162 +0,0 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class SimpleRotateTests
{
#region measure
[Test]
public void Measure_Wrap()
{
TestPlan
.For(x => new SimpleRotate
{
Child = x.CreateChild(),
TurnCount = 0
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(400, 300), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
}
[Test]
public void Measure_PartialRender()
{
TestPlan
.For(x => new SimpleRotate
{
Child = x.CreateChild(),
TurnCount = 0
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(400, 300), SpacePlan.PartialRender(300, 200))
.CheckMeasureResult(SpacePlan.PartialRender(300, 200));
}
[Test]
public void Measure_RotateRight()
{
TestPlan
.For(x => new SimpleRotate
{
Child = x.CreateChild(),
TurnCount = 1
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(300, 400), SpacePlan.FullRender(200, 300))
.CheckMeasureResult(SpacePlan.FullRender(300, 200));
}
[Test]
public void Measure_RotateFlip()
{
TestPlan
.For(x => new SimpleRotate
{
Child = x.CreateChild(),
TurnCount = 2
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(400, 300), SpacePlan.FullRender(200, 100))
.CheckMeasureResult(SpacePlan.FullRender(200, 100));
}
[Test]
public void Measure_RotateLeft()
{
TestPlan
.For(x => new SimpleRotate
{
Child = x.CreateChild(),
TurnCount = 3 // or -1
})
.MeasureElement(new Size(500, 400))
.ExpectChildMeasure(new Size(400, 500), SpacePlan.FullRender(300, 350))
.CheckMeasureResult(SpacePlan.FullRender(350, 300));
}
#endregion
#region draw
[Test]
public void Draw_Simple()
{
TestPlan
.For(x => new SimpleRotate
{
Child = x.CreateChild(),
TurnCount = 0
})
.DrawElement(new Size(640, 480))
.ExpectCanvasTranslate(0, 0)
.ExpectCanvasRotate(0)
.ExpectChildDraw(new Size(640, 480))
.ExpectCanvasRotate(0)
.ExpectCanvasTranslate(0, 0)
.CheckDrawResult();
}
[Test]
public void Draw_RotateRight()
{
TestPlan
.For(x => new SimpleRotate
{
Child = x.CreateChild(),
TurnCount = 1
})
.DrawElement(new Size(640, 480))
.ExpectCanvasTranslate(640, 0)
.ExpectCanvasRotate(90)
.ExpectChildDraw(new Size(480, 640))
.ExpectCanvasRotate(-90)
.ExpectCanvasTranslate(-640, 0)
.CheckDrawResult();
}
[Test]
public void Draw_RotateFlip()
{
TestPlan
.For(x => new SimpleRotate
{
Child = x.CreateChild(),
TurnCount = 2
})
.DrawElement(new Size(640, 480))
.ExpectCanvasTranslate(640, 480)
.ExpectCanvasRotate(180)
.ExpectChildDraw(new Size(640, 480))
.ExpectCanvasRotate(-180)
.ExpectCanvasTranslate(-640, -480)
.CheckDrawResult();
}
[Test]
public void Draw_RotateLeft()
{
TestPlan
.For(x => new SimpleRotate
{
Child = x.CreateChild(),
TurnCount = 3 // or -1
})
.DrawElement(new Size(640, 480))
.ExpectCanvasTranslate(0, 480)
.ExpectCanvasRotate(270)
.ExpectChildDraw(new Size(480, 640))
.ExpectCanvasRotate(-270)
.ExpectCanvasTranslate(0, -480)
.CheckDrawResult();
}
#endregion
}
}
+43 -118
View File
@@ -1,7 +1,6 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
@@ -16,80 +15,80 @@ namespace QuestPDF.UnitTests
public void Measure_ReturnsWrap_WhenFirstChildWraps()
{
TestPlan
.For(x => new BinaryStack
.For(x => new SimpleStack
{
First = x.CreateChild("first"),
Second = x.CreateChild("second")
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
.ExpectChildMeasure("first", new Size(400, 300), new Wrap())
.CheckMeasureResult(new Wrap());
}
[Test]
public void Measure_ReturnsPartialRender_WhenFirstChildReturnsPartialRender()
{
TestPlan
.For(x => new BinaryStack
.For(x => new SimpleStack
{
First = x.CreateChild("first"),
Second = x.CreateChild("second")
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.PartialRender(300, 200))
.CheckMeasureResult(SpacePlan.PartialRender(300, 200));
.ExpectChildMeasure("first", new Size(400, 300), new PartialRender(300, 200))
.CheckMeasureResult(new PartialRender(300, 200));
}
[Test]
public void Measure_ReturnsPartialRender_WhenSecondChildWraps()
{
TestPlan
.For(x => new BinaryStack
.For(x => new SimpleStack
{
First = x.CreateChild("first"),
Second = x.CreateChild("second")
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
.ExpectChildMeasure("second", new Size(400, 200), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.PartialRender(200, 100));
.ExpectChildMeasure("first", new Size(400, 300), new FullRender(200, 100))
.ExpectChildMeasure("second", new Size(400, 200), new Wrap())
.CheckMeasureResult(new PartialRender(200, 100));
}
[Test]
public void Measure_ReturnsPartialRender_WhenSecondChildReturnsPartialRender()
{
TestPlan
.For(x => new BinaryStack
.For(x => new SimpleStack
{
First = x.CreateChild("first"),
Second = x.CreateChild("second")
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
.ExpectChildMeasure("second", new Size(400, 200), SpacePlan.PartialRender(300, 150))
.CheckMeasureResult(SpacePlan.PartialRender(300, 250));
.ExpectChildMeasure("first", new Size(400, 300), new FullRender(200, 100))
.ExpectChildMeasure("second", new Size(400, 200), new PartialRender(300, 150))
.CheckMeasureResult(new PartialRender(300, 250));
}
[Test]
public void Measure_ReturnsFullRender_WhenSecondChildReturnsFullRender()
{
TestPlan
.For(x => new BinaryStack
.For(x => new SimpleStack
{
First = x.CreateChild("first"),
Second = x.CreateChild("second")
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
.ExpectChildMeasure("second", new Size(400, 200), SpacePlan.FullRender(100, 50))
.CheckMeasureResult(SpacePlan.FullRender(200, 150));
.ExpectChildMeasure("first", new Size(400, 300), new FullRender(200, 100))
.ExpectChildMeasure("second", new Size(400, 200), new FullRender(100, 50))
.CheckMeasureResult(new FullRender(200, 150));
}
[Test]
public void Measure_UsesEmpty_WhenFirstChildIsRendered()
{
TestPlan
.For(x => new BinaryStack
.For(x => new SimpleStack
{
First = x.CreateChild("first"),
Second = x.CreateChild("second"),
@@ -97,8 +96,8 @@ namespace QuestPDF.UnitTests
IsFirstRendered = true
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure("second", new Size(400, 300), SpacePlan.FullRender(200, 300))
.CheckMeasureResult(SpacePlan.FullRender(200, 300));
.ExpectChildMeasure("second", new Size(400, 300), new FullRender(200, 300))
.CheckMeasureResult(new FullRender(200, 300));
}
#endregion
@@ -109,13 +108,13 @@ namespace QuestPDF.UnitTests
public void Draw_WhenFirstChildWraps()
{
TestPlan
.For(x => new BinaryStack
.For(x => new SimpleStack
{
First = x.CreateChild("first"),
Second = x.CreateChild("second")
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.Wrap())
.ExpectChildMeasure("first", new Size(400, 300), new Wrap())
.CheckDrawResult();
}
@@ -123,13 +122,13 @@ namespace QuestPDF.UnitTests
public void Draw_WhenFirstChildPartiallyRenders()
{
TestPlan
.For(x => new BinaryStack
.For(x => new SimpleStack
{
First = x.CreateChild("first"),
Second = x.CreateChild("second")
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.PartialRender(200, 100))
.ExpectChildMeasure("first", new Size(400, 300), new PartialRender(200, 100))
.ExpectChildDraw("first", new Size(400, 100))
.CheckDrawResult();
}
@@ -138,15 +137,15 @@ namespace QuestPDF.UnitTests
public void Draw_WhenFirstChildFullyRenders_AndSecondChildWraps()
{
TestPlan
.For(x => new BinaryStack
.For(x => new SimpleStack
{
First = x.CreateChild("first"),
Second = x.CreateChild("second")
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
.ExpectChildMeasure("first", new Size(400, 300), new FullRender(200, 100))
.ExpectChildDraw("first", new Size(400, 100))
.ExpectChildMeasure("second", new Size(400, 200), SpacePlan.Wrap())
.ExpectChildMeasure("second", new Size(400, 200), new Wrap())
.CheckDrawResult();
}
@@ -154,15 +153,15 @@ namespace QuestPDF.UnitTests
public void Draw_WhenFirstChildFullyRenders_AndSecondChildPartiallyRenders()
{
TestPlan
.For(x => new BinaryStack
.For(x => new SimpleStack
{
First = x.CreateChild("first"),
Second = x.CreateChild("second")
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
.ExpectChildMeasure("first", new Size(400, 300), new FullRender(200, 100))
.ExpectChildDraw("first", new Size(400, 100))
.ExpectChildMeasure("second", new Size(400, 200), SpacePlan.PartialRender(250, 150))
.ExpectChildMeasure("second", new Size(400, 200), new PartialRender(250, 150))
.ExpectCanvasTranslate(0, 100)
.ExpectChildDraw("second", new Size(400, 150))
.ExpectCanvasTranslate(0, -100)
@@ -173,15 +172,15 @@ namespace QuestPDF.UnitTests
public void Draw_WhenFirstChildFullyRenders_AndSecondChildFullyRenders()
{
TestPlan
.For(x => new BinaryStack
.For(x => new SimpleStack
{
First = x.CreateChild("first"),
Second = x.CreateChild("second")
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
.ExpectChildMeasure("first", new Size(400, 300), new FullRender(200, 100))
.ExpectChildDraw("first", new Size(400, 100))
.ExpectChildMeasure("second", new Size(400, 200), SpacePlan.FullRender(250, 150))
.ExpectChildMeasure("second", new Size(400, 200), new FullRender(250, 150))
.ExpectCanvasTranslate(0, 100)
.ExpectChildDraw("second", new Size(400, 150))
.ExpectCanvasTranslate(0, -100)
@@ -192,7 +191,7 @@ namespace QuestPDF.UnitTests
public void Draw_UsesEmpty_WhenFirstChildIsRendered()
{
TestPlan
.For(x => new BinaryStack
.For(x => new SimpleStack
{
First = x.CreateChild("first"),
Second = x.CreateChild("second"),
@@ -200,11 +199,11 @@ namespace QuestPDF.UnitTests
IsFirstRendered = true
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure("second", new Size(400, 300), SpacePlan.PartialRender(200, 300))
.ExpectChildMeasure("second", new Size(400, 300), new PartialRender(200, 300))
.ExpectCanvasTranslate(0, 0)
.ExpectChildDraw("second", new Size(400, 300))
.ExpectCanvasTranslate(0, 0)
.CheckState<BinaryStack>(x => x.IsFirstRendered)
.CheckState<SimpleStack>(x => x.IsFirstRendered)
.CheckDrawResult();
}
@@ -212,7 +211,7 @@ namespace QuestPDF.UnitTests
public void Draw_TogglesFirstRenderedFlag_WhenSecondFullyRenders()
{
TestPlan
.For(x => new BinaryStack
.For(x => new SimpleStack
{
First = x.CreateChild("first"),
Second = x.CreateChild("second"),
@@ -220,91 +219,17 @@ namespace QuestPDF.UnitTests
IsFirstRendered = true
})
.DrawElement(new Size(400, 300))
.ExpectChildMeasure("second", new Size(400, 300), SpacePlan.FullRender(200, 300))
.ExpectChildMeasure("second", new Size(400, 300), new FullRender(200, 300))
.ExpectCanvasTranslate(0, 0)
.ExpectChildDraw("second", new Size(400, 300))
.ExpectCanvasTranslate(0, 0)
.CheckDrawResult()
.CheckState<BinaryStack>(x => !x.IsFirstRendered);
.CheckState<SimpleStack>(x => !x.IsFirstRendered);
}
#endregion
#region Structure
[Test]
public void Structure_Simple()
{
// arrange
var childA = TestPlan.CreateUniqueElement();
var childB = TestPlan.CreateUniqueElement();
var childC = TestPlan.CreateUniqueElement();
var childD = TestPlan.CreateUniqueElement();
var childE = TestPlan.CreateUniqueElement();
const int spacing = 20;
// act
var structure = new Container();
structure.Stack(stack =>
{
stack.Spacing(spacing);
stack.Item().Element(childA);
stack.Item().Element(childB);
stack.Item().Element(childC);
stack.Item().Element(childD);
stack.Item().Element(childE);
});
// assert
var expected = new Padding
{
Bottom = -spacing,
Child = new BinaryStack
{
First = new BinaryStack
{
First = new Padding
{
Bottom = spacing,
Child = childA
},
Second = new Padding
{
Bottom = spacing,
Child = childB
}
},
Second = new BinaryStack
{
First = new Padding
{
Bottom = spacing,
Child = childC
},
Second = new BinaryStack
{
First = new Padding
{
Bottom = spacing,
Child = childD
},
Second = new Padding
{
Bottom = spacing,
Child = childE
}
}
}
}
};
TestPlan.CompareOperations(structure, expected);
}
#endregion
// TODO: add tests for the spacing property
// TODO: add tests for the tree builder method
}
}
@@ -4,25 +4,41 @@ using SkiaSharp;
namespace QuestPDF.UnitTests.TestEngine
{
internal class MockCanvas : ICanvas
internal class CanvasMock : ICanvas
{
public Action<Position> TranslateFunc { get; set; }
public Action<float> RotateFunc { get; set; }
public Action<float, float> ScaleFunc { get; set; }
public Action<SKImage, Position, Size> DrawImageFunc { get; set; }
public Action<string, Position, TextStyle> DrawTextFunc { get; set; }
public Action<Position, Size, string> DrawRectFunc { get; set; }
public void Translate(Position vector) => TranslateFunc(vector);
public void Rotate(float angle) => RotateFunc(angle);
public void Scale(float scaleX, float scaleY) => ScaleFunc(scaleX, scaleY);
public void DrawRectangle(Position vector, Size size, string color) => DrawRectFunc(vector, size, color);
public void DrawText(string text, Position position, TextStyle style) => DrawTextFunc(text, position, style);
public void DrawImage(SKImage image, Position position, Size size) => DrawImageFunc(image, position, size);
public void DrawExternalLink(string url, Size size) => throw new NotImplementedException();
public void DrawLocationLink(string locationName, Size size) => throw new NotImplementedException();
public void DrawLocation(string locationName) => throw new NotImplementedException();
public void DrawExternalLink(string url, Size size)
{
throw new NotImplementedException();
}
public void DrawLocationLink(string locationName, Size size)
{
throw new NotImplementedException();
}
public void DrawLocation(string locationName)
{
throw new NotImplementedException();
}
public void DrawLink(string url, Size size)
{
throw new NotImplementedException();
}
public Size MeasureText(string text, TextStyle style)
{
return new Size(text.Length * style.Size, style.Size);
}
}
}
+3 -3
View File
@@ -1,5 +1,5 @@
using System;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Infrastructure;
namespace QuestPDF.UnitTests.TestEngine
@@ -7,10 +7,10 @@ namespace QuestPDF.UnitTests.TestEngine
internal class ElementMock : Element
{
public string Id { get; set; }
public Func<Size, SpacePlan> MeasureFunc { get; set; }
public Func<Size, ISpacePlan> MeasureFunc { get; set; }
public Action<Size> DrawFunc { get; set; }
internal override SpacePlan Measure(Size availableSpace) => MeasureFunc(availableSpace);
internal override ISpacePlan Measure(Size availableSpace) => MeasureFunc(availableSpace);
internal override void Draw(Size availableSpace) => DrawFunc(availableSpace);
}
}
@@ -1,25 +0,0 @@
using System;
using System.Collections.Generic;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine.Operations;
using SkiaSharp;
namespace QuestPDF.UnitTests.TestEngine
{
internal class OperationRecordingCanvas : ICanvas
{
public ICollection<OperationBase> Operations { get; } = new List<OperationBase>();
public void Translate(Position vector) => Operations.Add(new CanvasTranslateOperation(vector));
public void Rotate(float angle) => Operations.Add(new CanvasRotateOperation(angle));
public void Scale(float scaleX, float scaleY) => Operations.Add(new CanvasScaleOperation(scaleX, scaleY));
public void DrawRectangle(Position vector, Size size, string color) => Operations.Add(new CanvasDrawRectangleOperation(vector, size, color));
public void DrawText(string text, Position position, TextStyle style) => Operations.Add(new CanvasDrawTextOperation(text, position, style));
public void DrawImage(SKImage image, Position position, Size size) => Operations.Add(new CanvasDrawImageOperation(position, size));
public void DrawExternalLink(string url, Size size) => throw new NotImplementedException();
public void DrawLocationLink(string locationName, Size size) => throw new NotImplementedException();
public void DrawLocation(string locationName) => throw new NotImplementedException();
}
}
@@ -2,12 +2,12 @@
namespace QuestPDF.UnitTests.TestEngine.Operations
{
internal class CanvasDrawImageOperation : OperationBase
internal class CanvasDrawImageOperationBase : OperationBase
{
public Position Position { get; }
public Size Size { get; }
public CanvasDrawImageOperation(Position position, Size size)
public CanvasDrawImageOperationBase(Position position, Size size)
{
Position = position;
Size = size;
@@ -2,13 +2,13 @@
namespace QuestPDF.UnitTests.TestEngine.Operations
{
internal class CanvasDrawRectangleOperation : OperationBase
internal class CanvasDrawRectangleOperationBase : OperationBase
{
public Position Position { get; }
public Size Size { get; }
public string Color { get; }
public CanvasDrawRectangleOperation(Position position, Size size, string color)
public CanvasDrawRectangleOperationBase(Position position, Size size, string color)
{
Position = position;
Size = size;
@@ -2,13 +2,13 @@
namespace QuestPDF.UnitTests.TestEngine.Operations
{
internal class CanvasDrawTextOperation : OperationBase
internal class CanvasDrawTextOperationBase : OperationBase
{
public string Text { get; }
public Position Position { get; }
public TextStyle Style { get; }
public CanvasDrawTextOperation(string text, Position position, TextStyle style)
public CanvasDrawTextOperationBase(string text, Position position, TextStyle style)
{
Text = text;
Position = position;
@@ -1,12 +0,0 @@
namespace QuestPDF.UnitTests.TestEngine.Operations
{
public class CanvasRotateOperation : OperationBase
{
public float Angle { get; }
public CanvasRotateOperation(float angle)
{
Angle = angle;
}
}
}
@@ -1,14 +0,0 @@
namespace QuestPDF.UnitTests.TestEngine.Operations
{
public class CanvasScaleOperation : OperationBase
{
public float ScaleX { get; }
public float ScaleY { get; }
public CanvasScaleOperation(float scaleX, float scaleY)
{
ScaleX = scaleX;
ScaleY = scaleY;
}
}
}
@@ -2,11 +2,11 @@
namespace QuestPDF.UnitTests.TestEngine.Operations
{
internal class CanvasTranslateOperation : OperationBase
internal class CanvasTranslateOperationBase : OperationBase
{
public Position Position { get; }
public CanvasTranslateOperation(Position position)
public CanvasTranslateOperationBase(Position position)
{
Position = position;
}
@@ -2,12 +2,12 @@
namespace QuestPDF.UnitTests.TestEngine.Operations
{
public class ChildDrawOperation : OperationBase
public class ChildDrawOperationBase : OperationBase
{
public string ChildId { get; }
public Size Input { get; }
public ChildDrawOperation(string childId, Size input)
public ChildDrawOperationBase(string childId, Size input)
{
ChildId = childId;
Input = input;
@@ -1,15 +1,15 @@
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Infrastructure;
namespace QuestPDF.UnitTests.TestEngine.Operations
{
internal class ChildMeasureOperation : OperationBase
internal class ChildMeasureOperationBase : OperationBase
{
public string ChildId { get; }
public Size Input { get; }
public SpacePlan Output { get; }
public ISpacePlan Output { get; }
public ChildMeasureOperation(string childId, Size input, SpacePlan output)
public ChildMeasureOperationBase(string childId, Size input, ISpacePlan output)
{
ChildId = childId;
Input = input;
@@ -2,9 +2,9 @@
namespace QuestPDF.UnitTests.TestEngine.Operations
{
public class ElementMeasureOperation : OperationBase
public class ElementMeasureOperationBase : OperationBase
{
public ElementMeasureOperation(Size input)
public ElementMeasureOperationBase(Size input)
{
}
@@ -1,67 +0,0 @@
using QuestPDF.Drawing;
using QuestPDF.Infrastructure;
namespace QuestPDF.UnitTests.TestEngine
{
internal static class SimpleContainerTests
{
#region measure
public static void Measure<TElement>() where TElement : Element, IContainer, new()
{
Measure_Wrap<TElement>();
Measure_PartialRender<TElement>();
Measure_FullRender<TElement>();
}
private static void Measure_Wrap<TElement>() where TElement : Element, IContainer, new()
{
TestPlan
.For(x => new TElement
{
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(400, 300), SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
}
private static void Measure_PartialRender<TElement>() where TElement : Element, IContainer, new()
{
TestPlan
.For(x => new TElement
{
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(400, 300), SpacePlan.PartialRender(200, 100))
.CheckMeasureResult(SpacePlan.PartialRender(200, 100));
}
private static void Measure_FullRender<TElement>() where TElement : Element, IContainer, new()
{
TestPlan
.For(x => new TElement
{
Child = x.CreateChild()
})
.MeasureElement(new Size(400, 300))
.ExpectChildMeasure(new Size(400, 300), SpacePlan.FullRender(250, 150))
.CheckMeasureResult(SpacePlan.FullRender(250, 150));
}
#endregion
public static void Draw<TElement>() where TElement : Element, IContainer, new()
{
TestPlan
.For(x => new TElement
{
Child = x.CreateChild()
})
.DrawElement(new Size(1200, 900))
.ExpectChildDraw(new Size(1200, 900))
.CheckDrawResult();
}
}
}
@@ -0,0 +1,31 @@
using FluentAssertions;
using NUnit.Framework;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Infrastructure;
namespace QuestPDF.UnitTests.TestEngine
{
public static class SingleChildTests
{
internal static void MeasureWithoutChild<T>(this T element) where T : ContainerElement
{
element.Child = null;
element.Measure(Size.Zero).Should().BeEquivalentTo(new FullRender(Size.Zero));
}
internal static void DrawWithoutChild<T>(this T element) where T : ContainerElement
{
// component does not throw an exception when called with null child
Assert.DoesNotThrow(() =>
{
element.Child = null;
// component does not perform any canvas operation when called with null child
TestPlan
.For(x => element)
.DrawElement(new Size(200, 100))
.CheckDrawResult();
});
}
}
}
+48 -91
View File
@@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using FluentAssertions;
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
@@ -14,8 +13,6 @@ namespace QuestPDF.UnitTests.TestEngine
internal class TestPlan
{
private const string DefaultChildName = "child";
private static Random Random { get; } = new Random();
private Element Element { get; set; }
private ICanvas Canvas { get; }
@@ -48,31 +45,20 @@ namespace QuestPDF.UnitTests.TestEngine
private ICanvas CreateCanvas()
{
return new MockCanvas
return new CanvasMock
{
TranslateFunc = position =>
{
var expected = GetExpected<CanvasTranslateOperation>();
var expected = GetExpected<CanvasTranslateOperationBase>();
Assert.AreEqual(expected.Position.X, position.X, "Translate X");
Assert.AreEqual(expected.Position.Y, position.Y, "Translate Y");
},
RotateFunc = angle =>
{
var expected = GetExpected<CanvasRotateOperation>();
Assert.AreEqual(expected.Angle, angle, "Rotate angle");
},
ScaleFunc = (scaleX, scaleY) =>
{
var expected = GetExpected<CanvasScaleOperation>();
Assert.AreEqual(expected.ScaleX, scaleX, "Scale X");
Assert.AreEqual(expected.ScaleY, scaleY, "Scale Y");
//position.Should().BeEquivalentTo(expected.Position);
},
DrawRectFunc = (position, size, color) =>
{
var expected = GetExpected<CanvasDrawRectangleOperation>();
var expected = GetExpected<CanvasDrawRectangleOperationBase>();
Assert.AreEqual(expected.Position.X, position.X, "Draw rectangle: X");
Assert.AreEqual(expected.Position.Y, position.Y, "Draw rectangle: Y");
@@ -81,10 +67,14 @@ namespace QuestPDF.UnitTests.TestEngine
Assert.AreEqual(expected.Size.Height, size.Height, "Draw rectangle: height");
Assert.AreEqual(expected.Color, color, "Draw rectangle: color");
/*position.Should().BeEquivalentTo(expected.Position);
size.Should().BeEquivalentTo(expected.Size);
color.Should().Be(expected.Color);*/
},
DrawTextFunc = (text, position, style) =>
{
var expected = GetExpected<CanvasDrawTextOperation>();
var expected = GetExpected<CanvasDrawTextOperationBase>();
Assert.AreEqual(expected.Text, text);
@@ -94,16 +84,23 @@ namespace QuestPDF.UnitTests.TestEngine
Assert.AreEqual(expected.Style.Color, style.Color, "Draw text: color");
Assert.AreEqual(expected.Style.FontType, style.FontType, "Draw text: font");
Assert.AreEqual(expected.Style.Size, style.Size, "Draw text: size");
/*text.Should().Be(expected.Text);
position.Should().BeEquivalentTo(expected.Position);
style.Should().BeEquivalentTo(expected.Style);*/
},
DrawImageFunc = (image, position, size) =>
{
var expected = GetExpected<CanvasDrawImageOperation>();
var expected = GetExpected<CanvasDrawImageOperationBase>();
Assert.AreEqual(expected.Position.X, position.X, "Draw image: X");
Assert.AreEqual(expected.Position.Y, position.Y, "Draw image: Y");
Assert.AreEqual(expected.Size.Width, size.Width, "Draw image: width");
Assert.AreEqual(expected.Size.Height, size.Height, "Draw image: height");
/*position.Should().BeEquivalentTo(expected.Position);
size.Should().BeEquivalentTo(expected.Size);*/
}
};
}
@@ -117,23 +114,29 @@ namespace QuestPDF.UnitTests.TestEngine
Id = id,
MeasureFunc = availableSpace =>
{
var expected = GetExpected<ChildMeasureOperation>();
var expected = GetExpected<ChildMeasureOperationBase>();
Assert.AreEqual(expected.ChildId, id);
Assert.AreEqual(expected.Input.Width, availableSpace.Width, $"Measure: width of child '{expected.ChildId}'");
Assert.AreEqual(expected.Input.Height, availableSpace.Height, $"Measure: height of child '{expected.ChildId}'");
// id.Should().Be(expected.ChildId);
// availableSpace.Should().Be(expected.Input);
return expected.Output;
},
DrawFunc = availableSpace =>
{
var expected = GetExpected<ChildDrawOperation>();
var expected = GetExpected<ChildDrawOperationBase>();
Assert.AreEqual(expected.ChildId, id);
Assert.AreEqual(expected.Input.Width, availableSpace.Width, $"Draw: width of child '{expected.ChildId}'");
Assert.AreEqual(expected.Input.Height, availableSpace.Height, $"Draw: width of child '{expected.ChildId}'");
/*id.Should().Be(expected.ChildId);
availableSpace.Should().Be(expected.Input);*/
}
};
}
@@ -156,14 +159,14 @@ namespace QuestPDF.UnitTests.TestEngine
return this;
}
public TestPlan ExpectChildMeasure(Size expectedInput, SpacePlan returns)
public TestPlan ExpectChildMeasure(Size expectedInput, ISpacePlan returns)
{
return ExpectChildMeasure(DefaultChildName, expectedInput, returns);
}
public TestPlan ExpectChildMeasure(string child, Size expectedInput, SpacePlan returns)
public TestPlan ExpectChildMeasure(string child, Size expectedInput, ISpacePlan returns)
{
return AddOperation(new ChildMeasureOperation(child, expectedInput, returns));
return AddOperation(new ChildMeasureOperationBase(child, expectedInput, returns));
}
public TestPlan ExpectChildDraw(Size expectedInput)
@@ -173,55 +176,50 @@ namespace QuestPDF.UnitTests.TestEngine
public TestPlan ExpectChildDraw(string child, Size expectedInput)
{
return AddOperation(new ChildDrawOperation(child, expectedInput));
return AddOperation(new ChildDrawOperationBase(child, expectedInput));
}
public TestPlan ExpectCanvasTranslate(Position position)
{
return AddOperation(new CanvasTranslateOperation(position));
return AddOperation(new CanvasTranslateOperationBase(position));
}
public TestPlan ExpectCanvasTranslate(float left, float top)
{
return AddOperation(new CanvasTranslateOperation(new Position(left, top)));
return AddOperation(new CanvasTranslateOperationBase(new Position(left, top)));
}
public TestPlan ExpectCanvasScale(float scaleX, float scaleY)
{
return AddOperation(new CanvasScaleOperation(scaleX, scaleY));
}
public TestPlan ExpectCanvasRotate(float angle)
{
return AddOperation(new CanvasRotateOperation(angle));
}
public TestPlan ExpectCanvasDrawRectangle(Position position, Size size, string color)
{
return AddOperation(new CanvasDrawRectangleOperation(position, size, color));
return AddOperation(new CanvasDrawRectangleOperationBase(position, size, color));
}
public TestPlan ExpectCanvasDrawText(string text, Position position, TextStyle style)
{
return AddOperation(new CanvasDrawTextOperation(text, position, style));
return AddOperation(new CanvasDrawTextOperationBase(text, position, style));
}
public TestPlan ExpectCanvasDrawImage(Position position, Size size)
{
return AddOperation(new CanvasDrawImageOperation(position, size));
return AddOperation(new CanvasDrawImageOperationBase(position, size));
}
public TestPlan CheckMeasureResult(SpacePlan expected)
public TestPlan CheckMeasureResult(ISpacePlan expected)
{
Element.HandleVisitor(x => x?.Initialize(null, Canvas));
var actual = Element.Measure(OperationInput);
Assert.AreEqual(expected.GetType(), actual.GetType());
Assert.AreEqual(expected.Width, actual.Width, "Measure: width");
Assert.AreEqual(expected.Height, actual.Height, "Measure: height");
Assert.AreEqual(expected.Type, actual.Type, "Measure: height");
var expectedSize = expected as Size;
var actualSize = actual as Size;
if (expectedSize != null)
{
Assert.AreEqual(expectedSize.Width, actualSize.Width, "Measure: width");
Assert.AreEqual(expectedSize.Height, actualSize.Height, "Measure: height");
}
return this;
}
@@ -248,51 +246,10 @@ namespace QuestPDF.UnitTests.TestEngine
public static Element CreateUniqueElement()
{
return new Constrained
return new DynamicImage
{
MinWidth = 90,
MinHeight = 60,
Child = new DynamicImage
{
Source = Placeholders.Image
}
Source = Placeholders.Image
};
}
public static void CompareOperations(Element value, Element expected, Size? availableSpace = null)
{
CompareMeasureOperations(value, expected, availableSpace);
CompareDrawOperations(value, expected, availableSpace);
}
private static void CompareMeasureOperations(Element value, Element expected, Size? availableSpace = null)
{
availableSpace ??= new Size(400, 300);
var canvas = new FreeCanvas();
value.HandleVisitor(x => x.Initialize(null, canvas));
var valueMeasure = value.Measure(availableSpace.Value);
expected.HandleVisitor(x => x.Initialize(null, canvas));
var expectedMeasure = expected.Measure(availableSpace.Value);
valueMeasure.Should().BeEquivalentTo(expectedMeasure);
}
private static void CompareDrawOperations(Element value, Element expected, Size? availableSpace = null)
{
availableSpace ??= new Size(400, 300);
var valueCanvas = new OperationRecordingCanvas();
value.HandleVisitor(x => x.Initialize(null, valueCanvas));
value.Draw(availableSpace.Value);
var expectedCanvas = new OperationRecordingCanvas();
expected.HandleVisitor(x => x.Initialize(null, expectedCanvas));
expected.Draw(availableSpace.Value);
valueCanvas.Operations.Should().BeEquivalentTo(expectedCanvas.Operations);
}
}
}
-22
View File
@@ -1,22 +0,0 @@
using FluentAssertions;
using NUnit.Framework;
namespace QuestPDF.UnitTests
{
[SetUpFixture]
public class TestsBase
{
[OneTimeSetUp]
public void RunBeforeAnyTests()
{
AssertionOptions.AssertEquivalencyUsing(options => options
.IncludingNestedObjects()
.IncludingInternalProperties()
.IncludingInternalFields()
.AllowingInfiniteRecursion()
.RespectingRuntimeTypes()
.WithTracing()
.WithStrictOrdering());
}
}
}
+10
View File
@@ -0,0 +1,10 @@
using NUnit.Framework;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class TextTests
{
}
}
-31
View File
@@ -1,31 +0,0 @@
using NUnit.Framework;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class TranslateTests
{
[Test]
public void Measure() => SimpleContainerTests.Measure<Translate>();
[Test]
public void Draw()
{
TestPlan
.For(x => new Translate
{
Child = x.CreateChild(),
TranslateX = 50,
TranslateY = 75
})
.DrawElement(new Size(400, 300))
.ExpectCanvasTranslate(50, 75)
.ExpectChildDraw(new Size(400, 300))
.ExpectCanvasTranslate(-50, -75)
.CheckDrawResult();
}
}
}
-100
View File
@@ -1,100 +0,0 @@
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class UnconstrainedTests
{
#region measure
[Test]
public void Measure_Wrap()
{
TestPlan
.For(x => new Unconstrained
{
Child = x.CreateChild()
})
.MeasureElement(new Size(900, 800))
.ExpectChildMeasure(Size.Max, SpacePlan.Wrap())
.CheckMeasureResult(SpacePlan.Wrap());
}
[Test]
public void Measure_PartialRender()
{
TestPlan
.For(x => new Unconstrained
{
Child = x.CreateChild()
})
.MeasureElement(new Size(900, 800))
.ExpectChildMeasure(Size.Max, SpacePlan.PartialRender(1200, 1600))
.CheckMeasureResult(SpacePlan.PartialRender(Size.Zero));
}
[Test]
public void Measure_FullRender()
{
TestPlan
.For(x => new Unconstrained
{
Child = x.CreateChild()
})
.MeasureElement(new Size(900, 800))
.ExpectChildMeasure(Size.Max, SpacePlan.FullRender(1200, 1600))
.CheckMeasureResult(SpacePlan.FullRender(Size.Zero));
}
#endregion
#region draw
[Test]
public void Draw_SkipWhenChildWraps()
{
TestPlan
.For(x => new Unconstrained
{
Child = x.CreateChild()
})
.DrawElement(new Size(900, 800))
.ExpectChildMeasure(Size.Max, SpacePlan.Wrap())
.CheckDrawResult();
}
[Test]
public void Draw_WhenChildPartiallyRenders()
{
TestPlan
.For(x => new Unconstrained
{
Child = x.CreateChild()
})
.DrawElement(new Size(900, 800))
.ExpectChildMeasure(Size.Max, SpacePlan.PartialRender(1200, 1600))
.ExpectChildDraw(new Size(1200, 1600))
.CheckDrawResult();
}
[Test]
public void Draw_WhenChildFullyRenders()
{
TestPlan
.For(x => new Unconstrained
{
Child = x.CreateChild()
})
.DrawElement(new Size(900, 800))
.ExpectChildMeasure(Size.Max, SpacePlan.FullRender(1600, 1000))
.ExpectChildDraw(new Size(1600, 1000))
.CheckDrawResult();
}
#endregion
}
}
+1 -2
View File
@@ -2,5 +2,4 @@
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
[assembly: InternalsVisibleTo("QuestPDF.UnitTests")]
[assembly: InternalsVisibleTo("QuestPDF.Examples")]
[assembly: InternalsVisibleTo("QuestPDF.ReportSample")]
[assembly: InternalsVisibleTo("QuestPDF.Examples")]
@@ -1,23 +1,15 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Collections.Concurrent;
using QuestPDF.Infrastructure;
using SkiaSharp;
namespace QuestPDF.Drawing
{
public static class FontManager
internal static class CanvasCache
{
private static ConcurrentDictionary<string, SKTypeface> Typefaces = new ConcurrentDictionary<string, SKTypeface>();
internal static ConcurrentDictionary<string, SKPaint> Paints = new ConcurrentDictionary<string, SKPaint>();
private static ConcurrentDictionary<string, SKFontMetrics> FontMetrics = new ConcurrentDictionary<string, SKFontMetrics>();
private static ConcurrentDictionary<string, SKPaint> Paints = new ConcurrentDictionary<string, SKPaint>();
private static ConcurrentDictionary<string, SKPaint> ColorPaint = new ConcurrentDictionary<string, SKPaint>();
public static void RegisterFontType(string fontName, Stream stream)
{
Typefaces.TryAdd(fontName, SKTypeface.FromStream(stream));
}
internal static SKPaint ColorToPaint(this string color)
{
return ColorPaint.GetOrAdd(color, Convert);
@@ -37,25 +29,16 @@ namespace QuestPDF.Drawing
static SKPaint Convert(TextStyle style)
{
var slant = style.IsItalic ? SKFontStyleSlant.Italic : SKFontStyleSlant.Upright;
return new SKPaint
{
Color = SKColor.Parse(style.Color),
Typeface = GetTypeface(style),
Typeface = SKTypeface.FromFamilyName(style.FontType, (int)style.FontWeight, (int)SKFontStyleWidth.Normal, slant),
TextSize = style.Size,
TextEncoding = SKTextEncoding.Utf32
};
}
static SKTypeface GetTypeface(TextStyle style)
{
if (Typefaces.TryGetValue(style.FontType, out var result))
return result;
var slant = style.IsItalic ? SKFontStyleSlant.Italic : SKFontStyleSlant.Upright;
return SKTypeface.FromFamilyName(style.FontType, (int)style.FontWeight, (int)SKFontStyleWidth.Normal, slant)
?? throw new ArgumentException($"The typeface {style.FontType} could not be found.");
}
}
internal static SKFontMetrics ToFontMetrics(this TextStyle style)
+9 -54
View File
@@ -2,7 +2,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using QuestPDF.Drawing.Exceptions;
using QuestPDF.Drawing.Proxy;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Infrastructure;
@@ -36,22 +36,11 @@ namespace QuestPDF.Drawing
var metadata = document.GetMetadata();
var pageContext = new PageContext();
DebuggingState debuggingState = null;
if (System.Diagnostics.Debugger.IsAttached)
{
debuggingState = ApplyDebugging(content);
}
else
{
ApplyCaching(content);
}
RenderPass(pageContext, new FreeCanvas(), content, metadata, debuggingState);
RenderPass(pageContext, canvas, content, metadata, debuggingState);
RenderPass(pageContext, new FreeCanvas(), content, metadata);
RenderPass(pageContext, canvas, content, metadata);
}
internal static void RenderPass<TCanvas>(PageContext pageContext, TCanvas canvas, Container content, DocumentMetadata documentMetadata, DebuggingState? debuggingState)
private static void RenderPass<TCanvas>(PageContext pageContext, TCanvas canvas, Container content, DocumentMetadata documentMetadata)
where TCanvas : ICanvas, IRenderingCanvas
{
content.HandleVisitor(x => x?.Initialize(pageContext, canvas));
@@ -64,15 +53,10 @@ namespace QuestPDF.Drawing
while(true)
{
pageContext.SetPageNumber(currentPage);
debuggingState?.Reset();
var spacePlan = content.Measure(Size.Max);
var spacePlan = content.Measure(Size.Max) as Size;
if (spacePlan.Type == SpacePlanType.Wrap)
{
canvas.EndDocument();
ThrowLayoutException();
}
if (spacePlan == null)
break;
try
{
@@ -90,45 +74,16 @@ namespace QuestPDF.Drawing
if (currentPage >= documentMetadata.DocumentLayoutExceptionThreshold)
{
canvas.EndDocument();
ThrowLayoutException();
throw new DocumentLayoutException("Composed layout generates infinite document.");
}
if (spacePlan.Type == SpacePlanType.FullRender)
if (spacePlan is FullRender)
break;
currentPage++;
}
canvas.EndDocument();
void ThrowLayoutException()
{
throw new DocumentLayoutException("Composed layout generates infinite document.")
{
ElementTrace = debuggingState?.BuildTrace() ?? "Debug trace is available only in the DEBUG mode."
};
}
}
private static void ApplyCaching(Container content)
{
content.HandleVisitor(x =>
{
if (x is ICacheable)
x.CreateProxy(y => new CacheProxy(y));
});
}
private static DebuggingState ApplyDebugging(Container content)
{
var debuggingState = new DebuggingState();
content.HandleVisitor(x =>
{
x.CreateProxy(y => new DebuggingProxy(debuggingState, y));
});
return debuggingState;
}
}
}
@@ -4,8 +4,6 @@ namespace QuestPDF.Drawing.Exceptions
{
public class DocumentLayoutException : Exception
{
public string ElementTrace { get; set; }
public DocumentLayoutException()
{
-10
View File
@@ -66,16 +66,6 @@ namespace QuestPDF.Drawing
}
public void Rotate(float angle)
{
}
public void Scale(float scaleX, float scaleY)
{
}
#endregion
}
}
+3 -3
View File
@@ -25,10 +25,10 @@ namespace QuestPDF.Drawing
public override void EndDocument()
{
Canvas?.Dispose();
Canvas.Dispose();
Document?.Close();
Document?.Dispose();
Document.Close();
Document.Dispose();
}
public override void BeginPage(Size size)
-45
View File
@@ -1,45 +0,0 @@
using System;
using QuestPDF.Infrastructure;
namespace QuestPDF.Drawing.Proxy
{
internal class CacheProxy : ElementProxy
{
public Size? AvailableSpace { get; set; }
public SpacePlan? MeasurementResult { get; set; }
public CacheProxy(Element child)
{
Child = child;
}
internal override SpacePlan Measure(Size availableSpace)
{
if (MeasurementResult != null &&
AvailableSpace != null &&
IsClose(AvailableSpace.Value.Width, availableSpace.Width) &&
IsClose(AvailableSpace.Value.Height, availableSpace.Height))
{
return MeasurementResult.Value;
}
AvailableSpace = availableSpace;
MeasurementResult = base.Measure(availableSpace);
return MeasurementResult.Value;
}
internal override void Draw(Size availableSpace)
{
AvailableSpace = null;
MeasurementResult = null;
base.Draw(availableSpace);
}
private bool IsClose(float x, float y)
{
return Math.Abs(x - y) < Size.Epsilon;
}
}
}
-14
View File
@@ -1,14 +0,0 @@
using System.Collections.Generic;
using QuestPDF.Infrastructure;
namespace QuestPDF.Drawing.Proxy
{
public class DebugStackItem
{
public IElement Element { get; internal set; }
public Size AvailableSpace { get; internal set; }
public SpacePlan SpacePlan { get; internal set; }
public ICollection<DebugStackItem> Stack { get; internal set; } = new List<DebugStackItem>();
}
}
-24
View File
@@ -1,24 +0,0 @@
using QuestPDF.Infrastructure;
namespace QuestPDF.Drawing.Proxy
{
internal class DebuggingProxy : ElementProxy
{
private DebuggingState DebuggingState { get; }
public DebuggingProxy(DebuggingState debuggingState, Element child)
{
DebuggingState = debuggingState;
Child = child;
}
internal override SpacePlan Measure(Size availableSpace)
{
DebuggingState.RegisterMeasure(Child, availableSpace);
var spacePlan = base.Measure(availableSpace);
DebuggingState.RegisterMeasureResult(Child, spacePlan);
return spacePlan;
}
}
}
-130
View File
@@ -1,130 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QuestPDF.Elements;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Drawing.Proxy
{
internal class DebuggingState
{
private DebugStackItem Root { get; set; }
private Stack<DebugStackItem> Stack { get; set; }
public DebuggingState()
{
Reset();
}
public void Reset()
{
Root = null;
Stack = new Stack<DebugStackItem>();
}
public void RegisterMeasure(IElement element, Size availableSpace)
{
if (element.GetType() == typeof(Container))
return;
var item = new DebugStackItem
{
Element = element,
AvailableSpace = availableSpace
};
Root ??= item;
if (Stack.Any())
Stack.Peek().Stack.Add(item);
Stack.Push(item);
}
public void RegisterMeasureResult(IElement element, SpacePlan spacePlan)
{
if (element.GetType() == typeof(Container))
return;
var item = Stack.Pop();
if (item.Element != element)
throw new Exception();
item.SpacePlan = spacePlan;
}
public string BuildTrace()
{
var builder = new StringBuilder();
var nestingLevel = 0;
Traverse(Root);
return builder.ToString();
void Traverse(DebugStackItem item)
{
var indent = new string(' ', nestingLevel * 4);
var title = item.Element.GetType().Name;
if (item.Element is DebugPointer debugPointer)
{
title = debugPointer.Target;
title += debugPointer.Highlight ? " 🌟" : string.Empty;
}
if (item.SpacePlan.Type == SpacePlanType.Wrap)
title = "🔥 " + title;
builder.AppendLine(indent + title);
builder.AppendLine(indent + new string('-', title.Length));
builder.AppendLine(indent + "Available space: " + item.AvailableSpace);
builder.AppendLine(indent + "Requested space: " + item.SpacePlan);
foreach (var configuration in GetElementConfiguration(item.Element))
builder.AppendLine(indent + configuration);
builder.AppendLine();
nestingLevel++;
item.Stack.ToList().ForEach(Traverse);
nestingLevel--;
}
static IEnumerable<string> GetElementConfiguration(IElement element)
{
if (element is DebugPointer)
return Enumerable.Empty<string>();
return element
.GetType()
.GetProperties()
.Select(x => new
{
Property = x.Name.PrettifyName(),
Value = x.GetValue(element)
})
.Where(x => !(x.Value is IElement))
.Where(x => !(x.Value is IEnumerable<IElement>))
.Where(x => !(x.Value is TextStyle))
.Select(x => $"{x.Property}: {FormatValue(x.Value)}");
string FormatValue(object value)
{
const int maxLength = 100;
var text = value?.ToString() ?? "-";
if (text.Length < maxLength)
return text;
return text.AsSpan(0, maxLength).ToString() + "...";
}
}
}
}
}
-9
View File
@@ -1,9 +0,0 @@
using QuestPDF.Infrastructure;
namespace QuestPDF.Drawing.Proxy
{
internal class ElementProxy : ContainerElement
{
}
}
-10
View File
@@ -51,15 +51,5 @@ namespace QuestPDF.Drawing
{
Canvas.DrawNamedDestinationAnnotation(new SKPoint(0, 0), locationName);
}
public void Rotate(float angle)
{
Canvas.RotateDegrees(angle);
}
public void Scale(float scaleX, float scaleY)
{
Canvas.Scale(scaleX, scaleY);
}
}
}
-42
View File
@@ -1,42 +0,0 @@
using System.Collections.Generic;
using QuestPDF.Infrastructure;
namespace QuestPDF.Drawing
{
public readonly struct SpacePlan
{
public readonly SpacePlanType Type;
public readonly float Width;
public readonly float Height;
internal SpacePlan(SpacePlanType type, float width, float height)
{
Type = type;
Width = width;
Height = height;
}
internal static SpacePlan Wrap() => new SpacePlan(SpacePlanType.Wrap, 0, 0);
internal static SpacePlan PartialRender(float width, float height) => new SpacePlan(SpacePlanType.PartialRender, width, height);
internal static SpacePlan PartialRender(Size size) => PartialRender(size.Width, size.Height);
internal static SpacePlan FullRender(float width, float height) => new SpacePlan(SpacePlanType.FullRender, width, height);
internal static SpacePlan FullRender(Size size) => FullRender(size.Width, size.Height);
public override string ToString()
{
if (Type == SpacePlanType.Wrap)
return Type.ToString();
return $"{Type} | width {Width:N2} | height {Height:N2}";
}
public static implicit operator Size(SpacePlan spacePlan)
{
return new Size(spacePlan.Width, spacePlan.Height);
}
}
}
+19
View File
@@ -0,0 +1,19 @@
using QuestPDF.Infrastructure;
namespace QuestPDF.Drawing.SpacePlan
{
internal class FullRender : Size, ISpacePlan
{
public FullRender(Size size) : this(size.Width, size.Height)
{
}
public FullRender(float width, float height) : base(width, height)
{
}
public override string ToString() => $"FullRender {base.ToString()}";
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace QuestPDF.Drawing.SpacePlan
{
internal interface ISpacePlan
{
}
}
@@ -0,0 +1,19 @@
using QuestPDF.Infrastructure;
namespace QuestPDF.Drawing.SpacePlan
{
internal class PartialRender : Size, ISpacePlan
{
public PartialRender(Size size) : this(size.Width, size.Height)
{
}
public PartialRender(float width, float height) : base(width, height)
{
}
public override string ToString() => $"PartialRender {base.ToString()}";
}
}
@@ -1,4 +1,4 @@
namespace QuestPDF.Drawing
namespace QuestPDF.Drawing.SpacePlan
{
internal struct TextMeasurement
{
+13
View File
@@ -0,0 +1,13 @@
namespace QuestPDF.Drawing.SpacePlan
{
internal class TextRender : FullRender
{
public float Ascent { get; set; }
public float Descent { get; set; }
public TextRender(float width, float height) : base(width, height)
{
}
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace QuestPDF.Drawing.SpacePlan
{
internal class Wrap : ISpacePlan
{
public override string ToString() => "Wrap";
}
}
-9
View File
@@ -1,9 +0,0 @@
namespace QuestPDF.Drawing
{
public enum SpacePlanType
{
Wrap,
PartialRender,
FullRender
}
}
+3 -4
View File
@@ -1,5 +1,4 @@
using System;
using QuestPDF.Drawing;
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
@@ -14,16 +13,16 @@ namespace QuestPDF.Elements
if (Child == null)
return;
var childSize = base.Measure(availableSpace);
var childSize = Child.Measure(availableSpace) as Size;
if (childSize.Type == SpacePlanType.Wrap)
if (childSize == null)
return;
var top = GetTopOffset(availableSpace, childSize);
var left = GetLeftOffset(availableSpace, childSize);
Canvas.Translate(new Position(left, top));
base.Draw(childSize);
Child.Draw(childSize);
Canvas.Translate(new Position(-left, -top));
}
+14 -14
View File
@@ -1,37 +1,37 @@
using System;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
{
internal class AspectRatio : ContainerElement, ICacheable
internal class AspectRatio : ContainerElement
{
public float Ratio { get; set; } = 1;
public AspectRatioOption Option { get; set; } = AspectRatioOption.FitWidth;
internal override SpacePlan Measure(Size availableSpace)
internal override ISpacePlan Measure(Size availableSpace)
{
if(Child == null)
return SpacePlan.FullRender(0, 0);
return new FullRender(Size.Zero);
var targetSize = GetTargetSize(availableSpace);
if (targetSize.Height > availableSpace.Height + Size.Epsilon)
return SpacePlan.Wrap();
return new Wrap();
if (targetSize.Width > availableSpace.Width + Size.Epsilon)
return SpacePlan.Wrap();
return new Wrap();
var childSize = base.Measure(targetSize);
var childSize = Child.Measure(targetSize);
if (childSize.Type == SpacePlanType.Wrap)
return SpacePlan.Wrap();
if (childSize is Wrap)
return new Wrap();
if (childSize.Type == SpacePlanType.PartialRender)
return SpacePlan.PartialRender(targetSize);
if (childSize is PartialRender)
return new PartialRender(targetSize);
if (childSize.Type == SpacePlanType.FullRender)
return SpacePlan.FullRender(targetSize);
if (childSize is FullRender)
return new FullRender(targetSize);
throw new NotSupportedException();
}
@@ -42,7 +42,7 @@ namespace QuestPDF.Elements
return;
var size = GetTargetSize(availableSpace);
base.Draw(size);
Child?.Draw(size);
}
private Size GetTargetSize(Size availableSpace)
+1 -1
View File
@@ -10,7 +10,7 @@ namespace QuestPDF.Elements
internal override void Draw(Size availableSpace)
{
Canvas.DrawRectangle(Position.Zero, availableSpace, Color);
base.Draw(availableSpace);
Child?.Draw(availableSpace);
}
}
}
+1 -6
View File
@@ -14,7 +14,7 @@ namespace QuestPDF.Elements
internal override void Draw(Size availableSpace)
{
base.Draw(availableSpace);
Child?.Draw(availableSpace);
Canvas.DrawRectangle(
new Position(-Left/2, -Top/2),
@@ -36,10 +36,5 @@ namespace QuestPDF.Elements
new Size(Right, availableSpace.Height + Top/2 + Bottom/2),
Color);
}
public override string ToString()
{
return $"Border: Top({Top}) Right({Right}) Bottom({Bottom}) Left({Left}) Color({Color})";
}
}
}
+4 -5
View File
@@ -1,5 +1,4 @@
using QuestPDF.Drawing;
using QuestPDF.Infrastructure;
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
{
@@ -7,12 +6,12 @@ namespace QuestPDF.Elements
{
internal override void Draw(Size availableSpace)
{
var targetSize = base.Measure(availableSpace);
var targetSize = Child?.Measure(availableSpace) as Size;
if (targetSize.Type == SpacePlanType.Wrap)
if (targetSize == null)
return;
base.Draw(targetSize);
Child?.Draw(targetSize);
}
}
}
+4 -4
View File
@@ -1,4 +1,4 @@
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Infrastructure;
using SkiaSharp;
@@ -6,13 +6,13 @@ namespace QuestPDF.Elements
{
public delegate void DrawOnCanvas(SKCanvas canvas, Size availableSpace);
internal class Canvas : Element, ICacheable
internal class Canvas : Element
{
public DrawOnCanvas Handler { get; set; }
internal override SpacePlan Measure(Size availableSpace)
internal override ISpacePlan Measure(Size availableSpace)
{
return SpacePlan.FullRender(availableSpace);
return new FullRender(availableSpace);
}
internal override void Draw(Size availableSpace)
+29 -25
View File
@@ -1,44 +1,45 @@
using System;
using System.Linq;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
{
internal class Constrained : ContainerElement, ICacheable
internal class Constrained : ContainerElement
{
public float? MinWidth { get; set; }
public float? MaxWidth { get; set; }
public float? MinHeight { get; set; }
public float? MaxHeight { get; set; }
internal override SpacePlan Measure(Size availableSpace)
internal override ISpacePlan Measure(Size availableSpace)
{
if (MinWidth > availableSpace.Width + Size.Epsilon)
return SpacePlan.Wrap();
return new Wrap();
if (MinHeight > availableSpace.Height + Size.Epsilon)
return SpacePlan.Wrap();
return new Wrap();
var available = new Size(
LimitMin(availableSpace.Width, MaxWidth),
LimitMin(availableSpace.Height, MaxHeight));
MathHelpers.Min(MaxWidth, availableSpace.Width),
MathHelpers.Min(MaxHeight, availableSpace.Height));
var measurement = base.Measure(available);
var measurement = Child?.Measure(available) ?? new FullRender(Size.Zero);
var size = measurement as Size;
if (measurement.Type == SpacePlanType.Wrap)
return SpacePlan.Wrap();
if (measurement is Wrap)
return new Wrap();
var actualSize = new Size(
LimitMax(measurement.Width, MinWidth),
LimitMax(measurement.Height, MinHeight));
MathHelpers.Max(MinWidth, size.Width),
MathHelpers.Max(MinHeight, size.Height));
if (measurement.Type == SpacePlanType.FullRender)
return SpacePlan.FullRender(actualSize);
if (size is FullRender)
return new FullRender(actualSize);
if (measurement.Type == SpacePlanType.PartialRender)
return SpacePlan.PartialRender(actualSize);
if (size is PartialRender)
return new PartialRender(actualSize);
throw new NotSupportedException();
}
@@ -46,20 +47,23 @@ namespace QuestPDF.Elements
internal override void Draw(Size availableSpace)
{
var available = new Size(
LimitMin(availableSpace.Width, MaxWidth),
LimitMin(availableSpace.Height, MaxHeight));
MathHelpers.Min(MaxWidth, availableSpace.Width),
MathHelpers.Min(MaxHeight, availableSpace.Height));
base.Draw(available);
Child?.Draw(available);
}
private float LimitMin(float value, float? limit)
}
static class MathHelpers
{
public static float Min(params float?[] values)
{
return limit.HasValue ? Math.Min(value, limit.Value) : value;
return values.Where(x => x.HasValue).Min().Value;
}
private float LimitMax(float value, float? limit)
public static float Max(params float?[] values)
{
return limit.HasValue ? Math.Max(value, limit.Value) : value;
return values.Where(x => x.HasValue).Max().Value;
}
}
}
@@ -5,7 +5,7 @@ using SkiaSharp;
namespace QuestPDF.Elements
{
internal class DebugArea : IComponent
internal class Debug : IComponent
{
public IElement? Child { get; set; }
@@ -30,7 +30,7 @@ namespace QuestPDF.Elements
.Box()
.Background(Colors.White)
.Padding(2)
.Text(Text, TextStyle.Default.Color(Color).FontType(Fonts.Consolas).Size(8));
.Text(Text, TextStyle.Default.Color(Color).FontType("Consolas").Size(8));
});
}
}
-10
View File
@@ -1,10 +0,0 @@
using System.ComponentModel;
namespace QuestPDF.Elements
{
internal class DebugPointer : Container
{
public string Target { get; set; }
public bool Highlight { get; set; }
}
}
+18 -24
View File
@@ -1,5 +1,5 @@
using System;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
@@ -11,7 +11,7 @@ namespace QuestPDF.Elements
Append
}
internal class BinaryDecoration : Element, ICacheable
internal class SimpleDecoration : Element
{
public Element DecorationElement { get; set; } = Empty.Instance;
public Element ContentElement { get; set; } = Empty.Instance;
@@ -25,40 +25,34 @@ namespace QuestPDF.Elements
base.HandleVisitor(visit);
}
internal override void CreateProxy(Func<Element, Element> create)
internal override ISpacePlan Measure(Size availableSpace)
{
DecorationElement = create(DecorationElement);
ContentElement = create(ContentElement);
}
internal override SpacePlan Measure(Size availableSpace)
{
var decorationMeasure = DecorationElement.Measure(availableSpace);
var decorationMeasure = DecorationElement?.Measure(availableSpace);
if (decorationMeasure.Type == SpacePlanType.Wrap || decorationMeasure.Type == SpacePlanType.PartialRender)
return SpacePlan.Wrap();
if (decorationMeasure is Wrap || decorationMeasure is PartialRender)
return new Wrap();
var decorationSize = decorationMeasure;
var contentMeasure = ContentElement.Measure(new Size(availableSpace.Width, availableSpace.Height - decorationSize.Height));
var decorationSize = decorationMeasure as Size ?? Size.Zero;
var contentMeasure = ContentElement?.Measure(new Size(availableSpace.Width, availableSpace.Height - decorationSize.Height)) ?? new FullRender(Size.Zero);
if (contentMeasure.Type == SpacePlanType.Wrap)
return SpacePlan.Wrap();
if (contentMeasure is Wrap)
return new Wrap();
var contentSize = contentMeasure;
var contentSize = contentMeasure as Size ?? Size.Zero;
var resultSize = new Size(availableSpace.Width, decorationSize.Height + contentSize.Height);
if (contentSize.Type == SpacePlanType.PartialRender)
return SpacePlan.PartialRender(resultSize);
if (contentSize is PartialRender)
return new PartialRender(resultSize);
if (contentSize.Type == SpacePlanType.FullRender)
return SpacePlan.FullRender(resultSize);
if (contentSize is FullRender)
return new FullRender(resultSize);
throw new NotSupportedException();
}
internal override void Draw(Size availableSpace)
{
var decorationSize = DecorationElement.Measure(availableSpace);
var decorationSize = DecorationElement?.Measure(availableSpace) as Size ?? Size.Zero;
var contentSize = new Size(availableSpace.Width, availableSpace.Height - decorationSize.Height);
var translateHeight = Type == DecorationType.Prepend ? decorationSize.Height : contentSize.Height;
@@ -83,11 +77,11 @@ namespace QuestPDF.Elements
public void Compose(IContainer container)
{
container.Element(new BinaryDecoration
container.Element(new SimpleDecoration
{
Type = DecorationType.Prepend,
DecorationElement = Header,
ContentElement = new BinaryDecoration
ContentElement = new SimpleDecoration
{
Type = DecorationType.Append,
ContentElement = Content,
-120
View File
@@ -1,120 +0,0 @@
using System;
using QuestPDF.Drawing;
using QuestPDF.Drawing.Exceptions;
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
{
internal class DynamicHost : Element, IStateResettable
{
private IDynamicComponent Child { get; }
public DynamicHost(IDynamicComponent child)
{
Child = child;
}
public void ResetState()
{
GetContent(Size.Zero, DynamicLayoutOperation.Reset);
}
internal override SpacePlan Measure(Size availableSpace)
{
var content = GetContent(availableSpace, DynamicLayoutOperation.Measure);
var measurement = content.Measure(availableSpace);
if (measurement.Type != SpacePlanType.FullRender)
throw new DocumentLayoutException("Dynamic component generated content that does not fit on a single page.");
return content.HasMoreContent
? SpacePlan.PartialRender(measurement)
: SpacePlan.FullRender(measurement);
}
internal override void Draw(Size availableSpace)
{
GetContent(availableSpace, DynamicLayoutOperation.Draw).Draw(availableSpace);
}
DynamicContainer GetContent(Size availableSize, DynamicLayoutOperation operation)
{
var context = new DynamicContext
{
PageNumber = PageContext.GetLocationPage(Infrastructure.PageContext.CurrentPageSlot),
PageContext = PageContext,
Canvas = Canvas,
AvailableSize = availableSize,
Operation = operation
};
var container = new DynamicContainer();
Child.Compose(context, container);
container.HandleVisitor(x => x?.Initialize(PageContext, Canvas));
container.HandleVisitor(x => (x as IStateResettable)?.ResetState());
return container;
}
}
public enum DynamicLayoutOperation
{
Reset,
Measure,
Draw
}
public class DynamicContext
{
internal IPageContext PageContext { get; set; }
internal ICanvas Canvas { get; set; }
public int PageNumber { get; internal set; }
public Size AvailableSize { get; internal set; }
public DynamicLayoutOperation Operation { get; internal set; }
public IDynamicElement CreateElement(Action<IContainer> content)
{
var container = new DynamicElement();
content(container);
container.HandleVisitor(x => x?.Initialize(PageContext, Canvas));
container.HandleVisitor(x => (x as IStateResettable)?.ResetState());
container.Size = container.Measure(AvailableSize);
return container;
}
}
public interface IDynamicContainer : IContainer
{
}
internal class DynamicContainer : Container, IDynamicContainer
{
internal bool HasMoreContent { get; set; }
}
public static class DynamicContainerExtensions
{
public static IDynamicContainer HasMoreContent(this IDynamicContainer container)
{
(container as DynamicContainer).HasMoreContent = true;
return container;
}
}
public interface IDynamicElement : IElement
{
Size Size { get; }
}
internal class DynamicElement : ContainerElement, IDynamicElement
{
public Size Size { get; internal set; }
}
}
+3 -3
View File
@@ -1,5 +1,5 @@
using System;
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Infrastructure;
using SkiaSharp;
@@ -9,9 +9,9 @@ namespace QuestPDF.Elements
{
public Func<Size, byte[]>? Source { get; set; }
internal override SpacePlan Measure(Size availableSpace)
internal override ISpacePlan Measure(Size availableSpace)
{
return SpacePlan.FullRender(availableSpace.Width, availableSpace.Height);
return new FullRender(availableSpace.Width, availableSpace.Height);
}
internal override void Draw(Size availableSpace)
+3 -3
View File
@@ -1,4 +1,4 @@
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
@@ -7,9 +7,9 @@ namespace QuestPDF.Elements
{
internal static Empty Instance { get; } = new Empty();
internal override SpacePlan Measure(Size availableSpace)
internal override ISpacePlan Measure(Size availableSpace)
{
return SpacePlan.FullRender(0, 0);
return new FullRender(Size.Zero);
}
internal override void Draw(Size availableSpace)
+5 -5
View File
@@ -1,19 +1,19 @@
using QuestPDF.Drawing;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
{
internal class EnsureSpace : ContainerElement, ICacheable
internal class EnsureSpace : ContainerElement
{
public const float DefaultMinHeight = 150;
public float MinHeight { get; set; } = DefaultMinHeight;
internal override SpacePlan Measure(Size availableSpace)
internal override ISpacePlan Measure(Size availableSpace)
{
var measurement = base.Measure(availableSpace);
if (measurement.Type == SpacePlanType.PartialRender && availableSpace.Height < MinHeight)
return SpacePlan.Wrap();
if (measurement is PartialRender && availableSpace.Height < MinHeight)
return new Wrap();
return measurement;
}

Some files were not shown because too many files have changed in this diff Show More