示例#1
0
        public int CreatePDF(Stream stream)
        {
            // Number of pages to generate:
            const int N   = Common.Util.LargeDocumentIterations;
            var       doc = new GcPdfDocument();

            // Start creating the document by this call:
            doc.StartDoc(stream);
            // Prep a TextLayout to hold/format the text:
            var tl = new TextLayout(72)
            {
                MaxWidth  = doc.PageSize.Width,
                MaxHeight = doc.PageSize.Height,
                MarginAll = 72,
            };

            tl.DefaultFormat.Font     = StandardFonts.Times;
            tl.DefaultFormat.FontSize = 12;
            // Start with a title page:
            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}.", DateTime.Now), tf1);
            tl.TextAlignment = TextAlignment.Center;
            tl.PerformLayout(true);
            doc.Pages.Add().Graphics.DrawTextLayout(tl, PointF.Empty);
            tl.Clear();
            tl.FirstLineIndent = 36;
            tl.TextAlignment   = TextAlignment.Leading;
            // Generate the document:
            for (int pageIdx = 0; pageIdx < N; ++pageIdx)
            {
                tl.Append(Common.Util.LoremIpsum(1));
                tl.PerformLayout(true);
                doc.NewPage().Graphics.DrawTextLayout(tl, PointF.Empty);
                tl.Clear();
            }
            // NOTE: Certain operations (e.g. the one below) will throw an error when using StartDoc/EndDoc:
            //   doc.Pages.Insert(0);
            //
            // Done - call EndDoc instead of Save():
            doc.EndDoc();
            return(doc.Pages.Count);
        }
示例#2
0
        // Creates a sample document with 100 pages of 'lorem ipsum':
        private string MakeDocumentToIndex()
        {
            const int N     = 100;
            string    tfile = Path.GetTempFileName();

            using (var fsOut = new FileStream(tfile, FileMode.Open, FileAccess.ReadWrite))
            {
                var tdoc = new GcPdfDocument();
                // See StartEndDoc for details on StartDoc/EndDoc mode:
                tdoc.StartDoc(fsOut);
                // Prep a TextLayout to hold/format the text:
                var tl = new TextLayout(72);
                tl.FontCollection         = _fc;
                tl.DefaultFormat.FontName = _fontFamily;
                tl.DefaultFormat.FontSize = 12;
                // Use TextLayout to layout the whole page including margins:
                tl.MaxHeight       = tdoc.PageSize.Height;
                tl.MaxWidth        = tdoc.PageSize.Width;
                tl.MarginAll       = 72;
                tl.FirstLineIndent = 72 / 2;
                // Generate the document:
                for (int pageIdx = 0; pageIdx < N; ++pageIdx)
                {
                    tl.Append(Common.Util.LoremIpsum(1));
                    tl.PerformLayout(true);
                    tdoc.NewPage().Graphics.DrawTextLayout(tl, PointF.Empty);
                    tl.Clear();
                }
                tdoc.EndDoc();
            }
            return(tfile);
        }
示例#3
0
        private RectangleF DrawText(string text, TextStyle ts)
        {
            var        page = CurrPage;
            TextLayout tl   = page.Graphics.CreateTextLayout();

            tl.MaxWidth = page.Size.Width - MarginRight - _ip.X;
            if (ts.FontSize == TsTitle.FontSize) // patch
            {
                tl.TextAlignment = TextAlignment.Center;
            }
            tl.DefaultFormat.Font               = ts.Font;
            tl.DefaultFormat.FontSize           = ts.FontSize;
            tl.DefaultFormat.GlyphAdvanceFactor = ts.GlyphAdvanceFactor;
            tl.DefaultFormat.ForeColor          = ts.ForeColor;
            tl.Append(text);
            tl.PerformLayout(true);

            var line           = tl.Lines[tl.Lines.Count - 1];
            var run            = line.GlyphRuns[0];
            var baselineOffset = run.BaselineOffset;

            var p = _lastBaselineOffset.HasValue ?
                    new PointF(_ip.X, _ip.Y + _lastBaselineOffset.Value - baselineOffset) : _ip;

            page.Graphics.DrawTextLayout(tl, p);
            if (!_lastBaselineOffset.HasValue)
            {
                _lastBaselineOffset = baselineOffset; // within one 'line', keep using the first offset
            }
            return(new RectangleF(_ip.X + tl.ContentX, _ip.Y + tl.ContentY, tl.ContentWidth, tl.ContentHeight));
        }
示例#4
0
        public void CreatePDF(Stream stream)
        {
            // Rotation angle, degrees clockwise:
            float angle = -45;
            //
            var doc = new GcPdfDocument();
            var g   = doc.NewPage().Graphics;
            // Create a text layout, pick a font and font size:
            TextLayout tl = g.CreateTextLayout();

            tl.DefaultFormat.Font     = StandardFonts.Times;
            tl.DefaultFormat.FontSize = 24;
            // Add a text, and perform layout:
            tl.Append("Rotated text.");
            tl.PerformLayout(true);
            // Text insertion point at (1",1"):
            var ip = new PointF(72, 72);
            // Now that we have text size, create text rectangle with top left at insertion point:
            var rect = new RectangleF(ip.X, ip.Y, tl.ContentWidth, tl.ContentHeight);

            // Rotate the text around its bounding rect's center:
            // we now have the text size, and can rotate it about its center:
            g.Transform = Matrix3x2.CreateRotation((float)(angle * Math.PI) / 180f, new Vector2(ip.X + tl.ContentWidth / 2, ip.Y + tl.ContentHeight / 2));
            // Draw rotated text and bounding rectangle:
            g.DrawTextLayout(tl, ip);
            g.DrawRectangle(rect, Color.Black, 1);
            // Remove rotation and draw the bounding rectangle where the non-rotated text would have been:
            g.Transform = Matrix3x2.Identity;
            g.DrawRectangle(rect, Color.ForestGreen, 1);
            //
            doc.Save(stream);
        }
示例#5
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 pageIdx = 0; pageIdx < N; ++pageIdx)
            {
                tl.Append(Common.Util.LoremIpsum(1));
                tl.PerformLayout(true);
                doc.NewPage().Graphics.DrawTextLayout(tl, 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()
            {
                Font = fnt, FontSize = 24, FontBold = true
            };

            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);
        }
示例#6
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);
        }
示例#7
0
        // Static ctor:
        static GoodsReturnForm()
        {
            // Init Textbox:
            TextLayout tl = new TextLayout(72);

            tl.Append("Qwerty");
            tl.DefaultFormat.Font     = Textbox.Font;
            tl.DefaultFormat.FontSize = Textbox.FontSize;
            tl.PerformLayout(true);
            Textbox.Height         = tl.ContentHeight;
            Textbox.BaselineOffset = tl.Lines[0].GlyphRuns[0].BaselineOffset;
            // Init Checkbox:
            tl.Clear();
            tl.Append("Qwerty");
            tl.DefaultFormat.Font     = Checkbox.Font;
            tl.DefaultFormat.FontSize = Checkbox.FontSize;
            tl.PerformLayout(true);
            Checkbox.Height         = tl.ContentHeight;
            Checkbox.BaselineOffset = tl.Lines[0].GlyphRuns[0].BaselineOffset;
        }
示例#8
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);
        }
示例#9
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);
        }
示例#10
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);
        }
示例#11
0
        // Renders a list of nodes as a numbered list.
        private PointF RenderNodes(ref Page page, PointF pt, List <Node> nodes, int level)
        {
            TextLayout tlBullet = new TextLayout(72);

            tlBullet.DefaultFormat.Font = StandardFonts.Times;
            tlBullet.MarginLeft         = Layout.ListIndent * level;

            TextLayout tlText = new TextLayout(72);

            tlText.DefaultFormat.Font = StandardFonts.Times;
            tlText.MarginLeft         = Layout.ListOffset + Layout.ListIndent * level;

            for (int i = 0; i < nodes.Count; ++i)
            {
                var g = page.Graphics;
                // Prep item text:
                tlText.Clear();
                tlText.Append(nodes[i].Text);
                tlText.PerformLayout(true);
                if (pt.Y + tlText.ContentHeight > page.Size.Height - Layout.Margin)
                {
                    page = page.Doc.NewPage();
                    g    = page.Graphics;
                    pt.Y = Layout.Margin;
                }
                // Prep item number:
                tlBullet.Clear();
                tlBullet.Append(ItemIdxToString(i, level, tlBullet));
                tlBullet.PerformLayout(true);
                // Render item:
                g.DrawTextLayout(tlBullet, pt);
                g.DrawTextLayout(tlText, pt);
                // Advance insertion point:
                pt.Y += tlText.ContentHeight;
                // Render children:
                if (nodes[i].Children.Count > 0)
                {
                    pt = RenderNodes(ref page, pt, nodes[i].Children, level + 1);
                }
            }
            return(pt);
        }
示例#12
0
        public void CreatePDF(Stream stream)
        {
            // Rotation angle, degrees clockwise:
            float angle = -45;
            //
            var doc = new GcPdfDocument();
            var g   = doc.NewPage().Graphics;
            // Create a text layout, pick a font and font size:
            TextLayout tl = g.CreateTextLayout();

            tl.DefaultFormat.Font     = StandardFonts.Times;
            tl.DefaultFormat.FontSize = 24;
            // Add a text, and perform layout:
            tl.Append("Rotated text.");
            tl.PerformLayout(true);
            // Text insertion point at (1",1"):
            var ip = new PointF(72, 72);
            // Now that we have text size, create text rectangle with top left at insertion point:
            var rect = new RectangleF(ip.X, ip.Y, tl.ContentWidth, tl.ContentHeight);
            // Rotation center point in the middel of text bounding rectangle:
            var center = new PointF(ip.X + tl.ContentWidth / 2, ip.Y + tl.ContentHeight / 2);

            // Transformations can be combined by multiplying matrices.
            // Note that matrix multiplication is not commutative -
            // the sequence of operands is important, and is applied from last to first
            // matrices being multiplied:
            // 3) Translate the origin back to (0,0):
            // 2) Rotate around new origin by the specified angle:
            // 1) Translate the origin from default (0,0) to rotation center:
            g.Transform =
                Matrix3x2.CreateTranslation(-center.X, -center.Y) *
                Matrix3x2.CreateRotation((float)(angle * Math.PI) / 180f) *
                Matrix3x2.CreateTranslation(center.X, center.Y);
            // Draw rotated text and bounding rectangle:
            g.DrawTextLayout(tl, ip);
            g.DrawRectangle(rect, Color.Black, 1);
            // Remove transformation and draw the bounding rectangle where the non-rotated text would have been:
            g.Transform = Matrix3x2.Identity;
            g.DrawRectangle(rect, Color.ForestGreen, 1);
            // Done:
            doc.Save(stream);
        }
示例#13
0
        // Method drawing a language's caption and test text:
        private void DrawText(string caption, string text, Font font, bool rtl)
        {
            _captionLayout.Clear();
            _captionLayout.Append(caption);
            _captionLayout.PerformLayout(true);

            _textLayout.Clear();
            _textLayout.DefaultFormat.Font = font;
            _textLayout.RightToLeft        = rtl;
            _textLayout.Append(text);
            _textLayout.PerformLayout(true);
            // Add new page if needed:
            GcGraphics g;

            if (_doc.Pages.Count == 0 || _ipY + tlHeight(_captionLayout) + tlHeight(_textLayout) + c_CaptionToText > _doc.PageSize.Height - c_Margin)
            {
                _ipY = c_Margin;
                g    = _doc.Pages.Add().Graphics;
            }
            else
            {
                g = _doc.Pages.Last.Graphics;
            }
            // Draw caption:
            g.FillRectangle(new RectangleF(c_Margin, _ipY, _captionLayout.MaxWidth.Value, tlHeight(_captionLayout)), Color.SteelBlue);
            g.DrawTextLayout(_captionLayout, new PointF(c_Margin, _ipY));
            _ipY += tlHeight(_captionLayout);
            _ipY += c_CaptionToText;
            // Draw test text:
            g.DrawRectangle(new RectangleF(c_Margin, _ipY, _textLayout.MaxWidth.Value, tlHeight(_textLayout)), Color.LightSteelBlue, 0.5f);
            g.DrawTextLayout(_textLayout, new PointF(c_Margin, _ipY));
            _ipY += tlHeight(_textLayout);
            _ipY += c_TextToCaption;
            return;

            float tlHeight(TextLayout tl)
            {
                return(tl.MarginTop + tl.ContentHeight + tl.MarginBottom);
            }
        }
示例#14
0
        // Utility method to draw a part of a page header or footer.
        // Parameters:
        // - text: The part's text.
        // - tf: The text format to use.
        // - pageIdx: The page index.
        // - header: True if this is a header, false if a footer.
        // - horzAlign: Horizontal alignment (left/center/right).
        private void RenderHeader(string text, TextFormat tf, int pageIdx, bool header, TextAlignment horzAlign)
        {
            var        page = _doc.Pages[pageIdx];
            TextLayout tl   = new TextLayout(page.Graphics.Resolution);

            tl.MaxWidth  = page.Size.Width;
            tl.MaxHeight = page.Size.Height;
            // 1" margins, adjust as needed:
            tl.MarginLeft = tl.MarginRight = 72;
            // 1/3" spacing above top/below bottom header, adjust as needed:
            tl.MarginTop = tl.MarginBottom = 72 / 3;
            // Vertical alignment:
            tl.ParagraphAlignment = header ? ParagraphAlignment.Near : ParagraphAlignment.Far;
            // Horizontal alignment:
            tl.TextAlignment = horzAlign;
            tl.Append(text, tf);
            // NOTE: if some part of a header or footer is static, we could cache the corresponding TextLayout
            // object and save some cycles by just drawing that cached TextLayout on each page w/out anything else:
            tl.PerformLayout(true);
            // Draw the header at (0,0) (header located by margins and alignment):
            page.Graphics.DrawTextLayout(tl, PointF.Empty);
        }
示例#15
0
 // Replaces any text fields in the document with regular text:
 private void FlattenDoc(GcPdfDocument doc)
 {
     foreach (var f in doc.AcroForm.Fields)
     {
         if (f is TextField fld)
         {
             var w = fld.Widget;
             var g = w.Page.Graphics;
             _inputTl.Clear();
             _inputTl.Append(fld.Value, _inputTf);
             _inputTl.MaxHeight = w.Rect.Height;
             _inputTl.PerformLayout(true);
             g.DrawTextLayout(_inputTl, w.Rect.Location);
         }
     }
     for (int i = doc.AcroForm.Fields.Count - 1; i >= 0; --i)
     {
         if (doc.AcroForm.Fields[i] is TextField)
         {
             doc.AcroForm.Fields.RemoveAt(i);
         }
     }
 }
示例#16
0
        public void CreatePDF(Stream stream)
        {
            GcPdfDocument doc = new GcPdfDocument();

            // The original file stream must be kept open while working with the loaded PDF, see LoadPDF for details:
            using (var fs = new FileStream(Path.Combine("Resources", "PDFs", "FormFields.pdf"), FileMode.Open, FileAccess.Read))
            {
                doc.Load(fs);
                var           page = doc.Pages.Last;
                StringBuilder sb   = new StringBuilder();
                sb.AppendLine("Log of updates made by the FillForm sample:\r\n");

                foreach (Field fld in doc.AcroForm.Fields)
                {
                    if (fld is CombTextField ctfld)
                    {
                        sb.Append($"CombTextField.Value was '{ctfld.Value}', ");
                        ctfld.Value = "Comb text";
                        sb.AppendLine($"now '{ctfld.Value}'.");
                    }
                    else if (fld is TextField tfld)
                    {
                        sb.Append($"TextField.Value was '{tfld.Value}', ");
                        tfld.Value = $"Text updated on {DateTime.Now}";
                        sb.AppendLine($"now '{tfld.Value}'.");
                    }
                    else if (fld is CheckBoxField cfld)
                    {
                        sb.Append($"CheckBoxField.Value was '{cfld.Value}', ");
                        cfld.Value = !cfld.Value;
                        sb.AppendLine($"now '{cfld.Value}'.");
                    }
                    else if (fld is RadioButtonField rbfld)
                    {
                        sb.Append($"RadioButtonField.Value was '{rbfld.Value}', ");
                        rbfld.Value = rbfld.Widgets.Count - 1;
                        sb.AppendLine($"now '{rbfld.Value}'.");
                    }
                    else if (fld is ComboBoxField cmbfld)
                    {
                        sb.Append($"ComboBoxField selection was '{cmbfld.Items[cmbfld.SelectedIndex].Text}', ");
                        cmbfld.SelectedIndex = cmbfld.Items.Count - 1;
                        sb.AppendLine($"now '{cmbfld.Items[cmbfld.SelectedIndex].Text}'.");
                    }
                    else if (fld is ListBoxField lbfld)
                    {
                        sb.Append($"ListBoxField selection was '{lbfld.Items[lbfld.SelectedIndex].Text}', ");
                        lbfld.SelectedIndex = lbfld.Items.Count - 1;
                        sb.AppendLine($"now '{lbfld.Items[lbfld.SelectedIndex].Text}'.");
                    }
                    else if (fld is SignatureField sfld)
                    {
                        sb.AppendLine("SignatureField found.");
                    }
                    else if (fld is PushButtonField btnfld)
                    {
                        sb.AppendLine($"PushButtonField '{btnfld.Widget.ButtonAppearance.Caption}' found.");
                    }
                    else
                    {
                        sb.AppendLine($"Field '{fld}' found/");
                    }
                }
                // Add a log of what we did at the bottom of the page:
                var tl = new TextLayout(72)
                {
                    MaxWidth           = page.Size.Width,
                    MaxHeight          = page.Size.Height,
                    MarginLeft         = 80,
                    MarginRight        = 80,
                    MarginBottom       = 80,
                    ParagraphAlignment = ParagraphAlignment.Far
                };
                tl.Append(sb.ToString(), new TextFormat()
                {
                    Font = StandardFonts.Times, FontSize = 12
                });
                tl.PerformLayout(true);
                var rc = tl.ContentRectangle;
                rc.Inflate(8, 8);
                page.Graphics.FillRectangle(rc, Color.LightYellow);
                page.Graphics.DrawRectangle(rc, Color.Orange);
                page.Graphics.DrawTextLayout(tl, PointF.Empty);

                // Done:
                doc.Save(stream);
            }
        }
示例#17
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);
                    }
        }
示例#18
0
        // Creates the Time Sheet form:
        private GcPdfDocument MakeTimeSheetForm()
        {
            const float marginH = 72, marginV = 48;
            var         doc  = new GcPdfDocument();
            var         page = doc.NewPage();
            var         g    = page.Graphics;
            var         ip   = new PointF(marginH, marginV);

            var tl = new TextLayout(g.Resolution)
            {
                FontCollection = _fc
            };

            tl.Append("TIME SHEET", new TextFormat()
            {
                FontName = "Segoe UI", FontSize = 18
            });
            tl.PerformLayout(true);
            g.DrawTextLayout(tl, ip);
            ip.Y += tl.ContentHeight + 15;

            var logo = Image.FromFile(Path.Combine("Resources", "ImagesBis", "AcmeLogo-vertical-250px.png"));

            _disposables.Add(logo);
            var s = new SizeF(250f * 0.75f, 64f * 0.75f);

            g.DrawImage(logo, new RectangleF(ip, s), null, ImageAlign.Default);
            ip.Y += s.Height + 5;

            tl.Clear();
            tl.Append("Where Business meets Technology",
                      new TextFormat()
            {
                FontName = "Segoe UI", FontItalic = true, FontSize = 10
            });
            tl.PerformLayout(true);
            g.DrawTextLayout(tl, ip);
            ip.Y += tl.ContentHeight + 15;

            tl.Clear();
            tl.Append("1901, Halford Avenue,\r\nSanta Clara, California – 95051-2553,\r\nUnited States",
                      new TextFormat()
            {
                FontName = "Segoe UI", FontSize = 9
            });
            tl.MaxWidth      = page.Size.Width - marginH * 2;
            tl.TextAlignment = TextAlignment.Trailing;
            tl.PerformLayout(true);
            g.DrawTextLayout(tl, ip);
            ip.Y += tl.ContentHeight + 25;

            var pen = new Pen(Color.Gray, 0.5f);

            var colw    = (page.Size.Width - marginH * 2) / 2;
            var fields1 = DrawTable(ip,
                                    new float[] { colw, colw },
                                    new float[] { 30, 30, 30 },
                                    g, pen);

            var tf = new TextFormat()
            {
                FontName = "Segoe UI", FontSize = 9
            };

            tl.ParagraphAlignment = ParagraphAlignment.Center;
            tl.TextAlignment      = TextAlignment.Leading;
            tl.MarginLeft         = tl.MarginRight = tl.MarginTop = tl.MarginBottom = 4;

            // t_ - caption
            // b_ - bounds
            // f_ - field name, null means no field
            Action <string, RectangleF, string> drawField = (t_, b_, f_) =>
            {
                float tWidth;
                if (!string.IsNullOrEmpty(t_))
                {
                    tl.Clear();
                    tl.MaxHeight = b_.Height;
                    tl.MaxWidth  = b_.Width;
                    tl.Append(t_, tf);
                    tl.PerformLayout(true);
                    g.DrawTextLayout(tl, b_.Location);
                    tWidth = tl.ContentRectangle.Right;
                }
                else
                {
                    tWidth = 0;
                }
                if (!string.IsNullOrEmpty(f_))
                {
                    var fld = new TextField()
                    {
                        Name = f_
                    };
                    fld.Widget.Page = page;
                    fld.Widget.Rect = new RectangleF(
                        b_.X + tWidth + _inputMargin, b_.Y + _inputMargin,
                        b_.Width - tWidth - _inputMargin * 2, b_.Height - _inputMargin * 2);
                    fld.Widget.TextFormat   = _inputTf;
                    fld.Widget.Border.Color = Color.LightSlateGray;
                    fld.Widget.Border.Width = 0.5f;
                    doc.AcroForm.Fields.Add(fld);
                }
            };

            drawField("EMPLOYEE NAME: ", fields1[0, 0], _Names.EmpName);
            drawField("TITLE: ", fields1[1, 0], _Names.EmpTitle);
            drawField("EMPLOYEE NUMBER: ", fields1[0, 1], _Names.EmpNum);
            drawField("STATUS: ", fields1[1, 1], _Names.EmpStatus);
            drawField("DEPARTMENT: ", fields1[0, 2], _Names.EmpDep);
            drawField("SUPERVISOR: ", fields1[1, 2], _Names.EmpSuper);

            ip.Y = fields1[0, 2].Bottom;

            float col0 = 100;

            colw = (page.Size.Width - marginH * 2 - col0) / 5;
            float rowh    = 25;
            var   fields2 = DrawTable(ip,
                                      new float[] { col0, colw, colw, colw, colw, colw },
                                      new float[] { 50, rowh, rowh, rowh, rowh, rowh, rowh, rowh, rowh },
                                      g, pen);

            tl.ParagraphAlignment = ParagraphAlignment.Far;
            drawField("DATE", fields2[0, 0], null);
            drawField("START TIME", fields2[1, 0], null);
            drawField("END TIME", fields2[2, 0], null);
            drawField("REGULAR HOURS", fields2[3, 0], null);
            drawField("OVERTIME HOURS", fields2[4, 0], null);
            tf.FontBold = true;
            drawField("TOTAL HOURS", fields2[5, 0], null);
            tf.FontBold           = false;
            tl.ParagraphAlignment = ParagraphAlignment.Center;
            tf.ForeColor          = Color.Gray;
            for (int i = 0; i < 7; ++i)
            {
                drawField(_Names.Dows[i], fields2[0, i + 1], _Names.DtNames[_Names.Dows[i]][0]);
            }
            tf.ForeColor = Color.Black;
            for (int row = 1; row <= 7; ++row)
            {
                for (int col = 1; col <= 5; ++col)
                {
                    drawField(null, fields2[col, row], _Names.DtNames[_Names.Dows[row - 1]][col]);
                }
            }

            tf.FontBold = true;
            drawField("WEEKLY TOTALS", fields2[0, 8], null);
            tf.FontBold = false;

            drawField(null, fields2[3, 8], _Names.TotalReg);
            drawField(null, fields2[4, 8], _Names.TotalOvr);
            drawField(null, fields2[5, 8], _Names.TotalHours);

            ip.Y = fields2[0, 8].Bottom;

            col0 = 72 * 4;
            colw = page.Size.Width - marginH * 2 - col0;
            var fields3 = DrawTable(ip,
                                    new float[] { col0, colw },
                                    new float[] { rowh + 10, rowh, rowh },
                                    g, pen);

            drawField("EMPLOYEE SIGNATURE: ", fields3[0, 1], null);
            var r = fields3[0, 1];

            _empSignRect = new RectangleF(r.X + r.Width / 2, r.Y, r.Width / 2 - _inputMargin * 2, r.Height);
            // For a digital employee signature, uncomment this code:

            /*
             * SignatureField sf = new SignatureField();
             * sf.Name = _Names.EmpSign;
             * sf.Widget.Rect = new RectangleF(r.X + r.Width / 2, r.Y + _inputMargin, r.Width / 2 - _inputMargin * 2, r.Height - _inputMargin * 2);
             * sf.Widget.Page = page;
             * sf.Widget.BackColor = Color.LightSeaGreen;
             * doc.AcroForm.Fields.Add(sf);
             */
            drawField("DATE: ", fields3[1, 1], _Names.EmpSignDate);

            drawField("SUPERVISOR SIGNATURE: ", fields3[0, 2], null);
            // Supervisor signature:
            r = fields3[0, 2];
            SignatureField sf = new SignatureField();

            sf.Name             = _Names.SupSign;
            sf.Widget.Rect      = new RectangleF(r.X + r.Width / 2, r.Y + _inputMargin, r.Width / 2 - _inputMargin * 2, r.Height - _inputMargin * 2);
            sf.Widget.Page      = page;
            sf.Widget.BackColor = Color.LightYellow;
            doc.AcroForm.Fields.Add(sf);
            drawField("DATE: ", fields3[1, 2], _Names.SupSignDate);

            // Done:
            return(doc);
        }
示例#19
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);
            }
        }
示例#20
0
        private RectangleF DrawTable(float[] widths, string[] captions, string[] samples, int rowCount)
        {
            System.Diagnostics.Debug.Assert(captions.Length == widths.Length && samples.Length == widths.Length);

            var ipSave = _ip;
            Pen p      = new Pen(Color.Black, 0.5f);

            var        g  = CurrGraphics;
            TextLayout tl = g.CreateTextLayout();

            tl.ParagraphAlignment               = ParagraphAlignment.Center;
            tl.TextAlignment                    = TextAlignment.Center;
            tl.DefaultFormat.Font               = TsNormal.Font;
            tl.DefaultFormat.FontSize           = TsNormal.FontSize;
            tl.DefaultFormat.GlyphAdvanceFactor = TsNormal.GlyphAdvanceFactor;
            tl.DefaultFormat.ForeColor          = Color.White;
            tl.WrapMode  = WrapMode.NoWrap;
            tl.MaxHeight = TableCaptionHeight;
            float totW = 0;

            for (int i = 0; i < widths.Length; ++i)
            {
                if (i == widths.Length - 1)
                {
                    widths[i] = CurrPage.Size.Width - MarginLeft - MarginRight - totW - 1;
                    totW     += 1;
                }
                totW += widths[i];
            }
            g.FillRectangle(new RectangleF(MarginLeft, _ip.Y, totW, TableCaptionHeight), Color.Black);
            var pt = new PointF(MarginLeft, _ip.Y);

            for (int i = 0; i < widths.Length; ++i)
            {
                tl.MaxWidth = widths[i];
                tl.Append(captions[i]);
                tl.PerformLayout(true);
                g.DrawTextLayout(tl, pt);
                pt.X = pt.X + widths[i];
                tl.Inlines.Clear();
            }
            tl.DefaultFormat.ForeColor = Color.Teal;
            tl.MaxHeight = TableSampleHeight;
            pt           = new PointF(MarginLeft, _ip.Y + TableCaptionHeight);
            for (int i = 0; i < widths.Length; ++i)
            {
                tl.MaxWidth = widths[i];
                tl.Append(samples[i]);
                tl.PerformLayout(true);
                g.DrawTextLayout(tl, pt);
                pt.X = pt.X + widths[i];
                tl.Inlines.Clear();
            }
            SetY(_ip.Y + TableCaptionHeight + TableSampleHeight, 0.5f);
            for (int row = 0; row < rowCount; ++row)
            {
                _ip.X = MarginLeft + 1;
                for (int i = 0; i < widths.Length; ++i)
                {
                    var cr = DrawTextbox(widths[i] - 1, true);
                    _ip.X = cr.Right + 1;
                }
                g.DrawLine(new PointF(MarginLeft, _ip.Y - 0.5f), new PointF(MarginLeft + totW, _ip.Y - 0.5f), p);
                SetY(null, Textbox.Height + 1);
            }
            var totH = TableCaptionHeight + TableSampleHeight + (Textbox.Height + 1) * rowCount;

            _ip.X = MarginLeft + 0.5f;
            for (int i = 0; i < widths.Length - 1; ++i)
            {
                _ip.X += widths[i];
                g.DrawLine(new PointF(_ip.X, ipSave.Y), new PointF(_ip.X, ipSave.Y + totH), p);
            }

            var rect = new RectangleF(MarginLeft, ipSave.Y, totW, totH);

            g.DrawRectangle(rect, p);

            return(rect);
        }
示例#21
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;
            }
        }
示例#22
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);
        }
示例#23
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);
        }
示例#24
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);
        }
示例#25
0
        public void CreatePDF(Stream stream)
        {
            // Create a FontCollection instance:
            FontCollection fc = new FontCollection();

            // Populate it with fonts from the specified directory:
            fc.RegisterDirectory(Path.Combine("Resources", "Fonts"));

            // Generate a sample document using the font collection to provide fonts:
            var doc  = new GcPdfDocument();
            var page = doc.Pages.Add();
            var g    = page.Graphics;

            // For TextLayout/TextFormat to be able to use a font collection, it must be
            // associated with it like so:
            var tl = new TextLayout(g.Resolution)
            {
                FontCollection = fc
            };

            // Render some strings using the different fonts from our collection:
            var tf = new TextFormat()
            {
                FontName = "times new roman", FontSize = 16
            };

            tl.Append("Using FontCollection to manage fonts and render text\n\n", tf);
            tf.FontSize = 12;
            tl.Append("Text rendered using Times New Roman regular font. \n", tf);
            // Setting a font style (bold or italic) will tell the font collection
            // to search for a suitable font (if it is not found, emulation will be used):
            tf.FontItalic = true;
            tl.Append("Text rendered using Times New Roman italic font. \n", tf);
            // Text format is applied to a text run when the text is appended,
            // so we can re-use the same format, modifying its properties
            // to render differently formatted texts:
            tf.FontBold = true;
            tl.Append("Text rendered using Times New Roman bold italic font. \n", tf);
            tf.FontItalic = false;
            tl.Append("Text rendered using Times New Roman bold font. \n", tf);
            tf.FontName = "segoe ui";
            tl.Append("Text rendered using Segoe UI bold font. \n", tf);
            tf.FontBold = false;
            tl.Append("Text rendered using Segoe UI regular font. \n", tf);

            // Apply page settings to the page layout and render the page:
            tl.MaxWidth  = page.Size.Width;
            tl.MaxHeight = page.Size.Height;
            tl.MarginAll = 72;
            tl.PerformLayout(true);
            g.DrawTextLayout(tl, PointF.Empty);

            // If using GcGraphics.DrawString/MeasureString, this will allow the TextLayout
            // created internally by GcGraphics to find the specified fonts in the font collection:
            g.FontCollection = fc;

            // Use GcGraphics.DrawString to show that the font collection is also used
            // by the graphics once the FontCollection has been set on it:
            g.DrawString("Text rendered using Segoe UI bold, drawn by GcGraphics.DrawString() method.",
                         new TextFormat()
            {
                FontName = "segoe ui", FontBold = true, FontSize = 10
            },
                         new PointF(72, tl.ContentRectangle.Bottom + 12));

            // Done:
            doc.Save(stream);
        }
示例#26
0
        void Page2(GcPdfDocument doc)
        {
            var page = doc.Pages.Add();
            var g    = page.Graphics;
            var tl   = new TextLayout(g.Resolution)
            {
                FontCollection = _fc
            };
            var col0X    = 36;
            var colWidth = page.Size.Width / 3 - 40;
            var colGap   = 20;
            var vgap     = 10;
            var ser1Y    = 100;
            var ser2Y    = 72 * 6;
            var h        = 45;

            List <(string caption, List <string> points)> gcpdf = new List <(string, List <string>)>()
            {
                ("Advanced Text Handling", new List <string> {
                    "Standard PDF Fonts, Truetype Fonts, Open type Fonts, WOFF Fonts, system font loading, font embedding, fallback and linked fonts, EUDC fonts",
                    "Advanced text rendering features",
                    "Special character support",
                }),
                ("Cross-Platform, Cross-Framework compatibility", new List <string>
                {
                    ".NET Standard 2.0",
                    ".NET Core 2.0",
                    ".NET Framework",
                    "Mono",
                    "Xamarin iOS",
                    "VSTO-style API"
                }),
                ("Security", new List <string>
                {
                    "Encryption and decrpyption",
                    "User and owner passwords",
                    "AllowCopyContent, AllowEditAnnotations, AllowEditContent, AllowPrint",
                    "Digital Signatures"
                }),
                ("Annotations", new List <string>
                {
                    "Figures",
                    "Comments",
                    "Text",
                    "Signatures",
                    "Stamps",
                    "Modify, extract or delete annotations from existing PDFs"
                }),
                ("Fillable Form Fields", new List <string>
                {
                    "Textbox",
                    "Checkbox",
                    "Combobox",
                    "Listbox",
                    "Radio button",
                    "Push button",
                    "Signature field",
                    "Modify, extract or delete form fields from existing PDFs"
                }),
                ("Navigation", new List <string>
                {
                    "Outlines",
                    "Hyperlinks"
                }),
                ("Additional Features", new List <string>
                {
                    "50 barcodes and properties",
                    "Create PDF/A files",
                    "Maintain document history with document properties",
                    "Generate linearized PDFs for fast web view",
                    "Full image and graphic support on all platforms",
                    "Add and delete pages",
                    "Chage page sizes",
                    "Page orientation"
                }),
            };

            List <(string caption, List <string> points)> gcexcel = new List <(string, List <string>)>()
            {
                ("Fast and Efficient", new List <string>
                {
                    "Lightweight",
                    "Optimized for processing large Excel documents quickly"
                }),
                ("Cross-Platform, Cross-Framework compatibility", new List <string>
                {
                    ".NET Standard 2.0",
                    ".NET Core 2.0",
                    ".NET Framework",
                    "Mono",
                    "Xamarin.iOS",
                    "VSTO-style API",
                }),
                ("Data Visualization", new List <string>
                {
                    "Shapes and pictures",
                    "Slicers",
                    "Sparklines",
                    "Charts",
                }),
                ("Powerful Calculation Engine", new List <string>
                {
                    "450+ Excel functions",
                    "Calculate",
                    "Query",
                    "Generate",
                    "Sorting",
                    "Filtering",
                    "Grouping",
                }),
                ("Seamless Excel Compatibility", new List <string>
                {
                    "Import and export Excel files",
                    "Export to PDF",
                    "Encrypt files",
                    "Workbooks and worksheets",
                    "Cell range operations",
                    "Pivot and Excel tables",
                    "Data validation",
                    "Annotations",
                    "Comments",
                }),
                ("Conditional Formatting Rules", new List <string>
                {
                    "Cell value",
                    "Average",
                    "Color scale",
                    "Data bar",
                    "Icon sets",
                    "Top and Bottom",
                    "Unique",
                    "Expression",
                }),
                ("Flexible Themes And Components", new List <string>
                {
                    "Customizable themes",
                    "Configurable components",
                    "Summary data",
                    "Custom styles",
                    "Embedded drawing objects",
                    "Integrated calculation engine",
                }),
            };

            addHeader(45,
                      "GrapeCity Documents for PDF",
                      "This high-speed, feature-rich PDF document API for .NET Standard 2.0 gives you total " +
                      "control of your PDF documents, with no dependencies on Adobe Acrobat.Generate, " +
                      "edit, and store feature - rich PDF documents without compromising design or features.");

            PointF ipt = new PointF(col0X, ser1Y);

            foreach (var(caption, points) in gcpdf)
            {
                var rc = addList(ipt, caption, points.ToArray());
                if (rc.Bottom < ser2Y - 120)
                {
                    ipt = new PointF(rc.X, rc.Bottom + vgap);
                }
                else
                {
                    ipt = new PointF(rc.X + colWidth + colGap, ser1Y);
                }
            }

            addHeader(ser2Y,
                      "GrapeCity Documents for Excel",
                      "Generate high-performance Excel spreadsheets with no dependencies on Excel! " +
                      "Generate, convert, calculate, format, and parse spreadsheets in any app.");

            var topY = ser2Y + h + 10;

            ipt = new PointF(col0X, topY);
            foreach (var(caption, points) in gcexcel)
            {
                var rc = addList(ipt, caption, points.ToArray());
                if (rc.Bottom < page.Size.Height - 100)
                {
                    ipt = new PointF(rc.X, rc.Bottom + vgap);
                }
                else
                {
                    ipt = new PointF(rc.X + colWidth + colGap, topY);
                }
            }

            var hdrRc = new RectangleF(28, 0, page.Size.Width - 28 * 2, 36);

            g.FillRectangle(hdrRc, _darkGray);
            var w = hdrRc.Width / 7;

            string[] hdrs  = new string[] { "Create", "Load", "Edit", "Save", "Analyze" };
            var      hdrTf = new TextFormat()
            {
                FontName = "open sans", FontSize = 12, ForeColor = Color.White
            };
            var trc = new RectangleF(hdrRc.X + w, hdrRc.Y, w, hdrRc.Height);

            for (int i = 0; i < hdrs.Length; ++i)
            {
                g.DrawString(hdrs[i], hdrTf, trc, TextAlignment.Center, ParagraphAlignment.Center, false);
                if (i < hdrs.Length - 1)
                {
                    g.DrawLine(trc.Right, trc.Top + 12, trc.Right, trc.Bottom - 12, Color.White, 1);
                }
                trc.Offset(w, 0);
            }
            var ftrRc = new RectangleF(0, page.Size.Height - 36, page.Size.Width, 36);

            g.FillRectangle(ftrRc, _darkGray);
            var ftr0 = "GrapeCity.com";
            var ftr1 = "© 2018 GrapeCity, Inc.All rights reserved.All other product and brand names are trademarks and/or registered trademarks of their respective holders.";

            ftrRc.Inflate(-col0X, -5);
            hdrTf.FontSize = 12;
            g.DrawString(ftr0, hdrTf, ftrRc, TextAlignment.Leading, ParagraphAlignment.Near, false);
            hdrTf.FontSize = 6;
            g.DrawString(ftr1, hdrTf, ftrRc, TextAlignment.Leading, ParagraphAlignment.Far, false);
            ftrRc.Inflate(0, -5);
            g.DrawImage(GetImage(Path.Combine("Resources", "ImagesBis", "logo-GC-white.png")), ftrRc, null,
                        new ImageAlign()
            {
                AlignHorz = ImageAlignHorz.Right, AlignVert = ImageAlignVert.Center, BestFit = true
            });

            void addHeader(float y, string caption, string text)
            {
                var bluerc = new RectangleF(0, y, 28, h);

                g.FillRectangle(bluerc, _blue);
                var caprc = new RectangleF(bluerc.Right, y, 72 * 2.75f, h);

                g.FillRectangle(caprc, _lightGray);
                caprc.X      = col0X;
                caprc.Width -= col0X - bluerc.Width;
                g.DrawString(caption, new TextFormat()
                {
                    FontName = "open sans semibold", FontSize = 12
                }, caprc, TextAlignment.Leading, ParagraphAlignment.Center, false);
                var textrc = new RectangleF(caprc.Right, caprc.Top, page.Size.Width - caprc.Right, caprc.Height);

                textrc.Inflate(-10, 0);
                g.DrawString(text, new TextFormat()
                {
                    FontName = "open sans light", FontSize = 9
                }, textrc, TextAlignment.Leading, ParagraphAlignment.Center, true);
            }

            RectangleF addList(PointF pt, string caption, params string[] items)
            {
                var tf = new TextFormat()
                {
                    FontName = "open sans light", FontSize = 9
                };
                var ret = new RectangleF(pt, SizeF.Empty);

                tl.Clear();
                tl.MaxWidth = colWidth;
                tl.AppendLine(caption, new TextFormat()
                {
                    FontName = "open sans", FontBold = true, FontSize = 9
                });
                tl.PerformLayout(true);
                g.DrawTextLayout(tl, pt);
                ret.Width  = tl.ContentWidth;
                ret.Height = tl.ContentHeight;
                pt.Y      += ret.Height;
                tl.Clear();
                var itemPrefix = "\u2022  ";

                tl.FirstLineIndent = -g.MeasureStringWithTrailingWhitespace(itemPrefix, tf).Width;
                foreach (var item in items)
                {
                    tl.AppendLine(itemPrefix + item, tf);
                }
                tl.PerformLayout(true);
                g.DrawTextLayout(tl, pt);
                ret.Width   = Math.Max(ret.Width, tl.ContentWidth);
                ret.Height += tl.ContentHeight;
                return(ret);
            }
        }
示例#27
0
        private RectangleF DrawExchangesTable()
        {
            // This table has two special extra titles spanning two tolumns.
            // To achieve this, we:
            // - force the column titles in those 4 columns to print as '2nd paragraph',
            //   thus leaving an empty line for the span title;
            // - print the span titles here as a special case.
            float[] widths = new float[]
            {
                50,
                25,
                25,
                25,
                25,
                60,
                150,
                50,
                40,
                25,
                35,
                0
            };
            string[] captions = new string[]
            {
                "Item",
                "Style",
                "\r\n1st",
                "\r\n2nd",
                "Size",
                "Sleeve Length\r\n& Inseam",
                "Item Name",
                "\r\nCharacters",
                "\r\nStyle",
                "Qty.",
                "Price",
                "Total"
            };
            string[] samples = new string[]
            {
                "LH123456",
                "Plain",
                "Tan",
                "Olive",
                "8",
                "28",
                "Example Item Only",
                "Amanda",
                "Block",
                "1",
                "49.95",
                "49.95"
            };

            var cr = DrawTable(widths, captions, samples, 4);

            // print 2 spanning titles:
            var        g  = CurrGraphics;
            TextLayout tl = g.CreateTextLayout();

            tl.ParagraphAlignment               = ParagraphAlignment.Near;
            tl.TextAlignment                    = TextAlignment.Center;
            tl.DefaultFormat.Font               = TsNormal.Font;
            tl.DefaultFormat.FontSize           = TsNormal.FontSize;
            tl.DefaultFormat.GlyphAdvanceFactor = TsNormal.GlyphAdvanceFactor;
            tl.DefaultFormat.ForeColor          = Color.White;
            tl.WrapMode = WrapMode.NoWrap;
            // Color Choice
            var width = widths[2] + widths[3];

            tl.MaxWidth = width;
            tl.Append("Color Choice");
            tl.PerformLayout(true);
            var pt = new PointF(cr.Left + widths[0] + widths[1], cr.Top);

            g.DrawTextLayout(tl, pt);
            Pen pen = new Pen(Color.White, 0.5f);
            var pt1 = new PointF(pt.X + 0.5f, pt.Y + TableCaptionHeight / 2);
            var pt2 = new PointF(pt1.X + width, pt1.Y);

            g.DrawLine(pt1, pt2, pen);
            pt1 = new PointF(pt.X + widths[2] + 0.5f, pt.Y + TableCaptionHeight / 2);
            pt2 = new PointF(pt1.X, pt.Y + TableCaptionHeight);
            g.DrawLine(pt1, pt2, pen);
            pt1 = new PointF(pt.X + 0.5f, pt.Y);
            pt2 = new PointF(pt1.X, pt.Y + TableCaptionHeight);
            g.DrawLine(pt1, pt2, pen);
            pt1 = new PointF(pt.X + width + 0.5f, pt.Y);
            pt2 = new PointF(pt1.X, pt.Y + TableCaptionHeight);
            g.DrawLine(pt1, pt2, pen);

            // Monogramming
            width = widths[7] + widths[8];
            tl.Inlines.Clear();
            tl.MaxWidth = width;
            tl.Append("Monogramming");
            tl.PerformLayout(true);
            pt = new PointF(cr.Left + widths[0] + widths[1] + widths[2] + widths[3] + widths[4] + widths[5] + widths[6], cr.Top);
            g.DrawTextLayout(tl, pt);
            pt1 = new PointF(pt.X + 0.5f, pt.Y + TableCaptionHeight / 2);
            pt2 = new PointF(pt1.X + width, pt1.Y);
            g.DrawLine(pt1, pt2, pen);
            pt1 = new PointF(pt.X + widths[7] + 0.5f, pt.Y + TableCaptionHeight / 2);
            pt2 = new PointF(pt1.X, pt.Y + TableCaptionHeight);
            g.DrawLine(pt1, pt2, pen);
            pt1 = new PointF(pt.X + 0.5f, pt.Y);
            pt2 = new PointF(pt1.X, pt.Y + TableCaptionHeight);
            g.DrawLine(pt1, pt2, pen);
            pt1 = new PointF(pt.X + width + 0.5f, pt.Y);
            pt2 = new PointF(pt1.X, pt.Y + TableCaptionHeight);
            g.DrawLine(pt1, pt2, pen);

            return(cr);
        }
示例#28
0
        void Page1(GcPdfDocument doc)
        {
            var page = doc.Pages.Add();
            var g    = page.Graphics;
            var tl   = new TextLayout(g.Resolution)
            {
                FontCollection = _fc
            };

            var gclogo   = GetImage(Path.Combine("Resources", "ImagesBis", "gc-logo-100px.png"));
            var gclogoRc = new RectangleF(36, 0, 72 * 1.8f, 72);

            g.DrawImage(gclogo, gclogoRc, null,
                        new ImageAlign(ImageAlignHorz.Left, ImageAlignVert.Center, true, true, true, false, false), out RectangleF[] rcs);
            g.DrawLine(rcs[0].Right + 10, rcs[0].Top, rcs[0].Right + 10, rcs[0].Bottom, _darkGray, 1);

            tl.Clear();
            tl.ParagraphAlignment = ParagraphAlignment.Center;
            tl.MaxHeight          = gclogoRc.Height;
            tl.Append("Developer Solutions",
                      new TextFormat()
            {
                FontName = "open sans", FontSize = 16, ForeColor = _darkGray
            });
            tl.PerformLayout(true);
            g.DrawTextLayout(tl, new PointF(gclogoRc.Right + 20, gclogoRc.Y));

            var back       = GetImage(Path.Combine("Resources", "ImagesBis", "GCDocs-datasheet-sm.png"));
            var backRcClip = new RectangleF(0, 72, page.Size.Width, page.Size.Width - 72 * 1.75f);
            var backRc     = new RectangleF(-72, -72 * 4, page.Size.Width + 72 * 4, page.Size.Height + 72 * 4);

            g.DrawImage(back, backRc, backRcClip, ImageAlign.StretchImage);
            g.FillRectangle(new RectangleF(0, backRcClip.Bottom, page.Size.Width, page.Size.Height - backRcClip.Bottom), _lightGray);
            g.DrawLine(backRcClip.X, backRcClip.Bottom, backRcClip.Right, backRcClip.Bottom, Color.White, 1, null);
            g.DrawLine(backRcClip.X, backRcClip.Bottom + 1, backRcClip.Right, backRcClip.Bottom + 1, _darkGray, 1, null);

            var blueRc = new RectangleF(0, backRcClip.Y, page.Size.Width, 72 * 4);

            g.FillRectangle(blueRc, Color.FromArgb(220, _blue));

            blueRc.Inflate(0, -36);
            g.FillRectangle(new RectangleF(blueRc.Location, new SizeF(10, blueRc.Height)), Color.White);

            blueRc.Inflate(-36, 0);
            tl.Clear();
            tl.ParagraphAlignment = ParagraphAlignment.Near;
            tl.MaxWidth           = blueRc.Width;
            tl.MaxHeight          = blueRc.Height;
            tl.Append("NEW PRODUCT LINE",
                      new TextFormat()
            {
                FontName = "open sans semibold", FontSize = 20, ForeColor = Color.White
            });
            tl.PerformLayout(true);
            g.DrawTextLayout(tl, blueRc.Location);

            var midRc = new RectangleF(blueRc.X, blueRc.Y + tl.ContentHeight, blueRc.Width, blueRc.Height - tl.ContentHeight);

            tl.Clear();
            tl.ParagraphAlignment = ParagraphAlignment.Far;
            tl.Append(
                "Take total control of your digital documents with this NEW collection of ultra-fast, low-footprint document APIs for .NET Standard 2.0. These intuitive, extensible APIs " +
                "allow you to create, load, modify, and save Excel spreadsheets and PDF files in any .NET Standard 2.0 application",
                new TextFormat()
            {
                FontName = "open sans light", FontSize = 14, ForeColor = Color.White
            });
            tl.PerformLayout(true);
            g.DrawTextLayout(tl, blueRc.Location);

            midRc.Height -= tl.ContentHeight;
            midRc.Inflate(0, -20);

            var hex   = GetImage(Path.Combine("Resources", "ImagesBis", "gcd-hex-logo-white.png"));
            var hexRc = new RectangleF(midRc.Location, new SizeF(midRc.Height, midRc.Height));

            g.DrawImage(hex, hexRc, null, ImageAlign.StretchImage);

            tl.Clear();
            tl.ParagraphAlignment = ParagraphAlignment.Center;
            tl.MaxHeight          = midRc.Height;
            tl.Append("GrapeCity Documents",
                      new TextFormat()
            {
                FontName = "open sans semibold", FontSize = 26, ForeColor = Color.White
            });
            tl.PerformLayout(true);
            g.DrawTextLayout(tl, new PointF(midRc.X + midRc.Height + 10, midRc.Y));

            var pointRc = new RectangleF(0, backRcClip.Bottom, page.Size.Width / 2, (page.Size.Height - backRcClip.Bottom) / 2 - 12);

            tl.ParagraphAlignment = ParagraphAlignment.Near;
            tl.MaxWidth           = pointRc.Width;
            tl.MaxHeight          = pointRc.Height;
            tl.MarginLeft         = 80;
            tl.MarginTop          = 25;
            tl.MarginBottom       = 0;

            addPoint(GetImage(Path.Combine("Resources", "ImagesBis", "ico-hex-.NET.png")),
                     "Expand the reach of modern apps",
                     "With full support for .NET Standard 2.0, you can target multiple platforms, devices, and cloud with one code base.");

            pointRc.Offset(0, pointRc.Height);
            addPoint(GetImage(Path.Combine("Resources", "ImagesBis", "ico-hex-code.png")),
                     "Comprehensive, highly programmable",
                     "Do more with your Excel spreadsheets and PDFs: these APIs support Windows, Mac, Linux, and a wide variety of features for your documents.");

            pointRc.Offset(pointRc.Width, -pointRc.Height);
            tl.MarginRight = 30;
            addPoint(GetImage(Path.Combine("Resources", "ImagesBis", "ico-hex-speed.png")),
                     "High-speed, small footprint",
                     "The API architecture is designed to generate large, optimized documents, fast—while remaining lightweight and extensible.");

            pointRc.Offset(0, pointRc.Height);
            addPoint(GetImage(Path.Combine("Resources", "ImagesBis", "ico-hex-nodependences.png")),
                     "No dependencies",
                     "Generate and edit digital documents with no Acrobat or Excel dependencies.");

            g.FillRectangle(new RectangleF(0, page.Size.Height - 16, page.Size.Width, 16), _darkGray);

            drawCircle(new PointF(page.Size.Width - 160, backRcClip.Bottom - 105));

            void addPoint(IImage img, string caption, string text)
            {
                var imgRc = new RectangleF(pointRc.X + 20, pointRc.Y + tl.MarginTop, 48, 48);

                g.DrawImage(img, imgRc, null, new ImageAlign()
                {
                    AlignHorz = ImageAlignHorz.Center, AlignVert = ImageAlignVert.Center, BestFit = true
                });
                tl.Clear();
                tl.AppendLine(caption, new TextFormat()
                {
                    FontName = "open sans semibold", FontSize = 11
                });
                tl.Append(text, new TextFormat()
                {
                    FontName = "open sans light", FontSize = 11
                });
                tl.PerformLayout(true);
                if (!tl.ContentHeightFitsInBounds)
                {
                    throw new Exception("Unexpected: text overflow.");
                }
                g.DrawTextLayout(tl, pointRc.Location);
            }

            void drawCircle(PointF p)
            {
                float D     = 128;
                float angle = (float)(16 * Math.PI) / 180f;

                g.Transform =
                    Matrix3x2.CreateTranslation(-D / 2, -D / 2) *
                    Matrix3x2.CreateRotation(angle) *
                    Matrix3x2.CreateTranslation(p.X + D / 2, p.Y + D / 2);

                var r = new RectangleF(PointF.Empty, new SizeF(D, D));

                for (int i = 0; i < 3; ++i)
                {
                    g.FillEllipse(r, Color.FromArgb(30 + i * 10, _darkGray));
                    r.Inflate(-1, -1);
                }
                g.FillEllipse(r, _darkGray);
                r.Inflate(-1, -1);
                g.FillEllipse(r, Color.White);
                r.Inflate(-6, -6);
                g.FillEllipse(r, _darkGray);

                tl.Clear();
                tl.MaxHeight          = tl.MaxWidth = D;
                tl.MarginLeft         = tl.MarginRight = tl.MarginTop = tl.MarginBottom = 0;
                tl.TextAlignment      = TextAlignment.Center;
                tl.ParagraphAlignment = ParagraphAlignment.Center;
                tl.ParagraphSpacing   = -4;
                var tf = new TextFormat()
                {
                    FontName = "open sans light", FontSize = 18, ForeColor = Color.White
                };

                tl.Append("DEPLOY\nTO", tf);
                tl.Append(" AZURE\n", new TextFormat(tf)
                {
                    FontName = "open sans semibold"
                });
                tl.Append(" ");
                tl.PerformLayout(true);
                g.DrawTextLayout(tl, PointF.Empty);

                g.Transform = Matrix3x2.Identity;
            }
        }
示例#29
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);
        }
示例#30
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);
        }