The GimpLayer implementation of the GimpItem transform functions,
and the GimpDrawable convert_type() function, apply their operation
to both the layer and its mask. The subclasses of GimpLayer --
GimpGroupLayer and GimpTextLayer -- override some of these
functions, providing their own logic for the layer part, and
duplicating the mask part.
Avoid this duplication by adding a set of virtual transform and
type-conversion functions to GimpLayer. Have the GimpLayer
implementaion of the corresponding GimpItem and GimpDrawable
functions use these functions to apply the operation to the layer,
while taking care of the mask themselves. Have GimpLayer's
subclasses override the new virtual functions, instead of the
GimpItem and GimpDrawable ones.
Note that the existing implementation of convert_type() in
GimpTextLayer neglected to convert the mask, hence text layer masks
retained their old format after conversion. This issue is fixed as
a side effect of this commit.
Humanize action names to make them readable while
preserving their original grouping. Mark for translation
the missing ones. Use absolute values to make
"increase/decrease more" less cryptic since we hardcode
those values anyway.
so widgets can return which handle was clicked. The values boolean
semantics stay the same so if(retval) gives the same result. This is
useful for the upcoming transform tool widgets.
The GEGL ops sanity check causes all ops to be initialized. The
strings used by their properties will pick the translation selected
at the time of the check. It must therefore run after language
intiailization, otherwise the selected translation would correspond
to the system locale, even if the user selected a different language
in the preferences.
Split the sanity check into early and late stages. The early stage
is run before the call to app_run(), as it did before, while the
late stage is run during app_run(), after the configuration has been
loaded. Currently, the GEGL ops check is the only late-stage check;
all other checks are performed during the early stage.
The identity parameter checks added to the raster brush
transformation functions in the previous commit are unnecessary,
since we're already testing for the identity matrix. Remove them.
Check if the brush parameters match the identity parameters, and
return the original brush mask/pixmap if they do, in the actual
mask/pixmap transformation virtual functions, instead of in their
wrappers. While the identity parameters for raster brushes are
always scale=1, aspect-ratio=0, angle=0, and hardness=1, for
generated brushes they depend on the specific brush
parameterization.
Thanks to Lionel N. who bugged me with his Windows installation where
the XML file was not found by GIMP. We should output a warning when this
happens so that packagers can detect the issue and the expected
installation path for this dependency.
The reporter wants me to call him "Padawan Lionel" but I won't fall for
it! Or did I? :-D
This option behaves similarly to the other transform tool, however
it's limited to "adjust" and "clip" only. Now that the flip tool
can reflect across guides, this option is meaningful.
... when clipping, if they have an alpha channel
Right now, this case is only reachable through PDB, but it will become
relevant for the flip tool soon.
When compressing tool motion events, only compress motion events
at the front of the event queue, targeted at the same widget as,
and having similar characteristics to, the initial motion event;
stop compressing upon the first mismatched event.
Previously, all pending motion events targeted at the canvas were
compressed, stopping only at a button-release event targeted at the
canvas. As a result, when adding a guide by dragging from a ruler,
there could be a situation where a pending button-release event
targeted at the ruler would be followed by motion events targeted at
the canvas, with a cleared state mask. These motion events would
get compressed to the initial motion event targeted at the ruler,
resulting in a motion event with a cleared state mask being processed
before the said button-release event. This, in turn, would cause the
guide tool's cursor_update function to be called, while the tool is
still active, emitting a CRITICAL. Sheesh.
The moral of the story is: let's play it safe.
which encapsulates a bunch of GimpCanvasItems plus their interaction,
using GimpTool-like virtual functions like button_press(),
button_release() motion() etc. Also has GimpDrawTool-like API to
manage the canvas items of its subclasses.
Call gimp_canvas_group_remove_item() and don't just unref them, so
their state gets restored and signals get disconnected. They may not
be owned by the group, or have other external references.
Simply increase its change_count in dispose(). There is really no
reason to build expensive update regions and emitting signals when we
are about to go away.
Add a log handler so that GIMP can display errors outputted by GEGL.
Since third party code may run in threads and we have no control on
these, we have to be sure GTK+ code is run in a thread-safe way, hence
the usage of gdk_threads_add_idle_full(). This was the case here for
GEGL, and handling GEGL logs the same way as other GIMP logs would
result in crashes.
This way, you can increment repeated messages even when not the last
one and you don't overflow the error dialog needelessly when 2 errors
repeat one after another.
by encoding them directly in the string attached to all filter
actions. The code now supports both "gegl:some-operation" and
"gegl:some-operation\n<serialized config>".
Add "default_settings" to GimpGeglProcedure to store the settings of
the invoking action, much like the "default_run_mode" member.
Change filters-commands.c to parse the new operation string, create
GimpGeglProcedures with the deserialized settings, and use those
settings when the procedures are ran.
Change the filter history to be smarter about what is already in the
history, there can now be several different procedures with the same
name.
Remove the dilate and erode actions from the drawable group, and add
them to filters, they are just special cases of value-propagate with
fixed settings.
Allow NONE(0) for "wrapmode" (which translates to GEGL_ABYSS_NONE) in
the plug-in-edge PDB compat wrapper. The old plug-in accepted this
(undocumented) value and used a GimpPixelFetches in NONE mode.
which determines if a filter is applied directly (RUN_NONINTERACTIVE)
or asynchronously using GimpOperationTool (RUN_INTERACTIVE).
Split filter actions in two groups, one for direct apply and one for
interactive apply, which have separate callbacks that create
GimpGeglProcedures with the right default_run_mode set.
(After doing this distinction automatically based on the existance of
editable properties, I figured will might want direct apply also for
filters that do have properties, such as e.g. dilate and erode, which
are just value-propagate with some constant property values)
which gets added automatically by procedure_commands_get_display_args().
Move the non-interactive and run-with-last-vals code to
gimp_gegl_procedure_execute() (not execute_async()) because it makes
more sence to call it synchronously anyway (not implemented yet).
This commit should change no behavior.
Since commit bc4589968c, GimpFilterTool
assumes that color picking is only ever enabled through color picker
toggles, created using gimp_filter_tool_add_color_picker(). However,
the curves tool enables color picking using the color tool functions
directly. CRITICALS ensued.
Use the new gimp_filter_tool_enable_color_picking() function, added
in the previous commit, and handle picking through the filter tool
interface, instead of the color tool interface. This fixes the
issue.
Subclasses of GimpFilterTool should use these functions to control
picking, instead of using gimp_color_tool_{enable,disable}()
directly. This makes sure that the tool's picking state is
consistent, and allows the caller to control the pick identifier,
and use abyss picking (not currently needed by any subclass, but
maybe in the future, who knows.)
Return only the config object's GType and do the g_object_new() in the
caller (one caller only needs the type, there is no need to create a
dummy object just to get to its type).
around calling the actual execute vfuncs, Seen a crash when quitting
GIMP while a script-fu window was open, the progress was already
finalized. Now it simply prints the error message about the failing
script on the concole.
so they show up in recent filters, and don't need their own callbacks.
This has the problem that they now show a GUI with no options, but
that simply puts on more pressure to fix this general uglyness of ops
without editable properties.
We don't search recursively but only at the first level. If a plugin is
in its own subdirectory, the entry point has to be named the same (minus
extension) as the directory. For instance my-plugin/my-plugin for a
binary, or my-plugin/my-plugin.(py|exe|…).
This way, a plugin can load shared objects (libraries, other script
files, etc.) without polluting the main plug-ins directories, and in
particular without interfering with other plug-ins.
This is a first step to fix bug 757057 (DLL files which were used in
various plugins).
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).
The layer blend space, composite space, and composite mode
properties have a special AUTO value, which may map to different
concrete values based on the layer mode. Make sure we can change
this mapping in the future, without affecting existing XCFs (saved
after this commit), by encoding these properties as follows:
When saving an XCF, if the property has a concrete (non-AUTO)
value, which is always positive, encode it as is. If the property
is AUTO, which is always 0, encode it as the negative of the value
it actually maps to at the time of saving (note that in some cases
AUTO may map to AUTO, in which case it's encoded as 0).
When loading an XCF, if the encoded property (stored in the file)
is nonnegative, use it as is. Otherwise, compare the negative of
the encoded property to the value AUTO maps to at the time of
loading. If the values are equal, set the property to AUTO;
otherwise, use the concrete value (i.e., the negative of the value
stored in the XCF).
Note that XCFs saved prior to this commit still load fine, it's
simply that if we change the AUTO mapping in the future, all their
AUTO properties will keep being loaded as AUTO, even if the
resulting concrete values will have changed.
... to the warp tool
The interpolation and abyss policy options control the sampler type
and abyss policy of the map-relative node. The high quality preview
option determines whether to use the same sampler for map-relative
during preview as the one used during commit, or whether to use a
fast nearest-neighbor sampler.
A bit too much? Maybe :)
... and to disable/control the rate of the periodic stroke.
The warp tool is now fast enough to enable stroking directly in
the motion handler, which gives better-quality response to motion
than stroking periodically. It's not quite fast enough to enable
exact motion, though :/
Allow individually enabling/disabling stroking during motion and
periodically, and allow controlling the rate of the periodical
stroke.
because the scale is useless otherwise with its range of 2..10000,
and because I needed a test case for the next commit (the
gimp_scale_entry_set_logarithmic() API was unused).
When using the MOVE behavior, don't append the current cursor
position to the stroke path in the timeout proc if the cursor
hasn't moved since last time. It has no effect, except for
requiring an unnecessary update.
When undoing a warp stroke, don't disconnect the current warp node
from its predecessor; rather, keep the graph as-is, and only
reconnect the render_node to the previous node. This avoids
invalidating the undone node, so that redoing it (which, likewise,
only involves reconnecting the render_node) doesn't require
reprocessing, making it much faster.
The spacing parameter controls the stroke spacing of the warp op.
It's similar, but not identical, to the brush spacing parameter of
the paint tools. It provides a tradeoff between speed and quality.
Change the UI range of the hardness parameter from [0, 1] to [0, 100],
to match the other parameters.
"layers-text-tool" action shows as "Text Tool" while "vectors-path-tool"
shows as "Path Tool". That's very confusing with tools-text and
tools-vectors respectively.
These actions are mostly about entering in edit mode with the active
layer or path. For text layers, it will enter text edition on canvas,
whereas just open the attributes edition dialog on other layers. For
consistency, layers-text-edit is renamed as well too layers-edit-text.
This also fix the side effect of commits 10099bd and 526918b where I
didn't realize that layers-text-tool was also working on non text layers
on purpose (being very badly named). Now there is a separate layers-edit
and layers-edit-text.
Thanks to Pat David for English corrections. :-)
Limit the number of lines drawn in the transform tool canvas grid to
one line every 5 image pixels. This should probably be done in display
pixels, didn't change that yet.
When transform tools are applied on a path, set their bounding box as follow:
- if a selection exists, use the selection bounds
- else if the path has a valid bounding box, use it
- else use the image canvas bounds
Also disable transform tools on an empty path (path without strokes) since
there is no data to transform.
Add support for The following GEGL op property keys, which shall
contain GUM expressions of the specified type, controlling the
corresponding UI attributes of the property's widget:
- sensitive [boolean]: controls widget sensitivity.
- visible [boolean]: controls widget visibility.
- label [string]: controls widget label (or the label of the
associated label widget).
- description [string]: controls widget tooltip text.
When any of above keys are present, the values they evaluate to take
precedence over the static values the corresponding attributes would
otherwise have.
GUM is a small DSL, used in some property keys of GEGL operations
to dynamically control UI attributes based on context. This commit
only adds an interpreter for the language; see the next commit for
the actual handling of the relevant keys.
See the comment at the top of gimppropgui-eval.c for a description
of the language.
Note that the interpreter is licensed under the LGPL.
If focus is on the layer list for instance, running this action from
right-click menu raises the on-canvas toolbar, ready for edition, with a
visible text cursor. But if the canvas has no focus (since you clicked
on the layer list, it has the focus), you still have to move your mouse
over and click the text on canvas. That doesn't make sense and there
would be barely any reason to use this over selecting the text tool then
clicking the canvas.
... non-text layers.
Since commit 10099bd, the action will be non-sensitive with non-text
layers, so if it happens, there is a bug somewhere. Therefore
g_return_if_fail() on this condition.
Moreover opening the edit attributes dialog was absolutely confusing on
what this action is supposed to do. We should not have these kind of
random behaviors.
When a layer is removed from a layer stack, and its backdrop needs
invalidating, emit the UPDATE signals for the backdrop only after
the layer has been removed from the container.
A subclass of GimpDrawableStack, for layer stacks. Invalidates the
layers' backdrop as/when necessary, according to the value of their
excludes_backdrop property.
Make gimp_drawable_stack_update() protected, instead of private, so
that we can use it in GimpLayerStack.
A boolean flag, specifying whether the backdrop is clipped to the
layer. That's the case when the layer's composite mode is dst-atop
or src-in.
This is a read-only property, derived from the other attributes of
the layer. We compute its value through a virtual function, so that
GimpGroupLayer will eventually be able to specialize it for pass-
through groups.
The next commit uses this property to actually do something useful.
Takes a layer mode and a composite mode, and returns the region
included in the composition.
Use this function in GimpOperationLayerMode, instead of testing
for specific composite modes directly. Will also be used by
the next commit.
Indentation cleanup in gimp_layer_modes.h
... so that we can use it for other functions that involve
compositing regions (which we do in the next commit).
Rename gimp_operation_layer_mode_get_affect_mask() and
friends to _get_affected_region().
With bigger and denser default images, the older 18px font default is
very small (~ 4pt font at 300PPI).
I decided to settle for a 15pt font, i.e. 62 px at 300 PPI, which seems
like quite an acceptable relative size for our FullHD defaults.
It is bigger than a default font size for —say— a text processor, but
GIMP is not really designed to process large walls of small text anyway.
Rather shorter texts at bigger sizes (i.e. designs, etc.). So this seems
like quite an ok default.
Note that as any defaults, this only goes as far and won't be what most
people need most of the time anyway. But at least we should get rid of
this ridiculous 18px default.
... tool when font unit is not pixel.
The default size is 18px. If for instance one is on a 300 PPI image, and
set the unit to mm, hitting "Reset to default values" sets to 213 px
(which corresponds to 18mm at 300PPI). I'm not 100% sure of the source
of the problem, but resetting the font size before the unit fixes it and
properly sets back to 18px. Let's go the lazy way and just do this.
Add the additional enum values to enum GimpSelectCriterion, and
the few needed lines to gimppickable-contiguous-region.c.
It's horribly slow, but works.
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.
gimp_unit_get_digits() won't return relevant information when using
higher resolution. gimp_unit_get_scaled_digits() will provide the right
amount of details relatively to the actual print resolution of the
active image.
Add "import-raw-plug-in" to gimprc, and a new procedure
gimp_register_file_handler_raw(). On startup, remove all load
procedures that are marked as "handles raw" but are not implemented by
the configured plug-in. Add the list of available plug-ins to prefs ->
import/export. Register all file-darktable procedures as handling raw.
... 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.
Determines if the tool can pick at a given coordinate, without
actually picking. The default implementation uses
gimp_image_coords_in_active_pickable(); GimpFilterTool overrides
this function, to return TRUE whenever the active picker has
pick_abyss == TRUE.
Use this function when updating the cursor, and when determining
whether to draw the sample-average region indicator.
Add a boolean 'pick_abyss' parameter to GimpCreatePickerFunc. When
this parameter is TRUE, the picker should pick outside the bounds
of the drawable. Use FALSE for color pickers, and TRUE for position
pickers.
and use them for the new image in "Paste as new image". We were using
the resolution and unit of the image the paste command was invoked
from, which is entirely random and useless.
Change wording in Advanced Color Options drop-down menu to not imply
that GIMP isn't color-managed.
Slightly changed wording from Elle's original patch (mitch).
Also set the combo box' "ellipsize" property to END because it's too
wide. As mentioned before, this doesn't work for whatever reason,
hints are appreciated :)
when a click is detected by gimp_tool_check_click_distance(), only do
a motion() back to the button_press() coordinates if there has been a
motion at all since button_press(). This should not change any tool's
behavior, it's only an optimization to keep tools from doing useless
work.
The halftones transfer mode of dodge/burn uses pow(), which produces
NaN for negative input values. This tool doesn't really have OOG
values in mind, but using an odd power function fixes this issue,
and is in line with the behavior of the other modes w.r.t. OOG
values.
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.
Add a "mask-only" property to GimpBrushClipboard. When TRUE, only
create a brush mask (not a pixmap brush with mask and image).
Keep two clipboard brushes around: one classic "Clipboard Image" one
to be used as "stamp", and one new "Clipboard Mask" one that turns the
clipboard into a brush mask.
Fix the edit-paste and edit-paste-as-new-image PDB wrappers to use
gimp_get_clipboard_object(), not just clipboard_buffer(), and deal
correctly with entire images in the clipboard.
Fix brush shrinking used to compensate for the blur: avoid over-
shrinking the brush and changing its aspect ratio.
Change the way hardness maps to blur radius: hardness == 0 maps to
the largest radius such that, when the kernel is applied to the
middle pixel of the brush, the kernel is completely within the brush
bounds, taking brush shrinking into account, *assuming the brush is
a circle*.
Use the dimensions of the unrotated brush when calculating the blur
radius, so that rotation doesn't affect the blur amount (the blur
itself is not isotropic, though, and is applied after rotation, so
while the blur amount remains uniform, its effect does depend on the
brush angle.)
Get rid of the blur-radius upper limit -- it's fast enough to handle
large radii now.
A few additional minor speedups.
Also, make sure we don't overflow for large blur radii. Not a
problem yet, since the blur radius is capped, but soon...
Add a specialized convolution algorithm for the hardness blur. It
uses the same kernel as before, but performs the convolution in
(amortized) O(1)-per-pixel time, instead of O(n^2), where n is the
size of the kernel (or the blur radius).
Note that the new code performs the convolution in the input color
space, instead of always using a linear space. Since our brush
pixmaps (but the not masks) are currently perceptual, the result is
a bit different.
Add a debug procedure group, living in 'debug.pdb', which would host
useful debug helper functions. Functions in this group are not part
of the stable API, and may be changed at any point.
All procedures added to 'debug.pdb' should have a 'debug_' prefix,
and use the new std_pdb_debug() macro, which adds the proper "here be
dragons" warning to their description.
Add two debug procedures: gimp-debug-timer-start() and
gimp-debug-timer-end(), which measure elapsed time, a la
GIMP_TIMER_{START,END}, and can be used to profile script-fu
commands.
If the transformed item is a layer, and we are transforming the entire
layer (if there is now selection), hide the original layer during the
interactive transform. Based on a 2.8 patch from saulgoode.
Commit 9d4084c82f skips conversion and
blending of (some) transparent source and destination pixels. When
`blend_out == blend_layer`, it banks on the fact that the alpha values
of `blend_out` would be the same as those of `blend_layer`, and hence
the same as those of `layer`; thing is, we only copy those values from
`layer` to `blend_layer` for the pixels that we *don't* skip, so this
assumption is just wrong :P This leaves us with bogus alpha values in
`blend_out` for the skipped pixels, when the above equality holds.
For composite modes that use the alpha values of `blend_op` (aka `comp`)
even for transparent input pixels (i.e., src-atop and src-in), this may
result in artifacts.
Fix this by simply initializing the alpha values of `blend_out` for
skipped pixels unconditionally.
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.
Copy TransInfo arrays around using memcpy(), use memcmp() to
compare them, add a function to allocate one. Clean up some
logic in gimp_transform_tool_check_active_item().
and a GimpSettingsBox. This brings savable settings to all ops, also
the automatic ones in the GEGL tool. It also makes the code cleaner
and more general.
... have been saved.
No need to keep a list of 0 images when the creator requested a quit or
close-all actions and manually went through the list to save all
remaining images. Yet one can still cancel the quit/close-all action by
hitting Esc (or Cancel button) during the last save, since it is an
idle source action.
GimpFilterTool::get_settings_ui() is no longer needed, replace
it by a simple utility function in gimpfiltertool-settings.c.
Also, use the GimpFilterOptions functions added earlier, and some
random cleanup.
and add them as return values to GimpFilterToool::get_operation(), so
the tools is configured entirely per-instance now.
This makes get_operations()'s signature more evil, but helps making
GimpOperationTool less conplicated and convoluted.
We were still saving channel colors in 8 bit, this additionally
saves/loads the color as float values. Still save the old PROP_COLOR
for compatibility.
from gimpdir/tool-options/ to gimpdir/filters/, and only if moving
fails try reading from the old location as fallback. We don't normally
move files around, but this one-liner nicely avoids cluttering
gimpdir.
Filters settings used to be serialized and deserialized only
when a filter tool's GUI was shown, too late for the code that
re-runs/re-shows filters with previous values.
Move the entire loading/saving code to gimp-operation-config.c, even
adding/removing the dummy separator item between timestamped automatic
history and manually saved settings. Load the settings automatically
when a settings container is requested, but still trigger saving from
the few places the container is changed in the GUI; could also
automate that later.
This commit also moves all settings of filters that have their own
tools from gimpdir/tool-options/ to gimpdir/filters/. Add compat code
to try the old filename if the new doesn't exist, so files are
migrated automatically.
WIP, but this step already fixes the bug.
Both in the GimpImage API and in the GUI. The toggle in the save
dialog now controls ZLIB compression directly. Changed the various
info labels accordingly. Ditch the XCF parasite that saved the XCF
compat mode.
Commit 4beff2f was basing it on the screen y PPI but that is not really
consistent or logical actually. Since the actual stroke dialog uses the
y resolution of the current image, it makes sense that the generic
stroke defaults in the preferences should use the y resolution of the
default image.
Enable 64 bit file offsets in XCF files, starting with newly added XCF
version 11.
We use at least version 11 if:
- we would use the previous version 10 (essentially skipping 10)
- the in-memory size of the image is larger than 4 Gig
Change the xcf_read_foo() functions to take the XcfInfo* instead of
a GInputStream*, and make them advance the info->cp offset by
themselves. Makes xcf-load.c a lot more readable.
Step one, without changing anything in the saved XCFs yet:
Abstract reading and writing of file offsets away into their own
xcf_read_offset() and xcf_write_offset() functions, which take
"goffset" instead of "guint32". Also change xcf_seek_pos() to take a
goffset argument.
Change all file offset variables in xcf-load.c, xcf-write.c and struct
XcfInfo to goffset, and add new member "bytes_per_offset" to XcfInfo,
which is currently always 4.
This value could be based on either the x or y resolution, or maybe some
kind of mean values. It could also be based off the print resolution of
any image (if the user sets a physical dimension, the actual pixel width
will vary depending on the print resolution). There is no actual "good"
answer here. But any of these values will be better than a default 96.0.
The abbreviated commit hash we show in the shell and the about
dialog is currently just the last 7 characters of 'git describe',
based on the assumption that abbreviated hashes are always 7-digits
long. When the hash is longer than that, we're just showing a
nonsense commit.
This was never a good idea, since users can override this, and
since disambiguation can result in longer hashes, but since git
2.11, the default abbreviated hash length is determined based on
the size of the repository, which currently results in 10 digits
for us.
Let's just do it right.
It is a little fuzzy whether expected or not, architecturally-wise. On
one hand, I can see some core/ header includes under config/. Though on
the other hand, app/Makefile.am explicitly sorts config/ below core/.
Anyway let's just use g_cclosure_marshal_VOID__VOID which is the same as
gimp_marshal_VOID__VOID and get rid of the include.
This fixes builds from scratch.
It was agreed that we should write "plug-in" consistently. Only possibly
user-visible strings were updated.
Thanks to scootergrisen for a first patch which could not make it
after changing decision on the canonical writing.
Current code only guess resolution for a single monitor. Ideally
the widget sizes could be different depending on the window where a
given widget is on. But that's a start.
In particular all rotate/flip actions can apply to an image or drawable.
Let's make it clear, especially when it is run out of the menu context,
for instance in the action search.
which unlike HSL Lightness is actually physically meaningful and
also generally speaking much more useful than HSL Lightness.
Change "Lightness" to "Lightness (HSL)" to make it clear that
the "Lightness" in the Colors/Desaturate/Desaturate menu is not the
same as "Lightness" in LAB/LCH.
For completeness add the option to desaturate to "Value (HSV)".
Add links in app/operations/gimpoperationdesaturate.c
to the Wikipedia article with definitions of L/I/V in HSL/HSI/HSV.
Use gimp_item_translate() instead of gimp_item_set_offset() to set
a pasted item's position, so that the offsets of pasted layer group
children are updated correctly. Otherwise, only the group itself
moves, while its children remain positioned relative to the top-left
corner of the image.
... since that's the color space it actually works in.
Keep the legacy "Color (HSV)" mode's name as is, wrong as it is,
since, well, that's what it used to be called...
No need to do full back and forth RGB/HSV conversions.
Change the behavior such that fully desaturated values remain
desaturated, instead of saturating towards red.
Pixels whose source or destination alpha is zero are not blended, and
therefore do not need to be converted between the composite and blend
spaces (assuming a conversion is necessary to begin with.) When there
is a large enough segment of consecutive pixels that don't need
blending, split the conversion/blending process around it, so that
we don't convert too many unblended pixels unnecessarily.
For layers with lots of transparency, this can dramatically reduce
compositing time; for layers with no transparency, the added
overhead is rather negligible.
When adding an item to a filter stack that doesn't have a graph yet,
calling gimp_filter_stack_update_last_node() may ultimately lead to
the invocation of gimp_filter_stack_get_graph(), which would create
a new graph, and add the item's node to it; gimp_filter_stack_add()
would then erroneously attempt to re-add the node to the graph.
Fix this by calling gimp_filter_stack_update_last_node() after
(potentially) adding the node to the graph in
gimp_filter_stack_add().
The function has been unused since commit b5cc2a9.
Its work is now divided into gimp_tool_palette_set_toolbox() and
gimp_tool_palette_hierarchy_changed().
Argh! Always triple-check commits before pushing!
Commit e30c92c had completely wrong big values, which I was using
to make tab border update really visible while testing.
Allow overriding icon sizes set in themes from the preferences.
This initial commit updates only toolbox icons. More to come.
4 options are available: small, medium, large and huge (the later would
likely be useful for HiDPI screens).
Uses a new widget GimpIconSizeScale.
Merge mode lays the source layer on top of the destination, same as
normal mode, however, it assumes the source and destination are two
parts of an original whole, and are therefore mutually exclusive.
This is useful for blending cut & pasted content without artifacts,
or for replacing erased content in general.
Calculates the dot product of the two input colors, and uses that
as the value for all the output color's components. Basically,
a per-pixel mono mixer.
Useful for custom desaturation, component extraction, and crazier
stuff (bump mapping!)
Include erase mode in the menu for layers and general paint tools.
This makes the eraser tool somewhat unnecessary, but allows for
interesting use cases (e.g., airbrush eraser, etc.)
... possibly due to small win32 stack
Limit the number of samples processed in one go by gimp_composite_blend()
so that we don't overflow the stack when we alloca() buffers on it.
... and get rid of the dedicated op. This gives us support for all
the blend/composite options for this mode.
Rename COLOR_ERASE to COLOR_ERASE_LEGACY, with perceptual blending/
compositing and immutable everything, and add a new COLOR_ERASE
mode, defaulting to linear blending/compositing, with mutable
everything. Modify affected code.
These are more general, and more expensive, versions of the non-
subtractive compositing functions. They are used with modes that
specify the SUBTRACTIVE flag. This doesn't affect anything yet, but
the next commit ports color-erase mode to a blendfun.