Пример #1
0
        public static Bitmap Convert(this FTBitmap ftbmp, Color color, uint charCode)
        {
            switch (ftbmp.PixelMode)
            {
            case PixelMode.Mono:
                return(FromMono(ftbmp, color));

            case PixelMode.Gray4:
                throw new NotImplementedException();

            case PixelMode.Gray:
                return(FromGray(ftbmp, color));

            case PixelMode.Lcd:
                throw new NotImplementedException();

            default:
#if NET45
                return(ftbmp.ToGdipBitmap());
#else
                throw new NotImplementedException();
#endif
            }
        }
Пример #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
        public Texture2D RenderString(Face font, string text, Color4 foreColor, Color4 backColor, bool wrapText)
        {
            LineMetrics[] metrics = formatText(font, text, wrapText);

            float maxWidth = 0f, maxHeight = 0f, totalHeight = 0f;

            for (int lineIndex = 0; lineIndex < metrics.Length; lineIndex++)
            {
                LineMetrics lineMetric = metrics[lineIndex];
                maxWidth  = (lineMetric.Width > maxWidth) ? lineMetric.Width : maxWidth;
                maxHeight = (lineMetric.Height > maxHeight) ? lineMetric.Height : maxHeight;

                //Check is to ensure we don't have additional extra space accumulating beneath the texture for large Heights (commas being an example)
                totalHeight += (lineIndex < metrics.Length - 1) ? lineMetric.BaseHeight + LineSpacing : lineMetric.Height;

                metrics[lineIndex] = lineMetric;
            }

            //If any dimension is 0, we can't create a bitmap
            if (maxWidth <= 0 || totalHeight <= 0)
            {
                return(null);
            }

            //Create a new bitmap that fits the string.
            Bitmap bmp = new Bitmap((int)Math.Ceiling(maxWidth), (int)Math.Ceiling(totalHeight));

            using (var g = Graphics.FromImage(bmp))
            {
                #region Rendering Code
                g.CompositingQuality = CompositingQuality.HighQuality;
                g.SmoothingMode      = SmoothingMode.HighQuality;
                g.CompositingMode    = CompositingMode.SourceOver;

                g.Clear((Color)backColor);

                //Draw the string into the bitmap.
                float lineOffset = 0f;
                for (int lineIndex = 0; lineIndex < metrics.Length; lineIndex++)
                {
                    LineMetrics lineMetrics = metrics[lineIndex];

                    //float xOffset = (maxWidth - lineMetrics.Width) / 2f; //Centered
                    float xOffset = 0f;
                    //float xOffset = maxWidth - lineMetrics.Width - 20f;

                    float penX = 0f, penY = 0f;
                    for (int i = 0; i < lineMetrics.Characters.Count; i++)
                    {
                        var  cm = lineMetrics.Characters[i];
                        char c  = cm.Character;

                        uint glyphIndex = font.GetCharIndex(c);
                        font.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                        font.Glyph.RenderGlyph(RenderMode.Normal);
                        FTBitmap ftbmp = font.Glyph.Bitmap;

                        //Underrun
                        if (penX == 0) //First character
                        {
                            penX += -(cm.BearingX);
                        }

                        //We can't draw a 0-size bitmap, but the pen position will still get advanced.
                        if (ftbmp.Width > 0 && ftbmp.Rows > 0)
                        {
                            using (Bitmap cBmp = ftbmp.ToGdipBitmap((Color)foreColor))
                            {
                                int x = (int)Math.Round(penX + cm.BearingX + xOffset);
                                int y = (int)Math.Round(penY + lineMetrics.Top - cm.BearingY + lineOffset);

                                g.DrawImageUnscaled(cBmp, x, y);
                            }
                        }

                        //Advance pen position for the next character
                        penX += cm.AdvanceX + cm.Kern;
                    }

                    lineOffset += lineMetrics.BaseHeight + LineSpacing;
                }
                #endregion
            }

            Texture2D texture = Texture2D.CreateFromBitmap(bmp);
            bmp.Dispose();

            return(texture);
        }
Пример #4
0
        internal static Bitmap RenderString(Library library, Face face, string text, Color foreColor, Color backColor)
        {
            var   measuredChars = new List <DebugChar>();
            var   renderedChars = new List <DebugChar>();
            float penX = 0, penY = 0;
            float stringWidth      = 0; // the measured width of the string
            float stringHeight     = 0; // the measured height of the string
            float overrun          = 0;
            float underrun         = 0;
            float kern             = 0;
            int   spacingError     = 0;
            bool  trackingUnderrun = true;
            int   rightEdge        = 0; // tracking rendered right side for debugging

            // Bottom and top are both positive for simplicity.
            // Drawing in .Net has 0,0 at the top left corner, with positive X to the right
            // and positive Y downward.
            // Glyph metrics have an origin typically on the left side and at baseline
            // of the visual data, but can draw parts of the glyph in any quadrant, and
            // even move the origin (via kerning).
            float top = 0, bottom = 0;

            // Measure the size of the string before rendering it. We need to do this so
            // we can create the proper size of bitmap (canvas) to draw the characters on.
            for (int i = 0; i < text.Length; i++)
            {
                #region Load character
                char c = text[i];

                // Look up the glyph index for this character.
                uint glyphIndex = face.GetCharIndex(c);

                // Load the glyph into the font's glyph slot. There is usually only one slot in the font.
                face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);

                // Refer to the diagram entitled "Glyph Metrics" at http://www.freetype.org/freetype2/docs/tutorial/step2.html.
                // There is also a glyph diagram included in this example (glyph-dims.svg).
                // The metrics below are for the glyph loaded in the slot.
                float gAdvanceX = (float)face.Glyph.Advance.X; // same as the advance in metrics
                float gBearingX = (float)face.Glyph.Metrics.HorizontalBearingX;
                //float gWidth = face.Glyph.Metrics.Width.ToSingle();
                float gWidth = face.Glyph.Metrics.Width;
                var   rc     = new DebugChar(c, gAdvanceX, gBearingX, gWidth);
                #endregion
                #region Underrun
                // Negative bearing would cause clipping of the first character
                // at the left boundary, if not accounted for.
                // A positive bearing would cause empty space.
                underrun += -(gBearingX);
                if (stringWidth == 0)
                {
                    stringWidth += underrun;
                }
                if (trackingUnderrun)
                {
                    rc.Underrun = underrun;
                }
                if (trackingUnderrun && underrun <= 0)
                {
                    underrun         = 0;
                    trackingUnderrun = false;
                }
                #endregion
                #region Overrun
                // Accumulate overrun, which coould cause clipping at the right side of characters near
                // the end of the string (typically affects fonts with slanted characters)
                if (gBearingX + gWidth > 0 || gAdvanceX > 0)
                {
                    overrun -= Math.Max(gBearingX + gWidth, gAdvanceX);
                    if (overrun <= 0)
                    {
                        overrun = 0;
                    }
                }
                overrun += (float)(gBearingX == 0 && gWidth == 0 ? 0 : gBearingX + gWidth - gAdvanceX);
                // On the last character, apply whatever overrun we have to the overall width.
                // Positive overrun prevents clipping, negative overrun prevents extra space.
                if (i == text.Length - 1)
                {
                    stringWidth += overrun;
                }
                rc.Overrun = overrun; // accumulating (per above)
                #endregion

                #region Top/Bottom
                // If this character goes higher or lower than any previous character, adjust
                // the overall height of the bitmap.
                float glyphTop    = (float)face.Glyph.Metrics.HorizontalBearingY;
                float glyphBottom = (float)(face.Glyph.Metrics.Height - face.Glyph.Metrics.HorizontalBearingY);
                if (glyphTop > top)
                {
                    top = glyphTop;
                }
                if (glyphBottom > bottom)
                {
                    bottom = glyphBottom;
                }
                #endregion

                // Accumulate the distance between the origin of each character (simple width).
                stringWidth += gAdvanceX;
                rc.RightEdge = stringWidth;
                measuredChars.Add(rc);

                #region Kerning (for NEXT character)
                // Calculate kern for the NEXT character (if any)
                // The kern value adjusts the origin of the next character (positive or negative).
                if (face.HasKerning && i < text.Length - 1)
                {
                    char cNext = text[i + 1];
                    kern = (float)face.GetKerning(glyphIndex, face.GetCharIndex(cNext), KerningMode.Default).X;
                    // sanity check for some fonts that have kern way out of whack
                    if (kern > gAdvanceX * 5 || kern < -(gAdvanceX * 5))
                    {
                        kern = 0;
                    }
                    rc.Kern      = kern;
                    stringWidth += kern;
                }

                #endregion
            }

            stringHeight = top + bottom;

            // If any dimension is 0, we can't create a bitmap
            if (stringWidth == 0 || stringHeight == 0)
            {
                return(null);
            }

            // Create a new bitmap that fits the string.
            Bitmap bmp = new Bitmap((int)Math.Ceiling(stringWidth), (int)Math.Ceiling(stringHeight));
            trackingUnderrun = true;
            underrun         = 0;
            overrun          = 0;
            stringWidth      = 0;
            using (var g = Graphics.FromImage(bmp))
            {
                #region Set up graphics
                // HighQuality and GammaCorrected both specify gamma correction be applied (2.2 in sRGB)
                // https://msdn.microsoft.com/en-us/library/windows/desktop/ms534094(v=vs.85).aspx
                g.CompositingQuality = CompositingQuality.HighQuality;
                // HighQuality and AntiAlias both specify antialiasing
                g.SmoothingMode = SmoothingMode.HighQuality;
                // If a background color is specified, blend over it.
                g.CompositingMode = CompositingMode.SourceOver;

                g.Clear(backColor);
                #endregion

                // Draw the string into the bitmap.
                // A lot of this is a repeat of the measuring steps, but this time we have
                // an actual bitmap to work with (both canvas and bitmaps in the glyph slot).
                for (int i = 0; i < text.Length; i++)
                {
                    #region Load character
                    char c = text[i];

                    // Same as when we were measuring, except RenderGlyph() causes the glyph data
                    // to be converted to a bitmap.
                    uint glyphIndex = face.GetCharIndex(c);
                    face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                    face.Glyph.RenderGlyph(RenderMode.Normal);
                    FTBitmap ftbmp = face.Glyph.Bitmap;

                    float gAdvanceX = (float)face.Glyph.Advance.X;
                    float gBearingX = (float)face.Glyph.Metrics.HorizontalBearingX;
                    float gWidth    = (float)face.Glyph.Metrics.Width;

                    var rc = new DebugChar(c, gAdvanceX, gBearingX, gWidth);
                    #endregion
                    #region Underrun
                    // Underrun
                    underrun += -(gBearingX);
                    if (penX == 0)
                    {
                        penX += underrun;
                    }
                    if (trackingUnderrun)
                    {
                        rc.Underrun = underrun;
                    }
                    if (trackingUnderrun && underrun <= 0)
                    {
                        underrun         = 0;
                        trackingUnderrun = false;
                    }
                    #endregion
                    #region Draw glyph
                    // Whitespace characters sometimes have a bitmap of zero size, but a non-zero advance.
                    // We can't draw a 0-size bitmap, but the pen position will still get advanced (below).
                    if ((ftbmp.Width > 0 && ftbmp.Rows > 0))
                    {
                        // Get a bitmap that .Net can draw (GDI+ in this case).
                        Bitmap cBmp = ftbmp.ToGdipBitmap(foreColor);
                        rc.Width    = cBmp.Width;
                        rc.BearingX = face.Glyph.BitmapLeft;
                        int x = (int)Math.Round(penX + face.Glyph.BitmapLeft);
                        int y = (int)Math.Round(penY + top - (float)face.Glyph.Metrics.HorizontalBearingY);
                        //Not using g.DrawImage because some characters come out blurry/clipped. (Is this still true?)
                        g.DrawImageUnscaled(cBmp, x, y);
                        rc.Overrun = face.Glyph.BitmapLeft + cBmp.Width - gAdvanceX;
                        // Check if we are aligned properly on the right edge (for debugging)
                        rightEdge    = Math.Max(rightEdge, x + cBmp.Width);
                        spacingError = bmp.Width - rightEdge;
                    }
                    else
                    {
                        rightEdge    = (int)(penX + gAdvanceX);
                        spacingError = bmp.Width - rightEdge;
                    }
                    #endregion

                    #region Overrun
                    if (gBearingX + gWidth > 0 || gAdvanceX > 0)
                    {
                        overrun -= Math.Max(gBearingX + gWidth, gAdvanceX);
                        if (overrun <= 0)
                        {
                            overrun = 0;
                        }
                    }
                    overrun += (float)(gBearingX == 0 && gWidth == 0 ? 0 : gBearingX + gWidth - gAdvanceX);
                    if (i == text.Length - 1)
                    {
                        penX += overrun;
                    }
                    rc.Overrun = overrun;
                    #endregion

                    // Advance pen positions for drawing the next character.
                    penX += (float)face.Glyph.Advance.X; // same as Metrics.HorizontalAdvance?
                    penY += (float)face.Glyph.Advance.Y;

                    rc.RightEdge = penX;
                    spacingError = bmp.Width - (int)Math.Round(rc.RightEdge);
                    renderedChars.Add(rc);

                    #region Kerning (for NEXT character)
                    // Adjust for kerning between this character and the next.
                    if (face.HasKerning && i < text.Length - 1)
                    {
                        char cNext = text[i + 1];
                        kern = (float)face.GetKerning(glyphIndex, face.GetCharIndex(cNext), KerningMode.Default).X;
                        if (kern > gAdvanceX * 5 || kern < -(gAdvanceX * 5))
                        {
                            kern = 0;
                        }
                        rc.Kern = kern;
                        penX   += (float)kern;
                    }
                    #endregion
                }
            }
            bool printedHeader = false;
            if (spacingError != 0)
            {
                for (int i = 0; i < renderedChars.Count; i++)
                {
                    //if (measuredChars[i].RightEdge != renderedChars[i].RightEdge)
                    //{
                    if (!printedHeader)
                    {
                        DebugChar.PrintHeader();
                    }
                    printedHeader = true;
                    Debug.Print(measuredChars[i].ToString());
                    Debug.Print(renderedChars[i].ToString());
                    //}
                }
                string msg = string.Format("Right edge: {0,3} ({1}) {2}",
                                           spacingError,
                                           spacingError == 0 ? "perfect" : spacingError > 0 ? "space  " : "clipped",
                                           face.FamilyName);
                System.Diagnostics.Debug.Print(msg);
                //throw new ApplicationException(msg);
            }
            return(bmp);
        }
Пример #5
0
        public NISFont DrawT3BFontBitmap(char[] strings)
        {
            NISFont  fnt_data = new NISFont();
            Bitmap   bmp      = new Bitmap(Config.texture_width, Config.texture_height);
            Graphics g        = Graphics.FromImage(bmp);

            g.Clear(Color.FromArgb(0x00000000));
            int     x = 0, y = 0;
            int     tile_w = Config.fontWidth;
            int     tile_h = Config.fontHeight;
            int     relativePositionX = 1;
            int     relativePositionY = -2;
            int     font_height = Config.fontSize;
            Library library = new Library();
            string  facename = Config.ttfName;
            Face    face = library.NewFace(facename, 0);
            float   left, right, top, bottom, FHT;
            int     FHD, kx, ky;

            foreach (char currentChar0 in strings)
            {
                uint charid = uchar2code(currentChar0.ToString());
                face.SetCharSize(0, font_height, 0, 72);
                if (charid < 0x7f)
                {
                    font_height = Config.fontSize - 2;
                    face.SetCharSize(0, font_height, 0, 72);
                }
                else
                {
                    font_height = Config.fontSize;
                }
                face.SetPixelSizes((uint)0, (uint)font_height);

                uint glyphIndex = face.GetCharIndex(charid);

                //Console.WriteLine(glyphIndex);
                face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Lcd);
                face.Glyph.Outline.Embolden(0.5);
                face.Glyph.RenderGlyph(RenderMode.Normal);

                FTBitmap ftbmp  = face.Glyph.Bitmap;
                FTBitmap ftbmp2 = face.Glyph.Bitmap;

                left   = (float)face.Glyph.Metrics.HorizontalBearingX;
                right  = (float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width;
                top    = (float)face.Glyph.Metrics.HorizontalBearingY;
                bottom = (float)face.Glyph.Metrics.HorizontalBearingY + (float)face.Glyph.Metrics.Height;

                FHT = font_height;
                FHD = (int)Math.Ceiling(FHT);
                kx  = x + (int)Math.Round(left);
                ky  = (int)Math.Round((float)y + (float)Math.Ceiling(FHT) - (float)top);


                if (ftbmp.Width == 0 || glyphIndex < 0x20)
                {
                    Face face1 = library.NewFace(Config.baseName, 0);
                    face1.SetCharSize(0, font_height, 0, 72);
                    face1.SetPixelSizes((uint)0, (uint)font_height);
                    glyphIndex = face1.GetCharIndex(charid);
                    face1.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Lcd);
                    face1.Glyph.Outline.Embolden(Fixed26Dot6.FromDouble(0.4));
                    face1.Glyph.RenderGlyph(RenderMode.Normal);

                    left   = (float)face1.Glyph.Metrics.HorizontalBearingX;
                    right  = (float)face1.Glyph.Metrics.HorizontalBearingX + (float)face1.Glyph.Metrics.Width;
                    top    = (float)face1.Glyph.Metrics.HorizontalBearingY;
                    bottom = (float)face1.Glyph.Metrics.HorizontalBearingY + (float)face1.Glyph.Metrics.Height;

                    FHT    = font_height;
                    FHD    = (int)Math.Ceiling(FHT);
                    kx     = x + (int)Math.Round(left);
                    ky     = (int)Math.Round((float)y + (float)Math.Ceiling(FHT) - (float)top);
                    ftbmp  = face1.Glyph.Bitmap;
                    ftbmp2 = face1.Glyph.Bitmap;
                }

                fnt_data.charvalues.Add(new XYWH((int)uchar2code(currentChar0.ToString()),
                                                 x,
                                                 y,
                                                 tile_w,
                                                 tile_h,
                                                 0));

                if (ftbmp2.Width == 0)
                {
                    x += tile_w;
                    if (x + tile_w > Config.texture_width)
                    {
                        x  = 0;
                        y += tile_h;
                    }
                    continue;
                }
                Bitmap cBmp = ftbmp2.ToGdipBitmap(Color.White);
                g.DrawImageUnscaled(cBmp, kx + relativePositionX, ky + relativePositionY);
                g.DrawImageUnscaled(cBmp, kx + relativePositionX, ky + relativePositionY);
                cBmp.Dispose();



                x += tile_w;
                if (x + tile_w > Config.texture_width)
                {
                    x  = 0;
                    y += tile_h;
                }
            }
            fnt_data.bitmap = bmp;
            return(fnt_data);
        }
Пример #6
0
        public Bitmap test_draw(string teststrings)
        {
            //teststrings = teststrings.Replace("\n" , "");
            //teststrings = teststrings.Replace("\r", "");
            Library library = new Library();
            Face    face    = library.NewFace(fontName, 0);


            Bitmap   bmp = new Bitmap((int)Math.Ceiling((double)image_width), (int)Math.Ceiling((double)image_height));
            Graphics g   = Graphics.FromImage(bmp);

            g.Clear(GlobalSettings.cBgColor);
            //g.Clear(Color.Black);
            int x = 0, y = 0;

            for (int i = 0; i < teststrings.ToCharArray().Length; i++)
            {
                string currentChar0 = teststrings.ToCharArray()[i].ToString();
                uint   glyphIndex   = face.GetCharIndex(uchar2code(currentChar0));



                if (this.fontHeight <= 14)
                {
                    face.SetPixelSizes((uint)0, (uint)this.fontHeight);
                    face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                    face.Glyph.RenderGlyph(RenderMode.Normal);
                }
                else
                {
                    face.SetCharSize(0, this.fontHeight, 0, 72);
                    face.LoadGlyph(glyphIndex, LoadFlags.ForceAutohint, LoadTarget.Lcd);
                    face.Glyph.RenderGlyph(RenderMode.Lcd);
                }

                //获取字符对齐
                float left, right, top, bottom, FHT;
                int   FHD, kx, ky;

                left   = (float)face.Glyph.Metrics.HorizontalBearingX;
                right  = (float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width;
                top    = (float)face.Glyph.Metrics.HorizontalBearingY;
                bottom = (float)face.Glyph.Metrics.HorizontalBearingY + (float)face.Glyph.Metrics.Height;
                FHT    = this.fontHeight;
                FHD    = (int)Math.Ceiling(FHT);
                kx     = x + face.Glyph.BitmapLeft;
                ky     = (int)Math.Round((float)y + (FHD - face.Glyph.BitmapTop));

                //选择渲染模式(1倍 or 2倍)
                if (this.grender_mode == "freetype_nearestneighbor")
                {
                    face.SetCharSize(0, this.fontHeight * 2, 0, 72);
                    face.LoadGlyph(glyphIndex, LoadFlags.ForceAutohint, LoadTarget.Lcd);
                    face.Glyph.RenderGlyph(RenderMode.Lcd);
                    left   = (float)face.Glyph.Metrics.HorizontalBearingX;
                    right  = (float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width;
                    top    = (float)face.Glyph.Metrics.HorizontalBearingY;
                    bottom = (float)face.Glyph.Metrics.HorizontalBearingY + (float)face.Glyph.Metrics.Height;
                    FHT    = this.fontHeight;
                    FHD    = (int)Math.Ceiling(FHT);
                    kx     = x + face.Glyph.BitmapLeft;
                    ky     = (int)Math.Round((float)y + (FHD - face.Glyph.BitmapTop));


                    kx = x + face.Glyph.BitmapLeft;
                    ky = (int)Math.Round((float)y + (FHD - (float)face.Glyph.Metrics.HorizontalBearingY));
                    FTBitmap ftbmp = face.Glyph.Bitmap;
                    if (ftbmp.Width == 0)
                    {
                        x += this.tile_width;
                        if (x + this.tile_width > this.image_width)
                        {
                            x  = 0;
                            y += this.tile_height;
                        }
                        continue;
                    }

                    Bitmap tmpBmp = ftbmp.ToGdipBitmap(this.penColor);

                    tmpBmp = kPasteImage(tmpBmp, tile_width * 2, tile_height * 2, (int)face.Glyph.BitmapLeft,
                                         (int)Math.Round(((float)this.fontHeight * 2 - face.Glyph.BitmapTop)));

                    Bitmap cBmp = kResizeImage(tmpBmp, tmpBmp.Width / 2, tmpBmp.Height / 2, System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor);
                    Bitmap nBmp = gray2alpha(cBmp);
                    cBmp.Dispose();

                    g.DrawImageUnscaled(nBmp, x + GlobalSettings.relativePositionX, y + GlobalSettings.relativePositionY);
                    nBmp.Dispose();
                }
                else if (this.grender_mode == "freetype_HighQualityBicubic")
                {
                    face.SetCharSize(0, this.fontHeight * 2, 0, 72);
                    face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                    face.Glyph.RenderGlyph(RenderMode.Normal);
                    left   = (float)face.Glyph.Metrics.HorizontalBearingX;
                    right  = (float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width;
                    top    = (float)face.Glyph.Metrics.HorizontalBearingY;
                    bottom = (float)face.Glyph.Metrics.HorizontalBearingY + (float)face.Glyph.Metrics.Height;
                    FHT    = this.fontHeight;
                    FHD    = (int)Math.Ceiling(FHT);
                    kx     = x + face.Glyph.BitmapLeft;
                    ky     = (int)Math.Round((float)y + (FHD - face.Glyph.BitmapTop));


                    kx = x + face.Glyph.BitmapLeft;
                    ky = (int)Math.Round((float)y + (FHD - (float)face.Glyph.Metrics.HorizontalBearingY));
                    FTBitmap ftbmp = face.Glyph.Bitmap;
                    if (ftbmp.Width == 0)
                    {
                        x += this.tile_width;
                        if (x + this.tile_width > this.image_width)
                        {
                            x  = 0;
                            y += this.tile_height;
                        }
                        continue;
                    }

                    Bitmap tmpBmp = ftbmp.ToGdipBitmap(this.penColor);

                    tmpBmp = kPasteImage(tmpBmp, tile_width * 2, tile_height * 2, (int)face.Glyph.BitmapLeft,
                                         (int)Math.Round(((float)this.fontHeight * 2 - face.Glyph.BitmapTop)));

                    Bitmap cBmp = kResizeImage(tmpBmp, tmpBmp.Width / 2, tmpBmp.Height / 2, System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic);
                    Bitmap nBmp = gray2alpha(cBmp);
                    cBmp.Dispose();

                    g.DrawImageUnscaled(nBmp, x + GlobalSettings.relativePositionX, y + GlobalSettings.relativePositionY);
                    nBmp.Dispose();
                }
                else if (this.grender_mode == "freetype_drawtwice")
                {
                    face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                    face.Glyph.RenderGlyph(RenderMode.Normal);
                    left   = (float)face.Glyph.Metrics.HorizontalBearingX;
                    right  = (float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width;
                    top    = (float)face.Glyph.Metrics.HorizontalBearingY;
                    bottom = (float)face.Glyph.Metrics.HorizontalBearingY + (float)face.Glyph.Metrics.Height;
                    FHT    = this.fontHeight;
                    FHD    = (int)Math.Ceiling(FHT);
                    kx     = x + face.Glyph.BitmapLeft;
                    ky     = (int)Math.Round((float)y + (FHD - face.Glyph.BitmapTop));


                    kx = x + face.Glyph.BitmapLeft;
                    ky = (int)Math.Round((float)y + (FHD - (float)face.Glyph.Metrics.HorizontalBearingY));
                    FTBitmap ftbmp = face.Glyph.Bitmap;
                    if (ftbmp.Width == 0)
                    {
                        x += this.tile_width;
                        if (x + this.tile_width > this.image_width)
                        {
                            x  = 0;
                            y += this.tile_height;
                        }
                        continue;
                    }

                    //这是一个临时描边的功能,还没有添加到UI
                    if (GlobalSettings.bUseOutlineEffect == true)
                    {
                        Bitmap cBmp = ftbmp.ToGdipBitmap(this.penColor);
                        face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                        face.Glyph.Outline.Embolden(2);
                        face.Glyph.RenderGlyph(RenderMode.Normal);

                        left   = (float)face.Glyph.Metrics.HorizontalBearingX;
                        right  = (float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width;
                        top    = (float)face.Glyph.Metrics.HorizontalBearingY;
                        bottom = (float)face.Glyph.Metrics.HorizontalBearingY + (float)face.Glyph.Metrics.Height;
                        FHT    = this.fontHeight;
                        FHD    = (int)Math.Ceiling(FHT);
                        kx     = x + face.Glyph.BitmapLeft;
                        ky     = (int)Math.Round((float)y + (FHD - face.Glyph.BitmapTop));

                        kx = x + face.Glyph.BitmapLeft;
                        ky = (int)Math.Round((float)y + (FHD - (float)face.Glyph.Metrics.HorizontalBearingY));
                        FTBitmap ftbmp1 = face.Glyph.Bitmap;
                        Bitmap   sBmp   = ftbmp1.ToGdipBitmap(GlobalSettings.cShadowColor);
                        Bitmap   nBmp   = gray2alpha(cBmp);
                        //Bitmap s2Bmp = gray2alpha(sBmp);

                        g.DrawImageUnscaled(sBmp, kx + GlobalSettings.relativePositionX - 1, ky + GlobalSettings.relativePositionY - 1);//draw twice
                        g.DrawImageUnscaled(nBmp, kx + GlobalSettings.relativePositionX, ky + GlobalSettings.relativePositionY);
                        cBmp.Dispose();
                        nBmp.Dispose();
                        sBmp.Dispose();
                    }
                    else
                    {
                        Bitmap cBmp = ftbmp.ToGdipBitmap(this.penColor);
                        face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                        face.Glyph.RenderGlyph(RenderMode.Normal);
                        left   = (float)face.Glyph.Metrics.HorizontalBearingX;
                        right  = (float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width;
                        top    = (float)face.Glyph.Metrics.HorizontalBearingY;
                        bottom = (float)face.Glyph.Metrics.HorizontalBearingY + (float)face.Glyph.Metrics.Height;
                        FHT    = this.fontHeight;
                        FHD    = (int)Math.Ceiling(FHT);
                        kx     = x + face.Glyph.BitmapLeft;
                        ky     = (int)Math.Round((float)y + (FHD - face.Glyph.BitmapTop));


                        kx = x + face.Glyph.BitmapLeft;
                        ky = (int)Math.Round((float)y + (FHD - (float)face.Glyph.Metrics.HorizontalBearingY));
                        FTBitmap ftbmp1 = face.Glyph.Bitmap;
                        Bitmap   sBmp   = ftbmp1.ToGdipBitmap(this.penColor);
                        Bitmap   nBmp   = gray2alpha(cBmp);
                        sBmp = gray2alpha(sBmp);
                        g.DrawImageUnscaled(sBmp, kx + GlobalSettings.relativePositionX - 1, ky + GlobalSettings.relativePositionY - 1);//draw twice
                        g.DrawImageUnscaled(nBmp, kx + GlobalSettings.relativePositionX, ky + GlobalSettings.relativePositionY);
                        cBmp.Dispose();
                        nBmp.Dispose();
                        sBmp.Dispose();
                    }
                }
                else if (this.grender_mode == "freetype_nosmoothing")
                {
                    face.SetPixelSizes((uint)0, (uint)this.fontHeight);
                    face.LoadGlyph(glyphIndex, LoadFlags.Monochrome, LoadTarget.Mono);
                    face.Glyph.RenderGlyph(RenderMode.Mono);
                    left   = (float)face.Glyph.Metrics.HorizontalBearingX;
                    right  = (float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width;
                    top    = (float)face.Glyph.Metrics.HorizontalBearingY;
                    bottom = (float)face.Glyph.Metrics.HorizontalBearingY + (float)face.Glyph.Metrics.Height;
                    FHT    = this.fontHeight;
                    FHD    = (int)Math.Ceiling(FHT);
                    kx     = x + face.Glyph.BitmapLeft;
                    ky     = (int)Math.Round((float)y + (FHD - face.Glyph.BitmapTop));

                    kx = x + face.Glyph.BitmapLeft;
                    ky = (int)Math.Round((float)y + (FHD - (float)face.Glyph.Metrics.HorizontalBearingY));
                    FTBitmap ftbmp = face.Glyph.Bitmap;
                    if (ftbmp.Width == 0)
                    {
                        x += this.tile_width;
                        if (x + this.tile_width > this.image_width)
                        {
                            x  = 0;
                            y += this.tile_height;
                        }
                        continue;
                    }
                    Bitmap cBmp = ftbmp.ToGdipBitmap(this.penColor);
                    g.DrawImageUnscaled(cBmp, kx + GlobalSettings.relativePositionX, ky + GlobalSettings.relativePositionY);
                    cBmp.Dispose();
                }


                else
                {
                    face.SetCharSize(0, this.fontHeight, 0, 72);
                    if (GlobalSettings.iFontBold > (float)0)
                    {
                        //临时加粗face.Glyph.Outline.Embolden(0.4);值要小于1,不然很丑
                        face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                        face.Glyph.Outline.Embolden(0.4);
                        face.Glyph.RenderGlyph(RenderMode.Normal);
                        left   = (float)face.Glyph.Metrics.HorizontalBearingX;
                        right  = (float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width;
                        top    = (float)face.Glyph.Metrics.HorizontalBearingY;
                        bottom = (float)face.Glyph.Metrics.HorizontalBearingY + (float)face.Glyph.Metrics.Height;
                        FHT    = this.fontHeight;
                        FHD    = (int)Math.Ceiling(FHT);
                        kx     = x + face.Glyph.BitmapLeft;
                        ky     = (int)Math.Round((float)y + (FHD - face.Glyph.BitmapTop));


                        kx = x + face.Glyph.BitmapLeft;
                        ky = (int)Math.Round((float)y + (FHD - (float)face.Glyph.Metrics.HorizontalBearingY));
                    }



                    FTBitmap ftbmp = face.Glyph.Bitmap;


                    if (ftbmp.Width == 0)
                    {
                        x += this.tile_width;
                        if (x + this.tile_width > this.image_width)
                        {
                            x  = 0;
                            y += this.tile_height;
                        }
                        continue;
                    }
                    if (GlobalSettings.bUseOutlineEffect == true)
                    {
                        Bitmap cBmp = ftbmp.ToGdipBitmap(this.penColor);
                        face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                        face.Glyph.Outline.Embolden(2);
                        face.Glyph.RenderGlyph(RenderMode.Normal);
                        left   = (float)face.Glyph.Metrics.HorizontalBearingX;
                        right  = (float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width;
                        top    = (float)face.Glyph.Metrics.HorizontalBearingY;
                        bottom = (float)face.Glyph.Metrics.HorizontalBearingY + (float)face.Glyph.Metrics.Height;
                        FHT    = this.fontHeight;
                        FHD    = (int)Math.Ceiling(FHT);
                        kx     = x + face.Glyph.BitmapLeft;
                        ky     = (int)Math.Round((float)y + (FHD - face.Glyph.BitmapTop));


                        kx = x + face.Glyph.BitmapLeft;
                        ky = (int)Math.Round((float)y + (FHD - (float)face.Glyph.Metrics.HorizontalBearingY));
                        FTBitmap ftbmp1 = face.Glyph.Bitmap;
                        Bitmap   sBmp   = ftbmp1.ToGdipBitmap(GlobalSettings.cShadowColor);
                        Bitmap   nBmp   = gray2alpha(cBmp);
                        //Bitmap s2Bmp = gray2alpha(sBmp);
                        g.DrawImageUnscaled(sBmp, kx + GlobalSettings.relativePositionX - 1, ky + GlobalSettings.relativePositionY - 1);//draw twice
                        g.DrawImageUnscaled(nBmp, kx + GlobalSettings.relativePositionX, ky + GlobalSettings.relativePositionY);
                        cBmp.Dispose();
                        nBmp.Dispose();
                        sBmp.Dispose();
                    }
                    else
                    {
                        Bitmap cBmp = ftbmp.ToGdipBitmap(this.penColor);
                        Bitmap nBmp = gray2alpha(cBmp);
                        cBmp.Dispose();
                        g.DrawImageUnscaled(nBmp, kx + GlobalSettings.relativePositionX, ky + GlobalSettings.relativePositionY);
                        nBmp.Dispose();
                    }
                }


                x += this.tile_width;
                if (x + this.tile_width > this.image_width)
                {
                    x  = 0;
                    y += this.tile_height;
                }
            }
            g.Dispose();
            library.Dispose();
            return(bmp);
        }
Пример #7
0
        public static Bitmap RenderString(Library library, Face face, string text)
        {
            float penX = 0, penY = 0;
            float width  = 0;
            float height = 0;

            //both bottom and top are positive for simplicity
            float top = 0, bottom = 0;

            //measure the size of the string before rendering it, requirement of Bitmap.
            for (int i = 0; i < text.Length; i++)
            {
                char c = text[i];

                uint glyphIndex = face.GetCharIndex(c);
                face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);

                width += (float)face.Glyph.Advance.X;

                if (face.HasKerning && i < text.Length - 1)
                {
                    char cNext = text[i + 1];
                    width += (float)face.GetKerning(glyphIndex, face.GetCharIndex(cNext), KerningMode.Default).X;
                }

                float glyphTop    = (float)face.Glyph.Metrics.HorizontalBearingY;
                float glyphBottom = (float)(face.Glyph.Metrics.Height - face.Glyph.Metrics.HorizontalBearingY);

                if (glyphTop > top)
                {
                    top = glyphTop;
                }
                if (glyphBottom > bottom)
                {
                    bottom = glyphBottom;
                }
            }

            height = top + bottom;

            //create a new bitmap that fits the string.
            Bitmap   bmp = new Bitmap((int)Math.Ceiling(width), (int)Math.Ceiling(height));
            Graphics g   = Graphics.FromImage(bmp);

            g.Clear(SystemColors.Control);

            //draw the string
            for (int i = 0; i < text.Length; i++)
            {
                char c = text[i];

                uint glyphIndex = face.GetCharIndex(c);
                face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                face.Glyph.RenderGlyph(RenderMode.Normal);

                if (c == ' ')
                {
                    penX += (float)face.Glyph.Advance.X;

                    if (face.HasKerning && i < text.Length - 1)
                    {
                        char cNext = text[i + 1];
                        width += (float)face.GetKerning(glyphIndex, face.GetCharIndex(cNext), KerningMode.Default).X;
                    }

                    penY += (float)face.Glyph.Advance.Y;
                }
                else
                {
                    //FTBitmap ftbmp = face.Glyph.Bitmap.Copy(library);
                    FTBitmap ftbmp = face.Glyph.Bitmap;
                    Bitmap   cBmp  = ftbmp.ToGdipBitmap(Color.Black);

                    //Not using g.DrawImage because some characters come out blurry/clipped.
                    g.DrawImageUnscaled(cBmp, (int)Math.Round(penX + face.Glyph.BitmapLeft), (int)Math.Round(penY + (top - (float)face.Glyph.Metrics.HorizontalBearingY)));

                    penX += (float)face.Glyph.Metrics.HorizontalAdvance;
                    penY += (float)face.Glyph.Advance.Y;

                    if (face.HasKerning && i < text.Length - 1)
                    {
                        char cNext = text[i + 1];
                        var  kern  = face.GetKerning(glyphIndex, face.GetCharIndex(cNext), KerningMode.Default);
                        penX += (float)kern.X;
                    }
                }
            }

            g.Dispose();
            return(bmp);
        }
Пример #8
0
        public void ExportFont(string outputPath)
        {
            // should this be user input?
            int padX = 5;
            int padY = 5;

            int   atlas = 0;
            float posX  = 0;
            float posY  = 0;

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

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

            graphics.Clear(Color.Transparent);

            string output = "module.font = {\n\tinformation = {\n";

            output += "\t\tfamily = \"" + family + "\";\n";
            output += "\t\tstyles = {" + string.Join(", ", getStyles()) + "};\n";
            output += "\t\tsizes = {" + string.Join(", ", sizes) + "};\n";
            output += "\t\tuseEnums = " + useEnums() + ";\n\t};\n";

            output += "\tstyles = {\n";

            foreach (Face face in faces)
            {
                infos[face.StyleName] = new List <Info>();
                output += "\t\t[\"" + face.StyleName + "\"] = {\n";

                foreach (int size in sizes)
                {
                    Info info = new Info(face.StyleName, size);

                    int lineAdvance = 0;
                    int firstAdjust = 0;

                    float width      = 0;
                    float height     = 0;
                    float lineHeight = 0;

                    face.SetCharSize(size * 96 / 72, 0, 96, 96);

                    for (int i = 0; i < characters.Length; i++)
                    {
                        char c     = characters[i];
                        uint index = face.GetCharIndex(c);
                        face.LoadGlyph(index, LoadFlags.Default, LoadTarget.Normal);

                        width += (float)face.Glyph.Metrics.HorizontalAdvance;

                        if (face.Glyph.Metrics.Height > lineHeight)
                        {
                            // Get extra space and subtract it from first line draw?
                            firstAdjust = face.Glyph.Metrics.VerticalAdvance.ToInt32() - face.Glyph.Metrics.HorizontalBearingY.ToInt32();
                            lineHeight  = (float)face.Glyph.Metrics.Height;
                        }

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

                            FTVector26Dot6 kern  = face.GetKerning(index, index2, KerningMode.Default);
                            int            kernx = kern.X.ToInt32();
                            int            kerny = kern.Y.ToInt32();

                            if (kernx != 0 | kerny != 0)
                            {
                                info.addKerning(c, new Info.kerningInfo(k, kernx, kerny));
                            }
                        }
                    }

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

                    face.SetUnpatentedHinting(true);

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

                        if (c == ' ')
                        {
                            posX += (float)face.Glyph.Metrics.HorizontalAdvance + (float)padX;
                            info.addCharacter(c, new Info.characterInfo(c, face.Glyph.Metrics.HorizontalAdvance.ToInt32(), 0, 0, 0, 0, 0, atlas));
                            continue;
                        }

                        if (posX + face.Glyph.Metrics.Width + face.Glyph.BitmapLeft + padX > width)
                        {
                            posX  = 0;
                            posY += lineHeight + padY;
                        }

                        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 += 1;
                        }

                        int xadvance  = face.Glyph.Metrics.HorizontalAdvance.ToInt32();
                        int imgWidth  = face.Glyph.Metrics.Width.ToInt32();
                        int imgHeight = face.Glyph.Metrics.Height.ToInt32();
                        int imgX      = (int)posX;
                        int imgY      = (int)posY;
                        int yoffset   = face.Glyph.Metrics.VerticalAdvance.ToInt32() - face.Glyph.Metrics.HorizontalBearingY.ToInt32();

                        // some fonts that might be missing characters will leave open spaces because their bitmap is empty.
                        if (face.Glyph.Bitmap.Width > 0)
                        {
                            FTBitmap ftbmp = face.Glyph.Bitmap;
                            Bitmap   copy  = ftbmp.ToGdipBitmap(Color.White);
                            graphics.DrawImageUnscaled(copy, imgX, imgY);
                        }

                        info.addCharacter(c, new Info.characterInfo(c, xadvance, imgX, imgY, yoffset, imgWidth, imgHeight, atlas));

                        posX       += (float)imgWidth + (float)padX;
                        lineAdvance = face.Glyph.Metrics.VerticalAdvance.ToInt32();
                    }

                    posX  = 0;
                    posY += lineHeight + padY;

                    info.lineHeight  = lineAdvance;
                    info.firstAdjust = firstAdjust;

                    infos[face.StyleName].Add(info);
                    output += info.buildLuaString("\t\t\t") + "\n";
                }
                output += "\t\t};\n";
            }
            output += "\t};\n};\n";

            bitmaps.Add(bitmap);
            graphics.Dispose();

            // create images
            int count = 0;

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

            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\n" + output;
            header += "\n\nreturn module;";


            File.WriteAllText(outputPath + "\\" + family + ".lua", header);
        }
Пример #9
0
        public T3BFont DrawT3BFontBitmap(char[] strings)
        {
            T3BFont t3bFont = new T3BFont();

            #region font texture settings
            int    texture_width     = 512;
            int    texture_height    = 512;
            int    font_height       = 14;
            int    tile_w            = 17;
            int    tile_h            = 17;
            int    swizzle_w         = 32;
            int    swizzle_h         = 8;
            int    a2                = texture_width / tile_w;
            string fontName          = "Font/font.ttf";
            int    relativePositionX = 1;
            int    relativePositionY = -1;

            byte[]   o_data   = File.ReadAllBytes("Font/base.font");
            Bitmap   _bm      = new Bitmap("Font/base.png");
            Graphics base_grp = System.Drawing.Graphics.FromImage(_bm);
            #endregion
            Library library    = new Library();
            Face    face       = library.NewFace(fontName, 0);
            int     tmp_length = strings.Length;
            if (tmp_length <= 0x76d)
            {
                Console.WriteLine("字太少了,多放点字到charlist.txt");
                throw new Exception("字太少了,多放点字到charlist.txt");
            }
            if (tmp_length >= 2700)
            {
                Console.WriteLine("字太多了,无法装入那么多字,>2700");
                throw new Exception("字太多了,无法装入那么多字");
            }

            if (tmp_length >= 0x76d)
            {
                //当超出0x76D时,加入按钮占用的tile数
                tmp_length += 23;
            }
            //获得texture能达到的最大tile数,00000024h
            int max_tiles = ((int)Math.Ceiling(((double)tmp_length / (double)30)) + 1) * 30;
            t3bFont.max_tiles = max_tiles;

            //获取符合32x8并能容下所有字符的最接近texture_height
            int t1 = tmp_length / 900;
            int t2 = tmp_length % 900;
            int t3 = t1 * 512 + (int)Math.Ceiling(((double)t2 / (double)a2) + 1) * tile_h;

            texture_height = (int)Math.Ceiling((double)t3 / (double)swizzle_h) * swizzle_h;


            Bitmap   bmp = new Bitmap((int)Math.Ceiling((double)texture_width), (int)Math.Ceiling((double)texture_height));
            Graphics g   = Graphics.FromImage(bmp);
            g.Clear(Color.Transparent);
            int  x = 0, y = 0;
            bool bGetFromBitmap = false;
            for (int i = 0; i < tmp_length; i++)
            {
                string currentChar0;
                if (i <= 0xc8)
                {
                    //字母数字和标点, 从原始图片中截取(bGetFromBitmap = true)
                    t3bFont.tbl.Add(string.Format("{0:x4}={1}", i, strings[i].ToString()));
                    currentChar0   = " ";
                    bGetFromBitmap = true;
                }
                else if ((0xc9 <= i) && (i <= 0x76c))
                {
                    //在按钮之前的字符, 使用freetype绘制点阵
                    currentChar0 = strings[i].ToString();
                    t3bFont.tbl.Add(string.Format("{0:x4}={1}", i, strings[i].ToString()));
                    bGetFromBitmap = false;
                }
                else if (i >= 0x784)
                {
                    //在按钮之后的字符, 使用freetype绘制点阵
                    currentChar0 = strings[i - 23].ToString();
                    t3bFont.tbl.Add(string.Format("{0:x4}={1}", i, currentChar0.ToString()));
                    bGetFromBitmap = false;
                }
                else
                {
                    //按钮图片, 从原始图片中截取(bGetFromBitmap = true)
                    currentChar0   = " ";
                    bGetFromBitmap = true;
                }

                if (bGetFromBitmap == false)
                {
                    face.SetCharSize(0, font_height, 0, 72);
                    face.SetPixelSizes((uint)0, (uint)font_height);
                    uint glyphIndex = face.GetCharIndex(uchar2code(currentChar0));
                    //face.LoadGlyph(glyphIndex, LoadFlags.Monochrome, LoadTarget.Mono);
                    //face.Glyph.RenderGlyph(RenderMode.Mono);

                    face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Lcd);
                    face.Glyph.RenderGlyph(RenderMode.Normal);
                    float left   = (float)face.Glyph.Metrics.HorizontalBearingX;
                    float right  = (float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width;
                    float top    = (float)face.Glyph.Metrics.HorizontalBearingY;
                    float bottom = (float)face.Glyph.Metrics.HorizontalBearingY + (float)face.Glyph.Metrics.Height;
                    float FHT    = font_height;
                    int   FHD    = (int)Math.Ceiling(FHT);
                    int   kx     = x + (int)Math.Round(left);
                    int   ky     = (int)Math.Round((float)y + (FHD - top));
                    //int ky = (int)Math.Round((float)y + (FHD - face.Glyph.BitmapTop));


                    FTBitmap ftbmp = face.Glyph.Bitmap;
                    if (ftbmp.Width == 0)
                    {
                        x += tile_w;
                        if (x + tile_w > tile_w)
                        {
                            x  = 0;
                            y += tile_h;
                        }
                        if (i + 1 == 900 || i + 1 == 1800 || i + 1 == 2700)
                        {
                            y += (2);
                        }
                        continue;
                    }

                    Bitmap dBmp = ftbmp.ToGdipBitmap(Color.FromArgb(255, 0x24, 0x24, 0x24));
                    g.DrawImageUnscaled(dBmp, kx + relativePositionX - 1, ky + relativePositionY);
                    g.DrawImageUnscaled(dBmp, kx + relativePositionX + 1, ky + relativePositionY);
                    g.DrawImageUnscaled(dBmp, kx + relativePositionX, ky + relativePositionY - 1);
                    g.DrawImageUnscaled(dBmp, kx + relativePositionX, ky + relativePositionY + 1);
                    dBmp.Dispose();

                    FTBitmap ftbmp2 = face.Glyph.Bitmap;
                    Bitmap   cBmp   = ftbmp2.ToGdipBitmap(Color.White);
                    g.DrawImageUnscaled(cBmp, kx + relativePositionX, ky + relativePositionY);
                    g.DrawImageUnscaled(cBmp, kx + relativePositionX, ky + relativePositionY);
                    cBmp.Dispose();


                    x += tile_w;
                    if (x + tile_w > texture_width)
                    {
                        x  = 0;
                        y += tile_h;
                    }
                    if (i + 1 == 900 || i + 1 == 1800 || i + 1 == 2700)
                    {
                        y += (2);
                    }
                    t3bFont.charvalues.Add(16);
                }
                else
                {
                    //从原版位图中获取并粘贴位置;
                    //do somethings.

                    int kx = x;
                    int ky = y;
                    int kw = (int)o_data[i + 0x47840];
                    int kh = 17;

                    if (kw > 0)
                    {
                        Bitmap   current_bm = new Bitmap(kw, kh);
                        Graphics _tmp_grp   = System.Drawing.Graphics.FromImage(current_bm);
                        _tmp_grp.DrawImage(_bm, new Rectangle(0, 0, kw, kh), new Rectangle(kx, ky, kw, kh), GraphicsUnit.Pixel);

                        _tmp_grp.Dispose();
                        g.DrawImageUnscaled(current_bm, kx, ky);

                        //Console.WriteLine(String.Format("x:{0},y:{1},w:{2},h:{3}" , x, y ,kw ,kh));
                    }

                    x += tile_w;

                    if (x + tile_w > texture_width)
                    {
                        x  = 0;
                        y += tile_h;
                    }
                    if (i + 1 == 900 || i + 1 == 1800 || i + 1 == 2700)
                    {
                        y += (2);
                    }
                    t3bFont.charvalues.Add(kw);
                }
            }
            g.Dispose();
            base_grp.Dispose();
            _bm.Dispose();
            library.Dispose();
            t3bFont.bitmap = bmp;
            return(t3bFont);
        }
        public static bool DrawBitmap(string currentChar0, int width, int height, string ttfName, float scaleRatio, out Bitmap bmp)
        {
            if (charConstDictionary.ContainsKey(currentChar0))
            {
                currentChar0 = charConstDictionary[currentChar0];
            }

            bmp = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(bmp);

            g.Clear(Color.Transparent);
            //设定字体信息
            int    font_height       = (int)Math.Round((float)height * 3f / 4f * scaleRatio);
            int    relativePositionX = 0;
            int    relativePositionY = 0;
            string fontName          = ttfName;

            Library library = new Library();
            Face    face    = library.NewFace(fontName, 0);

            face.SetCharSize(0, font_height, 0, 96);

            face.SetPixelSizes((uint)0, (uint)font_height);
            uint glyphIndex = face.GetCharIndex(uchar2code(currentChar0));

            face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Lcd);
            face.Glyph.RenderGlyph(RenderMode.Normal);
            float left   = (float)face.Glyph.Metrics.HorizontalBearingX;
            float right  = (float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width;
            float top    = (float)face.Glyph.Metrics.HorizontalBearingY;
            float bottom = (float)face.Glyph.Metrics.HorizontalBearingY + (float)face.Glyph.Metrics.Height;

            int FHD = (int)Math.Ceiling((float)font_height);

            int      kx = (int)Math.Round(left);
            int      ky = (int)Math.Round((float)0 + (FHD - top));
            Bitmap   dBmp;
            FTBitmap ftbmp = face.Glyph.Bitmap;

            bool hasGlyph = false;

            if (ftbmp.Width == 0)
            {
                dBmp = new Bitmap(width, width);
            }
            else
            {
                dBmp     = ftbmp.ToGdipBitmap(Color.FromArgb(255, 0, 0, 255));//描边
                hasGlyph = true;
            }
            g.DrawImageUnscaled(dBmp, kx + relativePositionX - 1, ky + relativePositionY);
            g.DrawImageUnscaled(dBmp, kx + relativePositionX + 1, ky + relativePositionY);
            g.DrawImageUnscaled(dBmp, kx + relativePositionX, ky + relativePositionY - 1);
            g.DrawImageUnscaled(dBmp, kx + relativePositionX, ky + relativePositionY + 1);
            dBmp.Dispose();
            if (hasGlyph)
            {
                FTBitmap ftbmp2 = face.Glyph.Bitmap;
                Bitmap   cBmp   = ftbmp2.ToGdipBitmap(Color.FromArgb(255, 0xf0, 0xf0, 0xf0));//实色
                g.DrawImageUnscaled(cBmp, kx + relativePositionX, ky + relativePositionY);
                g.DrawImageUnscaled(cBmp, kx + relativePositionX, ky + relativePositionY);
                cBmp.Dispose();
            }

            g.Dispose();
            return(hasGlyph);
        }
Пример #11
0
        public Bitmap test_draw(ObservableCollection <System.Windows.UIElement> list,
                                ObservableCollection <FontModel> fontList,
                                MaxRectsBinPack binPack,
                                string alphabet,
                                FontSettings fontSettings)
        {
            alphabet = alphabet.Replace("\n", "");
            alphabet = alphabet.Replace("\r", "");
            Library library = new Library();
            Face    face    = library.NewFace(fontSettings.FontName, 0);

            // Find the largest glyph bounding rectangle
            //  Rect glyphRect = getGlyphRect(face, alphabet);
            //int glyphWidth = (int)Math.Ceiling(glyphRect.Width) + 4 * fontSettings.OutlineWidth;
            //int glyphHeight = (int)Math.Ceiling(glyphRect.Height) + 4 * fontSettings.OutlineWidth;
            int glyphWidth  = 18 + 4 * fontSettings.OutlineWidth;
            int glyphHeight = 18 + 4 * fontSettings.OutlineWidth;

            //add new font

            FontModel newFont = new FontModel()
            {
                Id            = (ushort)fontSettings.FontSize,
                size          = fontSettings.FontSize,
                lineheight    = glyphHeight,              // 22,
                spacelength   = (int)(glyphWidth * 0.6f), //todo ?
                baseline      = 0,
                kerning       = -0.5f,
                monowidth     = fontSettings.FontSize + 1,
                letterspacing = 0,
                rangeFrom     = alphabet[0],
                rangeTo       = alphabet[alphabet.Length - 1]
            };

            fontList.Add(newFont);


            Bitmap   bmp = new Bitmap((int)Math.Ceiling((double)fontSettings.ImageWidth), (int)Math.Ceiling((double)fontSettings.ImageHeight));
            Graphics g   = Graphics.FromImage(bmp);

            g.Clear(fontSettings.BgColor);
            //g.Clear(Color.Black);q
            int x = 0, y = 0;

            for (int i = 0; i < alphabet.ToCharArray().Length; i++)
            {
                string currentChar0 = alphabet.ToCharArray()[i].ToString();
                uint   glyphIndex   = face.GetCharIndex(uchar2code(currentChar0));


                if (fontSettings.FontSize <= 14)
                {
                    face.SetPixelSizes((uint)0, (uint)fontSettings.FontSize);
                    face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                    face.Glyph.RenderGlyph(RenderMode.Normal);
                }
                else
                {
                    face.SetCharSize(0, fontSettings.FontSize, 0, 72);
                    face.LoadGlyph(glyphIndex, LoadFlags.ForceAutohint, LoadTarget.Lcd);
                    face.Glyph.RenderGlyph(RenderMode.Lcd);
                }

                //Get character alignment
                float left   = (float)face.Glyph.Metrics.HorizontalBearingX;
                float right  = (float)face.Glyph.Metrics.HorizontalBearingX + (float)face.Glyph.Metrics.Width;
                float top    = (float)face.Glyph.Metrics.HorizontalBearingY;
                float bottom = (float)face.Glyph.Metrics.HorizontalBearingY + (float)face.Glyph.Metrics.Height;
                float FHT    = fontSettings.FontSize;
                int   FHD    = (int)Math.Ceiling(FHT);
                int   kx     = x + face.Glyph.BitmapLeft;
                int   ky     = (int)Math.Round((float)y + (FHD - face.Glyph.BitmapTop));


                ////Select render mode (1 times or 2 times)
                //if (this.grender_mode == "freetype_nearestneighbor")
                //{
                //    face.SetCharSize(0, this.fontHeight * 2, 0, 72);
                //    face.LoadGlyph(glyphIndex, LoadFlags.ForceAutohint, LoadTarget.Lcd);
                //    face.Glyph.RenderGlyph(RenderMode.Lcd);
                //    FTBitmap ftbmp = face.Glyph.Bitmap;
                //    if (ftbmp.Width == 0)
                //    {
                //        x += this.tile_width;
                //        if (x + this.tile_width > this.image_width)
                //        {
                //            x = 0;
                //            y += this.tile_height;
                //        }
                //        continue;
                //    }

                //    Bitmap tmpBmp = ftbmp.ToGdipBitmap(this.penColor);

                //    tmpBmp = kPasteImage(tmpBmp, tile_width * 2, tile_height * 2, (int)face.Glyph.BitmapLeft,
                //                        (int)Math.Round(((float)this.fontHeight * 2 - face.Glyph.BitmapTop)));

                //    Bitmap cBmp = kResizeImage(tmpBmp, tmpBmp.Width / 2, tmpBmp.Height / 2, System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor);
                //    Bitmap nBmp = gray2alpha(cBmp);
                //    cBmp.Dispose();

                //    g.DrawImageUnscaled(nBmp, x + FontSettings.relativePositionX, y + FontSettings.relativePositionY);
                //    nBmp.Dispose();
                //}
                //else if (this.grender_mode == "freetype_HighQualityBicubic")
                //{
                //    face.SetCharSize(0, this.fontHeight * 2, 0, 72);
                //    face.LoadGlyph(glyphIndex, LoadFlags.ForceAutohint, LoadTarget.Lcd);
                //    face.Glyph.RenderGlyph(RenderMode.Lcd);
                //    FTBitmap ftbmp = face.Glyph.Bitmap;
                //    if (ftbmp.Width == 0)
                //    {
                //        x += this.tile_width;
                //        if (x + this.tile_width > this.image_width)
                //        {
                //            x = 0;
                //            y += this.tile_height;
                //        }
                //        continue;
                //    }

                //    Bitmap tmpBmp = ftbmp.ToGdipBitmap(this.penColor);

                //    tmpBmp = kPasteImage(tmpBmp, tile_width * 2, tile_height * 2, (int)face.Glyph.BitmapLeft,
                //        (int)Math.Round(((float)this.fontHeight * 2 - face.Glyph.BitmapTop)));

                //    Bitmap cBmp = kResizeImage(tmpBmp, tmpBmp.Width / 2, tmpBmp.Height / 2, System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic);
                //    Bitmap nBmp = gray2alpha(cBmp);
                //    cBmp.Dispose();

                //    g.DrawImageUnscaled(nBmp, x + FontSettings.relativePositionX, y + FontSettings.relativePositionY);
                //    nBmp.Dispose();

                //}
                //else if (this.grender_mode == "freetype_drawtwice")
                //{
                //    face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                //    face.Glyph.RenderGlyph(RenderMode.Normal);
                //    FTBitmap ftbmp = face.Glyph.Bitmap;
                //    if (ftbmp.Width == 0)
                //    {
                //        x += this.tile_width;
                //        if (x + this.tile_width > this.image_width)
                //        {
                //            x = 0;
                //            y += this.tile_height;
                //        }
                //        continue;
                //    }
                //    Bitmap cBmp = ftbmp.ToGdipBitmap(this.penColor);
                //    Bitmap sBmp = ftbmp.ToGdipBitmap(this.shadowColor);

                //    Bitmap nBmp = gray2alpha(cBmp);
                //    cBmp.Dispose();

                //    g.DrawImageUnscaled(sBmp, kx + FontSettings.relativePositionX + 1, ky + FontSettings.relativePositionY + 1);//draw twice
                //    g.DrawImageUnscaled(nBmp, kx + FontSettings.relativePositionX, ky + FontSettings.relativePositionY);
                //    cBmp.Dispose();
                //    nBmp.Dispose();

                //}
                //else if (this.grender_mode == "freeyype_nosmoothing")
                //{
                //    face.SetPixelSizes((uint)0, (uint)this.fontHeight);
                //    face.LoadGlyph(glyphIndex, LoadFlags.Monochrome, LoadTarget.Mono);
                //    face.Glyph.RenderGlyph(RenderMode.Mono);
                //    FTBitmap ftbmp = face.Glyph.Bitmap;
                //    if (ftbmp.Width == 0)
                //    {
                //        x += this.tile_width;
                //        if (x + this.tile_width > this.image_width)
                //        {
                //            x = 0;
                //            y += this.tile_height;
                //        }
                //        continue;
                //    }
                //    Bitmap cBmp = ftbmp.ToGdipBitmap(this.penColor);
                //    g.DrawImageUnscaled(cBmp, kx + FontSettings.relativePositionX, ky + FontSettings.relativePositionY);
                //    cBmp.Dispose();
                //}

                //    int tile_width = 24;
                //int tile_height = FontSettings.iFontHeight;//24;
                ////else
                ////{
                FTBitmap ftbmp = face.Glyph.Bitmap;

                //    if (ftbmp.Width == 0)
                //    {
                //        x += tile_width;
                //        if (x + tile_width > this.image_width)
                //        {
                //            x = 0;
                //            y += tile_height;
                //        }
                //        continue;
                //    }


                Bitmap cBmp = ftbmp.ToGdipBitmap(fontSettings.PenColor);
                Bitmap nBmp = gray2alpha(cBmp);

                Rect newPos = binPack.Insert(cBmp.Width, cBmp.Height, MaxRectsBinPack.FreeRectChoiceHeuristic.RectBottomLeftRule);

                //DebugRectangle
                System.Windows.Shapes.Rectangle testRect = new System.Windows.Shapes.Rectangle
                {
                    Stroke          = System.Windows.Media.Brushes.LightGreen,
                    StrokeThickness = 0
                };

                ImageBrush ib = new ImageBrush();
                //    cBmp.MakeTransparent();
                cBmp.Dispose();
                var source = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(nBmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty,
                                                                                          System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
                nBmp.Dispose();
                ib.ImageSource  = source;
                testRect.Fill   = ib;
                testRect.Width  = newPos.Width;
                testRect.Height = newPos.Height;
                Canvas.SetLeft(testRect, newPos.Left);
                Canvas.SetTop(testRect, newPos.Top);
                list.Add(testRect);

                Glyph newGlyph = new Glyph()
                {
                    X      = (int)Math.Ceiling(newPos.Left),
                    Y      = (int)Math.Ceiling(newPos.Top),
                    width  = (int)Math.Ceiling(newPos.Width),
                    height = (int)Math.Ceiling(newPos.Height)
                };
                newFont.SetGlyph(currentChar0, newGlyph);

                //if(glyphIndex == 33)
                //{

                //}
                // Construct KerningData
                for (int j = 0; j < alphabet.ToCharArray().Length; j++)
                {
                    string left_Char0      = alphabet.ToCharArray()[j].ToString();
                    uint   left_glyphIndex = face.GetCharIndex(uchar2code(left_Char0));

                    //if (left_glyphIndex == 45)
                    //{

                    //}
                    //char c1 = mAlphabet[i];
                    //FT_UInt c1Index = FT_Get_Char_Index(face, c1);
                    var delta = face.GetKerning(left_glyphIndex, glyphIndex, KerningMode.Default);

                    // KerningData kd = new KerningData(kern_currentChar0, currentChar0, delta.X.ToInt32() >> 6, 0, delta.Y.ToInt32() >> 6, 0);
                    if (left_glyphIndex == 0 || delta.X == 0) //no kerning
                    {
                        continue;
                    }

                    Kerning newKerning = new Kerning();
                    newKerning.RightGlyphID = left_glyphIndex;
                    newKerning.KerningValue = delta.X.ToInt32() >> 6;
                    newFont.SetKerning(left_Char0, newKerning);
                }

                newFont.SetVerticalOffset(currentChar0, ky);

                //cBmp.Dispose();
                //g.DrawImageUnscaled(nBmp, (int)Math.Ceiling(newPos.X) + fontSettings.relativePositionX, (int)Math.Ceiling(newPos.Y) + fontSettings.relativePositionY);
                //// g.DrawImageUnscaled(nBmp, kx + FontSettings.relativePositionX, ky + FontSettings.relativePositionY);
                //nBmp.Dispose();
            }
            g.Dispose();
            library.Dispose();
            return(bmp);
        }