Commit 1993d8a4 authored by Jehan's avatar Jehan

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.
parent 12ec7976
......@@ -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;
......
......@@ -272,6 +272,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
......
......@@ -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);
......
......@@ -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;
}
}
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment