core: add nominal size

This commit is contained in:
Vaxry 2024-12-18 15:42:49 +00:00
parent f388aacd22
commit 06060bb27d
5 changed files with 33 additions and 18 deletions

View file

@ -54,6 +54,7 @@ struct SCursorRawShapeDataC {
char* overridenBy; char* overridenBy;
enum eHyprcursorResizeAlgo resizeAlgo; enum eHyprcursorResizeAlgo resizeAlgo;
enum eHyprcursorDataType type; enum eHyprcursorDataType type;
float nominalSize;
}; };
typedef struct SCursorRawShapeDataC hyprcursor_cursor_raw_shape_data; typedef struct SCursorRawShapeDataC hyprcursor_cursor_raw_shape_data;

View file

@ -307,13 +307,15 @@ SCursorImageData** CHyprcursorManager::getShapesC(int& outSize, const char* shap
if (REQUESTEDSHAPE != shape->directory && std::find(shape->overrides.begin(), shape->overrides.end(), REQUESTEDSHAPE) == shape->overrides.end()) if (REQUESTEDSHAPE != shape->directory && std::find(shape->overrides.begin(), shape->overrides.end(), REQUESTEDSHAPE) == shape->overrides.end())
continue; continue;
const int PIXELSIDE = std::round(info.size / shape->nominalSize);
hotX = shape->hotspotX; hotX = shape->hotspotX;
hotY = shape->hotspotY; hotY = shape->hotspotY;
// 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) if (image->side != PIXELSIDE)
continue; continue;
// found size // found size
@ -333,7 +335,7 @@ SCursorImageData** CHyprcursorManager::getShapesC(int& outSize, const char* shap
// find nearest // find nearest
int leader = 13371337; int leader = 13371337;
for (auto& image : impl->loadedShapes[shape.get()].images) { for (auto& image : impl->loadedShapes[shape.get()].images) {
if (std::abs((int)(image->side - info.size)) > std::abs((int)(leader - info.size))) if (std::abs((int)(image->side - PIXELSIDE)) > std::abs((int)(leader - PIXELSIDE)))
continue; continue;
leader = image->side; leader = image->side;
@ -392,8 +394,9 @@ SCursorRawShapeDataC* CHyprcursorManager::getRawShapeDataC(const char* shape_) {
data->overridenBy = nullptr; data->overridenBy = nullptr;
data->images = nullptr; data->images = nullptr;
data->len = 0; data->len = 0;
data->hotspotX = 0; data->hotspotX = 0.f;
data->hotspotY = 0; data->hotspotY = 0.F;
data->nominalSize = 1.F;
data->resizeAlgo = eHyprcursorResizeAlgo::HC_RESIZE_NONE; data->resizeAlgo = eHyprcursorResizeAlgo::HC_RESIZE_NONE;
data->type = eHyprcursorDataType::HC_DATA_PNG; data->type = eHyprcursorDataType::HC_DATA_PNG;
@ -418,9 +421,10 @@ SCursorRawShapeDataC* CHyprcursorManager::getRawShapeDataC(const char* shape_) {
resultingImages.push_back(i.get()); resultingImages.push_back(i.get());
} }
data->hotspotX = shape->hotspotX; data->hotspotX = shape->hotspotX;
data->hotspotY = shape->hotspotY; data->hotspotY = shape->hotspotY;
data->type = shape->shapeType == SHAPE_PNG ? HC_DATA_PNG : HC_DATA_SVG; data->nominalSize = shape->nominalSize;
data->type = shape->shapeType == SHAPE_PNG ? HC_DATA_PNG : HC_DATA_SVG;
break; break;
} }
@ -494,12 +498,16 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
Debug::log(HC_LOG_TRACE, logFn, "loadThemeStyle: png shape {} has {} frames", shape->directory, FRAMES.size()); Debug::log(HC_LOG_TRACE, logFn, "loadThemeStyle: png shape {} has {} frames", shape->directory, FRAMES.size());
const int PIXELSIDE = std::round(info.size / shape->nominalSize);
Debug::log(HC_LOG_TRACE, logFn, "loadThemeStyle: png shape has nominal {:.2f}, pixel size will be {}x", shape->nominalSize, PIXELSIDE);
for (auto& f : FRAMES) { 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 = PIXELSIDE;
newImage->artificialData = new char[info.size * info.size * 4]; newImage->artificialData = new char[PIXELSIDE * PIXELSIDE * 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, PIXELSIDE, PIXELSIDE, PIXELSIDE * 4);
newImage->delay = f->delay; newImage->delay = f->delay;
const auto PCAIRO = cairo_create(newImage->cairoSurface); const auto PCAIRO = cairo_create(newImage->cairoSurface);
@ -513,12 +521,12 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
const auto PTN = cairo_pattern_create_for_surface(f->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)f->side; const float scale = PIXELSIDE / (float)f->side;
cairo_scale(PCAIRO, scale, scale); cairo_scale(PCAIRO, scale, scale);
cairo_pattern_set_filter(PTN, shape->resizeAlgo == HC_RESIZE_BILINEAR ? CAIRO_FILTER_GOOD : CAIRO_FILTER_NEAREST); cairo_pattern_set_filter(PTN, shape->resizeAlgo == HC_RESIZE_BILINEAR ? CAIRO_FILTER_GOOD : CAIRO_FILTER_NEAREST);
cairo_set_source(PCAIRO, PTN); cairo_set_source(PCAIRO, PTN);
cairo_rectangle(PCAIRO, 0, 0, info.size, info.size); cairo_rectangle(PCAIRO, 0, 0, PIXELSIDE, PIXELSIDE);
cairo_fill(PCAIRO); cairo_fill(PCAIRO);
cairo_surface_flush(newImage->cairoSurface); cairo_surface_flush(newImage->cairoSurface);
@ -531,12 +539,16 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
Debug::log(HC_LOG_TRACE, logFn, "loadThemeStyle: svg shape {} has {} frames", shape->directory, FRAMES.size()); Debug::log(HC_LOG_TRACE, logFn, "loadThemeStyle: svg shape {} has {} frames", shape->directory, FRAMES.size());
const int PIXELSIDE = std::round(info.size / shape->nominalSize);
Debug::log(HC_LOG_TRACE, logFn, "loadThemeStyle: svg shape has nominal {:.2f}, pixel size will be {}x", shape->nominalSize, PIXELSIDE);
for (auto& f : FRAMES) { 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 = PIXELSIDE;
newImage->artificialData = new char[info.size * info.size * 4]; newImage->artificialData = new char[PIXELSIDE * PIXELSIDE * 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, PIXELSIDE, PIXELSIDE, PIXELSIDE * 4);
newImage->delay = f->delay; newImage->delay = f->delay;
const auto PCAIRO = cairo_create(newImage->cairoSurface); const auto PCAIRO = cairo_create(newImage->cairoSurface);
@ -584,7 +596,7 @@ void CHyprcursorManager::cursorSurfaceStyleDone(const SCursorStyleInfo& info) {
const bool isArtificial = e->artificial; const bool isArtificial = e->artificial;
// clean artificial rasters made for this // clean artificial rasters made for this
if (isArtificial && e->side == info.size) if (isArtificial && e->side == std::round(info.size / shape->nominalSize))
return true; return true;
// clean invalid non-svg rasters // clean invalid non-svg rasters

View file

@ -37,7 +37,7 @@ struct SCursorImage {
struct SCursorShape { struct SCursorShape {
std::string directory; std::string directory;
float hotspotX = 0, hotspotY = 0; float hotspotX = 0, hotspotY = 0, nominalSize = 1.F;
eHyprcursorResizeAlgo resizeAlgo = HC_RESIZE_NEAREST; eHyprcursorResizeAlgo resizeAlgo = HC_RESIZE_NEAREST;
std::vector<SCursorImage> images; std::vector<SCursorImage> images;
std::vector<std::string> overrides; std::vector<std::string> overrides;

View file

@ -142,6 +142,7 @@ std::optional<std::string> CMeta::parseHL() {
meta = std::make_unique<Hyprlang::CConfig>(rawdata.c_str(), Hyprlang::SConfigOptions{.pathIsStream = !dataPath}); meta = std::make_unique<Hyprlang::CConfig>(rawdata.c_str(), Hyprlang::SConfigOptions{.pathIsStream = !dataPath});
meta->addConfigValue("hotspot_x", Hyprlang::FLOAT{0.F}); meta->addConfigValue("hotspot_x", Hyprlang::FLOAT{0.F});
meta->addConfigValue("hotspot_y", Hyprlang::FLOAT{0.F}); meta->addConfigValue("hotspot_y", Hyprlang::FLOAT{0.F});
meta->addConfigValue("nominal_size", Hyprlang::FLOAT{1.F});
meta->addConfigValue("resize_algorithm", Hyprlang::STRING{"nearest"}); meta->addConfigValue("resize_algorithm", Hyprlang::STRING{"nearest"});
meta->registerHandler(::parseDefineSize, "define_size", {.allowFlags = false}); meta->registerHandler(::parseDefineSize, "define_size", {.allowFlags = false});
meta->registerHandler(::parseOverride, "define_override", {.allowFlags = false}); meta->registerHandler(::parseOverride, "define_override", {.allowFlags = false});
@ -164,6 +165,7 @@ std::optional<std::string> CMeta::parseTOML() {
parsedData.hotspotX = MANIFEST["General"]["hotspot_x"].value_or(0.f); parsedData.hotspotX = MANIFEST["General"]["hotspot_x"].value_or(0.f);
parsedData.hotspotY = MANIFEST["General"]["hotspot_y"].value_or(0.f); parsedData.hotspotY = MANIFEST["General"]["hotspot_y"].value_or(0.f);
parsedData.hotspotY = MANIFEST["General"]["nominal_size"].value_or(1.f);
const std::string OVERRIDES = MANIFEST["General"]["define_override"].value_or(""); const std::string OVERRIDES = MANIFEST["General"]["define_override"].value_or("");
const std::string SIZES = MANIFEST["General"]["define_size"].value_or(""); const std::string SIZES = MANIFEST["General"]["define_size"].value_or("");

View file

@ -20,7 +20,7 @@ class CMeta {
struct { struct {
std::string resizeAlgo; std::string resizeAlgo;
float hotspotX = 0, hotspotY = 0; float hotspotX = 0, hotspotY = 0, nominalSize = 1.F;
std::vector<std::string> overrides; std::vector<std::string> overrides;
std::vector<SDefinedSize> definedSizes; std::vector<SDefinedSize> definedSizes;
} parsedData; } parsedData;