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(SIGC REQUIRED sigc++-2.0>=2.3.1)
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)
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
{
w = savedAsIcon->get()->get_width ();
h = savedAsIcon->get()->get_height ();
w = savedAsIcon->getWidth ();
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
{
w = editedIcon->get()->get_width ();
h = editedIcon->get()->get_height ();
w = editedIcon->getWidth ();
h = editedIcon->getHeight ();
}
FileThumbnailButtonSet* FileBrowserEntry::getThumbButtonSet ()

View File

@ -25,8 +25,8 @@ LWButton::LWButton (std::shared_ptr<RTSurface> i, int aCode, void* aData, Alignm
{
if (i) {
w = i->getWidth () + 2;
h = i->getHeight () + 2;
w = i->getWidth ();
h = i->getHeight ();
} else {
w = h = 2;
}
@ -65,8 +65,8 @@ void LWButton::setIcon (std::shared_ptr<RTSurface> i)
icon = i;
if (i) {
w = i->getWidth () + 2;
h = i->getHeight () + 2;
w = i->getWidth ();
h = i->getHeight ();
} else {
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
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->rectangle (xpos + 0.5, ypos + 0.5, w - 1.0, h - 1.0);
context->rectangle (xpos, ypos, w, h);
if (state == Pressed_In) {
context->set_source_rgb (fgr, fgg, fgb);
@ -205,7 +205,7 @@ void LWButton::redraw (Cairo::RefPtr<Cairo::Context> context)
}
context->stroke ();
int dilat = 1;
int dilat = 0;
if (state == Pressed_In) {
dilat++;

View File

@ -36,7 +36,13 @@ void RTScalable::updateDPInScale(const Gtk::Window* window, double &newDPI, int
if (window) {
const auto screen = window->get_screen();
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;
}
@ -174,33 +165,44 @@ Cairo::RefPtr<Cairo::ImageSurface> RTScalable::loadSurfaceFromSVG(const Glib::us
return surf;
}
int w, h;
if (width == -1 || height == -1) {
// Use SVG image natural width and height
RsvgDimensionData dim;
rsvg_handle_get_dimensions(handle, &dim); // Get SVG image dimensions
surf = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, dim.width, dim.height);
double _w, _h;
const bool has_dim = rsvg_handle_get_intrinsic_size_in_pixels(handle, &_w, &_h); // Get SVG image dimensions
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 {
// 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
Cairo::RefPtr<Cairo::Context> c = Cairo::Context::create(surf);
c->set_source_rgba (0., 0., 0., 0.);
c->set_operator (Cairo::OPERATOR_CLEAR);
c->paint();
// Render surface based on SVG image
// Render upscaled surface based on SVG image
error = nullptr;
RsvgRectangle rect = {
.x = 0.,
.y = 0.,
.width = static_cast<double>(width * RTScalable::getScale()), // SVG image is upscaled to avoid blur effect
.height = static_cast<double>(height * RTScalable::getScale()) // SVG image is upscaled to avoid blur effect
.width = static_cast<double>(w * RTScalable::getScale()),
.height = static_cast<double>(h * RTScalable::getScale())
};
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);
if (!success && error) {
@ -210,6 +212,11 @@ Cairo::RefPtr<Cairo::ImageSurface> RTScalable::loadSurfaceFromSVG(const Glib::us
}
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 {
if (rtengine::settings->verbose) {
std::cerr << "Failed to load SVG file \"" << fname << "\"" << std::endl;

View File

@ -90,7 +90,7 @@ int RTSurface::getWidth()
{
return
surface
? surface->get_width()
? (surface->get_width() / RTScalable::getScale())
: -1;
}
@ -98,7 +98,7 @@ int RTSurface::getHeight()
{
return
surface
? surface->get_height()
? (surface->get_height() / RTScalable::getScale())
: -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);
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
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
type = RTPixbuf::IconType;
@ -177,8 +191,22 @@ RTPixbuf::RTPixbuf(const Glib::ustring &fname) :
const Cairo::RefPtr<Cairo::ImageSurface> surface = RTScalable::loadSurfaceFromPNG(fname);
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
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
type = RTPixbuf::PNGType;
@ -192,8 +220,22 @@ RTPixbuf::RTPixbuf(const Glib::ustring &fname) :
const Cairo::RefPtr<Cairo::ImageSurface> surface = RTScalable::loadSurfaceFromSVG(fname);
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
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
type = RTPixbuf::SVGType;

View File

@ -34,7 +34,7 @@ bool SplashImage::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr)
{
if (surface->hasSurface()) {
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();
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_line_width(3.);
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);
cr->stroke_preserve();
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
{
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
{
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