Merge branch 'icon-theme-api-rework' into 'master'

Icon theme api rework

See merge request GNOME/gtk!1390
This commit is contained in:
Alexander Larsson 2020-02-10 12:45:56 +00:00
commit 1698369d52
38 changed files with 1350 additions and 1014 deletions

View File

@ -9,6 +9,7 @@
#include <gtk/gtk.h>
#include <stdlib.h> /* for exit() */
#include "paintable.h"
static void easter_egg_callback (GtkWidget *button, gpointer data);
@ -130,20 +131,18 @@ insert_text (GtkTextView *view)
GtkTextBuffer *buffer = gtk_text_view_get_buffer (view);
GtkTextIter iter;
GtkTextIter start, end;
GdkTexture *texture;
GtkIconTheme *icon_theme;
GtkIconPaintable *icon;
GdkPaintable *nuclear;
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (widget));
icon = gtk_icon_theme_lookup_icon (icon_theme,
"gtk3-demo",
"face-cool",
NULL,
32, 1,
gtk_widget_get_direction (widget),
0);
texture = gtk_icon_paintable_download_texture (icon, NULL);
g_object_unref (icon);
g_assert (texture);
nuclear = gtk_nuclear_animation_new ();
/* get start of buffer; each insertion will revalidate the
* iterator to point to just after the inserted text.
@ -239,9 +238,11 @@ insert_text (GtkTextView *view)
"heading", NULL);
gtk_text_buffer_insert (buffer, &iter, "The buffer can have images in it: ", -1);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE (icon));
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE (icon));
gtk_text_buffer_insert_paintable (buffer, &iter, nuclear);
gtk_text_buffer_insert (buffer, &iter, " for example.\n\n", -1);
gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Spacing. ", -1,
@ -386,7 +387,8 @@ insert_text (GtkTextView *view)
gtk_text_buffer_end_irreversible_action (buffer);
g_object_unref (texture);
g_object_unref (icon);
g_object_unref (nuclear);
}
static gboolean

View File

@ -49,7 +49,9 @@ struct _IconBrowserWindow
GtkWidget *image4;
GtkWidget *image5;
GtkWidget *image6;
GtkWidget *label6;
GtkWidget *image7;
GtkWidget *image8;
GtkWidget *label8;
GtkWidget *description;
};
@ -113,21 +115,23 @@ item_activated (GtkIconView *icon_view, GtkTreePath *path, IconBrowserWindow *wi
}
gtk_window_set_title (GTK_WINDOW (win->details), name);
set_image (win->image1, name, 16);
set_image (win->image2, name, 24);
set_image (win->image3, name, 32);
set_image (win->image4, name, 48);
set_image (win->image5, name, 64);
set_image (win->image1, name, 8);
set_image (win->image2, name, 16);
set_image (win->image3, name, 18);
set_image (win->image4, name, 24);
set_image (win->image5, name, 32);
set_image (win->image6, name, 48);
set_image (win->image7, name, 64);
if (win->symbolic)
{
gtk_widget_show (win->image6);
gtk_widget_show (win->label6);
set_image (win->image6, name, 64);
gtk_widget_show (win->image8);
gtk_widget_show (win->label8);
set_image (win->image8, name, 64);
}
else
{
gtk_widget_hide (win->image6);
gtk_widget_hide (win->label6);
gtk_widget_hide (win->image8);
gtk_widget_hide (win->label8);
}
if (description && description[0])
{
@ -372,7 +376,7 @@ get_image_paintable (GtkImage *image)
NULL,
size, 1,
gtk_widget_get_direction (GTK_WIDGET (image)),
GTK_ICON_LOOKUP_FORCE_SIZE);
0);
if (icon == NULL)
return NULL;
return GDK_PAINTABLE (icon);
@ -419,7 +423,6 @@ get_file (GValue *value,
GtkIconTheme *icon_theme;
const char *name;
GtkIconPaintable *info;
GFile *file;
name = gtk_image_get_icon_name (GTK_IMAGE (data));
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (data)));
@ -430,9 +433,7 @@ get_file (GValue *value,
32, 1,
gtk_widget_get_direction (GTK_WIDGET (data)),
0);
file = g_file_new_for_path (gtk_icon_paintable_get_filename (info));
g_value_set_object (value, file);
g_object_unref (file);
g_value_take_object (value, gtk_icon_paintable_get_file (info));
g_object_unref (info);
}
@ -484,7 +485,9 @@ icon_browser_window_init (IconBrowserWindow *win)
setup_image_dnd (win->image3);
setup_image_dnd (win->image4);
setup_image_dnd (win->image5);
setup_scalable_image_dnd (win->image6);
setup_image_dnd (win->image6);
setup_image_dnd (win->image7);
setup_scalable_image_dnd (win->image8);
win->contexts = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, context_free);
@ -541,7 +544,9 @@ icon_browser_window_class_init (IconBrowserWindowClass *class)
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image4);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image5);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image6);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, label6);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image7);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image8);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, label8);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, description);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), search_text_changed);

View File

@ -198,7 +198,7 @@
<property name="halign">center</property>
<property name="valign">end</property>
<accessibility>
<relation type="labelled-by" target="label6"/>
<relation type="labelled-by" target="label5"/>
</accessibility>
<layout>
<property name="left-attach">5</property>
@ -206,11 +206,37 @@
</layout>
</object>
</child>
<child>
<object class="GtkImage" id="image7">
<property name="halign">center</property>
<property name="valign">end</property>
<accessibility>
<relation type="labelled-by" target="label5"/>
</accessibility>
<layout>
<property name="left-attach">6</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkImage" id="image8">
<property name="halign">center</property>
<property name="valign">end</property>
<accessibility>
<relation type="labelled-by" target="label6"/>
</accessibility>
<layout>
<property name="left-attach">7</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">16×16</property>
<property name="label">8×8</property>
<style>
<class name="dim-label"/>
</style>
@ -227,7 +253,7 @@
<object class="GtkLabel" id="label2">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">24×24</property>
<property name="label">16×16</property>
<style>
<class name="dim-label"/>
</style>
@ -244,7 +270,7 @@
<object class="GtkLabel" id="label3">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">32×32</property>
<property name="label">18×18</property>
<style>
<class name="dim-label"/>
</style>
@ -261,7 +287,7 @@
<object class="GtkLabel" id="label4">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">48×48</property>
<property name="label">24×24</property>
<style>
<class name="dim-label"/>
</style>
@ -278,7 +304,7 @@
<object class="GtkLabel" id="label5">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">64×64</property>
<property name="label">32×32</property>
<style>
<class name="dim-label"/>
</style>
@ -295,7 +321,7 @@
<object class="GtkLabel" id="label6">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">scalable</property>
<property name="label">48×48</property>
<style>
<class name="dim-label"/>
</style>
@ -308,6 +334,40 @@
</layout>
</object>
</child>
<child>
<object class="GtkLabel" id="label7">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">64×64</property>
<style>
<class name="dim-label"/>
</style>
<accessibility>
<relation type="label-for" target="image7"/>
</accessibility>
<layout>
<property name="left-attach">6</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel" id="label8">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">scalable</property>
<style>
<class name="dim-label"/>
</style>
<accessibility>
<relation type="label-for" target="image8"/>
</accessibility>
<layout>
<property name="left-attach">7</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
</object>
</child>
<child>

View File

@ -4784,9 +4784,10 @@ gtk_icon_theme_choose_icon_finish
gtk_icon_theme_lookup_by_gicon
gtk_icon_theme_list_icons
gtk_icon_theme_get_icon_sizes
gtk_icon_paintable_get_filename
gtk_icon_paintable_new_for_file
gtk_icon_paintable_get_file
gtk_icon_paintable_get_icon_name
gtk_icon_paintable_is_symbolic
gtk_icon_paintable_download_texture
<SUBSECTION Standard>
GtkIconClass
GTK_ICON_THEME

View File

@ -45,6 +45,15 @@ gsk_pango_renderer_set_state (GskPangoRenderer *crenderer,
crenderer->state = state;
}
void
gsk_pango_renderer_set_shape_handler (GskPangoRenderer *crenderer,
GskPangoShapeHandler handler)
{
g_return_if_fail (GSK_IS_PANGO_RENDERER (crenderer));
crenderer->shape_handler = handler;
}
static void
get_color (GskPangoRenderer *crenderer,
PangoRenderPart part,
@ -240,26 +249,49 @@ gsk_pango_renderer_draw_shape (PangoRenderer *renderer,
gpointer shape_renderer_data;
double base_x = (double)x / PANGO_SCALE;
double base_y = (double)y / PANGO_SCALE;
gboolean handled = FALSE;
cr = gtk_snapshot_append_cairo (crenderer->snapshot, &crenderer->bounds);
if (crenderer->shape_handler)
{
double shape_x = base_x;
double shape_y = (double) (y + attr->logical_rect.y) / PANGO_SCALE;
layout = pango_renderer_get_layout (renderer);
if (!layout)
return;
if (shape_x != 0 || shape_y != 0)
{
gtk_snapshot_save (crenderer->snapshot);
gtk_snapshot_translate (crenderer->snapshot, &GRAPHENE_POINT_INIT (shape_x, shape_y));
}
shape_renderer = pango_cairo_context_get_shape_renderer (pango_layout_get_context (layout),
&shape_renderer_data);
handled = crenderer->shape_handler (attr,
crenderer->snapshot,
(double)attr->logical_rect.width / PANGO_SCALE,
(double)attr->logical_rect.height / PANGO_SCALE);
if (shape_x != 0 || shape_y != 0)
gtk_snapshot_restore (crenderer->snapshot);
}
if (!shape_renderer)
return;
if (!handled)
{
cr = gtk_snapshot_append_cairo (crenderer->snapshot, &crenderer->bounds);
set_color (crenderer, PANGO_RENDER_PART_FOREGROUND, cr);
layout = pango_renderer_get_layout (renderer);
if (!layout)
return;
cairo_move_to (cr, base_x, base_y);
shape_renderer = pango_cairo_context_get_shape_renderer (pango_layout_get_context (layout),
&shape_renderer_data);
shape_renderer (cr, attr, FALSE, shape_renderer_data);
if (!shape_renderer)
return;
cairo_destroy (cr);
set_color (crenderer, PANGO_RENDER_PART_FOREGROUND, cr);
cairo_move_to (cr, base_x, base_y);
shape_renderer (cr, attr, FALSE, shape_renderer_data);
cairo_destroy (cr);
}
}
static void
@ -408,6 +440,10 @@ gsk_pango_renderer_acquire (void)
}
renderer = cached_renderer;
/* Reset to standard state */
renderer->state = GSK_PANGO_RENDERER_NORMAL;
renderer->shape_handler = NULL;
}
else
{

View File

@ -41,6 +41,11 @@ typedef enum
GSK_PANGO_RENDERER_CURSOR
} GskPangoRendererState;
typedef gboolean (*GskPangoShapeHandler) (PangoAttrShape *attr,
GdkSnapshot *snapshot,
double width,
double height);
/*
* This is a PangoRenderer implementation that translates all the draw calls to
* gsk render nodes, using the GtkSnapshot helper class. Glyphs are translated
@ -60,6 +65,7 @@ struct _GskPangoRenderer
GdkRGBA *error_color;
GskPangoRendererState state;
GskPangoShapeHandler shape_handler;
/* house-keeping options */
guint is_cached_renderer : 1;
@ -73,6 +79,8 @@ struct _GskPangoRendererClass
GType gsk_pango_renderer_get_type (void) G_GNUC_CONST;
void gsk_pango_renderer_set_state (GskPangoRenderer *crenderer,
GskPangoRendererState state);
void gsk_pango_renderer_set_shape_handler (GskPangoRenderer *crenderer,
GskPangoShapeHandler handler);
GskPangoRenderer *gsk_pango_renderer_acquire (void);
void gsk_pango_renderer_release (GskPangoRenderer *crenderer);

View File

@ -223,6 +223,8 @@
#include "gtkprivate.h"
#include "gtktypebuiltins.h"
#include "gtkicontheme.h"
#include "gtkiconthemeprivate.h"
#include "gdkpixbufutilsprivate.h"
static void gtk_builder_finalize (GObject *object);
static void gtk_builder_set_property (GObject *object,
@ -2159,25 +2161,11 @@ gtk_builder_value_from_string_type (GtkBuilder *builder,
if (pixbuf == NULL)
{
GtkIconTheme *theme;
GtkIconPaintable *icon;
GdkTexture *texture;
g_warning ("Could not load image '%s': %s",
string, tmp_error->message);
g_error_free (tmp_error);
/* fall back to a missing image */
/* FIXME: this should be using the correct display */
theme = gtk_icon_theme_get_for_display (gdk_display_get_default ());
icon = gtk_icon_theme_lookup_icon (theme, "image-missing", NULL, 16, 1,
GTK_TEXT_DIR_NONE,
0);
texture = gtk_icon_paintable_download_texture (icon, NULL);
pixbuf = gdk_pixbuf_get_from_texture (texture);
g_object_unref (icon);
g_object_unref (texture);
pixbuf = _gdk_pixbuf_new_from_resource (IMAGE_MISSING_RESOURCE_PATH, "png", NULL);
}
if (pixbuf)

View File

@ -403,7 +403,6 @@ create_icon_helper (GtkCellRendererPixbuf *cellpixbuf,
icon_helper = gtk_icon_helper_new (gtk_style_context_get_node (gtk_widget_get_style_context (widget)),
widget);
_gtk_icon_helper_set_use_fallback (icon_helper, TRUE);
_gtk_icon_helper_set_force_scale_pixbuf (icon_helper, TRUE);
_gtk_icon_helper_set_definition (icon_helper, priv->image_def);
return icon_helper;

View File

@ -68,13 +68,6 @@ gtk_css_image_icon_theme_snapshot (GtkCssImage *image,
icon_theme->scale,
GTK_TEXT_DIR_NONE,
0);
if (icon == NULL)
icon = gtk_icon_theme_lookup_icon (icon_theme->icon_theme,
"image-missing",
NULL,
size, icon_theme->scale,
GTK_TEXT_DIR_NONE,
0);
g_assert (icon != NULL);

View File

@ -198,7 +198,8 @@ get_directory_index (GtkIconCache *cache,
GHashTable *
gtk_icon_cache_list_icons_in_directory (GtkIconCache *cache,
const gchar *directory)
const gchar *directory,
GtkStringSet *set)
{
gint directory_index;
guint32 hash_offset, n_buckets;
@ -239,7 +240,7 @@ gtk_icon_cache_list_icons_in_directory (GtkIconCache *cache,
{
guint32 name_offset = GET_UINT32 (cache->buffer, chain_offset + 4);
const char *name = cache->buffer + name_offset;
char *converted_name;
const char *interned_name;
guint32 hash_flags = 0;
/* Icons named foo.symbolic.png are stored in the cache as "foo.symbolic" with ICON_CACHE_FLAG_PNG,
@ -247,18 +248,20 @@ gtk_icon_cache_list_icons_in_directory (GtkIconCache *cache,
* Otherwise we use the same enum values and names as on disk. */
if (g_str_has_suffix (name, ".symbolic") && (flags & ICON_CACHE_FLAG_PNG_SUFFIX) != 0)
{
char *converted_name = g_strndup (name, strlen (name) - 9);
interned_name = gtk_string_set_add (set, converted_name);
g_free (converted_name);
flags |= ICON_CACHE_FLAG_SYMBOLIC_PNG_SUFFIX;
flags &= ~ICON_CACHE_FLAG_PNG_SUFFIX;
converted_name = g_strndup (name, strlen(name) - 9);
}
else
converted_name = g_strdup (name);
interned_name = gtk_string_set_add (set, name);
if (!icons)
icons = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
icons = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
hash_flags = GPOINTER_TO_INT (g_hash_table_lookup (icons, converted_name));
g_hash_table_replace (icons, converted_name, GUINT_TO_POINTER (hash_flags|flags));
hash_flags = GPOINTER_TO_INT (g_hash_table_lookup (icons, interned_name));
g_hash_table_replace (icons, (char *)interned_name, GUINT_TO_POINTER (hash_flags|flags));
}
chain_offset = GET_UINT32 (cache->buffer, chain_offset);

View File

@ -18,6 +18,7 @@
#define __GTK_ICON_CACHE_PRIVATE_H__
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gtk/gtkiconthemeprivate.h>
G_BEGIN_DECLS
@ -40,7 +41,8 @@ typedef struct _GtkIconCache GtkIconCache;
GtkIconCache *gtk_icon_cache_new (const gchar *data);
GtkIconCache *gtk_icon_cache_new_for_path (const gchar *path);
GHashTable *gtk_icon_cache_list_icons_in_directory (GtkIconCache *cache,
const gchar *directory);
const gchar *directory,
GtkStringSet *set);
GtkIconCache *gtk_icon_cache_ref (GtkIconCache *cache);
void gtk_icon_cache_unref (GtkIconCache *cache);

View File

@ -46,7 +46,6 @@ struct _GtkIconHelper
gint pixel_size;
guint use_fallback : 1;
guint force_scale_pixbuf : 1;
guint texture_is_symbolic : 1;
GtkWidget *owner;
@ -63,9 +62,6 @@ get_icon_lookup_flags (GtkIconHelper *self,
flags = 0;
if (self->pixel_size != -1 || self->force_scale_pixbuf)
flags |= GTK_ICON_LOOKUP_FORCE_SIZE;
icon_style = _gtk_css_icon_style_value_get (style->icon->icon_style);
switch (icon_style)
@ -91,6 +87,7 @@ ensure_paintable_for_gicon (GtkIconHelper *self,
GtkCssStyle *style,
GtkTextDirection dir,
gint scale,
gboolean preload,
GIcon *gicon,
gboolean *symbolic)
{
@ -101,6 +98,8 @@ ensure_paintable_for_gicon (GtkIconHelper *self,
icon_theme = gtk_css_icon_theme_value_get_icon_theme (style->core->icon_theme);
flags = get_icon_lookup_flags (self, style);
if (preload)
flags |= GTK_ICON_LOOKUP_PRELOAD;
width = height = gtk_icon_helper_get_size (self);
@ -109,13 +108,6 @@ ensure_paintable_for_gicon (GtkIconHelper *self,
MIN (width, height),
dir,
scale, flags);
if (icon == NULL)
icon = gtk_icon_theme_lookup_icon (icon_theme,
"image-missing",
NULL,
width, scale,
dir,
flags);
*symbolic = gtk_icon_paintable_is_symbolic (icon);
return GDK_PAINTABLE (icon);
@ -123,6 +115,7 @@ ensure_paintable_for_gicon (GtkIconHelper *self,
static GdkPaintable *
gtk_icon_helper_load_paintable (GtkIconHelper *self,
gboolean preload,
gboolean *out_symbolic)
{
GdkPaintable *paintable;
@ -145,16 +138,18 @@ gtk_icon_helper_load_paintable (GtkIconHelper *self,
gtk_css_node_get_style (self->node),
gtk_widget_get_scale_factor (self->owner),
gtk_widget_get_direction (self->owner),
preload,
gicon,
&symbolic);
g_object_unref (gicon);
break;
case GTK_IMAGE_GICON:
paintable = ensure_paintable_for_gicon (self,
paintable = ensure_paintable_for_gicon (self,
gtk_css_node_get_style (self->node),
gtk_widget_get_scale_factor (self->owner),
gtk_widget_get_direction (self->owner),
preload,
gtk_image_definition_get_gicon (self->def),
&symbolic);
break;
@ -172,14 +167,14 @@ gtk_icon_helper_load_paintable (GtkIconHelper *self,
}
static void
gtk_icon_helper_ensure_paintable (GtkIconHelper *self)
gtk_icon_helper_ensure_paintable (GtkIconHelper *self, gboolean preload)
{
gboolean symbolic;
if (self->paintable)
return;
self->paintable = gtk_icon_helper_load_paintable (self, &symbolic);
self->paintable = gtk_icon_helper_load_paintable (self, preload, &symbolic);
self->texture_is_symbolic = symbolic;
}
@ -194,7 +189,7 @@ gtk_icon_helper_paintable_snapshot (GdkPaintable *paintable,
style = gtk_css_node_get_style (self->node);
gtk_icon_helper_ensure_paintable (self);
gtk_icon_helper_ensure_paintable (self, FALSE);
if (self->paintable == NULL)
return;
@ -223,8 +218,7 @@ gtk_icon_helper_paintable_snapshot (GdkPaintable *paintable,
gtk_css_style_snapshot_icon_paintable (style,
snapshot,
self->paintable,
w, h,
self->texture_is_symbolic);
w, h);
gtk_snapshot_restore (snapshot);
}
else
@ -232,8 +226,7 @@ gtk_icon_helper_paintable_snapshot (GdkPaintable *paintable,
gtk_css_style_snapshot_icon_paintable (style,
snapshot,
self->paintable,
w, h,
self->texture_is_symbolic);
w, h);
}
@ -280,8 +273,7 @@ gtk_icon_helper_paintable_snapshot (GdkPaintable *paintable,
gtk_css_style_snapshot_icon_paintable (style,
snapshot,
self->paintable,
w, h,
self->texture_is_symbolic);
w, h);
gtk_snapshot_restore (snapshot);
}
else
@ -289,8 +281,7 @@ gtk_icon_helper_paintable_snapshot (GdkPaintable *paintable,
gtk_css_style_snapshot_icon_paintable (style,
snapshot,
self->paintable,
w, h,
self->texture_is_symbolic);
w, h);
}
}
break;
@ -302,7 +293,7 @@ gtk_icon_helper_paintable_get_current_image (GdkPaintable *paintable)
{
GtkIconHelper *self = GTK_ICON_HELPER (paintable);
gtk_icon_helper_ensure_paintable (self);
gtk_icon_helper_ensure_paintable (self, FALSE);
if (self->paintable == NULL)
return NULL;
@ -378,6 +369,9 @@ gtk_icon_helper_invalidate_for_change (GtkIconHelper *self,
{
gtk_widget_queue_draw (self->owner);
}
/* The css size is valid now, preload */
gtk_icon_helper_ensure_paintable (self, TRUE);
}
static void
@ -571,23 +565,6 @@ _gtk_icon_helper_get_is_empty (GtkIconHelper *self)
return gtk_image_definition_get_storage_type (self->def) == GTK_IMAGE_EMPTY;
}
gboolean
_gtk_icon_helper_get_force_scale_pixbuf (GtkIconHelper *self)
{
return self->force_scale_pixbuf;
}
void
_gtk_icon_helper_set_force_scale_pixbuf (GtkIconHelper *self,
gboolean force_scale)
{
if (self->force_scale_pixbuf != force_scale)
{
self->force_scale_pixbuf = force_scale;
gtk_icon_helper_invalidate (self);
}
}
void
gtk_icon_size_set_style_classes (GtkCssNode *cssnode,
GtkIconSize icon_size)

View File

@ -66,10 +66,6 @@ const gchar *_gtk_icon_helper_get_icon_name (GtkIconHelper *self);
int gtk_icon_helper_get_size (GtkIconHelper *self);
gboolean _gtk_icon_helper_get_force_scale_pixbuf (GtkIconHelper *self);
void _gtk_icon_helper_set_force_scale_pixbuf (GtkIconHelper *self,
gboolean force_scale);
void gtk_icon_helper_invalidate (GtkIconHelper *self);
void gtk_icon_helper_invalidate_for_change (GtkIconHelper *self,
GtkCssStyleChange *change);

File diff suppressed because it is too large Load Diff

View File

@ -40,20 +40,20 @@ typedef struct _GtkIconTheme GtkIconTheme;
/**
* GtkIconLookupFlags:
* @GTK_ICON_LOOKUP_FORCE_SIZE: Always get the icon scaled to the
* requested size
* @GTK_ICON_LOOKUP_FORCE_REGULAR: Try to always load regular icons, even
* when symbolic icon names are given
* @GTK_ICON_LOOKUP_FORCE_SYMBOLIC: Try to always load symbolic icons, even
* when regular icon names are given
* @GTK_ICON_LOOKUP_PREALOAD: Starts loading the texture in the background
* so it is ready when later needed.
*
* Used to specify options for gtk_icon_theme_lookup_icon()
*/
typedef enum
{
GTK_ICON_LOOKUP_FORCE_SIZE = 1 << 0,
GTK_ICON_LOOKUP_FORCE_REGULAR = 1 << 1,
GTK_ICON_LOOKUP_FORCE_SYMBOLIC = 1 << 2
GTK_ICON_LOOKUP_FORCE_REGULAR = 1 << 0,
GTK_ICON_LOOKUP_FORCE_SYMBOLIC = 1 << 1,
GTK_ICON_LOOKUP_PRELOAD = 1 << 2,
} GtkIconLookupFlags;
/**
@ -134,18 +134,21 @@ GtkIconPaintable *gtk_icon_theme_lookup_by_gicon (GtkIconTheme
GtkTextDirection direction,
GtkIconLookupFlags flags);
GDK_AVAILABLE_IN_ALL
GtkIconPaintable *gtk_icon_paintable_new_for_file (GFile *file,
gint size,
gint scale);
GDK_AVAILABLE_IN_ALL
GList * gtk_icon_theme_list_icons (GtkIconTheme *self);
GDK_AVAILABLE_IN_ALL
GType gtk_icon_paintable_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
const gchar * gtk_icon_paintable_get_filename (GtkIconPaintable *self);
GFile * gtk_icon_paintable_get_file (GtkIconPaintable *self);
GDK_AVAILABLE_IN_ALL
gboolean gtk_icon_paintable_is_symbolic (GtkIconPaintable *self);
const gchar * gtk_icon_paintable_get_icon_name (GtkIconPaintable *self);
GDK_AVAILABLE_IN_ALL
GdkTexture * gtk_icon_paintable_download_texture (GtkIconPaintable *self,
GError **error);
gboolean gtk_icon_paintable_is_symbolic (GtkIconPaintable *self);
G_END_DECLS

View File

@ -21,6 +21,12 @@
#include <gtk/gtkicontheme.h>
#include <gtk/gtkcssstyleprivate.h>
typedef struct _GtkStringSet GtkStringSet;
const char *gtk_string_set_add (GtkStringSet *set,
const char *string);
#define IMAGE_MISSING_RESOURCE_PATH "/org/gtk/libgtk/icons/16x16/status/image-missing.png"
void gtk_icon_theme_lookup_symbolic_colors (GtkCssStyle *style,
GdkRGBA *color_out,
GdkRGBA *success_out,

View File

@ -55,7 +55,8 @@
#include "gtkgestureclick.h"
#include "gtkmodelbuttonprivate.h"
#include "gtkpopover.h"
#include "gtksnapshot.h"
#include "gdktextureprivate.h"
#include <glib/gprintf.h>
/**
@ -1137,6 +1138,36 @@ diff_sorted_arrays (GArray *array1,
}
}
static GdkTexture *
render_paintable_to_texture (GdkPaintable *paintable)
{
GtkSnapshot *snapshot;
GskRenderNode *node;
int width, height;
cairo_surface_t *surface;
cairo_t *cr;
GdkTexture *texture;
width = gdk_paintable_get_intrinsic_width (paintable);
height = gdk_paintable_get_intrinsic_height (paintable);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, width, height);
node = gtk_snapshot_free_to_node (snapshot);
cr = cairo_create (surface);
gsk_render_node_draw (node, cr);
cairo_destroy (cr);
gsk_render_node_unref (node);
texture = gdk_texture_new_for_surface (surface);
cairo_surface_destroy (surface);
return texture;
}
static void
add_pid_to_process_list_store (GtkMountOperation *mount_operation,
@ -1180,7 +1211,7 @@ add_pid_to_process_list_store (GtkMountOperation *mount_operation,
24, 1,
gtk_widget_get_direction (GTK_WIDGET (mount_operation->priv->dialog)),
0);
texture = gtk_icon_paintable_download_texture (icon, NULL);
texture = render_paintable_to_texture (GDK_PAINTABLE (icon));
g_object_unref (icon);
}

View File

@ -519,8 +519,7 @@ gtk_render_icon (GtkStyleContext *context,
snapshot,
GDK_PAINTABLE (texture),
gdk_texture_get_width (texture),
gdk_texture_get_height (texture),
FALSE);
gdk_texture_get_height (texture));
node = gtk_snapshot_free_to_node (snapshot);
if (node == NULL)
return;

View File

@ -93,11 +93,12 @@ gtk_css_style_snapshot_icon_paintable (GtkCssStyle *style,
GtkSnapshot *snapshot,
GdkPaintable *paintable,
double width,
double height,
gboolean recolor)
double height)
{
GskTransform *transform;
gboolean has_shadow;
gboolean is_icon_paintable;
GdkRGBA fg, sc, wc, ec;
g_return_if_fail (GTK_IS_CSS_STYLE (style));
g_return_if_fail (snapshot != NULL);
@ -111,31 +112,21 @@ gtk_css_style_snapshot_icon_paintable (GtkCssStyle *style,
has_shadow = gtk_css_shadow_value_push_snapshot (style->icon->icon_shadow, snapshot);
if (recolor)
is_icon_paintable = GTK_IS_ICON_PAINTABLE (paintable);
if (is_icon_paintable)
{
graphene_matrix_t color_matrix;
graphene_vec4_t color_offset;
GdkRGBA fg, sc, wc, ec;
gtk_icon_theme_lookup_symbolic_colors (style, &fg, &sc, &wc, &ec);
if (fg.alpha == 0.0f)
goto transparent;
graphene_matrix_init_from_float (&color_matrix, (float[16]) {
sc.red - fg.red, sc.green - fg.green, sc.blue - fg.blue, 0,
wc.red - fg.red, wc.green - fg.green, wc.blue - fg.blue, 0,
ec.red - fg.red, ec.green - fg.green, ec.blue - fg.blue, 0,
0, 0, 0, fg.alpha
});
graphene_vec4_init (&color_offset, fg.red, fg.green, fg.blue, 0);
gtk_snapshot_push_color_matrix (snapshot, &color_matrix, &color_offset);
}
if (transform == NULL)
{
gdk_paintable_snapshot (paintable, snapshot, width, height);
if (is_icon_paintable)
gtk_icon_paintable_snapshot_with_colors (GTK_ICON_PAINTABLE (paintable), snapshot, width, height, &fg, &sc, &wc, &ec);
else
gdk_paintable_snapshot (paintable, snapshot, width, height);
}
else
{
@ -146,14 +137,14 @@ gtk_css_style_snapshot_icon_paintable (GtkCssStyle *style,
gtk_snapshot_transform (snapshot, transform);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- width / 2.0, - height / 2.0));
gdk_paintable_snapshot (paintable, snapshot, width, height);
if (is_icon_paintable)
gtk_icon_paintable_snapshot_with_colors (GTK_ICON_PAINTABLE (paintable), snapshot, width, height, &fg, &sc, &wc, &ec);
else
gdk_paintable_snapshot (paintable, snapshot, width, height);
gtk_snapshot_restore (snapshot);
}
if (recolor)
gtk_snapshot_pop (snapshot);
transparent:
if (has_shadow)
gtk_snapshot_pop (snapshot);

View File

@ -38,8 +38,7 @@ void gtk_css_style_snapshot_icon_paintable (GtkCssStyle *style,
GtkSnapshot *snapshot,
GdkPaintable *paintable,
double width,
double height,
gboolean recolor);
double height);
void gtk_css_style_render_icon_get_extents (GtkCssStyle *style,
GdkRectangle *extents,

View File

@ -1259,9 +1259,8 @@ _gtk_text_btree_insert (GtkTextIter *iter,
}
static void
insert_texture_or_widget_segment (GtkTextIter *iter,
GtkTextLineSegment *seg)
insert_paintable_or_widget_segment (GtkTextIter *iter,
GtkTextLineSegment *seg)
{
GtkTextIter start;
GtkTextLineSegment *prevPtr;
@ -1297,19 +1296,21 @@ insert_texture_or_widget_segment (GtkTextIter *iter,
*iter = start;
gtk_text_iter_forward_char (iter); /* skip forward past the segment */
DV (g_print ("invalidating due to inserting texture/widget (%s)\n", G_STRLOC));
DV (g_print ("invalidating due to inserting paintable/widget (%s)\n", G_STRLOC));
_gtk_text_btree_invalidate_region (tree, &start, iter, FALSE);
}
void
_gtk_text_btree_insert_texture (GtkTextIter *iter,
GdkTexture *texture)
_gtk_text_btree_insert_paintable (GtkTextIter *iter,
GdkPaintable *paintable)
{
GtkTextLineSegment *seg;
seg = _gtk_texture_segment_new (texture);
seg = _gtk_paintable_segment_new (paintable);
seg->body.paintable.tree = _gtk_text_iter_get_btree (iter);
seg->body.paintable.line = _gtk_text_iter_get_text_line (iter);
insert_texture_or_widget_segment (iter, seg);
insert_paintable_or_widget_segment (iter, seg);
}
void
@ -1330,7 +1331,7 @@ _gtk_text_btree_insert_child_anchor (GtkTextIter *iter,
tree = seg->body.child.tree = _gtk_text_iter_get_btree (iter);
seg->body.child.line = _gtk_text_iter_get_text_line (iter);
insert_texture_or_widget_segment (iter, seg);
insert_paintable_or_widget_segment (iter, seg);
if (tree->child_anchor_table == NULL)
tree->child_anchor_table = g_hash_table_new (NULL, NULL);
@ -2380,7 +2381,7 @@ copy_segment (GString *string,
/* printf (" :%s\n", string->str); */
}
else if (seg->type == &gtk_text_texture_type ||
else if (seg->type == &gtk_text_paintable_type ||
seg->type == &gtk_text_child_type)
{
gboolean copy = TRUE;

View File

@ -63,13 +63,13 @@ gboolean _gtk_text_btree_is_end (GtkTextBTree *tree,
/* Indexable segment mutation */
void _gtk_text_btree_delete (GtkTextIter *start,
GtkTextIter *end);
void _gtk_text_btree_insert (GtkTextIter *iter,
const gchar *text,
gint len);
void _gtk_text_btree_insert_texture (GtkTextIter *iter,
GdkTexture *texture);
void _gtk_text_btree_delete (GtkTextIter *start,
GtkTextIter *end);
void _gtk_text_btree_insert (GtkTextIter *iter,
const gchar *text,
gint len);
void _gtk_text_btree_insert_paintable (GtkTextIter *iter,
GdkPaintable *texture);
void _gtk_text_btree_insert_child_anchor (GtkTextIter *iter,
GtkTextChildAnchor *anchor);
@ -161,6 +161,9 @@ gboolean _gtk_text_btree_get_iter_at_mark_name (GtkTextBTree *tree,
void _gtk_text_btree_get_iter_at_mark (GtkTextBTree *tree,
GtkTextIter *iter,
GtkTextMark *mark);
void _gtk_text_btree_get_iter_at_paintable (GtkTextBTree *tree,
GtkTextIter *iter,
GtkTextLineSegment *seg);
void _gtk_text_btree_get_end_iter (GtkTextBTree *tree,
GtkTextIter *iter);
void _gtk_text_btree_get_iter_at_line (GtkTextBTree *tree,

View File

@ -87,7 +87,7 @@ struct _ClipboardRequest
enum {
INSERT_TEXT,
INSERT_TEXTURE,
INSERT_PAINTABLE,
INSERT_CHILD_ANCHOR,
DELETE_RANGE,
CHANGED,
@ -128,9 +128,9 @@ static void gtk_text_buffer_real_insert_text (GtkTextBuffer *buffe
GtkTextIter *iter,
const gchar *text,
gint len);
static void gtk_text_buffer_real_insert_texture (GtkTextBuffer *buffer,
static void gtk_text_buffer_real_insert_paintable (GtkTextBuffer *buffer,
GtkTextIter *iter,
GdkTexture *texture);
GdkPaintable *paintable);
static void gtk_text_buffer_real_insert_anchor (GtkTextBuffer *buffer,
GtkTextIter *iter,
GtkTextChildAnchor *anchor);
@ -434,7 +434,7 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass)
object_class->get_property = gtk_text_buffer_get_property;
klass->insert_text = gtk_text_buffer_real_insert_text;
klass->insert_texture = gtk_text_buffer_real_insert_texture;
klass->insert_paintable = gtk_text_buffer_real_insert_paintable;
klass->insert_child_anchor = gtk_text_buffer_real_insert_anchor;
klass->delete_range = gtk_text_buffer_real_delete_range;
klass->apply_tag = gtk_text_buffer_real_apply_tag;
@ -596,33 +596,33 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass)
_gtk_marshal_VOID__BOXED_STRING_INTv);
/**
* GtkTextBuffer::insert-texture:
* GtkTextBuffer::insert-paintable:
* @textbuffer: the object which received the signal
* @location: position to insert @texture in @textbuffer
* @texture: the #GdkTexture to be inserted
* @location: position to insert @paintable in @textbuffer
* @paintable: the #GdkPaintable to be inserted
*
* The ::insert-texture signal is emitted to insert a #GdkTexture
* The ::insert-paintable signal is emitted to insert a #GdkPaintable
* in a #GtkTextBuffer. Insertion actually occurs in the default handler.
*
* Note that if your handler runs before the default handler it must not
* invalidate the @location iter (or has to revalidate it).
* The default signal handler revalidates it to be placed after the
* inserted @texture.
* inserted @paintable.
*
* See also: gtk_text_buffer_insert_texture().
* See also: gtk_text_buffer_insert_paintable().
*/
signals[INSERT_TEXTURE] =
g_signal_new (I_("insert-texture"),
signals[INSERT_PAINTABLE] =
g_signal_new (I_("insert-paintable"),
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkTextBufferClass, insert_texture),
G_STRUCT_OFFSET (GtkTextBufferClass, insert_paintable),
NULL, NULL,
_gtk_marshal_VOID__BOXED_OBJECT,
G_TYPE_NONE,
2,
GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE,
GDK_TYPE_TEXTURE);
g_signal_set_va_marshaller (signals[INSERT_TEXTURE],
GDK_TYPE_PAINTABLE);
g_signal_set_va_marshaller (signals[INSERT_PAINTABLE],
G_TYPE_FROM_CLASS (klass),
_gtk_marshal_VOID__BOXED_OBJECTv);
@ -1519,19 +1519,19 @@ insert_range_untagged (GtkTextBuffer *buffer,
}
else if (gtk_text_iter_get_char (&range_end) == GTK_TEXT_UNKNOWN_CHAR)
{
GdkTexture *texture;
GdkPaintable *paintable;
GtkTextChildAnchor *anchor;
texture = gtk_text_iter_get_texture (&range_end);
paintable = gtk_text_iter_get_paintable (&range_end);
anchor = gtk_text_iter_get_child_anchor (&range_end);
if (texture)
if (paintable)
{
r = save_range (&range_start,
&range_end,
&end);
gtk_text_buffer_insert_texture (buffer, iter, texture);
gtk_text_buffer_insert_paintable (buffer, iter, paintable);
restore_range (r);
r = NULL;
@ -1733,7 +1733,7 @@ gtk_text_buffer_real_insert_range (GtkTextBuffer *buffer,
* @start: a position in a #GtkTextBuffer
* @end: another position in the same buffer as @start
*
* Copies text, tags, and texture between @start and @end (the order
* Copies text, tags, and paintables between @start and @end (the order
* of @start and @end doesnt matter) and inserts the copy at @iter.
* Used instead of simply getting/inserting text because it preserves
* images and tags. If @start and @end are in a different buffer from
@ -2215,7 +2215,7 @@ gtk_text_buffer_get_text (GtkTextBuffer *buffer,
* the returned string do correspond to byte
* and character indexes into the buffer. Contrast with
* gtk_text_buffer_get_text(). Note that 0xFFFC can occur in normal
* text as well, so it is not a reliable indicator that a texture or
* text as well, so it is not a reliable indicator that a paintable or
* widget is in the buffer.
*
* Returns: (transfer full): an allocated UTF-8 string
@ -2243,41 +2243,41 @@ gtk_text_buffer_get_slice (GtkTextBuffer *buffer,
*/
static void
gtk_text_buffer_real_insert_texture (GtkTextBuffer *buffer,
GtkTextIter *iter,
GdkTexture *texture)
gtk_text_buffer_real_insert_paintable (GtkTextBuffer *buffer,
GtkTextIter *iter,
GdkPaintable *paintable)
{
_gtk_text_btree_insert_texture (iter, texture);
_gtk_text_btree_insert_paintable (iter, paintable);
g_signal_emit (buffer, signals[CHANGED], 0);
}
/**
* gtk_text_buffer_insert_texture:
* gtk_text_buffer_insert_paintable:
* @buffer: a #GtkTextBuffer
* @iter: location to insert the texture
* @texture: a #GdkTexture
* @iter: location to insert the paintable
* @paintable: a #GdkPaintable
*
* Inserts an image into the text buffer at @iter. The image will be
* counted as one character in character counts, and when obtaining
* the buffer contents as a string, will be represented by the Unicode
* object replacement character 0xFFFC. Note that the slice
* variants for obtaining portions of the buffer as a string include
* this character for texture, but the text variants do
* this character for paintable, but the text variants do
* not. e.g. see gtk_text_buffer_get_slice() and
* gtk_text_buffer_get_text().
**/
void
gtk_text_buffer_insert_texture (GtkTextBuffer *buffer,
GtkTextIter *iter,
GdkTexture *texture)
gtk_text_buffer_insert_paintable (GtkTextBuffer *buffer,
GtkTextIter *iter,
GdkPaintable *paintable)
{
g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
g_return_if_fail (iter != NULL);
g_return_if_fail (GDK_IS_TEXTURE (texture));
g_return_if_fail (GDK_IS_PAINTABLE (paintable));
g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer);
g_signal_emit (buffer, signals[INSERT_TEXTURE], 0, iter, texture);
g_signal_emit (buffer, signals[INSERT_PAINTABLE], 0, iter, paintable);
}
/*

View File

@ -85,7 +85,7 @@ struct _GtkTextBuffer
* GtkTextBufferClass:
* @parent_class: The object class structure needs to be the first.
* @insert_text: The class handler for the #GtkTextBuffer::insert-text signal.
* @insert_texture: The class handler for the #GtkTextBuffer::insert-texture signal.
* @insert_paintable: The class handler for the #GtkTextBuffer::insert-paintable signal.
* @insert_child_anchor: The class handler for the #GtkTextBuffer::insert-child-anchor signal.
* @delete_range: The class handler for the #GtkTextBuffer::delete-range signal.
* @changed: The class handler for the #GtkTextBuffer::changed signal.
@ -107,9 +107,9 @@ struct _GtkTextBufferClass
const gchar *new_text,
gint new_text_length);
void (* insert_texture) (GtkTextBuffer *buffer,
void (* insert_paintable) (GtkTextBuffer *buffer,
GtkTextIter *iter,
GdkTexture *texture);
GdkPaintable *paintable);
void (* insert_child_anchor) (GtkTextBuffer *buffer,
GtkTextIter *iter,
@ -267,11 +267,11 @@ gchar *gtk_text_buffer_get_slice (GtkTextBuffer *buffer,
const GtkTextIter *end,
gboolean include_hidden_chars);
/* Insert a texture */
/* Insert a paintable */
GDK_AVAILABLE_IN_ALL
void gtk_text_buffer_insert_texture (GtkTextBuffer *buffer,
void gtk_text_buffer_insert_paintable (GtkTextBuffer *buffer,
GtkTextIter *iter,
GdkTexture *texture);
GdkPaintable *texture);
/* Insert a child anchor */
GDK_AVAILABLE_IN_ALL

View File

@ -72,67 +72,109 @@
} \
} G_STMT_END
#define TEXTURE_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
+ sizeof (GtkTextTexture)))
#define PAINTABLE_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
+ sizeof (GtkTextPaintable)))
#define WIDGET_SEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
+ sizeof (GtkTextChildBody)))
static GtkTextLineSegment *
texture_segment_cleanup_func (GtkTextLineSegment *seg,
GtkTextLine *line)
static void
paintable_invalidate_size (GdkPaintable *paintable,
GtkTextLineSegment *seg)
{
/* nothing */
if (seg->body.paintable.tree)
{
GtkTextIter start, end;
_gtk_text_btree_get_iter_at_paintable (seg->body.paintable.tree, &start, seg);
end = start;
gtk_text_iter_forward_char (&end);
_gtk_text_btree_invalidate_region (seg->body.paintable.tree, &start, &end, FALSE);
}
}
static void
paintable_invalidate_contents (GdkPaintable *paintable,
GtkTextLineSegment *seg)
{
/* These do the same anyway */
paintable_invalidate_size (paintable, seg);
}
static GtkTextLineSegment *
paintable_segment_cleanup_func (GtkTextLineSegment *seg,
GtkTextLine *line)
{
seg->body.paintable.line = line;
return seg;
}
static int
texture_segment_delete_func (GtkTextLineSegment *seg,
GtkTextLine *line,
gboolean tree_gone)
paintable_segment_delete_func (GtkTextLineSegment *seg,
GtkTextLine *line,
gboolean tree_gone)
{
if (seg->body.texture.texture)
g_object_unref (seg->body.texture.texture);
GdkPaintable *paintable;
guint flags;
g_slice_free1 (TEXTURE_SEG_SIZE, seg);
seg->body.paintable.tree = NULL;
seg->body.paintable.line = NULL;
paintable = seg->body.paintable.paintable;
if (paintable)
{
flags = gdk_paintable_get_flags (paintable);
if ((flags & GDK_PAINTABLE_STATIC_CONTENTS) == 0)
g_signal_handlers_disconnect_by_func (paintable, G_CALLBACK (paintable_invalidate_contents), seg);
if ((flags & GDK_PAINTABLE_STATIC_SIZE) == 0)
g_signal_handlers_disconnect_by_func (paintable, G_CALLBACK (paintable_invalidate_size), seg);
g_object_unref (paintable);
}
g_slice_free1 (PAINTABLE_SEG_SIZE, seg);
return 0;
}
static void
texture_segment_check_func (GtkTextLineSegment *seg,
GtkTextLine *line)
paintable_segment_check_func (GtkTextLineSegment *seg,
GtkTextLine *line)
{
if (seg->next == NULL)
g_error ("texture segment is the last segment in a line");
g_error ("paintable segment is the last segment in a line");
if (seg->byte_count != GTK_TEXT_UNKNOWN_CHAR_UTF8_LEN)
g_error ("texture segment has byte count of %d", seg->byte_count);
g_error ("paintable segment has byte count of %d", seg->byte_count);
if (seg->char_count != 1)
g_error ("texture segment has char count of %d", seg->char_count);
g_error ("paintable segment has char count of %d", seg->char_count);
}
const GtkTextLineSegmentClass gtk_text_texture_type = {
"texture", /* name */
FALSE, /* leftGravity */
NULL, /* splitFunc */
texture_segment_delete_func, /* deleteFunc */
texture_segment_cleanup_func, /* cleanupFunc */
NULL, /* lineChangeFunc */
texture_segment_check_func /* checkFunc */
const GtkTextLineSegmentClass gtk_text_paintable_type = {
"paintable", /* name */
FALSE, /* leftGravity */
NULL, /* splitFunc */
paintable_segment_delete_func, /* deleteFunc */
paintable_segment_cleanup_func, /* cleanupFunc */
NULL, /* lineChangeFunc */
paintable_segment_check_func /* checkFunc */
};
GtkTextLineSegment *
_gtk_texture_segment_new (GdkTexture *texture)
_gtk_paintable_segment_new (GdkPaintable *paintable)
{
GtkTextLineSegment *seg;
guint flags;
seg = g_slice_alloc (TEXTURE_SEG_SIZE);
seg = g_slice_alloc (PAINTABLE_SEG_SIZE);
seg->type = &gtk_text_texture_type;
seg->type = &gtk_text_paintable_type;
seg->next = NULL;
@ -142,9 +184,24 @@ _gtk_texture_segment_new (GdkTexture *texture)
seg->byte_count = GTK_TEXT_UNKNOWN_CHAR_UTF8_LEN;
seg->char_count = 1;
seg->body.texture.texture = texture;
seg->body.paintable.paintable = paintable;
seg->body.paintable.tree = NULL;
seg->body.paintable.line = NULL;
g_object_ref (texture);
flags = gdk_paintable_get_flags (paintable);
if ((flags & GDK_PAINTABLE_STATIC_CONTENTS) == 0)
g_signal_connect (paintable,
"invalidate-contents",
G_CALLBACK (paintable_invalidate_contents),
seg);
if ((flags & GDK_PAINTABLE_STATIC_SIZE) == 0)
g_signal_connect (paintable,
"invalidate-size",
G_CALLBACK (paintable_invalidate_size),
seg);
g_object_ref (paintable);
return seg;
}

View File

@ -54,14 +54,16 @@
G_BEGIN_DECLS
typedef struct _GtkTextTexture GtkTextTexture;
typedef struct _GtkTextPaintable GtkTextPaintable;
struct _GtkTextTexture
struct _GtkTextPaintable
{
GdkTexture *texture;
GdkPaintable *paintable;
GtkTextBTree *tree;
GtkTextLine *line;
};
GtkTextLineSegment *_gtk_texture_segment_new (GdkTexture *texture);
GtkTextLineSegment *_gtk_paintable_segment_new (GdkPaintable *paintable);
typedef struct _GtkTextChildBody GtkTextChildBody;

View File

@ -173,7 +173,7 @@ gtk_text_iter_make_surreal (const GtkTextIter *_iter)
_gtk_text_btree_get_chars_changed_stamp (iter->tree))
{
g_warning ("Invalid text buffer iterator: either the iterator "
"is uninitialized, or the characters/textures/widgets "
"is uninitialized, or the characters/paintables/widgets "
"in the buffer have been modified since the iterator "
"was created.\nYou must use marks, character numbers, "
"or line numbers to preserve a position across buffer "
@ -896,7 +896,7 @@ gtk_text_iter_get_char (const GtkTextIter *iter)
* such as images. Because images are encoded in the slice, byte and
* character offsets in the returned array will correspond to byte
* offsets in the text buffer. Note that 0xFFFC can occur in normal
* text as well, so it is not a reliable indicator that a texture or
* text as well, so it is not a reliable indicator that a paintable or
* widget is in the buffer.
*
* Returns: (transfer full): slice of text from the buffer
@ -990,16 +990,16 @@ gtk_text_iter_get_visible_text (const GtkTextIter *start,
}
/**
* gtk_text_iter_get_texture:
* gtk_text_iter_get_paintable:
* @iter: an iterator
*
* If the element at @iter is a texture, the texture is returned
* If the element at @iter is a paintable, the paintable is returned
* (with no new reference count added). Otherwise, %NULL is returned.
*
* Returns: (transfer none): the texture at @iter
* Returns: (transfer none): the paintable at @iter
**/
GdkTexture *
gtk_text_iter_get_texture (const GtkTextIter *iter)
GdkPaintable *
gtk_text_iter_get_paintable (const GtkTextIter *iter)
{
GtkTextRealIter *real;
@ -1012,10 +1012,10 @@ gtk_text_iter_get_texture (const GtkTextIter *iter)
check_invariants (iter);
if (real->segment->type != &gtk_text_texture_type)
if (real->segment->type != &gtk_text_paintable_type)
return NULL;
else
return real->segment->body.texture.texture;
return real->segment->body.paintable.paintable;
}
/**
@ -2444,7 +2444,7 @@ gtk_text_iter_backward_chars (GtkTextIter *iter, gint count)
* @iter: a #GtkTextIter
* @count: number of chars to move
*
* Moves forward by @count text characters (textures, widgets,
* Moves forward by @count text characters (paintables, widgets,
* etc. do not count as characters for this). Equivalent to moving
* through the results of gtk_text_iter_get_text(), rather than
* gtk_text_iter_get_slice().
@ -2465,7 +2465,7 @@ gtk_text_iter_forward_text_chars (GtkTextIter *iter,
* @iter: a #GtkTextIter
* @count: number of chars to move
*
* Moves backward by @count text characters (textures, widgets,
* Moves backward by @count text characters (paintables, widgets,
* etc. do not count as characters for this). Equivalent to moving
* through the results of gtk_text_iter_get_text(), rather than
* gtk_text_iter_get_slice().
@ -5666,6 +5666,20 @@ _gtk_text_btree_get_iter_at_mark_name (GtkTextBTree *tree,
}
}
void
_gtk_text_btree_get_iter_at_paintable (GtkTextBTree *tree,
GtkTextIter *iter,
GtkTextLineSegment *seg)
{
g_return_if_fail (iter != NULL);
g_return_if_fail (tree != NULL);
iter_init_from_segment (iter, tree,
seg->body.paintable.line, seg);
g_assert (seg->body.paintable.line == _gtk_text_iter_get_text_line (iter));
check_invariants (iter);
}
void
_gtk_text_btree_get_iter_at_mark (GtkTextBTree *tree,
GtkTextIter *iter,

View File

@ -38,7 +38,7 @@ G_BEGIN_DECLS
* GtkTextSearchFlags:
* @GTK_TEXT_SEARCH_VISIBLE_ONLY: Search only visible data. A search match may
* have invisible text interspersed.
* @GTK_TEXT_SEARCH_TEXT_ONLY: Search only text. A match may have textures or
* @GTK_TEXT_SEARCH_TEXT_ONLY: Search only text. A match may have paintables or
* child widgets mixed inside the matched range.
* @GTK_TEXT_SEARCH_CASE_INSENSITIVE: The text will be matched regardless of
* what case it is in.
@ -47,7 +47,7 @@ G_BEGIN_DECLS
*
* If neither #GTK_TEXT_SEARCH_VISIBLE_ONLY nor #GTK_TEXT_SEARCH_TEXT_ONLY are
* enabled, the match must be exact; the special 0xFFFC character will match
* embedded textures or child widgets.
* embedded paintables or child widgets.
*/
typedef enum {
GTK_TEXT_SEARCH_VISIBLE_ONLY = 1 << 0,
@ -155,9 +155,9 @@ gchar *gtk_text_iter_get_visible_text (const GtkTextIter *start,
const GtkTextIter *end);
GDK_AVAILABLE_IN_ALL
GdkTexture * gtk_text_iter_get_texture (const GtkTextIter *iter);
GdkPaintable *gtk_text_iter_get_paintable (const GtkTextIter *iter);
GDK_AVAILABLE_IN_ALL
GSList * gtk_text_iter_get_marks (const GtkTextIter *iter);
GSList *gtk_text_iter_get_marks (const GtkTextIter *iter);
GDK_AVAILABLE_IN_ALL
GtkTextChildAnchor* gtk_text_iter_get_child_anchor (const GtkTextIter *iter);

View File

@ -1710,20 +1710,31 @@ add_text_attrs (GtkTextLayout *layout,
}
static void
add_texture_attrs (GtkTextLayout *layout,
GtkTextLineDisplay *display,
GtkTextAttributes *style,
GtkTextLineSegment *seg,
PangoAttrList *attrs,
gint start)
add_paintable_attrs (GtkTextLayout *layout,
GtkTextLineDisplay *display,
GtkTextAttributes *style,
GtkTextLineSegment *seg,
PangoAttrList *attrs,
gint start)
{
PangoAttribute *attr;
PangoRectangle logical_rect;
GtkTextTexture *texture = &seg->body.texture;
GtkTextPaintable *paintable = &seg->body.paintable;
gint width, height;
width = gdk_texture_get_width (texture->texture);
height = gdk_texture_get_height (texture->texture);
width = gdk_paintable_get_intrinsic_width (paintable->paintable);
height = gdk_paintable_get_intrinsic_height (paintable->paintable);
/* Pick *some* default size */
if (width == 0)
width = 32;
if (height == 0)
{
double aspect = gdk_paintable_get_intrinsic_aspect_ratio (paintable->paintable);
if (aspect == 0)
aspect = 1.0;
height = width / aspect;
}
logical_rect.x = 0;
logical_rect.y = -height * PANGO_SCALE;
@ -1731,7 +1742,7 @@ add_texture_attrs (GtkTextLayout *layout,
logical_rect.height = height * PANGO_SCALE;
attr = pango_attr_shape_new_with_data (&logical_rect, &logical_rect,
texture->texture, NULL, NULL);
paintable->paintable, NULL, NULL);
attr->start_index = start;
attr->end_index = start + seg->byte_count;
pango_attr_list_insert (attrs, attr);
@ -2149,7 +2160,7 @@ gtk_text_layout_update_display_cursors (GtkTextLayout *layout,
{
/* Displayable segments */
if (seg->type == &gtk_text_char_type ||
seg->type == &gtk_text_texture_type ||
seg->type == &gtk_text_paintable_type ||
seg->type == &gtk_text_child_type)
{
gtk_text_layout_get_iter_at_line (layout, &iter, line,
@ -2346,14 +2357,14 @@ gtk_text_layout_create_display (GtkTextLayout *layout,
{
/* Displayable segments */
if (seg->type == &gtk_text_char_type ||
seg->type == &gtk_text_texture_type ||
seg->type == &gtk_text_paintable_type ||
seg->type == &gtk_text_child_type)
{
style = get_style (layout, tags);
initial_toggle_segments = FALSE;
/* We have to delay setting the paragraph values until we
* hit the first texture or text segment because toggles at
* hit the first paintable or text segment because toggles at
* the beginning of the paragraph should affect the
* paragraph-global values
*/
@ -2430,15 +2441,15 @@ gtk_text_layout_create_display (GtkTextLayout *layout,
&last_scale_attr,
&last_fallback_attr);
}
else if (seg->type == &gtk_text_texture_type)
else if (seg->type == &gtk_text_paintable_type)
{
add_generic_attrs (layout,
&style->appearance,
seg->byte_count,
attrs, layout_byte_offset,
size_only, FALSE);
add_texture_attrs (layout, display, style,
seg, attrs, layout_byte_offset);
add_paintable_attrs (layout, display, style,
seg, attrs, layout_byte_offset);
memcpy (text + layout_byte_offset, _gtk_text_unknown_char_utf8,
seg->byte_count);
layout_byte_offset += seg->byte_count;
@ -4072,6 +4083,21 @@ render_para (GskPangoRenderer *crenderer,
pango_layout_iter_free (iter);
}
static gboolean
snapshot_shape (PangoAttrShape *attr,
GdkSnapshot *snapshot,
double width,
double height)
{
if (GDK_IS_PAINTABLE (attr->data))
{
gdk_paintable_snapshot (GDK_PAINTABLE (attr->data), snapshot, width, height);
return TRUE;
}
return FALSE;
}
void
gtk_text_layout_snapshot (GtkTextLayout *layout,
GtkWidget *widget,
@ -4106,6 +4132,8 @@ gtk_text_layout_snapshot (GtkTextLayout *layout,
crenderer = gsk_pango_renderer_acquire ();
gsk_pango_renderer_set_shape_handler (crenderer, snapshot_shape);
crenderer->widget = widget;
crenderer->snapshot = snapshot;
crenderer->fg_color = color;

View File

@ -142,10 +142,10 @@ struct _GtkTextLineSegment {
char chars[4]; /* Characters that make up character
* info. Actual length varies to
* hold as many characters as needed.*/
GtkTextToggleBody toggle; /* Information about tag toggle. */
GtkTextMarkBody mark; /* Information about mark. */
GtkTextTexture texture; /* Child texture */
GtkTextChildBody child; /* Child widget */
GtkTextToggleBody toggle; /* Information about tag toggle. */
GtkTextMarkBody mark; /* Information about mark. */
GtkTextPaintable paintable; /* Child texture */
GtkTextChildBody child; /* Child widget */
} body;
};

View File

@ -50,7 +50,7 @@ extern G_GNUC_INTERNAL const GtkTextLineSegmentClass gtk_text_left_mark_type;
extern G_GNUC_INTERNAL const GtkTextLineSegmentClass gtk_text_right_mark_type;
/* In gtktextchild.c */
extern G_GNUC_INTERNAL const GtkTextLineSegmentClass gtk_text_texture_type;
extern G_GNUC_INTERNAL const GtkTextLineSegmentClass gtk_text_paintable_type;
extern G_GNUC_INTERNAL const GtkTextLineSegmentClass gtk_text_child_type;
/*

View File

@ -3994,6 +3994,37 @@ icon_size_compare (GdkTexture *a,
return area_a - area_b;
}
static GdkTexture *
render_paintable_to_texture (GdkPaintable *paintable)
{
GtkSnapshot *snapshot;
GskRenderNode *node;
int width, height;
cairo_surface_t *surface;
cairo_t *cr;
GdkTexture *texture;
width = gdk_paintable_get_intrinsic_width (paintable);
height = gdk_paintable_get_intrinsic_height (paintable);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, width, height);
node = gtk_snapshot_free_to_node (snapshot);
cr = cairo_create (surface);
gsk_render_node_draw (node, cr);
cairo_destroy (cr);
gsk_render_node_unref (node);
texture = gdk_texture_new_for_surface (surface);
cairo_surface_destroy (surface);
return texture;
}
static GList *
icon_list_from_theme (GtkWindow *window,
const gchar *name)
@ -4004,6 +4035,7 @@ icon_list_from_theme (GtkWindow *window,
GtkCssValue *value;
GtkIconTheme *icon_theme;
GtkIconPaintable *info;
GdkTexture *texture;
gint *sizes;
gint i;
@ -4031,14 +4063,10 @@ icon_list_from_theme (GtkWindow *window,
sizes[i], priv->scale,
gtk_widget_get_direction (GTK_WIDGET (window)),
0);
if (info)
{
GdkTexture *texture = gtk_icon_paintable_download_texture (info, NULL);
if (texture)
list = g_list_insert_sorted (list, texture, (GCompareFunc) icon_size_compare);
g_object_unref (info);
}
texture = render_paintable_to_texture (GDK_PAINTABLE (info));
list = g_list_insert_sorted (list, texture, (GCompareFunc) icon_size_compare);
g_object_unref (info);
}
g_free (sizes);
@ -4111,7 +4139,7 @@ gtk_window_get_icon_for_size (GtkWindow *window,
info = gtk_icon_theme_lookup_icon (gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (window))),
name, NULL, size, priv->scale,
gtk_widget_get_direction (GTK_WIDGET (window)),
GTK_ICON_LOOKUP_FORCE_SIZE);
0);
if (info == NULL)
return NULL;

View File

@ -126,7 +126,28 @@ size_prepared_cb2 (GdkPixbufLoader *loader,
{
int *scales = data;
gdk_pixbuf_loader_set_size (loader, scales[0], scales[1]);
if (scales[2]) /* keep same aspect ratio as original, while fitting in given size */
{
double aspect = (double) height / width;
/* First use given width and calculate size */
width = scales[0];
height = scales[0] * aspect;
/* Check if it fits given height, otherwise scale down */
if (height > scales[1])
{
width *= (double) scales[1] / height;
height = scales[1];
}
}
else
{
width = scales[0];
height = scales[1];
}
gdk_pixbuf_loader_set_size (loader, width, scales[1]);
}
GdkPixbuf *
@ -140,7 +161,7 @@ _gdk_pixbuf_new_from_stream_at_scale (GInputStream *stream,
{
GdkPixbufLoader *loader;
GdkPixbuf *pixbuf;
int scales[2];
int scales[3];
if (format)
{
@ -153,6 +174,7 @@ _gdk_pixbuf_new_from_stream_at_scale (GInputStream *stream,
scales[0] = width;
scales[1] = height;
scales[2] = aspect;
g_signal_connect (loader, "size-prepared",
G_CALLBACK (size_prepared_cb2), scales);

View File

@ -17,6 +17,48 @@
#include <gtk/gtk.h>
static GdkTexture *
render_paintable_to_texture (GdkPaintable *paintable)
{
GtkSnapshot *snapshot;
GskRenderNode *node;
int width, height;
cairo_surface_t *surface;
cairo_t *cr;
GdkTexture *texture;
GBytes *bytes;
width = gdk_paintable_get_intrinsic_width (paintable);
height = gdk_paintable_get_intrinsic_height (paintable);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, width, height);
node = gtk_snapshot_free_to_node (snapshot);
cr = cairo_create (surface);
gsk_render_node_draw (node, cr);
cairo_destroy (cr);
gsk_render_node_unref (node);
bytes = g_bytes_new_with_free_func (cairo_image_surface_get_data (surface),
cairo_image_surface_get_height (surface)
* cairo_image_surface_get_stride (surface),
(GDestroyNotify) cairo_surface_destroy,
cairo_surface_reference (surface));
texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface),
GDK_MEMORY_DEFAULT,
bytes,
cairo_image_surface_get_stride (surface));
g_bytes_unref (bytes);
cairo_surface_destroy (surface);
return texture;
}
static void
clipboard_changed_cb (GdkClipboard *clipboard,
GtkWidget *stack)
@ -292,7 +334,7 @@ get_button_list (GdkClipboard *clipboard,
48, 1,
gtk_widget_get_direction (box),
0);
texture = gtk_icon_paintable_download_texture (icon, NULL);
texture = render_paintable_to_texture (GDK_PAINTABLE (icon));
g_value_take_object (&value, gdk_pixbuf_get_from_texture (texture));
g_object_unref (texture);
g_object_unref (icon);

View File

@ -6,6 +6,53 @@
#include <io.h>
#endif
static GdkTexture *
render_paintable_to_texture (GdkPaintable *paintable)
{
GtkSnapshot *snapshot;
GskRenderNode *node;
int width, height;
cairo_surface_t *surface;
cairo_t *cr;
GdkTexture *texture;
GBytes *bytes;
width = gdk_paintable_get_intrinsic_width (paintable);
if (width == 0)
width = 32;
height = gdk_paintable_get_intrinsic_height (paintable);
if (height == 0)
height = 32;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, width, height);
node = gtk_snapshot_free_to_node (snapshot);
cr = cairo_create (surface);
gsk_render_node_draw (node, cr);
cairo_destroy (cr);
gsk_render_node_unref (node);
bytes = g_bytes_new_with_free_func (cairo_image_surface_get_data (surface),
cairo_image_surface_get_height (surface)
* cairo_image_surface_get_stride (surface),
(GDestroyNotify) cairo_surface_destroy,
cairo_surface_reference (surface));
texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface),
GDK_MEMORY_DEFAULT,
bytes,
cairo_image_surface_get_stride (surface));
g_bytes_unref (bytes);
cairo_surface_destroy (surface);
return texture;
}
static GdkTexture *
get_image_texture (GtkImage *image,
int *out_size)
@ -13,7 +60,7 @@ get_image_texture (GtkImage *image,
GtkIconTheme *icon_theme;
const char *icon_name;
int width = 48;
GdkPaintable *paintable;
GdkPaintable *paintable = NULL;
GdkTexture *texture = NULL;
GtkIconPaintable *icon;
@ -21,29 +68,28 @@ get_image_texture (GtkImage *image,
{
case GTK_IMAGE_PAINTABLE:
paintable = gtk_image_get_paintable (image);
if (GDK_IS_TEXTURE (paintable))
{
*out_size = gdk_paintable_get_intrinsic_width (paintable);
texture = g_object_ref (GDK_TEXTURE (paintable));
}
break;
case GTK_IMAGE_ICON_NAME:
icon_name = gtk_image_get_icon_name (image);
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (image)));
*out_size = width;
icon = gtk_icon_theme_lookup_icon (icon_theme,
icon_name,
NULL,
width, 1,
gtk_widget_get_direction (GTK_WIDGET (image)),
0);
if (icon)
texture = gtk_icon_paintable_download_texture (icon, NULL);
g_object_unref (icon);
paintable = GDK_PAINTABLE (icon);
break;
default:
g_warning ("Image storage type %d not handled",
gtk_image_get_storage_type (image));
}
if (paintable)
texture = render_paintable_to_texture (paintable);
g_object_unref (paintable);
return texture;
}
@ -238,6 +284,9 @@ update_source_icon (GtkDragSource *source,
int hot_x, hot_y;
int size = 48;
if (widget == NULL)
return;
icon = gtk_icon_theme_lookup_icon (gtk_icon_theme_get_for_display (gtk_widget_get_display (widget)),
icon_name,
NULL,

View File

@ -114,6 +114,8 @@ main (int argc, char *argv[])
}
else if (strcmp (argv[1], "lookup") == 0)
{
GFile *file;
if (argc < 4)
{
g_object_unref (icon_theme);
@ -128,17 +130,12 @@ main (int argc, char *argv[])
scale = atoi (argv[5]);
icon = gtk_icon_theme_lookup_icon (icon_theme, argv[3], NULL, size, scale, direction, flags);
file = gtk_icon_paintable_get_file (icon);
g_print ("icon for %s at %dx%d@%dx is %s\n", argv[3], size, size, scale,
icon ? gtk_icon_paintable_get_filename (icon) : "<none>");
file ? g_file_get_uri (file) : "<none>");
if (icon)
{
GdkPaintable *paintable = GDK_PAINTABLE (icon);
g_print ("texture size: %dx%d\n", gdk_paintable_get_intrinsic_width (paintable), gdk_paintable_get_intrinsic_height (paintable));
g_object_unref (icon);
}
g_print ("texture size: %dx%d\n", gdk_paintable_get_intrinsic_width (GDK_PAINTABLE (icon)), gdk_paintable_get_intrinsic_height (GDK_PAINTABLE (icon)));
g_object_unref (icon);
}
else
{

View File

@ -58,6 +58,8 @@ assert_icon_lookup_size (const char *icon_name,
gint pixbuf_size)
{
GtkIconPaintable *info;
GFile *file;
char *path = NULL;
if (fallbacks)
{
@ -78,31 +80,31 @@ assert_icon_lookup_size (const char *icon_name,
return;
}
file = gtk_icon_paintable_get_file (info);
if (file)
{
path = g_file_get_path (file);
g_object_unref (file);
}
if (filename)
{
if (!g_str_has_suffix (gtk_icon_paintable_get_filename (info), filename))
if (path == NULL || !g_str_has_suffix (path, filename))
{
g_error ("Icon for \"%s\" with flags %s at size %d should be \"...%s\" but is \"...%s\"",
icon_name, lookup_flags_to_string (flags), size,
filename, gtk_icon_paintable_get_filename (info) + strlen (g_get_current_dir ()));
filename, path);
return;
}
}
else
{
g_assert (gtk_icon_paintable_get_filename (info) == NULL);
g_assert (path == NULL);
}
if (pixbuf_size > 0)
{
GdkTexture *texture;
GError *error = NULL;
g_free (path);
texture = gtk_icon_paintable_download_texture (info, &error);
g_assert_no_error (error);
g_assert_cmpint (gdk_texture_get_width (texture), ==, pixbuf_size);
g_object_unref (texture);
}
g_assert_cmpint (gdk_paintable_get_intrinsic_width (GDK_PAINTABLE (info)), ==, size);
g_object_unref (info);
}
@ -128,13 +130,9 @@ assert_icon_lookup_fails (const char *icon_name,
info = gtk_icon_theme_lookup_icon (get_test_icontheme (FALSE), icon_name, NULL, size, 1, direction, flags);
if (info != NULL)
{
g_error ("Should not find an icon for \"%s\" with flags %s at size %d, but found \"%s\"",
icon_name, lookup_flags_to_string (flags), size, gtk_icon_paintable_get_filename (info) + strlen (g_get_current_dir ()));
g_object_unref (info);
return;
}
/* We never truly *fail*, but check that we got the image-missing fallback */
g_assert (info != NULL);
g_assert_cmpstr (gtk_icon_paintable_get_icon_name (info), ==, "image-missing");
}
static GList *lookups = NULL;
@ -593,24 +591,20 @@ test_symbolic_single_size (void)
static void
test_svg_size (void)
{
/* To understand these results, keep in mind that we never allow upscaling,
* and don't respect min/max size for scaling (though we do take it into
* account for choosing).
*/
/* Check we properly load a svg icon from a sized directory */
assert_icon_lookup_size ("twosize-fixed", 48, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/32x32/twosize-fixed.svg", 32);
assert_icon_lookup_size ("twosize-fixed", 48, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/32x32/twosize-fixed.svg", 48);
assert_icon_lookup_size ("twosize-fixed", 32, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/32x32/twosize-fixed.svg", 32);
assert_icon_lookup_size ("twosize-fixed", 20, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/32x32/twosize-fixed.svg", 32);
assert_icon_lookup_size ("twosize-fixed", 20, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/32x32/twosize-fixed.svg", 20);
assert_icon_lookup_size ("twosize-fixed", 16, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/16x16/twosize-fixed.svg", 16);
/* Check that we still properly load it even if a different size is requested */
assert_icon_lookup_size ("twosize", 64, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/32x32s/twosize.svg", 48);
assert_icon_lookup_size ("twosize", 64, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/32x32s/twosize.svg", 64);
assert_icon_lookup_size ("twosize", 48, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/32x32s/twosize.svg", 48);
assert_icon_lookup_size ("twosize", 32, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/32x32s/twosize.svg", 32);
assert_icon_lookup_size ("twosize", 24, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/32x32s/twosize.svg", 24);
assert_icon_lookup_size ("twosize", 16, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/16x16s/twosize.svg", 16);
assert_icon_lookup_size ("twosize", 12, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/16x16s/twosize.svg", 12);
assert_icon_lookup_size ("twosize", 8, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/16x16s/twosize.svg", 12);
assert_icon_lookup_size ("twosize", 8, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/16x16s/twosize.svg", 8);
}
static void
@ -625,42 +619,21 @@ test_size (void)
assert_icon_lookup_size ("size-test", 18, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/16-22/size-test.png", 19);
assert_icon_lookup_size ("size-test", 19, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/16-22/size-test.png", 19);
/* the next 3 are because we never scale up */
assert_icon_lookup_size ("size-test", 20, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/25+/size-test.svg", 25);
assert_icon_lookup_size ("size-test", 21, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/25+/size-test.svg", 25);
assert_icon_lookup_size ("size-test", 22, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/25+/size-test.svg", 25);
assert_icon_lookup_size ("size-test", 20, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/25+/size-test.svg", 20);
assert_icon_lookup_size ("size-test", 21, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/25+/size-test.svg", 21);
assert_icon_lookup_size ("size-test", 22, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/25+/size-test.svg", 22);
assert_icon_lookup_size ("size-test", 23, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/25+/size-test.svg", 25);
assert_icon_lookup_size ("size-test", 23, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/25+/size-test.svg", 25);
assert_icon_lookup_size ("size-test", 23, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/25+/size-test.svg", 23);
assert_icon_lookup_size ("size-test", 23, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/25+/size-test.svg", 23);
assert_icon_lookup_size ("size-test", 25, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/25+/size-test.svg", 25);
assert_icon_lookup_size ("size-test", 28, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/25+/size-test.svg", 28);
/* the next 2 are because we never scale up */
assert_icon_lookup_size ("size-test", 31, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/35+/size-test.svg", 35);
assert_icon_lookup_size ("size-test", 34, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/35+/size-test.svg", 35);
assert_icon_lookup_size ("size-test", 31, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/35+/size-test.svg", 31);
assert_icon_lookup_size ("size-test", 34, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/35+/size-test.svg", 34);
assert_icon_lookup_size ("size-test", 37, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/35+/size-test.svg", 37);
assert_icon_lookup_size ("size-test", 40, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/35+/size-test.svg", 40);
assert_icon_lookup_size ("size-test", 45, GTK_TEXT_DIR_NONE, 0, FALSE, "/icons/35+/size-test.svg", 45);
assert_icon_lookup_size ("size-test", 12, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/15/size-test.png", 12);
assert_icon_lookup_size ("size-test", 13, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/15/size-test.png", 13);
assert_icon_lookup_size ("size-test", 14, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/15/size-test.png", 14);
assert_icon_lookup_size ("size-test", 15, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/15/size-test.png", 15);
assert_icon_lookup_size ("size-test", 16, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/16-22/size-test.png", 16);
assert_icon_lookup_size ("size-test", 17, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/16-22/size-test.png", 17);
assert_icon_lookup_size ("size-test", 18, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/16-22/size-test.png", 18);
assert_icon_lookup_size ("size-test", 19, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/16-22/size-test.png", 19);
//assert_icon_lookup_size ("size-test", 20, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/16-22/size-test.png", 20);
//assert_icon_lookup_size ("size-test", 21, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/16-22/size-test.png", 21);
//assert_icon_lookup_size ("size-test", 22, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/16-22/size-test.png", 22);
assert_icon_lookup_size ("size-test", 23, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/25+/size-test.svg", 23);
assert_icon_lookup_size ("size-test", 24, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/25+/size-test.svg", 24);
assert_icon_lookup_size ("size-test", 25, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/25+/size-test.svg", 25);
assert_icon_lookup_size ("size-test", 28, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/25+/size-test.svg", 28);
//assert_icon_lookup_size ("size-test", 31, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/25+/size-test.svg", 31);
//assert_icon_lookup_size ("size-test", 34, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/25+/size-test.svg", 34);
assert_icon_lookup_size ("size-test", 37, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/35+/size-test.svg", 37);
assert_icon_lookup_size ("size-test", 40, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/35+/size-test.svg", 40);
assert_icon_lookup_size ("size-test", 45, GTK_TEXT_DIR_NONE, GTK_ICON_LOOKUP_FORCE_SIZE, FALSE, "/icons/35+/size-test.svg", 45);
}
static void
@ -745,26 +718,34 @@ test_inherit (void)
static void
test_nonsquare_symbolic (void)
{
gint width, height;
gint width, height, size;
GtkIconTheme *icon_theme;
GtkIconPaintable *info;
GFile *file;
GIcon *icon;
GError *error = NULL;
GdkTexture *texture;
GdkPixbuf *pixbuf;
GtkSnapshot *snapshot;
GskRenderNode *node;
graphene_rect_t bounds;
gchar *path = g_build_filename (g_test_get_dir (G_TEST_DIST),
"icons",
"scalable",
"nonsquare-symbolic.svg",
NULL);
"icons",
"scalable",
"nonsquare-symbolic.svg",
NULL);
/* load the original image for reference */
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (path, &error);
pixbuf = gdk_pixbuf_new_from_file (path, &error);
g_assert_no_error (error);
g_assert_nonnull (pixbuf);
width = gdk_pixbuf_get_width (pixbuf);
height = gdk_pixbuf_get_height (pixbuf);
size = MAX (width, height);
g_object_unref (pixbuf);
g_assert_cmpint (width, !=, height);
/* now load it through GtkIconTheme */
@ -775,51 +756,28 @@ test_nonsquare_symbolic (void)
height, 1, GTK_TEXT_DIR_NONE, 0);
g_assert_nonnull (info);
g_object_unref (pixbuf);
texture = gtk_icon_paintable_download_texture (info, &error);
/* we are loaded successfully */
g_assert_no_error (error);
g_assert_nonnull (texture);
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (GDK_PAINTABLE (info), snapshot, size, size);
node = gtk_snapshot_free_to_node (snapshot);
/* the original dimensions have been preserved */
g_assert_cmpint (gdk_texture_get_width (texture), ==, width);
g_assert_cmpint (gdk_texture_get_height (texture), ==, height);
gsk_render_node_get_bounds (node, &bounds);
g_assert (bounds.size.width == width);
g_assert (bounds.size.height == height);
gsk_render_node_unref (node);
g_free (path);
g_object_unref (texture);
g_object_unref (file);
g_object_unref (icon);
g_object_unref (info);
}
static GLogWriterOutput
log_writer_drop_warnings (GLogLevelFlags log_level,
const GLogField *fields,
gsize n_fields,
gpointer user_data)
{
gboolean *ignore_warnings = user_data;
if (log_level == G_LOG_LEVEL_WARNING && *ignore_warnings)
return G_LOG_WRITER_HANDLED;
return g_log_writer_default (log_level, fields, n_fields, user_data);
}
int
main (int argc, char *argv[])
{
gboolean ignore_warnings = TRUE;
gtk_test_init (&argc, &argv);
/* Ignore the one-time warning that the fallback icon theme cant be found
* (because weve changed the search paths). */
g_log_set_writer_func (log_writer_drop_warnings, &ignore_warnings, NULL);
assert_icon_lookup_fails ("this-icon-totally-does-not-exist", 16, GTK_TEXT_DIR_NONE, 0);
ignore_warnings = FALSE;
g_test_add_func ("/icontheme/basics", test_basics);
g_test_add_func ("/icontheme/lookup-order", test_lookup_order);
g_test_add_func ("/icontheme/generic-fallback", test_generic_fallback);

View File

@ -686,11 +686,11 @@ fill_buffer (GtkTextBuffer *buffer)
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE (texture));
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 1);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE (texture));
str = g_strdup_printf ("%d Hello World!\nwoo woo woo woo woo woo woo woo\n",
i);
@ -706,20 +706,20 @@ fill_buffer (GtkTextBuffer *buffer)
"Spanish (Espa\303\261ol) \302\241Hola! / French (Fran\303\247ais) Bonjour, Salut / German (Deutsch S\303\274d) Gr\303\274\303\237 Gott (testing Latin-1 chars encoded in UTF8)\nThai (we can't display this, just making sure we don't crash) (\340\270\240\340\270\262\340\270\251\340\270\262\340\271\204\340\270\227\340\270\242) \340\270\252\340\270\247\340\270\261\340\270\252\340\270\224\340\270\265\340\270\204\340\270\243\340\270\261\340\270\232, \340\270\252\340\270\247\340\270\261\340\270\252\340\270\224\340\270\265\340\270\204\340\271\210\340\270\260\n",
-1);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE(texture));
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE(texture));
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 4);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE(texture));
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 7);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE(texture));
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 8);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE(texture));
gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 8);
iter2 = iter;