Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NanoVG string width #627

Open
nextdayy opened this issue Apr 21, 2022 · 13 comments
Open

NanoVG string width #627

nextdayy opened this issue Apr 21, 2022 · 13 comments

Comments

@nextdayy
Copy link

Hi. I am currently trying to calculate the width of my text using nvgTextBounds, however it seems to only work with a font size of 12px. I have tried to divide the result by 12 then multiply it by the target font size, yet this still leads to small deviations especially after a lot of characters.

Is there any other way to get string width, or how can I improve my current method?

Can anyone help me?

@memononen
Copy link
Owner

It should work on all sizes. Can you show the code you use and explain more in detail what you'd expect to get.

Also worth taking a look at drawParagraph() in demo.c.

@nextdayy
Copy link
Author

hi, thanks for your reply!

here is my code (note this is the LWJGL bind, in java):
public static float getTextWidth(long vg, String text, float fontSize) {
float[] bounds = new float[4];
return (nvgTextBounds(vg, 0, 0, text, bounds) / 12) * fontSize;
}

I'll be sure to look over that, thanks!

@memononen
Copy link
Owner

The font settings affect the text bounds, you will need to set them before you measure.

Also, what values you get and what do you expect? How to you use the value and which way it does not match?

@nextdayy
Copy link
Author

Hi, thanks for your help! Just setting the font size using the nvg function before made it calculate correctly.
I have a couple more things as well that I have found, here is the first one:

  • I have been trying for ages to parse then draw an SVG. I have got the SVG to parse correctly, however I can't draw it properly. (note this is java bind) It uses the same code in your nanovg library example, translated to java, except one line (where I believe it goes wrong) which I couldn't understand. the line is: float* p = &path->pts[i*2];
    here is my code:
public static void drawSVGImage(long vg, String fileName, float x, float y, float width, float height) {
        if (ImageLoader.INSTANCE.loadSVGImage(fileName)) {
            try {
                NSVGImage image = ImageLoader.INSTANCE.getSVG(fileName);
                NSVGShape shape;
                NSVGPath path;
                int i;
                for (shape = image.shapes(); shape != null; shape.next()) {
                    //if ((shape.flags() == NSVG_FLAGS_VISIBLE)) {
                    //    continue;
                    //}

                    nvgFillColor(vg, color(vg, shape.fill().color()));
                    nvgStrokeColor(vg, color(vg, shape.stroke().color()));
                    nvgStrokeWidth(vg, shape.strokeWidth());

                    for (path = shape.paths(); path != null; path.next()) {
                        nvgBeginPath(vg);
                        FloatBuffer points = path.pts();
                        nvgMoveTo(vg, points.get(0), points.get(1));
                        for (i = 0; i < path.npts() - 1; i += 3) {
                            float[] p = new float[10];
                            for (int j = 0; j < i * 2 + 3; j++) {           // THIS WONT WORK
                                p[j] = points.get(j);
                                System.out.println(j + " " + p[j]);
                            }
                            nvgBezierTo(vg, p[2], p[3], p[4], p[5], p[6], p[7]);
                        }
                        if (path.closed() == 1) {
                            nvgLineTo(vg, points.get(0), points.get(1));
                        }
                        nvgStroke(vg);
                    }


                }
            } catch (Exception e ) {
                //e.printStackTrace();
            }
        }
    }```

@memononen
Copy link
Owner

Sneaky! You should not make me do your debugging ;)

for (i = 1; i < path.npts() - 1; i += 3) {
	int b = i * 2;
	nvgBezierTo(vg, points.get(b), points.get(b+1), points.get(b+2), points.get(b+3), points.get(b+4), points.get(b+5));
}

The loop starts from 1 since you submitted the first point already.

The data for the splines are stored like this:

Px,Py, CP0x,CP0y, CP1x,CP1y, Px,Py, CP0x,CP0y, CP1x,CP1y, ...

And nvgBezierTo expects:

CP0x,CP0y, CP1x,CP1y, Px,Py

When drawing the first point of the bezier is the previous draw location (i.e. moveTo, or last point of previously drawn path).

@nextdayy
Copy link
Author

hi, thanks for your help! I tried this earlier, but still nothing :(
At least instead of crashing it just hangs now! Do you have any idea what would be wrong with my code, or should I just give up and raster it? I have been wanting to draw without rastering it because of performance reasons, or is that actually a problem?

Thanks you so much for your help :)

@memononen
Copy link
Owner

If the svg has a lot of small details, then the AA in nanovg wont work. Rasterization is safe bet.

@nextdayy
Copy link
Author

Okay, thanks. Is there any major performance impact to rasterization? I haven't been wanting to use it because I was concerned about lag when the GUI opens, and high memory usage. Is this actually an issue?

@memononen
Copy link
Owner

It should not be a problem, but you should of course profile it if you're concerned.

@nextdayy
Copy link
Author

nextdayy commented May 5, 2022

hi! thanks for all your help, we decided in the end to just use PNGs!
back to my original point, it seems after much troubleshooting that nanoVG renders text at the wrong size compared to other programs (figma).

here is the font rendered at 12px, with a rectangle behind it demonstrating the expected height of the font,
image

however the expected height is only reached at a size of 14px:
image

is this to do with how NanoVG calculates ascends and descend of the font? is there any way to fix this, or do I just have to manually set all the font sizes to be slightly larger?
thanks so much for your help :)

@mulle-nat
Copy link
Contributor

AFAIK Font characters are designed so you can place consecutive lines below each other and that there is enough vertical spacing between the characters. So some space is to be expected.

@nextdayy
Copy link
Author

nextdayy commented May 6, 2022

Okay, yet why would this differ from many other programs, such as figma? It appears nanoVG calculates the font size as the maximum ascend and descend height scaled to the font size you specified, yet many other programs use the font size as the standard/baseline height, and the ascend/descend extend beyond that.

Is there any way to change this in NanoVG?

@Laxystem
Copy link

@nxtdaydelivery @memononen thank you very much! Sorry for the ping, but you absolutely saved me! I'm working on an actually readable debug screen in Kotlin, and just couldn't find out how to have both bold and regular text on the same line. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants