Esempio n. 1
0
        public int CreatePDF(Stream stream)
        {
            const int NPAR = 40;
            var       doc  = new GcPdfDocument();
            var       tl   = new TextLayout(72)
            {
                FirstLineIndent = 72 / 2,
                MaxWidth        = doc.PageSize.Width,
                MaxHeight       = doc.PageSize.Height,
                MarginAll       = 72,
            };

            tl.DefaultFormat.Font     = StandardFonts.Times;
            tl.DefaultFormat.FontSize = 12;
            // Text format for paragraphs kept together with next one:
            var tf = new TextFormat(tl.DefaultFormat)
            {
                FontSize = tl.DefaultFormat.FontSize + 2,
                FontBold = true
            };

            // We add a number of random 'lorem ipsum' paragraphs to this document,
            // adding a 'caption' before each paragraph which is kept together
            // with the following 'lorem ipsum' paragraph:
            for (int i = 0; i < NPAR; i++)
            {
                // 'Caption' kept together with the next paragraph:
                tl.Append("Caption kept together with the next paragraph. No page break after this.", tf);
                // AppendParagraphBreak adds a paragraph break but prevents a page break between the two paragraphs:
                tl.AppendParagraphBreak();
                // Random paragraph after 'caption':
                tl.Append(Common.Util.LoremIpsum(1));
            }
            tl.PerformLayout(true);
            // We force all paragraph lines to stay on the same page,
            // this makes it more obvious that 'caption' and following paragraph
            // are kept on the same page:
            TextSplitOptions to = new TextSplitOptions(tl)
            {
                KeepParagraphLinesTogether = true,
            };

            // In a loop, split and render the text:
            while (true)
            {
                // 'rest' will accept the text that did not fit:
                var splitResult = tl.Split(to, out TextLayout rest);
                doc.Pages.Add().Graphics.DrawTextLayout(tl, PointF.Empty);
                if (splitResult != SplitResult.Split)
                {
                    break;
                }
                tl = rest;
            }
            // Done:
            doc.Save(stream);
            return(doc.Pages.Count);
        }
Esempio n. 2
0
        public int CreatePDF(Stream stream)
        {
            // Setup:
            GcPdfDocument doc = new GcPdfDocument();
            TextLayout    tl  = new TextLayout(72)
            {
                MaxWidth  = doc.PageSize.Width,
                MaxHeight = doc.PageSize.Height,
                MarginAll = 72,
            };

            tl.DefaultFormat.FontSize = 7;
            var tfH = new TextFormat()
            {
                Font = StandardFonts.TimesBold, FontSize = 12
            };
            var tfP = new TextFormat()
            {
                Font = StandardFonts.Times, FontSize = 11
            };

            // Loop through all system fonts,
            // list Unicode ranges provided by each font:
            foreach (Font font in FontCollection.SystemFonts)
            {
                tl.AppendLine($"{font.FontFileName} [{font.FullFontName}] [{font.FontFamilyName}]", tfH);
                var shot = font.CreateFontTables(TableTag.OS2);
                tl.AppendLine(shot.GetUnicodeRanges(), tfP);
                tl.AppendLine();
            }

            // Split and render TextLayout as shown in the PaginatedText sample:
            TextSplitOptions to = new TextSplitOptions(tl)
            {
                MinLinesInFirstParagraph = 2,
                MinLinesInLastParagraph  = 2
            };

            tl.PerformLayout(true);
            while (true)
            {
                var splitResult = tl.Split(to, out TextLayout rest);
                doc.Pages.Add().Graphics.DrawTextLayout(tl, PointF.Empty);
                if (splitResult != SplitResult.Split)
                {
                    break;
                }
                tl = rest;
            }

            // Done:
            doc.Save(stream);
            return(doc.Pages.Count);
        }
Esempio n. 3
0
        public void CreatePDF(Stream stream)
        {
            var doc = new GcPdfDocument();
            // Use TextLayout to render text:
            var tl = new TextLayout(72);

            // If not specifying formats for individual runs, we MUST provide
            // font and font size on TextLayout.DefaultFormat:
            tl.DefaultFormat.Font     = StandardFonts.Times;
            tl.DefaultFormat.FontSize = 12;
            // First line offset 1/2":
            tl.FirstLineIndent = 72 / 2;
            //
            // All other formatting properties are left at their default values.
            // In particular, TextLayout's default resolution is 72 dpi -
            // the same as GcPdf's, and WordWrap is true.
            //
            // Set TextLayout's area to the whole page:
            tl.MaxWidth  = doc.PageSize.Width;
            tl.MaxHeight = doc.PageSize.Height;
            // ...and have it manage the page margins (1" all around):
            tl.MarginAll = tl.Resolution;
            //
            // Append the text (20 paragraphs so they would not fit on a single page)
            // (note that TextLayout interprets "\r\n" as paragraph delimiter):
            tl.Append(Common.Util.LoremIpsum(20));
            //
            // When all text has been added, we must calculate the glyphs needed to render the text,
            // and perform the layout. This can be done by a single call to PerformLayout, passing true to
            // recalculate glyphs first (even though the text won't all fit in the specified max size,
            // we only need to call PerformLayout once):
            tl.PerformLayout(true);
            // Use split options to provide widow/orphan control:
            TextSplitOptions to = new TextSplitOptions(tl);

            to.MinLinesInFirstParagraph = 2;
            to.MinLinesInLastParagraph  = 2;
            // In a loop, split and render the text:
            while (true)
            {
                // 'rest' will accept the text that did not fit:
                var splitResult = tl.Split(to, out TextLayout rest);
                doc.Pages.Add().Graphics.DrawTextLayout(tl, PointF.Empty);
                if (splitResult != SplitResult.Split)
                {
                    break;
                }
                tl = rest;
            }
            // Done:
            doc.Save(stream);
        }
Esempio n. 4
0
        public static void Run()
        {
            string filePath    = Constants.SAMPLE_TXT;
            string filePathOut = Path.Combine(Constants.GetOutputDirectoryPath(), "text_{0}.{1}");

            TextSplitOptions splitOptions = new TextSplitOptions(filePathOut, TextSplitMode.Interval, new int[] { 3, 6 });

            using (Merger merger = new Merger(filePath))
            {
                merger.Split(splitOptions);
            }

            Console.WriteLine("Source document was splitted successfully.");
            Console.WriteLine($"Check output {filePathOut}.");
        }
Esempio n. 5
0
        // Main entry point:
        public void CreatePDF(Stream stream)
        {
            var doc = new GcPdfDocument();
            var ip  = new PointF(Layout.Margin, Layout.Margin);
            // Use TextLayout.MarginLeft to reserve space for list numbers/bullets:
            var tl = new TextLayout(72)
            {
                MaxWidth         = doc.PageSize.Width - Layout.Margin * 2,
                MaxHeight        = doc.PageSize.Height - Layout.Margin * 2,
                ParagraphSpacing = 8,
                MarginLeft       = Layout.ListOffset,
            };

            tl.DefaultFormat.Font = StandardFonts.Times;

            // Add 20 paragraphs of text that will render as a numbered list of 20 items:
            tl.Append(Common.Util.LoremIpsum(20, 1, 6));
            // Perform layout:
            tl.PerformLayout(true);
            // Use split options to provide widow/orphan control:
            TextSplitOptions to = new TextSplitOptions(tl);

            to.MinLinesInFirstParagraph = 2;
            to.MinLinesInLastParagraph  = 2;
            // In a loop, split and render the text (see PaginatedText),
            // and add list numbers:
            int itemNo = 1;

            while (true)
            {
                // 'rest' will accept the text that did not fit:
                var splitResult = tl.Split(to, out TextLayout rest);
                var g           = doc.Pages.Add().Graphics;
                g.DrawTextLayout(tl, ip);
                AddBullets(g, ip, tl, ref itemNo);
                if (splitResult != SplitResult.Split)
                {
                    break;
                }
                tl = rest;
            }
            // Done:
            doc.Save(stream);
        }
Esempio n. 6
0
        // Adds a word index to the end of the passed document:
        private void AddWordIndex(GcPdfDocument doc, IEnumerable <string> words)
        {
            var tStart = DateTime.Now;

            // Words and page indices where they occur, sorted on words:
            SortedDictionary <string, List <int> > index = new SortedDictionary <string, List <int> >();

            // Here the main loop building the index is on key words.
            // An alternative would be to loop over the pages.
            // Depending on the relative sizes of the keyword dictionary vs
            // the number of pages in the document, one or the other might be better,
            // but this is beyond the scope of this sample.
            foreach (string word in words)
            {
                bool wholeWord = word.IndexOf(' ') == -1;
                var  ft        = doc.FindText(new FindTextParams(word, wholeWord, false), OutputRange.All);
                var  pgs       = ft.Select(fp_ => fp_.PageIndex).Distinct();
                // A very simplistic way of also finding plurals:
                if (wholeWord && !word.EndsWith('s'))
                {
                    var ftpl = doc.FindText(new FindTextParams(word + "s", wholeWord, false), OutputRange.All);
                    pgs = pgs.Concat(ftpl.Select(fp_ => fp_.PageIndex).Distinct()).Distinct();
                }
                if (pgs.Any())
                {
                    var sorted = pgs.ToList();
                    sorted.Sort();
                    index.Add(word, sorted);
                }
            }

            // Prepare to render the index. The whole index is built
            // in a single TextLayout instance, set up to render it
            // in two columns per page.
            // The main rendering loop uses the TextLayout.SplitAndBalance method
            // using the approach demonstrated in BalancedColumns sample.
            // The complication here is that we need to associate a link to the
            // relevant page with each page number rendered, see linkIndices below.
            // Set up the TextLayout:
            const float margin     = 72;
            var         pageWidth  = doc.PageSize.Width;
            var         pageHeight = doc.PageSize.Height;
            var         cW         = pageWidth - margin * 2;
            // Caption (index letter) format:
            var tfCap = new TextFormat()
            {
                FontName = _fontFamily,
                FontBold = true,
                FontSize = 16,
                LineGap  = 24,
            };
            // Index word and pages format:
            var tfRun = new TextFormat()
            {
                FontName = _fontFamily,
                FontSize = 10,
            };
            // Page headers/footers:
            var tfHdr = new TextFormat()
            {
                FontName   = _fontFamily,
                FontItalic = true,
                FontSize   = 10,
            };
            // FirstLineIndent = -18 sets up hanging indent:
            var tl = new TextLayout(72)
            {
                FontCollection         = _fc,
                FirstLineIndent        = -18,
                MaxWidth               = pageWidth,
                MaxHeight              = pageHeight,
                MarginLeft             = margin,
                MarginRight            = margin,
                MarginBottom           = margin,
                MarginTop              = margin,
                ColumnWidth            = cW * 0.46f,
                TextAlignment          = TextAlignment.Leading,
                ParagraphSpacing       = 4,
                LineGapBeforeFirstLine = false,
            };

            // The list of text runs created for page numbers:
            List <Tuple <TextRun, int> > pgnumRuns = new List <Tuple <TextRun, int> >();
            // This loop builds the index on the TextLayout, saving the text runs
            // created for each page number rendered. Note that at this point
            // (prior to the PerformLayout(true) call) the text runs do not contain any info
            // about their code points and render locations, so we can only save the text runs here.
            // Later they will be used to add links to referenced pages in the PDF:
            char litera = ' ';

            foreach (KeyValuePair <string, List <int> > kvp in index)
            {
                var word        = kvp.Key;
                var pageIndices = kvp.Value;
                if (Char.ToUpper(word[0]) != litera)
                {
                    litera = Char.ToUpper(word[0]);
                    tl.Append($"{litera}\u2029", tfCap);
                }
                tl.Append(word, tfRun);
                tl.Append("  ", tfRun);
                for (int i = 0; i < pageIndices.Count; ++i)
                {
                    var from = pageIndices[i];
                    var tr   = tl.Append((from + 1).ToString(), tfRun);
                    pgnumRuns.Add(Tuple.Create(tr, from));
                    // We merge sequential pages into "..-M":
                    int k = i;
                    for (int j = i + 1; j < pageIndices.Count && pageIndices[j] == pageIndices[j - 1] + 1; ++j)
                    {
                        k = j;
                    }
                    if (k > i + 1)
                    {
                        tl.Append("-", tfRun);
                        var to = pageIndices[k];
                        tr = tl.Append((to + 1).ToString(), tfRun);
                        pgnumRuns.Add(Tuple.Create(tr, to));
                        // Fast forward:
                        i = k;
                    }
                    if (i < pageIndices.Count - 1)
                    {
                        tl.Append(", ", tfRun);
                    }
                    else
                    {
                        tl.AppendLine(tfRun);
                    }
                }
            }
            // This calculates the glyphs and lays out the whole index.
            // The tl.SplitAndBalance() call in the loop below does not require redoing the layout:
            tl.PerformLayout(true);

            //
            // Now we are ready to split and render the text layout, and also add links to page numbers.
            //

            // Split areas and options - see BalancedColumns for details:
            var psas = new PageSplitArea[] {
                new PageSplitArea(tl)
                {
                    MarginLeft = tl.MarginLeft + (cW * 0.54f)
                },
            };
            TextSplitOptions tso = new TextSplitOptions(tl)
            {
                KeepParagraphLinesTogether = true,
            };

            // First original code point index in the current column:
            int cpiStart = 0;
            // Max+1 original code point index in the current column:
            int cpiEnd = 0;
            // Current index in pgnumRuns:
            int pgnumRunsIdx = 0;

            // Split and render the index in 2 columns:
            for (var page = doc.Pages.Add(); ; page = doc.Pages.Add())
            {
                var g = page.Graphics;
                // Add a simple page header:
                g.DrawString($"Index generated by GcPdf on {tStart}", tfHdr,
                             new RectangleF(margin, 0, pageWidth - margin * 2, margin),
                             TextAlignment.Center, ParagraphAlignment.Center, false);
                // 'rest' will accept the text that did not fit on this page:
                var splitResult = tl.SplitAndBalance(psas, tso, out TextLayout rest);
                // Render text:
                g.DrawTextLayout(tl, PointF.Empty);
                g.DrawTextLayout(psas[0].TextLayout, PointF.Empty);
                // Add links from page numbers to pages:
                linkIndices(tl, page);
                linkIndices(psas[0].TextLayout, page);
                // Are we done yet?
                if (splitResult != SplitResult.Split)
                {
                    break;
                }
                tl = rest;
            }
            // Done:
            return;

            // Method to add links to actual pages over page numbers in the current column:
            void linkIndices(TextLayout tl_, Page page_)
            {
                cpiEnd += tl_.CodePointCount;
                for (; pgnumRunsIdx < pgnumRuns.Count; ++pgnumRunsIdx)
                {
                    var run     = pgnumRuns[pgnumRunsIdx];
                    var textRun = run.Item1;
                    int cpi     = textRun.CodePointIndex;
                    if (cpi >= cpiEnd)
                    {
                        break;
                    }
                    cpi -= cpiStart;
                    var rects = tl_.GetTextRects(cpi, textRun.CodePointCount);
                    System.Diagnostics.Debug.Assert(rects.Count > 0);
                    page_.Annotations.Add(new LinkAnnotation(rects[0].ToRectangleF(), new DestinationFit(run.Item2)));
                }
                cpiStart += tl_.CodePointCount;
            }
        }
Esempio n. 7
0
        public int CreatePDF(Stream stream)
        {
            var sourcePDF = "CompleteJavaScriptBook.pdf";

            GcPdfDocument doc  = new GcPdfDocument();
            var           page = doc.NewPage();

            var rc = Common.Util.AddNote(
                "This sample loads an arbitrary PDF into a temporary GcPdfDocument, " +
                "and lists all fonts found in that document, with some of their properties. " +
                "It also tries to create a Font object from each of those PDF fonts, " +
                "and reports whether this operation succeeded.",
                page);

            // Text layout to render the text:
            var tab = 24;
            var tl  = page.Graphics.CreateTextLayout();

            tl.DefaultFormat.Font     = StandardFonts.Times;
            tl.DefaultFormat.FontSize = 12;
            tl.MaxWidth  = doc.PageSize.Width;
            tl.MaxHeight = doc.PageSize.Height;
            tl.MarginAll = rc.Left;
            tl.MarginTop = rc.Bottom + 36;
            tl.TabStops  = new List <TabStop>()
            {
                new TabStop(tab)
            };
            tl.FirstLineIndent = -tab;
            tl.MarginRight     = 144;

            // Text split options for widow/orphan control:
            TextSplitOptions to = new TextSplitOptions(tl)
            {
                KeepParagraphLinesTogether = true,
                MinLinesInFirstParagraph   = 2,
                MinLinesInLastParagraph    = 2,
                RestMarginTop = rc.Left,
            };

            // Open an arbitrary PDF, load it into a temp document and get all fonts:
            using (var fs = new FileStream(Path.Combine("Resources", "PDFs", sourcePDF), FileMode.Open, FileAccess.Read))
            {
                var doc1 = new GcPdfDocument();
                doc1.Load(fs);

                var fonts = doc1.GetFonts();

                tl.AppendLine($"Total of {fonts.Count} fonts found in {sourcePDF}:");
                tl.AppendLine();
                int i = 0;
                foreach (var font in fonts)
                {
                    var nativeFont = font.CreateNativeFont();
                    tl.Append($"{i}:\tBaseFont: {font.BaseFont}; IsEmbedded: {font.IsEmbedded}.");
                    tl.AppendParagraphBreak();
                    if (nativeFont != null)
                    {
                        tl.AppendLine($"\tCreateNativeFont succeeded, family: {nativeFont.FontFamilyName}; bold: {nativeFont.FontBold}; italic: {nativeFont.FontItalic}.");
                    }
                    else
                    {
                        tl.AppendLine("\tCreateNativeFont failed");
                    }
                    tl.AppendLine();
                    ++i;
                }
                tl.PerformLayout(true);
                while (true)
                {
                    // 'rest' will accept the text that did not fit:
                    var splitResult = tl.Split(to, out TextLayout rest);
                    doc.Pages.Last.Graphics.DrawTextLayout(tl, PointF.Empty);
                    if (splitResult != SplitResult.Split)
                    {
                        break;
                    }
                    tl = rest;
                    doc.NewPage();
                }
            }
            // Done:
            doc.Save(stream);
            return(doc.Pages.Count);
        }
Esempio n. 8
0
        public int CreatePDF(Stream stream)
        {
            GcPdfDocument doc  = new GcPdfDocument();
            var           page = doc.NewPage();

            var rc = Common.Util.AddNote(
                "This sample loads the PDF created by the TimeSheet sample into a temporary GcPdfDocument, " +
                "gets the text map for the first page, and prints out the coordinates and texts of all " +
                "line fragments in the map. " +
                "It also uses the map's HitTest method to find the text at specific coordinates in the PDF " +
                "and prints the result. " +
                "The original TimeSheet.pdf used by this sample (consisting of 1 page) is appended for reference.",
                page);

            // Setup text formatting and layout:
            var tf = new TextFormat()
            {
                Font     = StandardFonts.Times,
                FontSize = 13
            };
            var tfFound = new TextFormat()
            {
                Font      = StandardFonts.TimesBold,
                FontSize  = 14,
                ForeColor = Color.DarkBlue
            };
            var tl = new TextLayout(72)
            {
                MaxWidth  = doc.PageSize.Width,
                MaxHeight = doc.PageSize.Height,
                MarginAll = rc.Left,
                MarginTop = rc.Bottom + 36,
                TabStops  = new List <TabStop>()
                {
                    new TabStop(72 * 2)
                },
            };
            TextSplitOptions to = new TextSplitOptions(tl)
            {
                MinLinesInFirstParagraph = 2,
                MinLinesInLastParagraph  = 2,
                RestMarginTop            = rc.Left,
            };

            // Open an arbitrary PDF, load it into a temp document and use the map to find some texts:
            using (var fs = new FileStream(Path.Combine("Resources", "PDFs", "TimeSheet.pdf"), FileMode.Open, FileAccess.Read))
            {
                var doc1 = new GcPdfDocument();
                doc1.Load(fs);
                var tmap = doc1.Pages[0].GetTextMap();

                // We retrieve the text at a specific (known to us) geometric location on the page:
                float       tx0 = 2.1f, ty0 = 3.37f, tx1 = 3.1f, ty1 = 3.5f;
                HitTestInfo htiFrom = tmap.HitTest(tx0 * 72, ty0 * 72);
                HitTestInfo htiTo   = tmap.HitTest(ty0 * 72, ty1 * 72);
                tmap.GetFragment(htiFrom.Pos, htiTo.Pos, out TextMapFragment range1, out string text1);
                tl.AppendLine($"Looked for text inside rectangle x={tx0:F2}\", y={ty0:F2}\", width={tx1-tx0:F2}\", height={ty1-ty0:F2}\", found:", tf);
                tl.AppendLine(text1, tfFound);
                tl.AppendLine();

                // Get all text fragments and their locations on the page:
                tl.AppendLine("List of all texts found on the page", tf);
                tmap.GetFragment(out TextMapFragment range, out string text);
                foreach (TextLineFragment tlf in range)
                {
                    var coords = tmap.GetCoords(tlf);
                    tl.Append($"Text at ({coords.B.X / 72:F2}\",{coords.B.Y / 72:F2}\"):\t", tf);
                    tl.AppendLine(tmap.GetText(tlf), tfFound);
                }

                // Print the results:
                tl.PerformLayout(true);
                while (true)
                {
                    // 'rest' will accept the text that did not fit:
                    var splitResult = tl.Split(to, out TextLayout rest);
                    doc.Pages.Last.Graphics.DrawTextLayout(tl, PointF.Empty);
                    if (splitResult != SplitResult.Split)
                    {
                        break;
                    }
                    tl = rest;
                    doc.NewPage();
                }

                // Append the original document for reference:
                doc.MergeWithDocument(doc1, new MergeDocumentOptions());
            }
            // Done:
            doc.Save(stream);
            return(doc.Pages.Count);
        }
Esempio n. 9
0
        // The main sample driver.
        public int CreatePDF(Stream stream)
        {
            GcPdfDocument doc = new GcPdfDocument();
            // This will hold the llst of images so we can dispose them after saving the document:
            List <IDisposable> disposables = new List <IDisposable>();

            // Page footer:
            var ftrImg = Image.FromFile(Path.Combine("Resources", "ImagesBis", "logo-GC-devsol.png"));

            disposables.Add(ftrImg);
            var fx    = ftrImg.HorizontalResolution / 72f;
            var fy    = ftrImg.VerticalResolution / 72f;
            var ftrRc = new RectangleF(
                doc.PageSize.Width / 2 - ftrImg.Width / fx / 2,
                doc.PageSize.Height - 40,
                ftrImg.Width / fx,
                ftrImg.Height / fy);

            // Color for the title:
            var colorBlue = Color.FromArgb(0x3B, 0x5C, 0xAA);
            // Color for the highlights:
            var colorRed = Color.Red;
            // The text layout used to render text:
            TextLayout tl = new TextLayout(72)
            {
                MaxWidth     = doc.PageSize.Width,
                MaxHeight    = doc.PageSize.Height,
                MarginLeft   = 72,
                MarginRight  = 72,
                MarginTop    = 72,
                MarginBottom = 72,
            };

            tl.DefaultFormat.Font     = Font.FromFile(Path.Combine("Resources", "Fonts", "segoeui.ttf"));
            tl.DefaultFormat.FontSize = 11;

            var page = doc.NewPage();

            addFtr();
            var g = page.Graphics;

            // Caption:
            tl.TextAlignment = TextAlignment.Center;
            tl.Append("Introduction\n", new TextFormat()
            {
                FontSize = 16, ForeColor = colorBlue
            });
            tl.Append("The Importance of Wetlands", new TextFormat()
            {
                FontSize = 13, ForeColor = colorBlue
            });
            tl.PerformLayout(true);
            g.DrawTextLayout(tl, PointF.Empty);

            // Move below the caption for the first para:
            tl.MarginTop = tl.ContentHeight + 72 * 2;
            tl.Clear();
            tl.TextAlignment    = TextAlignment.Leading;
            tl.ParagraphSpacing = 12;

            // For the first para we want a bigger initial letter, but no first line indent,
            // so we render it separately from the rest of the text:
            tl.Append(_paras[0].Substring(0, 1), new TextFormat(tl.DefaultFormat)
            {
                FontSize = 22
            });
            addPara(_paras[0].Substring(1));
            tl.PerformLayout(true);
            g.DrawTextLayout(tl, PointF.Empty);

            // Account for the first para, and set up the text layout
            // for the rest of the text (a TextLayout allows to render multiple paragraphs,
            // but they all must have the same paragraph format):
            tl.MarginTop = tl.ContentRectangle.Bottom;
            tl.Clear();
            tl.FirstLineIndent = 36;

            // Add remaining paragraphs:
            foreach (var para in _paras.Skip(1))
            {
                // Paragraphs starting with '::' indicate images to be rendered across the page width:
                if (para.StartsWith("::"))
                {
                    var img = Image.FromFile(Path.Combine("Resources", "ImagesBis", para.Substring(2)));
                    disposables.Add(img);
                    var w = tl.MaxWidth.Value - tl.MarginLeft - tl.MarginRight;
                    var h = (float)img.Height / (float)img.Width * w;
                    tl.AppendInlineObject(img, w, h);
                    tl.AppendLine();
                }
                else
                {
                    addPara(para);
                }
            }
            // Layout the paragraphs:
            tl.PerformLayout(true);
            // Text split options allow to implement widow and orphan control:
            var tso = new TextSplitOptions(tl)
            {
                RestMarginTop            = 72,
                MinLinesInFirstParagraph = 2,
                MinLinesInLastParagraph  = 2,
            };
            // Image alignment used to render the pictures:
            var ia = new ImageAlign(ImageAlignHorz.Left, ImageAlignVert.Top, true, true, true, false, false)
            {
                BestFit = true
            };

            // In a loop, split and render the text:
            while (true)
            {
                var splitResult = tl.Split(tso, out TextLayout rest);
                g = doc.Pages.Last.Graphics;
                doc.Pages.Last.Graphics.DrawTextLayout(tl, PointF.Empty);
                // Render all images that occurred on this page:
                foreach (var io in tl.InlineObjects)
                {
                    doc.Pages.Last.Graphics.DrawImage((Image)io.Object, io.ObjectRect.ToRectangleF(), null, ia);
                }
                // Break unless there is more to render:
                if (splitResult != SplitResult.Split)
                {
                    break;
                }
                // Assign the remaining text to the 'main' TextLayout, add a new page and continue:
                tl = rest;
                doc.Pages.Add();
                addFtr();
            }

            // Save the PDF:
            doc.Save(stream);
            // Dispose images (can be done only after saving the document):
            disposables.ForEach(d_ => d_.Dispose());
            // Done:
            return(doc.Pages.Count);

            void addPara(string para)
            {
                // We implement a primitive markup to highlight some fragments in red:
                var txt = para.Split(new string[] { "<red>", "</red>" }, StringSplitOptions.None);

                for (int i = 0; i < txt.Length; ++i)
                {
                    if (i % 2 == 0)
                    {
                        tl.Append(txt[i]);
                    }
                    else
                    {
                        tl.Append(txt[i], new TextFormat(tl.DefaultFormat)
                        {
                            ForeColor = colorRed
                        });
                    }
                }
                tl.AppendLine();
            }

            void addFtr()
            {
                doc.Pages.Last.Graphics.DrawImage(ftrImg, ftrRc, null, ImageAlign.StretchImage);
            }
        }
Esempio n. 10
0
        public int CreatePDF(Stream stream)
        {
            var doc = new GcPdfDocument();
            var g   = doc.NewPage().Graphics;

            //
            // We want to draw 3 images in certain arbitrary locations on the first page,
            // and then print a text that would take 2-3 pages, and have it flow around
            // the images on the first page.
            //
            // Get the images and their rectangles. Note that we specify a square
            // area for all images - but they will be aligned within that area
            // preserving their original aspect ratios, so we will later retrieve
            // the actual rectangles where the images were drawn:
            using (var imgPuffins = Image.FromFile("Resources/Images/puffins.jpg"))
                using (var imgReds = Image.FromFile("Resources/Images/reds.jpg"))
                    using (var imgLavender = 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);
                        // Set up ImageAlign that would fit and center an image within a specified area,
                        // preserving the image's original aspect ratio:
                        ImageAlign ia = new ImageAlign(ImageAlignHorz.Center, ImageAlignVert.Center, true, true, true, false, false);
                        // Draw each image, providing an array of rectangles as an output parameter for each DrawImage call,
                        // so that we get the actual rectangle taken by the image (an array is needed to handle tiled images):
                        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);
                        // Create and set up a TextLayout object to print the text:
                        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" margins all around
                        tl.MarginAll = 72 / 2;
                        // ObjectRect is the type used to specify the areas to flow around to TextLayout.
                        // We set up a local function to create an ObjecRect based on an image rectangle,
                        // adding some padding so that the result looks nicer:
                        Func <RectangleF, ObjectRect> makeObjectRect = rect_ =>
                                                                       new ObjectRect(rect_.X - 6, rect_.Y - 2, rect_.Width + 12, rect_.Height + 4);
                        // Specify the array of ObjectRects on the TextLayout:
                        tl.ObjectRects = new List <ObjectRect>()
                        {
                            makeObjectRect(rectsPuffins[0]),
                            makeObjectRect(rectsReds[0]),
                            makeObjectRect(rectsLavender[0]),
                        };
                        // Add several paragraphs of text:
                        tl.Append(Common.Util.LoremIpsum(7, 5, 6, 28, 32));
                        // Calculate glyphs and lay out the text:
                        tl.PerformLayout(true);
                        // Split options to control splitting of text between pages.
                        // We can either use the default ctor and set up values like MaxWidth etc,
                        // or create a TextSplitOptions based on the TextLayout, and clear RestObjectRects:
                        TextSplitOptions to = new TextSplitOptions(tl)
                        {
                            RestObjectRects          = null,
                            MinLinesInFirstParagraph = 2,
                            MinLinesInLastParagraph  = 2
                        };
                        // In a loop, split and render the text:
                        while (true)
                        {
                            // 'rest' will accept the text that did not fit:
                            var splitResult = tl.Split(to, out TextLayout rest);
                            doc.Pages.Last.Graphics.DrawTextLayout(tl, PointF.Empty);
                            if (splitResult != SplitResult.Split)
                            {
                                break;
                            }
                            tl = rest;
                            // We only draw images on the first page:
                            tl.ObjectRects = null;
                            doc.Pages.Add();
                        }
                        // Done:
                        doc.Save(stream);
                        return(doc.Pages.Count);
                    }
        }
Esempio n. 11
0
        public int CreatePDF(Stream stream)
        {
            const string pdfName = "ExternalCMapTest.pdf";

            // This line may not be needed if the GcPdfDocument class ctor finds
            // the GrapeCity.Documents.Pdf.Resources.dll at startup
            // (this depends on the way the app is deployed):
            GcPdfDocument.CMapProvider = CMapProvider.Instance;

            GcPdfDocument doc  = new GcPdfDocument();
            var           page = doc.NewPage();

            var rc = Common.Util.AddNote("This sample loads a PDF into a temporary GcPdfDocument, " +
                                         "retrieves all text from each page of the loaded document using the Page.GetText() method, " +
                                         "adds all those texts to a TextLayout and renders it into the current document. " +
                                         "CMaps used by the PDF in this sample are provided by the optional " +
                                         "https://www.nuget.org/packages/GrapeCity.Documents.Pdf.Resources/ package. " +
                                         "Without a reference to that package most of the text in this particular PDF will not be found " +
                                         "as it uses the less common CMaps that are not built into GcPdf itself." +
                                         "\n\n" +
                                         "To use GrapeCity.Documents.Pdf.Resources in a project, add a reference to it, " +
                                         "and either make sure that GrapeCity.Documents.Pdf.Resources.dll is present in the runtime directory, " +
                                         "or add the line:" +
                                         "\n\tGcPdfDocument.CMapProvider = CMapProvider.Instance;" +
                                         "\nto the project's initialization code.",
                                         page);

            Font arialbd  = Font.FromFile(Path.Combine("Resources", "Fonts", "arialbd.ttf"));
            Font segoe    = Font.FromFile(Path.Combine("Resources", "Fonts", "segoeui.ttf"));
            Font arialuni = Font.FromFile(Path.Combine("Resources", "Fonts", "arialuni.ttf"));

            segoe.AddLinkedFont(arialuni);

            // Text format for captions:
            var tf = new TextFormat()
            {
                Font      = arialbd,
                FontSize  = 14,
                ForeColor = Color.Blue
            };
            // Text layout to render the text:
            var tl = new TextLayout(72);

            tl.DefaultFormat.Font     = segoe;
            tl.DefaultFormat.FontSize = 12;
            tl.MaxWidth  = doc.PageSize.Width;
            tl.MaxHeight = doc.PageSize.Height;
            tl.MarginAll = rc.Left;
            tl.MarginTop = rc.Bottom + 36;

            // Text split options for widow/orphan control:
            TextSplitOptions to = new TextSplitOptions(tl)
            {
                MinLinesInFirstParagraph = 2,
                MinLinesInLastParagraph  = 2,
                RestMarginTop            = rc.Left,
            };

            // Open an arbitrary PDF, load it into a temp document and get all page texts:
            using (var fs = new FileStream(Path.Combine("Resources", "PDFs", pdfName), FileMode.Open, FileAccess.Read))
            {
                var doc1 = new GcPdfDocument();
                doc1.Load(fs);

                // Get the texts of the loaded document's pages:
                var texts = new List <string>();
                doc1.Pages.ToList().ForEach(p_ => texts.Add(p_.GetText()));

                // Add texts and captions to the text layout:
                for (int i = 0; i < texts.Count; ++i)
                {
                    tl.AppendLine($"Text from page {i + 1} of {pdfName}:", tf);
                    tl.AppendLine(texts[i]);
                }
                tl.PerformLayout(true);
                while (true)
                {
                    // 'rest' will accept the text that did not fit:
                    var splitResult = tl.Split(to, out TextLayout rest);
                    doc.Pages.Last.Graphics.DrawTextLayout(tl, PointF.Empty);
                    if (splitResult != SplitResult.Split)
                    {
                        break;
                    }
                    tl = rest;
                    doc.NewPage();
                }
            }
            // Done:
            doc.Save(stream);
            return(doc.Pages.Count);
        }
Esempio n. 12
0
        public void CreatePDF(Stream stream)
        {
            var doc = new GcPdfDocument();

            // Create a Part element, it will contain P (paragraph) elements:
            StructElement sePart = new StructElement("Part");

            doc.StructTreeRoot.Children.Add(sePart);

            // Create and set up a TextLayout to render paragraphs:
            var tl = new TextLayout(72);

            tl.DefaultFormat.Font     = StandardFonts.Times;
            tl.DefaultFormat.FontSize = 12;
            tl.FirstLineIndent        = 72 / 2;
            tl.MaxWidth  = doc.PageSize.Width;
            tl.MaxHeight = doc.PageSize.Height;
            tl.MarginAll = tl.Resolution;
            //
            // Append the text (20 paragraphs so they would not fit on a single page)
            // (note that TextLayout interprets "\r\n" as paragraph delimiter):
            //
            // Get the text (20 paragraphs):
            var text = Common.Util.LoremIpsum(20);
            // In order to tag the individual paragraphs, we need to split the text into paragraphs,
            // and use each paragraph format's Tag property (which is not related to PDF tags,
            // it is just an arbitrary data that can be associated with a TextFormat) to add the
            // paragraph's index to the paragraph:
            var pars = text.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

            for (int i = 0; i < pars.Length; ++i)
            {
                var tf = new TextFormat(tl.DefaultFormat)
                {
                    Tag = i
                };
                tl.AppendLine(pars[i], tf);
            }

            // Layout the text:
            tl.PerformLayout(true);
            // Use split options to provide widow/orphan control:
            TextSplitOptions to = new TextSplitOptions(tl)
            {
                MinLinesInFirstParagraph = 2,
                MinLinesInLastParagraph  = 2,
            };
            // TextLayoutHandler implements ITextLayoutHandler, which
            // allows to tag the text as it is rendered:
            TextLayoutHandler tlh = new TextLayoutHandler()
            {
                ParentElement = sePart
            };

            // In a loop, split and render the text:
            while (true)
            {
                // 'rest' will accept the text that did not fit:
                var splitResult = tl.Split(to, out TextLayout rest);
                var page        = doc.Pages.Add();
                var g           = page.Graphics;
                // Tell the TextLayoutHandler which page we're on:
                tlh.Page = page;
                // ..and associate it with the graphics:
                g.TextLayoutHandler = tlh;
                // Draw the text that fits on the current page, and advance to next page unless we're done:
                g.DrawTextLayout(tl, PointF.Empty);
                if (splitResult != SplitResult.Split)
                {
                    break;
                }
                tl = rest;
            }
            // Mark document as tagged:
            doc.MarkInfo.Marked = true;

            // Done:
            doc.Save(stream);
        }
Esempio n. 13
0
        public int CreatePDF(Stream stream)
        {
            GcPdfDocument doc  = new GcPdfDocument();
            var           page = doc.NewPage();

            var rc = Common.Util.AddNote(
                "This sample loads an arbitrary PDF into a temporary GcPdfDocument, " +
                "then retrieves text from each page of the loaded document using the Page.GetText() method, " +
                "adds all those texts to a TextLayout and renders it into the current document. " +
                "An alternative to Page.GetText() is the method GcPdfDocument.GetText() " +
                "which retrieves the text from the whole document at once.",
                page);

            // Text format for captions:
            var tf = new TextFormat()
            {
                Font      = Font.FromFile(Path.Combine("Resources", "Fonts", "yumin.ttf")),
                FontSize  = 14,
                ForeColor = Color.Blue
            };
            // Text layout to render the text:
            var tl = new TextLayout(72);

            tl.DefaultFormat.Font     = StandardFonts.Times;
            tl.DefaultFormat.FontSize = 12;
            tl.MaxWidth  = doc.PageSize.Width;
            tl.MaxHeight = doc.PageSize.Height;
            tl.MarginAll = rc.Left;
            tl.MarginTop = rc.Bottom + 36;

            // Text split options for widow/orphan control:
            TextSplitOptions to = new TextSplitOptions(tl)
            {
                MinLinesInFirstParagraph = 2,
                MinLinesInLastParagraph  = 2,
                RestMarginTop            = rc.Left,
            };

            // Open an arbitrary PDF, load it into a temp document and get all page texts:
            using (var fs = new FileStream(Path.Combine("Resources", "PDFs", "Wetlands.pdf"), FileMode.Open, FileAccess.Read))
            {
                var doc1 = new GcPdfDocument();
                doc1.Load(fs);

                // Get the texts of the loaded document's pages:
                var texts = new List <string>();
                doc1.Pages.ToList().ForEach(p_ => texts.Add(p_.GetText()));

                // Add texts and captions to the text layout:
                for (int i = 0; i < texts.Count; ++i)
                {
                    tl.AppendLine(string.Format("Text from page {0} of the loaded document:", i + 1), tf);
                    tl.AppendLine(texts[i]);
                }
                tl.PerformLayout(true);
                while (true)
                {
                    // 'rest' will accept the text that did not fit:
                    var splitResult = tl.Split(to, out TextLayout rest);
                    doc.Pages.Last.Graphics.DrawTextLayout(tl, PointF.Empty);
                    if (splitResult != SplitResult.Split)
                    {
                        break;
                    }
                    tl = rest;
                    doc.NewPage();
                }
            }
            // Done:
            doc.Save(stream);
            return(doc.Pages.Count);
        }
Esempio n. 14
0
        public int CreatePDF(Stream stream)
        {
            using (var clouds = Image.FromFile(Path.Combine("Resources", "Images", "clouds.jpg")))
                using (var firth = Image.FromFile(Path.Combine("Resources", "Images", "firth.jpg")))
                    using (var lavender = Image.FromFile(Path.Combine("Resources", "Images", "lavender.jpg")))
                    {
                        var yumin = Font.FromFile(Path.Combine("Resources", "Fonts", "yumin.ttf"));
                        var ia    = new ImageAlign(ImageAlignHorz.Left, ImageAlignVert.Top, true, true, true, false, false);

                        var doc = new GcPdfDocument();

                        // The TextLayout that will hold and render the text:
                        var tl = new TextLayout(72);
                        tl.FirstLineIndent       = 18;
                        tl.ParagraphSpacing      = 6;
                        tl.FlowDirection         = FlowDirection.VerticalRightToLeft;
                        tl.TextAlignment         = TextAlignment.Justified;
                        tl.AlignmentDelayToSplit = true;
                        var tf = new TextFormat()
                        {
                            Font = yumin, FontSize = 12
                        };
                        // Repeat test text to fill a few pages:
                        for (int i = 0; i < 25; ++i)
                        {
                            tl.Append(text, tf);
                            tl.AppendLine();
                        }

                        // Layout text in 4 horizontal columns:
                        // (The logic/code in this sample is identical to ArabicColumns):
                        const int NCOLS  = 4;
                        var       margin = 36f;
                        var       gap    = 18f;
                        var       page   = doc.NewPage();
                        page.Landscape = true;
                        var colHeight = (page.Size.Height - margin * 2 - gap * (NCOLS - 1)) / NCOLS;
                        tl.MaxWidth     = page.Size.Width;
                        tl.MaxHeight    = page.Size.Height;
                        tl.MarginLeft   = tl.MarginRight = margin;
                        tl.MarginTop    = margin;
                        tl.MarginBottom = margin + (colHeight + gap) * (NCOLS - 1);
                        // We can specify arbitrary rectangles for the text to flow around.
                        // In this case, we add 3 areas to draw some images:
                        tl.ObjectRects = new List <ObjectRect>()
                        {
                            new ObjectRect(page.Size.Width - margin - 267, margin, 267, 200),
                            new ObjectRect(margin + 100, margin + 60, 133, 100),
                            new ObjectRect(margin, page.Size.Height - margin - 301, 200, 301),
                        };
                        // Convert object rects to image areas, adjust to provide nice looking padding:
                        var rClouds = tl.ObjectRects[0].ToRectangleF();
                        rClouds.Inflate(-4, -3);
                        var rFirth = tl.ObjectRects[1].ToRectangleF();
                        rFirth.Inflate(-4, -3);
                        var rLavender = tl.ObjectRects[2].ToRectangleF();
                        rLavender.Inflate(-4, -3);
                        page.Graphics.DrawImage(clouds, rClouds, null, ia);
                        page.Graphics.DrawImage(firth, rFirth, null, ia);
                        page.Graphics.DrawImage(lavender, rLavender, null, ia);

                        // THE call: it calculates the glyphs needed to draw the text, and lays it out:
                        tl.PerformLayout(true);

                        // Loop while there is still text to render:
                        bool done = false;
                        while (!done)
                        {
                            for (int col = 0; col < NCOLS; ++col)
                            {
                                int nextcol = (col < NCOLS - 1) ? col + 1 : 0;
                                // TextSplitOptions tell TextLayout.Split() how to layout the remaining text.
                                // In this case we advance from column to column by updating top and bottom margins:
                                var tso = new TextSplitOptions(tl)
                                {
                                    RestMarginTop    = margin + (colHeight + gap) * nextcol,
                                    RestMarginBottom = margin + (colHeight + gap) * (NCOLS - 1 - nextcol)
                                };
                                var split = tl.Split(tso, out TextLayout rest);
                                page.Graphics.DrawTextLayout(tl, PointF.Empty);
                                if (split != SplitResult.Split)
                                {
                                    done = true;
                                    break;
                                }
                                tl = rest;
                            }
                            if (!done)
                            {
                                page           = doc.NewPage();
                                page.Landscape = true;
                                // We only want to render images on the first page, so clear ObjectRect:
                                if (tl.ObjectRects != null)
                                {
                                    tl.ObjectRects = null;
                                    // We need to redo the layout, but no need to recalculate the glyphs:
                                    tl.PerformLayout(false);
                                }
                            }
                        }
                        // Done:
                        doc.Save(stream);
                        return(doc.Pages.Count);
                    }
        }
Esempio n. 15
0
        public void CreatePDF(Stream stream)
        {
            var doc = new GcPdfDocument();
            // Text layout for main text (default GcPdf resolution is 72dpi):
            var tl = new TextLayout(72);

            tl.DefaultFormat.Font     = StandardFonts.Times;
            tl.DefaultFormat.FontSize = 12;
            tl.FirstLineIndent        = 72 / 2;
            tl.MaxWidth  = doc.PageSize.Width;
            tl.MaxHeight = doc.PageSize.Height;
            tl.MarginAll = tl.Resolution;
            // Text layout for chapter headers:
            var tlCaption = new TextLayout(72);

            tlCaption.DefaultFormat.Font      = StandardFonts.TimesBold;
            tlCaption.DefaultFormat.FontSize  = tl.DefaultFormat.FontSize + 4;
            tlCaption.DefaultFormat.Underline = true;
            tlCaption.MaxWidth  = tl.MaxWidth;
            tlCaption.MarginAll = tlCaption.Resolution;
            // Split options to control splitting of text between pages:
            TextSplitOptions to = new TextSplitOptions(tl)
            {
                RestMarginTop            = tl.Resolution,
                MinLinesInFirstParagraph = 2,
                MinLinesInLastParagraph  = 2
            };
            // Generate a number of "chapters", provide outline entry for each:
            const int NChapters = 20;

            for (int i = 0; i < NChapters; ++i)
            {
                // Chapter title - print as chapter header and add as outline node:
                string chapter = $"Chapter {i + 1}";

                // All it takes to add page lables is to add a PageLabelingRange
                // associated with the index of the first page in the range,
                // and the range prefix and numbering style:
                doc.PageLabelingRanges.Add(doc.Pages.Count, new PageLabelingRange($"{chapter}, p. ", NumberingStyle.DecimalArabic, 1));

                doc.Pages.Add();
                tlCaption.Clear();
                tlCaption.Append(chapter);
                tlCaption.PerformLayout(true);
                // Add outline node for the chapter:
                doc.Outlines.Add(new OutlineNode(chapter, new DestinationFitH(doc.Pages.Count - 1, tlCaption.MarginTop)));
                // Print the caption:
                doc.Pages.Last.Graphics.DrawTextLayout(tlCaption, PointF.Empty);
                // Chapter text:
                tl.Clear();
                tl.FirstLineIsStartOfParagraph = true;
                tl.LastLineIsEndOfParagraph    = true;
                tl.Append(Common.Util.LoremIpsum(7));
                // Account for chapter header in the main text layout:
                tl.MarginTop = tlCaption.ContentRectangle.Bottom + 12;
                tl.PerformLayout(true);
                // Print the chapter:
                while (true)
                {
                    // 'rest' will accept the text that did not fit:
                    var splitResult = tl.Split(to, out TextLayout rest);
                    doc.Pages.Last.Graphics.DrawTextLayout(tl, PointF.Empty);
                    if (splitResult != SplitResult.Split)
                    {
                        break;
                    }
                    tl = rest;
                    var p = doc.Pages.Add();
                }
            }
            // Done:
            doc.Save(stream);
        }
Esempio n. 16
0
        public void 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 GcPdf):
            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 GcPdf 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;
            tl.AlignmentDelayToSplit = true;
            // 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:
            TextSplitOptions 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.Count - 1, 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);
        }
Esempio n. 17
0
        public int CreatePDF(Stream stream)
        {
            // Number of pages to generate:
            const int N     = Common.Util.LargeDocumentIterations;
            var       start = DateTime.Now;
            var       doc   = new GcPdfDocument();
            // Prep a TextLayout to hold/format the text:
            var tl = new TextLayout(72)
            {
                MaxWidth        = doc.PageSize.Width,
                MaxHeight       = doc.PageSize.Height,
                MarginAll       = 72,
                FirstLineIndent = 36,
            };

            tl.DefaultFormat.Font     = StandardFonts.Times;
            tl.DefaultFormat.FontSize = 12;
            // Generate the document:
            for (int paraIdx = 0; paraIdx < N; ++paraIdx)
            {
                tl.AppendLine(Common.Util.LoremIpsum(1));
            }
            // Split and render TextLayout as shown in the PaginatedText sample:
            TextSplitOptions tso = new TextSplitOptions(tl)
            {
                MinLinesInFirstParagraph = 2,
                MinLinesInLastParagraph  = 2,
            };

            tl.PerformLayout(true);
            // The loop splitting and rendering the layout:
            var tls = new TextLayoutSplitter(tl);

            for (var tlPage = tls.Split(tso); tlPage != null; tlPage = tls.Split(tso))
            {
                doc.NewPage().Graphics.DrawTextLayout(tlPage, PointF.Empty);
            }

            tl.Clear();
            // Insert a title page (cannot be done if using StartDoc/EndDoc):
            tl.FirstLineIndent = 0;
            var fnt = Font.FromFile(Path.Combine("Resources", "Fonts", "yumin.ttf"));
            var tf0 = new TextFormat()
            {
                FontSize = 24, FontBold = true, Font = fnt
            };

            tl.Append(string.Format("Large Document\n{0} Pages of Lorem Ipsum\n\n", N), tf0);
            var tf1 = new TextFormat(tf0)
            {
                FontSize = 14, FontItalic = true
            };

            tl.Append(string.Format("Generated on {0} in {1:m\\m\\ s\\s\\ fff\\m\\s}.", DateTime.Now, DateTime.Now - start), tf1);
            tl.TextAlignment = TextAlignment.Center;
            tl.PerformLayout(true);
            doc.Pages.Insert(0).Graphics.DrawTextLayout(tl, PointF.Empty);
            // Done:
            doc.Save(stream);
            return(doc.Pages.Count);
        }