Files
wxWidgets/src/gtk/image_gtk.cpp
Vadim Zeitlin a81e0d83c1 Use wxBitmap::GetLogicalXXX() instead of GetScaledXXX()
Replace old functions with the new ones in the library code itself.

Note that wxSTC and wxRichText still use GetScaledXXX(), but they're
different functions that might need to be renamed/dealt with separately.
2022-01-22 18:57:31 +00:00

196 lines
5.3 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: src/gtk/image_gtk.cpp
// Author: Paul Cornett
// Copyright: (c) 2020 Paul Cornett
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/window.h"
#include "wx/gtk/private/wrapgtk.h"
#include "wx/gtk/private/image.h"
namespace
{
#ifdef __WXGTK3__
// Default provider for HiDPI common case
struct BitmapProviderDefault: wxGtkImage::BitmapProvider
{
BitmapProviderDefault(wxWindow* win) : m_win(win) { }
virtual double GetScale() const wxOVERRIDE;
virtual wxBitmap Get() const wxOVERRIDE;
virtual void Set(const wxBitmapBundle& bitmap) wxOVERRIDE;
// This pointer can be null if there is no associated window.
wxWindow* const m_win;
// All the bitmaps we use.
wxBitmapBundle m_bitmapBundle;
// This bitmap is created on demand from m_bitmapBundle when necessary (and
// is mutable because this is done in const Get()).
mutable wxBitmap m_bitmapDisabled;
};
double BitmapProviderDefault::GetScale() const
{
return m_win ? m_win->GetDPIScaleFactor() : 1.0;
}
wxBitmap BitmapProviderDefault::Get() const
{
if ( m_win && !m_win->IsEnabled() )
{
if ( !m_bitmapDisabled.IsOk() && m_bitmapBundle.IsOk() )
m_bitmapDisabled = GetAtScale(m_bitmapBundle).CreateDisabled();
return m_bitmapDisabled;
}
// We currently don't return the bitmap we use from here when scale is 1,
// as then we can just let GtkImage draw the bitmap it has.
return IsScaled() ? GetAtScale(m_bitmapBundle) : wxBitmap();
}
void BitmapProviderDefault::Set(const wxBitmapBundle& bitmapBundle)
{
m_bitmapBundle = bitmapBundle;
// Ensure it's recreated if needed later.
m_bitmapDisabled.UnRef();
}
#else // !__WXGTK3__
// Trivial version for GTK < 3 which doesn't provide any high DPI support.
struct BitmapProviderDefault: wxGtkImage::BitmapProvider
{
BitmapProviderDefault(wxWindow*) { }
virtual double GetScale() const wxOVERRIDE { return 1.0; }
virtual wxBitmap Get() const wxOVERRIDE { return wxBitmap(); }
};
#endif // __WXGTK3__/!__WXGTK3__
} // namespace
extern "C" {
static void wxGtkImageClassInit(void* g_class, void* class_data);
}
GType wxGtkImage::Type()
{
static GType type;
if (type == 0)
{
const GTypeInfo info = {
sizeof(GtkImageClass),
NULL, NULL,
wxGtkImageClassInit, NULL, NULL,
sizeof(wxGtkImage), 0, NULL,
NULL
};
type = g_type_register_static(
GTK_TYPE_IMAGE, "wxGtkImage", &info, GTypeFlags(0));
}
return type;
}
GtkWidget* wxGtkImage::New(BitmapProvider* provider)
{
wxGtkImage* image = WX_GTK_IMAGE(g_object_new(Type(), NULL));
image->m_provider = provider;
return GTK_WIDGET(image);
}
GtkWidget* wxGtkImage::New(wxWindow* win)
{
return New(new BitmapProviderDefault(win));
}
void wxGtkImage::Set(const wxBitmapBundle& bitmapBundle)
{
m_provider->Set(bitmapBundle);
// Always set the default bitmap to use the correct size, even if we draw a
// different bitmap below.
wxBitmap bitmap = bitmapBundle.GetBitmap(wxDefaultSize);
GdkPixbuf* pixbuf = NULL;
if (bitmap.IsOk())
{
pixbuf = bitmap.GetPixbuf();
}
gtk_image_set_from_pixbuf(GTK_IMAGE(this), pixbuf);
}
static GtkWidgetClass* wxGtkImageParentClass;
extern "C"
{
#ifdef __WXGTK3__
static gboolean wxGtkImageDraw(GtkWidget* widget, cairo_t* cr)
#else
static gboolean wxGtkImageDraw(GtkWidget* widget, GdkEventExpose* event)
#endif
{
wxGtkImage* image = WX_GTK_IMAGE(widget);
const wxBitmap bitmap(image->m_provider->Get());
if (!bitmap.IsOk())
{
// Just let GtkImage draw the bitmap in standard DPI. Arguably, we
// should still be drawing it ourselves even in this case just for
// consistency, but for now keep the original behaviour.
#ifdef __WXGTK3__
return wxGtkImageParentClass->draw(widget, cr);
#else
return wxGtkImageParentClass->expose_event(widget, event);
#endif
}
GtkAllocation alloc;
gtk_widget_get_allocation(widget, &alloc);
int x = (alloc.width - int(bitmap.GetLogicalWidth() )) / 2;
int y = (alloc.height - int(bitmap.GetLogicalHeight())) / 2;
#ifdef __WXGTK3__
gtk_render_background(gtk_widget_get_style_context(widget),
cr, 0, 0, alloc.width, alloc.height);
bitmap.Draw(cr, x, y);
#else
x += alloc.x;
y += alloc.y;
gdk_draw_pixbuf(
gtk_widget_get_window(widget), gtk_widget_get_style(widget)->black_gc, bitmap.GetPixbuf(),
0, 0, x, y,
-1, -1, GDK_RGB_DITHER_NORMAL, 0, 0);
#endif
return false;
}
static void wxGtkImageFinalize(GObject* object)
{
wxGtkImage* image = WX_GTK_IMAGE(object);
delete image->m_provider;
image->m_provider = NULL;
G_OBJECT_CLASS(wxGtkImageParentClass)->finalize(object);
}
static void wxGtkImageClassInit(void* g_class, void* /*class_data*/)
{
#ifdef __WXGTK3__
GTK_WIDGET_CLASS(g_class)->draw = wxGtkImageDraw;
#else
GTK_WIDGET_CLASS(g_class)->expose_event = wxGtkImageDraw;
#endif
G_OBJECT_CLASS(g_class)->finalize = wxGtkImageFinalize;
wxGtkImageParentClass = GTK_WIDGET_CLASS(g_type_class_peek_parent(g_class));
}
} // extern "C"