Lasso selection works by allowing the user to draw an arbitrary shape
much like the pen tool and ensuring the shape is closed by connecting
the start/end points when the user is done drawing. Everything inside
the shape becomes the selection.
Selection is determined via an outer flood fill. We begin a flood fill
from a point that is guaranteed to be outside of the drawn shape, and
anything the fill doesn't touch is determined to be the selection
region.
Previously, all keydown KeyEvents were accepted, causing parent widgets
not to receive them. With the addition of shortcut handling to keydown,
shortcuts were not called when the ImageEditor was focused.
This patch mitigates a rough gradient for the brush tool with a low
hardness. Previously the gradient alpha value was truncated by the type
conversion to int. Now the desired alpha value is scaled up to mitigate
the information loss due to type conversion which results in a much
smoother gradient.
This effectively creates a double-buffer for tools to use when modifying
the layer's bitmap (content or mask). Once the changes have been made
the tool reports to the layer that it has made changes along with a Rect
of the changed region. The layer will then merge the changes from the
scratch image to the real bitmap. This merge is done as follows: If a
given pixel is inside the selected region, the pixel from the scratch
bitmap is copied to the real bitmap. If the pixel is not inside the
selected region, the pixel from the real bitmap is copied to the scratch
bitmap.
As an optimization, when there is no selection active, the new method
for getting the scratch bitmap will return the real bitmap and no
merging will need to take place.
Polygonal selection tool allows for the drawing of any arbitrary
polygonal shape. It tracks clicked points in a vector, upon double
clicking we finalize the polygon and generate the selection mask. The
user can press the escape key during selection to cancel.
The mask is generated as follows:
- First we calculate the size of the bounding rect needed to hold the
polygon
- We add 2 pixels to height/width to allow us a 1 pixel border, the
polygon will be centered in this bitmap
- Draw the polygon into the bitmap via Gfx::Painter, making sure to
connect final polygon point to the first to ensure an enclosed shape
- Generate a selection mask the size of the bitmap, with all pixels
initially selected
- Perform a flood fill from (0,0) which is guaranteed to be outside the
polygon
- For every pixel reached by the flood fill, we clear the selected pixel
from the selection mask
- Finally we merge the selection mask like other selection tools.
Before this commit, when the wand select tool was used on a layer that
was moved, it would make the selection relative to the image, and not
relative to the layer. This commit fixes that issue.
Refactored PickerTool functionality to the ImageEditor level and added a
flag to Tool Base Class to allow for tools to override Alt+Click
ColorPicker functionality
This patch adds scaling function to the move tool.
When the cursor is over the lower right corner of the layer, it changes.
This is to signify that the layer can be scaled by dragging the mouse.
There is currently no preview of the scaling.
Doing a resize every time the mouse moves leads to unexpected behavior.
Wand Selection tool uses similar logic to the Bucket Tool. Flood filling
and threshold calculations to determine the affected area just in this
case we do not set the pixels of the selected area, instead we use
those pixels to alter the selection mask.
In the future we can probably abstract out the shared flood logic so
both tools can share the code.
Specializing point_position_to_preferred_cell for the
RectangleSelectTool as it selects a new cells with a rounding
behavior instead of a flooring behavior
This method is used to point a position at the preferred pixel of
the image. Certain tools may want to specify a different preferred
pixel for the same input position.
The Undo/Redo actions now tell you what kind of action will be
undone/redone. This is achieved by adding an "action text" field to the
ImageUndoCommand and having everyone who calls did_complete_action()
provide this text.
The non-AA outline ellipse was drawn outside the bounding rectangle
unlike all other ellipses. This commit now scales it to match the
size of the other ellipse drawing modes (AA, filled, etc).
Each of these strings would previously rely on StringView's char const*
constructor overload, which would call __builtin_strlen on the string.
Since we now have operator ""sv, we can replace these with much simpler
versions. This opens the door to being able to remove
StringView(char const*).
No functional changes.
This algorithm utilizes a modified scanline method that takes advantage
of the fact that if you are filling rows starting from the top left and
going right, you do not need to check pixels very often except in
certain cases such as at the beginning or end of a row.
There are some tests on top of this that ensure correct filling in all
other cases. This leads to much-improved speed compared to the
4-directional queue method, and no heap allocations.
This commit adds draw_ellipse() and moves the shared code
for circles and ellipses to draw_ellipse_part().
draw_ellipse_part() can draw an entire circle in one call using
8-way symmetry and an ellipse in two calls using 4-way symmetry.
This is in preparation to support masking of Layers. We now distinguish
between the "display_bitmap" which will be the whole Layer with every
effect applied and the "content_bitmap" which contains the actual
unmodified pixels in the Layer.
Now while dragging a new rectangular selection you can cancel it by
hitting Escape. Existing selections are cleared by Escape as well if the
RectangularSelectTool is active.