Exemplo n.º 1
0
        private FT_GlyphSlotRec GetCharBitmap(uint c)
        {
            uint index = FT.FT_Get_Char_Index(faceptr, c);

            int ret = FT.FT_Load_Glyph(faceptr, index, FT.FT_LOAD_DEFAULT);

            FT_GlyphSlotRec glyph_rec = (FT_GlyphSlotRec)Marshal.PtrToStructure(face.glyph, typeof(FT_GlyphSlotRec));
            int             retb      = FT.FT_Render_Glyph(ref glyph_rec, FT_Render_Mode.FT_RENDER_MODE_NORMAL);

            return(glyph_rec);
        }
Exemplo n.º 2
0
        public override int GetCharWidth(PDFFont pdfFont, TTFontData data,
                                         char charCode)
        {
            InitLibrary();

            int aint = (int)charCode;

            if (data.Widths.IndexOfKey(charCode) >= 0)
            {
                return(data.Widths[charCode]);
            }
            LogFontFt cfont = data.LogFont;

            cfont.OpenFont();

            int awidth = 0;

            Monitor.Enter(flag);
            try
            {
                if (data.Widths.IndexOfKey(charCode) >= 0)
                {
                    awidth = data.Widths[charCode];
                }
                else
                {
                    if (0 == FT.FT_Load_Char(cfont.iface, (uint)charCode, (int)FT.FT_LOAD_NO_SCALE))
                    {
                        FT_FaceRec      aface  = (FT_FaceRec)Marshal.PtrToStructure(cfont.iface, typeof(FT_FaceRec));
                        FT_GlyphSlotRec aglyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(aface.glyph, typeof(FT_GlyphSlotRec));
                        ushort          width1 = (ushort)(aglyph.linearHoriAdvance >> 16);
                        ushort          width2 = (ushort)(aglyph.linearHoriAdvance & 0x0000FFFF);
                        double          dwidth = width1 + width2 / (double)65535;
                        awidth = System.Convert.ToInt32(Math.Round(cfont.widthmult * dwidth));
                    }
                    data.Widths[charCode] = awidth;
                    data.Glyphs[charCode] = System.Convert.ToInt32(FT.FT_Get_Char_Index(cfont.iface, charCode));
                    if (data.FirstLoaded > aint)
                    {
                        data.FirstLoaded = aint;
                    }
                    if (data.LastLoaded < aint)
                    {
                        data.LastLoaded = aint;
                    }
                }
            }
            finally
            {
                Monitor.Exit(flag);
            }
            return(awidth);
        }
Exemplo n.º 3
0
	static extern int FT_Render_Glyph (ref FT_GlyphSlotRec slot, FT_Render_Mode render_mode);
Exemplo n.º 4
0
    /// <summary>
    /// Create a bitmap font from the specified dynamic font.
    /// </summary>

    static public bool CreateFont(Font ttf, int size, int faceIndex, bool kerning, string characters, int padding, out BMFont font, out Texture2D tex)
    {
        font = null;
        tex  = null;

        if (ttf == null || !isPresent)
        {
            return(false);
        }

        IntPtr lib  = IntPtr.Zero;
        IntPtr face = IntPtr.Zero;

        if (FT_Init_FreeType(out lib) != 0)
        {
            Debug.LogError("Failed to initialize FreeType");
            return(false);
        }

        string fileName = Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length) +
                          UnityEditor.AssetDatabase.GetAssetPath(ttf);

        if (!File.Exists(fileName))
        {
            Debug.LogError("Unable to use the chosen font.");
        }
        else if (FT_New_Face(lib, fileName, faceIndex, out face) != 0)
        {
            Debug.LogError("Unable to use the chosen font (FT_New_Face).");
        }
        else
        {
            font          = new BMFont();
            font.charSize = size;

            Color32          white    = Color.white;
            List <int>       entries  = new List <int>();
            List <Texture2D> textures = new List <Texture2D>();

            FT_FaceRec faceRec = (FT_FaceRec)Marshal.PtrToStructure(face, typeof(FT_FaceRec));
            FT_Set_Pixel_Sizes(face, 0, (uint)size);

            // Calculate the baseline value that would let the printed font be centered vertically
            //int ascender = (faceRec.met.ascender >> 6);
            //int descender = (faceRec.descender >> 6);
            //int baseline = ((ascender - descender) >> 1);
            //if ((baseline & 1) == 1) --baseline;

            //Debug.Log(ascender + " " + descender + " " + baseline);

            // Space character is not renderable
            FT_Load_Glyph(face, FT_Get_Char_Index(face, 32), FT_LOAD_DEFAULT);
            FT_GlyphSlotRec space = (FT_GlyphSlotRec)Marshal.PtrToStructure(faceRec.glyph, typeof(FT_GlyphSlotRec));

            // Space is not visible and doesn't have a texture
            BMGlyph spaceGlyph = font.GetGlyph(32, true);
            spaceGlyph.offsetX = 0;
            spaceGlyph.offsetY = 0;
            spaceGlyph.advance = (space.metrics.horiAdvance >> 6);
            spaceGlyph.channel = 15;
            spaceGlyph.x       = 0;
            spaceGlyph.y       = 0;
            spaceGlyph.width   = 0;
            spaceGlyph.height  = 0;

            // Save kerning information
            if (kerning)
            {
                for (int b = 0; b < characters.Length; ++b)
                {
                    uint ch2 = characters[b];
                    if (ch2 == 32)
                    {
                        continue;
                    }

                    FT_Vector vec;
                    if (FT_Get_Kerning(face, ch2, 32, 0, out vec) != 0)
                    {
                        continue;
                    }

                    int offset = (vec.x >> 6);
                    if (offset != 0)
                    {
                        spaceGlyph.SetKerning((int)ch2, offset);
                    }
                }
            }

            // Run through all requested characters
            foreach (char ch in characters)
            {
                uint charIndex = FT_Get_Char_Index(face, (uint)ch);
                FT_Load_Glyph(face, charIndex, FT_LOAD_DEFAULT);
                FT_GlyphSlotRec glyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(faceRec.glyph, typeof(FT_GlyphSlotRec));
                FT_Render_Glyph(ref glyph, FT_Render_Mode.FT_RENDER_MODE_NORMAL);

                if (glyph.bitmap.width > 0 && glyph.bitmap.rows > 0)
                {
                    byte[] buffer = new byte[glyph.bitmap.width * glyph.bitmap.rows];
                    Marshal.Copy(glyph.bitmap.buffer, buffer, 0, buffer.Length);

                    Texture2D texture = new Texture2D(glyph.bitmap.width, glyph.bitmap.rows, UnityEngine.TextureFormat.ARGB32, false);
                    Color32[] colors  = new Color32[buffer.Length];

                    for (int i = 0, y = 0; y < glyph.bitmap.rows; ++y)
                    {
                        for (int x = 0; x < glyph.bitmap.width; ++x)
                        {
                            white.a = buffer[i++];
                            colors[x + glyph.bitmap.width * (glyph.bitmap.rows - y - 1)] = white;
                        }
                    }

                    // Save the texture
                    texture.SetPixels32(colors);
                    texture.Apply();
                    textures.Add(texture);
                    entries.Add(ch);

                    // Record the metrics
                    BMGlyph bmg = font.GetGlyph(ch, true);
                    bmg.offsetX = (glyph.metrics.horiBearingX >> 6);
                    bmg.offsetY = -(glyph.metrics.horiBearingY >> 6);
                    bmg.advance = (glyph.metrics.horiAdvance >> 6);
                    bmg.channel = 15;

                    // Save kerning information
                    if (kerning)
                    {
                        for (int b = 0; b < characters.Length; ++b)
                        {
                            uint ch2 = characters[b];
                            if (ch2 == ch)
                            {
                                continue;
                            }

                            FT_Vector vec;
                            if (FT_Get_Kerning(face, ch2, ch, 0, out vec) != 0)
                            {
                                continue;
                            }

                            int offset = (vec.x >> 6);
                            if (offset != 0)
                            {
                                bmg.SetKerning((int)ch2, offset);
                            }
                        }
                    }
                }
            }

            // Create a packed texture with all the characters
            tex = new Texture2D(32, 32, TextureFormat.ARGB32, false);
            Rect[] rects = tex.PackTextures(textures.ToArray(), padding);

            // Make the RGB channel pure white
            Color32[] cols = tex.GetPixels32();
            for (int i = 0, imax = cols.Length; i < imax; ++i)
            {
                Color32 c = cols[i];
                c.r     = 255;
                c.g     = 255;
                c.b     = 255;
                cols[i] = c;
            }
            tex.SetPixels32(cols);
            tex.Apply();

            font.texWidth  = tex.width;
            font.texHeight = tex.height;

            int min = int.MaxValue;
            int max = int.MinValue;

            // Other glyphs are visible and need to be added
            for (int i = 0, imax = entries.Count; i < imax; ++i)
            {
                // Destroy the texture now that it's a part of an atlas
                UnityEngine.Object.DestroyImmediate(textures[i]);
                textures[i] = null;
                Rect rect = rects[i];

                // Set the texture coordinates
                BMGlyph glyph = font.GetGlyph(entries[i], true);
                glyph.x      = Mathf.RoundToInt(rect.x * font.texWidth);
                glyph.y      = Mathf.RoundToInt(rect.y * font.texHeight);
                glyph.width  = Mathf.RoundToInt(rect.width * font.texWidth);
                glyph.height = Mathf.RoundToInt(rect.height * font.texHeight);

                // Flip the Y since the UV coordinate system is different
                glyph.y = font.texHeight - glyph.y - glyph.height;

                max = Mathf.Max(max, -glyph.offsetY);
                min = Mathf.Min(min, -glyph.offsetY - glyph.height);
            }

            int baseline = size + min;
            baseline += ((max - min - size) >> 1);

            // Offset all glyphs so that they are not using the baseline
            for (int i = 0, imax = entries.Count; i < imax; ++i)
            {
                BMGlyph glyph = font.GetGlyph(entries[i], true);
                glyph.offsetY += baseline;
            }
        }

        if (face != IntPtr.Zero)
        {
            FT_Done_Face(face);
        }
#if !UNITY_3_5
        if (lib != IntPtr.Zero)
        {
            FT_Done_FreeType(lib);
        }
#endif
        return(tex != null);
    }
Exemplo n.º 5
0
 static extern int FT_Render_Glyph(ref FT_GlyphSlotRec slot, FT_Render_Mode render_mode);
Exemplo n.º 6
0
        private void CompileCharacterToTexture(FT_FaceRec face, int c)
        {
            FTGlyphOffset offset = new FTGlyphOffset();

            //We first convert the number index to a character index
            uint index = FT.FT_Get_Char_Index(faceptr, (uint)c);

            string sError = "";

            if (index == 0)
            {
                sError = "No Glyph";
            }

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

            if (ret != 0)
            {
                Console.Write("Load_Glyph failed for character " + c.ToString());
            }

            FT_GlyphSlotRec glyphrec = (FT_GlyphSlotRec)Marshal.PtrToStructure(face.glyph, typeof(FT_GlyphSlotRec));

            ret = FT.FT_Render_Glyph(ref glyphrec, FT_Render_Mode.FT_RENDER_MODE_NORMAL);

            if (ret != 0)
            {
                Console.Write("Render failed for character " + c.ToString());
            }

            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[2 * width * height];
            for (int j = 0; j < height; j++)
            {
                for (int i = 0; i < width; i++)
                {
                    //Luminance
                    expanded[2 * (i + j * width)] = (byte)255;
                    //expanded[4 * (i + j * width) + 1] = (byte)255;
                    //expanded[4 * (i + j * width) + 2] = (byte)255;

                    // Alpha
                    expanded[2 * (i + j * width) + 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(Gl.GL_TEXTURE_2D, textures[c]);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, Gl.GL_CLAMP_TO_EDGE);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, Gl.GL_CLAMP_TO_EDGE);
            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((list_base + c), Gl.GL_COMPILE);
            Gl.glBindTexture(Gl.GL_TEXTURE_2D, 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);
            float x = (float)glyphrec.bitmap.width / (float)width;
            float y = (float)glyphrec.bitmap.rows / (float)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(0, glyphrec.bitmap.rows);
            Gl.glTexCoord2d(0, y); Gl.glVertex2f(0, 0);
            Gl.glTexCoord2d(x, y); Gl.glVertex2f(glyphrec.bitmap.width, 0);
            Gl.glTexCoord2d(x, 0); Gl.glVertex2f(glyphrec.bitmap.width, glyphrec.bitmap.rows);
            Gl.glEnd();
            Gl.glPopMatrix();

            //Advance for the next character
            Gl.glTranslatef(glyphrec.bitmap.width, 0, 0);
            extent_x[c] = glyphrec.bitmap_left + glyphrec.bitmap.width;
            Gl.glEndList();
            sChars += "f:" + c.ToString() + "[w:" + glyphrec.bitmap.width.ToString() + "][h:" + glyphrec.bitmap.rows.ToString() + "]" + sError;
        }
Exemplo n.º 7
0
Arquivo: TTF.cs Projeto: 9087/Saffiano
        public CharacterInfo RequestCharacterInfo(int charactorCode)
        {
            var glyphIndex = FT.FT_Get_Char_Index(face.Face, (uint)charactorCode);

            if (glyphIndex == 0)
            {
                return(null);
            }
            FT_Error error;

            error = FT.FT_Load_Glyph(face.Face, glyphIndex, FT.FT_LOAD_DEFAULT);
            if (error != FT_Error.FT_Err_Ok)
            {
                throw new FreeTypeException(error);
            }
            FT_Render_Mode renderMode = antialias ? FT_Render_Mode.FT_RENDER_MODE_NORMAL : FT_Render_Mode.FT_RENDER_MODE_MONO;
            IntPtr         pGlyphSlot;

            unsafe
            {
                pGlyphSlot = (IntPtr)face.GlyphSlot;
            }
            error = FT.FT_Render_Glyph(pGlyphSlot, renderMode);
            if (error != FT_Error.FT_Err_Ok)
            {
                throw new FreeTypeException(error);
            }
            FT_GlyphSlotRec glyphSlot = (FT_GlyphSlotRec)Marshal.PtrToStructure(pGlyphSlot, typeof(FT_GlyphSlotRec));
            FT_Bitmap       bitmap    = glyphSlot.bitmap;

            if (bitmap.buffer == IntPtr.Zero)
            {
                return(new CharacterInfo(this, charactorCode, new Vector2((int)glyphSlot.advance.x >> 6, (int)glyphSlot.advance.y >> 6)));
            }

            Texture texture = Font.atlas.Allocate(bitmap.width, bitmap.rows);

            switch ((FT_Pixel_Mode)bitmap.pixel_mode)
            {
            case FT_Pixel_Mode.FT_PIXEL_MODE_GRAY:
            {
                uint   length = bitmap.width * bitmap.rows;
                byte[] buffer = new Byte[length];
                Marshal.Copy(bitmap.buffer, buffer, 0, (int)length);
                Color[] pixels = new Color[length];
                int     count  = 0;
                for (int y = (int)bitmap.rows - 1; y >= 0; y--)
                {
                    for (int x = 0; x < bitmap.width; x++)
                    {
                        int index = y * (int)bitmap.width + x;
                        pixels[count] = new Color {
                            r = 1, g = 1, b = 1, a = (float)buffer[index] / 255.0f
                        };
                        count++;
                    }
                }
                texture.SetPixels(pixels);
            }
            break;

            case FT_Pixel_Mode.FT_PIXEL_MODE_MONO:
            {
                uint   length = bitmap.width * bitmap.rows;
                byte[] buffer = new Byte[bitmap.pitch * bitmap.rows];
                Marshal.Copy(bitmap.buffer, buffer, 0, (int)buffer.Length);
                Color[] pixels = new Color[length];
                int     count  = 0;
                for (int y = (int)bitmap.rows - 1; y >= 0; y--)
                {
                    for (int x = 0; x < bitmap.width; x++)
                    {
                        int   index = y * bitmap.pitch + (int)(x / 8);
                        byte  group = buffer[index];
                        float pixel = (group & (1 << (7 - x % 8))) > 0 ? 255.0f : 0;
                        pixels[count] = new Color {
                            r = 1, g = 1, b = 1, a = pixel / 255.0f
                        };
                        count++;
                    }
                }
                texture.SetPixels(pixels);
            }
            break;

            default:
                throw new NotImplementedException(string.Format("Pixel mode ({0})", bitmap.pixel_mode.ToString()));
            }
            return(new CharacterInfo(
                       this,
                       charactorCode,
                       new Vector2((float)glyphSlot.advance.x / (float)(1 << 6), (float)glyphSlot.advance.y / (float)(1 << 6)),
                       texture,
                       new Vector2(glyphSlot.bitmap_left, glyphSlot.bitmap_top)
                       ));
        }