Пример #1
0
static void
gtk_css_image_cross_fade_draw (GtkCssImage        *image,
                               cairo_t            *cr,
                               double              width,
                               double              height)
{
  GtkCssImageCrossFade *cross_fade = GTK_CSS_IMAGE_CROSS_FADE (image);

  if (cross_fade->progress <= 0.0)
    {
      if (cross_fade->start)
        _gtk_css_image_draw (cross_fade->start, cr, width, height);
    }
  else if (cross_fade->progress >= 1.0)
    {
      if (cross_fade->end)
        _gtk_css_image_draw (cross_fade->end, cr, width, height);
    }
  else
    {
      if (cross_fade->start && cross_fade->end)
        {
          /* to reduce the group size */
          cairo_rectangle (cr, 0, 0, ceil (width), ceil (height));
          cairo_clip (cr);

          cairo_push_group (cr);

          /* performance trick */
          cairo_reset_clip (cr);

          _gtk_css_image_draw (cross_fade->start, cr, width, height);

          cairo_push_group (cr);
          _gtk_css_image_draw (cross_fade->end, cr, width, height);
          cairo_pop_group_to_source (cr);

          cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
          cairo_paint_with_alpha (cr, cross_fade->progress);

          cairo_pop_group_to_source (cr);
          cairo_paint (cr);
        }
      else if (cross_fade->start || cross_fade->end)
        {
          cairo_push_group (cr);
          _gtk_css_image_draw (cross_fade->start ? cross_fade->start : cross_fade->end, cr, width, height);
          cairo_pop_group_to_source (cr);

          cairo_paint_with_alpha (cr, cross_fade->start ? 1.0 - cross_fade->progress : cross_fade->progress);
        }
    }
}
Пример #2
0
cairo_surface_t *
_gtk_css_image_get_surface (GtkCssImage     *image,
                            cairo_surface_t *target,
                            int              surface_width,
                            int              surface_height)
{
  cairo_surface_t *result;
  cairo_t *cr;

  g_return_val_if_fail (GTK_IS_CSS_IMAGE (image), NULL);
  g_return_val_if_fail (surface_width > 0, NULL);
  g_return_val_if_fail (surface_height > 0, NULL);

  if (target)
    result = cairo_surface_create_similar (target,
                                           CAIRO_CONTENT_COLOR_ALPHA,
                                           surface_width,
                                           surface_height);
  else
    result = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
                                         surface_width,
                                         surface_height);

  cr = cairo_create (result);
  _gtk_css_image_draw (image, cr, surface_width, surface_height);
  cairo_destroy (cr);

  return result;
}
Пример #3
0
static void
gtk_css_image_url_draw (GtkCssImage        *image,
                        cairo_t            *cr,
                        double              width,
                        double              height)
{
  GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image);

  _gtk_css_image_draw (gtk_css_image_url_load_image (url), cr, width, height);
}
Пример #4
0
cairo_surface_t *
_gtk_css_image_get_surface (GtkCssImage     *image,
                            cairo_surface_t *target,
                            int              surface_width,
                            int              surface_height)
{
  cairo_surface_t *result;
  cairo_t *cr;
  double sx, sy;

  g_return_val_if_fail (GTK_IS_CSS_IMAGE (image), NULL);
  g_return_val_if_fail (surface_width > 0, NULL);
  g_return_val_if_fail (surface_height > 0, NULL);


  if (target)
    {
#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
      cairo_surface_get_device_scale (target, &sx, &sy);
#else
      sx = sy = 1;
#endif

      result = cairo_surface_create_similar (target,
					     CAIRO_CONTENT_COLOR_ALPHA,
					     surface_width*sx,
					     surface_height*sy);

#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
      cairo_surface_set_device_scale (result, sx, sy);
#endif
    }
  else
    result = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
                                         surface_width,
                                         surface_height);

  cr = cairo_create (result);
  _gtk_css_image_draw (image, cr, surface_width, surface_height);
  cairo_destroy (cr);

  return result;
}
Пример #5
0
static void
gtk_css_image_fallback_draw (GtkCssImage *image,
                             cairo_t     *cr,
                             double       width,
                             double       height)
{
  GtkCssImageFallback *fallback = GTK_CSS_IMAGE_FALLBACK (image);

  if (fallback->used < 0)
    {
      if (fallback->color)
        gdk_cairo_set_source_rgba (cr, _gtk_css_rgba_value_get_rgba (fallback->color));
      else
        cairo_set_source_rgb (cr, 1, 0, 9);

      cairo_rectangle (cr, 0, 0, width, height);
      cairo_fill (cr);
    }
  else
    _gtk_css_image_draw (fallback->images[fallback->used], cr, width, height);
}
Пример #6
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);
}
Пример #7
0
void
gtk_css_image_builtin_draw (GtkCssImage            *image,
                            cairo_t                *cr,
                            double                  width,
                            double                  height,
                            GtkCssImageBuiltinType  image_type)
{
  if (!GTK_IS_CSS_IMAGE_BUILTIN (image))
    {
      _gtk_css_image_draw (image, cr, width, height);
      return;
    }

  switch (image_type)
  {
  default:
    g_assert_not_reached ();
    break;
  case GTK_CSS_IMAGE_BUILTIN_NONE:
    break;
  case GTK_CSS_IMAGE_BUILTIN_CHECK:
  case GTK_CSS_IMAGE_BUILTIN_CHECK_CHECKED:
  case GTK_CSS_IMAGE_BUILTIN_CHECK_INCONSISTENT:
    gtk_css_image_builtin_draw_check (image, cr,
                                      width, height,
                                      image_type == GTK_CSS_IMAGE_BUILTIN_CHECK_CHECKED,
                                      image_type == GTK_CSS_IMAGE_BUILTIN_CHECK_INCONSISTENT);
    break;
  case GTK_CSS_IMAGE_BUILTIN_OPTION:
  case GTK_CSS_IMAGE_BUILTIN_OPTION_CHECKED:
  case GTK_CSS_IMAGE_BUILTIN_OPTION_INCONSISTENT:
    gtk_css_image_builtin_draw_option (image, cr,
                                       width, height,
                                       image_type == GTK_CSS_IMAGE_BUILTIN_OPTION_CHECKED,
                                       image_type == GTK_CSS_IMAGE_BUILTIN_OPTION_INCONSISTENT);
    break;
  case GTK_CSS_IMAGE_BUILTIN_ARROW_UP:
  case GTK_CSS_IMAGE_BUILTIN_ARROW_DOWN:
  case GTK_CSS_IMAGE_BUILTIN_ARROW_LEFT:
  case GTK_CSS_IMAGE_BUILTIN_ARROW_RIGHT:
    gtk_css_image_builtin_draw_arrow (image, cr,
                                      width, height,
                                      image_type);
    break;
  case GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_LEFT:
    gtk_css_image_builtin_draw_expander (image, cr,
                                         width, height,
                                         TRUE, FALSE, FALSE);
    break;
  case GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_LEFT:
    gtk_css_image_builtin_draw_expander (image, cr,
                                         width, height,
                                         FALSE, FALSE, FALSE);
    break;
  case GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_RIGHT:
    gtk_css_image_builtin_draw_expander (image, cr,
                                         width, height,
                                         TRUE, TRUE, FALSE);
    break;
  case GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_RIGHT:
    gtk_css_image_builtin_draw_expander (image, cr,
                                         width, height,
                                         FALSE, TRUE, FALSE);
    break;
  case GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_LEFT_EXPANDED:
    gtk_css_image_builtin_draw_expander (image, cr,
                                         width, height,
                                         TRUE, FALSE, TRUE);
    break;
  case GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_LEFT_EXPANDED:
    gtk_css_image_builtin_draw_expander (image, cr,
                                         width, height,
                                         FALSE, FALSE, TRUE);
    break;
  case GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_RIGHT_EXPANDED:
    gtk_css_image_builtin_draw_expander (image, cr,
                                         width, height,
                                         TRUE, TRUE, TRUE);
    break;
  case GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_RIGHT_EXPANDED:
    gtk_css_image_builtin_draw_expander (image, cr,
                                         width, height,
                                         FALSE, TRUE, TRUE);
    break;
  case GTK_CSS_IMAGE_BUILTIN_GRIP_TOPLEFT:
  case GTK_CSS_IMAGE_BUILTIN_GRIP_TOP:
  case GTK_CSS_IMAGE_BUILTIN_GRIP_TOPRIGHT:
  case GTK_CSS_IMAGE_BUILTIN_GRIP_RIGHT:
  case GTK_CSS_IMAGE_BUILTIN_GRIP_BOTTOMRIGHT:
  case GTK_CSS_IMAGE_BUILTIN_GRIP_BOTTOM:
  case GTK_CSS_IMAGE_BUILTIN_GRIP_BOTTOMLEFT:
  case GTK_CSS_IMAGE_BUILTIN_GRIP_LEFT:
    gtk_css_image_builtin_draw_grip (image, cr,
                                     width, height,
                                     image_type);
    break;
  case GTK_CSS_IMAGE_BUILTIN_PANE_SEPARATOR:
    gtk_css_image_builtin_draw_pane_separator (image, cr,
                                               width, height);
    break;
  case GTK_CSS_IMAGE_BUILTIN_HANDLE:
    gtk_css_image_builtin_draw_handle (image, cr,
                                       width, height);
    break;
  case GTK_CSS_IMAGE_BUILTIN_SPINNER:
    gtk_css_image_builtin_draw_spinner (image, cr,
                                        width, height);
    break;
  }
}