[p5.js 2.0 Beta Bug Report]: Document difference between textWidth and fontWidth with respect to whitespace
Most appropriate sub-area of p5.js?
- [ ] Accessibility
- [ ] Color
- [ ] Core/Environment/Rendering
- [ ] Data
- [ ] DOM
- [ ] Events
- [ ] Image
- [ ] IO
- [ ] Math
- [x] Typography
- [ ] Utilities
- [ ] WebGL
- [ ] Build process
- [ ] Unit testing
- [ ] Internationalization
- [ ] Friendly errors
- [ ] Other (specify if possible)
p5.js version
Latest dev-2.0
Web browser and version
Firefox
Operating system
MacOS
Steps to reproduce this
This logs 0 in 2.0 but something around 5 in 1.x:
function setup() {
createCanvas(200, 200)
textSize(20)
console.log(textWidth(' '))
}
Live: https://editor.p5js.org/davepagurek/sketches/xlqZOPgIR
Looks like maybe a conditional logic issue, with the empty string not getting evaluated? If the space is between characters, it is counted:
With 2.0:
function setup() {
createCanvas(200, 200)
textSize(20)
console.log(textWidth(' ')) // 0
console.log(textWidth('x')) // 9.58984375
console.log(textWidth('xy')) // 19.658203125
console.log(textWidth('x y')) // 25.21484375
}
Volunteers welcome to work on fixing this issue! Specifically, textWidth(' ') should not be 0, rather something around 5.
Hi! I would like to be assigned to this issue.
Thanks @HughJacks ! I'll assign this to you.
I looked into the issue with textWidth(' ') returning 0. From what I can see the issue has to do with the fact that we calculate text width using actualBoundingBoxLeft and actualBoundingBoxRight from the TextMetrics object.
Current behavior:
let metrics = this.textDrawingContext().measureText(s);
let abl = metrics.actualBoundingBoxLeft;
let abr = metrics.actualBoundingBoxRight;
return abr + abl;
For a space character, both actualBoundingBoxLeft and actualBoundingBoxRight are 0, resulting in a total width of 0. However, the space character does have a visual width that should be measured.
Looking at the TextMetrics object for a space:
Metrics: TextMetrics {
width: 5.556640625, // This is the actual advance width
actualBoundingBoxLeft: 0, // No left extension
actualBoundingBoxRight: 0, // No right extension
fontBoundingBoxAscent: 1.6875,
fontBoundingBoxDescent: 21.3125,
...
}
Below is a screenshot showing how we handle other cases.
I notice that ' x y ' has the same width as 'x y'.
I'm not sure if the issue is within _textWidthSingle or the conditional logic within _processLines.
What are the desired outputs of calling textWidth on each of these cases?
Maybe @dhowe has some more info on what the difference between fontWidth and textWidth should be in general? fontWidth uses the width property while textWidth measures using actualBoundingBoxLeft/Right.
Some possible options I could see here:
- If leading/trailing whitespace are the only differences in general between
textWidth/fontWidth, we could document thattextWidthmeasures just the text content, ignoring leading/trailing spaces, and that you should usefontWidthif you need them to be significant. - If there are other differences and leading/trailing spaces are supposed to count, maybe we could match
/^\s*/and/\s*$/for each line (the leading and trailing whitespace, respectively) and add the.widthproperty for each of those to the total width? - If leading/trailing whitespace are the only differences in general between
textWidth/fontWidthand we think whitespace should always be significant, maybe we should merge those functions?
fontWidth() gives the width of the text via measureText(string).width including leading/trailing invisibles (spaces, etc.)
textWidth() gives the width of the smallest bounding box containing the visible text, by returning the width of that bounding box (not including invisible characters)
It sounds like we do want space to be significant in that case? Since a single space character would still have a bounding box. So would it sound right to you to take the width returned by the current implementation of textWidth and add to that the width due to leading and trailing whitespace?
Here is the current behavior (which is consistent) for the two varieties of xWidth and xBounds, noting that textBounds() uses the same metrics as textWidth(), and fontBounds() uses the same metrics as fontWidth().
textBounds() gives the visual bounding box for the drawn text (with textWidth() giving the width of that box), while fontBounds() uses the browser's measureText(string).width
So it may be that we only need to make this clear in the reference (?)
ok, I think that makes sense! In probably the references for both text and font width, we could briefly explain that one is tight and one is loose, and possibly show a comparison example on both references too (could be the same one on both.)
Thank you so much for the explanation and investigation @HughJacks @dhowe and @davepagurek!
@HughJacks so the current behavior is actually the expected/correct behavior, but it the documentation + examples could really benefit from updates as suggested above:
- explain that one is tight and one is loose
- possibly show a comparison example on both references too (could be the same example on both)
Are you still interested in addressing this issue? If so, please feel free to go ahead and put together a PR updating the documentation for these 2 functions.
Hey @ksen0 sorry for slightly delayed response. Yes I would be interested in updating the documentation and examples. I will get on that soon.
Thanks to everyone for their help.
No worries and no rush @HughJacks ! Thanks for taking this on
Hi @HughJacks ! Are you currently working on this / still interested in working on it?
Hello, my apologies. I am no longer able to work on it. Best!
hello , I want to work on this issue
Hi @Sushma-1706 are you still interested in working on this issue? If so, go ahead!
yes, i am still intrested thank you
It's yours @Sushma-1706 ! Let us know (here or on Discord in the contribute-to-p5 channel) if you have any questions !
Hey @Sushma-1706 are you still working on this issue? if no, then I would like to work on it thank you
@hxrshxz hey , I'm not working on it anymore you go ahead
Hey @ksen0 Can you assign it to me thank you
Hey @ksen0 I would like working on this issue. Can you assign it to me.