mirror of
https://github.com/hyprwm/hyprcursor.git
synced 2024-12-22 10:19:48 +01:00
lib: fix animated types rasterization
This commit is contained in:
parent
ea1c1ff897
commit
7be76c1ae0
3 changed files with 82 additions and 65 deletions
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
};
|
|
@ -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})) {
|
||||
|
|
Loading…
Reference in a new issue