static void bg(GtkStyleContext* sc, wxColour& color, int state = GTK_STATE_FLAG_NORMAL) { GdkRGBA* rgba; cairo_pattern_t* pattern = NULL; gtk_style_context_set_state(sc, GtkStateFlags(state)); gtk_style_context_get(sc, GtkStateFlags(state), "background-color", &rgba, "background-image", &pattern, NULL); color = wxColour(*rgba); gdk_rgba_free(rgba); // "background-image" takes precedence over "background-color". // If there is an image, try to get a color out of it. if (pattern) { if (cairo_pattern_get_type(pattern) == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_t* surf; cairo_pattern_get_surface(pattern, &surf); if (cairo_surface_get_type(surf) == CAIRO_SURFACE_TYPE_IMAGE) { const guchar* data = cairo_image_surface_get_data(surf); const int stride = cairo_image_surface_get_stride(surf); // choose a pixel in the middle vertically, // images often have a vertical gradient const int i = stride * (cairo_image_surface_get_height(surf) / 2); const unsigned* p = reinterpret_cast<const unsigned*>(data + i); const unsigned pixel = *p; guchar r, g, b, a = 0xff; switch (cairo_image_surface_get_format(surf)) { case CAIRO_FORMAT_ARGB32: a = guchar(pixel >> 24); // fallthrough case CAIRO_FORMAT_RGB24: r = guchar(pixel >> 16); g = guchar(pixel >> 8); b = guchar(pixel); break; default: a = 0; break; } if (a != 0) { if (a != 0xff) { // un-premultiply r = guchar((r * 0xff) / a); g = guchar((g * 0xff) / a); b = guchar((b * 0xff) / a); } color.Set(r, g, b, a); } } } cairo_pattern_destroy(pattern); }
wxSize wxSpinButton::DoGetBestSize() const { wxSize best = base_type::DoGetBestSize(); #ifdef __WXGTK3__ GtkStyleContext* sc = gtk_widget_get_style_context(m_widget); GtkBorder pad = { 0, 0, 0, 0 }; gtk_style_context_get_padding(sc, GtkStateFlags(0), &pad); best.x -= pad.left + pad.right; #else gtk_widget_ensure_style(m_widget); int w = PANGO_PIXELS(pango_font_description_get_size(m_widget->style->font_desc)); w &= ~1; if (w < 6) w = 6; best.x = w + 2 * m_widget->style->xthickness; #endif CacheBestSize(best); return best; }