When downscaling raster brushes, we currently resample the original
brush with no fitlering (other than bilinear interpolation), which
results in very noticable aliasing when using heavily downscaled
big brushes.
This commit constructs a box-filtered mipmap hierarchy for the
original brush on-demand, and the closest mipmap is used as the
resampling source for downscaled brushes, significantly improving
the output quality.
... which converts a (scale, aspect_ratio) pair to a (scale_x,
scale_y) pair.
Change gimp_brush_transform_matrix() to take (scale_x, scale_y)
parameters, instead of (scale, aspect_ratio), and change the rest
of the code accordingly.
When loading ABR brushes, error out on negative scan-line lengths,
instead of trying to allocate a huge buffer. This entire code
could use a whole lot more unsignedness, but this should cover the
crash.
Improve the efficiency of decoding RLE data when loading ABR
brushes, by reading entire scanlines into a buffer all-at-once,
instead of reading the stream byte-by-byte.
... containing a floating selection
When destroying a GimpGroupLayer, remove all the children signal
handlers before destroying the container, so that we don't attempt
to reallocate the group's projection in response to
"update-bounding-box" signals emitted during layer destruction,
which can happen for floating selections.
Add a new Gimp::tool_item_ui_list, which is a GimpTreeProxy over
Gimp::tool_item_list. This allows us to use either a hierarchical
or a flat tool list in the UI, by setting the "flat" property of
the new list.
Use Gimp::tool_item_ui_list in GimpToolPalette, so that the toolbox
layout is affected by this choice.
Add a "Use tool groups" toggle to the toolbox preferences, and bind
it to the "flat" property of Gimp::tool_item_ui_list.
Add a new GimpTreeProxy container class, which proxies a
GimpViewable tree. The proxy has a dynamically-settable boolean
"flat" property, which controls if the tree hierarchy is preserved,
or if it's viewed as a flat list.
Add a new GimpContainer::search() virtual function, and a
corresponding gimp_container_search() function, which works
similarly to gimp_container_foreach(), except that the callback
returns a boolean. When the callback returns TRUE, the search is
stopped, and the current object is returned.
Implement GimpContainer::search() in GimpList.
Add a new read-only GimpToolItem::shown property, and a
corresponding GimpToolItem::shown-changed signal, which determines
if a tool item is visible throughtout the hierarchy, i.e., if it
and all its ancestors are visible. This replaces
gimp_tool_item_is_visible().
Use the new property and signal in GimpToolPalette and
GimpToolEditor, to simplify the code, and in preparation for a flat
toolbox view.
In GimpToolManager, use a weak pointer for tracking the active tool
group, instead of taking a reference on it. This avoids
erroneously extending the group's lifetime, which can cause
problems with the tool-item hierarchy.
In GimpToolGroup, make sure that newly-added tools don't already
have a parent.
Move the logic for translating a tool identifier to a corresponding
action name to GimpToolInfo. It's currently only used in
tools-actions.c, but the next commits will use it in tool buttons.
Allow creating GimpToolInfo objects with a NULL menu label, and do
that for GimpOperationTool. The previous commit effectively
removed it from the Preferences tool editor, and this commit also
removes it from the action search.
Add a new Gimp::tool_item_list list, in addition to
Gimp::tool_info_list. The latter may contain arbitrary tool items,
including tool groups, and is intended for use in the UI (namely,
the toolbox and the preferences tool editor).
In gimp-tools, use Gimp::tool_item_list for representing the UI
tool order (while still using Gimp::tool_info_list as a flat list
of all GimpToolInfo objects), and add support for saving and
loading tool groups to/from toolrc.
Introduce file-version tracking in toolrc, and drop its contents on
version mismatch, or when new tools are introduced. This is
slightly disruptive, but merging new changes with existing toolrc
files is non-trivial, and it doesn't happen very often.
Add support for a sysconf toolrc file, which is used if there's no
user toolrc file (i.e., on first use). If neither file is found,
the hard-coded flat tool order is used. This commit doesn't
provide a default toolrc file, but the next commits will.
Make the gimp-tools serialization and deserialization functions
public, for use in GimpToolEditor in the next commits.
... if not using unique names
Add a new GimpContainer::get_unique_names() virtual function, and a
corresponding gimp_container_get_unique_names() function, which
determines if the container uses unique names for its objects.
Override get_unique_names() in GimpList, to return the corresponding
property.
In gimp_container_deserialize(), don't merge new objects with
existing objects sharing the same name if the container doesn't use
unique names.
Add GimpToolGroup as a new subclass of GimpToolItem, representing a
collection of tools. The end goal is to display tool groups using
a single button in the toolbox.
Tool groups are not recursive: they can only contain individual
tools, not other groups. Each group has a single "active tool",
normally the most-recently-used tool of the group, which is
activated when clicking on the tool's button.
Add GimpToolItem as a common base class for toolbox items.
Derive GimpToolInfo from GimpToolItem, representing an individual
tool. The next commits add support for tool groups, represented by
an alternative subclass of GimpToolItem.
Most of the tool-info properties remain in GimpToolInfo, however,
GimpToolItem takes care of tool-item visibility.
Changed the reflection method to find the middle of the slice the
user is drawing on, and reflecting on that. This reflects the slice
in place, making it easier to rotate it to the intended location.
This fix preserves the order the dabs are drawn on the
slices, to be counterclockwise.
Fixed the brush transform, by setting the reflect output variable,
and calculating accordingly.
When dowscaling an image (or a layer group), empty layer groups
can be discarded as a result of their new dimensions being too
small, since we're calculating their new dimensions according to
their fake 1x1 dimensions. However, these dimensions are purely an
implementation detail and shouldn't affect the result, and neither
do we show a warning for them.
Instead, simply avoid discarding empty layer groups.
Restrict last commit's workaround to layer groups only (which is
the only relevant case ATM), since it negatively impacts the warp
tool, which does rely on the ability to perform (accurate) partial
updates with filters to improve performance. It's only a temporary
hack anyway.
When a drawable has filters attached, they may influence the area
affected by drawable updates. Currently, we ignore that, updating
the original region regardless. This can lead to drawable updates
not affecting the correct regions. This couldn't be triggered
until now, but since layer groups can now have a transform op
attached as a filter, updates to their sublayers -- which can
happen while the transform tool is active -- run into this problem.
Fix it for now by simply updating the full drawable region when the
drawable has filters. This is a very conservative approach -- we
don't even bother checking if we're only dealing with point
filters, as this change only influences transformed groups right
now. Ultimately, we need to rely on node invalidation to drive
updates, which takes this into account.
Using any clipping mode other than ADJUST is currently broken for
layer groups, since each layer in the group is clipped
individually, instead of clipping being applied to the group as a
whole. Ultimately, we should fix that, but for now, simply disable
clipping for layer groups, by overriding GimpItem::get_clip() to
always return ADJUST.
... (used to add one automatically)
In GimpFilterTool and gimp_drawable_apply_operation(), use
gimp_drawable_filter_set_add_alpha() to add an alpha channel when
applying an operation that specifies "needs-alpha" to a drawable
that can have alpha.
Don't disable gegl:color-to-alpha (which has "needs-alpha") when
the drawable doesn't have an alpha channel, if one can be added.
Add a new GimpDrawable::supports_alpha() virtual function, and a
corresponding gimp_drawable_supports_alpha() function, which
determine if the drawable supports an alpha channel. The default
implementation returns FALSE, and GimpLayer overrides it to return
TRUE.
The crop-to-result and crop-with-aspect transform-boundary
algorithms seem to consistently fail in some cases, and spit out a
warning, which can be too verbose if it triggers the debug dialog.
Demote the warning to a g_printerr(), with an eye to just dropping
these algorithms altogether.
In GimpDrawableFilter, add a
gimp_drawable_filter_set_override_constraints() function, which
allows bypassing certain constraints applied to the filter, based
on the drawable type and state.
Yes, this is a bit of a hack, added mostly as a quick-and-dirty way
to allow us to add filters to layer masks that affect their
bounding box, in preparation for composited transform previews.
Add an optional "format" parameter to gimp_drawable_merge_filter(),
which specifies the format to use for the output, possibly changing
the drawable's format.
In GimpDrawableFilter, add a gimp_drawable_filter_set_add_alpha()
function, which allows the filter to add an alpha channel to the
drawable when committed (by passing an appropriate format to
gimp_drawable_merge_filter()).
Change the default implementation of
GimpDrawable::get_bounding_box() to return the drawable source
node's bounding box, instead of the drawable's item bounds. This
allows filters to affect the size of all drawables, including, in
particular, layer masks.
Change GimpLayer's implementation of get_bounding_box() to return
the intersection of the layer's own bounding box, and the layer
mask's bounding box (if it has one), and update the layer's
bounding box when the mask is enabled/disabled, or when its
bounding box changes.
... by synchronously flushing the group's projection. This is
necessary for pass-through groups, since their projection is
normally flushed asynchronously.
Add a "clip" property to GimpCanvasTransformPreview, specifying the
transform's clipping mode, and clip the preview accordingly.
In GimpTransformGridTool, sync the tool's clipping mode with the
preview's clipping mode.
Which is a linear transform of xyY that is more perceptually
uniform, and so well-suited for eventually adding chromaticity
diagrams to GIMP color tools. ACES documentation uses this color
space instead of xyY for showing chromaticity diagrams. Moving
forward I expect other venues also will start using Yu'v' as
the advantages over xyY chromaticity diagrams are fairly obvious.