Introduction
This is a proposal to improve the Krita brush stroke preview system. It primarily affects the ‘Clone Brush’-workflow, a combination of using the brush tools and the Duplicate PaintOp (KisDuplicateOp). Additionally, other combinations of tools and paintops could possibly benefit from an improved preview system.
Current workflow
Currently the Krita brush preview system displays a polygonal QPainterPath following the outline set by the currently selected PaintOp. Although this works fine for most brush tool / paintop combinations, while using KisDuplicateOp in combination with KisToolBrush, the placement of the brush is rather inaccurate, as is illustrated here:
Improved workflow
To improve the workflow, instead of drawing an outline for the active paintop, Krita could show a bitmap representation of the stroke as the paintop will paint if the stroke would be applied, as is shown here:
With this preview system, the stroke can be interactively adjusted to align, even before the application of the stroke has started. This will result in a much better alignment of the stroke and therefore in a much more versatile clone tool as is shown here:
Proof of concept
A proof-of-concept was coded to proof the feasibility of preview functionality. This turned out to work well in terms of usability as well as performance. A video of the new functionality was uploaded to Youtube: link
Scope
The suggestion to improve the outline preview system was initially inspired by the shortcomings of the current ‘Clone Brush’-workflow. However, an improved preview system could potentially improve other Tool / PaintOp workflows as well.
For example, brush and shape tools could show the stroke (or dab) to be applied in advance, providing both better alignment as well as a more accurate representation of the end result, including the colors to be applied by the currently selected PaintOp.
Lastly, a more refined, for example anti-aliased, outline could be combined with the new preview system, improving over the current -sometimes harsh- xor-ed outline and resulting in a more pleasant painting experience while working with Krita.
Implementation
At first I have tried to put all extra functionality in a separate plugin, so the code would be independent of Krita. Since I could not link to KisToolBrush in kritadefaulttools (since that is a plugin as well), I had to copy all of KisToolBrush to a new copied class, which is no good imo. Therefore, the preview cannot be implemented without touching the rest of Krita.
Separate Tool?
For the proof-of-concept, I have added a 'Clone Stamp Tool' to differentiate from the original Freehand Brush Tool, and keep the latter available for comparison purposes. A separate tool could be implemented to isolate the 'Clone Brush Workflow'. That would however contradict the design of the Krita tool system in which a combination of a Tool and a PaintOp defines the workflow.
Some combinations of Tools and PaintOps do not make sense, and no mechanism to exclude such combinations exists in Krita afaik.
Krita has a docker for 'Tool Options' but not for 'Brush Options', so a separate Tool would have the advantage of showing specific options in its 'Tool Options'.
Preview code
To enable the proof-of-concept preview code, KisOpenGLCanvas2 was modified to provide a paintToolPreview function in addition to paintToolOutline.
Custom vertex- and fragment shaders are loaded to draw the preview before the stroke starts. The preview is hidden while drawing or when setting a new source point. The size of the preview is hard coded for now, but can be variable. The shaders are used to fade out the opacity from the center.
Other Tools
The new preview functionality could be implemented exclusively for the Clone Brush PaintOp, but it could also be implemented universally, so other Tools can benefit from it as well. For example, It could show an actual representation of a Freehand Brush before starting the stroke.
I think it would be awesome if PaintOps could override the default preview code (currently in KisOpenGLCanvas2::paintToolOutline. I am aware that this could possibly conflict because it would put UI-code into a PaintOp, however the Clone Brush-workflow dictates the need for such functionality imo.
To Do
Further development of the Clone Brush Preview would require taking the following steps first:
- Decide if a Clone Stamp Tool should be a separate tool.
- Decide if the preview functionality will be specific to Clone Brush PaintOp or a universal system overriding preview code in a PaintOp.