~ubuntu-branches/ubuntu/vivid/gimp/vivid

« back to all changes in this revision

Viewing changes to app/display/gimpmotionbuffer.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach
  • Date: 2012-05-08 18:50:03 UTC
  • mto: (1.1.26) (0.5.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 71.
  • Revision ID: package-import@ubuntu.com-20120508185003-tltkvbaysf8d2426
ImportĀ upstreamĀ versionĀ 2.8.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GIMP - The GNU Image Manipulation Program
 
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 3 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
16
 */
 
17
 
 
18
#include "config.h"
 
19
 
 
20
#include <string.h>
 
21
 
 
22
#include <gegl.h>
 
23
#include <gtk/gtk.h>
 
24
 
 
25
#include "libgimpmath/gimpmath.h"
 
26
 
 
27
#include "display-types.h"
 
28
 
 
29
#include "core/gimpcoords.h"
 
30
#include "core/gimpcoords-interpolate.h"
 
31
#include "core/gimpmarshal.h"
 
32
 
 
33
#include "gimpmotionbuffer.h"
 
34
 
 
35
 
 
36
/* Velocity unit is screen pixels per millisecond we pass to tools as 1. */
 
37
#define VELOCITY_UNIT        3.0
 
38
#define EVENT_FILL_PRECISION 6.0
 
39
#define DIRECTION_RADIUS     (1.5 / MAX (scale_x, scale_y))
 
40
#define SMOOTH_FACTOR        0.3
 
41
 
 
42
 
 
43
enum
 
44
{
 
45
  PROP_0
 
46
};
 
47
 
 
48
enum
 
49
{
 
50
  STROKE,
 
51
  HOVER,
 
52
  LAST_SIGNAL
 
53
};
 
54
 
 
55
 
 
56
/*  local function prototypes  */
 
57
 
 
58
static void     gimp_motion_buffer_dispose             (GObject          *object);
 
59
static void     gimp_motion_buffer_finalize            (GObject          *object);
 
60
static void     gimp_motion_buffer_set_property        (GObject          *object,
 
61
                                                        guint             property_id,
 
62
                                                        const GValue     *value,
 
63
                                                        GParamSpec       *pspec);
 
64
static void     gimp_motion_buffer_get_property        (GObject          *object,
 
65
                                                        guint             property_id,
 
66
                                                        GValue           *value,
 
67
                                                        GParamSpec       *pspec);
 
68
 
 
69
static void     gimp_motion_buffer_push_event_history  (GimpMotionBuffer *buffer,
 
70
                                                        const GimpCoords *coords);
 
71
static void     gimp_motion_buffer_pop_event_queue     (GimpMotionBuffer *buffer,
 
72
                                                        GimpCoords       *coords);
 
73
 
 
74
static void     gimp_motion_buffer_interpolate_stroke  (GimpMotionBuffer *buffer,
 
75
                                                        GimpCoords       *coords);
 
76
static gboolean gimp_motion_buffer_event_queue_timeout (GimpMotionBuffer *buffer);
 
77
 
 
78
 
 
79
G_DEFINE_TYPE (GimpMotionBuffer, gimp_motion_buffer, GIMP_TYPE_OBJECT)
 
80
 
 
81
#define parent_class gimp_motion_buffer_parent_class
 
82
 
 
83
static guint motion_buffer_signals[LAST_SIGNAL] = { 0 };
 
84
 
 
85
static const GimpCoords default_coords = GIMP_COORDS_DEFAULT_VALUES;
 
86
 
 
87
 
 
88
static void
 
89
gimp_motion_buffer_class_init (GimpMotionBufferClass *klass)
 
90
{
 
91
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
92
 
 
93
  motion_buffer_signals[STROKE] =
 
94
    g_signal_new ("stroke",
 
95
                  G_TYPE_FROM_CLASS (klass),
 
96
                  G_SIGNAL_RUN_FIRST,
 
97
                  G_STRUCT_OFFSET (GimpMotionBufferClass, stroke),
 
98
                  NULL, NULL,
 
99
                  gimp_marshal_VOID__POINTER_UINT_FLAGS,
 
100
                  G_TYPE_NONE, 3,
 
101
                  G_TYPE_POINTER,
 
102
                  G_TYPE_UINT,
 
103
                  GDK_TYPE_MODIFIER_TYPE);
 
104
 
 
105
  motion_buffer_signals[HOVER] =
 
106
    g_signal_new ("hover",
 
107
                  G_TYPE_FROM_CLASS (klass),
 
108
                  G_SIGNAL_RUN_FIRST,
 
109
                  G_STRUCT_OFFSET (GimpMotionBufferClass, hover),
 
110
                  NULL, NULL,
 
111
                  gimp_marshal_VOID__POINTER_FLAGS_BOOLEAN,
 
112
                  G_TYPE_NONE, 3,
 
113
                  G_TYPE_POINTER,
 
114
                  GDK_TYPE_MODIFIER_TYPE,
 
115
                  G_TYPE_BOOLEAN);
 
116
 
 
117
  object_class->dispose      = gimp_motion_buffer_dispose;
 
118
  object_class->finalize     = gimp_motion_buffer_finalize;
 
119
  object_class->set_property = gimp_motion_buffer_set_property;
 
120
  object_class->get_property = gimp_motion_buffer_get_property;
 
121
}
 
122
 
 
123
static void
 
124
gimp_motion_buffer_init (GimpMotionBuffer *buffer)
 
125
{
 
126
  buffer->event_history = g_array_new (FALSE, FALSE, sizeof (GimpCoords));
 
127
  buffer->event_queue   = g_array_new (FALSE, FALSE, sizeof (GimpCoords));
 
128
}
 
129
 
 
130
static void
 
131
gimp_motion_buffer_dispose (GObject *object)
 
132
{
 
133
  GimpMotionBuffer *buffer = GIMP_MOTION_BUFFER (object);
 
134
 
 
135
  if (buffer->event_delay_timeout)
 
136
    {
 
137
      g_source_remove (buffer->event_delay_timeout);
 
138
      buffer->event_delay_timeout = 0;
 
139
    }
 
140
 
 
141
  G_OBJECT_CLASS (parent_class)->dispose (object);
 
142
}
 
143
 
 
144
static void
 
145
gimp_motion_buffer_finalize (GObject *object)
 
146
{
 
147
  GimpMotionBuffer *buffer = GIMP_MOTION_BUFFER (object);
 
148
 
 
149
  if (buffer->event_history)
 
150
    {
 
151
      g_array_free (buffer->event_history, TRUE);
 
152
      buffer->event_history = NULL;
 
153
    }
 
154
 
 
155
  if (buffer->event_queue)
 
156
    {
 
157
      g_array_free (buffer->event_queue, TRUE);
 
158
      buffer->event_queue = NULL;
 
159
    }
 
160
 
 
161
  G_OBJECT_CLASS (parent_class)->finalize (object);
 
162
}
 
163
 
 
164
static void
 
165
gimp_motion_buffer_set_property (GObject      *object,
 
166
                                 guint         property_id,
 
167
                                 const GValue *value,
 
168
                                 GParamSpec   *pspec)
 
169
{
 
170
  switch (property_id)
 
171
    {
 
172
    default:
 
173
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
174
      break;
 
175
    }
 
176
}
 
177
 
 
178
static void
 
179
gimp_motion_buffer_get_property (GObject    *object,
 
180
                                 guint       property_id,
 
181
                                 GValue     *value,
 
182
                                 GParamSpec *pspec)
 
183
{
 
184
  switch (property_id)
 
185
    {
 
186
    default:
 
187
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
188
      break;
 
189
    }
 
190
}
 
191
 
 
192
 
 
193
/*  public functions  */
 
194
 
 
195
GimpMotionBuffer *
 
196
gimp_motion_buffer_new (void)
 
197
{
 
198
  return g_object_new (GIMP_TYPE_MOTION_BUFFER,
 
199
                       NULL);
 
200
}
 
201
 
 
202
void
 
203
gimp_motion_buffer_begin_stroke (GimpMotionBuffer *buffer,
 
204
                                 guint32           time,
 
205
                                 GimpCoords       *last_motion)
 
206
{
 
207
  g_return_if_fail (GIMP_IS_MOTION_BUFFER (buffer));
 
208
  g_return_if_fail (last_motion != NULL);
 
209
 
 
210
  buffer->last_read_motion_time = time;
 
211
 
 
212
  *last_motion = buffer->last_coords;
 
213
}
 
214
 
 
215
void
 
216
gimp_motion_buffer_end_stroke (GimpMotionBuffer *buffer)
 
217
{
 
218
  g_return_if_fail (GIMP_IS_MOTION_BUFFER (buffer));
 
219
 
 
220
  if (buffer->event_delay_timeout)
 
221
    {
 
222
      g_source_remove (buffer->event_delay_timeout);
 
223
      buffer->event_delay_timeout = 0;
 
224
    }
 
225
 
 
226
  gimp_motion_buffer_event_queue_timeout (buffer);
 
227
}
 
228
 
 
229
/**
 
230
 * gimp_motion_buffer_motion_event:
 
231
 * @buffer:
 
232
 * @coords:
 
233
 * @time:
 
234
 * @scale_x:
 
235
 * @scale_y:
 
236
 * @event_fill:
 
237
 *
 
238
 * This function evaluates the event to decide if the change is big
 
239
 * enough to need handling and returns FALSE, if change is less than
 
240
 * set filter level taking a whole lot of load off any draw tools that
 
241
 * have no use for these events anyway. If the event is seen fit at
 
242
 * first look, it is evaluated for speed and smoothed.  Due to lousy
 
243
 * time resolution of events pretty strong smoothing is applied to
 
244
 * timestamps for sensible speed result. This function is also ideal
 
245
 * for other event adjustment like pressure curve or calculating other
 
246
 * derived dynamics factors like angular velocity calculation from
 
247
 * tilt values, to allow for even more dynamic brushes. Calculated
 
248
 * distance to last event is stored in GimpCoords because its a
 
249
 * sideproduct of velocity calculation and is currently calculated in
 
250
 * each tool. If they were to use this distance, more resouces on
 
251
 * recalculating the same value would be saved.
 
252
 *
 
253
 * Return value: %TRUE if the motion was significant enough to be
 
254
 *               processed, %FALSE otherwise.
 
255
 **/
 
256
gboolean
 
257
gimp_motion_buffer_motion_event (GimpMotionBuffer *buffer,
 
258
                                 GimpCoords       *coords,
 
259
                                 guint32           time,
 
260
                                 gdouble           scale_x,
 
261
                                 gdouble           scale_y,
 
262
                                 gboolean          event_fill)
 
263
{
 
264
  gdouble  delta_time  = 0.001;
 
265
  gdouble  delta_x     = 0.0;
 
266
  gdouble  delta_y     = 0.0;
 
267
  gdouble  dir_delta_x = 0.0;
 
268
  gdouble  dir_delta_y = 0.0;
 
269
  gdouble  distance    = 1.0;
 
270
 
 
271
  g_return_val_if_fail (GIMP_IS_MOTION_BUFFER (buffer), FALSE);
 
272
  g_return_val_if_fail (coords != NULL, FALSE);
 
273
 
 
274
  /*  the last_read_motion_time most be set unconditionally, so set
 
275
   *  it early
 
276
   */
 
277
  buffer->last_read_motion_time = time;
 
278
 
 
279
  delta_time = (buffer->last_motion_delta_time * (1 - SMOOTH_FACTOR) +
 
280
                (time - buffer->last_motion_time) * SMOOTH_FACTOR);
 
281
 
 
282
  if (buffer->last_motion_time == 0)
 
283
    {
 
284
      /*  First pair is invalid to do any velocity calculation, so we
 
285
       *  apply a constant value.
 
286
       */
 
287
      coords->velocity = 1.0;
 
288
    }
 
289
  else
 
290
    {
 
291
      GimpCoords last_dir_event = buffer->last_coords;
 
292
      gdouble    filter;
 
293
      gdouble    dist;
 
294
      gdouble    delta_dir;
 
295
 
 
296
      delta_x = last_dir_event.x - coords->x;
 
297
      delta_y = last_dir_event.y - coords->y;
 
298
 
 
299
      /*  Events with distances less than the screen resolution are
 
300
       *  not worth handling.
 
301
       */
 
302
      filter = MIN (1.0 / scale_x, 1.0 / scale_y) / 2.0;
 
303
 
 
304
      if (fabs (delta_x) < filter &&
 
305
          fabs (delta_y) < filter)
 
306
        {
 
307
          return FALSE;
 
308
        }
 
309
 
 
310
      distance = dist = sqrt (SQR (delta_x) + SQR (delta_y));
 
311
 
 
312
      /*  If even smoothed time resolution does not allow to guess for
 
313
       *  speed, use last velocity.
 
314
       */
 
315
      if (delta_time == 0)
 
316
        {
 
317
          coords->velocity = buffer->last_coords.velocity;
 
318
        }
 
319
      else
 
320
        {
 
321
          /*  We need to calculate the velocity in screen coordinates
 
322
           *  for human interaction
 
323
           */
 
324
          gdouble screen_distance = (distance * MIN (scale_x, scale_y));
 
325
 
 
326
          /* Calculate raw valocity */
 
327
          coords->velocity = ((screen_distance / delta_time) / VELOCITY_UNIT);
 
328
 
 
329
          /* Adding velocity dependent smoothing, feels better in tools. */
 
330
          coords->velocity = (buffer->last_coords.velocity *
 
331
                              (1 - MIN (SMOOTH_FACTOR, coords->velocity)) +
 
332
                              coords->velocity *
 
333
                              MIN (SMOOTH_FACTOR, coords->velocity));
 
334
 
 
335
          /* Speed needs upper limit */
 
336
          coords->velocity = MIN (coords->velocity, 1.0);
 
337
        }
 
338
 
 
339
      if (((fabs (delta_x) > DIRECTION_RADIUS) &&
 
340
           (fabs (delta_y) > DIRECTION_RADIUS)) ||
 
341
          (buffer->event_history->len < 4))
 
342
        {
 
343
          dir_delta_x = delta_x;
 
344
          dir_delta_y = delta_y;
 
345
        }
 
346
      else
 
347
        {
 
348
          gint x = 3;
 
349
 
 
350
          while (((fabs (dir_delta_x) < DIRECTION_RADIUS) ||
 
351
                  (fabs (dir_delta_y) < DIRECTION_RADIUS)) &&
 
352
                 (x >= 0))
 
353
            {
 
354
              last_dir_event = g_array_index (buffer->event_history,
 
355
                                              GimpCoords, x);
 
356
 
 
357
              dir_delta_x = last_dir_event.x - coords->x;
 
358
              dir_delta_y = last_dir_event.y - coords->y;
 
359
 
 
360
              x--;
 
361
            }
 
362
        }
 
363
 
 
364
      if ((fabs (dir_delta_x) < DIRECTION_RADIUS) ||
 
365
          (fabs (dir_delta_y) < DIRECTION_RADIUS))
 
366
        {
 
367
          coords->direction = buffer->last_coords.direction;
 
368
        }
 
369
      else
 
370
        {
 
371
          coords->direction = gimp_coords_direction (&last_dir_event, coords);
 
372
        }
 
373
 
 
374
      coords->direction = coords->direction - floor (coords->direction);
 
375
 
 
376
      delta_dir = coords->direction - buffer->last_coords.direction;
 
377
 
 
378
      if (delta_dir < -0.5)
 
379
        {
 
380
          coords->direction = (0.5 * coords->direction +
 
381
                               0.5 * (buffer->last_coords.direction - 1.0));
 
382
        }
 
383
      else if (delta_dir > 0.5)
 
384
        {
 
385
          coords->direction = (0.5 * coords->direction +
 
386
                               0.5 * (buffer->last_coords.direction + 1.0));
 
387
        }
 
388
      else
 
389
        {
 
390
          coords->direction = (0.5 * coords->direction +
 
391
                               0.5 * buffer->last_coords.direction);
 
392
        }
 
393
 
 
394
      coords->direction = coords->direction - floor (coords->direction);
 
395
 
 
396
      /* do event fill for devices that do not provide enough events */
 
397
      if (distance >= EVENT_FILL_PRECISION &&
 
398
          event_fill                       &&
 
399
          buffer->event_history->len >= 2)
 
400
        {
 
401
          if (buffer->event_delay)
 
402
            {
 
403
              gimp_motion_buffer_interpolate_stroke (buffer, coords);
 
404
            }
 
405
          else
 
406
            {
 
407
              buffer->event_delay = TRUE;
 
408
              gimp_motion_buffer_push_event_history (buffer, coords);
 
409
            }
 
410
        }
 
411
      else
 
412
        {
 
413
          if (buffer->event_delay)
 
414
            buffer->event_delay = FALSE;
 
415
 
 
416
          gimp_motion_buffer_push_event_history (buffer, coords);
 
417
        }
 
418
 
 
419
#ifdef EVENT_VERBOSE
 
420
      g_printerr ("DIST: %f, DT:%f, Vel:%f, Press:%f,smooth_dd:%f, POS: (%f, %f)\n",
 
421
                  distance,
 
422
                  delta_time,
 
423
                  buffer->last_coords.velocity,
 
424
                  coords->pressure,
 
425
                  distance - dist,
 
426
                  coords->x,
 
427
                  coords->y);
 
428
#endif
 
429
    }
 
430
 
 
431
  g_array_append_val (buffer->event_queue, *coords);
 
432
 
 
433
  buffer->last_coords            = *coords;
 
434
  buffer->last_motion_time       = time;
 
435
  buffer->last_motion_delta_time = delta_time;
 
436
  buffer->last_motion_delta_x    = delta_x;
 
437
  buffer->last_motion_delta_y    = delta_y;
 
438
  buffer->last_motion_distance   = distance;
 
439
 
 
440
  return TRUE;
 
441
}
 
442
 
 
443
guint32
 
444
gimp_motion_buffer_get_last_motion_time (GimpMotionBuffer *buffer)
 
445
{
 
446
  g_return_val_if_fail (GIMP_IS_MOTION_BUFFER (buffer), 0);
 
447
 
 
448
  return buffer->last_read_motion_time;
 
449
}
 
450
 
 
451
void
 
452
gimp_motion_buffer_request_stroke (GimpMotionBuffer *buffer,
 
453
                                   GdkModifierType   state,
 
454
                                   guint32           time)
 
455
{
 
456
  GdkModifierType  event_state;
 
457
  gint             keep = 0;
 
458
 
 
459
  g_return_if_fail (GIMP_IS_MOTION_BUFFER (buffer));
 
460
 
 
461
  if (buffer->event_delay)
 
462
    {
 
463
      /* If we are in delay we use LAST state, not current */
 
464
      event_state = buffer->last_active_state;
 
465
 
 
466
      keep = 1; /* Holding one event in buf */
 
467
    }
 
468
  else
 
469
    {
 
470
      /* Save the state */
 
471
      event_state = state;
 
472
    }
 
473
 
 
474
  if (buffer->event_delay_timeout)
 
475
    {
 
476
      g_source_remove (buffer->event_delay_timeout);
 
477
      buffer->event_delay_timeout = 0;
 
478
    }
 
479
 
 
480
  buffer->last_active_state = state;
 
481
 
 
482
  while (buffer->event_queue->len > keep)
 
483
    {
 
484
      GimpCoords buf_coords;
 
485
 
 
486
      gimp_motion_buffer_pop_event_queue (buffer, &buf_coords);
 
487
 
 
488
      g_signal_emit (buffer, motion_buffer_signals[STROKE], 0,
 
489
                     &buf_coords, time, event_state);
 
490
    }
 
491
 
 
492
  if (buffer->event_delay)
 
493
    {
 
494
      buffer->event_delay_timeout =
 
495
        g_timeout_add (50,
 
496
                       (GSourceFunc) gimp_motion_buffer_event_queue_timeout,
 
497
                       buffer);
 
498
    }
 
499
}
 
500
 
 
501
void
 
502
gimp_motion_buffer_request_hover (GimpMotionBuffer *buffer,
 
503
                                  GdkModifierType   state,
 
504
                                  gboolean          proximity)
 
505
{
 
506
  g_return_if_fail (GIMP_IS_MOTION_BUFFER (buffer));
 
507
 
 
508
  if (buffer->event_queue->len > 0)
 
509
    {
 
510
      GimpCoords buf_coords = g_array_index (buffer->event_queue,
 
511
                                             GimpCoords,
 
512
                                             buffer->event_queue->len - 1);
 
513
 
 
514
      g_signal_emit (buffer, motion_buffer_signals[HOVER], 0,
 
515
                     &buf_coords, state, proximity);
 
516
 
 
517
      g_array_set_size (buffer->event_queue, 0);
 
518
    }
 
519
}
 
520
 
 
521
 
 
522
/*  private functions  */
 
523
 
 
524
static void
 
525
gimp_motion_buffer_push_event_history (GimpMotionBuffer *buffer,
 
526
                                       const GimpCoords *coords)
 
527
{
 
528
  if (buffer->event_history->len == 4)
 
529
    g_array_remove_index (buffer->event_history, 0);
 
530
 
 
531
  g_array_append_val (buffer->event_history, *coords);
 
532
}
 
533
 
 
534
static void
 
535
gimp_motion_buffer_pop_event_queue (GimpMotionBuffer *buffer,
 
536
                                    GimpCoords       *coords)
 
537
{
 
538
  *coords = g_array_index (buffer->event_queue, GimpCoords, 0);
 
539
 
 
540
  g_array_remove_index (buffer->event_queue, 0);
 
541
}
 
542
 
 
543
static void
 
544
gimp_motion_buffer_interpolate_stroke (GimpMotionBuffer *buffer,
 
545
                                       GimpCoords       *coords)
 
546
{
 
547
  GArray *ret_coords;
 
548
  gint    i = buffer->event_history->len - 1;
 
549
 
 
550
  /* Note that there must be exactly one event in buffer or bad things
 
551
   * can happen. This must never get called under other circumstances.
 
552
   */
 
553
  ret_coords = g_array_new (FALSE, FALSE, sizeof (GimpCoords));
 
554
 
 
555
  gimp_coords_interpolate_catmull (g_array_index (buffer->event_history,
 
556
                                                  GimpCoords, i - 1),
 
557
                                   g_array_index (buffer->event_history,
 
558
                                                  GimpCoords, i),
 
559
                                   g_array_index (buffer->event_queue,
 
560
                                                  GimpCoords, 0),
 
561
                                   *coords,
 
562
                                   EVENT_FILL_PRECISION / 2,
 
563
                                   &ret_coords,
 
564
                                   NULL);
 
565
 
 
566
  /* Push the last actual event in history */
 
567
  gimp_motion_buffer_push_event_history (buffer,
 
568
                                         &g_array_index (buffer->event_queue,
 
569
                                                         GimpCoords, 0));
 
570
 
 
571
  g_array_set_size (buffer->event_queue, 0);
 
572
 
 
573
  g_array_append_vals (buffer->event_queue,
 
574
                       &g_array_index (ret_coords, GimpCoords, 0),
 
575
                       ret_coords->len);
 
576
 
 
577
  g_array_free (ret_coords, TRUE);
 
578
}
 
579
 
 
580
static gboolean
 
581
gimp_motion_buffer_event_queue_timeout (GimpMotionBuffer *buffer)
 
582
{
 
583
  buffer->event_delay         = FALSE;
 
584
  buffer->event_delay_timeout = 0;
 
585
 
 
586
  if (buffer->event_queue->len > 0)
 
587
    {
 
588
      GimpCoords last_coords = g_array_index (buffer->event_queue,
 
589
                                              GimpCoords,
 
590
                                              buffer->event_queue->len - 1);
 
591
 
 
592
      gimp_motion_buffer_push_event_history (buffer, &last_coords);
 
593
 
 
594
      gimp_motion_buffer_request_stroke (buffer,
 
595
                                         buffer->last_active_state,
 
596
                                         buffer->last_read_motion_time);
 
597
    }
 
598
 
 
599
  return FALSE;
 
600
}