Footprint algorithms: in the stamp, or in the paintop?

Cyrille Berger cberger at cberger.net
Tue Mar 25 19:38:30 CET 2008


On Tuesday 25 March 2008, you wrote:
> Il Tuesday 25 March 2008 11:30:05 Cyrille Berger ha scritto:
> > That said, the priority for Krita 2.0 would be KisStampManipulator (with
> > a better name), all the rest can happen when we have, at last, make that
> > release.
>
> Well. This has a flaw, and I hope to very clear at explaining it.
> If we use KisStampManipulator, we are still relying on a certain paintop
> to "build up" the behavior of the stamp.
>
> Let me explain...
> Imagine: we will prepare a set of KisStampManipulator classes, each of them
> transforms the input stamp in something different, taking pressure, tilt,
> et cetera into account, at paintop discretion. We can imagine something
> like a chain of manipulators that the paintop can build up to obtain the
> final stamp.
>
> This way, the code that "builds up" the stamp is in a particular paintop:
> for example in KisBrushOp there will be the chain that builds a brush-like
> stamp.
>
> But what happens then? It happens that a particular chain is binded to a
> particular paintop. You want a brush stamp? You've to use KisBrushOp! You
> need a pencil stamp? You've to use KisPencilOp (or KisPenOp).
> But again, these paintops not only decide how the *stamp* will look like
> (size, shape, position, et cetera); they decide what to do with that stamp
> too (and, as everyone knows, they just "print" the stamp onto the canvas
> using the current color).
> So, with this infrastructure, KisPaintOp does *two* things:
> 1) Takes a certain stamp from KisStamp and applies to this stamp a chain of
> manipulations.
> 2) Decides what to do with this manipulated stamp.
>
> I think that these two operations needs to be separated. A certain class -
> indipendently from KisPaintOp - has to take and manipulate the stamp using
> current information and settings. Then the paintop has just to decide what
> to do with this ready-to-use stamp.
>
> To make the difference more evident, consider this simil-code:
>
> 1) This is how the code will look like with Cyrille's suggested structure:
>
> KisBrushOp::paintAt(information)
> {
>     stamp = currentStamp(information);
>     manipulatedStamp = applyBrushManipulationChain(information);
>
>     stampDevice->setColor(currentColor);
>     bitBlt(stampDevice to canvasDevice);
> }
>
> KisPenOp::paintAt(information)
> {
>     stampDevice = currentStamp(information);
>     manipulatedStamp = applyPenManipulationChain(information);
>
>     stampDevice->setColor(currentColor);
>     bitBlt(stampDevice to canvasDevice);
> }
>
> KisCloneOp::paintAt(information)
> {
>     stampDevice = currentStamp(information);
>     manipulatedStamp = ?????????? <---- You see, here, what will the
>                                   manipulated stamp? A Brush stamp?
>                                   a pencil stamp? And what will happen
>                                   when the number of different chains
>                                   will grow?
>
>     bitBlt(sourceDevice to stampDevice);
>     bitBlt(stampDevice to canvasDevice);
> }

Wrong, with my proposal it would be 

KisPenOp::paintAt(information)
{
    stampDevice = manipulation->createStamp(stampobject, information, 
currentColor); // yes currentColor need to be set at stamp creation
     bitBlt(stampDevice to canvasDevice);
}

KisCloneOp::paintAt(information)
{
    stampDevice = manipulation->createStamp(stampobject, information, 
sourceDevice); // again no need to copy the source device to the stamp device
     bitBlt(stampDevice to canvasDevice);
}

It could even be :

KisDrawingOp::paintAt(information)
{
    stampDevice = manipulation->createStamp(stampobject, information, 
colorSource); // again no need to copy the source device to the stamp device
     bitBlt(stampDevice to canvasDevice);     
}

No clone op, no filter op, no brush op, no pencil op. Brush op and pencil op 
are replaced by a KisBrushStamp and KisPencilStamp (like in your proposal), 
clone, filter and plain color happen in the color source.

Then dynamic brush can be either implemented as a paint op (like done 
currently)

KisDynamicOp::paintAt(information)
{
  stampDevice = stamp->createStamp( size => sensor1, rotation => 
sensor2, ... , colorInformation );
  bitBlt( stampDevice to canvasDevice);
}

Or directly builting by extending the manipulation class.

> 2) This is how the code will look like with my idea:
>
> KisBrushStamp::createStamp(information)
> {
>     return brushManipulationChainStamp(information);
> }
>
> KisPencilStamp::createStamp(information)
> {
>     return pencilManipulationChainStamp(information);
> }
>
> ...
> ...
> resources::currentStamp = registry->stamp("brushstamp"); <--- call done,
> for example, througth a nice UI. ...
> ...
>
> KisDrawingOp::paintAt(information)
> {
>     stampDevice = currentStamp->createStamp(information); <--- currentStamp
>                                           builds directly a complete stamp!
>
>     stampDevice->setColor(currentColor);  <--- this can even done directly
> in create Stamp!
>
>     bitBlt(stampDevice to canvasDevice);
> }
>
> KisCloneOp::paintAt(information)
> {
>     stampDevice = currentStamp->createStamp(information); <--- currentStamp
>                                           builds directly a complete stamp!
>
>     bitBlt(sourceDevice to stampDevice);
>     bitBlt(stampDevice to canvasDevice);
> }

In fact what you want is a function in the stamp that will call the 
manipulator ? Instead of having the manipulator called with the stamp object. 
It's not really a problem if there is only one kind of manipulator, but if 
you want to have different type of manipulator, then it becomes a problem, or 
else you recreate an instance of the brush each time the manipulator change.

For me stamp are ressource. While manipulators are algorithms. That's why I 
prefer to see them separated, we have allways done this in Krita : algorithms 
(filter, pigment's color transformation, KisPainter, KisStampManipulator) 
takes ressources as input (KisPaintDevice, raw channels, KisStamp ).

> PS: by the way this integrates perfectly with boud new code.
So does the current code...

-- 
Cyrille Berger


More information about the kimageshop mailing list