[gimp] Bug 768872 - Tiling Symmetry doesn't wrap vertical coordinates over...
- From: Jehan Pagès <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 768872 - Tiling Symmetry doesn't wrap vertical coordinates over...
- Date: Wed, 11 Apr 2018 00:13:26 +0000 (UTC)
commit 1993d8a4a78fbd424a535ed31be9e5b36f37f8f9
Author: Jehan <jehan girinstud io>
Date: Wed Apr 11 02:09:21 2018 +0200
Bug 768872 - Tiling Symmetry doesn't wrap vertical coordinates over...
... edges for MyPaint brush.
Adding the concept of "stateful" symmetry when a tool needs to make sure
of corresponding stroke numbers and orders while painting (i.e. stroke N
at time T+1 is the continuation of stroke N at time T). This is the case
for the MyPaint brushes and the ink tool.
app/core/gimpsymmetry-tiling.c | 117 ++++++++++++++++++++++++++++++----------
app/core/gimpsymmetry.c | 27 +++++++++
app/core/gimpsymmetry.h | 3 +
app/paint/gimpink.c | 2 +
app/paint/gimpmybrushcore.c | 2 +
5 files changed, 123 insertions(+), 28 deletions(-)
---
diff --git a/app/core/gimpsymmetry-tiling.c b/app/core/gimpsymmetry-tiling.c
index 7b519f8..dfd2db3 100644
--- a/app/core/gimpsymmetry-tiling.c
+++ b/app/core/gimpsymmetry-tiling.c
@@ -324,45 +324,106 @@ gimp_tiling_update_strokes (GimpSymmetry *sym,
width = gimp_item_get_width (GIMP_ITEM (drawable));
height = gimp_item_get_height (GIMP_ITEM (drawable));
- if (origin->x > 0 && tiling->max_x == 0 && tiling->interval_x >= 1.0)
- startx = fmod (origin->x, tiling->interval_x) - tiling->interval_x;
-
- if (origin->y > 0 && tiling->max_y == 0 && tiling->interval_y >= 1.0)
+ if (sym->stateful)
{
- starty = fmod (origin->y, tiling->interval_y) - tiling->interval_y;
+ /* While I can compute exactly the right number of strokes to
+ * paint on-canvas for stateless tools, stateful tools need to
+ * always have the same number and order of strokes. For this
+ * reason, I compute strokes to fill 2 times the width and height.
+ * This makes the symmetry less efficient with stateful tools, but
+ * also weird behavior may happen if you decide to paint out of
+ * canvas and expect tiling to work in-canvas since it won't
+ * actually be infinite (as no new strokes can be added while
+ * painting since we are stateful).
+ */
+ gint i, j;
+
+ if (tiling->interval_x < 1.0)
+ {
+ x_count = 1;
+ }
+ else if (tiling->max_x == 0)
+ {
+ x_count = (gint) ceil (width / tiling->interval_x);
+ startx -= tiling->interval_x * (gdouble) x_count;
+ x_count = 2 * x_count + 1;
+ }
+ else
+ {
+ x_count = tiling->max_x;
+ }
- if (tiling->shift > 0.0)
- startx -= tiling->shift * floor (origin->y / tiling->interval_y + 1);
- }
+ if (tiling->interval_y < 1.0)
+ {
+ y_count = 1;
+ }
+ else if (tiling->max_y == 0)
+ {
+ y_count = (gint) ceil (height / tiling->interval_y);
+ starty -= tiling->interval_y * (gdouble) y_count;
+ y_count = 2 * y_count + 1;
+ }
+ else
+ {
+ y_count = tiling->max_y;
+ }
+
+ for (i = 0, x = startx; i < x_count; i++)
+ {
+ for (j = 0, y = starty; j < y_count; j++)
+ {
+ coords = g_memdup (origin, sizeof (GimpCoords));
+ coords->x = x;
+ coords->y = y;
+ strokes = g_list_prepend (strokes, coords);
- for (y_count = 0, y = starty; y < height + tiling->interval_y;
- y_count++, y += tiling->interval_y)
+ y += tiling->interval_y;
+ }
+ x += tiling->interval_x;
+ }
+ }
+ else
{
- if (tiling->max_y && y_count >= tiling->max_y)
- break;
+ if (origin->x > 0 && tiling->max_x == 0 && tiling->interval_x >= 1.0)
+ startx = fmod (origin->x, tiling->interval_x) - tiling->interval_x;
- for (x_count = 0, x = startx; x < width + tiling->interval_x;
- x_count++, x += tiling->interval_x)
+ if (origin->y > 0 && tiling->max_y == 0 && tiling->interval_y >= 1.0)
{
- if (tiling->max_x && x_count >= tiling->max_x)
- break;
+ starty = fmod (origin->y, tiling->interval_y) - tiling->interval_y;
- coords = g_memdup (origin, sizeof (GimpCoords));
- coords->x = x;
- coords->y = y;
- strokes = g_list_prepend (strokes, coords);
+ if (tiling->shift > 0.0)
+ startx -= tiling->shift * floor (origin->y / tiling->interval_y + 1);
+ }
- if (tiling->interval_x < 1.0)
+ for (y_count = 0, y = starty; y < height + tiling->interval_y;
+ y_count++, y += tiling->interval_y)
+ {
+ if (tiling->max_y && y_count >= tiling->max_y)
break;
- }
- if (tiling->max_x || startx + tiling->shift <= 0.0)
- startx = startx + tiling->shift;
- else
- startx = startx - tiling->interval_x + tiling->shift;
+ for (x_count = 0, x = startx; x < width + tiling->interval_x;
+ x_count++, x += tiling->interval_x)
+ {
+ if (tiling->max_x && x_count >= tiling->max_x)
+ break;
- if (tiling->interval_y < 1.0)
- break;
+ coords = g_memdup (origin, sizeof (GimpCoords));
+ coords->x = x;
+ coords->y = y;
+ strokes = g_list_prepend (strokes, coords);
+
+ if (tiling->interval_x < 1.0)
+ break;
+ }
+
+ if (tiling->max_x || startx + tiling->shift <= 0.0)
+ startx = startx + tiling->shift;
+ else
+ startx = startx - tiling->interval_x + tiling->shift;
+
+ if (tiling->interval_y < 1.0)
+ break;
+ }
}
sym->strokes = strokes;
diff --git a/app/core/gimpsymmetry.c b/app/core/gimpsymmetry.c
index c4090f8..d2d875a 100644
--- a/app/core/gimpsymmetry.c
+++ b/app/core/gimpsymmetry.c
@@ -273,6 +273,33 @@ gimp_symmetry_real_update_version (GimpSymmetry *symmetry)
/***** Public Functions *****/
/**
+ * gimp_symmetry_set_stateful:
+ * @sym: the #GimpSymmetry
+ * @stateful: whether the symmetry should be stateful or stateless.
+ *
+ * By default, symmetry is made stateless, which means in particular
+ * that the size of points can change from one stroke to the next, and
+ * in particular you cannot map the coordinates from a stroke to the
+ * next. I.e. stroke N at time T+1 is not necessarily the continuation
+ * of stroke N at time T.
+ * To obtain corresponding strokes, stateful tools, such as MyPaint
+ * brushes or the ink tool, need to run this function. They should reset
+ * to stateless behavior once finished painting.
+ *
+ * One of the first consequence of being stateful is that the number of
+ * strokes cannot be changed, so more strokes than possible on canvas
+ * may be computed, and oppositely it will be possible to end up in
+ * cases with missing strokes (e.g. a tiling, theoretically infinite,
+ * won't be for the ink tool if one draws too far out of canvas).
+ **/
+void
+gimp_symmetry_set_stateful (GimpSymmetry *symmetry,
+ gboolean stateful)
+{
+ symmetry->stateful = stateful;
+}
+
+/**
* gimp_symmetry_set_origin:
* @sym: the #GimpSymmetry
* @drawable: the #GimpDrawable where painting will happen
diff --git a/app/core/gimpsymmetry.h b/app/core/gimpsymmetry.h
index 7e2de45..9cd0317 100644
--- a/app/core/gimpsymmetry.h
+++ b/app/core/gimpsymmetry.h
@@ -50,6 +50,7 @@ struct _GimpSymmetry
gint version;
GList *strokes;
+ gboolean stateful;
};
struct _GimpSymmetryClass
@@ -74,6 +75,8 @@ struct _GimpSymmetryClass
GType gimp_symmetry_get_type (void) G_GNUC_CONST;
+void gimp_symmetry_set_stateful (GimpSymmetry *symmetry,
+ gboolean stateful);
void gimp_symmetry_set_origin (GimpSymmetry *symmetry,
GimpDrawable *drawable,
GimpCoords *origin);
diff --git a/app/paint/gimpink.c b/app/paint/gimpink.c
index 3a3e6d8..32af20a 100644
--- a/app/paint/gimpink.c
+++ b/app/paint/gimpink.c
@@ -168,6 +168,7 @@ gimp_ink_paint (GimpPaintCore *paint_core,
GimpContext *context = GIMP_CONTEXT (paint_options);
GimpRGB foreground;
+ gimp_symmetry_set_stateful (sym, TRUE);
gimp_context_get_foreground (context, &foreground);
gimp_palettes_add_color_history (context->gimp,
&foreground);
@@ -217,6 +218,7 @@ gimp_ink_paint (GimpPaintCore *paint_core,
break;
case GIMP_PAINT_STATE_FINISH:
+ gimp_symmetry_set_stateful (sym, FALSE);
break;
}
}
diff --git a/app/paint/gimpmybrushcore.c b/app/paint/gimpmybrushcore.c
index eb65057..52ef69e 100644
--- a/app/paint/gimpmybrushcore.c
+++ b/app/paint/gimpmybrushcore.c
@@ -212,6 +212,7 @@ gimp_mybrush_core_paint (GimpPaintCore *paint_core,
case GIMP_PAINT_STATE_INIT:
gimp_context_get_foreground (context, &fg);
gimp_palettes_add_color_history (context->gimp, &fg);
+ gimp_symmetry_set_stateful (sym, TRUE);
mybrush->private->surface =
gimp_mypaint_surface_new (gimp_drawable_get_buffer (drawable),
@@ -233,6 +234,7 @@ gimp_mybrush_core_paint (GimpPaintCore *paint_core,
break;
case GIMP_PAINT_STATE_FINISH:
+ gimp_symmetry_set_stateful (sym, FALSE);
mypaint_surface_unref ((MyPaintSurface *) mybrush->private->surface);
mybrush->private->surface = NULL;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]