SVG in KDE

Freedom of Beauty


Abstract


KDE [KDE] is an international technology team that creates Free Software for desktop and portable computing. Among KDE's products are a modern desktop system for Linux and UNIX platforms, comprehensive office productivity and groupware suites and hundreds of software titles in many categories including Internet and web applications, multimedia, entertainment, educational, graphics and software development.

KDE 4 is the latest release of the KDE software stack. One of the most notable changes in KDE 4 is a pervasive usage of SVG. SVG files are used for themes, icons, storage system and transport. They are at the beating heart of beauty of the KDE 4 interfaces.

Furthermore, the whole graphics stack utilized by KDE has been heavily influenced by the SVG standard. A new Free Software graphics driver model, called Gallium3D, has been written in order to utilize modern graphics hardware for accelerating API's such as OpenVG and OpenGL to assure real time rendering of SVG files using minimum amount of resources. On top of that the Qt library, which KDE is layered upon, has a graphics API fully compatible with the SVG rendering model.

To cope with variety of uses of the SVG technology KDE comes with two SVG rendering engines. Th SVG 1.2 Tiny [SVG12] compliant QtSvg library, which is meant to be a minimal rendering engine, suitable for things like icons, and QtWebKit's SVG which is a full SVG engine.

KDE 4 has just begun its existence and almost every day engineers working on it come up with new and creative ideas, tools and use cases for how to better utilize SVG. Unlike most of the technologies leveraging SVG, KDE's focus is on interactivity and animation. A whole set of tools and utilities has been developed to aid that goal. The best example of such uncommon usage of the SVG standard is the Plasma [Plasma] project, which comes with its own animation framework layered on top of the SVG rendering model.

The openness of the SVG standard aided by the creativity of the Free Software engineers created something truly unique and exceptional.


Table of Contents

What is KDE?
History
Rendering model
Extra Features
Current Usage
Icons
Plasma
Games
Problems
Rounded Corners
Small Sizes
Animations
Gradients
References

Definition of KDE [KDE] is intentionally broad. KDE started as a software project, the name itself stood for the "K Desktop Environment" and clearly described the purpose of the project. KDE now provides an easy to use contemporary desktop environment available for UNIX and compatible systems. Together with a free implementation of UNIX such as GNU/Linux, UNIX/KDE constitutes a completely free and open computing platform available to anyone free of charge. Source code is available for anyone to look at, learn from, modify and improve. Whilst there is always room for improvement, KDE today delivers a viable feature packed alternative to the more commonly found commercial operating systems/desktops combinations available.

What makes KDE very unique is the community around it. A group of people connected by the ideals of freedom, beauty and usability make KDE a living entity. As all living beings KDE evolves. From its humble start as a desktop environment it became an ideal, of Free Software and creative freedom, that binds engineers, artists, translators and all its users.

Besides a desktop environment KDE produces a whole suite of libraries, frameworks, applications and art. At the graphical core of it all stands SVG.

The real precursor to the SVG support in KDE is the work done for the KHTML library. KHTML is the HTML layout engine developed by the KDE project. In May 1999 Lars Knoll (currently VP of Engineering at Trolltech, Nokia Company) began researching implementation of the W3C DOM specification. On August 16th 1999 he announced a new version of the KHTML library with a working implementation of the W3C DOM. Soon Harri Porten's KJS library has been integrated with KHTML to enable Javascript support. Finally around March 2000 Lars Knoll together with Antti Koivisto and Dirk Mueller finished most of the work to support CSS.

The first version of KHTML was officially released as part of the KDE 2.0 release on October 23rd, 2000.

Soon after the release of KHTML Rob Buis and Nikolas Zimmermann started working on KSVG1. KSVG1 was essentially a fork of KHTML adjusted to support SVG. The forking was necessary because KHTML had no public interfaces that would allow hooking in the DOM external rendering API's. Due to those shortcomings Rob and Nikolas decided to create a DOM library which could be shared by both KHTML and KSVG libraries. The resulting solution, called KDOM, was the reason why KSVG2 was born.

Around the same time developers at Trolltech were working on the first release of the version 4.0 of the Qt toolkit [Qt]. Qt is a cross-platform application development framework, widely used for the development of GUI programs, and also used for developing non-GUI programs such as console tools and servers. Qt is the foundation of the KDE software. One of the main features of the new release of Qt was a completely rewritten graphics engine called Arthur. The rendering model in Arthur has been heavily influenced by the SVG 1.1 standard and made to be compatible with it. Some of its new features included fill brushes, alpha-blended drawing, anti-aliasing, using paths as a graphical primitive and stroke and fill transformations.

As part of the internal framework to test Arthur a small application, which was rendering SVG files, has been created. The combination of Qt graphics and SVG captured the minds of engineers at Trolltech and the QtSVG library was born.

QtSVG is a very small SVG rendering engine. It's compatible with SVG 1.2 Tiny Standard [SVG12]. QtSVG was meant to be a very fast and minimal SVG renderer. Support for DOM and Javascript was never planned for it.

An implementation of SVG with full DOM and Ecmascript support, created largely by the KSVG developers, has been added to the WebKit project. WebKit was originally derived from the KDE's KHTML library by Apple, Inc. for use as the engine of Mac OS X’s Safari web browser, and has now been further developed by Apple, Nokia, Google and others. Qt 4.4 marked the first official release of the QtWebKit library.

With QtSVG and QtWebKit KDE has two excellent SVG rendering engines.

As previously mentioned the rendering model used by the current major version of the Qt toolkit has been hugely influenced by the SVG standard. Resolution independent UI has been a very tempting proposition for the Qt developers and it was very clear that it could never be achieved without a great graphics framework.

Due to the cross platform nature of the Qt toolkit the rendering engine had to be capable of rendering on multiple platforms, to a lot of various surfaces using a number of different native API's. A side-effect of this design is that the users of the API are capable of selecting which backend will be used for rendering (a number of different accelerated API's is supported including OpenGL, OpenVG, Direct3D and Xrender). At the very core of the API sits a QPainter object which is responsible for propagating the actual drawing commands to platform specific QPaintEngine which in turn renders to an object derived from a QPaintDevice. QPaintEngine abstracts the rendering backend, e.g. OpenGL, Xrender, Direct3D. QPaintDevice can be thought as the surface to which the given backend is rendering to e.g. in the case of the OpenGL QPaintEngine those could be pixel buffers, framebuffer objects or simply GL windows.

The principal graphical primitive of vector graphics is a path. In Qt they are described in a QPainterPath object. Abstraction of the rendering model in the form of QPaintEngine allows utilization of different methods of rendering paths. The raster engine (one which renders on the CPU to a memory buffer) uses scanline rasterization [Turner07], the X11 engine uses tessellation and OpenGL engine uses the stencil method.[RedBook]

The QPainterPath abstracts some useful operations on paths like simplification (removal of self-intersections), boolean operations (e.g. union of paths) and positioning of objects on the path itself. This allows applications using Qt to create very attractive vector graphics effects with ease.

One of the examples is dynamic generation of shadows:


A commonly used effect is positioning of objects on the path and animating them:


Another is layouting of text on a path:


Visually KDE 4 desktop has been largely built on top of SVG. Most of the user interface elements of the desktop have been styled with SVG files.

Plasma [Plasma] is one of the key technologies of KDE 4, and one of the most visible to users. It is the component that is "in charge" of the desktop interface; the desktop, panel and related elements. Plasma has been designed in a way that makes it possible to easily and conveniently change its visual characteristics. Plasma can use "themes", which are essentially a number of SVG images and files specifying the colors and shapes, to change its appearance. This means there is no need for theme authors to know C++ or any other programming language to create a great looking theme.

The center of Plasma's styling infrastructure is occupied by the Plasma::Theme object. Plasma::Theme abstracts the look of the KDE desktop - from colors, through dialogs, wallpapers to widgets. The interface for rendering SVG is held within the Plasma::Svg object. Besides abstracting SVG specific functionality Plasma::Svg class has knowledge of the currently selected theme, this in turn allows it to automatically change every single element of the desktop once a new theme has been selected.

Due to KDE's bleeding edge usage of SVG we were forced to deal with a few new problems. While resolving them internally helped us push the desktop metaphor further, we feel that a few of those problems need to be addressed on a more global scale. In this section we will present the most visible problems we have encountered and propose some sample solutions.

One of the major problems that Qt/KDE applications are facing is a dreaded "rounded corner" problem.

In modern interfaces there's a strong desire to make the transition between elements seem smoother. That implies heavy usage of gradients and rounded, instead of sharp edges. The human brain has been conditioned to see sharp transitions and rough edges as a warning sign. In turn that makes them visually displeasing. Huge effort has been put into the KDE 4 interface to make sure that all the transitions are as smooth, peaceful and visually pleasing as possible. That is why KDE 4 user interfaces make a heavy usage of rounded corners.

Due to styling the visual appearence of the elements is often encoded in the SVG files. Unfortunately in SVG 1.2 Tiny standard the path element doesn't contain the arc elements and the rounded corner arcs are created with Bezier curves. Unfortunately not uniform scaling in either direction changes the curvature of Bezier curves, a side-effect of which is a complete change in the appearance of the element.



To solve that problem elements with rounded corners are split into multiple segments. Each segment get a different XML:ID and the the code renders each segment individually. This allows the application to control which segments get scaled, e.g. rounded corner never get scaled but straight horizontal and vertical segments are.

The loss of quality in vector graphics at small size is a severe problems. Rendering vector graphics primitives at low resolutions introduces a certain amount of blur into the output. This is mainly caused by horizontal and vertical primitives which happen to fall between pixel boundaries, which in turn makes the anti-aliasing algorithms try to cope with it by rasterizing two, instead of one rows/columns but at a lower color intensity. For primitives which are rendered at small sizes the goals of "resolution independence" and "preserving their good looks across resolutions" diverges a lot. We have the former, we need the latter.

One of the ways of dealing with this problem is hinting. The problem of hinting vector graphics primitives has been extensively researched by the way of font technologies. Grid-fitting (aka. "font hinting") is a crucial step on the way to produce legible output at small sizes for a lot of fonts. Hinting can be manual (e.g TrueType has a stack-based language for it, each glyph in the font contains its own little hint program and as a result of running that program control points for the outlines can be adjusted in any way the creator of the hints desired) or automatic (as used by FreeType). An interesting medium is described in "Example-Based Hinting of TrueType Fonts" paper, in which a method of reusing hints from one font for another are described. All in all it's a very common problem for fonts.

The research the engineers from the FreeType project conducted on auto-hinting is outstanding. Right now the way KDE artists go around this problem is by producing certain SVG icons with different viewport sizes. This allows them to manually adjust the rendering for certain native resolutions.

Lack of authoring tools supporting creation of SVG animations forces developers to utilize various hacks to create dynamic interfaces. While QtSvg library supports procedural animations, as defined in SVG 1.2 Tiny Standard, they are virtually never used in practice. They are far too limiting to express complex user interface interactions with them. SVG is canvas based, which makes it significantly different from other formats which can be used for animations, as they are frame-based. One of the major features missing from SVG is the ability to interpolate paths. Defining a starting, ending shape and letting the technology do the work to interpolate between them and automatically create an animation has been very popular lately.

The lack of tools that could be used to create animations is the core problem. Furthermore the requirement to use full DOM scripting in order to incorporate simple interactivity within the created interface makes the process of creating even the simplest animation quite complex. Currently KDE works around that problem, by making SVG a completely static format. The animations are defined in code which loads SVG, selects the elements from the SVG (via xml:id) and manipulates them independently of the SVG they were loaded from.

In order to create realistically looking graphics a fair amount of shading techniques has to be used. In vector graphics shading effects are achieved with gradients. Unfortunately the gradient primitives specified in the SVG standard are very limiting. Artists have a hard time working with both linear and radial gradients.

To solve the shading problem a concept of "gradient meshes" has been introduced. A gradient mesh is a lattice which stores color information at each vertex. During rendering the colors stored at the vertices are linearly interpolated. Gradient meshes are a lot more powerful tool than linear or radial gradient. Unfortunately the toplogical complexity of them is often prohibitive for real-time vector graphics. Furthermore creating more complex gradient meshes is a very slow process requiring a lot of work from the artist. Recently some reserach has been done on the topic of auto-vectorization using optimized gradient meshes by Sun et al [Sun07] but while their approach simplifies the topologies it doesn't help free-hand creation of art at all.

A realization that most color variations in an image can be assumed to be caused by edges led to creation of a new vector primitive called a "diffusion curve" [DiffCurves08]. To quote the paper "A diffusion curve is a curve that diffuses colors on both sides of the space that it divides". This simple representation is capable of representing even very subtle shading effects. The concept is based on a number of research papers which proved that edges constitute a near-complete and natural primitive for encoding and editing images. It's also a model that closely matches the creation of SVG art as the primitives are naturally used to encode the edges. It's also the reason why the gradient model in SVG is disconnected from the process of creation of the actual shapes. The primitives themselves can be rather complex curves but shading between those curves can only be either be rectangular (for linear gradients) or circular (for radial gradients). Diffusion curves remedy that fact by seemingly integrating shading into the process of art creation instead of making it an afterthought.

A simple example of a rendering created with diffusion curves is shown below along a image showing diffusion curves used to create it.