Merge pull request #807 from turtleli/windows-dpi-image-scaling

Scale images according to DPI (Windows)
Partially fix theming
This commit is contained in:
Jonathan Li 2015-09-19 10:31:53 +01:00
commit e576f259e4
6 changed files with 59 additions and 35 deletions

View File

@ -242,6 +242,7 @@ public:
ScopedPtr<wxImageList> ToolbarImages; ScopedPtr<wxImageList> ToolbarImages;
ScopedPtr<wxIconBundle> IconBundle; ScopedPtr<wxIconBundle> IconBundle;
ScopedPtr<wxBitmap> Bitmap_Logo; ScopedPtr<wxBitmap> Bitmap_Logo;
ScopedPtr<wxBitmap> ScreenshotBitmap;
ScopedPtr<AppGameDatabase> GameDB; ScopedPtr<AppGameDatabase> GameDB;
pxAppResources(); pxAppResources();
@ -559,6 +560,7 @@ public:
pxAppResources& GetResourceCache(); pxAppResources& GetResourceCache();
const wxIconBundle& GetIconBundle(); const wxIconBundle& GetIconBundle();
const wxBitmap& GetLogoBitmap(); const wxBitmap& GetLogoBitmap();
const wxBitmap& GetScreenshotBitmap();
wxImageList& GetImgList_Config(); wxImageList& GetImgList_Config();
wxImageList& GetImgList_Toolbars(); wxImageList& GetImgList_Toolbars();

View File

@ -21,8 +21,11 @@
#include <wx/wfstream.h> #include <wx/wfstream.h>
#include <wx/imaglist.h> #include <wx/imaglist.h>
#include "MSWstuff.h"
#include "Resources/EmbeddedImage.h" #include "Resources/EmbeddedImage.h"
#include "Resources/BackgroundLogo.h" #include "Resources/BackgroundLogo.h"
#include "Resources/ButtonIcon_Camera.h"
#include "Resources/ConfigIcon_Cpu.h" #include "Resources/ConfigIcon_Cpu.h"
#include "Resources/ConfigIcon_Video.h" #include "Resources/ConfigIcon_Video.h"
@ -144,17 +147,42 @@ const wxBitmap& Pcsx2App::GetLogoBitmap()
wxImage img; wxImage img;
EmbeddedImage<res_BackgroundLogo> temp; // because gcc can't allow non-const temporaries. EmbeddedImage<res_BackgroundLogo> temp; // because gcc can't allow non-const temporaries.
LoadImageAny( img, useTheme, mess, L"BackgroundLogo", temp ); LoadImageAny( img, useTheme, mess, L"BackgroundLogo", temp );
logo = new wxBitmap( img ); float scale = MSW_GetDPIScale(); // 1.0 for non-Windows
logo = new wxBitmap(img.Scale(img.GetWidth() * scale, img.GetHeight() * scale, wxIMAGE_QUALITY_HIGH));
return *logo; return *logo;
} }
const wxBitmap& Pcsx2App::GetScreenshotBitmap()
{
ScopedPtr<wxBitmap>& screenshot(GetResourceCache().ScreenshotBitmap);
if (screenshot) return *screenshot;
wxFileName mess;
bool useTheme = (g_Conf->DeskTheme != L"default");
if (useTheme)
{
wxDirName theme(PathDefs::GetThemes() + g_Conf->DeskTheme);
mess = theme.ToString();
}
wxImage img;
EmbeddedImage<res_ButtonIcon_Camera> temp; // because gcc can't allow non-const temporaries.
LoadImageAny(img, useTheme, mess, L"ButtonIcon_Camera", temp);
float scale = MSW_GetDPIScale(); // 1.0 for non-Windows
screenshot = new wxBitmap(img.Scale(img.GetWidth() * scale, img.GetHeight() * scale, wxIMAGE_QUALITY_HIGH));
return *screenshot;
}
wxImageList& Pcsx2App::GetImgList_Config() wxImageList& Pcsx2App::GetImgList_Config()
{ {
ScopedPtr<wxImageList>& images( GetResourceCache().ConfigImages ); ScopedPtr<wxImageList>& images( GetResourceCache().ConfigImages );
if( !images ) if( !images )
{ {
images = new wxImageList(32, 32); int image_size = MSW_GetDPIScale() * g_Conf->Listbook_ImageSize;
images = new wxImageList(image_size, image_size);
wxFileName mess; wxFileName mess;
bool useTheme = (g_Conf->DeskTheme != L"default"); bool useTheme = (g_Conf->DeskTheme != L"default");
@ -168,14 +196,19 @@ wxImageList& Pcsx2App::GetImgList_Config()
// GCC Specific: wxT() macro is required when using string token pasting. For some // GCC Specific: wxT() macro is required when using string token pasting. For some
// reason L generates syntax errors. >_< // reason L generates syntax errors. >_<
// TODO: This can be fixed with something like
// #define L_STR(x) L_STR2(x)
// #define L_STR2(x) L ## x
// but it's probably best to do it everywhere at once. wxWidgets
// recommends not to use it since v2.9.0.
#undef FancyLoadMacro #undef FancyLoadMacro
#define FancyLoadMacro( name ) \ #define FancyLoadMacro( name ) \
{ \ { \
EmbeddedImage<res_ConfigIcon_##name> temp( g_Conf->Listbook_ImageSize, g_Conf->Listbook_ImageSize ); \ EmbeddedImage<res_ConfigIcon_##name> temp; \
m_Resources->ImageId.Config.name = images->Add( LoadImageAny( \ LoadImageAny(img, useTheme, mess, L"ConfigIcon_" wxT(#name), temp); \
img, useTheme, mess, L"ConfigIcon_" wxT(#name), temp ) \ img.Rescale(image_size, image_size, wxIMAGE_QUALITY_HIGH); \
); \ m_Resources->ImageId.Config.name = images->Add(img); \
} }
FancyLoadMacro( Paths ); FancyLoadMacro( Paths );
@ -190,6 +223,7 @@ wxImageList& Pcsx2App::GetImgList_Config()
return *images; return *images;
} }
// This stuff seems unused?
wxImageList& Pcsx2App::GetImgList_Toolbars() wxImageList& Pcsx2App::GetImgList_Toolbars()
{ {
ScopedPtr<wxImageList>& images( GetResourceCache().ToolbarImages ); ScopedPtr<wxImageList>& images( GetResourceCache().ToolbarImages );

View File

@ -22,9 +22,6 @@
#include "ModalPopups.h" #include "ModalPopups.h"
#include "Panels/ConfigurationPanels.h" #include "Panels/ConfigurationPanels.h"
#include "Resources/EmbeddedImage.h"
#include "Resources/ButtonIcon_Camera.h"
#include <wx/artprov.h> #include <wx/artprov.h>
#include <wx/filepicker.h> #include <wx/filepicker.h>
#include <wx/listbook.h> #include <wx/listbook.h>
@ -187,7 +184,7 @@ void Dialogs::BaseConfigurationDialog::AddOkCancel( wxSizer* sizer )
if( wxWindow* apply = FindWindow( wxID_APPLY ) ) apply->Disable(); if( wxWindow* apply = FindWindow( wxID_APPLY ) ) apply->Disable();
SomethingChanged_StateModified_IsChanged(); SomethingChanged_StateModified_IsChanged();
wxBitmapButton& screenshotButton( *new wxBitmapButton( this, wxID_SAVE, EmbeddedImage<res_ButtonIcon_Camera>().Get() ) ); wxBitmapButton& screenshotButton(*new wxBitmapButton(this, wxID_SAVE, wxGetApp().GetScreenshotBitmap()));
screenshotButton.SetToolTip( _("Saves a snapshot of this settings panel to a PNG file.") ); screenshotButton.SetToolTip( _("Saves a snapshot of this settings panel to a PNG file.") );
*m_extraButtonSizer += screenshotButton|pxMiddle; *m_extraButtonSizer += screenshotButton|pxMiddle;

View File

@ -28,11 +28,13 @@ void MSW_SetWindowAfter( WXWidget hwnd, WXWidget hwndAfter )
#endif #endif
} }
// Text scales automatically on Windows but that's about it. The dialog widths
// and images need to be scaled manually.
float MSW_GetDPIScale() float MSW_GetDPIScale()
{ {
#ifdef __WXMSW__ #ifdef __WXMSW__
HDC screen = GetDC(0); HDC screen = GetDC(0);
float scale = GetDeviceCaps(screen, LOGPIXELSX) / 96.0; float scale = GetDeviceCaps(screen, LOGPIXELSX) / 96.0; // 96.0 dpi = 100% scale
ReleaseDC(NULL, screen); ReleaseDC(NULL, screen);
return scale; return scale;

View File

@ -348,7 +348,9 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
wxSize backsize( m_background.GetSize() ); // The background logo and its window size are different on Windows. Use the
// background logo size, which is what it'll eventually be resized to.
wxSize backsize(m_background.GetBitmap().GetWidth(), m_background.GetBitmap().GetHeight());
wxString wintitle; wxString wintitle;
if( PCSX2_isReleaseVersion ) if( PCSX2_isReleaseVersion )
@ -385,6 +387,10 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
wxBoxSizer& joe( *new wxBoxSizer( wxVERTICAL ) ); wxBoxSizer& joe( *new wxBoxSizer( wxVERTICAL ) );
joe.Add( &m_background ); joe.Add( &m_background );
SetSizerAndFit( &joe ); SetSizerAndFit( &joe );
// Makes no sense, but this is needed for the window size to be correct for
// 200% DPI on Windows. The SetSizerAndFit is supposed to be doing the exact
// same thing.
GetSizer()->SetSizeHints(this);
// Use default window position if the configured windowpos is invalid (partially offscreen) // Use default window position if the configured windowpos is invalid (partially offscreen)
if( g_Conf->MainGuiPosition == wxDefaultPosition || !pxIsValidWindowPosition( *this, g_Conf->MainGuiPosition) ) if( g_Conf->MainGuiPosition == wxDefaultPosition || !pxIsValidWindowPosition( *this, g_Conf->MainGuiPosition) )

View File

@ -26,8 +26,7 @@ class IEmbeddedImage
{ {
public: public:
virtual const wxImage& Get()=0; virtual const wxImage& Get()=0;
virtual wxImage Rescale( int width, int height )=0; virtual wxImage Scale( int width, int height )=0;
virtual wxImage Resample( int width, int height )=0;
}; };
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -59,7 +58,7 @@ protected:
m_Image.LoadFile( joe, ImageType::GetFormat() ); m_Image.LoadFile( joe, ImageType::GetFormat() );
if( m_ResampleTo.IsFullySpecified() && ( m_ResampleTo.GetWidth() != m_Image.GetWidth() || m_ResampleTo.GetHeight() != m_Image.GetHeight() ) ) if( m_ResampleTo.IsFullySpecified() && ( m_ResampleTo.GetWidth() != m_Image.GetWidth() || m_ResampleTo.GetHeight() != m_Image.GetHeight() ) )
m_Image = m_Image.ResampleBox( m_ResampleTo.GetWidth(), m_ResampleTo.GetHeight() ); m_Image.Rescale( m_ResampleTo.GetWidth(), m_ResampleTo.GetHeight(), wxIMAGE_QUALITY_HIGH );
} }
} }
@ -107,31 +106,15 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Performs a pixel resize of the loaded image and returns a new image handle (EmbeddedImage // Performs a pixel resize of the loaded image and returns a new image handle (EmbeddedImage
// is left unmodified). Useful for creating ugly versions of otherwise nice graphics. Do // is left unmodified).
// us all a favor and use Resample() instead.
// //
// (this method included for sake of completeness only).
//
wxImage Rescale( int width, int height )
{
_loadImage();
if( width != m_Image.GetWidth() || height != m_Image.GetHeight() )
return m_Image.Rescale( width, height );
else
return m_Image;
}
// ------------------------------------------------------------------------ wxImage Scale( int width, int height )
// Implementation Note: This function uses wxWidgets ResampleBox method to resize the image.
// wxWidgets ResampleBicubic appears to be buggy and produces fairly poor results when down-
// sampling images (basically resembles a pixel resize). ResampleBox produces much cleaner
// results.
//
wxImage Resample( int width, int height )
{ {
_loadImage(); _loadImage();
// Not strictly necessary - wxWidgets does the dimensions check anyway.
if( width != m_Image.GetWidth() || height != m_Image.GetHeight() ) if( width != m_Image.GetWidth() || height != m_Image.GetHeight() )
return m_Image.ResampleBox( width, height ); return m_Image.Scale( width, height, wxIMAGE_QUALITY_HIGH );
else else
return m_Image; return m_Image;
} }