lib: fix animated types rasterization

This commit is contained in:
Vaxry 2024-03-11 21:01:14 +00:00
parent ea1c1ff897
commit 7be76c1ae0
3 changed files with 82 additions and 65 deletions

View file

@ -31,10 +31,6 @@ static bool themeAccessible(const std::string& path) {
if (!std::filesystem::exists(path + "/manifest.hl")) if (!std::filesystem::exists(path + "/manifest.hl"))
return false; return false;
const auto MANIFESTSTATUS = std::filesystem::status(path + "/manifest.hl");
if ((MANIFESTSTATUS.permissions() & std::filesystem::perms::others_read) == std::filesystem::perms::none)
return false;
} catch (std::exception& e) { return false; } } catch (std::exception& e) { return false; }
return true; return true;
@ -205,7 +201,7 @@ SCursorImageData** CHyprcursorManager::getShapesC(int& outSize, const char* shap
// matched :) // matched :)
bool foundAny = false; bool foundAny = false;
for (auto& image : impl->loadedShapes[shape.get()].images) { for (auto& image : impl->loadedShapes[shape.get()].images) {
if (image->side != info.size || (!image->artificial && shape->shapeType == SHAPE_SVG)) if (image->side != info.size)
continue; continue;
// found size // found size
@ -285,13 +281,10 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
break; break;
} }
// size wasn't found, let's resample.
if (sizeFound) if (sizeFound)
continue; continue;
}
// size wasn't found, let's resample.
// if svg, render.
if (shape->shapeType == SHAPE_PNG) {
SLoadedCursorImage* leader = nullptr; SLoadedCursorImage* leader = nullptr;
int leaderVal = 1000000; int leaderVal = 1000000;
for (auto& image : impl->loadedShapes[shape.get()].images) { for (auto& image : impl->loadedShapes[shape.get()].images) {
@ -320,11 +313,15 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
return false; return false;
} }
const auto FRAMES = impl->getFramesFor(shape.get(), leader->side);
for (auto& f : FRAMES) {
auto& newImage = impl->loadedShapes[shape.get()].images.emplace_back(std::make_unique<SLoadedCursorImage>()); auto& newImage = impl->loadedShapes[shape.get()].images.emplace_back(std::make_unique<SLoadedCursorImage>());
newImage->artificial = true; newImage->artificial = true;
newImage->side = info.size; newImage->side = info.size;
newImage->artificialData = new char[info.size * info.size * 4]; newImage->artificialData = new char[info.size * info.size * 4];
newImage->cairoSurface = cairo_image_surface_create_for_data((unsigned char*)newImage->artificialData, CAIRO_FORMAT_ARGB32, info.size, info.size, info.size * 4); newImage->cairoSurface = cairo_image_surface_create_for_data((unsigned char*)newImage->artificialData, CAIRO_FORMAT_ARGB32, info.size, info.size, info.size * 4);
newImage->delay = f->delay;
const auto PCAIRO = cairo_create(newImage->cairoSurface); const auto PCAIRO = cairo_create(newImage->cairoSurface);
@ -335,9 +332,9 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
cairo_paint(PCAIRO); cairo_paint(PCAIRO);
cairo_restore(PCAIRO); cairo_restore(PCAIRO);
const auto PTN = cairo_pattern_create_for_surface(leader->cairoSurface); const auto PTN = cairo_pattern_create_for_surface(f->cairoSurface);
cairo_pattern_set_extend(PTN, CAIRO_EXTEND_NONE); cairo_pattern_set_extend(PTN, CAIRO_EXTEND_NONE);
const float scale = info.size / (float)leader->side; const float scale = info.size / (float)f->side;
cairo_scale(PCAIRO, scale, scale); cairo_scale(PCAIRO, scale, scale);
cairo_pattern_set_filter(PTN, shape->resizeAlgo == RESIZE_BILINEAR ? CAIRO_FILTER_GOOD : CAIRO_FILTER_NEAREST); cairo_pattern_set_filter(PTN, shape->resizeAlgo == RESIZE_BILINEAR ? CAIRO_FILTER_GOOD : CAIRO_FILTER_NEAREST);
cairo_set_source(PCAIRO, PTN); cairo_set_source(PCAIRO, PTN);
@ -349,14 +346,17 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
cairo_pattern_destroy(PTN); cairo_pattern_destroy(PTN);
cairo_destroy(PCAIRO); cairo_destroy(PCAIRO);
}
} else if (shape->shapeType == SHAPE_SVG) { } else if (shape->shapeType == SHAPE_SVG) {
const auto ORIGINALSVG = impl->loadedShapes[shape.get()].images[0].get(); const auto FRAMES = impl->getFramesFor(shape.get(), 0);
for (auto& f : FRAMES) {
auto& newImage = impl->loadedShapes[shape.get()].images.emplace_back(std::make_unique<SLoadedCursorImage>()); auto& newImage = impl->loadedShapes[shape.get()].images.emplace_back(std::make_unique<SLoadedCursorImage>());
newImage->artificial = true; newImage->artificial = true;
newImage->side = info.size; newImage->side = info.size;
newImage->artificialData = new char[info.size * info.size * 4]; newImage->artificialData = new char[info.size * info.size * 4];
newImage->cairoSurface = cairo_image_surface_create_for_data((unsigned char*)newImage->artificialData, CAIRO_FORMAT_ARGB32, info.size, info.size, info.size * 4); newImage->cairoSurface = cairo_image_surface_create_for_data((unsigned char*)newImage->artificialData, CAIRO_FORMAT_ARGB32, info.size, info.size, info.size * 4);
newImage->delay = f->delay;
const auto PCAIRO = cairo_create(newImage->cairoSurface); const auto PCAIRO = cairo_create(newImage->cairoSurface);
@ -366,7 +366,7 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
cairo_restore(PCAIRO); cairo_restore(PCAIRO);
GError* error = nullptr; GError* error = nullptr;
RsvgHandle* handle = rsvg_handle_new_from_data((unsigned char*)ORIGINALSVG->data, ORIGINALSVG->dataLen, &error); RsvgHandle* handle = rsvg_handle_new_from_data((unsigned char*)f->data, f->dataLen, &error);
if (!handle) { if (!handle) {
Debug::log(ERR, "Failed reading svg: {}", error->message); Debug::log(ERR, "Failed reading svg: {}", error->message);
@ -383,6 +383,7 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
// done // done
cairo_surface_flush(newImage->cairoSurface); cairo_surface_flush(newImage->cairoSurface);
cairo_destroy(PCAIRO); cairo_destroy(PCAIRO);
}
} else { } else {
Debug::log(ERR, "Invalid shapetype in loadThemeStyle"); Debug::log(ERR, "Invalid shapetype in loadThemeStyle");
return false; return false;
@ -602,6 +603,7 @@ std::optional<std::string> CHyprcursorImplementation::loadTheme() {
Debug::log(TRACE, "Loading {} for shape {}", i.filename, cursor.path().stem().string()); Debug::log(TRACE, "Loading {} for shape {}", i.filename, cursor.path().stem().string());
auto* IMAGE = LOADEDSHAPE.images.emplace_back(std::make_unique<SLoadedCursorImage>()).get(); auto* IMAGE = LOADEDSHAPE.images.emplace_back(std::make_unique<SLoadedCursorImage>()).get();
IMAGE->side = i.size; IMAGE->side = i.size;
IMAGE->delay = i.delay;
// read from zip // read from zip
zip_file_t* image_file = zip_fopen(zip, i.filename.c_str(), ZIP_FL_UNCHANGED); zip_file_t* image_file = zip_fopen(zip, i.filename.c_str(), ZIP_FL_UNCHANGED);
@ -620,8 +622,6 @@ std::optional<std::string> CHyprcursorImplementation::loadTheme() {
IMAGE->cairoSurface = cairo_image_surface_create_from_png_stream(::readPNG, IMAGE); IMAGE->cairoSurface = cairo_image_surface_create_from_png_stream(::readPNG, IMAGE);
IMAGE->delay = i.delay;
if (const auto STATUS = cairo_surface_status(IMAGE->cairoSurface); STATUS != CAIRO_STATUS_SUCCESS) { if (const auto STATUS = cairo_surface_status(IMAGE->cairoSurface); STATUS != CAIRO_STATUS_SUCCESS) {
delete[] (char*)IMAGE->data; delete[] (char*)IMAGE->data;
IMAGE->data = nullptr; IMAGE->data = nullptr;
@ -645,3 +645,19 @@ std::optional<std::string> CHyprcursorImplementation::loadTheme() {
return {}; return {};
} }
std::vector<SLoadedCursorImage*> CHyprcursorImplementation::getFramesFor(SCursorShape* shape, int size) {
std::vector<SLoadedCursorImage*> frames;
for (auto& image : loadedShapes[shape].images) {
if (!image->isSVG && image->side != size)
continue;
if (image->artificial)
continue;
frames.push_back(image.get());
}
return frames;
}

View file

@ -47,4 +47,5 @@ class CHyprcursorImplementation {
// //
std::optional<std::string> loadTheme(); std::optional<std::string> loadTheme();
std::vector<SLoadedCursorImage*> getFramesFor(SCursorShape* shape, int size);
}; };

View file

@ -2,7 +2,7 @@
#include <hyprcursor/hyprcursor.hpp> #include <hyprcursor/hyprcursor.hpp>
int main(int argc, char** argv) { int main(int argc, char** argv) {
Hyprcursor::CHyprcursorManager mgr(nullptr); Hyprcursor::CHyprcursorManager mgr("BIBATAWAIT");
// preload size 48 for testing // preload size 48 for testing
if (!mgr.loadThemeStyle(Hyprcursor::SCursorStyleInfo{.size = 48})) { if (!mgr.loadThemeStyle(Hyprcursor::SCursorStyleInfo{.size = 48})) {