= 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<PdfController> _logger;

        public PdfController(ILogger<PdfController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        [Route("[controller]/[action]/{title}")]
        public async Task<FileResult> 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<byte[]> fileBytes = System.IO.File.ReadAllBytesAsync(filePath);
            await fileBytes;
            return File(fileBytes.Result, mimeType, $"{millisSinceDawnTime}_test.pdf");
        }
    }
}
}}}