Commit graph

24 commits

Author SHA1 Message Date
Jehan
5ff80c7dfb app: fix duplicating link layers.
Link layer duplicates were reusing the same GimpLink as the original
layer, because the properties sync was done after we created a new link
object.
2025-11-08 13:34:16 +01:00
Jehan
8a0754a5be Issue #15121: link layer positioning problem.
Only store a PROP_TRANSFORM if there is a transform. Otherwise the
stored offsets are bogus and would only break the position at load.
2025-11-08 12:37:45 +01:00
Jehan
1235bf00bd app: factorize auto-rename code into GimpRasterizable.
Rasterizable objects are all created from some side data and can be
renamed automatically based on this data (from the link file for link
layers; from the path for vector layers; from the text for text layers).

So let's share code.
2025-10-22 22:29:19 +02:00
Jehan
c5cdea4842 app: copy the rasterization state for all 3 types implementing GimpRasterizable. 2025-10-14 22:06:04 +02:00
Jehan
d593cb3230 app, pdb, po: new GimpRasterizable interface.
Share the whole rasterize logic of the text, link and vector layer into
an interface. I didn't write it as an abstract parent class, because we
might have more rasterizable items in the future, which may not be
layers (e.g. there were discussions of vector masks).
2025-10-13 15:37:11 +02:00
Jehan
7c7f7b4898 app, libgimpwidgets: add 2 new icon macros.
New libgimpwidgets icon macros: GIMP_ICON_LAYER_LINK_LAYER and
GIMP_ICON_LAYER_VECTOR_LAYER. Note that the actual icons still need to
be done so I use temporary actual icon designs for now.

Also adding some TODOs for these.

Fix run warning:

> WARNING: icon theme has no icon 'gimp-vector-layer'.
2025-10-10 23:34:37 +02:00
Jehan
38c379cd92 app: properly forbid paint tools to draw on link layers and forbid…
… filter tools to merge filters, both on link and vector layers.
2025-08-30 10:12:17 +02:00
Jehan
4f3aee5e83 Issue #14759: link layers (of vector files) initial dimensions will fill…
… the whole canvas while keeping aspect ratio of the source image.

The previous dimensions were not entirely "out of the blue" since they
were taken from the file, but very often dimensions from vector images
are kinda bogus (apart from aspect ratio, they don't mean much) anyway.

Now we will just fill the canvas box by default.

When changing the source file of an existing link layer though (through
Link Layer properties), the dimensions will be within the current layer
bounding box.

Also I realized that we need to also store the link width/height in the
XCF because the buffer width/height may not be right (in case a
transform matrix was applied). This commit therefore breaks XCF file
with link layers made in the last 2 days. Since we have not made even a
dev release, it's probably fine to do this and not bump the XCF version.
2025-08-28 23:13:03 +02:00
Jehan
16a1283f07 Issue #14758: link layers resize can not be undone. 2025-08-27 19:36:02 +02:00
Jehan
1f79e4314e Issue #14760: fix wrong offset when scaling a link layer.
This commit also makes the scaling detection a bit more forgiving to
"imperfect" scale matrix by using an epsilon low enough that it probably
won't make much of a big difference, transform-wise, while it would make
a big difference quality-wise.
2025-08-27 19:35:56 +02:00
Jehan
97bf7e1bfa app: rework load/save of link layers.
- We now bump to XCF version 25 since vector layers were implemented in
  XCF 24.
- Fix some now broken code in saving/loading, also rename
  PROP_LINK_LAYER_DATA to simply PROP_LINK_LAYER and use the generic
  gimp_layer_from_layer() which I created in commit afb8867bce and is
  also used for text and vector layers.
- Add a PROP_TRANSFORM layer property. It is separate from
  PROP_LINK_LAYER because I will likely reuse this for other (all even)
  types of layers as well.
2025-08-27 11:34:04 +02:00
Jehan
95f1d768c3 app: link layers must still have a converted buffer.
Otherwise we may end up with discrepancy such as layers having a u8
buffer on a u16 image.
2025-08-27 11:34:04 +02:00
Jehan
8280058c5a app: properly reapply the transform matrix after link layer source updated.
Also make sure that a link layer duplicate shows the proper contents
too!
2025-08-27 11:34:04 +02:00
Jehan
2821dbab58 app: add generic support for less destructive transform tools.
This commit will make all transform tools run on a link layer cumulate
their transform matrix on top of the previous transform steps. It means
that as long as you don't edit the pixels another way (e.g. with a paint
tool), all your transformations will apply as a single transformation.

For instance it means that applying several transform tool steps on a
monitored link layer will be less destructive than applying the exact
same transformations on the exact same "normal" layer contents.
Even scaling an image to 1x1 then back to a big size will work very
fine!

Note nevertheless the following limitations in current implementation:

* The link layer with transformations will still show as a standard link
  layer. Nothing says it has transformation applied on it right now.
* To drop transformations applied on a link layer, you have to discard
  the link info, then monitor the link again. A specific action in the
  contextual menu could be worth it.
* This should work with all transform tools (scale, rotation, unified,
  perspective, 3D, even Warp…) but it won't work for the Flip tool, nor
  will it work for the Transform actions. I will need to implement
  GimpItem's rotate(), flip() and resize() methods next.
* The layer mask would still be destructively transformed (I have not
  made any tests with layer masks yet, but this should be done next
  too).
* I think that the "scaled-only" property is now meaningless. It is now
  being replaced by the presence of the GimpMatrix3. Nevertheless I have
  still not removed this property.
* The load/save code has not been redone yet to include all these
  changes.

The kind of caveats we'd have to know about (and which are not planned
for change, because it's just how it is):

* Any intermediate interpolation methods are dropped when cumulating
  transform steps. Only the last interpolation is stored. This is
  because anyway the interpolation is only there as the best algorithm
  where we visually see the less quality loss. Applying several
  transformations as a single matrix will always be visually better than
  applying several matrices (whatever the intermediate interpolation
  methods chosen).
* This only works with the "Adjust" clipping method (basically no
  clipping) because 2 transform steps with clipping won't produce the
  same result as the multiplied matrix with clipping. It means that
  applying a transform with clipping will downgrade your link layer to
  being a normal layer.
  The only issue I have with this is how to best convey that clipping is
  a major setting setting here, which disables our less-destructive
  abilities. Right now, people will just have to "know" it.
* Vector link layers in particular will have 2 levels of
  non/less-destructivity transforms. In particular any scaling (both
  through "Scale Image", "Scale Layers" and transform tools — since I
  added code to detect a matrix doing only scaling and optionally
  translation) done **first** will be completely non-destructive since
  we will simply reload the original vector source at the right
  dimensions. Any other kind of transforms will be appended through the
  cumulative matrix, as raster link layers. This also includes scaling
  done **after** other transforms, since we cannot easily move the
  scaling first (matrix multiplication is not commutative). This second
  level of scaling will therefore be *less* destructive, but still
  destructive.
  It is possible eventually to improve the whole thing if we add some
  day the ability to request loading a vector image with a transform
  matrix (it will then be up to each vector format plug-in to support
  this feature or not).

Note: it could be argued that this whole implementation could in fact be
moved over to base layers, since it would allow also less-destructivity
when applying multiple transformations in a row. We would only merge
results once we edit pixels more directly.
But I think that it's not a bad idea to experiment with this new code in
the link layer. Eventually I may likely move this to the parent
GimpLayer if no blocking issues are found.
2025-08-27 11:34:04 +02:00
Jehan
3e5fce27cb app: move logic to know if a link layer is being monitored to GimpLink.
Instead of keeping a "modified" property in GimpLinkLayer, we just check
if the link is being monitored. It's also a better wording because we
may "discard the link information" without actually modifying the layer
pixels.

Also I now actually shut down the file monitoring process. This can be a
bit expensive so when we don't need it, let's really free the
GFileMonitor.

This commit also fixes scaling of link layer (which got broken along the
way) and improves the undo code.

Note: I'll probably want to modify the XCF flags, but let's do this in
the end, depending on further changes too.
2025-08-27 11:34:04 +02:00
Jehan
4128c789f9 app: more efficient GimpLink rendering.
We now re-render a link (by loading its file) immediately upon setting
the new file, i.e. during the calls of gimp_link_new() or
gimp_link_set_file(). As part of this change:

* A GimpLink now stores a GeglBuffer. And this is changed each time a
  file change happens (per the GFileMonitor). In particular that also
  means that gimp_link_get_buffer() does not reload the image file at
  each call for no reasons, and gimp_link_is_broken() does not have a
  `recheck` argument either. This is much more efficient.
* These 2 functions also have a GimpProgress and GError now. We use this
  among other things to pass on a specific GimpProgress object. In
  particular, the image file dialogs now show correct loading
  progression again.
* As a general rule, the code is less confusing as we don't have to
  wonder whether a GimpLink is ready. We can assume it always is, from
  now on.

Note that gimp_link_duplicate() does not trigger a reload of the image
file. Since we assume that the source GimpLink is supposed to be
up-to-date already, we just copy its buffer as-is as an optimization.
2025-08-27 11:34:04 +02:00
Jehan
0b8397ff56 app: "Discard Links" and undo should trigger thumbnail update.
Even if no actual drawable change may have happen, let's manually
trigger an "update" signal, hence triggering thumbnail updates too, but
also contextual menu update in the Layers dockable.
2025-08-27 11:34:04 +02:00
Jehan
9b0f426fbd app: all images (except remote files, XCF and compressed XCF) opened as links.
This is still mostly a test of workflow. It is based on the idea that
link layers are normal yet enhanced layers: eventually we should be able
to have some improved less-destructive scaling/rotation (even without
NDE transform effects); you can manually drop the link anytime anyway
(hence getting back to the good old fully destructive workflow); any
pixel editing automatically drops the link too.

Now this still raises quite a lot of questions:

* The link can be confusing to people used to the old way and they may
  not realize that editing the original file separately would also
  update the render in this file (which may not be what they wanted;
  maybe they just wanted to grab a snapshot of this file at a given
  time).
* You could also want to link XCF files.
* You could also want to link remote files (especially in a controlled
  network environment).
* Linked images are currently taken as a whole; we definitely want layer
  support to handle multi-layer image formats (so that you could link
  only a single layer, or a collection of layers; do we want to be able
  to edit visibility of linked layers separately too? Would be neat). So
  how would we handle automatic linking when opening a file? Maybe we
  just reproduce the layer structure as link layers (one link layer
  monitoring only one layer from the linked file)?

Anyway this is work-in-progress, UX-wise.
2025-08-27 11:34:04 +02:00
Jehan
2dac66d979 app: fix gimp_link_layer_duplicate() for modified link layers. 2025-08-27 11:34:04 +02:00
Jehan
f4a2158458 app: scale linked raster images back from source file.
Unless other types of edits have been done on a link layer (e.g.
painting), we avoid quality loss by multiple scaling of raster link
layers by always re-scaling from the source file.
2025-08-27 11:34:04 +02:00
Jehan
28bf061f4d app: properly handle vector images as link layers.
This commit was edited after GIMP 3.0, now that we have dedicated
support for loading vector images with GimpVectorLoadProcedure.

- By default, when loaded as GimpLinkLayer, vector images are loaded at
  a size so that they are exactly contained in the image.
- When scaled with Scale Layer dialog, link layers of type vector are
  re-loaded from the source file to always stay perfectly crisp.
2025-08-27 11:34:03 +02:00
Jehan
0b5aa01bb9 app: more rebasing after GIMP 3.0 release. 2025-08-27 11:34:03 +02:00
Jehan
6e91826865 app: add saving/loading of link layers. 2025-08-27 11:34:03 +02:00
Jehan
20083bcabe app: new link layers.
These are layers who content depends on another source (right now only
an external image). This can be useful when for instance working at
several people on a single artwork, hence being able to load new
versions of an image without even touching anything in the XCF (for
instance, say you draw an animated character while someone else is
taking care of the background).

Similarly to what we do for text layers, once you start modifying the
contents, it turns into a "normal" layer. The link information is still
available though, so it is possible to revert to the monitoring state
with the menu item "Monitor Linked Image" which appear when a link layer
became a normal layer.

This is not finale as I'm still experimenting. In particular, I have not
implemented XCF saving/loading yet for this new layer type.
2025-08-27 11:34:03 +02:00