State of HTML5 in QtWebKit

(Please note that this article discusses the current trunk of QtWebKit, so some parts are not relevant for Qt 4.7.x)

Quick introduction

<canvas> is a new feature in HTML5 - a block element with an imperative painting API. It's (somewhat hyperbolically) being hailed as a "Flash killer." You can use it to create graphically rich web pages and new technology demos are popping up daily. The feature originates from WebKit, developed initially for Mac OS X's Dashboard. Naturally QtWebKit supports it as well.

“Qt!” handsomely written using FlowerPower
“Qt!” handsomely written using the FlowerPower demo.


Spec compliance is high - we're passing over 90% of Philip Taylor's test suite, and there are patches in the pipeline for many of the remaining failures. Furthermore, some of the tests have become invalid after changes to the spec. Most of the known misrenderings have been corrected and we're approaching a pixel perfect match with Chromium and Safari.

The big exception is radial gradients; HTML5 defines its radial gradients based on the original CoreGraphics implementation which differs from the standard SVG gradients (which is what QRadialGradient implements.) I've tried convincing the WHATWG to adopt SVG-style gradients for canvas, but they felt it was too late in the game for such a change. Fortunately I have yet to see someone exploiting the additional possibilities of CoreGraphics-style gradients "in the wild."

We recently got support for blurred shadows, thanks to Ariya Hidayat. This was the last big missing feature in our implementation.

Radial gradients in Qt 4.6 vs Qt 4.7
One of the many rendering bugs fixed since Qt 4.6, screenshots from the Parcycle demo.


Performance has been steadily improving since the release of Qt 4.6 and in Qt 4.7 you'll see large speedups thanks to Benjamin Poulain's efforts in vectorizing QPainter's blending code. We're still not where Skia (Chromium's toolkit) is when blending scaled and/or transformed pixmaps, but Olivier Goffart is working on this right now and preliminary numbers are looking good.

Since there is no native "Color" object, stroke and fill colors are managed using CSS strings. Previously this would go through the (lex) generated CSS parser which is very slow. I recently landed an optimized "rgba()" color parser that helps boost any application that paints with many different colors.

Pixel manipulation speed is acceptable, though we're not at our limits yet. Mostly because we're forced to do RGB/BGR conversion on the fly in putImageData() and getImageData(). This could be alleviated by adding QImage::Format_ABGR32_Premultiplied but I feel this would be overkill right now. More realistically we could at least vectorize the format conversion inside WebKit.

Our biggest weakness is path stroking - Qt's path stroker and rasterizer is slow compared to other toolkits. Some people from Google are working on GPU-accelerated paths and we're watching this with great interest.

The second biggest weakness is gradient rendering. Qt caches the data for up to 60 gradients but it's very common for canvas applications to use many more unique gradients which turns the caching mechanism into pure overhead. Optimization (and vectorization) of these operations is in the research queue.

Future work

Google engineers are working on a hardware accelerated canvas implementation for WebKit. Hopefully we'll be able to take advantage of this work on platforms where it makes sense.

More immediately, we're looking into optimizing our bilinear filtering code which currently sticks out in many performance profiles.


All right, enough talk. Here are some of my favorite <canvas> demos for your viewing/poking pleasure:

* Parcycle
* Interferoplasma
* Monster
* Trail
* Canvas Cycle

Tons of more demos at

Blog Topics: