frmatthew / exsurge

A JavaScript library for rendering Gregorian Chant in square note notation
MIT License
54 stars 13 forks source link

Feature/canvas measure text #76

Closed bbloomf closed 8 years ago

bbloomf commented 8 years ago

I noticed that using canvasCtxt.measureText() is much faster than using an svg (at least on Chrome; I haven't tried this in any other browsers yet), so I thought maybe you'd be interested in this code.

frmatthew commented 8 years ago

Hi @bbloomf, as a matter of fact this is more or less how I originally implemented all of the text measuring: the chant context held on to a canvas context which it used for text measuring, even when outputting to SVG. I was trying to squeeze more performance out of the layout pipeline, and while it mostly works (canvas text measuring is not quite as precise as measuring SVG text nodes, but usable in most cases), the bigger issue is that the canvas doesn't support strings with more advanced typography. For example, canvas small caps uses faux small caps not true smcp glyphs.

I seem to also recall that there is no way to actually get baseline measurements via the canvas, meaning that text alignment needs kludges (like the "this.bounds.height = this.fontSize * 1.2" in the pull request).

But you're right, it's much faster using the canvas to measure text, since there is no DOM manipulation involved. Maybe it could be implemented as an optional feature for those preferring speed over output quality/features?

bbloomf commented 8 years ago

Yes, it looks like there are additional text metrics that may someday be supported by canvasCtxt.measureText() but aren't supported in any browsers right now, that would return various measurements relating to the vertical axis: https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics

I do think it would be nice to have the option of preferring either speed or precision.

bbloomf commented 8 years ago

I just changed this to allow either strategy for measuring the text based on an optional argument passed into the ChantContext constructor. Let me know what you think.

frmatthew commented 8 years ago

Yeah, that looks good. I think I'd prefer that the logic of text measuring (based on the strategy) be encapsulated in the ChantContext, but that could be refactored later too... Thx!