TextLayout - Inconsistent behavior with Split and ObjectRects

Posted by: Alberto on 3 March 2021, 3:54 am EST

  • Posted 3 March 2021, 3:54 am EST

    Hello,

    I found an inconsistent behavior of the TextLayout, when Split is not used.
    When Split is used then it works as espected. The text is split to the remaining new TextLayout. See Page 1 and Page 4.
    When Split and ObjectRects are not used then the Text is drawed outside the LayoutRectangle (red) and the resulting ContentRectangle (green) is much bigger, till the end of the Page. See Page 2.
    When Split is not used but ObjectsRects is defined (without adding any Object), so it should have no effect at all, then the Text is not drawed ouside the LayoutRectangle but the ContentRectangle is still bigger than the LayoutRectangle. See Page 3.

    What is incorrect in my code?

    using System;

    namespace Messerli.LayouterOne.Infrastructure.BasicPdf.Test.BugReport
    {
    /// <summary>
    /// I found an inconsistent behavior of the TextLayout, when Split is not used.
    /// When Split is used then it works as espected.The text is split to the remaining new TextLayout.See Page 1 and Page 4.
    /// When Split and ObjectRects are not used then the Text is drawed outside the LayoutRectangle(red) and the
    /// resulting ContentRectangle(green) is much bigger, till the end of the Page.See Page 2.
    /// When Split is not used but ObjectsRects is defined(without adding any Object), so it should have no effect at all,
    /// then the Text is not drawed ouside the LayoutRectangle but the ContentRectangle is still bigger than the LayoutRectangle. See Page 3.
    /// </summary>
    public class TextLayoutOutsideRectangle
    {
    public const float Resolution = 72f;
    public const float Point = 1f;
    public const float Inch = Point * Resolution;
    public const float CM = Inch / 2.54f;
    public const float MM = CM / 10;

    GrapeCity.Documents.Pdf.GcPdfDocument Document;
    GrapeCity.Documents.Text.TextFormat TextFormat1;
    GrapeCity.Documents.Pdf.GcPdfGraphics Graphics;
    GrapeCity.Documents.Pdf.Page Page;
    System.Drawing.SizeF PageSize;
    System.Drawing.RectangleF TextRect;

    public static void ShowIssue(Object doc)
    {
    new TextLayoutOutsideRectangle((GrapeCity.Documents.Pdf.GcPdfDocument)doc).DrawPages();
    }

    TextLayoutOutsideRectangle(GrapeCity.Documents.Pdf.GcPdfDocument doc)
    {
    Document = doc;
    TextFormat1 = new GrapeCity.Documents.Text.TextFormat()
    {
    Font = GrapeCity.Documents.Text.FontCollection.SystemFonts.FindFamilyName("Segoe UI", false, true),
    FontSize = 48,
    ForeColor = System.Drawing.Color.Black,
    UseTypoMetrics = true, // cross platform independent
    EnableFontHinting = true, // is default true
    FontSizeInGraphicUnits = false, // typographic units
    };
    }

    void AddPage()
    {
    Page = Document.NewPage();
    Page.PaperKind = GrapeCity.Documents.Common.PaperKind.A4;
    Page.Landscape = false;
    PageSize = Page.GetRenderSize(Resolution, Resolution);
    Graphics = Page.Graphics;
    Graphics.Resolution = Resolution;
    TextRect = new System.Drawing.RectangleF(0, 0, PageSize.Width, PageSize.Height);
    TextRect.Inflate(-2.5f * CM, -2.7f * CM);
    Graphics.DrawRectangle(TextRect, new GrapeCity.Documents.Drawing.Pen(System.Drawing.Color.Red, 2f * MM));
    }

    void DrawPage(bool useSplit, bool useObjectRect)
    {
    AddPage();

    // create TextLayout
    var rect = TextRect;
    var text = new GrapeCity.Documents.Text.TextLayout(Graphics.Resolution)
    {
    MarginLeft = rect.X,
    MarginTop = rect.Y,
    MarginRight = 0,
    MarginBottom = 0,
    MaxWidth = rect.Right,
    MaxHeight = rect.Bottom,
    EllipsisCharCode = '.',
    ParagraphAlignment = GrapeCity.Documents.Text.ParagraphAlignment.Near,
    TextAlignment = GrapeCity.Documents.Text.TextAlignment.Leading,
    //AlignmentDelayToSplit = useSplit,
    //LastLineIsEndOfParagraph = true,
    //HonorLastLineSpacing = true,
    //AllowOverhangingWords = true,
    //TrimmingGranularity = GrapeCity.Documents.Text.TrimmingGranularity.Character,
    };
    string lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer sodales iaculis dictum. Nam in porta dolor. Pellentesque neque orci, maximus in accumsan eget, tincidunt nec eros. Aenean vitae nisi vel purus maximus dignissim. Proin sagittis elementum pharetra. Mauris eu tellus pretium, luctus dui eget, pharetra velit. Nunc fermentum tortor ante, eget sodales sapien imperdiet ut.";
    text.Append(string.Format("Page: {0}, Split: {1}, ObjectRect: {2}. ", Page.Index+1, useSplit, useObjectRect) + lorem, TextFormat1);
    text.RecalculateGlyphs();

    // Add Optional ObjectRectangles
    if (useObjectRect)
    {
    // add object list. But without objects. It should have no effect.
    text.ObjectRects = new System.Collections.Generic.List<GrapeCity.Documents.Text.ObjectRect>();
    }
    // Perform Layout
    text.PerformLayout(false);
    // Split if requested but ignore the resulting text.
    if (useSplit)
    {
    text.Split(new GrapeCity.Documents.Text.TextSplitOptions(), out GrapeCity.Documents.Text.TextLayout _);
    }
    // Draw TextLayout
    Graphics.DrawTextLayout(text, System.Drawing.PointF.Empty);
    // Draw Rectangle of the resulting ContentRectangle
    Graphics.DrawRectangle(text.ContentRectangle, new GrapeCity.Documents.Drawing.Pen(System.Drawing.Color.LightGreen, 1f * MM));
    }

    void DrawPages()
    {
    DrawPage(true, false);
    DrawPage(false, false);
    DrawPage(false, true);
    DrawPage(true, true);
    }
    }
    }


    Thank You
    Alberto

  • Replied 3 March 2021, 4:19 am EST

    To test the code:

                var pdf = new GrapeCity.Documents.Pdf.GcPdfDocument();
    TextLayoutOutsideRectangle.ShowIssue(pdf);
    pdf.Save("test.pdf");
    System.Diagnostics.Process.Start("explorer", "test.pdf");


    Is this behaviour a Bug or is it by Design?
    How can I not use the Split feature to draw a simple text, getting a correct ContentRectangle and avoiding that the text is drawed outside the LayoutRectangle?
  • Replied 3 March 2021, 4:31 am EST

    Using always Split to avoid this issue, has the limitation that ParagraphAlignment is forced to be GrapeCity.Documents.Text.ParagraphAlignment.Near. It is not possible to align the Text Vertically in the Center or at the Bottom (Far or Justified or Distributed). Well this limitation is there also if ObjectRects is used...
  • Replied 3 March 2021, 11:42 pm EST

    Another inconsistent behaviour. If I use Softhypen, Split and ObjectRect then the ContentRectangle is incorrect, it uses the whole LayoutRectangle instead of the drawed area. If ObjectRect is not used then the ContentRectangle is correct.
    Page 1 correct.
    Page 4 incorrect.

    string lorem = "Lorem ip\x00ADsum dolor sit amet, consectetur adipiscing elit. Inte\x00ADger so\u00ADdales iaculis dic\x00ADtum. Nam in porta dolor. Pel\x00ADlentesque neque orci, maximus in accumsan eget, tin\x00ADcidunt nec eros. Aenean vitae nisi vel purus maximus di\x00ADgnis\x00ADsim. Proin sag\x00ADit\x00ADtis elementum pharetra. Mauris eu tellus pretium, luctus dui eget, pharetra velit. Nunc fermentum tortor ante, eget sodales sapien imperdiet ut.";


  • Replied 4 March 2021, 10:00 pm EST

    Hello,

    We are discussing this with the developers and will get back to you with the updates soon.
    [Internal Tracking ID: 2834]
    Regards,
    Prabhat Sharma.
  • Replied 8 March 2021, 9:32 pm EST

    Thank you.

    To summarize the only correct behaviour is Page 1, with Split=True, ObjectRect=false. The ContentRectangle equals to the printed area of the text.

    Page 2: Split=false, ObjectRect=false --> It prints outside the LayoutRectangle and ContentRectangle is till the end of the page.

    Page 3: Split=false, ObjetRect=true --> It prints correctly but ContentRectangle ist wrong, bigger than LayoutRectangle but smaller than the end of the page.

    Page 4: Split=True, ObjectRect=true --> It prints correctly but ContentRectangle ist wrong, it equals to LayoutRectangle.
  • Replied 10 March 2021, 9:11 pm EST

    Hi,

    As Per the developers, inconsistencies are between the two pages with Split==false. This is because the text does not fit in the provided bounds. If after TextLayout.PerformLayout TextLayout.ContentHeightFitsInBounds is false (i.e. not all text fits in the provided bounds), your code must call TextLayout.Split, otherwise, the results of the PerformLayout call are basically undefined. This is by design due to performance considerations (the Split parameters may affect the layout of the portion that fits on the 1st page).

    Regards,
    Prabhat Sharma.
  • Replied 30 March 2021, 11:35 pm EST

    Hello,
    I saw only now the answer, didn't got an e-mail notification.

    I understand. If TextLayout.ContentHeight/WidthFitsInBounds is false then the results of the PerformLayout call is undefined behaviour.
    Then I suppose the correct sequence is this here:
    text.PerformLayout(false);
    if (!text.ContentWidthFitsInBounds || !text.ContentHeightFitsInBounds) {
    text.Split(new GrapeCity.Documents.Text.TextSplitOptions(), out text2);
    text.PerformLayout(false);
    }
    Graphics.DrawTextLayout(text, System.Drawing.PointF.Empty);

    If the text doesn't fit then split is called and then again PerformLayout. Only after that I can call DrawTextLayout else the Text could be written outside the Bounds and the results of PerformLayout is incorrect.
    Is that correct?
    It should be written somewhere in the Documentation.

    In this case there is still an issue if Softhypen is used. With Softhypen active, Split=true and ObjectRect=true, the resulting ContentRect is the whole Bounds instead of the printed area. It is wrong.

    If ObjectRect=false then the resulting ContentRect is the expected correct one.
    See the last two examples Page 1 and Page 4 where both Split=true.

    Thank you
  • Replied 31 March 2021, 7:06 pm EST

    Hello,

    We are passing your comments to the developers and will let you know as soon as we get the update from their end.

    Regards,
    Prabhat Sharma.
Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels