Allow drawing HiDPI bitmaps with GTK3
1. Override wxWindow::GetContentScaleFactor() to use gdk_window_get_scale_factor() when available, and to use correct scale (1.0) otherwise, as wxDC::GetPPI() (used by overridden method) is not properly implemented for wxGTK 2. Record scale in wxBitmap(wxImage&) ctor and wxBitmap::CreateScaled() 3. Adjust cairo scale for drawing bitmap, and (inversely) for drawing on bitmap
This commit is contained in:
parent
ed09b7b6c0
commit
f95fd11e08
@ -90,7 +90,10 @@ public:
|
||||
{ return Create(sz.GetWidth(), sz.GetHeight(), depth); }
|
||||
bool Create(int width, int height, const wxDC& WXUNUSED(dc))
|
||||
{ return Create(width,height); }
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
virtual bool CreateScaled(int w, int h, int depth, double scale) wxOVERRIDE;
|
||||
virtual double GetScaleFactor() const wxOVERRIDE;
|
||||
#endif
|
||||
|
||||
virtual int GetHeight() const wxOVERRIDE;
|
||||
virtual int GetWidth() const wxOVERRIDE;
|
||||
|
@ -92,6 +92,7 @@ public:
|
||||
|
||||
virtual int GetCharHeight() const wxOVERRIDE;
|
||||
virtual int GetCharWidth() const wxOVERRIDE;
|
||||
virtual double GetContentScaleFactor() const wxOVERRIDE;
|
||||
|
||||
virtual void SetScrollbar( int orient, int pos, int thumbVisible,
|
||||
int range, bool refresh = true ) wxOVERRIDE;
|
||||
|
@ -338,6 +338,7 @@ public:
|
||||
GdkPixbuf* m_pixbufMask;
|
||||
GdkPixbuf* m_pixbufNoMask;
|
||||
cairo_surface_t* m_surface;
|
||||
double m_scaleFactor;
|
||||
#else
|
||||
GdkPixmap *m_pixmap;
|
||||
GdkPixbuf *m_pixbuf;
|
||||
@ -363,6 +364,7 @@ wxBitmapRefData::wxBitmapRefData(int width, int height, int depth)
|
||||
m_pixbufMask = NULL;
|
||||
m_pixbufNoMask = NULL;
|
||||
m_surface = NULL;
|
||||
m_scaleFactor = 1;
|
||||
#else
|
||||
m_pixmap = NULL;
|
||||
m_pixbuf = NULL;
|
||||
@ -590,7 +592,7 @@ static void CopyImageData(
|
||||
|
||||
#if wxUSE_IMAGE
|
||||
#ifdef __WXGTK3__
|
||||
wxBitmap::wxBitmap(const wxImage& image, int depth, double WXUNUSED(scale))
|
||||
wxBitmap::wxBitmap(const wxImage& image, int depth, double scale)
|
||||
{
|
||||
wxCHECK_RET(image.IsOk(), "invalid image");
|
||||
|
||||
@ -602,6 +604,7 @@ wxBitmap::wxBitmap(const wxImage& image, int depth, double WXUNUSED(scale))
|
||||
else if (depth != 1 && depth != 32)
|
||||
depth = 24;
|
||||
wxBitmapRefData* bmpData = new wxBitmapRefData(w, h, depth);
|
||||
bmpData->m_scaleFactor = scale;
|
||||
m_refData = bmpData;
|
||||
GdkPixbuf* pixbuf_dst = gdk_pixbuf_new(GDK_COLORSPACE_RGB, depth == 32, 8, w, h);
|
||||
bmpData->m_pixbufNoMask = pixbuf_dst;
|
||||
@ -970,6 +973,18 @@ bool wxBitmap::CopyFromIcon(const wxIcon& icon)
|
||||
}
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
bool wxBitmap::CreateScaled(int w, int h, int depth, double scale)
|
||||
{
|
||||
Create(int(w * scale), int(h * scale), depth);
|
||||
M_BMPDATA->m_scaleFactor = scale;
|
||||
return true;
|
||||
}
|
||||
|
||||
double wxBitmap::GetScaleFactor() const
|
||||
{
|
||||
return M_BMPDATA->m_scaleFactor;
|
||||
}
|
||||
|
||||
static cairo_surface_t* GetSubSurface(cairo_surface_t* surface, const wxRect& rect)
|
||||
{
|
||||
cairo_surface_flush(surface);
|
||||
@ -1008,6 +1023,7 @@ wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
|
||||
ret.m_refData = newRef;
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
newRef->m_scaleFactor = bmpData->m_scaleFactor;
|
||||
if (bmpData->m_pixbufNoMask)
|
||||
{
|
||||
GdkPixbuf* pixbuf = gdk_pixbuf_new_subpixbuf(bmpData->m_pixbufNoMask, rect.x, rect.y, w, h);
|
||||
@ -1318,6 +1334,8 @@ cairo_t* wxBitmap::CairoCreate() const
|
||||
bmpData->m_pixbufMask = NULL;
|
||||
}
|
||||
wxASSERT(cr && cairo_status(cr) == 0);
|
||||
if (!wxIsSameDouble(bmpData->m_scaleFactor, 1))
|
||||
cairo_scale(cr, bmpData->m_scaleFactor, bmpData->m_scaleFactor);
|
||||
return cr;
|
||||
}
|
||||
|
||||
@ -1326,6 +1344,14 @@ void wxBitmap::Draw(cairo_t* cr, int x, int y, bool useMask, const wxColour* fg,
|
||||
wxCHECK_RET(IsOk(), "invalid bitmap");
|
||||
|
||||
wxBitmapRefData* bmpData = M_BMPDATA;
|
||||
if (!wxIsSameDouble(bmpData->m_scaleFactor, 1))
|
||||
{
|
||||
cairo_translate(cr, x, y);
|
||||
const double scale = 1 / bmpData->m_scaleFactor;
|
||||
cairo_scale(cr, scale, scale);
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
SetSourceSurface(cr, x, y, fg, bg);
|
||||
cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST);
|
||||
cairo_surface_t* mask = NULL;
|
||||
@ -1490,6 +1516,7 @@ wxGDIRefData* wxBitmap::CloneGDIRefData(const wxGDIRefData* data) const
|
||||
oldRef->m_height,
|
||||
oldRef->m_bpp);
|
||||
#ifdef __WXGTK3__
|
||||
newRef->m_scaleFactor = oldRef->m_scaleFactor;
|
||||
if (oldRef->m_pixbufNoMask)
|
||||
newRef->m_pixbufNoMask = gdk_pixbuf_copy(oldRef->m_pixbufNoMask);
|
||||
if (oldRef->m_surface)
|
||||
|
@ -343,8 +343,8 @@ void wxMemoryDCImpl::Setup()
|
||||
m_ok = m_bitmap.IsOk();
|
||||
if (m_ok)
|
||||
{
|
||||
m_width = m_bitmap.GetWidth();
|
||||
m_height = m_bitmap.GetHeight();
|
||||
m_width = int(m_bitmap.GetScaledWidth());
|
||||
m_height = int(m_bitmap.GetScaledHeight());
|
||||
cairo_t* cr = m_bitmap.CairoCreate();
|
||||
gc = wxGraphicsContext::CreateFromNative(cr);
|
||||
gc->EnableOffset(true);
|
||||
|
@ -3471,6 +3471,20 @@ void wxWindowGTK::DoGetTextExtent( const wxString& string,
|
||||
txm.GetTextExtent(string, x, y, descent, externalLeading);
|
||||
}
|
||||
|
||||
double wxWindowGTK::GetContentScaleFactor() const
|
||||
{
|
||||
double scaleFactor = 1;
|
||||
#if GTK_CHECK_VERSION(3,10,0)
|
||||
if (m_widget && gtk_check_version(3,10,0) == NULL)
|
||||
{
|
||||
GdkWindow* window = gtk_widget_get_window(m_widget);
|
||||
if (window)
|
||||
scaleFactor = gdk_window_get_scale_factor(window);
|
||||
}
|
||||
#endif
|
||||
return scaleFactor;
|
||||
}
|
||||
|
||||
void wxWindowGTK::GTKDisableFocusOutEvent()
|
||||
{
|
||||
g_signal_handlers_block_by_func( m_focusWidget,
|
||||
|
Loading…
Reference in New Issue
Block a user