/// <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(); }