Compare commits

...

83 Commits

Author SHA1 Message Date
MarcinZiabek e01835cc55 Minor code refactoring 2023-04-22 09:52:33 +02:00
MarcinZiabek fdc395f956 Bug fixes + test 2023-04-21 09:22:14 +02:00
MarcinZiabek bd4aac0594 FontStyle: making method arguments explicit 2023-04-19 22:57:16 +02:00
MarcinZiabek f79bd1db62 Code refactoring 2023-04-19 22:51:59 +02:00
MarcinZiabek 8cec0059d8 Fixed applying text style for fallback styles 2023-04-19 20:25:58 +02:00
MarcinZiabek ef89be9710 Improvement: updated the CreateNotMatchingFontException text to mention that glyph checking operation can be disabled with the Settings.CheckIfAllTextGlyphsAreAvailable setting 2023-04-17 02:15:19 +02:00
MarcinZiabek 176566801b 2022.12.3 release 2023-04-17 00:10:46 +02:00
MarcinZiabek 22a696fab9 Fix(#470): the inlined element is shown only once in the header but should be repeated on each page 2023-04-17 00:01:32 +02:00
MarcinZiabek 9809faccb6 Improvement (#528): added validation for color arguments 2023-04-16 23:49:47 +02:00
MarcinZiabek 6ad465b9fa Fix(#499): inconsistent text height when using multiple lines 2023-04-16 11:42:38 +02:00
MarcinZiabek e6c7befac4 Revert "Building QuestPDF Previewer for dotnet 7"
This reverts commit b05f76f848.
2023-03-15 19:48:56 +01:00
MarcinZiabek be3e4b59ec Revert "Update dotnet-desktop.yml"
This reverts commit e751bfd2ff.
2023-03-15 19:48:56 +01:00
Marcin Ziąbek e751bfd2ff Update dotnet-desktop.yml 2023-03-15 10:53:44 +01:00
MarcinZiabek b05f76f848 Building QuestPDF Previewer for dotnet 7 2023-03-14 12:28:04 +01:00
MarcinZiabek b5d7dbb346 2022.12.2 release 2023-03-12 22:14:17 +01:00
Marcin Ziąbek 0ab73f4f2b Update README.md 2023-03-11 22:18:34 +01:00
MarcinZiabek 458b379208 Remove loop to calculate maximum (target) width, remove capturing lambda 2023-03-07 21:22:45 +01:00
Marcin Ziąbek c3c0d7631c Merge pull request #454 from thomasstevens89/main
Update DynamicOptimized Example to use non-deprecated methods
2023-03-07 21:03:04 +01:00
MarcinZiabek a3ea8bceb6 Text rendering optimization: cache codepoint for space 2023-03-06 22:29:06 +01:00
MarcinZiabek 455d187897 Code formatting improvement 2023-03-06 21:42:38 +01:00
Marcin Ziąbek 65e5d36ded Merge pull request #474 from AntonyCorbett/fix_render_bug_382
Fix #382
2023-03-06 21:38:23 +01:00
Marcin Ziąbek ad5e8ab27d Merge pull request #489 from AntonyCorbett/perf_linq_02
Small perf improvement in LINQ (2)
2023-03-06 20:15:53 +01:00
Marcin Ziąbek a17197addc Merge pull request #490 from AntonyCorbett/var_scope_change_01
reduce scope of variable (remove unneeded calc)
2023-03-06 20:12:27 +01:00
Marcin Ziąbek a1e7cbbeb3 Merge pull request #505 from avobelk/fix-fallback-not-found-glyph
fix glyph check in FontFallback.MatchFallbackOption
2023-03-06 20:10:23 +01:00
Marcin Ziąbek c00ac5e9c7 Merge pull request #493 from AntonyCorbett/var_scope_change_02
reduce variable scope
2023-03-06 11:08:53 +01:00
Marcin Ziąbek 0e0a8d5d69 Merge pull request #488 from AntonyCorbett/perf_linq_01
Small perf improvement in LINQ
2023-03-06 10:54:10 +01:00
Marcin Ziąbek bc341da6dd Merge pull request #476 from AntonyCorbett/small_dictionary_perf
prevent double lookup
2023-03-06 10:49:00 +01:00
Alexander V 6096771b51 fix glyph check in FontFallback.MatchFallbackOption 2023-02-23 23:09:30 +03:00
Antony Corbett 4f097d0fed reduce variable scope 2023-02-13 17:06:15 +00:00
Antony Corbett 24beea80c7 reduce scope of variable (remove unneeded calc) 2023-02-12 14:06:55 +00:00
Antony Corbett e1e5778ff0 Small perf improvement in LINQ 2023-02-12 14:01:41 +00:00
Antony Corbett 8679391609 Small perf improvement in LINQ 2023-02-12 13:59:31 +00:00
Marcin Ziąbek c1b60287ca Update README.md 2023-02-12 00:01:47 +01:00
Marcin Ziąbek 011e1b7ce9 Update README.md 2023-02-10 00:21:17 +01:00
Antony Corbett 5fd72cbb4b prevent double lookup 2023-02-03 15:10:57 +00:00
Antony Corbett 7284998657 Fix #382 2023-02-03 10:20:39 +00:00
Marcin Ziąbek 30bd7420e2 Merge pull request #467 from AntonyCorbett/fix_exception_ctor
Fix exception ctor call.
2023-01-29 22:22:13 +01:00
Marcin Ziąbek bd48688670 Merge pull request #466 from AntonyCorbett/fix_multiple_enum
Avoid multiple enumeration
2023-01-29 22:20:48 +01:00
Marcin Ziąbek 68e3efde59 Merge pull request #465 from AntonyCorbett/unit_test_user_agent_fix
Add user agent string
2023-01-29 22:18:05 +01:00
Marcin Ziąbek 805fd55d94 Minor code formatting 2023-01-29 22:17:22 +01:00
MarcinZiabek b3a3deb354 Added example showing how to detect span position in text block (hack) 2023-01-29 22:00:14 +01:00
MarcinZiabek 68e4a10e81 Deleted obsolete performance tests 2023-01-29 22:00:14 +01:00
Antony Corbett e15a21ab0e Fix exception ctor call. 2023-01-26 14:31:44 +00:00
Antony Corbett f851221718 avoid multiple enumeration 2023-01-26 14:29:40 +00:00
Antony Corbett 91c93e68b5 Add user agent string 2023-01-26 13:49:42 +00:00
Marcin Ziąbek 3dcc35be97 Update README.md 2023-01-23 21:21:49 +01:00
Marcin Ziąbek 3f32c6e2c5 Update README.md 2023-01-19 10:07:09 +01:00
Thomas Stevens f1f609ccc1 use content() not stack() 2023-01-14 12:17:41 -05:00
Thomas Stevens 5c07485cc1 Update DynamicOptimizedExample to use non-deprecated methods 2023-01-14 12:09:11 -05:00
Marcin Ziąbek 42684ec180 Update README.md 2023-01-14 00:54:40 +01:00
MarcinZiabek 08f9f706ce Adjusted package details 2023-01-13 22:53:25 +01:00
MarcinZiabek 1f199423b0 Package description: use images from trusted sources 2023-01-13 22:48:40 +01:00
Marcin Ziąbek d8e640fcf3 Update README.md 2023-01-13 22:30:22 +01:00
MarcinZiabek fb02d97a10 Improved package description 2023-01-13 22:28:19 +01:00
MarcinZiabek d5f8a884d6 Adjusted package description 2023-01-13 22:05:31 +01:00
Marcin Ziąbek 5de5be6429 Update dotnet-desktop.yml 2023-01-13 21:41:08 +01:00
MarcinZiabek 96d57b241e 2022.12.1 2023-01-13 21:26:41 +01:00
Marcin Ziąbek 920e61fc5e Update dotnet-desktop.yml 2023-01-11 23:15:17 +01:00
Marcin Ziąbek 1cc606261c Update dotnet-desktop.yml 2023-01-11 23:04:22 +01:00
Marcin Ziąbek 0a6c021fe9 Update README.md 2023-01-11 22:54:23 +01:00
Marcin Ziąbek b65ee32daf Update README.md 2023-01-11 22:54:01 +01:00
MarcinZiabek e496917d84 Updated readme 2023-01-11 22:27:51 +01:00
MarcinZiabek a5004b986c Exposed missing API for dynamic components 2023-01-11 22:24:59 +01:00
MarcinZiabek 84d7fcf41f Improved documentation for the DocumentLayoutExceptionThreshold setting by providing the unit information 2023-01-10 12:23:48 +01:00
MarcinZiabek 641cc6dee2 Fixed: loading fonts from embedded resource via the FontManager.RegisterFontFromEmbeddedResource method 2023-01-09 11:59:11 +01:00
Marcin Ziąbek 9dbed14559 Update README.md 2023-01-06 00:48:29 +01:00
Marcin Ziąbek 6323a8dba2 Update README.md 2023-01-06 00:47:30 +01:00
Marcin Ziąbek 356dbb020d Rename LICENSE to LICENSE.md 2023-01-06 00:46:52 +01:00
Marcin Ziąbek bad6be1a28 Rename readme.md to README.md 2023-01-06 00:46:23 +01:00
MarcinZiabek 27c7383437 Updated repository structure 2023-01-06 00:45:12 +01:00
Marcin Ziąbek ecac19ee46 Update readme.md 2023-01-06 00:14:06 +01:00
Marcin Ziąbek fd37070d3b Update readme.md 2023-01-05 23:31:04 +01:00
Marcin Ziąbek 3b433f3efb Update readme.md 2023-01-04 01:22:56 +01:00
Marcin Ziąbek b3d6a39a98 Update readme.md 2023-01-04 00:34:13 +01:00
Marcin Ziąbek 8d1a449e69 Content cleanup 2023-01-03 23:58:39 +01:00
Marcin Ziąbek 7f0be69ffc Updated stargazers section, fixed readability 2023-01-03 23:53:10 +01:00
Marcin Ziąbek 8553131b99 Readme content adjustments 2023-01-03 23:46:35 +01:00
Marcin Ziąbek 1bf9198a51 Adjusted button sizes 2023-01-03 23:32:58 +01:00
MarcinZiabek 563b782f6a Fixed text configuration for twitter share button 2022-12-26 10:45:34 +01:00
MarcinZiabek edf8db878a Updated share links 2022-12-24 00:34:09 +01:00
Marcin Ziąbek 5fd6488068 Updated github star count 2022-12-24 00:12:35 +01:00
MarcinZiabek d6a7c3703d Removed GitHub sponsors section 2022-12-23 22:32:11 +01:00
MarcinZiabek 5844d3bdba Column: improved layout stability 2022-12-23 00:11:33 +01:00
312 changed files with 758 additions and 514 deletions
+4 -1
View File
@@ -32,17 +32,20 @@ jobs:
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: |
View File
-75
View File
@@ -1,75 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Engines;
using BenchmarkDotNet.Running;
using Microsoft.VisualStudio.TestPlatform.TestHost;
using NUnit.Framework;
using QuestPDF.Drawing;
using QuestPDF.Drawing.Proxy;
using QuestPDF.Elements;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using QuestPDF.ReportSample.Layouts;
namespace QuestPDF.ReportSample
{
[SimpleJob(RunStrategy.Monitoring, launchCount: 0, warmupCount: 1, targetCount: 256)]
[MinColumn, MaxColumn, MeanColumn, MedianColumn]
public class PerformanceTests
{
private PageContext PageContext { get; set; }
private DocumentMetadata Metadata { get; set; }
private Container Content { get; set; }
[Test]
public void Run()
{
ImagePlaceholder.Solid = true;
var configuration = ManualConfig
.Create(DefaultConfig.Instance)
.WithOptions(ConfigOptions.DisableOptimizationsValidator);
BenchmarkRunner.Run<PerformanceTests>(configuration);
}
[IterationSetup]
public void GenerateReportData()
{
ImagePlaceholder.Solid = true;
var model = DataSource.GetReport();
var report = new StandardReport(model);
Metadata = report.GetMetadata();
var documentContainer = new DocumentContainer();
report.Compose(documentContainer);
Content = documentContainer.Compose();
PageContext = new PageContext();
DocumentGenerator.RenderPass(PageContext, new FreeCanvas(), Content, null);
var sw = new Stopwatch();
sw.Start();
Content.VisitChildren(x =>
{
if (x is ICacheable)
x.CreateProxy(y => new CacheProxy(y));
});
sw.Stop();
Console.WriteLine($"Creating cache took: {sw.ElapsedMilliseconds}");
}
[Benchmark]
public void GenerationTest()
{
DocumentGenerator.RenderPass(PageContext, new FreeCanvas(), Content, null);
}
}
}
-93
View File
@@ -1,93 +0,0 @@
[![Dotnet](https://img.shields.io/badge/platform-.NET-blue)](https://www.nuget.org/packages/QuestPDF/)
[![GitHub Repo stars](https://img.shields.io/github/stars/QuestPDF/QuestPDF)](https://github.com/QuestPDF/QuestPDF/stargazers)
[![Nuget version](https://img.shields.io/nuget/v/QuestPdf)](https://www.nuget.org/packages/QuestPDF/)
[![Nuget download](https://img.shields.io/nuget/dt/QuestPDF)](https://www.nuget.org/packages/QuestPDF/)
[![License](https://img.shields.io/github/license/QuestPDF/QuestPDF)](https://github.com/QuestPDF/QuestPDF/blob/main/LICENSE)
[![Sponsor project](https://img.shields.io/badge/sponsor-project-red)](https://github.com/sponsors/QuestPDF)
QuestPDF is an open-source .NET library for PDF documents generation.
It offers a layout engine designed with a full paging support in mind. The document consists of many simple elements (e.g. border, background, image, text, padding, table, grid etc.) that are composed together to create more complex structures. This way, as a developer, you can understand the behavior of every element and use them with full confidence. Additionally, the document and all its elements support paging functionality. For example, an element can be moved to the next page (if there is not enough space) or even be split between pages like table's rows. All of it done with predictable and discoverable Fluent API.
## Installation
The library is available as a nuget package. You can install it as any other nuget package from your IDE, try to search by `QuestPDF`. You can find package details [on this webpage](https://www.nuget.org/packages/QuestPDF/).
```xml
// Package Manager
Install-Package QuestPDF
// .NET CLI
dotnet add package QuestPDF
// Package reference in .csproj file
<PackageReference Include="QuestPDF" Version="2022.12.0" />
```
## Documentation
[![Getting started tutorial]( https://img.shields.io/badge/%F0%9F%9A%80%20read-getting%20started-blue)](https://www.questpdf.com/documentation/getting-started.html)
A short and easy to follow tutorial showing how to design an invoice document under 200 lines of code.
[![API reference](https://img.shields.io/badge/%F0%9F%93%96%20read-API%20reference-blue)](https://www.questpdf.com/documentation/api-reference.html)
A detailed description of behavior of all available components and how to use them with C# Fluent API.
[![Patterns and Practices](https://img.shields.io/badge/%F0%9F%94%8D%20read-patterns%20and%20practices-blue)](https://www.questpdf.com/documentation/patterns-and-practices.html#document-metadata)
Everything that may help you designing great reports and create reusable code that is easy to maintain.
## Simplicity is the key
How easy it is to start and prototype with QuestPDF? Really easy thanks to its minimal API! Please analyse the code below:
```#
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
// code in your main method
Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
page.Background(Colors.White);
page.DefaultTextStyle(x => x.FontSize(20));
page.Header()
.Text("Hello PDF!")
.SemiBold().FontSize(36).FontColor(Colors.Blue.Medium);
page.Content()
.PaddingVertical(1, Unit.Centimetre)
.Column(x =>
{
x.Spacing(20);
x.Item().Text(Placeholders.LoremIpsum());
x.Item().Image(Placeholders.Image(200, 100));
});
page.Footer()
.AlignCenter()
.Text(x =>
{
x.Span("Page ");
x.CurrentPageNumber();
});
});
})
.GeneratePdf("hello.pdf");
```
And compare it to the produced PDF file:
![invoice](https://raw.githubusercontent.com/QuestPDF/QuestPDF-Documentation/main/images/minimal-example-shadow.png)
## Are you ready for more?
The Fluent API of QuestPDF scales really well. It is easy to create and maintain even most complex documents. Read [the Getting started tutorial](https://www.questpdf.com/documentation/getting-started.html) to learn QuestPDF basics and implement an invoice under 200 lines of code. You can also investigate and play with the code from [the example repository](https://github.com/QuestPDF/example-invoice).
![invoice](https://raw.githubusercontent.com/QuestPDF/QuestPDF-Documentation/main/images/invoice-small.png)
-78
View File
@@ -1,78 +0,0 @@
[![Dotnet](https://img.shields.io/badge/platform-.NET-blue)](https://www.nuget.org/packages/QuestPDF/)
[![GitHub Repo stars](https://img.shields.io/github/stars/QuestPDF/QuestPDF)](https://github.com/QuestPDF/QuestPDF/stargazers)
[![Nuget version](https://img.shields.io/nuget/v/QuestPdf)](https://www.nuget.org/packages/QuestPDF/)
[![Nuget download](https://img.shields.io/nuget/dt/QuestPDF)](https://www.nuget.org/packages/QuestPDF/)
[![License](https://img.shields.io/github/license/QuestPDF/QuestPDF)](https://github.com/QuestPDF/QuestPDF/blob/main/LICENSE)
[![Sponsor project](https://img.shields.io/badge/sponsor-project-red)](https://github.com/sponsors/QuestPDF)
QuestPDF is an open-source .NET library for PDF documents generation.
It offers a layout engine designed with a full paging support in mind. The document consists of many simple elements (e.g. border, background, image, text, padding, table, grid etc.) that are composed together to create more complex structures. This way, as a developer, you can understand the behavior of every element and use them with full confidence. Additionally, the document and all its elements support paging functionality. For example, an element can be moved to the next page (if there is not enough space) or even be split between pages like table's rows.
## Documentation
[![Getting started tutorial]( https://img.shields.io/badge/%F0%9F%9A%80%20read-getting%20started-blue)](https://www.questpdf.com/getting-started.html)
A short and easy to follow tutorial showing how to design an invoice document under 200 lines of code.
[![API reference](https://img.shields.io/badge/%F0%9F%93%96%20read-API%20reference-blue)](https://www.questpdf.com/api-reference/index.html)
A detailed description of behavior of all available components and how to use them with C# Fluent API.
[![Patterns and Practices](https://img.shields.io/badge/%F0%9F%94%8D%20read-patterns%20and%20practices-blue)](https://www.questpdf.com/design-patterns.html)
Everything that may help you designing great reports and create reusable code that is easy to maintain.
## Simplicity is the key
How easy it is to start and prototype with QuestPDF? Really easy thanks to its minimal API! Please analyse the code below:
```#
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
// code in your main method
Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
page.Background(Colors.White);
page.DefaultTextStyle(x => x.FontSize(20));
page.Header()
.Text("Hello PDF!")
.SemiBold().FontSize(36).FontColor(Colors.Blue.Medium);
page.Content()
.PaddingVertical(1, Unit.Centimetre)
.Column(x =>
{
x.Spacing(20);
x.Item().Text(Placeholders.LoremIpsum());
x.Item().Image(Placeholders.Image(200, 100));
});
page.Footer()
.AlignCenter()
.Text(x =>
{
x.Span("Page ");
x.CurrentPageNumber();
});
});
})
.GeneratePdf("hello.pdf");
```
And compare it to the produced PDF file:
![invoice](https://raw.githubusercontent.com/QuestPDF/QuestPDF-Documentation/main/docs/public/minimal-example-shadow.png)
## Are you ready for more?
The Fluent API of QuestPDF scales really well. It is easy to create and maintain even most complex documents. Read [the Getting started tutorial](https://www.questpdf.com/documentation/getting-started.html) to learn QuestPDF basics and implement an invoice under 200 lines of code. You can also investigate and play with the code from [the example repository](https://github.com/QuestPDF/example-invoice).
![invoice](https://raw.githubusercontent.com/QuestPDF/QuestPDF-Documentation/main/docs/public/invoice-small.png)
-4
View File
@@ -1,4 +0,0 @@
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
+92
View File
@@ -0,0 +1,92 @@
<a href="https://www.questpdf.com/" target="_blank">
<img src="https://github.com/QuestPDF/example-invoice/raw/main/images/logo.svg" width="400">
</a>
---
[![QuestPDF Homepage](https://img.shields.io/badge/Homepage-blue?style=for-the-badge)](https://www.questpdf.com)
[![Dotnet](https://img.shields.io/badge/platform-.NET-blue?style=for-the-badge)](https://www.nuget.org/packages/QuestPDF/)
[![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)
<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>
<td>Design PDF documents using C# and employ a code-only approach. Utilize your version control system to its fullest potential.</td>
</tr>
<tr>
<td>🧱</td>
<td>Compose PDF document with a range of powerful and predictable structural elements, such as text, image, border, table, and many more.</td>
</tr>
<tr>
<td>⚙️</td>
<td>Utilize a comprehensive layout engine, specifically designed for PDF document generation and paging support.</td>
</tr>
<tr>
<td>📖</td>
<td>Write code using concise and easy-to-understand C# Fluent API. Utilize IntelliSense to quickly discover available options.</td>
</tr>
<tr>
<td>🔗</td>
<td>Don't be limited to any proprietary scripting language or format. Follow your experience and leverage all modern C# features.</td>
</tr>
<tr>
<td>⌛</td>
<td>Save time thanks to a hot-reload capability, allowing real-time PDF document preview without code recompilation.</td>
</tr>
</table>
<br />
<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" />
## Please share with the community
As an open-source project without funding, I cannot afford advertising QuestPDF in a typical way. Instead, the library relies on community interactions. Please consider sharing a post about QuestPDF and the value it provides. It really does help!
[![Share on Reddit](https://img.shields.io/badge/share%20on-reddit-red?logo=reddit&style=for-the-badge)](https://reddit.com/submit?url=https://github.com/QuestPDF/QuestPDF&title=Check%20out%20QuestPDF%20%F0%9F%8E%8A%20a%20modern%20open-source%20.NET%20library%20%20for%20PDF%20document%20generation%20%F0%9F%9A%80)
[![Share on Twitter](https://img.shields.io/badge/share%20on-twitter-03A9F4?logo=twitter&style=for-the-badge)](https://twitter.com/share?url=https://github.com/QuestPDF/QuestPDF&text=Check%20out%20QuestPDF%20%F0%9F%8E%8A%20a%20modern%20open-source%20.NET%20library%20%20for%20PDF%20document%20generation%20%F0%9F%9A%80%20%23dotnet%20%23csharp%20%23questpdf)
[![Share on HackerNews](https://img.shields.io/badge/share%20on-hacker%20news-orange?logo=ycombinator&style=for-the-badge)](https://news.ycombinator.com/submitlink?u=https://github.com/QuestPDF/QuestPDF&t=QuestPDF%20-%20a%20modern%20open-source%20.NET%20library%20%20for%20PDF%20document%20generation)
[![Share on Facebook](https://img.shields.io/badge/share%20on-facebook-1976D2?logo=facebook&style=for-the-badge)](https://www.facebook.com/sharer/sharer.php?u=https://github.com/QuestPDF/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.
Read the Getting Started tutorial to familiarize yourself with general library architecture, important layout structures as well as to better understand helpful patterns and practices. Easily start designing your PDF documents, reports, invoices and even more.
[![Getting started tutorial](https://img.shields.io/badge/%F0%9F%9A%80%20read-getting%20started-blue?style=for-the-badge)](https://www.questpdf.com/getting-started.html)
<img src="https://github.com/QuestPDF/QuestPDF-Documentation/blob/main/docs/public/invoice-small.png?raw=true" width="400px">
<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!
<a href="https://www.youtube.com/watch?v=-iYvZvpLX0g">
<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)
-1
View File
@@ -1 +0,0 @@
<svg height="180" viewBox="0 0 180 180" width="180" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="32.64" x2="82.77" y1="61.16" y2="85.54"><stop offset=".21" stop-color="#fe2857"/><stop offset="1" stop-color="#293896"/></linearGradient><linearGradient id="b" gradientUnits="userSpaceOnUse" x1="17.38" x2="82.95" y1="69.86" y2="21.23"><stop offset="0" stop-color="#fe2857"/><stop offset=".01" stop-color="#fe2857"/><stop offset=".86" stop-color="#ff318c"/></linearGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="74.17" x2="160.27" y1="21.58" y2="99.76"><stop offset=".02" stop-color="#ff318c"/><stop offset=".21" stop-color="#fe2857"/><stop offset=".86" stop-color="#fdb60d"/></linearGradient><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="155.46" x2="55.07" y1="89.8" y2="158.9"><stop offset=".01" stop-color="#fdb60d"/><stop offset=".86" stop-color="#fcf84a"/></linearGradient><path d="m81.56 83.71-41.35-35a15 15 0 1 0 -14.47 25.7h.15l.39.12 52.16 15.89a3.53 3.53 0 0 0 1.18.21 3.73 3.73 0 0 0 1.93-6.91z" fill="url(#a)"/><path d="m89.85 25.93a10.89 10.89 0 0 0 -16.85-9.18l-50.5 30.66a15 15 0 1 0 17.9 24l45.27-36.89.36-.3a10.93 10.93 0 0 0 3.82-8.29z" fill="url(#b)"/><path d="m163.29 92-76.62-73.79a10.91 10.91 0 1 0 -14.81 16l.14.12 81.4 68.58a7.36 7.36 0 0 0 12.09-5.65 7.39 7.39 0 0 0 -2.2-5.26z" fill="url(#c)"/><path d="m165.5 97.29a7.35 7.35 0 0 0 -11.67-6l-92.71 45.3a15 15 0 1 0 15.48 25.59l85.73-58.84a7.35 7.35 0 0 0 3.17-6.05z" fill="url(#d)"/><path d="m60 60h60v60h-60z"/><g fill="#fff"><path d="m66.53 108.75h22.5v3.75h-22.5z"/><path d="m65.59 75.47 1.67-1.58a1.88 1.88 0 0 0 1.47.87c.64 0 1.06-.45 1.06-1.32v-5.92h2.58v5.94a3.44 3.44 0 0 1 -.92 2.63 3.52 3.52 0 0 1 -2.57 1 3.84 3.84 0 0 1 -3.29-1.62z"/><path d="m73.53 67.52h7.53v2.19h-5v1.43h4.49v2h-4.45v1.49h5v2.2h-7.6z"/><path d="m84.73 69.79h-2.8v-2.27h8.21v2.27h-2.81v7.09h-2.6z"/><path d="m66.63 80.58h4.42a3.47 3.47 0 0 1 2.55.83 2.09 2.09 0 0 1 .61 1.52 2.18 2.18 0 0 1 -1.45 2.09 2.27 2.27 0 0 1 1.86 2.29c0 1.69-1.31 2.69-3.55 2.69h-4.44zm5 2.89c0-.52-.42-.8-1.18-.8h-1.29v1.64h1.25c.78 0 1.24-.27 1.24-.81zm-.9 2.66h-1.57v1.73h1.62c.8 0 1.24-.31 1.24-.86-.02-.53-.4-.87-1.27-.87z"/><path d="m75.45 80.58h4.15a4.14 4.14 0 0 1 3.05 1 2.92 2.92 0 0 1 .83 2.18 3 3 0 0 1 -1.93 2.89l2.24 3.35h-3l-1.89-2.84h-.87v2.84h-2.6zm4 4.5c.87 0 1.4-.43 1.4-1.12 0-.75-.55-1.13-1.41-1.13h-1.39v2.27z"/><path d="m87.09 80.51h2.5l4 9.44h-2.79l-.67-1.69h-3.63l-.67 1.74h-2.71zm2.28 5.73-1.05-2.65-1.06 2.65z"/><path d="m94 80.55h2.6v9.37h-2.6z"/><path d="m97.56 80.55h2.44l3.37 5v-5h2.57v9.37h-2.27l-3.53-5.14v5.14h-2.58z"/><path d="m106.37 88.53 1.44-1.73a4.86 4.86 0 0 0 3 1.13c.71 0 1.08-.25 1.08-.65 0-.41-.3-.61-1.59-.91-2-.46-3.53-1-3.53-2.93 0-1.74 1.38-3 3.63-3a5.88 5.88 0 0 1 3.85 1.25l-1.25 1.78a4.56 4.56 0 0 0 -2.62-.92c-.63 0-.94.25-.94.6 0 .43.32.62 1.63.91 2.15.47 3.48 1.17 3.48 2.92 0 1.91-1.51 3-3.78 3a6.56 6.56 0 0 1 -4.4-1.45z"/></g><path d="m0 0h180v180h-180z" fill="none"/></svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

@@ -50,15 +50,15 @@ namespace QuestPDF.Examples
{
container.MinimalBox().Decoration(decoration =>
{
decoration.Header().Element(header);
decoration.Before().Element(header);
decoration.Content().Box().Stack(stack =>
decoration.Content().Column(column =>
{
foreach (var row in rows)
stack.Item().Element(row.Element);
column.Item().Element(row.Element);
});
decoration.Footer().Element(footer);
decoration.After().Element(footer);
});
});
@@ -83,15 +83,14 @@ namespace QuestPDF.Examples
.BorderBottom(1)
.BorderColor(Colors.Grey.Darken2)
.Padding(5)
.DefaultTextStyle(TextStyle.Default.SemiBold())
.Row(row =>
{
var textStyle = TextStyle.Default.SemiBold();
row.ConstantItem(30).Text("#", textStyle);
row.RelativeItem().Text("Item name", textStyle);
row.ConstantItem(50).AlignRight().Text("Count", textStyle);
row.ConstantItem(50).AlignRight().Text("Price", textStyle);
row.ConstantItem(50).AlignRight().Text("Total", textStyle);
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");
});
});
}
@@ -106,7 +105,8 @@ namespace QuestPDF.Examples
.Width(context.AvailableSize.Width)
.Padding(5)
.AlignRight()
.Text($"Subtotal: {total}$", TextStyle.Default.Size(14).SemiBold());
.DefaultTextStyle(TextStyle.Default.FontSize(14).SemiBold())
.Text($"Subtotal: {total}$");
});
}
@@ -165,7 +165,7 @@ namespace QuestPDF.Examples
.Decoration(decoration =>
{
decoration
.Header()
.Before()
.PaddingBottom(5)
.Text(text =>
{
@@ -120,5 +120,42 @@ namespace QuestPDF.Examples
.Background(Placeholders.BackgroundColor());
}
}
[Test]
public void RepeatingInlinedInHeader_Test()
{
RenderingTest
.Create()
.ProduceImages()
.ShowResults()
.RenderDocument(document =>
{
document.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(1, Unit.Inch);
page.PageColor(Colors.White);
page.Header()
.Inlined(inlined =>
{
inlined.Spacing(10);
foreach (var i in Enumerable.Range(5, 5))
inlined.Item().Width(i * 10).Height(20).Background(Colors.Red.Medium);
});
page.Content()
.PaddingVertical(20)
.Column(column =>
{
column.Spacing(25);
foreach (var i in Enumerable.Range(10, 20))
column.Item().Width(i * 10).Height(50).Background(Colors.Grey.Lighten2);
});
});
});
}
}
}
@@ -19,10 +19,12 @@ 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);
}
@@ -59,4 +61,4 @@ namespace QuestPDF.Examples
});
}
}
}
}
@@ -300,17 +300,18 @@ namespace QuestPDF.Examples
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
columns.RelativeColumn();
});
table.Cell().RowSpan(4).Element(Block).Text("1");
var image = Placeholders.Image(400, 300);
table.Cell().RowSpan(2).Element(Block).Text("2");
table.Cell().RowSpan(1).Element(Block).Text("3");
table.Cell().RowSpan(1).Element(Block).Text("4");
table.Cell().RowSpan(2).Element(Block).Text("5");
table.Cell().RowSpan(1).Element(Block).Text("6");
table.Cell().RowSpan(1).Element(Block).Text("7");
table.Cell().Image(image);
table.Cell().Image(image);
table.Cell().Image(image);
table.Cell().Image(image);
table.Cell().Image(image);
table.Cell().Image(image);
});
});
}
@@ -7,6 +7,7 @@ using QuestPDF.Examples.Engine;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using SkiaSharp;
namespace QuestPDF.Examples
{
@@ -911,5 +912,132 @@ namespace QuestPDF.Examples
});
});
}
[Test]
public void DetectSpanPositionExample()
{
RenderingTest
.Create()
.PageSize(new PageSize(650, 800))
.ProduceImages()
.ShowResults()
.Render(container =>
{
var fontSize = 20;
var paint = new SKPaint
{
Color = SKColors.Red,
TextSize = fontSize
};
var fontMetrics = paint.FontMetrics;
var start = 0f;
var end = 0f;
// corner case: what if text is paged? clamp start and end?
container
.Padding(25)
.DefaultTextStyle(x => x.FontSize(fontSize).FontFamily("Calibri"))
.Layers(layers =>
{
layers.PrimaryLayer().Text(text =>
{
text.Span(Placeholders.Paragraph());
text.Span(" - ");
// record start
text.Element().Width(0).Height(0)
.Canvas((canvas, size) => start = canvas.TotalMatrix.TransY / canvas.TotalMatrix.ScaleY);
text.Span(Placeholders.LoremIpsum()).BackgroundColor(Colors.Red.Lighten4);
// record end
text.Element().Width(0).Height(0)
.Canvas((canvas, size) => end = canvas.TotalMatrix.TransY / canvas.TotalMatrix.ScaleY);
text.Span(" - ");
text.Span(Placeholders.Paragraph());
});
layers.Layer().Canvas((canvas, size) =>
{
canvas.Save();
canvas.Translate(-canvas.TotalMatrix.TransX / canvas.TotalMatrix.ScaleX, -canvas.TotalMatrix.TransY / canvas.TotalMatrix.ScaleY);
canvas.DrawRect(10, start + fontMetrics.Ascent, 5, end - start + (fontMetrics.Bottom - fontMetrics.Ascent), paint);
canvas.Restore();
});
});
});
}
[Test]
public void InconsistentLineHeightWhenUsingNewLineTest()
{
RenderingTest
.Create()
.PageSize(PageSizes.A4)
.ProduceImages()
.ShowResults()
.Render(container =>
{
container
.Padding(20)
.Background(Colors.Grey.Lighten4)
.Text(text =>
{
text.DefaultTextStyle(x => x.FontSize(16));
text.Line(Placeholders.Paragraph());
text.Line("");
text.Line(Placeholders.Paragraph());
text.Line(Placeholders.Label()).FontSize(48);
text.Line(Placeholders.Paragraph());
text.Line("");
text.Line(Placeholders.Paragraph());
});
});
}
[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();
});
});
});
}
}
}

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

@@ -31,7 +31,7 @@ namespace QuestPDF.ReportSample
public static string FormatAsRomanNumeral(this int number)
{
if (number < 0 || number > 3999)
throw new ArgumentOutOfRangeException("Number should be in range from 1 to 3999");
throw new ArgumentOutOfRangeException(nameof(number), "Number should be in range from 1 to 3999");
return RomanNumeralCache.GetOrAdd(number, x =>
{

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Before

Width:  |  Height:  |  Size: 993 B

After

Width:  |  Height:  |  Size: 993 B

@@ -38,20 +38,5 @@ namespace QuestPDF.ReportSample
Report.GenerateXps(path);
Process.Start("explorer.exe", path);
}
[Test]
public void Profile()
{
ImagePlaceholder.Solid = true;
var container = new DocumentContainer();
Report.Compose(container);
var content = container.Compose();
var pageContext = new PageContext();
DocumentGenerator.RenderPass(pageContext, new FreeCanvas(), content, null);
DocumentGenerator.RenderPass(pageContext, new FreeCanvas(), content, null);
}
}
}

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