font, bitmap and texture coordiante.
Пример #1
0
        /// <summary>
        /// Gets a <see cref="FontBitmap"/>'s intance.
        /// </summary>
        /// <param name="font"></param>
        /// <param name="charSet"></param>
        /// <param name="drawBoundary"></param>
        /// <returns></returns>
        public static FontBitmap GetFontBitmap(this Font font, string charSet, bool drawBoundary = false)
        {
            var fontBitmap = new FontBitmap();

            fontBitmap.GlyphFont = font;

            // 以下几步,不能调换先后顺序。
            // Don't change the order in which these functions invoked.
            int singleCharWidth, singleCharHeight;

            PrepareInitialGlyphDict(fontBitmap, charSet, out singleCharWidth, out singleCharHeight);
            int width, height;

            PrepareFinalBitmapSize(fontBitmap, out width, out height);
            PrintBitmap(fontBitmap, singleCharWidth, singleCharHeight, width, height);
            if (drawBoundary)
            {
                using (var graphics = Graphics.FromImage(fontBitmap.GlyphBitmap))
                {
                    bool odd = false;
                    foreach (GlyphInfo item in fontBitmap.GlyphInfoDictionary.Values)
                    {
                        graphics.DrawRectangle(
                            odd ? Pens.Green : Pens.Blue,
                            item.ToRectangle(1, 1, -2, -1));
                        odd = !odd;
                    }
                    graphics.DrawRectangle(Pens.Red, 0, 0, fontBitmap.GlyphBitmap.Width - 1, fontBitmap.GlyphBitmap.Height - 1);
                }
            }
            return(fontBitmap);
        }
Пример #2
0
        /// <summary>
        /// prepare final bitmap's size.
        /// </summary>
        /// <param name="fontBitmap"></param>
        /// <param name="width">final bitmap's width.</param>
        /// <param name="height">final bitmap's height.</param>
        private static void PrepareFinalBitmapSize(FontBitmap fontBitmap, out int width, out int height)
        {
            int sideLength;
            int maxGlyphHeight = 0;
            {
                int totalWidth = 0;
                foreach (GlyphInfo item in fontBitmap.GlyphInfoDictionary.Values)
                {
                    totalWidth += item.width + glyphInterval;
                    if (maxGlyphHeight < item.height)
                    {
                        maxGlyphHeight = item.height;
                    }
                }
                int area = totalWidth * maxGlyphHeight;
                sideLength             = (int)Math.Ceiling(Math.Sqrt(area));
                fontBitmap.GlyphHeight = maxGlyphHeight;
            }
            {
                int maxWidth = 0, maxHeight = 0;
                int currentX = leftMargin, currentY = 0;
                foreach (var item in fontBitmap.GlyphInfoDictionary)
                {
                    if (currentX + item.Value.width < sideLength)
                    {
                        currentX += item.Value.width + glyphInterval;
                    }
                    else// new row will start.
                    {
                        if (maxWidth < currentX)
                        {
                            maxWidth = currentX;
                        }
                        currentX  = leftMargin;
                        currentY += maxGlyphHeight;
                        currentX += item.Value.width + glyphInterval;
                    }
                }

                // if there is no glyph
                // or if there is only 1 line of glyph.
                if (maxWidth < currentX)
                {
                    maxWidth = currentX;
                }

                if (currentX > leftMargin)// last line is not finished.
                {
                    maxHeight = currentY + maxGlyphHeight;
                }
                else// last line is finished and new line is started and new line has no glyph.
                {
                    maxHeight = currentY;
                }

                width  = maxWidth;
                height = maxHeight;
            }
        }
        private static FontTexture InitializeDefaultFontTexture()
        {
            Font        font        = new Font("Arial", 64.0f, FontStyle.Regular, GraphicsUnit.Pixel);// SystemFonts.DefaultFont;
            FontBitmap  fontBitmap  = font.GetFontBitmap(defaultCharSet);
            FontTexture fontTexture = fontBitmap.GetFontTexture();

            return(fontTexture);
        }
        /// <summary>
        /// Get glyph's size by graphics.MeasureString().
        /// Then shrink glyph's size.
        /// xoffset now means offset in a single glyph's bitmap.
        /// </summary>
        /// <param name="fontBitmap"></param>
        /// <param name="charSet"></param>
        /// <param name="singleCharWidth"></param>
        /// <param name="singleCharHeight"></param>
        private static void PrepareInitialGlyphDict(FontBitmap fontBitmap, string charSet, out int singleCharWidth, out int singleCharHeight)
        {
            // Get glyph's size by graphics.MeasureString().
            {
                int maxWidth = 0, maxHeight = 0;

                float fontSize = fontBitmap.GlyphFont.Size;

                using (var bitmap = new Bitmap(1, 1, PixelFormat.Format24bppRgb))
                {
                    using (Graphics graphics = Graphics.FromImage(bitmap))
                    {
                        foreach (char c in charSet)
                        {
                            SizeF size = graphics.MeasureString(c.ToString(), fontBitmap.GlyphFont);
                            var   info = new GlyphInfo(0, 0, (int)size.Width, (int)size.Height);
                            fontBitmap.GlyphInfoDictionary.Add(c, info);
                            if (maxWidth < (int)size.Width)
                            {
                                maxWidth = (int)size.Width;
                            }
                            if (maxHeight < (int)size.Height)
                            {
                                maxHeight = (int)size.Height;
                            }
                        }
                    }
                }
                singleCharWidth  = maxWidth;
                singleCharHeight = maxHeight;
            }
            // shrink glyph's size.
            // xoffset now means offset in a single glyph's bitmap.
            {
                using (var bitmap = new Bitmap(singleCharWidth, singleCharHeight))
                {
                    using (var graphics = Graphics.FromImage(bitmap))
                    {
                        Color clearColor = Color.FromArgb(0, 0, 0, 0);
                        foreach (var item in fontBitmap.GlyphInfoDictionary)
                        {
                            if (item.Key == ' ' || item.Key == '\t' || item.Key == '\r' || item.Key == '\n')
                            {
                                continue;
                            }

                            graphics.Clear(clearColor);
                            graphics.DrawString(item.Key.ToString(), fontBitmap.GlyphFont, Brushes.White, 0, 0);
                            BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
                            RetargetGlyphRectangleInwards(data, item.Value);
                            bitmap.UnlockBits(data);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// prepare final bitmap's size.
        /// </summary>
        /// <param name="fontBitmap"></param>
        /// <param name="width">final bitmap's width.</param>
        /// <param name="height">final bitmap's height.</param>
        private static void PrepareFinalBitmapSize(FontBitmap fontBitmap, out int width, out int height)
        {
            int sideLength;
            int maxGlyphHeight = 0;
            {
                int totalWidth = 0;
                foreach (GlyphInfo item in fontBitmap.GlyphInfoDictionary.Values)
                {
                    totalWidth += item.width + glyphInterval;
                    if (maxGlyphHeight < item.height) { maxGlyphHeight = item.height; }
                }
                int area = totalWidth * maxGlyphHeight;
                sideLength = (int)Math.Ceiling(Math.Sqrt(area));
                fontBitmap.GlyphHeight = maxGlyphHeight;
            }
            {
                int maxWidth = 0, maxHeight = 0;
                int currentX = leftMargin, currentY = 0;
                foreach (KeyValuePair<char, GlyphInfo> item in fontBitmap.GlyphInfoDictionary)
                {
                    if (currentX + item.Value.width < sideLength)
                    {
                        currentX += item.Value.width + glyphInterval;
                    }
                    else// new row will start.
                    {
                        if (maxWidth < currentX) { maxWidth = currentX; }
                        currentX = leftMargin;
                        currentY += maxGlyphHeight;
                        currentX += item.Value.width + glyphInterval;
                    }
                }

                // if there is no glyph
                // or if there is only 1 line of glyph.
                if (maxWidth < currentX) { maxWidth = currentX; }

                if (currentX > leftMargin)// last line is not finished.
                {
                    maxHeight = currentY + maxGlyphHeight;
                }
                else// last line is finished and new line is started and new line has no glyph.
                {
                    maxHeight = currentY;
                }

                width = maxWidth;
                height = maxHeight;
            }
        }
        /// <summary>
        /// Get glyph's size by graphics.MeasureString().
        /// Then shrink glyph's size.
        /// xoffset now means offset in a single glyph's bitmap.
        /// </summary>
        /// <param name="fontBitmap"></param>
        /// <param name="charSet"></param>
        /// <param name="singleCharWidth"></param>
        /// <param name="singleCharHeight"></param>
        private static void PrepareInitialGlyphDict(FontBitmap fontBitmap, string charSet, out int singleCharWidth, out int singleCharHeight)
        {
            // Get glyph's size by graphics.MeasureString().
            {
                int maxWidth = 0, maxHeight = 0;

                float fontSize = fontBitmap.GlyphFont.Size;

                using (var bitmap = new Bitmap(1, 1, PixelFormat.Format24bppRgb))
                {
                    using (Graphics graphics = Graphics.FromImage(bitmap))
                    {
                        foreach (char c in charSet)
                        {
                            SizeF size = graphics.MeasureString(c.ToString(), fontBitmap.GlyphFont);
                            var info = new GlyphInfo(0, 0, (int)size.Width, (int)size.Height);
                            fontBitmap.GlyphInfoDictionary.Add(c, info);
                            if (maxWidth < (int)size.Width) { maxWidth = (int)size.Width; }
                            if (maxHeight < (int)size.Height) { maxHeight = (int)size.Height; }
                        }
                    }
                }
                singleCharWidth = maxWidth;
                singleCharHeight = maxHeight;
            }
            // shrink glyph's size.
            // xoffset now means offset in a single glyph's bitmap.
            {
                using (var bitmap = new Bitmap(singleCharWidth, singleCharHeight))
                {
                    using (var graphics = Graphics.FromImage(bitmap))
                    {
                        Color clearColor = Color.FromArgb(0, 0, 0, 0);
                        foreach (KeyValuePair<char, GlyphInfo> item in fontBitmap.GlyphInfoDictionary)
                        {
                            if (item.Key == ' ' || item.Key == '\t' || item.Key == '\r' || item.Key == '\n') { continue; }

                            graphics.Clear(clearColor);
                            graphics.DrawString(item.Key.ToString(), fontBitmap.GlyphFont, Brushes.White, 0, 0);
                            BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
                            RetargetGlyphRectangleInwards(data, item.Value);
                            bitmap.UnlockBits(data);
                        }
                    }
                }
            }
        }
Пример #7
0
        /// <summary>
        /// Gets an instance of <see cref="FontTexture"/>.
        /// </summary>
        /// <param name="fontBitmap"></param>
        /// <param name="parameters"></param>
        /// <param name="mipmapFiltering"></param>
        /// <returns></returns>
        public static FontTexture GetFontTexture(this FontBitmap fontBitmap,
                                                 SamplerParameters parameters = null,
                                                 MipmapFilter mipmapFiltering = MipmapFilter.LinearMipmapLinear)
        {
            var texture = new Texture(fontBitmap.GlyphBitmap,
                                      parameters, mipmapFiltering);

            texture.Initialize();
            var result = new FontTexture();

            result.GlyphFont           = fontBitmap.GlyphFont;
            result.GlyphHeight         = fontBitmap.GlyphHeight;
            result.TextureSize         = fontBitmap.GlyphBitmap.Size;
            result.GlyphInfoDictionary = fontBitmap.GlyphInfoDictionary;
            result.TextureObj          = texture;
            return(result);
        }
Пример #8
0
        /// <summary>
        /// Print the final bitmap that contains all glyphs.
        /// And also setup glyph's xoffset, yoffset.
        /// </summary>
        /// <param name="fontBitmap"></param>
        /// <param name="singleCharWidth"></param>
        /// <param name="singleCharHeight"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        private static void PrintBitmap(FontBitmap fontBitmap, int singleCharWidth, int singleCharHeight, int width, int height)
        {
            var bitmap = new Bitmap(width, height);

            using (var graphics = Graphics.FromImage(bitmap))
            {
                using (var glyphBitmap = new Bitmap(singleCharWidth, singleCharHeight))
                {
                    using (var glyphGraphics = Graphics.FromImage(glyphBitmap))
                    {
                        int   currentX = leftMargin, currentY = 0;
                        Color clearColor = Color.FromArgb(0, 0, 0, 0);
                        foreach (KeyValuePair <char, GlyphInfo> item in fontBitmap.GlyphInfoDictionary)
                        {
                            glyphGraphics.Clear(clearColor);
                            glyphGraphics.DrawString(item.Key.ToString(), fontBitmap.GlyphFont,
                                                     Brushes.White, 0, 0);
                            // move to new line if this line is full.
                            if (currentX + item.Value.width > width)
                            {
                                currentX  = leftMargin;
                                currentY += singleCharHeight;
                            }
                            // draw the current glyph.
                            graphics.DrawImage(glyphBitmap,
                                               new Rectangle(currentX, currentY, item.Value.width, item.Value.height),
                                               item.Value.ToRectangle(),
                                               GraphicsUnit.Pixel);
                            // move line cursor to next(right) position.
                            item.Value.xoffset = currentX;
                            item.Value.yoffset = currentY;
                            // prepare for next glyph's position.
                            currentX += item.Value.width + glyphInterval;
                        }
                    }
                }
            }

            fontBitmap.GlyphBitmap = bitmap;
        }
        /// <summary>
        /// Print the final bitmap that contains all glyphs.
        /// And also setup glyph's xoffset, yoffset.
        /// </summary>
        /// <param name="fontBitmap"></param>
        /// <param name="singleCharWidth"></param>
        /// <param name="singleCharHeight"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        private static void PrintBitmap(FontBitmap fontBitmap, int singleCharWidth, int singleCharHeight, int width, int height)
        {
            var bitmap = new Bitmap(width, height);
            using (var graphics = Graphics.FromImage(bitmap))
            {
                using (var glyphBitmap = new Bitmap(singleCharWidth, singleCharHeight))
                {
                    using (var glyphGraphics = Graphics.FromImage(glyphBitmap))
                    {
                        int currentX = leftMargin, currentY = 0;
                        Color clearColor = Color.FromArgb(0, 0, 0, 0);
                        foreach (KeyValuePair<char, GlyphInfo> item in fontBitmap.GlyphInfoDictionary)
                        {
                            glyphGraphics.Clear(clearColor);
                            glyphGraphics.DrawString(item.Key.ToString(), fontBitmap.GlyphFont,
                                Brushes.White, 0, 0);
                            // move to new line if this line is full.
                            if (currentX + item.Value.width > width)
                            {
                                currentX = leftMargin;
                                currentY += singleCharHeight;
                            }
                            // draw the current glyph.
                            graphics.DrawImage(glyphBitmap,
                                new Rectangle(currentX, currentY, item.Value.width, item.Value.height),
                                item.Value.ToRectangle(),
                                GraphicsUnit.Pixel);
                            // move line cursor to next(right) position.
                            item.Value.xoffset = currentX;
                            item.Value.yoffset = currentY;
                            // prepare for next glyph's position.
                            currentX += item.Value.width + glyphInterval;
                        }
                    }
                }
            }

            fontBitmap.GlyphBitmap = bitmap;
        }
Пример #10
0
        /// <summary>
        /// Gets a <see cref="FontBitmap"/>'s intance.
        /// </summary>
        /// <param name="font">建议最大字体不超过32像素高度,否则可能无法承载所有Unicode字符。</param>
        /// <param name="charSet"></param>
        /// <param name="drawBoundary"></param>
        /// <returns></returns>
        public static FontBitmap GetFontBitmap(this Font font, string charSet, bool drawBoundary = false)
        {
            var fontBitmap = new FontBitmap();

            fontBitmap.GlyphFont = font; //fontBitmap.GlyphInfoDictionary //fontBitmap.GlyphHeight //fontBitmap.GlyphBitmap
            // 先获取各个glyph的width和height
            fontBitmap.GlyphInfoDictionary = GetGlyphDict(font, charSet);
            // 获取所有glyph的面积之和,开方得到最终贴图的宽度textureWidth
            int textureWidth = GetTextureWidth(fontBitmap.GlyphInfoDictionary);

            // 以所有glyph中height最大的为标准高度
            fontBitmap.GlyphHeight = GetGlyphHeight(fontBitmap.GlyphInfoDictionary, textureWidth);
            // 摆放glyph,得到x偏移和y偏移量,同时顺便得到最终贴图的高度textureHeight
            int textureHeight = LayoutGlyphs(fontBitmap.GlyphInfoDictionary, textureWidth, fontBitmap.GlyphHeight);

            // 根据glyph的摆放位置,生成最终的贴图
            fontBitmap.GlyphBitmap = PaintTexture(textureWidth, textureHeight, fontBitmap.GlyphInfoDictionary, font);

            if (drawBoundary)
            {
                using (var graphics = Graphics.FromImage(fontBitmap.GlyphBitmap))
                {
                    bool odd = false;
                    foreach (GlyphInfo item in fontBitmap.GlyphInfoDictionary.Values)
                    {
                        graphics.DrawRectangle(
                            odd ? Pens.Green : Pens.Blue,
                            item.ToRectangle(1, 1, -2, -1));
                        odd = !odd;
                    }
                    graphics.DrawRectangle(Pens.Red, 0, 0, fontBitmap.GlyphBitmap.Width - 1, fontBitmap.GlyphBitmap.Height - 1);
                }
            }
            //fontBitmap.GlyphBitmap.Save("aaaaaaaaaaaaa.png");
            return(fontBitmap);
        }