/// <summary>
///
/// </summary>
protected unsafe void UpdateGeometry()
{
if (font == null || text == null || !geomPositionsOutOfDate)
{
// 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);
renderOp.vertexData.vertexCount = charLength * 6;
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;
}
// get pos/tex buffer
HardwareVertexBuffer buffer = renderOp.vertexData.vertexBufferBinding.GetBuffer(POSITION_TEXCOORD);
IntPtr data = buffer.Lock(BufferLocking.Discard);
float *vertPtr = (float *)data.ToPointer();
int index = 0;
bool newLine = true;
// go through each character and process
for (int i = 0; i < text.Length; i++)
{
char c = text[i];
if (newLine)
{
float length = 0.0f;
// precalc the length of this line
for (int j = i; j < text.Length && text[j] != '\n'; j++)
{
if (text[j] == ' ')
{
length += spaceWidth;
}
else
{
length += font.GetGlyphAspectRatio(text[j]) * charHeight * 2;
}
} // for j
if (alignment == HorizontalAlignment.Right)
{
left -= length;
}
else if (alignment == 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
renderOp.vertexData.vertexCount -= 6;
continue;
}
if (c == ' ')
{
// leave a gap, no tris required
left += spaceWidth;
// reduce tri count
renderOp.vertexData.vertexCount -= 6;
continue;
}
float horizHeight = font.GetGlyphAspectRatio(c);
float 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
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;
}
// update colors
UpdateColors();
}