private void RenderAsTexture(FT_GlyphSlotRec glyphrec, int c) { int ret = FT.FT_Render_Glyph(ref glyphrec, FT_Render_Mode.FT_RENDER_MODE_NORMAL); FTGlyphOffset offset = new FTGlyphOffset(); if (ret != 0) { Report("Render failed for character " + c.ToString()); } string sError = ""; int size = (glyphrec.bitmap.width * glyphrec.bitmap.rows); if (size <= 0) { //Console.Write("Blank Character: " + c.ToString()); //space is a special `blank` character extent_x[c] = 0; if (c == 32) { Gl.glNewList((list_base + c), Gl.GL_COMPILE); Gl.glTranslatef(font_size >> 1, 0, 0); extent_x[c] = font_size >> 1; Gl.glEndList(); offset.left = 0; offset.top = 0; offset.height = 0; offset.width = extent_x[c]; offsets[c] = offset; } return; } byte[] bmp = new byte[size]; Marshal.Copy(glyphrec.bitmap.buffer, bmp, 0, bmp.Length); //Next we expand the bitmap into an opengl texture int width = next_po2(glyphrec.bitmap.width); int height = next_po2(glyphrec.bitmap.rows); byte[, ,] expanded = new byte[height + 2, width + 2, 2]; for (int j = 0; j < height + 2; j++) { for (int i = 0; i < width + 2; i++) { //Luminance expanded[j, i, 0] = (byte)255; expanded[j, i, 1] = 0; } } for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { //expanded[4 * (i + j * width) + 1] = (byte)255; //expanded[4 * (i + j * width) + 2] = (byte)255; // Alpha expanded[j + 1, i + 1,1] = (i >= glyphrec.bitmap.width || j >= glyphrec.bitmap.rows) ? (byte)0 : (byte)(bmp[i + glyphrec.bitmap.width * j]); } } //Set up some texture parameters for opengl Gl.glBindTexture(Engine.Renderer.GlTextureMode, textures[c]); Gl.glTexParameteri(Engine.Renderer.GlTextureMode, Gl.GL_TEXTURE_WRAP_S, Gl.GL_CLAMP_TO_EDGE); Gl.glTexParameteri(Engine.Renderer.GlTextureMode, Gl.GL_TEXTURE_WRAP_T, Gl.GL_CLAMP_TO_EDGE); Gl.glTexParameteri(Engine.Renderer.GlTextureMode, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR); Gl.glTexParameteri(Engine.Renderer.GlTextureMode, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR); //Create the texture Gl.glTexImage2D(Engine.Renderer.GlTextureMode, 0, Gl.GL_RGBA, width +2, height+2, 0, Gl.GL_LUMINANCE_ALPHA, Gl.GL_UNSIGNED_BYTE, expanded); expanded = null; bmp = null; //Create a display list and bind a texture to it Gl.glNewList((list_base + c), Gl.GL_COMPILE); Gl.glBindTexture(Engine.Renderer.GlTextureMode, textures[c]); //Account for freetype spacing rules Gl.glTranslatef(glyphrec.bitmap_left, 0, 0); Gl.glPushMatrix(); Gl.glTranslatef(0, glyphrec.bitmap_top - glyphrec.bitmap.rows, 0); double x = Engine.Renderer.TextureCoordinate(glyphrec.bitmap.width, width); double y = Engine.Renderer.TextureCoordinate(glyphrec.bitmap.rows, height); offset.left = glyphrec.bitmap_left; offset.top = glyphrec.bitmap_top; offset.height = glyphrec.bitmap.rows; offset.width = glyphrec.bitmap.width; offset.advance = glyphrec.advance; offset.lsb_delta = glyphrec.lsb_delta; offset.rsb_delta = glyphrec.rsb_delta; offset.linearHoriAdvance = glyphrec.linearHoriAdvance; offset.linearVertAdvance = glyphrec.linearVertAdvance; offsets[c] = offset; //Draw the quad Gl.glBegin(Gl.GL_QUADS); Gl.glTexCoord2d(0, 0); Gl.glVertex2f(-1, glyphrec.bitmap.rows+1); Gl.glTexCoord2d(0, y); Gl.glVertex2f(-1, -1); Gl.glTexCoord2d(x, y); Gl.glVertex2f(glyphrec.bitmap.width+1, -1); Gl.glTexCoord2d(x, 0); Gl.glVertex2f(glyphrec.bitmap.width+1, glyphrec.bitmap.rows+1); Gl.glEnd(); Gl.glPopMatrix(); //Advance for the next character Gl.glTranslatef(glyphrec.advance.x >> 6, 0, 0); extent_x[c] = glyphrec.bitmap_left + (glyphrec.advance.x >> 6); Gl.glEndList(); sChars += "f:" + c.ToString() + "[w:" + glyphrec.bitmap.width.ToString() + "][h:" + glyphrec.bitmap.rows.ToString() + "]" + sError; }
public static extern int FT_Render_Glyph(ref FT_GlyphSlotRec slot, FT_Render_Mode render_mode);