Closed laurentvd closed 1 year ago
Thanks for posting. Looks like the transformation matrixes aren't being applied in headless mode for some reason. I'll take a look at this on Monday
So, the issue is that Two.js forms font styles with a leading. As per the specification here, the font
command is the same as the CSS command of the same name which can be seen here. Because ctx.fillText
is only one line, the line-height
metric (which is the leading
property in Two.js) is ignored in the browser.
Unfortunately, this simply breaks in node-canvas
which is why the font size isn't parsed and ultimately not respected in your demo. We can approach this in two ways:
node-canvas
team in the hopes to implement a parse with the line-height
property.ctx.font
assignment when it is undefined or null.As a bandaid, you can update line 20 of src/Renderer.js
in your demo to this to make it work (though I don't know that this is a longterm solution):
scene.makeText('This is a test', 512, 512, {
family: 'BlueStone',
leading: null,
size: 100,
fill: '#FFFFFF',
leading: null,
});
Thanks a lot for diving into this! Really appreciate it. I don't have enough knowledge about the specs yet to fully understand what you're saying, so I'll dive into it. I did try your band-aid, but for me it makes it render in the incorrect font (both node-canvas and canvas) and incorrect size.
Like this:
Thanks again for your explanation @jonobr1, I understand the issue now. In my case I can actually define the leading
. When I set the leading
to be the same as the size
, the font size is rendered exactly the same in both canvases. However, it seems to be placed a few pixels 'lower' using node-canvas
. Do you know what could cause this? Because if I understood your explanation correctly, with the leading
defined, it should render the same, right?
Glad to hear you were able to get it working in both places. It should render the same, but there could be discrepancies between node-canvas
and browser implementations for vertical alignment. You can try setting baseline
to top
, bottom
, and middle
(or some other ones based on the specification) like so:
scene.makeText('This is a test', 512, 512, {
family: 'BlueStone',
leading: null,
size: 100,
fill: '#FFFFFF',
leading: 100,
baseline: 'top'
});
The default for Two.js is middle
. Perhaps a different baseline would be treated the same by both the browser and node-canvas
?
Thanks @jonobr1 for the hint on where to look! I got it working properly for single line texts using these settings:
scene.makeText('This is a test', 512, 512, {
family: 'BlueStone',
fill: '#FFFFFF',
leading: 100,
size: 100,
baseline: 'baseline',
});
Being restricted to baseline only is not ideal, but I can correct this by wrapping it in a group and setting the y
position on the text. If node-canvas
does indeed only support baseline: 'baseline'
, maybe we can add a note of that to the documentation?
One more thing; I am using https://github.com/juliendargelos/twojs-multiline-text/ to allow multiline texts in Two.js, but the large leading
doesn't play nice with it. It works perfectly fine when the leading is not defined. I guess I have to take a look at that and figure out why it does that. Any pointers are very welcome :) And also, I was surprised to find out Two.js doesn't support multiline out of the box. But perhaps the complexity involved with it is the reason.
Thanks. Glad you got it working.
I'm not deeply familiar with that multiline text plugin. For my purposes, multiline text (like in http://typatone.com/) was always done in DOM and then a Two.js scene is super (or in the case of Typatone sub) imposed and animations. But, it could make sense to make it an extra like Two.ZUI
in the extras
folder.
I added a documentation note here: https://github.com/jonobr1/two.js/commit/8090e2b8b2e394aaeb132837b2e8017e60918069
Great stuff! Thanks for adding the note in the docs. One more thing for others finding this issue in the future; I was able to have consistent output using the following configuration:
const text = new MultilineText("this is my text", 0, 0, {
family: "YourFont",
size: 100,
leading: 100,
absoluteLeading: true, // This make it consistent between Node and browser
fill: '#ff0000',
measure: 'font',
mode: 'pre',
baseline: 'baseline'
});
Now that we've added a little warning in the docs, I'd say we can close this ticket. Would you agree @jonobr1?
Thanks for that! I'll close this out then.
Describe the bug The text rendering is inconsistent between web and node canvasses.
To Reproduce I've created a separate repo to reproduce the issue. It can be found here: https://github.com/laurentvd/isomorphic-text-rendering-bug
Expected behavior I'd expect the HTML canvas to look exactly the same as the generated image from
node-canvas
. However, the text is rendered much smaller in the headless canvas.Screenshots
HTML canvas:
Node canvas:
Environment (please select one):
Desktop (please complete the following information):