Advertisement

xadvance values seem wrong

Started by January 21, 2015 12:48 AM
3 comments, last by WitchLord 9 years, 10 months ago

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):
OafmbQm.png
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)

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

bArvwJa.png

it is still clearly a bit wrong though.

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

wAaCt5g.png

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.

Advertisement

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 ] );
	}

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
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.

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 )
    return;

  int page = -1;
  render->Begin(RENDER_QUAD_LIST);

  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 )
    {
      render->End();
      page = ch->page;
      render->GetGraphics()->SetTexture(pages[page]);
      render->Begin(RENDER_QUAD_LIST);
    }

    render->VtxColor(color);
    render->VtxData(ch->chnl);
    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));
  }

  render->End();
}

 

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement