mirror of https://github.com/GNOME/gimp.git
app: use gradient cache for conical gradients
Add gimp_drawable_gradient_adjust_coords(), which adjusts the gradient segment coords according to the gradient type, so that, in cases where the gradient span is unrelated to the segment length, the gradient cache (in GimpOperationGradient) is big enough not to produce banding. Use the new function in gimp_drawable_gradient() and in the gradient tool, instead of duplicating the logic. Move the shapreburst coordinate-adjustment logic to the new function, and add appropriate logic for conical gradients. Remove the code that avoids using the gradient cache for conical gradients from GimpOperationGradient.
This commit is contained in:
parent
38ba45cf31
commit
5970046e25
|
@ -21,6 +21,8 @@
|
||||||
#include <gegl.h>
|
#include <gegl.h>
|
||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
|
||||||
|
#include "libgimpmath/gimpmath.h"
|
||||||
|
|
||||||
#include "core-types.h"
|
#include "core-types.h"
|
||||||
|
|
||||||
#include "gegl/gimp-gegl-apply-operation.h"
|
#include "gegl/gimp-gegl-apply-operation.h"
|
||||||
|
@ -93,17 +95,13 @@ gimp_drawable_gradient (GimpDrawable *drawable,
|
||||||
gimp_drawable_gradient_shapeburst_distmap (drawable, metric,
|
gimp_drawable_gradient_shapeburst_distmap (drawable, metric,
|
||||||
GEGL_RECTANGLE (x, y, width, height),
|
GEGL_RECTANGLE (x, y, width, height),
|
||||||
progress);
|
progress);
|
||||||
|
|
||||||
/* in shapeburst mode, make sure the "line" is long enough to
|
|
||||||
* span across the selection, so the operation's cache has the
|
|
||||||
* right size
|
|
||||||
*/
|
|
||||||
startx = x;
|
|
||||||
starty = y;
|
|
||||||
endx = x + width;
|
|
||||||
endy = y + height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gimp_drawable_gradient_adjust_coords (drawable,
|
||||||
|
gradient_type,
|
||||||
|
GEGL_RECTANGLE (x, y, width, height),
|
||||||
|
&startx, &starty, &endx, &endy);
|
||||||
|
|
||||||
render = gegl_node_new_child (NULL,
|
render = gegl_node_new_child (NULL,
|
||||||
"operation", "gimp:gradient",
|
"operation", "gimp:gradient",
|
||||||
"context", context,
|
"context", context,
|
||||||
|
@ -235,3 +233,73 @@ gimp_drawable_gradient_shapeburst_distmap (GimpDrawable *drawable,
|
||||||
|
|
||||||
return dist_buffer;
|
return dist_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gimp_drawable_gradient_adjust_coords (GimpDrawable *drawable,
|
||||||
|
GimpGradientType gradient_type,
|
||||||
|
const GeglRectangle *region,
|
||||||
|
gdouble *startx,
|
||||||
|
gdouble *starty,
|
||||||
|
gdouble *endx,
|
||||||
|
gdouble *endy)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
||||||
|
g_return_if_fail (region != NULL);
|
||||||
|
g_return_if_fail (startx != NULL);
|
||||||
|
g_return_if_fail (starty != NULL);
|
||||||
|
g_return_if_fail (endx != NULL);
|
||||||
|
g_return_if_fail (endy != NULL);
|
||||||
|
|
||||||
|
/* we potentially adjust the gradient coordinates according to the gradient
|
||||||
|
* type, so that in cases where the gradient span is not related to the
|
||||||
|
* segment length, the gradient cache (in GimpOperationGradient) is big
|
||||||
|
* enough not to produce banding.
|
||||||
|
*/
|
||||||
|
|
||||||
|
switch (gradient_type)
|
||||||
|
{
|
||||||
|
/* for conical gradients, use a segment with the original origin and
|
||||||
|
* direction, whose length is the circumference of the largest circle
|
||||||
|
* centered at the origin, passing through one of the regions's vertices.
|
||||||
|
*/
|
||||||
|
case GIMP_GRADIENT_CONICAL_SYMMETRIC:
|
||||||
|
case GIMP_GRADIENT_CONICAL_ASYMMETRIC:
|
||||||
|
{
|
||||||
|
gdouble r = 0.0;
|
||||||
|
GimpVector2 v;
|
||||||
|
|
||||||
|
r = MAX (r, hypot (region->x - *startx,
|
||||||
|
region->y - *starty));
|
||||||
|
r = MAX (r, hypot (region->x + region->width - *startx,
|
||||||
|
region->y - *starty));
|
||||||
|
r = MAX (r, hypot (region->x - *startx,
|
||||||
|
region->y + region->height - *starty));
|
||||||
|
r = MAX (r, hypot (region->x + region->width - *startx,
|
||||||
|
region->y + region->height - *starty));
|
||||||
|
|
||||||
|
gimp_vector2_set (&v, *endx - *startx, *endy - *starty);
|
||||||
|
gimp_vector2_normalize (&v);
|
||||||
|
gimp_vector2_mul (&v, 2.0 * G_PI * r);
|
||||||
|
|
||||||
|
*endx = *startx + v.x;
|
||||||
|
*endy = *starty + v.y;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* for shaped gradients, only the segment's length matters; use the
|
||||||
|
* regions's diagonal, which is the largest possible distance between two
|
||||||
|
* points in the region.
|
||||||
|
*/
|
||||||
|
case GIMP_GRADIENT_SHAPEBURST_ANGULAR:
|
||||||
|
case GIMP_GRADIENT_SHAPEBURST_SPHERICAL:
|
||||||
|
case GIMP_GRADIENT_SHAPEBURST_DIMPLED:
|
||||||
|
*startx = region->x;
|
||||||
|
*starty = region->y;
|
||||||
|
*endx = region->x + region->width;
|
||||||
|
*endy = region->y + region->height;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,32 +19,39 @@
|
||||||
#define __GIMP_DRAWABLE_GRADIENT_H__
|
#define __GIMP_DRAWABLE_GRADIENT_H__
|
||||||
|
|
||||||
|
|
||||||
void gimp_drawable_gradient (GimpDrawable *drawable,
|
void gimp_drawable_gradient (GimpDrawable *drawable,
|
||||||
GimpContext *context,
|
GimpContext *context,
|
||||||
GimpGradient *gradient,
|
GimpGradient *gradient,
|
||||||
GeglDistanceMetric metric,
|
GeglDistanceMetric metric,
|
||||||
GimpLayerMode paint_mode,
|
GimpLayerMode paint_mode,
|
||||||
GimpGradientType gradient_type,
|
GimpGradientType gradient_type,
|
||||||
gdouble opacity,
|
gdouble opacity,
|
||||||
gdouble offset,
|
gdouble offset,
|
||||||
GimpRepeatMode repeat,
|
GimpRepeatMode repeat,
|
||||||
gboolean reverse,
|
gboolean reverse,
|
||||||
GimpGradientBlendColorSpace blend_color_space,
|
GimpGradientBlendColorSpace blend_color_space,
|
||||||
gboolean supersample,
|
gboolean supersample,
|
||||||
gint max_depth,
|
gint max_depth,
|
||||||
gdouble threshold,
|
gdouble threshold,
|
||||||
gboolean dither,
|
gboolean dither,
|
||||||
gdouble startx,
|
gdouble startx,
|
||||||
gdouble starty,
|
gdouble starty,
|
||||||
gdouble endx,
|
gdouble endx,
|
||||||
gdouble endy,
|
gdouble endy,
|
||||||
GimpProgress *progress);
|
GimpProgress *progress);
|
||||||
|
|
||||||
GeglBuffer *
|
GeglBuffer * gimp_drawable_gradient_shapeburst_distmap (GimpDrawable *drawable,
|
||||||
gimp_drawable_gradient_shapeburst_distmap (GimpDrawable *drawable,
|
GeglDistanceMetric metric,
|
||||||
GeglDistanceMetric metric,
|
const GeglRectangle *region,
|
||||||
const GeglRectangle *region,
|
GimpProgress *progress);
|
||||||
GimpProgress *progress);
|
|
||||||
|
void gimp_drawable_gradient_adjust_coords (GimpDrawable *drawable,
|
||||||
|
GimpGradientType gradient_type,
|
||||||
|
const GeglRectangle *region,
|
||||||
|
gdouble *startx,
|
||||||
|
gdouble *starty,
|
||||||
|
gdouble *endx,
|
||||||
|
gdouble *endy);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __GIMP_DRAWABLE_GRADIENT_H__ */
|
#endif /* __GIMP_DRAWABLE_GRADIENT_H__ */
|
||||||
|
|
|
@ -1226,21 +1226,6 @@ gimp_operation_gradient_validate_cache (GimpOperationGradient *self)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (self->gradient_type)
|
|
||||||
{
|
|
||||||
case GIMP_GRADIENT_CONICAL_SYMMETRIC:
|
|
||||||
case GIMP_GRADIENT_CONICAL_ASYMMETRIC:
|
|
||||||
/* don't use a gradient cache for conical gradients, since the necessary
|
|
||||||
* cache size is not related to the line length
|
|
||||||
*/
|
|
||||||
g_mutex_unlock (&self->gradient_cache_mutex);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cache_size = ceil (hypot (self->start_x - self->end_x,
|
cache_size = ceil (hypot (self->start_x - self->end_x,
|
||||||
self->start_y - self->end_y)) *
|
self->start_y - self->end_y)) *
|
||||||
GRADIENT_CACHE_N_SUPERSAMPLES;
|
GRADIENT_CACHE_N_SUPERSAMPLES;
|
||||||
|
|
|
@ -875,8 +875,9 @@ gimp_gradient_tool_create_graph (GimpGradientTool *gradient_tool)
|
||||||
static void
|
static void
|
||||||
gimp_gradient_tool_update_graph (GimpGradientTool *gradient_tool)
|
gimp_gradient_tool_update_graph (GimpGradientTool *gradient_tool)
|
||||||
{
|
{
|
||||||
GimpTool *tool = GIMP_TOOL (gradient_tool);
|
GimpTool *tool = GIMP_TOOL (gradient_tool);
|
||||||
gint off_x, off_y;
|
GimpGradientOptions *options = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
|
||||||
|
gint off_x, off_y;
|
||||||
|
|
||||||
gimp_item_get_offset (GIMP_ITEM (tool->drawable), &off_x, &off_y);
|
gimp_item_get_offset (GIMP_ITEM (tool->drawable), &off_x, &off_y);
|
||||||
|
|
||||||
|
@ -912,35 +913,29 @@ gimp_gradient_tool_update_graph (GimpGradientTool *gradient_tool)
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (gimp_gradient_tool_is_shapeburst (gradient_tool))
|
GeglRectangle roi;
|
||||||
{
|
gdouble start_x, start_y;
|
||||||
/* in shapeburst mode, make sure the "line" is long enough
|
gdouble end_x, end_y;
|
||||||
* to span across the selection, so the operation's cache
|
|
||||||
* has the right size
|
|
||||||
*/
|
|
||||||
|
|
||||||
GimpImage *image = gimp_display_get_image (tool->display);
|
gimp_item_mask_intersect (GIMP_ITEM (tool->drawable),
|
||||||
gdouble x, y, w, h;
|
&roi.x, &roi.y, &roi.width, &roi.height);
|
||||||
|
|
||||||
gimp_item_bounds_f (GIMP_ITEM (gimp_image_get_mask (image)),
|
start_x = gradient_tool->start_x - off_x;
|
||||||
&x, &y, &w, &h);
|
start_y = gradient_tool->start_y - off_y;
|
||||||
|
end_x = gradient_tool->end_x - off_x;
|
||||||
|
end_y = gradient_tool->end_y - off_y;
|
||||||
|
|
||||||
gegl_node_set (gradient_tool->render_node,
|
gimp_drawable_gradient_adjust_coords (tool->drawable,
|
||||||
"start-x", x,
|
options->gradient_type,
|
||||||
"start-y", y,
|
&roi,
|
||||||
"end-x", x + w,
|
&start_x, &start_y, &end_x, &end_y);
|
||||||
"end-y", y + h,
|
|
||||||
NULL);
|
gegl_node_set (gradient_tool->render_node,
|
||||||
}
|
"start-x", start_x,
|
||||||
else
|
"start-y", start_y,
|
||||||
{
|
"end-x", end_x,
|
||||||
gegl_node_set (gradient_tool->render_node,
|
"end-y", end_y,
|
||||||
"start-x", gradient_tool->start_x - off_x,
|
NULL);
|
||||||
"start-y", gradient_tool->start_y - off_y,
|
|
||||||
"end-x", gradient_tool->end_x - off_x,
|
|
||||||
"end-y", gradient_tool->end_y - off_y,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue