is there any fancy “label” class within VCV Rack world where, given whatever font I want to write and any text:
I can set a fixed width/height for the box where the text will reside
Due to these sizes, align the inner text horizontally (left, right, center) and vertically (center, top, bottom)
Coming from the “web” world, these are the basics. I found hard do it on NanoVG.
Due to the size of the texts, the font and its size, I need to calculate manually the position.
Maybe there’s an already build-in class that do it automatically?
Thanks
Disclaimer: I am still very out of practice, so please forgive me if I ask things that may be obvious to others.
I’m curious as I have a custom label class derived from LedDisplay. My font of choice is proportional. Presently I mess around changing coords to get labels to line up with components, would be nice to have them centred automatically but not sure how to go about it with nvg etc I also have a ScribbleStrip class derived from LedDisplayTextField, same applies there.
I expect there are text metric functions somewhere to allow me to measure the width of a proportional font string and adjust coords accordingly, I don’t know and if I did I’m not sure where I’d need to put them.
the documentation for nanovg seems to be a little sparse, and tutorials out in the wild seem to be fairly rare, but there is documentation in the header file itself:
that should give you width of a text string. that’s the text section, and there are functions for multi-line management, etc.
not the best pointer, but it should be enough to get the math to work.
If you want an example of using nvgTextBounds I used it to make a function which draws a label with a rule at the bottom on either side sized to the size of the string.
that’s the function and here’s a UI where I called it 3 times with the resulting screen.
If anyone who actually knows what they’re doing fancies giving that a quick sanity check I’d be grateful for any suggestions / improvements / pointing out of cluelessness.
Unfortunately, this approch doesn’t work with every font
I’ve tried for example Segment7, and it seems that render it remove additional space in the top of the target box.
With DejaVuSansMono, nvgTextBounds returns height of 20px for example, and the font (16 pixels) is rendered 2 pixel from above, correctly (2+16+2 = 20); but with Segment7 the space is 0 (so 0 + 16 != 20), resulting in a font “moved” around the top.
Is there a way to also retrieve the “padding” between the the nvgTextBounds and actually where the font render? So I can compensate…
So, I can now center my custom labels, whoopee! Trying to do the same for my custom scribble strips (derived from LedDisplayTextField). I can get them centered easily enough, however the cursor no longer behaves as expected, I have to click several characters to the right of where I’d like the cursor, I’m not sure how to go about fixing that.
void draw(const DrawArgs &args) override {
if(cursor > numChars) {
text.resize(numChars);
cursor = numChars;
selection = numChars;
}
//nvgScissor(args.vg, RECT_ARGS(args.clipBox));
if (font->handle >= 0) {
bndSetFont(font->handle);
float bounds[4];
nvgTextBounds(args.vg, 0.0f, 0.0f, text.c_str(), NULL, bounds);
float textWidth = bounds[2];
// If we subtract textWidth / 2 from bndIconLabelCaret parameter 2 textOffset.x we get dynamically centered strips
// however the mouse doesn't position the cursor accordingly
NVGcolor highlightColor = color;
highlightColor.a = 0.5;
int begin = std::min(cursor, selection);
int end = (this == APP->event->selectedWidget) ? std::max(cursor, selection) : -1;
bndIconLabelCaret(args.vg, textOffset.x, textOffset.y,
box.size.x - 2*textOffset.x, box.size.y - 2*textOffset.y,
-1, color, textSize, text.c_str(), highlightColor, begin, end);
bndSetFont(APP->window->uiFont->handle);
}
//nvgResetScissor(args.vg);
}
Sure, but which code calculate the margin rendered for a fixed font? As I said above, it seems you cannot operate on “segment” the same way you do with other font, the space is different. It messes the whole calculation…
I’m really struggling to understand how knowing the exact size of the container, as well as the exact size of what you are trying to place inside of that container, makes math hard.
as I posted above, you can get the exact size of the string you are trying to render from nanovg:
as an array of floating point values, that gives you the starting X position, the ending X position, the starting Y position, and the ending Y position.
am I just missing something here?
if that math doesn’t work for you, you can go even more low level by working with the glyph positions:
you’re placing a known box, inside of another known box, relative to the position of that box.