Freetype:如何获取旋转的文本边界

时间:2016-06-20 08:50:56

标签: freetype freetype2

我正在渲染带有旋转字符的字体图集,因为我的整个文本框已旋转。 现在我想计算文本框轮廓以呈现彩色背景。

如果我只计算渲染顶点的最小包围矩形,则会产生未对齐的框,因为字符在纹理图集中旋转(参见1)。我还渲染了纹理切口以更好地理解问题(参见2):

角色地图集创建代码:

#include <ft2build.h>
#include FT_FREETYPE_H
....
FT_Face face = ...
int height = ...
int angle = ...
FT_Set_Pixel_Sizes(face, 0, height);
FT_GlyphSlot g = face->glyph;

int roww = border;
int rowh = 0;
int w = 0;
int h = 0;

FT_Matrix     matrix;              /* transformation matrix */
const float angleF = angle / 180.f * PI;
matrix.xx = (FT_Fixed)(cos(angleF) * 0x10000L);
matrix.xy = (FT_Fixed)(-sin(angleF) * 0x10000L);
matrix.yx = (FT_Fixed)(sin(angleF) * 0x10000L);
matrix.yy = (FT_Fixed)(cos(angleF) * 0x10000L);
FT_Set_Transform(face, &matrix, 0);

memset(character, 0, sizeof character);

/* Find minimum size for a texture holding all visible ASCII characters */
for (int i = 32; i < Character::MAXIMUM; i++) {
    if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
        fprintf(stderr, "Loading character %c failed! Height is %d\n", i, height);
        continue;
    }
    if (roww + g->bitmap.width + 1 + border >= MAXWIDTH) {
        w = std::max(w, roww);
        h += rowh;
        roww = border;
        rowh = 0;
    }
    roww += g->bitmap.width + 1 + border;
    rowh = std::max(rowh, (int)g->bitmap.rows + border);
}

w = std::max(w, roww);
h += rowh + border;

glUseProgram(0);
glEnable(GL_TEXTURE_2D);

/* Create a texture that will be used to hold all ASCII glyphs */

glActiveTexture(GL_TEXTURE0);
if (!OpenGLResourceManager::emptyTexture(tex, w, h, 1)) {
    // Texture loading failed. Keep this atlas empty
    glDisable(GL_TEXTURE_2D);
    return;
}
tex.bindTexture();

/* We require 1 byte alignment when uploading texture data */
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

{
    //Fill texture with black to prevent texture bleeding
    std::vector<GLubyte> emptyData(w * h, 0);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_LUMINANCE, GL_UNSIGNED_BYTE, &emptyData[0]);
}

/* Clamping to edges is important to prevent artifacts when scaling */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

/* Linear filtering usually looks best for text */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

/* Paste all glyph bitmaps into the texture, remembering the offset */
int ox = border;
int oy = border;

rowh = 0;

for (int i = 32; i < Character::MAXIMUM; i++) {
    if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
        fprintf(stderr, "Loading character %c failed!\n", i);
        continue;
    }

    if (ox + g->bitmap.width + 1 + border >= MAXWIDTH) {
        oy += rowh;
        rowh = 0;
        ox = border;
    }
    glTexSubImage2D(GL_TEXTURE_2D, 0, ox, oy, g->bitmap.width, g->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, g->bitmap.buffer);
    character[i].ax = g->advance.x >> 6;
    character[i].ay = g->advance.y >> 6;

    character[i].bw = g->bitmap.width;
    character[i].bh = g->bitmap.rows;

    character[i].bl = g->bitmap_left;
    character[i].bt = g->bitmap_top;

    character[i].tx = ox / (float)w;
    character[i].ty = oy / (float)h;

    rowh = std::max(rowh, (int)g->bitmap.rows + border);
    ox += g->bitmap.width + 1 + border;
}

glBindTexture(GL_TEXTURE_2D, NULL);
glDisable(GL_TEXTURE_2D);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);  //Standard

如何获取文本的视觉边界(而不是顶点边界)?

更新:必须为像素完美字体旋转纹理而不是顶点,请参阅以下特写:

旋转顶点 - Vertex rotation并旋转纹理 - Texture rotation

(请忽略投影中的差异)

0 个答案:

没有答案