private static SizeF GetSprites(
            GlyphEnumerator glyphs, ICollection <GlyphSprite> output, Vector2 position,
            Color color, float rotation, Vector2 origin, Vector2 scale, float depth, RectangleF?clipRect)
        {
            GlyphSprite sprite;
            SizeF       size = SizeF.Empty;

            int index = 0;

            while (glyphs.MoveNext())
            {
                Glyph glyph = glyphs.CurrentGlyph;
                if (glyph.FontRegion == null)
                {
                    continue;
                }

                Vector2         glyphOrigin = position - glyph.Position + origin;
                Vector2         newPos      = position;
                TextureRegion2D region      = glyph.FontRegion.TextureRegion;

                sprite.Visible = region.Bounds.IsVisible(
                    ref newPos, glyphOrigin, scale, clipRect, out RectangleF srcRect);

                if (!sprite.Visible) // restore values
                {
                    newPos  = position;
                    srcRect = region.Bounds;
                }

                sprite.Char       = glyph.Character;
                sprite.Texture    = region.Texture;
                sprite.Index      = index;
                sprite.SourceRect = srcRect;
                sprite.Position   = newPos;
                sprite.Color      = color;
                sprite.Rotation   = rotation;
                sprite.Origin     = glyphOrigin;
                sprite.Scale      = scale;
                sprite.Depth      = depth;

                output.Add(sprite);
                index++;

                float rowX = glyph.Position.X + srcRect.Width * scale.X - newPos.X;
                if (rowX > size.Width)
                {
                    size.Width = rowX;
                }

                float rowY = glyph.Position.Y + srcRect.Height * scale.Y - newPos.Y;
                if (rowY > size.Height)
                {
                    size.Height = rowY;
                }
            }
            return(new SizeF(size.Width, size.Height));
        }
        private static SizeF GetGlyphBatchedSprites(
            GlyphEnumerator glyphs, ICollection <GlyphBatchedSprite> output, Vector2 position,
            Color color, float rotation, Vector2 origin, Vector2?scale, float depth, RectangleF?clipRect)
        {
            GlyphBatchedSprite sprite;
            var size       = new SizeF();
            var scaleValue = scale ?? Vector2.One;
            int index      = 0;

            while (glyphs.MoveNext())
            {
                Glyph glyph = glyphs.CurrentGlyph;
                if (glyph.FontRegion == null)
                {
                    continue;
                }

                Vector2         glyphOrigin = position - glyph.Position + origin;
                Vector2         newPos      = position;
                TextureRegion2D region      = glyph.FontRegion.TextureRegion;

                sprite.Visible = region.Bounds.IsVisible(
                    ref newPos, glyphOrigin, scaleValue, clipRect, out RectangleF srcRect);

                if (!sprite.Visible) // restore values
                {
                    newPos  = position;
                    srcRect = region.Bounds;
                }

                sprite.Char    = glyph.Character;
                sprite.Index   = index;
                sprite.Texture = region.Texture;
                sprite.Sprite  = default;
                sprite.Sprite.SetTransform(newPos, rotation, scale, origin, srcRect.Size);
                sprite.Sprite.SetTexCoords(sprite.Texture.Texel, srcRect);
                sprite.Sprite.SetDepth(depth);
                sprite.Sprite.SetColor(color);

                output.Add(sprite);
                index++;

                float rowX = glyph.Position.X + srcRect.Width * scaleValue.X - newPos.X;
                if (rowX > size.Width)
                {
                    size.Width = rowX;
                }

                float rowY = glyph.Position.Y + srcRect.Height * scaleValue.Y - newPos.Y;
                if (rowY > size.Height)
                {
                    size.Height = rowY;
                }
            }
            return(new SizeF(size.Width, size.Height));
        }
        private static void DrawString(
            SpriteBatch batch, IEnumerator <Glyph> glyphs, Vector2 position, Color color,
            float rotation, Vector2 origin, Vector2 scale, float depth, RectangleF?clipRect)
        {
            while (glyphs.MoveNext())
            {
                Glyph glyph = glyphs.Current;
                if (glyph.FontRegion == null)
                {
                    continue;
                }

                Vector2 characterOrigin = position - glyph.Position + origin;
                batch.Draw(
                    glyph.FontRegion.TextureRegion, position, color,
                    rotation, characterOrigin, scale, SpriteEffects.None, depth, clipRect);
            }
        }
        private static void GetSprites(
            IList <Glyph> glyphs, ICollection <GlyphSprite> output, Vector2 position,
            Color color, float rotation, Vector2 origin, Vector2 scale, float depth, RectangleF?clipRect)
        {
            GlyphSprite sprite;

            for (int i = 0, count = glyphs.Count; i < count; i++)
            {
                Glyph glyph = glyphs[i];
                if (glyph.FontRegion != null)
                {
                    Vector2         glyphOrigin = origin - glyph.Position;
                    Vector2         newPos      = position;
                    TextureRegion2D region      = glyph.FontRegion.TextureRegion;

                    sprite.Visible = region.Bounds.IsVisible(
                        ref newPos, glyphOrigin, scale, clipRect, out RectangleF srcRect);

                    if (!sprite.Visible) // restore values
                    {
                        newPos  = position;
                        srcRect = region.Bounds;
                    }

                    sprite.Char       = glyph.Character;
                    sprite.Texture    = glyph.FontRegion.TextureRegion.Texture;
                    sprite.Index      = i;
                    sprite.SourceRect = srcRect;
                    sprite.Position   = newPos;
                    sprite.Color      = color;
                    sprite.Rotation   = rotation;
                    sprite.Origin     = glyphOrigin;
                    sprite.Scale      = scale;
                    sprite.Depth      = depth;

                    output.Add(sprite);
                }
            }
        }
        private static void GetBatchedSprites(
            IList <Glyph> glyphs, ICollection <GlyphBatchedSprite> output, Vector2 position, Color color,
            float rotation, Vector2 origin, Vector2 scale, float depth, RectangleF?clipRect)
        {
            GlyphBatchedSprite sprite;

            for (int i = 0, count = glyphs.Count; i < count; i++)
            {
                Glyph glyph = glyphs[i];
                if (glyph.FontRegion != null)
                {
                    Vector2         glyphOrigin = -glyph.Position + origin;
                    Vector2         newPos      = position;
                    TextureRegion2D region      = glyph.FontRegion.TextureRegion;

                    sprite.Visible = region.Bounds.IsVisible(
                        ref newPos, glyphOrigin, scale, clipRect, out RectangleF srcRect);

                    if (!sprite.Visible) // restore values
                    {
                        newPos  = position;
                        srcRect = region.Bounds;
                    }

                    sprite.Char    = glyph.Character;
                    sprite.Index   = i;
                    sprite.Texture = glyph.FontRegion.TextureRegion.Texture;
                    sprite.Sprite  = default;
                    sprite.Sprite.SetTransform(newPos, rotation, scale, origin, srcRect.Size);
                    sprite.Sprite.SetTexCoords(sprite.Texture.Texel, srcRect);
                    sprite.Sprite.SetDepth(depth);
                    sprite.Sprite.SetColor(color);

                    output.Add(sprite);
                }
            }
        }