In the applicator path of gimp_paint_core_replace(), actually use
the paint-core's applicator, instead of using
gimp_drawable_replace_buffer(). This improves speed, consolidates
code, and fixes some cases in which the latter is broken.
Furthermore, when using CONSTANT paint application-mode, use the
paint-core's undo_buffer as the compositing source, rather than the
drawable buffer, which is the correct behavior.
(cherry picked from commit 3451ffb62c)
In the applicator path of gimp_paint_core_paste(), use the paint
mask directly when combining it to the canvas buffer, rather than
using a copy of it, since it's not being modified.
Fix some comments.
(cherry picked from commit ba6713bbe1)
Implement the no-applicator path of gimp_paint_core_replace() in
terms of gimp_paint_core_loops_process(), using the algorithms
added in the previous commit, instead of using
gimp_drawable_replace_buffer(). This improves speed, consolidates
code, and fixes some cases in which the latter is broken.
Furthermore, when using CONSTANT paint application-mode, use the
paint-core's undo_buffer as the compositing source, rather than the
drawable buffer, which is the correct behavior.
(cherry picked from commit ddb69b77a7)
In gimppaintcore-loops, add CANVAS_BUFFER_TO_COMP_MASK and
PAINT_MASK_TO_COMP_MASK paint algorithms, which copy the canvas
buffer and the paint mask, respectively, to the compositing mask.
When there is an image mask buffer, the algorithms additionally
combine the copied mask with the mask buffer. When possible, the
algorithms use the canvas buffer/paint mask data directly as the
compositing mask data, instead of copying.
These algorithms are necessary in order to implement
gimp_paint_core_replace() in terms of
gimp_paint_core_loops_process(), which is done by the next commit.
(cherry picked from commit 183a55613e)
In gimppaintcore-loops, in the DO_LAYER_BLEND paint algorithm, and
in the CanvasBufferIterator algorithm helper-class, initialize the
iterator *before* initializing the base class, to make sure that
dest_buffer, or canvas_buffer, respectively and in that order, is
the primary buffer of the iterator. In particular, this avoids the
mask buffer being the primary buffer. This is desirable, since
most of the buffers we iterate over are tile-aligned to the dest/
canvas buffers.
(cherry picked from commit f9c072c328)
In gimppaintcore-loops, add a MaskBufferIterator algorithm helper-
class, which provides read-only iterator access to the mask buffer,
if one is used.
Use the new class in DoLayerBlend, instead of manually managing the
mask-buffer iterator.
(cherry picked from commit 44281ce2c4)
In gimppaintcore-loops, add a CompMask algorithm helper-class,
which provides access to the mask buffer used for compositing, to
be used by the DO_LAYER_BLEND algorithm instead of the image mask
buffer.
CompMask itself doesn't provide the storage for the mask; this is
rather the responsibility of the algorithms that use it. The
TempCompMask algorithm helper-class provides temporary storage for
the compositing mask, and can be used by algorithms that need a
temporary mask.
(cherry picked from commit e36847febb)
In gimppaintcore-loops, make the algorithm names, and the names of
the corresponding functions, more consistent.
(cherry picked from commit d23e239fed)
In gimppaintcore-loops, add finalize() and finalize_step()
algorithm functions, which get called at the end of processing the
entire area, and at the end of processing each chunk, respectively.
Algorithms can use these functions to clean up allocated resources.
(cherry picked from commit 4d2ce15400)
In gimppaintcore-loops, make the CanvasBufferIterator algorithm
helper-class self-contained, not having to rely on AlgorithmBase.
(cherry picked from commit 0d1f724112)
In the various gimppaintcore-loops algorithms, assign each
algorithm's iterator indices dynamically, rather than statically,
so that algorithms have more freedom in the way they initialize the
iterator.
(cherry picked from commit 9d1d21e716)
Add GimpData::save() implementation to GimpPattern, and change some
glue code to make patterns editable.
Also implement GimpData::duplicate() in GimpPatternClipboard, which
makes it possible to simply copy an area and duplicate the clipboard
pattern to create a new persistent pattern.
(cherry picked from commit e93fd73fac)
We currently have brush and pattern I/O code in both the core and
plug-ins. This commit starts removing plug-in code in favor of having
one copy of the code in the core, much like XCF loading and saving is
implemented.
Add app/file-data/ module with file procedure registering code, for
now just with an implementation of file-gbr-load.
Remove the file-gbr-load code from the file-gbr plug-in.
(cherry picked from commit a4e77e57f6)
gimp_brush_load_brush(): support legacy gpb brushes, and port a check
for gsize overflow what was added to the plug-in.
(cherry picked from commit 619f999280)
Again some missing context when requesting the strings (while they were
declared with context in static NC_()).
Also some mixup with some zoom actions strings declared with different
context in the same GimpEnumActionEntry.
(cherry picked from commit 6c5b6c6135)
The line art imaginary segments/splines are not added when they create
too small zones, unless when these are just too small ("unsignificant").
Why the original algorithm keeps such micro-zones is because there may
be such zones created when several splines or segments are leaving from
a same key point (and we don't necessarily won't to forbid this). Also
we had cases when using very spiky brushes (for the line art) would
create many zones, and such micro-zones would appear just too often
(whereas with very smooth lines, they are much rarer, if not totally
absent most of the time).
Also it is to be noted that the original paper would call these
"unsignificant" indeed, but these are definitely significant for the
artists. Therefore having to "fix" the filling afterwards (with a brush
for instance) kind of defeat the whole purpose of this tool.
I already had code which would special-case (fill) 1-pixel zones in the
end, but bigger micro zones could appear (up to 4 pixels in the current
code, but this could change). Also I don't want to use the "Remove
Holes" (gimp:flood) operation as I want to make sure I remove only
micro-holes created by the line art closure code (not micro-holes from
original line arts in particular).
This code takes care of this issue by filling the micro-holes with
imaginary line art pixels, which may later be potentially bucket filled
when water-filling the line art.
(cherry picked from commit 72092fbdbc)
Plug-ins are not prepared to handle high-precision brushes/
patterns, even when they're otherwise aware of high-precision
drawables, so make sure to always use compat formats when
communicating brush/pattern data to plug-ins.
Allowing plug-ins to handle high-precision brush/pattern data would
require some additional API.
(cherry picked from commit 82c449496e)
Older --enable-binreloc configure option had basically the same purpose
as the newer --enable-relocatable-bundle, though the old binreloc was
only used for gimpenv.c code.
As a consequence, commit 10ce702188 was still not working fine since
gimp_installation_directory_file() also need binreloc enabled (to be
actually relocatable).
Let's get rid of this whole mess, by implying we want binreloc code to
be used when --enable-relocatable-bundle is ON. We don't need the
m4macros anymore, since AM_BINRELOC was basically just checking that
`/proc/self/maps` was present. But anyway being present at compile time
does not mean it will be at runtime (nor the opposite). So this test is
not that useful. The binreloc code will anyway fallback gracefully to
the non-binreloc code (i.e. trying to use build-time install paths) if
the procfs is lacking at runtime.
(cherry picked from commit 4d84c1d7ee)
Avoid unnecessary calls to gimp_temp_buf_data_clear() in various
places, where either the entire buffer is being written to, or most
of it is, only requiring clearing the edges.
(cherry picked from commit 9d19e804ed)
Promote the precision of generated brushes to 32-bit float, and
modify brush preview generation, and gimpbrushcore-loops, to handle
float brushes. This avoids posterization in large brushes.
Note that non-generated brushes are still uint8.
(cherry picked from commit 8ef1113dee)
In GimpTempBuf, add gimp_temp_buf_lock() and gimp_temp_buf_unlock()
functions, which lock/unlock the buffer for data access. Unlike
gimp_temp_buf_get_data(), which returns a direct pointer to the
buffer's data, the new functions take a format parameter and may
return a temporary buffer, allowing the buffer to be accessed using
an arbitrary format.
(cherry picked from commit 12dde445c4)
Add a GimpTransformGridTool::matrix_to_info() virtual function,
which should extract the tool-specific transformation parameters
given a transformation matrix, and the old parameter set (which is
needed in some tools, to derive the parameters that aren't encoded
in the matrix, such as the pivot point). The transformation matrix
can be any combination of matrices calculated by the tool, and
their inverses. Subclasses should only implement this function if
every such matrix can be mapped back to transformation parameters.
This is currently the case for all the transform-grid tools, except
for the shear tool (since it only supports shearing along one of
the horizontal or the vertical directions, however, the combined
matrix may require shearing in both directions).
When a transform-grid tool implements this function, show a chain-
button between the two transform-direction radio-buttons in the
tool options. When the chain-button is linked, whenever the
transform corresponding to the active direction is modified, adjust
the transform corresponding to the non-active direction such that
the overall transform remains the same.
One notable workflow that this enables is transforming a layer
while adjusting a different area than its boundary, by first
defining the area while the transform-directions are linked, and
then transforming the area while the transform-directions are
unlinked.
(cherry picked from commit 39e23267f7)
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
(cherry picked from commit de8e81f81f)
Add an undo_desc field to GimpTransformToolClass, which subclasses
should set to the tool's default undo description. Provide a
default implementation for the get_undo_desc() vfunc, which returns
(a copy of) undo_desc. This simplifies transform tools that have a
static undo descrption, as well as provides a fallback when a
detailed undo description can't be generated (not currently
relevant, but will be used in the next commit).
(cherry picked from commit d549440650)
When rotating an item around its center using the rotate tool,
i.e., if the pivot point hasn't been moved, don't include the pivot
coordinates in the undo description.
(cherry picked from commit 44c8a1f274)
In GimpToolCompass, add a read-only "effective-orientation"
property, which returns the actual orientation of the compass; in
particular, if the "orientation" property is set to AUTO,
"effective-orientation" returns HORIZONTAL or VERTICAL, depending
on the current compass direction. In 3-point mode, the property
always returns AUTO.
(cherry picked from commit 40c0913178)
In GimpMeasureTool, don't try to access the "straighten" button
when halting the tool if it's NULL, which can happen when the
measure tool is selected upon startup, but is changed before its
tool-options GUI is constructed.
(cherry picked from commit 7fc5698f32)
In gimp_transform_matrix_generic(), apply the resulting matrix even
if the transformation is invalid, since GimpGenericTransformTool
relies on the matrix to properly update the transform-grid widget.
(cherry picked from commit 59ef222c7f)
In GimpTransformGridTool, when the "show-preview" tool-option
changes, don't take the transform validity into account when
deciding whether to hide the current layer -- it should only affect
the visibility of the preview, not the layer.
(cherry picked from commit 7ed512040e)
...1920*1980 resolution
In GimpOperationTool, make the generated GUI scrollable if it is
higher than half the monitor's workarea. This is meant as a last
resort for generated GUIs that do not have a custom constructor that
makes them usable using better layouts.
(cherry picked from commit b85d7c2334)
gimplanguagestore-parser.c (parse_iso_codes): instead of
special-casing Windows and OS X, use ENABLE_RELOCATABLE_RESOURCES and
find the package relative to ${gimp_installation_directory}, so
relocating it works on all platforms (also flatpack, snap, whatever),
given the --enable-relocatable-bundle configure switch is used.
(cherry picked from commit 10ce702188)
When initializaing the perspective-clone tool in paint mode, the
GimpDrawTool may already be active, causing the call to
gimp_draw_tool_start() to fail with a CRITICAL. Stop the draw tool
first, if active, to avoid that.
(cherry picked from commit 07d2d5af5a)
In GimpPerspectiveCloneTool, use PIXEL_CENTER cursor precision
while setting the source, and place the source-position handle at
the center of the selected pixel, rather than at its top-left
corner.
Additionally, disable the paint tool while adjusting the
perspective, so that the brush outline isn't shown, and the cursor
precision remains SUBPIXEL, even if the hard-edge option is
toggled.
(cherry picked from commit e5c9314a88)
... which can use to enable/disable certain aspects of
GimpPaintTool (in particular, brush-outline drawing). Should be
used by subclasses, to temporarily disable the paint tool while in
a non-paint mode (currently, this is only needed by the
perspective-clone tool; see next commit.)
(cherry picked from commit 05dd5029ee)
In GimpCloneTool, set the cursor precision to PIXEL_CENTER while
setting a source, and have GimpBrushTool snap the brush outline to
pixel centers.
(cherry picked from commit ef2818231f)
Fix the cursor precision of the cage-transform, foreground-select,
n-point deformation, and warp-transform tools.
(cherry picked from commit 158705e4ef)
gimp_plug_in_handle_proc_install(): print the procedure name when
bailing out of a wrong proc install call. For an obsolete full-path
menu label, also print the label. Original patch by Liam Quin.
(cherry picked from commit 07e3c1c15b)
In libgimp, add a note to gimp_install_procedure() stating that
passing a full menu path as "menu_label" is deprecated.
... tools' brush options.
After discussions, it turned out that many people disliked that the spin
scale for brush size (and some other options) get you fractional values.
How often do you actually need to get a 4.32 pixel-size brush? And even
how meaningful is it? On the other hand, you usually want a 4 or a 5
pixel size brush and it's nearly impossible to get (exactly) by dragging
the scale widget.
It is so annoying that some even resort to edit the value with keyboard!
So I am adding an optional "constrain" feature to GimpSpinScale. It will
still be possible to get fractional values when constraining is on, for
instance with keyboard edit (the arrow incrementation also will keep any
fractional part). So the interaction for such scales is simply reversed
so that you get integers easily, and fractional parts with a bit more
effort.
It is not turned on by default (some feature actually need precision and
we don't want to break the sliders for these) and for the time being, I
only applied it to all the brush settings in paint tools. Now that it
exist, we may want to apply this to more scales in various parts of
GIMP.
(cherry picked from commit bff3903f37)
In gimp:gradient, when using adaptive supersampling, render the
gradient tile-by-tile, using an iterator, instead of row-by-row.
This significantly improves performance, while also avoiding the
assumption that gimp_adaptive_supersample_area() works row-by-row.
Additionally, when not using supersampling, use a single GRand
instance, since the separation to distinct seed and per-tile
instances, which was a threading optimization (commit
7f39e41254), is no longer needed.
(cherry picked from commit 2cd7938f02)
When a fill zone was a bit too segmented, you'd want to just stroke
across it. But it was leaving some pieces uncolored, even though the
pointer dragged through it! The exact motion mode allows more events.
Note: I don't set it in the similar color filling (where it could have
been useful too) mostly because it is harder to remove events then (even
if a point was already filled, it could still serve as a seed for more
filling if threshold > 0), thus implied too much processing. Anyway in
all my tests, it was more a problem for line art filling anyway.
(cherry picked from commit 9c13058d54)
In GimpToolRectangle, fix the type of the cornder_radius field, so
that non-integer radii are properly displayed.
In GimpRectangleSelectOptions and GimpToolRectangle, increase the
maximal corner radius.
(cherry picked from commit a472696012)
We were doing it all the wrong way, fixing one combo box object at a
time. So this commit basically reverses commits 68a33ab5bd, 6dfca83c2a
and a9a979b2d0 and instead runs the same code in the class code. This
way, all objects based on these base classes will have the fix from
scratch.
These improved various other drop-down lists (I found some of them, and
probably not all) as I fixed all GIMP custom widgets based on
GtkComboBox.
Note that it has to be run after filling the list apparently (I had the
problem especially with GimpIntComboBox if running in the _init() code,
then the list widget showed wrong).
(cherry picked from commit 1d984542e9)
gimp_heal_motion(): when sample merged is active, simply initialize
the paint buffer from the projection instead of the drawable.
(cherry picked from commit e269a837cd)
When clearing a channel, do nothing if the channel is already
empty; otherwise, align the cleared rectangle to the channel
buffer's tile grid, so that all affected tiles are dropped, rather
than zeroed. Furthermore, only update the affected region of the
channel.
(cherry picked from commit ac5e4f4c33)
In commit c71b4916af, I forgot to disconnect signals on the bucket fill
options at finalization, leading the software to crash on an
non-existing tool.
(cherry picked from commit 0a952a3429)
After discussion with Sébastien Fourey and David Tschumperlé, it was
decided that a better fix for the edge case raised in #2785 was to add a
keypoint anyway, even if the point and none of its neigbours have a
positive smoothed curvature, yet they have a positive raw curvature. In
such case, we use the local maximum raw curvature instead of the local
maximum smoothed curvature.
(cherry picked from commit aa04258620)
Additionally to sample merge and active layer, now we can only use the
layer above or below the active layer as line art source.
The line art fill is meant to work on drawing lines. Though sample merge
still is ok in many cases, the more you fill with colors, the more the
line art computation becomes unecessarily complex. Also when you use a
lot of layers with some of them already filled with colors, it makes it
impossible to colorize some line art zones with the tool. Moreover you
just don't want to have to hide every layers out there to colorize one
layer (especially background layers and such as you may want to see the
result with your background).
Thus we want to be able to set the source as a unique layer, while it
not being necessarily the active one (because you want lines and colors
on different layers). In this case, I am assuming that the color and the
line layers are next to each other (most common organization).
(cherry picked from commit c71b4916af)
In gimp_projection_finish_draw(), clear the chunk iterator's
priority rect before finishing rendering, since it's not needed at
this point, and this is slightly more efficient.
(cherry picked from commit 9833da3431)
In GimpFilterTool, when the filter uses an on-canvas controller,
provide a toggle in the tool's filter-options dialog allowing to
toggle the controller's visibility. This allows getting the
controller out of the way when unneeded.
(cherry picked from commit 33c22ae2a3)
Add mew gimp_tool_widget_{get,set}_visible() functions, which allow
setting the visibility of a tool widget. While the widget is
invisible, it ignores all events.
(cherry picked from commit f1a7abaef9)
In GimpDrawTool, do nothing in the tool-widget signal handlers if
the draw-tool isn't active, to avoid CRITICALs due to a NULL
display. This can happen if a widget is set before the tool is
started.
(cherry picked from commit 34e6c8734b)
Add a GimpToolWidget::message signal, which can be emitted by tool
widgets to display a message, instead of using the ::status signal.
Add corresponding gimp_tool_widget_message[_literal]() functions.
(cherry picked from commit 1ac4b85ce0)
Several en_GB to en_US.
Also "Show a preview of the transform_grided image". "grided" should be
"gridded", but I also have a problem with the underscore. Should it be
"transform-gridded"? Even so, does it really make sense?
I chose to just read "Show a preview of the transformed image", which I
think is simpler and the most understandable (we don't need to leak the
implementation with a transform grid into the human read text IMO). If
anyone think that was not the right choice, feel free to propose
otherwise.
Thanks to Bruce Cowan for noticing these.
(cherry picked from commit f9c170dfbd)
This is sometimes asked, and myself also need to find it from time to
time. I may as well put the link inside the code comments, where it is
just easy to find!
(cherry picked from commit 005bc1406b)
In gimp_projection_chunk_render_start(), when the current
projection rendering is complete, but not finalized yet, and no new
rendering is started (since the current update region is empty),
make sure to invalidate the projectable's preview, since it
normally happens when rendering is finalized, which doesn't happen
in this case.
(cherry picked from commit 42845c9462)
In gimp_projection_chunk_render_start(), don't leak the current
update region when it's empty, but not NULL, and properly shut down
the idle source.
(cherry picked from commit 0e5de95760)
In the gradient tool, halt the gradient editor before committing
the filter, so that its image-flush idle source is removed before
applying the operation, to avoid flushing the image, and hence
restarting its projection rendering, during application.
(cherry picked from commit 2256ab22f7)
In gimp_tile_handler_validate_buffer_copy(), temporarily remove the
source buffer's validate handler, is exists, so that the subsequent
gegl_buffer_copy() can use fast tile copying, using the TILE_COPY
command. GEGL currently only uses TILE_COPY when the source buffer
doesn't have any user-provided tile handlers.
(cherry picked from commit f4750a0ae7)
In gimp_gegl_apply_cached_operation(), replace the use of
GeglProcessor with GimpChunkIterator, so that we use the same
chunking logic as for rendering projections. This has the
advantage of better chunk alignment to the tile grid and dynamic
chunk sizing, which improve performance.
Use chunking even when there's no progress indication, since it
generally results in better cache locality.
(cherry picked from commit 4110f7b7b1)
Factor out the region-chunking logic of GimpProjection into a new
GimpChunkIterator type, providing a generic mechanism for iterating
over a cairo region in discrete chunks. The iterator doesn't
perform any processing itself, but rather dispenses rectangular
chunks, which the user then processes.
Iteration is broken into intervals, the duration of which is
configurable. Each iteration begins with a call to
gimp_chunk_iterator_next(), after which
gimp_chunk_iterator_get_rect() should be called in succession to
fetch a rectangle to process, until it returns FALSE, which marks
the end of the iteration. Updates to the UI should take place in
the interval between iterations, but not during an iteration. The
iterator dynamically adjusts the chunk size according to processing
speed, in order to match the target iteration interval.
The iterator can be given a priority rectangle, which is processed
before the rest of the region. It can also be given a
representative tile rectangle, defining a regular tile grid;
dispensed chunks are aligned to the tile grid as much as possible.
(cherry picked from commit ba9ce34e10)
Though the layer list will also show updated, it is much easier to look
at the layer name in the status bar whose position never changes.
Anyway it makes sense to just show a temporary status info message
giving the picked layer name, making it all the easier to find the layer
you are looking for.
(cherry picked from commit 496bc02b49)
In GimpTool, track the last-seen pointer coordinates, modifier
state, and event time, during button_press() and motion() events
and use those to synthesize a button_release() event when
comitting/halting the tool, if the tool is still active, and a
matching button_release() event has not been received.
The paint tools (as well as other tools) require each
button_press() event to be matched by a button_release() event in
order to properly finish their operation, but one isn't organically
generated when switching tools due to a device change.
(cherry picked from commit 9b25611857)
In gimp_display_empty(), clear the image of all contexts whose
display is the current display, so that, in particular, when
subsequently updating the action groups, which causes certain
actions to be activated, the image that used to be bound to the
display is not found through the user context. This avoids re-
validating the image projection when closing the last image,
postponing image destruction.
(cherry picked from commit 49e57f8d6e)
The problem was not happening with the master code of
gimpdisplayshell-tool-events.c, but I encountered it in gimp-2-10 with
the layer picking code.
Even then, it still works, but I need to protect calls to
gdk_event_get_axis() to avoid CRITICALs.