diff --git a/CMakeLists.txt b/CMakeLists.txt index 5274a23..bbcee31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,8 +63,8 @@ pkg_check_modules( libjxl libjxl_cms libjxl_threads - hyprlang>=0.2.0 - hyprutils>=0.2.0 + hyprlang>=0.6.0 + hyprutils>=0.2.4 hyprgraphics) file(GLOB_RECURSE SRCFILES "src/*.cpp") diff --git a/flake.lock b/flake.lock index 268fe5c..d73836a 100644 --- a/flake.lock +++ b/flake.lock @@ -13,11 +13,11 @@ ] }, "locked": { - "lastModified": 1732808127, - "narHash": "sha256-jwqYmLVfvoLPu8UScEzZgdbbiNU3ioYcrsthjEEnGqI=", + "lastModified": 1733684019, + "narHash": "sha256-2kYREgmSmbLsmDpLEq96hxVAU3qz8aCvVhF65yCFZHY=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "4d927a52be7e15e0846456f2aa1b0ad76b5bf059", + "rev": "fb2c0268645a77403af3b8a4ce8fa7ba5917f15d", "type": "github" }, "original": { @@ -39,11 +39,11 @@ ] }, "locked": { - "lastModified": 1725188252, - "narHash": "sha256-yBH8c4GDaEAtBrh+BqIlrx5vp6gG/Gu8fQQK63KAQgs=", + "lastModified": 1734174076, + "narHash": "sha256-s7FX3ax1KCogPbEa8Cc8RWsYnr6jSkWbIdtYmh4cGrs=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "c12ab785ce1982f82594aff03b3104c598186ddd", + "rev": "f7acd5dabba315247497bc9f89da2c5e175aa9a1", "type": "github" }, "original": { @@ -62,11 +62,11 @@ ] }, "locked": { - "lastModified": 1724966483, - "narHash": "sha256-WXDgKIbzjYKczxSZOsJplCS1i1yrTUpsDPuJV/xpYLo=", + "lastModified": 1733502241, + "narHash": "sha256-KAUNC4Dgq8WQjYov5auBw/usaHixhacvb7cRDd0AG/k=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "8976e3f6a5357da953a09511d0c7f6a890fb6ec2", + "rev": "104117aed6dd68561be38b50f218190aa47f2cd8", "type": "github" }, "original": { @@ -85,11 +85,11 @@ ] }, "locked": { - "lastModified": 1721324119, - "narHash": "sha256-SOOqIT27/X792+vsLSeFdrNTF+OSRp5qXv6Te+fb2Qg=", + "lastModified": 1726874836, + "narHash": "sha256-VKR0sf0PSNCB0wPHVKSAn41mCNVCnegWmgkrneKDhHM=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "a048a6cb015340bd82f97c1f40a4b595ca85cc30", + "rev": "500c81a9e1a76760371049a8d99e008ea77aa59e", "type": "github" }, "original": { @@ -100,11 +100,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1725103162, - "narHash": "sha256-Ym04C5+qovuQDYL/rKWSR+WESseQBbNAe5DsXNx5trY=", + "lastModified": 1733940404, + "narHash": "sha256-Pj39hSoUA86ZePPF/UXiYHHM7hMIkios8TYG29kQT4g=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "12228ff1752d7b7624a54e9c1af4b222b3c1073b", + "rev": "5d67ea6b4b63378b9c13be21e2ec9d1afc921713", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index a21e882..8156707 100644 --- a/flake.nix +++ b/flake.nix @@ -62,7 +62,7 @@ inputs.hyprwayland-scanner.overlays.default (final: prev: rec { hyprpaper = final.callPackage ./nix/default.nix { - stdenv = final.gcc13Stdenv; + stdenv = final.gcc14Stdenv; version = version + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty"); commit = self.rev or ""; }; diff --git a/src/Hyprpaper.cpp b/src/Hyprpaper.cpp index ac603e6..1c03ad1 100644 --- a/src/Hyprpaper.cpp +++ b/src/Hyprpaper.cpp @@ -39,7 +39,7 @@ static void handleGlobal(CCWlRegistry* registry, uint32_t name, const char* inte static void handleGlobalRemove(CCWlRegistry* registry, uint32_t name) { for (auto& m : g_pHyprpaper->m_vMonitors) { if (m->wayland_name == name) { - Debug::log(LOG, "Destroying output %s", m->name.c_str()); + Debug::log(LOG, "Destroying output {}", m->name); g_pHyprpaper->clearWallpaperFromMonitor(m->name); std::erase_if(g_pHyprpaper->m_vMonitors, [&](const auto& other) { return other->wayland_name == name; }); return; @@ -139,7 +139,7 @@ void CHyprpaper::unloadWallpaper(const std::string& path) { const auto PRELOADPATH = it->get()->name; - Debug::log(LOG, "Unloading target %s, preload path %s", path.c_str(), PRELOADPATH.c_str()); + Debug::log(LOG, "Unloading target {}, preload path {}", path, PRELOADPATH); std::filesystem::remove(PRELOADPATH); @@ -161,7 +161,7 @@ void CHyprpaper::preloadAllWallpapersFromConfig() { bool exists = false; for (auto& [ewp, cls] : m_mWallpaperTargets) { if (ewp == wp) { - Debug::log(LOG, "Ignoring request to preload %s as it already is preloaded!", ewp.c_str()); + Debug::log(LOG, "Ignoring request to preload {} as it already is preloaded!", ewp); exists = true; break; } @@ -243,14 +243,13 @@ void CHyprpaper::removeOldHyprpaperImages() { memoryFreed += entry.file_size(); if (!std::filesystem::remove(entry.path())) - Debug::log(LOG, "Couldn't remove %s", entry.path().string().c_str()); + Debug::log(LOG, "Couldn't remove {}", entry.path().string()); cleaned++; } } - if (cleaned != 0) { - Debug::log(LOG, "Cleaned old hyprpaper preloads (%i), removing %.1fMB", cleaned, ((float)memoryFreed) / 1000000.f); - } + if (cleaned != 0) + Debug::log(LOG, "Cleaned old hyprpaper preloads ({}), removing {:.1f}MB", cleaned, ((float)memoryFreed) / 1000000.f); } SMonitor* CHyprpaper::getMonitorFromName(const std::string& monname) { @@ -294,7 +293,7 @@ void CHyprpaper::ensurePoolBuffersPresent() { PBUFFER->target = wt.m_szPath; - Debug::log(LOG, "Buffer created for target %s, Shared Memory usage: %.1fMB", wt.m_szPath.c_str(), PBUFFER->size / 1000000.f); + Debug::log(LOG, "Buffer created for target {}, Shared Memory usage: {:.1f}MB", wt.m_szPath, PBUFFER->size / 1000000.f); anyNewBuffers = true; } @@ -308,7 +307,7 @@ void CHyprpaper::ensurePoolBuffersPresent() { bytesUsed += bf->size; } - Debug::log(LOG, "Total SM usage for all buffers: %.1fMB", bytesUsed / 1000000.f); + Debug::log(LOG, "Total SM usage for all buffers: {:.1f}MB", bytesUsed / 1000000.f); } } @@ -398,7 +397,7 @@ void CHyprpaper::ensureMonitorHasActiveWallpaper(SMonitor* pMonitor) { if (!it->second) { pMonitor->hasATarget = false; - Debug::log(WARN, "Monitor %s does not have a target! A wallpaper will not be created.", pMonitor->name.c_str()); + Debug::log(WARN, "Monitor {} does not have a target! A wallpaper will not be created.", pMonitor->name); return; } @@ -507,8 +506,8 @@ SPoolBuffer* CHyprpaper::getPoolBuffer(SMonitor* pMonitor, CWallpaperTarget* pWa } void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { - static auto* const PRENDERSPLASH = reinterpret_cast(g_pConfigManager->config->getConfigValuePtr("splash")->getDataStaticPtr()); - static auto* const PSPLASHOFFSET = reinterpret_cast(g_pConfigManager->config->getConfigValuePtr("splash_offset")->getDataStaticPtr()); + static auto PRENDERSPLASH = Hyprlang::CSimpleConfigValue(g_pConfigManager->config.get(), "splash"); + static auto PSPLASHOFFSET = Hyprlang::CSimpleConfigValue(g_pConfigManager->config.get(), "splash_offset"); if (!m_mMonitorActiveWallpaperTargets[pMonitor]) recheckMonitor(pMonitor); @@ -565,8 +564,8 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { origin.x = -(PWALLPAPERTARGET->m_vSize.x * scale - DIMENSIONS.x) / 2.0 / scale; } - Debug::log(LOG, "Image data for %s: %s at [%.2f, %.2f], scale: %.2f (original image size: [%i, %i])", pMonitor->name.c_str(), PWALLPAPERTARGET->m_szPath.c_str(), origin.x, - origin.y, scale, (int)PWALLPAPERTARGET->m_vSize.x, (int)PWALLPAPERTARGET->m_vSize.y); + Debug::log(LOG, "Image data for {}: {} at [{:.2f}, {:.2f}], scale: {:.2f} (original image size: [{}, {}])", pMonitor->name, PWALLPAPERTARGET->m_szPath, origin.x, origin.y, + scale, (int)PWALLPAPERTARGET->m_vSize.x, (int)PWALLPAPERTARGET->m_vSize.y); if (TILE) { cairo_pattern_t* pattern = cairo_pattern_create_for_surface(PWALLPAPERTARGET->m_pCairoSurface->cairo()); @@ -579,7 +578,7 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { cairo_paint(PCAIRO); - if (**PRENDERSPLASH && getenv("HYPRLAND_INSTANCE_SIGNATURE")) { + if (*PRENDERSPLASH && getenv("HYPRLAND_INSTANCE_SIGNATURE")) { auto SPLASH = execAndGet("hyprctl splash"); SPLASH.pop_back(); @@ -590,20 +589,20 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { const auto FONTSIZE = (int)(DIMENSIONS.y / 76.0 / scale); cairo_set_font_size(PCAIRO, FONTSIZE); - static auto* const PSPLASHCOLOR = reinterpret_cast(g_pConfigManager->config->getConfigValuePtr("splash_color")->getDataStaticPtr()); + static auto PSPLASHCOLOR = Hyprlang::CSimpleConfigValue(g_pConfigManager->config.get(), "splash_color"); - Debug::log(LOG, "Splash color: %x", **PSPLASHCOLOR); + Debug::log(LOG, "Splash color: {:x}", *PSPLASHCOLOR); - cairo_set_source_rgba(PCAIRO, ((**PSPLASHCOLOR >> 16) & 0xFF) / 255.0, ((**PSPLASHCOLOR >> 8) & 0xFF) / 255.0, (**PSPLASHCOLOR & 0xFF) / 255.0, - ((**PSPLASHCOLOR >> 24) & 0xFF) / 255.0); + cairo_set_source_rgba(PCAIRO, ((*PSPLASHCOLOR >> 16) & 0xFF) / 255.0, ((*PSPLASHCOLOR >> 8) & 0xFF) / 255.0, (*PSPLASHCOLOR & 0xFF) / 255.0, + ((*PSPLASHCOLOR >> 24) & 0xFF) / 255.0); cairo_text_extents_t textExtents; cairo_text_extents(PCAIRO, SPLASH.c_str(), &textExtents); - cairo_move_to(PCAIRO, ((DIMENSIONS.x - textExtents.width * scale) / 2.0) / scale, ((DIMENSIONS.y * (100 - **PSPLASHOFFSET)) / 100 - textExtents.height * scale) / scale); + cairo_move_to(PCAIRO, ((DIMENSIONS.x - textExtents.width * scale) / 2.0) / scale, ((DIMENSIONS.y * (100 - *PSPLASHOFFSET)) / 100 - textExtents.height * scale) / scale); - Debug::log(LOG, "Splash font size: %d, pos: %.2f, %.2f", FONTSIZE, (DIMENSIONS.x - textExtents.width) / 2.0 / scale, - ((DIMENSIONS.y * (100 - **PSPLASHOFFSET)) / 100 - textExtents.height * scale) / scale); + Debug::log(LOG, "Splash font size: {}, pos: {:.2f}, {:.2f}", FONTSIZE, (DIMENSIONS.x - textExtents.width) / 2.0 / scale, + ((DIMENSIONS.y * (100 - *PSPLASHOFFSET)) / 100 - textExtents.height * scale) / scale); cairo_show_text(PCAIRO, SPLASH.c_str()); @@ -623,8 +622,8 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { pMonitor->pCurrentLayerSurface->pSurface->sendSetOpaqueRegion(opaqueRegion.get()); if (pMonitor->pCurrentLayerSurface->pFractionalScaleInfo) { - Debug::log(LOG, "Submitting viewport dest size %ix%i for %x", static_cast(std::round(pMonitor->size.x)), static_cast(std::round(pMonitor->size.y)), - pMonitor->pCurrentLayerSurface); + Debug::log(LOG, "Submitting viewport dest size {}x{} for {:x}", static_cast(std::round(pMonitor->size.x)), static_cast(std::round(pMonitor->size.y)), + (uintptr_t)pMonitor->pCurrentLayerSurface); pMonitor->pCurrentLayerSurface->pViewport->sendSetDestination(static_cast(std::round(pMonitor->size.x)), static_cast(std::round(pMonitor->size.y))); } pMonitor->pCurrentLayerSurface->pSurface->sendCommit(); diff --git a/src/Hyprpaper.hpp b/src/Hyprpaper.hpp index 9327906..0d6cb26 100644 --- a/src/Hyprpaper.hpp +++ b/src/Hyprpaper.hpp @@ -18,7 +18,7 @@ struct SWallpaperRenderData { bool contain = false; - bool tile = false; + bool tile = false; }; class CHyprpaper { diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp deleted file mode 100644 index bf3574d..0000000 --- a/src/debug/Log.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "Log.hpp" -#include "../includes.hpp" - -#include -#include - -void Debug::log(LogLevel level, const char* fmt, ...) { - - std::string levelstr = ""; - - switch (level) { - case LOG: levelstr = "[LOG] "; break; - case WARN: levelstr = "[WARN] "; break; - case ERR: levelstr = "[ERR] "; break; - case CRIT: levelstr = "[CRITICAL] "; break; - case INFO: levelstr = "[INFO] "; break; - default: break; - } - - char buf[LOGMESSAGESIZE] = ""; - char* outputStr; - int logLen; - - va_list args; - va_start(args, fmt); - logLen = vsnprintf(buf, sizeof buf, fmt, args); - va_end(args); - - if ((long unsigned int)logLen < sizeof buf) { - outputStr = strdup(buf); - } else { - outputStr = (char*)malloc(logLen + 1); - - if (!outputStr) { - printf("CRITICAL: Cannot alloc size %d for log! (Out of memory?)", logLen + 1); - return; - } - - va_start(args, fmt); - vsnprintf(outputStr, logLen + 1U, fmt, args); - va_end(args); - } - - // hyprpaper only logs to stdout - std::cout << levelstr << outputStr << "\n"; - - // free the log - free(outputStr); -} diff --git a/src/debug/Log.hpp b/src/debug/Log.hpp index 211a575..357f4f5 100644 --- a/src/debug/Log.hpp +++ b/src/debug/Log.hpp @@ -1,17 +1,57 @@ #pragma once +#include +#include #include -#define LOGMESSAGESIZE 1024 - -enum LogLevel { - NONE = -1, - LOG = 0, +enum eLogLevel { + TRACE = 0, + INFO, + LOG, WARN, ERR, CRIT, - INFO + NONE }; +#define RASSERT(expr, reason, ...) \ + if (!(expr)) { \ + Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n{}\n\nat: line {} in {}", \ + std::format(reason, ##__VA_ARGS__), __LINE__, \ + ([]() constexpr -> std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })().c_str()); \ + std::abort(); \ + } + +#define ASSERT(expr) RASSERT(expr, "?") + namespace Debug { - void log(LogLevel level, const char* fmt, ...); -} + inline bool quiet = false; + inline bool verbose = false; + + template + void log(eLogLevel level, const std::string& fmt, Args&&... args) { + + if (!verbose && level == TRACE) + return; + + if (quiet) + return; + + if (level != NONE) { + std::cout << '['; + + switch (level) { + case TRACE: std::cout << "TRACE"; break; + case INFO: std::cout << "INFO"; break; + case LOG: std::cout << "LOG"; break; + case WARN: std::cout << "WARN"; break; + case ERR: std::cout << "ERR"; break; + case CRIT: std::cout << "CRITICAL"; break; + default: break; + } + + std::cout << "] "; + } + + std::cout << std::vformat(fmt, std::make_format_args(args...)) << std::endl; + } +}; \ No newline at end of file diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index e35afcb..433553b 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -3,6 +3,9 @@ #include "../debug/Log.hpp" #include +#include +using namespace Hyprutils::OS; + bool vectorDeltaLessThan(const Vector2D& a, const Vector2D& b, const float& delta) { return std::abs(a.x - b.x) < delta && std::abs(a.y - b.y) < delta; } @@ -12,15 +15,8 @@ bool vectorDeltaLessThan(const Vector2D& a, const Vector2D& b, const Vector2D& d } std::string execAndGet(const char* cmd) { - std::array buffer; - std::string result; - const std::unique_ptr pipe(popen(cmd, "r"), pclose); - if (!pipe) { - Debug::log(ERR, "execAndGet: failed in pipe"); + CProcess proc("/bin/bash", {cmd}); + if (!proc.runSync()) return ""; - } - while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { - result += buffer.data(); - } - return result; + return proc.stdOut(); } diff --git a/src/ipc/Socket.cpp b/src/ipc/Socket.cpp index 852b79f..df92dbc 100644 --- a/src/ipc/Socket.cpp +++ b/src/ipc/Socket.cpp @@ -50,7 +50,7 @@ void CIPCSocket::initialize() { char readBuffer[1024] = {0}; - Debug::log(LOG, "hyprpaper socket started at %s (fd: %i)", socketPath.c_str(), SOCKET); + Debug::log(LOG, "hyprpaper socket started at {} (fd: {})", socketPath, SOCKET); while (1) { const auto ACCEPTEDCONNECTION = accept(SOCKET, (sockaddr*)&clientAddress, &clientSize); if (ACCEPTEDCONNECTION < 0) { @@ -58,7 +58,7 @@ void CIPCSocket::initialize() { break; } else { do { - Debug::log(LOG, "Accepted incoming socket connection request on fd %i", ACCEPTEDCONNECTION); + Debug::log(LOG, "Accepted incoming socket connection request on fd {}", ACCEPTEDCONNECTION); std::lock_guard lg(g_pHyprpaper->m_mtTickMutex); auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024); @@ -100,7 +100,7 @@ bool CIPCSocket::mainThreadParseRequest() { // now we can work on the copy - Debug::log(LOG, "Received a request: %s", copy.c_str()); + Debug::log(LOG, "Received a request: {}", copy); // set default reply m_szReply = "ok"; @@ -123,7 +123,7 @@ bool CIPCSocket::mainThreadParseRequest() { if (copy.find("listloaded") == 0) { const auto numWallpapersLoaded = g_pHyprpaper->m_mWallpaperTargets.size(); - Debug::log(LOG, "numWallpapersLoaded: %d", numWallpapersLoaded); + Debug::log(LOG, "numWallpapersLoaded: {}", numWallpapersLoaded); if (numWallpapersLoaded == 0) { m_szReply = "no wallpapers loaded"; @@ -145,7 +145,7 @@ bool CIPCSocket::mainThreadParseRequest() { if (copy.find("listactive") == 0) { const auto numWallpapersActive = g_pHyprpaper->m_mMonitorActiveWallpapers.size(); - Debug::log(LOG, "numWallpapersActive: %d", numWallpapersActive); + Debug::log(LOG, "numWallpapersActive: {}", numWallpapersActive); if (numWallpapersActive == 0) { m_szReply = "no wallpapers active"; diff --git a/src/main.cpp b/src/main.cpp index d458797..4b71110 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,7 +3,7 @@ #include "Hyprpaper.hpp" int main(int argc, char** argv, char** envp) { - Debug::log(LOG, "Welcome to hyprpaper!\nbuilt from commit %s (%s)", GIT_COMMIT_HASH, GIT_COMMIT_MESSAGE); + Debug::log(LOG, "Welcome to hyprpaper!\nbuilt from commit {} ({})", GIT_COMMIT_HASH, GIT_COMMIT_MESSAGE); // parse some args std::string configPath; @@ -11,7 +11,7 @@ int main(int argc, char** argv, char** envp) { for (int i = 1; i < argc; ++i) { if ((!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")) && argc >= i + 2) { configPath = std::string(argv[++i]); - Debug::log(LOG, "Using config location %s.", configPath.c_str()); + Debug::log(LOG, "Using config location {}.", configPath); } else if (!strcmp(argv[i], "--no-fractional") || !strcmp(argv[i], "-n")) { noFractional = true; Debug::log(LOG, "Disabling fractional scaling support!"); diff --git a/src/render/LayerSurface.cpp b/src/render/LayerSurface.cpp index 9122e1a..b9c2751 100644 --- a/src/render/LayerSurface.cpp +++ b/src/render/LayerSurface.cpp @@ -66,7 +66,7 @@ CLayerSurface::CLayerSurface(SMonitor* pMonitor) { pFractionalScaleInfo->setPreferredScale([this](CCWpFractionalScaleV1* r, uint32_t sc120) { const double SCALE = sc120 / 120.0; - Debug::log(LOG, "handlePreferredScale: %.2lf for %lx", SCALE, this); + Debug::log(LOG, "handlePreferredScale: {:.2f} for {:x}", SCALE, (uintptr_t)this); if (fScale != SCALE) { fScale = SCALE; diff --git a/src/render/WallpaperTarget.cpp b/src/render/WallpaperTarget.cpp index b5e7773..878b6ef 100644 --- a/src/render/WallpaperTarget.cpp +++ b/src/render/WallpaperTarget.cpp @@ -11,11 +11,11 @@ CWallpaperTarget::~CWallpaperTarget() { void CWallpaperTarget::create(const std::string& path) { m_szPath = path; - const auto BEGINLOAD = std::chrono::system_clock::now(); + const auto BEGINLOAD = std::chrono::system_clock::now(); - auto loadedImage = CImage(path); + auto loadedImage = CImage(path); if (!loadedImage.success()) { - Debug::log(CRIT, "Cannot load image %s: %s", path.c_str(), loadedImage.getError().c_str()); + Debug::log(CRIT, "Cannot load image {}: {}", path, loadedImage.getError()); exit(1); } @@ -23,7 +23,7 @@ void CWallpaperTarget::create(const std::string& path) { const auto MS = std::chrono::duration_cast(std::chrono::system_clock::now() - BEGINLOAD).count() / 1000.f; - Debug::log(LOG, "Preloaded target %s in %.2fms -> Pixel size: [%i, %i]", path.c_str(), MS, (int)m_vSize.x, (int)m_vSize.y); + Debug::log(LOG, "Preloaded target {} in {:.2f}ms -> Pixel size: [{}, {}]", path, MS, (int)m_vSize.x, (int)m_vSize.y); m_pCairoSurface = loadedImage.cairoSurface(); }