= Skia = * https://skia.org/ * https://skia.org/user/sample/pdf Skia is an open source 2D graphics library which provides common APIs that work across a variety of hardware and software platforms. It's able to generate PDF files with version 1.4. Header and tail for a PDF file is usually '''%PDF-1.4''' and '''%EOF'''. == SkiaSharp dotnetcore == Library wrapper to use Skia in a dotnet core environment, * https://github.com/mono/SkiaSharp {{{#!highlight bash dotnet add package SkiaSharp --version 1.57.1 dotnet add package Avalonia.Skia.Linux.Natives --version 1.57.1.4 # Install in docker container apt-get install -y libfontconfig1 # begin page SkDocument #end page SkDocument # end page SkDocument # close SkDocument # flush SkFileWStream # dispose SkFileWStream }}} == Example controller to generate PDF == * dotnet new webapi --name test-webapi * cd test-webapi * dotnet add package SkiaSharp --version 1.57.1 * dotnet add package Avalonia.Skia.Linux.Natives --version 1.57.1.4 * Install swagger to test invocation via GET {{{#!highlight csharp using System; using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using SkiaSharp; using System.Net.Mime; namespace test_webapi.Controllers { [ApiController] [Route("[controller]")] public class PdfController : ControllerBase { private readonly ILogger _logger; public PdfController(ILogger logger) { _logger = logger; } [HttpGet] [Route("[controller]/[action]/{title}")] public async Task CreatePdf(string title) { /* Adapted from https://github.com/mono/SkiaSharp/blob/master/samples/Gallery/Shared/Samples/CreatePdfSample.cs */ var metadata = new SKDocumentPdfMetadata { Author = "Cool Developer", Creation = DateTime.Now, Creator = "Cool Developer Library", Keywords = "SkiaSharp, Sample, PDF, Developer, Library", Modified = DateTime.Now, Producer = "SkiaSharp", Subject = "SkiaSharp Sample PDF", Title = title, }; var millisSinceDawnTime = DateTime.Now.Ticks / 10000; var filePath = $"{Path.GetTempPath()}{millisSinceDawnTime}_test.pdf"; using (var stream = new SKFileWStream(filePath)) using (var document = SKDocument.CreatePdf(stream, metadata)) using (var paint = new SKPaint()) { paint.TextSize = 64.0f; paint.IsAntialias = true; paint.Color = (SKColor)0xFF9CAFB7; paint.IsStroke = true; paint.StrokeWidth = 3; paint.TextAlign = SKTextAlign.Center; // var width = 840; // var height = 1188; // Portrait a4 in pts units. 1 pt = 127/360mm // https://en.wikipedia.org/wiki/Paper_size // https://skia-doc.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkDocument.html var width = 595; var height = 842; // draw page 1 using (var pdfCanvas = document.BeginPage(width, height)) { // draw button var nextPagePaint = new SKPaint { IsAntialias = true, TextSize = 16, Color = SKColors.OrangeRed }; var nextText = "Next Page >>"; var btn = new SKRect(width - nextPagePaint.MeasureText(nextText) - 24, 0, width, nextPagePaint.TextSize + 24); pdfCanvas.DrawText(nextText, btn.Left + 12, btn.Bottom - 12, nextPagePaint); // make button link pdfCanvas.DrawLinkDestinationAnnotation(btn, "next-page"); // draw contents pdfCanvas.DrawText("...PDF 1/2...", width / 2, height / 4, paint); document.EndPage(); } // draw page 2 using (var pdfCanvas = document.BeginPage(width, height)) { // draw link destintion pdfCanvas.DrawNamedDestinationAnnotation(SKPoint.Empty, "next-page"); // draw contents pdfCanvas.DrawText("...PDF 2/2...", width / 2, height / 4, paint); document.EndPage(); } // end the doc document.Close(); } //var mimeType = "application/pdf"; var mimeType = MediaTypeNames.Application.Pdf; Task fileBytes = System.IO.File.ReadAllBytesAsync(filePath); await fileBytes; return File(fileBytes.Result, mimeType, $"{millisSinceDawnTime}_test.pdf"); } } } }}}