dotnet / dotnet/wpf

[API Proposal]: GlyphRun.TextFormattingMode

Open
#7,735 0 comments 2 reactions 0 assignees View on GitHub
API suggestion
Dominant language
C#
Stars
7.7k
Forks
1.3k
Avg merge
1d 11h
Merged PRs (30d)
61

Description

### Background and motivation

`GlyphRun.TextFormattingMode` is currently fixed to `TextFormattingMode.Ideal` when creating `GlyphRun` directly, while it already supports `TextFormattingModel.Display` via e.g. `TextBlock` (`TextOptions.TextFormattingMode`).

This makes it impossible to render individual glyphs into bitmap using `Display` formatting, which is required for GDI compatibility. Currently the property can be changed using reflection. This proposal is to add a public property to this field.

Originally proposed in #2638.

### API Proposal

```diff
public partial class GlyphRun : ISupportInitialize
{
[ObsoleteAttribute("Use the PixelsPerDip override", false)]
public GlyphRun();
public GlyphRun(float pixelsPerDip);
[CLSCompliantAttribute(false)]
[ObsoleteAttribute("Use the PixelsPerDip override", false)]
public GlyphRun(GlyphTypeface glyphTypeface, int bidiLevel, bool isSideways, double renderingEmSize, IList glyphIndices, Point baselineOrigin, IList advanceWidths, IList glyphOffsets, IList characters, string deviceFontName, IList clusterMap, IList caretStops, XmlLanguage language);
[CLSCompliantAttribute(false)]
public GlyphRun(GlyphTypeface glyphTypeface, int bidiLevel, bool isSideways, double renderingEmSize, float pixelsPerDip, IList glyphIndices, Point baselineOrigin, IList advanceWidths, IList glyphOffsets, IList characters, string deviceFontName, IList clusterMap, IList caretStops, XmlLanguage language);
[CLSCompliantAttribute(false)]
[TypeConverterAttribute(typeof(DoubleIListConverter))]
public IList AdvanceWidths { get; set; }
public Point BaselineOrigin { get; set; }
public int BidiLevel { get; set; }
[CLSCompliantAttribute(false)]
[TypeConverterAttribute(typeof(BoolIListConverter))]
public IList CaretStops { get; set; }
[CLSCompliantAttribute(false)]
[TypeConverterAttribute(typeof(CharIListConverter))]
public IList Characters { get; set; }
[CLSCompliantAttribute(false)]
[TypeConverterAttribute(typeof(UShortIListConverter))]
public IList ClusterMap { get; set; }
public string DeviceFontName { get; set; }
public double FontRenderingEmSize { get; set; }
[CLSCompliantAttribute(false)]
[TypeConverterAttribute(typeof(UShortIListConverter))]
public IList GlyphIndices { get; set; }
[CLSCompliantAttribute(false)]
[TypeConverterAttribute(typeof(PointIListConverter))]
public IList GlyphOffsets { get; set; }
public GlyphTypeface GlyphTypeface { get; set; }
public bool IsHitTestable { get; }
public bool IsSideways { get; set; }
public XmlLanguage Language { get; set; }
public float PixelsPerDip { get; set; }
+ public TextFormattingMode TextFormattingMode { get; set; }
public Geometry BuildGeometry();
public Rect ComputeAlignmentBox();
public Rect ComputeInkBoundingBox();
public CharacterHit GetCaretCharacterHitFromDistance(double distance, out bool isInside);
public double GetDistanceFromCaretCharacterHit(CharacterHit characterHit);
public CharacterHit GetNextCaretCharacterHit(CharacterHit characterHit);
public CharacterHit GetPreviousCaretCharacterHit(CharacterHit characterHit);
void ISupportInitialize.BeginInit();
void ISupportInitialize.EndInit();
}
```

### API Usage

```c#
var run = new GlyphRun();
run.TextFormattingMode = TextFormattingMode.Display; // new
run.GlyphTypeface = _typeface;
run.FontRenderingEmSize = 12;
run.GlyphIndices = new ushort[] { 0 };
run.AdvanceWidths = new double[] { 0.0 };

using (DrawingContext context = visual.RenderOpen())
{
context.DrawGlyphRun(Brushes.Black, run);
}
```

### Alternative Designs

Alternatively, the existing

```C#
internal TryCreate(
GlyphTypeface glyphTypeface,
int bidiLevel,
bool isSideways,
double renderingEmSize,
float pixelsPerDip,
IList glyphIndices,
Point baselineOrigin,
IList advanceWidths,
IList glyphOffsets,
IList characters,
string deviceFontName,
IList clusterMap,
IList caretStops,
XmlLanguage language,
TextFormattingMode textLayout)
```

coulde be made public.

There are also public `GlyphRun` constructors that take all the property values and pass them to `TryCreate`, but I don't see a need to add another constructor overload, since `GlyphRun` is `ISupportInitialize`

### Risks

Low, the `GlyphRun` already supports various `TextFormattingMode`s for other API.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.