API Proposal: Add safe overloads to TextRenderer to get output strings.
#3.710 aberto em 10 de ago. de 2020
Métricas do repositório
- Stars
- (4.100 stars)
- Métricas de merge de PR
- (Mesclagem média 14d 22h) (56 fundiu PRs em 30d)
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.