protected unsafe void UpdateGeometry()
{
if ( font == null || text == null || !this.isGeomPositionsOutOfDate )
{
// must not be initialized yet, probably due to order of creation in a template
return;
}
int charLength = text.Length;
// make sure the buffers are big enough
CheckMemoryAllocation( charLength );
renderOperation.vertexData.vertexCount = charLength * 6;
// get pos/tex buffer
HardwareVertexBuffer buffer = renderOperation.vertexData.vertexBufferBinding.GetBuffer( POSITION_TEXCOORD_BINDING );
IntPtr data = buffer.Lock( BufferLocking.Discard );
float largestWidth = 0.0f;
float left = this.DerivedLeft * 2.0f - 1.0f;
float top = -( ( this.DerivedTop * 2.0f ) - 1.0f );
// derive space width from the size of a capital A
if ( spaceWidth == 0 )
{
spaceWidth = font.GetGlyphAspectRatio( 'A' ) * charHeight * 2.0f * viewportAspectCoef;
}
bool newLine = true;
int index = 0;
// go through each character and process
for ( int i = 0; i < charLength; i++ )
{
char c = text[ i ];
if ( newLine )
{
float length = 0.0f;
// precalc the length of this line
for ( int j = i; j < charLength && text[ j ] != '\n'; j++ )
{
if ( text[ j ] == ' ' )
{
length += spaceWidth;
}
else
{
length += font.GetGlyphAspectRatio( text[ j ] ) * charHeight * 2f * viewportAspectCoef;
}
} // for j
if ( this.horzAlign == HorizontalAlignment.Right )
{
left -= length;
}
else if ( this.horzAlign == HorizontalAlignment.Center )
{
left -= length * 0.5f;
}
newLine = false;
} // if newLine
if ( c == '\n' )
{
left = this.DerivedLeft * 2.0f - 1.0f;
top -= charHeight * 2.0f;
newLine = true;
// reduce tri count
renderOperation.vertexData.vertexCount -= 6;
continue;
}
if ( c == ' ' )
{
// leave a gap, no tris required
left += spaceWidth;
// reduce tri count
renderOperation.vertexData.vertexCount -= 6;
continue;
}
float horizHeight = font.GetGlyphAspectRatio( c ) * viewportAspectCoef;
Real u1, u2, v1, v2;
// get the texcoords for the specified character
font.GetGlyphTexCoords( c, out u1, out v1, out u2, out v2 );
// each vert is (x, y, z, u, v)
// first tri
// upper left
float* vertPtr = (float*)data.ToPointer();
vertPtr[ index++ ] = left;
vertPtr[ index++ ] = top;
vertPtr[ index++ ] = -1.0f;
vertPtr[ index++ ] = u1;
vertPtr[ index++ ] = v1;
top -= charHeight * 2.0f;
// bottom left
vertPtr[ index++ ] = left;
vertPtr[ index++ ] = top;
vertPtr[ index++ ] = -1.0f;
vertPtr[ index++ ] = u1;
vertPtr[ index++ ] = v2;
top += charHeight * 2.0f;
left += horizHeight * charHeight * 2.0f;
// top right
vertPtr[ index++ ] = left;
vertPtr[ index++ ] = top;
vertPtr[ index++ ] = -1.0f;
vertPtr[ index++ ] = u2;
vertPtr[ index++ ] = v1;
// second tri
// top right (again)
vertPtr[ index++ ] = left;
vertPtr[ index++ ] = top;
vertPtr[ index++ ] = -1.0f;
vertPtr[ index++ ] = u2;
vertPtr[ index++ ] = v1;
top -= charHeight * 2.0f;
left -= horizHeight * charHeight * 2.0f;
// bottom left (again)
vertPtr[ index++ ] = left;
vertPtr[ index++ ] = top;
vertPtr[ index++ ] = -1.0f;
vertPtr[ index++ ] = u1;
vertPtr[ index++ ] = v2;
left += horizHeight * charHeight * 2.0f;
// bottom right
vertPtr[ index++ ] = left;
vertPtr[ index++ ] = top;
vertPtr[ index++ ] = -1.0f;
vertPtr[ index++ ] = u2;
vertPtr[ index++ ] = v2;
// go back up with top
top += charHeight * 2.0f;
float currentWidth = ( left + 1 ) / 2 - this.DerivedLeft;
if ( currentWidth > largestWidth )
{
largestWidth = currentWidth;
}
} // for i
// unlock vertex buffer
buffer.Unlock();
if ( metricsMode == MetricsMode.Pixels )
{
// Derive parametric version of dimensions
float vpWidth = OverlayManager.Instance.ViewportWidth;
largestWidth *= vpWidth;
}
// record the width as the longest width calculated for any of the lines
if ( this.Width < largestWidth )
{
this.Width = largestWidth;
}
}