Skip to content

Support context.letterSpacing #1014

Open

Description

@bhouston

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?

Activity

  1. Hjlxc commented on Oct 2, 2017

    @Hjlxc

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

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

  2. chearon commented on Oct 2, 2017

    @chearon
    Collaborator

    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.

  3. JamesCarlyleClarke commented on Nov 2, 2017

    @JamesCarlyleClarke

    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.

  4. asturur commented on Dec 19, 2017

    @asturur
    Contributor

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

  5. whatyoubendoing commented on Oct 8, 2018

    @whatyoubendoing

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

  6. asturur commented on May 3, 2019

    @asturur
    Contributor

    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.

  7. zbjornson commented on May 3, 2019

    @zbjornson
    Collaborator

    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.)

  8. asturur commented on May 3, 2019

    @asturur
    Contributor

    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.

  9. samizdatco commented on Jul 2, 2020

    @samizdatco
    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

  10. asturur commented on Jul 3, 2020

    @asturur
    Contributor

    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.

  11. chearon commented on Jul 6, 2020

    @chearon
    Collaborator

    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.

  12. asturur commented on Jul 6, 2020

    @asturur
    Contributor

    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?

  13. zbjornson commented on Jul 6, 2020

    @zbjornson
    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.

  14. asturur commented on Jul 6, 2020

    @asturur
    Contributor

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

  15. changed the title [-]Kerning of fonts like canvas.style.letterSpacing = "-3px;"[/-] [+]Support context.letterSpacing[/+] on Dec 29, 2022
  16. VityaSchel commented on Jun 6, 2023

    @VityaSchel

    +1

  17. konser80 commented on Nov 10, 2023

    @konser80

    please 🙏
    we're all waiting for letterSpacing

  18. yisibl commented on Feb 27, 2024

    @yisibl

    CanvasRenderingContext2D.letterSpacing is supported since Chrome 99 and Firefox 115

  19. trueicecold commented on Mar 31, 2024

    @trueicecold

    Any news on this? :/

  20. konser80 commented on Mar 31, 2024

    @konser80

    Any news on this? :/

    I just migrated to Fabric.js for letterSpacing

  21. TimChinye commented on Jul 11, 2024

    @TimChinye

    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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions