Text Trimming

Posted by: s.mcchesney on 20 June 2018, 4:58 am EST

  • Posted 20 June 2018, 4:58 am EST

    I am working through your library (we are in the process of purchasing it), and while I believe I know the answer to this question, I thought I would ask just in case.

    Is there any way to have a
    TextLayout
    object implement text trimming (i.e. if the provided text is too large for the layout's bounding rectangle, chop the text and add an ellipsis on the end)?

    Thanks!

    - Scott McChesney
  • Replied 20 June 2018, 10:19 am EST

    We actually have this feature in our plans but did not have the time to add it, it will be in the next update. In the meantime though you can relatively easily do it in user code, attached is a complete sample that demonstrates how this can be done. The relevant code is as follows:


    // ...
    var doc = new GcPdfDocument();
    var g = doc.Pages.Insert(0).Graphics;
    const float maxContentWidth = 400f;

    var text = "some long text that won't fit in a single line";
    var fmt = new TextFormat
    {
    FontName = "Segoe UI",
    FontSize = 20
    };
    var tl = new TextLayout();
    tl.Append(text, fmt);
    tl.PerformLayout(true);
    // If the text does not fit, trim it:
    if (tl.ContentWidth > maxContentWidth)
    TrimToWidth(text, fmt, tl, maxContentWidth);

    g.DrawTextLayout(tl, new PointF(100, 100));
    // ...
    }

    static void TrimToWidth(string text, TextFormat fmt, TextLayout tl, float width)
    {
    var runs = tl.Lines[0].GlyphRuns;
    int len = 0;
    for (int i = runs.Length - 1; i >= 0; i--)
    {
    var run = runs[i];
    if (run.Offset < width)
    {
    float xStop = (width - run.Offset) / run.FontUnitsToSize;
    var gi = run.FirstGlyph;
    for (int j = 0; j < run.GlyphCount; j++)
    {
    xStop -= gi.GlyphAdvance;
    if (xStop < 0)
    {
    break;
    }
    gi = gi.NextGlyph;
    }
    len = gi.CodePointIndex;
    break;
    }
    }
    var sb = new StringBuilder(text.Substring(0, len));
    if (len == 0)
    {
    sb.Append(' ');
    len = 1;
    }
    do
    {
    while (len > 1 && Char.IsWhiteSpace(sb[len - 2]))
    {
    len -= 1;
    }
    sb.Length = len;
    sb[len - 1] = '\u2026'; // Unicode ellipsis symbol

    tl.Clear();
    tl.Append(sb.ToString(), fmt);
    tl.PerformLayout(true);
    if (tl.ContentWidth <= width)
    {
    break;
    }
    len -= 1;
    } while (len > 1);
    }


    Let me know whether this helps.

    Ellipsis.zip


  • Replied 21 June 2018, 2:30 am EST

    This works like a charm. I look forward to this being integrated into the library.

    Thank you very much!

    - Scott McChesney
  • Marked as Answer

    Replied 21 June 2018, 3:38 am EST

    Great, thanks for the heads up!
  • Replied 6 October 2018, 8:35 am EST

    Note that in v2 we now have text trimming built into TextLayout:

    http://demos.componentone.com/gcdocs/gcpdf#TextTrimming

    Thanks.
Need extra support?

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

Learn More

Forum Channels