diff --git a/src/st/st-icon.c b/src/st/st-icon.c index 761c0afd74..47cfd715e9 100644 --- a/src/st/st-icon.c +++ b/src/st/st-icon.c @@ -57,6 +57,7 @@ struct _StIconPrivate gint theme_icon_size; /* icon size from theme node */ gint icon_size; /* icon size we are using */ gint icon_scale; + gfloat resource_scale; CoglPipeline *shadow_pipeline; @@ -72,6 +73,7 @@ static void st_icon_update (StIcon *icon); static gboolean st_icon_update_icon_size (StIcon *icon); static void st_icon_update_shadow_pipeline (StIcon *icon); static void st_icon_clear_shadow_pipeline (StIcon *icon); +static gfloat st_icon_get_resource_scale (StIcon *icon); #define DEFAULT_ICON_SIZE 48 #define DEFAULT_ICON_TYPE ST_ICON_SYMBOLIC @@ -244,6 +246,33 @@ st_icon_style_changed (StWidget *widget) st_icon_update (self); } +static gfloat +st_icon_get_resource_scale (StIcon *icon) +{ + gfloat resource_scale = 1.0; + + clutter_actor_get_resource_scale (CLUTTER_ACTOR (icon), &resource_scale); + + return resource_scale; +} + +static void +st_icon_resource_scale_changed (GObject *gobject, + GParamSpec *pspec, + gpointer user_data) +{ + StIcon *icon = ST_ICON (gobject); + StIconPrivate *priv = icon->priv; + gfloat resource_scale; + + resource_scale = st_icon_get_resource_scale (icon); + if (priv->resource_scale == resource_scale) + return; + + priv->resource_scale = resource_scale; + st_icon_update (icon); +} + static void st_icon_class_init (StIconClass *klass) { @@ -309,8 +338,12 @@ st_icon_init (StIcon *self) self->priv->shadow_pipeline = NULL; self->priv->icon_scale = 1; + self->priv->resource_scale = 1.0; self->priv->file_uri = NULL; + + g_signal_connect (self, "notify::resource-scale", + G_CALLBACK (st_icon_resource_scale_changed), NULL); } static void @@ -436,24 +469,31 @@ st_icon_update (StIcon *icon) return; priv->icon_scale = st_theme_context_get_scale_for_stage (); + priv->resource_scale = st_icon_get_resource_scale (icon); cache = st_texture_cache_get_default (); if (priv->gicon) { - priv->pending_texture = st_texture_cache_load_gicon (cache, - (priv->icon_type != ST_ICON_APPLICATION && - priv->icon_type != ST_ICON_DOCUMENT) ? - theme_node : NULL, - priv->gicon, - priv->icon_size); + priv->pending_texture = + st_texture_cache_load_gicon_with_scale (cache, + (priv->icon_type != ST_ICON_APPLICATION && + priv->icon_type != ST_ICON_DOCUMENT) ? + theme_node : NULL, + priv->gicon, + priv->icon_size, + priv->icon_scale, + priv->resource_scale); } else if (priv->icon_name) { - priv->pending_texture = st_texture_cache_load_icon_name (cache, - theme_node, - priv->icon_name, - priv->icon_type, - priv->icon_size); + priv->pending_texture = + st_texture_cache_load_icon_name_with_scale (cache, + theme_node, + priv->icon_name, + priv->icon_type, + priv->icon_size, + priv->icon_scale, + priv->resource_scale); } if (priv->pending_texture) diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c index 868e3773bd..d01ce9ec5a 100644 --- a/src/st/st-texture-cache.c +++ b/src/st/st-texture-cache.c @@ -595,7 +595,8 @@ pixbuf_to_st_content_image (GdkPixbuf *pixbuf, } static cairo_surface_t * -pixbuf_to_cairo_surface (GdkPixbuf *pixbuf) +pixbuf_to_cairo_surface (GdkPixbuf *pixbuf, + float resource_scale) { cairo_surface_t *dummy_surface; cairo_pattern_t *pattern; @@ -609,6 +610,7 @@ pixbuf_to_cairo_surface (GdkPixbuf *pixbuf) pattern = cairo_get_source (cr); cairo_pattern_get_surface (pattern, &surface); cairo_surface_reference (surface); + cairo_surface_set_device_scale (surface, resource_scale, resource_scale); cairo_destroy (cr); cairo_surface_destroy (dummy_surface); @@ -1835,11 +1837,13 @@ symbolic_name_for_icon (const char *name) * Return Value: (transfer none): A new #ClutterTexture for the icon */ ClutterActor * -st_texture_cache_load_icon_name (StTextureCache *cache, - StThemeNode *theme_node, - const char *name, - StIconType icon_type, - gint size) +st_texture_cache_load_icon_name_with_scale (StTextureCache *cache, + StThemeNode *theme_node, + const char *name, + StIconType icon_type, + gint size, + gint paint_scale, + gfloat resource_scale) { ClutterActor *texture; GIcon *themed; @@ -1851,24 +1855,28 @@ st_texture_cache_load_icon_name (StTextureCache *cache, { case ST_ICON_APPLICATION: themed = g_themed_icon_new (name); - texture = st_texture_cache_load_gicon (cache, theme_node, themed, size); + texture = st_texture_cache_load_gicon_with_scale (cache, theme_node, themed, size, + paint_scale, resource_scale); g_object_unref (themed); if (texture == NULL) { themed = g_themed_icon_new ("application-x-executable"); - texture = st_texture_cache_load_gicon (cache, theme_node, themed, size); + texture = st_texture_cache_load_gicon_with_scale (cache, theme_node, themed, size, + paint_scale, resource_scale); g_object_unref (themed); } return CLUTTER_ACTOR (texture); break; case ST_ICON_DOCUMENT: themed = g_themed_icon_new (name); - texture = st_texture_cache_load_gicon (cache, theme_node, themed, size); + texture = st_texture_cache_load_gicon_with_scale (cache, theme_node, themed, size, + paint_scale, resource_scale); g_object_unref (themed); if (texture == NULL) { themed = g_themed_icon_new ("x-office-document"); - texture = st_texture_cache_load_gicon (cache, theme_node, themed, size); + texture = st_texture_cache_load_gicon_with_scale (cache, theme_node, themed, size, + paint_scale, resource_scale); g_object_unref (themed); } @@ -1878,19 +1886,22 @@ st_texture_cache_load_icon_name (StTextureCache *cache, symbolic_name = symbolic_name_for_icon (name); themed = g_themed_icon_new (symbolic_name); g_free (symbolic_name); - texture = st_texture_cache_load_gicon (cache, theme_node, themed, size); + texture = st_texture_cache_load_gicon_with_scale (cache, theme_node, themed, size, + paint_scale, resource_scale); g_object_unref (themed); return CLUTTER_ACTOR (texture); break; case ST_ICON_FULLCOLOR: themed = g_themed_icon_new (name); - texture = st_texture_cache_load_gicon (cache, theme_node, themed, size); + texture = st_texture_cache_load_gicon_with_scale (cache, theme_node, themed, size, + paint_scale, resource_scale); g_object_unref (themed); if (texture == NULL) { themed = g_themed_icon_new ("image-missing"); - texture = st_texture_cache_load_gicon (cache, theme_node, themed, size); + texture = st_texture_cache_load_gicon_with_scale (cache, theme_node, themed, size, + paint_scale, resource_scale); g_object_unref (themed); } @@ -1901,6 +1912,19 @@ st_texture_cache_load_icon_name (StTextureCache *cache, } } +ClutterActor * +st_texture_cache_load_icon_name (StTextureCache *cache, + StThemeNode *theme_node, + const char *name, + StIconType icon_type, + gint size) +{ + return st_texture_cache_load_icon_name_with_scale (cache, theme_node, name, + icon_type, size, + st_theme_context_get_scale_for_stage (), + 1.0); +} + /** * st_texture_cache_load_uri_async: * @cache: The texture cache instance @@ -2012,7 +2036,7 @@ st_texture_cache_load_file_sync_to_cairo_surface (StTextureCache *cache, if (!pixbuf) goto out; - surface = pixbuf_to_cairo_surface (pixbuf); + surface = pixbuf_to_cairo_surface (pixbuf, resource_scale); g_object_unref (pixbuf); if (policy == ST_TEXTURE_CACHE_POLICY_FOREVER) @@ -2214,4 +2238,4 @@ st_texture_cache_can_load_mime_type (StTextureCache *cache, return FALSE; return g_hash_table_contains (priv->image_type_table, mime_type); -} \ No newline at end of file +} diff --git a/src/st/st-texture-cache.h b/src/st/st-texture-cache.h index 98ab13e98d..cd71b1da28 100644 --- a/src/st/st-texture-cache.h +++ b/src/st/st-texture-cache.h @@ -112,6 +112,14 @@ ClutterActor *st_texture_cache_load_icon_name (StTextureCache *cache, StIconType icon_type, gint size); +ClutterActor *st_texture_cache_load_icon_name_with_scale (StTextureCache *cache, + StThemeNode *theme_node, + const char *name, + StIconType icon_type, + gint size, + gint paint_scale, + gfloat resource_scale); + ClutterActor *st_texture_cache_load_file_async (StTextureCache *cache, GFile *file, int available_width, diff --git a/src/st/st-theme-node-drawing.c b/src/st/st-theme-node-drawing.c index f5fb1b4936..bdb18b27a1 100644 --- a/src/st/st-theme-node-drawing.c +++ b/src/st/st-theme-node-drawing.c @@ -479,8 +479,8 @@ get_background_position (StThemeNode *self, gdouble scale_w, scale_h; /* get the background image size */ - background_image_width = cogl_texture_get_width (self->background_texture); - background_image_height = cogl_texture_get_height (self->background_texture); + background_image_width = cogl_texture_get_width (self->background_texture) / self->resource_scale; + background_image_height = cogl_texture_get_height (self->background_texture) / self->resource_scale; /* get the painting area size */ painting_area_width = allocation->x2 - allocation->x1; @@ -596,6 +596,7 @@ create_cairo_pattern_of_background_gradient (StThemeNode *node) static cairo_pattern_t * create_cairo_pattern_of_background_image (StThemeNode *node, + float resource_scale, gboolean *needs_background_fill) { cairo_surface_t *surface; @@ -605,6 +606,7 @@ create_cairo_pattern_of_background_image (StThemeNode *node, const char *file; StTextureCache *texture_cache; + GFile *gfile; gdouble background_image_width, background_image_height; gdouble x, y; @@ -614,7 +616,12 @@ create_cairo_pattern_of_background_image (StThemeNode *node, texture_cache = st_texture_cache_get_default (); - surface = st_texture_cache_load_file_to_cairo_surface (texture_cache, file); + gfile = g_file_new_for_path (file); + surface = st_texture_cache_load_gfile_to_cairo_surface (texture_cache, + gfile, + st_theme_context_get_scale_for_stage (), + resource_scale); + g_object_unref (gfile); if (surface == NULL) return NULL; @@ -624,8 +631,8 @@ create_cairo_pattern_of_background_image (StThemeNode *node, content = cairo_surface_get_content (surface); pattern = cairo_pattern_create_for_surface (surface); - background_image_width = cairo_image_surface_get_width (surface); - background_image_height = cairo_image_surface_get_height (surface); + background_image_width = cairo_image_surface_get_width (surface) / resource_scale; + background_image_height = cairo_image_surface_get_height (surface) / resource_scale; *needs_background_fill = TRUE; @@ -941,7 +948,8 @@ paint_inset_box_shadow_to_cairo_context (StThemeNode *node, * cases (gradients, background images, etc). */ static CoglHandle -st_theme_node_prerender_background (StThemeNode *node) +st_theme_node_prerender_background (StThemeNode *node, + float resource_scale) { StBorderImage *border_image; CoglHandle texture; @@ -965,6 +973,7 @@ st_theme_node_prerender_background (StThemeNode *node) ClutterActorBox actor_box; ClutterActorBox paint_box; cairo_path_t *interior_path = NULL; + int texture_width, texture_height; border_image = st_theme_node_get_border_image (node); @@ -994,9 +1003,12 @@ st_theme_node_prerender_background (StThemeNode *node) paint_box.y2 += - paint_box.y1; paint_box.y1 += - paint_box.y1; + texture_width = ceilf ((paint_box.x2 - paint_box.x1) * resource_scale); + texture_height = ceilf ((paint_box.y2 - paint_box.y1) * resource_scale); + rowstride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, - paint_box.x2 - paint_box.x1); - data = g_new0 (guchar, (paint_box.y2 - paint_box.y1) * rowstride); + texture_width); + data = g_new0 (guchar, texture_height * rowstride); /* We zero initialize the destination memory, so it's fully transparent * by default. @@ -1005,9 +1017,10 @@ st_theme_node_prerender_background (StThemeNode *node) surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32, - paint_box.x2 - paint_box.x1, - paint_box.y2 - paint_box.y1, + texture_width, + texture_height, rowstride); + cairo_surface_set_device_scale (surface, resource_scale, resource_scale); cr = cairo_create (surface); /* TODO - support non-uniform border colors */ @@ -1046,6 +1059,7 @@ st_theme_node_prerender_background (StThemeNode *node) if (background_image != NULL) { pattern = create_cairo_pattern_of_background_image (node, + resource_scale, &draw_solid_background); if (shadow_spec && pattern != NULL) draw_background_image_shadow = TRUE; @@ -1262,8 +1276,8 @@ st_theme_node_prerender_background (StThemeNode *node) if (interior_path != NULL) cairo_path_destroy (interior_path); - texture = cogl_texture_new_from_data (paint_box.x2 - paint_box.x1, - paint_box.y2 - paint_box.y1, + texture = cogl_texture_new_from_data (texture_width, + texture_height, COGL_TEXTURE_NONE, CLUTTER_CAIRO_FORMAT_ARGB32, COGL_PIXEL_FORMAT_ANY, @@ -1335,7 +1349,8 @@ static void st_theme_node_paint_borders (StThemeNode *node, static void st_theme_node_render_resources (StThemeNode *node, float width, - float height) + float height, + float resource_scale) { StTextureCache *texture_cache; StBorderImage *border_image; @@ -1346,6 +1361,7 @@ st_theme_node_render_resources (StThemeNode *node, StShadow *box_shadow_spec; StShadow *background_image_shadow_spec; const char *background_image; + GFile *image_file; g_return_if_fail (width > 0 && height > 0); @@ -1359,6 +1375,7 @@ st_theme_node_render_resources (StThemeNode *node, node->alloc_width = width; node->alloc_height = height; + node->resource_scale = resource_scale; _st_theme_node_ensure_background (node); _st_theme_node_ensure_geometry (node); @@ -1413,7 +1430,13 @@ st_theme_node_render_resources (StThemeNode *node, filename = st_border_image_get_filename (border_image); - node->border_slices_texture = st_texture_cache_load_file_to_cogl_texture (texture_cache, filename); + image_file = g_file_new_for_path (filename); + node->border_slices_texture = + st_texture_cache_load_gfile_to_cogl_texture (texture_cache, + image_file, + st_theme_context_get_scale_for_stage (), + resource_scale); + g_object_unref (image_file); } if (node->border_slices_texture) @@ -1443,7 +1466,8 @@ st_theme_node_render_resources (StThemeNode *node, || (has_inset_box_shadow && (has_border || node->background_color.alpha > 0)) || (background_image && (has_border || has_border_radius)) || has_large_corners) - node->prerendered_texture = st_theme_node_prerender_background (node); + node->prerendered_texture = st_theme_node_prerender_background (node, + resource_scale); if (node->prerendered_texture) node->prerendered_material = _st_create_texture_pipeline (node->prerendered_texture); @@ -1505,7 +1529,13 @@ st_theme_node_render_resources (StThemeNode *node, background_image_shadow_spec = st_theme_node_get_background_image_shadow (node); if (background_image != NULL && !has_border && !has_border_radius) { - node->background_texture = st_texture_cache_load_file_to_cogl_texture (texture_cache, background_image); + image_file = g_file_new_for_path (background_image); + node->background_texture = + st_texture_cache_load_gfile_to_cogl_texture (texture_cache, + image_file, + st_theme_context_get_scale_for_stage (), + resource_scale); + g_object_unref (image_file); node->background_material = _st_create_texture_pipeline (node->background_texture); if (node->background_repeat) @@ -1860,10 +1890,10 @@ st_theme_node_paint_sliced_border_image (StThemeNode *node, img_width = cogl_texture_get_width (node->border_slices_texture); img_height = cogl_texture_get_height (node->border_slices_texture); - tx1 = border_left / img_width; - tx2 = (img_width - border_right) / img_width; - ty1 = border_top / img_height; - ty2 = (img_height - border_bottom) / img_height; + tx1 = (border_left * node->resource_scale) / img_width; + tx2 = (img_width - (border_right * node->resource_scale)) / img_width; + ty1 = (border_top * node->resource_scale) / img_height; + ty2 = (img_height - (border_bottom * node->resource_scale)) / img_height; ex = node->alloc_width - border_right; if (ex < 0) @@ -2000,6 +2030,7 @@ st_theme_node_paint (StThemeNode *node, CoglFramebuffer *fb, const ClutterActorBox *box, guint8 paint_opacity, + gfloat resource_scale, StBackgroundBlurEffect *background_blur_effect, StBackgroundBumpmapEffect *background_bumpmap_effect) { @@ -2017,8 +2048,13 @@ st_theme_node_paint (StThemeNode *node, allocation.x2 = width; allocation.y2 = height; - if (node->alloc_width != width || node->alloc_height != height) - st_theme_node_render_resources (node, width, height); + if (resource_scale <= 0.0) + resource_scale = 1.0; + + if (node->alloc_width != width || + node->alloc_height != height || + node->resource_scale != resource_scale) + st_theme_node_render_resources (node, width, height, resource_scale); /* Rough notes about the relationship of borders and backgrounds in CSS3; * see http://www.w3.org/TR/css3-background/ for more accurate details. @@ -2169,6 +2205,7 @@ st_theme_node_copy_cached_paint_state (StThemeNode *node, node->alloc_width = other->alloc_width; node->alloc_height = other->alloc_height; + node->resource_scale = other->resource_scale; if (other->background_shadow_material) node->background_shadow_material = cogl_object_ref (other->background_shadow_material); diff --git a/src/st/st-theme-node-private.h b/src/st/st-theme-node-private.h index 3307a66ade..fb50bc9b21 100644 --- a/src/st/st-theme-node-private.h +++ b/src/st/st-theme-node-private.h @@ -107,6 +107,7 @@ struct _StThemeNode { /* Graphics state */ float alloc_width; float alloc_height; + float resource_scale; CoglPipeline *background_shadow_material; CoglPipeline *box_shadow_material; diff --git a/src/st/st-theme-node-transition.c b/src/st/st-theme-node-transition.c index 36c5023326..eec4b1c083 100644 --- a/src/st/st-theme-node-transition.c +++ b/src/st/st-theme-node-transition.c @@ -314,9 +314,9 @@ setup_framebuffers (StThemeNodeTransition *transition, priv->offscreen_box.x2, priv->offscreen_box.y2, 0.0, 1.0); - st_theme_node_paint (priv->old_theme_node, priv->old_offscreen, allocation, 255, NULL, NULL); + st_theme_node_paint (priv->old_theme_node, priv->old_offscreen, allocation, 255, 1.0, NULL, NULL); - st_theme_node_paint (priv->new_theme_node, priv->new_offscreen, allocation, 255, NULL, NULL); + st_theme_node_paint (priv->new_theme_node, priv->new_offscreen, allocation, 255, 1.0, NULL, NULL); return TRUE; } diff --git a/src/st/st-theme-node.h b/src/st/st-theme-node.h index a68b7b5d80..b26943a40f 100644 --- a/src/st/st-theme-node.h +++ b/src/st/st-theme-node.h @@ -260,6 +260,7 @@ void st_theme_node_paint (StThemeNode *node, CoglFramebuffer *framebuffer, const ClutterActorBox *box, guint8 paint_opacity, + gfloat resource_scale, StBackgroundBlurEffect *background_blur_effect, StBackgroundBumpmapEffect *background_bumpmap_effect); diff --git a/src/st/st-widget.c b/src/st/st-widget.c index e9ac50d1e6..56dc950516 100644 --- a/src/st/st-widget.c +++ b/src/st/st-widget.c @@ -407,10 +407,14 @@ st_widget_paint_background (StWidget *widget, ClutterPaintContext *paint_context } CoglFramebuffer *fb = clutter_paint_context_get_framebuffer (paint_context); + gfloat resource_scale = 1.0; + + clutter_actor_get_resource_scale (CLUTTER_ACTOR (widget), &resource_scale); st_theme_node_paint (theme_node, fb, &allocation, opacity, + resource_scale, widget->priv->background_blur_effect, widget->priv->background_bumpmap_effect); }