HelloWorldHtml.cs
//
// This code is part of Document Solutions for PDF demos.
// Copyright (c) MESCIUS inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Html;

namespace DsPdfWeb.Demos
{
    // This sample shows how to render a hard-coded HTML string.
    //
    // Adding DsHtml to your projects:
    // - Public classes and extension methods that enable rendering HTML
    //   are provided by the GrapeCity.Documents.Html (DsHtml) package.
    // - DsHtml supports Windows, macOS and Linux platforms.
    //
    // Dealing with errors when using DsHtml:
    // - If DsHtml is not doing what you expect (e.g. rendering HTML to PDF
    //   produces an invalid PDF), check the content of the string property
    //   GcHtmlBrowser.ErrorLog after the call to SaveAsPdf returns,
    //   it may explain why the error occurred.
    //
    // DsHtml uses a local copy of a Chromium-based browser.
    // You can either rely on Google Chrome or Microsoft Edge browsers
    // installed in the operating system, or download an instance of
    // Chromium browser to the application's local folder or some shared folder.
    // If you know the custom path to an installed Chromium-based browser,
    // use it instead of the above-mentioned options.
    // The BrowserFetcher class can be used to install or fetch an already
    // installed browser, you can then use the BrowserFetcher.GetDownloadedPath()
    // to get the path to the browser. See the BrowserFetcher class for methods
    // retrieving the path to Chrome or Edge executables and for other
    // options and methods that help to download Chromium browser
    // to a local folder if necessary.
    //
    // See the Util.NewHtmlBrowser() utility method used by this sample for a
    // implementation example.
    //
    // The above notes apply to any project that uses DsHtml.
    public class HelloWorldHtml
    {
        public int CreatePDF(Stream stream)
        {
            // HTML code that represents the content to render:
            var html = "<!DOCTYPE html>" +
                "<html>" +
                "<head>" +
                "<style>" +
                "span.bold {" +
                    "font-weight: bold;" +
                "}" +
                "p.round {" +
                    "font: 36px arial, sans-serif;" +
                    "color: DarkSlateBlue;" +
                    "border: 4px solid SlateBlue;" +
                    "border-radius: 16px;" +
                    "padding: 3px 5px 3px 5px;" +
                    "text-shadow: 3px 2px LightSkyBlue;" +
                "}" +
                "</style>" +
                "</head>" +
                "<body>" +
                "<p class='round'>Hello, World, from <span class='bold'>DsHtml</span>!</p>" +
                "</body>" +
                "</html>";

            // Create a new PDF document, add a page, get graphics to draw on:
            var doc = new GcPdfDocument();
            var page = doc.NewPage();
            var g = page.Graphics;

            try
            {
                // Create an instance of GcHtmlBrowser that is used to render HTML:
                using var browser = Common.Util.NewHtmlBrowser();

                // Render HTML.
                // The return value from DrawHtml() indicates whether anything has been rendered.
                // The output parameter 'size' returns the actual size of the rendered content.
                var ok = g.DrawHtml(browser, html, 72, 72,
                    new HtmlToPdfFormat(false) { MaxPageWidth = 6.5f, MaxPageHeight = 9f },
                    out SizeF size);

                if (ok)
                {
                    // If anything has been rendered, draw an extra border around the rendered content:
                    var rc = new RectangleF(72 - 4, 72 - 4, size.Width + 8, size.Height + 8);
                    g.DrawRoundRect(rc, 8, Color.PaleVioletRed);
                }
                else if (!string.IsNullOrEmpty(browser.ErrorLog))
                {
                    // Optional diagnostics that may be useful when diagnosing browser errors.
                    // Note that the error log may contain harmless information messages
                    // even if there were no errors, so testing whether the error log is empty
                    // should not be used as the error indicator.
                    Common.Util.AddNote(browser.ErrorLog, page, 
                        new RectangleF(72, 72 + size.Height + 36, page.Size.Width - 144, page.Size.Height - size.Height - 108));
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"Error:\n{ex.Message}");
            }

            // Done:
            doc.Save(stream);
            return doc.Pages.Count;
        }
    }
}