diff --git a/CMakeLists.txt b/CMakeLists.txt index b51f353..5274a23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,8 @@ pkg_check_modules( libjxl_cms libjxl_threads hyprlang>=0.2.0 - hyprutils>=0.2.0) + hyprutils>=0.2.0 + hyprgraphics) file(GLOB_RECURSE SRCFILES "src/*.cpp") diff --git a/src/Hyprpaper.cpp b/src/Hyprpaper.cpp index cfbdf50..ac603e6 100644 --- a/src/Hyprpaper.cpp +++ b/src/Hyprpaper.cpp @@ -569,12 +569,12 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { 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_pattern_t* pattern = cairo_pattern_create_for_surface(PWALLPAPERTARGET->m_pCairoSurface->cairo()); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); cairo_set_source(PCAIRO, pattern); } else { cairo_scale(PCAIRO, scale, scale); - cairo_set_source_surface(PCAIRO, PWALLPAPERTARGET->m_pCairoSurface, origin.x, origin.y); + cairo_set_source_surface(PCAIRO, PWALLPAPERTARGET->m_pCairoSurface->cairo(), origin.x, origin.y); } cairo_paint(PCAIRO); @@ -607,7 +607,7 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) { cairo_show_text(PCAIRO, SPLASH.c_str()); - cairo_surface_flush(PWALLPAPERTARGET->m_pCairoSurface); + cairo_surface_flush(PWALLPAPERTARGET->m_pCairoSurface->cairo()); } cairo_restore(PCAIRO); diff --git a/src/helpers/Bmp.cpp b/src/helpers/Bmp.cpp deleted file mode 100644 index b92460d..0000000 --- a/src/helpers/Bmp.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#include "Bmp.hpp" - -#include -#include -#include -#include - -class BmpHeader { - public: - unsigned char format[2]; - uint32_t sizeOfFile; - uint16_t reserved1; - uint16_t reserved2; - uint32_t dataOffset; - uint32_t sizeOfBitmapHeader; - uint32_t width; - uint32_t height; - uint16_t numberOfColors; - uint16_t numberOfBitPerPixel; - uint32_t compressionMethod; - uint32_t imageSize; - uint32_t horizontalResolutionPPM; - uint32_t verticalResolutionPPM; - uint32_t numberOfCollors; - uint32_t numberOfImportantCollors; - - BmpHeader(std::ifstream& file) { - file.seekg(0, std::ios::end); - uint32_t streamLength = file.tellg(); - file.seekg(0, std::ios::beg); - - file.read(reinterpret_cast(&format), sizeof(format)); - if (!(format[0] == 66 && format[1] == 77)) { - Debug::log(ERR, "Unable to parse bitmap header: wrong bmp file type"); - exit(1); - } - - file.read(reinterpret_cast(&sizeOfFile), sizeof(sizeOfFile)); - - if (sizeOfFile != streamLength) { - Debug::log(ERR, "Unable to parse bitmap header: wrong value of file size header"); - exit(1); - } - - file.read(reinterpret_cast(&reserved1), sizeof(reserved1)); - file.read(reinterpret_cast(&reserved2), sizeof(reserved2)); - file.read(reinterpret_cast(&dataOffset), sizeof(dataOffset)); - file.read(reinterpret_cast(&sizeOfBitmapHeader), sizeof(sizeOfBitmapHeader)); - file.read(reinterpret_cast(&width), sizeof(width)); - file.read(reinterpret_cast(&height), sizeof(height)); - file.read(reinterpret_cast(&numberOfColors), sizeof(numberOfColors)); - file.read(reinterpret_cast(&numberOfBitPerPixel), sizeof(numberOfBitPerPixel)); - file.read(reinterpret_cast(&compressionMethod), sizeof(compressionMethod)); - file.read(reinterpret_cast(&imageSize), sizeof(imageSize)); - file.read(reinterpret_cast(&horizontalResolutionPPM), sizeof(horizontalResolutionPPM)); - file.read(reinterpret_cast(&verticalResolutionPPM), sizeof(verticalResolutionPPM)); - file.read(reinterpret_cast(&numberOfCollors), sizeof(numberOfCollors)); - file.read(reinterpret_cast(&numberOfImportantCollors), sizeof(numberOfImportantCollors)); - - if (!imageSize) - imageSize = sizeOfFile - dataOffset; - - if (imageSize != (width * height * numberOfBitPerPixel / 8)) { - Debug::log(ERR, "Unable to parse bitmap header: wrong image size"); - exit(1); - } - - file.seekg(dataOffset); - }; -}; - -void reflectImage(unsigned char* image, uint32_t numberOfRows, int stride) { - int rowStart = 0; - int rowEnd = numberOfRows - 1; - std::vector temp; - temp.resize(stride); - while (rowStart < rowEnd) { - memcpy(&temp[0], &image[rowStart * stride], stride); - memcpy(&image[rowStart * stride], &image[rowEnd * stride], stride); - memcpy(&image[rowEnd * stride], &temp[0], stride); - rowStart++; - rowEnd--; - } -}; - -void convertRgbToArgb(std::ifstream& imageStream, unsigned char* outputImage, uint32_t newImageSize) { - uint8_t forthBitCounter = 0; - unsigned long imgCursor = 0; - while (imgCursor < newImageSize) { - imageStream.read(reinterpret_cast(&outputImage[imgCursor]), 1); - imgCursor++; - forthBitCounter++; - if (forthBitCounter == 3) { - outputImage[imgCursor] = 0; - imgCursor++; - forthBitCounter = 0; - } - } -}; - -cairo_surface_t* BMP::createSurfaceFromBMP(const std::string& path) { - - if (!std::filesystem::exists(path)) { - Debug::log(ERR, "createSurfaceFromBMP: file doesn't exist??"); - exit(1); - } - - std::ifstream bitmapImageStream(path); - BmpHeader bitmapHeader(bitmapImageStream); - - cairo_format_t format = CAIRO_FORMAT_ARGB32; - int stride = cairo_format_stride_for_width(format, bitmapHeader.width); - unsigned char* imageData = (unsigned char*)malloc(bitmapHeader.height * stride); - - if (bitmapHeader.numberOfBitPerPixel == 24) - convertRgbToArgb(bitmapImageStream, imageData, bitmapHeader.height * stride); - else if (bitmapHeader.numberOfBitPerPixel == 32) - bitmapImageStream.read(reinterpret_cast(&imageData), bitmapHeader.imageSize); - else { - Debug::log(ERR, "createSurfaceFromBMP: unsupported bmp format"); - bitmapImageStream.close(); - exit(1); - } - bitmapImageStream.close(); - reflectImage(imageData, bitmapHeader.height, stride); - return cairo_image_surface_create_for_data(imageData, format, bitmapHeader.width, bitmapHeader.height, stride); -} \ No newline at end of file diff --git a/src/helpers/Bmp.hpp b/src/helpers/Bmp.hpp deleted file mode 100644 index c36e499..0000000 --- a/src/helpers/Bmp.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "../defines.hpp" - -namespace BMP { - cairo_surface_t* createSurfaceFromBMP(const std::string&); -}; \ No newline at end of file diff --git a/src/helpers/Jpeg.cpp b/src/helpers/Jpeg.cpp deleted file mode 100644 index e26e693..0000000 --- a/src/helpers/Jpeg.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "Jpeg.hpp" - -#include -#include - -cairo_surface_t* JPEG::createSurfaceFromJPEG(const std::string& path) { - - if (!std::filesystem::exists(path)) { - Debug::log(ERR, "createSurfaceFromJPEG: file doesn't exist??"); - exit(1); - } - - if (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__) { - Debug::log(CRIT, "tried to load a jpeg on a big endian system! ping vaxry he is lazy."); - exit(1); - } - - std::ifstream file(path, std::ios::binary | std::ios::ate); - file.exceptions(std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit); - std::vector bytes(file.tellg()); - file.seekg(0); - file.read(reinterpret_cast(bytes.data()), bytes.size()); - - // now the JPEG is in the memory - - jpeg_decompress_struct decompressStruct = {}; - jpeg_error_mgr errorManager = {}; - - decompressStruct.err = jpeg_std_error(&errorManager); - jpeg_create_decompress(&decompressStruct); - jpeg_mem_src(&decompressStruct, bytes.data(), bytes.size()); - jpeg_read_header(&decompressStruct, true); - -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - decompressStruct.out_color_space = JCS_EXT_BGRA; -#else - decompressStruct.out_color_space = JCS_EXT_ARGB; -#endif - - // decompress - jpeg_start_decompress(&decompressStruct); - - auto cairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, decompressStruct.output_width, decompressStruct.output_height); - - if (cairo_surface_status(cairoSurface) != CAIRO_STATUS_SUCCESS) { - Debug::log(ERR, "createSurfaceFromJPEG: Cairo Failed (?)"); - exit(1); - } - - const auto CAIRODATA = cairo_image_surface_get_data(cairoSurface); - const auto CAIROSTRIDE = cairo_image_surface_get_stride(cairoSurface); - JSAMPROW rowRead; - - while (decompressStruct.output_scanline < decompressStruct.output_height) { - const auto PROW = CAIRODATA + (decompressStruct.output_scanline * CAIROSTRIDE); - rowRead = PROW; - jpeg_read_scanlines(&decompressStruct, &rowRead, 1); - } - - cairo_surface_mark_dirty(cairoSurface); - cairo_surface_set_mime_data(cairoSurface, CAIRO_MIME_TYPE_JPEG, bytes.data(), bytes.size(), nullptr, nullptr); - jpeg_finish_decompress(&decompressStruct); - jpeg_destroy_decompress(&decompressStruct); - - return cairoSurface; -} diff --git a/src/helpers/Jpeg.hpp b/src/helpers/Jpeg.hpp deleted file mode 100644 index b217ec0..0000000 --- a/src/helpers/Jpeg.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "../defines.hpp" -#include - -namespace JPEG { - cairo_surface_t* createSurfaceFromJPEG(const std::string&); -}; \ No newline at end of file diff --git a/src/helpers/JpegXL.cpp b/src/helpers/JpegXL.cpp deleted file mode 100644 index 1174fc5..0000000 --- a/src/helpers/JpegXL.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include "JpegXL.hpp" - -#include -#include -#include -#include - -cairo_surface_t* JXL::createSurfaceFromJXL(const std::string& path) { - - if (!std::filesystem::exists(path)) { - Debug::log(ERR, "createSurfaceFromJXL: file doesn't exist??"); - exit(1); - } - - std::ifstream file(path, std::ios::binary | std::ios::ate); - file.exceptions(std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit); - std::vector bytes(file.tellg()); - file.seekg(0); - file.read(reinterpret_cast(bytes.data()), bytes.size()); - - JxlSignature signature = JxlSignatureCheck(bytes.data(), bytes.size()); - if (signature != JXL_SIG_CODESTREAM && signature != JXL_SIG_CONTAINER) { - Debug::log(ERR, "createSurfaceFromJXL: file is not JXL format"); - exit(1); - } - - auto dec = JxlDecoderMake(nullptr); - auto runner = JxlResizableParallelRunnerMake(nullptr); - if (JXL_DEC_SUCCESS != JxlDecoderSetParallelRunner(dec.get(), JxlResizableParallelRunner, runner.get())) { - Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderSetParallelRunner failed"); - exit(1); - } - - if (JXL_DEC_SUCCESS != JxlDecoderSubscribeEvents(dec.get(), JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE)) { - Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderSubscribeEvents failed"); - exit(1); - } - - JxlDecoderSetInput(dec.get(), bytes.data(), bytes.size()); - JxlDecoderCloseInput(dec.get()); - if (JXL_DEC_BASIC_INFO != JxlDecoderProcessInput(dec.get())) { - Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderProcessInput failed"); - exit(1); - } - - JxlBasicInfo basicInfo; - if (JXL_DEC_SUCCESS != JxlDecoderGetBasicInfo(dec.get(), &basicInfo)) { - Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderGetBasicInfo failed"); - exit(1); - } - - auto cairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, basicInfo.xsize, basicInfo.ysize); - if (cairo_surface_status(cairoSurface) != CAIRO_STATUS_SUCCESS) { - Debug::log(ERR, "createSurfaceFromJXL: Cairo Failed (?)"); - cairo_surface_destroy(cairoSurface); - exit(1); - } - - const auto CAIRODATA = cairo_image_surface_get_data(cairoSurface); - - JxlPixelFormat format = { - .num_channels = 4, - .data_type = JXL_TYPE_UINT8, - .endianness = JXL_LITTLE_ENDIAN, - .align = cairo_image_surface_get_stride(cairoSurface), - }; - - const auto OUTPUTSIZE = basicInfo.xsize * basicInfo.ysize * format.num_channels; - - for (;;) { - JxlDecoderStatus status = JxlDecoderProcessInput(dec.get()); - if (status == JXL_DEC_ERROR) { - Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderProcessInput failed"); - cairo_surface_destroy(cairoSurface); - exit(1); - } else if (status == JXL_DEC_NEED_MORE_INPUT) { - Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderProcessInput expected more input"); - cairo_surface_destroy(cairoSurface); - exit(1); - } else if (status == JXL_DEC_NEED_IMAGE_OUT_BUFFER) { - JxlResizableParallelRunnerSetThreads(runner.get(), JxlResizableParallelRunnerSuggestThreads(basicInfo.xsize, basicInfo.ysize)); - size_t bufferSize; - if (JXL_DEC_SUCCESS != JxlDecoderImageOutBufferSize(dec.get(), &format, &bufferSize)) { - Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderImageOutBufferSize failed"); - cairo_surface_destroy(cairoSurface); - exit(1); - } - if (bufferSize != OUTPUTSIZE) { - Debug::log(ERR, "createSurfaceFromJXL: invalid output buffer size"); - cairo_surface_destroy(cairoSurface); - exit(1); - } - if (JXL_DEC_SUCCESS != JxlDecoderSetImageOutBuffer(dec.get(), &format, CAIRODATA, bufferSize)) { - Debug::log(ERR, "createSurfaceFromJXL: JxlDecoderSetImageOutBuffer failed"); - cairo_surface_destroy(cairoSurface); - exit(1); - } - } else if (status == JXL_DEC_FULL_IMAGE) { - for (size_t i = 0; i < OUTPUTSIZE - 2; i += format.num_channels) { - std::swap(CAIRODATA[i + 0], CAIRODATA[i + 2]); - } - cairo_surface_mark_dirty(cairoSurface); - cairo_surface_set_mime_data(cairoSurface, "image/jxl", bytes.data(), bytes.size(), nullptr, nullptr); - return cairoSurface; - } - } -} diff --git a/src/helpers/JpegXL.hpp b/src/helpers/JpegXL.hpp deleted file mode 100644 index f4ef60f..0000000 --- a/src/helpers/JpegXL.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "../defines.hpp" - -namespace JXL { - cairo_surface_t* createSurfaceFromJXL(const std::string&); -}; diff --git a/src/helpers/Webp.cpp b/src/helpers/Webp.cpp deleted file mode 100644 index 812d5cd..0000000 --- a/src/helpers/Webp.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "Webp.hpp" - -#include -#include -#include - -cairo_surface_t* WEBP::createSurfaceFromWEBP(const std::string& path) { - - if (!std::filesystem::exists(path)) { - Debug::log(ERR, "createSurfaceFromWEBP: file doesn't exist??"); - exit(1); - } - - std::ifstream file(path, std::ios::binary | std::ios::ate); - file.exceptions(std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit); - std::vector bytes(file.tellg()); - file.seekg(0); - file.read(reinterpret_cast(bytes.data()), bytes.size()); - - // now the WebP is in the memory - - WebPDecoderConfig config; - if (!WebPInitDecoderConfig(&config)) { - Debug::log(CRIT, "WebPInitDecoderConfig Failed"); - exit(1); - } - - if (WebPGetFeatures(bytes.data(), bytes.size(), &config.input) != VP8_STATUS_OK) { - Debug::log(ERR, "createSurfaceFromWEBP: file is not webp format"); - exit(1); - } - - const auto HEIGHT = config.input.height; - const auto WIDTH = config.input.width; - - auto cairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, WIDTH, HEIGHT); - if (cairo_surface_status(cairoSurface) != CAIRO_STATUS_SUCCESS) { - Debug::log(CRIT, "createSurfaceFromWEBP: Cairo Failed (?)"); - cairo_surface_destroy(cairoSurface); - exit(1); - } - -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - config.output.colorspace = MODE_bgrA; -#else - config.output.colorspace = MODE_Argb; -#endif - - const auto CAIRODATA = cairo_image_surface_get_data(cairoSurface); - const auto CAIROSTRIDE = cairo_image_surface_get_stride(cairoSurface); - - config.options.no_fancy_upsampling = 1; - config.output.u.RGBA.rgba = CAIRODATA; - config.output.u.RGBA.stride = CAIROSTRIDE; - config.output.u.RGBA.size = CAIROSTRIDE * HEIGHT; - config.output.is_external_memory = 1; - config.output.width = WIDTH; - config.output.height = HEIGHT; - - if (WebPDecode(bytes.data(), bytes.size(), &config) != VP8_STATUS_OK) { - Debug::log(CRIT, "createSurfaceFromWEBP: WebP Decode Failed (?)"); - exit(1); - } - - cairo_surface_mark_dirty(cairoSurface); - cairo_surface_set_mime_data(cairoSurface, "image/webp", bytes.data(), bytes.size(), nullptr, nullptr); - - WebPFreeDecBuffer(&config.output); - - return cairoSurface; -} diff --git a/src/helpers/Webp.hpp b/src/helpers/Webp.hpp deleted file mode 100644 index bc09611..0000000 --- a/src/helpers/Webp.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "../defines.hpp" - -namespace WEBP { - cairo_surface_t* createSurfaceFromWEBP(const std::string&); -}; diff --git a/src/render/WallpaperTarget.cpp b/src/render/WallpaperTarget.cpp index f64fdf0..b5e7773 100644 --- a/src/render/WallpaperTarget.cpp +++ b/src/render/WallpaperTarget.cpp @@ -1,10 +1,11 @@ #include "WallpaperTarget.hpp" #include -#include +#include +using namespace Hyprgraphics; CWallpaperTarget::~CWallpaperTarget() { - cairo_surface_destroy(m_pCairoSurface); + ; } void CWallpaperTarget::create(const std::string& path) { @@ -12,52 +13,17 @@ void CWallpaperTarget::create(const std::string& path) { const auto BEGINLOAD = std::chrono::system_clock::now(); - cairo_surface_t* CAIROSURFACE = nullptr; - const auto len = path.length(); - if (path.find(".png") == len - 4 || path.find(".PNG") == len - 4) { - CAIROSURFACE = cairo_image_surface_create_from_png(path.c_str()); - } else if (path.find(".jpg") == len - 4 || path.find(".JPG") == len - 4 || path.find(".jpeg") == len - 5 || path.find(".JPEG") == len - 5) { - CAIROSURFACE = JPEG::createSurfaceFromJPEG(path); - m_bHasAlpha = false; - } else if (path.find(".bmp") == len - 4 || path.find(".BMP") == len - 4) { - CAIROSURFACE = BMP::createSurfaceFromBMP(path); - m_bHasAlpha = false; - } else if (path.find(".webp") == len - 5 || path.find(".WEBP") == len - 5) { - CAIROSURFACE = WEBP::createSurfaceFromWEBP(path); - } else if (path.find(".jxl") == len - 4 || path.find(".JXL") == len - 4) { - CAIROSURFACE = JXL::createSurfaceFromJXL(path); - } else { - // magic is slow, so only use it when no recognized extension is found - auto handle = magic_open(MAGIC_NONE | MAGIC_COMPRESS); - magic_load(handle, nullptr); - - const auto type_str = std::string(magic_file(handle, path.c_str())); - const auto first_word = type_str.substr(0, type_str.find(" ")); - - if (first_word == "PNG") { - CAIROSURFACE = cairo_image_surface_create_from_png(path.c_str()); - } else if (first_word == "JPEG") { - CAIROSURFACE = JPEG::createSurfaceFromJPEG(path); - m_bHasAlpha = false; - } else if (first_word == "BMP") { - CAIROSURFACE = BMP::createSurfaceFromBMP(path); - m_bHasAlpha = false; - } else { - Debug::log(CRIT, "unrecognized image %s", path.c_str()); - exit(1); - } - } - - if (cairo_surface_status(CAIROSURFACE) != CAIRO_STATUS_SUCCESS) { - Debug::log(CRIT, "Failed to read image %s because of:\n%s", path.c_str(), cairo_status_to_string(cairo_surface_status(CAIROSURFACE))); + auto loadedImage = CImage(path); + if (!loadedImage.success()) { + Debug::log(CRIT, "Cannot load image %s: %s", path.c_str(), loadedImage.getError().c_str()); exit(1); } - m_vSize = {cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)}; + m_vSize = loadedImage.cairoSurface()->size(); 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); - m_pCairoSurface = CAIROSURFACE; + m_pCairoSurface = loadedImage.cairoSurface(); } diff --git a/src/render/WallpaperTarget.hpp b/src/render/WallpaperTarget.hpp index 0c79a32..7d352d2 100644 --- a/src/render/WallpaperTarget.hpp +++ b/src/render/WallpaperTarget.hpp @@ -1,22 +1,19 @@ #pragma once #include "../defines.hpp" -#include "../helpers/Jpeg.hpp" -#include "../helpers/Bmp.hpp" -#include "../helpers/Webp.hpp" -#include "../helpers/JpegXL.hpp" +#include class CWallpaperTarget { public: ~CWallpaperTarget(); - void create(const std::string& path); + void create(const std::string& path); - std::string m_szPath; + std::string m_szPath; - Vector2D m_vSize; + Vector2D m_vSize; - bool m_bHasAlpha = true; + bool m_bHasAlpha = true; - cairo_surface_t* m_pCairoSurface; + SP m_pCairoSurface; };