dhowe / ramble

Ramble v2.0
0 stars 3 forks source link

Issue with width calculation of similars #116

Open dhowe opened 2 years ago

dhowe commented 2 years ago

I've noticed that sometimes a similar is allowed in widthChangePercentage() that then causes the min or max wordspacing constraint to be violated for the line

I looked at this function (and also did some refactoring) and I've isolated the problem in the width-test branch. Running the branch will generate the console output below. Note that for the circled word, the wordspace required is -0.07, which is outside the allowable range (-0.05 - 0.5), yet it is allowed, and the resulting line is incorrect (see 2nd image)

I think that what is needed here for min/max allowed width is not +/- 5%, but the width of that line with the min and max word-spacing (ideally calculated without a loop that repeatedly calls measureWidthCtx)

image image
Real-John-Cheung commented 2 years ago

I think that what is needed here for min/max allowed width is not +/- 5%, but the width of that line with the min and max word-spacing (ideally calculated without a loop that repeatedly calls measureWidthCtx)

hmm it might sounds a bit weird but I think in this case, brotherwoods should be allowed according to our current idea... so currently the min/max allowed width is based on the "ideal width", a.k.a the bounding box (initialMetrics.lineWidths) (I may be wrong but) I think the idea is no matter how the current line looks like the replacement should make it closer to that "ideal width", and in this case: with brotherwoods and min wordspace, the width is close enough (within +-5%) to_ the "ideal width" although -0.07em will make it closest. And therefore if it is chosen it will be rendered with min word space (-0.05em)

the max and min word space of the initial lines might be far away from the ideal width. I am not so sure about using them. If we want to eliminate words like this, I think the best way is to choose them according to the best estimate word space (i.e. call with computeWordSpace every time) like this:

圖片

tho this might take more time

Real-John-Cheung commented 2 years ago

Another idea is to change the definition of close enough, now we define it as within _+5% of the ideal line width, which lead to (huge) gap of absolute value among the first and last line and the middle lines. Maybe we should use -+ some % of the initial width or the combination of them, like this

螢幕截圖 2022-06-06 上午10 47 56
dhowe commented 2 years ago

hmm it might sounds a bit weird but I think in this case, brotherwoods should be allowed according to our current idea... so currently the min/max allowed width is based on the "ideal width", a.k.a the bounding box (initialMetrics.lineWidths) (I may be wrong but) I think the idea is no matter how the current line looks like the replacement should make it closer to that "ideal width", and in this case: with brotherwoods and min wordspace, the width is close enough (within +-5%) to_ the "ideal width" although -0.07em will make it closest. And therefore if it is chosen it will be rendered with min word space (-0.05em)

But the primary objective of this algorithm is to avoid lines which require min or max wordspace, especially in cases like this when many other substitutions would be clearly better

the max and min wordspace of the initial lines might be far away from the ideal width. I am not so sure about using them.

But we want a very short initial line to grow over time and thus look better, due to substitutions (and vice versa for long lines). Again, what we are trying to avoid is lines which look bad because they are too long or too short, and thus require an extreme wordspace value.

In the example above, the line starts out with good wordspace, gets 7 potential similars, only one of which requires wordspace below the minimum. This similar needs to be rejected.

If we want to eliminate words like this, I think the best way is to choose them according to the best estimate word space (i.e. call with computeWordSpace every time) like this

This is one solution, but worry about the performance implications. Do you want to give a test?

Idea: If we had the width of each letter at the current font-size in a lookup table, couldn't we compute the required wordspace as the difference between the total width of the letters and the targetWidth, divided by the number of spaces? This would avoid the canvas measuring calls which I suspect to be quite slow (we should test this as well)

dhowe commented 2 years ago

Another thing to try is adjusting the percentages. The initial default wordspace is 0.1, which is much closer to the minimum (-0.05) than to the maximum (0.5). Perhaps we simply need to change the min/max allowed width, something like .995 and 1.05, rather than 5% on each side.

Real-John-Cheung commented 2 years ago

Perhaps we simply need to change the min/max allowed width, something like .995 and 1.05, rather than 5% on each side.

That's a good idea, but I do think that we should keep it the same on each side coz it doesn't really relate to the max and min word space (this limit is to make the whole display looks like a circle, while the max and min word space is to make the text readable) I shrink the limit to 0.03% on each side with 1% of the initial radius as the minimal scale for the offset (this is to prevent unexpected elimination in short lines): 圖片

it results quite good though rarely choice that make the line hit the word space limit still being accepted (happened less than 5 times in hundreds of steps). I think this can do for now before we figure out if

If we had the width of each letter at the current font-size in a lookup table, couldn't we compute the required wordspace as the difference between the total width of the letters and the targetWidth, divided by the number of spaces?

or

choose them according to the best estimate word space (i.e. call with computeWordSpace every time)

works.