将truetype字体默认值转换为NV路径中的像素大小



我正在使用NVidia路径扩展(NV Path)为OpenGL引擎编写文本模块。扩展允许加载系统和外部字体文件使用trutype指标。现在,我需要能够在呈现文本时为字形设置标准字体大小(以像素为单位)。默认情况下,加载的字形具有EMscale = 2048。搜索字形指标到像素的转换,我发现如下:

将单位转换为像素

em方中的值转换为像素中的值用一个尺度乘以坐标系。这个量表是:pointSize * resolution/(72 points per inch * units_per_em)

所以units_per_em等于2048,pointSize和分辨率是我无法解决的未知数。我如何得到分辨率值的视口宽度和高度进入这个方程?另外,如果我的输入是字体的像素大小,那么点的大小应该是多少?

我尝试用不同类型的输入来解决这个方程,但我渲染的文本总是比参考文本(AfterEffects)更小(或更大)。

NV_Path文档引用FreeType2度量。参考说:

在face->glyph->指标中找到的指标通常用26.6像素格式(即1/64像素),除非在调用FT_Load_Glyph或FT_Load_Char时使用FT_LOAD_NO_SCALE标志。在在这种情况下,指标将以原始字体单位表示。

我尝试将文本模型矩阵缩小1/64。它接近正确的大小,但仍不完美。

以下是我目前如何在代码中设置文本渲染:
            emScale=2048;
        glyphBase = glGenPathsNV(1+numChars);
    pathTemplate= ~0;
    glPathGlyphRangeNV(glyphBase,GL_SYSTEM_FONT_NAME_NV,
        "Verdana",GL_BOLD_BIT_NV,0,numChars,GL_SKIP_MISSING_GLYPH_NV,pathTemplate,emScale);

    /* Query font and glyph metrics. */
    glGetPathMetricRangeNV(
        GL_FONT_Y_MIN_BOUNDS_BIT_NV|
        GL_FONT_Y_MAX_BOUNDS_BIT_NV|
        GL_FONT_X_MIN_BOUNDS_BIT_NV|
        GL_FONT_X_MAX_BOUNDS_BIT_NV|
        GL_FONT_UNDERLINE_POSITION_BIT_NV|
        GL_FONT_UNDERLINE_THICKNESS_BIT_NV,glyphBase+' ' ,1 ,6*sizeof(GLfloat),font_data);

    glGetPathMetricRangeNV(GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV,
        glyphBase,numChars,0,horizontalAdvance);
    /* Query spacing information for example's message. */
    messageLen = strlen(message);
    xtranslate =(GLfloat*)malloc(sizeof(GLfloat) *messageLen);
    if(!xtranslate){
        fprintf(stderr, "%s: malloc of xtranslate failedn", "Text3D error");
        exit(1);
    }
    xtranslate[0] = 0.0f;  /* Initial xtranslate is zero. */
    /* Use 100% spacing; use 0.9 for both for 90% spacing. */
    GLfloat advanceScale = 1.0f,
        kerningScale = 1.0f; 
    glGetPathSpacingNV(GL_ACCUM_ADJACENT_PAIRS_NV,
        (GLsizei)messageLen,GL_UNSIGNED_BYTE,message,glyphBase,
        advanceScale,kerningScale,GL_TRANSLATE_X_NV,&xtranslate[1]); /* messageLen-1 accumulated translates are written here. */
    const unsigned char *message_ub = (const unsigned char*)message;
    totalAdvance = xtranslate[messageLen-1] +
        horizontalAdvance[message_ub[messageLen-1]];
    xBorder = totalAdvance / messageLen;
    glEnable(GL_STENCIL_TEST);
    glStencilFunc(GL_NOTEQUAL ,0 ,~0);
    glStencilOp(GL_KEEP,GL_KEEP,GL_ZERO);

    ////////// init matrices  /////////////
    translate(model ,vec3(0));
    translate(view  ,vec3(0));
                    float nearF=1 ,farF = 1200;
            glViewport(0,0,_viewPortW,_viewPortH);
        glMatrixLoadIdentityEXT(GL_PROJECTION);

        float aspect_ratio =(float) _viewPortW /(float) _viewPortH;
        glMatrixFrustumEXT(GL_PROJECTION ,-aspect_ratio,aspect_ratio,-1 ,1 ,nearF,farF);


        model=translate(model,vec3(0.0f,384.0,0.0f));//move up
            //scale by 26.6 also doesn't work:
    model=scale(model,vec3((1.0f/26.6f),1.0f/26.6f,1.0f/26.6f));
    view=lookAt(vec3(0,0,0),vec3(0,0,-1),vec3(0,1,0));
}

分辨率取决于设备,并使用您给出的公式DPI(每英寸点数)。point_size是字体的大小,由用户在Points中选择。A点= 1/72英寸(实际上这是PostScript中使用的点的大小,排字工使用的实际单位"点"略有不同)

设备分辨率可以通过操作系统相关的方法查询。谷歌"显示DPI $名称的操作系统"。使用以点为单位的大小,可以使您的物理字体大小与所使用的显示设备无关。

请注意,当使用OpenGL渲染时,您仍然需要经过转换管道,这必须考虑到

最新更新