mirror of
https://github.com/hyprwm/hyprcursor.git
synced 2024-12-22 18:29:48 +01:00
core: add nominal size
This commit is contained in:
parent
f388aacd22
commit
06060bb27d
5 changed files with 33 additions and 18 deletions
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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("");
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue