0

I'm using Microsoft's Cascadia Code font and drawing text with DirectWrite using ID2D1RenderTarget::DrawTextLayout, with individual glyphs colored using IDWriteTextLayout::SetDrawingEffect(CreateSolidColorBrush(...)).

Cascadia Code has a ligature for "greater than or equal to" (=>) that draws as a single arrow glyph. If I have half of the glyph selected, using HitTestTextRange to paint the background highlights the correct area, but setting the selected character's drawingEffect to a different color than the unselected side doesn't work. The entire glyph is painted using the drawing effect from the second character, resulting on one side drawing as white-on-white or black-on-blue. GetClusterMetrics returns two separate clusters for it. Conversely, if I have some Arabic text like ممم, which presumably uses a substituted font, it draws as a ligature, but the individual characters within it will draw as different colors.

Notepad vs App comparison

Is implementing IDWriteTextRenderer the best way to handle this situation or is there an easier one?

Also, comparing Cascadia Code's supported ligatures in Notepad or Visual Studio Code against my app shows that most ligatures are drawn like they should be, but a handful of them aren't. -~ (minus tilde) draws as a single symbol in Notepad, VS Code, my app, and the Windows SDK's PadWrite sample app, but /\ only draws as an inverted V in the first two. The "infinite arrows" like >==>==> are similarly broken up. Is there a setting I need to use to enable all of them?

Zoë Peterson
  • 13,094
  • 2
  • 44
  • 64
  • SetDrawingEffect applies to character ranges, not glyphs. If you want to color glyphs specifically, you'll need a custom renderer probably (depending on what you need exactly). Regarding different shaping results, it's probably easiest to take a look how this specific font defines /\ substitution for example, and see what feature uses it. Are you sure Notepad is using directwrite in modern versions, by the way? – bunglehead May 04 '21 at 20:58
  • @bunglehead I'm moving the caret using HitTestTextPosition, so the selection is character based and handles combining characters, but for =>, it stops in the middle. In that case, I just want to draw the selected half as white-on-blue instead of black-on-white. I can get the rectangles that should be blue using HitTestTextRange, so it sounds like the easiest way to handle this would be to clip the text and draw it twice, once normally and once selected? – Zoë Peterson May 04 '21 at 21:15
  • @bunglehead I'd also like to know what character ranges map to a single glyph so I know that a particular range will be a single color. I thought GetClusterMetrics gave that, but apparently not? As for for font substitution features, that's the IDWriteTypography interface? I don't know whether Notepad is using DirectWrite or not; I just expected that if Cascadia Code supports them and DirectWrite is the newest API, it must somehow be straightforward to enable them – Zoë Peterson May 04 '21 at 21:28
  • I don't think layout exposes clustermap, cluster metrics only tell you a number of clusters and how many characters each cluster took. What you need is a range of indices into glyphIndices that correspond to give range of characters. DWRITE_GLYPH_RUN_DESCRIPTION.clusterMap is for that, to be used with textPosition field. – bunglehead May 04 '21 at 21:42
  • Regarding features, what I mean is that you can examine actual font file for a GSUB table to see its features and lookups. It's possible that lower level clients like Edit control aka Notepad would be using IDWriteTextAnalyzer (if it was using directwrite), which allows user features directly. For layout, yes, you'll need IDWriteTypography instance if you want custom features. – bunglehead May 04 '21 at 21:44

0 Answers0