Add gimp_tools_blink_lock_box() utility function, in a new
gimptools-utils.c file, which takes a GimpItem, and blinks the
GimpItemTreeView lock-box of the corresponding dockable. This can
be used to hint that the item's lock toggles are preventing it from
being edited.
In the paint tools, when the current paint mode is invalid, i.e.,
when it requires an alpha channel, but the the current drawable has
no alpha channel, or its alpha channel is locked, blink the paint-
mode box widget in the tool options, in addition to showing an
error message in the status bar, to hint at the source of the
error.
In the transform tools, when there is no item of the selected type
to transform, blink the move-type box widget in the tool options,
in addition to showing an error message in the status bar, to hint
at the source of the error.
In the move tool, when there is no item of the selected type to
move, blink the move-type box widget in the tool options, in
addition to showing an error message in the status bar, to hint at
the source of the error.
In the selection tools, when the selected operation is invalid,
i.e., when trying to subtract-from or intersect-with an empty
selection, blink the selection-mode box widget in the tool options,
in addition to showing an error message in the status bar, to hint
at the source of the error.
In gimp_tool_compass_update_angle(), use fuzzy comparisson when
determining whether to update the angle properties, to avoid
infinite recursion due to floating-point inaccuracies. In
partcicular, on x86, when using the x87 FPU rather than SSE, the
floating-point registers are 80-bit, while the properties are
stored as 64-bit, which can create small discrepancies between the
calculated angles and the stored values.
The code was too much spread out, in core and tool code, and also it was
made too specific to fill. I'll want to reuse this code at least in the
fuzzy select tool. This will avoid code duplication, and also make this
new process more self-contained and simpler to review later (the
algorithm also has a lot of settings and it is much cleaner to have them
as properties rather than passing these as parameters through many
functions).
The refactoring may not be finished; that's at least a first step.
We had many reports of tablets from various brands (Huion, Gaomon,
XP-Pen…) broken in the last release (though working fine when
downgrading to 2.10.6). Latest Huion drivers seem to fix the issue
(according to at least one report), but this is not the case for other
tablets.
Though unable to test myself, provided stderr logs indicate that we hit
the case when 2 devices with the same name are registered. Therefore
this commit is basically reverting commit 717c183a3e (though keeping and
completing the comments). I don't think there is an ultimate solution
here but with this regression, experience shows us there seem to be a
lot more breakage when overwriting the device with newer occurences (at
least on Windows). It is unclear though if commit 717c183a3e was also
supposed to fix another case actually encountered. If so, we will need
to get an even more advanced solution.
In GimpProjection's chunk renderer, when the chunk height changes
in the middle of a row, we need to merge the remainder of the
current render area back into the renderer's update region, and
refetch the remainder of the row as the new render area, so that we
don't miss any unrendered area, or re-render already-rendered area,
due to the change in chunk height. However, we should previously
fail to verify that the fetched area is, in fact, the remainder of
the current row, which could cause us to render the wrong area,
missing parts of the update region.
Fix this, by breaking up some of the chunk-renderer fucntions into
smaller sub-functions, and using those in order to explicitly set
the new render area to the remainder of the current row when the
chunk height changes. This also avoids erroneously merging the
unflushed update region of the projection into the renderer's
update region.
Actually, image grids are saved as parasites, so even though older
GIMP versions round their coordinates upon loading, they maintain
the fractional coordinates when re-saving the image, hence bumping
the XCF version is not really necessary.
This reverts commit 13119efda33a7aba323dc13e6a56207a15a9f000.
Fractional-coordinate support for image grids was added in commit
1572bccc9f, right before the
introduction of XCF version 10. While images with fractional grid
coordinates can be loaded with earilier versions of GIMP, the grid
coordinates are rounded to the nearest integer.
Bump the minimal XCF version when saving images with fractional
grid coordinates to 10, which should have been the case all along.
The NULL terminator of the tile-offset array of dummy buffer-levels
is erroneously written as an int32, instead of an offset, even in
version-11+ XCFs, in which offsets are 64-bit.
Since the dummy levels aren't actually used by GIMP, we're going to
keep these fields as int32 as an exception, in order to remain
consistent with existing XCFs, and just add a comment in the code,
and update the docs. If we ever make use of the higher buffer
levels, we should change these fields to offsets, and bump the XCF
version.
Add a boolean "direct" parameter to gimp_projection_flush_now(),
which specifies if the projection buffer should only be invalidated
(FALSE), or rendered directly (TRUE).
Pass TRUE when flushing the projection during painting, so that the
affected regions are rendered in a single step, instead of tile-by-
tile. We previously only invalidated the projection buffer, but
since we synchronously flush the display right after that, the
invalidated regions would still get rendered, albeit less
efficiently.
Likewise, pass TRUE when benchmarking the projection through the
debug action, and avoid flushing the display, to more accurately
measure the render time.
In gimp_drawable_edit_fill(), when filling/clearing the whole
drawable, without any special compositing (i.e., when there's no
selection, the opacity is 100%, and the layer mode is trivial),
fill/clear the drawable's buffer directly, without using an
applicator. This makes such operations much faster, especially in
big images.
... which is similar to gimp_fill_options_create_buffer(), however,
it fills an existing buffer, instead of creating a new buffer.
Implement gimp_fill_options_create_buffer() in terms of the new
function.
Add a TRIVIAL layer-mode flag, and corresponding
gimp_layer_mode_is_trivial() function, which indicates if the blend
function of a given layer mode is trivial, i.e., either never
modifies the source pixels (for non-subtractive modes), or always
clears the destination pixels (for subtractive modes).
... which clears the alpha component of a given buffer region,
i.e., it makes the region transparent, while preserving color
information. This corresponds to the "edit-clear" action.
In gimp_paint_core_finish(), when copying the relevant region of
the cached undo buffer into a new buffer, align the region to the
buffer's tile grid, so that all copied tiles are COWed. This
avoids lag when finishing a stroke.
When creating a drawable undo from the drawable's buffer, align the
copied rectangle to the buffer's tile grid, so that all the copied
tiles are COWed, saving memory and gaining speed.
Add applied_x and applied_y fields to GimpDrawableUndo, specifying
the position at which to apply the applied_buffer, so that we apply
it in the right place, even if the undo rect has changed due to
alignment.
In the Luminance layer-mode, use the scratch allocator for
allocating temporary buffers, instead of using VLAs.
GimpOperationLayerMode already allocates data on the stack,
calculated as not to overflow the stack on any platform, so having
any of its descendants also allocate big buffers on the stack is
risky.
gimp-scratch is a fast memory allocator (on the order of magnitude
of alloca()), suitable for small (up to a few megabytes), short-
lived (usually, bound to the current stack-frame) allocations.
Unlike alloca(), gimp-scratch doesn't use the stack, and is
therefore safer, and will also serve bigger requests, by falling-
back to malloc().
The allocator itself is very simple: We keep a per-thread stack of
cached memory blocks (allocated using the normal allocator). When
serving an allocation request, we simply pop the top block off the
stack, and return it. If the block is too small, we replace it with
a big-enough block. When the block is freed, we push it back to
the top of the stack (note that even though each thread uses a
separate stack, blocks can be migrated between threads, i.e.,
allocated on one thread, and freed on another thread, although this
is not really an intended usage pattern.) The idea is that the
stacks will ultimately stabalize to contain blocks that can serve
all the encountered allocation patterns, without needing to reisze
any of the blocks; as a consequence, the amount of scratch memory
allocated at any given time should really be kept to a minimum.
Use gimp_async_add_callback_for_object(), added in the previous
commit, instead of gimp_async_add_callback(), in cases where the
destructor of the object owning the async doesn't wait for the
async to finish. This avoids leaking such ongoing asyncs on
shutdown, during which gimp-parallel either finishes or aborts the
asyncs: if at this point an async has any registered callbacks, an
idle source is added for running the callbacks, extending the
lifetime of the async; however, since we're not getting back into
the main loop, the idle is never run, and the async (and any
associated resources) are never freed.
... which is similar to gimp_async_add_callback(), taking an
additional GObject argument. The object is kept alive for the
duration of the callback, and the callback is automatically removed
when the object is destroyed (if it hasn't been already called).
This is analogous to g_signal_connect_object(), compared to
g_signal_connect().
In gimp_async_remove_callback(), if removing the last callback
while the callback idle-source is already pending, cancel the idle
source and unref the async object (the async is reffed when adding
the idle source.)
There was a global 3x3 array of babl fishes used for converting between
blending and compositing pixel representations, these were all hard-coded to
operate within the sRGB babl-space family. This commit updates a per-instance
array during operation prepare instead, that comes preconfigured with fishes
derived from the correct space. Since the same operation instance might get
different space input during its life time we store and compare the cached
fishes with the current format (which is unique depending on space).
This should address the problem seen in issue #2592
Use gimp_tile_handler_validate_validate(), added in the commit
before last, in gimp:buffer-source-validate, in order to pre-render
the necessary region of the buffer, instead of performing the
validation implicitly by iterating over the region. This is both
simpler, and, more importantly, allows us to render the entire
region in a single chunk, instead of tile-by-tile, which can be
considerably more efficient, especially with high thread counts.
This essentially extends the dynamic sizing of rendered projection
chunks to layer groups, which are rendered through
gimp:buffer-source-validate, rather than just the main image
projection.