processing / p5.js

p5.js is a client-side JS platform that empowers artists, designers, students, and anyone to learn to code and express themselves creatively on the web. It is based on the core principles of Processing. http://twitter.com/p5xjs —
http://p5js.org/
GNU Lesser General Public License v2.1
21.13k stars 3.23k forks source link

Support 'justified' alignment as an option for textAlign #3354

Open dhowe opened 5 years ago

dhowe commented 5 years ago

Support 'JUSTIFIED' alignment as an option for textAlign(), so that we can have text that looks like below. Note: we would need to check that the optional 'width' param was specified to text() when using this alignment. If I remember correctly there is an nice dynamic programming solution to this problem.

image

rdslade commented 4 years ago

Planning to work on this issue!

dhowe commented 4 years ago

Great. Note that in some of the approaches discussed online, extra space characters are added to extend the line, however this is not what we want here - rather we need to adjust the start position of each word

aditya-shrivastavv commented 1 year ago

Does anybody have an idea on how to implement this

dhowe commented 1 year ago

There is a somewhat well-known algorithm for this by Knuth/Plass (included in TeX/LaTeX) that uses dynamic programming - you can read about it here. There are also existing js libraries (here is one) that implement it, though I haven't tried any...

aditya-shrivastavv commented 1 year ago

I found a new way of doing it. since we have opentype.js library already being used in the project we can make use of it's letter spacing method if possible. check here - https://github.com/opentypejs/opentype.js/pull/219

aditya-shrivastavv commented 1 year ago

@davepagurek @dhowe should i try to implement this leetcode question's algorithm here ?

davepagurek commented 1 year ago

@aditya-shrivastavv I think something like that would be good, specifically the approach of first placing words into each line until they no longer fit before breaking to the next line. However, for us, width is based on pixels rather than characters. Then, rather than padding with spaces to reach a total character count, we would split lines on spaces and position the x value of each word so that they are evenly spaced, with the first word is aligned with the left of the block and the last word of the line is aligned with the right of the block.

dhowe commented 1 year ago

a few things to note:

davepagurek commented 1 year ago

For performance, from my own testing, I've found that rendering in smaller chunks can be fine as long as we avoid push/pop, which saves and restores a fair amount of state. So this could mean keeping track of incremental position changes and then manually resetting with a translate. Anyway, agreed, it's a good thing to keep in mind and measure!

limzykenneth commented 1 year ago

Just to mention, we may need to take into account hyphenated word break or quite often justified text would look quite weird with large gaps between words or characters. That will require its own algorithm as well if we want to do it properly as there are specific rules around how English word should be broken up with hyphens, and that's also not considering other languages and scripts as well.

Ideally there is a library or even browser API that can do all the implementation for us so we don't have to start from scratch.

dhowe commented 1 year ago

This library seems to do all of what we need, including handling hyphenization, as @limzykenneth correctly notes, but it would require non-trivial testing to make sure it can be integrated smoothly with our existing text-rendering routines

munusshih commented 10 months ago

I almost feel like instead of relying on another library, we can probably hard code something like this: https://riptutorial.com/html5-canvas/example/19482/justified-text

But then at the same time, I feel like incorporating this might requires more discussions and thinking. One of the issues with the library suggested by @dhowe is that it's using another library hyphen which only supports English right now. I've test it on Mandarin and Arabic, and it didn't seem to work on neither of them.