X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fwidgets%2Ficon.cpp;h=9be74a556f9151431dee10c24372351cd6702599;hb=7ec2a593a4a4046d6313fc868bd32ca1a5b2a119;hp=55dab2ba7dbcac32c4704cf7a32549095f1e251e;hpb=e42e6130e1aca183d24c4e696c9fae555c49beaa;p=inkscape.git diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index 55dab2ba7..9be74a556 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -18,6 +18,7 @@ +#include #include #include #include @@ -36,7 +37,7 @@ static gboolean icon_prerender_task(gpointer data); -static void addPreRender( GtkIconSize lsize, gchar const *name ); +static void addPreRender( Inkscape::IconSize lsize, gchar const *name ); static void sp_icon_class_init(SPIconClass *klass); static void sp_icon_init(SPIcon *icon); @@ -65,10 +66,24 @@ static int sp_icon_get_phys_size(int size); static void sp_icon_overlay_pixels( guchar *px, int width, int height, int stride, unsigned r, unsigned g, unsigned b ); +static void injectCustomSize(); + static GtkWidgetClass *parent_class; static bool sizeDirty = true; +static bool sizeMapDone = false; +static GtkIconSize iconSizeLookup[] = { + GTK_ICON_SIZE_INVALID, + GTK_ICON_SIZE_MENU, + GTK_ICON_SIZE_SMALL_TOOLBAR, + GTK_ICON_SIZE_LARGE_TOOLBAR, + GTK_ICON_SIZE_BUTTON, + GTK_ICON_SIZE_DND, + GTK_ICON_SIZE_DIALOG, + GTK_ICON_SIZE_MENU, // for Inkscape::ICON_SIZE_DECORATION +}; + GtkType sp_icon_get_type() { @@ -174,6 +189,19 @@ static int sp_icon_expose(GtkWidget *widget, GdkEventExpose *event) { if ( GTK_WIDGET_DRAWABLE(widget) ) { SPIcon *icon = SP_ICON(widget); + if ( !icon->pb ) { + sp_icon_fetch_pixbuf( icon ); + } + + sp_icon_paint(SP_ICON(widget), &event->area); + } + + return TRUE; +} + +void sp_icon_fetch_pixbuf( SPIcon *icon ) +{ + if ( icon ) { if ( !icon->pb ) { guchar *pixels = 0; @@ -182,12 +210,12 @@ static int sp_icon_expose(GtkWidget *widget, GdkEventExpose *event) pixels = sp_icon_image_load( icon, icon->name ); if (pixels) { - // don't pass the nr_free because we're caching the pixel + // don't pass the g_free because we're caching the pixel // space loaded through ... // I just changed this. make sure sp_icon_image_load still does the right thing. icon->pb = gdk_pixbuf_new_from_data(pixels, GDK_COLORSPACE_RGB, TRUE, 8, icon->psize, icon->psize, icon->psize * 4, - /*(GdkPixbufDestroyNotify)nr_free*/NULL, NULL); + /*(GdkPixbufDestroyNotify)g_free*/NULL, NULL); icon->pb_faded = gdk_pixbuf_copy(icon->pb); pixels = gdk_pixbuf_get_pixels(icon->pb_faded); @@ -206,14 +234,9 @@ static int sp_icon_expose(GtkWidget *widget, GdkEventExpose *event) g_warning ("failed to load icon '%s'", icon->name); } } - - sp_icon_paint(SP_ICON(widget), &event->area); } - - return TRUE; } - static void sp_icon_screen_changed( GtkWidget *widget, GdkScreen *previous_screen ) { if ( GTK_WIDGET_CLASS( parent_class )->screen_changed ) { @@ -242,7 +265,7 @@ static void sp_icon_theme_changed( SPIcon *icon ) static GtkWidget * -sp_icon_new_full( GtkIconSize lsize, gchar const *name ) +sp_icon_new_full( Inkscape::IconSize lsize, gchar const *name ) { static gint dump = prefs_get_int_attribute_limited( "debug.icons", "dumpGtk", 0, 0, 1 ); static gint fallback = prefs_get_int_attribute_limited( "debug.icons", "checkNames", 0, 0, 1 ); @@ -260,7 +283,13 @@ sp_icon_new_full( GtkIconSize lsize, gchar const *name ) GtkWidget *widget = 0; if ( tryLoad ) { - GtkWidget *img = gtk_image_new_from_stock( name, lsize ); + gint trySize = CLAMP( static_cast(lsize), 0, static_cast(G_N_ELEMENTS(iconSizeLookup) - 1) ); + + if ( !sizeMapDone ) { + injectCustomSize(); + } + + GtkWidget *img = gtk_image_new_from_stock( name, iconSizeLookup[trySize] ); if ( img ) { GtkImageType type = gtk_image_get_storage_type( GTK_IMAGE(img) ); if ( type == GTK_IMAGE_STOCK ) { @@ -282,7 +311,7 @@ sp_icon_new_full( GtkIconSize lsize, gchar const *name ) if ( !widget ) { SPIcon *icon = (SPIcon *)g_object_new(SP_TYPE_ICON, NULL); - icon->lsize = (Inkscape::IconSize)lsize; + icon->lsize = lsize; icon->name = g_strdup(name); icon->psize = sp_icon_get_phys_size(lsize); @@ -295,14 +324,13 @@ sp_icon_new_full( GtkIconSize lsize, gchar const *name ) GtkWidget * sp_icon_new( Inkscape::IconSize lsize, gchar const *name ) { -// TODO FIX THIS - return sp_icon_new_full( (GtkIconSize)lsize, name ); + return sp_icon_new_full( lsize, name ); } Gtk::Widget *sp_icon_get_icon( Glib::ustring const &oid, Inkscape::IconSize size ) { Gtk::Widget *result = 0; - GtkWidget *widget = sp_icon_new_full( (GtkIconSize)size, oid.c_str() ); + GtkWidget *widget = sp_icon_new_full( size, oid.c_str() ); if ( widget ) { if ( GTK_IS_IMAGE(widget) ) { @@ -342,13 +370,46 @@ sp_icon_get_gtk_size(int size) return map[size]; } +static void injectCustomSize() +{ + // TODO - still need to handle the case of theme changes and resize, especially as we can't re-register a string. + if ( !sizeMapDone ) + { + gint dump = prefs_get_int_attribute_limited( "debug.icons", "dumpDefault", 0, 0, 1 ); + gint width = 0; + gint height = 0; + if ( gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height ) ) { + gint newWidth = ((width * 3) / 4); + gint newHeight = ((height * 3) / 4); + GtkIconSize newSizeEnum = gtk_icon_size_register( "inkscape-decoration", newWidth, newHeight ); + if ( newSizeEnum ) { + if ( dump ) { + g_message("Registered (%d, %d) <= (%d, %d) as index %d", newWidth, newHeight, width, height, newSizeEnum); + } + guint index = static_cast(Inkscape::ICON_SIZE_DECORATION); + if ( index < G_N_ELEMENTS(iconSizeLookup) ) { + iconSizeLookup[index] = newSizeEnum; + } else if ( dump ) { + g_message("size lookup array too small to store entry"); + } + } + } + sizeMapDone = true; + } + +} + static int sp_icon_get_phys_size(int size) { static bool init = false; - static int lastSys[GTK_ICON_SIZE_DIALOG + 1]; - static int vals[GTK_ICON_SIZE_DIALOG + 1]; + static int lastSys[Inkscape::ICON_SIZE_DECORATION + 1]; + static int vals[Inkscape::ICON_SIZE_DECORATION + 1]; - size = CLAMP( size, GTK_ICON_SIZE_MENU, GTK_ICON_SIZE_DIALOG ); + size = CLAMP( size, GTK_ICON_SIZE_MENU, Inkscape::ICON_SIZE_DECORATION ); + + if ( !sizeMapDone ) { + injectCustomSize(); + } if ( sizeDirty && init ) { GtkIconSize const gtkSizes[] = { @@ -357,10 +418,14 @@ static int sp_icon_get_phys_size(int size) GTK_ICON_SIZE_LARGE_TOOLBAR, GTK_ICON_SIZE_BUTTON, GTK_ICON_SIZE_DND, - GTK_ICON_SIZE_DIALOG + GTK_ICON_SIZE_DIALOG, + static_cast(Inkscape::ICON_SIZE_DECORATION) < G_N_ELEMENTS(iconSizeLookup) ? + iconSizeLookup[static_cast(Inkscape::ICON_SIZE_DECORATION)] : + GTK_ICON_SIZE_MENU }; for (unsigned i = 0; i < G_N_ELEMENTS(gtkSizes) && init; ++i) { - unsigned const val_ix(gtkSizes[i]); + guint const val_ix = (gtkSizes[i] <= GTK_ICON_SIZE_DIALOG) ? (guint)gtkSizes[i] : (guint)Inkscape::ICON_SIZE_DECORATION; + g_assert( val_ix < G_N_ELEMENTS(vals) ); gint width = 0; @@ -374,6 +439,7 @@ static int sp_icon_get_phys_size(int size) if ( !init ) { sizeDirty = false; gint dump = prefs_get_int_attribute_limited( "debug.icons", "dumpDefault", 0, 0, 1 ); + if ( dump ) { g_message( "Default icon sizes:" ); } @@ -385,7 +451,10 @@ static int sp_icon_get_phys_size(int size) GTK_ICON_SIZE_LARGE_TOOLBAR, GTK_ICON_SIZE_BUTTON, GTK_ICON_SIZE_DND, - GTK_ICON_SIZE_DIALOG + GTK_ICON_SIZE_DIALOG, + static_cast(Inkscape::ICON_SIZE_DECORATION) < G_N_ELEMENTS(iconSizeLookup) ? + iconSizeLookup[static_cast(Inkscape::ICON_SIZE_DECORATION)] : + GTK_ICON_SIZE_MENU }; gchar const *const names[] = { "GTK_ICON_SIZE_MENU", @@ -393,13 +462,15 @@ static int sp_icon_get_phys_size(int size) "GTK_ICON_SIZE_LARGE_TOOLBAR", "GTK_ICON_SIZE_BUTTON", "GTK_ICON_SIZE_DND", - "GTK_ICON_SIZE_DIALOG" + "GTK_ICON_SIZE_DIALOG", + "inkscape-decoration" }; GtkWidget *icon = (GtkWidget *)g_object_new(SP_TYPE_ICON, NULL); for (unsigned i = 0; i < G_N_ELEMENTS(gtkSizes); ++i) { - unsigned const val_ix(gtkSizes[i]); + guint const val_ix = (gtkSizes[i] <= GTK_ICON_SIZE_DIALOG) ? (guint)gtkSizes[i] : (guint)Inkscape::ICON_SIZE_DECORATION; + g_assert( val_ix < G_N_ELEMENTS(vals) ); gint width = 0; @@ -458,12 +529,17 @@ static void sp_icon_paint(SPIcon *icon, GdkRectangle const *area) int const x1 = std::min(area->x + area->width, widget.allocation.x + padx + static_cast(icon->psize) ); int const y1 = std::min(area->y + area->height, widget.allocation.y + pady + static_cast(icon->psize) ); - gdk_draw_pixbuf(GDK_DRAWABLE(widget.window), NULL, image, - x0 - widget.allocation.x - padx, - y0 - widget.allocation.y - pady, - x0, y0, - x1 - x0, y1 - y0, - GDK_RGB_DITHER_NORMAL, x0, y0); + int width = x1 - x0; + int height = y1 - y0; + // Limit drawing to when we actually have something. Avoids some crashes. + if ( (width > 0) && (height > 0) ) { + gdk_draw_pixbuf(GDK_DRAWABLE(widget.window), NULL, image, + x0 - widget.allocation.x - padx, + y0 - widget.allocation.y - pady, + x0, y0, + width, height, + GDK_RGB_DITHER_NORMAL, x0, y0); + } } } @@ -513,7 +589,7 @@ sp_icon_image_load_pixmap(gchar const *name, unsigned lsize, unsigned psize) } guchar *spx = gdk_pixbuf_get_pixels(pb); int srs = gdk_pixbuf_get_rowstride(pb); - px = nr_new(guchar, 4 * psize * psize); + px = g_new(guchar, 4 * psize * psize); for (unsigned y = 0; y < psize; y++) { memcpy(px + 4 * y * psize, spx + y * srs, 4 * psize); } @@ -538,7 +614,7 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, if (object && SP_IS_ITEM(object)) { /* Find bbox in document */ NR::Matrix const i2doc(sp_item_i2doc_affine(SP_ITEM(object))); - NR::Rect dbox = SP_ITEM(object)->invokeBbox(i2doc); + NR::Maybe dbox = SP_ITEM(object)->getBounds(i2doc); if ( SP_OBJECT_PARENT(object) == NULL ) { @@ -547,7 +623,7 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, } /* This is in document coordinates, i.e. pixels */ - if (dbox.isEmpty() == false) { + if ( dbox && !dbox->isEmpty() ) { NRGC gc(NULL); /* Update to renderable state */ double sf = 1.0; @@ -560,10 +636,10 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, NR_ARENA_ITEM_STATE_NONE ); /* Item integer bbox in points */ NRRectL ibox; - ibox.x0 = (int) floor(sf * dbox.min()[NR::X] + 0.5); - ibox.y0 = (int) floor(sf * dbox.min()[NR::Y] + 0.5); - ibox.x1 = (int) floor(sf * dbox.max()[NR::X] + 0.5); - ibox.y1 = (int) floor(sf * dbox.max()[NR::Y] + 0.5); + ibox.x0 = (int) floor(sf * dbox->min()[NR::X] + 0.5); + ibox.y0 = (int) floor(sf * dbox->min()[NR::Y] + 0.5); + ibox.x1 = (int) floor(sf * dbox->max()[NR::X] + 0.5); + ibox.y1 = (int) floor(sf * dbox->max()[NR::Y] + 0.5); if ( dump ) { g_message( " box --'%s' (%f,%f)-(%f,%f)", name, (double)ibox.x0, (double)ibox.y0, (double)ibox.x1, (double)ibox.y1 ); @@ -592,10 +668,10 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE ); /* Item integer bbox in points */ - ibox.x0 = (int) floor(sf * dbox.min()[NR::X] + 0.5); - ibox.y0 = (int) floor(sf * dbox.min()[NR::Y] + 0.5); - ibox.x1 = (int) floor(sf * dbox.max()[NR::X] + 0.5); - ibox.y1 = (int) floor(sf * dbox.max()[NR::Y] + 0.5); + ibox.x0 = (int) floor(sf * dbox->min()[NR::X] + 0.5); + ibox.y0 = (int) floor(sf * dbox->min()[NR::Y] + 0.5); + ibox.x1 = (int) floor(sf * dbox->max()[NR::X] + 0.5); + ibox.y1 = (int) floor(sf * dbox->max()[NR::Y] + 0.5); if ( dump ) { g_message( " box2 --'%s' (%f,%f)-(%f,%f)", name, (double)ibox.x0, (double)ibox.y0, (double)ibox.x1, (double)ibox.y1 ); @@ -633,7 +709,7 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, g_message( " ua --'%s' (%f,%f)-(%f,%f)", name, (double)ua.x0, (double)ua.y0, (double)ua.x1, (double)ua.y1 ); } /* Set up pixblock */ - px = nr_new(guchar, 4 * psize * psize); + px = g_new(guchar, 4 * psize * psize); memset(px, 0x00, 4 * psize * psize); /* Render */ NRPixBlock B; @@ -642,7 +718,7 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, px + 4 * psize * (ua.y0 - area.y0) + 4 * (ua.x0 - area.x0), 4 * psize, FALSE, FALSE ); - nr_arena_item_invoke_render( root, &ua, &B, + nr_arena_item_invoke_render(NULL, root, &ua, &B, NR_ARENA_ITEM_RENDER_NO_CACHE ); nr_pixblock_release(&B); @@ -762,8 +838,8 @@ static guchar *load_svg_pixels(gchar const *name, // returns true if icon needed preloading, false if nothing was done static bool prerender_icon(gchar const *name, unsigned lsize, unsigned psize) { - Glib::ustring key=icon_cache_key(name, lsize, psize); - guchar *px=get_cached_pixels(key); + Glib::ustring key = icon_cache_key(name, lsize, psize); + guchar *px = get_cached_pixels(key); if (px) { return false; } else { @@ -778,10 +854,10 @@ static bool prerender_icon(gchar const *name, unsigned lsize, unsigned psize) static guchar * sp_icon_image_load_svg(gchar const *name, unsigned lsize, unsigned psize) { - Glib::ustring key=icon_cache_key(name, lsize, psize); + Glib::ustring key = icon_cache_key(name, lsize, psize); // did we already load this icon at this scale/size? - guchar *px=get_cached_pixels(key); + guchar *px = get_cached_pixels(key); if (!px) { px = load_svg_pixels(name, lsize, psize); if (px) { @@ -849,11 +925,11 @@ void sp_icon_overlay_pixels(guchar *px, int width, int height, int stride, class preRenderItem { public: - preRenderItem( GtkIconSize lsize, gchar const *name ) : + preRenderItem( Inkscape::IconSize lsize, gchar const *name ) : _lsize( lsize ), _name( name ) {} - GtkIconSize _lsize; + Inkscape::IconSize _lsize; Glib::ustring _name; }; @@ -863,7 +939,7 @@ public: static std::queue pendingRenders; static bool callbackHooked = false; -static void addPreRender( GtkIconSize lsize, gchar const *name ) +static void addPreRender( Inkscape::IconSize lsize, gchar const *name ) { if ( !callbackHooked )