Even clang-cl (the wrapper for MSVC) can't work with GNU C++.
So, let's use the ISO one.
As a result, we now set math.h/cmath defines on Windows builds.
This patch adds support for loading and
applying active legacy Outer Glow
layer styles in PSD images. It uses
gegl:dropshadow with certain preset values
to replicate the Photoshop filter.
To avoid duplicating code, I make a friend function to be reusable in
Paint Select options code: gimp_selection_options_get_mode_box().
I also get rid of GimpPaintSelectMode enum, which was clearly a
duplicate type to GimpChannelOps. Right now only ADD and SUBTRACT are
supported in Paint Select tool, yet we are perfectly able to generate
widgets showing only partial data. Which is what I do here by adding
appropriate min/max value args to the new function.
Note though that I don't see why we should not be able to replace or
intersect using Paint Select. But since these 2 modes are not
implemented right now, I haven't tried to add support in this commit.
For now, only making our GUI consistent so that Paint Select looks like
any other selection tools (simply only with 2 modes).
When the titlebar and menubar are merged, we
have control over the colors of the min/max/close buttons.
Some system themes define these colors in ways that
clash with our Default theme, so this patch adds explicit
CSS rules to ensure they match our theme style.
When a drawable is converted, we check if
it has filters. If any filter has a mask, we convert it
to use the new image instead of the old one.
This prevents several crashes where the filter's mask
still pointed to the old image if it was copy/pasted
into a new one.
Every time we press for a selection update, we will start with a blank
tri-map, instead of reusing previous "scribbles". In my various tests,
it felt like I would get better results this way. Also if you do some
mistakes (maybe getting off-border of your object in a previous stroke),
it would be much harder to fix, unless you are alway showing the
scribbles.
One can consider that once you edited the image selection, what is done
is done. You don't constantly edit the past, and your resulting
selection could have been done with any other selection tool (how it was
done doesn't matter anymore). This makes the tool actually stateless
in-between strokes.
Note that I reset the tri-map at the start of a stroke, rather than at
the end. This way, it still allows one to see the previous stroke (it
can be useful for verifying how it was done before undoing and
retrying).
This change won't do much right now, using upstream libmaxflow (though
it won't hurt either). It will really show its usefulness together once
this patch will have been merged in libmaxflow:
https://github.com/gerddie/maxflow/pull/8
… then once done, I will push also a small update in "gegl:paint-select"
code on GEGL repo, which will in turn report the progression as reported
by libmaxflow.
This is particularly needed for big images on limited hardware, which is
when the current algorithm or its implementation will start showing some
weakness. I had cases (on 4000×3000 images in Balanced power mode) where
the processing inside graph->maxflow() could take more than 10 seconds,
the GUI would look frozen and the desktop would warn you through a popup
that the software "is not responding" (with the option to kill the
process). Furthermore without any kind of feedback, you have no idea if
processing will be soon finished or if it will take 10 minutes, or 1
hour, or even if you may be stuck in some infinite loop. In such
conditions, even 10 seconds actually feel long and the software appear
broken.
But when you have the progression feedback, you see that processing is
soon finished, and when working on huge images, you may expect that some
things may take longer than others. In such a case, even longer time may
actually feel very acceptable.
Note: an alternative to show progression would have been to use a
GeglProcessor, but apparently it gets its progression status a different
way, by cutting the image into smaller pieces. This doesn't work with
"gegl:paint-select", or at least its current implementation. Using the
"progress" signal works fine though.
Increasing the viewport region with the region of same size, yet
centered around the cursor position (whether the button_release() one or
even any motion() position) doesn't make much sense.
If the idea is to limit the work on the viewport, which is indeed quite
interesting performance-wise, but also worflow-wise to allow targetting
parts of an image while ignoring the rest, then let's stick to the
actual viewport indeed!
I am only adding half the "brush size" to every edge of the viewport,
because technically we can move the cursor so that half of the brush
preview is off-view. Though even this, I am hesitating. Indeed
workflow-wise, it may be much more interesting to be able to really
limit where want the selection to stop. Selecting a bit further than
"what you see" may be unwanted, even if the brush itself could
technically go further.
… respectively Add or Subtract modes.
When all the "scribbles" are already inside the fully selected area, it
is likely unneeded to recompute the paint selection (it's not entirely
true, algorithmically-wise, but workflow-wise, it makes sense: if you
are not happy with your selection and want to add some parts of the
image, you would obviously "paint" in the area which you want to add in.
And reciprocally for removing some of the selection, you'd paint within
the existing selection.
This also cleans out some of the logic in the button_press() code, where
we were adding the initial "scribble" to the mask. In original code,
when clicking without any motion, what was happening was that you were
only adding this one round selection and nothing else was happening,
which I always found weird (when you want to add some tiny piece of the
image into the selection, you may not have a lot of space to move and
would still want to do a quick click while hoping it will compute a bit
more into the selection). Now the new code anyway computes during
button_release() so adding this initial small-round mask is even more
unneeded.
Last, I am moving more of the motion() code into button_release().
...on non-raster layers.
Resolve#15368
Per Bruno, the "Merge Filters" button on the
NDE filter pop-up should have the same warning
message if it is disabled as the "Merge Filter"
checkbox does in the Filter Tool itself.
Since the button is visible when there's a group
layer, a warning is also displayed for that, though
due to string freeze it is not yet set to be
translatable.
I can see why this was added when we used to re-process the graph during
motion (it was already slow and would have just been so much slower),
but if we only process at the end, it is simply counter-productive not
to store all motion events. It doesn't actually make the finale
processing (on release) slower, at least not obviously, and we get more
data for more accurate (hopefully) selection.
I can read in the source paper that the original goal was to have
instant feedback "as they drag the mouse", but truth is that right now,
this doesn't work out. On bigger images (yet reasonably sized, like
3000×4000, which is even smaller than what the paper claims should be
instant), we end up reprocessing for 10 seconds (on my laptop, in
"Balanced" power mode) multiple times in a single stroke!
Only processing on releasing the stroke (and only storing the
"scribbles" into the trimap during the stroke), we get back to a more
reasonable wait time, such as **once** 10 seconds on my test image and
laptop. And for smaller test images, like near-FullHD, we get very quick
processing on releasing the pointer click.
This may not be ideal, and the problem may be that our implementation is
not ideal and could be improved (I think it should be multi-threadable,
at least that's what it looks like when I read libmaxflow code — this is
where most of the processing time is actually spent! —, and also the
source paper mentions "multi-core graph-cut as an optimization). But
then we can revert to during-motion processing later. For now, all it
does is make this tool unusable.
GIMP's path import code is largely copied
from an earlier version of rsvg. Therefore,
it does not include updates that made
number processing more robust
(such as properly parsing 'c1.5.2' as '1.5, 0.2'
for curve coordinates)
Per the suggestion by @federico, this patch
updates our code using rsvg-path.c from
the last version of the C-based librsvg
(updated November 3rd, 2016).
Our original code also broke if there was any
spaces after the last item in the SVG transform
attribute. This patch adds a call to
g_strstrip () to trim any unnecessary spaces
either before or after the transform string
to prevent this issue.
- The "Healing Brush" paper URL is dead. It now leads to one of these
horrible parasitic websites which reuse domain names. And we for sure
don't want to promote this! I'm using instead the associated page on
our developer website. I just created this page and right now it's on
testing only. But this will be the URL for the main website.
- The URL for the foreground extraction paper is still valid, but from
my small research today when writing various algorithm' pages, I think
our own implementation diverged from this original paper (though it
may still have part of this original paper's algorithm; only a deeper
check of the code would tell).
See: https://testing.developer.gimp.org/core/algorithm/foreground-extraction/
Also this PDB procedure is called generically gimp_drawable_foreground_extract()
and it even has an argument to choose the algorithm (even though right
now, there is only a single choice, which is "Matting" algorithm, and
even there you can't choose which one; it's always Matting Global;
Matting Levin cannot be chosen for instance).
So anyway it is not a good idea to point to one specific algorithm,
and even less to leave an external URL (which may also disappear some
day) in API docs. So I am just getting rid of this paper title and
URL, and replace it with actually useful information, which is how to
set the trimap to represent foreground, background and uncertain
pixels (note: I notice that it would have been different with Matting
Levin where uncertain pixels must apparently be set transparent).
Since this is now a build breaker (on purpose), let's add some notes on
how to properly set your build system so that our list of GUI languages
are self-localized as we want them. I am guessing that if we don't add
this info, we may soon get reports by various distributions' packagers
about our build being broken.
This explains so much why I was regularly seeing screenshots of packaged
GIMP with a list of languages in English, in forums or tracker. Unlike
desktop machines, I am guessing that most build servers are just set as
C or POSIX locale and that would just break our pre-localization build
script.
Seems like our CI runners are configured with POSIX locale. Both C and
POSIX locales are basically overriding any attempt to localize during
the build (setting LANGUAGE doesn't work) and unfortunately we are now
self-localizing the list of languages during build.
So let's add a bogus en_US.UTF-8 locale before setting LANGUAGE. This
should fix the issue. It would probably also fix the same issue for
various third-party packages if distributions' build machines are set
similarly!
Resolves#15286
Adds a check to the memory allocation
in pnm_load_raw () with g_size_checked_mul ()
to see if the size would go out of bounds.
If so, we don't try to allocate and load the
image.