The basics of rendering text in DsPdf (DrawString and DrawTextLayout)

PDF TIFF SVG JPG C# VB
TextRendering.cs
  1. //
  2. // This code is part of Document Solutions for PDF demos.
  3. // Copyright (c) MESCIUS inc. All rights reserved.
  4. //
  5. using System;
  6. using System.IO;
  7. using System.Drawing;
  8. using GrapeCity.Documents.Pdf;
  9. using GrapeCity.Documents.Text;
  10. using GrapeCity.Documents.Drawing;
  11.  
  12. namespace DsPdfWeb.Demos.Basics
  13. {
  14. // This sample demonstrates the basics of rendering text in DsPdf.
  15. // The two main approaches are:
  16. // - using the MeasureString/DrawString pair, or
  17. // - using the TextLayout directly.
  18. // While the first approach may be easier in simple cases,
  19. // the second approach (using TextLayout) is much more powerful
  20. // and generally speaking yields better performance.
  21. // Please read the comments in code below for more details.
  22. // See also CharacterFormatting, PaginatedText, ParagraphAlign,
  23. // ParagraphFormatting, TextAlign.
  24. public class TextRendering
  25. {
  26. public int CreatePDF(Stream stream)
  27. {
  28. var doc = new GcPdfDocument();
  29. var page = doc.NewPage();
  30. var g = page.Graphics;
  31. // By default, DsPdf uses 72dpi:
  32. const float In = 72;
  33.  
  34. // TextFormat class is used throughout all DsPdf text rendering to specify
  35. // font and other character formatting:
  36. var tf = new TextFormat() { Font = StandardFonts.Times, FontSize = 12 };
  37.  
  38. // 1.
  39. // The easiest way to render a short string on a page at an arbitrary location,
  40. // when you are 100% sure that the string will fit in the available space,
  41. // is to use the GcGraphics.DrawString() overload accepting jus the point
  42. // at which to draw the string:
  43. g.DrawString("1. Test string. Please read the extensive comments in this sample's code." +
  44. "(Note that line breaks are allowed even in the simplest DrawString overload.)",
  45. tf, new PointF(In, In));
  46.  
  47. // 2.
  48. // Another overload taking a rectangle instead, plus alignment and wrapping
  49. // options, is also available and provides a bit more flexibility.
  50. // The parameters are:
  51. // - the text string;
  52. // - the text format;
  53. // - the layout rectangle;
  54. // - (optional) text alignment (the default is leading, left for LTR languages);
  55. // - (optional) paragraph alignment (the default is near, top for top-to-bottom flow);
  56. // - (optional) word wrapping (the default is true):
  57. g.DrawString("2. A longer test string which will probably need more than the allocated" +
  58. "4 inches so quite possibly will wrap to show that DrawString can do that.",
  59. tf,
  60. new RectangleF(In, In * 2, In * 4, In),
  61. TextAlignment.Leading,
  62. ParagraphAlignment.Near,
  63. true);
  64.  
  65. // 3.
  66. // Complementary to DrawString, a MeasureString() method is available
  67. // (with several different overloads), and can be used in pair with
  68. // DrawString when more control over text layout is needed:
  69. string tstr3 = "3. Test string to demo MeasureString() used with DrawString().";
  70. // Available layout size:
  71. SizeF layoutSize = new SizeF(In * 3, In * 0.8f);
  72. SizeF s = g.MeasureString(tstr3, tf, layoutSize, out int fitCharCount);
  73. // Show the passed in size in red, the measured size in blue,
  74. // and draw the string within the returned size as bounds:
  75. PointF pt = new PointF(In, In * 3);
  76. g.DrawRectangle(new RectangleF(pt, layoutSize), Color.Red);
  77. g.DrawRectangle(new RectangleF(pt, s), Color.Blue);
  78. g.DrawString(tstr3, tf, new RectangleF(pt, s));
  79.  
  80. // 4.
  81. // A much more powerful and with better performance, way to render text
  82. // is to use TextLayout. (TextLayout is used anyway by DrawString/MeasureString,
  83. // so when you use TextLayout directly, you basically cut the work in half.)
  84. // A TextLayout instance represents one or more paragraphs of text, with
  85. // the same paragraph formatting (character formats may be different,
  86. // see MultiFormattedText).
  87. var tl = g.CreateTextLayout();
  88. // To add text, use Append() or AppendLine() methods:
  89. tl.Append("4. First test string added to TextLayout. ", tf);
  90. tl.Append("Second test string added to TextLayout, continuing the same paragraph. ", tf);
  91. // Add a line break, effectively starting a new paragraph:
  92. tl.AppendLine();
  93. tl.Append("Third test string added to TextLayout, a new paragraph. ", tf);
  94. tl.Append("Fourth test string, with a different char formatting. ",
  95. new TextFormat(tf) { Font = StandardFonts.TimesBoldItalic, ForeColor = Color.DarkSeaGreen, });
  96. // Text can be added to TextLayout without explicit TextFormat:
  97. tl.Append("Fifth test string, using the TextLayout's default format.");
  98. // ...but in that case at least the Font must be specified on the
  99. // TextLayout's DefaultFormat, otherwise PerformLayout (below) will fail:
  100. tl.DefaultFormat.Font = StandardFonts.TimesItalic;
  101. // Specify the layout, such as max available size etc.
  102. // Here we only provide the max width, but many more parameters can be set:
  103. tl.MaxWidth = page.Size.Width - In * 2;
  104. // Paragraph formatting can also be set, here we set first line offset,
  105. // spacing between paragraphs and line spacing:
  106. tl.FirstLineIndent = In * 0.5f;
  107. tl.ParagraphSpacing = In * 0.05f;
  108. tl.LineSpacingScaleFactor = 0.8f;
  109.  
  110. // When all text has been added, and layout options specified,
  111. // the TextLayout needs to calculate the glyphs needed to render
  112. // the text, and perform the layout. This can be done with a
  113. // single call:
  114. tl.PerformLayout(true);
  115.  
  116. // Now we can draw it on the page:
  117. pt = new PointF(In, In * 4);
  118. g.DrawTextLayout(tl, pt);
  119. // TextLayout provides info about the text including the measured bounds
  120. // and much more. Here we draw the bounding box in orange red:
  121. g.DrawRectangle(new RectangleF(pt, tl.ContentRectangle.Size), Color.OrangeRed);
  122.  
  123. // 5.
  124. // TextLayout can be re-used to draw different paragraph(s), this can be useful
  125. // when you need to render a different text with the same paragraph formatting.
  126. // The Clear() call removes the text but preserves paragraph formatting:
  127. tl.Clear();
  128. tl.Append("5. This is text rendered re-using the same TextLayout. ");
  129. tl.Append("More text added to TextLayout being re-used, continuing the same paragraph. ", tf);
  130. tl.Append("And finally, some more text added.", tf);
  131. // The necessary call to calculate the glyphs and perform layout:
  132. tl.PerformLayout(true);
  133. // Render the text:
  134. g.DrawTextLayout(tl, new PointF(In, In * 5));
  135.  
  136. // Done:
  137. doc.Save(stream);
  138. return doc.Pages.Count;
  139. }
  140. }
  141. }
  142.