TextRendering.cs
C# VB
//// This code is part of Document Solutions for Imaging demos.// Copyright (c) MESCIUS inc. All rights reserved.//using System.IO;using System.Drawing;using GrapeCity.Documents.Imaging;using GrapeCity.Documents.Text;using GCTEXT = GrapeCity.Documents.Text;
namespace DsImagingWeb.Demos{ // Demonstrates the basics of rendering text in DsImaging. // The two main approaches are: // - using the MeasureString/DrawString pair, or // - using the TextLayout directly. // While the first approach may be easier in simple cases, // the second approach (using TextLayout) is much more powerful // and generally speaking yields better performance. // Please read the comments in code below for more details. public class TextRendering { public GcBitmap GenerateImage(Size pixelSize, float dpi, bool opaque, string[] sampleParams = null) { var bmp = new GcBitmap(pixelSize.Width, pixelSize.Height, true, dpi, dpi); var Inch = dpi; const float fontSize = 14; using (var g = bmp.CreateGraphics(Color.White)) { // TextFormat class is used throughout all DsImaging text rendering to specify // font and other character formatting: var tf = new TextFormat() { Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "NotoSerif-Regular.ttf")), FontSize = fontSize };
// 1. // The easiest way to render a short string on a page at an arbitrary location, // when you are 100% sure that the string will fit in the available space, // is to use the GcGraphics.DrawString() overload accepting just the point // at which to draw the string: g.DrawString( "1. Test string. Please read the extensive comments in this sample's code.\r\n" + "(Note that line breaks are allowed even in the simplest DrawString overload.)", tf, new PointF(Inch, Inch));
// 2. // Another overload taking a rectangle instead, plus alignment and wrapping // options, is also available and provides a bit more flexibility: g.DrawString( "2. A longer test string which will probably need more than the allocated " + "4 inches so quite possibly will wrap to show that DrawString can do that.", tf, new RectangleF(Inch, Inch * 2, Inch * 4, Inch), // the layout rectangle // The rest 3 args are optional, passing defaults here for illustration: TextAlignment.Leading, // leading (left for LTR languages) text align ParagraphAlignment.Near, // near (top for top-to-bottom flow) para align true); // word wrap
// 3. // Complementary to DrawString, a MeasureString() method is available // (with several different overloads), and can be used in pair with // DrawString when more control over text layout is needed: const string tstr3 = "3. Test string to demo MeasureString() used with DrawString().";
SizeF layoutSize = new SizeF(Inch * 3, Inch * 0.8f); // available size SizeF s = g.MeasureString(tstr3, tf, layoutSize, out int fitCharCount); // Show the passed in size in red, the measured size in blue, // and draw the string within the returned size as bounds: PointF pt = new PointF(Inch, Inch * 3); g.DrawRectangle(new RectangleF(pt, layoutSize), Color.Red); g.DrawRectangle(new RectangleF(pt, s), Color.Blue); g.DrawString(tstr3, tf, new RectangleF(pt, s));
// 4. // A much more powerful and with better performance, way to render text // is to use TextLayout. (TextLayout is used anyway by DrawString/MeasureString, // so when you use TextLayout directly, you basically cut the work in half.) // A TextLayout instance represents one or more paragraphs of text, with // the same paragraph formatting (character formats may be different, // see {MultiFormattedText}). var tl = g.CreateTextLayout(); // To add text, use Append() or AppendLine() methods: tl.Append("4. First test string added to TextLayout. ", tf); tl.Append("Second test string added to TextLayout, continuing the same paragraph. ", tf); tl.AppendLine(); // Add a line break, effectively starting a new paragraph tl.Append("Third test string added to TextLayout, a new paragraph. ", tf); tl.Append("Fourth test string, with a different char formatting. ", new TextFormat(tf) { Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "NotoSerif-BoldItalic.ttf")), FontSize = fontSize, FontBold = true, FontItalic = true, ForeColor = Color.DarkSeaGreen, }); // Text can be added to TextLayout without explicit TextFormat: tl.Append("Fifth test string, using the TextLayout's default format."); // ...but in that case at least the Font must be specified on the // TextLayout's DefaultFormat, otherwise PerformLayout (below) will fail: tl.DefaultFormat.Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "NotoSerif-Italic.ttf")); tl.DefaultFormat.FontSize = fontSize;
// Specify the layout, such as max available size etc. // Here we only provide the max width, but many more parameters can be set: tl.MaxWidth = g.Width - Inch * 2; // Paragraph formatting can also be set, here we set first line offset, // spacing between paragraphs and line spacing: tl.FirstLineIndent = Inch * 0.5f; tl.ParagraphSpacing = Inch * 0.05f; tl.LineSpacingScaleFactor = 0.8f;
// When all text has been added, and layout options specified, // the TextLayout needs to calculate the glyphs needed to render // the text, and perform the layout. This can be done with a // single call: tl.PerformLayout(true);
// Now we can draw it on the page: pt = new PointF(Inch, Inch * 4); g.DrawTextLayout(tl, pt); // TextLayout provides info about the text including the measured bounds // and much more. Here we draw the bounding box in orange red: g.DrawRectangle(new RectangleF(pt, tl.ContentRectangle.Size), Color.OrangeRed);
// 5. // TextLayout can be re-used to draw different paragraph(s), this can be useful // when you need to render a different text with the same paragraph formatting. // The Clear() call removes the text but preserves paragraph formatting: tl.Clear(); tl.Append("5. This is text rendered re-using the same TextLayout. "); tl.Append("More text added to TextLayout being re-used, continuing the same paragraph. ", tf); tl.Append("And finally, some more text added.", tf); // The necessary call to calculate the glyphs and perform layout: tl.PerformLayout(true); // Render the text: g.DrawTextLayout(tl, new PointF(Inch, Inch * 5)); // Draw border around the whole image: g.DrawRectangle(new RectangleF(0, 0, bmp.Width, bmp.Height), Color.DarkSlateBlue, 4); } // Done: return bmp; } }}