Skip to content
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

Support context.letterSpacing #1014

Open
bhouston opened this issue Sep 30, 2017 · 21 comments
Open

Support context.letterSpacing #1014

bhouston opened this issue Sep 30, 2017 · 21 comments

Comments

@bhouston
Copy link

bhouston commented Sep 30, 2017

Issue or Feature

I would like to be able to adjust the kerning/letter-spacing of fonts when drawing text on node-canvas. In a browser this is possible by setting canvas.style.letterSpacing to something like "-3px". But canvas.style I believe does not exist on node-canvas.

(BTW we love node-canvas, it is an amazing piece of software.)

Steps to Reproduce

Interactive example of it working with browser-based Canvas:

https://jsfiddle.net/hg4pbsne/1/

Example code:

  canvas.style.letterSpacing = '-5px';
  ctx = canvas.getContext('2d');
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  ctx.font = '4em sans-serif';
  ctx.fillText('World', can.width/2, can.height*3/4);

This is not possible to reproduce with node-canvas as there is no canvas.style property exposed.

Your Environment

All versions of node-canvas.

My Suggestion

We add a non-standard ctx._letterSpacing parameter to node-canvas that exposes this functionality?

@Hjlxc
Copy link

Hjlxc commented Oct 2, 2017

I found this possible solution that uses measure text to compute it manually:

https://gist.github.com/talltyler/5345894

@chearon
Copy link
Collaborator

chearon commented Oct 2, 2017

It could be done inside canvas with pango_attr_letter_spacing_new and pango_layout_set_attributes but I'm not sure if adding more non-standard features is a good path to go down.

@JamesCarlyleClarke
Copy link

Perhaps look at https://stackoverflow.com/questions/33955754/adding-letter-spacing-in-html-canvas (my post on Stack Overflow) that proposes a different method to the link above that resolves some of the issues mentioned in the link above. I'm sure it could be adapted.

@asturur
Copy link
Contributor

asturur commented Dec 19, 2017

I do not think the canvas style should influence drawing on the bitmap data.
That would throw off jsdom + node-canvas combinations i believe.

@whatyoubendoing
Copy link

Chrome now supports letter-spacing in v56 CreateJS/EaselJS#872. Could be time to revisit this.

@asturur
Copy link
Contributor

asturur commented May 3, 2019

if it is part of canvas api why not. we would need a jsdom patch too then.

At this point the title 'kerning' is misleading. Letter spacing is not kerning.

@zbjornson
Copy link
Collaborator

zbjornson commented May 3, 2019

Tracking/letter-spacing is not part of the HTML Canvas spec. Chrome (and only Chrome) applies the canvas element's current letter-spacing CSS value to the context when the context is retrieved (see https://stackoverflow.com/questions/8952909/letter-spacing-in-canvas-element for background and several workarounds). @asturur I'm not sure what your older comment meant (#1014 (comment)) but it sounds like a "nay" for that approach.

In any case, I'm not opposed to adding it as either canvas.style.letterSpacing or ctx._letterSpacing. (@LinusU is usually the maintainer most interested in staying strictly faithful to the spec.)

@asturur
Copy link
Contributor

asturur commented May 3, 2019

my old comment was a please no

I'm developer/mantainer of fabricJS and for me this node-canvas is the way to support the library in node. The less offspec things it does, the better i feel.

Imagine if i want to throw a letterSpacing in the middle of the things, as a personal preference, no.

If that would be a canvas api standard part, why not.

Adding a .style object to the node-canvas object that is not meant to be in the DOM is confusing in my opinion.

@samizdatco
Copy link
Contributor

I totally agree with @asturur that adding a .style.letterspacing value to the canvas object feels like an unnatural way to access this feature. My preference would be for it to be attached to the context rather than the canvas and ideally in a way that is independent of the current ctx.font setting. In addition it would be better for it to exist as an addition to the API rather than a non-standard interpretation of an existing attribute.

I took a stab at adding the feature in the form of a new ctx.textTracking attribute here: #1615

Here's a quick demo:

ctx.fillStyle = 'black'
ctx.font = '48px "Zilla Slab"'

ctx.fillText("Anyone who would letterspace lowercase", 30,75)

ctx.textTracking = 500
ctx.fillText("would steal sheep", 30,150)

ctx.textTracking = -60
ctx.fillText("—FREDERIC GOUDY", 30,225)

output

@asturur
Copy link
Contributor

asturur commented Jul 3, 2020

Im fifty fifty on this.
As a fabricjs mantainer my dream of course is a node tool that behaves as a canvas.
Adding extra functionality related to drawing does not hurt but does not help.
This seems a specific pango feature, and hard to mantain if developers decide to move away from pango/cairo and use skia or something else.

@chearon
Copy link
Collaborator

chearon commented Jul 6, 2020

This seems a specific pango feature, and hard to mantain if developers decide to move away from pango/cairo and use skia or something else.

I do think the ideal future for node-canvas wouldn't involve Pango at all. The only thing we need it for is fallback glyphs and font lookups, and font lookups on custom fonts have been buggy in a few cases since Pango doesn't give us enough control.

@asturur
Copy link
Contributor

asturur commented Jul 6, 2020

I may have this already in another thread and i lost it, or at the end i did not press the comment button.

What would stop somoeone to take the full firefox source code for canvas, and make the binding for it under node?
I understand is hard, but how much hard would it be?
That would make a node-canvas that is perfectly compatible with a real canvas?

@zbjornson
Copy link
Collaborator

I like that idea. It looks like it's fairly isolated in https://searchfox.org/mozilla-central/source/gfx/2d, but that's basically a cross-backend (Skia/Cairo) C++ API that provides the primitives for HTML Canvas. The actual Canvas API would be hard to extract but we could parallel its logic in a manual conversion (see https://searchfox.org/mozilla-central/source/dom/canvas/CanvasRenderingContext2D.cpp).

That'd give us:

  • Better font handling
  • The filter API
  • SIMD for more operations
  • Skia as an optional backend

Things I haven't figured out yet:

  • How/where do they do image parsing?
  • Can we preserve the pixelFormat and alpha context attributes?
  • Can we preserve PDF and SVG canvases? (Looks like yes.)

If we do that, I'd propose starting with NAPI and doing it under the node-gfx org since Automattic isn't involved in this repo anymore.

@asturur
Copy link
Contributor

asturur commented Jul 6, 2020

If you want to try that i would love to be involved in some way.

@RUSHt
Copy link

RUSHt commented Sep 30, 2022

@zbjornson zbjornson changed the title Kerning of fonts like canvas.style.letterSpacing = "-3px;" Support context.letterSpacing Dec 29, 2022
@VityaSchel
Copy link

+1

@konser80
Copy link

please 🙏
we're all waiting for letterSpacing

@yisibl
Copy link

yisibl commented Feb 27, 2024

CanvasRenderingContext2D.letterSpacing is supported since Chrome 99 and Firefox 115

@trueicecold
Copy link

Any news on this? :/

@konser80
Copy link

Any news on this? :/

I just migrated to Fabric.js for letterSpacing

@TimChinye
Copy link

Time has changed, the only browser that doesn't support letterSpacing is Safari.

I just migrated to Fabric.js for letterSpacing

Damn, I just migrated from node-canvas due to the lack of CSS filters...

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