Beispiel #1
0
        public Vector2 MeasureString(string text)
        {
            var pairs      = Font.StringToPair;
            var activeFont = this;

            if (string.IsNullOrEmpty(text))
            {
                return(new Vector2(0, Height / VectorScale));
            }

            var size     = new Vector2(0, Height / VectorScale);
            var subScale = 1f;

            MSDFGlyph next = null;

            if (text.Length > 0)
            {
                var c = text[0];
                next = GetGlyph(c);
            }
            for (int i = 0; i < text.Length; i++)
            {
                var glyph = next;
                if (next == null)
                {
                    if (i + 1 >= text.Length)
                    {
                        break;
                    }
                    var c = text[i + 1];
                    next = GetGlyph(c);
                    continue;
                }
                if (activeFont != next.Font)
                {
                    activeFont = next.Font;
                    pairs      = glyph.Font.Info.pairs;
                    subScale   = (activeFont != this) ? activeFont.VectorScale / VectorScale : 1f;
                }

                size.X += glyph.Glyph.Metrics.Advance * subScale;

                if (i < text.Length - 1)
                {
                    var c = text[i + 1];
                    next = GetGlyph(c);

                    if (next != null)
                    {
                        KerningPair pair;
                        if (pairs.TryGetValue(new string(new char[] { glyph.Glyph.Character, next.Glyph.Character }), out pair))
                        {
                            size.X += pair.Advance * subScale;
                        }
                    }
                }
            }

            return(size);
        }
Beispiel #2
0
        public void Draw(GraphicsDevice gd, string text, Vector2 pos, Color color, Vector2 scale, Matrix?mat)
        {
            if (string.IsNullOrEmpty(text))
            {
                return;
            }

            var point = new Vector2(0, 0);
            var atlas = GetAtlas(gd);

            var wv = Matrix.CreateScale(scale.X, scale.Y, 1)
                     * Matrix.CreateTranslation(pos.X, pos.Y, 0);

            if (mat != null)
            {
                wv = wv * mat.Value;

                wv.Decompose(out var scale2, out var quat, out var trans);
                scale.X = scale2.X;
                scale.Y = scale2.Y;
            }

            var wvp    = wv * Matrix.CreateOrthographicOffCenter(new Rectangle(0, 0, gd.Viewport.Width, gd.Viewport.Height), -0.1f, 1f);
            var effect = MSDFEffect;

            var groups     = new Dictionary <MSDFFont, MSDFRenderGroup>();
            var activeFont = this;

            var itemW = Info.itemW;
            var itemH = Info.itemH;

            var textureWidth  = Info.textureWidth;
            var textureHeight = Info.textureHeight;

            var cutUX = Info.cutUX;
            var cutUY = Info.cutUY;

            var uW = Info.uW;
            var uH = Info.uH;

            var atlasWidth = Info.atlasWidth;
            var pairs      = Info.pairs;
            var data       = new MSDFRenderGroup(this);

            groups[this] = data;

            var verts = data.Vertices;
            var inds  = data.Indices;

            effect.Parameters["WorldViewProjection"].SetValue(wvp);
            effect.Parameters["Color"].SetValue(color.ToVector4());

            effect.CurrentTechnique = effect.Techniques[0];
            var subScale = 1f;

            MSDFGlyph next = null;

            if (text.Length > 0)
            {
                var c = text[0];
                next = GetGlyph(c);
            }
            for (int i = 0; i < text.Length; i++)
            {
                var glyph = next;
                if (glyph == null)
                {
                    if (i + 1 >= text.Length)
                    {
                        break;
                    }
                    var c = text[i + 1];
                    next = GetGlyph(c);
                    continue;
                }

                if (glyph.Font != activeFont)
                {
                    activeFont = glyph.Font;
                    subScale   = (activeFont != this) ? activeFont.VectorScale / VectorScale : 1f;

                    var ainfo = activeFont.Info;
                    itemW = ainfo.itemW;
                    itemH = ainfo.itemH;

                    textureWidth  = ainfo.textureWidth;
                    textureHeight = ainfo.textureHeight;

                    cutUX = ainfo.cutUX;
                    cutUY = ainfo.cutUY;

                    uW = ainfo.uW;
                    uH = ainfo.uH;

                    atlasWidth = ainfo.atlasWidth;
                    pairs      = ainfo.pairs;
                    MSDFRenderGroup mdata = null;
                    if (!groups.TryGetValue(activeFont, out mdata))
                    {
                        mdata = new MSDFRenderGroup(activeFont);
                        groups[activeFont] = mdata;
                    }

                    verts = mdata.Vertices;
                    inds  = mdata.Indices;
                }

                var fglyph = glyph.Glyph;
                var mscale = fglyph.Metrics.Scale;


                var left   = point.X - (fglyph.Metrics.Translation.X - 1 / mscale) * subScale;
                var bottom = point.Y + (fglyph.Metrics.Translation.Y + activeFont.YOff / activeFont.VectorScale - 1 / mscale) * subScale;

                mscale /= subScale;
                var glyphHeight = (textureHeight - 2) / mscale;
                var glyphWidth  = (textureWidth - 2) / mscale;

                var right = left + glyphWidth;
                var top   = bottom - glyphHeight;

                var tx = (fglyph.AtlasIndex % atlasWidth) * itemW + cutUX;
                var ty = (fglyph.AtlasIndex / atlasWidth) * itemH + cutUY;

                var derivative = (new Vector2(uW / (right - left), uH / (bottom - top)) / scale) / 2;

                if (!char.IsWhiteSpace(fglyph.Character))
                {
                    RenderQuad(inds, verts, new Vector2(left, bottom), new Vector2(right, top), new Vector2(tx, ty + uH), new Vector2(tx + uW, ty), derivative);
                }

                point.X += fglyph.Metrics.Advance * subScale;

                if (i < text.Length - 1)
                {
                    var c = text[i + 1];
                    next = GetGlyph(c);

                    if (next != null)
                    {
                        KerningPair pair;
                        if (pairs.TryGetValue(new string(new char[] { fglyph.Character, next.Glyph.Character }), out pair))
                        {
                            point.X += pair.Advance * subScale;
                        }
                    }
                }
            }

            foreach (var group in groups.Values)
            {
                effect.Parameters["PxRange"].SetValue(group.Font.Font.PxRange);
                var groupAtlas = group.Font.GetAtlas(gd);
                effect.Parameters["TextureSize"].SetValue(new Vector2(groupAtlas.Width, groupAtlas.Height));
                effect.Parameters["GlyphTexture"].SetValue(groupAtlas);
                effect.CurrentTechnique.Passes[0].Apply();
                if (group.Vertices.Count == 0)
                {
                    continue;
                }

                gd.DrawUserIndexedPrimitives(PrimitiveType.TriangleList,
                                             group.Vertices.ToArray(), 0, group.Vertices.Count,
                                             group.Indices.ToArray(), 0, group.Indices.Count / 3);
            }
        }