gnome-shell-3.6.3.1/src/st/st-private.c

Location Tool Test ID Function Issue
st/st-private.c:475:7 gcc deprecated-declarations _st_create_shadow_material_from_actor 'clutter_texture_get_cogl_texture' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-texture.h:78)
  1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  2 /*
  3  * st-private.h: Private declarations and functions
  4  *
  5  * Copyright 2009, 2010 Red Hat, Inc.
  6  * Copyright 2010 Florian Mç«Żllner
  7  * Copyright 2010 Intel Corporation
  8  * Copyright 2010 Giovanni Campagna
  9  *
 10  * This program is free software; you can redistribute it and/or modify it
 11  * under the terms and conditions of the GNU Lesser General Public License,
 12  * version 2.1, as published by the Free Software Foundation.
 13  *
 14  * This program is distributed in the hope it will be useful, but WITHOUT ANY
 15  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 16  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 17  * more details.
 18  *
 19  * You should have received a copy of the GNU Lesser General Public License
 20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
 21  */
 22 #include <math.h>
 23 #include <string.h>
 24 
 25 #include "st-private.h"
 26 
 27 /**
 28  * _st_actor_get_preferred_width:
 29  * @actor: a #ClutterActor
 30  * @for_height: as with clutter_actor_get_preferred_width()
 31  * @y_fill: %TRUE if @actor will fill its allocation vertically
 32  * @min_width_p: as with clutter_actor_get_preferred_width()
 33  * @natural_width_p: as with clutter_actor_get_preferred_width()
 34  *
 35  * Like clutter_actor_get_preferred_width(), but if @y_fill is %FALSE,
 36  * then it will compute a width request based on the assumption that
 37  * @actor will be given an allocation no taller than its natural
 38  * height.
 39  */
 40 void
 41 _st_actor_get_preferred_width  (ClutterActor *actor,
 42                                 gfloat        for_height,
 43                                 gboolean      y_fill,
 44                                 gfloat       *min_width_p,
 45                                 gfloat       *natural_width_p)
 46 {
 47   if (!y_fill && for_height != -1)
 48     {
 49       ClutterRequestMode mode;
 50       gfloat natural_height;
 51 
 52       mode = clutter_actor_get_request_mode (actor);
 53       if (mode == CLUTTER_REQUEST_WIDTH_FOR_HEIGHT)
 54         {
 55           clutter_actor_get_preferred_height (actor, -1, NULL, &natural_height);
 56           if (for_height > natural_height)
 57             for_height = natural_height;
 58         }
 59     }
 60 
 61   clutter_actor_get_preferred_width (actor, for_height, min_width_p, natural_width_p);
 62 }
 63 
 64 /**
 65  * _st_actor_get_preferred_height:
 66  * @actor: a #ClutterActor
 67  * @for_width: as with clutter_actor_get_preferred_height()
 68  * @x_fill: %TRUE if @actor will fill its allocation horizontally
 69  * @min_height_p: as with clutter_actor_get_preferred_height()
 70  * @natural_height_p: as with clutter_actor_get_preferred_height()
 71  *
 72  * Like clutter_actor_get_preferred_height(), but if @x_fill is
 73  * %FALSE, then it will compute a height request based on the
 74  * assumption that @actor will be given an allocation no wider than
 75  * its natural width.
 76  */
 77 void
 78 _st_actor_get_preferred_height (ClutterActor *actor,
 79                                 gfloat        for_width,
 80                                 gboolean      x_fill,
 81                                 gfloat       *min_height_p,
 82                                 gfloat       *natural_height_p)
 83 {
 84   if (!x_fill && for_width != -1)
 85     {
 86       ClutterRequestMode mode;
 87       gfloat natural_width;
 88 
 89       mode = clutter_actor_get_request_mode (actor);
 90       if (mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
 91         {
 92           clutter_actor_get_preferred_width (actor, -1, NULL, &natural_width);
 93           if (for_width > natural_width)
 94             for_width = natural_width;
 95         }
 96     }
 97 
 98   clutter_actor_get_preferred_height (actor, for_width, min_height_p, natural_height_p);
 99 }
100 
101 /**
102  * _st_get_align_factors:
103  * @x_align: an #StAlign
104  * @y_align: an #StAlign
105  * @x_align_out: (out) (allow-none): @x_align as a #gdouble
106  * @y_align_out: (out) (allow-none): @y_align as a #gdouble
107  *
108  * Converts @x_align and @y_align to #gdouble values.
109  */
110 void
111 _st_get_align_factors (StAlign   x_align,
112                        StAlign   y_align,
113                        gdouble  *x_align_out,
114                        gdouble  *y_align_out)
115 {
116   if (x_align_out)
117     {
118       switch (x_align)
119         {
120         case ST_ALIGN_START:
121           *x_align_out = 0.0;
122           break;
123 
124         case ST_ALIGN_MIDDLE:
125           *x_align_out = 0.5;
126           break;
127 
128         case ST_ALIGN_END:
129           *x_align_out = 1.0;
130           break;
131 
132         default:
133           g_warn_if_reached ();
134           break;
135         }
136     }
137 
138   if (y_align_out)
139     {
140       switch (y_align)
141         {
142         case ST_ALIGN_START:
143           *y_align_out = 0.0;
144           break;
145 
146         case ST_ALIGN_MIDDLE:
147           *y_align_out = 0.5;
148           break;
149 
150         case ST_ALIGN_END:
151           *y_align_out = 1.0;
152           break;
153 
154         default:
155           g_warn_if_reached ();
156           break;
157         }
158     }
159 }
160 
161 /**
162  * _st_set_text_from_style:
163  * @text: Target #ClutterText
164  * @theme_node: Source #StThemeNode
165  *
166  * Set various GObject properties of the @text object using
167  * CSS information from @theme_node.
168  */
169 void
170 _st_set_text_from_style (ClutterText *text,
171                          StThemeNode *theme_node)
172 {
173 
174   ClutterColor color;
175   StTextDecoration decoration;
176   PangoAttrList *attribs;
177   const PangoFontDescription *font;
178   gchar *font_string;
179   StTextAlign align;
180 
181   st_theme_node_get_foreground_color (theme_node, &color);
182   clutter_text_set_color (text, &color);
183 
184   font = st_theme_node_get_font (theme_node);
185   font_string = pango_font_description_to_string (font);
186   clutter_text_set_font_name (text, font_string);
187   g_free (font_string);
188 
189   attribs = pango_attr_list_new ();
190 
191   decoration = st_theme_node_get_text_decoration (theme_node);
192   if (decoration & ST_TEXT_DECORATION_UNDERLINE)
193     {
194       PangoAttribute *underline = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE);
195       pango_attr_list_insert (attribs, underline);
196     }
197   if (decoration & ST_TEXT_DECORATION_LINE_THROUGH)
198     {
199       PangoAttribute *strikethrough = pango_attr_strikethrough_new (TRUE);
200       pango_attr_list_insert (attribs, strikethrough);
201     }
202   /* Pango doesn't have an equivalent attribute for _OVERLINE, and we deliberately
203    * skip BLINK (for now...)
204    */
205 
206   clutter_text_set_attributes (text, attribs);
207 
208   pango_attr_list_unref (attribs);
209 
210   align = st_theme_node_get_text_align (theme_node);
211   if(align == ST_TEXT_ALIGN_JUSTIFY) {
212     clutter_text_set_justify (text, TRUE);
213     clutter_text_set_line_alignment (text, PANGO_ALIGN_LEFT);
214   } else {
215     clutter_text_set_justify (text, FALSE);
216     clutter_text_set_line_alignment (text, (PangoAlignment) align);
217   }
218 }
219 
220 /**
221  * _st_create_texture_material:
222  * @src_texture: The CoglTexture for the material
223  *
224  * Creates a simple material which contains the given texture as a
225  * single layer.
226  */
227 CoglHandle
228 _st_create_texture_material (CoglHandle src_texture)
229 {
230   static CoglHandle texture_material_template = COGL_INVALID_HANDLE;
231   CoglHandle material;
232 
233   g_return_val_if_fail (src_texture != COGL_INVALID_HANDLE,
234                         COGL_INVALID_HANDLE);
235 
236   /* We use a material that has a dummy texture as a base for all
237      texture materials. The idea is that only the Cogl texture object
238      would be different in the children so it is likely that Cogl will
239      be able to share GL programs between all the textures. */
240   if (G_UNLIKELY (texture_material_template == COGL_INVALID_HANDLE))
241     {
242       static const guint8 white_pixel[] = { 0xff, 0xff, 0xff, 0xff };
243       CoglHandle dummy_texture;
244 
245       dummy_texture =
246         cogl_texture_new_from_data (1, 1,
247                                     COGL_TEXTURE_NONE,
248                                     COGL_PIXEL_FORMAT_RGBA_8888_PRE,
249                                     COGL_PIXEL_FORMAT_ANY,
250                                     4, white_pixel);
251 
252       texture_material_template = cogl_material_new ();
253       cogl_material_set_layer (texture_material_template, 0, dummy_texture);
254       cogl_handle_unref (dummy_texture);
255     }
256 
257   material = cogl_material_copy (texture_material_template);
258 
259   cogl_material_set_layer (material, 0, src_texture);
260 
261   return material;
262 }
263 
264 /*****
265  * Shadows
266  *****/
267 
268 static gdouble *
269 calculate_gaussian_kernel (gdouble   sigma,
270                            guint     n_values)
271 {
272   gdouble *ret, sum;
273   gdouble exp_divisor;
274   gint half, i;
275 
276   g_return_val_if_fail (sigma > 0, NULL);
277 
278   half = n_values / 2;
279 
280   ret = g_malloc (n_values * sizeof (gdouble));
281   sum = 0.0;
282 
283   exp_divisor = 2 * sigma * sigma;
284 
285   /* n_values of 1D Gauss function */
286   for (i = 0; i < n_values; i++)
287     {
288       ret[i] = exp (-(i - half) * (i - half) / exp_divisor);
289       sum += ret[i];
290     }
291 
292   /* normalize */
293   for (i = 0; i < n_values; i++)
294     ret[i] /= sum;
295 
296   return ret;
297 }
298 
299 static guchar *
300 blur_pixels (guchar  *pixels_in,
301              gint     width_in,
302              gint     height_in,
303              gint     rowstride_in,
304              gdouble  blur,
305              gint    *width_out,
306              gint    *height_out,
307              gint    *rowstride_out)
308 {
309   guchar *pixels_out;
310   float   sigma;
311 
312   /* The CSS specification defines (or will define) the blur radius as twice
313    * the Gaussian standard deviation. See:
314    *
315    * http://lists.w3.org/Archives/Public/www-style/2010Sep/0002.html
316    */
317   sigma = blur / 2.;
318 
319   if ((guint) blur == 0)
320     {
321       *width_out  = width_in;
322       *height_out = height_in;
323       *rowstride_out = rowstride_in;
324       pixels_out = g_memdup (pixels_in, *rowstride_out * *height_out);
325     }
326   else
327     {
328       gdouble *kernel;
329       guchar  *line;
330       gint     n_values, half;
331       gint     x_in, y_in, x_out, y_out, i;
332 
333       n_values = (gint) 5 * sigma;
334       half = n_values / 2;
335 
336       *width_out  = width_in  + 2 * half;
337       *height_out = height_in + 2 * half;
338       *rowstride_out = (*width_out + 3) & ~3;
339 
340       pixels_out = g_malloc0 (*rowstride_out * *height_out);
341       line       = g_malloc0 (*rowstride_out);
342 
343       kernel = calculate_gaussian_kernel (sigma, n_values);
344 
345       /* vertical blur */
346       for (x_in = 0; x_in < width_in; x_in++)
347         for (y_out = 0; y_out < *height_out; y_out++)
348           {
349             guchar *pixel_in, *pixel_out;
350             gint i0, i1;
351 
352             y_in = y_out - half;
353 
354             /* We read from the source at 'y = y_in + i - half'; clamp the
355              * full i range [0, n_values) so that y is in [0, height_in).
356              */
357             i0 = MAX (half - y_in, 0);
358             i1 = MIN (height_in + half - y_in, n_values);
359 
360             pixel_in  =  pixels_in + (y_in + i0 - half) * rowstride_in + x_in;
361             pixel_out =  pixels_out + y_out * *rowstride_out + (x_in + half);
362 
363             for (i = i0; i < i1; i++)
364               {
365                 *pixel_out += *pixel_in * kernel[i];
366                 pixel_in += rowstride_in;
367               }
368           }
369 
370       /* horizontal blur */
371       for (y_out = 0; y_out < *height_out; y_out++)
372         {
373           memcpy (line, pixels_out + y_out * *rowstride_out, *rowstride_out);
374 
375           for (x_out = 0; x_out < *width_out; x_out++)
376             {
377               gint i0, i1;
378               guchar *pixel_out, *pixel_in;
379 
380               /* We read from the source at 'x = x_out + i - half'; clamp the
381                * full i range [0, n_values) so that x is in [0, width_out).
382                */
383               i0 = MAX (half - x_out, 0);
384               i1 = MIN (*width_out + half - x_out, n_values);
385 
386               pixel_in  = line + x_out + i0 - half;
387               pixel_out = pixels_out + *rowstride_out * y_out + x_out;
388 
389               *pixel_out = 0;
390               for (i = i0; i < i1; i++)
391                 {
392                   *pixel_out += *pixel_in * kernel[i];
393                   pixel_in++;
394                 }
395             }
396         }
397       g_free (kernel);
398       g_free (line);
399     }
400 
401   return pixels_out;
402 }
403 
404 CoglHandle
405 _st_create_shadow_material (StShadow   *shadow_spec,
406                             CoglHandle  src_texture)
407 {
408   static CoglHandle shadow_material_template = COGL_INVALID_HANDLE;
409 
410   CoglHandle  material;
411   CoglHandle  texture;
412   guchar     *pixels_in, *pixels_out;
413   gint        width_in, height_in, rowstride_in;
414   gint        width_out, height_out, rowstride_out;
415 
416   g_return_val_if_fail (shadow_spec != NULL, COGL_INVALID_HANDLE);
417   g_return_val_if_fail (src_texture != COGL_INVALID_HANDLE,
418                         COGL_INVALID_HANDLE);
419 
420   width_in  = cogl_texture_get_width  (src_texture);
421   height_in = cogl_texture_get_height (src_texture);
422   rowstride_in = (width_in + 3) & ~3;
423 
424   pixels_in  = g_malloc0 (rowstride_in * height_in);
425 
426   cogl_texture_get_data (src_texture, COGL_PIXEL_FORMAT_A_8,
427                          rowstride_in, pixels_in);
428 
429   pixels_out = blur_pixels (pixels_in, width_in, height_in, rowstride_in,
430                             shadow_spec->blur,
431                             &width_out, &height_out, &rowstride_out);
432   g_free (pixels_in);
433 
434   texture = cogl_texture_new_from_data (width_out,
435                                         height_out,
436                                         COGL_TEXTURE_NONE,
437                                         COGL_PIXEL_FORMAT_A_8,
438                                         COGL_PIXEL_FORMAT_A_8,
439                                         rowstride_out,
440                                         pixels_out);
441 
442   g_free (pixels_out);
443 
444   if (G_UNLIKELY (shadow_material_template == COGL_INVALID_HANDLE))
445     {
446       shadow_material_template = cogl_material_new ();
447 
448       /* We set up the material to blend the shadow texture with the combine
449        * constant, but defer setting the latter until painting, so that we can
450        * take the actor's overall opacity into account. */
451       cogl_material_set_layer_combine (shadow_material_template, 0,
452                                        "RGBA = MODULATE (CONSTANT, TEXTURE[A])",
453                                        NULL);
454     }
455 
456   material = cogl_material_copy (shadow_material_template);
457 
458   cogl_material_set_layer (material, 0, texture);
459 
460   cogl_handle_unref (texture);
461 
462   return material;
463 }
464 
465 CoglHandle
466 _st_create_shadow_material_from_actor (StShadow     *shadow_spec,
467                                        ClutterActor *actor)
468 {
469   CoglHandle shadow_material = COGL_INVALID_HANDLE;
470 
471   if (CLUTTER_IS_TEXTURE (actor))
472     {
473       CoglHandle texture;
474 
475       texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (actor));
'clutter_texture_get_cogl_texture' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-texture.h:78)
(emitted by gcc)
476 shadow_material = _st_create_shadow_material (shadow_spec, texture); 477 } 478 else 479 { 480 CoglHandle buffer, offscreen; 481 ClutterActorBox box; 482 CoglColor clear_color; 483 float width, height; 484 485 clutter_actor_get_allocation_box (actor, &box); 486 clutter_actor_box_get_size (&box, &width, &height); 487 488 if (width == 0 || height == 0) 489 return COGL_INVALID_HANDLE; 490 491 buffer = cogl_texture_new_with_size (width, 492 height, 493 COGL_TEXTURE_NO_SLICING, 494 COGL_PIXEL_FORMAT_ANY); 495 496 if (buffer == COGL_INVALID_HANDLE) 497 return COGL_INVALID_HANDLE; 498 499 offscreen = cogl_offscreen_new_to_texture (buffer); 500 501 if (offscreen == COGL_INVALID_HANDLE) 502 { 503 cogl_handle_unref (buffer); 504 return COGL_INVALID_HANDLE; 505 } 506 507 cogl_color_set_from_4ub (&clear_color, 0, 0, 0, 0); 508 cogl_push_framebuffer (offscreen); 509 cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR); 510 cogl_ortho (0, width, height, 0, 0, 1.0); 511 clutter_actor_paint (actor); 512 cogl_pop_framebuffer (); 513 cogl_handle_unref (offscreen); 514 515 shadow_material = _st_create_shadow_material (shadow_spec, buffer); 516 517 cogl_handle_unref (buffer); 518 } 519 520 return shadow_material; 521 } 522 523 /** 524 * _st_create_shadow_cairo_pattern: 525 * @shadow_spec: the definition of the shadow 526 * @src_pattern: surface pattern for which we create the shadow 527 * (must be a surface pattern) 528 * 529 * This is a utility function for creating shadows used by 530 * st-theme-node.c; it's in this file to share the gaussian 531 * blur implementation. The usage of this function is quite different 532 * depending on whether shadow_spec->inset is %TRUE or not. If 533 * shadow_spec->inset is %TRUE, the caller should pass in a @src_pattern 534 * which is the <i>inverse</i> of what they want shadowed, and must take 535 * care of the spread and offset from the shadow spec themselves. If 536 * shadow_spec->inset is %FALSE then the caller should pass in what they 537 * want shadowed directly, and this function takes care of the spread and 538 * the offset. 539 */ 540 cairo_pattern_t * 541 _st_create_shadow_cairo_pattern (StShadow *shadow_spec, 542 cairo_pattern_t *src_pattern) 543 { 544 static cairo_user_data_key_t shadow_pattern_user_data; 545 cairo_t *cr; 546 cairo_surface_t *src_surface; 547 cairo_surface_t *surface_in; 548 cairo_surface_t *surface_out; 549 cairo_pattern_t *dst_pattern; 550 guchar *pixels_in, *pixels_out; 551 gint width_in, height_in, rowstride_in; 552 gint width_out, height_out, rowstride_out; 553 cairo_matrix_t shadow_matrix; 554 int i, j; 555 556 g_return_val_if_fail (shadow_spec != NULL, NULL); 557 g_return_val_if_fail (src_pattern != NULL, NULL); 558 559 cairo_pattern_get_surface (src_pattern, &src_surface); 560 561 width_in = cairo_image_surface_get_width (src_surface); 562 height_in = cairo_image_surface_get_height (src_surface); 563 564 /* We want the output to be a color agnostic alpha mask, 565 * so we need to strip the color channels from the input 566 */ 567 if (cairo_image_surface_get_format (src_surface) != CAIRO_FORMAT_A8) 568 { 569 surface_in = cairo_image_surface_create (CAIRO_FORMAT_A8, 570 width_in, height_in); 571 572 cr = cairo_create (surface_in); 573 cairo_set_source_surface (cr, src_surface, 0, 0); 574 cairo_paint (cr); 575 cairo_destroy (cr); 576 } 577 else 578 { 579 surface_in = cairo_surface_reference (src_surface); 580 } 581 582 pixels_in = cairo_image_surface_get_data (surface_in); 583 rowstride_in = cairo_image_surface_get_stride (surface_in); 584 585 pixels_out = blur_pixels (pixels_in, width_in, height_in, rowstride_in, 586 shadow_spec->blur, 587 &width_out, &height_out, &rowstride_out); 588 cairo_surface_destroy (surface_in); 589 590 /* Invert pixels for inset shadows */ 591 if (shadow_spec->inset) 592 { 593 for (j = 0; j < height_out; j++) 594 { 595 guchar *p = pixels_out + rowstride_out * j; 596 for (i = 0; i < width_out; i++, p++) 597 *p = ~*p; 598 } 599 } 600 601 surface_out = cairo_image_surface_create_for_data (pixels_out, 602 CAIRO_FORMAT_A8, 603 width_out, 604 height_out, 605 rowstride_out); 606 cairo_surface_set_user_data (surface_out, &shadow_pattern_user_data, 607 pixels_out, (cairo_destroy_func_t) g_free); 608 609 dst_pattern = cairo_pattern_create_for_surface (surface_out); 610 cairo_surface_destroy (surface_out); 611 612 cairo_pattern_get_matrix (src_pattern, &shadow_matrix); 613 614 if (shadow_spec->inset) 615 { 616 /* For inset shadows, offsets and spread radius have already been 617 * applied to the original pattern, so all left to do is shift the 618 * blurred image left, so that it aligns centered under the 619 * unblurred one 620 */ 621 cairo_matrix_translate (&shadow_matrix, 622 (width_out - width_in) / 2.0, 623 (height_out - height_in) / 2.0); 624 cairo_pattern_set_matrix (dst_pattern, &shadow_matrix); 625 return dst_pattern; 626 } 627 628 /* Read all the code from the cairo_pattern_set_matrix call 629 * at the end of this function to here from bottom to top, 630 * because each new affine transformation is applied in 631 * front of all the previous ones */ 632 633 /* 6. Invert the matrix back */ 634 cairo_matrix_invert (&shadow_matrix); 635 636 /* 5. Adjust based on specified offsets */ 637 cairo_matrix_translate (&shadow_matrix, 638 shadow_spec->xoffset, 639 shadow_spec->yoffset); 640 641 /* 4. Recenter the newly scaled image */ 642 cairo_matrix_translate (&shadow_matrix, 643 - shadow_spec->spread, 644 - shadow_spec->spread); 645 646 /* 3. Scale up the blurred image to fill the spread */ 647 cairo_matrix_scale (&shadow_matrix, 648 (width_in + 2.0 * shadow_spec->spread) / width_in, 649 (height_in + 2.0 * shadow_spec->spread) / height_in); 650 651 /* 2. Shift the blurred image left, so that it aligns centered 652 * under the unblurred one */ 653 cairo_matrix_translate (&shadow_matrix, 654 - (width_out - width_in) / 2.0, 655 - (height_out - height_in) / 2.0); 656 657 /* 1. Invert the matrix so we can work with it in pattern space 658 */ 659 cairo_matrix_invert (&shadow_matrix); 660 661 cairo_pattern_set_matrix (dst_pattern, &shadow_matrix); 662 663 return dst_pattern; 664 } 665 666 void 667 _st_paint_shadow_with_opacity (StShadow *shadow_spec, 668 CoglHandle shadow_material, 669 ClutterActorBox *box, 670 guint8 paint_opacity) 671 { 672 ClutterActorBox shadow_box; 673 CoglColor color; 674 675 g_return_if_fail (shadow_spec != NULL); 676 g_return_if_fail (shadow_material != COGL_INVALID_HANDLE); 677 678 st_shadow_get_box (shadow_spec, box, &shadow_box); 679 680 cogl_color_set_from_4ub (&color, 681 shadow_spec->color.red * paint_opacity / 255, 682 shadow_spec->color.green * paint_opacity / 255, 683 shadow_spec->color.blue * paint_opacity / 255, 684 shadow_spec->color.alpha * paint_opacity / 255); 685 cogl_color_premultiply (&color); 686 687 cogl_material_set_layer_combine_constant (shadow_material, 0, &color); 688 689 cogl_set_source (shadow_material); 690 cogl_rectangle_with_texture_coords (shadow_box.x1, shadow_box.y1, 691 shadow_box.x2, shadow_box.y2, 692 0, 0, 1, 1); 693 }