DirectWrite painting ligatures with multiple colors? - directwrite

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.
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?

Related

Minimise width of the multi-line text in Flutter

I have a variable-width container (screen width) and fixed left and right margins. Remaining area gives me a constraint for maximum text width, where I'm placing text of variable content (multiple languages). I want text to fit into that width without truncation, wrapping if needed. Text is relatively short - it may fit into single line, likely to fit into 2 lines and will fit into 3 lines for sure.
I want to avoid cases like (2) - where text wraps into long and a short line. It does not look nice. Instead I would like it to wrap more evenly, like in case (3).
For the demo purposes I've hardcoded hand-picked margins, but I want solution to work automatically for any text content and any container width.
Is it achievable using built-in Flutter widgets, or I need to implement something custom, similar to https://pub.dartlang.org/packages/auto_size_text?

Partial ligature selection with DirectWrite

Using HitTestTextPosition style API from IDWriteTextLayout I did not managed to handle properly text positions inside "ti", "ffi" or other ligatures with fonts like Calibri. It always returns position after or before ligature not inside like t|i or f|f|i.
What is the recommended way to do a caret movement inside ligatures with DirectWrite API?
There... is no "inside" position if you have GSUB replacements turned on?
Opentype GSUB ligatures are single glyph replacements for codepoint sequences, rather than being "several glyphs, smushed together". They are literally distinct, single glyphs, with single bounding boxes, and a single left and right side bearing for cursor placement/alignment. If you have the text A + E and the font has a ligature replacement that turns it into Ӕ then with ligatures enabled there really are only two cursor positions in that code sequence: |Ӕ and Ӕ|. You can't place the cursor "in the middle", because there is no "middle"; it's a single, atomic, indivisible element.
The same goes for f. ligatures like ff, fi, fl, ffi, ffl, or ſt: these are single glyphs once shaped with GSUB turned on. This is in fact what's supposed to happen: having GSUB ligatures enabled means you expressly want text to be presented—for all intents and purposes—as having atomic glyphs for many-to-one substitutions, like turning the full phrase "صلى الله عليه وعلى آله وسلم‎", as well as variations of that, into the single glyph ﷺ.
If you want to work with the base codepoint sequences (so that if you have a text with f + f + i it doesn't turn that into ffi) you will need to load the font with the liga OpenType feature disabled.
The text editors I know of use the simple hack of (1) dividing the width of the glyph cluster by the number of code points within the cluster (excluding any zero width combining marks), rather than use the GDEF caret positioning information. This includes even Word, which you can tell if you look closely enough below. It's not precise, but since it's simple and close enough at ordinary reading sizes, it's what many do:
(2) I've heard that some may (but don't know which) also use the original glyph advances of the unshaped characters (pre-ligation) and scale them proportionally to the ligature cluster width.
(3) Some text editors may use the GDEF table, but I never knew of any for sure (possibly Adobe In-Design?).
The most challenging aspect of using methods 2 or 3 with IDWriteTextLayout is that accessing the corresponding IDWriteFontFace in that run requires quite the indirection because the specific IDWriteFontFace used (after resolving font family name+WWS+variable font axes) is stored in the layout but not publicly accessible via any "getter" API. The only way you can extract them is by "drawing" the glyph runs via IDWriteTextLayout::Draw into a user-defined IDWriteTextRenderer interface to record all the DWRITE_GLYPH_RUN::fontFace's. Then you could call IDWriteFontFace::GetDesignGlyphAdvances on the code points or IDWriteFontFace::TryGetFontTable to read the OpenType GDEF table (which is complex to read). It's a lot of work, and that's because...
The official PadWrite example has the same issue
IDWriteTextLayout was designed for displaying text rather than editing it. It has some functionality for hit-testing which is useful if you want to display an underlined link in a paragraph and test for it being clicked (in which case the ligature would be whole anyway within a word), or if you want to draw some decorations around some text, but it wasn't really intended for the full editing experience, which includes caret navigation. It was always intended that actual text editing engines (e.g. those used in Word, PowerPoint, OpenOffice, ...) would call the lower level API's, which they do.
The PadWrite sample I wrote is a little misleading because although it supports basic editing, that was just so you can play around with the formatting and see how things worked. It had a long way to go before it could really be an interactive editor. For one (the big one), it completely recreated the IDWriteTextLayout each edit, which is why the sample only presented a few paragraphs of text, because a full editor with several pages of text would want to incrementally update the text. I don't work on that team anymore, but I've thought of creating a DWrite helper library on GitHub to fill in some hindsight gaps, and if I ever did, I'd probably just ... use method 1 :b.

Colorize Layers in Inkscape

I need to draw a diagram with different colors. Therefore I would like to have one layer per color.
When I add a layer that contains only a rectangular filled with a color above a layer with a white drawing on a black background. Then I can use the "Blend mode" multiply and the white drawing is colorized.
Is it also possible to just colorize everything in a layer that is black?
I don't think there'll be any GUI-based solution lighter than the one you have.
But since you are in StackOverflow, you can probably code. Then you could use a script with a text file parser (such as sed) to modify the colour of desired elements in the svg file.

Do the colors of the "Zither strings" in VS 2013 signify something? If so, what?

I like the "zither strings" that Visual Studio 2013 displays, that help visually align the braces in try / using / while / etc. blocks of code. I also enjoy them aesthetically, as they appear in different visual representations of points along the electromagnetic spectrum:
But, are those colors "more than a pretty face"? In the screen shot above, I see, from left to right, gray, teal, midnight blue, grey, gray, grey, gray, purple, and grey again. Is this just to help differentiate one line from another? If so, why are several succeeding lines the same hue (as far as I can tell)?
Or, do the colors signify something, such as teal for classes, midnight blue for methods, purple for while, and gr[a,e]y for everything else?
These are part of the Productivity Power Tools for VS2013 (see here). Specifically they are part of the Structure Visualizer feature.
There does seem to be some meaning in the colours. I haven't been able to find a definitive list of colours, but I've noticed the following:
Grey for general blocks, like namespaces, try / catch blocks and using
blocks. The grey for namespaces seems to be a bit darker than other block types.
Teal for classes
Blue for methods
Green for conditional blocks (if / then, switch)
Purple for looping blocks (for, foreach)
You can turn the lines on and off in the Productivity Power Tools section of the Options dialog.

What is the proper way of drawing label in OpenGL Viewport?

I have a multiviewport OpenGL modeler application. It has three different viewports : perspective, front and top. Now I want to paint a label for each viewport and not succeeding in doing it.
What is the best way to print a label for each different perspective?
EDITED : The result
Here is the result of my attempt:
I don't understand why the perspective viewport label got scrambled like that. And, Actually I want to draw it in the upper left corner. How do I accomplished this, because I think it want 3D coordinate... is that right? Here is my code of drawing the label
glColor3f(1,0,0);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glRasterPos2f(0,0);
glPushAttrib(GL_LIST_BIT); // Pushes The Display List Bits
glListBase(base - 32); // Sets The Base Character to 32
glCallLists(strlen("Perspective"), GL_UNSIGNED_BYTE, "Perspective"); // Draws The Display List Textstrlen(label)
glPopAttrib();
I use the code from here http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=13
thanks
For each viewport switch into a projection that allows you to supply "viewport space" coordinates, disable depth testing (glDisable(GL_DEPTH_TEST)) and depth writes (glDepthMask(GL_FALSE)) and draw the text using one of the methods used to draw text in OpenGL (texture mapped fonts, rendering the full text into a texture drawing that one, draw glyphs as actual geometry).
Along with #datenwolf's excellent answer, I'd add just one bit of advice: rather than drawing the label in the viewport, it's usually easier (and often looks better) to draw the label just outside the viewport. This avoids the label covering anything in the viewport, and makes it easy to get nice, cleanly anti-aliased text (which you can normally do in OpenGL as well, but it's more difficult).
If you decide you need to draw the text inside the viewport anyway, I'll add just one minor detail to what #datenwolf said: since you generally do want your text anti-aliased (even if the rest of the picture isn't) you generally want to draw the label after all the other geometry of the picture itself. If you haven't turned on anti-aliasing otherwise, you generally will want to turn it on for drawing the text.

Resources