Compare commits

..

2 Commits

Author SHA1 Message Date
Marcin Ziąbek 9f927ec402 Updated package version + added release notes 2021-04-03 00:53:09 +02:00
MarcinZiabek 9dc3e2b533 Updated tests for the Constrained element 2021-03-28 17:43:52 +02:00
555 changed files with 2684 additions and 20280 deletions
-70
View File
@@ -1,70 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '22 16 * * 5'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'csharp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
-32
View File
@@ -1,32 +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 BarcodeExamples
{
[Test]
public void Example()
{
FontManager.RegisterFontType("LibreBarcode39", File.OpenRead("LibreBarcode39-Regular.ttf"));
RenderingTest
.Create()
.PageSize(400, 100)
.ShowResults()
.Render(container =>
{
container
.Background(Colors.White)
.AlignCenter()
.AlignMiddle()
.Text("*QuestPDF*", TextStyle.Default.FontType("LibreBarcode39").Size(64));
});
}
}
}
-57
View File
@@ -1,57 +0,0 @@
using Microcharts;
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using SkiaSharp;
namespace QuestPDF.Examples
{
public class CanvasExamples
{
[Test]
public void BorderRadius()
{
RenderingTest
.Create()
.PageSize(175, 100)
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Background(Colors.Grey.Lighten2)
.Padding(25)
.MinimalBox()
.Layers(layers =>
{
layers.Layer().Canvas((canvas, size) =>
{
DrawRoundedRectangle(Colors.White, false);
DrawRoundedRectangle(Colors.Blue.Darken2, true);
void DrawRoundedRectangle(string color, bool isStroke)
{
using var paint = new SKPaint
{
Color = SKColor.Parse(color),
IsStroke = isStroke,
StrokeWidth = 2,
IsAntialias = true
};
canvas.DrawRoundRect(0, 0, size.Width, size.Height, 20, 20, paint);
}
});
layers
.PrimaryLayer()
.PaddingVertical(10)
.PaddingHorizontal(20)
.Text("Sample text", TextStyle.Default.Size(16).Color(Colors.Blue.Darken2).SemiBold());
});
});
}
}
}
-85
View File
@@ -1,85 +0,0 @@
using System.Linq;
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using Microcharts;
using SkiaSharp;
namespace QuestPDF.Examples
{
public class ChartExample
{
[Test]
public void MicrochartChart()
{
var entries = new[]
{
new ChartEntry(212)
{
Label = "UWP",
ValueLabel = "112",
Color = SKColor.Parse("#2c3e50")
},
new ChartEntry(248)
{
Label = "Android",
ValueLabel = "648",
Color = SKColor.Parse("#77d065")
},
new ChartEntry(128)
{
Label = "iOS",
ValueLabel = "428",
Color = SKColor.Parse("#b455b6")
},
new ChartEntry(514)
{
Label = "Forms",
ValueLabel = "214",
Color = SKColor.Parse("#3498db")
}
};
RenderingTest
.Create()
.PageSize(400, 600)
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Background(Colors.White)
.Padding(25)
.Stack(stack =>
{
stack
.Item()
.PaddingBottom(10)
.Text("Chart example", TextStyle.Default.Size(20).SemiBold().Color(Colors.Blue.Medium));
stack
.Item()
.Border(1)
.ExtendHorizontal()
.Height(300)
.Canvas((canvas, size) =>
{
var chart = new BarChart
{
Entries = entries,
LabelOrientation = Orientation.Horizontal,
ValueLabelOrientation = Orientation.Horizontal,
IsAnimated = false,
};
chart.DrawContent(canvas, (int)size.Width, (int)size.Height);
});
});
});
}
}
}
@@ -1,56 +0,0 @@
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
public class ComplexLayoutBenchmark
{
[Test]
public void ComplexLayout()
{
RenderingTest
.Create()
.PageSize(PageSizes.A4)
.ProducePdf()
.ShowResults()
.Render(x => GenerateStructure(x, 16));
}
private void GenerateStructure(IContainer container, int level)
{
if (level <= 0)
{
container.Background(Placeholders.BackgroundColor()).Height(10);
return;
}
level--;
if (level % 3 == 0)
{
container
.Border(level / 4f)
.BorderColor(Colors.Black)
.Row(row =>
{
row.RelativeColumn().Element(x => GenerateStructure(x, level));
row.RelativeColumn().Element(x => GenerateStructure(x, level));
});
}
else
{
container
.Border(level / 4f)
.BorderColor(Colors.Black)
.Stack(stack =>
{
stack.Item().Element(x => GenerateStructure(x, level));
stack.Item().Element(x => GenerateStructure(x, level));
});
}
}
}
}
-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);
}
}
}
-76
View File
@@ -1,76 +0,0 @@
using NUnit.Framework;
using QuestPDF.Drawing.Exceptions;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
namespace QuestPDF.Examples
{
public class DebuggingTesting
{
[Test]
public void Stack()
{
Assert.Throws<DocumentLayoutException>(() =>
{
RenderingTest
.Create()
.PageSize(500, 360)
.Render(container =>
{
container
.Padding(10)
.Width(100)
.Background(Colors.Grey.Lighten3)
.DebugPointer("Example debug pointer")
.Stack(x =>
{
x.Item().Text("Test");
x.Item().Width(150);
});
});
});
}
[Test]
public void Simple()
{
Assert.Throws<DocumentLayoutException>(() =>
{
RenderingTest
.Create()
.PageSize(500, 360)
.Render(container =>
{
container
.Padding(10)
.Width(100)
.Background(Colors.Grey.Lighten3)
.Width(150)
.Text("Test");
});
});
}
[Test]
public void DebugPointer()
{
Assert.Throws<DocumentLayoutException>(() =>
{
RenderingTest
.Create()
.PageSize(500, 360)
.Render(container =>
{
container
.Background(Colors.Grey.Lighten3)
.Padding(10)
.Width(100)
.DebugPointer("Example debug pointer")
.Width(150)
.Text("Example");
});
});
}
}
}
@@ -1,48 +0,0 @@
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
public class DefaultTextStyleExample
{
[Test]
public void DefaultTextStyle()
{
RenderingTest
.Create()
.ProduceImages()
.ShowResults()
.RenderDocument(container =>
{
container.Page(page =>
{
// all text in this set of pages has size 20
page.DefaultTextStyle(TextStyle.Default.Size(20));
page.Margin(20);
page.Size(PageSizes.A4);
page.Background(Colors.White);
page.Content().Stack(stack =>
{
stack.Item().Text(Placeholders.Sentence());
stack.Item().Text(text =>
{
// text in this block is additionally semibold
text.DefaultTextStyle(TextStyle.Default.SemiBold());
text.Line(Placeholders.Sentence());
// this text has size 20 but also semibold and red
text.Span(Placeholders.Sentence(), TextStyle.Default.Color(Colors.Red.Medium));
});
});
});
});
}
}
}
@@ -1,53 +0,0 @@
using System.Drawing;
using System.Linq;
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
public class DefaultTextStyleExamples
{
[Test]
public void Placeholder()
{
RenderingTest
.Create()
.PageSize(220, 270)
.ProduceImages()
.ShowResults()
.EnableDebugging()
.Render(container =>
{
container
.Padding(10)
.DefaultTextStyle(TextStyle.Default.Bold().Underline())
.Stack(stack =>
{
stack.Item().Text("Default style applies to all children", TextStyle.Default);
stack.Item().Text("You can override certain styles", TextStyle.Default.Underline(false).Color(Colors.Green.Darken2));
stack.Item().PaddingTop(10).Border(1).Grid(grid =>
{
grid.Columns(4);
foreach (var i in Enumerable.Range(1, 16))
{
grid.Item()
.Border(1)
.BorderColor(Colors.Grey.Lighten1)
.Background(Colors.Grey.Lighten3)
.Width(50)
.Height(50)
.AlignCenter()
.AlignMiddle()
.Text(i, TextStyle.Default.Size(16 + i / 4));
}
});
});
});
}
}
}
@@ -1,55 +0,0 @@
using System.Linq;
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
public class DifferentHeaderOnFirstPageExample
{
[Test]
public void Placeholder()
{
RenderingTest
.Create()
.PageSize(PageSizes.A6)
.ProduceImages()
.ShowResults()
.EnableDebugging()
.RenderDocument(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A6);
page.Margin(30);
page.Background(Colors.White);
page.Header().Stack(stack =>
{
stack.Item().ShowOnce().Background(Colors.Blue.Lighten2).Height(60);
stack.Item().SkipOnce().Background(Colors.Green.Lighten2).Height(40);
});
page.Content().PaddingVertical(10).Stack(stack =>
{
stack.Spacing(10);
foreach (var _ in Enumerable.Range(0, 13))
stack.Item().Background(Colors.Grey.Lighten2).Height(40);
});
page.Footer().AlignCenter().Text(text =>
{
text.DefaultTextStyle(TextStyle.Default.Size(16));
text.CurrentPageNumber();
text.Span(" / ");
text.TotalPages();
});
});
});
}
}
}
+123 -788
View File
@@ -1,835 +1,170 @@
using System.Linq;
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using SkiaSharp;
namespace QuestPDF.Examples
{
[TestFixture]
public class ElementExamples
public class ElementExamples : ExampleTestBase
{
[Test]
public void Placeholder()
//[ShowResult]
[ImageSize(200, 150)]
public void Placeholder(IContainer container)
{
RenderingTest
.Create()
.PageSize(200, 150)
.Render(container =>
{
container
.Background("#FFF")
.Padding(25)
.Placeholder();
});
container
.Background("#FFF")
.Padding(25)
.Placeholder();
}
[Test]
public void Decoration()
//[ShowResult]
[ImageSize(300, 300)]
public void Section(IContainer container)
{
RenderingTest
.Create()
.PageSize(300, 300)
.Render(container =>
container
.Background("#FFF")
.Padding(25)
.Section(section =>
{
container
.Background("#FFF")
.Padding(25)
.Decoration(decoration =>
{
decoration
.Header()
.Background(Colors.Grey.Medium)
.Padding(10)
.Text("Notes", TextStyle.Default.Size(16).Color("#FFF"));
decoration
.Content()
.Background(Colors.Grey.Lighten3)
.Padding(10)
.ExtendVertical()
.Text(Helpers.Placeholders.LoremIpsum());
});
});
}
[Test]
public void Row()
{
RenderingTest
.Create()
.PageSize(740, 200)
.Render(container =>
{
container
.Background("#FFF")
.Padding(20)
.Stack(stack =>
{
stack.Item()
.PaddingBottom(10)
.AlignCenter()
.Text("This Row element is 700pt wide");
stack.Item().Row(row =>
{
row.ConstantColumn(100)
.Background(Colors.Grey.Lighten1)
.Padding(10)
.ExtendVertical()
.Text("This column is 100 pt wide");
row.RelativeColumn()
.Background(Colors.Grey.Lighten2)
.Padding(10)
.Text("This column takes 1/3 of the available space (200pt)");
row.RelativeColumn(2)
.Background(Colors.Grey.Lighten3)
.Padding(10)
.Text("This column takes 2/3 of the available space (400pt)");
});
});
});
}
[Test]
public void RowSpacing()
{
RenderingTest
.Create()
.PageSize(740, 200)
.Render(container =>
{
container
.Background("#FFF")
.Padding(20)
.Row(row =>
{
row.Spacing(20);
row.RelativeColumn(2).Border(1).Background(Colors.Grey.Lighten1);
row.RelativeColumn(3).Border(1).Background(Colors.Grey.Lighten2);
row.RelativeColumn(4).Border(1).Background(Colors.Grey.Lighten3);
});
});
}
[Test]
public void Stack()
{
RenderingTest
.Create()
.PageSize(500, 360)
.Render(container =>
{
container
.Background("#FFF")
.Padding(15)
.Stack(stack =>
{
stack.Spacing(15);
stack.Item().Background(Colors.Grey.Medium).Height(50);
stack.Item().Background(Colors.Grey.Lighten1).Height(100);
stack.Item().Background(Colors.Grey.Lighten2).Height(150);
});
});
}
[Test]
public void Debug()
{
RenderingTest
.Create()
.PageSize(210, 210)
.Render(container =>
{
container
.Padding(25)
.DebugArea("Grid example", Colors.Blue.Medium)
.Grid(grid =>
{
grid.Columns(3);
grid.Spacing(5);
foreach (var _ in Enumerable.Range(0, 8))
grid.Item().Height(50).Placeholder();
});
});
}
[Test]
public void ElementEnd()
{
RenderingTest
.Create()
.PageSize(300, 200)
.Render(container =>
{
var text = "";
container
section
.Header()
.Background("#888")
.Padding(10)
.Element(x =>
{
if (string.IsNullOrWhiteSpace(text))
x.Height(10).Width(50).Background("#DDD");
else
x.Text(text);
});
});
}
[Test]
public void GridExample()
{
RenderingTest
.Create()
.PageSize(400, 230)
.Render(container =>
{
var textStyle = TextStyle.Default.Size(14);
container
.Padding(15)
.AlignRight()
.Grid(grid =>
{
grid.VerticalSpacing(10);
grid.HorizontalSpacing(10);
grid.AlignCenter();
grid.Columns(10); // 12 by default
grid.Item(6).Background(Colors.Blue.Lighten1).Height(50);
grid.Item(4).Background(Colors.Blue.Lighten3).Height(50);
.Text("Notes", TextStyle.Default.Size(16).Color("#FFF"));
grid.Item(2).Background(Colors.Teal.Lighten1).Height(70);
grid.Item(3).Background(Colors.Teal.Lighten2).Height(70);
grid.Item(5).Background(Colors.Teal.Lighten3).Height(70);
grid.Item(2).Background(Colors.Green.Lighten1).Height(50);
grid.Item(2).Background(Colors.Green.Lighten2).Height(50);
grid.Item(2).Background(Colors.Green.Lighten3).Height(50);
});
});
}
[Test]
public void Canvas()
{
RenderingTest
.Create()
.PageSize(300, 200)
.Render(container =>
{
container
.Background("#FFF")
.Padding(25)
.Canvas((canvas, size) =>
{
using var paint = new SKPaint
{
Color = SKColors.Red,
StrokeWidth = 10,
IsStroke = true
};
// move origin to the center of the available space
canvas.Translate(size.Width / 2, size.Height / 2);
// draw a circle
canvas.DrawCircle(0, 0, 50, paint);
});
});
}
[Test]
public void LayersExample()
{
RenderingTest
.Create()
.PageSize(400, 250)
.Render(container =>
{
container
.Padding(25)
.Layers(layers =>
{
// layer below main content
layers
.Layer()
.Height(100)
.Width(100)
.Background(Colors.Grey.Lighten3);
layers
.PrimaryLayer()
.Padding(25)
.Stack(stack =>
{
stack.Spacing(5);
foreach (var _ in Enumerable.Range(0, 7))
stack.Item().Text(Placeholders.Sentence());
});
// layer above the main content
layers
.Layer()
.AlignCenter()
.AlignMiddle()
.Text("Watermark", TextStyle.Default.Size(48).Bold().Color(Colors.Green.Lighten3));
layers
.Layer()
.AlignBottom()
.Text(text => text.CurrentPageNumber(TextStyle.Default.Size(16).Color(Colors.Green.Medium)));
});
});
}
// [Test]
// public void EnsureSpace()
// {
// RenderingTest
// .Create()
// .PageSize(300, 400)
// .Render(container =>
// {
// container
// .Padding(50)
// .Page(page =>
// {
// page.Header().PageNumber("Page {pdf:currentPage}");
//
// page.Content().Height(300).Stack(content =>
// {
// content.Item().Height(200).Background(Colors.Grey.Lighten2);
//
// content.Item().EnsureSpace(100).Stack(stack =>
// {
// stack.Spacing(10);
//
// foreach (var _ in Enumerable.Range(0, 4))
// stack.Item().Height(50).Background(Colors.Green.Lighten1);
// });
// });
// });
// });
// }
[Test]
public void RandomColorMatrix()
{
RenderingTest
.Create()
.PageSize(300, 300)
.Render(container =>
{
container
.Padding(25)
.Grid(grid =>
{
grid.Columns(5);
Enumerable
.Range(0, 25)
.Select(x => Placeholders.BackgroundColor())
.ToList()
.ForEach(x => grid.Item().Height(50).Background(x));
});
});
}
[Test]
public void DefinedColors()
{
var colors = new[]
{
Colors.Green.Darken4,
Colors.Green.Darken3,
Colors.Green.Darken2,
Colors.Green.Darken1,
Colors.Green.Medium,
Colors.Green.Lighten1,
Colors.Green.Lighten2,
Colors.Green.Lighten3,
Colors.Green.Lighten4,
Colors.Green.Lighten5,
Colors.Green.Accent1,
Colors.Green.Accent2,
Colors.Green.Accent3,
Colors.Green.Accent4,
};
RenderingTest
.Create()
.PageSize(450, 150)
.Render(container =>
{
container
.Padding(25)
.Height(100)
.Row(row =>
{
foreach (var color in colors)
row.RelativeColumn().Background(color);
});
});
}
[Test]
public void DefinedFonts()
{
var fonts = new[]
{
Fonts.Calibri,
Fonts.Candara,
Fonts.Arial,
Fonts.TimesNewRoman,
Fonts.Consolas,
Fonts.Tahoma,
Fonts.Impact,
Fonts.Trebuchet,
Fonts.ComicSans
};
RenderingTest
.Create()
.PageSize(500, 175)
.Render(container =>
{
container
.Padding(25)
.Grid(grid =>
{
grid.Columns(3);
foreach (var font in fonts)
{
grid.Item()
.Border(1)
.BorderColor(Colors.Grey.Medium)
.Padding(10)
.Text(font, TextStyle.Default.FontType(font).Size(16));
}
});
});
}
[Test]
public void Layers()
{
RenderingTest
.Create()
.PageSize(300, 300)
.Render(container =>
{
container
.Background("#FFF")
.Padding(25)
.Layers(layers =>
{
layers.Layer().Text("Something else");
layers.PrimaryLayer().Stack(stack =>
{
stack.Item().PaddingTop(20).Text("Text 1");
stack.Item().PaddingTop(40).Text("Text 2");
});
layers.Layer().Canvas((canvas, size) =>
{
using var paint = new SKPaint
{
Color = SKColors.Red,
StrokeWidth = 5
};
canvas.Translate(size.Width / 2, size.Height / 2);
canvas.DrawCircle(0, 0, 50, paint);
});
layers.Layer().Background("#8F00").Extend();
layers.Layer().PaddingTop(40).Text("It works!", TextStyle.Default.Size(24));
});
});
}
[Test]
public void Box()
{
RenderingTest
.Create()
.PageSize(300, 150)
.Render(container =>
{
container
.Background("#FFF")
.Padding(15)
.Border(4)
.BorderColor(Colors.Blue.Medium)
//.MinimalBox()
.Background(Colors.Grey.Lighten2)
.Padding(15)
.Text("Test of the \n box element", TextStyle.Default.Size(20));
});
}
[Test]
public void Scale()
{
RenderingTest
.Create()
.PageSize(300, 175)
.Render(container =>
{
container
.Background(Colors.White)
section
.Content()
.Background("#DDD")
.Padding(10)
.Decoration(decoration =>
{
var headerFontStyle = TextStyle
.Default
.Size(20)
.Color(Colors.Blue.Darken2)
.SemiBold();
decoration
.Header()
.PaddingBottom(10)
.Text("Example: scale component", headerFontStyle);
decoration
.Content()
.Stack(stack =>
{
var scales = new[] { 0.8f, 0.9f, 1.1f, 1.2f };
foreach (var scale in scales)
{
var fontColor = scale <= 1f
? Colors.Red.Lighten4
: Colors.Green.Lighten4;
var fontStyle = TextStyle.Default.Size(16);
stack
.Item()
.Border(1)
.Background(fontColor)
.Scale(scale)
.Padding(5)
.Text($"Content with {scale} scale.", fontStyle);
}
});
});
});
}
[Test]
public void Translate()
{
RenderingTest
.Create()
.PageSize(300, 200)
.Render(container =>
{
container
.Background("#FFF")
.MinimalBox()
.Padding(25)
.Background(Colors.Green.Lighten3)
.TranslateX(15)
.TranslateY(15)
.Border(2)
.BorderColor(Colors.Green.Darken1)
.Padding(50)
.Text("Moved text", TextStyle.Default.Size(25));
});
}
[Test]
public void ConstrainedRotate()
{
RenderingTest
.Create()
.PageSize(650, 450)
.Render(container =>
{
container
.Padding(20)
.Grid(grid =>
{
grid.Columns(2);
grid.Spacing(10);
foreach (var turns in Enumerable.Range(0, 4))
{
grid.Item()
.Width(300)
.Height(200)
.Background(Colors.Grey.Lighten2)
.Padding(10)
.Element(element =>
{
foreach (var x in Enumerable.Range(0, turns))
element = element.RotateRight();
return element;
})
.MinimalBox()
.Background(Colors.White)
.Padding(10)
.Text($"Rotated {turns * 90}°", TextStyle.Default.Size(16));
}
});
.ExtendVertical()
.Text(TextPlaceholder.LoremIpsum());
});
}
[Test]
public void FreeRotate()
//[ShowResult]
[ImageSize(298, 421)]
public void Page(IContainer container)
{
RenderingTest
.Create()
.PageSize(300, 300)
.Render(container =>
container
.Background("#FFF")
.Padding(15)
.Page(page =>
{
container
.Padding(25)
.Background(Colors.Grey.Lighten2)
page.Header()
.Height(60)
.Background("#BBB")
.AlignCenter()
.AlignMiddle()
.Background(Colors.White)
.Rotate(30)
.Width(100)
.Height(100)
.Background(Colors.Blue.Medium);
});
}
[Test]
public void FreeRotateCenter()
{
RenderingTest
.Create()
.PageSize(300, 300)
.Render(container =>
{
container
.Padding(25)
.Background(Colors.Grey.Lighten2)
.Text("Header");
page.Content()
.Background("#DDD")
.AlignCenter()
.AlignMiddle()
.Text("Content");
.Background(Colors.White)
.TranslateX(50)
.TranslateY(50)
.Rotate(30)
page.Footer()
.Height(30)
.Background("#BBB")
.AlignCenter()
.AlignMiddle()
.Text("Footer");
});
}
//[ShowResult]
[ImageSize(740, 200)]
public void Row(IContainer container)
{
container
.Background("#FFF")
.Padding(20)
.Stack(stack =>
{
stack.Element()
.PaddingBottom(10)
.AlignCenter()
.Text("This Row element is 700pt wide");
.TranslateX(-50)
.TranslateY(-50)
.Width(100)
.Height(100)
.Background(Colors.Blue.Medium);
});
}
stack.Element().Row(row =>
{
row.ConstantColumn(100)
.Background("#DDD")
.Padding(10)
.ExtendVertical()
.Text("This column is 100 pt wide");
[Test]
public void Flip()
{
RenderingTest
.Create()
.PageSize(350, 350)
.Render(container =>
{
container
.Padding(20)
.Grid(grid =>
{
grid.Columns(2);
grid.Spacing(10);
foreach (var turns in Enumerable.Range(0, 4))
{
grid.Item()
.Width(150)
.Height(150)
.Background(Colors.Grey.Lighten3)
.Padding(10)
.Element(element =>
{
if (turns == 1 || turns == 2)
element = element.FlipHorizontal();
row.RelativeColumn()
.Background("#BBB")
.Padding(10)
.Text("This column takes 1/3 of the available space (200pt)");
if (turns == 2 || turns == 3)
element = element.FlipVertical();
return element;
})
.MinimalBox()
.Background(Colors.White)
.Padding(10)
.Text($"Flipped {turns}", TextStyle.Default.Size(16));
}
});
row.RelativeColumn(2)
.Background("#DDD")
.Padding(10)
.Text("This column takes 2/3 of the available space (400pt)");
});
});
}
[Test]
public void RotateInTable()
//[ShowResult]
[ImageSize(500, 350)]
public void Column(IContainer container)
{
RenderingTest
.Create()
.PageSize(200, 200)
.Render(container =>
container
.Background("#FFF")
.Padding(15)
.Stack(column =>
{
container
.Padding(10)
.Border(2)
.Row(row =>
{
row.ConstantColumn(25)
.Border(1)
.RotateLeft()
.AlignCenter()
.AlignMiddle()
.Text("Sample text");
row.RelativeColumn().Border(1).Padding(5).Text(Placeholders.Paragraph());
});
column.Spacing(10);
column
.Element()
.Background("#999")
.Height(50);
column
.Element()
.Background("#BBB")
.Height(100);
column
.Element()
.Background("#DDD")
.Height(150);
});
}
[Test]
public void Unconstrained()
//[ShowResult]
[ImageSize(300, 200)]
public void Debug(IContainer container)
{
RenderingTest
.Create()
.PageSize(400, 350)
.Render(container =>
container
.Padding(25)
.Debug()
.Padding(-5)
.Row(row =>
{
container
.Padding(25)
.PaddingLeft(75)
.Stack(stack =>
{
stack.Item().Width(300).Height(150).Background(Colors.Blue.Lighten4);
stack
.Item()
// creates an infinite space for its child
.Unconstrained()
// moves the child up and left
.TranslateX(-50)
.TranslateY(-50)
// limits the space for the child
.Width(100)
.Height(100)
.Background(Colors.Blue.Darken1);
stack.Item().Width(300).Height(150).Background(Colors.Blue.Lighten3);
});
row.RelativeColumn().Padding(5).Extend().Placeholder();
row.RelativeColumn().Padding(5).Extend().Placeholder();
});
}
[Test]
public void ComplexLayout()
[ShowResult]
[ImageSize(300, 200)]
public void ElementEnd(IContainer container)
{
RenderingTest
.Create()
.PageSize(500, 225)
.Render(container =>
var text = "";
container
.Padding(10)
.Element(x =>
{
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)
.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));
}
});
if (string.IsNullOrWhiteSpace(text))
x.Height(10).Width(50).Background("#DDD");
else
x.Text(text);
});
}
}
}
}
@@ -0,0 +1,96 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Elements;
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
using SkiaSharp;
namespace QuestPDF.Examples.Engine
{
[TestFixture]
public class ExampleTestBase
{
private readonly Size DefaultImageSize = new Size(400, 300);
private const string ResultPath = "Result";
[SetUp]
public void Setup()
{
if (Directory.Exists(ResultPath))
Directory.Delete(ResultPath, true);
Directory.CreateDirectory(ResultPath);
}
[Test]
public void RunTest()
{
GetType()
.GetMethods()
.Where(IsExampleMethod)
.ToList()
.ForEach(HandleExample);
}
private bool IsExampleMethod(MethodInfo method)
{
var parameters = method.GetParameters();
return parameters.Length == 1 && parameters.First().ParameterType == typeof(IContainer);
}
private T GetAttribute<T>(MethodInfo methodInfo) where T : Attribute
{
return methodInfo.GetCustomAttributes().FirstOrDefault(y => y is T) as T;
}
private void HandleExample(MethodInfo methodInfo)
{
var size = GetAttribute<ImageSizeAttribute>(methodInfo)?.Size ?? DefaultImageSize;
var fileName = GetAttribute<FileNameAttribute>(methodInfo)?.FileName ?? methodInfo.Name;
var showResult = GetAttribute<ShowResultAttribute>(methodInfo) != null;
var shouldIgnore = GetAttribute<IgnoreAttribute>(methodInfo) != null;
if (shouldIgnore)
return;
var container = new Container();
methodInfo.Invoke(this, new object[] {container});
Func<int, string> fileNameSchema = i => $"{fileName.ToLower()}-${i}.png";
try
{
var document = new SimpleDocument(container, size);
document.GenerateImages(fileNameSchema);
}
catch (Exception e)
{
throw new Exception($"Cannot perform test ${fileName}", e);
}
if (showResult)
Process.Start("explorer", fileNameSchema(0));
}
private byte[] RenderPage(Element element, Size size)
{
// scale the result so it is more readable
const float scalingFactor = 2;
var imageInfo = new SKImageInfo((int)(size.Width * scalingFactor), (int)(size.Height * scalingFactor));
using var surface = SKSurface.Create(imageInfo);
surface.Canvas.Scale(scalingFactor);
var canvas = new Canvas(surface.Canvas);
element?.Draw(canvas, size);
surface.Canvas.Save();
return surface.Snapshot().Encode(SKEncodedImageFormat.Png, 100).ToArray();
}
}
}
@@ -0,0 +1,14 @@
using System;
namespace QuestPDF.Examples.Engine
{
public class FileNameAttribute : Attribute
{
public string FileName { get; }
public FileNameAttribute(string fileName)
{
FileName = fileName;
}
}
}
@@ -0,0 +1,9 @@
using System;
namespace QuestPDF.Examples.Engine
{
public class IgnoreAttribute : Attribute
{
}
}
@@ -0,0 +1,19 @@
using System;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples.Engine
{
public class ImageSizeAttribute : Attribute
{
private int Width { get; }
private int Height { get; }
public Size Size => new Size(Width, Height);
public ImageSizeAttribute(int width, int height)
{
Width = width;
Height = height;
}
}
}
-131
View File
@@ -1,131 +0,0 @@
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using QuestPDF.Elements;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples.Engine
{
public enum RenderingTestResult
{
Pdf,
Images
}
public class RenderingTest
{
private string FileNamePrefix = "test";
private Size Size { get; set; }
private int? MaxPagesThreshold { get; set; }
private bool ShowResult { get; set; }
private bool ApplyCaching { get; set; }
private bool ApplyDebugging { get; set; }
private RenderingTestResult ResultType { get; set; } = RenderingTestResult.Images;
private RenderingTest()
{
}
public static RenderingTest Create([CallerMemberName] string fileName = "test")
{
return new RenderingTest().FileName(fileName);
}
public RenderingTest FileName(string fileName)
{
FileNamePrefix = fileName;
return this;
}
public RenderingTest PageSize(Size size)
{
Size = size;
return this;
}
public RenderingTest PageSize(int width, int height)
{
return PageSize(new Size(width, height));
}
public RenderingTest ProducePdf()
{
ResultType = RenderingTestResult.Pdf;
return this;
}
public RenderingTest ProduceImages()
{
ResultType = RenderingTestResult.Images;
return this;
}
public RenderingTest ShowResults()
{
ShowResult = true;
return this;
}
public RenderingTest MaxPages(int value)
{
MaxPagesThreshold = value;
return this;
}
public RenderingTest EnableCaching(bool value = true)
{
ApplyCaching = value;
return this;
}
public RenderingTest EnableDebugging(bool value = true)
{
ApplyDebugging = value;
return this;
}
public void Render(Action<IContainer> content)
{
RenderDocument(container =>
{
container.Page(page =>
{
page.Size(new PageSize(Size.Width, Size.Height));
page.Content().Container().Background(Colors.White).Element(content);
});
});
}
public void RenderDocument(Action<IDocumentContainer> content)
{
MaxPagesThreshold ??= ResultType == RenderingTestResult.Pdf ? 1000 : 10;
var document = new SimpleDocument(content, MaxPagesThreshold.Value, ApplyCaching, ApplyDebugging);
Render(document);
}
private void Render(IDocument document)
{
if (ResultType == RenderingTestResult.Images)
{
Func<int, string> fileNameSchema = i => $"{FileNamePrefix}-${i}.png";
document.GenerateImages(fileNameSchema);
if (ShowResult)
Process.Start("explorer", fileNameSchema(0));
}
if (ResultType == RenderingTestResult.Pdf)
{
var fileName = $"{FileNamePrefix}.pdf";
document.GeneratePdf(fileName);
if (ShowResult)
Process.Start("explorer", fileName);
}
}
}
}
@@ -0,0 +1,9 @@
using System;
namespace QuestPDF.Examples.Engine
{
public class ShowResultAttribute : Attribute
{
}
}
+11 -21
View File
@@ -1,6 +1,4 @@
using System;
using QuestPDF.Drawing;
using QuestPDF.Elements;
using QuestPDF.Drawing;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
@@ -9,35 +7,27 @@ namespace QuestPDF.Examples.Engine
{
public class SimpleDocument : IDocument
{
public const int ImageScalingFactor = 2;
private Action<IDocumentContainer> Content { get; }
private int MaxPages { get; }
private bool ApplyCaching { get; }
private bool ApplyDebugging { get; }
private IContainer Container { get; }
private Size Size { get; }
public SimpleDocument(Action<IDocumentContainer> content, int maxPages, bool applyCaching, bool applyDebugging)
public SimpleDocument(IContainer container, Size size)
{
Content = content;
MaxPages = maxPages;
ApplyCaching = applyCaching;
ApplyDebugging = applyDebugging;
Container = container;
Size = size;
}
public DocumentMetadata GetMetadata()
{
return new DocumentMetadata()
{
RasterDpi = PageSizes.PointsPerInch * ImageScalingFactor,
DocumentLayoutExceptionThreshold = MaxPages,
ApplyCaching = ApplyCaching,
ApplyDebugging = ApplyDebugging
RasterDpi = PageSizes.PointsPerInch * 2,
Size = Size
};
}
public void Compose(IDocumentContainer container)
public void Compose(IContainer container)
{
Content(container);
container.Background("#FFF").Element(Container.Child);
}
}
}
-53
View File
@@ -1,53 +0,0 @@
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
public class EnsureSpaceExample
{
[Test]
public void EnsureSpaceWith()
{
RenderingTest
.Create()
.ProduceImages()
.ShowResults()
.RenderDocument(container =>
{
container.Page(page =>
{
page.Margin(20);
page.Size(PageSizes.A7.Landscape());
page.Background(Colors.White);
page.Header().Text("With ensure space", TextStyle.Default.SemiBold());
page.Content().Stack(stack =>
{
stack
.Item()
.ExtendHorizontal()
.Height(75)
.Background(Colors.Grey.Lighten2);
stack
.Item()
.EnsureSpace(100)
.Text(Placeholders.LoremIpsum());
});
page.Footer().Text(text =>
{
text.Span("Page ");
text.CurrentPageNumber();
text.Span(" out of ");
text.TotalPages();
});
});
});
}
}
}
+18 -26
View File
@@ -1,4 +1,4 @@
using NUnit.Framework;
using System.Linq;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
@@ -12,41 +12,33 @@ namespace QuestPDF.Examples
{
return container
.Border(1)
.BorderColor(Colors.Grey.Medium)
.Background(dark ? Colors.Grey.Lighten3 : Colors.White)
.Padding(5);
.Background(dark ? "#EEE" : "#FFF")
.Padding(10);
}
public static void LabelCell(this IContainer container, string text) => container.Cell(true).Text(text, TextStyle.Default.SemiBold());
public static IContainer LabelCell(this IContainer container) => container.Cell(true);
public static IContainer ValueCell(this IContainer container) => container.Cell(false);
public static void ValueCell(this IContainer container, string text) => container.ValueCell().Text(text, TextStyle.Default);
}
public class FrameExample
public class FrameExample: ExampleTestBase
{
[Test]
public void Frame()
[ImageSize(550, 400)]
[ShowResult]
public void Frame(IContainer container)
{
RenderingTest
.Create()
.PageSize(550, 400)
.ShowResults()
.Render(container =>
container
.Background("#FFF")
.Padding(25)
.Stack(stack =>
{
container
.Background("#FFF")
.Padding(25)
.Stack(stack =>
for(var i=1; i<=4; i++)
{
stack.Element().Row(row =>
{
for(var i = 1; i <= 4; i++)
{
stack.Item().Row(row =>
{
row.RelativeColumn(2).LabelCell(Placeholders.Label());
row.RelativeColumn(3).ValueCell().Text(Placeholders.Paragraph());
});
}
row.RelativeColumn(2).LabelCell().Text(TextPlaceholder.Label());
row.RelativeColumn(3).ValueCell().Text(TextPlaceholder.Paragraph());
});
}
});
}
}
-51
View File
@@ -1,51 +0,0 @@
using System.IO;
using NUnit.Framework;
using QuestPDF.Drawing.Exceptions;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
namespace QuestPDF.Examples
{
public class ImageExamples
{
[Test]
public void LoadingImage()
{
RenderingTest
.Create()
.PageSize(PageSizes.A5)
.ProducePdf()
.ShowResults()
.Render(page =>
{
page.Padding(25).Stack(stack =>
{
stack.Spacing(25);
stack.Item().Image("logo.png");
var binaryData = File.ReadAllBytes("logo.png");
stack.Item().Image(binaryData);
using var stream = new FileStream("logo.png", FileMode.Open);
stack.Item().Image(stream);
});
});
}
[Test]
public void Exception()
{
Assert.Throws<DocumentComposeException>(() =>
{
RenderingTest
.Create()
.PageSize(PageSizes.A2)
.ProducePdf()
.ShowResults()
.Render(page => page.Image("non_existent.png"));
});
}
}
}
-123
View File
@@ -1,123 +0,0 @@
using System;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
public class InlinedExamples
{
[Test]
public void Inlined()
{
RenderingTest
.Create()
.PageSize(800, 650)
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Padding(25)
.Decoration(decoration =>
{
decoration.Header().Text(text =>
{
text.DefaultTextStyle(TextStyle.Default.Size(20));
text.CurrentPageNumber();
text.Span(" / ");
text.TotalPages();
});
decoration
.Content()
.PaddingTop(25)
//.MinimalBox()
.Border(1)
.Background(Colors.Grey.Lighten2)
.Inlined(inlined =>
{
inlined.Spacing(25);
inlined.AlignSpaceAround();
inlined.BaselineMiddle();
var random = new Random(123);
foreach (var _ in Enumerable.Range(0, 50))
{
var width = random.Next(2, 7);
var height = random.Next(2, 7);
var sizeText = $"{width}×{height}";
inlined
.Item()
.Border(1)
.Width(width * 25)
.Height(height * 25)
.Background(Placeholders.BackgroundColor())
.Layers(layers =>
{
layers.Layer().Grid(grid =>
{
grid.Columns(width);
Enumerable.Range(0, width * height).ToList().ForEach(x => grid.Item().Border(1).BorderColor(Colors.White).Width(25).Height(25));
});
layers
.PrimaryLayer()
.AlignCenter()
.AlignMiddle()
.Text(sizeText, TextStyle.Default.Size(15));
});
}
});
});
});
}
[Test]
public void Inline_AlignLeft_BaselineBottom()
{
RenderingTest
.Create()
.PageSize(800, 600)
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Padding(20)
.MinimalBox()
.Border(1)
.Background(Colors.Grey.Lighten4)
.Inlined(inlined =>
{
inlined.VerticalSpacing(50);
inlined.HorizontalSpacing(25);
inlined.AlignRight();
inlined.BaselineMiddle();
foreach (var _ in Enumerable.Range(0, 100))
inlined.Item().Element(RandomBlock);
});
});
void RandomBlock(IContainer container)
{
container
.Width(Placeholders.Random.Next(1, 5) * 20)
.Height(Placeholders.Random.Next(1, 5) * 20)
.Border(1)
.BorderColor(Colors.Grey.Darken2)
.Background(Placeholders.BackgroundColor());
}
}
}
}
Binary file not shown.
+16 -24
View File
@@ -1,5 +1,4 @@
using System.Net;
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
@@ -28,34 +27,27 @@ namespace QuestPDF.Examples
}
}
public class LoremPicsumExample
public class LoremPicsumExample : ExampleTestBase
{
[Test]
public void LoremPicsum()
[ShowResult]
[ImageSize(350, 280)]
public void LoremPicsum(IContainer container)
{
RenderingTest
.Create()
.PageSize(350, 280)
.ProducePdf()
.ShowResults()
.Render(container =>
container
.Background("#FFF")
.Padding(25)
.Stack(column =>
{
container
.Background("#FFF")
.Padding(25)
.Stack(column =>
{
column.Spacing(10);
column.Spacing(10);
column
.Item()
.Component(new LoremPicsum(true));
column
.Element()
.Component(new LoremPicsum(true));
column
.Item()
.AlignRight()
.Text("From Lorem Picsum");
});
column
.Element()
.AlignRight()
.Text("From Lorem Picsum");
});
}
}
+98 -129
View File
@@ -1,163 +1,132 @@
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
public class Examples
public class Examples : ExampleTestBase
{
[Test]
public void Padding()
public void Padding(IContainer container)
{
RenderingTest
.Create()
.PageSize(300, 300)
.ShowResults()
.Render(container =>
{
container
.Background("#FDD")
.Padding(50)
container
.Background("#FDD")
.Padding(50)
.Background("#AFA")
.PaddingVertical(50)
.Background("#AFA")
.PaddingVertical(50)
.Background("#77F")
.PaddingHorizontal(50)
.Background("#77F")
.PaddingHorizontal(50)
.Background("#444");
});
.Background("#444");
}
[Test]
public void Border()
public void Border(IContainer container)
{
RenderingTest
.Create()
.PageSize(200, 150)
.Render(container =>
{
container
.Background("#EEE")
.Padding(25)
container
.Background("#EEE")
.Padding(25)
.AlignBottom()
.AlignCenter()
.BorderBottom(2)
.BorderColor("#000")
.AlignBottom()
.AlignCenter()
.BorderBottom(2)
.BorderColor("#000")
.Background("FFF")
.Padding(5)
.Background("FFF")
.Padding(5)
.Text("Sample text", TextStyle.Default.FontType("Segoe UI emoji").Alignment(HorizontalAlignment.Center));
}
public void Alignment(IContainer container)
{
container
.Stack(column =>
{
column
.Element()
.Height(100)
.Background("#FFF")
.AlignLeft()
.AlignMiddle()
.Width(50)
.Height(50)
.Background("#444");
column
.Element()
.Height(100)
.Background("#DDD")
.AlignCenter()
.Text("Sample text", TextStyle.Default.FontType("Segoe UI emoji"));
.AlignMiddle()
.Width(50)
.Height(50)
.Background("#222");
column
.Element()
.Height(100)
.Background("#BBB")
.AlignRight()
.AlignMiddle()
.Width(50)
.Height(50)
.Background("#000");
});
}
[Test]
public void Alignment()
public void Expand(IContainer container)
{
RenderingTest
.Create()
.PageSize(200, 150)
.Render(container =>
container
.Stack(column =>
{
container
.Stack(column =>
column
.Element()
.Height(150)
.Row(row =>
{
column
.Item()
.Height(100)
.Background("#FFF")
.AlignLeft()
.AlignMiddle()
row.RelativeColumn()
.Extend()
.Background("FFF")
.Width(50)
.Height(50)
.Background("#444");
column
.Item()
.Height(100)
.Background("#DDD")
.AlignCenter()
.AlignMiddle()
.Width(50)
.Background("444");
row.RelativeColumn()
.Extend()
.Background("BBB")
.Width(50)
.Height(50)
.Background("#222");
column
.Item()
.Height(100)
.Background("#BBB")
.AlignRight()
.AlignMiddle()
.Width(50)
.Height(50)
.Background("#000");
.ExtendHorizontal()
.Background("444");
});
});
}
[Test]
public void Expand()
{
RenderingTest
.Create()
.PageSize(200, 150)
.Render(container =>
{
container
.Stack(column =>
{
column
.Item()
.Height(150)
.Row(row =>
{
row.RelativeColumn()
.Extend()
.Background("FFF")
.Height(50)
.Width(50)
.Background("444");
row.RelativeColumn()
.Extend()
.Background("BBB")
.Height(50)
.ExtendHorizontal()
.Background("444");
});
column
.Item()
.Height(150)
.Row(row =>
{
row.RelativeColumn()
.Extend()
.Background("BBB")
column
.Element()
.Height(150)
.Row(row =>
{
row.RelativeColumn()
.Extend()
.Background("BBB")
.ExtendVertical()
.Width(50)
.Background("444");
.ExtendVertical()
.Width(50)
.Background("444");
row.RelativeColumn()
.Extend()
.Background("BBB")
row.RelativeColumn()
.Extend()
.Background("BBB")
.ExtendVertical()
.ExtendHorizontal()
.Background("444");
});
.ExtendVertical()
.ExtendHorizontal()
.Background("444");
});
});
}
+3 -21
View File
@@ -6,32 +6,14 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
<PackageReference Include="microcharts" Version="0.9.5.9" />
<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="Svg.Skia" Version="0.5.10" />
<PackageReference Include="SkiaSharp" Version="2.80.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\QuestPDF\QuestPDF.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="quo-vadis.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="LibreBarcode39-Regular.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="logo.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="pdf-icon.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
-94
View File
@@ -1,94 +0,0 @@
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
public class RowExamples
{
[Test]
public void ColumnTypes()
{
RenderingTest
.Create()
.ProducePdf()
.PageSize(650, 300)
.ShowResults()
.Render(container =>
{
container
.Padding(25)
.MinimalBox()
.Border(1)
.Stack(stack =>
{
stack.Item().LabelCell("Total width: 600px");
stack.Item().Row(row =>
{
row.ConstantColumn(150).ValueCell("150px");
row.ConstantColumn(100).ValueCell("100px");
row.RelativeColumn(4).ValueCell("200px");
row.RelativeColumn(3).ValueCell("150px");
});
stack.Item().Row(row =>
{
row.ConstantColumn(100).ValueCell("100px");
row.ConstantColumn(50).ValueCell("50px");
row.RelativeColumn(3).ValueCell("300px");
row.RelativeColumn(1).ValueCell("100px");
row.ConstantColumn(50).ValueCell("50px");
});
});
});
}
[Test]
public void Stability()
{
// up to version 2021.12, this code would always result with the infinite layout exception
RenderingTest
.Create()
.ProducePdf()
.MaxPages(100)
.PageSize(250, 150)
.ShowResults()
.Render(container =>
{
container
.Padding(25)
.Row(row =>
{
row.RelativeColumn().Stack(stack =>
{
stack.Item().ShowOnce().Element(CreateBox).Text("X");
stack.Item().Element(CreateBox).Text("1");
stack.Item().Element(CreateBox).Text("2");
});
row.RelativeColumn().Stack(stack =>
{
stack.Item().Element(CreateBox).Text("1");
stack.Item().Element(CreateBox).Text("2");
});
});
});
static IContainer CreateBox(IContainer container)
{
return container
.ExtendHorizontal()
.ExtendVertical()
.Background(Colors.Grey.Lighten4)
.Border(1)
.AlignCenter()
.AlignMiddle()
.ShowOnce();
}
}
}
}
-54
View File
@@ -1,54 +0,0 @@
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
public class ShowOnceExample
{
[Test]
public void ShowOnce()
{
RenderingTest
.Create()
.ProduceImages()
.ShowResults()
.RenderDocument(container =>
{
container.Page(page =>
{
page.Margin(20);
page.Size(PageSizes.A7.Landscape());
page.Background(Colors.White);
page.Header().Text("With show once", TextStyle.Default.SemiBold());
page.Content().PaddingVertical(5).Row(row =>
{
row.RelativeColumn()
.Background(Colors.Grey.Lighten2)
.Border(1)
.Padding(5)
.ShowOnce()
.Text(Placeholders.Label());
row.RelativeColumn(2)
.Border(1)
.Padding(5)
.Text(Placeholders.Paragraph());
});
page.Footer().Text(text =>
{
text.Span("Page ");
text.CurrentPageNumber();
text.Span(" out of ");
text.TotalPages();
});
});
});
}
}
}
-47
View File
@@ -1,47 +0,0 @@
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
public class SkipOnceExample
{
[Test]
public void SkipOnce()
{
RenderingTest
.Create()
.ProduceImages()
.ShowResults()
.RenderDocument(container =>
{
container.Page(page =>
{
page.Margin(20);
page.Size(PageSizes.A7.Landscape());
page.Background(Colors.White);
page.Header().Stack(stack =>
{
stack.Item().ShowOnce().Text("This header is visible on the first page.");
stack.Item().SkipOnce().Text("This header is visible on the second page and all following.");
});
page.Content()
.PaddingVertical(10)
.Text(Placeholders.Paragraphs(), TextStyle.Default.Color(Colors.Grey.Medium));
page.Footer().Text(text =>
{
text.Span("Page ");
text.CurrentPageNumber();
text.Span(" out of ");
text.TotalPages();
});
});
});
}
}
}
-36
View File
@@ -1,36 +0,0 @@
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using SkiaSharp;
using Svg.Skia;
namespace QuestPDF.Examples
{
public class SvgImageExample
{
[Test]
public void BorderRadius()
{
RenderingTest
.Create()
.PageSize(175, 100)
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Background(Colors.Grey.Lighten2)
.Padding(25)
.Canvas((canvas, space) =>
{
using var svg = new SKSvg();
svg.Load("pdf-icon.svg");
canvas.DrawPicture(svg.Picture);
});
});
}
}
}
-500
View File
@@ -1,500 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using IContainer = QuestPDF.Infrastructure.IContainer;
namespace QuestPDF.Examples
{
public class TableExamples
{
[Test]
public void BasicPlacement()
{
RenderingTest
.Create()
.ProduceImages()
.PageSize(220, 220)
.ShowResults()
.Render(container =>
{
container
.Padding(10)
.MinimalBox()
.Border(1)
.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
});
// by using custom 'Element' method, we can reuse visual configuration
table.Cell().Row(1).Column(4).Element(Block).Text("A");
table.Cell().Row(2).Column(2).Element(Block).Text("B");
table.Cell().Row(3).Column(3).Element(Block).Text("C");
table.Cell().Row(4).Column(1).Element(Block).Text("D");
});
});
}
[Test]
public void PagingSupport()
{
RenderingTest
.Create()
.ProducePdf()
.PageSize(420, 220)
.ShowResults()
.Render(container =>
{
container
.Padding(10)
.MinimalBox()
.Border(1)
.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
});
// by using custom 'Element' method, we can reuse visual configuration
table.Cell().Element(Block).Text(Placeholders.Label());
table.Cell().Element(Block).Text(Placeholders.Label());
table.Cell().Element(Block).Text(Placeholders.Paragraph());
table.Cell().Element(Block).Text(Placeholders.Label());
});
});
}
[Test]
public void DefaultCellStyle()
{
RenderingTest
.Create()
.ProduceImages()
.PageSize(220, 120)
.ShowResults()
.Render(container =>
{
container
.Padding(10)
.MinimalBox()
.Border(1)
.DefaultTextStyle(TextStyle.Default.Size(16))
.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
});
table.Cell().Row(1).Column(1).Element(Block).Text("A");
table.Cell().Row(2).Column(2).Element(Block).Text("B");
table.Cell().Row(1).Column(3).Element(Block).Text("C");
table.Cell().Row(2).Column(4).Element(Block).Text("D");
});
});
}
[Test]
public void ColumnsDefinition()
{
RenderingTest
.Create()
.ProduceImages()
.PageSize(320, 80)
.ShowResults()
.Render(container =>
{
container
.Padding(10)
.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.ConstantColumn(50);
columns.ConstantColumn(100);
columns.RelativeColumn(2);
columns.RelativeColumn(3);
});
table.Cell().ColumnSpan(4).LabelCell("Total width: 300px");
table.Cell().ValueCell("50px");
table.Cell().ValueCell("100px");
table.Cell().ValueCell("100px");
table.Cell().ValueCell("150px");
});
});
}
[Test]
public void PartialAutoPlacement()
{
RenderingTest
.Create()
.ProduceImages()
.PageSize(220, 220)
.ShowResults()
.Render(container =>
{
container
.Padding(10)
.MinimalBox()
.Border(1)
.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
});
table.Cell().Element(Block).Text("A");
table.Cell().Row(2).Column(2).Element(Block).Text("B");
table.Cell().Element(Block).Text("C");
table.Cell().Row(3).Column(3).Element(Block).Text("D");
table.Cell().ColumnSpan(2).Element(Block).Text("E");
});
});
}
[Test]
public void ExtendLastCellsToTableBottom()
{
RenderingTest
.Create()
.ProduceImages()
.PageSize(220, 170)
.ShowResults()
.Render(container =>
{
container
.Padding(10)
.MinimalBox()
.Border(1)
.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
});
table.ExtendLastCellsToTableBottom();
table.Cell().Row(1).Column(1).Element(Block).Text("A");
table.Cell().Row(3).Column(1).Element(Block).Text("B");
table.Cell().Row(2).Column(2).Element(Block).Text("C");
table.Cell().Row(3).Column(3).Element(Block).Text("D");
table.Cell().Row(2).RowSpan(2).Column(4).Element(Block).Text("E");
});
});
}
[Test]
public void Overlapping()
{
RenderingTest
.Create()
.ProduceImages()
.PageSize(170, 170)
.ShowResults()
.Render(container =>
{
container
.Padding(10)
.MinimalBox()
.Border(1)
.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
});
table.Cell().Row(1).RowSpan(3).Column(1).ColumnSpan(3).Background(Colors.Grey.Lighten3).MinHeight(150);
table.Cell().Row(1).RowSpan(2).Column(1).ColumnSpan(2).Background(Colors.Grey.Lighten1).MinHeight(100);
table.Cell().Row(3).Column(3).Background(Colors.Grey.Darken1).MinHeight(50);
});
});
}
[Test]
public void Spans()
{
RenderingTest
.Create()
.ProduceImages()
.PageSize(220, 170)
.ShowResults()
.Render(container =>
{
container
.Padding(10)
.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
});
table.Cell().RowSpan(2).ColumnSpan(2).Element(Block).Text("1");
table.Cell().ColumnSpan(2).Element(Block).Text("2");
table.Cell().Element(Block).Text("3");
table.Cell().Element(Block).Text("4");
table.Cell().RowSpan(2).Element(Block).Text("5");
table.Cell().ColumnSpan(2).Element(Block).Text("6");
table.Cell().RowSpan(2).Element(Block).Text("7");
table.Cell().Element(Block).Text("8");
table.Cell().Element(Block).Text("9");
});
});
}
[Test]
public void Stability()
{
RenderingTest
.Create()
.ProduceImages()
.PageSize(300, 300)
.ShowResults()
.Render(container =>
{
container
.Padding(10)
.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
});
table.Cell().RowSpan(4).Element(Block).Text("1");
table.Cell().RowSpan(2).Element(Block).Text("2");
table.Cell().RowSpan(1).Element(Block).Text("3");
table.Cell().RowSpan(1).Element(Block).Text("4");
table.Cell().RowSpan(2).Element(Block).Text("5");
table.Cell().RowSpan(1).Element(Block).Text("6");
table.Cell().RowSpan(1).Element(Block).Text("7");
});
});
}
[Test]
public void TableHeader()
{
RenderingTest
.Create()
.ProduceImages()
.PageSize(500, 200)
.ShowResults()
.EnableDebugging()
.Render(container =>
{
var pageSizes = new List<(string name, double width, double height)>()
{
("Letter (ANSI A)", 8.5f, 11),
("Legal", 8.5f, 14),
("Ledger (ANSI B)", 11, 17),
("Tabloid (ANSI B)", 17, 11),
("ANSI C", 22, 17),
("ANSI D", 34, 22),
("ANSI E", 44, 34)
};
const int inchesToPoints = 72;
container
.Padding(10)
.MinimalBox()
.Border(1)
.Table(table =>
{
IContainer DefaultCellStyle(IContainer container, string backgroundColor)
{
return container
.Border(1)
.BorderColor(Colors.Grey.Lighten1)
.Background(backgroundColor)
.PaddingVertical(5)
.PaddingHorizontal(10)
.AlignCenter()
.AlignMiddle();
}
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn();
columns.ConstantColumn(75);
columns.ConstantColumn(75);
columns.ConstantColumn(75);
columns.ConstantColumn(75);
});
table.Header(header =>
{
header.Cell().RowSpan(2).Element(CellStyle).ExtendHorizontal().AlignLeft().Text("Document type");
header.Cell().ColumnSpan(2).Element(CellStyle).Text("Inches");
header.Cell().ColumnSpan(2).Element(CellStyle).Text("Points");
header.Cell().Element(CellStyle).Text("Width");
header.Cell().Element(CellStyle).Text("Height");
header.Cell().Element(CellStyle).Text("Width");
header.Cell().Element(CellStyle).Text("Height");
// you can extend already existing styles by creating additional methods
IContainer CellStyle(IContainer container) => DefaultCellStyle(container, Colors.Grey.Lighten3);
});
foreach (var page in pageSizes)
{
table.Cell().Element(CellStyle).ExtendHorizontal().AlignLeft().Text(page.name);
// inches
table.Cell().Element(CellStyle).Text(page.width);
table.Cell().Element(CellStyle).Text(page.height);
// points
table.Cell().Element(CellStyle).Text(page.width * inchesToPoints);
table.Cell().Element(CellStyle).Text(page.height * inchesToPoints);
IContainer CellStyle(IContainer container) => DefaultCellStyle(container, Colors.White);
}
});
});
}
[Test]
public void PerformanceText_TemperatureReport()
{
RenderingTest
.Create()
.ProducePdf()
.PageSize(PageSizes.A4)
.MaxPages(10_000)
.EnableCaching()
.EnableDebugging(false)
.ShowResults()
.Render(container => GeneratePerformanceStructure(container, 250));
}
public static void GeneratePerformanceStructure(IContainer container, int repeats)
{
container
.Padding(25)
//.Background(Colors.Blue.Lighten2)
.MinimalBox()
.Border(1)
//.Background(Colors.Red.Lighten2)
.Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.ConstantColumn(100);
columns.RelativeColumn();
columns.ConstantColumn(100);
columns.RelativeColumn();
});
table.ExtendLastCellsToTableBottom();
foreach (var i in Enumerable.Range(0, repeats))
{
table.Cell().RowSpan(3).LabelCell("Project");
table.Cell().RowSpan(3).ShowEntire().ValueCell(Placeholders.Sentence());
table.Cell().LabelCell("Report number");
table.Cell().ValueCell(i.ToString());
table.Cell().LabelCell("Date");
table.Cell().ValueCell(Placeholders.ShortDate());
table.Cell().LabelCell("Inspector");
table.Cell().ValueCell("Marcin Ziąbek");
table.Cell().ColumnSpan(2).LabelCell("Morning weather");
table.Cell().ColumnSpan(2).LabelCell("Evening weather");
table.Cell().ValueCell("Time");
table.Cell().ValueCell("7:13");
table.Cell().ValueCell("Time");
table.Cell().ValueCell("18:25");
table.Cell().ValueCell("Description");
table.Cell().ValueCell("Sunny");
table.Cell().ValueCell("Description");
table.Cell().ValueCell("Windy");
table.Cell().ValueCell("Wind");
table.Cell().ValueCell("Mild");
table.Cell().ValueCell("Wind");
table.Cell().ValueCell("Strong");
table.Cell().ValueCell("Temperature");
table.Cell().ValueCell("17°C");
table.Cell().ValueCell("Temperature");
table.Cell().ValueCell("32°C");
table.Cell().LabelCell("Remarks");
table.Cell().ColumnSpan(3).ValueCell(Placeholders.Paragraph());
}
});
}
// this method uses a higher order function to define a custom and dynamic style
static IContainer Block(IContainer container)
{
return container
.Border(1)
.Background(Colors.Grey.Lighten3)
.ShowOnce()
.MinWidth(50)
.MinHeight(50)
.Padding(10)
.AlignCenter()
.AlignMiddle();
}
}
}
-226
View File
@@ -1,226 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
public class TextBenchmark
{
[Test]
public void Generate()
{
var chapters = GetBookChapters().ToList();
RenderingTest
.Create()
.PageSize(PageSizes.A4)
.ProducePdf()
.ShowResults()
.Render(x => ComposeBook(x, chapters));
}
[Test]
public void Benchmark()
{
var chapters = GetBookChapters().ToList();
var results = PerformTest(16).ToList();
Console.WriteLine($"Min: {results.Min():F}");
Console.WriteLine($"Max: {results.Max():F}");
Console.WriteLine($"Avg: {results.Average():F}");
void GenerateDocument()
{
RenderingTest
.Create()
.PageSize(PageSizes.A4)
.ProducePdf()
.Render(x => ComposeBook(x, chapters));
}
IEnumerable<float> PerformTest(int attempts)
{
foreach (var i in Enumerable.Range(0, attempts))
{
var timer = new Stopwatch();
timer.Start();
GenerateDocument();
timer.Stop();
Console.WriteLine($"Attempt {i}: {timer.ElapsedMilliseconds:F}");
yield return timer.ElapsedMilliseconds;
}
}
}
class BookChapter
{
public string Title { get; set; }
public string Content { get; set; }
}
private static IEnumerable<BookChapter> GetBookChapters()
{
var book = File.ReadAllLines("quo-vadis.txt");
var chapterPointers = book
.Select((line, index) => new
{
LineNumber = index,
Text = line
})
.Where(x => x.Text.Length < 50 && x.Text.Contains("Rozdział") || x.Text.Contains("-----"))
.Select(x => x.LineNumber)
.ToList();
foreach (var index in Enumerable.Range(0, chapterPointers.Count - 1))
{
var chapter = chapterPointers[index];
var title = book[chapter];
var lineFrom = chapterPointers[index];
var lineTo = chapterPointers[index + 1] - 1;
var lines = book.Skip(lineFrom + 1).Take(lineTo - lineFrom).Where(x => !string.IsNullOrWhiteSpace(x));
var content = string.Join(Environment.NewLine, lines);
yield return new BookChapter
{
Title = title,
Content = content
};
}
}
private void ComposeBook(IContainer container, ICollection<BookChapter> chapters)
{
var subtitleStyle = TextStyle.Default.Size(24).SemiBold().Color(Colors.Blue.Medium);
var normalStyle = TextStyle.Default.Size(14);
ComposePage(container);
void ComposePage(IContainer container)
{
container
.Padding(50)
.Decoration(decoration =>
{
decoration
.Content()
.Stack(stack =>
{
stack.Item().Element(Title);
stack.Item().PageBreak();
stack.Item().Element(TableOfContents);
stack.Item().PageBreak();
Chapters(stack);
stack.Item().Element(Acknowledgements);
});
decoration.Footer().Element(Footer);
});
}
void Title(IContainer container)
{
container
.Extend()
.PaddingBottom(200)
.AlignBottom()
.Stack(stack =>
{
stack.Item().Text("Quo Vadis", TextStyle.Default.Size(72).Bold().Color(Colors.Blue.Darken2));
stack.Item().Text("Henryk Sienkiewicz", TextStyle.Default.Size(24).Color(Colors.Grey.Darken2));
});
}
void TableOfContents(IContainer container)
{
container.Stack(stack =>
{
SectionTitle(stack, "Spis treści");
foreach (var chapter in chapters)
{
stack.Item().InternalLink(chapter.Title).Row(row =>
{
row.RelativeColumn().Text(chapter.Title, normalStyle);
row.ConstantColumn(100).AlignRight().Text(text => text.PageNumberOfLocation(chapter.Title, normalStyle));
});
}
});
}
void Chapters(StackDescriptor stack)
{
foreach (var chapter in chapters)
{
stack.Item().Element(container => Chapter(container, chapter.Title, chapter.Content));
}
}
void Chapter(IContainer container, string title, string content)
{
container.Stack(stack =>
{
SectionTitle(stack, title);
stack.Item().Text(text =>
{
text.ParagraphSpacing(5);
text.Span(content, normalStyle);
});
stack.Item().PageBreak();
});
}
void Acknowledgements(IContainer container)
{
container.Stack(stack =>
{
SectionTitle(stack, "Podziękowania");
stack.Item().Text(text =>
{
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.Span(". Dziękuję za wspieranie polskiego czytelnictwa!");
});
});
}
void SectionTitle(StackDescriptor stack, string text)
{
stack.Item().Location(text).Text(text, subtitleStyle);
stack.Item().PaddingTop(10).PaddingBottom(50).BorderBottom(1).BorderColor(Colors.Grey.Lighten2).ExtendHorizontal();
}
void Footer(IContainer container)
{
container
.AlignCenter()
.Text(text =>
{
text.CurrentPageNumber();
text.Span(" / ");
text.TotalPages();
});
}
}
}
}
-271
View File
@@ -1,271 +0,0 @@
using System;
using System.Linq;
using System.Text;
using NUnit.Framework;
using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
public class TextExamples
{
[Test]
public void SimpleTextBlock()
{
RenderingTest
.Create()
.PageSize(500, 300)
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Padding(5)
.MinimalBox()
.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)
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Padding(5)
.MinimalBox()
.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)
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Padding(5)
.MinimalBox()
.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)
.ProducePdf()
.ShowResults()
.Render(container =>
{
container
.Padding(20)
.Padding(10)
.MinimalBox()
.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)
.ProducePdf()
.ShowResults()
.Render(container =>
{
container
.Padding(20)
.Padding(10)
.MinimalBox()
.Border(1)
.Padding(5)
.Padding(10)
.Text(text =>
{
text.DefaultTextStyle(TextStyle.Default);
text.AlignLeft();
text.ParagraphSpacing(10);
foreach (var i in Enumerable.Range(1, 100))
text.Line($"{i}: {Placeholders.Paragraph()}");
});
});
}
[Test]
public void SpaceIssue()
{
RenderingTest
.Create()
.PageSize(PageSizes.A4)
.ProducePdf()
.ShowResults()
.Render(container =>
{
container
.Padding(20)
.Padding(10)
.MinimalBox()
.Border(1)
.Padding(5)
.Padding(10)
.Text(text =>
{
text.DefaultTextStyle(TextStyle.Default);
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)
.ProducePdf()
.ShowResults()
.Render(container =>
{
container
.Padding(20)
.Padding(10)
.MinimalBox()
.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();
}
});
});
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

-149
View File
@@ -1,149 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="75.320129mm"
height="92.604164mm"
viewBox="0 0 75.320129 92.604164"
version="1.1"
id="svg8"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="PDF file icon.svg">
<title
id="title2682">PDF file icon</title>
<defs
id="defs2">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath839">
<rect
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
id="rect841"
width="68.688263"
height="67.886459"
x="-74.033661"
y="141.44913" />
</clipPath>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="122.12727"
inkscape:cy="167.02823"
inkscape:document-units="mm"
inkscape:current-layer="g899"
showgrid="false"
inkscape:object-nodes="false"
inkscape:window-width="1366"
inkscape:window-height="705"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:snap-page="false"
inkscape:snap-others="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>PDF file icon</dc:title>
<dc:date>08/10/2018</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Adobe Systems</dc:title>
</cc:Agent>
</dc:creator>
<dc:publisher>
<cc:Agent>
<dc:title>CMetalCore</dc:title>
</cc:Agent>
</dc:publisher>
<dc:description>Fuente del texto &quot;PDF&quot;:
Franklin Gothic Medium Cond</dc:description>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="Capa 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(36.076172,-93.731774)">
<g
id="g899"
transform="matrix(1.4843054,0,0,1.4843054,17.471885,-90.243502)">
<g
id="g876">
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ff2116;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.11666656;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m -29.632812,123.94727 c -3.551967,0 -6.44336,2.89347 -6.44336,6.44531 v 49.49804 c 0,3.55185 2.891393,6.44532 6.44336,6.44532 H 8.2167969 c 3.5519661,0 6.4433591,-2.89335 6.4433591,-6.44532 v -40.70117 c 0,0 0.101353,-1.19181 -0.416015,-2.35156 -0.484969,-1.08711 -1.275391,-1.84375 -1.275391,-1.84375 a 1.0584391,1.0584391 0 0 0 -0.0059,-0.008 L 3.5722246,125.7752 a 1.0584391,1.0584391 0 0 0 -0.015625,-0.0156 c 0,0 -0.8017392,-0.76344 -1.9902344,-1.27344 -1.39939552,-0.6005 -2.8417968,-0.53711 -2.8417968,-0.53711 l 0.021484,-0.002 z"
id="path890" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#f5f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.11666656;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m -29.632812,126.06445 h 28.3789058 a 1.0584391,1.0584391 0 0 0 0.021484,0 c 0,0 1.13480448,0.011 1.96484378,0.36719 0.79889772,0.34282 1.36536982,0.86176 1.36914062,0.86524 1.25e-5,1e-5 0.00391,0.004 0.00391,0.004 l 9.3671868,9.18945 c 0,0 0.564354,0.59582 0.837891,1.20899 0.220779,0.49491 0.234375,1.40039 0.234375,1.40039 a 1.0584391,1.0584391 0 0 0 -0.002,0.0449 v 40.74609 c 0,2.41592 -1.910258,4.32813 -4.3261717,4.32813 H -29.632812 c -2.415914,0 -4.326172,-1.91209 -4.326172,-4.32813 v -49.49804 c 0,-2.41603 1.910258,-4.32813 4.326172,-4.32813 z"
id="rect2684" />
<path
sodipodi:nodetypes="scccscccscccccssscacccsccccccccccccccccccccaccccccccc"
inkscape:connector-curvature="0"
d="m -23.40766,161.09299 c -1.45669,-1.45669 0.11934,-3.45839 4.39648,-5.58397 l 2.69124,-1.33743 1.04845,-2.29399 c 0.57665,-1.26169 1.43729,-3.32036 1.91254,-4.5748 l 0.8641,-2.28082 -0.59546,-1.68793 c -0.73217,-2.07547 -0.99326,-5.19438 -0.52872,-6.31588 0.62923,-1.51909 2.69029,-1.36323 3.50626,0.26515 0.63727,1.27176 0.57212,3.57488 -0.18329,6.47946 l -0.6193,2.38125 0.5455,0.92604 c 0.30003,0.50932 1.1764,1.71867 1.9475,2.68743 l 1.44924,1.80272 1.8033728,-0.23533 c 5.72900399,-0.74758 7.6912472,0.523 7.6912472,2.34476 0,2.29921 -4.4984914,2.48899 -8.2760865,-0.16423 -0.8499666,-0.59698 -1.4336605,-1.19001 -1.4336605,-1.19001 0,0 -2.3665326,0.48178 -3.531704,0.79583 -1.202707,0.32417 -1.80274,0.52719 -3.564509,1.12186 0,0 -0.61814,0.89767 -1.02094,1.55026 -1.49858,2.4279 -3.24833,4.43998 -4.49793,5.1723 -1.3991,0.81993 -2.86584,0.87582 -3.60433,0.13733 z m 2.28605,-0.81668 c 0.81883,-0.50607 2.47616,-2.46625 3.62341,-4.28553 l 0.46449,-0.73658 -2.11497,1.06339 c -3.26655,1.64239 -4.76093,3.19033 -3.98386,4.12664 0.43653,0.52598 0.95874,0.48237 2.01093,-0.16792 z m 21.21809,-5.95578 c 0.80089,-0.56097 0.68463,-1.69142 -0.22082,-2.1472 -0.70466,-0.35471 -1.2726074,-0.42759 -3.1031574,-0.40057 -1.1249,0.0767 -2.9337647,0.3034 -3.2403347,0.37237 0,0 0.993716,0.68678 1.434896,0.93922 0.58731,0.33544 2.0145161,0.95811 3.0565161,1.27706 1.02785,0.31461 1.6224,0.28144 2.0729,-0.0409 z m -8.53152,-3.54594 c -0.4847,-0.50952 -1.30889,-1.57296 -1.83152,-2.3632 -0.68353,-0.89643 -1.02629,-1.52887 -1.02629,-1.52887 0,0 -0.4996,1.60694 -0.90948,2.57394 l -1.27876,3.16076 -0.37075,0.71695 c 0,0 1.971043,-0.64627 2.97389,-0.90822 1.0621668,-0.27744 3.21787,-0.70134 3.21787,-0.70134 z m -2.74938,-11.02573 c 0.12363,-1.0375 0.1761,-2.07346 -0.15724,-2.59587 -0.9246,-1.01077 -2.04057,-0.16787 -1.85154,2.23517 0.0636,0.8084 0.26443,2.19033 0.53292,3.04209 l 0.48817,1.54863 0.34358,-1.16638 c 0.18897,-0.64151 0.47882,-2.02015 0.64411,-3.06364 z"
style="fill:#ff2116;fill-opacity:1;stroke-width:0.26458335"
id="path2697" />
<g
id="g858">
<path
inkscape:connector-curvature="0"
id="path845"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:125%;font-family:'Franklin Gothic Medium Cond';-inkscape-font-specification:'Franklin Gothic Medium Cond';letter-spacing:0px;word-spacing:4.26000023px;fill:#2c2c2c;fill-opacity:1;stroke:none;stroke-width:0.35824656px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -20.930423,167.83862 h 2.364986 q 1.133514,0 1.840213,0.2169 0.706698,0.20991 1.189489,0.9446 0.482795,0.72769 0.482795,1.75625 0,0.94459 -0.391832,1.6233 -0.391833,0.67871 -1.056548,0.97958 -0.65772,0.30087 -2.02913,0.30087 h -0.818651 v 3.72941 h -1.581322 z m 1.581322,1.22447 v 3.33058 h 0.783664 q 1.049552,0 1.44838,-0.39184 0.405826,-0.39183 0.405826,-1.27345 0,-0.65772 -0.265887,-1.06355 -0.265884,-0.41282 -0.587747,-0.50378 -0.314866,-0.098 -1.000572,-0.098 z" />
<path
inkscape:connector-curvature="0"
id="path847"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:125%;font-family:'Franklin Gothic Medium Cond';-inkscape-font-specification:'Franklin Gothic Medium Cond';letter-spacing:0px;word-spacing:4.26000023px;fill:#2c2c2c;fill-opacity:1;stroke:none;stroke-width:0.35824656px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -13.842461,167.83862 h 2.148082 q 1.560333,0 2.4909318,0.55276 0.9375993,0.55276 1.4133973,1.6443 0.482791,1.09153 0.482791,2.42096 0,1.3994 -0.4338151,2.49793 -0.4268149,1.09153 -1.3154348,1.76324 -0.8816233,0.67172 -2.5189212,0.67172 h -2.267031 z m 1.581326,1.26645 v 7.018 h 0.657715 q 1.378411,0 2.001144,-0.9516 0.6227329,-0.95858 0.6227329,-2.5539 0,-3.5125 -2.6238769,-3.5125 z" />
<path
inkscape:connector-curvature="0"
id="path849"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:125%;font-family:'Franklin Gothic Medium Cond';-inkscape-font-specification:'Franklin Gothic Medium Cond';letter-spacing:0px;word-spacing:4.26000023px;fill:#2c2c2c;fill-opacity:1;stroke:none;stroke-width:0.35824656px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -5.7889096,167.83862 h 5.30372941 v 1.26645 H -4.2075842 v 2.85478 h 2.9807225 v 1.26646 h -2.9807225 v 4.16322 h -1.5813254 z" />
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long
+32 -18
View File
@@ -2,11 +2,15 @@ using System;
using System.Collections.Generic;
using System.Linq;
using QuestPDF.Helpers;
using QuestPDF.ReportSample.Layouts;
namespace QuestPDF.ReportSample
{
public static class DataSource
{
public static int SectionCounter { get; set; }
public static int FieldCounter { get; set; }
public static ReportModel GetReport()
{
return new ReportModel
@@ -14,9 +18,9 @@ namespace QuestPDF.ReportSample
Title = "Sample Report Document",
HeaderFields = HeaderFields(),
LogoData = Helpers.GetImage("Logo.png"),
Sections = Enumerable.Range(0, 40).Select(x => GenerateSection()).ToList(),
Photos = Enumerable.Range(0, 25).Select(x => GetReportPhotos()).ToList()
LogoData = Helpers.GetImage("logo.png"),
Sections = Enumerable.Range(0, 8).Select(x => GenerateSection()).ToList(),
Photos = Enumerable.Range(0, 8).Select(x => GetReportPhotos()).ToList()
};
List<ReportHeaderField> HeaderFields()
@@ -37,11 +41,6 @@ namespace QuestPDF.ReportSample
{
Label = "Date",
Value = DateTime.Now.ToString("g")
},
new ReportHeaderField()
{
Label = "Status",
Value = "Completed, found 2 issues"
}
};
}
@@ -49,12 +48,12 @@ namespace QuestPDF.ReportSample
ReportSection GenerateSection()
{
var sectionLength = Helpers.Random.NextDouble() > 0.75
? Helpers.Random.Next(20, 40)
: Helpers.Random.Next(5, 10);
? Helpers.Random.Next(10, 20)
: Helpers.Random.Next(3, 11);
return new ReportSection
{
Title = Placeholders.Label(),
Title = TextPlaceholder.Label(),
Parts = Enumerable.Range(0, sectionLength).Select(x => GetRandomElement()).ToList()
};
}
@@ -63,10 +62,10 @@ namespace QuestPDF.ReportSample
{
var random = Helpers.Random.NextDouble();
if (random < 0.9f)
if (random < 0.8f)
return GetTextElement();
if (random < 0.95f)
if (random < 0.9f)
return GetMapElement();
return GetPhotosElement();
@@ -76,16 +75,19 @@ namespace QuestPDF.ReportSample
{
return new ReportSectionText
{
Label = Placeholders.Label(),
Text = Placeholders.Paragraph()
Label = TextPlaceholder.Label(),
Text = TextPlaceholder.Paragraph()
};
}
ReportSectionMap GetMapElement()
{
var rnd = Helpers.Random.Next(0, 64);
return new ReportSectionMap
{
Label = "Location",
ImageSource = x => Helpers.GetDocumentMap($"{rnd}.jpg"),
Location = Helpers.RandomLocation()
};
}
@@ -95,17 +97,29 @@ namespace QuestPDF.ReportSample
return new ReportSectionPhotos
{
Label = "Photos",
PhotoCount = Helpers.Random.Next(1, 15)
Photos = Enumerable
.Range(0, Helpers.Random.Next(1, 10))
.Select(x => Helpers.Random.Next(0, 128))
.Select(x => Helpers.GetPhoto($"{x}.jpg"))
.ToList()
};
}
ReportPhoto GetReportPhotos()
{
var photoId = Helpers.Random.Next(0, 128);
var mapId = Helpers.Random.Next(0, 64);
return new ReportPhoto()
{
Comments = Placeholders.Sentence(),
PhotoData = Helpers.GetPhoto($"{photoId}.jpg"),
Comments = TextPlaceholder.Paragraph(),
Date = DateTime.Now - TimeSpan.FromDays(Helpers.Random.NextDouble() * 100),
Location = Helpers.RandomLocation()
Location = Helpers.RandomLocation(),
MapContextSource = x => Helpers.GetContextMap($"{mapId}.jpg"),
MapDetailsSource = x => Helpers.GetDetailsMap($"{mapId}.jpg")
};
}
}
+9 -2
View File
@@ -1,15 +1,22 @@
using System;
using System.IO;
using QuestPDF.ReportSample.Layouts;
using SkiaSharp;
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);
public static byte[] GetDocumentMap(string name) => GetImage(Path.Combine("Maps", "Document", name));
public static byte[] GetDetailsMap(string name) => GetImage(Path.Combine("Maps", "Details", name));
public static byte[] GetContextMap(string name) => GetImage(Path.Combine("Maps", "Context", name));
public static byte[] GetPhoto(string name) => GetImage(Path.Combine("Photos", name));
public static byte[] GetImage(string name)
{
var photoPath = GetTestItem(name);
@@ -1,85 +0,0 @@
using QuestPDF.Drawing;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.ReportSample.Layouts
{
public class DifferentHeadersTemplate : IDocument
{
public DocumentMetadata GetMetadata() => DocumentMetadata.Default;
public void Compose(IDocumentContainer container)
{
container
.Page(page =>
{
page.Margin(40);
page.Size(PageSizes.A4);
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().Element(ComposeFooter);
});
}
private void ComposeHeader(IContainer container)
{
container.Background(Colors.Grey.Lighten3).Border(1).Stack(stack =>
{
stack.Item().ShowOnce().Padding(5).AlignMiddle().Row(row =>
{
row.RelativeColumn(2).AlignMiddle().Text("PRIMARY HEADER", TextStyle.Default.Color(Colors.Grey.Darken3).Size(30).Bold());
row.RelativeColumn(1).AlignRight().MinimalBox().AlignMiddle().Background(Colors.Blue.Darken2).Padding(30);
});
stack.Item().SkipOnce().Padding(5).Row(row =>
{
row.RelativeColumn(2).Text("SECONDARY HEADER", TextStyle.Default.Color(Colors.Grey.Darken3).Size(30).Bold());
row.RelativeColumn(1).AlignRight().MinimalBox().Background(Colors.Blue.Lighten4).Padding(15);
});
});
}
private void ComposeContent(IContainer container)
{
container.Stack(stack =>
{
stack.Item().PaddingVertical(80).Text("First");
stack.Item().PageBreak();
stack.Item().PaddingVertical(80).Text("Second");
stack.Item().PageBreak();
stack.Item().PaddingVertical(80).Text("Third");
stack.Item().PageBreak();
});
}
private void ComposeFooter(IContainer container)
{
container.Background(Colors.Grey.Lighten3).Stack(stack =>
{
stack.Item().ShowOnce().Background(Colors.Grey.Lighten3).Row(row =>
{
row.RelativeColumn().Text(x =>
{
x.CurrentPageNumber();
x.Span(" / ");
x.TotalPages();
});
row.RelativeColumn().AlignRight().Text("Footer for header");
});
stack.Item().SkipOnce().Background(Colors.Grey.Lighten3).Row(row =>
{
row.RelativeColumn().Text(x =>
{
x.CurrentPageNumber();
x.Span(" / ");
x.TotalPages();
});
row.RelativeColumn().AlignRight().Text("Footer for every page except header");
});
});
}
}
}
+6 -8
View File
@@ -1,29 +1,27 @@
using System;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.ReportSample.Layouts
{
public static class Helpers
{
static IContainer Cell(this IContainer container, bool background)
static IContainer Cell(this IContainer container, string color)
{
return container
.Border(0.5f)
.BorderColor(Colors.Grey.Lighten1)
.Background(background ? Colors.Grey.Lighten4 : Colors.White)
.Background(color)
.Padding(5);
}
public static IContainer ValueCell(this IContainer container)
public static IContainer LightCell(this IContainer container)
{
return container.Cell(false);
return container.Cell("#0000");
}
public static IContainer LabelCell(this IContainer container)
public static IContainer DarkCell(this IContainer container)
{
return container.Cell(true);
return container.Cell("#1000");
}
public static string Format(this Location location)
@@ -1,20 +0,0 @@
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.ReportSample.Layouts
{
public class ImagePlaceholder : IComponent
{
public static bool Solid { get; set; } = false;
public void Compose(IContainer container)
{
if (Solid)
container.Background(Placeholders.Color());
else
container.Image(Placeholders.Image);
}
}
}
@@ -0,0 +1,31 @@
using System;
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
namespace QuestPDF.ReportSample.Layouts
{
public class ImageTemplate : IComponent
{
private Func<Size, byte[]> Source { get; }
private float AspectRatio { get; }
public ImageTemplate(byte[] source, float aspectRatio = 1.333333f) : this(_ => source, aspectRatio)
{
}
public ImageTemplate(Func<Size, byte[]> source, float aspectRatio = 1.333333f)
{
Source = source;
AspectRatio = aspectRatio;
}
public void Compose(IContainer container)
{
container
.AspectRatio(AspectRatio)
.Background("#EEEEEE")
.Image(Source(Size.Zero));
}
}
}
+21 -20
View File
@@ -1,5 +1,4 @@
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.ReportSample.Layouts
@@ -16,45 +15,47 @@ namespace QuestPDF.ReportSample.Layouts
public void Compose(IContainer container)
{
container
.ShowEntire()
.Stack(stack =>
{
stack.Spacing(5);
stack.Item().Element(PhotoWithMaps);
stack.Item().Element(PhotoDetails);
stack.Element(PhotoWithMaps);
stack.Element(PhotoDetails);
});
}
void PhotoWithMaps(IContainer container)
{
container
.Padding(-3)
.PaddingBottom(3)
.Row(row =>
{
row.RelativeColumn(2).AspectRatio(4 / 3f).Component<ImagePlaceholder>();
row.RelativeColumn(2).Padding(3).Component(new ImageTemplate(Model.PhotoData));
row.RelativeColumn().PaddingLeft(5).Stack(stack =>
row.RelativeColumn().Stack(stack =>
{
stack.Spacing(7f);
stack.Item().AspectRatio(4 / 3f).Component<ImagePlaceholder>();
stack.Item().AspectRatio(4 / 3f).Component<ImagePlaceholder>();
stack.Element().Padding(3).Component(new ImageTemplate(Model.MapDetailsSource));
stack.Element().Padding(3).Component(new ImageTemplate(Model.MapContextSource));
});
});
}
void PhotoDetails(IContainer container)
{
container.Border(0.75f).BorderColor(Colors.Grey.Medium).Grid(grid =>
container.Stack(stack =>
{
grid.Columns(6);
stack.Element().Row(row =>
{
row.RelativeColumn().DarkCell().Text("Date", Typography.Normal);
row.RelativeColumn(2).LightCell().Text(Model.Date?.ToString("g") ?? string.Empty, Typography.Normal);
row.RelativeColumn().DarkCell().Text("Location", Typography.Normal);
row.RelativeColumn(2).LightCell().Text(Model.Location.Format(), Typography.Normal);
});
grid.Item().LabelCell().Text("Date");
grid.Item(2).ValueCell().Text(Model.Date?.ToString("g") ?? string.Empty);
grid.Item().LabelCell().Text("Location");
grid.Item(2).ValueCell().Text(Model.Location.Format());
grid.Item().LabelCell().Text("Comments");
grid.Item(5).ValueCell().Text(Model.Comments);
stack.Element().Row(row =>
{
row.RelativeColumn().DarkCell().Text("Comments", Typography.Normal);
row.RelativeColumn(5).LightCell().Text(Model.Comments, Typography.Normal);
});
});
}
}
@@ -1,6 +1,6 @@
using System;
using System.Linq;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.ReportSample.Layouts
@@ -17,25 +17,25 @@ namespace QuestPDF.ReportSample.Layouts
public void Compose(IContainer container)
{
container
.EnsureSpace()
.Decoration(decoration =>
.MinHeight(100)
.Section(section =>
{
decoration
section
.Header()
.PaddingBottom(5)
.Text(Model.Title, Typography.Headline);
decoration.Content().Border(0.75f).BorderColor(Colors.Grey.Medium).Stack(stack =>
section.Content().PageableStack(stack =>
{
foreach (var part in Model.Parts)
{
stack.Item().EnsureSpace(25).Row(row =>
stack.Element().Row(row =>
{
row.ConstantColumn(150).LabelCell().Text(part.Label);
var frame = row.RelativeColumn().ValueCell();
row.ConstantColumn(150).DarkCell().Text(part.Label, Typography.Normal);
var frame = row.RelativeColumn().LightCell();
if (part is ReportSectionText text)
frame.ShowEntire().Text(text.Text);
frame.Text(text.Text, Typography.Normal);
if (part is ReportSectionMap map)
frame.Element(x => MapElement(x, map));
@@ -50,38 +50,44 @@ namespace QuestPDF.ReportSample.Layouts
void MapElement(IContainer container, ReportSectionMap model)
{
if (model.Location == null)
if (model.ImageSource == null || model.Location == null)
{
container.Text("No location provided");
container.Text("No location provided", Typography.Normal);
return;
}
container.ShowEntire().Stack(stack =>
container.PageableStack(stack =>
{
stack.Spacing(5);
stack.Item().MaxWidth(250).AspectRatio(4 / 3f).Component<ImagePlaceholder>();
stack.Item().Text(model.Location.Format());
stack.Element().Component(new ImageTemplate(model.ImageSource));
stack.Element().Text(model.Location.Format(), Typography.Normal);
});
}
void PhotosElement(IContainer container, ReportSectionPhotos model)
{
if (model.PhotoCount == 0)
if (model.Photos.Count == 0)
{
container.Text("No photos", Typography.Normal);
return;
}
container.DebugArea("Photos").Grid(grid =>
var rowCount = (int) Math.Ceiling(model.Photos.Count / 3f);
container.Debug().Padding(-2).PageableStack(stack =>
{
grid.Spacing(5);
grid.Columns(3);
Enumerable
.Range(0, model.PhotoCount)
.ToList()
.ForEach(x => grid.Item().AspectRatio(4 / 3f).Component<ImagePlaceholder>());
foreach (var rowId in Enumerable.Range(0, rowCount))
{
stack.Element().Row(row =>
{
foreach (var id in Enumerable.Range(0, 3))
{
var data = model.Photos.ElementAtOrDefault(rowId + id);
row.RelativeColumn().Padding(2).Component(new ImageTemplate(data));
}
});
}
});
}
}
+42 -46
View File
@@ -18,83 +18,79 @@ namespace QuestPDF.ReportSample.Layouts
{
return new DocumentMetadata()
{
Title = Model.Title
Title = Model.Title,
Size = PageSizes.A4
};
}
public void Compose(IDocumentContainer container)
public void Compose(IContainer container)
{
container
.PaddingVertical(40)
.PaddingHorizontal(50)
.Page(page =>
{
page.DefaultTextStyle(Typography.Normal);
page.MarginVertical(40);
page.MarginHorizontal(50);
page.Size(PageSizes.A4);
page.Header().Element(ComposeHeader);
page.Content().Element(ComposeContent);
page.Footer().AlignCenter().Text(text =>
{
text.CurrentPageNumber();
text.Span(" / ");
text.TotalPages();
});
page.Header(ComposeHeader);
page.Content(ComposeContent);
page.Footer().AlignCenter().PageNumber("Page {number}");
});
}
private void ComposeHeader(IContainer container)
{
container.Stack(stack =>
container.Row(row =>
{
stack.Item().Row(row =>
row.RelativeColumn().MaxWidth(300).Stack(stack =>
{
row.Spacing(50);
stack.Spacing(5);
row.RelativeColumn().PaddingTop(-10).Text(Model.Title, Typography.Title);
row.ConstantColumn(90).ExternalLink("https://www.questpdf.com").MaxHeight(30).Component<ImagePlaceholder>();
});
stack.Item().ShowOnce().PaddingVertical(15).Border(1f).BorderColor(Colors.Grey.Lighten1).ExtendHorizontal();
stack.Item().ShowOnce().Grid(grid =>
{
grid.Columns(2);
grid.Spacing(5);
foreach (var field in Model.HeaderFields)
stack
.Element()
.PaddingBottom(5)
.Text(Model.Title, Typography.Title);
stack.Element().ShowOnce().Stack(table =>
{
grid.Item().Text(text =>
table.Spacing(5);
foreach (var field in Model.HeaderFields)
{
text.Span($"{field.Label}: ", TextStyle.Default.SemiBold());
text.Span(field.Value);
});
}
table.Element().Row(row =>
{
row.ConstantColumn(50)
.AlignLeft()
.Text($"{field.Label}:", Typography.Normal);
row.RelativeColumn()
.PaddingLeft(10)
.Text(field.Value, Typography.Normal);
});
}
});
});
row.ConstantColumn(150).ExternalLink("https://www.questpdf.com").Image(Model.LogoData);
});
}
void ComposeContent(IContainer container)
{
container.PaddingVertical(20).Stack(stack =>
container.PaddingVertical(20).PageableStack(stack =>
{
stack.Spacing(20);
stack.Item().Component(new TableOfContentsTemplate(Model.Sections));
stack.Item().PageBreak();
stack.Element().Component(new TableOfContentsTemplate(Model.Sections));
foreach (var section in Model.Sections)
stack.Item().Location(section.Title).Component(new SectionTemplate(section));
stack.Element().Location(section.Title).Component(new SectionTemplate(section));
stack.Item().PageBreak();
stack.Item().Location("Photos");
stack.Element().PageBreak();
stack.Element().Location("Photos");
foreach (var photo in Model.Photos)
stack.Item().Component(new PhotoTemplate(photo));
stack.Element().Component(new PhotoTemplate(photo));
});
}
}
@@ -1,4 +1,6 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
@@ -16,21 +18,21 @@ namespace QuestPDF.ReportSample.Layouts
public void Compose(IContainer container)
{
container
.Decoration(decoration =>
.Section(section =>
{
decoration
section
.Header()
.PaddingBottom(5)
.Text("Table of contents", Typography.Headline);
decoration.Content().Stack(stack =>
section.Content().PageableStack(stack =>
{
stack.Spacing(5);
for (var i = 0; i < Sections.Count; i++)
stack.Item().Element(c => DrawLink(c, i+1, Sections[i].Title));
stack.Element(c => DrawLink(c, i+1, Sections[i].Title));
stack.Item().Element(c => DrawLink(c, Sections.Count+1, "Photos"));
stack.Element(c => DrawLink(c, Sections.Count+1, "Photos"));
});
});
}
@@ -41,9 +43,8 @@ namespace QuestPDF.ReportSample.Layouts
.InternalLink(locationName)
.Row(row =>
{
row.ConstantColumn(25).Text($"{number}.");
row.RelativeColumn().Text(locationName);
row.ConstantColumn(150).AlignRight().Text(text => text.PageNumberOfLocation(locationName));
row.ConstantColumn(25).Text($"{number}.", Typography.Normal);
row.RelativeColumn().Text(locationName, Typography.Normal);
});
}
}
+8 -2
View File
@@ -44,16 +44,22 @@ namespace QuestPDF.ReportSample
public class ReportSectionMap : ReportSectionElement
{
public Func<Size, byte[]> ImageSource { get; set; }
public Location Location { get; set; }
}
public class ReportSectionPhotos : ReportSectionElement
{
public int PhotoCount { get; set; }
public List<byte[]> Photos { get; set; }
}
public class ReportPhoto
{
{
public byte[] PhotoData { get; set; }
public Func<Size, byte[]> MapDetailsSource { get; set; }
public Func<Size, byte[]> MapContextSource { get; set; }
public Location Location { get; set; }
public DateTime? Date { get; set; }
-75
View File
@@ -1,75 +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.Helpers;
using QuestPDF.Infrastructure;
using QuestPDF.ReportSample.Layouts;
namespace QuestPDF.ReportSample
{
[SimpleJob(RunStrategy.Monitoring, launchCount: 0, warmupCount: 1, targetCount: 256)]
[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()
{
ImagePlaceholder.Solid = true;
var configuration = ManualConfig
.Create(DefaultConfig.Instance)
.WithOptions(ConfigOptions.DisableOptimizationsValidator);
BenchmarkRunner.Run<PerformanceTests>(configuration);
}
[IterationSetup]
public void GenerateReportData()
{
ImagePlaceholder.Solid = true;
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.VisitChildren(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,14 +8,19 @@
</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>
<Folder Include="Resources" />
</ItemGroup>
<ItemGroup>
<Content Include="Resources\Photos\readme.txt" />
<Content Include="Resources\**\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -24,8 +29,4 @@
<ItemGroup>
<ProjectReference Include="..\QuestPDF\QuestPDF.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\Logo.png" />
</ItemGroup>
</Project>
Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

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