0

I am using drawingContext.DrawGlyphRun in my scenario, as I need the best performance I can get as I am rendering a large amount of text at lots of different positions on screen.

However, I have come into a slight snag. The font I am using is missing some unicode characters for codes such as ✓, ∞

It looks like drawingContext.DrawText has a very handy feature where a fallback font is used where characters are missing, such that you still at least get something rendered.

So now I am wondering how I could achieve something similar without losing all the performance gains I got from switching to DrawGlyphRun

Seems like I would need to break up the call in multiple parts

"My string with ∞ unsupported character"
[My string with ][∞][ unsupported character]

So 3 calls to drawingContext.DrawGlyphRun, with the 2nd one using a different font :(

And then I would also need to compute the position offsets so it all aligns correctly.

Other than changing the font (something I can't really do) am I missing an obvious easy way of doing this?

asked Oct 13, 2024 at 10:35
8
  • How about a TextBlock with multiple Inline (text) Runs, that specify the font attributes. I (can) use a single TextBlock to display Segoe (colored) MDL2, Emoji and (colored) Symbol characters at the same time; including unicode. As for performance, I animate a few hundred user controls (at the same time) using this pattern to show "status" on the element. Commented Oct 13, 2024 at 21:22
  • TextBlock uses drawingContext.DrawText. I'm rendering about 1500+ of these strings on a large display (a bit like a spreadsheet, and all are in view at the same time, so virtualisation is no help) and it gets very slow with DrawText. One option I am thinking of is to just fall back to DrawText if the string contains an unknown character. But knowing my luck, all 1500 strings will have the unknown char :P Commented Oct 14, 2024 at 8:46
  • I'm not doing any "virtualization"; these are individual user controls that host a TextBlock that displays different strings based on a toggle. The "canvas" is 6500 by 5800. A ScrollViewer zooms the whole thing in and out. I used a "few hundred" as a number. I can host thousands. All animating. Commented Oct 17, 2024 at 23:34
  • @GerrySchmitz interesting. Do you think you could share the code on github or something please? I am curious to see what you're doing Commented Oct 20, 2024 at 11:48
  • The essence of my response is TextBlock.Inlines and Run; which this link touches on. learn.microsoft.com/en-us/uwp/api/… Commented Oct 22, 2024 at 16:53

1 Answer 1

0

I managed to get this working by using the Global User Interface fontfamily. Which a collection of typefaces that are used as fallbacks when a character code is not found in the target font.

I decided to cache the typeface for these missing character codes.

private readonly Dictionary<int, GlyphTypeface?> _fallbackGlyphMapping = [];
private bool TryGetFallbackGlyphTypeface(int code, [NotNullWhen(true)] out GlyphTypeface? glyphTypeface)
{
 if (!_fallbackGlyphMapping.TryGetValue(code, out glyphTypeface))
 {
 _globalFontFamily ??= new FontFamily("Global User Interface");
 foreach (var map in _globalFontFamily.FamilyMaps)
 {
 var typeface = new Typeface(new FontFamily(map.Target), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal);
 if (typeface.TryGetGlyphTypeface(out GlyphTypeface? tempGlyphTypeface))
 {
 if (tempGlyphTypeface.CharacterToGlyphMap.TryGetValue(code, out var index))
 {
 _fallbackGlyphMapping[code] = tempGlyphTypeface;
 glyphTypeface = tempGlyphTypeface;
 return true;
 }
 }
 }
 // couldn't locate
 _fallbackGlyphMapping[code] = null;
 return false;
 }
 return glyphTypeface != null;
}
answered Oct 27, 2024 at 17:17
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.