TextAroundImages.cs
// 完毕:
using System;
using System.IO;
using System.Drawing;
using System.Collections.Generic;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Drawing;
using GCTEXT = GrapeCity.Documents.Text;
using GCDRAW = GrapeCity.Documents.Drawing;

namespace DsPdfWeb.Demos.Basics
{
    // 此示例展示了如何在矩形区域周围流动大块文本,
    // 在本例中是图像。它还演示了如何获取实际边界
    // 使用特定 ImageAlign 在页面上呈现的图像的图像。
    public class TextAroundImages
    {
        public int CreatePDF(Stream stream)
        {
            var doc = new GcPdfDocument();
            var g = doc.NewPage().Graphics;
            // 我们想在第一页的某些任意位置绘制 3 个图像,
            // 然后打印需要 2-3 页的文本,并让它四处流动
            // 第一页上的图像。
            // 
            // 获取图像及其矩形。请注意,我们指定了一个正方形
            // 所有图像的区域 - 但它们将在该区域内对齐
            // 保留它们原来的长宽比,所以我们稍后会检索
            // 绘制图像的实际矩形:
            using (var imgPuffins = GCDRAW.Image.FromFile("Resources/Images/puffins.jpg"))
            using (var imgReds = GCDRAW.Image.FromFile("Resources/Images/reds.jpg"))
            using (var imgLavender = GCDRAW.Image.FromFile("Resources/Images/lavender.jpg"))
            {
                var rectPuffins = new RectangleF(100, 70, 180, 180);
                var rectReds = new RectangleF(300, 280, 180, 180);
                var rectLavender = new RectangleF(190, 510, 180, 180);
                // 设置 ImageAlign 使图像适合并居中于指定区域内,
                // 保留图像的原始长宽比:
                var ia = new ImageAlign(ImageAlignHorz.Center, ImageAlignVert.Center, true, true, true, false, false);
                // 绘制每个图像,为每个 DrawImage 调用提供一个矩形数组作为输出参数,
                // 这样我们就得到了图像所拍摄的实际矩形(需要一个数组来处理平铺图像):
                g.DrawImage(imgPuffins, rectPuffins, null, ia, out RectangleF[] rectsPuffins);
                g.DrawImage(imgReds, rectReds, null, ia, out RectangleF[] rectsReds);
                g.DrawImage(imgLavender, rectLavender, null, ia, out RectangleF[] rectsLavender);
                // 创建并设置一个 TextLayout 对象来打印文本:
                var tl = g.CreateTextLayout();
                tl.DefaultFormat.Font = StandardFonts.Times;
                tl.DefaultFormat.FontSize = 9;
                tl.TextAlignment = TextAlignment.Justified;
                tl.ParagraphSpacing = 72 / 8;
                tl.MaxWidth = doc.PageSize.Width;
                tl.MaxHeight = doc.PageSize.Height;
                // 周围 1/2" 边距
                tl.MarginAll = 72 / 2;
                // ObjectRect 是用于指定要流向 TextLayout 的区域的类型。
                //  我们设置一个本地函数来根据图像矩形创建一个 ObjecRect,
                // 添加一些填充以使结果看起来更好:
                Func<RectangleF, ObjectRect> makeObjectRect = rect_ =>
                    new ObjectRect(rect_.X - 6, rect_.Y - 2, rect_.Width + 12, rect_.Height + 4);
                // 指定 TextLayout 上的 ObjectRect 数组:
                tl.ObjectRects = new List<ObjectRect>()
                {
                    makeObjectRect(rectsPuffins[0]),
                    makeObjectRect(rectsReds[0]),
                    makeObjectRect(rectsLavender[0]),
                };
                // 添加几段文字:
                tl.Append(Common.Util.LoremIpsum(7, 5, 6, 28, 32));
                // 计算字形并布置文本:
                tl.PerformLayout(true);
                // 拆分选项可控制页面之间的文本拆分。
                // 我们可以使用默认的 ctor 并设置 MaxWidth 等值,
                // 或者基于TextLayout创建一个TextSplitOptions,并清除RestObjectRects:
                var to = new TextSplitOptions(tl)
                {
                    RestObjectRects = null,
                    MinLinesInFirstParagraph = 2,
                    MinLinesInLastParagraph = 2
                };
                // 在循环中,分割并渲染文本:
                while (true)
                {
                    // 'rest' 将接受不适合的文本:
                    var splitResult = tl.Split(to, out TextLayout rest);
                    doc.Pages.Last.Graphics.DrawTextLayout(tl, PointF.Empty);
                    if (splitResult != SplitResult.Split)
                        break;
                    tl = rest;
                    // 我们只在第一页上绘制图像:
                    tl.ObjectRects = null;
                    doc.Pages.Add();
                }
                // 完毕:
                doc.Save(stream);
                return doc.Pages.Count;
            }
        }
    }
}