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); }
|
{ return Create(sz.GetWidth(), sz.GetHeight(), depth); }
|
||||||
bool Create(int width, int height, const wxDC& WXUNUSED(dc))
|
bool Create(int width, int height, const wxDC& WXUNUSED(dc))
|
||||||
{ return Create(width,height); }
|
{ 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 GetHeight() const wxOVERRIDE;
|
||||||
virtual int GetWidth() const wxOVERRIDE;
|
virtual int GetWidth() const wxOVERRIDE;
|
||||||
|
@ -92,6 +92,7 @@ public:
|
|||||||
|
|
||||||
virtual int GetCharHeight() const wxOVERRIDE;
|
virtual int GetCharHeight() const wxOVERRIDE;
|
||||||
virtual int GetCharWidth() const wxOVERRIDE;
|
virtual int GetCharWidth() const wxOVERRIDE;
|
||||||
|
virtual double GetContentScaleFactor() const wxOVERRIDE;
|
||||||
|
|
||||||
virtual void SetScrollbar( int orient, int pos, int thumbVisible,
|
virtual void SetScrollbar( int orient, int pos, int thumbVisible,
|
||||||
int range, bool refresh = true ) wxOVERRIDE;
|
int range, bool refresh = true ) wxOVERRIDE;
|
||||||
|
@ -338,6 +338,7 @@ public:
|
|||||||
GdkPixbuf* m_pixbufMask;
|
GdkPixbuf* m_pixbufMask;
|
||||||
GdkPixbuf* m_pixbufNoMask;
|
GdkPixbuf* m_pixbufNoMask;
|
||||||
cairo_surface_t* m_surface;
|
cairo_surface_t* m_surface;
|
||||||
|
double m_scaleFactor;
|
||||||
#else
|
#else
|
||||||
GdkPixmap *m_pixmap;
|
GdkPixmap *m_pixmap;
|
||||||
GdkPixbuf *m_pixbuf;
|
GdkPixbuf *m_pixbuf;
|
||||||
@ -363,6 +364,7 @@ wxBitmapRefData::wxBitmapRefData(int width, int height, int depth)
|
|||||||
m_pixbufMask = NULL;
|
m_pixbufMask = NULL;
|
||||||
m_pixbufNoMask = NULL;
|
m_pixbufNoMask = NULL;
|
||||||
m_surface = NULL;
|
m_surface = NULL;
|
||||||
|
m_scaleFactor = 1;
|
||||||
#else
|
#else
|
||||||
m_pixmap = NULL;
|
m_pixmap = NULL;
|
||||||
m_pixbuf = NULL;
|
m_pixbuf = NULL;
|
||||||
@ -590,7 +592,7 @@ static void CopyImageData(
|
|||||||
|
|
||||||
#if wxUSE_IMAGE
|
#if wxUSE_IMAGE
|
||||||
#ifdef __WXGTK3__
|
#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");
|
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)
|
else if (depth != 1 && depth != 32)
|
||||||
depth = 24;
|
depth = 24;
|
||||||
wxBitmapRefData* bmpData = new wxBitmapRefData(w, h, depth);
|
wxBitmapRefData* bmpData = new wxBitmapRefData(w, h, depth);
|
||||||
|
bmpData->m_scaleFactor = scale;
|
||||||
m_refData = bmpData;
|
m_refData = bmpData;
|
||||||
GdkPixbuf* pixbuf_dst = gdk_pixbuf_new(GDK_COLORSPACE_RGB, depth == 32, 8, w, h);
|
GdkPixbuf* pixbuf_dst = gdk_pixbuf_new(GDK_COLORSPACE_RGB, depth == 32, 8, w, h);
|
||||||
bmpData->m_pixbufNoMask = pixbuf_dst;
|
bmpData->m_pixbufNoMask = pixbuf_dst;
|
||||||
@ -970,6 +973,18 @@ bool wxBitmap::CopyFromIcon(const wxIcon& icon)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __WXGTK3__
|
#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)
|
static cairo_surface_t* GetSubSurface(cairo_surface_t* surface, const wxRect& rect)
|
||||||
{
|
{
|
||||||
cairo_surface_flush(surface);
|
cairo_surface_flush(surface);
|
||||||
@ -1008,6 +1023,7 @@ wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
|
|||||||
ret.m_refData = newRef;
|
ret.m_refData = newRef;
|
||||||
|
|
||||||
#ifdef __WXGTK3__
|
#ifdef __WXGTK3__
|
||||||
|
newRef->m_scaleFactor = bmpData->m_scaleFactor;
|
||||||
if (bmpData->m_pixbufNoMask)
|
if (bmpData->m_pixbufNoMask)
|
||||||
{
|
{
|
||||||
GdkPixbuf* pixbuf = gdk_pixbuf_new_subpixbuf(bmpData->m_pixbufNoMask, rect.x, rect.y, w, h);
|
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;
|
bmpData->m_pixbufMask = NULL;
|
||||||
}
|
}
|
||||||
wxASSERT(cr && cairo_status(cr) == 0);
|
wxASSERT(cr && cairo_status(cr) == 0);
|
||||||
|
if (!wxIsSameDouble(bmpData->m_scaleFactor, 1))
|
||||||
|
cairo_scale(cr, bmpData->m_scaleFactor, bmpData->m_scaleFactor);
|
||||||
return cr;
|
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");
|
wxCHECK_RET(IsOk(), "invalid bitmap");
|
||||||
|
|
||||||
wxBitmapRefData* bmpData = M_BMPDATA;
|
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);
|
SetSourceSurface(cr, x, y, fg, bg);
|
||||||
cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST);
|
cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST);
|
||||||
cairo_surface_t* mask = NULL;
|
cairo_surface_t* mask = NULL;
|
||||||
@ -1490,6 +1516,7 @@ wxGDIRefData* wxBitmap::CloneGDIRefData(const wxGDIRefData* data) const
|
|||||||
oldRef->m_height,
|
oldRef->m_height,
|
||||||
oldRef->m_bpp);
|
oldRef->m_bpp);
|
||||||
#ifdef __WXGTK3__
|
#ifdef __WXGTK3__
|
||||||
|
newRef->m_scaleFactor = oldRef->m_scaleFactor;
|
||||||
if (oldRef->m_pixbufNoMask)
|
if (oldRef->m_pixbufNoMask)
|
||||||
newRef->m_pixbufNoMask = gdk_pixbuf_copy(oldRef->m_pixbufNoMask);
|
newRef->m_pixbufNoMask = gdk_pixbuf_copy(oldRef->m_pixbufNoMask);
|
||||||
if (oldRef->m_surface)
|
if (oldRef->m_surface)
|
||||||
|
@ -343,8 +343,8 @@ void wxMemoryDCImpl::Setup()
|
|||||||
m_ok = m_bitmap.IsOk();
|
m_ok = m_bitmap.IsOk();
|
||||||
if (m_ok)
|
if (m_ok)
|
||||||
{
|
{
|
||||||
m_width = m_bitmap.GetWidth();
|
m_width = int(m_bitmap.GetScaledWidth());
|
||||||
m_height = m_bitmap.GetHeight();
|
m_height = int(m_bitmap.GetScaledHeight());
|
||||||
cairo_t* cr = m_bitmap.CairoCreate();
|
cairo_t* cr = m_bitmap.CairoCreate();
|
||||||
gc = wxGraphicsContext::CreateFromNative(cr);
|
gc = wxGraphicsContext::CreateFromNative(cr);
|
||||||
gc->EnableOffset(true);
|
gc->EnableOffset(true);
|
||||||
|
@ -3471,6 +3471,20 @@ void wxWindowGTK::DoGetTextExtent( const wxString& string,
|
|||||||
txm.GetTextExtent(string, x, y, descent, externalLeading);
|
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()
|
void wxWindowGTK::GTKDisableFocusOutEvent()
|
||||||
{
|
{
|
||||||
g_signal_handlers_block_by_func( m_focusWidget,
|
g_signal_handlers_block_by_func( m_focusWidget,
|
||||||
|
Loading…
Reference in New Issue
Block a user