Tuesday, November 27, 2012

Krita Sketch is: Rounded

A quick recap of the main topic: My employer, KO GmbH, has been working on a touch version of Krita, called Krita Sketch, over the last few months, and is gearing up towards a first release. So, i'm doing a bit of writing, talking about some of the work i've been doing as a part of this project.


There are two things in Krita Sketch which are rounded, and i will be covering the first of these in this entry. The first is the simple rounded corners in various places around the application, which are done in three ways (that i will get back to in a moment), and the other is the colour selector, which is an entirely different matter. That one will be covered in the next entry.

So, rounded corners in QML, how do you do that? Well, in reality it really is quite simple, but i thought i would spend a little while talking about it anyway. In addition to just using a set of Images manually, lining them op as appropriate (which we did in a lot of places), you have two options when making them, depending on precisely what you are trying to do.

Pure QML painting

The first option is to use the radius option on a Rectangle item. A very simple approach, which does however come with one caveat, which is not the radius itself, but rather a problem of how borders work in Qt in general (it will also be known to people who work with WebKit, which behaves in the same way). Shortly, borders are painted on the centre of the element's edge, rather than on either side of it. If you are aware of this, it is easy enough to work with, but you must be aware of the behaviour for it all to make sense.

Using the radius property means that all four corners on the element will be rounded a number of pixels equal to that radius. Easy to work with. Except in the case where you only want some of your corners to be rounded. We have not used this trick in Krita Sketch, but it's a useful trick to know: Use the Item item's clipping property, fill it with your rounded-cornered Rectangle, and make that Rectangle larger than the Item by way of adding negative margins in the appropriate places. For example, the following code will give you a blue rectangle with the two top corners rounded:

BlueRectangle.qml:


import QtQuick 1.0
Item {
    Item {
        width: 50;
        height: 50;
        anchors.centerIn: parent;
        clip: true;
        Rectangle {
            anchors {
                fill: parent;
                bottomMargin: -radius;
            }
            radius: 10;
            color: "blue";
        }
    }
}


A total hack? Yes, absolutely. But it works a treat :)

The BorderImage Compoment

The solution we should have used in Krita Sketch in the majority of cases was the BorderImage component. A very simple but extremely powerful component, which shortly takes an image, cuts it into nine slices according to what's set in your border property, and arranges those slices according to your desire (scaling and tiling according to the settings you choose). The documentation for this component is extensive and well written, so i won't talk about this other than saying it is very powerful.

An important thing, however, is to make sure that you know it exists. It is a non-obvious thing to have available, and if you do not know it's there you'll find yourself reinventing a lot of things and doing a lot of manual cutting which, on mobile devices in particular, means that you are using more texture space than you should. In our case this is not any serious cost (we have a LOT of images in memory already, and not using this component does not seriously impact on this), but if you are targeting mobile devices, in particular the smaller variety (smartphones), make sure you're not reinventing the wheel here.


The word of the day is: Squircle

Labels: , ,

9 Comments:

Blogger Teemu Erkkola said...

Clipping is slow. Couldn't you just use something like this?

import QtQuick 1.1;

Item {
width: 400
height: 400

Rectangle {
id: rounder
color: "blue"
z: rect.z - 1
radius: 10
height: radius * 2
width: rect.width
anchors.verticalCenter: rect.top
anchors.horizontalCenter: rect.horizontalCenter
}

Rectangle {
id: rect
anchors.centerIn: parent
width: 100
height: 100
color: "red"
}
}

27 November 2012 at 18:41  
Blogger leinir said...

You know, that's actually a good idea, yes :) Obvious solution is obvious, thanks for that :)

27 November 2012 at 21:16  
Blogger sebas said...

" make sure you're not reinventing the wheel here."

So why not use Plasma's QML components? The kind of low-level issues you're writing about to me sound that you're solving the wrong (class of) problems, you're writing a widget set. Using the QML components means that you use a well-designed API, get easy to replace components, save yourself a lot of work, get SVG theming, touch-friendliness and a whole lot of other cool stuff for free. On top of that, you save yourself a lot of work and can tap into maintainance work done by a whole group on these widgets.

See http://api.kde.org/4.x-api/plasma-qml-apidocs/ for the QML components API, there's a widgetgallery in kdeexamples/plasma/declarative, and you can find many more useful components for problems you might run into at http://techbase.kde.org/Development/Tutorials/Plasma/QML/API

28 November 2012 at 07:19  
Blogger Dennis Nienhüser said...

What sebas said. Using Qt Components will also make sure that a sane font size is used by default in buttons.

28 November 2012 at 12:15  
Blogger Unknown said...

@Sebas & Dennis:

Since I'm partly responsible for that decision, I guess I should answer.

There are a few reasons that come to mind on why we did not use Plasma components:

First, I started working on this project something like 5 or 6 months ago. Plasma components were no where near as mature back then as they are now. Arguably, creating your own components does not guarantee any stability, but any bugs are purely your own.

Second, our target platform is Windows 8. I personally do not know the state of window support for the Plasma components, but seeing as that they are fairly new, they likely would need porting. Related to this is also that it means we would depend on libplasma for the UI, which adds a pretty large dependency chain to a package where we are already really hard trying to reduce dependencies and size.

Another thing that comes to mind is that a lot of this has evolved during development and there really was not that much time spent on creating these components as it seems. To be honest, I think we would have spent more time on porting, learning how to theme and fixing bugs than we have spent now on the actual development of these components. In a project where we were already pressed for time soon after we began, needing more time for those kinds of "unrelated" things is not something you can really afford.

Now, this might not be super-water-tight reasoning or anything, but then again, the question is a bit of an "in hindsight" issue. Plasma's component set is quickly maturing to a proper usable set of components. For a new project, I'd be harder pressed to not use them, especially if individual theming is possible.

- ahiemstra

7 December 2012 at 13:31  
Blogger sebas said...

You're trading a one-time effort (which you admit you have not even looked into) for creating your own widget set.

That does indeed sound short-sighted to me.

On top of that, it's sad since you rather invest time into reinventing the wheel (come one, clipping on a widget with rounded corners in 2012?), rather than piggy-backing on the efforts of the rest of the community.

I can't speak about Windows8, but libplasma on Windows was working at some point. The X11 dependencies are rather minimal (and ifdef'ed away in most cases), so I don't expect the effort to be that much work, especially for the gains of your project and the entire community's.

On top of that, the usefulness of Krita sketch on non-Windows8 platforms is severely reduced. Work to port the whole thing to Plasma Components will need to be redone.

Sorry to say, but I'm quite disappointed.

9 December 2012 at 17:04  
Blogger sebas said...

By the way, I suppose Krita already depends on kdelilbs, that also includes libplasma. How does this even work?

9 December 2012 at 17:05  
Blogger Notmart said...

"Second, our target platform is Windows 8. I personally do not know the state of window support for the Plasma components"

plasma builds on windows since kde 4.1 days.
the components do depend from libplasma for painting and theming, but should work just fine on windows.

I do get that it may be a big dependency, would be cool tough if it would be at least tried, if not working, at least a compatible components api should be used, to be possible to actually have the application well integrated on Linux systems.

That is an application i would love to have in active, but the current look is really too much alien...

9 December 2012 at 17:21  
Blogger Unknown said...

The application wasn't written for Active -- it was written for Windows 8. Everyone is free, of course, to fork it, it's still GPLv2+ (which makes Krita Sketch unique already).

The big problem I currently have isn't that we had to reinvent the wheel -- at least this way we got the GUI elements pretty much completely right for our application, and I daresay that the overlap of what we need and what other component libraries provides is pretty small anyway, but that the download is still way too. No non-essential dependency needs to apply!

Right now, the KDE we use is already cut down to the minimum, there are no daemons (dbus, kded) running, large chunks of kdelibs have been chopped off (kde:clones/kdelibs/rempt/kdelibs-stripped.git).

And I intend to strip the download down way more, and use the same procedure for the regular windows version of Krita.

14 December 2012 at 15:27  

Post a Comment

<< Home