Skip to content
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

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

Open
dhowe opened this issue Dec 3, 2018 · 12 comments
Open

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

dhowe opened this issue Dec 3, 2018 · 12 comments

Comments

@dhowe
Copy link
Contributor

dhowe commented Dec 3, 2018

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
Copy link

rdslade commented Dec 2, 2019

Planning to work on this issue!

@dhowe
Copy link
Contributor Author

dhowe commented Dec 2, 2019

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
Copy link
Contributor

Does anybody have an idea on how to implement this

@dhowe
Copy link
Contributor Author

dhowe commented Mar 10, 2023

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
Copy link
Contributor

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 - opentypejs/opentype.js#219

@aditya-shrivastavv
Copy link
Contributor

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

@davepagurek
Copy link
Contributor

@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
Copy link
Contributor Author

dhowe commented Mar 20, 2023

a few things to note:

  • we may also need to test that we get similar alignment when using the DOM's text-justify property with the inter-word property
  • we may also want to measure the performance hit for rendering each word separately, as we don't want sketches to slow down when a user switches to 'justified' alignment from some other method
  • we may also want to specify what happens when a line (for example, with very few words) ends up with very large spaces
  • also, while the greedy approach is a good exercise, it results in noticeably less optimal lines than the approach I've linked above, at least for the inter-character case (not sure about inter-word, but my intuition is that it would be similar) - some more info on the tradeoffs

@davepagurek
Copy link
Contributor

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
Copy link
Member

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
Copy link
Contributor Author

dhowe commented Mar 24, 2023

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
Copy link
Contributor

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.

@limzykenneth limzykenneth moved this to Proposal in p5.js 2.0 May 28, 2024
@limzykenneth limzykenneth moved this from Proposal to Out of Scope in p5.js 2.0 Jun 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Out of Scope
Development

No branches or pull requests

8 participants
@dhowe @davepagurek @limzykenneth @rdslade @Qianqianye @munusshih @aditya-shrivastavv and others