Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[API Proposal]: Add ReadOnlySpan<char> overloads to System.Drawing.Graphics #8844

Closed
udaken opened this issue May 13, 2022 · 9 comments · Fixed by #8877
Closed

[API Proposal]: Add ReadOnlySpan<char> overloads to System.Drawing.Graphics #8844

udaken opened this issue May 13, 2022 · 9 comments · Fixed by #8877
Assignees
Labels
api-approved (4) API was approved in API review, it can be implemented area-System.Drawing System.Drawing issues

Comments

@udaken
Copy link

udaken commented May 13, 2022

Background and motivation

When drawing strings manually in WinForms, new text is frequently created.
Since the methods System.Drawing.Graphics and System.Drawing.GraphicsPath only accept strings
String allocations occur frequently.

It would be better to add an overload that accepts ReadOnlySpan<char> so that the buffer can be passed directly.

API Proposal

namespace System.Drawing
{
    public sealed partial class Graphics : System.MarshalByRefObject, System.Drawing.IDeviceContext, System.IDisposable
    {
        // Existing:
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.PointF point) { }
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.PointF point, System.Drawing.StringFormat? format) { }
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.RectangleF layoutRectangle) { }
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.RectangleF layoutRectangle, System.Drawing.StringFormat? format) { }
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, float x, float y) { }
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, float x, float y, System.Drawing.StringFormat? format) { }
        public System.Drawing.Region[] MeasureCharacterRanges(string? text, System.Drawing.Font font, System.Drawing.RectangleF layoutRect, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, System.Drawing.PointF origin, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, System.Drawing.SizeF layoutArea) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, System.Drawing.SizeF layoutArea, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, System.Drawing.SizeF layoutArea, System.Drawing.StringFormat? stringFormat, out int charactersFitted, out int linesFilled) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, int width) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, int width, System.Drawing.StringFormat? format) { throw null; }

        // Proposal
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.PointF point) { }
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.PointF point, System.Drawing.StringFormat? format) { }
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.RectangleF layoutRectangle) { }
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.RectangleF layoutRectangle, System.Drawing.StringFormat? format) { }
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, float x, float y) { }
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, float x, float y, System.Drawing.StringFormat? format) { }
        public System.Drawing.Region[] MeasureCharacterRanges(ReadOnlySpan<char> text, System.Drawing.Font font, System.Drawing.RectangleF layoutRect, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, System.Drawing.PointF origin, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, System.Drawing.SizeF layoutArea) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, System.Drawing.SizeF layoutArea, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, System.Drawing.SizeF layoutArea, System.Drawing.StringFormat? stringFormat, out int charactersFitted, out int linesFilled) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, int width) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, int width, System.Drawing.StringFormat? format) { throw null; }
    }

    public sealed partial class GraphicsPath : System.MarshalByRefObject, System.ICloneable, System.IDisposable
    {
        // Existing:
        public void AddString(string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.Point origin, System.Drawing.StringFormat? format) { }
        public void AddString(string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.PointF origin, System.Drawing.StringFormat? format) { }
        public void AddString(string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.Rectangle layoutRect, System.Drawing.StringFormat? format) { }
        public void AddString(string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.RectangleF layoutRect, System.Drawing.StringFormat? format) { }

        // Proposal
        public void AddString(ReadOnlySpan<char> s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.Point origin, System.Drawing.StringFormat? format) { }
        public void AddString(ReadOnlySpan<char> s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.PointF origin, System.Drawing.StringFormat? format) { }
        public void AddString(ReadOnlySpan<char> s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.Rectangle layoutRect, System.Drawing.StringFormat? format) { }
        public void AddString(ReadOnlySpan<char> s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.RectangleF layoutRect, System.Drawing.StringFormat? format) { }
    }
}

API Usage

It is possible to pass buffers on the stack.

GraphicsPath gp = new GraphicsPath();
...
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    var g = e.Graphics;
    Span<char> buf = stackalloc char[512];
    DateTime.Now.TryFormat(buf, out var writtern);
    g.DrawString(buf, ...);

    gp.AddString(buf, ...);
}

Alternative Designs

I can't think of any.

Risks

I can't think of any.

@udaken udaken added the api-suggestion (1) Early API idea and discussion, it is NOT ready for implementation label May 13, 2022
@ghost ghost added the untriaged The team needs to look at this issue in the next triage label May 13, 2022
@dotnet-issue-labeler dotnet-issue-labeler bot added the area-System.Drawing System.Drawing issues label May 13, 2022
@ghost
Copy link

ghost commented May 13, 2022

Tagging subscribers to this area: @dotnet/area-system-drawing
See info in area-owners.md if you want to be subscribed.

Issue Details

Background and motivation

When drawing strings manually in WinForms, new text is frequently created.
Since the methods System.Drawing.Graphics and System.Drawing.GraphicsPath only accept strings
String allocations occur frequently.

It would be better to add an overload that accepts ReadOnlySpan<char> so that the buffer can be passed directly.

API Proposal

namespace System.Drawing
{
    public sealed partial class Graphics : System.MarshalByRefObject, System.Drawing.IDeviceContext, System.IDisposable
    {
        // Existing:
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.PointF point) { }
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.PointF point, System.Drawing.StringFormat? format) { }
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.RectangleF layoutRectangle) { }
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.RectangleF layoutRectangle, System.Drawing.StringFormat? format) { }
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, float x, float y) { }
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, float x, float y, System.Drawing.StringFormat? format) { }
        public System.Drawing.Region[] MeasureCharacterRanges(string? text, System.Drawing.Font font, System.Drawing.RectangleF layoutRect, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, System.Drawing.PointF origin, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, System.Drawing.SizeF layoutArea) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, System.Drawing.SizeF layoutArea, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, System.Drawing.SizeF layoutArea, System.Drawing.StringFormat? stringFormat, out int charactersFitted, out int linesFilled) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, int width) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, int width, System.Drawing.StringFormat? format) { throw null; }

        // Proposal
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.PointF point) { }
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.PointF point, System.Drawing.StringFormat? format) { }
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.RectangleF layoutRectangle) { }
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.RectangleF layoutRectangle, System.Drawing.StringFormat? format) { }
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, float x, float y) { }
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, float x, float y, System.Drawing.StringFormat? format) { }
        public System.Drawing.Region[] MeasureCharacterRanges(ReadOnlySpan<char> text, System.Drawing.Font font, System.Drawing.RectangleF layoutRect, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, System.Drawing.PointF origin, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, System.Drawing.SizeF layoutArea) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, System.Drawing.SizeF layoutArea, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, System.Drawing.SizeF layoutArea, System.Drawing.StringFormat? stringFormat, out int charactersFitted, out int linesFilled) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, int width) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, int width, System.Drawing.StringFormat? format) { throw null; }
    }

    public sealed partial class GraphicsPath : System.MarshalByRefObject, System.ICloneable, System.IDisposable
    {
        // Existing:
        public void AddString(string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.Point origin, System.Drawing.StringFormat? format) { }
        public void AddString(string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.PointF origin, System.Drawing.StringFormat? format) { }
        public void AddString(string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.Rectangle layoutRect, System.Drawing.StringFormat? format) { }
        public void AddString(string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.RectangleF layoutRect, System.Drawing.StringFormat? format) { }

        // Proposal
        public void AddString(ReadOnlySpan<char> s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.Point origin, System.Drawing.StringFormat? format) { }
        public void AddString(ReadOnlySpan<char> s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.PointF origin, System.Drawing.StringFormat? format) { }
        public void AddString(ReadOnlySpan<char> s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.Rectangle layoutRect, System.Drawing.StringFormat? format) { }
        public void AddString(ReadOnlySpan<char> s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.RectangleF layoutRect, System.Drawing.StringFormat? format) { }
    }
}

API Usage

It is possible to pass buffers on the stack.

GraphicsPath gp = new GraphicsPath();
...
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    var g = e.Graphics;
    Span<char> buf = stackalloc char[512];
    DateTime.Now.TryFormat(buf, out var writtern);
    g.DrawString(buf, ...);

    gp.AddString(buf, ...);
}

Alternative Designs

I can't think of any.

Risks

I can't think of any.

Author: udaken
Assignees: -
Labels:

api-suggestion, area-System.Drawing, untriaged

Milestone: -

@udaken
Copy link
Author

udaken commented May 13, 2022

Note:
System.Windows.Forms.TextRenderer already has an overload that accepts ReadOnlySpan. (#3651)

@ViktorHofer
Copy link
Member

cc @JeremyKuhne

@carlossanlop carlossanlop removed the untriaged The team needs to look at this issue in the next triage label Jun 1, 2022
@carlossanlop carlossanlop modified the milestone: Future Jun 1, 2022
@JeremyKuhne
Copy link
Member

Seems rational. Would just need to double check that the underlying GDI+ APIs all take a length (and not a null-terminated string). I believe that is the case...

@ViktorHofer
Copy link
Member

@JeremyKuhne is this something that WinForms would benefit from? We try to not churn up System.Drawing.Common much.

@JeremyKuhne
Copy link
Member

is this something that WinForms would benefit from?

WinForms customers would, and the implementation should be trivial.

@ViktorHofer
Copy link
Member

ViktorHofer commented Jun 3, 2022

Got it. Who would be the champion to drive this forward and represent it in the API Review meeting? Would it be someone on your team, you or us? // Just making sure that I understand the process for these Drawing issues.

@JeremyKuhne JeremyKuhne transferred this issue from dotnet/runtime Mar 14, 2023
@JeremyKuhne JeremyKuhne added api-ready-for-review (2) API is ready for formal API review; applied by the issue owner blocking Used by the API Review Board and removed api-suggestion (1) Early API idea and discussion, it is NOT ready for implementation labels Mar 14, 2023
@bartonjs
Copy link
Member

Assuming that all the underlying APIs take a (w)char and separate length (vs expecting null termination), looks good as proposed.

namespace System.Drawing
{
    public sealed partial class Graphics : System.MarshalByRefObject, System.Drawing.IDeviceContext, System.IDisposable
    {
        // Existing:
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.PointF point) { }
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.PointF point, System.Drawing.StringFormat? format) { }
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.RectangleF layoutRectangle) { }
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.RectangleF layoutRectangle, System.Drawing.StringFormat? format) { }
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, float x, float y) { }
        public void DrawString(string? s, System.Drawing.Font font, System.Drawing.Brush brush, float x, float y, System.Drawing.StringFormat? format) { }
        public System.Drawing.Region[] MeasureCharacterRanges(string? text, System.Drawing.Font font, System.Drawing.RectangleF layoutRect, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, System.Drawing.PointF origin, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, System.Drawing.SizeF layoutArea) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, System.Drawing.SizeF layoutArea, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, System.Drawing.SizeF layoutArea, System.Drawing.StringFormat? stringFormat, out int charactersFitted, out int linesFilled) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, int width) { throw null; }
        public System.Drawing.SizeF MeasureString(string? text, System.Drawing.Font font, int width, System.Drawing.StringFormat? format) { throw null; }

        // Proposal
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.PointF point) { }
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.PointF point, System.Drawing.StringFormat? format) { }
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.RectangleF layoutRectangle) { }
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.RectangleF layoutRectangle, System.Drawing.StringFormat? format) { }
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, float x, float y) { }
        public void DrawString(ReadOnlySpan<char> s, System.Drawing.Font font, System.Drawing.Brush brush, float x, float y, System.Drawing.StringFormat? format) { }
        public System.Drawing.Region[] MeasureCharacterRanges(ReadOnlySpan<char> text, System.Drawing.Font font, System.Drawing.RectangleF layoutRect, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, System.Drawing.PointF origin, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, System.Drawing.SizeF layoutArea) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, System.Drawing.SizeF layoutArea, System.Drawing.StringFormat? stringFormat) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, System.Drawing.SizeF layoutArea, System.Drawing.StringFormat? stringFormat, out int charactersFitted, out int linesFilled) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, int width) { throw null; }
        public System.Drawing.SizeF MeasureString(ReadOnlySpan<char> text, System.Drawing.Font font, int width, System.Drawing.StringFormat? format) { throw null; }
    }

    public sealed partial class GraphicsPath : System.MarshalByRefObject, System.ICloneable, System.IDisposable
    {
        // Existing:
        public void AddString(string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.Point origin, System.Drawing.StringFormat? format) { }
        public void AddString(string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.PointF origin, System.Drawing.StringFormat? format) { }
        public void AddString(string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.Rectangle layoutRect, System.Drawing.StringFormat? format) { }
        public void AddString(string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.RectangleF layoutRect, System.Drawing.StringFormat? format) { }

        // Proposal
        public void AddString(ReadOnlySpan<char> s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.Point origin, System.Drawing.StringFormat? format) { }
        public void AddString(ReadOnlySpan<char> s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.PointF origin, System.Drawing.StringFormat? format) { }
        public void AddString(ReadOnlySpan<char> s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.Rectangle layoutRect, System.Drawing.StringFormat? format) { }
        public void AddString(ReadOnlySpan<char> s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.RectangleF layoutRect, System.Drawing.StringFormat? format) { }
    }
}

@bartonjs bartonjs added api-approved (4) API was approved in API review, it can be implemented and removed api-ready-for-review (2) API is ready for formal API review; applied by the issue owner blocking Used by the API Review Board labels Mar 16, 2023
@JeremyKuhne JeremyKuhne added this to the .NET 8.0 milestone Mar 16, 2023
@JeremyKuhne JeremyKuhne self-assigned this Mar 16, 2023
JeremyKuhne added a commit to JeremyKuhne/winforms that referenced this issue Mar 20, 2023
Adds `ReadOnlySpan<char>` overloads to `Graphics.DrawString`, `MeasureCharacterRanges`, and `MeasureString`.

Cleaned up docs for these methods as well and called span/string overloads in existing tests.

Fixes: dotnet#8844
@ghost ghost added the 🚧 work in progress Work that is current in progress label Mar 20, 2023
JeremyKuhne added a commit that referenced this issue Mar 21, 2023
Adds `ReadOnlySpan<char>` overloads to `Graphics.DrawString`, `MeasureCharacterRanges`, and `MeasureString`.

Cleaned up docs for these methods as well and called span/string overloads in existing tests.

Fixes: #8844
@ghost ghost removed the 🚧 work in progress Work that is current in progress label Mar 21, 2023
@ghost ghost removed this from the .NET 8.0 milestone Mar 21, 2023
@Philip-Wang01
Copy link

Verified this on .NET 8.0 latest build: 8.0.100-preview.4.23179.4, has been added ReadOnlySpan<char> overloads to Graphics.DrawString.
image

@dotnet dotnet locked as resolved and limited conversation to collaborators Apr 29, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-approved (4) API was approved in API review, it can be implemented area-System.Drawing System.Drawing issues
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants