vexflow icon indicating copy to clipboard operation
vexflow copied to clipboard

SVGContext's scale(x, y) works differently from CanvasContext's scale(x,y)

Open ronyeh opened this issue 3 years ago • 2 comments

While migrating tests, I encountered a weird bit of code in NoteHeadTests:

https://github.com/0xfe/vexflow/blob/b37ddd7a228c69b165c96f4431598b703585fc37/tests/notehead_tests.ts#L34-L62

The setupContext() scales the context to 0.9, 0.9. The basic() test case applies another scale of 2.0, 2.0. (It also ignores the stave created by setupContext and creates its own stave, but that's another story.)

The scaling transformation should be multiplied against the existing scale: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/scale

So 0.9 * 2.0 => 1.8 final scale.

flow.html shows that the Canvas renderer works as expected, but the SVG renderer sets the final scale to 2.0, 2.0.

The fix might be straightforward. In SVGContext's scale method, we have: this.state.scale = { x, y };

We probably just need to multiply it into the existing scale.

This bug has existed for a while, as it repros on vexflow.com: https://www.vexflow.com/tests/?module=NoteHead

You can verify the bug by doing something like this:

  ctx.scale(2.0, 2.0);
  ctx.scale(0.5, 0.5);
  ctx.scale(2.0, 2.0);
  ctx.scale(0.5, 0.5);

The final output will look like:

S 2021-09-01 at 10 25 22

ronyeh avatar Sep 01 '21 17:09 ronyeh

That is a bug -- and great catch! It's an implementation detail I never realized.

I think we should fix it for correctness, however practically, scale is just called once on a new renderer.

0xfe avatar Sep 04 '21 10:09 0xfe

@ronyeh you wanted to correct that in 4.1

rvilarl avatar Jun 09 '22 20:06 rvilarl