gunnar
Graphics View
Painting
Graphics Dojo
OpenGL
Posted by gunnar
 in Graphics View, Painting, Graphics Dojo, OpenGL
 on Monday, January 11, 2010 @ 09:25

Previous posts in this topic:

So, its time for my next post. Todays topic is how convenience relates to performance, specifically in the context of QGraphicsView. My goal is to illustrate that the way to achieve fast graphics is to pack your QPainter draw calls as tightly together as possible. The more stuff that happens in the middle, the slower it gets.

To illustrate this, I’ve implemented a virtual keyboard. Granted, its not a very common layout nor is it usable, but the rendering is the point here, not the functionality. The full source code is here and it looks like this:

Virtual Keyboard Image

I’ve implemented the keyboard using three different approaches. One using proxy widgets, one using graphics items and one where the entire view is one graphics item. In addition to that, I added a number of options to tweak various properties, such as whether or not the text is drawn. I measured this on an N900 rather than a desktop because the difference becomes more profound on a small device. On the desktop it is easy to be fooled because most things complete in a matter of micro seconds anyway. It is only when the entire application comes together one notices that things are not as smooth as in the prototype, but too much work has been invested into the current design that one loses out on the super-slick feeling application.

QGraphicsProxyWidget

Since we’re implementing a series of clickable buttons, a natural and convenient starting point is to use an existing button class, such as the QPushButton. It already implements the logic for mouse/keyboard interaction and has signals for clicking and all sorts of other useful functionality. To get widgets into QGraphicsView, we use a QGraphicsProxyWidget. To make the test “fair”, I actually use a plain QWidget which just paints a pixmap and a draws a text. Had I gone through the styling API, these numbers would have been even worse.

ProxyWidget Results
Milliseconds spent per frame including blit to screen when using QGraphicsProxyWidgets. Low is better!

If we look at the plain “-proxywidgets” run, the fastest engine was the raster engine, running at 26ms per frame. If I wanted to slide this keyboard onto screen, I have 16ms available if I want it running at 60 FPS and 33ms available if I want to do it at 30 FPS. When each frame takes 26ms, I can barely do 30, but with only a little bit of slack, so if another process is soaking up CPU time, that number is also a bit difficult to reach. So, not very good. (BTW, the exact numbers in the graphs are listed as a comment in the top of the .cpp file I linked above).

The first thing I noticed with this approach was that the each button now had a gray background. This is of course the widget background. A QWidget embedded in QGraphicsView will be treated as a top-level and will therefore draw its background. I added an option “-no-widget-background” which sets the Qt::WA_NoBackground on the widget. This brings the rendering speed with raster down to 22ms. 4ms saved per frame, just by setting a flag, not too bad, but still pretty far from being awsome.

I’ve mentioned before that text drawing is not as fast as we would like it, so just to compare how it looks without text, I added a “-no-text” option to the test. This brings the raster results down to 13ms. That is pretty nice and below the 16ms threshold required to achieve 60 FPS, but only with a small margin. And I’m not drawing any text! Before I give up with this approach, I’ll enable item caching. By setting ItemCoordinateCache on each button, I cache both the background pixmap and the text in one single pixmap. This brings the raster results down to 8.5ms, and its starting to look acceptable. But at a very high memory cost… In my original usecase I had one shared pixmap for all the button backgrounds, but now I have one per button.

You may notice that there was a vast difference between item caching and the proxy widget drawing the pixmap. One thing that adds to the proxy widget cost is that the QPainter is recreated and initialized for each button in the buttons paint event. Also, as I mentioned in my previous post, An Overview, you may remember that I said that each widget has a system clip and that there is an overhead involved with calling the paintEvent. For items in QGraphicsView, there is already a painter, and I don’t need a clip, nor do I need any of the other stuff that goes on behind the scenes there. When we enable item coordinate caching, we don’t leave graphics view world and we don’t enter the widget world. This crossing is expensive, so by not going into the widget world, we save a lot.

So, if there is a lesson to be learned it is that QGraphicsProxyWidget should be used with extreme caution. If you really need it, use very few of them.

QGraphicsWidget

If proxy widgets are too slow to be usable in this scenario, then the next best thing is to use a QGraphicsWidget. This is a subclass of both QObject and QGraphicsItem, which gives me signals, slots and properties, but its not a QWidget and therefore still fairly lightweight. The numbers are as follows:

GraphicsWidgets Results
Milliseconds spent per frame including blit to screen when using QGraphicsWidgets. Lower is better!

Compared to the proxy widgets approach we’re starting out quite a bit better, with raster at 13 ms per frame, OpenGL at 20ms and X11 at 22ms. Below this line is a new line: “-no-indexing -optimize-flags”. QGraphicsView will by default put all the items in a view into a BSP tree for fast lookup, this is beneficial when the scene contains many items and you often need to find items that intersect with a small portion of the scene. In the testcase we’re always doing a full update, so there is no benefit from the index, so it can be disabled by calling scene->setItemIndexMethod(QGraphicsScene::NoIndex). Having a BSP is the default behaviour because graphics view was initially intended to be a static scene for many items. The most common usecase today is a few (a few hundred at max) items which tend to move a lot. For this reason, it is always a good idea to try to disable the BSP and see if it makes a difference in performance. If it helps, then leave it off.

I also know that the items play nice, meaning that they don’t change the clip, translate the painter, change the composition mode or modify any other state that would propagate to other items. This means I can safely set the DontSavePainterState optimization flag. Actually, based on an old habit, I set all possible optimization flags. I only consider unsetting them if my drawing code starts to look weird, at which point I would rather fix the drawing code and keep the flags set. By disabling indexing and enabling optimization shaves off 2ms per frame in for all rendering backends, so that is definitely worth it.

If I don’t do text, the performance is about twice as fast. Again we see that text drawing is a huge cost. We’re working on an API to fix this and we’ll have more information for you when we do. You may notice that enabling item caching drops the performance a bit compared to the “-no-text” case. There isn’t much overhead inside QGraphcisView for this path. A likely reason for the decrease is that reading from multiple memory sources (multiple pixmaps) results in a lot of cache misses, compared to the straight approach which draws the same pixmap over and over.

ButtonView Item

In my previous post I briefly mentioned that there is a slight overhead involved with the use of a QGraphicsItem too. Prior to calling the paint function, the painter is transformed to the coordinate system of the item and the painter state is saved. If the item draws a big polygon, this setup cost can be ignored, but when drawing just a pixmap and a few pixels of text, then it may be worth considering. In the spirit of “The more direct the painting code is, the faster it gets”, I implemented the keyboard as a single item. The numbers are as follows:

ButtonView Results
Milliseconds per frame including blit to screen when using a single item. Lower is better!

Raster is now down to 10ms, which is 1ms better than the QGraphicsWidget approach when all optimizations were enabled, so even though graphics items are cheaper than widgets, they still cost a bit. The keyboard is now rendered in a tight loop, and the major difference in performance here is caused by the fact that items in the scene have a transform associated with them. Prior to calling paint() a transform is set to match the painter to the items local coordinate system. This causes a state change in the paint engine. For each button we’re drawing a 32×32 pixmap which means alpha blending 1024 pixels, followed by doing text layout and drawing a single character. Even then do we save about 10% time by not having a QPainter::translate() in the midst, so bear that in mind. By enabling the optimization flags and disabling the index, raster drops a bit more, so having those are still a good idea.

You may have noticed that there is one dataset that is named “cheat” for OpenGL. I was reluctant to include this, because its using a private API that is not, and I really mean NOT, subject to binary compatibility rules. You cannot call this from your application. We’re going to add a public API for this in the future, hopefully 4.7, so until its there, wait. In the interest of showing what we are thinking internally, I thought I would show it.

OpenGL is really great for accelerating graphics, but its way of working does not map optimally to how Qt works. GL is really good at taking a few large datasets of triangles and rendering them, but its not so good at drawing loads of small things. Small things like button backgrounds, icons, single text items, etc. However, all the buttons backgrounds are the same pixmaps, so what if I could tell QPainter to draw the same pixmap in multiple places at once? In GL this would correspond to setting up a texture and one vertex and texture coordinate array and drawing some 40 pixmaps in one go. This fits much better with how GL is made to work. The result is that drawing the buttons drop from 5.2ms to 3.9ms, so another piece of juice squeezed out. Naturally, the more times the pixmap is drawn and the smaller the pixmap gets, the more benefit you get from batching commands like this.

There is a second option to OpenGL for the button view case, which is the “-ordered”. This was done after Tom brought to my attention that the testcase would do a shader program update for each painter call. In the default buttonview implementation we do:

                    for (int i=0; i < m_rects.size(); ++i) {
                        p->drawPixmap(m_rects.at(i), *theButtonPixmap);
                        p->drawText(m_rects.at(i), Qt::AlignCenter, m_texts.at(i));
                    }

Because pixmaps use one shader pipeline and text drawing uses another, the pipeline needs to be switched and reset all the time, which renders at 16m per frame. To see if it makes a difference, I added a second alternative rendering, “-ordered”, where I do all the pixmaps first, then all the text:

                    for (int i=0; i < m_rects.size(); ++i)
                        p->drawPixmap(m_rects.at(i), *theButtonPixmap);
                    for (int i=0; i&lt;m_rects.size(); ++i)
                        p->drawText(m_rects.at(i), Qt::AlignCenter, m_texts.at(i));

This prevents the shader pipeline updates and bring the rendering time per frame down to 13ms, so definitely worth it.

Summing Up

Virtual Keyboard Combined Results
Milliseconds per frame including blit to screen for proxy widgets, graphics widgets and a single widget. Lower is better!

OpenGL comes out rather bad in this testcase, which I was a bit disappointed to see, but it did send Tom into an optimization frenzy, so we’re hoping to remove some of the constant overhead. It should also be said that when using the OpenGL graphics system, we enable multisampling by default, which increases rendering time on the N900 by around 30%. A plain QGLWidget would thus perform slightly better. Another aspect to OpenGL is that it uses a dedicated low-power chip, so even though it for this particular usecase runs at half the speed, it also uses a lot less battery, so it may still be the right choice. OpenGL will also scale significantly better than raster and X11 as the pixmaps get bigger or if the content of the button is slightly more advanced, say like a horizontal gradient.

The best numbers are definitely in the button view case, where all the content is rendered as one item, which is what I wanted to highlight with this blog. The button view item also opens up for other optimizations such as batching. We don’t have that many batching functions in QPainter today, its only drawRects(), drawLines() and drawPoints(), but we’re considering to add more, we are just not sure on how the API’s would look yet.

The bottom line is still that how Qt is used defines how well it performs. On one hand there may be an easy and convenient way to get the job done which performs quite sub-optimally. On the other hand there may be a more involved implementation which performs very well. I’m not trying to suggest that you do one or the other, there are a lot of good reasons for picking either one. But I hope that I’ve illustrated that some features come at a cost and that this is kept in mind along with what the target is when designs evaluated and chosen.

I’ll round off with a question. If you were to implement a particle effect when you press a button, which approach would you choose, having seen the numbers above?

kamlie
Qt
Contributors
Git
S60
Posted by kamlie
 in Qt, Contributors, Git, S60
 on Tuesday, September 15, 2009 @ 08:36

Many people have expressed some confusion over the the S60 port of Qt and where to find the relevant branches, so I thought I’d give a little update on where things are happening:

When the port was still young, it lived in the qt-s60 repository on gitorious. Here, both the master branch and feature branches coexisted happily. This however changed when the S60 port was merged back into the 4.6 branch of Qt. After this the master branch in the qt-s60 repository became abandoned.

rip-qt-s60-master

Since this branch will not be used for development anymore, I deleted it today. This does not mean that the repository is dead though. The Qt for S60 developers still use the repository to develop feature branches, and we will continue doing this in the near future. When they are done, they will be merged back to a branch in the Qt repository (like 4.6, 4.7 or master). So unless you want to track a specific feature branch of interest to you, all the relevant S60 development happens in qt/master.

So what about contributions? After the merge of the S60 port, the rule is simple: Submit all merge requests to the Qt repository, even if the request is based on code found only in the qt-s60 repository. This is easier for you (one single place to submit to) and for us (one single place to monitor).

A couple of other notes on contributions related to S60 code:

  • Be careful when you deal with code that can throw a Symbian leave. These have to be wrapped in special conversion macros. See this page for more information: Symbian exceptions safety.
  • Coding style. Traditionally Symbian has had its own coding style with a different indentation and naming scheme. This style does not apply to S60 code used in the Qt library; We still use the same style that we always have! If you need a cheat sheet to the Qt coding style, look here: Qt Coding Style. You might also want to read the Qt Coding Conventions. Update: If you are using Carbide, you can download the Qt_Code_Style.xml template. To add it, just go to Window > Preferences... > C/C++ > Code Style and import the file you just downloaded.
  • There are still problems when compiling Qt for hardware using GCCE. The emulator should work fine though. We hope to get this fixed in the future.
  • The rest of the contribution process should be explained in the Qt Contribution Guide.
  • Update: The win32-mwc mkspec that was used in earlier releases has been deprecated and is not supported anymore. You need to use either Microsoft Visual Studio or MinGW and use “-platform win32-msvc2008″ or “-platform win32-g++”, respectively.
Ariya Hidayat
Graphics Dojo
S60
Posted by Ariya Hidayat
 in Graphics Dojo, S60
 on Sunday, August 09, 2009 @ 09:09

A few days ago I was curious how fast Qt for S60 (Tower release) can blit the pixels to the screen. I decided to port the simple ray caster I wrote 14 years ago to Qt for S60 and to test-drive it on a Nokia E71. The result is something that our video maestro, Alessandro, assembled for us nicely (he showed it on a Nokia Navigator), see below or directly on YouTube:


There is a gazillion ray casting implementations (and tutorials) out there, for a number of different platforms/compilers/CPU (even for the web, using HTML canvas and JavaScript). This example will add one more to the crowd. Find the code in Graphics Dojo repository and use Qt 4.3 or newer to enjoy it. The demo weighs slightly less than 300 lines of code (too short for your taste?). It does however work only with keypad navigation, the users of Nokia N97 and 5800 need to implement some kind of mouse/finger navigation (a good exercise!). Of course, try it first on the desktop, it runs just fine:


True to Wolfenstein 3-D that made ray casting popular, my example also shows a different shading between the walls facing different direction. As you may witness from the shipped textures.png (which holds all the textures, adopted from a very nice Wolfenstein 3-D alternative texture library), this is achieved by having two version of the same wall texture, the normal one and the darker one. In addition to that, each wall texture source pixmap is prerotated by 90 degrees. This is again the old trick I used for the first time in PictureFlow (the same effect that powers Qt Fluid Launcher). The basic premise: improve the cache locality, this is because during texture mapping we scan the pixels within the same horizontal row (neighboring integers), not the vertical column (which means jumping far more than the size of the cache lines).

The code can be further optimized (of course!). In fact, there is no so much Qt-specific part in it (afterall, it’s ported from my old Mode X DOS-based test program). For a starter, I am sure a seasoned S60 developer know a bit or two about direct screen access (maybe via CDirectScreenBitmap aka Anti-Tearing API?), this surely improves the blitting although I don’t know how less portable the code would be. On a different side, you might see that I improved the inner loop by using simple fixed-point arithmetic. The outer loop is still based on floating-point, feel free to cast some fixed-point magic there, at the potential cost of readability. Sine and cosine can be stored as look-up tables, especially if you turn the viewing angle also to fixed-point. While you are on that, notice also how I got away with finding the sine and cosine for each ray (which you can nicely solve, once the fast look-up table is at your disposal), similar to Ken’s Labyrinth (afterall great cheaters think alike), at the price of a less perfect rendering. The mechanics behind ray casting is fairly easy (there are tons of tutorials in Internet), however if your math skill is rusty and parts of this example are difficult to decipher, it is time to grab a sheet of blank paper and to start scriblling, drawing, and playing with geometry. Hardware accelerated graphics, even on mobile platforms (via OpenGL ES and OpenVG), already starts to become the norm these days. This leaves classic stuff like ray casting to serve the educational purpose only.

If you are interested in doing more 3-D with Qt, don’t miss the more advanced WolfenQt demo. While this simple ray casting example is pure pixel-manipulation, WolfenQt relies on perspective transformation with Graphics View. It does allow interesting features of Graphics View, like embedding a web browser, a media player, and other fun widgets, as well as exploiting the benefits of OpenGL.

And there are still many steps if you want to base a game on this example (note: there is already S60 Wolfenstein 3-D, if you just want to have a look). Sprites support is still missing, sound also does not exist. On the rendering front, you might want to add some doors (hence the opening and closing logic) for a better game play. All of them is still doable for a weekend project, so have fun if you want to bring Captain Blazkowicz to life!

Ariya Hidayat
WebKit
Graphics Dojo
Posted by Ariya Hidayat
 in WebKit, Graphics Dojo
 on Tuesday, June 09, 2009 @ 07:01

An interesting feature of a navigation system (so I was told, I don’t own a car) is the so-called "night mode". Basically the display is adjusted so that the text and the map become more readable under low ambient light condition. An easy trick to do this is by inverting the color, just like what Mac OS X can do for the whole desktop.

Thanks to QPainter, it is fairly easy to do that in just a few lines of code. Basically we need to use a proper composition mode. If you think composition modes are like black magic, here is a chance to understand a bit of it. As you read the documentation on QPainter::CompositionMode_Difference or CompositionMode_Exclusion, you will find that Painting with white inverts the destination color. Voila! That is exactly the cheating path that we have to use.

The super-short example for color inversion is in the Graphics Dojo repository under the webnightmode directory (available for both Qt/C++ and PyQt). Although the trick here is illustrated for QWebView, of course it is suitable for other widgets, too (see Henrik’s yesMan example). Note that not every paint engine/device supports QPainter::CompositionMode_Difference, hence why in the code I force the use of raster graphics system under X11.

Note that an actual implementation of a night-mode feature is likely more complicated than just a color inversion method (feel free to suggest or brainstorm the ideas for such an algorithm). The overall brightness and constrast should be taken into account. Likely this requires an adventure in the non-RGB color space, something that is outside the scope of this example. Most of the cases however, you can get away with the discussed trick.

Exercise for the brave readers: use selectors (CSS or jQuery) to find the map element, then invert that element only.

Ariya Hidayat
WebKit
Graphics Dojo
Posted by Ariya Hidayat
 in WebKit, Graphics Dojo
 on Tuesday, June 02, 2009 @ 07:25

For any widget system, be it KDE4 Plasma, Mac OS X Dashboard, Yahoo! Widgets, Opera Widget, Google Gadgets, Microsoft Gadgets, and so on, weather applet is usually the typical example (beside a digital clock, an analog clock, or other variants of the clock). What is shown here is yet another little weather info tool, built using QtWebKit.

The idea came up when the other day I presented a challenge to myself: what is the shortest possible code that shows the weather, along with the forecasts for the next few days, for any places in the world? Usually this involves a lot of thinking. Thanks to Google however, the solution came instantly (avid Google users know this by heart). Hint: see the result of searching for "Weather in Oslo".

By smartly (some people call it cheating, though) combining this powerful Google service and a web rendering engine, the solution magically appears. Or rather it should not. Because by using magic, I will be unfair to my fellow (poor) software engineers, I decided to fire my Qt Creator and implemented the answer to that challenge the hard way, i.e. by actually doing it. The screenshot first:


The logic of the program is rather simple. Just loads the proper URL corresponding to the search for the weather, as if you would have typed in manually in your favorite web browser. After the web page shows up, find the DOM element that represents that information snippet (we are not interested in the search results lists), this is done using little jQuery-based JavaScript code. The web page is rendered to a pixmap, only the region of that DOM element is painted, and then the pixmap is shown.

The code is just one git clone (or git pull) away from the Graphics Dojo repository (yes, we are also moving to Gitorious). Check the subdirectory named gweather. You need Qt at least version 4.5.

As healthy exercises for the readers, try the following things. Implement an auto-reload feature (be gentle, no need to refresh the page every 5 minutes). In addition, add a possibility to change the location or city. Remember, magic is not allowed.

Ariya Hidayat
WebKit
Graphics Dojo
Posted by Ariya Hidayat
 in WebKit, Graphics Dojo
 on Sunday, March 08, 2009 @ 15:09

Of course, I cheated. The trick is actually by using Google’s own iPhone web application, which is pure HTML and JavaScript. Despite the name Google Talk, unfortunately it has no support for voice chat, rather only text chat.

The secret is to find the actual URL and load it in QWebView. Since initially it presents a login page, this particular client also automatically fills the username and password for you, getting them from its own login page. Overall, the code is very simple and does not even reach 200 lines, including some rudimentary error handling (wrong password, failed login). The user interface was created completely using Qt Designer. Careful readers might notice that I deliberately added the flick support (kinetic scrolling) using Flick Charm. This quick-and-dirty chat client was completed in less than quarter an hour.

Check the code at the usual Graphics Dojo git repository, find it under the webgtalk folder. This example requires Qt 4.5, which has just been released, in particular due to the use document.getElementByid. Exercise for the reader: tweak the little JavaScript snippets used in this program so that it works also with Qt 4.4. Another challenge: there is also
chat client for iGoogle which performs better but then it requires Flash plugin.

Ariya Hidayat
Graphics Dojo
Posted by Ariya Hidayat
 in Graphics Dojo
 on Monday, January 26, 2009 @ 09:57

In this era of digital photography, thumbnail preview is probably one of the most important features in any photo management software. Imagine if you have to flip through thousands of pictures, without being able to see the thumbnail previews. It would be a complete waste of time. Ideally the thumbnail preview is taken from what is stored in those JPEGs. However, suppose that you want larger or smaller previews, how to do that? With Qt, we can utilize QImage::scaled() function:

QImage result = img.scaled(200, 150, Qt::IgnoreAspectRatio, Qt::FastTransformation);

This gives a very fast downscaling, however the result is perhaps not so satisfactory because the resizing is only using the nearest-neighborhood method. For extra filtering, use the following instead:

QImage result = img.scaled(200, 150, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);

Due to Qt::SmoothTransformation, the thumbnail has a better quality. The drawback is that it is very slow compared to the previous Qt::FastTransformation.

A trick known to almost every graphics programmer out there is this one:

QImage result = img.scaled(400, 300).scaled(200, 150, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);

The first scaling is using Qt::FastTransformation (we do not need to specify it explicity, it is the default) to twice our target size. This is of course very fast. The second scaling does some smoothing for the final result.

Another obvious and better alternative is of course:

QImage result = img.scaled(800, 600).scaled(200, 150, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);

which is essentially the same, only now we scale to four times the target size first.

So basically we “cheat” by not really scaling and filtering the whole image. This will speed up thumbnail generation process significantly. But don’t be surprised when I say that we can still make it even more faster. The trick? Use the previously discussed faster halfscaling method! The following chart shows the overall performance comparison (longer is better), take it with a grain of salt:

“Cheat scaling” is apparently very fast. This lies in the fact that it processes ARGB components at once (see the blog entry on fast image halfscaling) at the expense of less-precise low bits. The numbers represent the iterations for every 10e12 CPU ticks in order to resize a 10-megapixel image to 200×150 pixels. As you can see, the improvement is clearly obvious, though you may get less speed-up if the original and target size are not that extreme. You could probably push the performance further by falling back to processor-specific vector operations, e.g. SSE on modern Intel CPU.

How about the quality? Check the example at Graphics Dojo repository under the subdirectory thumbview. After building and running it, drag an image (from file manager or web browser) and drop it there. Please try a very big image, i.e. exercise the program with pictures from a fairly modern digital camera. The screenshot looks something this:

Press 1, 2, or 3 to change the scaling method for the bottom right image. To compare the quality between Qt::SmoothTransformation and cheat scaling method, you can flip using 2 and 3 quickly. Are you able to spot the difference? You’d be the judge!

Of course this cheat scaling method is not a silver bullet, nor it is a replacement for Qt::SmoothTransformation. For our specific case, namely creating a small preview of a very large, relatively patternless digital picture in ARGB32 format, the trick works well.

Ariya Hidayat
Qt
Graphics View
Graphics Dojo
Posted by Ariya Hidayat
 in Qt, Graphics View, Graphics Dojo
 on Monday, December 15, 2008 @ 15:08

Let us start with the code:

svn checkout svn://labs.trolltech.com/svn/graphics/dojo/genie
cd genie && qmake && make && ./genie

For the impatient, a screencast is worth a thousand screenshots. For your pleasure, here is the 20-second screencast. Or view it on blip.tv, YouTube, or grab the Ogg Theora file (1.4 MB).

Usually you would not want to do the genie effect (made famous in Mac OS X) like in this implementation, as you can get mesh deformation easily using GLSL. Here I just want to show code as another example of one of the messages from my graphics talk in Qt Developer Days, namely "cheat whenever you can". If you inspect the inner loop, you can see that it is fairly simple. The idea is to store the outline of the genie shape in a table (I use logistic function, as "S" shape looks really good). During the animation, the left start-point and right end-point of each row is used to scale a horizontal slice of the original pixmap. One dimensional scaling like this is fairly cheap, as in ray casting trick. Furthermore, the only division in the loop can be optimized (at the cost of visual quality) to be carried out every N rows (the alternative is a look-up table). Since we are animating anyway, decide yourself if you can get away with the sacrificed quality.

I have no doubt that the experienced readers can further squeeze the scaling code, I left it just like it is because it starts to be less readable. Of course, feel free to have more fun there!

Final word: special thanks to Enrico Ros for the discussion, initial code, and the feedback.

Alessandro
Qt
News
Posted by Alessandro
 in Qt, News
 on Wednesday, July 11, 2007 @ 14:54

Trolltech is about to release its development tools as Qt Eclipse Integration. Here is a short introduction in Q&A style to what it is and how you can start hacking, today, plus a few screenshots.

About

  • What is Eclipse?
    Many people think of it as just a Java IDE. But Eclipse is a plugin-based platform for creating (for example) IDEs. It is often shipped with the Java development tools, hence it offers a Java IDE out-of-the-box in those cases.
  • Does Eclipse support C++ development?
    Support for programming languages in Eclipse is realized via plugins. There are Eclipse plugins for all possible languages. The standard C++ Plugin for Eclipse is called CDT. It brings GDB based debugging, managed makefiles, simple refactoring and so much more to Eclipse. Trolltechs Qt Eclipse Integration is built on top of the CDT.
  • What does the Qt Eclipse Integration add to Eclipses C++?
    The Qt Eclipse Integration seamlessly integrates the whole Qt development workflow:

    • Pure qmake based project management (not imposing Eclipse specific project file formats) with a .pro file importer and graphical project editor
    • Embedded, well known UI Designer with its Form- Property- Signal/Slot- and Action editor
    • Wizards for creation of new Qt gui and console projects. Wizards for creation of new Qt classes.
    • Embedded Qt Resource editor
    • Integrated Qt reference, a Qt Eclipse tutorial and a “cheat sheet”
  • Which platforms are supported?
    The plugin runs on Windows and Linux x86. Debugging does not work on Windows x64, because GDB crashes, there. OSX will be supported in a later release.
  • What do I need in order to start?
    Download and install the following ingredients:

  • How do I start?
    Start Eclipse (on Windows, use the “Start Eclipse with MinGW” shortcut from the Start Menu). Follow the instructions of the Qt Eclipse Integration cheat sheet, which will guide you through the necessary steps.
  • Who will help me?
    Subscribe to the Qt preview mailing list and post your question and browse the archive. You will get polite and competent answers

New Qt Gui Application Wizard

Define the name of the project, the type of the first UI class and the required Qt modules.
New Qt Gui Application Wizard

Code editor with auto completion

Editing code can be easy and fun when the auto completion actually works and gives usable suggestions.
Code editor with auto completion

The Qt designer components, embedded into Eclipse

The seamlessly embedded Qt Designer reduces the creation of great UIs to a few clicks. No external Designer instance needs to be launched.
The Qt designer components, embedded into the Eclipse based IDE



© 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.