dotnet/winforms

API Proposal: Add safe overloads to TextRenderer to get output strings.

Open

#3 710 ouverte le 10 août 2020

Voir sur GitHub
 (4 commentaires) (2 réactions) (2 assignés)C# (922 forks)batch import
api-approvedhelp wanted

Métriques du dépôt

Stars
 (4 100 stars)
Métriques de merge PR
 (Merge moyen 14j 22h) (56 PRs mergées en 30 j)

Description

Proposal

We need to add new overloads that allow getting out the actual rendered string when using ellipses options (TextFormatFlags.PathEllipsis and TextFormatFlags.WordEllipsis). This is currently done with TextFormatFlags.ModifyString, which mutates the input string. We block this option in the newer span overloads and have obsoleted it.

This is a follow-up to #3651.

namespace System.Windows.Forms
{
    public sealed class TextRenderer
    {
        // Existing flags APIs:
        public static void DrawText(IDeviceContext dc, string text, Font font, Point pt, Color foreColor, Color backColor, TextFormatFlags flags);
        public static void DrawText(IDeviceContext dc, string text, Font font, Point pt, Color foreColor, TextFormatFlags flags);
        public static void DrawText(IDeviceContext dc, string text, Font font, Rectangle bounds, Color foreColor, Color backColor, TextFormatFlags flags);
        public static void DrawText(IDeviceContext dc, string text, Font font, Rectangle bounds, Color foreColor, TextFormatFlags flags);
        public static Size MeasureText(IDeviceContext dc, string text, Font font, Size proposedSize, TextFormatFlags flags);
        public static Size MeasureText(string text, Font font, Size proposedSize, TextFormatFlags flags);
        public static void DrawText(IDeviceContext dc, ReadOnlySpan<char> text, Font font, Point pt, Color foreColor, Color backColor, TextFormatFlags flags);
        public static void DrawText(IDeviceContext dc, ReadOnlySpan<char> text, Font font, Point pt, Color foreColor, TextFormatFlags flags);
        public static void DrawText(IDeviceContext dc, ReadOnlySpan<char> text, Font font, Rectangle bounds, Color foreColor, Color backColor, TextFormatFlags flags);
        public static void DrawText(IDeviceContext dc, ReadOnlySpan<char> text, Font font, Rectangle bounds, Color foreColor, TextFormatFlags flags);
        public static Size MeasureText(IDeviceContext dc, ReadOnlySpan<char> text, Font font, Size proposedSize, TextFormatFlags flags);
        public static Size MeasureText(ReadOnlySpan<char> text, Font font, Size proposedSize, TextFormatFlags flags);

        // Proposed
        public static void DrawText(IDeviceContext dc, string text, Font font, Point pt, Color foreColor, Color backColor, TextFormatFlags flags, out string outputText);
        public static void DrawText(IDeviceContext dc, ReadOnlySpan<char> text, Font font, Point pt, Color foreColor, Color backColor, TextFormatFlags flags, Span<char> outputTextBuffer, out int outputTextLength);
        public static void DrawText(IDeviceContext dc, string text, Font font, Rectangle bounds, Color foreColor, Color backColor, TextFormatFlags flags, out string outputText);
        public static void DrawText(IDeviceContext dc, ReadOnlySpan<char> text, Font font, Rectangle bounds, Color foreColor, Color backColor, TextFormatFlags flags, Span<char> outputTextBuffer, out int outputTextLength);
        public static Size MeasureText(IDeviceContext dc, string text, Font font, Size proposedSize, TextFormatFlags flags, out string outputText);
        public static Size MeasureText(IDeviceContext dc, ReadOnlySpan<char> text, Font font, Size proposedSize, TextFormatFlags flags, Span<char> outputTextBuffer, out int outputTextLength);
        public static Size MeasureText(string text, Font font, Size proposedSize, TextFormatFlags flags, out string outputText);
        public static Size MeasureText(ReadOnlySpan<char> text, Font font, Size proposedSize, TextFormatFlags flags, Span<char> outputTextBuffer, out int outputTextLength);
    }
}

Justification

It is still a valid scenario to want to know what Windows actually outputs. Providing these overloads will let us fully block the mutation of the input strings, which is extremely dangerous.

The proposed surface area aligns with the existing API definitions and allows utilizing the same buffer for the Span APIs for advanced users.

Implementation Details

These APIs will presume you want the output string without requiring the obsoleted flag. When the ellipses flags are set we will get the actual output string from Windows and either create a new string or copy the output into the Span buffer provided and return the length. In all other scenarios we will pass back the input.

The Span overloads will require that the passed in Span<char> is at least as long as the input ReadOnlySpan<char>. If it is not, the API will throw.

We'll skip the overloads for just foreColor and document that Color.Empty is required for a transparent background as these APIs are not as common.

We'll match additional throwing behavior of the original APIs. The original APIs did not throw for null or empty strings, they just no-op.

Guide contributeur