예제 #1
0
        public void generateAtlases(string outputPath, int maxWidth, int maxHeight, bool genJSON, bool genRBXLua)
        {
            int atlas = 0;
            int posX = 0, posY = 0;

            List<Bitmap> bitmaps = new List<Bitmap>();
            Dictionary<string, List<FontInfo>> infos = new Dictionary<string, List<FontInfo>>();

            Bitmap bitmap = new Bitmap(maxWidth, maxHeight, PixelFormat.Format32bppArgb);
            Graphics graphics = Graphics.FromImage(bitmap);
            graphics.Clear(Color.Transparent);

            foreach (Face face in faces)
            {
                infos[face.StyleName] = new List<FontInfo>();
                for (int i = 0; i < sizes.Length; i++)
                {
                    int size = sizes[i];
                    FontInfo info = new FontInfo(face.StyleName, size);

                    int width = 0;
                    int height = 0;
                    int lineHeight = 0;
                    int firstAdjust = 0;

                    face.SetPixelSizes((uint)size + extraSize, (uint)size + extraSize);
                    face.SetUnpatentedHinting(true);

                    getKernWidthHeight(face, info, out width, out lineHeight, out firstAdjust);

                    if (width > maxWidth)
                    {
                        int overlaps = (int)Math.Truncate((float)(width / maxWidth));
                        width = maxWidth;
                        height = (overlaps + 1) * (lineHeight + padY);
                    }
                    else
                    {
                        width = maxWidth;
                        height = lineHeight + padY;
                    }

                    for (int j = 0; j < characters.Length; j++)
                    {
                        char character = characters[j];
                        uint index = face.GetCharIndex(character);
                        face.LoadGlyph(index, LoadFlags.Default, LoadTarget.Normal);
                        face.Glyph.RenderGlyph(RenderMode.Normal);

                        // case where the glyph won't fit horizontally
                        if (posX + face.Glyph.Metrics.Width + face.Glyph.BitmapLeft + padX > width)
                        {
                            posX = 0;
                            posY += lineHeight + padY;
                        }
                        // case where the glyph won't fit vertically
                        if (posY > maxHeight - (lineHeight + padY))
                        {
                            bitmaps.Add(bitmap);

                            bitmap = new Bitmap(maxWidth, maxHeight, PixelFormat.Format32bppArgb);
                            graphics = Graphics.FromImage(bitmap);
                            graphics.Clear(Color.Transparent);

                            posX = 0;
                            posY = 0;
                            atlas++;
                        }

                        // draw the character
                        posX += renderCharacter(face, characters[j], posX, posY, atlas, info, graphics) + padX;
                    }

                    // new font size means resetting some stuff
                    posX = 0;
                    posY += lineHeight + padY;

                    // set the info line height and first adjust
                    info.lineHeight = lineHeight;
                    info.firstAdjust = firstAdjust;

                    // add the info to the list
                    infos[face.StyleName].Add(info);
                }
            }

            // add the current bitmap
            bitmaps.Add(bitmap);
            graphics.Dispose();

            // export
            int count = 0;
            foreach (Bitmap bmp in bitmaps)
            {
                count++;
                bmp.Save(outputPath + "\\" + family + "_" + count + ".png");
            }

            // export data
            if (genJSON)
            {
                int c = 0;
                string output = prepOutputDataJSON();
                foreach (Face face in faces)
                {
                    c++;
                    output += "\t\t\"" + face.StyleName + "\" : {\n";
                    int c2 = 0;
                    foreach (FontInfo info in infos[face.StyleName])
                    {
                        c2++;
                        output += info.makeJSON("\t\t\t") + (c2 < infos[face.StyleName].Count ? "," : "") + "\n";
                    }
                    output += "\t\t}" + (c < faces.Length ? "," : "") + "\n";
                }
                output += "\t}\n}";
                // write json file
                File.WriteAllText(outputPath + "\\" + family + ".json", output);
            }

            if (genRBXLua)
            {
                int c = 0;
                string output = prepOutputDataLua();
                foreach (Face face in faces)
                {
                    c++;
                    output += "\t\t[\"" + face.StyleName + "\"] = {\n";
                    int c2 = 0;
                    foreach (FontInfo info in infos[face.StyleName])
                    {
                        c2++;
                        output += info.makeLua("\t\t\t") + (c2 < infos[face.StyleName].Count ? "," : "") + "\n";
                    }
                    output += "\t\t}" + (c < faces.Length ? "," : "") + "\n";
                }
                output += "\t}\n}";

                // Setup module
                string header = "--[[\n\t@Font " + family + "\n";
                header += "\t@Sizes {" + string.Join(", ", sizes) + "}\n";
                header += "\t@Author N/A\n";
                header += "\t@Link N/A\n--]]\n\n";

                header += "local module = {}\n\n";
                header += "module.atlases = {\n";

                for (int i = 1; i <= count; i++)
                {
                    header += "\t[" + i + "] = \"rbxassetid://\";\n";
                }

                header += "};\n\nmodule.font = " + output;
                header += "\n\nreturn module";

                // write Lua file
                File.WriteAllText(outputPath + "\\" + family + ".lua", header);
            }
        }
예제 #2
0
        private int renderCharacter(Face face, char character, int posX, int posY, int atlas, FontInfo info, Graphics graphics)
        {
            uint index = face.GetCharIndex(character);
            face.LoadGlyph(index, LoadFlags.Default, LoadTarget.Normal);
            face.Glyph.RenderGlyph(RenderMode.Normal);

            GlyphMetrics metrics = face.Glyph.Metrics;
            int width = metrics.Width.ToInt32() + metrics.HorizontalBearingX.ToInt32();
            int xAdvance = metrics.HorizontalAdvance.ToInt32();
            int yoffset = metrics.VerticalAdvance.ToInt32() - metrics.HorizontalBearingY.ToInt32();
            int charHeight = metrics.Height.ToInt32();

            if (face.Glyph.Bitmap.Width > 0)
            {
                FTBitmap ftbmp = face.Glyph.Bitmap;
                Bitmap copy = ftbmp.ToGdipBitmap(Color.White);
                graphics.DrawImageUnscaled(copy, posX + metrics.HorizontalBearingX.ToInt32(), posY);
            }

            info.addCharacter(new CharacterInfo(character, posX, posY, width, charHeight, xAdvance, yoffset, atlas));

            return width;
        }
예제 #3
0
        private int renderCharacter(Face face, char character, int posX, int posY, int atlas, FontInfo info, Graphics graphics)
        {
            uint index = face.GetCharIndex(character);

            face.LoadGlyph(index, LoadFlags.Default, LoadTarget.Normal);
            face.Glyph.RenderGlyph(RenderMode.Normal);

            GlyphMetrics metrics    = face.Glyph.Metrics;
            int          width      = metrics.Width.ToInt32() + metrics.HorizontalBearingX.ToInt32();
            int          xAdvance   = metrics.HorizontalAdvance.ToInt32();
            int          yoffset    = metrics.VerticalAdvance.ToInt32() - metrics.HorizontalBearingY.ToInt32();
            int          charHeight = metrics.Height.ToInt32();

            if (face.Glyph.Bitmap.Width > 0)
            {
                FTBitmap ftbmp = face.Glyph.Bitmap;
                Bitmap   copy  = ftbmp.ToGdipBitmap(Color.White);
                graphics.DrawImageUnscaled(copy, posX + metrics.HorizontalBearingX.ToInt32(), posY);
            }

            info.addCharacter(new CharacterInfo(character, posX, posY, width, charHeight, xAdvance, yoffset, atlas));

            return(width);
        }
예제 #4
0
        private void getKernWidthHeight(Face face, FontInfo info, out int width, out int maxHeight, out int firstAdjust)
        {
            width = 0;
            maxHeight = 0;
            firstAdjust = 0;

            for (int i = 0; i < characters.Length; i++)
            {
                char character1 = characters[i];
                uint index1 = face.GetCharIndex(character1);

                face.LoadGlyph(index1, LoadFlags.Default, LoadTarget.Normal);
                GlyphMetrics metrics = face.Glyph.Metrics;

                int yoffset = metrics.VerticalAdvance.ToInt32() - metrics.HorizontalBearingY.ToInt32();
                int nheight = yoffset + metrics.Height.ToInt32();
                int height = metrics.Height.ToInt32();
                if (height > maxHeight)
                {
                    maxHeight = height; //nheight;
                    firstAdjust = yoffset;
                }

                for (int j = 0; j < characters.Length; j++)
                {
                    char character2 = characters[j];
                    uint index2 = face.GetCharIndex(character2);

                    FTVector26Dot6 kern = face.GetKerning(index1, index2, KerningMode.Default);
                    int kernX = kern.X.ToInt32();
                    int kernY = kern.Y.ToInt32();
                    if (kernX != 0 || kernY != 0)
                    {
                        info.addKerning(new KerningInfo(character1, character2, kernX, kernY));
                    }
                }

                if (i + 1 == characters.Length)
                {
                    width += metrics.Width.ToInt32() + metrics.HorizontalBearingX.ToInt32() + padX;
                }
                else
                {
                    width += metrics.HorizontalAdvance.ToInt32() + padX;
                }
            }
        }
예제 #5
0
        public void generateAtlases(string outputPath, int maxWidth, int maxHeight, bool genJSON, bool genRBXLua)
        {
            int atlas = 0;
            int posX = 0, posY = 0;

            List <Bitmap> bitmaps = new List <Bitmap>();
            Dictionary <string, List <FontInfo> > infos = new Dictionary <string, List <FontInfo> >();

            Bitmap   bitmap   = new Bitmap(maxWidth, maxHeight, PixelFormat.Format32bppArgb);
            Graphics graphics = Graphics.FromImage(bitmap);

            graphics.Clear(Color.Transparent);

            foreach (Face face in faces)
            {
                infos[face.StyleName] = new List <FontInfo>();
                for (int i = 0; i < sizes.Length; i++)
                {
                    int      size = sizes[i];
                    FontInfo info = new FontInfo(face.StyleName, size);

                    int width       = 0;
                    int height      = 0;
                    int lineHeight  = 0;
                    int firstAdjust = 0;

                    face.SetPixelSizes((uint)size + extraSize, (uint)size + extraSize);
                    face.SetUnpatentedHinting(true);

                    getKernWidthHeight(face, info, out width, out lineHeight, out firstAdjust);

                    if (width > maxWidth)
                    {
                        int overlaps = (int)Math.Truncate((float)(width / maxWidth));
                        width  = maxWidth;
                        height = (overlaps + 1) * (lineHeight + padY);
                    }
                    else
                    {
                        width  = maxWidth;
                        height = lineHeight + padY;
                    }

                    for (int j = 0; j < characters.Length; j++)
                    {
                        char character = characters[j];
                        uint index     = face.GetCharIndex(character);
                        face.LoadGlyph(index, LoadFlags.Default, LoadTarget.Normal);
                        face.Glyph.RenderGlyph(RenderMode.Normal);

                        // case where the glyph won't fit horizontally
                        if (posX + face.Glyph.Metrics.Width + face.Glyph.BitmapLeft + padX > width)
                        {
                            posX  = 0;
                            posY += lineHeight + padY;
                        }
                        // case where the glyph won't fit vertically
                        if (posY > maxHeight - (lineHeight + padY))
                        {
                            bitmaps.Add(bitmap);

                            bitmap   = new Bitmap(maxWidth, maxHeight, PixelFormat.Format32bppArgb);
                            graphics = Graphics.FromImage(bitmap);
                            graphics.Clear(Color.Transparent);

                            posX = 0;
                            posY = 0;
                            atlas++;
                        }

                        // draw the character
                        posX += renderCharacter(face, characters[j], posX, posY, atlas, info, graphics) + padX;
                    }

                    // new font size means resetting some stuff
                    posX  = 0;
                    posY += lineHeight + padY;

                    // set the info line height and first adjust
                    info.lineHeight  = lineHeight;
                    info.firstAdjust = firstAdjust;

                    // add the info to the list
                    infos[face.StyleName].Add(info);
                }
            }

            // add the current bitmap
            bitmaps.Add(bitmap);
            graphics.Dispose();

            // export
            int count = 0;

            foreach (Bitmap bmp in bitmaps)
            {
                count++;
                bmp.Save(outputPath + "\\" + family + "_" + count + ".png");
            }

            // export data
            if (genJSON)
            {
                int    c      = 0;
                string output = prepOutputDataJSON();
                foreach (Face face in faces)
                {
                    c++;
                    output += "\t\t\"" + face.StyleName + "\" : {\n";
                    int c2 = 0;
                    foreach (FontInfo info in infos[face.StyleName])
                    {
                        c2++;
                        output += info.makeJSON("\t\t\t") + (c2 < infos[face.StyleName].Count ? "," : "") + "\n";
                    }
                    output += "\t\t}" + (c < faces.Length ? "," : "") + "\n";
                }
                output += "\t}\n}";
                // write json file
                File.WriteAllText(outputPath + "\\" + family + ".json", output);
            }

            if (genRBXLua)
            {
                int    c      = 0;
                string output = prepOutputDataLua();
                foreach (Face face in faces)
                {
                    c++;
                    output += "\t\t[\"" + face.StyleName + "\"] = {\n";
                    int c2 = 0;
                    foreach (FontInfo info in infos[face.StyleName])
                    {
                        c2++;
                        output += info.makeLua("\t\t\t") + (c2 < infos[face.StyleName].Count ? "," : "") + "\n";
                    }
                    output += "\t\t}" + (c < faces.Length ? "," : "") + "\n";
                }
                output += "\t}\n}";

                // Setup module
                string header = "--[[\n\t@Font " + family + "\n";
                header += "\t@Sizes {" + string.Join(", ", sizes) + "}\n";
                header += "\t@Author N/A\n";
                header += "\t@Link N/A\n--]]\n\n";

                header += "local module = {}\n\n";
                header += "module.atlases = {\n";

                for (int i = 1; i <= count; i++)
                {
                    header += "\t[" + i + "] = \"rbxassetid://\";\n";
                }

                header += "};\n\nmodule.font = " + output;
                header += "\n\nreturn module";

                // write Lua file
                File.WriteAllText(outputPath + "\\" + family + ".lua", header);
            }
        }