Example #1
0
        /// <summary>
        /// Sets up a single character as a OpenGL texture for rendering.
        /// </summary>
        /// <param name="face"></param>
        /// <param name="faceptr"></param>
        /// <param name="c"></param>
        private void CompileCharacter(Face face, IntPtr faceptr, int c)
        {
            //We first convert the number index to a character index
            int index = Face.FT_Get_Char_Index(faceptr, Convert.ToChar(c));

            //Here we load the actual glyph for the character
            int ret = Face.FT_Load_Glyph(faceptr, index, FT_LOAD_TYPES.FT_LOAD_DEFAULT);

            if (ret != 0)
            {
                return;
            }

            //Convert the glyph to a bitmap
            IntPtr glyph;
            int    retb = Glyph.FT_Get_Glyph(face.glyphrec, out glyph);

            if (retb != 0)
            {
                return;
            }

            // Render the glphy to a bitmap
            Glyph.FT_Glyph_To_Bitmap(out glyph, FT_RENDER_MODES.FT_RENDER_MODE_NORMAL, 0, 1);
            BitmapGlyph glyph_bmp = (BitmapGlyph)Marshal.PtrToStructure(glyph, typeof(BitmapGlyph));
            int         size      = (glyph_bmp.bitmap.width * glyph_bmp.bitmap.rows);

            if (size <= 0)
            {
                //space is a special `blank` character
                extent_x[c] = 0;

                if (c == 32)
                {
                    Gl.glNewList((int)(list_base + c), Gl.GL_COMPILE);
                    Gl.glTranslatef(fontSize >> 1, 0, 0);
                    extent_x[c] = fontSize >> 1;
                    Gl.glEndList();
                }
                return;
            }

            // Allocate space and grab the bitmap
            byte[] bmp = new byte[size];
            Marshal.Copy(glyph_bmp.bitmap.buffer, bmp, 0, bmp.Length);

            // Save the size of the bitmap and create a power of 2 version
            // for OpenGL.
            glyphSizes[c] =
                new SizeF(glyph_bmp.bitmap.width,
                          glyph_bmp.bitmap.rows);
            baselines[c] = glyph_bmp.top - glyph_bmp.bitmap.rows;
            int width  = next_po2(glyph_bmp.bitmap.width);
            int height = next_po2(glyph_bmp.bitmap.rows);

            byte[] expanded = new byte[2 * width * height];

            for (int j = 0; j < height; j++)
            {
                for (int i = 0; i < width; i++)
                {
                    expanded[2 * (i + j * width)] = expanded[2 * (i + j * width) + 1] =
                        (i >= glyph_bmp.bitmap.width || j >= glyph_bmp.bitmap.rows) ?
                        (byte)0 : bmp[i + glyph_bmp.bitmap.width * j];
                }
            }

            // Set up some texture parameters for opengl
            Gl.glBindTexture(Gl.GL_TEXTURE_2D, textures[c]);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);

            // Create the texture
            Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA, width, height,
                            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((int)(list_base + c), Gl.GL_COMPILE);
            Gl.glBindTexture(Gl.GL_TEXTURE_2D, textures[c]);

            //Account for freetype spacing rules
            Gl.glTranslatef(glyph_bmp.left, 0, 0);
            Gl.glPushMatrix();
            //Gl.glRotatef(180, 1f, 0, 0);
            Gl.glScalef(1, -1, 1);
            Gl.glTranslatef(0, glyph_bmp.top - glyph_bmp.bitmap.rows, 0);
            float x = (float)glyph_bmp.bitmap.width / (float)width;
            float y = (float)glyph_bmp.bitmap.rows / (float)height;

            //Draw the quad
            Gl.glBegin(Gl.GL_QUADS);
            {
                Gl.glTexCoord2d(0, 0);
                Gl.glVertex2f(0, glyph_bmp.bitmap.rows);
                Gl.glTexCoord2d(0, y);
                Gl.glVertex2f(0, 0);
                Gl.glTexCoord2d(x, y);
                Gl.glVertex2f(glyph_bmp.bitmap.width, 0);
                Gl.glTexCoord2d(x, 0);
                Gl.glVertex2f(glyph_bmp.bitmap.width, glyph_bmp.bitmap.rows);
            }
            Gl.glEnd();
            Gl.glPopMatrix();

            // Advance for the next character
            Gl.glTranslatef(glyph_bmp.bitmap.width, 0, 0);
            extent_x[c] = glyph_bmp.left + glyph_bmp.bitmap.width;
            Gl.glEndList();
        }