Some progress, at least

Progress with Krita has been slow, the past two weeks, considering that I’ve been at home nearly permanently. Still, I’ve been working on some things, and thinking about others.

There’s now an eraser tool, and a line tool, and I made a start porting the stamp tool. At least, I thought that it was a stamp tool, but it turns out it is a tool that paints with patterns instead of brushes, not something that takes the last selected bit of the image, and paints with that. Perhaps I’d better wait for Patrick Julien to checkin the odds and ends for selecting and pasting he says he has lying about, and make a start on a convolve tool.

I also ported (that’s to say, copy, paste, search & replace) a large number of less interesting composition operations to Krita from GraphicsMagick, after I was given the green light by Leonard Rosenthol about the licensing. The more interesting composition operations are harder to port, since they either work on a whole image at a time, instead of on regions, or they use a number of extra functions from GraphicsMagick that I don’t feel the urge to port, too.

A persistent pain in the neck with working on Krita (or C++, perhaps, I am not sure), is the hard-coded nature of everything. With Python I can define a number of classes, perhaps even dynamically, read a list of classnames in a Python list from a configuration file, iterate over the list and instantiate the classes — easy as pie. But that’s because in Python, classes are an object; in C++ classes are — I don’t know what, exactly, but not objects, and no fun either. Look at Python:

class A: pass 
class B: pass
class C: pass
class D: pass

l = []

for clsname in file("classes.cfg").read().split():
	l.append(eval(clsname))	
print l

Of course, this is a very simple-minded example, but image a situation where you have a large number of classes, say — for the sake of argument — composition operators, one class per op, and you have a smaller number of image types, and some comp. ops. are useful for all image types, others only for a few, and others again for only one. The GUI, of course, must show only the relevant composition ops in the various listboxes. And when I add one, I don’t want to have to go through all the code to add those.

But still, I’m prepared to do precisely that: hardcode the instances of the relevant ops in the correct places, Krita, however, currently doesn’t have anything like that. There is a long enumeration in kis_global.h; there are user-visible string somewhere else, and a big switch statement that uses the enum to switch between function calls.

Here, I should create a factory that creates all defined ops, and some kind of a database that ties together all functionality, preferably defined in a configuration file, but hardcoding will do for now. I’m not sure about naming; I need something that forms the basis of all these capabilities that are now described in enums, and inherit from there.

Likewise, KisPainter is big monolith that looks a lot like QPainter. It combines geometric functions with simple paint functions, but that’s unpleasant, because I would prefer to have one function for creating lines that I can feed not only brush types and things, but also paint operations: hard paint, soft paint, airbrush, convolve, erase — so, instead of:

void eraseCircle(Qpoint p1, Q_INT32 radius);
void eraseLine(QPoint p1, QPoint p2);
void eraseAt(QPoint p);

void eraseLine(Qpoint p1, Q_INT32 radius);
void paintLine(QPoint p1, QPoint p2):
void paintAt(QPoint p)

void convolveCircle(...

I’d like:

class PaintOp;
class erase;
class convolve;
class paint;

class KisPainter{
...
void line(const PaintOp & op, QPoint p1, QPoint p2);
void circle(const PaintOp & op, QPoint p1, Q{Point p2);

Etcetera… Add in a CompositeOp class hierarchy, and life will almost seem to be as sweet as Python makes possible again. Of course, there’s more… We already have a KisResource structure that handles brushes, patterns and other bits of artistic licentiousness that are read from disk; here we have a lot of code duplication, even though the process is fairly dynamic.

And I should finish that convolve tool.