public RwGlTypeFaceBufferData GetVboForString(string text) { var characterRects = new List <Rectanglei>(); var uvRects = new List <Rectanglei>(); int xOffset = 0; for (int i = 0; i < text.Length; i++) { char c = text[i]; // Obtain character UV // if (!InternalCharacterMap.ContainsKey(c)) { LoadGlyphToTextureCache(c); } Rectanglei uvRect = InternalCharacterMap[c]; if (uvRect.Width > 0 && uvRect.Height > 0) { characterRects.Add(new Rectanglei(xOffset, 0, uvRect.Width, uvRect.Height)); uvRects.Add(uvRect); } xOffset += 32; // Temporary until character metrics are implemented } // Expand Rectanglei objects into floats for VBOs and return them // return(new RwGlTypeFaceBufferData( ExpandRectangleiList(characterRects), ExpandRectangleiList(uvRects) )); }
private void LoadGlyphToTextureCache(char c) { if (InternalCharacterMap.ContainsKey(c)) { throw new InvalidOperationException("The glyph is already present in the texture cache."); } // Load and render the glyph into memory // uint glyphIndex = Face.GetCharIndex(c); Face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); Face.Glyph.RenderGlyph(RenderMode.Normal); FTBitmap glyphBitmap = Face.Glyph.Bitmap; // If the bitmap is zero size, skip the texture cache and add a dummy UV map to the dictionary // if (glyphBitmap.Width == 0 || glyphBitmap.Rows == 0) { InternalCharacterMap.Add(c, new Rectanglei(0, 0, 0, 0)); return; } // Bind the glyph cache texture in GL // GL.BindTexture(TextureTarget.Texture2D, GlTextureId); // Store x-offset for the next glyph to be loaded into // int charXOffset = InternalTextureWidth; // Resize the glyph cache texture's height if needed // if (InternalTextureHeight < glyphBitmap.Rows) { InternalTextureHeight = glyphBitmap.Rows; } InternalTextureWidth += glyphBitmap.Width; GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, InternalTextureWidth, InternalTextureHeight, 0, PixelFormat.Rgb, PixelType.UnsignedByte, IntPtr.Zero); // Load the glyph bitmap into the texture // byte[] gBuffer = new byte[glyphBitmap.Width * glyphBitmap.Rows * 3]; for (int y = 0; y < glyphBitmap.Rows; y++) { for (int x = 0; x < glyphBitmap.Width; x++) { for (int i = 0; i < 3; i++) { gBuffer[(x + y * glyphBitmap.Width) * 3 + i] = glyphBitmap.BufferData[x + glyphBitmap.Width * y]; } } } GL.TexSubImage2D(TextureTarget.Texture2D, 0, charXOffset, 0, glyphBitmap.Width, glyphBitmap.Rows, PixelFormat.Rgb, PixelType.UnsignedByte, gBuffer); // Confirm the texture coordinates in the dictionary // InternalCharacterMap.Add(c, new Rectanglei(charXOffset, 0, glyphBitmap.Width, glyphBitmap.Rows)); }