danieltian / stream-deck-api

API to interact with the Elgato Stream Deck controller
69 stars 11 forks source link

Text on button #2

Closed jhasselbring closed 6 years ago

jhasselbring commented 6 years ago

How do you draw text on button instead of buttons?

danieltian commented 6 years ago

This is currently not supported, but it's a WIP. I'm still playing around with the best way of drawing text. jimp supports text drawing, but the text it draws doesn't look great. It's also missing some features such as text wrapping.

GraphicsMagick has much better-looking text, but I would need to distribute the binary for each OS, which may be undesirable.

I also need to add in the ability to disable image caching, or else every piece of text drawn will be cached. This isn't a problem if you only have a small set of text, but if you're drawing a lot of dynamic text, it will blow up the memory usage. I will likely have to add in a LRU cache to prevent this from happening.

danieltian commented 6 years ago

Going to close this issue as a won't fix. After evaluating most of the popular JS image manipulation libraries, I feel that it's best to have the consumer of the library pick their own library and send over an image buffer to draw. This is for several reasons:

  1. Jimp is slow and only supports bitmap fonts. Although its font rendering looks the best, this also means that for every font, font size, and color combination, there needs to be 1 image for that combo. Jimp also doesn't support text wrapping or text measuring. Although it's possible to pass in a bitmap font file to use for text rendering, at that point you're better off just using Jimp directly to create the image, then pass the image buffer to stream-deck-api to draw to the device.

  2. Sharp is very fast, but only supports drawing text through SVG definitions, which does not support text wrapping natively. There's a d3plus-text library to handle text wrapping, but it expects a canvas element and has no API to output just the SVG definition. There also seems to be an issue where Sharp will draw the text offset from the coordinates that you specify, and it can be very difficult to get the text centered properly, particularly if you're wrapping text.

  3. gm supports text with text wrapping through its caption option, and the quality is good (not as good as Jimp's bitmap fonts, but it's pretty good). However, it requires a separate executable; gm is only a wrapper for this executable. The library also does not expose the caption property, and it needs to be passed in as a command-line parameter. There's a native library called node-gm-native, but it likewise does not have caption support and implements even less of the GraphicsMagick API. It's possible to add in support for this library to do text drawing, but as with Jimp, at this point you're better off just using it directly and then passing in the image buffer.

  4. Other libraries such as node-images and lwip do not support text drawing.

For now, I will omit the font drawing feature and leave it up to the library user to handle it themselves. In the future I may consider adding in really basic support for it (do let me know if this is something you really want!), but because the image manipulation libraries don't have good support for text drawing, and also because it forces compromises (for example, Jimp is slow at drawing images but has the best text support, whereas Sharp is fast at drawing images but has poor text support), I'd rather this be something that's handled by the user before it's passed into stream-deck-api.