Example #1
0
        private Glyph GenerateOutline(char c)
        {
            LoadGlyph(c);

            var sz = new Size(face.Glyph.Metrics.Width.ToInt32(), face.Glyph.Metrics.Height.ToInt32());

            if (sz == Size.Empty)
            {
                return new Glyph {
                           Advance = face.Glyph.Advance.X.ToSingle()
                }
            }
            ;

            using (var glyph = face.Glyph.GetGlyph())
                using (var stroker = new Stroker(face.Glyph.Library))
                {
                    stroker.Set(64 * 1, StrokerLineCap.Round, StrokerLineJoin.Round, 0);
                    using (var strokedGlyph = glyph.StrokeBorder(stroker, false, false))
                    {
                        strokedGlyph.ToBitmap(RenderMode.Normal, new FTVector26Dot6(), false);
                        var bbox  = strokedGlyph.GetCBox(GlyphBBoxMode.Pixels);
                        var image = ToPixmap(strokedGlyph.ToBitmapGlyph().Bitmap);
                        return(new Glyph
                        {
                            Advance = strokedGlyph.Advance.X.ToSingle(),
                            Offset = new Point2D(bbox.Left, -bbox.Top),
                            Image = atlas.Add(image)
                        });
                    }
                }
        }
Example #2
0
        public static bool LoadGlyph(ref Texture_Font_T font, char codepoint)
        {
            int             i;
            int             x;
            int             y;
            Glyph           glyph;
            GlyphSlot       glyphSlot;
            FTBitmap        fTBitmap;
            uint            glyphindex;
            Texture_Glyph_T glyph_T;
            int             glyphtop  = 0;
            int             glyphleft = 0;
            Region          region;
            int             missed = 0;

            //check glyph has not already been loaded
            if (FindGlyph(ref font, codepoint, out glyph_T))
            {
                return(true);
            }
            // handle null codepoint
            if (codepoint == '\0')
            {
                region  = Atlas.Atlas.GetRegion(ref font.Atlas, 5, 5);
                glyph_T = InitGlyph();
                byte[] data = new byte[4 * 4 * 3] {
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                };
                if (region.X < 0)
                {
                    //throw new Exception("texture atlas is full!");
                    return(false);
                }
                Atlas.Atlas.SetRegion(ref font.Atlas, region.X, region.Y, 4, 4, data, 0);
                glyph_T.Codepoint = -1;
                glyph_T.S01       = (region.X + 2) / (float)font.Atlas.Width;
                glyph_T.T01       = (region.Y + 2) / (float)font.Atlas.Height;
                glyph_T.S11       = (region.X + 3) / (float)font.Atlas.Width;
                glyph_T.T11       = (region.Y + 3) / (float)font.Atlas.Height;
                font.Glyphs.Add(glyph_T);
                return(true);
            }
            LoadFlags  flags  = 0;
            LoadTarget target = 0;

            glyphindex = face.GetCharIndex((uint)char.ConvertToUtf32(codepoint.ToString(), 0));
            if (font.Rendermode != RenderMode.RENDER_NORMAL && font.Rendermode != RenderMode.RENDER_SIGNED_DISTANCE_FIELD)
            {
                flags |= LoadFlags.NoBitmap;
            }
            else
            {
                flags |= LoadFlags.Render;
            }
            if (!font.Hinting)
            {
                flags |= LoadFlags.NoHinting | LoadFlags.NoAutohint;
            }
            else
            {
                flags |= LoadFlags.ForceAutohint;
            }
            if (font.Atlas.Depth == 3)
            {
                library.SetLcdFilter(LcdFilter.Light);
                target |= LoadTarget.Lcd;
                if (font.Filtering)
                {
                    library.SetLcdFilterWeights(font.Lcd_filter_weights);
                }
            }
            else if (HRES == 1)
            {
                target |= LoadTarget.Light;
            }
            face.LoadGlyph(glyphindex, flags, target);
            if (font.Rendermode == RenderMode.RENDER_NORMAL || font.Rendermode == RenderMode.RENDER_SIGNED_DISTANCE_FIELD)
            {
                glyphSlot = face.Glyph;
                fTBitmap  = glyphSlot.Bitmap;
                glyphtop  = glyphSlot.BitmapTop;
                glyphleft = glyphSlot.BitmapLeft;
            }
            else
            {
                Stroker     stroker = new Stroker(library);
                BitmapGlyph bitmapGlyph;

                stroker.Set((int)(font.Outlinethickness * HRES), StrokerLineCap.Round, StrokerLineJoin.Round, 0);
                glyph = face.Glyph.GetGlyph();
                if (font.Rendermode == RenderMode.RENDER_OUTLINE_EDGE)
                {
                    glyph.Stroke(stroker, true);
                }
                else if (font.Rendermode == RenderMode.RENDER_OUTLINE_NEGATIVE)
                {
                    glyph.StrokeBorder(stroker, true, true);
                }
                else if (font.Rendermode == RenderMode.RENDER_OUTLINE_POSITIVE)
                {
                    glyph.StrokeBorder(stroker, false, true);
                }
                if (font.Atlas.Depth == 1)
                {
                    glyph.ToBitmap(SharpFont.RenderMode.Normal, new FTVector26Dot6(0, 0), true);
                }
                else
                {
                    glyph.ToBitmap(SharpFont.RenderMode.Lcd, new FTVector26Dot6(0, 0), true);
                }
                bitmapGlyph = glyph.ToBitmapGlyph();
                fTBitmap    = bitmapGlyph.Bitmap;
                glyphtop    = bitmapGlyph.Top;
                glyphleft   = bitmapGlyph.Left;

                stroker.Dispose();
            }
            Padding padding = new Padding(0, 1, 0, 1);

            if (font.Rendermode == RenderMode.RENDER_SIGNED_DISTANCE_FIELD)
            {
                padding.Top  = 1;
                padding.Left = 1;
            }
            if (font.Padding != 0)
            {
                padding.Left   += font.Padding;
                padding.Right  += font.Padding;
                padding.Top    += font.Padding;
                padding.Bottom += font.Padding;
            }
            int width  = (fTBitmap.Width / font.Atlas.Depth) + padding.Left + padding.Right;
            int height = fTBitmap.Rows + padding.Top + padding.Bottom;

            region = Atlas.Atlas.GetRegion(ref font.Atlas, width, height);
            if (region.X < 0)
            {
                //throw new exception("texture atlas full");
                return(false);
            }
            byte[] data = new byte[width * height * font.Atlas.Depth];
            data = fTBitmap.BufferData;
            if (font.Rendermode == RenderMode.RENDER_SIGNED_DISTANCE_FIELD)
            {
                // todo ? where is make distance map comming from
                throw new NotImplementedException();
            }
            Atlas.Atlas.SetRegion(ref font.Atlas, region.X, region.Y, width, height, data, width * font.Atlas.Depth);
            glyph_T                  = InitGlyph();
            glyph_T.Codepoint        = (uint)char.ConvertToUtf32(codepoint.ToString(), 0);
            glyph_T.Width            = (uint)width;
            glyph_T.Height           = (uint)height;
            glyph_T.RenderMode       = font.Rendermode;
            glyph_T.Outlinethickness = font.Outlinethickness;
            glyph_T.OffsetX          = glyphleft;
            glyph_T.OffsetY          = glyphtop;
            glyph_T.S01              = region.X / (float)font.Atlas.Width;
            glyph_T.T01              = region.Y / (float)font.Atlas.Height;
            glyph_T.S11              = (region.X + width) / (float)font.Atlas.Width;
            glyph_T.T11              = (region.Y + height) / (float)font.Atlas.Height;
            face.LoadGlyph(glyphindex, LoadFlags.Render | LoadFlags.NoHinting, target);
            glyphSlot        = face.Glyph;
            glyph_T.Advancex = glyphSlot.Advance.X.ToSingle();
            glyph_T.Advancey = glyphSlot.Advance.Y.ToSingle();
            font.Glyphs.Add(glyph_T);
            if (font.Rendermode != RenderMode.RENDER_NORMAL && font.Rendermode != RenderMode.RENDER_SIGNED_DISTANCE_FIELD)
            {
                glyph.Dispose();
            }
            GenerateKerning(ref font);
            return(true);
        }