Esempio n. 1
0
 static public int SetKerning(IntPtr l)
 {
     try {
         BMGlyph      self = (BMGlyph)checkSelf(l);
         System.Int32 a1;
         checkType(l, 2, out a1);
         System.Int32 a2;
         checkType(l, 3, out a2);
         self.SetKerning(a1, a2);
         pushValue(l, true);
         return(1);
     }
     catch (Exception e) {
         return(error(l, e));
     }
 }
Esempio n. 2
0
    /// <summary>
    /// Reload the font data.
    /// </summary>

    static public void Load(BMFont font, string name, byte[] bytes)
    {
        font.Clear();

        if (bytes != null)
        {
            ByteReader reader    = new ByteReader(bytes);
            char[]     separator = new char[] { ' ' };

            while (reader.canRead)
            {
                string line = reader.ReadLine();
                if (string.IsNullOrEmpty(line))
                {
                    break;
                }
                string[] split = line.Split(separator, System.StringSplitOptions.RemoveEmptyEntries);
                int      len   = split.Length;

                if (split[0] == "char")
                {
                    // Expected data style:
                    // char id=13 x=506 y=62 width=3 height=3 xoffset=-1 yoffset=50 xadvance=0 page=0 chnl=15

                    int channel = (len > 10) ? GetInt(split[10]) : 15;

                    if (len > 9 && GetInt(split[9]) > 0)
                    {
                        Debug.LogError("Your font was exported with more than one texture. Only one texture is supported by NGUI.\n" +
                                       "You need to re-export your font, enlarging the texture's dimensions until everything fits into just one texture.");
                        break;
                    }

                    if (len > 8)
                    {
                        int     id    = GetInt(split[1]);
                        BMGlyph glyph = font.GetGlyph(id, true);

                        if (glyph != null)
                        {
                            glyph.x       = GetInt(split[2]);
                            glyph.y       = GetInt(split[3]);
                            glyph.width   = GetInt(split[4]);
                            glyph.height  = GetInt(split[5]);
                            glyph.offsetX = GetInt(split[6]);
                            glyph.offsetY = GetInt(split[7]);
                            glyph.advance = GetInt(split[8]);
                            glyph.channel = channel;
                        }
                        else
                        {
                            Debug.Log("Char: " + split[1] + " (" + id + ") is NULL");
                        }
                    }
                    else
                    {
                        Debug.LogError("Unexpected number of entries for the 'char' field (" + name + ", " + split.Length + "):\n" + line);
                        break;
                    }
                }
                else if (split[0] == "kerning")
                {
                    // Expected data style:
                    // kerning first=84 second=244 amount=-5

                    if (len > 3)
                    {
                        int first  = GetInt(split[1]);
                        int second = GetInt(split[2]);
                        int amount = GetInt(split[3]);

                        BMGlyph glyph = font.GetGlyph(second, true);
                        if (glyph != null)
                        {
                            glyph.SetKerning(first, amount);
                        }
                    }
                    else
                    {
                        Debug.LogError("Unexpected number of entries for the 'kerning' field (" +
                                       name + ", " + split.Length + "):\n" + line);
                        break;
                    }
                }
                else if (split[0] == "common")
                {
                    // Expected data style:
                    // common lineHeight=64 base=51 scaleW=512 scaleH=512 pages=1 packed=0 alphaChnl=1 redChnl=4 greenChnl=4 blueChnl=4

                    if (len > 5)
                    {
                        font.charSize   = GetInt(split[1]);
                        font.baseOffset = GetInt(split[2]);
                        font.texWidth   = GetInt(split[3]);
                        font.texHeight  = GetInt(split[4]);

                        int pages = GetInt(split[5]);

                        if (pages != 1)
                        {
                            Debug.LogError("Font '" + name + "' must be created with only 1 texture, not " + pages);
                            break;
                        }
                    }
                    else
                    {
                        Debug.LogError("Unexpected number of entries for the 'common' field (" +
                                       name + ", " + split.Length + "):\n" + line);
                        break;
                    }
                }
                else if (split[0] == "page")
                {
                    // Expected data style:
                    // page id=0 file="textureName.png"

                    if (len > 2)
                    {
                        font.spriteName = GetString(split[2]).Replace("\"", "");
                        font.spriteName = font.spriteName.Replace(".png", "");
                        font.spriteName = font.spriteName.Replace(".tga", "");
                    }
                }
            }
        }
    }
Esempio n. 3
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);
    }