Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Text size is a bit off using Graphics and very wrong using GraphicsPath #7485

Open
janseris opened this issue Jul 23, 2022 · 4 comments
Open
Assignees
Labels
area-System.Drawing System.Drawing issues help wanted Good issue for external contributors
Milestone

Comments

@janseris
Copy link

janseris commented Jul 23, 2022

.NET version

.NET Framework 4.7.2

Did it work in .NET Framework?

No

Did it work in any of the earlier releases of .NET Core or .NET 5+?

probably in none

Issue description

What was my initial goal:

  • create a rectangle which by resizing, fits text into itself
  • this rectangle should show the bounds of the text and the text should fit tightly into the rectangle (just like the blue GraphicsPath sample does but its size is wrong)

This seems like an impossible task with current WinForms API because there are two string size calculations which produce different results and both are wrong. Graphics is approx. to 90 % right while GraphicsPath is like 60 % right or less,

Drawing a string with font size 60 points on coordinates [200, 200] with Graphics and GraphicsPath produces two very different results (shown by text).
String size calculation using Graphics.MeasureString and GraphicsPath.GetBounds methods produces two very different results (shown by rectangles).

image

Steps to reproduce

WindowsFormsApp2.zip

Note: because of the GraphicsPath behavior, the best size calculation (fit into rectangle) can be done by bruteforcing font size from largest to lowest using GraphicsPath with GetBounds. However the result works fine only for drawing by GraphicsPath (if drawn by Graphics with font size calculated using GraphicsPath, the text will be much bigger because font sizes returned by GraphicsPath are very small (unrealistic))

  • what GraphicsPath only does well is calculating the bounding rectangle of the string (wrong font size and shifted position!)

Edit: this project shows how to get the drawn position of GraphicsPath right, however it is kinda complicated because if GraphicsPath contains multiple objects, this must probably be done for every object (create an additional GraphicsPath object, measure size and offset, drop the GraphicsPath object and then use the correction to draw the actual GraphicsPath object):
GraphicsPath corrected drawing location.zip

  • the font size compared to Graphics.MeasureString issue persists
    image

image

@janseris janseris added the untriaged The team needs to look at this issue in the next triage label Jul 23, 2022
@janseris janseris changed the title Text size calculation is wrong using Graphics and GraphicsPath Text drawing is wrong using Graphics and GraphicsPath Jul 23, 2022
@janseris janseris changed the title Text drawing is wrong using Graphics and GraphicsPath Text drawing is wrong using Graphics and very wrong using GraphicsPath Jul 23, 2022
@janseris janseris changed the title Text drawing is wrong using Graphics and very wrong using GraphicsPath Text size is a bit off using Graphics and very wrong using GraphicsPath Jul 23, 2022
@janseris
Copy link
Author

janseris commented Jul 27, 2022

@JeremyKuhne
Having played with this a lot, I noticed that the offset of the GraphicsPath containing string is probably caused by the fact that for different string content, a different offset is generated because different symbols are sized differently and might reach the max value which is that offset of the GraphicsPath bounding rectangle from the original point would be 0. I have not tested this though. And if this is true, the offset is not an issue.

I have created a sample project which might help illustrating this (among other different things):
https://github.com/janseris/GraphicsPathRotatedStringDrawingIssue

@dreddy-work dreddy-work removed the untriaged The team needs to look at this issue in the next triage label Jul 29, 2022
@weltkante
Copy link
Contributor

you can use Graphics.MeasureCharacterRanges to get tight bounds for Graphics.DrawString.

Never used GraphicsPath so no idea why it interprets font size differently than the rest of the APIs.

@JeremyKuhne
Copy link
Member

@janseris Sorry that I couldn't look at this any sooner. One fundamental difference is that when you draw directly to the Graphics object a scale factor is applied to the em size based on the font unit. This isn't done when writing to a path.

The logic looks something like this:

public static float EmScale(Font font, Graphics g)
{
    switch (font.Unit)
    {
        case GraphicsUnit.Document:
            return g.DpiX / 300.0f / g.PageScale;
        case GraphicsUnit.Point:
            return g.DpiX / 72.0f / g.PageScale;
        case GraphicsUnit.Inch:
            return g.DpiX / g.PageScale;
        case GraphicsUnit.Millimeter:
            return g.DpiX / 25.4f / g.PageScale;
        case GraphicsUnit.Display:
        case GraphicsUnit.Pixel:
        case GraphicsUnit.World:
        default:
            return 1.0f;
    }
}

If you use this logic to multiply the em parameter for AddString you'll get the right scale.

image

I don't know much about the details of how outputting to path differs from rendering to pixels outside of that. Unfortunately I probably won't get a chance to dig into that part in the near future.

@elachlan elachlan added area-System.Drawing System.Drawing issues help wanted Good issue for external contributors labels Nov 3, 2023
@ghost ghost added this to the Help wanted milestone Nov 3, 2023
@ghost
Copy link

ghost commented Nov 3, 2023

This issue is now marked as "help wanted", and we’re looking for a community volunteer to work on this issue. If we receive no interest in 180 days, we will close the issue. To learn more about how we handle feature requests, please see our documentation.

Happy Coding!

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
area-System.Drawing System.Drawing issues help wanted Good issue for external contributors
Projects
None yet
Development

No branches or pull requests

5 participants