Truncating nvgText to 2 lines?

In my groovebox module, I have this code to draw the track labels:

  void draw_track_label(std::string label, NVGcontext *vg)
  {
    float text_left_margin = 6;

    nvgFontSize(vg, 10);
    nvgTextLetterSpacing(vg, 0);
    nvgFillColor(vg, nvgRGBA(255, 215, 20, 0xff));
    nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
    float wrap_at = 130.0;

    float bounds[4];
    nvgTextBoxBounds(vg, text_left_margin, 10, wrap_at, label.c_str(), NULL, bounds);

    float textHeight = bounds[3];
    nvgTextBox(vg, text_left_margin, (box.size.y / 2.0f) - (textHeight / 2.0f) + 8, wrap_at, label.c_str(), NULL);
  }

This code does a reasonably good job of vertically centering the track names:

But, as you can see, the last track starts to get a bit messy. Once the sample name is too long, it starts to overflow past the allotted space.

Is there any way to say, “Dear nvg, please truncate the text so that only the first two lines appear.”?

Not a solution for your problem, but if you use a non-proportional font where all letters have the same width, it’s quite easy to truncate the text to the amount of letters that only fill 2 lines.

look at nvgTextBreakLines. It fills an array with details of where it split the text into lines.

1 Like

I think this is the procedure you want. I’ve not tested any of this.

declare a char* end which is null

Call nvgTextBreakLines passing in an array of 3 NVGtextRow structs and a maxRows value of 3. If the return value is greater than 1 then

end = rows[1].end

pass that end variable as the last parameter into your nvgTextBox call.

NB I am assuming here that the value of label.c_str() is stable between calls so long as you don’t modify the label object. I don’t know std::string well enough to be sure of that.

edit: Apparently this c style string representation is guaranteed to remain valid while the std::string is not modified.

Wow! That worked David! :trophy: Thanks so much! :raised_hands:

Here’s my final code to draw a label that’s up to 2 lines of text and vertically centered:

  void draw_track_label(std::string label, NVGcontext *vg)
  {
    float text_left_margin = 6;

    nvgFontSize(vg, 10);
    nvgTextLetterSpacing(vg, 0);
    nvgFillColor(vg, nvgRGBA(255, 215, 20, 0xff));
    nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
    float wrap_at = 130.0; // width of the bounding box

    const char *end = NULL;
    NVGtextRow rows[3];
    unsigned int max_rows = 3;
    unsigned int number_of_lines = nvgTextBreakLines(vg, label.c_str(), NULL, wrap_at, rows, max_rows);

    if(number_of_lines > 1) end = rows[1].end;

    float bounds[4];
    nvgTextBoxBounds(vg, text_left_margin, 10, wrap_at, label.c_str(), end, bounds);

    float textHeight = bounds[3];
    nvgTextBox(vg, text_left_margin, (box.size.y / 2.0f) - (textHeight / 2.0f) + 8, wrap_at, label.c_str(), end);
  }

Here’s what it looks like in action:

4 Likes