Skip to content

Text gets chopped when rotated >60 degrees #175

@kutukvpavel

Description

@kutukvpavel

Prerequisites

  • I have written a descriptive issue title
  • I have verified that I am running the latest version of ImageSharp.Drawing
  • I have verified if the problem exist in both DEBUG and RELEASE mode
  • I have searched open and closed issues to ensure it has not already been reported

Description

I'm trying to fill some rectangles and place tags (text) into them so that the tags are centered and rotated to match orientation of each rectangle. This means that I'm using DrawText either with a -90° rotation transform or without one. In case of the former, each character of the output text gets its bottom part cut at a consistent height that seems to depend on character index.

Take a look at 3 vertically oriented rectangles, two brown and one blue.
Example

I've done some testing and observed that the issue occures for angles above ~60°. Angle sign does not matter. For example, this happens when I set the angle to +100° (set of rectangles is a random solution for an optimization problem, disregard the position changes).
Example at 100deg

Steps to Reproduce

First, I generate an image to draw on (it's padded to allow some rectangles that cross the expected boundary).

public static float ImageExtraSpaceMultiplier { get; set; } = 1.2f;

public static Image<Rgba32> CreateImage(Rectangle bounds, out float xOffset, out float yOffset)
{
            Image<Rgba32> image = new Image<Rgba32>(
                (int)Math.Ceiling(bounds.Width * ImageExtraSpaceMultiplier),
                (int)Math.Ceiling(bounds.Height * ImageExtraSpaceMultiplier));
            float _xOffset = bounds.Width * (ImageExtraSpaceMultiplier - 1) / 2;
            float _yOffset = bounds.Height * (ImageExtraSpaceMultiplier - 1) / 2;

            image.Mutate(x => x.BackgroundColor(Color.Black));
            image.Mutate(x => x.Draw(Color.White, 2.0f, new RectangleF(
                bounds.X + _xOffset,
                bounds.Y + _yOffset,
                bounds.Width, bounds.Height)));

            xOffset = _xOffset;
            yOffset = _yOffset;
            return image;
}

Then I draw a bunch of rectangles. I've tested it with a different font/size combination, no luck. Uncomment Draw() call to draw TextMeasure rectangle and see that it's always rendered correctly. The issue is somewhere inside DrawText.

public static Font TagFont { get; set; } = new Font(SystemFonts.Find("Arial"), 200);

public static void AddRects(this Image<Rgba32> image, float xOffset, float yOffset, 
            IEnumerable<PlottableRect> rectangles)
{
            foreach (var item in rectangles)
            {
                if (item.Area == 0) continue;
                RectangleF r = item.Rect;
                r.Offset(xOffset, yOffset);
                image.Mutate(x => x.Fill(item.Color, r));
                if (item.Tag == null) continue;
                bool o = item.Orientation;
                var textPoint = RectangleF.Center(r);
                var tMeasure = TextMeasurer.Measure(item.Tag, new RendererOptions(TagFont));
                float tLenOffset = -tMeasure.Width / 2;
                float tHOffset = -tMeasure.Height / 2;
                textPoint.Offset(o ? tHOffset : tLenOffset, o ? -tLenOffset : tHOffset);
                image.Mutate(x => 
                {
                    var rdo = o ? new DrawingOptions { Transform = GetTextRotationMatrix(textPoint) } 
                        : new DrawingOptions();
                    x.DrawText(rdo, item.Tag, TagFont, Color.White, textPoint);
                    //x.Draw(rdo, Color.White, 5.0f, new RectangleF(textPoint, new SizeF(tMeasure.Width, tMeasure.Height)));
                });
            }
}

private static System.Numerics.Matrix3x2 GetTextRotationMatrix(PointF p)
{
            return Matrix3x2Extensions.CreateRotationDegrees(-90, p);
}

public class PlottableRect
{
        private Rectangle _Rect;
        public Rectangle Rect { get => _Rect; //This accessor copies the Rectangle struct isolating _Rect
            protected set
            {
                _Rect = value;
            }
        }
        public Color Color { get; set; }
        public virtual string Tag { get; set; }
        public int Area { get => _Rect.Width * _Rect.Height; }
        public bool Orientation { get => _Rect.Height > _Rect.Width; } //Vertical
}

Afterwards I resize and save the image (as PNG). I tested the code without final resizing, the problem persists.

System Configuration

  • ImageSharp.Drawing version: beta13
  • Other ImageSharp packages and versions: main = 1.0.4
  • Environment (Operating system, version and so on): Win7x64, Win10x64 LTSC 1809
  • .NET Framework version: .NET Core 3.1
  • Additional information:

Metadata

Metadata

Assignees

No one assigned

    Labels

    blockingbugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions