Move gimp_brush_core_{subsample,pressurize,solidify}_mask() to a
separate gimpbrushcore-loops.cc file, so that they can be C++-ified
independently from the rest of the code. The next commit
parallelizes them.
Add the color in gimp_smudge_paint(INIT) like GimpPaintbrush does.
Achieve this by calling gimp_palettes_add_color_history() directly,
not by inheriting GimpPaintbrush because GimpPaintbrush and GimpSmudge seem to share few common features.
We are not doing any write operation on this mask data so copying all
the data just to read it and unreffing it in the end is only a cost on
performance.
See also bug 694917.
In gimp_brush_core_color_area_with_pixmap(), use the native area
format when painting the brush, instead of always going through
"RGBA float", and create the pixmap -> area fish only once, instead
of once per scanrow.
In gimp_brush_core_paint_line_pixmap_mask(), avoid modulus
calculation at each pixel.
See bug #694917.
... on perceptual gamma image
When constructing the paint core's paint buffer, in GimpBrushCore
and GimpInk, use the drawable's format as the preferred format in
the call to gimp_layer_mode_get_format(), instead of NULL.
Subsequently, use the paint buffer's format, instead of the source
buffer's format, as the preferred iterator format in
do_layer_blend(), since the iterator format must match the paint
buffer format.
This reverts commit 94c6bb4603, because
unlike what the bug title suggests, Smudge apparently *should* use
perceptual RGB, so now everything works as before.
which is just a #define to g_assert for now, but can now easily be
turned into something that does some nicer debugging using our new
stack trace infrastructure. This commit also reverts all constructed()
functions to use assert again.
Replace the "lock brush size to zoom" paint option with a "lock
brush to view" option, which links the entire brush transform to
the view transform, so that the brush remains invariant in display
space under scaling, rotation, and reflection.
Add support for reflecting brushes as part of their transformation.
The reflection is performed as the last step of the transformation,
across the vertical axis.
The option to reflect the brush is not exposed in the UI, or
through the PDB, but is intended to be used for linking the brush
transformation to the view transformation, in the next commit.
Add an offset_angle parameter to gimp_constrain_line(), which
offsets the radial lines by a given angle.
Add gimpdisplayshell-utils.[ch], with two new functions:
- gimp_display_shell_get_constrained_line_offset_angle():
Returns the offset angle to be passed to
gimp_constrain_line(), in order to constrain line angles in
display space, according to the shell's rotation angle and
flip mode.
- gimp_display_shell_constrain_line(): A convenience function
which calls gimp_constrain_line() with the said offset angle.
Use the new functions in all instances where we constrain line
angles, so that angles are constrained in display space, rather
than image space.
The only exception is GimpEditSelectionTool, which keeps
constraining angles in image space, since it's not entirely obvious
that we want to constrain angles of dragged layers/selections in
display space.
It never belonged inside "tools". Also rename its "pdb" subdirectory
to "groups". This had to happen before 2.10 so cherry-picking between
branches doesn't become a nightmare in the future.
Update the dprod production of generated enum files to include
abbreviated value descriptions, as per the previous commits.
Add a comment for translators above the abbreviated descriptions,
specifying the full description they abbreviate.
Looked a bit deeper into heal: while I didn't try to understand what
it's actually doing, this is strange: there is a comment that says
that healing should done in perceptual space, and the code uses
R'G'B'A float (at least it completely did before the last commit).
On the other hand, the code adds and subtracts temporary buffers,
which screams "gamma artifacts" unless done in linear space.
This commit changes everything to use linear float buffers,
and removes the comment. It "looks" right to me now, please test.
Commit 3635cf04ab moved the special
handling of bottom-layer compositing to GimpOperationLayerMode.
This required giving the op more control over the process()
function of its subclasses. As a temporary workaround, the commit
bypassed the subclasses entirely, using "gimp:layer-mode" for all
modes. This is the reckoning :)
Add a process() virtual function to GimpOperationLayerMode, which
its subclasses should override instead of
GeglOperationPointComposer3's process() functions. Reinstate the
subclasses (by returning the correct op in
gimp_layer_mode_get_oepration()), and have them override this
function.
Improve the way gimp_operation_layer_mode_process() dispatches to
the actual process function, to slightly lower its overhead and
fix some thread-safety issues.
Remove the "function" field of the layer-mode info array, and have
gimp_layer_mode_get_function() return the
GimpOperationLayerMode::process() function of the corresponding
op's class (caching the result, to keep it cheap.) This reduces
redundancy, allows us to make the ops' process() functions private,
and simplifies SSE dispatching (only used by NORMAL mode,
currently.)
Move the blend and composite functions of the non-specialized
layer modes to gimpoperationlayermode-{blend,composite}.[hc],
respectively, to improve code organization.
Move the SSE2 composite functions to a separate file, so that they
can be built as part of libapplayermodes_sse2, allowing
libapplayermodes to be built without SSE2 compiler flags. This
allows building GIMP with SSE acceleration enabled, while running
the resulting binary on a target with no SSE accelration.
Add a "blend_function" field to the layer-mode info array, and use
it to specify the blend function for the non-specialized modes.
This replaces the separate switch() statement that we used
previously.
Remove the "affected_region" field of the layer-mode info array.
We don't need it anymore, since we can go back to using
GimpOperationLayerMode's virtual get_affected_region() function.
Last but not least, a bunch of code cleanups and consistency
adjustments.
Use GIMP_LAYER_MODE_NORMAL (not NORMAL_LEGACY) when falling back from
gimp_paint_core_replace() to gimp_paint_core_paste() for layers
without alpha. Adapt the format of the used paint buffers accordingly.
More than 2000 lines of code less in app/, instead of
if (instance->member)
{
g_object_unref/g_free/g_whatever (instance->member);
instance->member = NULL;
}
we now simply use
g_clear_object/pointer (&instance->member);
Commit 1e6acbd4e1 modified the
generated enum recipes to run gimp-mkenums from the source
directory, instead of the build directory, so that only the
basenames of the corresponding header files would appear in
the comment at the top of the generated files. This was a
mistake -- $(GIMP_MKENUMS) is expecting to be invoked from the
build directory.
Switch back to running gimp-mkenums from the build directory. To
avoid including the relative path from the build directory to the
source directory in the generated file, add a @basename@ production
variable to gimp-mkenums, which exapnds to the basename of the
input file, and use it instead of @filename@ in the recipes for the
generated enum files.
When regenerating an enum file, don't copy it back to the source
directory if it hasn't actually changed. This allows using a read-
only source directory where the enum header is newer than the
generated file, as long as they're not really out of sync.
OTOH, *do* touch the generated source-dir file even when unchanged,
in order to avoid re-running its recipe on the next build, however,
allow this to silently fail (which is harmless).
We check them into git, so this makes it easier to keep them in
sync when using a separate build directory.
Case in point -- this commit also syncs a few enum files that went
out-of-sync with their headers.
... brush features.
My previous commit only fixed aspect ratio reset, but I realize that
much more brush options are affected by defaults of generated brushes
(size, hardness, aspect ratio, angle and spacing). Let's reset all these
after the basic property reset.
Generated brushes can have specific aspect ratio, hence resetting to
fixed property defaults may be wrong. Therefore GimpPaintOptions needs
to redefine the reset() method from GimpConfigInterface.
Note: the specific "Reset aspect ratio to brush's native aspect ratio"
button was alright. But the broader "Reset to default values" was not.
Spotted by José Americo Gobbo: when using a pattern source
for the clone tool, the top left corner was picked
as starting control point, which made the "fixed" aligment
rather useless. Using the pattern center allows the
better control of a pattern source.
The expression `src_offset_x - coords->x + origin->x` is parsed as
`(src_offset_x - coords->x) + origin->x`; since floating point
arithmetic is not generally associative, even when
`coords->x == origin->x` (in particular, when there is no active
symmetry), it may still yield a different result than plain
`src_offset_x` if there's not enough precision for the intermediary
result (which is usually the case when `{origin,coords}->x` is
noninteger.) Since `src_offset_x` is an integer, and since the result
of this expression is rounded to an integer, if the error happens to
be in the direction of the rounding, it's magnified to a whole pixel,
which causes visible "jitter". (Ditto for `src_offset_y` and co.)
Regardless of this issue, we want to individually round `origin->[xy]`
and `coord->[xy]` down before taking their difference, since the
original offset is calculated according to rounded-down coordinates.
This solves the original issue along the way.
We don't support subpixel source sampling, so there's no use in
pretending that we do. Demoting everything to int as soon as
possible helps guarantee that these values are at least rounded
properly and in fewer places.
Make sure we always round coordinates down, and not toward zero.
Keep using floats only in the signatures of the relevant PDB
functions.
Instead, add a gimp_layer_mode_get_format() function, which takes
the layer mode, composite space, and blend space, and returns the
I/O format.
Currently, we always use the composite space format as the I/O
format. This simplifies gimp_composite_blend(), and gives us
composite-space support for the "special" layer mode ops for free.
Add a "paint_composite_mode" field to GimpLayerModeInfo and set the
mode of the eraser to SRC_ATOP. Defaulting to SRC_OVER for all
painting didn't quite do it for all modes.
and to operations/layer-modes/, respectively.
Add gimp_layer_modes_init() which asserts on the correct order of the
GimpLayerModeInfo array, and switch to accessing the array directly in
gimp_layer_mode_info().
Largely based on a patch by Ell, with the enum type renamed and
various small changes. Adds another axis of configurability to the
existing layer mode madness, and is WIP too.
Since CIE Lab is one of the supported color spaces for doing the blending -
this enum is not only about transfer functions/curves or gamma. This finishes
already started cleanups.
Implement a common utility function gimp_blend_composite that uses utility
functions for implementing layer modes, with separate (possibly SIMD) optimized
loops for blending and compositing, with configured linear TRC, perceptual
gamma TRC or even using CIE Lab as the space.
from gimp_applicator_new() and gimp_gegl_mode_node_set_mode().
Compositing doesn't depend on the layer format any longer, only on the
layer mode. Painting with "use applicator" unchecked is still broken
in some cases and needs more fixing.
like all other function typedefs and add GimpBlendFunc typedef which
will be needed soon. Also rename get_layer_mode_function() to
gimp_get_layer_mode_function().
Temporarily slower - but permits paint modes like overlay/softlight to work at
all for linear TRC pixel encodings. Should be reverted when the non-graph
approach works properly again.
with proper value names. Mark most values as _BROKEN because they use
weird alpha compositing that has to die. Move GimpLayerModeEffects to
libgimpbase, deprecate it, and set it as compat enum for GimpLayerMode.
Add the GimpLayerModeEffects values as compat constants to script-fu
and pygimp.
Initialization was failing when a paint buffer could not be returned for
a stroke (which was bound to happen in tiling). Instead it must just
ignore the coordinates which won't result in painting, and continue to
the next ones.
...are not submitted to respective Tool Options sliders
Treat brush angle and aspect ratio like all other paint options values
that can be linked to brush defaults and take their default values
from the brush. They were special casing their defaults to constants,
and GimpBrushGenerated was adding the passed dynamic radius and aspect
values to its own. This was totally incomprehensible.
Now GimpBrushGenerated's transform_size() and transform_mask()
implementations just translate between these APIs value ranges and the
brush's own value range and only use the passed values (not the
brush's native values), which makes the editor <-> tool options
interaction and the painted brush shape predictable.
Also connect the active brush's property notifications to the paint
options properties, so the paint options follow a brush edit live if
the respective "linked" toggles are checked.
And some cleanup.
Fix GimpAirbrush to not keep a GimpSymmetry instance around across
paint strokes. The symmetry refs its drawable but lacks the code of
dropping the reference when the drawable is removed from the image, or
the image is closed.
Also cleaned up gimp_airbrush_paint() a bit.
and remove lots of labels from calls to gimp_prop_foo_new(). Also
had to manually remove some unwanted labels that are now added
automatically, fixes bug #761880.
You can now set any paint tool to mirror painting relatively
horizontal/vertical axis or a central point (any combination of these 3
symmetries).
This has been implemented as a new multi-stroke core, where every stroke
is actually handled as a multi-stroke (default of size 1).
This is also the first usage of custom guides for symmetry guiding.
Current version has to be activated in the playground.
Remove the code that links size, spacing etc. to brush defaults from
the GimpPaintOptions class impl and add it to gimppaintoptions-gui.c
as a callback instead.
It's not a core thing and that magic with side effects should only be
applied to the GimpPaintOptions behind the tool options GUI.
This adds a boolean to GimpCoords struct that is true for enabled
extended non-mouse devices and false for all the rest allowing
the mypaint brush to override the the pressure sent to the paint library.
This (doesn't quite) fix an obscure part of the tool preset bugs: when
changing the brush on a GimpPaintOptions instance, we might or might
not change the brush size, aspect etc. to the set brush's native
values, possibly overwriting the intended values from a tool preset.
Implement GimpConfig::copy() and copy the affected values again after
the entire object has been copied, so we actually use the value of
gimp_config_copy()'s "source" object.
This would fix that particular tool preset problem if there wasn't
another bug that is still unfixed, stay tuned...
This reverts commit 15b5b2c8b3.
This feature is "undiscoverable" according to Mitch, and we are not sure
how much the endpoint colors are special to the user.
Now the history of recently used colors is not updated when selecting
in the color dialog anymore, but when a color is actually used.
Tools supported right now are: Ink, MyPaint brush, all PaintBrush tools,
bucket fill and eraser (background color on non-alpha drawables).
Moreover from now on, colors already saved are properly moved to first
position when reused.
Implement GimpConfigInterface::duplicate() and after duplicating the
paint options, copy the brush-related properties again, because they
might have been changed by setting the brush on the copy (if they are
set to be linked to the brush's native values).
The work-in-progress was using a source tree of libmypaint embedded
into GIMP tree. This is a cleaning with pkg-config test in configure,
and correct includes.
Add "link" buttons to the tool options that are duplicates of brush
properties, so the tool options values can be set to change along with
the current brush.
Add "gboolean use_cache" to gimp_applicator_new(). Don't use a cache
anywhere but in GimpImageMap because it incrementally fills that cache
via the projection update. In gimp_drawable_merge_filter(), get that
cache and pass it to gimp_gegl_apply_cached_operation() which then
avoids doing the work twice for the already cached results. Win!
GIMP_ADD_foo_MASK -> GIMP_ADD_MASK_foo
GIMP_foo_MODE -> GIMP_BLEND_foo
GIMP_foo_CLONE -> GIMP_CLONE_foo
GIMP_foo -> GIMP_DODGE_BURN_TYPE_foo
GIMP_foo -> GIMP_TRANSFER_foo
Add compat values for the old names and compat code to script-fu
and pygimp.