sroedal
KDE
Graphics Dojo
Posted by sroedal
 in KDE, Graphics Dojo
 on Tuesday, September 23, 2008 @ 18:41

When running an X11 compositing manager it’s possible to have translucent widgets by using 32 bit visuals, also known as ARGB visuals. We don’t use these visuals by default in Qt because we’ve seen some driver issues which cause buggy rendering and widgets containing garbage pixels when first being shown, as well as generic slow-downs in some cases. However, we’re now adding conditional ARGB visuals to top-level widgets that are non-opaque, i.e. either have the Qt::WA_NoSystemBackground attribute set or have a transparent or semi-transparent background color specified in the palette. This means that the ARGB visuals will be opt-in instead of being forced onto every Qt application.

What this all means that in 4.5 you’ll be able to have nice translucent Qt widgets on your Linux desktop without any hassle, as long as you have a compositing manager running (which should be easy to enable on newer distributions). Of course, this wouldn’t be a proper graphics dojo post without a nice and shiny example, so I’ve cooked up an example which puts some nice chrome buttons inside a graphics view, and does a fancy animation when you click on the buttons. Here’s a screenshot:

Translucent widget example

Translucent widget video capture

To play with the source and try the example out for yourself, do “svn checkout svn://labs.trolltech.com/svn/graphics/dojo/glossygradients”. You’ll have to wait for the snapshots to be back online to get the translucency effect though :)

gunnar
Qt
Painting
Graphics Dojo
Posted by gunnar
 in Qt, Painting, Graphics Dojo
 on Monday, September 22, 2008 @ 13:07

Sorry guys…

I know you have spent a lot of money on buying faster machines to get Qt to run fast enough for the software you are creating, but I’m now sad to inform you that Qt won’t make full use of these machines. In fact it will use your CPU a little bit less.

Jokes aside… We’ve been running a few optimizations internally, under the code name “Qt Falcon” (its going to make Qt fly!), and I wanted to share some of the current results. These things are not yet integrated into Qt Main, but they should be in place by the time Qt 4.5 goes Tech Preview.

Personally I sit on Windows for most of my daily work, so the benchmarks are from a Windows XP machine, and during the falcon initiative we did take the time to iron out a few things that has bothered us with the windows code paths along the way. Windows uses a software rendering engine, internally referred to as the “Raster Engine”. This is also the engine used for embedded and QImage drawing on X11 and Mac.

Lets start at the beginning, QPainter::begin(), a function that is called at the start of every single paint event in the history of Qt. When we originally designed the paint engines, we aimed at them being shared amongst different instances of the same subclass. e.g. all QWidget painting was done using a single paint engine. For this reason, we put most of the initialization logic into QPaintEngine::begin(), because the actual device changed all the time. With the introduction of the backingstore in 4.2 all widgets are actually being drawn to the same device so this begin() initialization started to make less sense, but the design stayed. With 4.5, we make raster engines be one per image and one per backingstore. The initialization is done outside of begin(), in the constructor if you can believe that.

On Windows, we also checked, in QRasterPaintEngine::begin(), if the system had switched its cleartype settings since the last time. This check was actually costing ~25% of the call to QPainter::begin() (ouch!). By listening for the system event when the users changes the settings instead of polling the value in the registry, we could kill those 25% and also support the feature that Qt switches cleartype when the user press “Apply” in the control panel, which we previously didn’t do.

A comparison of a plain QPainter::begin() / end() looks like this:

begin_end.png

The graph shows, in microseconds, the time to create a QPainter on a device and call end on it

We had a fair idea that save / restore was very costly when clipping was enabled in the 4.4. Part of the reason for this is that the communication between QPainter / QPaintEngine was done via a flat state update. A restore was performed by replaying the previous stack element, so if you consider the case of

p.setClipRect(rect1, Qt::ReplaceClip);
p.scale(2, 2);
p.setClipRect(rect2, Qt::IntersectClip);
p.rotate(10);
p.setClipRect(rect3, Qt::IntersectClip);
p.save();
p.drawStuff();
p.restore();

In the last line, restore(), QPainter would replay three clip operations to the underlying engine. Horrible you may think, and it is a piece of code that has been troubling me since I wrote it in the early 4.0 days. With Falcon, the engines can be made aware of QPainters stack, making it possible to cache the results on each level. That means that restore() becomes just a stack pop(). The results look like this:

save_restore.png

The graph shows, in microseconds, the time it takes to run save, followed by a state change, followed by restore

Another Windows thing that had bugged me for a while is the text drawing. Two separate things came together in QRasterPaintEngine::drawTextItem() as a bit of a mess. Again, I’m much to blame and the code has been troubling me for some time, but I didn’t have time to get back and fix these things. Until now, anyway… Point one, was that the only way to draw nice fonts on windows is using GDI, it does (in my opinion, I know people disagree ;) ) the nicest font rendering of all the systems, so using FreeType or another method would not be acceptable visually, as Qt would look worse than other apps on the platform. So we had to mix GDI and our own raster engine together to do clipping, textured / gradient text. The other point is that any pixel touched by GDI will have 0 as its alpha channel. The raster engine relies on premultiplied alpha so this basically destroys all rendering done afterwards. *sigh*

The solution to the two was to use GDI to render into a buffer and sample the values back into the raster engines buffer and at the same time patching the alpha channel. For cleartype this was even worse as the separate buffer first needed to be filled with the background (cleartype pixels depend on the background as well as the foreground). It ran “ok”, but it we were quite aware of that it could be done better. With Falcon, we introduce a mask-texture for each font engine, which generates the glyphs once using GDI. The approach supports both normal and cleartype text drawing and the cleartype approach even does the full RGB blend with Gamma correction (thanks to Samuel who spent an entire day with me to get the gamma correction of three-component alphablending proper). The speedups are quite noticeable. The results are measured in milliseconds:

text_windows.png

The graph shows, in milliseconds, the time it takes to draw the text “abcdefg” on a QPixmap using the default font with either cleartype or non-cleartype

We also removed some of the overhead of drawPixmap() on the raster engine. The problem was that there was a bit of set-up before we could get into the actual pixel-by-pixel blending. Instead of going through the generic rendering pipeline, we introduced a faster path for unclipped pixmaps (or pixmaps that fit inside a rectangular clip). I won’t bore you with the details, as this blog is already twice as long as I intended it to be. The results for 4.4 and Falcon fall together and become identically, speed wise, at around 200×200, but for the icon-size pixmap drawing, there is quite a visible difference.

draw_pixmap.png

The graph shows, in microseconds, how long time it takes to draw a QPixmap, solid or semi-transparent, at the specified sizes

What I’ve mentioned above, are a bunch of separate small things, and you may be thinking that how does this affect me in the real-world. You probably don’t do for-loops of begin/end() or save/restore. So I’ll finish up with some real-world examples. The numbers below are taken from a benchmark of a few widgets where we simply run “repaint()” a bunch of times. The QLabel numbers don’t have much relation to QComboBox etc, so don’t pay too much attention to that, but rather how each widget changes from 4.4 to Falcon.

overall.png

The graph shows, in milliseconds, how long repaint of a few widgets take

Now, much of the overall speedup here, probably over 50% of it is caused by some awesome work that Bjørn Erik has done in the backingstore. The rest is due to small things here and there, like the ones mentioned above.

There has been quite a bit of refactoring in the works here, and some work is still ahead of us, (like re-enabling GDI based glyph-generation of transformed text, which will be vector path based in the upcoming TP) but I hope that the changes we’ve made will benefit most users and that those that see problems with the new approaches let us know so we can look at those too.

Cheers!

Thomas Zander
Qt
KDE
Graphics Dojo
Posted by Thomas Zander
 in Qt, KDE, Graphics Dojo
 on Thursday, August 28, 2008 @ 13:28

For the last 5 years a huge focus of my work has been on fonts and text. You know you went to far when you can tell the difference between a Helvetica and an Arial by just looking at the printed ‘a’.
Its unsurprising that people end up asking me what the difference is between leading and linespacing, why the customer claims we don’t do kerning for that specific font, why WYSIWYG actually fails for most people. I naturally can’t be because I’m the only one stupid enough to claim to know this, right?
I considered claiming ignorance, but then my weird behavior may no longer have any reason, so that would just make me a worse freak. Instead I just wrote an application that shows everyone how text works. And I’ll write a blog or two about what you can see on screen and how that relates to your questions even before you have them. Genius or what?
So, here is an example text;
fontanatomy1.png
let me quickly go over the different parts. In red we have the outline, this is the total amount of space that the text takes. This is what is reserved in your user interface for the text. The sizes you see on the right hand side are the major anatomical dividers of a font face. Much like your body has a head and legs (I’m making assumptions about that, work with me). The baseline is the only one that is really interesting to point out. it’s the zero-point for a font. All measurements start from there. So you have a part that’s above and a part that’s below the baseline. I’ll leave it to your imagination to mirror that to your own anatomy.
In blue we have the size taken by the individual characters. But when we are talking about fonts we actually should be talking about glyphs. There are subtle differences, but I won’t bore you with that. Each glyph has its own rectangle as you can see in the blue. This is useful to see since the m is wider than the j, which is useful to know since you position the characters next to each other. The blue little gradients are helpers (called bearings) to position the glyphs better so they visually look more pleasing.

Ok, with the basics behind you here are a bit more interesting things; consider the two following screenshots.
fontanatomy2.pngfontanatomy3.png

The only difference is that kerning is turned on for the first and turned off for the second. Notice how the blue boxes overlap in the first image and how they are simply placed side by side in the second.
In general you want kerning to be turned on, its on by default in Qt because it increases readability.

Last example; this one is tricky.
fontanatomy4.pngfontanatomy5.png
Fonts are designed in a way that they can be scaled and reused for any size. Which is a pretty neat idea since it avoids using a crystal ball to figure out which sizes to ship your font in. There is a little problem, though. A font that is printed on paper at 10cm per character needs a lot of detail but if you use the same character at on screen at just a couple of millimeters height, you have problems to make that one look good.
So, font makers ship something called ‘hints’. Which make their fonts look better at smaller sizes then the computer could do automatically. This is enabled per default and is practically speaking exactly what you want.
Except for one problem; if you add all those little adjustments they can add up. So much that if you have a sentence you can have a word that fits just fine when you show the font on screen, but if you then take the same width and same text but on paper, those little adjustments may just move a word to the next line.
In other words; hinting gets in the way of what you see is what you get text-layout. So, in Qt you can turn this off. Allowing you to get the exact same line-breakings on screen as you get on paper.
Look at the following two screenshots. You will see a little spacing between the little blue squares in the one where the hinting is turned off. We call this mode ‘designer metrics’.
if you want to play around with this stuff yourself, here you can find the sources;

svn checkout svn://labs.trolltech.com/svn/graphics/fontAnatomy

For the people that are still here, thanks for sharing the pain! And I’ll answer the question of “why should I care!”. The concepts shown in this blog have good support in Qt4. The point to take home is that the font is the one that specifies all the information. If the font doesn’t have kerning, game over. If the font has horrible sizing information, you are out of luck. With this little tool at least you can see the differences that different fonts make.

ariya
WebKit
Graphics Dojo
Posted by ariya
 in WebKit, Graphics Dojo
 on Wednesday, August 06, 2008 @ 09:14

Usually you will use QSvgRenderer or QSvgWidget to show the content of SVG (Scalable Vector Graphics) files. So far, QtSvg supports SVG 1.2 Tiny static, without any DOM nor scripting supports. For a much more advanced SVG dancing, one way to do it is by using QtWebKit [1] that is available since Qt 4.4. More detailed information can be obtained by tracking the SVG status support in WebKit.

For the dojo example, here I present less-than-150-lines of code that rasterizes an SVG [2] into an image. The principle is surprisingly simple: we just use QWebView to load the SVG. To rasterize it, we create a QPainter that operates on an image then ask the main web frame to render to the image by using this painter. A little bit complication is on the scaling. To keep the code cleaner and easier to understand, this little SVG rasterizer is made to work only on SVG that has a valid size, i.e. the SVG explicitly specifies both width and height attributes. Since DOM API is not available yet in Qt 4.4, a trick which is employed here to get both attributes is by using QWebFrame::evaluateJavaScript() function [3].

Without further ado, get the code:

svn checkout svn://labs.trolltech.com/svn/graphics/dojo/svg2png

As with many other vector graphics-related goodies, here is the obligatory “Tiger” screenshot (click to enlarge). On the left side is the SVG file shown inside Inkscape, on the right side is the rasterized version (using svg2png) displayed with Gwenview. Due to the said restriction (specifying width, height), the SVG is not really the same as the commonly used example, I added both the necessary height and width attributes.

Result of WebKit-based SVG rasterizer

As an exercise to the reader, modify the program so that it works with a remote file, e.g. an URL with http or ftp scheme. Hint: check for guessUrlFromString() function in the Qt 4.4 Demo Browser.

[1] However, filter effects are not fully implemented yet.
[2] .svgz is not supported
[3] Use the JavaScript console in the Web Inspector to check and play with the DOM elements and their attributes.

Thomas Zander
Qt
KDE
Graphics Dojo
Posted by Thomas Zander
 in Qt, KDE, Graphics Dojo
 on Monday, August 04, 2008 @ 10:08

Some of my colleagues on the graphics team have been writing graphics dojo demos with impressive speed and with a rainy weekend I thought I’d get into the action.
As I’m regarded as the text guy I thought it would be fitting to have a demo that uses text, so I made a text effect class that animates text fading in and fading out.

One thing that I see a lot of people do is that if they want to zoom into text, they change the fontsize. There is a fundamental problem with that approach as text doesn’t scale linearly (due to hinting). So in Qt4 we have a much simpler and more powerful way of scaling text that fits better in graphics concepts. You simply scale the QPainter during painting.
This means that if you call myPainter.scale(2,2); your 12pt font will suddenly appear as a nicely scaled 24pt font. Or, more accurately, it will show the original text at 200% zoom.

This is very simple and due to us reusing the same font settings we avoid recalculation and text layout. So it will actually be quite fast. So fast that you can animate it quite smoothly. As is shown in the demo.

There is not much more to say about it, so just grab the code and run it!
svn checkout svn://labs.trolltech.com/svn/graphics/dojo/zoomingtext

zoom1.png
zoom2.png
zoom3.png
zoom4.png

sroedal
Qt
Graphics Dojo
Posted by sroedal
 in Qt, Graphics Dojo
 on Friday, August 01, 2008 @ 12:45

For this episode of the graphics dojo I’ve implemented the classic radial blur effect. The core radial blur effect is implemented with per-pixel manipulation, which Qt lets us do quite elegantly using the QImage class. The final dojo example uses the radial blur effect in combination with scrolling text drawn using QPainter to create a nice visual impression. Below is a screenshot of the effect as well as a recording:

Radial blur screenshot

Radial blur movie capture

As usual, the source code is available from the SVN repository: svn checkout svn://labs.trolltech.com/svn/graphics/dojo/radialblur

ariya
Qt
Graphics Dojo
Posted by ariya
 in Qt, Graphics Dojo
 on Sunday, July 13, 2008 @ 14:27

Distorting the geometry of an image with a specific periodic pattern can give the illusion of being underwater. This trick was for example employed in the very first version of Quake, either to oscillate the water surface or to modify the view when you jump inside the water. Apparently, it is not difficult to do that, even with pixel-per-pixel manipulation of QImage.

Check out the code from the usual place:

svn checkout svn://labs.trolltech.com/svn/graphics/dojo/underwater

It is recommended to build the program and see the effect by yourself, the following screenshot can hardly describe the animation. As usual, once the example is running (it would show the included bridge picture), you can change the picture by dragging an image (from local disk or a web browser, e.g. Flickr or Picasa Web) and dropping it on the main window.

Qt for doing underwater effect

Note: the snappers picture is from james_wicks, distributed under the Creative Commons Attribution 2.0 Generic.

ariya
Qt
Graphics Dojo
Posted by ariya
 in Qt, Graphics Dojo
 on Saturday, July 05, 2008 @ 19:48

Time for another fresh example for the Graphics Dojo. This time I present a small tool that does nothing but showing the famous HSV cylinder. To give some realism, subtle blurred reflection is also added but can be easily disabled. Manual full-scene anti-aliasing is provided by the usual multisampling approach. Everything is done using pure QImage per-pixel manipulation along with some tricks, no OpenGL (or even its GLSL) is involved.

HSV Pie

For the code, check it out using:

svn checkout svn://labs.trolltech.com/svn/graphics/dojo/hsvpie

Note that the tool is not optimized for speed (evidenced by lots of setPixel() calls) so there is definitely room for improvement. Some possible further enhancements left as exercises for the readers are interactivity (mouse dragging to change e.g. the depth of the pie) and threaded rendering (so that the application remains responsive, just adapt the Mandelbrot example).

Have some dojo-fun!

ariya
Qt
Graphics Dojo
Posted by ariya
 in Qt, Graphics Dojo
 on Sunday, June 29, 2008 @ 01:35

If you play games like Rainbox Six: Vegas or watch movies like Elephant Dream, you will notice the use of the so-called Bloom effect. In fact, Vegas is so bright and surrealist that this game becomes known for its Bloom overuse.

In this Graphics Dojo example, I would like to show how to render an image with the Bloom effect. This extends the previous example from Zack on making real-time glow effect. The technique: create a copy of the image, blur it, increase its brightness and then combine with the original image with a certain composition mode and opacity. Since a picture is worth a 2^10 words, I will let the following screenshot (click to enlarge) speaks for itself.

Bloom effect with Qt

The image on the left side is the original, whereas the right one shows the result of applying Bloom. As you can see, there are few sliders where you can tweak the parameter to achieve the effect that suits your taste. Different composition modes can give (not so radically) different results as well, just play around with it.

How to get it? Just do “svn checkout svn://labs.trolltech.com/svn/graphics/dojo/bloom” followed by the usual “cd bloom && qmake && make && ./bloom”. Once the main window shows up, you can also change the image by using drag-and-drop from a file on your disk or even a link from the web browser (e.g. straight from your Flickr gallery). Have fun!

sroedal
Qt
Graphics View
Graphics Items
Graphics Dojo
Posted by sroedal
 in Qt, Graphics View, Graphics Items, Graphics Dojo
 on Friday, June 27, 2008 @ 13:47

To breathe some new life into the graphics dojo, here’s an example of how to put widgets on top of an OpenGL scene using QGraphicsView. By leveraging the synergy (tounge in cheek) of the OpenGL module and graphics view’s in 4.4 new widget capabilities, the long lacking feature of putting widgets in OpenGL becomes possible. All that’s needed is to set a QGLWidget as viewport on the graphics view, override QGraphicsScene::drawBackground() to do the OpenGL rendering, and add widgets and other graphics items to the graphics scene as usual. The result can be seen in the screenshot below, which shows a simple obj-model viewer application written in just a couple of hundred lines of code:

Widgets on top of an OpenGL scene

The source code is available by “svn checkout svn://labs.trolltech.com/svn/graphics/dojo/modelviewer”. Have fun!



© 2008 Nokia Corporation and/or its subsidiaries. Nokia, Qt and their respective logos are trademarks of Nokia Corporation in Finland and/or other countries worldwide.
All other trademarks are property of their respective owners.