This file is indexed.

/usr/share/gtk-doc/html/clutter-cookbook/animations-path.html is in libclutter-1.0-doc 1.20.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>10. Animating an actor along a curved path</title><link rel="stylesheet" type="text/css" href="style.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="index.html" title="The Clutter Cookbook"><link rel="up" href="animations.html" title="Chapter 5. Animations"><link rel="prev" href="animations-scaling.html" title="9. Animated scaling"><link rel="next" href="text.html" title="Chapter 6. Text"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">10. Animating an actor along a curved path</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="animations-scaling.html">Prev</a> </td><th width="60%" align="center">Chapter 5. Animations</th><td width="20%" align="right"> <a accesskey="n" href="text.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="animations-path"></a>10. Animating an actor along a curved path</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp75493600"></a>10.1. Problem</h3></div></div></div><p>You want to animate an actor along a curved path: for
      example, to move an actor in a circle or spiral.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp75494880"></a>10.2. Solution</h3></div></div></div><p>Create a <span class="type">ClutterPath</span> to describe the
      path the actor should move along; then create a
      <span class="type">ClutterPathConstraint</span> based on that path:</p><div class="informalexample"><pre class="programlisting">ClutterPath *path;
ClutterConstraint *constraint;

/* create the path */
path = clutter_path_new ();

/* first node is at 30,60 */
clutter_path_add_move_to (path, 30, 60);

/* add a curve to the top-right of the stage, with control
 * points relative to the start point at 30,60
 */
clutter_path_add_rel_curve_to (path,
                               120, 180,
                               180, 120,
                               240, 0);

/* create a constraint based on the path */
constraint = clutter_path_constraint_new (path, 0.0);</pre></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>For more on the types of curve and line segment available,
        see the <span class="type">ClutterPath</span> API documentation.</p></div><p>Next, add the constraint to an actor; in this case, the
      actor is a red rectangle:</p><div class="informalexample"><pre class="programlisting">ClutterActor *rectangle;
ClutterActor *stage = clutter_stage_new ();

/* ...set size stage, color, etc... */

const ClutterColor *red_color = clutter_color_new (255, 0, 0, 255);

rectangle = clutter_rectangle_new_with_color (red_color);
clutter_actor_set_size (rectangle, 60, 60);

/* add the constraint to the rectangle; note that this
 * puts the rectangle at the start of the path, i.e. at position 30,60;
 * we also give the constraint a name, so we can use it from an implicit
 * animation
 */
clutter_actor_add_constraint_with_name (rectangle, "path", constraint);

/* add the rectangle to the stage */
clutter_actor_add_child (stage, rectangle);</pre></div><p>Note how the constraint has to be assigned a name (here, "path")
      to make it accessible via implicit animations.</p><p>Finally, animate the constraint's <code class="varname">offset</code>
      property; which in turn moves the actor along the path:</p><div class="informalexample"><pre class="programlisting">ClutterTimeline *timeline;

/* create a timeline with 1000 milliseconds duration, which loops
 * indefinitely and reverses its direction each time it completes
 */
timeline = clutter_timeline_new (1000);
clutter_timeline_set_repeat_count (timeline, -1);
clutter_timeline_set_auto_reverse (timeline, TRUE);

/* animate the offset property on the constraint from 0.0 to 1.0;
 * note the syntax used to refer to the constraints metadata for the
 * rectangle actor:
 *
 *   "@constraints.&lt;constraint name&gt;.&lt;property&gt;"
 */
clutter_actor_animate_with_timeline (rectangle, CLUTTER_LINEAR, timeline,
                                     "@constraints.path.offset", 1.0,
                                     NULL);

/* ...show the stage, run the mainloop, free memory on exit... */</pre></div><p>The <a class="link" href="animations-path.html#animations-path-example-1" title="Example 5.16. Using a ClutterPathConstraint with implicit animations to move an actor along a curved path">full
      example</a> shows how these fragments fit together.
      The animation produced by this example looks
      like this:</p><p><video controls="controls" src="videos/animations-path.ogv"><a href="videos/animations-path.ogv"></a></video></p><p>The <a class="link" href="animations-path.html#animations-path-example-2" title="Example 5.17. Using a ClutterPathConstraint with ClutterAnimator to animate an actor on a simulated circular path">second full
      example</a> animates an actor around a simulated circle
      using a more complex <span class="type">ClutterPath</span>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idp75510048"></a>10.3. Discussion</h3></div></div></div><p>Animating an actor using <span class="type">ClutterPathConstraint</span>
      is the recommended way to animate actors along curved paths. It
      replaces the older <span class="type">ClutterBehaviourPath</span>.</p><p>A <span class="type">ClutterPathConstraint</span> constrains an
      actor's <code class="varname">x</code> and <code class="varname">y</code> properties
      to a position along such a <span class="type">ClutterPath</span>: a path through
      2D space. The <span class="type">ClutterPath</span> itself is composed of nodes
      (x,y positions in 2D space), connected by straight lines or (cubic)
      <a class="ulink" href="http://en.wikipedia.org/wiki/B%C3%A9zier_curve" target="_top">Bézier
      curves</a>.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p><span class="type">ClutterPath</span> doesn't have to be used in animations:
        it can also be used in drawing (see the
        <a class="link" href="actors-non-rectangular.html" title="6. Creating an actor with a non-rectangular shape">non-rectangular actor
        recipe</a>).</p></div><p>The actor's position along the path is determined by the constraint's
      <code class="varname">offset</code> property, which has a
      value between 0.0 and 1.0. When the offset is 0.0, the actor
      is at the beginning of the path; when the actor is at 1.0, the
      actor is at the end of the path. Between 0.0 and 1.0, the actor
      is some fraction of the way along the path.</p><p>If you immediately set the <code class="varname">offset</code> for the
      constraint (e.g. to <code class="code">0.5</code>), the actor is instantly placed
      at that position along the path: for <code class="code">offset = 0.5</code>,
      at the halfway point.</p><p>By contrast, to animate an actor along a path, you
      <span class="emphasis"><em>animate</em></span> the offset property of a
      <span class="type">ClutterPathConstraint</span>. The actor's position
      along the path is dependent on the progress of the animation:
      when the animation starts, the actor is at the beginning of the path;
      by the end of the animation, it will have reached its end.</p><p>If you animate the constraint using a linear easing mode,
      the progress of the animation matches progress along the path: at
      half-way through the animation, the actor will be half-way along
      the path.</p><p>However, if you are using a non-linear easing mode
      (e.g. a quintic or cubic mode), the offset along the path and
      progress through the animation may differ. This is because the
      offset along the path is computed from the alpha value at that
      point in the animation; this in turn depends on the alpha function
      applied by the animation. (See the
      <a class="link" href="animations.html#animations-introduction" title="1. Introduction">animations introduction</a>
      for more details about alphas.)</p><p>One way to think about this is to imagine the actor
      making a journey along the path. The alpha function governs the
      actor's speed, including how it speeds up and slows down
      during its journey. The actor's speed may be constant
      (as in a linear easing mode). Alternatively, the actor's speed
      may not be constant: it might start out fast then slow down
      (ease out); or start slow and speed up (ease in); or start and
      end fast, but slow down in the middle (ease in and ease out); or
      some other more complex arrangement (as in the bounce and elastic
      easing modes). So where the actor is on the path at a particular
      time doesn't directly relate to how long it's been travelling:
      the position is determined both by how long it's been travelling,
      and changes in its speed throughout the journey.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="idp75524320"></a>10.3.1. Other ways to animate along a path</h4></div></div></div><p><span class="type">ClutterPathConstraint</span> is the only
        decent way of animating along curves in a predictable
        and manageable fashion. It can also be used to animate along
        paths composed of straight lines, though this isn't essential: you
        can do straight line animations directly with <span class="type">ClutterAnimator</span>,
        <span class="type">ClutterState</span> or implicit animations. But if
        you need to animate between more than a half a dozen sets of
        points joined by straight lines, <span class="type">ClutterPathConstraint</span>
        makes sense then too.</p><p>It is also possible to animate actors over very simple, non-Bézier
        curves without using <span class="type">ClutterPathConstraint</span>. This
        can be done by animating the actor's position properties using
        a non-linear easing mode (see the <span class="type">ClutterAlpha</span>
        documentation for available modes, or write your own custom
        alpha function). <a class="link" href="animations-path.html#animations-path-example-3" title="Example 5.18. Animating actors on curved paths using easing modes">This
        example</a> shows how to animate two actors on
        curved paths around each other without
        <span class="type">ClutterPathConstraint</span>.</p><p>However, it is difficult to precisely calculate paths
        with this approach. It is also only practical where you have a
        very simple curve: if you want to chain together several curved
        motions (as in the <a class="link" href="animations-path.html#animations-path-example-2" title="Example 5.17. Using a ClutterPathConstraint with ClutterAnimator to animate an actor on a simulated circular path">circle
        example</a>), this quickly becomes unwieldy.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Tip</h3><p>
          If you want physics-based animation, look at
          <a class="ulink" href="http://git.clutter-project.org/clutter-box2d/" target="_top">clutter-box2d</a>.
          </p></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="animations-path-examples"></a>10.4. Full examples</h3></div></div></div><div class="example"><a name="animations-path-example-1"></a><p class="title"><b>Example 5.16. Using a <span class="type">ClutterPathConstraint</span> with
        implicit animations to move an actor along a curved path</b></p><div class="example-contents"><pre class="programlisting">#include &lt;stdlib.h&gt;
#include &lt;clutter/clutter.h&gt;

int
main (int   argc,
      char *argv[])
{
  ClutterActor *stage;
  ClutterPath *path;
  ClutterConstraint *constraint;
  ClutterActor *rectangle;
  ClutterTimeline *timeline;

  const ClutterColor *stage_color = clutter_color_new (51, 51, 85, 255);
  const ClutterColor *red_color = clutter_color_new (255, 0, 0, 255);

  if (clutter_init (&amp;argc, &amp;argv) != CLUTTER_INIT_SUCCESS)
    return 1;

  stage = clutter_stage_new ();
  clutter_actor_set_size (stage, 360, 300);
  clutter_stage_set_color (CLUTTER_STAGE (stage), stage_color);
  g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);

  /* create the path */
  path = clutter_path_new ();
  clutter_path_add_move_to (path, 30, 60);

  /* add a curve round to the top-right of the stage */
  clutter_path_add_rel_curve_to (path,
                                 120, 180,
                                 180, 120,
                                 240, 0);

  /* create a constraint based on the path */
  constraint = clutter_path_constraint_new (path, 0.0);

  /* put a rectangle at the start of the path */
  rectangle = clutter_rectangle_new_with_color (red_color);
  clutter_actor_set_size (rectangle, 60, 60);

  /* add the constraint to the rectangle */
  clutter_actor_add_constraint_with_name (rectangle, "path", constraint);

  /* add the rectangle to the stage */
  clutter_container_add_actor (CLUTTER_CONTAINER (stage), rectangle);

  /* set up the timeline */
  timeline = clutter_timeline_new (1000);
  clutter_timeline_set_repeat_count (timeline, -1);
  clutter_timeline_set_auto_reverse (timeline, TRUE);

  clutter_actor_animate_with_timeline (rectangle, CLUTTER_LINEAR, timeline,
                                       "@constraints.path.offset", 1.0,
                                       NULL);

  clutter_actor_show (stage);

  clutter_main ();

  return EXIT_SUCCESS;
}
</pre></div></div><br class="example-break"><div class="example"><a name="animations-path-example-2"></a><p class="title"><b>Example 5.17. Using a <span class="type">ClutterPathConstraint</span> with
        <span class="type">ClutterAnimator</span> to animate an actor on
        a simulated circular path</b></p><div class="example-contents"><pre class="programlisting">#include &lt;stdlib.h&gt;
#include &lt;clutter/clutter.h&gt;

#define STAGE_SIDE 400.0

static const ClutterColor stage_color = { 0x33, 0x33, 0x55, 0xff };
static const ClutterColor red_color = { 0xff, 0x00, 0x00, 0xff };

/* Build a "circular" path out of 4 Bezier curves
 *
 * code modified from
 * http://git.clutter-project.org/dax/tree/dax/dax-traverser-clutter.c#n328
 *
 * see http://www.whizkidtech.redprince.net/bezier/circle/
 * for further explanation
 */
static ClutterPath *
build_circular_path (gfloat cx,
                     gfloat cy,
                     gfloat r)
{
  ClutterPath *path;
  static gfloat kappa = 4 * (G_SQRT2 - 1) / 3;

  path = clutter_path_new ();

  clutter_path_add_move_to (path, cx + r, cy);
  clutter_path_add_curve_to (path,
                             cx + r, cy + r * kappa,
                             cx + r * kappa, cy + r,
                             cx, cy + r);
  clutter_path_add_curve_to (path,
                             cx - r * kappa, cy + r,
                             cx - r, cy + r * kappa,
                             cx - r, cy);
  clutter_path_add_curve_to (path,
                             cx - r, cy - r * kappa,
                             cx - r * kappa, cy - r,
                             cx, cy - r);
  clutter_path_add_curve_to (path,
                             cx + r * kappa, cy - r,
                             cx + r, cy - r * kappa,
                             cx + r, cy);
  clutter_path_add_close (path);

  return path;
}

static gboolean
key_pressed_cb (ClutterActor *actor,
                ClutterEvent *event,
                gpointer      user_data)
{
  ClutterTimeline *timeline = CLUTTER_TIMELINE (user_data);

  if (!clutter_timeline_is_playing (timeline))
    clutter_timeline_start (timeline);

  return TRUE;
}

int
main (int   argc,
      char *argv[])
{
  ClutterPath *path;
  ClutterConstraint *constraint;
  ClutterAnimator *animator;
  ClutterTimeline *timeline;
  ClutterActor *stage;
  ClutterActor *rectangle;

  if (clutter_init (&amp;argc, &amp;argv) != CLUTTER_INIT_SUCCESS)
    return 1;

  stage = clutter_stage_new ();
  clutter_actor_set_size (stage, STAGE_SIDE, STAGE_SIDE);
  clutter_stage_set_color (CLUTTER_STAGE (stage), &amp;stage_color);
  g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);

  rectangle = clutter_rectangle_new_with_color (&amp;red_color);
  clutter_actor_set_size (rectangle, STAGE_SIDE / 8, STAGE_SIDE / 8);
  clutter_actor_set_position (rectangle,
                              STAGE_SIDE / 2,
                              STAGE_SIDE / 2);

  clutter_container_add_actor (CLUTTER_CONTAINER (stage),
                               rectangle);

  /* set up a path and make a constraint with it */
  path = build_circular_path (STAGE_SIDE / 2,
                              STAGE_SIDE / 2,
                              STAGE_SIDE / 4);
  constraint = clutter_path_constraint_new (path, 0.0);

  /* apply the constraint to the rectangle; note that there
   * is no need to name the constraint, as we will be animating
   * the constraint's offset property directly using ClutterAnimator
   */
  clutter_actor_add_constraint (rectangle, constraint);

  /* animation to animate the path offset */
  animator = clutter_animator_new ();
  clutter_animator_set_duration (animator, 5000);

  /* use ClutterAnimator to animate the constraint directly */
  clutter_animator_set (animator,
                        constraint, "offset", CLUTTER_LINEAR, 0.0, 0.0,
                        constraint, "offset", CLUTTER_LINEAR, 1.0, 1.0,
                        NULL);

  timeline = clutter_animator_get_timeline (animator);
  clutter_timeline_set_repeat_count (timeline, -1);
  clutter_timeline_set_auto_reverse (timeline, TRUE);

  g_signal_connect (stage,
                    "key-press-event",
                    G_CALLBACK (key_pressed_cb),
                    timeline);

  clutter_actor_show (stage);

  clutter_main ();

  /* clean up */
  g_object_unref (animator);

  return EXIT_SUCCESS;
}
</pre></div></div><br class="example-break"><div class="example"><a name="animations-path-example-3"></a><p class="title"><b>Example 5.18. Animating actors on curved paths using easing modes</b></p><div class="example-contents"><pre class="programlisting">#include &lt;stdlib.h&gt;
#include &lt;clutter/clutter.h&gt;

typedef struct {
  ClutterActor *red;
  ClutterActor *green;
  ClutterTimeline *timeline;
} State;

static const ClutterColor stage_color = { 0x33, 0x33, 0x55, 0xff };
static const ClutterColor red_color = { 0xff, 0x00, 0x00, 0xff };
static const ClutterColor green_color = { 0x00, 0xff, 0x00, 0xff };

static void
reverse_timeline (ClutterTimeline *timeline)
{
  ClutterTimelineDirection dir = clutter_timeline_get_direction (timeline);

  if (dir == CLUTTER_TIMELINE_FORWARD)
    dir = CLUTTER_TIMELINE_BACKWARD;
  else
    dir = CLUTTER_TIMELINE_FORWARD;

  clutter_timeline_set_direction (timeline, dir);
}

/* a key press either starts the timeline or reverses it */
static gboolean
key_pressed_cb (ClutterActor *actor,
                ClutterEvent *event,
                gpointer      user_data)
{
  State *state = (State *) user_data;

  if (clutter_timeline_is_playing (state-&gt;timeline))
    reverse_timeline (state-&gt;timeline);
  else
    clutter_timeline_start (state-&gt;timeline);

  return TRUE;
}

int
main (int   argc,
      char *argv[])
{
  State *state = g_new0 (State, 1);

  ClutterActor *stage;
  ClutterAnimator *animator;

  if (clutter_init (&amp;argc, &amp;argv) != CLUTTER_INIT_SUCCESS)
    return 1;

  stage = clutter_stage_new ();
  clutter_actor_set_size (stage, 400, 400);
  clutter_stage_set_color (CLUTTER_STAGE (stage), &amp;stage_color);
  g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);

  state-&gt;red = clutter_rectangle_new_with_color (&amp;red_color);
  clutter_actor_set_size (state-&gt;red, 100, 100);
  clutter_actor_set_position (state-&gt;red, 300, 300);

  state-&gt;green = clutter_rectangle_new_with_color (&amp;green_color);
  clutter_actor_set_size (state-&gt;green, 100, 100);
  clutter_actor_set_position (state-&gt;green, 0, 0);

  animator = clutter_animator_new ();
  clutter_animator_set_duration (animator, 1000);

  clutter_animator_set (animator,
                        state-&gt;red, "x", CLUTTER_LINEAR, 0.0, 300.0,
                        state-&gt;red, "y", CLUTTER_LINEAR, 0.0, 300.0,
                        state-&gt;red, "x", CLUTTER_LINEAR, 1.0, 0.0,
                        state-&gt;red, "y", CLUTTER_EASE_IN_QUINT, 1.0, 0.0,
                        NULL);

  clutter_animator_set (animator,
                        state-&gt;green, "x", CLUTTER_LINEAR, 0.0, 0.0,
                        state-&gt;green, "y", CLUTTER_LINEAR, 0.0, 0.0,
                        state-&gt;green, "x", CLUTTER_LINEAR, 1.0, 300.0,
                        state-&gt;green, "y", CLUTTER_EASE_IN_QUINT, 1.0, 300.0,
                        NULL);

  state-&gt;timeline = clutter_animator_get_timeline (animator);

  clutter_timeline_set_auto_reverse (state-&gt;timeline, TRUE);

  g_signal_connect (stage,
                    "key-press-event",
                    G_CALLBACK (key_pressed_cb),
                    state);

  clutter_container_add (CLUTTER_CONTAINER (stage), state-&gt;red, state-&gt;green, NULL);

  clutter_actor_show (stage);

  clutter_main ();

  g_object_unref (animator);

  g_free (state);

  return EXIT_SUCCESS;
}
</pre></div></div><br class="example-break"></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="animations-scaling.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="animations.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="text.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">9. Animated scaling </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 6. Text</td></tr></table></div></body></html>