diff --git a/include/wx/gtk/bitmap.h b/include/wx/gtk/bitmap.h index ed5b731bda..3b3cf99cff 100644 --- a/include/wx/gtk/bitmap.h +++ b/include/wx/gtk/bitmap.h @@ -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; diff --git a/include/wx/gtk/window.h b/include/wx/gtk/window.h index bfaa707cae..9f912fd57c 100644 --- a/include/wx/gtk/window.h +++ b/include/wx/gtk/window.h @@ -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; diff --git a/src/gtk/bitmap.cpp b/src/gtk/bitmap.cpp index 38a3416167..5e57df7410 100644 --- a/src/gtk/bitmap.cpp +++ b/src/gtk/bitmap.cpp @@ -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) diff --git a/src/gtk/dc.cpp b/src/gtk/dc.cpp index 7d13a2f689..92aa308207 100644 --- a/src/gtk/dc.cpp +++ b/src/gtk/dc.cpp @@ -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); diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index ba5afaabc2..7967cb1c9a 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -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,