Canvas-kit Paragraph's alignment with spaces

239 views
Skip to first unread message

Данил Буланов

unread,
Oct 13, 2023, 2:31:52 PM10/13/23
to skia-discuss
Is it possible to take spaces into account when pagagraph is aligned by center or right? It seems that by default spaces are just ommited from the line when the alignement happens.

jlav...@google.com

unread,
Oct 13, 2023, 3:52:27 PM10/13/23
to skia-discuss
I am not sure about "taking spaces into account". Does it mean:
1. Include spaces into the line width? 
2. Include space codepoints into line info?
3. Show spaces on screen somehow?
4. Or something else?
In general centering the text or shifting the text to the right is not done by adding some spaces. 
But I still think we can figure out how to get you what you need. 
(It would be helpful to have a small code example that demonstrates the issue)

Thanks, Julia

Данил Буланов

unread,
Oct 13, 2023, 4:06:35 PM10/13/23
to skia-discuss
Generaly speaking, I want to have a behaviour the same as this html code
```
<!DOCTYPE html>
<html>
<body>

<div style="width: 100px; word-break: break-word; white-space: pre-wrap; border: 1px solid red; text-align: center">
Hello hehe
</div>

</body>
</html>
```

So whitespaces are taken into account for alignment (white-space: pre-wrap is responsible for that). And if two words are too long, those are broken so that the first word is on the first line (with all the spaces between those two words) and the second word is on the second line (that is important, because by default paragraph does not always put the word on the second line, depending on the length of the word it can be broken in the middle of the second word, so that one part of the second word is on the first line, and the other is on the second)

I will make several examples in the next message.


пятница, 13 октября 2023 г. в 21:31:52 UTC+3, Данил Буланов:

Данил Буланов

unread,
Oct 13, 2023, 4:25:37 PM10/13/23
to skia-discuss
I added two examples, which I described earlier, by this link
https://jsfiddle.skia.org/canvaskit/3604c4789afb74fbd9433c54edd4aae15722acb793b4b64732418fefd4852b72
пятница, 13 октября 2023 г. в 22:52:27 UTC+3, jlav...@google.com:

John Stiles

unread,
Oct 13, 2023, 4:37:40 PM10/13/23
to skia-d...@googlegroups.com
I think your "example1" is broken because it doesn't use a word; colons and parentheses will allow line breaking to occur.
When I change it to const example1 = 'hello   worldIIIIIIIIIIII'; it works as you would like.


--
You received this message because you are subscribed to the Google Groups "skia-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to skia-discuss...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/skia-discuss/3565dc00-1807-4b63-9784-35aead097812n%40googlegroups.com.

jlav...@google.com

unread,
Oct 13, 2023, 4:43:33 PM10/13/23
to skia-discuss
Ok, now I think I see what you want. You want a custom formatting on top of our standard center formatting.
We do not support that but there is a way to get what you want, I think... 
In your example I changed the second text:
const example2 = "hello\u00A0\u00A0\u00A0\u00A0\u00A0 world"
\u00A0 is a non-breaking space; it show as a space but does not let the text to be broken at that codepoint.
You still need one normal space before the word "world" so the text gets broken by lines but your "hello" words gets shifted...
I do not like it much because you will have to know too much about the text shown but it should get you what you wanted.
Let me know if it helps.

Julia

Данил Буланов

unread,
Oct 13, 2023, 5:11:52 PM10/13/23
to skia-discuss
I was wondering about changing the actual algorithm under the hood, but for now It seems too complicated, since I never done such thing before

I have just found this issue, which is opened quite a while ago, so maybe that is not the easiest thing to do

https://issues.skia.org/issues/40043028

пятница, 13 октября 2023 г. в 23:43:33 UTC+3, jlav...@google.com:

Данил Буланов

unread,
Oct 13, 2023, 5:11:52 PM10/13/23
to skia-discuss
The problem is that it depends on the length, if I would use this string (just added a little bit more `I`s)

const example1 = 'hello   worldIIIIIIIIIIIIII';

it will not break the line, but in my case this is preferable behaviour :)

пятница, 13 октября 2023 г. в 23:37:40 UTC+3, johns...@google.com:

Данил Буланов

unread,
Oct 13, 2023, 5:11:52 PM10/13/23
to skia-discuss
It seems to be working with several spaces, but If there is just one space, It won't, because I need this one space to be on the first line for alignment 

пятница, 13 октября 2023 г. в 23:43:33 UTC+3, jlav...@google.com:
Ok, now I think I see what you want. You want a custom formatting on top of our standard center formatting.

jlav...@google.com

unread,
Oct 13, 2023, 5:17:22 PM10/13/23
to skia-discuss
This is exactly what I meant: it gets trickier with every change.
You can use a combination of non-breaking space + zero width space instead of the last space:
"hello\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u200Bworld"
It preserves the shift (by \u00A0) but still breaks the line at zero width space (\u200B).

Данил Буланов

unread,
Oct 13, 2023, 5:27:26 PM10/13/23
to skia-discuss
Ah, that's smart :) But there is another problem, for some reason if the second word is longer than the certain length -- it just does not put it to the second line, it prefers to break it in the middle, and I don't know to make it to do that

суббота, 14 октября 2023 г. в 00:17:22 UTC+3, jlav...@google.com:

jlav...@google.com

unread,
Oct 13, 2023, 5:46:06 PM10/13/23
to skia-discuss
This is a normal SkParagraph formatting algorithm. It breaks the text by lines trying to fit as much text on each line as possible.
The only case when SkParagraph breaks the word in the middle is when the word does not fit the line (word is longer than the line length).
Your second word "world:)))))))))))" is longer than the line width, so SkParagraph breaks it whenever it likes.
The only way to deal with it I could think of is: to check if there is an undesirable part of the text on the first line (it's doable) and then modify the initial text by inserting a new line 
"\n" codepoint at the place you want the break to happen. You will have to do all the paragraph work again then. 
And you will have to do this inserting/removing "\n" every time your layout width is changing.
It would work but maybe we should consider a different approach?  
If you tell me more about the task you are trying to solve I probably could help you more.

Julia

Данил Буланов

unread,
Oct 15, 2023, 12:31:14 PM10/15/23
to skia-discuss
I noticed that the algorithm is not quite like what you described, here are two examples, https://jsfiddle.skia.org/canvaskit/c5e71ac56041f759246edf7609a60df2daeb08044ce2c15cffa9faa1a9bf9cbb

In the first example paragraph is broken as I would like, despite that the second word is definitely longer than line.
The second example shows that if I add third word, it will, for some reason, break the second word in the middle.
And the third example shows that if I add one more letter to the second word from the first example, it will break second word in the middle.
I am not sure that it is right behaviour, looks like some sort of a bug.

My problem is basically the following, I have a rich text editor written in html, but it is not very performant, since I want to be able to scale this editor quite freequently. So I decided to live the editing part using html, since it is already written, but display the editor using canvas-kit, so that it is able to scale fast. Since editing is done via html, I should stick to their way of wrapping and centering text, I sent some html code in one of previous posts.

Your solution seems fine, but I am concerned about performance, I am not sure how expensive the rebuild of paragraph is, since I have to do that several times just for single change, however I can imagine some ways to optimize that.

About another approach. Is it possible to change the skia's algorithm itself? This difference between wrapping seems to be minor, maybe there is an exact place in the code which handles that. This solution is quite good, because I will be able to use paragraph in the same way I do now, without tweaking (except that magic with different kind of whitespaces)
 

суббота, 14 октября 2023 г. в 00:46:06 UTC+3, jlav...@google.com:

jlav...@google.com

unread,
Oct 16, 2023, 9:37:59 AM10/16/23
to skia-discuss
SkParagraph was designed and implemented as a text rendering engine for Flutter, and then tuned up for Flutter even more.
 It does not have enough flexibility because nobody ever wanted it.
This particular problem with breaking a too long word appeared few times and we finally settled for what we have.

About re-layout solution (bad solution but easily implementable):
SkParagraph layout is a very time-consuming procedure and should not be done unnecessarily. 
You can check the performance drop yourself  to decide whether you want to go that way (editing usually allows some performance drop without  problems).
It's not a smart solution, I don't like it very much but it's simple and works fine.

About changing the algorithm (clean solution, don't know if possible):
Change it a bit and see if you like it, then we can discuss it.
However, the only way I could ever include this change into Skia code is to make it parametrized (another paragraph style option, I assume). 
Since you are not the first person raising this issue I would probably consider a reasonable proposal (but no promise).

But I have to warn you, in general, mixing two text-rendering systems is going to be problematic in complex cases (LRT/RTL mix, multiple languages and such). 
There are too many differences between html text rendering and SkParagraph text rendering that you will not be able to fix easily or at all.
Reply all
Reply to author
Forward
0 new messages