Skip to content

Incorrect text scaling #1544

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

Open
dangreen opened this issue Mar 23, 2020 · 41 comments
Open

Incorrect text scaling #1544

dangreen opened this issue Mar 23, 2020 · 41 comments

Comments

@dangreen
Copy link

const fs = require('fs');
const {
	createCanvas
} = require('canvas');

const text = "2020";
const canvas = createCanvas(500, 500);
const ctx = canvas.getContext('2d');

ctx.font = '36px Verdana';
ctx.fillStyle = 'red';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';

ctx.scale(1, 4);
ctx.fillText(text, 50, 50);

fs.writeFileSync('canvas-text-scale.png', canvas.toBuffer(undefined, 3, canvas.PNG_FILTER_NONE));

Output:
canvas-text-scale

Expected:
Снимок экрана 2020-03-23 в 14 36 57

macOS 10.15.3
node 11.15.0
canvas 2.6.1

@asturur
Copy link
Contributor

asturur commented Apr 25, 2020

image

the latest compiled version of node-canvas handles it fine ( apart the baseLine with scaling but that is another known issue)
I wonder if the pre-packaged version is working correctly.

this is the code i used in the test app:

tests['#1544 text scaling issue'] = function (ctx) {
  ctx.font = '24px Verdana';
  ctx.fillStyle = 'red';
  ctx.textAlign = 'left';
  ctx.textBaseline = 'top';
  ctx.scale(1, 4);
  ctx.fillText('2020', 20, 20);
}

@blitzbohne
Copy link

@asturur So you think it was / is a node-canvas issue also when we apply a zoom or viewportTransform to fabric and it should be fine in latest node-canvas from master?

@blitzbohne
Copy link

@asturur but I can see fabric uses already 2.6.1? Because according to commits to node-canvas since 2.6.1 I could not find anything relevant that would fix this issue

@asturur
Copy link
Contributor

asturur commented Apr 25, 2020

i made this PR here to improve a bit the top position:
#1562

I work on a macbook.
if i install fabric with npm install, i get the precompiled node-canvas 2.6.1 and i see this problem here under node.
If i go in the downloaded node_modules/node-canvas and i compile the binary there, run the same code again, i get a good output.

Something is off, maybe the default binary does not use pango on mac? ( i m totally shooting i have no idea )

@asturur
Copy link
Contributor

asturur commented Apr 25, 2020

#1506 same issue

@blitzbohne
Copy link

@asturur Sorry for the dumb question but I've tried to then install node canvas from source via npm install canvas --build-from-source but I still get the same issue. Did I do anything wrong on this?

@blitzbohne
Copy link

I've now cleared node_modules/canvas/build*** and ran a node-gyp rebuild there. Everything was compiled fine but still running I see the same text issue resisting?

@asturur
Copy link
Contributor

asturur commented Apr 27, 2020

That is weird. I had a couple of difficulties recompiling because of NVM and a shadow copy of my modules being somewhere. Are you using NVM?

@blitzbohne
Copy link

@asturur No I am not using NVM. I also changed the rendering code in node-canvas, rebuild and it correctly rendered with my changes so its definitely the right thing.

I am currently investigating maybe I can figure something in the code.

@blitzbohne
Copy link

@asturur I can not find any relevant changes in node rendering context changed the past 2-3 years that may have effects on this. The only thing I can imagine is issues on either pango or cairo though I would say pango as it seems to generate a wrong path. Could you tell me versions of both pango and cairo you have @asturur maybe that will help?

I have:

$ pkg-config --modversion pango
1.44.7
$ pkg-config --modversion cairo
1.16.0

@asturur
Copy link
Contributor

asturur commented Apr 27, 2020

abogazzi@abogazzi-mbp $ pkg-config --modversion pango
1.42.4
abogazzi@abogazzi-mbp $ pkg-config --modversion cairo
1.14.12

@blitzbohne
Copy link

Ok I think I figured the cause of this @asturur --

https://github.com/Automattic/node-canvas/blob/master/src/CanvasRenderingContext2d.cc#L2362

Here it assigns the current viewport transformation to pango. If I, for testing, reset the current context's transform to the identity matrix, then call this function, then reset the context's transformation it works perfectly as it is supposed to be.

@blitzbohne
Copy link

@asturur I do currently have troubles downgrading pango / cairo. Would it be possible for you to quickly get the latest pango and cairo from brew then rebuild node canvas if the issue then happens to you, too again?

@blitzbohne
Copy link

@asturur Ok I think I start to understand the issue:

Let's say I have a current cairo matrix on context of [0.5, 0, 0, 0.5, 0, 0] to scale for the half. Now as started before, we assign this current transformation matrix from cairo to pango which then sets the same scaling on the pango context:

https://gitlab.gnome.org/GNOME/pango/blob/1.42.3/pango/pangocairo-context.c#L134

Then we retrieve the path from pango for the text (which already is scaled by 0.5) and then we paint it (!) within the current context's transformation matrix which also is 0.5. And this is where the issue comes from as now we have scaled down twice.

However what I do not understand is the fact that this works on some setups and on some not. For me this looks like a clear issue.

@asturur
Copy link
Contributor

asturur commented Apr 27, 2020

I use this laptop to verify and develop fabricJS and if i mess it up, then i do not have time to fix it.
I was looking at the source line, i m more trying to understand if is possible that there is a bug there. There is something new in cairo 1.17.4 that by far could be related. Can you try to bump it up if is easier?

@asturur
Copy link
Contributor

asturur commented Apr 27, 2020

But the point is that the visual bug does not match the logic bug.
Following your hint, we should see the text scaled vertically by 16 rather than 4.

@asturur
Copy link
Contributor

asturur commented Apr 27, 2020

What can do is adding a test for this in fabricJS and see what the standard travis container thinks about it and what version it uses.

@blitzbohne
Copy link

@asturur Hmm that's correct. It would scale horizontally then too. This is really weird. However I still do not see why is the assignment of the cairo context's transformation matrix required to be assigned to pango which only takes the first four parameters and ignores translations. As I can see later we call pango_cairo_layout_path() which then adds the text path to the current context's path then draws it which would then apply the cairo's transformation again on the already transformed path?

@blitzbohne
Copy link

blitzbohne commented Apr 27, 2020

Ok checking out their sample it seems to be the correct way node-canvas does it:

https://gitlab.gnome.org/GNOME/pango/-/blob/1.42.3/examples/cairosimple.c#L57

So the issue must be somewhere else. Let me try to change the lib version.

@blitzbohne
Copy link

I downgraded cairo but that one fails to run properly. I think the issue will though happen to everyone now as can be seen on the prebuilt-node-canvas because brew, Macports etc. they all have only cairo 1.16.0 which I think causes that issue

@blitzbohne
Copy link

@asturur What would be your advice to do now? The only thing I can think off is to de-activate assigning the viewport matrix to pango when cairo is >= 1.15 <= 1.16 in node-canvas. Would that be reasonable? As of now, with the prebuilts or anyone building on a recent system, it is NOT possible to use text as soon as one uses transformations at all?

@blitzbohne
Copy link

So I couldn't get cairo to work at all outside brew. However I tried to downgrade pango to 1.42 like on your system but the output is still the same. So I assume the issue resides within cairo?

@blitzbohne
Copy link

So it seems pango uses this matrix for text hinting only. So I think it'd be safe enough to de-activate that code part until cairo or pango (whatever is the reason) deliver a fixed version but it seems cairo didn't release any version after 1.16 since a long time.

@asturur
Copy link
Contributor

asturur commented Apr 27, 2020

Did you check for 1.17.2?
in the changelog you find:

type1: fallback if the font matrix is not a uniform scale

I'm not sure if it is remotely related.

@blitzbohne
Copy link

I tried to many versions but got none of them working on my system. Not sure if I did something wrong. recompiled cairo from source and pango got both installed but any version crashed on different ways for me :( I am now patching Node-Canvas class locally which hopefully works.

@blitzbohne
Copy link

@asturur I assume you mean this one:

https://github.com/freedesktop/cairo/commit/717f0e0a40b8d947dad3fb9f25c3aad1619aae87

But it seems to be not related to this issue. For example I do have an uniform matrix where both sx=sy and furthermore there're no changes in this file before 1.14 release which seemed to work.

@blitzbohne
Copy link

@asturur Hmm I think its pango. I can for example correct the issue by compensating the charSpacing in fabricJS with exactly my transformation value giving identical results. So it seems the kerning / hinting for whatever reason is broken and uses ma transformation-matrix for calculating the kerning which gives exactly the troublesome results. So this is not a cairo and/or transformation issue.

The question however is how to fix that

@q-state
Copy link

q-state commented Apr 27, 2020

I had this problem recently and could only fix it by reverting from Node v13.x to Node v12.4.0

Node 12.4.0
Mac OS X: 10.15.4
pango: 1.44.7
canvas: 2.6.1

@blitzbohne
Copy link

blitzbohne commented Apr 27, 2020

@q-state hmm interesting. I think the version of node should not matter. I am, for example, on node 12.11 already.

Though it seems you have the same pango version as I do. Weird. Which cairo version do you have @q-state ?

@q-state
Copy link

q-state commented Apr 27, 2020

I have cairo 1.16.0

@blitzbohne
Copy link

@q-state Now this becomes really confusing. And are you using the node-canvas prebuilt binaries or did you build node-canvas by yourself?

@blitzbohne
Copy link

Ok I upgraded to exactly node 12.4.0 but as I expected it makes no difference the issue is still there :(

@q-state
Copy link

q-state commented Apr 27, 2020

Yeah that's strange. I was using the prebuilt binaries. I have two Macbook Pros and I tested these configurations on each and the node version was the only difference.

@kondis
Copy link

kondis commented Jul 27, 2020

Has there been any progress on this? I’m currently experiencing this as well when I scale an SVG with text. It’s a show stopper for me and I’m not quite sure how to help fix this, as I’m newer to Node and Canvas.

@asturur
Copy link
Contributor

asturur commented Jul 27, 2020

i m hitting the same problem on my new macbook while it was working fine on my old.

@jss-codd
Copy link

I am also facing the same issue , I followed the thread , Is there any update on the fix ?

@SLKnutson
Copy link

I only see only on when running tests in jest, not when running normally.

@vk0novalov
Copy link

The problem is still here

Node: 16.16.0
Cairo: 1.16.0
pango: 1.50.8
canvas: 2.9.3

OS: macOS 12.4; Ubuntu 20.04.3 LTS

@zbjornson
Copy link
Collaborator

I can't reproduce this with 2.10.1 on Windows, neither built from source nor using prebuilds. If folks are still having this issue, can you please list your node-canvas version (node -p "require('canvas').version"), if you compiled from source or used a prebuild, and a reproducible example (if different from the OP)?

@asturur
Copy link
Contributor

asturur commented Sep 10, 2022

This was so long ago and i couldn't reproduce it anymore after getting a new laptop and reinstalling

@trembry
Copy link

trembry commented Oct 5, 2024

Still encountering this issue (build from source):

Node: 20.17.0
node-canvas: 2.11.2
cairo: 1.18.2
pango: 1.54.0
node-gyp: 10.2.0

Chip: M2
OS: Sonoma 14.3

Basic Example (without scaleX, looks beautiful):
Image

import { StaticCanvas, FabricText } from "fabric/node"

const canvas = new StaticCanvas(null, { width: 600, height: 600 })
canvas.backgroundColor = "white"
const text = new FabricText("Hello world", {
  fontSize: 40,
  left: 20,
  top: 20,
})
text.scaleX = 0.5
canvas.add(text)
canvas.renderAll()

canvas.createPNGStream().pipe(fs.createWriteStream("./example.png"))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants