void _gtk_icon_helper_get_size (GtkIconHelper *self, GtkStyleContext *context, gint *width_out, gint *height_out) { cairo_surface_t *surface; gint width, height; width = height = 0; surface = _gtk_icon_helper_ensure_surface (self, context); if (surface != NULL) { width = self->priv->rendered_surface_width; height = self->priv->rendered_surface_height; cairo_surface_destroy (surface); } else if (self->priv->storage_type == GTK_IMAGE_ANIMATION) { width = gdk_pixbuf_animation_get_width (self->priv->animation); height = gdk_pixbuf_animation_get_height (self->priv->animation); } else if (self->priv->icon_size != -1) { ensure_icon_size (self, context, &width, &height); } if (width_out) *width_out = width; if (height_out) *height_out = height; }
static void ensure_pixbuf_for_gicon (GtkIconHelper *self, GtkStyleContext *context) { GtkIconTheme *icon_theme; gint width, height; GtkIconInfo *info; GtkIconLookupFlags flags; if (!check_invalidate_pixbuf (self, context)) return; icon_theme = gtk_icon_theme_get_for_screen (gtk_style_context_get_screen (context)); flags = get_icon_lookup_flags (self, context); ensure_icon_size (self, context, &width, &height); if (self->priv->gicon != NULL) { info = gtk_icon_theme_lookup_by_gicon (icon_theme, self->priv->gicon, MIN (width, height), flags); } else { g_assert_not_reached (); return; } self->priv->rendered_pixbuf = ensure_stated_icon_from_info (self, context, info); if (info) g_object_unref (info); }
static void get_surface_size (GtkIconHelper *self, GtkStyleContext *context, cairo_surface_t *surface, int *width, int *height) { double x_scale, y_scale; if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE) { x_scale = y_scale = 1; #ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE cairo_surface_get_device_scale (surface, &x_scale, &y_scale); #endif /* Assume any set scaling is icon scale */ *width = ceil (cairo_image_surface_get_width (surface) / x_scale); *height = ceil (cairo_image_surface_get_height (surface) / y_scale); } else ensure_icon_size (self, context, width, height); }
static void get_surface_size (GtkIconHelper *self, cairo_surface_t *surface, int *width, int *height) { GdkRectangle clip; cairo_t *cr; cr = cairo_create (surface); if (gdk_cairo_get_clip_rectangle (cr, &clip)) { if (clip.x != 0 || clip.y != 0) { g_warning ("origin of surface is %d %d, not supported", clip.x, clip.y); } *width = clip.width; *height = clip.height; } else { g_warning ("infinite surface size not supported"); ensure_icon_size (self, width, height); } cairo_destroy (cr); }
void _gtk_icon_helper_get_size (GtkIconHelper *self, GtkStyleContext *context, gint *width_out, gint *height_out) { GdkPixbuf *pix; gint width, height; width = height = 0; pix = _gtk_icon_helper_ensure_pixbuf (self, context); if (pix != NULL) { width = gdk_pixbuf_get_width (pix); height = gdk_pixbuf_get_height (pix); g_object_unref (pix); } else if (self->priv->storage_type == GTK_IMAGE_ANIMATION) { width = gdk_pixbuf_animation_get_width (self->priv->animation); height = gdk_pixbuf_animation_get_height (self->priv->animation); } else if (self->priv->icon_size != -1) { ensure_icon_size (self, context, &width, &height); } if (width_out) *width_out = width; if (height_out) *height_out = height; }
static void ensure_surface_from_pixbuf (GtkIconHelper *self, GtkStyleContext *context) { gint width, height; GdkPixbuf *pixbuf; int scale; if (!check_invalidate_surface (self, context)) return; if (self->priv->rendered_surface) return; scale = get_scale_factor (self, context); if (self->priv->force_scale_pixbuf && (self->priv->pixel_size != -1 || self->priv->icon_size != GTK_ICON_SIZE_INVALID)) { ensure_icon_size (self, context, &width, &height); if (scale != self->priv->orig_pixbuf_scale || width < gdk_pixbuf_get_width (self->priv->orig_pixbuf) / self->priv->orig_pixbuf_scale || height < gdk_pixbuf_get_height (self->priv->orig_pixbuf) / self->priv->orig_pixbuf_scale) { width = MIN (width * scale, gdk_pixbuf_get_width (self->priv->orig_pixbuf) * scale / self->priv->orig_pixbuf_scale); height = MIN (height * scale, gdk_pixbuf_get_height (self->priv->orig_pixbuf) * scale / self->priv->orig_pixbuf_scale); pixbuf = gdk_pixbuf_scale_simple (self->priv->orig_pixbuf, width, height, GDK_INTERP_BILINEAR); } else { pixbuf = g_object_ref (self->priv->orig_pixbuf); scale = self->priv->orig_pixbuf_scale; } } else { pixbuf = g_object_ref (self->priv->orig_pixbuf); scale = self->priv->orig_pixbuf_scale; } self->priv->rendered_surface_width = (gdk_pixbuf_get_width (pixbuf) + scale - 1) / scale; self->priv->rendered_surface_height = (gdk_pixbuf_get_height (pixbuf) + scale - 1) / scale; self->priv->rendered_surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale, self->priv->window); g_object_unref (pixbuf); }
static void ensure_pixbuf_at_size (GtkIconHelper *self, GtkStyleContext *context) { gint width, height; GdkPixbuf *stated; if (!check_invalidate_pixbuf (self, context)) return; if (self->priv->rendered_pixbuf) return; if (self->priv->force_scale_pixbuf && (self->priv->pixel_size != -1 || self->priv->icon_size != GTK_ICON_SIZE_INVALID)) { ensure_icon_size (self, context, &width, &height); if (self->priv->orig_pixbuf_scale > 1 || /* These should divide the orig_pixbuf size by scale, but need not due to the above scale > 1 check */ width < gdk_pixbuf_get_width (self->priv->orig_pixbuf) || height < gdk_pixbuf_get_height (self->priv->orig_pixbuf)) { width = MIN (width, gdk_pixbuf_get_width (self->priv->orig_pixbuf) / self->priv->orig_pixbuf_scale); height = MIN (height, gdk_pixbuf_get_height (self->priv->orig_pixbuf) / self->priv->orig_pixbuf_scale); self->priv->rendered_pixbuf = gdk_pixbuf_scale_simple (self->priv->orig_pixbuf, width, height, GDK_INTERP_BILINEAR); } } else if (self->priv->orig_pixbuf_scale > 1) { width = gdk_pixbuf_get_width (self->priv->orig_pixbuf) / self->priv->orig_pixbuf_scale; height =gdk_pixbuf_get_height (self->priv->orig_pixbuf) / self->priv->orig_pixbuf_scale; self->priv->rendered_pixbuf = gdk_pixbuf_scale_simple (self->priv->orig_pixbuf, width, height, GDK_INTERP_BILINEAR); } if (!self->priv->rendered_pixbuf) self->priv->rendered_pixbuf = g_object_ref (self->priv->orig_pixbuf); stated = ensure_stated_pixbuf_from_pixbuf (self, context, self->priv->rendered_pixbuf); g_object_unref (self->priv->rendered_pixbuf); self->priv->rendered_pixbuf = stated; }
static gboolean get_pixbuf_size (GtkIconHelper *self, GtkStyleContext *context, gint *width_out, gint *height_out, gint *scale_out) { gboolean scale_pixmap; gint width, height; int scale; scale = get_scale_factor (self, context); scale_pixmap = FALSE; if (self->priv->force_scale_pixbuf && (self->priv->pixel_size != -1 || self->priv->icon_size != GTK_ICON_SIZE_INVALID)) { ensure_icon_size (self, context, &width, &height); if (scale != self->priv->orig_pixbuf_scale || width < gdk_pixbuf_get_width (self->priv->orig_pixbuf) / self->priv->orig_pixbuf_scale || height < gdk_pixbuf_get_height (self->priv->orig_pixbuf) / self->priv->orig_pixbuf_scale) { width = MIN (width * scale, gdk_pixbuf_get_width (self->priv->orig_pixbuf) * scale / self->priv->orig_pixbuf_scale); height = MIN (height * scale, gdk_pixbuf_get_height (self->priv->orig_pixbuf) * scale / self->priv->orig_pixbuf_scale); scale_pixmap = TRUE; } else { width = gdk_pixbuf_get_width (self->priv->orig_pixbuf); height = gdk_pixbuf_get_height (self->priv->orig_pixbuf); scale = self->priv->orig_pixbuf_scale; } } else { width = gdk_pixbuf_get_width (self->priv->orig_pixbuf); height = gdk_pixbuf_get_height (self->priv->orig_pixbuf); scale = self->priv->orig_pixbuf_scale; } *width_out = width; *height_out = height; *scale_out = scale; return scale_pixmap; }
static void ensure_surface_for_icon_name_or_gicon (GtkIconHelper *self, GtkStyleContext *context) { GtkIconTheme *icon_theme; gint width, height, scale; GtkIconInfo *info; GtkIconLookupFlags flags; if (!check_invalidate_surface (self, context)) return; icon_theme = gtk_icon_theme_get_default (); flags = get_icon_lookup_flags (self); ensure_icon_size (self, context, &width, &height); scale = get_scale_factor (self, context); if (self->priv->storage_type == GTK_IMAGE_ICON_NAME && self->priv->icon_name != NULL) { info = gtk_icon_theme_lookup_icon_for_scale (icon_theme, self->priv->icon_name, MIN (width, height), scale, flags); } else if (self->priv->storage_type == GTK_IMAGE_GICON && self->priv->gicon != NULL) { info = gtk_icon_theme_lookup_by_gicon_for_scale (icon_theme, self->priv->gicon, MIN (width, height), scale, flags); } else { g_assert_not_reached (); return; } ensure_stated_surface_from_info (self, context, info, scale); if (info) g_object_unref (info); }
void _gtk_icon_helper_get_size (GtkIconHelper *self, GtkStyleContext *context, gint *width_out, gint *height_out) { cairo_surface_t *surface; gint width, height, scale; width = height = 0; /* Certain kinds of images are easy to calculate the size for, these we do immediately to avoid having to potentially load the image data for something that may not yet be visible */ switch (self->priv->storage_type) { case GTK_IMAGE_SURFACE: get_surface_size (self, context, self->priv->orig_surface, &width, &height); break; case GTK_IMAGE_PIXBUF: get_pixbuf_size (self, context, &width, &height, &scale); width = (width + scale - 1) / scale; height = (height + scale - 1) / scale; break; case GTK_IMAGE_ICON_NAME: case GTK_IMAGE_GICON: if (self->priv->pixel_size != -1 || self->priv->force_scale_pixbuf) ensure_icon_size (self, context, &width, &height); break; case GTK_IMAGE_STOCK: case GTK_IMAGE_ICON_SET: case GTK_IMAGE_ANIMATION: case GTK_IMAGE_EMPTY: default: break; } /* Otherwise we load the surface to guarantee we get a size */ if (width == 0) { surface = _gtk_icon_helper_ensure_surface (self, context); if (surface != NULL) { width = self->priv->rendered_surface_width; height = self->priv->rendered_surface_height; cairo_surface_destroy (surface); } else if (self->priv->storage_type == GTK_IMAGE_ANIMATION) { width = gdk_pixbuf_animation_get_width (self->priv->animation); height = gdk_pixbuf_animation_get_height (self->priv->animation); } else if (self->priv->icon_size != GTK_ICON_SIZE_INVALID) { ensure_icon_size (self, context, &width, &height); } } if (width_out) *width_out = width; if (height_out) *height_out = height; }
void _gtk_icon_helper_get_size (GtkIconHelper *self, gint *width_out, gint *height_out) { gint width, height, scale; width = height = 0; /* Certain kinds of images are easy to calculate the size for, these we do immediately to avoid having to potentially load the image data for something that may not yet be visible */ switch (gtk_image_definition_get_storage_type (self->priv->def)) { case GTK_IMAGE_SURFACE: get_surface_size (self, gtk_image_definition_get_surface (self->priv->def), &width, &height); break; case GTK_IMAGE_PIXBUF: get_pixbuf_size (self, gtk_widget_get_scale_factor (gtk_css_gadget_get_owner (GTK_CSS_GADGET (self))), gtk_image_definition_get_pixbuf (self->priv->def), gtk_image_definition_get_scale (self->priv->def), &width, &height, &scale); width = (width + scale - 1) / scale; height = (height + scale - 1) / scale; break; case GTK_IMAGE_ANIMATION: { GdkPixbufAnimation *animation = gtk_image_definition_get_animation (self->priv->def); width = gdk_pixbuf_animation_get_width (animation); height = gdk_pixbuf_animation_get_height (animation); break; } case GTK_IMAGE_ICON_NAME: case GTK_IMAGE_GICON: if (self->priv->pixel_size != -1 || self->priv->force_scale_pixbuf) ensure_icon_size (self, &width, &height); break; case GTK_IMAGE_STOCK: case GTK_IMAGE_ICON_SET: case GTK_IMAGE_EMPTY: default: break; } /* Otherwise we load the surface to guarantee we get a size */ if (width == 0) { gtk_icon_helper_ensure_surface (self); if (self->priv->rendered_surface != NULL) { get_surface_size (self, self->priv->rendered_surface, &width, &height); } else if (self->priv->icon_size != GTK_ICON_SIZE_INVALID) { ensure_icon_size (self, &width, &height); } } if (width_out) *width_out = width; if (height_out) *height_out = height; }
static cairo_surface_t * ensure_surface_for_gicon (GtkIconHelper *self, GtkCssStyle *style, GtkTextDirection dir, gint scale, GIcon *gicon) { GtkIconHelperPrivate *priv = self->priv; GtkIconTheme *icon_theme; gint width, height; GtkIconInfo *info; GtkIconLookupFlags flags; cairo_surface_t *surface; GdkPixbuf *destination; gboolean symbolic; icon_theme = gtk_css_icon_theme_value_get_icon_theme (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_THEME)); flags = get_icon_lookup_flags (self, style, dir); ensure_icon_size (self, &width, &height); info = gtk_icon_theme_lookup_by_gicon_for_scale (icon_theme, gicon, MIN (width, height), scale, flags); if (info) { symbolic = gtk_icon_info_is_symbolic (info); if (symbolic) { GdkRGBA fg, success_color, warning_color, error_color; gtk_icon_theme_lookup_symbolic_colors (style, &fg, &success_color, &warning_color, &error_color); destination = gtk_icon_info_load_symbolic (info, &fg, &success_color, &warning_color, &error_color, NULL, NULL); } else { destination = gtk_icon_info_load_icon (info, NULL); } g_object_unref (info); } else { destination = NULL; } if (destination == NULL) { destination = gtk_icon_theme_load_icon (icon_theme, "image-missing", width, flags | GTK_ICON_LOOKUP_USE_BUILTIN | GTK_ICON_LOOKUP_GENERIC_FALLBACK, NULL); /* We include this image as resource, so we always have it available or * the icontheme code is broken */ g_assert (destination); symbolic = FALSE; } surface = gdk_cairo_surface_create_from_pixbuf (destination, scale, gtk_widget_get_window (gtk_css_gadget_get_owner (GTK_CSS_GADGET (self)))); if (!symbolic) { GtkCssIconEffect icon_effect; icon_effect = _gtk_css_icon_effect_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_EFFECT)); gtk_css_icon_effect_apply (icon_effect, surface); } else { priv->rendered_surface_is_symbolic = TRUE; } g_object_unref (destination); return surface; }