1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/image_gtk.cpp
3 // Author: Paul Cornett
4 // Copyright: (c) 2020 Paul Cornett
5 // Licence: wxWindows licence
6 ///////////////////////////////////////////////////////////////////////////////
7
8 #include "wx/wxprec.h"
9
10 #include "wx/bitmap.h"
11 #include "wx/window.h"
12
13 #include "wx/gtk/private/wrapgtk.h"
14 #include "wx/gtk/private/image.h"
15
16 namespace
17 {
18 // Default provider for HiDPI common case
19 struct BitmapProviderDefault: wxGtkImage::BitmapProvider
20 {
21 #ifdef __WXGTK3__
BitmapProviderDefault__anon7bed05fd0111::BitmapProviderDefault22 BitmapProviderDefault(wxWindow* win) : m_win(win) { }
23 virtual wxBitmap Get() const wxOVERRIDE;
24 virtual void Set(const wxBitmap& bitmap) wxOVERRIDE;
25 wxWindow* const m_win;
26 wxBitmap m_bitmap;
27 wxBitmap m_bitmapDisabled;
28 #else
29 BitmapProviderDefault(wxWindow*) { }
30 virtual wxBitmap Get() const wxOVERRIDE { return wxBitmap(); }
31 #endif
32 };
33
34 #ifdef __WXGTK3__
Get() const35 wxBitmap BitmapProviderDefault::Get() const
36 {
37 return (m_win == NULL || m_win->IsEnabled()) ? m_bitmap : m_bitmapDisabled;
38 }
39
Set(const wxBitmap & bitmap)40 void BitmapProviderDefault::Set(const wxBitmap& bitmap)
41 {
42 m_bitmap.UnRef();
43 m_bitmapDisabled.UnRef();
44 if (bitmap.IsOk() && bitmap.GetScaleFactor() > 1)
45 {
46 m_bitmap = bitmap;
47 if (m_win)
48 m_bitmapDisabled = bitmap.CreateDisabled();
49 }
50 }
51 #endif // __WXGTK3__
52 } // namespace
53
54 extern "C" {
55 static void wxGtkImageClassInit(void* g_class, void* class_data);
56 }
57
Type()58 GType wxGtkImage::Type()
59 {
60 static GType type;
61 if (type == 0)
62 {
63 const GTypeInfo info = {
64 sizeof(GtkImageClass),
65 NULL, NULL,
66 wxGtkImageClassInit, NULL, NULL,
67 sizeof(wxGtkImage), 0, NULL,
68 NULL
69 };
70 type = g_type_register_static(
71 GTK_TYPE_IMAGE, "wxGtkImage", &info, GTypeFlags(0));
72 }
73 return type;
74 }
75
New(BitmapProvider * provider)76 GtkWidget* wxGtkImage::New(BitmapProvider* provider)
77 {
78 wxGtkImage* image = WX_GTK_IMAGE(g_object_new(Type(), NULL));
79 image->m_provider = provider;
80 return GTK_WIDGET(image);
81 }
82
New(wxWindow * win)83 GtkWidget* wxGtkImage::New(wxWindow* win)
84 {
85 return New(new BitmapProviderDefault(win));
86 }
87
Set(const wxBitmap & bitmap)88 void wxGtkImage::Set(const wxBitmap& bitmap)
89 {
90 m_provider->Set(bitmap);
91
92 GdkPixbuf* pixbuf = NULL;
93 GdkPixbuf* pixbufNew = NULL;
94 if (bitmap.IsOk())
95 {
96 if (bitmap.GetScaleFactor() <= 1)
97 pixbuf = bitmap.GetPixbuf();
98 else
99 {
100 // Placeholder pixbuf for correct size
101 pixbufNew =
102 pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8,
103 int(bitmap.GetScaledWidth()), int(bitmap.GetScaledHeight()));
104 }
105 }
106 gtk_image_set_from_pixbuf(GTK_IMAGE(this), pixbuf);
107 if (pixbufNew)
108 g_object_unref(pixbufNew);
109 }
110
111 static GtkWidgetClass* wxGtkImageParentClass;
112
113 extern "C"
114 {
115 #ifdef __WXGTK3__
wxGtkImageDraw(GtkWidget * widget,cairo_t * cr)116 static gboolean wxGtkImageDraw(GtkWidget* widget, cairo_t* cr)
117 #else
118 static gboolean wxGtkImageDraw(GtkWidget* widget, GdkEventExpose* event)
119 #endif
120 {
121 wxGtkImage* image = WX_GTK_IMAGE(widget);
122 const wxBitmap bitmap(image->m_provider->Get());
123 if (!bitmap.IsOk())
124 {
125 #ifdef __WXGTK3__
126 return wxGtkImageParentClass->draw(widget, cr);
127 #else
128 return wxGtkImageParentClass->expose_event(widget, event);
129 #endif
130 }
131
132 GtkAllocation alloc;
133 gtk_widget_get_allocation(widget, &alloc);
134 int x = (alloc.width - int(bitmap.GetScaledWidth() )) / 2;
135 int y = (alloc.height - int(bitmap.GetScaledHeight())) / 2;
136 #ifdef __WXGTK3__
137 gtk_render_background(gtk_widget_get_style_context(widget),
138 cr, 0, 0, alloc.width, alloc.height);
139 bitmap.Draw(cr, x, y);
140 #else
141 x += alloc.x;
142 y += alloc.y;
143 gdk_draw_pixbuf(
144 gtk_widget_get_window(widget), gtk_widget_get_style(widget)->black_gc, bitmap.GetPixbuf(),
145 0, 0, x, y,
146 -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0);
147 #endif
148 return false;
149 }
150
wxGtkImageFinalize(GObject * object)151 static void wxGtkImageFinalize(GObject* object)
152 {
153 wxGtkImage* image = WX_GTK_IMAGE(object);
154 delete image->m_provider;
155 image->m_provider = NULL;
156 G_OBJECT_CLASS(wxGtkImageParentClass)->finalize(object);
157 }
158
wxGtkImageClassInit(void * g_class,void *)159 static void wxGtkImageClassInit(void* g_class, void* /*class_data*/)
160 {
161 #ifdef __WXGTK3__
162 GTK_WIDGET_CLASS(g_class)->draw = wxGtkImageDraw;
163 #else
164 GTK_WIDGET_CLASS(g_class)->expose_event = wxGtkImageDraw;
165 #endif
166 G_OBJECT_CLASS(g_class)->finalize = wxGtkImageFinalize;
167 wxGtkImageParentClass = GTK_WIDGET_CLASS(g_type_class_peek_parent(g_class));
168 }
169 } // extern "C"
170