BalancedColumns.cs
- //
- // This code is part of Document Solutions for PDF demos.
- // Copyright (c) MESCIUS inc. All rights reserved.
- //
- using System;
- using System.IO;
- using System.Drawing;
- using GrapeCity.Documents.Pdf;
- using GrapeCity.Documents.Text;
-
- namespace DsPdfWeb.Demos.Basics
- {
- // Creates a multi-column text layout with balanced columns.
- // The heart of this sample is the TextLayout.SplitAndBalance() method
- // which allows splitting a text between multiple columns,
- // AND balance those columns so that their heights are similar,
- // thus allowing to produce magazine- and newspaper-like text layouts.
- public class BalancedColumns
- {
- public int CreatePDF(Stream stream)
- {
- var doc = new GcPdfDocument();
- var font = StandardFonts.Times;
- var fontSize = 12;
- // 1/2" margins all around (72 dpi is the default resolution used by DsPdf):
- var margin = 72 / 2;
- var pageWidth = doc.PageSize.Width;
- var pageHeight = doc.PageSize.Height;
- var cW = pageWidth - margin * 2;
- // Text format for the chapter titles:
- var tlCaption = new TextLayout(72);
- tlCaption.DefaultFormat.Font = font;
- tlCaption.DefaultFormat.FontSize = fontSize + 4;
- tlCaption.DefaultFormat.Underline = true;
- tlCaption.MaxWidth = pageWidth;
- tlCaption.MaxHeight = pageHeight;
- tlCaption.MarginLeft = tlCaption.MarginTop = tlCaption.MarginRight = tlCaption.MarginBottom = margin;
- tlCaption.TextAlignment = TextAlignment.Center;
- // Height of chapter caption (use a const for simplicity):
- const float captionH = 24;
- // Text layout for main document body (default DsPdf resolution is 72dpi):
- var tl = new TextLayout(72);
- tl.DefaultFormat.Font = font;
- tl.DefaultFormat.FontSize = fontSize;
- tl.FirstLineIndent = 72 / 2;
- tl.MaxWidth = pageWidth;
- tl.MaxHeight = pageHeight;
- tl.MarginLeft = tl.MarginRight = tl.MarginBottom = margin;
- tl.MarginTop = margin + captionH;
- tl.ColumnWidth = cW * 0.3f;
- tl.TextAlignment = TextAlignment.Justified;
- // Array of PageSplitArea's which control additional columns (1st column is controlled by
- // the 'main' TextLayout, for each additional one a PageSplitArea must be provided -
- // it will create and return a TextLayout that can then be used to render the column):
- var psas = new PageSplitArea[]
- {
- new PageSplitArea(tl) { MarginLeft = tl.MarginLeft + (cW * 0.35f) },
- new PageSplitArea(tl) { ColumnWidth = -cW * 0.3f }
- };
- // Split options to control splitting text between pages:
- var tso = new TextSplitOptions(tl)
- {
- RestMarginTop = margin,
- MinLinesInFirstParagraph = 2,
- MinLinesInLastParagraph = 2
- };
- // Generate a number of "chapters", provide outline entry for each:
- const int NChapters = 20;
- doc.Pages.Add();
- for (int i = 0; i < NChapters; ++i)
- {
- // Print chapter header across all columns:
- string chapter = $"Chapter {i + 1}";
- tlCaption.Clear();
- tlCaption.Append(chapter);
- tlCaption.PerformLayout(true);
- doc.Pages.Last.Graphics.DrawTextLayout(tlCaption, PointF.Empty);
- // Add outline node for the chapter:
- doc.Outlines.Add(new OutlineNode(chapter, new DestinationFitV(doc.Pages.Last, null)));
- //
- // Clear last chapter's text and add new chapter:
- tl.FirstLineIsStartOfParagraph = true;
- tl.LastLineIsEndOfParagraph = true;
- tl.Clear();
- tl.Append(Common.Util.LoremIpsum(5, 7, 9, 15, 25));
- tl.PerformLayout(true);
- // Variable to hold last chapter end's bottom coord:
- float contentBottom = 0f;
- // Print the chapter:
- var tls = new TextLayoutSplitter(tl);
- while (true)
- {
- var tlCol0 = tls.SplitAndBalance(psas, tso);
- var g = doc.Pages.Last.Graphics;
- g.DrawTextLayout(tlCol0, PointF.Empty);
- g.DrawTextLayout(psas[0].TextLayout, PointF.Empty);
- g.DrawTextLayout(psas[1].TextLayout, PointF.Empty);
- if (tls.SplitResult != SplitResult.Split)
- {
- // End of chapter, find out how much height left on page for next chapter:
- contentBottom = tl.ContentY + tl.ContentHeight;
- contentBottom = Math.Max(contentBottom, psas[0].TextLayout.ContentRectangle.Bottom);
- contentBottom = Math.Max(contentBottom, psas[1].TextLayout.ContentRectangle.Bottom);
- // Done printing chapter:
- break;
- }
- // Continue printing chapter on new page:
- psas[0].MarginTop = psas[1].MarginTop = margin;
- doc.Pages.Add();
- }
- // Next chapter - find out if we have enough space left on current page to start new chapter:
- if (contentBottom + captionH < pageHeight * 0.8f)
- {
- // Start new chapter on current page:
- contentBottom += pageHeight * 0.05f;
- tlCaption.MarginTop = contentBottom;
- tl.MarginTop = psas[0].MarginTop = psas[1].MarginTop = contentBottom + captionH;
- }
- else if (i < NChapters - 1)
- {
- // Start new chapter on new page:
- tlCaption.MarginTop = margin;
- tl.MarginTop = psas[0].MarginTop = psas[1].MarginTop = margin + captionH;
- doc.Pages.Add();
- }
- }
- // Done:
- doc.Save(stream);
- return doc.Pages.Count;
- }
- }
- }
-