public GlyphRun(OpenGLFont font, string text, float sizeWidth, float sizeHeight, OpenGLTextAlignment alignment, bool autoEllipsis) { Font = font; List <LineBreak> linebreaks = new List <LineBreak>(); string processingText = text; int totalHeight = 0; int totalWidth = 0; int totalChars = 0; int intWidth; if (sizeWidth != float.PositiveInfinity) { intWidth = (int)sizeWidth; } else { intWidth = int.MaxValue; } int intHeight; if (sizeHeight != float.PositiveInfinity) { intHeight = (int)sizeHeight; } else { intHeight = int.MaxValue; } LineBreak lineBreak = FitString(processingText, 0, intWidth); while (lineBreak.Index != processingText.Length) { LineBreak nextBreak = FitString(processingText, lineBreak.Index, intWidth); // see if this line needs ellipsis if (Font.myHeight + Font.myHeight + totalHeight > intHeight && autoEllipsis) { string lineText = lineBreak.Text; int ellipsisStart = lineText.Length - 3; if (ellipsisStart < 0) { ellipsisStart = 0; } lineText = lineText.Substring(0, ellipsisStart) + "..."; lineBreak.Width = MeasureString(lineText); lineBreak.Text = lineText; break; } linebreaks.Add(lineBreak); totalWidth = Math.Max(totalWidth, lineBreak.Width); totalHeight += Font.myHeight; totalChars += lineBreak.Text.Length; lineBreak = nextBreak; } linebreaks.Add(lineBreak); totalHeight += Font.myHeight; totalWidth = Math.Max(totalWidth, lineBreak.Width); totalChars += lineBreak.Text.Length; myTriangleCount = totalChars * 2; GlyphPosition[] rectangles = new GlyphPosition[totalChars]; GlyphTexCoords[] texCoords = new GlyphTexCoords[totalChars]; short[] indices = new short[totalChars * 6]; Glyphs = rectangles; FontCoords = texCoords; Indices = indices; if (sizeWidth == float.PositiveInfinity) { myWidth = totalWidth; } else { myWidth = sizeWidth; } if (sizeHeight == float.PositiveInfinity) { myHeight = totalHeight; } else { myHeight = sizeHeight; } float y = 0; int curChars = 0; for (int i = 0; i < linebreaks.Count; i++) { LineBreak lbreak = linebreaks[i]; float x; float spaceAdjust = 0; string lbreakText = lbreak.Text; switch (alignment) { case OpenGLTextAlignment.Left: x = 0; break; case OpenGLTextAlignment.Right: x = myWidth - lbreak.Width; break; case OpenGLTextAlignment.Center: x = (myWidth - lbreak.Width) / 2; break; case OpenGLTextAlignment.Justified: x = 0; if (i != linebreaks.Count - 1) { lbreakText = lbreakText.TrimStart(' ').TrimEnd(' '); int spaceCount = 0; foreach (char c in lbreakText) { if (c == ' ') { spaceCount++; } } int newWidth = MeasureString(lbreakText); if (spaceCount != 0) { spaceAdjust = (myWidth - newWidth) / spaceCount; } } break; default: throw new ArgumentException("Unknown alignment type."); } BuildLine(font, lbreakText, curChars, x, y, spaceAdjust); y += Font.myHeight; curChars += lbreakText.Length; } }
unsafe public OpenGLFont(Font font) { IntPtr hdc = myTempGraphics.GetHdc(); IntPtr hfont = font.ToHfont(); SelectObject(hdc, hfont); if (!GetCharWidth32(hdc, 0, 255, CharacterWidths)) { throw new SystemException("Unable to measure character widths."); } tagTEXTMETRIC metrics = new tagTEXTMETRIC(); GetTextMetrics(hdc, ref metrics); myLeadingSpace = metrics.tmInternalLeading; myTrailingSpace = metrics.tmExternalLeading; myTempGraphics.ReleaseHdc(hdc); int width = 0; for (int i = myFirstCharacterOfInterest; i <= myLastCharacterOfInterest; i++) { CharacterWidths[i] += myLeadingSpace + myTrailingSpace; width += CharacterWidths[i]; } myHeight = (int)Math.Round(myTempGraphics.MeasureString(myCharactersOfInterest, font).Height); mySquareDim = (int)Math.Ceiling(Math.Sqrt(width * myHeight)); mySquareDim = Texture.GetValidTextureDimensionFromSize(mySquareDim); float fSquareDim = mySquareDim; Bitmap bitmap = new Bitmap(mySquareDim, mySquareDim, PixelFormat.Format16bppRgb565); using (Graphics g = Graphics.FromImage(bitmap)) { int x = 0; int y = 0; for (char i = myFirstCharacterOfInterest; i <= myLastCharacterOfInterest; i++) { if (x + CharacterWidths[i] >= mySquareDim) { y += myHeight; x = 0; } CharacterLocations[i] = new Point(x, y); float uStart = x / fSquareDim; float uEnd = (x + CharacterWidths[i]) / fSquareDim; float vStart = y / fSquareDim; float vEnd = (y + myHeight) / fSquareDim; TextureCoordinates[i] = new GlyphTexCoords(uStart, vStart, uEnd, vEnd); g.DrawString(i.ToString(), font, myWhiteBrush, x, y); x += CharacterWidths[i]; } } byte[] alphaBytes = new byte[bitmap.Width * bitmap.Height]; BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat.Format16bppRgb565); int pixCount = 0; for (int y = 0; y < bitmap.Height; y++) { short *yp = (short *)((int)data.Scan0 + data.Stride * y); for (int x = 0; x < bitmap.Width; x++, pixCount++) { short *p = (short *)(yp + x); short pixel = *p; byte b = (byte)((pixel & 0x1F) << 3); byte g = (byte)(((pixel >> 5) & 0x3F) << 2); byte r = (byte)(((pixel >> 11) & 0x1F) << 3); byte totalAlpha = (byte)((r + g + b) / 3); alphaBytes[pixCount] = totalAlpha; } } bitmap.UnlockBits(data); uint tex = 0; gl.GenTextures(1, &tex); myName = tex; gl.BindTexture(gl.GL_TEXTURE_2D, myName); fixed(byte *alphaBytesPointer = alphaBytes) { gl.TexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_ALPHA, mySquareDim, mySquareDim, 0, gl.GL_ALPHA, gl.GL_UNSIGNED_BYTE, (IntPtr)alphaBytesPointer); } gl.TexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR); gl.TexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR); gl.TexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE); gl.TexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE); // below is debug code I used to see the results of my texture generation //try //{ // Directory.CreateDirectory("\\Temp"); //} //catch (Exception) //{ //} //bitmap.Save("\\temp\\temp.png", ImageFormat.Png); //for (int i = myFirstCharacterOfInterest; i <= myLastCharacterOfInterest; i++) //{ // using (Bitmap ch = new Bitmap(bfont.CharacterWidths[i], height, PixelFormat.Format16bppRgb565)) // { // using (Graphics tg = Graphics.FromImage(ch)) // { // tg.DrawImage(bitmap, 0, 0, new Rectangle(bfont.CharacterLocations[i].X, bfont.CharacterLocations[i].Y, ch.Width, ch.Height), GraphicsUnit.Pixel); // } // ch.Save(string.Format("\\temp\\{0}.png", i), ImageFormat.Png); // } //} bitmap.Dispose(); }