Example #1
0
        // Create a display list coresponding to the give character.
        // return character width
        private int make_dlist(Face face, uint ch, uint list_base, uint[] tex_base)
        {
            int charWidth = 0;

            //The first thing we do is get FreeType to render our character
            //into a bitmap.  This actually requires a couple of FreeType commands:

            //Load the Glyph for our character.
            face.LoadGlyph(face.GetCharIndex(ch), LoadFlags.Default, LoadTarget.Normal);

            //Move the face's glyph into a Glyph object.
            Glyph glyph = face.Glyph.GetGlyph();

            //Convert the glyph to a bitmap.
            glyph.ToBitmap(RenderMode.Normal, new FTVector26Dot6(0, 0), true);
            BitmapGlyph bitmap_glyph = glyph.ToBitmapGlyph();

            //This reference will make accessing the bitmap easier
            FTBitmap bitmap = bitmap_glyph.Bitmap;

            //Use our helper function to get the widths of
            //the bitmap data that we will need in order to create
            //our texture.
            int width  = next_p2(bitmap.Width);
            int height = next_p2(bitmap.Rows);

            //Allocate memory for the texture data.
            byte[] expanded_data = new byte[2 * width * height];

            //Here we fill in the data for the expanded bitmap.
            //Notice that we are using two channel bitmap (one for
            //luminocity and one for alpha), but we assign
            //both luminocity and alpha to the value that we
            //find in the FreeType bitmap.
            //We use the ?: operator so that value which we use
            //will be 0 if we are in the padding zone, and whatever
            //is the the Freetype bitmap otherwise.
            for (int j = 0; j < height; j++)
            {
                for (int i = 0; i < width; i++)
                {
                    expanded_data[2 * (i + j * width)] = 255;

                    if (i >= bitmap.Width || j >= bitmap.Rows)
                    {
                        expanded_data[2 * (i + j * width) + 1] = 0;
                    }
                    else
                    {
                        expanded_data[2 * (i + j * width) + 1] = bitmap.BufferData[i + bitmap.Width * j];
                    }
                }
            }

            //Now we just setup some texture paramaters.
            glView.glBindTexture2D(tex_base[ch]);
            glView.glTex2DParameterMinFilterLinear();
            glView.glTex2DParameterMagFilterLinear();

            //Here we actually create the texture itself, notice
            //that we are using GL_LUMINANCE_ALPHA to indicate that
            //we are using 2 channel data.
            glView.glTexImage2D_IntFormatRGBA_formatLumAlpha_bytes(width, height, expanded_data);

            //So now we can create the display list
            glView.glNewListCompile(list_base + ch);
            glView.glBindTexture2D(tex_base[ch]);

            glView.glPushMatrix();                                // better results with popping the matrix here..

            //first we need to move over a little so that
            //the character has the right amount of space
            //between it and the one before it.
            glView.glTranslate((float)bitmap_glyph.Left, 0f, 0f);

            //Now we move down a little in the case that the
            //bitmap extends past the bottom of the line
            //(this is only true for characters like 'g' or 'y'.
            //GL.PushMatrix();                              // better results without popping the matrix before top translation
            int topOffset = bitmap_glyph.Top - bitmap.Rows;

            glView.glTranslate(0f, (float)topOffset, 0f);
            //glTranslatef(0, (GLfloat)bitmap_glyph->top-bitmap.rows, 0);

            //Now we need to account for the fact that many of
            //our textures are filled with empty padding space.
            //We figure what portion of the texture is used by
            //the actual character and store that information in
            //the x and y variables, then when we draw the
            //quad, we will only reference the parts of the texture
            //that we contain the character itself.
            float x = (float)bitmap.Width / (float)width,
                  y = (float)bitmap.Rows / (float)height;

            //Here we draw the texturemaped quads.
            //The bitmap that we got from FreeType was not
            //oriented quite like we would like it to be,
            //so we need to link the texture to the quad
            //so that the result will be properly aligned.
            glView.glBeginQuads();
            glView.glTexCoord2(0, 0); glView.glVertex2(0f, (float)bitmap.Rows);
            glView.glTexCoord2(0, y); glView.glVertex2(0f, 0f);
            glView.glTexCoord2(x, y); glView.glVertex2((float)bitmap.Width, 0);
            glView.glTexCoord2(x, 0); glView.glVertex2((float)bitmap.Width, (float)bitmap.Rows);
            glView.glEnd();
            glView.glPopMatrix();
            glView.glTranslate((float)(face.Glyph.Advance.X), 0f, 0f);

            // set the char width
            charWidth = (int)face.Glyph.Advance.X;

            //Finish the display list
            glView.glEndList();

            // free the glyph memory (bugfix)
            bitmap.Dispose();
            bitmap_glyph.Dispose();
            glyph.Dispose();

            // return the character width
            return(charWidth);
        }
Example #2
0
        public unsafe GlyphInfo CompileCharacter(Face face, uint glyphindex, char character)
        {
            // Load or generate new Texture and store the Handle in m_Textures
            if (m_Textures.Length <= Count)
            {
                Array.Resize(ref m_Textures, Math.Max(32, m_Textures.Length * 2));
            }
            int TextureIndex = m_Textures [Count];

            if (TextureIndex == 0)
            {
                int[] textures = new int[1];
                GL.GenTextures(1, textures);
                if (textures [0] == 0)
                {
                    return(GlyphInfo.Empty);
                }
                m_Textures [Count] = textures [0];
                TextureIndex       = textures [0];
            }

            int ListIndex = (int)glyphindex;

            //if (m_ListBase == 0) {
            if (OnDemand)
            {
                ListIndex = GL.GenLists(1);
                if (ListIndex == 0)
                {
                    return(GlyphInfo.Empty);
                }
            }

            try {
                face.LoadGlyph(glyphindex, LoadFlags.ForceAutohint, LoadTarget.Normal);
            } catch (Exception ex) {
                ex.LogWarning();
                return(GlyphInfo.Empty);
            }

            Glyph glyph = face.Glyph.GetGlyph();

            if (glyph == null)
            {
                return(GlyphInfo.Empty);
            }

            Height = Math.Max(Height, (float)face.Glyph.Metrics.Height);

            //glyph.ToBitmap (SharpFont.RenderMode.Normal, new FTVector26Dot6(0.15, 0.15), true);
            glyph.ToBitmap(SharpFont.RenderMode.Normal, new FTVector26Dot6(0, 0), true);

            BitmapGlyph bmg   = glyph.ToBitmapGlyph();
            int         width = bmg.Bitmap.Width;
            int         rows  = bmg.Bitmap.Rows;
            int         size  = width * rows;

            if (size <= 0)
            {
                glyph.Dispose();

                //if (Filter == GlyphFilterFlags.All)
                //	m_ExtentsX[(int)glyphindex] = 0;
                int spaceWidth = 0;
                if (character == 32)
                {
                    Count++;
                    spaceWidth = (Size * ScaleFactor / 3f).Ceil();
                    GL.NewList(m_ListBase + ListIndex, ListMode.Compile);                       // evtl character
                    GL.Translate(spaceWidth, 0, 0);
                    GL.EndList();
                    return(new GlyphInfo(ListIndex, spaceWidth));
                }
                return(GlyphInfo.Empty);
            }

            Count++;

            int expandedBitmapWidth  = (width + 1).NextPowerOf2();
            int expandedBitmapHeight = rows.NextPowerOf2();

            byte[] expandedBitmapBytes = new byte[expandedBitmapWidth * expandedBitmapHeight];

            fixed(byte *p = bmg.Bitmap.BufferData)
            fixed(byte *q = expandedBitmapBytes)
            {
                try {
                    byte *pTemp = p;
                    for (int countY = 0; countY < expandedBitmapHeight; countY++)
                    {
                        for (int countX = 0; countX < expandedBitmapWidth; countX++)
                        {
                            byte *qTemp = q + (countX + countY * expandedBitmapWidth);
                            if ((countX >= width || countY >= rows))
                            {
                                *qTemp = 0;
                            }
                            else
                            {
                                *qTemp = *(pTemp + countX);
                            }
                        }
                        pTemp += width;
                    }

                    if (IsSpecialChar(character))
                    {
                        for (int i = 0; i < expandedBitmapBytes.Length; i++)
                        {
                            byte *qTemp = q + i;
                            *     qTemp = (byte)(*qTemp / 2);
                        }
                    }
                } catch (Exception ex) {
                    ex.LogError();
                }
            }

            GL.BindTexture(TextureTarget.Texture2D, TextureIndex);

            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Clamp);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Clamp);

            //GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);

            GL.TexImage2D(TextureTarget.Texture2D,
                          0,                         // level-of-detail
                          PixelInternalFormat.Alpha, // texture-format 32bit
                          (int)expandedBitmapWidth,  // texture-width
                          (int)expandedBitmapHeight, // texture-height
                          0,                         // border
                          PixelFormat.Alpha,         // pixel-data-format
                          PixelType.UnsignedByte,    // pixel-data-type
                          expandedBitmapBytes);

            // ---------------------------------------------------------------------------
            //Create a display list (of precompiled GL commands) and bind a texture to it.
            GL.NewList(m_ListBase + ListIndex, ListMode.Compile);
            GL.BindTexture(TextureTarget.Texture2D, TextureIndex);

            // Account for freetype spacing rules.

            float glyphWidth = (float)glyph.Advance.X;

            //float left = (glyphWidth - bmg.Left) / 2f;

            GL.Translate(bmg.Left, 0, 0);
            GL.PushMatrix();
            GL.Translate(0, bmg.Top - rows, 0);

            float x = width / (float)expandedBitmapWidth;
            float y = rows / (float)expandedBitmapHeight;

            // Draw the quad.
            GL.Begin(PrimitiveType.Quads);
            GL.TexCoord2(0, 0); GL.Vertex2(0, rows);
            GL.TexCoord2(0, y); GL.Vertex2(0, 0);
            GL.TexCoord2(x, y); GL.Vertex2(width, 0);
            GL.TexCoord2(x, 0); GL.Vertex2(width, rows);
            GL.End();
            GL.PopMatrix();

            //GL.Translate (face.Glyph.Metrics.HorizontalAdvance - bmg.Left, 0, 0);


            GL.Translate(glyphWidth - bmg.Left, 0, 0);


            // Advance for the next character.

            /***
             * if (!Monospace)
             *      GL.Translate (face.Glyph.Metrics.HorizontalAdvance - bmg.Left, 0, 0);
             * else
             *      GL.Translate (glyphWidth, 0, 0);
             ***/

            GL.EndList();

            // ---------------------------------------------------------------------------
            //m_ExtentsX[glyphindex] = face.Glyph.Metrics.HorizontalAdvance.Ceiling();
            //m_ExtentsX[ListIndex] = glyphWidth.Ceil();

            glyph.Dispose();
            return(new GlyphInfo(ListIndex, glyphWidth.Ceil()));
        }