Ejemplo n.º 1
0
        Character GetCharacter(char c)
        {
            if (chars.ContainsKey(c))
            {
                return(chars[c]);
            }

            //rendering character
            face.LoadChar(c, LoadFlags.Render, LoadTarget.Light);
            FTBitmap bitmap = face.Glyph.Bitmap;

            //calculating position
            if (x + bitmap.Width > mapSize)
            {
                y += ymax;
                x  = 0;
            }

            if (y + bitmap.Rows > mapSize)
            {
                throw new Exception("out of memory string");
            }

            if (ymax < bitmap.Rows)
            {
                ymax = bitmap.Rows;
            }

            charmap.AddSubImage(bitmap.Buffer, x, y, bitmap.Width, bitmap.Rows);
            Character ch = new Character(new Vector2(x / (float)mapSize, y / (float)mapSize),
                                         new Vector2(bitmap.Width, bitmap.Rows),
                                         new Vector2(face.Glyph.BitmapLeft, face.Glyph.BitmapTop),
                                         face.Glyph.Advance.X.Value);

            chars.Add(c, ch);

            x += bitmap.Width + 1;

            bitmap.Dispose();

            return(ch);
        }
Ejemplo n.º 2
0
        public Table.XYWH[] GetXYWHTable(string fTextStrings)
        {
            Library library = new Library();
            Face    face    = library.NewFace(fontName, 0);

            face.SetCharSize(0, this.fontHeight, 0, 72);


            List <Table.XYWH> tmp     = new List <Table.XYWH>();
            StringReader      fReader = new StringReader(fTextStrings);
            int img_nums;
            int chars_per_page = (image_width / tile_width) * (image_height / tile_height);

            if (fTextStrings.Length < (chars_per_page))
            {
                img_nums = 1;
            }
            else
            {
                img_nums = (fTextStrings.Length / chars_per_page);
                if ((fTextStrings.Length % chars_per_page) > 0)
                {
                    img_nums = (fTextStrings.Length / chars_per_page) + 1;
                }
            }
            for (int i = 0; i < img_nums; i++)
            {
                int    pos = 0;
                string currentString;
                if (i != img_nums - 1)
                {
                    char[] buffer = new char[chars_per_page];
                    fReader.Read(buffer, pos, chars_per_page);
                    currentString = new string(buffer);
                    pos          += currentString.Length;
                }
                else
                {
                    currentString = fReader.ReadToEnd();
                }
                currentString = currentString.Replace("\n", "");
                currentString = currentString.Replace("\r", "");

                int x = 0, y = 0;
                for (int n = 0; n < currentString.ToCharArray().Length; n++)
                {
                    Table.XYWH currentXYWH = new Table.XYWH();
                    currentXYWH.x_pos    = (uint)x;
                    currentXYWH.y_pos    = (uint)y;
                    currentXYWH.page_num = (uint)i + 1;
                    string currentChar0 = currentString.ToCharArray()[n].ToString();
                    uint   char_code    = uchar2code(currentChar0);
                    uint   glyphIndex   = face.GetCharIndex(uchar2code(currentChar0));
                    currentXYWH.charid = char_code; //set charid
                    face.LoadChar((uint)glyphIndex, LoadFlags.Render, LoadTarget.Lcd);
                    face.LoadGlyph((uint)glyphIndex, LoadFlags.Render, LoadTarget.Lcd);
                    face.Glyph.RenderGlyph(RenderMode.Lcd);

                    FTBitmap ftbmp = face.Glyph.Bitmap;
                    if (ftbmp.Width == 0)
                    {
                        currentXYWH.c_width = (uint)tile_width;
                    }
                    else
                    {
                        float advance = (float)face.Glyph.Metrics.HorizontalAdvance;
                        if (advance >= (float)tile_width)
                        {
                            currentXYWH.c_width = (uint)tile_width;
                        }
                        else
                        {
                            currentXYWH.c_width = (uint)face.Glyph.BitmapLeft + (uint)((float)face.Glyph.Metrics.HorizontalBearingX +
                                                                                       (float)GlobalSettings.relativePositionX +
                                                                                       (float)face.Glyph.Metrics.Width);
                        }
                    }
                    //currentXYWH.c_width = (uint)((float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width);//set c_width
                    if (char_code == (uint)32)
                    {
                        currentXYWH.c_width = (uint)tile_width / 2 - 1;
                    }
                    else if ((char_code <= (uint)0x3000) && (char_code >= (uint)0x7e))
                    {
                        currentXYWH.c_width = (uint)tile_width;
                    }

                    else if (char_code >= (uint)8000)
                    {
                        currentXYWH.c_width = (uint)tile_width;
                    }
                    currentXYWH.c_height = (uint)tile_height;
                    tmp.Add(currentXYWH);
                    x += this.tile_width;
                    if (x + this.tile_width > this.image_width)
                    {
                        x  = 0;
                        y += this.tile_height;
                    }

                    ftbmp.Dispose();
                }
            }
            return(tmp.ToArray());
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// </summary>
        /// <param name="fontBytes"></param>
        /// <param name="fontSize"></param>
        /// <param name="glyphCount"></param>
        /// <param name="charSize">
        /// Whether to create the characters in char size, on by default. If off the font size passed will
        /// be the pixel size instead.
        /// </param>
        public FreeTypeAtlas(byte[] fontBytes, uint fontSize, int glyphCount = 128, bool charSize = true)
        {
            Glyphs = new Glyph[glyphCount];

            Library library = new Library();
            Face    face    = new Face(library, fontBytes, 0);

            if (charSize)
            {
                face.SetCharSize(0, (int)fontSize, 96, 96);
            }
            else
            {
                face.SetPixelSizes(0, fontSize);
            }

            // Get line spacing.
            LineSpacing = (float)face.Size.Metrics.Height;
            Ascent      = (float)face.Size.Metrics.Ascender.ToDouble();
            // Get max size of the atlas texture.
            int maxDimension = (int)((1 + face.Size.Metrics.Height) * Math.Ceiling(Math.Sqrt(glyphCount)));
            int texWidth     = 1;

            while (texWidth < maxDimension)
            {
                texWidth <<= 1;
            }

            byte[] pixels = new byte[texWidth * texWidth];
            int    penX   = 0;
            int    penY   = 0;

            // Cache all glyphs.
            for (int i = 0; i < glyphCount; i++)
            {
                face.LoadChar((uint)i, LoadFlags.Render | LoadFlags.ForceAutohint, LoadTarget.Light);
                FTBitmap bitmap = face.Glyph.Bitmap;

                if (penX + bitmap.Width >= texWidth)
                {
                    penX  = 0;
                    penY += (int)(face.Size.Metrics.Height + 1);
                }

                // Copy pixels.
                for (int row = 0; row < bitmap.Rows; row++)
                {
                    for (int col = 0; col < bitmap.Width; col++)
                    {
                        int x = penX + col;
                        int y = penY + row;
                        pixels[y * texWidth + x] = bitmap.BufferData[row * bitmap.Pitch + col];
                    }
                }

                // Create glyph data.
                Glyphs[i] = new Glyph
                {
                    X      = penX,
                    Y      = penY,
                    Width  = bitmap.Width,
                    Height = bitmap.Rows,

                    XOffset  = face.Glyph.BitmapLeft,
                    YOffset  = face.Glyph.BitmapTop,
                    MinX     = (float)face.Glyph.Metrics.HorizontalBearingX.ToDouble(),
                    Advance  = (float)face.Glyph.Metrics.HorizontalAdvance.ToDouble(),
                    YBearing = (float)(face.Size.Metrics.Ascender.ToDouble() - face.Glyph.Metrics.HorizontalBearingY.ToDouble()),

                    MaxX = (float)(face.Glyph.Metrics.HorizontalBearingX.ToDouble() + face.Glyph.Metrics.Width.ToDouble()),
                    MinY = (float)(face.Glyph.Metrics.HorizontalBearingY.ToDouble() - Math.Ceiling(face.Glyph.Metrics.Height.ToDouble())),
                    MaxY = (float)face.Glyph.Metrics.HorizontalBearingY.ToDouble()
                };

                // Increment pen. Leave one pixel space.
                penX += bitmap.Width + 1;
                bitmap.Dispose();
            }

            // Assign the face.
            Face = face;

            // Create texture.
            GLThread.ExecuteGLThread(() =>
            {
                uint texturePointer = Engine.GraphicsManager.CreateTexture();
                Engine.GraphicsManager.BindTexture(texturePointer);
                // Set the red channel to the alpha channel and set all others to 1.
                Engine.GraphicsManager.SetTextureMask(0xffffffff, 0xffffffff, 0xffffffff, 0xff000000);
                Engine.GraphicsManager.UploadToTexture(pixels, new Vector2(texWidth, texWidth), TextureInternalFormat.R8, TexturePixelFormat.Red);
                Texture = new GLTexture(texturePointer, new Vector2(texWidth, texWidth), Matrix4x4.CreateScale(1, -1, 1), $"{face.FamilyName} {fontSize}");
            });
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Create a new font atlas.
        /// </summary>
        /// <param name="fontBytes">The bytes of the font to create an atlas from.</param>
        /// <param name="fontSize">The font size in points to create an atlas at.</param>
        /// <param name="glyphCount">the number of glyphs to cache.</param>
        public Atlas(byte[] fontBytes, uint fontSize, int glyphCount = 128)
        {
            Glyphs = new Glyph[glyphCount];

            Library library = new Library();
            Face    face    = new Face(library, fontBytes, 0);

            face.SetCharSize(0, (int)fontSize, 96, 96);

            // Get line spacing.
            LineSpacing = (float)face.Size.Metrics.Height;
            Ascent      = (float)face.Size.Metrics.Ascender.ToDouble();
            // Get max size of the atlas texture.
            int maxDimension = (int)((1 + face.Size.Metrics.Height) * Math.Ceiling(Math.Sqrt(glyphCount)));
            int texWidth     = 1;

            while (texWidth < maxDimension)
            {
                texWidth <<= 1;
            }

            byte[] pixels = new byte[texWidth * texWidth];
            int    penX   = 0;
            int    penY   = 0;

            // Cache all glyphs.
            for (int i = 0; i < glyphCount; i++)
            {
                face.LoadChar((uint)i, LoadFlags.Render | LoadFlags.ForceAutohint, LoadTarget.Light);
                FTBitmap bitmap = face.Glyph.Bitmap;

                if (penX + bitmap.Width >= texWidth)
                {
                    penX  = 0;
                    penY += (int)(face.Size.Metrics.Height + 1);
                }

                // Copy pixels.
                for (int row = 0; row < bitmap.Rows; row++)
                {
                    for (int col = 0; col < bitmap.Width; col++)
                    {
                        int x = penX + col;
                        int y = penY + row;
                        pixels[y * texWidth + x] = bitmap.BufferData[row * bitmap.Pitch + col];
                    }
                }

                // Create glyph data.
                Glyphs[i] = new Glyph
                {
                    X      = penX,
                    Y      = penY,
                    Width  = bitmap.Width,
                    Height = bitmap.Rows,

                    XOffset  = face.Glyph.BitmapLeft,
                    YOffset  = face.Glyph.BitmapTop,
                    MinX     = (float)face.Glyph.Metrics.HorizontalBearingX.ToDouble(),
                    Advance  = (float)face.Glyph.Metrics.HorizontalAdvance.ToDouble(),
                    YBearing = (float)(face.Size.Metrics.Ascender.ToDouble() - face.Glyph.Metrics.HorizontalBearingY.ToDouble()),

                    MaxX = (float)(face.Glyph.Metrics.HorizontalBearingX.ToDouble() + face.Glyph.Metrics.Width.ToDouble()),
                    MinY = (float)(face.Glyph.Metrics.HorizontalBearingY.ToDouble() - Math.Ceiling(face.Glyph.Metrics.Height.ToDouble())),
                    MaxY = (float)face.Glyph.Metrics.HorizontalBearingY.ToDouble()
                };

                // Increment pen. Leave one pixel space.
                penX += bitmap.Width + 1;
                bitmap.Dispose();
            }

            // Assign the face.
            Face = face;

            // Create texture.
            GLThread.ExecuteGLThread(() => { Texture = new Texture(pixels, texWidth, texWidth, $"{face.FamilyName} {fontSize}"); });
        }