Previously, calling `.right()` on a `Gfx::Rect` would return the last
column's coordinate still inside the rectangle, or `left + width - 1`.
This is called 'endpoint inclusive' and does not make a lot of sense for
`Gfx::Rect<float>` where a rectangle of width 5 at position (0, 0) would
return 4 as its right side. This same problem exists for `.bottom()`.
This changes `Gfx::Rect` to be endpoint exclusive, which gives us the
nice property that `width = right - left` and `height = bottom - top`.
It enables us to treat `Gfx::Rect<int>` and `Gfx::Rect<float>` exactly
the same.
All users of `Gfx::Rect` have been updated accordingly.
The "Resize Image" action will now scale layer such that
the corners of each layer maintain their position relative to the edge
of the canvas.
Previously, each layer was scaled to the same size of the canvas.
This class had slightly confusing semantics and the added weirdness
doesn't seem worth it just so we can say "." instead of "->" when
iterating over a vector of NNRPs.
This patch replaces NonnullRefPtrVector<T> with Vector<NNRP<T>>.
This makes undoing actions performed on layer masks work as
expected.
did_modify_bitmap() is now also called on redo, to ensure the layer
mask is displayed correctly.
The "Merge Active Layer Up" and "Merge Active Layer Down" actions now
work with layers of different sizes. These actions now expand the
bounding rect of the newly merged layer to contain all layers being
merged. Layers which are not visible are now ignored by these actions.
The "Flatten Image" and "Merge Visible" actions now work with layers
of different sizes. These actions now expand the bounding rect of the
newly merged layer to contain all layers being merged.
`Stream` will be qualified as `AK::Stream` until we remove the
`Core::Stream` namespace. `IODevice` now reuses the `SeekMode` that is
defined by `SeekableStream`, since defining its own would require us to
qualify it with `AK::SeekMode` everywhere.
We now propagate errors when using the {Layer,Image}::flip(),
{Layer,Image}::crop(), {Layer,Image}::rotate() and
{Layer,Image}::resize() functions.
We handle these errors by show an error DialogBox with the error's
message.
This removes 8 FIXMEs:))
Previously layers weren't compressed at all and the file size could go
up really fast in a project with multiple layers. By switching to PNG,
the situation is slightly better now.
Interestingly enough, this change won't break compatibility with old
files, as PixelPaint loads layers using ImageDecoder which will try
every codec possible. :^)
This is a first step towards handling PNG encoding failures instead of
just falling over and crashing the program.
This initial step will cause encode() to return an error if the final
ByteBuffer copy fails to allocate. There are more potential failures
that will be surfaced by subsequent commits.
Two FIXMEs were killed in the making of this patch. :^)
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
When cropping to content with a layer not positioned at 0,0 the moved
layers content disappeared and the layers position was not updated
according to the crop offset.
There's probably an easier/more efficient way, but for my testcase this
improves the behavior.
This command finds the smallest non-empty content bounding rect
by looking for the outermost non-transparent pixels in the image,
and then crops the image to that rect.
It's implemented in a pretty naive way, but it's a start. :^)
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.
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.
Error::from_string_literal now takes direct char const*s, while
Error::from_string_view does what Error::from_string_literal used to do:
taking StringViews. This change will remove the need to insert `sv`
after error strings when returning string literal errors once
StringView(char const*) is removed.
No functional changes.
ImageViewer and PixelPaint would crash when the ImageDecoderClient
returns a frame without a bitmap. This can happen with `.ico` files
with an unsupported BPP, for example.
-Layer now has methods for flip/rotate/crop, which are responsible
for handling the alpha mask.
-Fixed crash when the display image size is out of sync with
the content image size.
-Changed API for setting content and mask image in Layer. Now, both
must be set at the same time, and it can result in an error if
you provide mismatched dimensions.