Poor image quality of SvgSwitch containing text

My Rhythm Explorer module uses SvgSwitch widgets to create square buttons with text. The static text varies for each frame of the switch. The text started out as a font that was then converted to paths, just like with the faceplate svg.

In the browser, all looks great. Everything scales nicely (at least as nicely as the underlying faceplate svg anyway). Here is a screen capture of the browser at 71%:


But in a patch, the SvgSwitch text looks horrible as I reduce the scale - it becomes very blocky and hard to read. Here is the same module at 71% in a patch:


Does anyone have any idea what I could do to improve the image within the patch?

I suppose I could change the design to dynamically draw the text each time the switch changes state. But I prefer to keep the SvgSwitch with static images for now.

This is a case where I may file a bug report with VCV, depending on the response I get to this post.

That looks to me like you have a frame buffer somewhere which didn’t invalidate when zoom changed or is sized wrong and is scaling up. Without knowing your code at all that’s maybe where I would look?

I’m not doing anything odd or fancy.

In the module widget I define a struct derived from SvgSwitch

  struct ModeSwitch : app::SvgSwitch {
    ModeSwitch() {
      shadow->opacity = 0.0;

And in the constructor I create some params with code like the following:

addParam(createParamCentered<ModeSwitch>(Vec(x,y), module, RhythmExplorer::MODE_CHANNEL_PARAM + si));

Beyond that I just let VCV to its thing. I don’t have any overrides or other special code to manipulate the behavior of the switch.

Well, that is not totally true - I do mess around with the SwitchQuantity a bit within the module. I have a button that locks the state of the SvgSwitches by setting the min and max values to the current value. So I have to override the getDisplayValueString() to display the correct label for the currently selected option when you hover over the switch or activate its context menu. But the visual scaling problems have always been present, long before I added the lock feature. So that bit of code should be irrelevant.

I am pretty sure the frame buffer is getting refreshed at the correct time. As I change the zoom setting, the display starts out looking one way at a particular size, and then after a brief pause it snaps to looking like my screen shot, without changing overall size. The text suddenly becomes bolder and blockier. So the switch image is definitely getting updated.

I don’t know what you mean by “sized wrong and is scaling up”, or what I would look for.

I find it odd that the browser scales perfectly fine, but the module in the patch does not.

hmm yeah. and no ‘step’ overrides where you forget to call the parent step or anything?

if neither of those then I have no idea!

My module widget has a step override that checks if the plugin default theme has changed, and reloads a new panel svg when appropriate. But I call Widget::step(); at the end, so all should be good. If it weren’t, I imagine a hell-of-a-lot else would be going wrong. And here again, the scaling problem existed long before I put the code in for user selectable default themes.

I would try another font. As the ‘l’ in this font seems to be one pixel even at 140% zoom. May be a bold face does better.

I might explore that, but I don’t think that will help. The text looks just fine at 71% within the browser. But within a patch it does not look good. I expect the result would be consistent if the problem is the font.

it’s odd - they look the same as other text on my system. I have a 4k monitor, so things run at double resolution (like on a mac), but I took this screen capture at 38% to compensate. Everything seems equally blocky to me. I got no explanation. Different graphics card?

btw, I get a new home computer about every 10 years. Two years ago was my lucky year. VCV looks a ton better on a retina/4k monitor.


1 Like

Here’s 71% on my machine:

1 Like

Very interesting, thanks. That 38% image does look perfectly fine - not at all like my experience.

I have a similar problem in Meander that I haven’t tried to understand, but is probably worth sharing here. My panel is purely procedural at runtime and PNG based in the browser. Thus, all of my panel text is NVG based.Two things happen.

  1. The font rendering changes dramatically, dependent on zoom.This is mostly text positioning and sizing. Text that fits in the available space at one zoom may not at another.

  2. Dynamic text such as my melodic arpeggiator last note played display at the top of the module gets thicker and darker with each screen update such that if the same arp note is being played several times in succession on different “beats”, the text gets thicker and bolder with each repeat of the note. I suspect that I am not clearing the panel area between displays or that I am somehow changing the font stroke width incrementally with each render. I have also considered that this could be an artifact of how the NVG text render does alpha blending. I’ve tried to capture this but can’t seem to get it.

I doubt this is any use, but I mention it anyway.

1 - Yes, non linear scaling of fonts (true rendered text) is a widespread and very irritating, but separate issue. It plagues all the notes type modules that I have tried (text notes, not musical), as well as the Stoermelder GLUE labeling module.

2 - That is weird. Perhaps related, perhaps not. One key difference is you are actually rendering text, whereas the SvgSwitch relies on svg files where the text has been converted into paths. So no dynamic font rendering in my case. In theory the vector graphics behind the pathified text should scale very well. It does do well with the panel, but on my machine it does not scale well with the SvgSwitch.

But for Squinky it seems to work well, so maybe graphics card and/or drivers play into this somehow.

1 Like

Yes, maybe type hinting is responsible. (an active mechanism in the font to change the bezier points as the type size shrinks, to aid clarity of drawing).

This is essential, as the aliasing code does a blend with the background, so if it’s not the background, but say text coloured, the alias blend will go more towards the font colour.

1 Like

But even if hardware can make a difference, the fact that pathified text on the panel svg scales well but does not scale well within a SvgSwitch (for me anyway) implies that there is a fundamental difference in how the panel and SvgSwitch images are rendered within VCV Rack.

I have submitted an enquiry to VCV Support

1 Like

Yep. I use the SVG file only for panel size and color. The panel image should be cleared automatically on each frame as I have to totally recreate my procedural panel each frame. So, it is not clear how the src/dst alpha blending of text to panel persists between frames. But, I’m trying to trace it out to better understand it.

Yeah, my problem is that I was actually drawing the text multiple times per frame, so the blending with the panel graphics happened multiple time.

So, this is in no way related to this current topic.

1 Like