[{"content":"The last time I wrote here about the layer based SVG engine (LBSE) was back in autumn 2021, when I published the technical design document. A lot has happened since then, but maybe not what you would expect after almost four years. The engine landed in WebKit and it works well, but it is still not the default. You have to switch it on by toggling a runtime setting (in MiniBrowser). Between autumn 2021 and late 2022 LBSE was bootstrapped upstream, patch after patch. We added support for all the individual building blocks that make up SVG: paths, shapes, text, polygons, etc. within the new LBSE design. After that first big push the work stalled for a few months and resumed in mid-2023, and lasted until April 2024, due to generous support by Wix. During that period most advanced painting features, such as clipping, masking, filters, non-solid paint servers (patterns, gradients), markers, etc. were all implemented, sharing the logic with HTML and CSS rather than running through the separate code paths, as the legacy SVG engine did. Then the work paused again. A project of this size needs sustained funding to move forward, and for a while that funding was not there.\nLBSE is promising, but it still has to earn its place, and it is worth being precise about what that means, because the goal was never simply \u0026ldquo;make SVG faster\u0026rdquo;. The legacy SVG engine is an island: historically grown, it has its own painting code, its own handling of transforms, clipping, masking, etc. and it shares only a little of the code that renders HTML and CSS for historical reasons. Many improvements that went into WebKit, went into \u0026ldquo;the other engine\u0026rdquo;, the main part, the HTML/CSS rendering engine. GPU-accelerated transforms and animations, accelerated compositing, all the work that made HTML/CSS fast. SVG sat right next to it and got none of it. That is what LBSE is really about. Put SVG on the same machinery, and it inherits all of that at once, and it keeps inheriting whatever comes next, instead of someone having to build it a second time for SVG alone.\nThe catch is that shared machinery is general machinery, and generality is not free. The legacy engine has been hand tuned for exactly one job, with two decades of tuning behind it. LBSE, on the other hand, has to integrate surgically into the shared HTML/CSS rendering code, without regressing that code even a little. This is the hottest code in the engine and it renders every web page out there, so sprinkling SVG special cases through layout and painting until LBSE looks good is simply not an option. Whatever LBSE needs either fits the existing design, or it has to make the existing design better for HTML and CSS too.\nThere is a second kind of work hiding in there as well. Some things that are rare in HTML are everywhere in SVG. Transformations are the obvious example. A typical web page has a handful of transformed elements, while in SVG almost every single element can carry a transform, and deeply nested transforms are the norm rather than the exception. The shared code was written with HTML in mind, and it does its job perfectly well there. So parts of the shared machinery have to be reworked, and fast paths that nobody ever needed for HTML have to be invented from scratch, without making anything slower for HTML in the process.\nSo the bar is a double one. LBSE first has to be competitive with the legacy engine on the plain, everyday rendering that legacy is already good at, because nobody switches engines if a static icon that never moves suddenly takes longer to paint. The rest, the hardware acceleration and every future improvement to the HTML/CSS engine that SVG now gets for free, only counts as a win once that first bar is met.\nFast forward to early 2026: This year the status quo finally changed. Igalia made a one-off investment into a fresh round of LBSE development, to give the engine the chance to prove itself. We are hopeful to finally show the world that LBSE is performant, and to attract new partners who share our vision that a performant, hardware-accelerated SVG engine is the future for UIs on embedded devices. This is the first of two posts covering the first half of 2026, where we stand now and how the LBSE project evolved since the long break in 2024. The last six months were intense, and ended with the single most invasive change to LBSE since it was first written. This post covers that change, and the next one picks up the hard problem it left behind.\nA quick reminder of where we were When we designed LBSE, the central idea was simple. Instead of keeping the old, separate SVG painting code, SVG should reuse the very same machinery that HTML and CSS already use, the RenderLayer tree. That is what unlocked hardware-accelerated transform animations, perspective transformations, z-index support - all the nice things SVG never had before in WebKit.\nTo get there quickly, we took a shortcut in the early days. Every single SVG renderer got its own RenderLayer. A \u0026lt;rect\u0026gt;, a \u0026lt;path\u0026gt;, a \u0026lt;g\u0026gt;, everything. The reason was convenience: if every element has a layer, then the existing layer tree already knows how to order children, apply transforms, clip and composite. We did not have to reinvent any of that. Furthermore, the intrinsic SVG paint order, which follows the DOM structure 1:1, is guaranteed automatically this way, while z-index support is still there to deviate from that order when desired. All of that just works out of the box once every renderer receives its own layer. RenderSVGModelObject::requiresLayer() simply returned true all the time, and the rest of WebCore did the heavy lifting.\nWe knew from the start that this approach would most likely never ship in this form, because it is simply too wasteful. But that was fine. It was never meant to be the final design. What it gave us was a way to finally try out the things SVG had been missing for years, all running through the same machinery as HTML and CSS. It also gave us the possibility to reimplement all SVG render tree classes, in a way that\u0026rsquo;s fully unified between HTML and SVG, so that e.g. an SVG \u0026lt;clipPath\u0026gt; applied to an SVG element or an HTML element would no longer run through different code paths, as it historically did in WebKit. Thus just maintaining a 1:1 correspondence between renderers and layers was the fastest path to seeing the idea actually work, and once we had, the real shape of the engine could follow.\nCorrectness first When we resumed work on LBSE, we first had to make sure the engine worked again properly after the long pause of upstream work. LBSE received no testing during that period, so it was likely to be in a broken state, and that turned out to be the case. Text rendering was initially fully broken, most testing baselines were outdated, many new regressions were present, where the legacy SVG engine received fixes but LBSE did not. It took us a while to recover.\nRob Buis, my partner in the endeavor to bootstrap LBSE, did a lot of this work, so I could focus on attacking the remaining performance problems, profiling the engine, and trying new designs. We fixed a pile of crashes, for example in getBBox on \u0026lt;use\u0026gt; elements, in paths with NaN coordinates and line caps, and in markers whose children change. We fixed real rendering bugs too, including text not rendering at all, text opacity, gradients with a non-invertible gradientTransform, and support for SVG view fragments.\nFilters got a lot of attention through spring. We made invalid filters behave like they do for HTML instead of dropping the element entirely, fixed feOffset clipping, filter scaling, and a convolution filter test. The most important filter change, though, has not landed yet. Once conditional layer creation, the change the rest of this post is about, removes the intermediate layers, a filter\u0026rsquo;s coordinate space no longer lines up with what the painting code assumed, and a lot of filtered content ends up in the wrong place. A pending pull request corrects that for non-layered renderers and clears a large batch of filter test failures under LBSE once conditional layers are enabled.\nNone of this is glamorous, but it is the foundation. With the engine behaving well again, we could finally go after the thing this whole effort was about.\nThe real goal, performance The point of LBSE was always performance. It was designed to unlock hardware-accelerated animations, which can potentially run much faster than in the legacy engine, since re-layouts and re-rasterization can be skipped entirely as the compositor is responsible for applying those transformations to the already-rasterized content. The catch is that scenarios which deliberately avoid that fast path suffer instead from the overhead of a layer per element. The benchmark we measure ourselves against here is MotionMark, and in particular its Suits subtest. Suits adds a large number of SVG primitives (rects and paths) that are clipped via \u0026lt;clipPath\u0026gt; elements, and animates them by modifying the transform attribute of each shape programmatically, in a requestAnimationFrame driven setup. It measures how many of them the browser can keep moving smoothly, which makes it a demanding, honest test of the SVG pipeline.\nAnd here our early shortcut came back to bite us. Remember, every SVG renderer had its own RenderLayer. On a scene with thousands of shapes, that means thousands of layers. Each layer costs memory, and worse, each layer takes part in a lot of per-frame bookkeeping. Position updates, z-order lists, transform updates, repaint walks. None of these shapes should actually need a layer - a path/rect with a plain 2D transform is the most ordinary thing an SVG can contain. Yet we paid the full layer price for every one of them.\nSo the way forward was clear: stop giving every renderer a layer, and create one only when an element actually needs it. The first focus is transformed elements, the plain shapes that carry nothing but a 2D transform. Clipped elements keep their layer for now, and dropping that one too is future work. In Suits this first step already removes the layer from every transformed path, leaving only the clipped rects and the \u0026lt;svg\u0026gt; root, as the diagram below illustrates.\nOld: a layer for everything New: no layers for transformed elements \u0026lt;svg\u0026gt; defsgrad + clips \u0026lt;rect\u0026gt;clip-pathtransform \u0026lt;path\u0026gt;transform \u0026lt;rect\u0026gt;clip-pathtransform \u0026lt;path\u0026gt;transform … L L L L L one RenderLayer per shape, thousands of them \u0026lt;svg\u0026gt; defsgrad + clips \u0026lt;rect\u0026gt;clip-pathtransform \u0026lt;path\u0026gt;transform \u0026lt;rect\u0026gt;clip-pathtransform \u0026lt;path\u0026gt;transform … L L L layers only for the clipped rects and the \u0026lt;svg\u0026gt; root Suits builds a flat list of shapes directly under the \u0026lt;svg\u0026gt; root: alternating clipped \u0026lt;rect\u0026gt; elements and plain \u0026lt;path\u0026gt; elements, each with a gradient fill and a transform that is updated on every animation frame. A blue L marks a renderer that owns a RenderLayer. On the left every shape has one. On the right the plain transformed paths no longer do, while the clipped rects keep theirs for now, so only they and the \u0026lt;svg\u0026gt; root own a layer.\nHowever, it turned out that we cannot easily remove layers for transformed containers, only for transformed leaf elements - we\u0026rsquo;ll get back to that later.\nConditional layer creation Pulling layers out from under the whole engine is risky, but the real reason we did not do it in one jump is that it would have been a huge, unreviewable patch, since a lot of new concepts had to be invented first. A string of preparation patches had to land instead, each one dormant on its own, so that the eventual switch to conditional layers had solid ground to stand on.\nThe groundwork was mostly about finding a new home for the things that used to live on the layer. A RenderLayer carried a pile of SVG-only fields that non-SVG layers never need, so we moved them into a lazily allocated SVGData struct that only exists for layers within an LBSE subtree. That was a good cleanup on its own, and everything else built on top of it, starting with the transform. We used to cache an element\u0026rsquo;s local transform on its RenderLayer, and with no layer we needed a different place to cache it, rather than recomputing it on every use. So we did what the legacy SVG engine had done all along and cached the transform on the renderer itself, with a m_localTransform member and an updateLocalTransform() method that plays the same role the layer version used to. A couple of follow-up patches (311763@main and 315597@main) then made sure dynamic transform updates work for both layered and non-layered SVG renderers.\nWith the SVG data and the transform moved into their new homes, we built a DOM-order paint path for non-layered SVG children, followed immediately by the matching DOM-order hit-test path. Behind both sits an SVG-specific, DOM-order collection of the renderable children, and it plays a crucial role in making conditional layer creation work at all.\nHTML and SVG behave differently here. Take a block with three \u0026lt;div\u0026gt; elements where the middle one carries a CSS transform. The transform makes that middle element establish its own stacking context, so it no longer paints in place. The paint order becomes the first div, then the third, and only then the transformed middle one on top, assuming it has a non-negative z-index. For SVG that would be wrong. SVG content has to paint in strict document order, whether or not a layer is involved, so the middle child still paints between its two siblings. Adding z-index support so SVG can deviate on purpose is a separate issue. None of this had to be solved by hand when every renderer had a layer and the layer tree sorted everything for us. With conditional layers, and a mix of layered and non-layered children, we now have to guarantee that document order ourselves.\nBoth paths were gated behind a check that still saw a layer on every renderer, so they had no effect yet and stayed inactive until conditional layers turned them on. Next we taught non-layered transformed content to position itself correctly inside the paint recursion, folding the transform of a shape, image or piece of text into the coordinate system during painting. And just before enabling conditional layers, we landed a large batch of tests for the tricky mixed cases, so any regression from the coming change would surface right away. There is also an internal flag, LayerBasedSVGEngineForceLayerCreationEnabled, that brings back the old behavior, and it was a great help for bisecting problems, because it lets you compare the two worlds side by side.\nWith all of that in place, we could finally flip the switch. The headline change, conditional layer creation, landed in June 2026. The idea is to create a RenderLayer only when an element needs one for an intrinsic reason. Each renderer now implements a new method, requiresLayerForSVGIntrinsicReasons(), and its return value alone decides whether that renderer gets a layer. An SVG element gets a layer only when some painting effect needs the extra machinery a layer provides. That means opacity groups, clipping, masking, filters, blend modes, and isolation. A 3D transform needs one too, along with a handful of related properties like perspective, preserve-3d, and an explicit z-index. Everything else, the vast majority of shapes and groups, gets no layer at all.\nPlain 2D transforms need a bit more care. On a leaf element like a shape or a piece of text, a 2D transform no longer forces a layer of its own. We store the transform on the renderer and fold it into the coordinate system at paint time, concatenating it onto the current transformation matrix just before the element draws. The exception is a transformed container, which still keeps its own layer. The compositing logic is built around the layer tree, not the render tree, and expects every transformed container to have one, because it computes a composited element\u0026rsquo;s current transformation matrix (CTM) by walking up the chain of ancestor layers and concatenating their transforms. A transformed container without a layer would drop out of that walk, so its transform would be lost and the composited descendant would be left with the wrong CTM. Reworking that expectation would be a substantial effort, so for now we settled on a compromise and keep a layer for every transformed container, which at least guarantees that an element\u0026rsquo;s ancestor chain transformation can be correctly computed.\nWith conditional layer creation in place, LBSE can now decide, renderer by renderer, whether a layer is needed at all, and create one only where an SVG renderer genuinely requires it. For non-composited content this is exactly what we wanted. The transform folds straight into the paint recursion, the shape draws in the right place, and no layer appears. Composited content, though, is now broken. As soon as a single composited element sits among plain, layer-less siblings, the strict SVG paint-order contract falls apart. The compositing code path can only order content that owns a layer, and now that conditional layer creation has taken layers away from most of the tree, it can no longer keep that composited element in its correct document-order slot.\nWe won the fast common case and lost the composited one in the same move, and winning it back without undoing all of this is the hard part the next post is about: the interesting compositing problem, and the design that finally solved it.\nLet me close with a huge thanks to the Apple developers, involved in validating the LBSE work: thanks Simon, Said, Karl for the insightful discussions and input how to move LBSE forward! Thanks for reading until the end :-)\n","permalink":"https://blogs.igalia.com/nzimmermann/posts/2026-07-14-lbse-conditional-layers/","summary":"\u003cp\u003eThe last time I wrote here about the \u003cstrong\u003elayer based SVG engine\u003c/strong\u003e (LBSE) was back in autumn 2021, when I published\nthe \u003ca href=\"../2021-10-29-layer-based-svg-engine\"\u003etechnical design document\u003c/a\u003e. A lot has happened since then, but maybe\nnot what you would expect after almost four years. The engine landed in WebKit and it works well, but it is still\nnot the default. You have to switch it on by toggling a runtime setting (in MiniBrowser). Between autumn 2021 and\nlate 2022 LBSE was bootstrapped upstream, patch after patch. We added support for all the individual building blocks\nthat make up SVG: paths, shapes, text, polygons, etc. within the new LBSE design. After that first big push the work\nstalled for a few months and resumed in mid-2023, and lasted until April 2024, due to generous support\nby \u003ca href=\"https://www.wix.com\"\u003eWix\u003c/a\u003e. During that period most advanced painting features, such as clipping, masking,\nfilters, non-solid paint servers (patterns, gradients), markers, etc. were all implemented, sharing the logic with HTML\nand CSS rather than running through the separate code paths, as the legacy SVG engine did. Then the work paused again.\nA project of this size needs sustained funding to move forward, and for a while that funding was not there.\u003c/p\u003e","title":"Reducing layer overhead in LBSE"},{"content":"Yikes, it\u0026rsquo;s been more than a year since my last post. Time flies, especially during the pandemic that hit us all like a stroke in 2020.\nLet me start with a few personal notes: Luckily no one in my family got the disease, but we paid a huge price - as everybody else - by reducing the social contacts down to an absolute minimum. My wife gave birth to our daughter in September 2020, so we were especially cautious that no one brings back Corona home.\nGood news: it worked out for us. 2020 was a crazy year for me personally, as my working conditions suddenly had to change, since our two boys could not go to Kindergarten for a long time. Working partly during the day, and often from late evening into the night became the new normal in 2020. This year I realized how exhausting 2020 really was and I\u0026rsquo;m thankful that all family members, except the children, were vaccinated by now.\nI wish that we can all feel safe again in 2022 and the wounds from Corona heal.\nFast forward to October 2021\u0026hellip; \u0026hellip; my working times returned to normal since a few months and I feel much more productive and energetic.\nBesides the fact that I did not blog about my work, I have been steadily working on the SVG PoC branch that I reported about in my last post.\nEnd of September I presented a status update during the WebKit contributor meeting which was well received by the community. Here\u0026rsquo;s a video of my presentation:\nYour browser doesn't support embedded videos, but don't worry, you can download it and watch it with your favorite video player! I hope you enjoyed to see the layer based SVG engine, demoing a real world example. Stay tuned for another post, covering the technical description of the work.\n","permalink":"https://blogs.igalia.com/nzimmermann/posts/2021-10-13-svg-performance/","summary":"\u003cp\u003eYikes, it\u0026rsquo;s been more than a year since my last post. Time flies, especially during the pandemic\nthat hit us all like a stroke in 2020.\u003c/p\u003e\n\u003cp\u003eLet me start with a few personal notes: Luckily no one in my family got the disease, but we paid a huge price - as everybody else -\nby reducing the social contacts down to an absolute minimum. My wife gave birth to our daughter\nin September 2020, so we were especially cautious that no one brings back Corona home.\u003c/p\u003e","title":"Accelerating SVG - an update"},{"content":"As mentioned in my first article, I have a long relationship with the WebKit project, and its SVG implementation. In this post I will explain some exciting new developments and possible advances, and I present some demos of the state of the art (if you cannot wait, go and watch them, and come back for the details). To understand why these developments are both important and achievable now though, we\u0026rsquo;ll have to first understand some history.\nNote: In order to focus on the high-level overview, many technical details are omitted or shortened \u0026ndash; the intention of the article is to provide an overview of the status of SVG and technological advances for both developers and web authors.\nResolving the co-evolutionary branches of HTML, CSS and SVG - and why it matters Many of the concepts that empower SVG were not present in HTML/CSS at the time when the first SVG 1.0 specification was released back in 2001. SVG requires to position and paint graphical elements in arbitrary user coordinate systems. What does that mean in practice? You can define a SVG document fragment in a coordinate system that only spans one pixel and scale it up by factor of 100 using an affine transformation. In the early 2000s none of this was possible with HTML and CSS: CSS (2D) Transforms were not born yet and HTML was laid out and painted in integer based coordinate systems.\nTo support SVG in a web browser the rendering pipeline needs to support fractional coordinate systems. Back in 2005 when ksvg2 was integrated into WebKit a new rendering path was defined: a floating-point number based layout and painting model, as opposed to the existing integer based layout and painting model.\nHistory of transformation support for HTML/CSS In 2007, WebKit pioneered support for arbitrary affine transformations on CSS boxes through the -webkit-transform CSS property. This was the beginning of a success story: CSS Transforms were born, and later formalized in CSS Transforms Module Level 1, opening up many new possibilities for web page authors. Two years later CSS 3D transformations were invented and prototyped in WebKit: a killer feature allowing many new possibilities and a whole new dimension of graphical effects for web page authors. And at the same time these new 2D/3D transform features made scripting web pages using JavaScript much harder and - back then - unpredictable.\nWhy? Since the whole HTML/CSS rendering engine was still integer based simple questions such as asking for the size of an CSS box might turn an integer width/height into a non-integer value, e.g. due to a rotation, or a non-integral scale value that is applied to the box. The obvious answer is: all sizes, positions, etc. need to become floating-point numbers. As often, the straight-forward solution is naive and has major drawbacks: floating-point numbers are a natural source of numerical instabilities leading to rendering artefacts such as unwanted aliasing when objects are painted on non-integral positions, not aligned anymore with device pixels.\nIntroduction of sub-pixel rendering for HTML/CSS To avoid switching to floating-point numbers WebKit invented so-called “LayoutUnits“. LayoutUnit is an abstraction used to represent positions and sizes in fractions of a pixel. WebKit chose to divide each logical pixel in 64 chunks, thus representing all values as multiples of 1/64th of a CSS pixel. This allows to continue to use integer math and avoids floating-point imprecision, while still exposing sub-pixel precision to web authors.\nThis work started roughly in 2012, driven by Google, as it was the only way forward to properly support CSS 2D/3D transforms throughout the engine: during layout, painting and hit-testing. As you can imagine, this is a multi-year effort to carefully transition all integer based code to LayoutUnits. However, transitioning the engine from integers to LayoutUnits is only one side of the coin: all APIs exposed to the Web need to be revised in order to support non-integer locations/sizes. An old article from the IE team highlights some of the difficulties that arose: be sure to read the article to get a feeling about the complexity of the problem.\nIn 2013, the Apple WebKit ports enabled sub-pixel layout by default, and many regressions were fixed in the following months. At the same time specification authors worked hard on addressing the problems that arose and to change the relevant specifications where needed.\nFrom HTML/CSS perspective many problems were properly solved at this time: sub-pixel precision is achieved, layout, painting and hit-testing works on sub-pixel precision \u0026ndash; many APIs (such as CSS OM) now report non-integral results, that can be queried from JavaScript etc. Job done, goal achieved for HTML/CSS! But what about SVG?\nHardware accelerated web page rendering in WebKit Before we examine how all of these things related to SVG rendering, there is one more thing to keep in mind. In the early 2000s there was no support for animations in HTML/CSS, other than scripting using JavaScript. This has changed with the introduction of CSS Animations/Transitions (e.g. end of 2007 in WebKit). These features allow web authors to animate many CSS properties, using CSS alone, not involving JavaScript.\nOne of the properties that can be animated is the transform (previously known as -webkit-transform) property. How would you implement animating a transform of a CSS box? In a naive implementation, you would simply re-layout the element at a new position given a time t and re-render the whole web page. This will be very time consuming, since the layout operation is non-trivial and thus not cheap at all. Furthermore, if you consider that the animated CSS box is e.g. absolutely positioned, and drawn on top of everything else there is no need to render the whole web page “below” it (ignore transparency in this simple example), since the non-animated content remains static. To make a long story short: WebKit defines layers that need to be rendered into a separated backing store. In the given example, the whole web page would be rendered into one backing store (except the animated box), and the animated box in another. When rendering the web page to the screen, only the layer that has an animated transform needs to be re-drawn, the static content remains as-is. Then, these two image buffers will be composited into one final image, that is painted on the screen \u0026ndash; and all backed by image buffers residing in the GPU. This is efficient and we call it hardware accelerated compositing.\nSo HTML/CSS is laid out on sub-pixel boundaries, supports CSS 2D/3D transformations, CSS animations/transitions, all hardware-accelerated.\n“One platform”: Paving the way towards a unification of the HTML/CSS \u0026amp; SVG rendering engine The SVG implementation in WebKit does not support hardware acceleration composition at all. All techniques mentioned before were only implemented in the HTML/CSS rendering code path and are not applicable for SVG. You might ask yourself why it is not possible to apply these techniques to SVG? Indeed it is possible, but nobody wanted to reinvent the wheel back in 2012. Back then I hoped that the following CSS3/SVG2 specifications would formalize how to properly integrate SVG with all these CSS features like 2D/3D transformations, animations/transitions etc. If that is done, we can try to re-use the existing WebKit implementation and make it work for SVG too, instead of re-implementing all the hardware acceleration code again separately for SVG. Lesson learned from the last two decades: It is extremely difficult to maintain two different rendering code paths, and we should invest more time to unify them. Furthermore, making SVG less special is an important goal to unleash its true power: less confusing for Web authors, easier to implement for developers. Be sure to checkout the post from my colleague Brian Kardell on that topic.\nJust to show one example why formalization is necessary first: Take the SVG transform attribute as example: What happens if you specify both the SVG transform attribute and the CSS transform property at the same time on a SVG element: do both transformations take effect, or does one of them override the other? What about the SVG DOM? It exposes an API to query the transformations from e.g. JavaScript \u0026ndash; how does it respond if a CSS transform property is set? The list of open questions is huge! It required many years of hard work by the SVG and CSS working groups to define and specify the rules how all of these technologies work together.\nNowadays the answer is clear: the SVG transform attribute is mapped to the CSS transform property, as specified in CSS Transforms Module Level 1 (which is still only a W3C candidate recommendation!).\nSo does WebKit have a fast, fluent SVG animation engine in 2019, all hardware-accelerated? No. Why? Simply because no one attempted to unify the rendering code paths, event though from specification point of view, many open questions were answered. It is doable now, we only need a few dedicated people to tackle it.\n2020: Hardware-acceleration for SVG My first task at Igalia is to demonstrate that we can re-implement the SVG rendering engine on top of HTML/CSS, while preserving the SVG specific needs such as arbitrary precision coordinate systems (not limited to 1/64th of a CSS pixel). This will make SVG “less special” and as bonus we get all nifty features such as CSS 3D transformations for SVG for free. Furthermore, many long standing issues can be tackled related to improper foreignObject support, repainting issues when embedded SVG in HTML (or vice-versa), etc. Without going too much into details, believe me that this is a huge step forward.\nThe video below shows a screen cast of a reveal.js presentation that I showed during the WebKit codecamp in the last Igalia meeting in A Coruña. You can see my Proof-Of-Concept implementation using the WebKitGTK port in action, demoing for the first time: CSS 3D transformations in SVG. I am excited about this and I hope you enjoy the video.\nYour browser doesn't support embedded videos, but don't worry, you can download it and watch it with your favorite video player! Demo using WPE WebKit port on low-power hardware Igalia maintains the WPE port and deeply cares about embedded systems. My fellow Igalian, Brian Kardell, immediately asked me after the demo how it would perform on low-power hardware, such as a Rasberry Pi 3. A few days later my colleague Pablo Saavedra crafted an image that allowed us to compare the Proof-Of-Concept branch with vanilla WebKit \u0026ndash; thanks Pablo and Brian!\nThe first 20 seconds of the video show a demo using vanilla WebKit, where the SVG tiger is slightly rotated in 2D space. In addition a 3D perspective transformation is applied, whose effect is unobservable since it is unsupported in vanilla WebKit. The animation appears jumpy and slow - not something you can deploy in your web application (no hardware accelerated compositing!). In the next 15 seconds the same demo is executed using the Proof-Of-Concept WebKit branch and it appears smooth and fluent, as you would expect from a state-of-the-art SVG rendering engine!\nAfterwards the SVG tiger is animated (skewed and rotated) using vanilla WebKit - the performance is lousy. Finally the same animation is demoed using the Proof-Of-Concept WebKit branch.\nYour browser doesn't support embedded videos, but don't worry, you can download it and watch it with your favorite video player! I hope you share my excitement about these developments. The code is not public yet, but will be shared soon \u0026ndash; once I am convinced that the experiment works out, and the design of the new rendering engine is sane.\nThanks to Igalia for allowing me to work on this important aspect of SVG. Special thanks to Brian Kardell, who suggested to write about this topic, Pablo Saavedra for setting up the test hardware and the whole WebKit graphics team at Igalia for their support!\nThanks for reading the article \u0026ndash; spread the news about these exciting SVG developments. Stay tuned!\n","permalink":"https://blogs.igalia.com/nzimmermann/posts/2019-12-12-3d-transformations/","summary":"\u003cp\u003eAs mentioned in my \u003ca href=\"../2019-11-24-back-in-town\"\u003efirst article\u003c/a\u003e, I have a long relationship with the WebKit\nproject, and its SVG implementation.  In this post I will explain some exciting new developments and possible\nadvances, and I present some demos of the state of the art (if you cannot wait, go and \u003ca href=\"/nzimmermann/posts/2019-12-12-3d-transformations/#2020-hardware-acceleration-for-svg\"\u003ewatch\u003c/a\u003e them, and come back for the details).\nTo understand why these developments are both important and achievable now though, we\u0026rsquo;ll have to first understand some history.\u003c/p\u003e","title":"CSS 3D transformations \u0026 SVG"},{"content":"Welcome to my blog!\nFinally I\u0026rsquo;m back after my long detour to physics :-)\nSome of you might know that my colleague Rob Buis and me founded the ksvg project a little more than 18 years ago (announcement mail to kfm-devel) and met again after many years in Galicia last month.\nRob (left) and Niko (right) We worked together on ksvg1 as a hobby from 2001 to 2003, delivering a high-quality, open-source implementation of the SVG 1.0 standard, but with a few intrinsic limitations. It was a standalone SVG viewer, which registered itself for image/svg+xml documents \u0026mdash; and there was no support to embed SVGs inline into (X)HTML documents or supporting SVG \u0026lt;foreignObject\u0026gt;. Back then we decided that we have to integrate our work into khtml, the HTML rendering engine pioneered by the KDE project. However the SVG and the HTML world were largely disjoint. HTML content had no support for affine transformations, was laid out on integer boundaries, adheres to the CSS Box Model object, whereas SVG had its own complex layout model, support for arbitrary transformations, all rendered using sub-pixel precision.\nIt was unclear how to unify these rendering approaches, especially not without impacting the HTML rendering performance. At the end, we have two disjoint rendering models: an integer based rendering path for HTML and a floating-point number based rendering path for SVG. Everything that can be shared between HTML and SVG goes into a common library (kcanvas). On top of that, HTML and SVG rendering can be implemented (khtml2 / ksvg2).\nThis led to the creation of four different software projects:\nkdom: Provides support for parsing/tokenizing of (X)HTML/SVG documents, building a DOM tree, offering a JavaScript interpreter, C++ Web bindings (IDL support), etc. It included an almost feature complete implementation of DOM Level 2 and Level 3 Core, XPath, a CSS2 compatible parser and many more things I forgot.\nkcanvas: Provides a rendering engine abstraction layer, offering a generic interface to Anti-Grain Geometry, Cairo, QPainter, etc.. kcanvas had support for all graphics primitives, necessary to implement SVG and HTML rendering, such as clipping, masking support, stroking/ filling using solid color, patterns, gradients, etc.\nkhtml2: Implements khtml on top of kdom and kcanvas.\nksvg2: Implements SVG from scratch on top of kdom and kcanvas, based on the lessons learned with ksvg1.\nBy mid-2005 we were able to render basic webpages\nRendering of kde.org using khtml2 had basic support for SVG content inline in HTML (unfortunately, I cannot find any screenshot from that time) and had a quite decent amount of the SVG specification implemented.\nIn 2005, Eric Seidel (back then working for Apple, now head of Flutter development at Google) reached out to us explaining their plans to import ksvg2 including kdom and kcanvas into their WebKit project. WebKit \u0026mdash; at that time \u0026mdash; was advancing rapidly with dozens of engineers working on it, so both of us felt that it would be the right moment to join efforts and continue to work on WebKit to advance SVG on the Web. From 2006 to 2012, I worked upstream on WebKit SVG, as hobby initially, later on paid by TorchMobile/RIM/BlackBerry until I left in 2012 to finish my Diploma in physics with the clear vision to return in 2013 after graduation.\nHistory proofs: I was wrong. Instead of returning, I began the work on my PhD in 2013 and only handed in the thesis in late 2019. After almost seven years of absence in the Web world I am happy to announce that I am back, resuming my upstream WebKit work thanks to Igalia.\nMy longtime hacker colleague, Rob Buis, joined Igalia a few years before and explained the idea of the company and why Igalia is a unique place. I was lucky to join Igalia early in October, since there were regular, twice-annually face to face meetings scheduled only two weeks later: the Web Engines Hackfest and the Igalia Summit. The hackfest was inspiring, bringing together people from different companies to talk about and advance the Web technologies across browsers and vendors \u0026mdash; my colleague Manuel Rego has a nice review of the event. I got to know many Igalians during the first three days in A Coruña \u0026mdash; thanks to all of you for the warm welcome and the inspirational atmosphere. I am happy to be onboard!\nThe bi-yearly Igalia summit took place afterwards which was the ideal event for a newcomer to learn more about the fellow Igalians, their work and their personalities. We visited the city of Lugo, played traditional Galician games (ancient bowling), nifty quizzes, ate together all in a relaxed, open-minded atmosphere. Check out the group photo.\nMy first trip to A Coruña was excellent, I got to know many outstanding engineers, all passionate about their work and very supportive. In the past months I have been working on an experimental WebKit prototype that overhauls the SVG rendering engine (stay tuned for details) to pave the way towards supporting hardware accelerated composition, 3D transformations, and many more nifty features.\nThanks for reading my first blog after ages, hope you enjoyed it.\nStay tuned for upcoming WebKit news.\n","permalink":"https://blogs.igalia.com/nzimmermann/posts/2019-11-24-back-in-town/","summary":"\u003cp\u003eWelcome to my blog!\u003c/p\u003e\n\u003cp\u003eFinally I\u0026rsquo;m back after my long detour to physics :-)\u003c/p\u003e\n\u003cp\u003eSome of you might know that my colleague Rob Buis and me founded the\n\u003ca href=\"https://en.wikipedia.org/wiki/KHTML#Other_modules\"\u003e\u003cstrong\u003eksvg project\u003c/strong\u003e\u003c/a\u003e a little more\nthan 18 years ago (announcement mail to \u003ca href=\"https://marc.info/?l=kfm-devel\u0026amp;m=99254089623466\u0026amp;w=2\"\u003ekfm-devel\u003c/a\u003e)\nand met again after many years in Galicia last month.\u003c/p\u003e","title":"Back in town"}]