Beispiel #1
0
        private void SaveToStream(SKWStream stream)
        {
            var metadata = new SKDocumentPdfMetadata
            {
                Author   = Author,
                Creation = DateTime.Now,
                Creator  = Creator,
                Keywords = Keywords,
                Modified = DateTime.Now,
                Producer = Producer,
                Subject  = Subject,
                Title    = Title,
            };

            int dpi = 72;

            using (var document = SKDocument.CreatePdf(stream, metadata, dpi))
            {
                foreach (var page in Pages)
                {
                    var pdfCanvas = document.BeginPage(page.Width, page.Height, page.Dimensions.GetContentRect().ToSKRect());

                    var pageRenderer = new PageRenderer(page);
                    pageRenderer.Render(pdfCanvas);

                    document.EndPage();
                }

                // end the doc
                document.Close();
            }
        }
        /// <summary>
        /// Encode output image as PDF
        /// </summary>
        /// <param name="surface"></param>
        /// <param name="width">Requested output width (pixels)</param>
        /// <param name="height">Requested output height (pixels)</param>
        /// <param name="q">Image quality (percentage)</param>
        /// <param name="pdfMetadata">Optional metadata to include in the PDF</param>
        /// <returns></returns>
        public static Stream EncodePdf(SKSurface surface, int width, int height, int q, Conf.PdfMetadata pdfMetadata)
        {
            // have to encode to JPEG then paint the encoded bytes, otherwise you get full JP2 quality
            var output = new MemoryStream();

            var metadata = new SKDocumentPdfMetadata()
            {
                Creation = DateTime.Now,
            };

            if (null != pdfMetadata)
            {
                metadata.Author = pdfMetadata.Author;
            }

            using (var skstream = new SKManagedWStream(output))
                using (var writer = SKDocument.CreatePdf(skstream, metadata))
                    using (var snapshot = surface.Snapshot())
                        using (var data = snapshot.Encode(SKEncodedImageFormat.Jpeg, q))
                            using (var image = SKImage.FromEncodedData(data))
                                using (var paint = new SKPaint())
                                {
                                    using (var canvas = writer.BeginPage(width, height))
                                    {
                                        paint.FilterQuality = SKFilterQuality.High;
                                        canvas.DrawImage(image, new SKRect(0, 0, width, height), paint);
                                        writer.EndPage();
                                    }
                                }
            output.Seek(0, SeekOrigin.Begin);
            return(output);
        }
Beispiel #3
0
        /// <summary>
        /// Creates a PDF document displaying the given identity as QR code and text and
        /// providing some guidance for the user.
        /// </summary>
        /// <param name="fileName">The full file name (including the path) for the document.</param>
        /// <param name="identity">The identity for which to create the document.</param>
        /// <param name="blockTypes">Spciefies a list of block types to include.</param>
        public static void CreateIdentityDocument(string fileName, SQRLIdentity identity, List <ushort> blockTypes)
        {
            if (string.IsNullOrEmpty(fileName) ||
                identity == null ||
                blockTypes == null ||
                blockTypes.Count < 1)
            {
                throw new ArgumentException(string.Format("{0}, {1} and {2} must be specified and valid!",
                                                          nameof(fileName), nameof(identity), nameof(blockTypes)));
            }

            _pageNr = 0;
            string title = "\"" + identity.IdentityName + "\" " + _loc.GetLocalizationValue("FileDialogFilterName");
            string identityEncryptionMessage = blockTypes.Contains(1) ?
                                               _loc.GetLocalizationValue("IdentityDocEncMsgPassword") :
                                               _loc.GetLocalizationValue("IdentityDocEncMsgRC");
            string textualIdentityMessage = _loc.GetLocalizationValue("IdentityDocumentTextualIdentityMessage");
            string guidanceMessage        = _loc.GetLocalizationValue("IdentityDocumentGuidanceMessage");
            var    identityBytes          = identity.ToByteArray(includeHeader: true, blockTypes);
            string textualIdentity        = SQRL.GenerateTextualIdentityBase56(identityBytes);

            var metadata = new SKDocumentPdfMetadata
            {
                Author          = _assemblyName,
                Creation        = DateTime.Now,
                Creator         = _assemblyName,
                Keywords        = "SQRL,Identity",
                Modified        = DateTime.Now,
                Producer        = "SkiaSharp",
                Subject         = "SQRL Identity Document",
                Title           = "SQRL Identity Document",
                EncodingQuality = 300,
                RasterDpi       = 300
            };

            using (SKBitmap qrCode = CreateQRCode(identityBytes))
                using (var stream = new SKFileWStream(fileName))
                    using (_document = SKDocument.CreatePdf(stream, metadata))
                    {
                        StartNextPage();

                        float qrCodeWidth  = (qrCode.Width <= QRCODE_MAX_SIZE) ? qrCode.Width : QRCODE_MAX_SIZE;
                        float qrCodeHeight = (qrCode.Height <= QRCODE_MAX_SIZE) ? qrCode.Height : QRCODE_MAX_SIZE;

                        DrawTextBlock(title, _fontBold, 23, SKColors.Black, 10f);
                        DrawTextBlock(identityEncryptionMessage, _fontRegular, 12, SKColors.DarkGray, -5f, SKTextAlign.Left, 1.3f);
                        DrawBitmap(qrCode, SKTextAlign.Center, qrCodeWidth, qrCodeHeight, 15f);
                        DrawTextBlock(textualIdentityMessage, _fontRegular, 12, SKColors.DarkGray, 10f, SKTextAlign.Left, 1.3f);
                        DrawTextBlock(textualIdentity, _fontMonoBold, 12, SKColors.Black, 15f, SKTextAlign.Center, 1.3f);;
                        DrawTextBlock(guidanceMessage, _fontRegular, 12, SKColors.DarkGray, 0f, SKTextAlign.Left, 1.3f);

                        EndPage();
                        _document.Close();
                    }
        }
Beispiel #4
0
        /// <summary>
        /// Creates a PDF document displaying the given identity as QR code and text and
        /// providing some guidance for the user.
        /// </summary>
        /// <param name="fileName">The full file name (including the path) for the document.</param>
        /// <param name="identity">The identity for which to create the document.</param>
        /// <param name="blockTypes">Spciefies a list of block types to include.</param>
        public static void CreateIdentityDocument(string fileName, SQRLIdentity identity, List <ushort> blockTypes)
        {
            if (string.IsNullOrEmpty(fileName) || identity == null)
            {
                throw new ArgumentException(string.Format("{0} and {1} must be specified and valid!",
                                                          nameof(fileName), nameof(identity)));
            }

            float  yPos                   = MARGIN_TOP;
            string title                  = "\"" + identity.IdentityName + "\" " + _loc.GetLocalizationValue("FileDialogFilterName");
            string qrCodeMessage          = _loc.GetLocalizationValue("IdentityDocumentQRCodeMessage");
            string textualIdentityMessage = _loc.GetLocalizationValue("IdentityDocumentTextualIdentityMessage");
            string guidanceMessage        = _loc.GetLocalizationValue("IdentityDocumentGuidanceMessage");
            var    identityBytes          = identity.ToByteArray(includeHeader: true, blockTypes);
            string textualIdentity        = SQRL.GenerateTextualIdentityBase56(identityBytes);

            var metadata = new SKDocumentPdfMetadata
            {
                Author          = _assemblyName,
                Creation        = DateTime.Now,
                Creator         = _assemblyName,
                Keywords        = "SQRL,Identity",
                Modified        = DateTime.Now,
                Producer        = "SkiaSharp",
                Subject         = "SQRL Identity Document",
                Title           = "SQRL Identity Document",
                EncodingQuality = 300,
                RasterDpi       = 300
            };

            using (SKBitmap qrCode = CreateQRCode(identityBytes))
                using (var stream = new SKFileWStream(fileName))
                    using (var document = SKDocument.CreatePdf(stream, metadata))
                        using (var canvas = document.BeginPage(PAGE_WIDTH, PAGE_HEIGHT))
                        {
                            float qrCodeWidth  = (qrCode.Width <= QRCODE_MAX_SIZE) ? qrCode.Width : QRCODE_MAX_SIZE;
                            float qrCodeHeight = (qrCode.Height <= QRCODE_MAX_SIZE) ? qrCode.Height : QRCODE_MAX_SIZE;
                            float qrCodeXPos   = PAGE_WIDTH / 2 - qrCodeWidth / 2;

                            yPos += 10 + DrawTextBlock(canvas, title, yPos, _fontBold, 23, SKColors.Black);
                            yPos += -15 + DrawTextBlock(canvas, qrCodeMessage, yPos, _fontRegular, 12, SKColors.DarkGray, SKTextAlign.Left, 1.3f);
                            canvas.DrawBitmap(qrCode, new SKRect(qrCodeXPos, yPos, qrCodeXPos + qrCodeWidth, yPos + qrCodeHeight));
                            yPos += qrCodeHeight + 15;
                            yPos += 10 + DrawTextBlock(canvas, textualIdentityMessage, yPos, _fontRegular, 12, SKColors.DarkGray, SKTextAlign.Left, 1.3f);
                            yPos += 15 + DrawTextBlock(canvas, textualIdentity, yPos, _fontMonoBold, 12, SKColors.Black, SKTextAlign.Center, 1.3f);
                            yPos += 00 + DrawTextBlock(canvas, guidanceMessage, yPos, _fontRegular, 12, SKColors.DarkGray, SKTextAlign.Left, 1.3f);
                            DrawFooter(canvas);

                            document.EndPage();
                            document.Close();
                        }
        }
Beispiel #5
0
        /// <summary>
        /// Creates a PDF document prominently displaying the given <paramref name="rescueCode"/>
        /// and <paramref name="identityName"/>, providing additional guidance for the user.
        /// </summary>
        /// <param name="fileName">The full file name (including the path) for the document to be created.</param>
        /// <param name="rescueCode">The rescue code to be printed to the document.</param>
        /// <param name="identityName">The name of the identity. This is optional, just
        /// pass <c>null</c> if no identity name should be printed to the pdf file.</param>
        public static void CreateRescueCodeDocument(string fileName, string rescueCode, string identityName = null)
        {
            if (string.IsNullOrEmpty(fileName) || string.IsNullOrEmpty(rescueCode))
            {
                throw new ArgumentException(string.Format("{0} and {1} must be specified!",
                                                          nameof(fileName), nameof(rescueCode)));
            }

            identityName = identityName != null ? identityName : "";

            _pageNr = 0;
            string title           = _loc.GetLocalizationValue("RescueCodeDocumentTitle");
            string warning         = _loc.GetLocalizationValue("RescueCodeDocumentDiscardWarning");
            string text            = _loc.GetLocalizationValue("RescueCodeDocumentText");
            string identityLabel   = _loc.GetLocalizationValue("IdentityNameLabel");
            string rescueCodeLabel = _loc.GetLocalizationValue("RescueCodeLabel");

            var metadata = new SKDocumentPdfMetadata
            {
                Author   = _assemblyName,
                Creation = DateTime.Now,
                Creator  = _assemblyName,
                Keywords = "SQRL,Rescue code",
                Modified = DateTime.Now,
                Producer = "SkiaSharp",
                Subject  = "SQRL Rescue Code Document",
                Title    = "SQRL Rescue Code Document"
            };

            using (var stream = new SKFileWStream(fileName))
                using (_document = SKDocument.CreatePdf(stream, metadata))
                {
                    StartNextPage();
                    DrawHeader();

                    _yPos = MARGIN_TOP + HEADER_ICON_SIZE + 80;
                    DrawTextBlock(title, _fontBold, 25, SKColors.Black, 15f);
                    DrawTextBlock(warning, _fontBold, 20, SKColors.Red, 20f);
                    DrawTextBlock(text, _fontRegular, 12, SKColors.DarkGray, 30f, SKTextAlign.Left, 1.3f);

                    if (!string.IsNullOrEmpty(identityName))
                    {
                        DrawTextBlock(identityLabel, _fontRegular, 12, SKColors.DarkGray, 15f);
                        DrawTextBlock(identityName, _fontBold, 16, SKColors.Black);
                    }
                    DrawTextBlock(rescueCodeLabel, _fontRegular, 12, SKColors.DarkGray, 25f);
                    DrawTextBlock(rescueCode, _fontBold, 24, SKColors.Black);

                    EndPage();
                    _document.Close();
                }
        }
Beispiel #6
0
        /// <summary>
        /// Creates a PDF document prominently displaying the given rescue code and
        /// providing some guidance for the user.
        /// </summary>
        /// <param name="fileName">The full file name (including the path) for the document.</param>
        /// <param name="rescueCode">The rescue code to be printed to the document.</param>
        /// <param name="identityName">The name of the identity. This is optional, just
        /// pass <c>null</c> if no identity name should be printed to the pdf file.</param>
        public static void CreateRescueCodeDocument(string fileName, string rescueCode, string identityName = null)
        {
            if (string.IsNullOrEmpty(fileName) || string.IsNullOrEmpty(rescueCode))
            {
                throw new ArgumentException(string.Format("{0} and {1} must be specified!",
                                                          nameof(fileName), nameof(rescueCode)));
            }

            identityName = identityName != null ? identityName : "";

            float  yPos            = MARGIN_TOP + HEADER_ICON_SIZE + 80;
            string title           = _loc.GetLocalizationValue("RescueCodeDocumentTitle");
            string warning         = _loc.GetLocalizationValue("RescueCodeDocumentDiscardWarning");
            string text            = _loc.GetLocalizationValue("RescueCodeDocumentText");
            string identityLabel   = _loc.GetLocalizationValue("IdentityNameLabel");
            string rescueCodeLabel = _loc.GetLocalizationValue("RescueCodeLabel");

            var metadata = new SKDocumentPdfMetadata
            {
                Author   = _assemblyName,
                Creation = DateTime.Now,
                Creator  = _assemblyName,
                Keywords = "SQRL,Rescue code",
                Modified = DateTime.Now,
                Producer = "SkiaSharp",
                Subject  = "SQRL Rescue Code Document",
                Title    = "SQRL Rescue Code Document"
            };

            using (var stream = new SKFileWStream(fileName))
                using (var document = SKDocument.CreatePdf(stream, metadata))
                    using (var canvas = document.BeginPage(PAGE_WIDTH, PAGE_HEIGHT))
                    {
                        DrawHeader(canvas);
                        yPos += 10 + DrawTextBlock(canvas, title, yPos, _fontBold, 25, SKColors.Black);
                        yPos += 20 + DrawTextBlock(canvas, warning, yPos, _fontBold, 20, SKColors.Red);
                        yPos += 30 + DrawTextBlock(canvas, text, yPos, _fontRegular, 12, SKColors.DarkGray, SKTextAlign.Left, 1.3f);
                        if (!string.IsNullOrEmpty(identityName))
                        {
                            yPos += 05 + DrawTextBlock(canvas, identityLabel, yPos, _fontRegular, 12, SKColors.DarkGray);
                            yPos += 15 + DrawTextBlock(canvas, identityName, yPos, _fontBold, 16, SKColors.Black);
                        }
                        yPos += 10 + DrawTextBlock(canvas, rescueCodeLabel, yPos, _fontRegular, 12, SKColors.DarkGray);
                        yPos += 15 + DrawTextBlock(canvas, rescueCode, yPos, _fontBold, 24, SKColors.Black);
                        DrawFooter(canvas);

                        document.EndPage();
                        document.Close();
                    }
        }
        protected override void OnTapped()
        {
            base.OnTapped();

            var path = Path.Combine(root, $"{Guid.NewGuid().ToString("N")}.pdf");

            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    = "Sample PDF",
            };

            using (var stream = new SKFileWStream(path))
                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;

                        // 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();
                    }

            // display to the user
            SamplesManager.OnOpenFile(path);
        }
        public override void PrintPattern(float scale, Pattern pattern, List <Vector2> positions, Vector2 padding, string path)
        {
            this.scale = scale;
            //PDF pages are sized in point units. 1 pt == 1/72 inch == 127/360 mm.
            //< table >
            //< thead >< tr >< th class="tdw1">Size</th><th class="tdw2">Width x Height(mm)</th><th class="tdw2">Width x Height(in)</th></tr></thead>
            //<tbody>
            //<tr><td>4A0</td><td>1682 x 2378 mm</td><td>66.2 x 93.6 in</td></tr>
            //<tr><td>2A0</td><td>1189 x 1682 mm</td><td>46.8 x 66.2 in</td></tr>
            //<tr><td>A0</td><td>841 x 1189 mm</td><td>33.1 x 46.8 in</td></tr>
            //<tr><td>A1</td><td>594 x 841 mm</td><td>23.4 x 33.1 in</td></tr>
            //<tr><td>A2</td><td>420 x 594 mm</td><td>16.5 x 23.4 in</td></tr>
            //<tr><td>A3</td><td>297 x 420 mm</td><td>11.7 x 16.5 in</td></tr>
            //<tr><td>A4</td><td> 210 x 297 mm</td><td>8.3 x 11.7 in</td></tr>
            //<tr><td>A5</td><td>148 x 210 mm</td><td>5.8 x 8.3 in</td></tr>
            //<tr><td>A6</td><td>105 x 148 mm</td><td>4.1 x 5.8 in</td></tr>
            //<tr><td>A7</td><td>74 x 105 mm</td><td>2.9 x 4.1 in</td></tr>
            //<tr><td>A8</td><td>52 x 74 mm</td><td>2.0 x 2.9 in</td></tr>
            //<tr><td>A9</td><td>37 x 52 mm</td><td>1.5 x 2.0 in</td></tr>
            //<tr><td>A10</td><td>26 x 37 mm</td><td>1.0 x 1.5 in</td></tr>
            //</tbody>
            //</table>

            SKDocumentPdfMetadata metadata = new SKDocumentPdfMetadata
            {
                Author   = "Hoodie Maker",
                Creation = DateTime.Now,
                Creator  = "Hoodie Maker",
                Keywords = "PDF, Hoodie, Pattern",
                Modified = DateTime.Now,
                Producer = "Hoodie Maker",
                Subject  = "Hoodie Maker Pattern",
                Title    = "Hoodie Pattern",
            };

            using (SKFileWStream stream = new SKFileWStream(path))
                using (SKDocument document = SKDocument.CreatePdf(stream, metadata))
                {
                    for (int i = 0; i < pattern.Parts.Count; i++)
                    {
                        Vector2     position = positions[i];
                        PatternPart part     = pattern.Parts[i];
                        //A0 841mm x 1189 mm
                        //float width = pageSize.X * Utils.pntPerMM;
                        //float height = pageSize.Y * Utils.pntPerMM;
                        PartExtents extents = PartExtents.CalcPartExtents(part);
                        using (SKCanvas pdfCanvas = document.BeginPage(Scale(extents.Width + padding.X), Scale(extents.Height + padding.Y)))
                        {
                            canvas = pdfCanvas;
                            DrawPart(part, position,
                                     colorFillPrint,
                                     MapEntityColorsForPrint(EntityType.Normal),
                                     MapEntityColorsForPrint(EntityType.Text));
                            document.EndPage();
                        }
                    }
                    document.Close();
                }
            System.Diagnostics.Debug.WriteLine(path);
            //Task.Run(async () => await OpenDoc(path));
        }
Beispiel #9
0
        private void GenerateDocument()
        {
            if (!isSupported || (isSupported && File.Exists(path)))
            {
                return;
            }

            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    = "Sample PDF",
            };

            using var document = SKDocument.CreatePdf(path, metadata);

            if (document == null)
            {
                isSupported = false;
                return;
            }

            using var paint = new SKPaint
                  {
                      TextSize    = 64.0f,
                      IsAntialias = true,
                      Color       = 0xFF9CAFB7,
                      IsStroke    = true,
                      StrokeWidth = 3,
                      TextAlign   = SKTextAlign.Center
                  };

            var pageWidth  = 840;
            var pageHeight = 1188;

            // draw page 1
            using (var pdfCanvas = document.BeginPage(pageWidth, pageHeight))
            {
                // draw button
                using var nextPagePaint = new SKPaint
                      {
                          IsAntialias = true,
                          TextSize    = 16,
                          Color       = SKColors.OrangeRed
                      };
                var nextText = "Next Page >>";
                var btn      = new SKRect(pageWidth - nextPagePaint.MeasureText(nextText) - 24, 0, pageWidth, 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...", pageWidth / 2, pageHeight / 4, paint);
                document.EndPage();
            }

            // draw page 2
            using (var pdfCanvas = document.BeginPage(pageWidth, pageHeight))
            {
                // draw link destintion
                pdfCanvas.DrawNamedDestinationAnnotation(SKPoint.Empty, "next-page");

                // draw contents
                pdfCanvas.DrawText("...PDF 2/2...", pageWidth / 2, pageHeight / 4, paint);
                document.EndPage();
            }

            // end the doc
            document.Close();
        }
Beispiel #10
0
        private void GenerateDocument(string path)
        {
            var metadata = new SKDocumentPdfMetadata
            {
                Author   = "GiveCamp 2020",
                Creation = DateTime.Now,
                Creator  = "That Conference Library",
                Keywords = "GiveCamp, That Conference, Test",
                Modified = DateTime.Now,
                Producer = "Test",
                Subject  = "Test",
                Title    = "Test PDF",
            };

            using var document = SKDocument.CreatePdf(path, metadata);
            using var paint    = new SKPaint
                  {
                      TextSize    = 64.0f,
                      IsAntialias = true,
                      Color       = 0xFF9CAFB7,
                      IsStroke    = true,
                      StrokeWidth = 3,
                      TextAlign   = SKTextAlign.Center
                  };
            var pageWidth  = 840;
            var pageHeight = 1188;

            // draw page 1
            using (var pdfCanvas = document.BeginPage(pageWidth, pageHeight))
            {
                // draw button
                using var nextPagePaint = new SKPaint
                      {
                          IsAntialias = true,
                          TextSize    = 16,
                          Color       = SKColors.OrangeRed
                      };
                var nextText = "Next Page >>";
                var btn      = new SKRect(pageWidth - nextPagePaint.MeasureText(nextText) - 24, 0, pageWidth, 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...", pageWidth / 2, pageHeight / 4, paint);

                document.EndPage();
            }
            // draw page 2
            using (var pdfCanvas = document.BeginPage(pageWidth, pageHeight))
            {
                // draw link destintion
                pdfCanvas.DrawNamedDestinationAnnotation(SKPoint.Empty, "next-page");

                // draw contents
                pdfCanvas.DrawText("...PDF 2/2...", pageWidth / 2, pageHeight / 4, paint);
                document.EndPage();
            }

            // end the doc
            document.Close();
        }