Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fc33056434 | |||
| d3e8386418 |
@@ -1 +0,0 @@
|
||||
github: QuestPDF
|
||||
@@ -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
|
||||
@@ -1,54 +0,0 @@
|
||||
name: Build And Create Nuget Package
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '3 0 * * 0'
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ${{ matrix.environment }}
|
||||
strategy:
|
||||
matrix:
|
||||
environment:
|
||||
- macos-latest
|
||||
- ubuntu-latest
|
||||
- windows-latest
|
||||
env:
|
||||
DOTNET_NOLOGO: 1
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
|
||||
UNIT_TEST_PROJECT: QuestPDF.UnitTests/QuestPDF.UnitTests.csproj
|
||||
|
||||
steps:
|
||||
- name: 📝 Fetch Sources 📝
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: ⚙ Setup .NET 6.0 SDK ⚙
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '6.0.x'
|
||||
|
||||
- name: 🔄 Restore Nuget Packages 🔄
|
||||
shell: bash
|
||||
run: dotnet restore
|
||||
working-directory: ./Source
|
||||
|
||||
- name: 🛠 Build Solution 🛠
|
||||
shell: bash
|
||||
run: dotnet build -c Release --no-restore
|
||||
working-directory: ./Source
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
if: ${{ matrix.environment == 'windows-latest' }}
|
||||
with:
|
||||
name: Build Package
|
||||
path: |
|
||||
**/*.nupkg
|
||||
**/*.snupkg
|
||||
!.nuget
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 QuestPDF
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,13 +0,0 @@
|
||||
# QuestPDF Community MIT License
|
||||
|
||||
|
||||
## License Permissions
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
## Copyright
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
|
||||
## Limitation Of Liability
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,29 +0,0 @@
|
||||
# QuestPDF Professional And Enterprise Use License
|
||||
|
||||
|
||||
## Do No Harm
|
||||
By downloading or using the Software, the Licensee agrees not to utilize the software in a manner which is disparaging to QuestPDF, and not to rent, lease or otherwise transfer rights to the Software.
|
||||
|
||||
|
||||
## License Permissions
|
||||
Grants the use of the Software by a specified number of developers to create and deploy closed-source software for unlimited end user organizations ("The Organization") in multiple locations. This license covers unlimited applications or projects. The Software may be deployed upon any number of machines for the end-use of The Organization. This license also intrinsically covers for development, staging and production servers for each project.
|
||||
|
||||
Grants the use of the Software by a specified number of developers to create and deploy closed-source software for unlimited end user organizations ("The Organization") in multiple locations. This license covers unlimited applications or projects. The Software may be deployed upon any number of machines for the end-use of The Organization. This license also intrinsically covers for development, staging and production servers for each project.
|
||||
|
||||
|
||||
## License Fees
|
||||
A. If you wish to use the Software in a production environment, you may download and use the Software for one year upon payment of the appropriate license fee as indicated on the pricing page in accordance with the terms and conditions of this Agreement.
|
||||
|
||||
B. If you wish to use the Software in a non-production environment, you may download and access the source and/or binaries at no charge solely for testing and evaluation purposes and in accordance with all license limitations and restrictions set forth in this Agreement.
|
||||
|
||||
|
||||
## Ownership
|
||||
QuestPDF shall at all times retain ownership of the QuestPDF Software library and all subsequent copies.
|
||||
|
||||
|
||||
## Copyright
|
||||
Title, ownership rights, and intellectual property rights in and to the Software shall remain with QuestPDF. The Software is protected by the international copyright laws. Title, ownership rights, and intellectual property rights in and to the content accessed through the Software is the property of the applicable content owner and may be protected by applicable copyright or other law. This License gives you no rights to such content.
|
||||
|
||||
|
||||
## Limitation Of Liability
|
||||
THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. QUESTPDF AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL QUESTPDF OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF QUESTPDF HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
@@ -1,23 +0,0 @@
|
||||
# What License Do You Need?
|
||||
|
||||
## General License Overview
|
||||
|
||||
Open-source projects are an important foundation for the software development ecosystem. Modern applications are depending more and more upon the work of enthusiast and experts. Open-source is not anymore just sharing knowledge and passion with everybody. Over last years, maintaining and developing those projects have became a highly responsible task.
|
||||
|
||||
We identify the importance of the QuestPDF library in your projects, and therefore want to make sure you can safely and confidently continue the development. We strongly believe that a dual-licensing model is the best solution for all users: providing the best development experience and feature set for everybody and every project, but also offering stability for every professional and enterprise product.
|
||||
|
||||
Being a healthy and growing community is our primary goal that motivates us to pursue professionalism.
|
||||
|
||||
[Read more about exact terms](https://www.questpdf.com/pricing.html)
|
||||
|
||||
|
||||
## QuestPDF Professional Or Enterprise Use License
|
||||
|
||||
If you are consuming the QuestPDF library as a Direct Package Dependency for usage in a Closed Source software in the capacity of a for-profit company/individual with more than 1M USD annual gross revenue, you must purchase the `QuestPDF Professional or Enterprise` License, depending on number of software developers. [Read more](https://www.questpdf.com/license-commercial.html)
|
||||
|
||||
|
||||
## QuestPDF Community MIT License
|
||||
|
||||
We love and highly appreciate the .NET Community and therefore the vast majority of users are welcome to use the library completely for free. If you do not meet the criteria described above, you are eligible to use the `QuestPDF Community MIT` License, without any limitations, even for commercial usage. [Read more](https://www.questpdf.com/license-community.html)
|
||||
|
||||
If you still want to support library development, please consider purchasing the Professional License.
|
||||
@@ -8,16 +8,17 @@ using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Examples
|
||||
{
|
||||
public class BarcodeExamples
|
||||
public class BarCode
|
||||
{
|
||||
[Test]
|
||||
public void Example()
|
||||
{
|
||||
FontManager.RegisterFont(File.OpenRead("LibreBarcode39-Regular.ttf"));
|
||||
FontManager.RegisterFontType("LibreBarcode39", File.OpenRead("LibreBarcode39-Regular.ttf"));
|
||||
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(400, 200)
|
||||
.PageSize(400, 100)
|
||||
.FileName()
|
||||
.ShowResults()
|
||||
.Render(container =>
|
||||
{
|
||||
@@ -25,9 +26,7 @@ namespace QuestPDF.Examples
|
||||
.Background(Colors.White)
|
||||
.AlignCenter()
|
||||
.AlignMiddle()
|
||||
.Text("*QuestPDF*")
|
||||
.FontFamily("Libre Barcode 39")
|
||||
.FontSize(64);
|
||||
.Text("*QuestPDF*", TextStyle.Default.FontType("LibreBarcode39").Size(64));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Examples.Engine;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Examples
|
||||
{
|
||||
[TestFixture]
|
||||
public class BarcodeExamples
|
||||
{
|
||||
[Test]
|
||||
public void Barcode()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 300)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(25)
|
||||
.Stack(stack =>
|
||||
{
|
||||
stack.Item().Border(1).Background(Colors.Grey.Lighten3).Padding(5).Text("Barcode Example");
|
||||
stack.Item().Border(1).Padding(5).AlignCenter().Text("*123456789*", TextStyle.Default.FontType("CarolinaBar-Demo-25E2").Size(20));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,10 +22,10 @@ namespace QuestPDF.Examples
|
||||
|
||||
page.Header().Text("Header");
|
||||
|
||||
page.Content().PaddingVertical(10).Border(1).Padding(10).Column(column =>
|
||||
page.Content().PaddingVertical(10).Border(1).Padding(10).Stack(stack =>
|
||||
{
|
||||
foreach (var index in Enumerable.Range(1, 100))
|
||||
column.Item().Text($"Line {index}").FontColor(Placeholders.Color());
|
||||
stack.Item().Text($"Line {index}", TextStyle.Default.Color(Placeholders.Color()));
|
||||
});
|
||||
|
||||
page.Footer().Text("Footer");
|
||||
@@ -0,0 +1,33 @@
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Examples.Engine;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
|
||||
namespace QuestPDF.Examples
|
||||
{
|
||||
public class DebuggingTesting
|
||||
{
|
||||
[Test]
|
||||
public void Stack()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(500, 360)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Background(Colors.White)
|
||||
.Padding(15)
|
||||
.Grid(grid =>
|
||||
{
|
||||
grid.Spacing(15);
|
||||
|
||||
grid.Item().Background(Colors.Grey.Medium).Text(Placeholders.LoremIpsum());
|
||||
grid.Item().DebugPointer("Test").Background(Colors.Grey.Lighten1).Height(1000); // <-- problem
|
||||
grid.Item().Background(Colors.Grey.Lighten2).Height(150);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
-63
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Elements;
|
||||
@@ -16,29 +15,25 @@ namespace QuestPDF.Examples
|
||||
public int Price { get; set; } = Placeholders.Random.Next(1, 11) * 10;
|
||||
public int Count { get; set; } = Placeholders.Random.Next(1, 11);
|
||||
}
|
||||
|
||||
public struct OrdersTableState
|
||||
{
|
||||
public int ShownItemsCount { get; set; }
|
||||
}
|
||||
|
||||
public class OptimizedOrdersTable : IDynamicComponent<OrdersTableState>
|
||||
public class OrdersTable : IDynamicComponent
|
||||
{
|
||||
private ICollection<OrderItem> Items { get; }
|
||||
public OrdersTableState State { get; set; }
|
||||
|
||||
public OptimizedOrdersTable(ICollection<OrderItem> items)
|
||||
private ICollection<OrderItem> ItemsLeft { get; set; }
|
||||
|
||||
public OrdersTable(ICollection<OrderItem> items)
|
||||
{
|
||||
Items = items;
|
||||
|
||||
State = new OrdersTableState
|
||||
{
|
||||
ShownItemsCount = 0
|
||||
};
|
||||
}
|
||||
|
||||
public DynamicComponentComposeResult Compose(DynamicContext context)
|
||||
public void Compose(DynamicContext context, IDynamicContainer container)
|
||||
{
|
||||
if (context.Operation == DynamicLayoutOperation.Reset)
|
||||
{
|
||||
ItemsLeft = new List<OrderItem>(Items);
|
||||
return;
|
||||
}
|
||||
|
||||
var header = ComposeHeader(context);
|
||||
var sampleFooter = ComposeFooter(context, Enumerable.Empty<OrderItem>());
|
||||
var decorationHeight = header.Size.Height + sampleFooter.Size.Height;
|
||||
@@ -46,32 +41,24 @@ namespace QuestPDF.Examples
|
||||
var rows = GetItemsForPage(context, decorationHeight).ToList();
|
||||
var footer = ComposeFooter(context, rows.Select(x => x.Item));
|
||||
|
||||
var content = context.CreateElement(container =>
|
||||
if (ItemsLeft.Count > rows.Count)
|
||||
container.HasMoreContent();
|
||||
|
||||
if (context.Operation == DynamicLayoutOperation.Draw)
|
||||
ItemsLeft = ItemsLeft.Skip(rows.Count).ToList();
|
||||
|
||||
container.Box().Decoration(decoration =>
|
||||
{
|
||||
container.MinimalBox().Decoration(decoration =>
|
||||
decoration.Header().Element(header);
|
||||
|
||||
decoration.Content().Box().Stack(stack =>
|
||||
{
|
||||
decoration.Before().Element(header);
|
||||
|
||||
decoration.Content().Column(column =>
|
||||
{
|
||||
foreach (var row in rows)
|
||||
column.Item().Element(row.Element);
|
||||
});
|
||||
|
||||
decoration.After().Element(footer);
|
||||
foreach (var row in rows)
|
||||
stack.Item().Element(row.Element);
|
||||
});
|
||||
|
||||
decoration.Footer().Element(footer);
|
||||
});
|
||||
|
||||
State = new OrdersTableState
|
||||
{
|
||||
ShownItemsCount = State.ShownItemsCount + rows.Count
|
||||
};
|
||||
|
||||
return new DynamicComponentComposeResult
|
||||
{
|
||||
Content = content,
|
||||
HasMoreContent = State.ShownItemsCount < Items.Count
|
||||
};
|
||||
}
|
||||
|
||||
private IDynamicElement ComposeHeader(DynamicContext context)
|
||||
@@ -79,18 +66,18 @@ namespace QuestPDF.Examples
|
||||
return context.CreateElement(element =>
|
||||
{
|
||||
element
|
||||
.Width(context.AvailableSize.Width)
|
||||
.BorderBottom(1)
|
||||
.BorderColor(Colors.Grey.Darken2)
|
||||
.Padding(5)
|
||||
.DefaultTextStyle(TextStyle.Default.SemiBold())
|
||||
.Row(row =>
|
||||
{
|
||||
row.ConstantItem(30).Text("#");
|
||||
row.RelativeItem().Text("Item name");
|
||||
row.ConstantItem(50).AlignRight().Text("Count");
|
||||
row.ConstantItem(50).AlignRight().Text("Price");
|
||||
row.ConstantItem(50).AlignRight().Text("Total");
|
||||
var textStyle = TextStyle.Default.SemiBold();
|
||||
|
||||
row.ConstantColumn(30).Text("#", textStyle);
|
||||
row.RelativeColumn().Text("Item name", textStyle);
|
||||
row.ConstantColumn(50).AlignRight().Text("Count", textStyle);
|
||||
row.ConstantColumn(50).AlignRight().Text("Price", textStyle);
|
||||
row.ConstantColumn(50).AlignRight().Text("Total", textStyle);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -102,36 +89,32 @@ namespace QuestPDF.Examples
|
||||
return context.CreateElement(element =>
|
||||
{
|
||||
element
|
||||
.Width(context.AvailableSize.Width)
|
||||
.Padding(5)
|
||||
.AlignRight()
|
||||
.DefaultTextStyle(TextStyle.Default.FontSize(14).SemiBold())
|
||||
.Text($"Subtotal: {total}$");
|
||||
.Text($"Subtotal: {total}$", TextStyle.Default.Size(14).SemiBold());
|
||||
});
|
||||
}
|
||||
|
||||
private IEnumerable<(OrderItem Item, IDynamicElement Element)> GetItemsForPage(DynamicContext context, float decorationHeight)
|
||||
{
|
||||
var totalHeight = decorationHeight;
|
||||
|
||||
foreach (var index in Enumerable.Range(State.ShownItemsCount, Items.Count - State.ShownItemsCount))
|
||||
var counter = Items.Count - ItemsLeft.Count + 1;
|
||||
|
||||
foreach (var orderItem in ItemsLeft)
|
||||
{
|
||||
var item = Items.ElementAt(index);
|
||||
|
||||
var element = context.CreateElement(content =>
|
||||
{
|
||||
content
|
||||
.Width(context.AvailableSize.Width)
|
||||
.BorderBottom(1)
|
||||
.BorderColor(Colors.Grey.Lighten2)
|
||||
.Padding(5)
|
||||
.Row(row =>
|
||||
{
|
||||
row.ConstantItem(30).Text((index + 1).ToString(CultureInfo.InvariantCulture));
|
||||
row.RelativeItem().Text(item.ItemName);
|
||||
row.ConstantItem(50).AlignRight().Text(item.Count.ToString(CultureInfo.InvariantCulture));
|
||||
row.ConstantItem(50).AlignRight().Text($"{item.Price}$");
|
||||
row.ConstantItem(50).AlignRight().Text($"{item.Count*item.Price}$");
|
||||
row.ConstantColumn(30).Text(counter++);
|
||||
row.RelativeColumn().Text(orderItem.ItemName);
|
||||
row.ConstantColumn(50).AlignRight().Text(orderItem.Count);
|
||||
row.ConstantColumn(50).AlignRight().Text($"{orderItem.Price}$");
|
||||
row.ConstantColumn(50).AlignRight().Text($"{orderItem.Count*orderItem.Price}$");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -141,12 +124,12 @@ namespace QuestPDF.Examples
|
||||
break;
|
||||
|
||||
totalHeight += elementHeight;
|
||||
yield return (item, element);
|
||||
yield return (orderItem, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class DynamicOptimizedExamples
|
||||
public static class DynamicExamples
|
||||
{
|
||||
[Test]
|
||||
public static void Dynamic()
|
||||
@@ -154,6 +137,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(PageSizes.A5)
|
||||
.FileName()
|
||||
.ShowResults()
|
||||
.Render(container =>
|
||||
{
|
||||
@@ -165,11 +149,11 @@ namespace QuestPDF.Examples
|
||||
.Decoration(decoration =>
|
||||
{
|
||||
decoration
|
||||
.Before()
|
||||
.Header()
|
||||
.PaddingBottom(5)
|
||||
.Text(text =>
|
||||
{
|
||||
text.DefaultTextStyle(TextStyle.Default.SemiBold().FontColor(Colors.Blue.Darken2).FontSize(16));
|
||||
text.DefaultTextStyle(TextStyle.Default.SemiBold().Color(Colors.Blue.Darken2).Size(16));
|
||||
text.Span("Page ");
|
||||
text.CurrentPageNumber();
|
||||
text.Span(" of ");
|
||||
@@ -178,7 +162,7 @@ namespace QuestPDF.Examples
|
||||
|
||||
decoration
|
||||
.Content()
|
||||
.Dynamic(new OptimizedOrdersTable(items));
|
||||
.Dynamic(new OrdersTable(items));
|
||||
});
|
||||
});
|
||||
}
|
||||
+87
-74
@@ -17,6 +17,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(200, 150)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -32,6 +33,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 300)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -40,12 +42,10 @@ namespace QuestPDF.Examples
|
||||
.Decoration(decoration =>
|
||||
{
|
||||
decoration
|
||||
.Before()
|
||||
.Header()
|
||||
.Background(Colors.Grey.Medium)
|
||||
.Padding(10)
|
||||
.Text("Notes")
|
||||
.FontSize(16)
|
||||
.FontColor("#FFF");
|
||||
.Text("Notes", TextStyle.Default.Size(16).Color("#FFF"));
|
||||
|
||||
decoration
|
||||
.Content()
|
||||
@@ -63,32 +63,33 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(740, 200)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(20)
|
||||
.Column(column =>
|
||||
.Stack(stack =>
|
||||
{
|
||||
column.Item()
|
||||
stack.Item()
|
||||
.PaddingBottom(10)
|
||||
.AlignCenter()
|
||||
.Text("This Row element is 700pt wide");
|
||||
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.ConstantItem(100)
|
||||
row.ConstantColumn(100)
|
||||
.Background(Colors.Grey.Lighten1)
|
||||
.Padding(10)
|
||||
.ExtendVertical()
|
||||
.Text("This column is 100 pt wide");
|
||||
|
||||
row.RelativeItem()
|
||||
row.RelativeColumn()
|
||||
.Background(Colors.Grey.Lighten2)
|
||||
.Padding(10)
|
||||
.Text("This column takes 1/3 of the available space (200pt)");
|
||||
|
||||
row.RelativeItem(2)
|
||||
row.RelativeColumn(2)
|
||||
.Background(Colors.Grey.Lighten3)
|
||||
.Padding(10)
|
||||
.Text("This column takes 2/3 of the available space (400pt)");
|
||||
@@ -103,6 +104,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(740, 200)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -111,31 +113,32 @@ namespace QuestPDF.Examples
|
||||
.Row(row =>
|
||||
{
|
||||
row.Spacing(20);
|
||||
row.RelativeItem(2).Border(1).Background(Colors.Grey.Lighten1);
|
||||
row.RelativeItem(3).Border(1).Background(Colors.Grey.Lighten2);
|
||||
row.RelativeItem(4).Border(1).Background(Colors.Grey.Lighten3);
|
||||
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 column()
|
||||
public void Stack()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(500, 360)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(15)
|
||||
.Column(column =>
|
||||
.Stack(stack =>
|
||||
{
|
||||
column.Spacing(15);
|
||||
stack.Spacing(15);
|
||||
|
||||
column.Item().Background(Colors.Grey.Medium).Height(50);
|
||||
column.Item().Background(Colors.Grey.Lighten1).Height(100);
|
||||
column.Item().Background(Colors.Grey.Lighten2).Height(150);
|
||||
stack.Item().Background(Colors.Grey.Medium).Height(50);
|
||||
stack.Item().Background(Colors.Grey.Lighten1).Height(100);
|
||||
stack.Item().Background(Colors.Grey.Lighten2).Height(150);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -146,6 +149,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(210, 210)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -168,6 +172,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 200)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
var text = "";
|
||||
@@ -190,6 +195,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(400, 230)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
var textStyle = TextStyle.Default.Size(14);
|
||||
@@ -224,6 +230,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 200)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -253,6 +260,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(400, 250)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -269,12 +277,12 @@ namespace QuestPDF.Examples
|
||||
layers
|
||||
.PrimaryLayer()
|
||||
.Padding(25)
|
||||
.Column(column =>
|
||||
.Stack(stack =>
|
||||
{
|
||||
column.Spacing(5);
|
||||
stack.Spacing(5);
|
||||
|
||||
foreach (var _ in Enumerable.Range(0, 7))
|
||||
column.Item().Text(Placeholders.Sentence());
|
||||
stack.Item().Text(Placeholders.Sentence());
|
||||
});
|
||||
|
||||
// layer above the main content
|
||||
@@ -282,15 +290,12 @@ namespace QuestPDF.Examples
|
||||
.Layer()
|
||||
.AlignCenter()
|
||||
.AlignMiddle()
|
||||
.Text("Watermark")
|
||||
.FontSize(48)
|
||||
.Bold()
|
||||
.FontColor(Colors.Green.Lighten3);
|
||||
.Text("Watermark", TextStyle.Default.Size(48).Bold().Color(Colors.Green.Lighten3));
|
||||
|
||||
layers
|
||||
.Layer()
|
||||
.AlignBottom()
|
||||
.Text(text => text.CurrentPageNumber().FontSize(16).FontColor(Colors.Green.Medium));
|
||||
.Text(text => text.CurrentPageNumber(TextStyle.Default.Size(16).Color(Colors.Green.Medium)));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -309,16 +314,16 @@ namespace QuestPDF.Examples
|
||||
// {
|
||||
// page.Header().PageNumber("Page {pdf:currentPage}");
|
||||
//
|
||||
// page.Content().Height(300).column(content =>
|
||||
// page.Content().Height(300).Stack(content =>
|
||||
// {
|
||||
// content.Item().Height(200).Background(Colors.Grey.Lighten2);
|
||||
//
|
||||
// content.Item().EnsureSpace(100).column(column =>
|
||||
// content.Item().EnsureSpace(100).Stack(stack =>
|
||||
// {
|
||||
// column.Spacing(10);
|
||||
// stack.Spacing(10);
|
||||
//
|
||||
// foreach (var _ in Enumerable.Range(0, 4))
|
||||
// column.Item().Height(50).Background(Colors.Green.Lighten1);
|
||||
// stack.Item().Height(50).Background(Colors.Green.Lighten1);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
@@ -331,6 +336,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 300)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -375,6 +381,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(450, 150)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -383,7 +390,7 @@ namespace QuestPDF.Examples
|
||||
.Row(row =>
|
||||
{
|
||||
foreach (var color in colors)
|
||||
row.RelativeItem().Background(color);
|
||||
row.RelativeColumn().Background(color);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -407,6 +414,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(500, 175)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -421,9 +429,7 @@ namespace QuestPDF.Examples
|
||||
.Border(1)
|
||||
.BorderColor(Colors.Grey.Medium)
|
||||
.Padding(10)
|
||||
.Text(font)
|
||||
.FontFamily(font)
|
||||
.FontSize(16);
|
||||
.Text(font, TextStyle.Default.FontType(font).Size(16));
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -435,6 +441,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 300)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -444,10 +451,10 @@ namespace QuestPDF.Examples
|
||||
{
|
||||
layers.Layer().Text("Something else");
|
||||
|
||||
layers.PrimaryLayer().Column(column =>
|
||||
layers.PrimaryLayer().Stack(stack =>
|
||||
{
|
||||
column.Item().PaddingTop(20).Text("Text 1");
|
||||
column.Item().PaddingTop(40).Text("Text 2");
|
||||
stack.Item().PaddingTop(20).Text("Text 1");
|
||||
stack.Item().PaddingTop(40).Text("Text 2");
|
||||
});
|
||||
|
||||
layers.Layer().Canvas((canvas, size) =>
|
||||
@@ -463,7 +470,7 @@ namespace QuestPDF.Examples
|
||||
});
|
||||
|
||||
layers.Layer().Background("#8F00").Extend();
|
||||
layers.Layer().PaddingTop(40).Text("It works!").FontSize(24);
|
||||
layers.Layer().PaddingTop(40).Text("It works!", TextStyle.Default.Size(24));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -474,6 +481,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 150)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -481,10 +489,10 @@ namespace QuestPDF.Examples
|
||||
.Padding(15)
|
||||
.Border(4)
|
||||
.BorderColor(Colors.Blue.Medium)
|
||||
//.MinimalBox()
|
||||
//.Box()
|
||||
.Background(Colors.Grey.Lighten2)
|
||||
.Padding(15)
|
||||
.Text("Test of the \n box element").FontSize(20);
|
||||
.Text("Test of the \n box element", TextStyle.Default.Size(20));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -494,6 +502,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 175)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -508,14 +517,13 @@ namespace QuestPDF.Examples
|
||||
.SemiBold();
|
||||
|
||||
decoration
|
||||
.Before()
|
||||
.Header()
|
||||
.PaddingBottom(10)
|
||||
.Text("Example: scale component")
|
||||
.Style(headerFontStyle);
|
||||
.Text("Example: scale component", headerFontStyle);
|
||||
|
||||
decoration
|
||||
.Content()
|
||||
.Column(column =>
|
||||
.Stack(stack =>
|
||||
{
|
||||
var scales = new[] { 0.8f, 0.9f, 1.1f, 1.2f };
|
||||
|
||||
@@ -527,14 +535,13 @@ namespace QuestPDF.Examples
|
||||
|
||||
var fontStyle = TextStyle.Default.Size(16);
|
||||
|
||||
column
|
||||
stack
|
||||
.Item()
|
||||
.Border(1)
|
||||
.Background(fontColor)
|
||||
.Scale(scale)
|
||||
.Padding(5)
|
||||
.Text($"Content with {scale} scale.")
|
||||
.Style(fontStyle);
|
||||
.Text($"Content with {scale} scale.", fontStyle);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -547,11 +554,12 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 200)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.MinimalBox()
|
||||
.Box()
|
||||
|
||||
.Padding(25)
|
||||
|
||||
@@ -564,8 +572,7 @@ namespace QuestPDF.Examples
|
||||
.BorderColor(Colors.Green.Darken1)
|
||||
|
||||
.Padding(50)
|
||||
.Text("Moved text")
|
||||
.FontSize(25);
|
||||
.Text("Moved text", TextStyle.Default.Size(25));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -575,6 +582,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(650, 450)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -598,11 +606,10 @@ namespace QuestPDF.Examples
|
||||
|
||||
return element;
|
||||
})
|
||||
.MinimalBox()
|
||||
.Box()
|
||||
.Background(Colors.White)
|
||||
.Padding(10)
|
||||
.Text($"Rotated {turns * 90}°")
|
||||
.FontSize(16);
|
||||
.Text($"Rotated {turns * 90}°", TextStyle.Default.Size(16));
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -614,6 +621,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 300)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -640,6 +648,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 300)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -671,6 +680,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(350, 350)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -697,11 +707,10 @@ namespace QuestPDF.Examples
|
||||
|
||||
return element;
|
||||
})
|
||||
.MinimalBox()
|
||||
.Box()
|
||||
.Background(Colors.White)
|
||||
.Padding(10)
|
||||
.Text($"Flipped {turns}")
|
||||
.FontSize(16);
|
||||
.Text($"Flipped {turns}", TextStyle.Default.Size(16));
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -713,6 +722,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(200, 200)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -720,14 +730,14 @@ namespace QuestPDF.Examples
|
||||
.Border(2)
|
||||
.Row(row =>
|
||||
{
|
||||
row.ConstantItem(25)
|
||||
row.ConstantColumn(25)
|
||||
.Border(1)
|
||||
.RotateLeft()
|
||||
.AlignCenter()
|
||||
.AlignMiddle()
|
||||
.Text("Sample text");
|
||||
|
||||
row.RelativeItem().Border(1).Padding(5).Text(Placeholders.Paragraph());
|
||||
row.RelativeColumn().Border(1).Padding(5).Text(Placeholders.Paragraph());
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -738,16 +748,17 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(400, 350)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(25)
|
||||
.PaddingLeft(50)
|
||||
.Column(column =>
|
||||
.PaddingLeft(75)
|
||||
.Stack(stack =>
|
||||
{
|
||||
column.Item().Width(300).Height(150).Background(Colors.Blue.Lighten4);
|
||||
stack.Item().Width(300).Height(150).Background(Colors.Blue.Lighten4);
|
||||
|
||||
column
|
||||
stack
|
||||
.Item()
|
||||
|
||||
// creates an infinite space for its child
|
||||
@@ -763,7 +774,7 @@ namespace QuestPDF.Examples
|
||||
|
||||
.Background(Colors.Blue.Darken1);
|
||||
|
||||
column.Item().Width(300).Height(150).Background(Colors.Blue.Lighten3);
|
||||
stack.Item().Width(300).Height(150).Background(Colors.Blue.Lighten3);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -774,17 +785,18 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(500, 225)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(25)
|
||||
.Column(column =>
|
||||
.Stack(stack =>
|
||||
{
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeItem().LabelCell("Label 1");
|
||||
row.RelativeColumn().LabelCell("Label 1");
|
||||
|
||||
row.RelativeItem(3).Grid(grid =>
|
||||
row.RelativeColumn(3).Grid(grid =>
|
||||
{
|
||||
grid.Columns(3);
|
||||
|
||||
@@ -796,11 +808,11 @@ namespace QuestPDF.Examples
|
||||
});
|
||||
});
|
||||
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeItem().ValueCell().Text("Value 1");
|
||||
row.RelativeColumn().ValueCell().Text("Value 1");
|
||||
|
||||
row.RelativeItem(3).Grid(grid =>
|
||||
row.RelativeColumn(3).Grid(grid =>
|
||||
{
|
||||
grid.Columns(3);
|
||||
|
||||
@@ -812,10 +824,10 @@ namespace QuestPDF.Examples
|
||||
});
|
||||
});
|
||||
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeItem().LabelCell("Label 6");
|
||||
row.RelativeItem().ValueCell().Text("Value 6");
|
||||
row.RelativeColumn().LabelCell("Label 6");
|
||||
row.RelativeColumn().ValueCell().Text("Value 6");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -827,6 +839,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(600, 310)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
+9
-47
@@ -3,7 +3,6 @@ using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using QuestPDF.Elements;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Examples.Engine
|
||||
@@ -18,25 +17,20 @@ namespace QuestPDF.Examples.Engine
|
||||
{
|
||||
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 bool ShowingResultsEnabled = true;
|
||||
|
||||
private RenderingTest()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static RenderingTest Create([CallerMemberName] string fileName = "test")
|
||||
public static RenderingTest Create()
|
||||
{
|
||||
return new RenderingTest().FileName(fileName);
|
||||
return new RenderingTest();
|
||||
}
|
||||
|
||||
public RenderingTest FileName(string fileName)
|
||||
public RenderingTest FileName([CallerMemberName] string fileName = "test")
|
||||
{
|
||||
FileNamePrefix = fileName;
|
||||
return this;
|
||||
@@ -71,52 +65,20 @@ namespace QuestPDF.Examples.Engine
|
||||
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);
|
||||
});
|
||||
});
|
||||
}
|
||||
var container = new Container();
|
||||
content(container);
|
||||
|
||||
public void RenderDocument(Action<IDocumentContainer> content)
|
||||
{
|
||||
MaxPagesThreshold ??= ResultType == RenderingTestResult.Pdf ? 1000 : 10;
|
||||
var document = new SimpleDocument(content, MaxPagesThreshold.Value, ApplyCaching, ApplyDebugging);
|
||||
var maxPages = ResultType == RenderingTestResult.Pdf ? 1000 : 10;
|
||||
var document = new SimpleDocument(container, Size, maxPages);
|
||||
|
||||
Render(document);
|
||||
}
|
||||
|
||||
private void Render(IDocument document)
|
||||
{
|
||||
if (ResultType == RenderingTestResult.Images)
|
||||
{
|
||||
Func<int, string> fileNameSchema = i => $"{FileNamePrefix}-${i}.png";
|
||||
document.GenerateImages(fileNameSchema);
|
||||
|
||||
if (ShowResult && ShowingResultsEnabled)
|
||||
if (ShowResult)
|
||||
Process.Start("explorer", fileNameSchema(0));
|
||||
}
|
||||
|
||||
@@ -125,7 +87,7 @@ namespace QuestPDF.Examples.Engine
|
||||
var fileName = $"{FileNamePrefix}.pdf";
|
||||
document.GeneratePdf(fileName);
|
||||
|
||||
if (ShowResult && ShowingResultsEnabled)
|
||||
if (ShowResult)
|
||||
Process.Start("explorer", fileName);
|
||||
}
|
||||
}
|
||||
+12
-13
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Elements;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
@@ -11,17 +10,15 @@ namespace QuestPDF.Examples.Engine
|
||||
{
|
||||
public const int ImageScalingFactor = 2;
|
||||
|
||||
private Action<IDocumentContainer> Content { get; }
|
||||
private IContainer Container { get; }
|
||||
private Size Size { get; }
|
||||
private int MaxPages { get; }
|
||||
private bool ApplyCaching { get; }
|
||||
private bool ApplyDebugging { get; }
|
||||
|
||||
public SimpleDocument(Action<IDocumentContainer> content, int maxPages, bool applyCaching, bool applyDebugging)
|
||||
public SimpleDocument(IContainer container, Size size, int maxPages)
|
||||
{
|
||||
Content = content;
|
||||
Container = container;
|
||||
Size = size;
|
||||
MaxPages = maxPages;
|
||||
ApplyCaching = applyCaching;
|
||||
ApplyDebugging = applyDebugging;
|
||||
}
|
||||
|
||||
public DocumentMetadata GetMetadata()
|
||||
@@ -29,15 +26,17 @@ namespace QuestPDF.Examples.Engine
|
||||
return new DocumentMetadata()
|
||||
{
|
||||
RasterDpi = PageSizes.PointsPerInch * ImageScalingFactor,
|
||||
DocumentLayoutExceptionThreshold = MaxPages,
|
||||
ApplyCaching = ApplyCaching,
|
||||
ApplyDebugging = ApplyDebugging
|
||||
DocumentLayoutExceptionThreshold = MaxPages
|
||||
};
|
||||
}
|
||||
|
||||
public void Compose(IDocumentContainer container)
|
||||
{
|
||||
Content(container);
|
||||
container.Page(page =>
|
||||
{
|
||||
page.Size(new PageSize(Size.Width, Size.Height));
|
||||
page.Content().Container().Background(Colors.White).Element(Container as Container);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,14 +12,12 @@ namespace QuestPDF.Examples
|
||||
{
|
||||
return container
|
||||
.Border(1)
|
||||
.BorderColor(Colors.Grey.Medium)
|
||||
.Background(dark ? Colors.Grey.Lighten3 : Colors.White)
|
||||
.Padding(5);
|
||||
.Background(dark ? Colors.Grey.Lighten2 : Colors.White)
|
||||
.Padding(10);
|
||||
}
|
||||
|
||||
public static void LabelCell(this IContainer container, string text) => container.Cell(true).Text(text).SemiBold();
|
||||
public static void LabelCell(this IContainer container, string text) => container.Cell(true).Text(text, TextStyle.Default.Medium());
|
||||
public static IContainer ValueCell(this IContainer container) => container.Cell(false);
|
||||
public static void ValueCell(this IContainer container, string text) => container.ValueCell().Text(text);
|
||||
}
|
||||
|
||||
public class FrameExample
|
||||
@@ -30,20 +28,21 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(550, 400)
|
||||
.FileName()
|
||||
.ShowResults()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(25)
|
||||
.Column(column =>
|
||||
.Stack(stack =>
|
||||
{
|
||||
for(var i = 1; i <= 4; i++)
|
||||
for(var i=1; i<=4; i++)
|
||||
{
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeItem(2).LabelCell(Placeholders.Label());
|
||||
row.RelativeItem(3).ValueCell().Text(Placeholders.Paragraph());
|
||||
row.RelativeColumn(2).LabelCell(Placeholders.Label());
|
||||
row.RelativeColumn(3).ValueCell().Text(Placeholders.Paragraph());
|
||||
});
|
||||
}
|
||||
});
|
||||
+4
-7
@@ -19,12 +19,10 @@ namespace QuestPDF.Examples
|
||||
{
|
||||
var url = "https://picsum.photos/300/200";
|
||||
|
||||
if (Greyscale)
|
||||
if(Greyscale)
|
||||
url += "?grayscale";
|
||||
|
||||
using var client = new WebClient();
|
||||
client.Headers.Add("user-agent", "QuestPDF/1.0 Unit Testing");
|
||||
|
||||
var response = client.DownloadData(url);
|
||||
container.Image(response);
|
||||
}
|
||||
@@ -38,14 +36,13 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(350, 280)
|
||||
.ProducePdf()
|
||||
.ShowResults()
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Background("#FFF")
|
||||
.Padding(25)
|
||||
.Column(column =>
|
||||
.Stack(column =>
|
||||
{
|
||||
column.Spacing(10);
|
||||
|
||||
@@ -61,4 +58,4 @@ namespace QuestPDF.Examples
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(300, 300)
|
||||
.FileName()
|
||||
.ShowResults()
|
||||
.Render(container =>
|
||||
{
|
||||
@@ -36,6 +37,7 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(200, 150)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
@@ -50,8 +52,7 @@ namespace QuestPDF.Examples
|
||||
.Background("FFF")
|
||||
.Padding(5)
|
||||
.AlignCenter()
|
||||
.Text("Sample text")
|
||||
.FontFamily("Segoe UI emoji");
|
||||
.Text("Sample text", TextStyle.Default.FontType("Segoe UI emoji"));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -61,10 +62,11 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(200, 150)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Column(column =>
|
||||
.Stack(column =>
|
||||
{
|
||||
column
|
||||
.Item()
|
||||
@@ -111,17 +113,18 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(200, 150)
|
||||
.FileName()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Column(column =>
|
||||
.Stack(column =>
|
||||
{
|
||||
column
|
||||
.Item()
|
||||
.Height(150)
|
||||
.Row(row =>
|
||||
{
|
||||
row.RelativeItem()
|
||||
row.RelativeColumn()
|
||||
.Extend()
|
||||
.Background("FFF")
|
||||
|
||||
@@ -129,7 +132,7 @@ namespace QuestPDF.Examples
|
||||
.Width(50)
|
||||
.Background("444");
|
||||
|
||||
row.RelativeItem()
|
||||
row.RelativeColumn()
|
||||
.Extend()
|
||||
.Background("BBB")
|
||||
|
||||
@@ -143,7 +146,7 @@ namespace QuestPDF.Examples
|
||||
.Height(150)
|
||||
.Row(row =>
|
||||
{
|
||||
row.RelativeItem()
|
||||
row.RelativeColumn()
|
||||
.Extend()
|
||||
.Background("BBB")
|
||||
|
||||
@@ -151,7 +154,7 @@ namespace QuestPDF.Examples
|
||||
.Width(50)
|
||||
.Background("444");
|
||||
|
||||
row.RelativeItem()
|
||||
row.RelativeColumn()
|
||||
.Extend()
|
||||
.Background("BBB")
|
||||
|
||||
+8
-10
@@ -3,15 +3,13 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<LangVersion>9</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.8.0" />
|
||||
<PackageReference Include="nunit" Version="3.13.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.88.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.80.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -19,12 +17,12 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Resources\FontContent.ttf">
|
||||
<None Update="quo-vadis.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="LibreBarcode39-Regular.ttf">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<EmbeddedResource Include="Resources\FontEmbeddedResource.ttf">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -21,9 +21,10 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(PageSizes.A4)
|
||||
.FileName()
|
||||
.ProducePdf()
|
||||
.ShowResults()
|
||||
.RenderDocument(x => ComposeBook(x, chapters));
|
||||
.Render(x => ComposeBook(x, chapters));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -31,7 +32,7 @@ namespace QuestPDF.Examples
|
||||
{
|
||||
var chapters = GetBookChapters().ToList();
|
||||
|
||||
var results = PerformTest(128).ToList();
|
||||
var results = PerformTest(16).ToList();
|
||||
|
||||
Console.WriteLine($"Min: {results.Min():F}");
|
||||
Console.WriteLine($"Max: {results.Max():F}");
|
||||
@@ -42,8 +43,9 @@ namespace QuestPDF.Examples
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(PageSizes.A4)
|
||||
.FileName()
|
||||
.ProducePdf()
|
||||
.RenderDocument(x => ComposeBook(x, chapters));
|
||||
.Render(x => ComposeBook(x, chapters));
|
||||
}
|
||||
|
||||
IEnumerable<float> PerformTest(int attempts)
|
||||
@@ -102,105 +104,112 @@ namespace QuestPDF.Examples
|
||||
}
|
||||
}
|
||||
|
||||
private void ComposeBook(IDocumentContainer container, ICollection<BookChapter> chapters)
|
||||
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);
|
||||
|
||||
container.Page(page =>
|
||||
void ComposePage(IContainer container)
|
||||
{
|
||||
page.Margin(50);
|
||||
|
||||
page.Content().PaddingVertical(10).Column(column =>
|
||||
{
|
||||
column.Item().Element(Title);
|
||||
column.Item().PageBreak();
|
||||
column.Item().Element(TableOfContents);
|
||||
column.Item().PageBreak();
|
||||
container
|
||||
.Padding(50)
|
||||
.Decoration(decoration =>
|
||||
{
|
||||
decoration
|
||||
.Content()
|
||||
.Stack(stack =>
|
||||
{
|
||||
stack.Item().Element(Title);
|
||||
stack.Item().PageBreak();
|
||||
stack.Item().Element(TableOfContents);
|
||||
stack.Item().PageBreak();
|
||||
|
||||
Chapters(column);
|
||||
Chapters(stack);
|
||||
|
||||
column.Item().Element(Acknowledgements);
|
||||
});
|
||||
|
||||
page.Footer().Element(Footer);
|
||||
});
|
||||
stack.Item().Element(Acknowledgements);
|
||||
});
|
||||
|
||||
decoration.Footer().Element(Footer);
|
||||
});
|
||||
}
|
||||
|
||||
void Title(IContainer container)
|
||||
{
|
||||
container
|
||||
.Extend()
|
||||
.PaddingBottom(200)
|
||||
.AlignBottom()
|
||||
.Column(column =>
|
||||
.Stack(stack =>
|
||||
{
|
||||
column.Item().Text("Quo Vadis").FontSize(72).Bold().FontColor(Colors.Blue.Darken2);
|
||||
column.Item().Text("Henryk Sienkiewicz").FontSize(24).FontColor(Colors.Grey.Darken2);
|
||||
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.Column(column =>
|
||||
container.Stack(stack =>
|
||||
{
|
||||
SectionTitle(column, "Spis treści");
|
||||
SectionTitle(stack, "Spis treści");
|
||||
|
||||
foreach (var chapter in chapters)
|
||||
{
|
||||
column.Item().InternalLink(chapter.Title).Row(row =>
|
||||
stack.Item().InternalLink(chapter.Title).Row(row =>
|
||||
{
|
||||
row.RelativeItem().Text(chapter.Title).Style(normalStyle);
|
||||
row.ConstantItem(100).AlignRight().Text(text => text.BeginPageNumberOfSection(chapter.Title).Style(normalStyle));
|
||||
row.RelativeColumn().Text(chapter.Title, normalStyle);
|
||||
row.ConstantColumn(100).AlignRight().Text(text => text.PageNumberOfLocation(chapter.Title, normalStyle));
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Chapters(ColumnDescriptor column)
|
||||
void Chapters(StackDescriptor stack)
|
||||
{
|
||||
foreach (var chapter in chapters)
|
||||
{
|
||||
column.Item().Element(container => Chapter(container, chapter.Title, chapter.Content));
|
||||
stack.Item().Element(container => Chapter(container, chapter.Title, chapter.Content));
|
||||
}
|
||||
}
|
||||
|
||||
void Chapter(IContainer container, string title, string content)
|
||||
{
|
||||
container.Column(column =>
|
||||
container.Stack(stack =>
|
||||
{
|
||||
SectionTitle(column, title);
|
||||
SectionTitle(stack, title);
|
||||
|
||||
column.Item().Text(text =>
|
||||
stack.Item().Text(text =>
|
||||
{
|
||||
text.ParagraphSpacing(5);
|
||||
text.Span(content).Style(normalStyle);
|
||||
text.Span(content, normalStyle);
|
||||
});
|
||||
|
||||
column.Item().PageBreak();
|
||||
stack.Item().PageBreak();
|
||||
});
|
||||
}
|
||||
|
||||
void Acknowledgements(IContainer container)
|
||||
{
|
||||
container.Column(column =>
|
||||
container.Stack(stack =>
|
||||
{
|
||||
SectionTitle(column, "Podziękowania");
|
||||
SectionTitle(stack, "Podziękowania");
|
||||
|
||||
column.Item().Text(text =>
|
||||
stack.Item().Text(text =>
|
||||
{
|
||||
text.DefaultTextStyle(normalStyle);
|
||||
|
||||
text.Span("Ten dokument został wygenerowany na podstawie książki w formacie TXT opublikowanej w serwisie ");
|
||||
text.Hyperlink("wolnelektury.pl", "https://wolnelektury.pl/").FontColor(Colors.Blue.Medium).Underline();
|
||||
text.ExternalLocation("wolnelektury.pl", "https://wolnelektury.pl/", normalStyle.Color(Colors.Blue.Medium).Underline());
|
||||
text.Span(". Dziękuję za wspieranie polskiego czytelnictwa!");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void SectionTitle(ColumnDescriptor column, string text)
|
||||
void SectionTitle(StackDescriptor stack, string text)
|
||||
{
|
||||
column.Item().Location(text).Text(text).Style(subtitleStyle);
|
||||
column.Item().PaddingTop(10).PaddingBottom(50).BorderBottom(1).BorderColor(Colors.Grey.Lighten2).ExtendHorizontal();
|
||||
stack.Item().Location(text).Text(text, subtitleStyle);
|
||||
stack.Item().PaddingTop(10).PaddingBottom(50).BorderBottom(1).BorderColor(Colors.Grey.Lighten2).ExtendHorizontal();
|
||||
}
|
||||
|
||||
void Footer(IContainer container)
|
||||
@@ -0,0 +1,277 @@
|
||||
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)
|
||||
.FileName()
|
||||
.ProduceImages()
|
||||
.ShowResults()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(5)
|
||||
.Box()
|
||||
.Border(1)
|
||||
.Padding(10)
|
||||
.Text(text =>
|
||||
{
|
||||
text.DefaultTextStyle(TextStyle.Default.Size(20));
|
||||
text.Span("This is a normal text, followed by an ");
|
||||
text.Span("underlined red text.", TextStyle.Default.Size(20).Color(Colors.Red.Medium).Underline());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParagraphSpacing()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(500, 300)
|
||||
.FileName()
|
||||
.ProduceImages()
|
||||
.ShowResults()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(5)
|
||||
.Box()
|
||||
.Border(1)
|
||||
.Padding(10)
|
||||
.Text(text =>
|
||||
{
|
||||
text.ParagraphSpacing(10);
|
||||
|
||||
foreach (var i in Enumerable.Range(1, 3))
|
||||
{
|
||||
text.Span($"Paragraph {i}: ", TextStyle.Default.SemiBold());
|
||||
text.Line(Placeholders.Paragraph());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CustomElement()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(500, 200)
|
||||
.FileName()
|
||||
.ProduceImages()
|
||||
.ShowResults()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(5)
|
||||
.Box()
|
||||
.Border(1)
|
||||
.Padding(10)
|
||||
.Text(text =>
|
||||
{
|
||||
text.DefaultTextStyle(TextStyle.Default.Size(20));
|
||||
text.Span("This is a random image aligned to the baseline: ");
|
||||
|
||||
text.Element()
|
||||
.PaddingBottom(-6)
|
||||
.Height(24)
|
||||
.Width(48)
|
||||
.Image(Placeholders.Image);
|
||||
|
||||
text.Span(".");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TextElements()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(PageSizes.A4)
|
||||
.FileName()
|
||||
.ProducePdf()
|
||||
.ShowResults()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(20)
|
||||
.Padding(10)
|
||||
.Box()
|
||||
.Border(1)
|
||||
.Padding(5)
|
||||
.Padding(10)
|
||||
.Text(text =>
|
||||
{
|
||||
text.DefaultTextStyle(TextStyle.Default);
|
||||
text.AlignLeft();
|
||||
text.ParagraphSpacing(10);
|
||||
|
||||
text.Line(Placeholders.LoremIpsum());
|
||||
|
||||
text.Span($"This is target text that should show up. {DateTime.UtcNow:T} > This is a short sentence that will be wrapped into second line hopefully, right? <", TextStyle.Default.Underline());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TextStack()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(PageSizes.A4)
|
||||
.FileName()
|
||||
.ProducePdf()
|
||||
.ShowResults()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(20)
|
||||
.Padding(10)
|
||||
.Box()
|
||||
.Border(1)
|
||||
.Padding(5)
|
||||
.Padding(10)
|
||||
.Text(text =>
|
||||
{
|
||||
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)
|
||||
.FileName()
|
||||
.ProducePdf()
|
||||
.ShowResults()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(20)
|
||||
.Padding(10)
|
||||
.Box()
|
||||
.Border(1)
|
||||
.Padding(5)
|
||||
.Padding(10)
|
||||
.Text(text =>
|
||||
{
|
||||
text.DefaultTextStyle(TextStyle.Default);
|
||||
text.AlignLeft();
|
||||
text.ParagraphSpacing(10);
|
||||
|
||||
text.Span(Placeholders.LoremIpsum());
|
||||
|
||||
text.EmptyLine();
|
||||
|
||||
text.Span("This text is a normal text, ");
|
||||
text.Span("this is a bold text, ", TextStyle.Default.Bold());
|
||||
text.Span("this is a red and underlined text, ", TextStyle.Default.Color(Colors.Red.Medium).Underline());
|
||||
text.Span("and this is slightly bigger text.", TextStyle.Default.Size(16));
|
||||
|
||||
text.EmptyLine();
|
||||
|
||||
text.Span("The new text element also supports injecting custom content between words: ");
|
||||
text.Element().PaddingBottom(-10).Height(16).Width(32).Image(Placeholders.Image);
|
||||
text.Span(".");
|
||||
|
||||
text.EmptyLine();
|
||||
|
||||
text.Span("This is page number ");
|
||||
text.CurrentPageNumber();
|
||||
text.Span(" out of ");
|
||||
text.TotalPages();
|
||||
|
||||
text.EmptyLine();
|
||||
|
||||
text.ExternalLocation("Please visit QuestPDF website", "https://www.questpdf.com");
|
||||
|
||||
text.EmptyLine();
|
||||
|
||||
text.Span(Placeholders.Paragraphs());
|
||||
|
||||
|
||||
text.EmptyLine();
|
||||
|
||||
text.Span(Placeholders.Paragraphs(), TextStyle.Default.Italic());
|
||||
|
||||
text.Line("This is target text that does not show up. " + Placeholders.Paragraph());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HugeList()
|
||||
{
|
||||
RenderingTest
|
||||
.Create()
|
||||
.PageSize(PageSizes.A4)
|
||||
.FileName()
|
||||
.ProducePdf()
|
||||
.ShowResults()
|
||||
.Render(container =>
|
||||
{
|
||||
container
|
||||
.Padding(20)
|
||||
.Padding(10)
|
||||
.Box()
|
||||
.Border(1)
|
||||
.Padding(5)
|
||||
.Padding(10)
|
||||
.Text(text =>
|
||||
{
|
||||
text.DefaultTextStyle(TextStyle.Default);
|
||||
text.AlignLeft();
|
||||
text.ParagraphSpacing(10);
|
||||
|
||||
text.Span("This text is a normal text, ");
|
||||
text.Span("this is a bold text, ", TextStyle.Default.Bold());
|
||||
text.Span("this is a red and underlined text, ", TextStyle.Default.Color(Colors.Red.Medium).Underline());
|
||||
text.Span("and this is slightly bigger text.", TextStyle.Default.Size(16));
|
||||
|
||||
text.Span("The new text element also supports injecting custom content between words: ");
|
||||
text.Element().PaddingBottom(-10).Height(16).Width(32).Image(Placeholders.Image);
|
||||
text.Span(".");
|
||||
|
||||
text.EmptyLine();
|
||||
|
||||
foreach (var i in Enumerable.Range(1, 100))
|
||||
{
|
||||
text.Line($"{i}: {Placeholders.Paragraph()}");
|
||||
|
||||
text.ExternalLocation("Please visit QuestPDF website", "https://www.questpdf.com");
|
||||
|
||||
text.Span("This is page number ");
|
||||
text.CurrentPageNumber();
|
||||
text.Span(" out of ");
|
||||
text.TotalPages();
|
||||
|
||||
text.EmptyLine();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,9 @@ 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
|
||||
@@ -86,6 +89,7 @@ namespace QuestPDF.ReportSample
|
||||
return new ReportSectionMap
|
||||
{
|
||||
Label = "Location",
|
||||
ImageSource = Placeholders.Image,
|
||||
Location = Helpers.RandomLocation()
|
||||
};
|
||||
}
|
||||
@@ -95,7 +99,10 @@ namespace QuestPDF.ReportSample
|
||||
return new ReportSectionPhotos
|
||||
{
|
||||
Label = "Photos",
|
||||
PhotoCount = Helpers.Random.Next(1, 15)
|
||||
Photos = Enumerable
|
||||
.Range(0, Helpers.Random.Next(1, 15))
|
||||
.Select(x => Placeholders.Image(400, 300))
|
||||
.ToList()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -103,9 +110,14 @@ namespace QuestPDF.ReportSample
|
||||
{
|
||||
return new ReportPhoto()
|
||||
{
|
||||
PhotoData = Placeholders.Image(800, 600),
|
||||
|
||||
Comments = Placeholders.Sentence(),
|
||||
Date = DateTime.Now - TimeSpan.FromDays(Helpers.Random.NextDouble() * 100),
|
||||
Location = Helpers.RandomLocation()
|
||||
Location = Helpers.RandomLocation(),
|
||||
|
||||
MapContextSource = x => Placeholders.Image(400, 300),
|
||||
MapDetailsSource = x => Placeholders.Image(400, 300)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace QuestPDF.ReportSample
|
||||
{
|
||||
public static class Helpers
|
||||
{
|
||||
public static Random Random { get; } = new Random(1);
|
||||
|
||||
public static string GetTestItem(string path) => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources", path);
|
||||
|
||||
public static byte[] GetImage(string name)
|
||||
{
|
||||
var photoPath = GetTestItem(name);
|
||||
return SKImage.FromEncodedData(photoPath).EncodedData.ToArray();
|
||||
}
|
||||
|
||||
public static Location RandomLocation()
|
||||
{
|
||||
return new Location
|
||||
{
|
||||
Longitude = Helpers.Random.NextDouble() * 360f - 180f,
|
||||
Latitude = Helpers.Random.NextDouble() * 180f - 90f
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
-17
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
@@ -18,11 +17,11 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
{
|
||||
container
|
||||
.ShowEntire()
|
||||
.Column(column =>
|
||||
.Stack(stack =>
|
||||
{
|
||||
column.Spacing(5);
|
||||
column.Item().Element(PhotoWithMaps);
|
||||
column.Item().Element(PhotoDetails);
|
||||
stack.Spacing(5);
|
||||
stack.Item().Element(PhotoWithMaps);
|
||||
stack.Item().Element(PhotoDetails);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -31,14 +30,14 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
container
|
||||
.Row(row =>
|
||||
{
|
||||
row.RelativeItem(2).AspectRatio(4 / 3f).Component<ImagePlaceholder>();
|
||||
row.RelativeColumn(2).AspectRatio(4 / 3f).Background(Colors.Grey.Lighten3);
|
||||
|
||||
row.RelativeItem().PaddingLeft(5).Column(column =>
|
||||
row.RelativeColumn().PaddingLeft(5).Stack(stack =>
|
||||
{
|
||||
column.Spacing(7f);
|
||||
stack.Spacing(7f);
|
||||
|
||||
column.Item().AspectRatio(4 / 3f).Component<ImagePlaceholder>();
|
||||
column.Item().AspectRatio(4 / 3f).Component<ImagePlaceholder>();
|
||||
stack.Item().AspectRatio(4 / 3f).Background(Colors.Grey.Lighten3);
|
||||
stack.Item().AspectRatio(4 / 3f).Background(Colors.Grey.Lighten3);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -48,14 +47,14 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
container.Border(0.75f).BorderColor(Colors.Grey.Medium).Grid(grid =>
|
||||
{
|
||||
grid.Columns(6);
|
||||
|
||||
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);
|
||||
grid.Item().LabelCell().Text("Date", Typography.Normal);
|
||||
grid.Item(2).ValueCell().Text(Model.Date?.ToString("g") ?? string.Empty, Typography.Normal);
|
||||
grid.Item().LabelCell().Text("Location", Typography.Normal);
|
||||
grid.Item(2).ValueCell().Text(Model.Location.Format(), Typography.Normal);
|
||||
|
||||
grid.Item().LabelCell().Text("Comments", Typography.Normal);
|
||||
grid.Item(5).ValueCell().Text(Model.Comments, Typography.Normal);
|
||||
});
|
||||
}
|
||||
}
|
||||
+18
-23
@@ -1,4 +1,3 @@
|
||||
using System.Linq;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
@@ -21,26 +20,25 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
.Decoration(decoration =>
|
||||
{
|
||||
decoration
|
||||
.Before()
|
||||
.Header()
|
||||
.PaddingBottom(5)
|
||||
.Text(Model.Title)
|
||||
.Style(Typography.Headline);
|
||||
.Text(Model.Title, Typography.Headline);
|
||||
|
||||
decoration.Content().Border(0.75f).BorderColor(Colors.Grey.Medium).Column(column =>
|
||||
decoration.Content().Border(0.75f).BorderColor(Colors.Grey.Medium).Stack(stack =>
|
||||
{
|
||||
foreach (var part in Model.Parts)
|
||||
{
|
||||
column.Item().EnsureSpace(25).Row(row =>
|
||||
stack.Item().EnsureSpace(25).Row(row =>
|
||||
{
|
||||
row.ConstantItem(150).LabelCell().Text(part.Label);
|
||||
var frame = row.RelativeItem().ValueCell();
|
||||
row.ConstantColumn(150).LabelCell().Text(part.Label, Typography.Normal);
|
||||
var frame = row.RelativeColumn().ValueCell();
|
||||
|
||||
if (part is ReportSectionText text)
|
||||
frame.ShowEntire().Text(text.Text);
|
||||
|
||||
frame.ShowEntire().Text(text.Text, Typography.Normal);
|
||||
|
||||
if (part is ReportSectionMap map)
|
||||
frame.Element(x => MapElement(x, map));
|
||||
|
||||
|
||||
if (part is ReportSectionPhotos photos)
|
||||
frame.Element(x => PhotosElement(x, photos));
|
||||
});
|
||||
@@ -51,26 +49,26 @@ 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().Column(column =>
|
||||
container.ShowEntire().Stack(stack =>
|
||||
{
|
||||
column.Spacing(5);
|
||||
stack.Spacing(5);
|
||||
|
||||
column.Item().MaxWidth(250).AspectRatio(4 / 3f).Component<ImagePlaceholder>();
|
||||
column.Item().Text(model.Location.Format());
|
||||
stack.Item().MaxWidth(250).AspectRatio(4 / 3f).Background(Colors.Grey.Lighten3);
|
||||
stack.Item().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").Style(Typography.Normal);
|
||||
container.Text("No photos", Typography.Normal);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -79,10 +77,7 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
grid.Spacing(5);
|
||||
grid.Columns(3);
|
||||
|
||||
Enumerable
|
||||
.Range(0, model.PhotoCount)
|
||||
.ToList()
|
||||
.ForEach(x => grid.Item().AspectRatio(4 / 3f).Component<ImagePlaceholder>());
|
||||
model.Photos.ForEach(x => grid.Item().AspectRatio(4 / 3f).Background(Colors.Grey.Lighten3));
|
||||
});
|
||||
}
|
||||
}
|
||||
+23
-23
@@ -27,8 +27,6 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
container
|
||||
.Page(page =>
|
||||
{
|
||||
page.DefaultTextStyle(Typography.Normal);
|
||||
|
||||
page.MarginVertical(40);
|
||||
page.MarginHorizontal(50);
|
||||
|
||||
@@ -39,28 +37,30 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
|
||||
page.Footer().AlignCenter().Text(text =>
|
||||
{
|
||||
text.CurrentPageNumber().Format(x => x?.FormatAsRomanNumeral() ?? "-----");
|
||||
text.DefaultTextStyle(Typography.Normal);
|
||||
|
||||
text.CurrentPageNumber();
|
||||
text.Span(" / ");
|
||||
text.TotalPages().Format(x => x?.FormatAsRomanNumeral() ?? "-----");
|
||||
text.TotalPages();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void ComposeHeader(IContainer container)
|
||||
{
|
||||
container.Column(column =>
|
||||
container.Stack(stack =>
|
||||
{
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.Spacing(50);
|
||||
|
||||
row.RelativeItem().PaddingTop(-10).Text(Model.Title).Style(Typography.Title);
|
||||
row.ConstantItem(90).Hyperlink("https://www.questpdf.com").MaxHeight(30).Component<ImagePlaceholder>();
|
||||
row.RelativeColumn().PaddingTop(-10).Text(Model.Title, Typography.Title);
|
||||
row.ConstantColumn(150).ExternalLink("https://www.questpdf.com").Background(Colors.Grey.Lighten3);
|
||||
});
|
||||
|
||||
column.Item().ShowOnce().PaddingVertical(15).Border(1f).BorderColor(Colors.Grey.Lighten1).ExtendHorizontal();
|
||||
stack.Item().ShowOnce().PaddingVertical(15).Border(1f).BorderColor(Colors.Grey.Lighten1).ExtendHorizontal();
|
||||
|
||||
column.Item().ShowOnce().Grid(grid =>
|
||||
stack.Item().ShowOnce().Grid(grid =>
|
||||
{
|
||||
grid.Columns(2);
|
||||
grid.Spacing(5);
|
||||
@@ -69,8 +69,8 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
{
|
||||
grid.Item().Text(text =>
|
||||
{
|
||||
text.Span($"{field.Label}: ").SemiBold();
|
||||
text.Span(field.Value);
|
||||
text.Span($"{field.Label}: ", Typography.Normal.SemiBold());
|
||||
text.Span(field.Value, Typography.Normal);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -79,23 +79,23 @@ namespace QuestPDF.ReportSample.Layouts
|
||||
|
||||
void ComposeContent(IContainer container)
|
||||
{
|
||||
container.PaddingVertical(20).Column(column =>
|
||||
container.PaddingVertical(20).Stack(stack =>
|
||||
{
|
||||
column.Spacing(20);
|
||||
stack.Spacing(20);
|
||||
|
||||
stack.Item().Component(new TableOfContentsTemplate(Model.Sections));
|
||||
|
||||
column.Item().Component(new TableOfContentsTemplate(Model.Sections));
|
||||
|
||||
column.Item().PageBreak();
|
||||
stack.Item().PageBreak();
|
||||
|
||||
foreach (var section in Model.Sections)
|
||||
column.Item().Section(section.Title).Component(new SectionTemplate(section));
|
||||
|
||||
column.Item().PageBreak();
|
||||
column.Item().Section("Photos");
|
||||
stack.Item().Location(section.Title).Component(new SectionTemplate(section));
|
||||
|
||||
stack.Item().PageBreak();
|
||||
stack.Item().Location("Photos");
|
||||
|
||||
foreach (var photo in Model.Photos)
|
||||
column.Item().Component(new PhotoTemplate(photo));
|
||||
stack.Item().Component(new PhotoTemplate(photo));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.ReportSample.Layouts
|
||||
{
|
||||
public class TableOfContentsTemplate : IComponent
|
||||
{
|
||||
private List<ReportSection> Sections { get; }
|
||||
|
||||
public TableOfContentsTemplate(List<ReportSection> sections)
|
||||
{
|
||||
Sections = sections;
|
||||
}
|
||||
|
||||
public void Compose(IContainer container)
|
||||
{
|
||||
container
|
||||
.Decoration(decoration =>
|
||||
{
|
||||
decoration
|
||||
.Header()
|
||||
.PaddingBottom(5)
|
||||
.Text("Table of contents", Typography.Headline);
|
||||
|
||||
decoration.Content().Stack(stack =>
|
||||
{
|
||||
stack.Spacing(5);
|
||||
|
||||
for (var i = 0; i < Sections.Count; i++)
|
||||
stack.Item().Element(c => DrawLink(c, i+1, Sections[i].Title));
|
||||
|
||||
stack.Item().Element(c => DrawLink(c, Sections.Count+1, "Photos"));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void DrawLink(IContainer container, int number, string locationName)
|
||||
{
|
||||
container
|
||||
.InternalLink(locationName)
|
||||
.Row(row =>
|
||||
{
|
||||
row.ConstantColumn(25).Text($"{number}.", Typography.Normal);
|
||||
row.RelativeColumn().Text(locationName, Typography.Normal);
|
||||
row.ConstantColumn(150).AlignRight().Text(text => text.PageNumberOfLocation(locationName, Typography.Normal));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Engines;
|
||||
using BenchmarkDotNet.Running;
|
||||
using Microsoft.VisualStudio.TestPlatform.TestHost;
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Drawing.Proxy;
|
||||
using QuestPDF.Elements;
|
||||
using QuestPDF.Infrastructure;
|
||||
using QuestPDF.ReportSample.Layouts;
|
||||
|
||||
namespace QuestPDF.ReportSample
|
||||
{
|
||||
[SimpleJob(RunStrategy.Monitoring, launchCount: 0, warmupCount: 1, targetCount: 100)]
|
||||
[MinColumn, MaxColumn, MeanColumn, MedianColumn]
|
||||
public class PerformanceTests
|
||||
{
|
||||
private PageContext PageContext { get; set; }
|
||||
private DocumentMetadata Metadata { get; set; }
|
||||
private Container Content { get; set; }
|
||||
|
||||
[Test]
|
||||
public void Run()
|
||||
{
|
||||
var configuration = ManualConfig
|
||||
.Create(DefaultConfig.Instance)
|
||||
.WithOptions(ConfigOptions.DisableOptimizationsValidator);
|
||||
|
||||
BenchmarkRunner.Run<PerformanceTests>(configuration);
|
||||
}
|
||||
|
||||
[IterationSetup]
|
||||
public void GenerateReportData()
|
||||
{
|
||||
var model = DataSource.GetReport();
|
||||
var report = new StandardReport(model);
|
||||
Metadata = report.GetMetadata();
|
||||
|
||||
var documentContainer = new DocumentContainer();
|
||||
report.Compose(documentContainer);
|
||||
Content = documentContainer.Compose();
|
||||
|
||||
PageContext = new PageContext();
|
||||
DocumentGenerator.RenderPass(PageContext, new FreeCanvas(), Content, Metadata, null);
|
||||
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
Content.HandleVisitor(x =>
|
||||
{
|
||||
if (x is ICacheable)
|
||||
x.CreateProxy(y => new CacheProxy(y));
|
||||
});
|
||||
|
||||
sw.Stop();
|
||||
Console.WriteLine($"Creating cache took: {sw.ElapsedMilliseconds}");
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void GenerationTest()
|
||||
{
|
||||
DocumentGenerator.RenderPass(PageContext, new FreeCanvas(), Content, Metadata, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<LangVersion>8</LangVersion>
|
||||
<RootNamespace>QuestPDF.ReportSample</RootNamespace>
|
||||
@@ -10,9 +10,9 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
|
||||
<PackageReference Include="nunit" Version="3.13.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.88.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.80.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
Before Width: | Height: | Size: 993 B After Width: | Height: | Size: 993 B |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
@@ -17,28 +17,31 @@ namespace QuestPDF.ReportSample
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
QuestPDF.Settings.License = LicenseType.Community;
|
||||
|
||||
var model = DataSource.GetReport();
|
||||
Report = new StandardReport(model);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenerateAndShowPdf()
|
||||
public void GenerateAndShow()
|
||||
{
|
||||
//ImagePlaceholder.Solid = true;
|
||||
|
||||
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"test_result.pdf");
|
||||
Report.GeneratePdf(path);
|
||||
|
||||
Process.Start("explorer.exe", path);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenerateAndShowXps()
|
||||
public void Profile()
|
||||
{
|
||||
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"test_result.xps");
|
||||
Report.GenerateXps(path);
|
||||
Process.Start("explorer.exe", path);
|
||||
var container = new DocumentContainer();
|
||||
Report.Compose(container);
|
||||
var content = container.Compose();
|
||||
|
||||
var metadata = Report.GetMetadata();
|
||||
var pageContext = new PageContext();
|
||||
|
||||
DocumentGenerator.RenderPass(pageContext, new FreeCanvas(), content, metadata, null);
|
||||
DocumentGenerator.RenderPass(pageContext, new FreeCanvas(), content, metadata, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,8 @@ namespace QuestPDF.ReportSample
|
||||
{
|
||||
public static class Typography
|
||||
{
|
||||
public static TextStyle Title => TextStyle.Default.FontFamily(Fonts.Lato).FontColor(Colors.Blue.Darken3).FontSize(26).Black();
|
||||
public static TextStyle Headline => TextStyle.Default.FontFamily(Fonts.Lato).FontColor(Colors.Blue.Medium).FontSize(16).SemiBold();
|
||||
public static TextStyle Normal => TextStyle.Default.FontFamily(Fonts.Lato).FontColor(Colors.Black).FontSize(10).LineHeight(1.2f);
|
||||
public static TextStyle Title => TextStyle.Default.FontType(Fonts.Calibri).Color(Colors.Blue.Darken3).Size(26).Black();
|
||||
public static TextStyle Headline => TextStyle.Default.FontType(Fonts.Calibri).Color(Colors.Blue.Medium).Size(16).SemiBold();
|
||||
public static TextStyle Normal => TextStyle.Default.FontType(Fonts.Calibri).Color(Colors.Black).Size(11).LineHeight(1.1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,43 +86,5 @@ namespace QuestPDF.UnitTests
|
||||
.ExpectCanvasTranslate(new Position(-300, 0))
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Draw_HorizontalCenter_VerticalNone()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new Alignment
|
||||
{
|
||||
Horizontal = HorizontalAlignment.Center,
|
||||
Vertical = null,
|
||||
|
||||
Child = x.CreateChild()
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: SpacePlan.FullRender(new Size(100, 50)))
|
||||
.ExpectCanvasTranslate(new Position(150, 0))
|
||||
.ExpectChildDraw(new Size(100, 300))
|
||||
.ExpectCanvasTranslate(new Position(-150, 0))
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Draw_HorizontalNone_VerticalMiddle()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new Alignment
|
||||
{
|
||||
Horizontal = null,
|
||||
Vertical = VerticalAlignment.Middle,
|
||||
|
||||
Child = x.CreateChild()
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: SpacePlan.FullRender(new Size(100, 50)))
|
||||
.ExpectCanvasTranslate(new Position(0, 125))
|
||||
.ExpectChildDraw(new Size(400, 50))
|
||||
.ExpectCanvasTranslate(new Position(0, -125))
|
||||
.CheckDrawResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
-40
@@ -153,9 +153,7 @@ namespace QuestPDF.UnitTests
|
||||
Ratio = 2f
|
||||
})
|
||||
.DrawElement(new Size(500, 200))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.ExpectChildDraw(new Size(400, 200))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
@@ -170,45 +168,7 @@ namespace QuestPDF.UnitTests
|
||||
Ratio = 2f
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.ExpectChildDraw(new Size(400, 200))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DrawChild_PerWidth_RightToLeft()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new AspectRatio
|
||||
{
|
||||
Child = x.CreateChild(),
|
||||
Option = AspectRatioOption.FitArea,
|
||||
Ratio = 2f,
|
||||
ContentDirection = ContentDirection.RightToLeft
|
||||
})
|
||||
.DrawElement(new Size(500, 200))
|
||||
.ExpectCanvasTranslate(100, 0)
|
||||
.ExpectChildDraw(new Size(400, 200))
|
||||
.ExpectCanvasTranslate(-100, 0)
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DrawChild_PerHeight_RightToLeft()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new AspectRatio
|
||||
{
|
||||
Child = x.CreateChild(),
|
||||
Option = AspectRatioOption.FitArea,
|
||||
Ratio = 2f,
|
||||
ContentDirection = ContentDirection.RightToLeft
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.ExpectChildDraw(new Size(400, 200))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.CheckDrawResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Elements;
|
||||
using QuestPDF.Infrastructure;
|
||||
using QuestPDF.UnitTests.TestEngine;
|
||||
|
||||
namespace QuestPDF.UnitTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class BoxTests
|
||||
{
|
||||
[Test]
|
||||
public void Measure() => SimpleContainerTests.Measure<Box>();
|
||||
|
||||
[Test]
|
||||
public void Draw_Wrap()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new Box
|
||||
{
|
||||
Child = x.CreateChild()
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: SpacePlan.Wrap())
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_PartialRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new Box
|
||||
{
|
||||
Child = x.CreateChild()
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure(expectedInput: new Size(400, 300), returns: SpacePlan.PartialRender(200, 100))
|
||||
.ExpectChildDraw(new Size(200, 100))
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_FullRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new Box
|
||||
{
|
||||
Child = x.CreateChild()
|
||||
})
|
||||
.MeasureElement(new Size(500, 400))
|
||||
.ExpectChildMeasure(expectedInput: new Size(500, 400), returns: SpacePlan.FullRender(300, 200))
|
||||
.ExpectChildDraw(new Size(300, 200))
|
||||
.CheckDrawResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
-88
@@ -9,8 +9,6 @@ namespace QuestPDF.UnitTests
|
||||
[TestFixture]
|
||||
public class ConstrainedTests
|
||||
{
|
||||
#region Height
|
||||
|
||||
[Test]
|
||||
public void Measure_MinHeight_ExpectWrap()
|
||||
{
|
||||
@@ -90,91 +88,5 @@ namespace QuestPDF.UnitTests
|
||||
.ExpectChildMeasure(new Size(400, 100), SpacePlan.Wrap())
|
||||
.CheckMeasureResult(SpacePlan.Wrap());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Width
|
||||
|
||||
[Test]
|
||||
public void Measure_MinWidth_ExpectWrap()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new Constrained
|
||||
{
|
||||
MinWidth = 100
|
||||
})
|
||||
.MeasureElement(new Size(50, 400))
|
||||
.CheckMeasureResult(SpacePlan.Wrap());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_MinWidth_ExtendHeight()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new Constrained
|
||||
{
|
||||
MinWidth = 100,
|
||||
Child = x.CreateChild()
|
||||
})
|
||||
.MeasureElement(new Size(200, 400))
|
||||
.ExpectChildMeasure(new Size(200, 400), SpacePlan.FullRender(50, 400))
|
||||
.CheckMeasureResult(SpacePlan.FullRender(100, 400));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_MinWidth_PassHeight()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new Constrained
|
||||
{
|
||||
MinWidth = 100,
|
||||
Child = x.CreateChild()
|
||||
})
|
||||
.MeasureElement(new Size(200, 400))
|
||||
.ExpectChildMeasure(new Size(200, 400), SpacePlan.FullRender(150, 400))
|
||||
.CheckMeasureResult(SpacePlan.FullRender(150, 400));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_MaxWidth_Empty()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new Constrained
|
||||
{
|
||||
MaxWidth = 100
|
||||
})
|
||||
.MeasureElement(new Size(150, 400))
|
||||
.CheckMeasureResult(SpacePlan.FullRender(0, 0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_MaxWidth_PartialRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new Constrained
|
||||
{
|
||||
MaxWidth = 100,
|
||||
Child = x.CreateChild()
|
||||
})
|
||||
.MeasureElement(new Size(200, 400))
|
||||
.ExpectChildMeasure(new Size(100, 400), SpacePlan.PartialRender(75, 400))
|
||||
.CheckMeasureResult(SpacePlan.PartialRender(75, 400));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_MaxWidth_ExpectWrap()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new Constrained
|
||||
{
|
||||
MaxWidth = 100,
|
||||
Child = x.CreateChild()
|
||||
})
|
||||
.MeasureElement(new Size(200, 400))
|
||||
.ExpectChildMeasure(new Size(100, 400), SpacePlan.Wrap())
|
||||
.CheckMeasureResult(SpacePlan.Wrap());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Elements;
|
||||
using QuestPDF.Infrastructure;
|
||||
using QuestPDF.UnitTests.TestEngine;
|
||||
|
||||
namespace QuestPDF.UnitTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class DecorationTests
|
||||
{
|
||||
#region Measure
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsWrap_WhenDecorationReturnsWrap()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryDecoration
|
||||
{
|
||||
Type = DecorationType.Append,
|
||||
DecorationElement = x.CreateChild("decoration"),
|
||||
ContentElement = x.CreateChild("content")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.Wrap())
|
||||
.CheckMeasureResult(SpacePlan.Wrap());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsWrap_WhenDecorationReturnsPartialRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryDecoration
|
||||
{
|
||||
Type = DecorationType.Append,
|
||||
DecorationElement = x.CreateChild("decoration"),
|
||||
ContentElement = x.CreateChild("content")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.PartialRender(300, 200))
|
||||
.CheckMeasureResult(SpacePlan.Wrap());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsWrap_WhenContentReturnsWrap()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryDecoration
|
||||
{
|
||||
Type = DecorationType.Append,
|
||||
DecorationElement = x.CreateChild("decoration"),
|
||||
ContentElement = x.CreateChild("content")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
|
||||
.ExpectChildMeasure("content", new Size(400, 200), SpacePlan.Wrap())
|
||||
.CheckMeasureResult(SpacePlan.Wrap());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsPartialRender_WhenContentReturnsPartialRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryDecoration
|
||||
{
|
||||
Type = DecorationType.Append,
|
||||
DecorationElement = x.CreateChild("decoration"),
|
||||
ContentElement = x.CreateChild("content")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
|
||||
.ExpectChildMeasure("content", new Size(400, 200), SpacePlan.PartialRender(200, 150))
|
||||
.CheckMeasureResult(SpacePlan.PartialRender(400, 250));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsFullRender_WhenContentReturnsFullRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryDecoration
|
||||
{
|
||||
Type = DecorationType.Append,
|
||||
DecorationElement = x.CreateChild("decoration"),
|
||||
ContentElement = x.CreateChild("content")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
|
||||
.ExpectChildMeasure("content", new Size(400, 200), SpacePlan.FullRender(200, 150))
|
||||
.CheckMeasureResult(SpacePlan.FullRender(400, 250));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Draw
|
||||
|
||||
[Test]
|
||||
public void Draw_Prepend()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryDecoration
|
||||
{
|
||||
Type = DecorationType.Prepend,
|
||||
DecorationElement = x.CreateChild("decoration"),
|
||||
ContentElement = x.CreateChild("content")
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
|
||||
.ExpectChildDraw("decoration", new Size(400, 100))
|
||||
.ExpectCanvasTranslate(0, 100)
|
||||
.ExpectChildDraw("content", new Size(400, 200))
|
||||
.ExpectCanvasTranslate(0, -100)
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Draw_Append()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryDecoration
|
||||
{
|
||||
Type = DecorationType.Append,
|
||||
DecorationElement = x.CreateChild("decoration"),
|
||||
ContentElement = x.CreateChild("content")
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("decoration", new Size(400, 300), SpacePlan.FullRender(300, 100))
|
||||
.ExpectChildDraw("content", new Size(400, 200))
|
||||
.ExpectCanvasTranslate(0, 200)
|
||||
.ExpectChildDraw("decoration", new Size(400, 100))
|
||||
.ExpectCanvasTranslate(0, -200)
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -66,7 +66,7 @@ namespace QuestPDF.UnitTests
|
||||
.ExpectCanvasDrawImage(Position.Zero, new Size(400, 300))
|
||||
.CheckDrawResult();
|
||||
|
||||
passedSize.Should().BeEquivalentTo(new Size(400, 300));
|
||||
passedSize.Should().Be(new Size(400, 300));
|
||||
}
|
||||
|
||||
byte[] GenerateImage(Size size)
|
||||
+1
-1
@@ -8,7 +8,7 @@ namespace QuestPDF.UnitTests
|
||||
public class ExternalLinkTests
|
||||
{
|
||||
[Test]
|
||||
public void Measure() => SimpleContainerTests.Measure<Hyperlink>();
|
||||
public void Measure() => SimpleContainerTests.Measure<ExternalLink>();
|
||||
|
||||
// TODO: consider tests for the Draw method
|
||||
}
|
||||
@@ -39,26 +39,26 @@ namespace QuestPDF.UnitTests
|
||||
// assert
|
||||
var expected = new Container();
|
||||
|
||||
expected.Column(column =>
|
||||
expected.Stack(stack =>
|
||||
{
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeItem(6).Element(childA);
|
||||
row.RelativeItem(4).Element(childB);
|
||||
row.RelativeItem(2);
|
||||
row.RelativeColumn(6).Element(childA);
|
||||
row.RelativeColumn(4).Element(childB);
|
||||
row.RelativeColumn(2);
|
||||
});
|
||||
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeItem(4).Element(childC);
|
||||
row.RelativeItem(2).Element(childD);
|
||||
row.RelativeItem(6);
|
||||
row.RelativeColumn(4).Element(childC);
|
||||
row.RelativeColumn(2).Element(childD);
|
||||
row.RelativeColumn(6);
|
||||
});
|
||||
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeItem(8).Element(childE);
|
||||
row.RelativeItem(4);
|
||||
row.RelativeColumn(8).Element(childE);
|
||||
row.RelativeColumn(4);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -93,29 +93,29 @@ namespace QuestPDF.UnitTests
|
||||
// assert
|
||||
var expected = new Container();
|
||||
|
||||
expected.Column(column =>
|
||||
expected.Stack(stack =>
|
||||
{
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeItem(1);
|
||||
row.RelativeItem(6).Element(childA);
|
||||
row.RelativeItem(4).Element(childB);
|
||||
row.RelativeItem(1);
|
||||
row.RelativeColumn(1);
|
||||
row.RelativeColumn(6).Element(childA);
|
||||
row.RelativeColumn(4).Element(childB);
|
||||
row.RelativeColumn(1);
|
||||
});
|
||||
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeItem(3);
|
||||
row.RelativeItem(4).Element(childC);
|
||||
row.RelativeItem(2).Element(childD);
|
||||
row.RelativeItem(3);
|
||||
row.RelativeColumn(3);
|
||||
row.RelativeColumn(4).Element(childC);
|
||||
row.RelativeColumn(2).Element(childD);
|
||||
row.RelativeColumn(3);
|
||||
});
|
||||
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeItem(2);
|
||||
row.RelativeItem(8).Element(childE);
|
||||
row.RelativeItem(2);
|
||||
row.RelativeColumn(2);
|
||||
row.RelativeColumn(8).Element(childE);
|
||||
row.RelativeColumn(2);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -150,26 +150,26 @@ namespace QuestPDF.UnitTests
|
||||
// assert
|
||||
var expected = new Container();
|
||||
|
||||
expected.Column(column =>
|
||||
expected.Stack(stack =>
|
||||
{
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeItem(2);
|
||||
row.RelativeItem(6).Element(childA);
|
||||
row.RelativeItem(4).Element(childB);
|
||||
row.RelativeColumn(2);
|
||||
row.RelativeColumn(6).Element(childA);
|
||||
row.RelativeColumn(4).Element(childB);
|
||||
});
|
||||
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeItem(6);
|
||||
row.RelativeItem(4).Element(childC);
|
||||
row.RelativeItem(2).Element(childD);
|
||||
row.RelativeColumn(6);
|
||||
row.RelativeColumn(4).Element(childC);
|
||||
row.RelativeColumn(2).Element(childD);
|
||||
});
|
||||
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.RelativeItem(4);
|
||||
row.RelativeItem(8).Element(childE);
|
||||
row.RelativeColumn(4);
|
||||
row.RelativeColumn(8).Element(childE);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -210,36 +210,36 @@ namespace QuestPDF.UnitTests
|
||||
// assert
|
||||
var expected = new Container();
|
||||
|
||||
expected.Column(column =>
|
||||
expected.Stack(stack =>
|
||||
{
|
||||
column.Spacing(20);
|
||||
stack.Spacing(20);
|
||||
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.Spacing(30);
|
||||
|
||||
row.RelativeItem(3);
|
||||
row.RelativeItem(5).Element(childA);
|
||||
row.RelativeItem(5).Element(childB);
|
||||
row.RelativeItem(3);
|
||||
row.RelativeColumn(3);
|
||||
row.RelativeColumn(5).Element(childA);
|
||||
row.RelativeColumn(5).Element(childB);
|
||||
row.RelativeColumn(3);
|
||||
});
|
||||
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.Spacing(30);
|
||||
|
||||
row.RelativeItem(3);
|
||||
row.RelativeItem(10).Element(childC);
|
||||
row.RelativeItem(3);
|
||||
row.RelativeColumn(3);
|
||||
row.RelativeColumn(10).Element(childC);
|
||||
row.RelativeColumn(3);
|
||||
});
|
||||
|
||||
column.Item().Row(row =>
|
||||
stack.Item().Row(row =>
|
||||
{
|
||||
row.Spacing(30);
|
||||
|
||||
row.RelativeItem(2);
|
||||
row.RelativeItem(12).Element(childD);
|
||||
row.RelativeItem(2);
|
||||
row.RelativeColumn(2);
|
||||
row.RelativeColumn(12).Element(childD);
|
||||
row.RelativeColumn(2);
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ namespace QuestPDF.UnitTests
|
||||
public class InternalLinkTests
|
||||
{
|
||||
[Test]
|
||||
public void Measure() => SimpleContainerTests.Measure<SectionLink>();
|
||||
public void Measure() => SimpleContainerTests.Measure<InternalLink>();
|
||||
|
||||
// TODO: consider tests for the Draw method
|
||||
}
|
||||
+1
-1
@@ -8,7 +8,7 @@ namespace QuestPDF.UnitTests
|
||||
public class InternalLocationTests
|
||||
{
|
||||
[Test]
|
||||
public void Measure() => SimpleContainerTests.Measure<SectionLink>();
|
||||
public void Measure() => SimpleContainerTests.Measure<InternalLink>();
|
||||
|
||||
// TODO: consider tests for the Draw method
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.1.0" />
|
||||
<PackageReference Include="nunit" Version="3.13.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.0" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.80.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\QuestPDF\QuestPDF.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,267 @@
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Elements;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Infrastructure;
|
||||
using QuestPDF.UnitTests.TestEngine;
|
||||
|
||||
namespace QuestPDF.UnitTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class RowTests
|
||||
{
|
||||
#region Measure
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsWrap_WhenLeftChildReturnsWrap()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryRow
|
||||
{
|
||||
Left = x.CreateChild("left"),
|
||||
Right = x.CreateChild("right")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("left", new Size(400, 300), SpacePlan.Wrap())
|
||||
.CheckMeasureResult(SpacePlan.Wrap());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsWrap_WhenRightChildReturnsWrap()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryRow
|
||||
{
|
||||
Left = x.CreateChild("left"),
|
||||
Right = x.CreateChild("right")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("left", new Size(400, 300), SpacePlan.FullRender(250, 150))
|
||||
.ExpectChildMeasure("right", new Size(150, 300), SpacePlan.Wrap())
|
||||
.CheckMeasureResult(SpacePlan.Wrap());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsPartialRender_WhenLeftChildReturnsPartialRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryRow
|
||||
{
|
||||
Left = x.CreateChild("left"),
|
||||
Right = x.CreateChild("right")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("left", new Size(400, 300), SpacePlan.PartialRender(250, 150))
|
||||
.ExpectChildMeasure("right", new Size(150, 300), SpacePlan.FullRender(100, 100))
|
||||
.CheckMeasureResult(SpacePlan.PartialRender(350, 150));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsPartialRender_WhenRightChildReturnsPartialRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryRow
|
||||
{
|
||||
Left = x.CreateChild("left"),
|
||||
Right = x.CreateChild("right")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("left", new Size(400, 300), SpacePlan.FullRender(250, 150))
|
||||
.ExpectChildMeasure("right", new Size(150, 300), SpacePlan.PartialRender(100, 100))
|
||||
.CheckMeasureResult(SpacePlan.PartialRender(350, 150));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsFullRender_WhenBothChildrenReturnFullRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryRow
|
||||
{
|
||||
Left = x.CreateChild("left"),
|
||||
Right = x.CreateChild("right")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("left", new Size(400, 300), SpacePlan.FullRender(200, 150))
|
||||
.ExpectChildMeasure("right", new Size(200, 300), SpacePlan.FullRender(100, 100))
|
||||
.CheckMeasureResult(SpacePlan.FullRender(300, 150));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Draw
|
||||
|
||||
[Test]
|
||||
public void Draw()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryRow
|
||||
{
|
||||
Left = x.CreateChild("left"),
|
||||
Right = x.CreateChild("right")
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("left", new Size(400, 300), SpacePlan.FullRender(250, 150))
|
||||
.ExpectChildDraw("left", new Size(250, 300))
|
||||
.ExpectCanvasTranslate(250, 0)
|
||||
.ExpectChildDraw("right", new Size(150, 300))
|
||||
.ExpectCanvasTranslate(-250, 0)
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Structure
|
||||
|
||||
[Test]
|
||||
public void Structure_RelativeColumnsHandling()
|
||||
{
|
||||
// arrange
|
||||
var childA = TestPlan.CreateUniqueElement();
|
||||
var childB = TestPlan.CreateUniqueElement();
|
||||
var childC = TestPlan.CreateUniqueElement();
|
||||
var childD = TestPlan.CreateUniqueElement();
|
||||
var childE = TestPlan.CreateUniqueElement();
|
||||
|
||||
const int spacing = 25;
|
||||
var availableSpace = new Size(1100, 400);
|
||||
|
||||
// act
|
||||
var value = new Container();
|
||||
|
||||
value.Row(row =>
|
||||
{
|
||||
row.Spacing(spacing);
|
||||
|
||||
row.ConstantColumn(150).Element(childA);
|
||||
row.ConstantColumn(250).Element(childB);
|
||||
row.RelativeColumn(1).Element(childC);
|
||||
row.RelativeColumn(2).Element(childD);
|
||||
row.RelativeColumn(3).Element(childE);
|
||||
});
|
||||
|
||||
// assert
|
||||
var expected = new Container();
|
||||
|
||||
expected.Row(row =>
|
||||
{
|
||||
row.Spacing(spacing);
|
||||
|
||||
row.ConstantColumn(150).Element(childA);
|
||||
row.ConstantColumn(250).Element(childB);
|
||||
row.ConstantColumn(100).Element(childC);
|
||||
row.ConstantColumn(200).Element(childD);
|
||||
row.ConstantColumn(300).Element(childE);
|
||||
});
|
||||
|
||||
TestPlan.CompareOperations(value, expected, availableSpace);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Structure_Tree()
|
||||
{
|
||||
// arrange
|
||||
var childA = TestPlan.CreateUniqueElement();
|
||||
var childB = TestPlan.CreateUniqueElement();
|
||||
var childC = TestPlan.CreateUniqueElement();
|
||||
var childD = TestPlan.CreateUniqueElement();
|
||||
var childE = TestPlan.CreateUniqueElement();
|
||||
|
||||
const int spacing = 25;
|
||||
var availableSpace = new Size(1200, 400);
|
||||
|
||||
// act
|
||||
var value = new Container();
|
||||
|
||||
value.Row(row =>
|
||||
{
|
||||
row.Spacing(spacing);
|
||||
|
||||
row.ConstantColumn(150).Element(childA);
|
||||
row.ConstantColumn(200).Element(childB);
|
||||
row.ConstantColumn(250).Element(childC);
|
||||
row.RelativeColumn(2).Element(childD);
|
||||
row.RelativeColumn(3).Element(childE);
|
||||
});
|
||||
|
||||
// assert
|
||||
var expected = new BinaryRow
|
||||
{
|
||||
Left = new BinaryRow
|
||||
{
|
||||
Left = new BinaryRow
|
||||
{
|
||||
Left = new Constrained
|
||||
{
|
||||
MinWidth = 150,
|
||||
MaxWidth = 150,
|
||||
Child = childA
|
||||
},
|
||||
Right = new Constrained
|
||||
{
|
||||
MinWidth = 25,
|
||||
MaxWidth = 25
|
||||
}
|
||||
},
|
||||
Right = new BinaryRow
|
||||
{
|
||||
Left = new Constrained
|
||||
{
|
||||
MinWidth = 200,
|
||||
MaxWidth = 200,
|
||||
Child = childB
|
||||
},
|
||||
Right = new Constrained
|
||||
{
|
||||
MinWidth = 25,
|
||||
MaxWidth = 25
|
||||
}
|
||||
}
|
||||
},
|
||||
Right = new BinaryRow
|
||||
{
|
||||
Left = new BinaryRow
|
||||
{
|
||||
Left = new Constrained
|
||||
{
|
||||
MinWidth = 250,
|
||||
MaxWidth = 250,
|
||||
Child = childC
|
||||
},
|
||||
Right = new Constrained
|
||||
{
|
||||
MinWidth = 25,
|
||||
MaxWidth = 25
|
||||
}
|
||||
},
|
||||
Right = new BinaryRow
|
||||
{
|
||||
Left = new Constrained
|
||||
{
|
||||
MinWidth = 200,
|
||||
MaxWidth = 200,
|
||||
Child = childD
|
||||
},
|
||||
Right = new BinaryRow
|
||||
{
|
||||
Left = new Constrained
|
||||
{
|
||||
MinWidth = 25,
|
||||
MaxWidth = 25
|
||||
},
|
||||
Right = new Constrained
|
||||
{
|
||||
MinWidth = 300,
|
||||
MaxWidth = 300,
|
||||
Child = childE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TestPlan.CompareOperations(value, expected, availableSpace);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Elements;
|
||||
using QuestPDF.Fluent;
|
||||
@@ -9,40 +8,19 @@ using QuestPDF.UnitTests.TestEngine;
|
||||
namespace QuestPDF.UnitTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ColumnTests
|
||||
public class StackTests
|
||||
{
|
||||
private Column CreateColumnWithTwoItems(TestPlan testPlan)
|
||||
{
|
||||
return new Column
|
||||
{
|
||||
Items =
|
||||
{
|
||||
new ColumnItem
|
||||
{
|
||||
Child = testPlan.CreateChild("first")
|
||||
},
|
||||
new ColumnItem
|
||||
{
|
||||
Child = testPlan.CreateChild("second")
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Column CreateColumnWithTwoItemsWhereFirstIsFullyRendered(TestPlan testPlan)
|
||||
{
|
||||
var column = CreateColumnWithTwoItems(testPlan);
|
||||
column.Items.First().IsRendered = true;
|
||||
return column;
|
||||
}
|
||||
|
||||
#region Measure
|
||||
|
||||
[Test]
|
||||
public void Measure_ReturnsWrap_WhenFirstChildWraps()
|
||||
{
|
||||
TestPlan
|
||||
.For(CreateColumnWithTwoItems)
|
||||
.For(x => new BinaryStack
|
||||
{
|
||||
First = x.CreateChild("first"),
|
||||
Second = x.CreateChild("second")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.Wrap())
|
||||
.CheckMeasureResult(SpacePlan.Wrap());
|
||||
@@ -52,7 +30,11 @@ namespace QuestPDF.UnitTests
|
||||
public void Measure_ReturnsPartialRender_WhenFirstChildReturnsPartialRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(CreateColumnWithTwoItems)
|
||||
.For(x => new BinaryStack
|
||||
{
|
||||
First = x.CreateChild("first"),
|
||||
Second = x.CreateChild("second")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.PartialRender(300, 200))
|
||||
.CheckMeasureResult(SpacePlan.PartialRender(300, 200));
|
||||
@@ -62,7 +44,11 @@ namespace QuestPDF.UnitTests
|
||||
public void Measure_ReturnsPartialRender_WhenSecondChildWraps()
|
||||
{
|
||||
TestPlan
|
||||
.For(CreateColumnWithTwoItems)
|
||||
.For(x => new BinaryStack
|
||||
{
|
||||
First = x.CreateChild("first"),
|
||||
Second = x.CreateChild("second")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
|
||||
.ExpectChildMeasure("second", new Size(400, 200), SpacePlan.Wrap())
|
||||
@@ -73,7 +59,11 @@ namespace QuestPDF.UnitTests
|
||||
public void Measure_ReturnsPartialRender_WhenSecondChildReturnsPartialRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(CreateColumnWithTwoItems)
|
||||
.For(x => new BinaryStack
|
||||
{
|
||||
First = x.CreateChild("first"),
|
||||
Second = x.CreateChild("second")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
|
||||
.ExpectChildMeasure("second", new Size(400, 200), SpacePlan.PartialRender(300, 150))
|
||||
@@ -84,13 +74,33 @@ namespace QuestPDF.UnitTests
|
||||
public void Measure_ReturnsFullRender_WhenSecondChildReturnsFullRender()
|
||||
{
|
||||
TestPlan
|
||||
.For(CreateColumnWithTwoItems)
|
||||
.For(x => new BinaryStack
|
||||
{
|
||||
First = x.CreateChild("first"),
|
||||
Second = x.CreateChild("second")
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
|
||||
.ExpectChildMeasure("second", new Size(400, 200), SpacePlan.FullRender(100, 50))
|
||||
.CheckMeasureResult(SpacePlan.FullRender(200, 150));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Measure_UsesEmpty_WhenFirstChildIsRendered()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new BinaryStack
|
||||
{
|
||||
First = x.CreateChild("first"),
|
||||
Second = x.CreateChild("second"),
|
||||
|
||||
IsFirstRendered = true
|
||||
})
|
||||
.MeasureElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("second", new Size(400, 300), SpacePlan.FullRender(200, 300))
|
||||
.CheckMeasureResult(SpacePlan.FullRender(200, 300));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Draw
|
||||
@@ -99,7 +109,11 @@ namespace QuestPDF.UnitTests
|
||||
public void Draw_WhenFirstChildWraps()
|
||||
{
|
||||
TestPlan
|
||||
.For(CreateColumnWithTwoItems)
|
||||
.For(x => new BinaryStack
|
||||
{
|
||||
First = x.CreateChild("first"),
|
||||
Second = x.CreateChild("second")
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.Wrap())
|
||||
.CheckDrawResult();
|
||||
@@ -109,12 +123,14 @@ namespace QuestPDF.UnitTests
|
||||
public void Draw_WhenFirstChildPartiallyRenders()
|
||||
{
|
||||
TestPlan
|
||||
.For(CreateColumnWithTwoItems)
|
||||
.For(x => new BinaryStack
|
||||
{
|
||||
First = x.CreateChild("first"),
|
||||
Second = x.CreateChild("second")
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.PartialRender(200, 100))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.ExpectChildDraw("first", new Size(400, 100))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
@@ -122,13 +138,15 @@ namespace QuestPDF.UnitTests
|
||||
public void Draw_WhenFirstChildFullyRenders_AndSecondChildWraps()
|
||||
{
|
||||
TestPlan
|
||||
.For(CreateColumnWithTwoItems)
|
||||
.For(x => new BinaryStack
|
||||
{
|
||||
First = x.CreateChild("first"),
|
||||
Second = x.CreateChild("second")
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
|
||||
.ExpectChildMeasure("second", new Size(400, 200), SpacePlan.Wrap())
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.ExpectChildDraw("first", new Size(400, 100))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.ExpectChildMeasure("second", new Size(400, 200), SpacePlan.Wrap())
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
@@ -136,13 +154,15 @@ namespace QuestPDF.UnitTests
|
||||
public void Draw_WhenFirstChildFullyRenders_AndSecondChildPartiallyRenders()
|
||||
{
|
||||
TestPlan
|
||||
.For(CreateColumnWithTwoItems)
|
||||
.For(x => new BinaryStack
|
||||
{
|
||||
First = x.CreateChild("first"),
|
||||
Second = x.CreateChild("second")
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
|
||||
.ExpectChildMeasure("second", new Size(400, 200), SpacePlan.PartialRender(250, 150))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.ExpectChildDraw("first", new Size(400, 100))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.ExpectChildMeasure("second", new Size(400, 200), SpacePlan.PartialRender(250, 150))
|
||||
.ExpectCanvasTranslate(0, 100)
|
||||
.ExpectChildDraw("second", new Size(400, 150))
|
||||
.ExpectCanvasTranslate(0, -100)
|
||||
@@ -153,13 +173,15 @@ namespace QuestPDF.UnitTests
|
||||
public void Draw_WhenFirstChildFullyRenders_AndSecondChildFullyRenders()
|
||||
{
|
||||
TestPlan
|
||||
.For(CreateColumnWithTwoItems)
|
||||
.For(x => new BinaryStack
|
||||
{
|
||||
First = x.CreateChild("first"),
|
||||
Second = x.CreateChild("second")
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("first", new Size(400, 300), SpacePlan.FullRender(200, 100))
|
||||
.ExpectChildMeasure("second", new Size(400, 200), SpacePlan.FullRender(250, 150))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.ExpectChildDraw("first", new Size(400, 100))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.ExpectChildMeasure("second", new Size(400, 200), SpacePlan.FullRender(250, 150))
|
||||
.ExpectCanvasTranslate(0, 100)
|
||||
.ExpectChildDraw("second", new Size(400, 150))
|
||||
.ExpectCanvasTranslate(0, -100)
|
||||
@@ -170,13 +192,19 @@ namespace QuestPDF.UnitTests
|
||||
public void Draw_UsesEmpty_WhenFirstChildIsRendered()
|
||||
{
|
||||
TestPlan
|
||||
.For(CreateColumnWithTwoItemsWhereFirstIsFullyRendered)
|
||||
.For(x => new BinaryStack
|
||||
{
|
||||
First = x.CreateChild("first"),
|
||||
Second = x.CreateChild("second"),
|
||||
|
||||
IsFirstRendered = true
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("second", new Size(400, 300), SpacePlan.PartialRender(200, 300))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.ExpectChildDraw("second", new Size(400, 300))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.CheckState<Column>(x => x.Items.First().IsRendered)
|
||||
.CheckState<BinaryStack>(x => x.IsFirstRendered)
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
@@ -184,14 +212,97 @@ namespace QuestPDF.UnitTests
|
||||
public void Draw_TogglesFirstRenderedFlag_WhenSecondFullyRenders()
|
||||
{
|
||||
TestPlan
|
||||
.For(CreateColumnWithTwoItemsWhereFirstIsFullyRendered)
|
||||
.For(x => new BinaryStack
|
||||
{
|
||||
First = x.CreateChild("first"),
|
||||
Second = x.CreateChild("second"),
|
||||
|
||||
IsFirstRendered = true
|
||||
})
|
||||
.DrawElement(new Size(400, 300))
|
||||
.ExpectChildMeasure("second", new Size(400, 300), SpacePlan.FullRender(200, 300))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.ExpectChildDraw("second", new Size(400, 300))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.CheckDrawResult()
|
||||
.CheckState<Column>(x => !x.Items.First().IsRendered);
|
||||
.CheckState<BinaryStack>(x => !x.IsFirstRendered);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Structure
|
||||
|
||||
[Test]
|
||||
public void Structure_Simple()
|
||||
{
|
||||
// arrange
|
||||
var childA = TestPlan.CreateUniqueElement();
|
||||
var childB = TestPlan.CreateUniqueElement();
|
||||
var childC = TestPlan.CreateUniqueElement();
|
||||
var childD = TestPlan.CreateUniqueElement();
|
||||
var childE = TestPlan.CreateUniqueElement();
|
||||
|
||||
const int spacing = 20;
|
||||
|
||||
// act
|
||||
var structure = new Container();
|
||||
|
||||
structure.Stack(stack =>
|
||||
{
|
||||
stack.Spacing(spacing);
|
||||
|
||||
stack.Item().Element(childA);
|
||||
stack.Item().Element(childB);
|
||||
stack.Item().Element(childC);
|
||||
stack.Item().Element(childD);
|
||||
stack.Item().Element(childE);
|
||||
});
|
||||
|
||||
// assert
|
||||
var expected = new Padding
|
||||
{
|
||||
Bottom = -spacing,
|
||||
|
||||
Child = new BinaryStack
|
||||
{
|
||||
First = new BinaryStack
|
||||
{
|
||||
First = new Padding
|
||||
{
|
||||
Bottom = spacing,
|
||||
Child = childA
|
||||
},
|
||||
Second = new Padding
|
||||
{
|
||||
Bottom = spacing,
|
||||
Child = childB
|
||||
}
|
||||
},
|
||||
Second = new BinaryStack
|
||||
{
|
||||
First = new Padding
|
||||
{
|
||||
Bottom = spacing,
|
||||
Child = childC
|
||||
},
|
||||
Second = new BinaryStack
|
||||
{
|
||||
First = new Padding
|
||||
{
|
||||
Bottom = spacing,
|
||||
Child = childD
|
||||
},
|
||||
Second = new Padding
|
||||
{
|
||||
Bottom = spacing,
|
||||
Child = childE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TestPlan.CompareOperations(structure, expected);
|
||||
}
|
||||
|
||||
#endregion
|
||||
+6
-6
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Infrastructure;
|
||||
using SkiaSharp;
|
||||
|
||||
@@ -11,6 +10,7 @@ namespace QuestPDF.UnitTests.TestEngine
|
||||
public Action<float> RotateFunc { get; set; }
|
||||
public Action<float, float> ScaleFunc { get; set; }
|
||||
public Action<SKImage, Position, Size> DrawImageFunc { get; set; }
|
||||
public Action<string, Position, TextStyle> DrawTextFunc { get; set; }
|
||||
public Action<Position, Size, string> DrawRectFunc { get; set; }
|
||||
|
||||
public void Translate(Position vector) => TranslateFunc(vector);
|
||||
@@ -18,11 +18,11 @@ namespace QuestPDF.UnitTests.TestEngine
|
||||
public void Scale(float scaleX, float scaleY) => ScaleFunc(scaleX, scaleY);
|
||||
|
||||
public void DrawRectangle(Position vector, Size size, string color) => DrawRectFunc(vector, size, color);
|
||||
public void DrawText(SKTextBlob skTextBlob, Position position, TextStyle style) => throw new NotImplementedException();
|
||||
public void DrawText(string text, Position position, TextStyle style) => DrawTextFunc(text, position, style);
|
||||
public void DrawImage(SKImage image, Position position, Size size) => DrawImageFunc(image, position, size);
|
||||
|
||||
public void DrawHyperlink(string url, Size size) => throw new NotImplementedException();
|
||||
public void DrawSectionLink(string sectionName, Size size) => throw new NotImplementedException();
|
||||
public void DrawSection(string sectionName) => throw new NotImplementedException();
|
||||
|
||||
public void DrawExternalLink(string url, Size size) => throw new NotImplementedException();
|
||||
public void DrawLocationLink(string locationName, Size size) => throw new NotImplementedException();
|
||||
public void DrawLocation(string locationName) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
+4
-5
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using QuestPDF.Drawing;
|
||||
using QuestPDF.Infrastructure;
|
||||
using QuestPDF.UnitTests.TestEngine.Operations;
|
||||
using SkiaSharp;
|
||||
@@ -16,11 +15,11 @@ namespace QuestPDF.UnitTests.TestEngine
|
||||
public void Scale(float scaleX, float scaleY) => Operations.Add(new CanvasScaleOperation(scaleX, scaleY));
|
||||
|
||||
public void DrawRectangle(Position vector, Size size, string color) => Operations.Add(new CanvasDrawRectangleOperation(vector, size, color));
|
||||
public void DrawText(SKTextBlob skTextBlob, Position position, TextStyle style) => throw new NotImplementedException();
|
||||
public void DrawText(string text, Position position, TextStyle style) => Operations.Add(new CanvasDrawTextOperation(text, position, style));
|
||||
public void DrawImage(SKImage image, Position position, Size size) => Operations.Add(new CanvasDrawImageOperation(position, size));
|
||||
|
||||
public void DrawHyperlink(string url, Size size) => throw new NotImplementedException();
|
||||
public void DrawSectionLink(string sectionName, Size size) => throw new NotImplementedException();
|
||||
public void DrawSection(string sectionName) => throw new NotImplementedException();
|
||||
public void DrawExternalLink(string url, Size size) => throw new NotImplementedException();
|
||||
public void DrawLocationLink(string locationName, Size size) => throw new NotImplementedException();
|
||||
public void DrawLocation(string locationName) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
+24
-6
@@ -82,6 +82,19 @@ namespace QuestPDF.UnitTests.TestEngine
|
||||
|
||||
Assert.AreEqual(expected.Color, color, "Draw rectangle: color");
|
||||
},
|
||||
DrawTextFunc = (text, position, style) =>
|
||||
{
|
||||
var expected = GetExpected<CanvasDrawTextOperation>();
|
||||
|
||||
Assert.AreEqual(expected.Text, text);
|
||||
|
||||
Assert.AreEqual(expected.Position.X, position.X, "Draw text: X");
|
||||
Assert.AreEqual(expected.Position.Y, position.Y, "Draw text: Y");
|
||||
|
||||
Assert.AreEqual(expected.Style.Color, style.Color, "Draw text: color");
|
||||
Assert.AreEqual(expected.Style.FontType, style.FontType, "Draw text: font");
|
||||
Assert.AreEqual(expected.Style.Size, style.Size, "Draw text: size");
|
||||
},
|
||||
DrawImageFunc = (image, position, size) =>
|
||||
{
|
||||
var expected = GetExpected<CanvasDrawImageOperation>();
|
||||
@@ -188,6 +201,11 @@ namespace QuestPDF.UnitTests.TestEngine
|
||||
return AddOperation(new CanvasDrawRectangleOperation(position, size, color));
|
||||
}
|
||||
|
||||
public TestPlan ExpectCanvasDrawText(string text, Position position, TextStyle style)
|
||||
{
|
||||
return AddOperation(new CanvasDrawTextOperation(text, position, style));
|
||||
}
|
||||
|
||||
public TestPlan ExpectCanvasDrawImage(Position position, Size size)
|
||||
{
|
||||
return AddOperation(new CanvasDrawImageOperation(position, size));
|
||||
@@ -195,7 +213,7 @@ namespace QuestPDF.UnitTests.TestEngine
|
||||
|
||||
public TestPlan CheckMeasureResult(SpacePlan expected)
|
||||
{
|
||||
Element.InjectDependencies(null, Canvas);
|
||||
Element.HandleVisitor(x => x?.Initialize(null, Canvas));
|
||||
|
||||
var actual = Element.Measure(OperationInput);
|
||||
|
||||
@@ -210,7 +228,7 @@ namespace QuestPDF.UnitTests.TestEngine
|
||||
|
||||
public TestPlan CheckDrawResult()
|
||||
{
|
||||
Element.InjectDependencies(null, Canvas);
|
||||
Element.HandleVisitor(x => x?.Initialize(null, Canvas));
|
||||
Element.Draw(OperationInput);
|
||||
return this;
|
||||
}
|
||||
@@ -253,10 +271,10 @@ namespace QuestPDF.UnitTests.TestEngine
|
||||
availableSpace ??= new Size(400, 300);
|
||||
|
||||
var canvas = new FreeCanvas();
|
||||
value.InjectDependencies(null, canvas);
|
||||
value.HandleVisitor(x => x.Initialize(null, canvas));
|
||||
var valueMeasure = value.Measure(availableSpace.Value);
|
||||
|
||||
expected.InjectDependencies(null, canvas);
|
||||
expected.HandleVisitor(x => x.Initialize(null, canvas));
|
||||
var expectedMeasure = expected.Measure(availableSpace.Value);
|
||||
|
||||
valueMeasure.Should().BeEquivalentTo(expectedMeasure);
|
||||
@@ -267,11 +285,11 @@ namespace QuestPDF.UnitTests.TestEngine
|
||||
availableSpace ??= new Size(400, 300);
|
||||
|
||||
var valueCanvas = new OperationRecordingCanvas();
|
||||
value.InjectDependencies(null, valueCanvas);
|
||||
value.HandleVisitor(x => x.Initialize(null, valueCanvas));
|
||||
value.Draw(availableSpace.Value);
|
||||
|
||||
var expectedCanvas = new OperationRecordingCanvas();
|
||||
expected.InjectDependencies(null, expectedCanvas);
|
||||
expected.HandleVisitor(x => x.Initialize(null, expectedCanvas));
|
||||
expected.Draw(availableSpace.Value);
|
||||
|
||||
valueCanvas.Operations.Should().BeEquivalentTo(expectedCanvas.Operations);
|
||||
-38
@@ -77,9 +77,7 @@ namespace QuestPDF.UnitTests
|
||||
})
|
||||
.DrawElement(new Size(900, 800))
|
||||
.ExpectChildMeasure(Size.Max, SpacePlan.PartialRender(1200, 1600))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.ExpectChildDraw(new Size(1200, 1600))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
@@ -93,43 +91,7 @@ namespace QuestPDF.UnitTests
|
||||
})
|
||||
.DrawElement(new Size(900, 800))
|
||||
.ExpectChildMeasure(Size.Max, SpacePlan.FullRender(1600, 1000))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.ExpectChildDraw(new Size(1600, 1000))
|
||||
.ExpectCanvasTranslate(0, 0)
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Draw_WhenChildPartiallyRenders_RightToLeft()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new Unconstrained
|
||||
{
|
||||
Child = x.CreateChild(),
|
||||
ContentDirection = ContentDirection.RightToLeft
|
||||
})
|
||||
.DrawElement(new Size(900, 800))
|
||||
.ExpectChildMeasure(Size.Max, SpacePlan.PartialRender(1200, 1600))
|
||||
.ExpectCanvasTranslate(-1200, 0)
|
||||
.ExpectChildDraw(new Size(1200, 1600))
|
||||
.ExpectCanvasTranslate(1200, 0)
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Draw_WhenChildFullyRenders_RightToLeft()
|
||||
{
|
||||
TestPlan
|
||||
.For(x => new Unconstrained
|
||||
{
|
||||
Child = x.CreateChild(),
|
||||
ContentDirection = ContentDirection.RightToLeft
|
||||
})
|
||||
.DrawElement(new Size(900, 800))
|
||||
.ExpectChildMeasure(Size.Max, SpacePlan.FullRender(1600, 1000))
|
||||
.ExpectCanvasTranslate(-1600, 0)
|
||||
.ExpectChildDraw(new Size(1600, 1000))
|
||||
.ExpectCanvasTranslate(1600, 0)
|
||||
.CheckDrawResult();
|
||||
}
|
||||
|
||||
@@ -8,15 +8,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuestPDF.UnitTests", "Quest
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuestPDF.Examples", "QuestPDF.Examples\QuestPDF.Examples.csproj", "{8BD0A2B4-2DC1-47BA-9724-C158320D9CAE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuestPDF.Previewer.Examples", "QuestPDF.Previewer.Examples\QuestPDF.Previewer.Examples.csproj", "{CA413A39-038F-4A9F-B56F-0E5413B6B158}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Configuration", "Configuration", "{73123649-216A-47B4-BFB2-DADF13FBE75D}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuestPDF.Previewer", "QuestPDF.Previewer\QuestPDF.Previewer.csproj", "{B2FF6003-3A45-4A78-A85D-B86C7F01D054}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -39,13 +30,5 @@ Global
|
||||
{8BD0A2B4-2DC1-47BA-9724-C158320D9CAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8BD0A2B4-2DC1-47BA-9724-C158320D9CAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8BD0A2B4-2DC1-47BA-9724-C158320D9CAE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CA413A39-038F-4A9F-B56F-0E5413B6B158}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CA413A39-038F-4A9F-B56F-0E5413B6B158}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CA413A39-038F-4A9F-B56F-0E5413B6B158}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CA413A39-038F-4A9F-B56F-0E5413B6B158}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B2FF6003-3A45-4A78-A85D-B86C7F01D054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B2FF6003-3A45-4A78-A85D-B86C7F01D054}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B2FF6003-3A45-4A78-A85D-B86C7F01D054}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B2FF6003-3A45-4A78-A85D-B86C7F01D054}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,6 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
||||
[assembly: InternalsVisibleTo("QuestPDF.UnitTests")]
|
||||
[assembly: InternalsVisibleTo("QuestPDF.Examples")]
|
||||
[assembly: InternalsVisibleTo("QuestPDF.ReportSample")]
|
||||
+3
-3
@@ -16,13 +16,13 @@ namespace QuestPDF.Drawing
|
||||
var container = new Container();
|
||||
|
||||
container
|
||||
.Column(column =>
|
||||
.Stack(stack =>
|
||||
{
|
||||
Pages
|
||||
.SelectMany(x => new List<Action>()
|
||||
{
|
||||
() => column.Item().PageBreak(),
|
||||
() => column.Item().Component(x)
|
||||
() => stack.Item().PageBreak(),
|
||||
() => stack.Item().Component(x)
|
||||
})
|
||||
.Skip(1)
|
||||
.ToList()
|
||||
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using QuestPDF.Drawing.Exceptions;
|
||||
using QuestPDF.Drawing.Proxy;
|
||||
using QuestPDF.Elements;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Drawing
|
||||
{
|
||||
static class DocumentGenerator
|
||||
{
|
||||
internal static void GeneratePdf(Stream stream, IDocument document)
|
||||
{
|
||||
var metadata = document.GetMetadata();
|
||||
var canvas = new PdfCanvas(stream, metadata);
|
||||
RenderDocument(canvas, document);
|
||||
}
|
||||
|
||||
internal static ICollection<byte[]> GenerateImages(IDocument document)
|
||||
{
|
||||
var metadata = document.GetMetadata();
|
||||
var canvas = new ImageCanvas(metadata);
|
||||
RenderDocument(canvas, document);
|
||||
|
||||
return canvas.Images;
|
||||
}
|
||||
|
||||
private static void RenderDocument<TCanvas>(TCanvas canvas, IDocument document)
|
||||
where TCanvas : ICanvas, IRenderingCanvas
|
||||
{
|
||||
var container = new DocumentContainer();
|
||||
document.Compose(container);
|
||||
var content = container.Compose();
|
||||
|
||||
var metadata = document.GetMetadata();
|
||||
var pageContext = new PageContext();
|
||||
|
||||
DebuggingState debuggingState = null;
|
||||
|
||||
if (System.Diagnostics.Debugger.IsAttached)
|
||||
{
|
||||
debuggingState = ApplyDebugging(content);
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyCaching(content);
|
||||
}
|
||||
|
||||
RenderPass(pageContext, new FreeCanvas(), content, metadata, debuggingState);
|
||||
RenderPass(pageContext, canvas, content, metadata, debuggingState);
|
||||
}
|
||||
|
||||
internal static void RenderPass<TCanvas>(PageContext pageContext, TCanvas canvas, Container content, DocumentMetadata documentMetadata, DebuggingState? debuggingState)
|
||||
where TCanvas : ICanvas, IRenderingCanvas
|
||||
{
|
||||
content.HandleVisitor(x => x?.Initialize(pageContext, canvas));
|
||||
content.HandleVisitor(x => (x as IStateResettable)?.ResetState());
|
||||
|
||||
canvas.BeginDocument();
|
||||
|
||||
var currentPage = 1;
|
||||
|
||||
while(true)
|
||||
{
|
||||
pageContext.SetPageNumber(currentPage);
|
||||
debuggingState?.Reset();
|
||||
|
||||
var spacePlan = content.Measure(Size.Max);
|
||||
|
||||
if (spacePlan.Type == SpacePlanType.Wrap)
|
||||
{
|
||||
canvas.EndDocument();
|
||||
ThrowLayoutException();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
canvas.BeginPage(spacePlan);
|
||||
content.Draw(spacePlan);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
canvas.EndDocument();
|
||||
throw new DocumentDrawingException("An exception occured during document drawing.", exception);
|
||||
}
|
||||
|
||||
canvas.EndPage();
|
||||
|
||||
if (currentPage >= documentMetadata.DocumentLayoutExceptionThreshold)
|
||||
{
|
||||
canvas.EndDocument();
|
||||
ThrowLayoutException();
|
||||
}
|
||||
|
||||
if (spacePlan.Type == SpacePlanType.FullRender)
|
||||
break;
|
||||
|
||||
currentPage++;
|
||||
}
|
||||
|
||||
canvas.EndDocument();
|
||||
|
||||
void ThrowLayoutException()
|
||||
{
|
||||
throw new DocumentLayoutException("Composed layout generates infinite document.")
|
||||
{
|
||||
ElementTrace = debuggingState?.BuildTrace() ?? "Debug trace is available only in the DEBUG mode."
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyCaching(Container content)
|
||||
{
|
||||
content.HandleVisitor(x =>
|
||||
{
|
||||
if (x is ICacheable)
|
||||
x.CreateProxy(y => new CacheProxy(y));
|
||||
});
|
||||
}
|
||||
|
||||
private static DebuggingState ApplyDebugging(Container content)
|
||||
{
|
||||
var debuggingState = new DebuggingState();
|
||||
|
||||
content.HandleVisitor(x =>
|
||||
{
|
||||
x.CreateProxy(y => new DebuggingProxy(debuggingState, y));
|
||||
});
|
||||
|
||||
return debuggingState;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
namespace QuestPDF.Drawing
|
||||
{
|
||||
public class DocumentMetadata
|
||||
{
|
||||
public int ImageQuality { get; set; } = 101;
|
||||
public int RasterDpi { get; set; } = 72;
|
||||
public bool PdfA { get; set; }
|
||||
|
||||
public string? Title { get; set; }
|
||||
public string? Author { get; set; }
|
||||
public string? Subject { get; set; }
|
||||
public string? Keywords { get; set; }
|
||||
public string? Creator { get; set; }
|
||||
public string? Producer { get; set; }
|
||||
|
||||
public DateTime CreationDate { get; set; } = DateTime.Now;
|
||||
public DateTime ModifiedDate { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// If the number of generated pages exceeds this threshold
|
||||
/// (likely due to infinite layout), the exception is thrown.
|
||||
/// </summary>
|
||||
public int DocumentLayoutExceptionThreshold { get; set; } = 250;
|
||||
|
||||
public static DocumentMetadata Default => new DocumentMetadata();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
namespace QuestPDF.Drawing.Exceptions
|
||||
{
|
||||
public class DocumentComposeException : Exception
|
||||
{
|
||||
public DocumentComposeException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public DocumentComposeException(string message) : base(message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public DocumentComposeException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
namespace QuestPDF.Drawing.Exceptions
|
||||
{
|
||||
public class DocumentDrawingException : Exception
|
||||
{
|
||||
public DocumentDrawingException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public DocumentDrawingException(string message) : base(message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public DocumentDrawingException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace QuestPDF.Drawing.Exceptions
|
||||
{
|
||||
public class DocumentLayoutException : Exception
|
||||
{
|
||||
public string ElementTrace { get; set; }
|
||||
|
||||
public DocumentLayoutException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public DocumentLayoutException(string message) : base(message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public DocumentLayoutException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using QuestPDF.Infrastructure;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace QuestPDF.Drawing
|
||||
{
|
||||
public static class FontManager
|
||||
{
|
||||
private static ConcurrentDictionary<string, SKTypeface> Typefaces = new ConcurrentDictionary<string, SKTypeface>();
|
||||
private static ConcurrentDictionary<string, SKFontMetrics> FontMetrics = new ConcurrentDictionary<string, SKFontMetrics>();
|
||||
private static ConcurrentDictionary<string, SKPaint> Paints = new ConcurrentDictionary<string, SKPaint>();
|
||||
private static ConcurrentDictionary<string, SKPaint> ColorPaint = new ConcurrentDictionary<string, SKPaint>();
|
||||
|
||||
public static void RegisterFontType(string fontName, Stream stream)
|
||||
{
|
||||
Typefaces.TryAdd(fontName, SKTypeface.FromStream(stream));
|
||||
}
|
||||
|
||||
internal static SKPaint ColorToPaint(this string color)
|
||||
{
|
||||
return ColorPaint.GetOrAdd(color, Convert);
|
||||
|
||||
static SKPaint Convert(string color)
|
||||
{
|
||||
return new SKPaint
|
||||
{
|
||||
Color = SKColor.Parse(color)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal static SKPaint ToPaint(this TextStyle style)
|
||||
{
|
||||
return Paints.GetOrAdd(style.ToString(), key => Convert(style));
|
||||
|
||||
static SKPaint Convert(TextStyle style)
|
||||
{
|
||||
return new SKPaint
|
||||
{
|
||||
Color = SKColor.Parse(style.Color),
|
||||
Typeface = GetTypeface(style),
|
||||
TextSize = style.Size,
|
||||
TextEncoding = SKTextEncoding.Utf32
|
||||
};
|
||||
}
|
||||
|
||||
static SKTypeface GetTypeface(TextStyle style)
|
||||
{
|
||||
if (Typefaces.TryGetValue(style.FontType, out var result))
|
||||
return result;
|
||||
|
||||
var slant = style.IsItalic ? SKFontStyleSlant.Italic : SKFontStyleSlant.Upright;
|
||||
|
||||
return SKTypeface.FromFamilyName(style.FontType, (int)style.FontWeight, (int)SKFontStyleWidth.Normal, slant)
|
||||
?? throw new ArgumentException($"The typeface {style.FontType} could not be found.");
|
||||
}
|
||||
}
|
||||
|
||||
internal static SKFontMetrics ToFontMetrics(this TextStyle style)
|
||||
{
|
||||
return FontMetrics.GetOrAdd(style.ToString(), key => style.ToPaint().FontMetrics);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ namespace QuestPDF.Drawing
|
||||
|
||||
}
|
||||
|
||||
public void DrawText(SKTextBlob skTextBlob, Position position, TextStyle style)
|
||||
public void DrawText(string text, Position position, TextStyle style)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -51,17 +51,17 @@ namespace QuestPDF.Drawing
|
||||
|
||||
}
|
||||
|
||||
public void DrawHyperlink(string url, Size size)
|
||||
public void DrawExternalLink(string url, Size size)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void DrawSectionLink(string sectionName, Size size)
|
||||
public void DrawLocationLink(string locationName, Size size)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void DrawSection(string sectionName)
|
||||
public void DrawLocation(string locationName)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,31 +1,47 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using QuestPDF.Drawing.Exceptions;
|
||||
using QuestPDF.Helpers;
|
||||
using System.IO;
|
||||
using QuestPDF.Infrastructure;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace QuestPDF.Drawing
|
||||
{
|
||||
internal class PdfCanvas : SkiaDocumentCanvasBase
|
||||
internal class PdfCanvas : SkiaCanvasBase
|
||||
{
|
||||
public PdfCanvas(Stream stream, DocumentMetadata documentMetadata)
|
||||
: base(CreatePdf(stream, documentMetadata))
|
||||
private SKDocument Document { get; }
|
||||
|
||||
public PdfCanvas(Stream stream, DocumentMetadata documentMetadata)
|
||||
{
|
||||
Document = SKDocument.CreatePdf(stream, MapMetadata(documentMetadata));
|
||||
}
|
||||
|
||||
~PdfCanvas()
|
||||
{
|
||||
Document.Dispose();
|
||||
}
|
||||
|
||||
public override void BeginDocument()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private static SKDocument CreatePdf(Stream stream, DocumentMetadata documentMetadata)
|
||||
public override void EndDocument()
|
||||
{
|
||||
try
|
||||
{
|
||||
return SKDocument.CreatePdf(stream, MapMetadata(documentMetadata));
|
||||
}
|
||||
catch (TypeInitializationException exception)
|
||||
{
|
||||
throw new InitializationException("PDF", exception);
|
||||
}
|
||||
Canvas?.Dispose();
|
||||
|
||||
Document?.Close();
|
||||
Document?.Dispose();
|
||||
}
|
||||
|
||||
public override void BeginPage(Size size)
|
||||
{
|
||||
Canvas = Document.BeginPage(size.Width, size.Height);
|
||||
}
|
||||
|
||||
public override void EndPage()
|
||||
{
|
||||
Document.EndPage();
|
||||
Canvas.Dispose();
|
||||
}
|
||||
|
||||
private static SKDocumentPdfMetadata MapMetadata(DocumentMetadata metadata)
|
||||
{
|
||||
return new SKDocumentPdfMetadata
|
||||
+2
-2
@@ -76,7 +76,7 @@ namespace QuestPDF.Drawing.Proxy
|
||||
title += debugPointer.Highlight ? " 🌟" : string.Empty;
|
||||
}
|
||||
|
||||
if (item.SpacePlan.Type != SpacePlanType.FullRender)
|
||||
if (item.SpacePlan.Type == SpacePlanType.Wrap)
|
||||
title = "🔥 " + title;
|
||||
|
||||
builder.AppendLine(indent + title);
|
||||
@@ -109,7 +109,7 @@ namespace QuestPDF.Drawing.Proxy
|
||||
Value = x.GetValue(element)
|
||||
})
|
||||
.Where(x => !(x.Value is IElement))
|
||||
.Where(x => x.Value is string || !(x.Value is IEnumerable))
|
||||
.Where(x => !(x.Value is IEnumerable<IElement>))
|
||||
.Where(x => !(x.Value is TextStyle))
|
||||
.Select(x => $"{x.Property}: {FormatValue(x.Value)}");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user