Skip to content

Add "continuous fill" (click and drag) capabilities to the fill tool

Deif Lou requested to merge deiflou/krita:deiflou/continuous_fill_tool into master

This MR adds "continuous fill" capabilities to the fill tool. "Continuous fill" is a name I just came up with and refers to the action of flood-filling several regions in one pointer press-move-release iteration (click and drag).

After the users first press the left button, two things can happen:

  • if the pointer stays within a radius of 4px and the users release the button, then a normal fill is performed. This is the same exact behavior as before, and doesn't use any masks or new code, it uses the same code as before. So, if the users just click (press/release), they shouln't notice any changes to the tool.

  • if the users move the pointer a distance greater or equal than 4px (in widget coordinates) then a continuous fill operation is started. In this mode, the path that the pointer makes is sampled (using some DDA line rasterization) using image coordinates. The points obtained from the path are used to perform several filling operations. Since flood filling is expensive and can produce bad effects if multiple fills are performed in the same region, we must return as early as possible from these filling operations. For that two checks are performed before the actual flood fill is started:

    • a mask with the already filled areas is mantained so we check if the pixel in the mask at the seed point is white. If it is, then we can return since the area was already filled in the current continuous fill operation.

    • the color of the pixel where the user first pressed is stored to be used as a reference. Then we check along the path if the pixel color under the pointer is the same as that reference color. If it is not then we can return. This allows to fill only regions that initially had the same color in the reference image.

I think this works fine both with colos and patterns, but I marked the MR as draft because I want to implement some feedback mechanism so the user can see what was filled. Basically I thought of two approaches:

  • Just paint a decoration path while the continuous fill is performed and then update the canvas when the button is released (mypaint uses this approach). It's the easiest approach.

  • Update the canvas every time a region is filled, within the same continuous fill operation (this is what csp does). The regions are already filled on the fly, as the users drag the pointer, but the canvas is only updated at the end (on the other hand, the layer thumbnail is refreshed with each fill). The code creates one KisProcessingApplicator for the continuous fill operation and then several FillProcessingVisitor are applied, one for each point to fill. I don't know if it is possible to update the canvas between each FillProcessingVisitor but I think this approach is better than the other.

Update: I was able to implement the intermediate updates, so the second point is how it works right now.

Update 2: Now there are two modes for the continuous fill:

  • Fill any regions: the regions under the pointer will be filled as the user drags if they weren't already, regardless of their color in the reference image.
    In this animation a series of classic fills (just click) are performed as well as some continuous fills using the "any region" continuous fill mode. Pointer press/release events are indicated by the red circle shown at the pointer position. Any fill inbetween the circle marks are part of a continuous (press + drag) fill operation.

  • Fill similar regions: only the regions that have the same color as the first point in the reference image will be filled if the user passes over them.
    In this animation a series of continuous fills are performed using the "similar regions" continuous fill mode. Pointer press/release events are indicated by the red circle shown at the pointer position. Any fill inbetween the circle marks are part of a continuous (press + drag) fill operation.

Formalities Checklist

  • I confirmed this builds.
  • I confirmed Krita ran and the relevant functions work.
  • I tested the relevant unit tests and can confirm they are not broken. (If not possible, don't hesitate to ask for help!)
  • I made sure my commits build individually and have good descriptions as per KDE guidelines.
  • I made sure my code conforms to the standards set in the HACKING file.
  • I can confirm the code is licensed and attributed appropriately, and that unattributed code is mine, as per KDE Licensing Policy.
Edited by Deif Lou

Merge request reports