Initial commit for real hidpi support
Note: This commit has only been tested on MacOS Changes: - Icons now use the native hidpi support from Gtk (through Icon Theme) - Icons are now directly generated from scalable file (i.e. SVG file) - Widget sizes are scaled based on DPI and scale factor - Font size is scaled based on DPI and scale factor
This commit is contained in:
201
rtgui/rtimage.cc
201
rtgui/rtimage.cc
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
* Copyright (c) 2018 Jean-Christophe FRISCH <natureh.510@gmail.com>
|
||||
* Copyright (c) 2022 Pierre CABRERA <pierre.cab@gmail.com>
|
||||
*
|
||||
* RawTherapee is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,205 +21,21 @@
|
||||
|
||||
#include "rtimage.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
#include "../rtengine/settings.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
std::map<std::string, Glib::RefPtr<Gdk::Pixbuf> > pixbufCache;
|
||||
std::map<std::string, Cairo::RefPtr<Cairo::ImageSurface> > surfaceCache;
|
||||
|
||||
}
|
||||
|
||||
double RTImage::dpiBack = 0.;
|
||||
int RTImage::scaleBack = 0;
|
||||
|
||||
RTImage::RTImage () {}
|
||||
|
||||
RTImage::RTImage (RTImage &other) : surface(other.surface), pixbuf(other.pixbuf)
|
||||
RTImage::RTImage (const Glib::ustring& iconName, const Gtk::IconSize iconSize) :
|
||||
Gtk::Image(iconName, iconSize),
|
||||
size(iconSize)
|
||||
{
|
||||
if (pixbuf) {
|
||||
set(pixbuf);
|
||||
} else if (surface) {
|
||||
set(surface);
|
||||
}
|
||||
}
|
||||
|
||||
RTImage::RTImage (const Glib::ustring& fileName, const Glib::ustring& rtlFileName) : Gtk::Image()
|
||||
void RTImage::set_from_icon_name(const Glib::ustring& iconName)
|
||||
{
|
||||
setImage (fileName, rtlFileName);
|
||||
Gtk::Image::set_from_icon_name(iconName, this->size);
|
||||
}
|
||||
|
||||
RTImage::RTImage (Glib::RefPtr<Gdk::Pixbuf> &pbuf)
|
||||
void RTImage::set_from_icon_name(const Glib::ustring& iconName, const Gtk::IconSize iconSize)
|
||||
{
|
||||
if (surface) {
|
||||
surface.clear();
|
||||
}
|
||||
if (pbuf) {
|
||||
set(pbuf);
|
||||
this->pixbuf = pbuf;
|
||||
}
|
||||
}
|
||||
|
||||
RTImage::RTImage (Cairo::RefPtr<Cairo::ImageSurface> &surf)
|
||||
{
|
||||
if (pixbuf) {
|
||||
pixbuf.clear();
|
||||
}
|
||||
if (surf) {
|
||||
set(surf);
|
||||
surface = surf;
|
||||
}
|
||||
}
|
||||
|
||||
RTImage::RTImage (Glib::RefPtr<RTImage> &other)
|
||||
{
|
||||
if (other) {
|
||||
if (other->get_surface()) {
|
||||
surface = other->get_surface();
|
||||
set(surface);
|
||||
} else {
|
||||
pixbuf = other->get_pixbuf();
|
||||
set(pixbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RTImage::setImage (const Glib::ustring& fileName, const Glib::ustring& rtlFileName)
|
||||
{
|
||||
Glib::ustring imageName;
|
||||
|
||||
if (!rtlFileName.empty() && getDirection() == Gtk::TEXT_DIR_RTL) {
|
||||
imageName = rtlFileName;
|
||||
} else {
|
||||
imageName = fileName;
|
||||
}
|
||||
|
||||
changeImage (imageName);
|
||||
}
|
||||
|
||||
/*
|
||||
* On windows, if scale = 2, the dpi is non significant, i.e. should be considered = 192
|
||||
*/
|
||||
void RTImage::setDPInScale (const double newDPI, const int newScale)
|
||||
{
|
||||
if (scaleBack != newScale || (scaleBack == 1 && dpiBack != newDPI)) {
|
||||
RTScalable::setDPInScale(newDPI, newScale);
|
||||
dpiBack = getDPI();
|
||||
scaleBack = getScale();
|
||||
updateImages();
|
||||
}
|
||||
}
|
||||
|
||||
void RTImage::changeImage (const Glib::ustring& imageName)
|
||||
{
|
||||
clear ();
|
||||
|
||||
if (imageName.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pixbuf) {
|
||||
auto iterator = pixbufCache.find (imageName);
|
||||
assert(iterator != pixbufCache.end ());
|
||||
pixbuf = iterator->second;
|
||||
set(iterator->second);
|
||||
} else { // if no Pixbuf is set, we update or create a Cairo::ImageSurface
|
||||
auto iterator = surfaceCache.find (imageName);
|
||||
if (iterator == surfaceCache.end ()) {
|
||||
auto surf = createImgSurfFromFile(imageName);
|
||||
iterator = surfaceCache.emplace (imageName, surf).first;
|
||||
}
|
||||
surface = iterator->second;
|
||||
set(iterator->second);
|
||||
}
|
||||
}
|
||||
|
||||
Cairo::RefPtr<Cairo::ImageSurface> RTImage::get_surface()
|
||||
{
|
||||
return surface;
|
||||
}
|
||||
|
||||
int RTImage::get_width()
|
||||
{
|
||||
if (surface) {
|
||||
return surface->get_width();
|
||||
}
|
||||
if (pixbuf) {
|
||||
return pixbuf->get_width();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int RTImage::get_height()
|
||||
{
|
||||
if (surface) {
|
||||
return surface->get_height();
|
||||
}
|
||||
if (pixbuf) {
|
||||
return pixbuf->get_height();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void RTImage::init()
|
||||
{
|
||||
dpiBack = RTScalable::getDPI();
|
||||
scaleBack = RTScalable::getScale();
|
||||
}
|
||||
|
||||
void RTImage::cleanup(bool all)
|
||||
{
|
||||
for (auto& entry : pixbufCache) {
|
||||
entry.second.reset();
|
||||
}
|
||||
for (auto& entry : surfaceCache) {
|
||||
entry.second.clear();
|
||||
}
|
||||
RTScalable::cleanup(all);
|
||||
}
|
||||
|
||||
void RTImage::updateImages()
|
||||
{
|
||||
for (auto& entry : pixbufCache) {
|
||||
entry.second = createPixbufFromFile(entry.first);
|
||||
}
|
||||
for (auto& entry : surfaceCache) {
|
||||
entry.second = createImgSurfFromFile(entry.first);
|
||||
}
|
||||
}
|
||||
|
||||
Glib::RefPtr<Gdk::Pixbuf> RTImage::createPixbufFromFile (const Glib::ustring& fileName)
|
||||
{
|
||||
Cairo::RefPtr<Cairo::ImageSurface> imgSurf = createImgSurfFromFile(fileName);
|
||||
return Gdk::Pixbuf::create(imgSurf, 0, 0, imgSurf->get_width(), imgSurf->get_height());
|
||||
}
|
||||
|
||||
Cairo::RefPtr<Cairo::ImageSurface> RTImage::createImgSurfFromFile (const Glib::ustring& fileName)
|
||||
{
|
||||
Cairo::RefPtr<Cairo::ImageSurface> surf;
|
||||
|
||||
try {
|
||||
surf = loadImage(fileName, getTweakedDPI());
|
||||
|
||||
// HOMBRE: As of now, GDK_SCALE is forced to 1, so setting the Cairo::ImageSurface scale is not required
|
||||
/*
|
||||
double x=0., y=0.;
|
||||
cairo_surface_get_device_scale(surf->cobj(), &x, &y);
|
||||
if (getScale() == 2) {
|
||||
cairo_surface_set_device_scale(surf->cobj(), 0.5, 0.5);
|
||||
cairo_surface_get_device_scale(surf->cobj(), &x, &y);
|
||||
surf->flush();
|
||||
}
|
||||
*/
|
||||
} catch (const Glib::Exception& exception) {
|
||||
if (rtengine::settings->verbose) {
|
||||
std::cerr << "Failed to load image \"" << fileName << "\": " << exception.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return surf;
|
||||
this->size = iconSize;
|
||||
Gtk::Image::set_from_icon_name(iconName, this->size);
|
||||
}
|
||||
|
Reference in New Issue
Block a user