-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Spaces are not underlined when using the underline tag or an underlined font with FormattedText #38
Comments
In the past, when implementing this functionality myself in my software, I've resorted to a special pass for underline, overline, and strike-through, which I've seen in other places like the Cairo formatter. Basically you calculate the contiguous size of the words, as a group, assuming the formatting isn't changing, and then draw a single horizontal line at the correct height and correct color. It can and should be assumed that you can have a horizontal word-break at any place where the format changes. For example, having One reason I think that the gradient was breaking for formatted text, but not for regular text, is that you're parsing the format of each word individually. A lot of other layout engines will grab the whole block which is identical, calculate in advance the layout of each word, including newlines, and then lay it out like that, keeping track of the current line and the current advance. This means it'll inform the next block of formatting where to begin, and it'll automatically pick up where it left off. One side-benefit of this method is that it provides for automatic line-height/line-spacing for formatted text, since the word's height is included in the new-line when doing the wrapping. This keeping the rendering as per-block instead of per-word would also mean that you can pass any other shapes to the text-layout engine at the same time, and it can calculate intersections with complex shapes as it goes through each of the lines. Once each line is broken up at the correct spot, the layout is pushed to screen, horizontal strike lines are added, and you're done. And since you have text brushes, you can easily incorporate gradients back in as a side-effect. As for the data structures, I have traditionally started with a raw string, and then broken it up into sections of identical formatting. Luckily, all of your formatting tags show you where the breaks are, so you can split that part up as a pre-pass, then create your format info to tag with each block. Also, for simplicity, I've often included any forced newlines as fixed \n at this point so that I make sure to incorporate them at the next step. Then block by block, you check the x and y advances with the next token's approximate size and see if it would exceed the bounds, if so, newline based on the current format's line height, then add the token to the next "line". This means you'll end up with a vector of strings, each entry into the vector is a uniform format. At the end of each string, you keep the newline to help the flow renderer. You should also make sure to never have a newline in the middle of an entry to this vector. Each vector entry is it's own line or a subpart of a single line which is too short or has multiple formats. Once you've got all of those individual strings, calculating the width of each one to do overline/underline/strike-through is trivial. When it comes time to render, you just iterate your previous vector and pass the whole block as necessary with the identical formatting parameters. If the format is the same as the previous line, you can keep the previous parameters in this next iteration, for things like gradients etc. If you encounter a newline at the end of one of these vector entries, then go to the next line. If you don't encounter a newline, you know that the format has changed and should continue at the new advance position. Luckily, you've already calculated that for things like the horizontal lines, so you know where to begin again. Yes, sadly, text flow layout is a 2-step process. I tried in vain for a long time to make it single pass. This process does have the added benefit that it lends itself well to using the GPU to do the rendering, since instead of using a blitting-pass/GDI, you can use it to make the GPU primitives necessary for repeated rendering. |
One side benefit I forgot to mention: the added benefit of pre-computing the positioning of blocks of text means align-bottom gets to be much easier for formatted text, so you can have parts aligned to the top and a certain section also aligned to the bottom of the available area. |
Thank you for all the thoughts and suggestions. 🧐 Admittedly the underlined issue has always annoyed me (just a bit) but so few people have ever complained about it. Some random thoughts:
On the gradients in FormattedText it's actually just an issue with the way rendering is done with translation transforms. I made a couple minor changes and was able to produce this: I'll check into the rest of the required tweaks to see if there are any significant problems. |
From my experience, I always thought it would be difficult to manage the changing states, but in your example above of the nested changes, that would just end up being 3 different entries in the format/textblock vector. The first entry would be My suggestion would be in agreement with your suggestion to make a third type and eventually deprecate the other two, but the basis for the implementation could start off what you've already got working for basic Text, rather than FormattedText. After the incept parser runs, just gotta have a new one for the final output to turn into the text blocks, calculate the block sizes in real-time as you traverse it based on the current format state, and then drop that result into the GDI outputter. In some ways, the first pass can be done token-by-token, read if it's basic text, or an markup tag start/end, and act accordingly. Btw, bravo with the formatted text gradients!!! |
Partial solution for this with FormattedText will be included with v.1.4.0.0-unstable.v.a5 Supported: I'm still investigating alternatives using an actual html renderer that would be a whole new element type. |
This would be nice to have fixed...
Note: Monospaced fonts will render underlines for trailing spaces in a string. Non-monospaced will not.
The text was updated successfully, but these errors were encountered: