using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.IO; using System.Linq; using System.Runtime.InteropServices; using GrapeCity.Documents.Drawing; using GrapeCity.Documents.Text; using GrapeCity.Documents.Pdf; using GrapeCity.Documents.Pdf.Annotations; using GrapeCity.Documents.Pdf.Actions; using GrapeCity.Documents.Html; using Color = System.Drawing.Color; using Font = GrapeCity.Documents.Text.Font; using RectangleF = System.Drawing.RectangleF; using SizeF = System.Drawing.SizeF; namespace DsPdfWeb.Demos.Common { public static class Util { public const int LargeDocumentIterations = 1000; private static int s_gen = 0; private static DateTime s_fixedTime = new DateTime(1989, 6, 21, 1, 23, 45, DateTimeKind.Utc); private static readonly string[] s_words = new[] { "lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit", "mauris", "id", "volutpat", "tellus", "ullamcorper", "sem", "praesent", "et", "ante", "laoreet", "lobortis", "nunc", "congue", "nisi", "donec", "ac", "tempus", "sed", "feugiat", "pulvinar", "pharetra", "turpis", "nonummy", "at", "felis", "eget", "molestie", "euismod", "non", "aliquet", "diam", "proin", "mi", "nibh", "massa", "tincidunt", "ut", "dolore", "magna", "aliquam", "erat", }; public static bool NoRandom { get; set; } = false; public static Random NewRandom() { if (NoRandom) return new Random(0); else return new Random((int)DateTime.Now.Ticks + Interlocked.Increment(ref s_gen)); } public static DateTime TimeNow() { if (NoRandom) return s_fixedTime; else return DateTime.Now; } private static string s_browserBasePath = null; private static readonly object s_browserBasePath_lock = new object(); // Set this to use the browser from a known location: public static void SetBrowserBasePath(string browserBasePath) { lock (s_browserBasePath_lock) s_browserBasePath = browserBasePath; } // DsHtml v6.0+: this method provides a single target location to be used // by the online samples, and also by all samples downloaded by a user, // so that multiple samples can share the same browser installation // rather than each sample downloading and installing its own copy. // On a system with Chrome installed, the BrowserFetcher.GetSystemChromePath() // call ensures that the installed browser is used. public static string GetBrowserPath() { if (s_browserBasePath == null) { var systemPath = BrowserFetcher.GetSystemChromePath(); if (systemPath != null) return systemPath; } var path = s_browserBasePath ?? Path.Combine(Path.GetTempPath(), ".gc-chromium"); var bf = new BrowserFetcher() { DestinationFolder = path }; return bf.GetDownloadedPath(); } // DsHtml v6.0: public static GcHtmlBrowser NewHtmlBrowser() { var path = GetBrowserPath(); try { if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return new GcHtmlBrowser(path, new LaunchOptions { RunWithNoSandbox = true }); else return new GcHtmlBrowser(path); } catch (Exception ex) { if (path == BrowserFetcher.GetSystemChromePath()) throw; else throw new Exception("Exception occurred when launching the browser (see inner exception for details), " + $"the browser installation in {Path.GetDirectoryName(path)} may be corrupt. Please remove it and try again.", ex); } } // https://stackoverflow.com/questions/4286487/is-there-any-lorem-ipsum-generator-in-c public static string LoremIpsum( int numParagraphs = 5, int minSentences = 5, int maxSentences = 10, int minWords = 5, int maxWords = 30) { int commaMax = 10; var rnd = NewRandom(); int numSentences = rnd.Next(maxSentences - minSentences) + minSentences + 1; int numWords = rnd.Next(maxWords - minWords) + minWords + 1; int wdslen = s_words.Length; var result = new StringBuilder(); for (int p = 0; p < numParagraphs; p++) { for (int s = 0; s < numSentences; s++) { for (int w = 0; w < numWords; w++) { var word = s_words[rnd.Next(wdslen)]; if (w == 0) { result.Append(char.ToUpper(word[0])); result.Append(word.Substring(1)); } else { if (rnd.Next(commaMax) == 0) result.Append(','); result.Append(' '); result.Append(word); } } result.Append(". "); } result.Append("\r\n"); } return result.ToString(); } // Gets the list of words used by the LoremIpsum method. public static List LoremWords() { return s_words.ToList(); } // https://stackoverflow.com/questions/273313/randomize-a-listt public static void Shuffle(this IList list) { var rnd = NewRandom(); int n = list.Count; while (n > 1) { n--; int k = rnd.Next(n + 1); T value = list[k]; list[k] = list[n]; list[n] = value; } } /// /// Adds a note to the document - a text fragment on a colored background. /// Used to insert meta info into sample documents. /// /// The text to draw. /// The page to draw on. /// The text bounds. If null, the whole page with 1" margins on all sides is used. /// If non-null but has zero height, used to specify margins. /// The actual rectangle occupied by the note. public static RectangleF AddNote(string text, Page page, RectangleF? bounds = null) { var g = page.Graphics; var tl = g.CreateTextLayout(); var pad = g.Resolution / 8f; tl.DefaultFormat.Font = StandardFonts.Helvetica; var yumin = Path.Combine("Resources", "Fonts", "yumin.ttf"); if (File.Exists(yumin)) tl.DefaultFormat.Font.AddLinkedFont(Font.FromFile(yumin)); tl.DefaultFormat.FontSize = 12; if (!bounds.HasValue) { var margin = g.Resolution; bounds = new RectangleF(margin, margin, page.Size.Width - margin * 2, page.Size.Height - margin * 2); } else if (bounds.Value.Height == 0) bounds = new RectangleF(bounds.Value.Location, new SizeF(bounds.Value.Width, page.Size.Height - bounds.Value.Top * 2)); tl.MaxWidth = bounds.Value.Width; if (bounds.Value.Height > 0) tl.MaxHeight = bounds.Value.Height; tl.MarginAll = pad; var texts = Regex.Split(text, "(https?://[\\S]+)", RegexOptions.IgnoreCase); var runs = new List(); var urls = new List(); foreach (var txt in texts) { if (txt.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { urls.Add(txt); runs.Add(tl.Append(txt, new TextFormat(tl.DefaultFormat) { ForeColor = Color.Blue, Underline = true, TextRunAsCluster = true, })); } else tl.Append(txt); } tl.PerformLayout(true); for (int i = 0; i < runs.Count; ++i) { var run = runs[i]; var rects = tl.GetTextRects(run.CodePointIndex, run.CodePointCount); foreach (var r in rects) { var rc = r.ToRectangleF(); rc.Offset(bounds.Value.Location); page.Annotations.Add(new LinkAnnotation(rc, new ActionURI(urls[i]))); } } var rect = tl.ContentRectangle; rect.Offset(bounds.Value.Location); rect.Inflate(pad, pad); g.FillRectangle(rect, Color.FromArgb(213, 221, 240)); g.DrawRectangle(rect, Color.FromArgb(59, 92, 170), 0.5f); g.DrawTextLayout(tl, bounds.Value.Location); return rect; } /// /// Loads an image from a disk file. /// /// The only point of this method is to provide better performance on a Windows system, /// by using GrapeCity.Documents.Drawing.Windows.WicImage which works via the /// Windows Imaging Component framework. If WicImage is not supported, this method /// defaults to platform-independent Image.FromFile() method. /// /// /// The image path. /// The Image object. public static IImage ImageFromFile(string path) { if (GrapeCity.Documents.Imaging.Windows.GcWicBitmap.IsSupported) return new GrapeCity.Documents.Imaging.Windows.GcWicBitmap(path); return Image.FromFile(path); } } }