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

View File

@ -21,8 +21,11 @@
#include <wx/wfstream.h>
#include <wx/imaglist.h>
#include "MSWstuff.h"
#include "Resources/EmbeddedImage.h"
#include "Resources/BackgroundLogo.h"
#include "Resources/ButtonIcon_Camera.h"
#include "Resources/ConfigIcon_Cpu.h"
#include "Resources/ConfigIcon_Video.h"
@ -144,17 +147,42 @@ const wxBitmap& Pcsx2App::GetLogoBitmap()
wxImage img;
EmbeddedImage<res_BackgroundLogo> temp; // because gcc can't allow non-const temporaries.
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;
}
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()
{
ScopedPtr<wxImageList>& images( GetResourceCache().ConfigImages );
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;
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
// 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
#define FancyLoadMacro( name ) \
{ \
EmbeddedImage<res_ConfigIcon_##name> temp( g_Conf->Listbook_ImageSize, g_Conf->Listbook_ImageSize ); \
m_Resources->ImageId.Config.name = images->Add( LoadImageAny( \
img, useTheme, mess, L"ConfigIcon_" wxT(#name), temp ) \
); \
EmbeddedImage<res_ConfigIcon_##name> temp; \
LoadImageAny(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 );
@ -190,6 +223,7 @@ wxImageList& Pcsx2App::GetImgList_Config()
return *images;
}
// This stuff seems unused?
wxImageList& Pcsx2App::GetImgList_Toolbars()
{
ScopedPtr<wxImageList>& images( GetResourceCache().ToolbarImages );

View File

@ -22,9 +22,6 @@
#include "ModalPopups.h"
#include "Panels/ConfigurationPanels.h"
#include "Resources/EmbeddedImage.h"
#include "Resources/ButtonIcon_Camera.h"
#include <wx/artprov.h>
#include <wx/filepicker.h>
#include <wx/listbook.h>
@ -187,7 +184,7 @@ void Dialogs::BaseConfigurationDialog::AddOkCancel( wxSizer* sizer )
if( wxWindow* apply = FindWindow( wxID_APPLY ) ) apply->Disable();
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.") );
*m_extraButtonSizer += screenshotButton|pxMiddle;

View File

@ -28,11 +28,13 @@ void MSW_SetWindowAfter( WXWidget hwnd, WXWidget hwndAfter )
#endif
}
// Text scales automatically on Windows but that's about it. The dialog widths
// and images need to be scaled manually.
float MSW_GetDPIScale()
{
#ifdef __WXMSW__
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);
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;
if( PCSX2_isReleaseVersion )
@ -385,6 +387,10 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
wxBoxSizer& joe( *new wxBoxSizer( wxVERTICAL ) );
joe.Add( &m_background );
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)
if( g_Conf->MainGuiPosition == wxDefaultPosition || !pxIsValidWindowPosition( *this, g_Conf->MainGuiPosition) )

View File

@ -26,8 +26,7 @@ class IEmbeddedImage
{
public:
virtual const wxImage& Get()=0;
virtual wxImage Rescale( int width, int height )=0;
virtual wxImage Resample( int width, int height )=0;
virtual wxImage Scale( int width, int height )=0;
};
//////////////////////////////////////////////////////////////////////////////////////////
@ -59,7 +58,7 @@ protected:
m_Image.LoadFile( joe, ImageType::GetFormat() );
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
// is left unmodified). Useful for creating ugly versions of otherwise nice graphics. Do
// us all a favor and use Resample() instead.
// is left unmodified).
//
// (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;
}
// ------------------------------------------------------------------------
// 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 )
wxImage Scale( int width, int height )
{
_loadImage();
// Not strictly necessary - wxWidgets does the dimensions check anyway.
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
return m_Image;
}