Exemplo n.º 1
0
static void
gtk_css_computed_values_create_css_transitions (GtkCssComputedValues *values,
        gint64                timestamp,
        GtkCssComputedValues *source)
{
    TransitionInfo transitions[GTK_CSS_PROPERTY_N_PROPERTIES] = { { 0, } };
    GtkCssValue *durations, *delays, *timing_functions;
    guint i;

    transition_infos_set (transitions, _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_TRANSITION_PROPERTY));

    durations = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_TRANSITION_DURATION);
    delays = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_TRANSITION_DELAY);
    timing_functions = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION);

    for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
    {
        GtkStyleAnimation *animation;
        GtkCssValue *start, *end;
        double duration, delay;

        if (!transitions[i].pending)
            continue;

        duration = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, transitions[i].index), 100);
        delay = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, transitions[i].index), 100);
        if (duration + delay == 0.0)
            continue;

        start = _gtk_css_computed_values_get_intrinsic_value (source, i);
        end = _gtk_css_computed_values_get_intrinsic_value (values, i);
        if (_gtk_css_value_equal (start, end))
        {
            animation = gtk_css_computed_values_find_transition (GTK_CSS_COMPUTED_VALUES (source), i);
            if (animation)
                values->animations = g_slist_prepend (values->animations, g_object_ref (animation));
        }
        else
        {
            animation = _gtk_css_transition_new (i,
                                                 _gtk_css_computed_values_get_value (source, i),
                                                 _gtk_css_array_value_get_nth (timing_functions, i),
                                                 timestamp + delay * G_USEC_PER_SEC,
                                                 timestamp + (delay + duration) * G_USEC_PER_SEC);
            values->animations = g_slist_prepend (values->animations, animation);
        }
    }
}
Exemplo n.º 2
0
static void
_gtk_theming_background_layer_apply_clip (GtkThemingBackground *bg,
                                          GtkThemingBackgroundLayer *layer)
{
  GtkCssValue *value = _gtk_style_context_peek_property (bg->context, GTK_CSS_PROPERTY_BACKGROUND_CLIP);
  GtkCssArea clip = _gtk_css_area_value_get (_gtk_css_array_value_get_nth (value, layer->idx));

  _gtk_theming_background_apply_clip (bg, &layer->clip_box, clip);
}
Exemplo n.º 3
0
void
gtk_theming_background_render (GtkStyleContext      *context,
                               cairo_t              *cr,
                               gdouble               x,
                               gdouble               y,
                               gdouble               width,
                               gdouble               height,
                               GtkJunctionSides      junction)
{
  GtkThemingBackground bg;
  gint idx;
  GtkCssValue *background_image;
  GtkCssValue *box_shadow;
  const GdkRGBA *bg_color;

  background_image = _gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BACKGROUND_IMAGE);
  bg_color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BACKGROUND_COLOR));
  box_shadow = _gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BOX_SHADOW);

  /* This is the common default case of no background */
  if (gtk_rgba_is_clear (bg_color) &&
      _gtk_css_array_value_get_n_values (background_image) == 1 &&
      _gtk_css_image_value_get_image (_gtk_css_array_value_get_nth (background_image, 0)) == NULL &&
      _gtk_css_shadows_value_is_none (box_shadow))
    return;

  bg.context = context;
  _gtk_theming_background_init_context (&bg, width, height, junction);

  cairo_save (cr);
  cairo_translate (cr, x, y);

  /* Outset shadows */
  _gtk_css_shadows_value_paint_box (box_shadow,
                                    cr,
                                    &bg.boxes[GTK_CSS_AREA_BORDER_BOX],
                                    FALSE);

  _gtk_theming_background_paint_color (&bg, cr, bg_color, background_image);

  for (idx = _gtk_css_array_value_get_n_values (background_image) - 1; idx >= 0; idx--)
    {
      _gtk_theming_background_paint_layer (&bg, idx, cr);
    }

  /* Inset shadows */
  _gtk_css_shadows_value_paint_box (box_shadow,
                                    cr,
                                    &bg.boxes[GTK_CSS_AREA_PADDING_BOX],
                                    TRUE);

  cairo_restore (cr);
}
Exemplo n.º 4
0
gboolean
_gtk_theming_background_has_background_image (GtkThemingBackground *bg)
{
  GtkCssImage *image;
  GtkCssValue *value = _gtk_style_context_peek_property (bg->context, GTK_CSS_PROPERTY_BACKGROUND_IMAGE);

  if (_gtk_css_array_value_get_n_values (value) == 0)
    return FALSE;

  image = _gtk_css_image_value_get_image (_gtk_css_array_value_get_nth (value, 0));
  return (image != NULL);
}
Exemplo n.º 5
0
static void
_gtk_theming_background_init_layer (GtkThemingBackground *bg,
                                    GtkThemingBackgroundLayer *layer,
                                    GtkCssValue *background_image,
                                    gint idx)
{
  layer->idx = idx;
  layer->clip_box = bg->border_box;

  _gtk_theming_background_layer_apply_clip (bg, layer);
  _gtk_theming_background_layer_apply_origin (bg, layer);

  layer->image = _gtk_css_image_value_get_image (_gtk_css_array_value_get_nth (background_image, layer->idx));
}
Exemplo n.º 6
0
static void
_gtk_theming_background_paint_color (GtkThemingBackground *bg,
                                     cairo_t              *cr,
                                     const GdkRGBA        *bg_color,
                                     GtkCssValue          *background_image)
{
  gint n_values = _gtk_css_array_value_get_n_values (background_image);
  GtkCssArea clip = _gtk_css_area_value_get 
    (_gtk_css_array_value_get_nth 
     (_gtk_style_context_peek_property (bg->context, GTK_CSS_PROPERTY_BACKGROUND_CLIP), 
      n_values - 1));

  _gtk_rounded_box_path (&bg->boxes[clip], cr);
  gdk_cairo_set_source_rgba (cr, bg_color);
  cairo_fill (cr);
}
Exemplo n.º 7
0
static void
_gtk_theming_background_layer_apply_origin (GtkThemingBackground *bg,
                                            GtkThemingBackgroundLayer *layer)
{
  cairo_rectangle_t image_rect;
  GtkCssValue *value = _gtk_style_context_peek_property (bg->context, GTK_CSS_PROPERTY_BACKGROUND_ORIGIN);
  GtkCssArea origin = _gtk_css_area_value_get (_gtk_css_array_value_get_nth (value, layer->idx));

  /* The default size of the background image depends on the
     background-origin value as this affects the top left
     and the bottom right corners. */
  switch (origin) {
  case GTK_CSS_AREA_BORDER_BOX:
    image_rect.x = 0;
    image_rect.y = 0;
    image_rect.width = bg->paint_area.width;
    image_rect.height = bg->paint_area.height;
    break;
  case GTK_CSS_AREA_CONTENT_BOX:
    image_rect.x = bg->border.left + bg->padding.left;
    image_rect.y = bg->border.top + bg->padding.top;
    image_rect.width = bg->paint_area.width - bg->border.left - bg->border.right - bg->padding.left - bg->padding.right;
    image_rect.height = bg->paint_area.height - bg->border.top - bg->border.bottom - bg->padding.top - bg->padding.bottom;
    break;
  case GTK_CSS_AREA_PADDING_BOX:
  default:
    image_rect.x = bg->border.left;
    image_rect.y = bg->border.top;
    image_rect.width = bg->paint_area.width - bg->border.left - bg->border.right;
    image_rect.height = bg->paint_area.height - bg->border.top - bg->border.bottom;
    break;
  }

  /* XXX: image_rect might have negative width/height here.
   * Do we need to do something about it? */
  layer->image_rect = image_rect;
}
Exemplo n.º 8
0
static void
transition_infos_set (TransitionInfo  infos[GTK_CSS_PROPERTY_N_PROPERTIES],
                      GtkCssValue    *transitions)
{
    guint i;

    for (i = 0; i < _gtk_css_array_value_get_n_values (transitions); i++)
    {
        GtkStyleProperty *property;
        GtkCssValue *prop_value;

        prop_value = _gtk_css_array_value_get_nth (transitions, i);
        if (g_ascii_strcasecmp (_gtk_css_ident_value_get (prop_value), "all") == 0)
            property = NULL;
        else
        {
            property = _gtk_style_property_lookup (_gtk_css_ident_value_get (prop_value));
            if (property == NULL)
                continue;
        }

        transition_info_add (infos, property, i);
    }
}
Exemplo n.º 9
0
static void
_gtk_theming_background_paint_color (GtkThemingBackground *bg,
                                     cairo_t              *cr,
                                     GtkCssValue          *background_image)
{
  GtkRoundedBox clip_box;
  gint n_values = _gtk_css_array_value_get_n_values (background_image);
  GtkCssArea clip = _gtk_css_area_value_get 
    (_gtk_css_array_value_get_nth 
     (_gtk_style_context_peek_property (bg->context, GTK_CSS_PROPERTY_BACKGROUND_CLIP), 
      n_values - 1));

  clip_box = bg->border_box;
  _gtk_theming_background_apply_clip (bg, &clip_box, clip);

  cairo_save (cr);
  _gtk_rounded_box_path (&clip_box, cr);
  cairo_clip (cr);

  gdk_cairo_set_source_rgba (cr, &bg->bg_color);
  cairo_paint (cr);

  cairo_restore (cr);
}
Exemplo n.º 10
0
static void
gtk_css_computed_values_create_css_animations (GtkCssComputedValues    *values,
        GtkCssComputedValues    *parent_values,
        gint64                   timestamp,
        GtkStyleProviderPrivate *provider,
        GtkCssComputedValues    *source)
{
    GtkCssValue *durations, *delays, *timing_functions, *animations;
    GtkCssValue *iteration_counts, *directions, *play_states, *fill_modes;
    guint i;

    animations = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_NAME);
    durations = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_DURATION);
    delays = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_DELAY);
    timing_functions = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION);
    iteration_counts = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT);
    directions = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_DIRECTION);
    play_states = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE);
    fill_modes = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_FILL_MODE);

    for (i = 0; i < _gtk_css_array_value_get_n_values (animations); i++)
    {
        GtkStyleAnimation *animation;
        GtkCssKeyframes *keyframes;
        const char *name;

        name = _gtk_css_ident_value_get (_gtk_css_array_value_get_nth (animations, i));
        if (g_ascii_strcasecmp (name, "none") == 0)
            continue;

        animation = gtk_css_computed_values_find_animation (values, name);
        if (animation)
            continue;

        if (source)
            animation = gtk_css_computed_values_find_animation (source, name);

        if (animation)
        {
            animation = _gtk_css_animation_copy (GTK_CSS_ANIMATION (animation),
                                                 timestamp,
                                                 _gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)));
        }
        else
        {
            keyframes = _gtk_style_provider_private_get_keyframes (provider, name);
            if (keyframes == NULL)
                continue;

            keyframes = _gtk_css_keyframes_compute (keyframes, provider, values, parent_values);

            animation = _gtk_css_animation_new (name,
                                                keyframes,
                                                timestamp,
                                                _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, i), 100) * G_USEC_PER_SEC,
                                                _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, i), 100) * G_USEC_PER_SEC,
                                                _gtk_css_array_value_get_nth (timing_functions, i),
                                                _gtk_css_direction_value_get (_gtk_css_array_value_get_nth (directions, i)),
                                                _gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)),
                                                _gtk_css_fill_mode_value_get (_gtk_css_array_value_get_nth (fill_modes, i)),
                                                _gtk_css_number_value_get (_gtk_css_array_value_get_nth (iteration_counts, i), 100));
            _gtk_css_keyframes_unref (keyframes);
        }
        values->animations = g_slist_prepend (values->animations, animation);
    }
}
Exemplo n.º 11
0
static void
_gtk_theming_background_paint_layer (GtkThemingBackground *bg,
                                     guint                 idx,
                                     cairo_t              *cr)
{
  GtkCssRepeatStyle hrepeat, vrepeat;
  const GtkCssValue *pos, *repeat;
  GtkCssImage *image;
  const GtkRoundedBox *origin;
  double image_width, image_height;
  double width, height;

  pos = _gtk_css_array_value_get_nth (_gtk_style_context_peek_property (bg->context, GTK_CSS_PROPERTY_BACKGROUND_POSITION), idx);
  repeat = _gtk_css_array_value_get_nth (_gtk_style_context_peek_property (bg->context, GTK_CSS_PROPERTY_BACKGROUND_REPEAT), idx);
  hrepeat = _gtk_css_background_repeat_value_get_x (repeat);
  vrepeat = _gtk_css_background_repeat_value_get_y (repeat);
  image = _gtk_css_image_value_get_image (
              _gtk_css_array_value_get_nth (
                  _gtk_style_context_peek_property (bg->context, GTK_CSS_PROPERTY_BACKGROUND_IMAGE),
                  idx));
  origin = &bg->boxes[
               _gtk_css_area_value_get (
                   _gtk_css_array_value_get_nth (
                       _gtk_style_context_peek_property (bg->context, GTK_CSS_PROPERTY_BACKGROUND_ORIGIN),
                       idx))];
  width = origin->box.width;
  height = origin->box.height;

  if (image == NULL || width <= 0 || height <= 0)
    return;

  _gtk_css_bg_size_value_compute_size (_gtk_css_array_value_get_nth (_gtk_style_context_peek_property (bg->context, GTK_CSS_PROPERTY_BACKGROUND_SIZE), idx),
                                       image,
                                       width,
                                       height,
                                       &image_width,
                                       &image_height);

  if (image_width <= 0 || image_height <= 0)
    return;

  /* optimization */
  if (image_width == width)
    hrepeat = GTK_CSS_REPEAT_STYLE_NO_REPEAT;
  if (image_height == height)
    vrepeat = GTK_CSS_REPEAT_STYLE_NO_REPEAT;


  cairo_save (cr);

  _gtk_rounded_box_path (
      &bg->boxes[
          _gtk_css_area_value_get (
              _gtk_css_array_value_get_nth (
                  _gtk_style_context_peek_property (bg->context, GTK_CSS_PROPERTY_BACKGROUND_CLIP),
                  idx))],
      cr);
  cairo_clip (cr);


  cairo_translate (cr, origin->box.x, origin->box.y);

  if (hrepeat == GTK_CSS_REPEAT_STYLE_NO_REPEAT && vrepeat == GTK_CSS_REPEAT_STYLE_NO_REPEAT)
    {
      cairo_translate (cr,
                       _gtk_css_position_value_get_x (pos, width - image_width),
                       _gtk_css_position_value_get_y (pos, height - image_height));
      /* shortcut for normal case */
      _gtk_css_image_draw (image, cr, image_width, image_height);
    }
  else
    {
      int surface_width, surface_height;
      cairo_rectangle_t fill_rect;
      cairo_surface_t *surface;
      cairo_t *cr2;

      /* If ‘background-repeat’ is ‘round’ for one (or both) dimensions,
       * there is a second step. The UA must scale the image in that
       * dimension (or both dimensions) so that it fits a whole number of
       * times in the background positioning area. In the case of the width
       * (height is analogous):
       *
       * If X ≠ 0 is the width of the image after step one and W is the width
       * of the background positioning area, then the rounded width
       * X' = W / round(W / X) where round() is a function that returns the
       * nearest natural number (integer greater than zero). 
       *
       * If ‘background-repeat’ is ‘round’ for one dimension only and if
       * ‘background-size’ is ‘auto’ for the other dimension, then there is
       * a third step: that other dimension is scaled so that the original
       * aspect ratio is restored. 
       */
      if (hrepeat == GTK_CSS_REPEAT_STYLE_ROUND)
        {
          double n = round (width / image_width);

          n = MAX (1, n);

          if (vrepeat != GTK_CSS_REPEAT_STYLE_ROUND
              /* && vsize == auto (it is by default) */)
            image_height *= width / (image_width * n);
          image_width = width / n;
        }
      if (vrepeat == GTK_CSS_REPEAT_STYLE_ROUND)
        {
          double n = round (height / image_height);

          n = MAX (1, n);

          if (hrepeat != GTK_CSS_REPEAT_STYLE_ROUND
              /* && hsize == auto (it is by default) */)
            image_width *= height / (image_height * n);
          image_height = height / n;
        }

      /* if hrepeat or vrepeat is 'space', we create a somewhat larger surface
       * to store the extra space. */
      if (hrepeat == GTK_CSS_REPEAT_STYLE_SPACE)
        {
          double n = floor (width / image_width);
          surface_width = n ? round (width / n) : 0;
        }
      else
        surface_width = round (image_width);

      if (vrepeat == GTK_CSS_REPEAT_STYLE_SPACE)
        {
          double n = floor (height / image_height);
          surface_height = n ? round (height / n) : 0;
        }
      else
        surface_height = round (image_height);

      surface = cairo_surface_create_similar (cairo_get_target (cr),
                                              CAIRO_CONTENT_COLOR_ALPHA,
                                              surface_width, surface_height);
      cr2 = cairo_create (surface);
      cairo_translate (cr2,
                       0.5 * (surface_width - image_width),
                       0.5 * (surface_height - image_height));
      _gtk_css_image_draw (image, cr2, image_width, image_height);
      cairo_destroy (cr2);

      cairo_set_source_surface (cr, surface,
                                _gtk_css_position_value_get_x (pos, width - image_width),
                                _gtk_css_position_value_get_y (pos, height - image_height));
      cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
      cairo_surface_destroy (surface);

      if (hrepeat == GTK_CSS_REPEAT_STYLE_NO_REPEAT)
        {
          fill_rect.x = _gtk_css_position_value_get_x (pos, width - image_width);
          fill_rect.width = image_width;
        }
      else
        {
          fill_rect.x = 0;
          fill_rect.width = width;
        }

      if (vrepeat == GTK_CSS_REPEAT_STYLE_NO_REPEAT)
        {
          fill_rect.y = _gtk_css_position_value_get_y (pos, height - image_height);
          fill_rect.height = image_height;
        }
      else
        {
          fill_rect.y = 0;
          fill_rect.height = height;
        }

      cairo_rectangle (cr, fill_rect.x, fill_rect.y,
                       fill_rect.width, fill_rect.height);
      cairo_fill (cr);
    }


  cairo_restore (cr);
}
Exemplo n.º 12
0
static GSList *
gtk_css_animated_style_create_css_transitions (GSList              *animations,
                                               GtkCssStyle         *base_style,
                                               gint64               timestamp,
                                               GtkCssStyle         *source)
{
  TransitionInfo transitions[GTK_CSS_PROPERTY_N_PROPERTIES] = { { 0, } };
  GtkCssValue *durations, *delays, *timing_functions;
  guint i;

  transition_infos_set (transitions, gtk_css_style_get_value (base_style, GTK_CSS_PROPERTY_TRANSITION_PROPERTY));

  durations = gtk_css_style_get_value (base_style, GTK_CSS_PROPERTY_TRANSITION_DURATION);
  delays = gtk_css_style_get_value (base_style, GTK_CSS_PROPERTY_TRANSITION_DELAY);
  timing_functions = gtk_css_style_get_value (base_style, GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION);

  for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++)
    {
      GtkStyleAnimation *animation;
      GtkCssValue *start, *end;
      double duration, delay;

      if (!transitions[i].pending)
        continue;

      duration = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, transitions[i].index), 100);
      delay = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, transitions[i].index), 100);
      if (duration + delay == 0.0)
        continue;

      if (GTK_IS_CSS_ANIMATED_STYLE (source))
        {
          start = gtk_css_animated_style_get_intrinsic_value (GTK_CSS_ANIMATED_STYLE (source), i);
          end = gtk_css_style_get_value (base_style, i);

          if (_gtk_css_value_equal (start, end))
            {
              animation = gtk_css_animated_style_find_transition (GTK_CSS_ANIMATED_STYLE (source), i);
              if (animation)
                {
                  animation = _gtk_style_animation_advance (animation, timestamp);
                  animations = g_slist_prepend (animations, animation);
                }

              continue;
            }
        }

      if (_gtk_css_value_equal (gtk_css_style_get_value (source, i),
                                gtk_css_style_get_value (base_style, i)))
        continue;

      animation = _gtk_css_transition_new (i,
                                           gtk_css_style_get_value (source, i),
                                           _gtk_css_array_value_get_nth (timing_functions, i),
                                           timestamp,
                                           duration * G_USEC_PER_SEC,
                                           delay * G_USEC_PER_SEC);
      animations = g_slist_prepend (animations, animation);
    }

  return animations;
}