TextAroundImages.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 System.Collections.Generic;
  9. using GrapeCity.Documents.Pdf;
  10. using GrapeCity.Documents.Text;
  11. using GrapeCity.Documents.Drawing;
  12. using GCTEXT = GrapeCity.Documents.Text;
  13. using GCDRAW = GrapeCity.Documents.Drawing;
  14.  
  15. namespace DsPdfWeb.Demos.Basics
  16. {
  17. // This sample shows how to flow a large block of text around rectangular areas,
  18. // in this case images. It also demonstrates how to get the actual bounds
  19. // of an image that has been rendered on a page using a specific ImageAlign.
  20. public class TextAroundImages
  21. {
  22. public int CreatePDF(Stream stream)
  23. {
  24. var doc = new GcPdfDocument();
  25. var g = doc.NewPage().Graphics;
  26. //
  27. // We want to draw 3 images in certain arbitrary locations on the first page,
  28. // and then print a text that would take 2-3 pages, and have it flow around
  29. // the images on the first page.
  30. //
  31. // Get the images and their rectangles. Note that we specify a square
  32. // area for all images - but they will be aligned within that area
  33. // preserving their original aspect ratios, so we will later retrieve
  34. // the actual rectangles where the images were drawn:
  35. using (var imgPuffins = GCDRAW.Image.FromFile("Resources/Images/puffins.jpg"))
  36. using (var imgReds = GCDRAW.Image.FromFile("Resources/Images/reds.jpg"))
  37. using (var imgLavender = GCDRAW.Image.FromFile("Resources/Images/lavender.jpg"))
  38. {
  39. var rectPuffins = new RectangleF(100, 70, 180, 180);
  40. var rectReds = new RectangleF(300, 280, 180, 180);
  41. var rectLavender = new RectangleF(190, 510, 180, 180);
  42. // Set up ImageAlign that would fit and center an image within a specified area,
  43. // preserving the image's original aspect ratio:
  44. var ia = new ImageAlign(ImageAlignHorz.Center, ImageAlignVert.Center, true, true, true, false, false);
  45. // Draw each image, providing an array of rectangles as an output parameter for each DrawImage call,
  46. // so that we get the actual rectangle taken by the image (an array is needed to handle tiled images):
  47. g.DrawImage(imgPuffins, rectPuffins, null, ia, out RectangleF[] rectsPuffins);
  48. g.DrawImage(imgReds, rectReds, null, ia, out RectangleF[] rectsReds);
  49. g.DrawImage(imgLavender, rectLavender, null, ia, out RectangleF[] rectsLavender);
  50. // Create and set up a TextLayout object to print the text:
  51. var tl = g.CreateTextLayout();
  52. tl.DefaultFormat.Font = StandardFonts.Times;
  53. tl.DefaultFormat.FontSize = 9;
  54. tl.TextAlignment = TextAlignment.Justified;
  55. tl.ParagraphSpacing = 72 / 8;
  56. tl.MaxWidth = doc.PageSize.Width;
  57. tl.MaxHeight = doc.PageSize.Height;
  58. // 1/2" margins all around
  59. tl.MarginAll = 72 / 2;
  60. // ObjectRect is the type used to specify the areas to flow around to TextLayout.
  61. // We set up a local function to create an ObjecRect based on an image rectangle,
  62. // adding some padding so that the result looks nicer:
  63. Func<RectangleF, ObjectRect> makeObjectRect = rect_ =>
  64. new ObjectRect(rect_.X - 6, rect_.Y - 2, rect_.Width + 12, rect_.Height + 4);
  65. // Specify the array of ObjectRects on the TextLayout:
  66. tl.ObjectRects = new List<ObjectRect>()
  67. {
  68. makeObjectRect(rectsPuffins[0]),
  69. makeObjectRect(rectsReds[0]),
  70. makeObjectRect(rectsLavender[0]),
  71. };
  72. // Add several paragraphs of text:
  73. tl.Append(Common.Util.LoremIpsum(7, 5, 6, 28, 32));
  74. // Calculate glyphs and lay out the text:
  75. tl.PerformLayout(true);
  76. // Split options to control splitting of text between pages.
  77. // We can either use the default ctor and set up values like MaxWidth etc,
  78. // or create a TextSplitOptions based on the TextLayout, and clear RestObjectRects:
  79. var to = new TextSplitOptions(tl)
  80. {
  81. RestObjectRects = null,
  82. MinLinesInFirstParagraph = 2,
  83. MinLinesInLastParagraph = 2
  84. };
  85. // In a loop, split and render the text:
  86. while (true)
  87. {
  88. // 'rest' will accept the text that did not fit:
  89. var splitResult = tl.Split(to, out TextLayout rest);
  90. doc.Pages.Last.Graphics.DrawTextLayout(tl, PointF.Empty);
  91. if (splitResult != SplitResult.Split)
  92. break;
  93. tl = rest;
  94. // We only draw images on the first page:
  95. tl.ObjectRects = null;
  96. doc.Pages.Add();
  97. }
  98. // Done:
  99. doc.Save(stream);
  100. return doc.Pages.Count;
  101. }
  102. }
  103. }
  104. }
  105.