How to render outlines in Qt?

I have seen some approaches how to paint tool outlines in KDE/Qt apps. We draw two types of outline in Krita:

* When you want to draw a line with line tool, you want to see the preview of the line. If you want to draw rectangle or ellipse or any shape in Krita, you also get the preview. Call this tool outline.

* When you paint with some brush in Krita, you need to see the position of the brush. You can have a cursor or the shape of the brush. That way you can see the preview of the brush borders. These shapes can be complicated. You can have brush shapes like big vector flower or something.

RasterOP_XOR

So far we used black lines for outlines in Krita2. It has big problem. You can’t see black line in black background, can you? So I wanted to resurrect XOR from Qt3 times in Krita. It has been also older regression. XOR has been removed, but it is somehow back. You can set QPainter to composite mode RasterOp_XOR. The disadvantage is that you can’t have anti-aliased lines with it. I solved this with CompositionMode_Exclusion. That one is similar to XOR. But that one does not work if you render on X11. You have to use QImage as buffer for your widget. So I added the QImage as buffer to our Arthur canvas (we also have OpenGL canvas, but we support both of them of course) and that way it worked.

Then thanks to C. Boemann showed me that it is not the solution. There are colors which make the outline invisible. When you use some colors as outline color(e.g. 128,255,128) and you have background RGB(127,127,127), the outline is invisible. This hidden problem is CompositeMode_Exclusion. But not in the RasterOp_XOR. That outline color (128,255,128) is not selected by random but by old bug report from Gimp. The selected color XORed to image is always contrast enough so it does not hide itself. So CompositeMode_Exclusion does not solve our problem, it just moves it away. We decided to use RasterOp_XOR so far. Outlines are not anti-aliased, but at least it does not hide itself. If you use OpenGL canvas in Krita, also XOR mode is used but lines are anti-aliased — we use OpenGL code for that. I wrote that piece of code through GSoC as you may remember..

We tried to paint outline 3px wide: semi-transparent black line 3px wide and white line 1px in between. That one may work but it looses some pixel precision in same use-cases. In a perfect world outline should be 1px wide — at least in pixel&image editing or painting app like Krita, Gimp..

What do you use to paint tool outline when you want pixel precision? And how do you paint outlines when the pixel precision is not important?Altering two colors looks usually too ugly :( At least for me..

The most nicer result I found is Inkscape. Inkscape uses some composition which makes it work on every color too. This was found in discussion what is Photoshop doing. When underlying pixel is bright enough, use dark color. If the underlying pixel is dark too much, use bright color? Maybe Inkscape uses also XOR with some color…I did not find out.
Write custom composite operation for Qt would be solution?

Zoom tool in Inkscape

This entry was posted in Design, KDE, Krita. Bookmark the permalink.

2 Responses to How to render outlines in Qt?

  1. purple-bobby says:

    When we did this rubber-banding in the 1980s, our graphics card only had 256 colour index into 24bit palette, we cycled the XOR colour (adding 1 to the index colour at about 50 times a second), which gave a kind of ghostly outline.

    Marching ants would probably overcome the problem.

    Ideally you would have a transparent/cursor layer on top of the other layers for all the guidelines, then you can quickly remove them.

    You need two (or more) strategies depending on the power of your hardware: with power and memory you can have a preview layer over the current image, then a guideline layer over the top. The guidelines give you a virtual setsquare to allow you to line up with objects on the current image.

    How do you implement “undo”, this may allow you to do drawing guidelines without XOR.

  2. Pingback: Week 28: Bug fixing « LukasT.mediablog.sk

Leave a Reply