Sunday, April 30, 2006

So what's up with KolourPaint in KDE4?

These last couple of weeks I've been trying to find a 1:1 mapping between the Qt3 graphics functions and the Qt4 ones. Later, I'll blog in the detail how to really port QPainter/QPixmap/QImage. The Qt4 porting guide is too scanty on important semantic changes.

In the meantime, KolourPaint in trunk/ has regressed a bit because of the KToolBar/KAction changes:



As you can see, the size hints for the Colour Box and Tool Box are not working and since those 6x6 tool icons are so hard to click, I had to manually add them to the main toolbar. I'll fix this stuff after I get the paint engine porting under control.

And apart from not working, KolourPaint is really slow (and blocks the X server) because of unneeded QPixmap <-> QImage transformations in the deprecated copyBlt() (my local changes have dropped copyBlt()) and calls to QPixmap::mask(). The latter has this rather amusing comment in qt-copy/src/gui/image/qpixmap_x11.cpp:


#ifndef QT_NO_XRENDER
if (data->picture && data->d == 32) {
// #### slow - there must be a better way
mask = QBitmap::fromImage(toImage().createAlphaMask());
} else
#endif


Well, at least it was amusing at 1am... See, QPixmap::mask() in Qt3 returned a pointer to a precomputed mask so it was real fast. In Qt4 however, it does X serverside magic and in the worst case (the above snippet of code for QPixmap's with alpha channels), it does 2 X server roundtrips plus computation. In fact, it takes 450ms for an 800x600 image on a 2.2Ghz processor. Simply unbearable.

But the good news is that most calls to QPixmap::mask() in KolourPaint are either for drawing on the mask (since QPainter3 would happily draw on the QPixmap but not update the mask; for Qt4, I will drop this code shortly) or determining whether the pixmap has a mask. For the latter, this Qt3 code:


if (pixmap.mask ())


should not be ported to:


if (!pixmap.mask ().isNull ())


contrary to a previous blog entry since QPixmap::mask() does expensive computation that we throw away anyway. Do this instead:


if (pixmap.hasAlpha ())


So in a couple of weeks, expect a commit that will make painting work. Also, the next time Trolltech and KDE make such sweeping changes to their APIs, they should feel free to send me a cheque :) I am simply spending far too much time porting 50 thousand lines of code (which feels like a "NOP" job) rather than writing new features or doing real work (uni).

An old joke is that if you don't understand what "deprecated method" means, you should update to Java 1.2 (or maybe it was 1.4?). Now, they can add Qt to that. I now have literally 500 "deprecated" warnings to go through. coolo, mueller and montel have been doing a lot of fixes though - thanks! But on the flip side, I'm duplicating some work (I don't commit often due to internet time limitations) and it means I have to review a lot of patches:


$ wc -l *.diff
36 521415.diff
859 528186.diff
492 530108-533650.diff
1000 535185-535614.diff
0 ALSO_REVIEW_CMAKE.diff
2387 total


Speaking of which, cmake works quite well. In fact, I'm going to remove the remaining Makefile.am's since compat/Makefile.am is already gone. cmake is faster than unsermake, which was faster than automake. cmake supports "make -t". Also, if you want to hack CXXFLAGS long after running "cmake", the file you want is kdegraphics-build/kolourpaint/CMakeFiles/kolourpaint.dir/flags.make.

Now, back to work!

No comments: