stb_truetype计算字符串的尺寸

时间:2016-08-24 17:31:51

标签: opengl true-type-fonts

我使用stb_truetype在OpenGL上下文中渲染TrueType字体。

有没有简单的方法在呈现字符串之前预先确定字符串的高度和宽度?

2 个答案:

答案 0 :(得分:1)

虽然@Tophandour的答案给出了宽度的良好近似值,但stb提供了更准确地执行此操作的功能。这是我现在在Java中使用的解决方案:

public float getWidth(String text) {
    float length = 0f;
    for (int i = 0; i < text.length(); i++) {
        IntBuffer advancewidth = BufferUtils.createIntBuffer(1);
        IntBuffer leftsidebearing = BufferUtils.createIntBuffer(1);
        stbtt_GetCodepointHMetrics(info, (int)text.charAt(i), advancewidth, leftsidebearing);
        length += advancewidth.get(0);
    }
    return length * cscale;
}

其中info是通过stbtt_InitFont创建的字体信息对象,cscale来自stbtt_ScaleForPixelHeight。

答案 1 :(得分:1)

LWJGL STB True Type演示包含现在(自2017年8月开始)的实现,其中包括字距调整:

lwjgl3 / Truetype.java

private float getStringWidth(STBTTFontinfo info, String text, int from, int to, int fontHeight) {
    int width = 0;

    try (MemoryStack stack = stackPush()) {
        IntBuffer pCodePoint       = stack.mallocInt(1);
        IntBuffer pAdvancedWidth   = stack.mallocInt(1);
        IntBuffer pLeftSideBearing = stack.mallocInt(1);

        int i = from;
        while (i < to) {
            i += getCP(text, to, i, pCodePoint);
            int cp = pCodePoint.get(0);

            stbtt_GetCodepointHMetrics(info, cp, pAdvancedWidth, pLeftSideBearing);
            width += pAdvancedWidth.get(0);

            if (isKerningEnabled() && i < to) {
                getCP(text, to, i, pCodePoint);
                width += stbtt_GetCodepointKernAdvance(info, cp, pCodePoint.get(0));
            }
        }
    }

    return width * stbtt_ScaleForPixelHeight(info, fontHeight);
}

private static int getCP(String text, int to, int i, IntBuffer cpOut) {
    char c1 = text.charAt(i);
    if (Character.isHighSurrogate(c1) && i + 1 < to) {
        char c2 = text.charAt(i + 1);
        if (Character.isLowSurrogate(c2)) {
            cpOut.put(0, Character.toCodePoint(c1, c2));
            return 2;
        }
    }
    cpOut.put(0, c1);
    return 1;
}