Jump to content
  • Advertisement
Sign in to follow this  

xadvance values seem wrong

This topic is 1247 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

mainly they seem to be consistently smaller than the character width which seems wrong.


i feel i am using them as documented and the same as other examples, but when rendering there is clearly something wrong in the x direction only.


the crucial bit of code that I have written looks like this:


const BMCharData& xCharData = **ppxCharData;
mfXCursor += xCharData.mfAdvanceX * fScale;
const BMKerningPair** ppxKerningData = mpxFont->mxKerningMap.Find( Render::Font::KerningHash( wcLastChar, wcCurrentChar ) );
if( ppxKerningData )
    mfXCursor += ( **ppxKerningData ).mfKerningAmount * fScale;
pxCurrentGeometry->AddCharacter( *mpxFont, fScale, mfXCursor, mfYCursor, wcCurrentChar );
wcLastChar = wcCurrentChar;
the visual result comes out looking like this (in this case no kerning hints are present to be applied, so the dodgy x positions are resulting entirely from the xadvance data):
to make it clear if it is not it should be reading 182.45 fps and RT: 0.8 ms
does anyone have any suggestions on why this may be the case? am i wrong to interpret xadvance as using the same scale factor as the x, y, width, height and x and y offsets?
as a dumb guess, maybe i am rendering the quads backwards with the uvs flipped in the u direction - although i wouldn't expect the kind of overlap i see here to result from that (smaller characters seem /further/ offset to the left - but my internal visualisation may well be a complete fiction). i will try this quickly... but that would be extremely odd. none of the other code i've found and looked at for reference seems to do that. (although y is inverted, which seems to be the way)

Share this post

Link to post
Share on other sites

for the record it does indeed look better when i flip the relative position of the character geometry in x:




it is still clearly a bit wrong though.


flipping the xoffset looks much better, but still a bit wrong imo:




my intuition is that these numbers should not be smaller than the character widths - however given the nature of the xoffset this thinking might be very wrong.


is it possible that my choice of font simply lacks enough kerning hints to make the 2 next to the 1 not look completely wrong? (its open sans btw)


again thanks in advance to any potential replies.

Share this post

Link to post
Share on other sites

for completeness the code adding vertices to the vertex buffers now looks like this:

        const BMCharData& xCharData = **ppxChar;
        const float fInnerX = fX - xCharData.mfOffsetX * fScale;
        const float fInnerY = fY - xCharData.mfOffsetY * fScale;
        const float fScaledWidth = xCharData.mfWidth * fScale;
        const float fScaledHeight = xCharData.mfHeight * fScale;
        FontVertex axVertices[ 4 ] =
	    { fInnerX, fInnerY,
                xCharData.mfUX + xCharData.mfWidth, xCharData.mfVY },
            { fInnerX, fInnerY - fScaledHeight,
                xCharData.mfUX + xCharData.mfWidth, xCharData.mfVY + xCharData.mfHeight },
            { fInnerX - fScaledWidth, fInnerY - fScaledHeight, xCharData.mfUX,
                xCharData.mfVY + xCharData.mfHeight },
            { fInnerX - fScaledWidth, fInnerY,
                xCharData.mfUX, xCharData.mfVY },

	for( int i = 0; i < 4; ++i )
	    maxVertices.Append( axVertices[ i ] );

Share this post

Link to post
Share on other sites

Sounds like your actual xadvance values are wrong. Here's a Verdana at 64 points:

char id=65   x=0     y=133   width=36    height=38    xoffset=0     yoffset=14    xadvance=36    page=0  chnl=15
char id=66   x=310   y=129   width=31    height=38    xoffset=4     yoffset=14    xadvance=36    page=0  chnl=15
char id=67   x=218   y=50    width=33    height=40    xoffset=2     yoffset=13    xadvance=36    page=0  chnl=15
char id=68   x=107   y=132   width=34    height=38    xoffset=4     yoffset=14    xadvance=40    page=0  chnl=15
char id=69   x=29    y=172   width=27    height=38    xoffset=4     yoffset=14    xadvance=33    page=0  chnl=15
char id=70   x=84    y=172   width=26    height=38    xoffset=4     yoffset=14    xadvance=30    page=0  chnl=15

Share this post

Link to post
Share on other sites

As you're just showing bits and pieces of your code it's hard to know but it seems to me that you're using moving the cursor before drawing the quad using the xadvance of the current character.


What you should be doing is to draw the quad of the current character at the current position, then move the cursor with the xadvance of that character.



In my CFont writer class the code looks like this:


void CFont::InternalWrite(float x, float y, float z, const char *text, int count, float spacing)
  if( render->GetGraphics() == 0 )

  int page = -1;

  y += scale * float(base);

  for( int n = 0; n < count; )
    int charId = GetTextChar(text, n, &n);
    SCharDescr *ch = GetChar(charId);
    if( ch == 0 ) ch = &defChar;

    // Map the center of the texel to the corners
    // in order to get pixel perfect mapping
    float u = (float(ch->srcX)+0.5f) / scaleW;
    float v = (float(ch->srcY)+0.5f) / scaleH;
    float u2 = u + float(ch->srcW) / scaleW;
    float v2 = v + float(ch->srcH) / scaleH;

    float a = scale * float(ch->xAdv);
    float w = scale * float(ch->srcW);
    float h = scale * float(ch->srcH);
    float ox = scale * float(ch->xOff);
    float oy = scale * float(ch->yOff);

    if( ch->page != page )
      page = ch->page;

    render->VtxTexCoord(u, v);
    render->VtxPos(x+ox, y-oy, z);
    render->VtxTexCoord(u2, v);
    render->VtxPos(x+w+ox, y-oy, z);
    render->VtxTexCoord(u2, v2);
    render->VtxPos(x+w+ox, y-h-oy, z);
    render->VtxTexCoord(u, v2);
    render->VtxPos(x+ox, y-h-oy, z);

    x += a;
    if( charId == ' ' )
      x += spacing;

    if( n < count )
      x += AdjustForKerningPairs(charId, GetTextChar(text,n));



Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!