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"))
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; }
return true;
@ -205,7 +201,7 @@ SCursorImageData** CHyprcursorManager::getShapesC(int& outSize, const char* shap
// matched :)
bool foundAny = false;
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;
// found size
@ -285,13 +281,10 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
break;
}
// size wasn't found, let's resample.
if (sizeFound)
continue;
}
// size wasn't found, let's resample.
// if svg, render.
if (shape->shapeType == SHAPE_PNG) {
SLoadedCursorImage* leader = nullptr;
int leaderVal = 1000000;
for (auto& image : impl->loadedShapes[shape.get()].images) {
@ -320,69 +313,77 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
return false;
}
auto& newImage = impl->loadedShapes[shape.get()].images.emplace_back(std::make_unique<SLoadedCursorImage>());
newImage->artificial = true;
newImage->side = info.size;
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);
const auto FRAMES = impl->getFramesFor(shape.get(), leader->side);
const auto PCAIRO = cairo_create(newImage->cairoSurface);
for (auto& f : FRAMES) {
auto& newImage = impl->loadedShapes[shape.get()].images.emplace_back(std::make_unique<SLoadedCursorImage>());
newImage->artificial = true;
newImage->side = info.size;
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->delay = f->delay;
cairo_set_antialias(PCAIRO, shape->resizeAlgo == RESIZE_BILINEAR ? CAIRO_ANTIALIAS_GOOD : CAIRO_ANTIALIAS_NONE);
const auto PCAIRO = cairo_create(newImage->cairoSurface);
cairo_save(PCAIRO);
cairo_set_operator(PCAIRO, CAIRO_OPERATOR_CLEAR);
cairo_paint(PCAIRO);
cairo_restore(PCAIRO);
cairo_set_antialias(PCAIRO, shape->resizeAlgo == RESIZE_BILINEAR ? CAIRO_ANTIALIAS_GOOD : CAIRO_ANTIALIAS_NONE);
const auto PTN = cairo_pattern_create_for_surface(leader->cairoSurface);
cairo_pattern_set_extend(PTN, CAIRO_EXTEND_NONE);
const float scale = info.size / (float)leader->side;
cairo_scale(PCAIRO, scale, scale);
cairo_pattern_set_filter(PTN, shape->resizeAlgo == RESIZE_BILINEAR ? CAIRO_FILTER_GOOD : CAIRO_FILTER_NEAREST);
cairo_set_source(PCAIRO, PTN);
cairo_save(PCAIRO);
cairo_set_operator(PCAIRO, CAIRO_OPERATOR_CLEAR);
cairo_paint(PCAIRO);
cairo_restore(PCAIRO);
cairo_rectangle(PCAIRO, 0, 0, info.size, info.size);
const auto PTN = cairo_pattern_create_for_surface(f->cairoSurface);
cairo_pattern_set_extend(PTN, CAIRO_EXTEND_NONE);
const float scale = info.size / (float)f->side;
cairo_scale(PCAIRO, scale, scale);
cairo_pattern_set_filter(PTN, shape->resizeAlgo == RESIZE_BILINEAR ? CAIRO_FILTER_GOOD : CAIRO_FILTER_NEAREST);
cairo_set_source(PCAIRO, PTN);
cairo_fill(PCAIRO);
cairo_surface_flush(newImage->cairoSurface);
cairo_rectangle(PCAIRO, 0, 0, info.size, info.size);
cairo_pattern_destroy(PTN);
cairo_destroy(PCAIRO);
cairo_fill(PCAIRO);
cairo_surface_flush(newImage->cairoSurface);
cairo_pattern_destroy(PTN);
cairo_destroy(PCAIRO);
}
} else if (shape->shapeType == SHAPE_SVG) {
const auto ORIGINALSVG = impl->loadedShapes[shape.get()].images[0].get();
const auto FRAMES = impl->getFramesFor(shape.get(), 0);
auto& newImage = impl->loadedShapes[shape.get()].images.emplace_back(std::make_unique<SLoadedCursorImage>());
newImage->artificial = true;
newImage->side = info.size;
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);
for (auto& f : FRAMES) {
auto& newImage = impl->loadedShapes[shape.get()].images.emplace_back(std::make_unique<SLoadedCursorImage>());
newImage->artificial = true;
newImage->side = info.size;
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->delay = f->delay;
const auto PCAIRO = cairo_create(newImage->cairoSurface);
const auto PCAIRO = cairo_create(newImage->cairoSurface);
cairo_save(PCAIRO);
cairo_set_operator(PCAIRO, CAIRO_OPERATOR_CLEAR);
cairo_paint(PCAIRO);
cairo_restore(PCAIRO);
cairo_save(PCAIRO);
cairo_set_operator(PCAIRO, CAIRO_OPERATOR_CLEAR);
cairo_paint(PCAIRO);
cairo_restore(PCAIRO);
GError* error = nullptr;
RsvgHandle* handle = rsvg_handle_new_from_data((unsigned char*)ORIGINALSVG->data, ORIGINALSVG->dataLen, &error);
GError* error = nullptr;
RsvgHandle* handle = rsvg_handle_new_from_data((unsigned char*)f->data, f->dataLen, &error);
if (!handle) {
Debug::log(ERR, "Failed reading svg: {}", error->message);
return false;
if (!handle) {
Debug::log(ERR, "Failed reading svg: {}", error->message);
return false;
}
RsvgRectangle rect = {0, 0, (double)info.size, (double)info.size};
if (!rsvg_handle_render_document(handle, PCAIRO, &rect, &error)) {
Debug::log(ERR, "Failed rendering svg: {}", error->message);
return false;
}
// done
cairo_surface_flush(newImage->cairoSurface);
cairo_destroy(PCAIRO);
}
RsvgRectangle rect = {0, 0, (double)info.size, (double)info.size};
if (!rsvg_handle_render_document(handle, PCAIRO, &rect, &error)) {
Debug::log(ERR, "Failed rendering svg: {}", error->message);
return false;
}
// done
cairo_surface_flush(newImage->cairoSurface);
cairo_destroy(PCAIRO);
} else {
Debug::log(ERR, "Invalid shapetype in loadThemeStyle");
return false;
@ -600,8 +601,9 @@ std::optional<std::string> CHyprcursorImplementation::loadTheme() {
// load image
Debug::log(TRACE, "Loading {} for shape {}", i.filename, cursor.path().stem().string());
auto* IMAGE = LOADEDSHAPE.images.emplace_back(std::make_unique<SLoadedCursorImage>()).get();
IMAGE->side = i.size;
auto* IMAGE = LOADEDSHAPE.images.emplace_back(std::make_unique<SLoadedCursorImage>()).get();
IMAGE->side = i.size;
IMAGE->delay = i.delay;
// read from zip
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->delay = i.delay;
if (const auto STATUS = cairo_surface_status(IMAGE->cairoSurface); STATUS != CAIRO_STATUS_SUCCESS) {
delete[] (char*)IMAGE->data;
IMAGE->data = nullptr;
@ -644,4 +644,20 @@ std::optional<std::string> CHyprcursorImplementation::loadTheme() {
}
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

@ -20,7 +20,7 @@ struct SLoadedCursorImage {
size_t readNeedle = 0;
void* data = nullptr;
size_t dataLen = 0;
bool isSVG = false; // if true, data is just a string of chars
bool isSVG = false; // if true, data is just a string of chars
cairo_surface_t* cairoSurface = nullptr;
int side = 0;
@ -46,5 +46,6 @@ class CHyprcursorImplementation {
std::unordered_map<SCursorShape*, SLoadedCursorShape> loadedShapes;
//
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>
int main(int argc, char** argv) {
Hyprcursor::CHyprcursorManager mgr(nullptr);
Hyprcursor::CHyprcursorManager mgr("BIBATAWAIT");
// preload size 48 for testing
if (!mgr.loadThemeStyle(Hyprcursor::SCursorStyleInfo{.size = 48})) {