Fixes blur rendering with RTSurface on hidpi screen

Other fixes:
- Fixes splash image not rendered
- Cleans commented code
- Replaces deprecated librsvg functions
- Updates Makefile librsvg required minimum version
- Correctly uses RTSurface getWidth / getHeight functions
- Improves lwbutton aspect

Known issues:
- Blur rendering with RTPixbuf on hidpi screen
This commit is contained in:
Pandagrapher 2022-08-21 15:45:07 +02:00
parent 7ee6fd795b
commit 36222d14a2
7 changed files with 95 additions and 46 deletions

View File

@ -467,7 +467,7 @@ pkg_check_modules(GTHREAD REQUIRED gthread-2.0>=2.48)
pkg_check_modules(GOBJECT REQUIRED gobject-2.0>=2.48) pkg_check_modules(GOBJECT REQUIRED gobject-2.0>=2.48)
pkg_check_modules(SIGC REQUIRED sigc++-2.0>=2.3.1) pkg_check_modules(SIGC REQUIRED sigc++-2.0>=2.3.1)
pkg_check_modules(LENSFUN REQUIRED lensfun>=0.2) pkg_check_modules(LENSFUN REQUIRED lensfun>=0.2)
pkg_check_modules(RSVG REQUIRED librsvg-2.0>=2.46) pkg_check_modules(RSVG REQUIRED librsvg-2.0>=2.52)
if(WIN32) if(WIN32)
add_definitions(-DWIN32) add_definitions(-DWIN32)

View File

@ -168,8 +168,8 @@ std::vector<Glib::RefPtr<Gdk::Pixbuf>> BatchQueueEntry::getIconsOnImageArea ()
void BatchQueueEntry::getIconSize (int& w, int& h) const void BatchQueueEntry::getIconSize (int& w, int& h) const
{ {
w = savedAsIcon->get()->get_width (); w = savedAsIcon->getWidth ();
h = savedAsIcon->get()->get_height (); h = savedAsIcon->getHeight ();
} }

View File

@ -195,8 +195,8 @@ void FileBrowserEntry::customBackBufferUpdate (Cairo::RefPtr<Cairo::Context> c)
void FileBrowserEntry::getIconSize (int& w, int& h) const void FileBrowserEntry::getIconSize (int& w, int& h) const
{ {
w = editedIcon->get()->get_width (); w = editedIcon->getWidth ();
h = editedIcon->get()->get_height (); h = editedIcon->getHeight ();
} }
FileThumbnailButtonSet* FileBrowserEntry::getThumbButtonSet () FileThumbnailButtonSet* FileBrowserEntry::getThumbButtonSet ()

View File

@ -25,8 +25,8 @@ LWButton::LWButton (std::shared_ptr<RTSurface> i, int aCode, void* aData, Alignm
{ {
if (i) { if (i) {
w = i->getWidth () + 2; w = i->getWidth ();
h = i->getHeight () + 2; h = i->getHeight ();
} else { } else {
w = h = 2; w = h = 2;
} }
@ -65,8 +65,8 @@ void LWButton::setIcon (std::shared_ptr<RTSurface> i)
icon = i; icon = i;
if (i) { if (i) {
w = i->getWidth () + 2; w = i->getWidth ();
h = i->getHeight () + 2; h = i->getHeight ();
} else { } else {
w = h = 2; w = h = 2;
} }
@ -186,9 +186,9 @@ void LWButton::redraw (Cairo::RefPtr<Cairo::Context> context)
{ {
GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected
context->set_line_width (1.0); context->set_line_width (2.0); // Line width shall be even to avoid blur effect when upscaling
context->set_antialias (Cairo::ANTIALIAS_SUBPIXEL); context->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
context->rectangle (xpos + 0.5, ypos + 0.5, w - 1.0, h - 1.0); context->rectangle (xpos, ypos, w, h);
if (state == Pressed_In) { if (state == Pressed_In) {
context->set_source_rgb (fgr, fgg, fgb); context->set_source_rgb (fgr, fgg, fgb);
@ -205,7 +205,7 @@ void LWButton::redraw (Cairo::RefPtr<Cairo::Context> context)
} }
context->stroke (); context->stroke ();
int dilat = 1; int dilat = 0;
if (state == Pressed_In) { if (state == Pressed_In) {
dilat++; dilat++;

View File

@ -36,7 +36,13 @@ void RTScalable::updateDPInScale(const Gtk::Window* window, double &newDPI, int
if (window) { if (window) {
const auto screen = window->get_screen(); const auto screen = window->get_screen();
newDPI = screen->get_resolution(); // Get DPI retrieved from the OS newDPI = screen->get_resolution(); // Get DPI retrieved from the OS
newScale = window->get_scale_factor(); // Get scale factor associated to the window
if (window->get_scale_factor() > 0) {
// Get scale factor associated to the window
newScale = window->get_scale_factor();
} else {
newScale = 1; // Default minimum value of 1 as scale is used to scale surface
}
} }
} }
@ -88,21 +94,6 @@ Cairo::RefPtr<Cairo::ImageSurface> RTScalable::loadSurfaceFromIcon(const Glib::u
} }
} }
/*
// Scale current surface size to desired scaled size
if (surface) {
// Note: surface is considered made from squared icon
const double scale_factor = static_cast<double>(size) / static_cast<double>(surface->get_width());
surf = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32,
static_cast<int>(surface->get_width() * scale_factor + 0.5),
static_cast<int>(surface->get_height() * scale_factor + 0.5));
const auto cr = Cairo::Context::create(surf);
cr->scale(scale_factor, scale_factor);
cr->set_source(surface, 0, 0);
cr->paint();
}
*/
return surf; return surf;
} }
@ -174,33 +165,44 @@ Cairo::RefPtr<Cairo::ImageSurface> RTScalable::loadSurfaceFromSVG(const Glib::us
return surf; return surf;
} }
int w, h;
if (width == -1 || height == -1) { if (width == -1 || height == -1) {
// Use SVG image natural width and height // Use SVG image natural width and height
RsvgDimensionData dim; double _w, _h;
rsvg_handle_get_dimensions(handle, &dim); // Get SVG image dimensions const bool has_dim = rsvg_handle_get_intrinsic_size_in_pixels(handle, &_w, &_h); // Get SVG image dimensions
surf = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, dim.width, dim.height); if (has_dim) {
w = std::ceil(_w);
h = std::ceil(_h);
} else {
w = h = 16; // Set to a default size of 16px (i.e. Gtk::ICON_SIZE_SMALL_TOOLBAR one)
}
} else { } else {
// Use given width and height // Use given width and height
surf = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, width, height); w = width;
h = height;
} }
// Create an upscaled surface to avoid blur effect
surf = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32,
w * RTScalable::getScale(),
h * RTScalable::getScale());
// Render (and erase with) default surface background // Render (and erase with) default surface background
Cairo::RefPtr<Cairo::Context> c = Cairo::Context::create(surf); Cairo::RefPtr<Cairo::Context> c = Cairo::Context::create(surf);
c->set_source_rgba (0., 0., 0., 0.); c->set_source_rgba (0., 0., 0., 0.);
c->set_operator (Cairo::OPERATOR_CLEAR); c->set_operator (Cairo::OPERATOR_CLEAR);
c->paint(); c->paint();
// Render surface based on SVG image // Render upscaled surface based on SVG image
error = nullptr; error = nullptr;
RsvgRectangle rect = { RsvgRectangle rect = {
.x = 0., .x = 0.,
.y = 0., .y = 0.,
.width = static_cast<double>(width * RTScalable::getScale()), // SVG image is upscaled to avoid blur effect .width = static_cast<double>(w * RTScalable::getScale()),
.height = static_cast<double>(height * RTScalable::getScale()) // SVG image is upscaled to avoid blur effect .height = static_cast<double>(h * RTScalable::getScale())
}; };
c->set_operator (Cairo::OPERATOR_OVER); c->set_operator (Cairo::OPERATOR_OVER);
c->scale(1. / RTScalable::getScale(), 1. / RTScalable::getScale()); // Cairo surface is scaled to match image dimensions
const bool success = rsvg_handle_render_document(handle, c->cobj(), &rect, &error); const bool success = rsvg_handle_render_document(handle, c->cobj(), &rect, &error);
if (!success && error) { if (!success && error) {
@ -210,6 +212,11 @@ Cairo::RefPtr<Cairo::ImageSurface> RTScalable::loadSurfaceFromSVG(const Glib::us
} }
rsvg_handle_free(handle); rsvg_handle_free(handle);
// Set device scale to avoid blur effect
cairo_surface_set_device_scale(surf->cobj(),
static_cast<double>(RTScalable::getScale()),
static_cast<double>(RTScalable::getScale()));
} else { } else {
if (rtengine::settings->verbose) { if (rtengine::settings->verbose) {
std::cerr << "Failed to load SVG file \"" << fname << "\"" << std::endl; std::cerr << "Failed to load SVG file \"" << fname << "\"" << std::endl;

View File

@ -90,7 +90,7 @@ int RTSurface::getWidth()
{ {
return return
surface surface
? surface->get_width() ? (surface->get_width() / RTScalable::getScale())
: -1; : -1;
} }
@ -98,7 +98,7 @@ int RTSurface::getHeight()
{ {
return return
surface surface
? surface->get_height() ? (surface->get_height() / RTScalable::getScale())
: -1; : -1;
} }
@ -152,8 +152,22 @@ RTPixbuf::RTPixbuf(const Glib::ustring &icon_name, const Gtk::IconSize iconSize)
const Cairo::RefPtr<Cairo::ImageSurface> surface = RTScalable::loadSurfaceFromIcon(icon_name, iconSize); const Cairo::RefPtr<Cairo::ImageSurface> surface = RTScalable::loadSurfaceFromIcon(icon_name, iconSize);
if (surface) { if (surface) {
// Downscale surface before creating pixbuf
const Cairo::RefPtr<Cairo::Surface> _surface = Cairo::Surface::create(surface,
Cairo::CONTENT_COLOR_ALPHA,
surface->get_width() / RTScalable::getScale(),
surface->get_height() / RTScalable::getScale());
const auto c = Cairo::Context::create(_surface);
c->scale(1. / static_cast<double>(RTScalable::getScale()), 1. / static_cast<double>(RTScalable::getScale()));
c->set_source(surface, 0., 0.);
c->paint();
// Create pixbuf from surface // Create pixbuf from surface
pixbuf = Gdk::Pixbuf::create(surface, 0, 0, surface->get_width(), surface->get_height()); pixbuf = Gdk::Pixbuf::create(_surface,
0,
0,
surface->get_width() / RTScalable::getScale(),
surface->get_height() / RTScalable::getScale());
// Save private parameters // Save private parameters
type = RTPixbuf::IconType; type = RTPixbuf::IconType;
@ -177,8 +191,22 @@ RTPixbuf::RTPixbuf(const Glib::ustring &fname) :
const Cairo::RefPtr<Cairo::ImageSurface> surface = RTScalable::loadSurfaceFromPNG(fname); const Cairo::RefPtr<Cairo::ImageSurface> surface = RTScalable::loadSurfaceFromPNG(fname);
if (surface) { if (surface) {
// Downscale surface before creating pixbuf
const Cairo::RefPtr<Cairo::Surface> _surface = Cairo::Surface::create(surface,
Cairo::CONTENT_COLOR_ALPHA,
surface->get_width() / RTScalable::getScale(),
surface->get_height() / RTScalable::getScale());
const auto c = Cairo::Context::create(_surface);
c->scale(1. / static_cast<double>(RTScalable::getScale()), 1. / static_cast<double>(RTScalable::getScale()));
c->set_source(surface, 0., 0.);
c->paint();
// Create pixbuf from surface // Create pixbuf from surface
pixbuf = Gdk::Pixbuf::create(surface, 0, 0, surface->get_width(), surface->get_height()); pixbuf = Gdk::Pixbuf::create(_surface,
0,
0,
surface->get_width() / RTScalable::getScale(),
surface->get_height() / RTScalable::getScale());
// Save private parameter // Save private parameter
type = RTPixbuf::PNGType; type = RTPixbuf::PNGType;
@ -192,8 +220,22 @@ RTPixbuf::RTPixbuf(const Glib::ustring &fname) :
const Cairo::RefPtr<Cairo::ImageSurface> surface = RTScalable::loadSurfaceFromSVG(fname); const Cairo::RefPtr<Cairo::ImageSurface> surface = RTScalable::loadSurfaceFromSVG(fname);
if (surface) { if (surface) {
// Downscale surface before creating pixbuf
const Cairo::RefPtr<Cairo::Surface> _surface = Cairo::Surface::create(surface,
Cairo::CONTENT_COLOR_ALPHA,
surface->get_width() / RTScalable::getScale(),
surface->get_height() / RTScalable::getScale());
const auto c = Cairo::Context::create(_surface);
c->scale(1. / static_cast<double>(RTScalable::getScale()), 1. / static_cast<double>(RTScalable::getScale()));
c->set_source(surface, 0., 0.);
c->paint();
// Create pixbuf from surface // Create pixbuf from surface
pixbuf = Gdk::Pixbuf::create(surface, 0, 0, surface->get_width(), surface->get_height()); pixbuf = Gdk::Pixbuf::create(_surface,
0,
0,
surface->get_width() / RTScalable::getScale(),
surface->get_height() / RTScalable::getScale());
// Save private parameter // Save private parameter
type = RTPixbuf::SVGType; type = RTPixbuf::SVGType;

View File

@ -34,7 +34,7 @@ bool SplashImage::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr)
{ {
if (surface->hasSurface()) { if (surface->hasSurface()) {
cr->set_source(surface->get(), 0., 0.); cr->set_source(surface->get(), 0., 0.);
cr->rectangle(0, 0, surface->get()->get_width(), surface->get()->get_height()); cr->rectangle(0, 0, surface->getWidth(), surface->getHeight());
cr->fill(); cr->fill();
Cairo::FontOptions cfo; Cairo::FontOptions cfo;
@ -68,7 +68,7 @@ bool SplashImage::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr)
cr->set_source_rgb (0., 0., 0.); cr->set_source_rgb (0., 0., 0.);
cr->set_line_width(3.); cr->set_line_width(3.);
cr->set_line_join(Cairo::LINE_JOIN_ROUND); cr->set_line_join(Cairo::LINE_JOIN_ROUND);
cr->move_to (surface->get()->get_width() - w - 32, surface->get()->get_height() - h - 20); cr->move_to (surface->getWidth() - w - 32, surface->getHeight() - h - 20);
version->add_to_cairo_context (cr); version->add_to_cairo_context (cr);
cr->stroke_preserve(); cr->stroke_preserve();
cr->set_source_rgb (1., 1., 1.); cr->set_source_rgb (1., 1., 1.);
@ -87,12 +87,12 @@ Gtk::SizeRequestMode SplashImage::get_request_mode_vfunc () const
void SplashImage::get_preferred_height_vfunc (int &minimum_height, int &natural_height) const void SplashImage::get_preferred_height_vfunc (int &minimum_height, int &natural_height) const
{ {
minimum_height = natural_height = surface ? surface->get()->get_height() : RTScalable::scalePixelSize(100); minimum_height = natural_height = surface ? surface->getHeight() : RTScalable::scalePixelSize(100);
} }
void SplashImage::get_preferred_width_vfunc (int &minimum_width, int &natural_width) const void SplashImage::get_preferred_width_vfunc (int &minimum_width, int &natural_width) const
{ {
minimum_width = natural_width = surface ? surface->get()->get_width() : RTScalable::scalePixelSize(100); minimum_width = natural_width = surface ? surface->getWidth() : RTScalable::scalePixelSize(100);
} }
void SplashImage::get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const void SplashImage::get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const