Compare commits

...

13 Commits

Author SHA1 Message Date
MarcinZiabek 27a808b389 2023.4.2 release 2023-05-09 02:38:17 +02:00
Marcin Ziąbek e23a7bd821 Table: fixed zindex rendering issue (#555) 2023-05-09 02:36:13 +02:00
MarcinZiabek 40603ada12 2023.4.1 release 2023-05-04 19:21:45 +02:00
MarcinZiabek b5d8fc403f Including documentation comments in nuget 2023-05-04 19:20:20 +02:00
MarcinZiabek 84ed879026 2023.4.0 Updated Previewer configuration 2023-05-04 13:48:30 +02:00
Marcin Ziąbek 3bcb0ed947 Update README.md 2023-05-04 13:41:30 +02:00
MarcinZiabek 498a86359a Release 2023.4.0 2023-05-04 13:35:11 +02:00
Marcin Ziąbek 4d1db6b76e Dual license integration (#545)
* Added library license validation check with a detailed description

* Improved license-related message

* Adjusted license information

* Updated nuget license

* Improved grammar

* License message: added link to license configuration

* Fixed build
2023-05-04 13:25:06 +02:00
Marcin Ziąbek 6796d4a181 License update (#539)
* License information + folder cleanup

* Updated license information

* Fixed spelling

* Spelling fix

* License information adjustments
2023-04-28 14:07:21 +02:00
MarcinZiabek 6074ed0e7e Font fallback: fixed regression 2023-04-27 17:01:50 +02:00
MarcinZiabek a560c6c864 Release 2022.12.4 2023-04-22 10:01:53 +02:00
Marcin Ziąbek 327c412c7d Fix(#483): TextStyle.Fallback incorrectly inherits parent's and global properties (#532)
* Fixed applying text style for fallback styles

* Code refactoring

* FontStyle: making method arguments explicit

* Bug fixes + test

* Minor code refactoring
2023-04-22 09:57:07 +02:00
Marcin Ziąbek 4b5eeea896 Update README.md 2023-04-18 23:50:24 +02:00
27 changed files with 473 additions and 112 deletions
View File
View File
-21
View File
@@ -1,21 +0,0 @@
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.
+13
View File
@@ -0,0 +1,13 @@
# 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.
@@ -0,0 +1,29 @@
# 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.
+23
View File
@@ -0,0 +1,23 @@
# 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.
+21 -4
View File
@@ -9,14 +9,15 @@
[![GitHub Repo stars](https://img.shields.io/github/stars/QuestPDF/QuestPDF?style=for-the-badge)](https://github.com/QuestPDF/QuestPDF/stargazers)
[![Nuget version](https://img.shields.io/nuget/v/QuestPdf?style=for-the-badge)](https://www.nuget.org/packages/QuestPDF/)
[![Nuget download](https://img.shields.io/nuget/dt/QuestPDF?style=for-the-badge)](https://www.nuget.org/packages/QuestPDF/)
[![License](https://img.shields.io/github/license/QuestPDF/QuestPDF?style=for-the-badge)](https://github.com/QuestPDF/QuestPDF/blob/main/LICENSE)
[![QuestPDF License](https://img.shields.io/badge/LICENSE%20details-Community%20MIT%20and%20professional-green?style=for-the-badge)](https://www.questpdf.com/pricing.html#license)
<br />
### QuestPDF is a modern open-source .NET library for PDF document generation. Offering comprehensive layout engine powered by concise and discoverable C# Fluent API.
<img src="https://github.com/QuestPDF/QuestPDF-Documentation/blob/main/docs/public/previewer/animation.gif?raw=true" width="100%">
<table>
<tr>
<td>👨‍💻</td>
@@ -48,13 +49,14 @@
<br />
## Please help by giving a star
Choosing a project dependency could be difficult. We need to ensure stability and maintainability of our projects. Surveys show that GitHub stars count play an important factor when assessing library quality.
⭐ Please give this repository a star. It takes seconds and help thousands of developers! ⭐
<img src="https://user-images.githubusercontent.com/9263853/224511996-9dd27a99-bef8-4d5e-bc14-9f6cfe0f5191.png" width="800" />
<img src="https://user-images.githubusercontent.com/9263853/236193691-efb9cff8-e919-4826-9720-dcfb492980ae.png" width="800" />
## Please share with the community
@@ -68,6 +70,7 @@ As an open-source project without funding, I cannot afford advertising QuestPDF
<br />
## Let's get started
Begin exploring the QuestPDF library today. You are 250 lines of C# code away from creating a fully functional PDF invoice implementation.
@@ -80,6 +83,21 @@ Read the Getting Started tutorial to familiarize yourself with general library a
<br />
## Library 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.
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.
If you still want to support library development, please consider purchasing the Professional License.
[![Library license details](https://img.shields.io/badge/%F0%9F%93%9C%0A%20read-license%20details-blue?style=for-the-badge)](https://www.questpdf.com/pricing.html#license)
[![Library pricing details](https://img.shields.io/badge/%F0%9F%92%8E%20read-pricing%20details-green?style=for-the-badge)](https://www.questpdf.com/pricing.html#tiers)
<br />
## QuestPDF on JetBrains OSS Power-Ups
QuestPDF was presented on one of the episodes of OSS Power-Ups hosted by JetBrains. Huge thanks for Matthias Koch and entire JetBrains team for giving me a chance to show QuestPDF. You are the best!
@@ -88,5 +106,4 @@ QuestPDF was presented on one of the episodes of OSS Power-Ups hosted by JetBrai
<img src="https://github.com/QuestPDF/QuestPDF-Documentation/blob/main/docs/public/jetbrains-oss-powerups-youtube.png?raw=true" width="600px">
</a>
[![YouTube video about QuestPDF]( https://img.shields.io/badge/watch%20on-YouTube-red?logo=youtube&style=for-the-badge)](https://www.youtube.com/watch?v=-iYvZvpLX0g)
+15
View File
@@ -0,0 +1,15 @@
using NUnit.Framework;
using QuestPDF.Infrastructure;
namespace QuestPDF.Examples
{
[SetUpFixture]
public class LicenseSetup
{
[OneTimeSetUp]
public static void Setup()
{
QuestPDF.Settings.License = LicenseType.Community;
}
}
}
+52
View File
@@ -316,6 +316,58 @@ namespace QuestPDF.Examples
});
}
[Test]
public void Bug_RowSpanWorksIncorrectly()
{
// https://github.com/QuestPDF/QuestPDF/issues/552
RenderingTest
.Create()
.ProduceImages()
.PageSize(PageSizes.A5.Landscape())
.ShowResults()
.Render(container =>
{
container.Padding(20).Table(table =>
{
table.ColumnsDefinition(columns =>
{
columns.RelativeColumn(1);
columns.RelativeColumn(2);
columns.RelativeColumn(2);
columns.RelativeColumn(2);
});
foreach (var i in Enumerable.Range(6, 9))
{
table.Cell().Element(CellStyleMainTable).Text($"{i:00}:00");
foreach (var j in Enumerable.Range(1, 3))
table.Cell().Element(CellStyleMainTable).Text("");
}
static IContainer CellStyleMainTable(IContainer container)
{
return container
.Border(0.5f).BorderColor(Colors.Blue.Lighten4)
.Background(Colors.Blue.Lighten5)
.PaddingVertical(5);
}
table.Cell().Row(1).RowSpan(3).Column(2).Element(BlockAccepted).Text("3 rows");
table.Cell().Row(1).RowSpan(6).Column(3).Element(BlockAccepted).Text("6 rows");
table.Cell().Row(3).RowSpan(5).Column(4).Element(BlockAccepted).Text("5 rows");
static IContainer BlockAccepted(IContainer container)
{
return container
.Border(1.5f).BorderColor(Colors.Green.Lighten2)
.Background(Colors.Green.Lighten4);
}
});
});
}
[Test]
public void TableHeader()
{
+35
View File
@@ -1004,5 +1004,40 @@ namespace QuestPDF.Examples
});
});
}
[Test]
public void FontFallback_Nested()
{
RenderingTest
.Create()
.ProduceImages()
.ShowResults()
.RenderDocument(container =>
{
container.Page(page =>
{
page.Margin(50);
page.PageColor(Colors.White);
page.Size(PageSizes.A5.Landscape());
page.DefaultTextStyle(x => x
.FontSize(24)
.Bold()
.FontFamily("Times New Roman")
.Fallback(y => y
.FontFamily("Microsoft YaHei")
.Underline()
.BackgroundColor(Colors.Red.Lighten2)));
page.Content().Text(text =>
{
text.Line("Default times new roman 中文文本 text.");
text.Line("Normal weight and green 中文文本 text.").NormalWeight().BackgroundColor(Colors.Green.Lighten2);
text.Line("Strikethrough without underline 中文文本 text.").Strikethrough().Underline(false);
text.Line("Lato italic 中文文本 text.").FontFamily("Lato").Italic();
});
});
});
}
}
}
@@ -4,11 +4,10 @@
<Authors>MarcinZiabek</Authors>
<Company>CodeFlint</Company>
<PackageId>QuestPDF.Previewer</PackageId>
<Version>2022.12.0</Version>
<Version>2023.4.0</Version>
<PackAsTool>true</PackAsTool>
<ToolCommandName>questpdf-previewer</ToolCommandName>
<PackageDescription>QuestPDF is an open-source, modern and battle-tested library that can help you with generating PDF documents by offering friendly, discoverable and predictable C# fluent API.</PackageDescription>
<PackageReleaseNotes>Initial release.</PackageReleaseNotes>
<LangVersion>10</LangVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageIcon>Logo.png</PackageIcon>
@@ -18,10 +17,8 @@
<RepositoryUrl>https://github.com/QuestPDF/library.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Copyright>Marcin Ziąbek, QuestPDF contributors</Copyright>
<PackageTags>pdf report file export generate generation tool create creation render portable document format quest html library converter open source free standard core previewer</PackageTags>
<PackageTags>previewer pdf report file export generate generation tool create creation render portable document format quest html library converter open source free standard core</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<OutputType>exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
+2
View File
@@ -17,6 +17,8 @@ namespace QuestPDF.ReportSample
[SetUp]
public void SetUp()
{
QuestPDF.Settings.License = LicenseType.Community;
var model = DataSource.GetReport();
Report = new StandardReport(model);
}
@@ -3,6 +3,7 @@
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<LangVersion>9</LangVersion>
</PropertyGroup>
<ItemGroup>
@@ -0,0 +1,59 @@
using FluentAssertions;
using NUnit.Framework;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.UnitTests
{
[TestFixture]
public class TextStyleTests
{
[Test]
public void ApplyInheritedAndGlobalStyle()
{
// arrange
var defaultTextStyle = TextStyle
.Default
.FontSize(20)
.FontFamily("Arial")
.BackgroundColor(Colors.Green.Lighten2)
.Fallback(y => y
.FontFamily("Microsoft YaHei")
.Underline()
.NormalWeight()
.BackgroundColor(Colors.Blue.Lighten2));
var spanTextStyle = TextStyle
.Default
.FontFamily("Times New Roman")
.Bold()
.Strikethrough()
.BackgroundColor(Colors.Red.Lighten2);
// act
var targetStyle = spanTextStyle.ApplyInheritedStyle(defaultTextStyle).ApplyGlobalStyle();
// assert
var expectedStyle = TextStyle.LibraryDefault with
{
Size = 20,
FontFamily = "Times New Roman",
FontWeight = FontWeight.Bold,
BackgroundColor = Colors.Red.Lighten2,
HasStrikethrough = true,
Fallback = TextStyle.LibraryDefault with
{
Size = 20,
FontFamily = "Microsoft YaHei",
FontWeight = FontWeight.Bold,
BackgroundColor = Colors.Red.Lighten2,
HasUnderline = true,
HasStrikethrough = true
}
};
targetStyle.Should().BeEquivalentTo(expectedStyle);
}
}
}
+43 -13
View File
@@ -17,6 +17,7 @@ namespace QuestPDF.Drawing
{
internal static void GeneratePdf(Stream stream, IDocument document)
{
ValidateLicense();
CheckIfStreamIsCompatible(stream);
var metadata = document.GetMetadata();
@@ -26,6 +27,7 @@ namespace QuestPDF.Drawing
internal static void GenerateXps(Stream stream, IDocument document)
{
ValidateLicense();
CheckIfStreamIsCompatible(stream);
var metadata = document.GetMetadata();
@@ -44,6 +46,8 @@ namespace QuestPDF.Drawing
internal static ICollection<byte[]> GenerateImages(IDocument document)
{
ValidateLicense();
var metadata = document.GetMetadata();
var canvas = new ImageCanvas(metadata);
RenderDocument(canvas, document);
@@ -51,6 +55,35 @@ namespace QuestPDF.Drawing
return canvas.Images;
}
private static void ValidateLicense()
{
if (Settings.License.HasValue)
return;
var newParagraph = Environment.NewLine + Environment.NewLine;
var exceptionMessage =
$"QuestPDF is a modern open-source library. " +
$"We identify the importance of the library in your projects and therefore want to make sure you can safely and confidently continue the development. " +
$"Being a healthy and growing community is the primary goal that motivates us to pursue professionalism. {newParagraph}" +
$"We love and highly appreciate the .NET Community, and therefore the vast majority of users are welcome to use the library completely for free under the QuestPDF Community MIT license. {newParagraph}" +
$"However, 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 the number of software developers. {newParagraph}" +
$"If you still want to support library development, please consider purchasing the Professional License. {newParagraph}" +
$"For evaluation purposes, feel free to use the QuestPDF Community License in a non-production environment. {newParagraph}" +
$"Please refer to the QuestPDF License and Pricing webpage for more details. (https://www.questpdf.com/pricing.html) {newParagraph}" +
$"If you are an existing QuestPDF user and for any reason cannot update, you can stay with the 2022.12.X release with the extended quality support but without any new features, improvements, or optimizations. That release will always be available under the MIT license, free for commercial usage. {newParagraph}" +
$"The library does not require any license key. " +
$"We trust our users, and therefore the process is simple. " +
$"To disable license validation and turn off this exception, please configure an eligible license using the QuestPDF.Settings.License API, for example: {newParagraph}" +
$"\"QuestPDF.Settings.License = LicenseType.Community;\" {newParagraph}" +
$"Learn more on: https://www.questpdf.com/license-configuration.html {newParagraph}";
throw new Exception(exceptionMessage)
{
HelpLink = "https://www.questpdf.com/pricing.html"
};
}
internal static ICollection<PreviewerPicture> GeneratePreviewerPictures(IDocument document)
{
var canvas = new SkiaPictureCanvas();
@@ -64,7 +97,7 @@ namespace QuestPDF.Drawing
var container = new DocumentContainer();
document.Compose(container);
var content = container.Compose();
ApplyDefaultTextStyle(content, TextStyle.LibraryDefault);
ApplyInheritedAndGlobalTexStyle(content, TextStyle.Default);
ApplyContentDirection(content, ContentDirection.LeftToRight);
var debuggingState = Settings.EnableDebugging ? ApplyDebugging(content) : null;
@@ -192,7 +225,7 @@ namespace QuestPDF.Drawing
ApplyContentDirection(child, direction);
}
internal static void ApplyDefaultTextStyle(this Element? content, TextStyle documentDefaultTextStyle)
internal static void ApplyInheritedAndGlobalTexStyle(this Element? content, TextStyle documentDefaultTextStyle)
{
if (content == null)
return;
@@ -202,26 +235,23 @@ namespace QuestPDF.Drawing
foreach (var textBlockItem in textBlock.Items)
{
if (textBlockItem is TextBlockSpan textSpan)
{
textSpan.Style = textSpan.Style.ApplyGlobalStyle(documentDefaultTextStyle);
}
else if (textBlockItem is TextBlockElement textElement)
{
ApplyDefaultTextStyle(textElement.Element, documentDefaultTextStyle);
}
textSpan.Style = textSpan.Style.ApplyInheritedStyle(documentDefaultTextStyle).ApplyGlobalStyle();
if (textBlockItem is TextBlockElement textElement)
ApplyInheritedAndGlobalTexStyle(textElement.Element, documentDefaultTextStyle);
}
return;
}
if (content is DynamicHost dynamicHost)
dynamicHost.TextStyle = dynamicHost.TextStyle.ApplyGlobalStyle(documentDefaultTextStyle);
dynamicHost.TextStyle = dynamicHost.TextStyle.ApplyInheritedStyle(documentDefaultTextStyle);
if (content is DefaultTextStyle defaultTextStyleElement)
documentDefaultTextStyle = defaultTextStyleElement.TextStyle.ApplyGlobalStyle(documentDefaultTextStyle);
documentDefaultTextStyle = defaultTextStyleElement.TextStyle.ApplyInheritedStyle(documentDefaultTextStyle);
foreach (var child in content.GetChildren())
ApplyDefaultTextStyle(child, documentDefaultTextStyle);
ApplyInheritedAndGlobalTexStyle(child, documentDefaultTextStyle);
}
}
}
}
+1 -1
View File
@@ -89,7 +89,7 @@ namespace QuestPDF.Elements
var container = new DynamicElement();
content(container);
container.ApplyDefaultTextStyle(TextStyle);
container.ApplyInheritedAndGlobalTexStyle(TextStyle);
container.ApplyContentDirection(ContentDirection);
container.InjectDependencies(PageContext, Canvas);
+1 -1
View File
@@ -112,7 +112,7 @@ namespace QuestPDF.Elements.Table
UpdateColumnsWidth(availableSpace.Width);
var renderingCommands = PlanLayout(availableSpace);
foreach (var command in renderingCommands)
foreach (var command in renderingCommands.OrderBy(x => x.Cell.ZIndex))
{
if (command.Measurement.Type == SpacePlanType.FullRender)
command.Cell.IsRendered = true;
@@ -8,6 +8,8 @@ namespace QuestPDF.Elements.Table
public int Column { get; set; } = 0;
public int ColumnSpan { get; set; } = 1;
public int ZIndex { get; set; }
public bool IsRendered { get; set; }
}
}
@@ -16,9 +16,13 @@ namespace QuestPDF.Elements.Table
{
var cellsWindow = new List<TableCell>();
(int x, int y) currentLocation = (1, 1);
var zIndex = 0;
foreach (var cell in cells)
{
cell.ZIndex = zIndex;
zIndex++;
if (cellsWindow.Count > Math.Max(columnsCount, 16))
{
cellsWindow = cellsWindow
@@ -0,0 +1,30 @@
namespace QuestPDF.Infrastructure
{
public enum LicenseType
{
/// <summary>
/// <para>We love and highly appreciate the .NET Community and therefore the vast majority of users are welcome to use the library under the QuestPDF Community MIT License, without any limitations, even for commercial usage. Please kindly check if you are eligible to use this license.</para>
/// <para>License comparison: http://www.questpdf.com/pricing.html#license</para>
/// <para>License link: https://www.questpdf.com/license-community.html</para>
/// </summary>
Community,
/// <summary>
/// <para>You must purchase the QuestPDF Professional 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, <c>and there are up to 10 developers</c>.</para>
/// <para>If the number of developers is more than 10, you must purchase the QuestPDF Enterprise license.</para>
/// <para>Before making a license purchase, please evaluate the library in a non-production environment.</para>
/// <para>License comparison: http://www.questpdf.com/pricing.html#license</para>
/// <para>License link: https://www.questpdf.com/license-commercial.html</para>
/// </summary>
Professional,
/// <summary>
/// <para>You must purchase the QuestPDF Professional 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.</para>
/// <para>If there are less than 10 developers, you are eligible to use the cheaper QuestPDF Professional License.</para>
/// <para>Before making a license purchase, please evaluate the library in a non-production environment.</para>
/// <para>License comparison: http://www.questpdf.com/pricing.html#license</para>
/// <para>License link: https://www.questpdf.com/license-commercial.html</para>
/// </summary>
Enterprise
}
}
@@ -25,16 +25,17 @@ namespace QuestPDF.Infrastructure
internal static class TextStyleManager
{
private static readonly ConcurrentDictionary<(TextStyle origin, TextStyleProperty property, object value), TextStyle> TextStyleMutateCache = new();
private static readonly ConcurrentDictionary<(TextStyle origin, TextStyle parent), TextStyle> TextStyleApplyGlobalCache = new();
private static readonly ConcurrentDictionary<(TextStyle origin, TextStyle parent), TextStyle> TextStyleApplyInheritedCache = new();
private static readonly ConcurrentDictionary<TextStyle, TextStyle> TextStyleApplyGlobalCache = new();
private static readonly ConcurrentDictionary<(TextStyle origin, TextStyle parent), TextStyle> TextStyleOverrideCache = new();
public static TextStyle Mutate(this TextStyle origin, TextStyleProperty property, object value)
{
var cacheKey = (origin, property, value);
return TextStyleMutateCache.GetOrAdd(cacheKey, x => MutateStyle(x.origin, x.property, x.value));
return TextStyleMutateCache.GetOrAdd(cacheKey, x => MutateStyle(x.origin, x.property, x.value, overrideValue: true));
}
private static TextStyle MutateStyle(TextStyle origin, TextStyleProperty property, object? value, bool overrideValue = true)
private static TextStyle MutateStyle(this TextStyle origin, TextStyleProperty property, object? value, bool overrideValue)
{
if (overrideValue && value == null)
return origin;
@@ -224,40 +225,42 @@ namespace QuestPDF.Infrastructure
throw new ArgumentOutOfRangeException(nameof(property), property, "Expected to mutate the TextStyle object. Provided property type is not supported.");
}
internal static TextStyle ApplyGlobalStyle(this TextStyle style, TextStyle parent)
internal static TextStyle ApplyInheritedStyle(this TextStyle style, TextStyle parent)
{
var cacheKey = (style, parent);
return TextStyleApplyGlobalCache.GetOrAdd(cacheKey, key => ApplyStyle(key.origin, key.parent, overrideStyle: false).ApplyFontFallback());
return TextStyleApplyInheritedCache.GetOrAdd(cacheKey, key => key.origin.ApplyStyleProperties(key.parent, overrideStyle: false, overrideFontFamily: false, applyFallback: true).UpdateFontFallback(overrideStyle: true));
}
private static TextStyle ApplyFontFallback(this TextStyle style)
internal static TextStyle ApplyGlobalStyle(this TextStyle style)
{
return TextStyleApplyGlobalCache.GetOrAdd(style, key => key.ApplyStyleProperties(TextStyle.LibraryDefault, overrideStyle: false, overrideFontFamily: false, applyFallback: true).UpdateFontFallback(overrideStyle: false));
}
private static TextStyle UpdateFontFallback(this TextStyle style, bool overrideStyle)
{
var targetFallbackStyle = style
?.Fallback
?.ApplyStyle(style, overrideStyle: false, applyFallback: false)
?.ApplyFontFallback();
?.ApplyStyleProperties(style, overrideStyle: overrideStyle, overrideFontFamily: false, applyFallback: false)
?.UpdateFontFallback(overrideStyle);
return MutateStyle(style, TextStyleProperty.Fallback, targetFallbackStyle);
return style.MutateStyle(TextStyleProperty.Fallback, targetFallbackStyle, overrideValue: true);
}
internal static TextStyle OverrideStyle(this TextStyle style, TextStyle parent)
{
var cacheKey = (style, parent);
return TextStyleOverrideCache.GetOrAdd(cacheKey, key =>
{
var result = ApplyStyle(key.origin, key.parent);
return MutateStyle(result, TextStyleProperty.Fallback, key.parent.Fallback);
});
return TextStyleOverrideCache.GetOrAdd(cacheKey, key => ApplyStyleProperties(key.origin, key.parent, overrideStyle: true, overrideFontFamily: true, applyFallback: true));
}
private static TextStyle ApplyStyle(this TextStyle style, TextStyle parent, bool overrideStyle = true, bool applyFallback = true)
private static TextStyle ApplyStyleProperties(this TextStyle style, TextStyle parent, bool overrideStyle, bool overrideFontFamily, bool applyFallback)
{
var result = style;
if (string.IsNullOrWhiteSpace(result.FontFamily) || overrideFontFamily)
result = MutateStyle(result, TextStyleProperty.FontFamily, parent.FontFamily, overrideStyle);
result = MutateStyle(result, TextStyleProperty.Color, parent.Color, overrideStyle);
result = MutateStyle(result, TextStyleProperty.BackgroundColor, parent.BackgroundColor, overrideStyle);
result = MutateStyle(result, TextStyleProperty.FontFamily, parent.FontFamily, overrideStyle);
result = MutateStyle(result, TextStyleProperty.Size, parent.Size, overrideStyle);
result = MutateStyle(result, TextStyleProperty.LineHeight, parent.LineHeight, overrideStyle);
result = MutateStyle(result, TextStyleProperty.LetterSpacing, parent.LetterSpacing, overrideStyle);
@@ -18,8 +18,8 @@ namespace QuestPDF.Previewer
public event Action? OnPreviewerStopped;
private const int RequiredPreviewerVersionMajor = 2022;
private const int RequiredPreviewerVersionMinor = 12;
private const int RequiredPreviewerVersionMajor = 2023;
private const int RequiredPreviewerVersionMinor = 4;
public PreviewerService(int port)
{
+40 -27
View File
@@ -3,7 +3,7 @@
<Authors>MarcinZiabek</Authors>
<Company>CodeFlint</Company>
<PackageId>QuestPDF</PackageId>
<Version>2022.12.3</Version>
<Version>2023.4.2</Version>
<PackageDescription>QuestPDF is an open-source, modern and battle-tested library that can help you with generating PDF documents by offering friendly, discoverable and predictable C# fluent API. Easily generate PDF reports, invoices, exports, etc.</PackageDescription>
<PackageReleaseNotes>$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/Resources/ReleaseNotes.txt"))</PackageReleaseNotes>
<LangVersion>9</LangVersion>
@@ -12,15 +12,17 @@
<PackageIconUrl>https://www.questpdf.com/images/package-logo.png</PackageIconUrl>
<PackageProjectUrl>https://www.questpdf.com/</PackageProjectUrl>
<PackageReadmeFile>PackageReadme.md</PackageReadmeFile>
<PackageLicenseFile>PackageLicense.md</PackageLicenseFile>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
<RepositoryUrl>https://github.com/QuestPDF/library.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Copyright>Marcin Ziąbek, QuestPDF contributors</Copyright>
<PackageTags>pdf report file export generate generation tool create creation render portable document format quest html library converter open source free standard core</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Nullable>enable</Nullable>
<TargetFrameworks>net462;netstandard2.0;netcoreapp2.0;netcoreapp3.0;net6.0</TargetFrameworks>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
@@ -37,32 +39,43 @@
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\ImagePlaceholder.png" />
<EmbeddedResource Include="Resources\Logo.png" />
<None Remove="ImagePlaceholder.png" />
<None Include="Resources\PackageReadme.md" Pack="true" PackagePath="\" />
<None Include="Resources\PackageLicense.md" Pack="true" PackagePath="\" />
<None Include="Resources\Logo.png" Pack="true" PackagePath="\" />
<EmbeddedResource Include="Resources\Logo.png" />
<None Include="Resources\Logo.png" Pack="true" PackagePath="\" />
<None Include="Resources\PackageReadme.md" Pack="true" PackagePath="\" />
<None Remove="ImagePlaceholder.png" />
<EmbeddedResource Include="Resources\ImagePlaceholder.png" />
<None Remove="Resources\DefaultFont\Lato-Black.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-Black.ttf" />
<None Remove="Resources\DefaultFont\Lato-BlackItalic.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-BlackItalic.ttf" />
<None Remove="Resources\DefaultFont\Lato-Bold.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-Bold.ttf" />
<None Remove="Resources\DefaultFont\Lato-BoldItalic.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-BoldItalic.ttf" />
<None Remove="Resources\DefaultFont\Lato-Italic.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-Italic.ttf" />
<None Remove="Resources\DefaultFont\Lato-Light.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-Light.ttf" />
<None Remove="Resources\DefaultFont\Lato-LightItalic.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-LightItalic.ttf" />
<None Remove="Resources\DefaultFont\Lato-Regular.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-Regular.ttf" />
<None Remove="Resources\DefaultFont\Lato-Thin.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-Thin.ttf" />
<None Remove="Resources\DefaultFont\Lato-ThinItalic.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-ThinItalic.ttf" />
<None Remove="Resources\DefaultFont\Lato-Black.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-Black.ttf" />
<None Remove="Resources\DefaultFont\Lato-BlackItalic.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-BlackItalic.ttf" />
<None Remove="Resources\DefaultFont\Lato-Bold.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-Bold.ttf" />
<None Remove="Resources\DefaultFont\Lato-BoldItalic.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-BoldItalic.ttf" />
<None Remove="Resources\DefaultFont\Lato-Italic.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-Italic.ttf" />
<None Remove="Resources\DefaultFont\Lato-Light.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-Light.ttf" />
<None Remove="Resources\DefaultFont\Lato-LightItalic.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-LightItalic.ttf" />
<None Remove="Resources\DefaultFont\Lato-Regular.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-Regular.ttf" />
<None Remove="Resources\DefaultFont\Lato-Thin.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-Thin.ttf" />
<None Remove="Resources\DefaultFont\Lato-ThinItalic.ttf" />
<EmbeddedResource Include="Resources\DefaultFont\Lato-ThinItalic.ttf" />
</ItemGroup>
</Project>
@@ -0,0 +1,59 @@
# QuestPDF License
## What license do you need?
Suppose 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. In that case, you must purchase the QuestPDF Professional or Enterprise License, depending on the number of software developers.
We love and highly appreciate the .NET Community. Therefore, most users are welcome to use the library entirely 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.
If you still want to support library development, please consider purchasing the Professional License.
Please find all details regarding the QuestPDF license on the [official webpage](https://www.questpdf.com/pricing.html).
Being a healthy and growing community is the primary goal that motivates us to pursue professionalism. Thank you!
## 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.
## 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 right to distribute the Software (without royalty) as part of packaged commercial products.
### 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.
+9 -19
View File
@@ -1,22 +1,12 @@
Feature: implemented LetterSpacing property for the Text element
Improvement: the Text element API accepts now only string values, objects are not automatically converted anymore
Fix: the Alignment element incorrectly limits size of its child when only one axis is set (horizontal or vertical)
Maintenance: Updated SkiaSharp dependency to 2.88.3
Version 2023.4.0
In version 2022.12.1:
Fixed: loading fonts from embedded resource via the FontManager.RegisterFontFromEmbeddedResource method
Fixed: better layout calculation stability for the Column element
Improvement: exposed missing API method for the Dynamic component, enabling applying more advanced optimizations
Improvement: better API documentation for the Settings.DocumentLayoutExceptionThreshold property
This release does not contain any features or quality improvements.
Its purpose is to mark the QuestPDF shift towards the dual-licensing model.
Most users are not affected by this change.
Please visit the https://www.questpdf.com/pricing.html webpage for more information.
In version 2022.12.2:
Performance improvements in various areas
Text rendering stability improvements
Fixed: the Settings.CheckIfAllTextGlyphsAreAvailable setting does not work correctly
Version 2023.4.1:
Added IntelliSense-powered documentation for certain API methods.
In version 2022.12.3:
Fix: inconsistent text height when using multiple lines with different TextStyles
Improvement: added validation for color arguments
Fix: the inlined element is shown only once in the header but should be repeated on each page
This release was possible thanks to enormous help of AntonyCorbett, thank you!
Version 2023.4.2:
Fix: fixed the rendering order of table cells in certain scenarios
+9 -1
View File
@@ -1,7 +1,15 @@
namespace QuestPDF
using QuestPDF.Infrastructure;
namespace QuestPDF
{
public static class Settings
{
/// <summary>
/// <para>Please kindly select license type that applies to your usage of the QuestPDF library.</para>
/// <para>For more details, please check the QuestPDF License and Pricing page: https://www.questpdf.com/pricing.html</para>
/// </summary>
public static LicenseType? License { get; set; }
/// <summary>
/// This value represents the maximum number of pages that the library produces.
/// This is useful when layout constraints are too strong, e.g. one element does not fit in another.