News for hackers. Stuff that matters.
Re:Inside font-rs, a font renderer written in Rust by amelius on Tuesday August 02, 2016 @09:51AM (#12209897)
I always wonder why a distinction is made between font rendering and rendering arbitrary SVG shapes. In other words, couldn't this renderer be much more useful when generalized?
Re:Inside font-rs, a font renderer written in Rust by rtpg on Tuesday August 02, 2016 @10:02AM (#12209971)
I would imagine that arbitrary SVG rendering is harder to get right?

With fonts you can probably cache a lot of the rendering (even considering things like ligatures), and considering how much text your machine is showing, the performance tricks could be extra useful.

Re:Inside font-rs, a font renderer written in Rust by valarauca1 on Tuesday August 02, 2016 @10:38AM (#12210256)
SVG standard includes JavaScript.

So SVG renderers are very non-trivial to implement.

Re:Inside font-rs, a font renderer written in Rust by posterboy on Tuesday August 02, 2016 @11:53AM (#12210823)
hilarious
Re:Inside font-rs, a font renderer written in Rust by kbenson on Tuesday August 02, 2016 @02:55PM (#12212304)
In a "laugh because the only other option is to break down and cry" sort of way, yes.
Re:Inside font-rs, a font renderer written in Rust by amelius on Tuesday August 02, 2016 @10:47AM (#12210320)
> and considering how much text your machine is showing, the performance tricks could be extra useful

Well, an SVG-based drawing program has to re-render a lot of the same SVG every time the user makes a little change. Also, when animating an SVG scene, a lot of the shapes are redrawn continuously.

Re:Inside font-rs, a font renderer written in Rust by raphlinus on Tuesday August 02, 2016 @11:20AM (#12210574)
I think there is value in applying these ideas to SVG rendering as well. There are of course a bunch of things that are different. For SVG, buffers get large enough you'd probably want to do _some_ banded rendering because the accumulation buffer might otherwise get too big.

Another serious potential win in SVG is that you might be able to interleave the area integration with alpha compositing / masking. Could end up pretty darned fast.

Re:Inside font-rs, a font renderer written in Rust by kragen on Thursday August 04, 2016 @01:37AM (#12223616)
I was thinking about using your prefix-sum approach for exactly that almost all of last night. I don't have an attack on the problem that I'm satisfied with yet:

1. Render each path to a fresh pixel buffer, alpha-compositing it down onto the final canvas. Advantage: straightforward, works for sure. Disadvantage: you need a lot of multiplies per pixel.

2. Partition paths into "layers" of nonoverlapping paths, render each layer as a unit, and composite each new layer down onto the final canvas. Overlapping opaque paths can be incorporated into the same layer as whatever is below them by cutting an overlap-shaped hole in what's below before adding in the new path; although that involves some intersection tests to know where to stop, my intuition is that it will be a big win. Advantages: straightforward, probably faster than the previous one. Disadvantages: the partitioning is a potentially costly extra step (one of those things that makes me wonder if it's NP-complete to do it optimally), and there are still potentially many multiplies per pixel.

3. Separately accumulate a numerator (total premultiplied color) and denominator (total alpha) for each pixel, then divide in the end. Advantages: You avoid doing lots of work per pixel. Disadvantages: This is a weighted sum, not alpha blending. Alpha blending is a different thing. So the result is wrong. Also, an honest division per pixel is more expensive than quite a number of multiplications, although maybe you could cheat on the final division with a table of approximate multiplicative inverses or something. So this would probably be super slow.

4. Find a different group other than ℤ/256ℤ in which to do prefix-sum that somehow gives you the right results. Then you can just render all the edges into the same buffer and do a single vectorizable prefix-sum operation over it.

Advantages: This sounds super fast.

Disadvantages: It seems clear that this group is going to have to be able to represent the entire Z-ordered stack of colors at every pixel, because if I'm looking at some translucent green on top of translucent red on top of opaque black on top of pale blue, and I reach the right (negative) edge of the opaque black path, somehow I have to have remembered the blue thing underneath in order for it to peek through, which suggests to me that I need an unbounded number of bits per pixel to implement this scheme, which probably is not going to admit an actually fast implementation. In effect it has to reduce to the second approach, except that the software has to deal with the stack of layers once for every pixel. Or is there some magical way around this, at least for a fast-path case?

This part is probably obvious to you, Raph, but you can do SVG linear gradients with two prefix-sum passes instead of one, where the first pass just runs over signed gradient stops and gradient clipping boundaries, and then you draw the signed path boundaries into the buffer before the second prefix-sum pass. (Is that clear? I suspect it may be too abbreviated.)

I suspect that with three prefix-sum passes you could do a decent quadratic-spline† approximation of arbitrary gradients, including the weird skew cone gradients SVG calls "radial gradients". But I haven't worked out the details.

I know you don't have a lot of time to hack on this stuff right now, but would you have time to provide feedback if I were to hack on it a bit? I imagine that I'd run into any number of places where talking to you about it for half an hour could save me days of wasted effort.

† here I'm talking about what Carl de Boor calls "splines", which I know disagrees with your usage of "splines". I think you called them "B-splines" in your dissertation.

Re:Inside font-rs, a font renderer written in Rust by raphlinus on Sunday August 07, 2016 @07:40PM (#12244405)
Thanks for the detailed comment.

I think you're going for something much more complicated than what I had in mind. My idea is simply to have two modes other than accum buffer -> 8 bit alpha mask. One would be accum buffer + constant RGBA color -> update RGBA buffer. (By update I mean read an RGBA pixel, do the compositing, and write the composited pixel in place). The other would be accum buffer + source RGBA buffer -> update RGBA buffer. Of course, it's possible to imagine interleaving even more operations in the generation of the source RGBA buffer, but at some point the register pressure overcomes the r/w bandwidth.

Prefix-sum is not a particularly fast SIMD operation, due to the horizontal data dependency. I chose it for font-rs because I don't know of any faster ones that can get the job done. For just computing gradients, it's almost certainly going to be faster to compute it directly (it's simple multiply-add in the case of linear gradients) than to try to strength reduce. The same is no doubt true for SVG radial (cone) gradients.

When the gradient doesn't have any sharp creases or singularities, a very reasonable strategy is to compute it in lower resolution and then up-res, say 2x or 4x to keep the math super-simple. When it does have creases, it might make sense to decompose into regions and use different approaches in different regions.

In any case, it sounds like you may be re-inventing Cairo or Skia here. Might make sense to take a closer look at what they do and whether there's truly any low-hanging fruit left. I know that Skia has a bunch of SIMD optimizations already.

But this is fun stuff to think about and experiment with. I certainly don't want to discourage you.

Re:Inside font-rs, a font renderer written in Rust by vardump on Tuesday August 02, 2016 @10:43AM (#12210286)
TrueType includes a virtual machine [1] for hinting. Text rendering also needs to alter shapes of glyphs for other reasons, like font weight and pseudo-italic.

[1]: https://en.wikipedia.org/wiki/TrueType#Hinting_language

Re:Inside font-rs, a font renderer written in Rust by wmil on Tuesday August 02, 2016 @11:02AM (#12210438)
There are specific clarity optimizations that are important for font rendering but don't generalize to all SVG rendering.
Re:Inside font-rs, a font renderer written in Rust by wldcordeiro on Tuesday August 02, 2016 @11:06AM (#12210471)
You could generalize that to image rendering too, same reason why Photoshop and other tools have 'optimize for text' and 'optimize for art' as options.
Re:Inside font-rs, a font renderer written in Rust by glippiglop on Tuesday August 02, 2016 @05:29PM (#12213565)
I work on a project that uses Free type for text and an improved version of AntiGrain for SVG rendering. The thought of using AGG for the font rendering has already crossed my mind, but mainly for reducing the size of the codebase. Speed isn't really a concern to me because the glyphs are already being cached to internal bitmaps, after which the bottleneck is the drawing algorithm (which is straightforward anyway). Overall, it's not worth my time to change the font engine.

The really nice thing about using an SVG engine to draw text is the potential for applying runtime effects, transformations and so forth. However that's an entirely different use case and can be done through SVG as it stands. Most of the time you want your text to be on the horizontal and easy to read, and vanilla FT is fine for that.

Re:Inside font-rs, a font renderer written in Rust by TheRealPomax on Tuesday August 02, 2016 @08:01PM (#12214405)
Fonts are not "collections of pictures", though, and haven't been since the mid 1980. Details in http://pomax.github.io/1449777175633/opentype-let-s-learn-ho... but the gist is that a font is a full, complex, 700-page-specced typesetting program that has to be run on a render engine, similar to how a game ROM is run on an emulator or hardware setup. Sure, you need the engine, but there is nothing to generalize: that engine needs to implement a really large spec, most of which is not "drawing a vector image".
Re:Inside font-rs, a font renderer written in Rust by stuaxo on Tuesday August 02, 2016 @02:45PM (#12212219)
Text is usually made up of lots of small solid shapes whereas SVG will usually have larger shapes, sometimes using effects such as gradients - so it's likely that different optimisations will work best on each one.
Re:Inside font-rs, a font renderer written in Rust by speps on Tuesday August 02, 2016 @10:05AM (#12209989)
The linked article[1] about stb_truetype seems to have polygons instead of fonts so it could be used for polygons or any vector.

[1] http://nothings.org/gamedev/rasterize/

Re:Inside font-rs, a font renderer written in Rust by kevin_thibedeau on Tuesday August 02, 2016 @07:57PM (#12214382)
Font rendering makes some optimizations that aren't general purpose. Rendered glyphs are (may be) cached. Assumption of a single color. No self intersecting outlines. These allow font renderers to take shortcuts for performance.