@@ -307,13 +307,15 @@ SCursorImageData** CHyprcursorManager::getShapesC(int& outSize, const char* shap
307307 if (REQUESTEDSHAPE != shape->directory && std::find (shape->overrides .begin (), shape->overrides .end (), REQUESTEDSHAPE ) == shape->overrides .end ())
308308 continue ;
309309
310+ const int PIXELSIDE = std::round (info.size / shape->nominalSize );
311+
310312 hotX = shape->hotspotX ;
311313 hotY = shape->hotspotY ;
312314
313315 // matched :)
314316 bool foundAny = false ;
315317 for (auto & image : impl->loadedShapes [shape.get ()].images ) {
316- if (image->side != info. size )
318+ if (image->side != PIXELSIDE )
317319 continue ;
318320
319321 // found size
@@ -333,7 +335,7 @@ SCursorImageData** CHyprcursorManager::getShapesC(int& outSize, const char* shap
333335 // find nearest
334336 int leader = 13371337 ;
335337 for (auto & image : impl->loadedShapes [shape.get ()].images ) {
336- if (std::abs ((int )(image->side - info. size )) > std::abs ((int )(leader - info. size )))
338+ if (std::abs ((int )(image->side - PIXELSIDE )) > std::abs ((int )(leader - PIXELSIDE )))
337339 continue ;
338340
339341 leader = image->side ;
@@ -392,8 +394,9 @@ SCursorRawShapeDataC* CHyprcursorManager::getRawShapeDataC(const char* shape_) {
392394 data->overridenBy = nullptr ;
393395 data->images = nullptr ;
394396 data->len = 0 ;
395- data->hotspotX = 0 ;
396- data->hotspotY = 0 ;
397+ data->hotspotX = 0 .f ;
398+ data->hotspotY = 0 .F ;
399+ data->nominalSize = 1 .F ;
397400 data->resizeAlgo = eHyprcursorResizeAlgo::HC_RESIZE_NONE ;
398401 data->type = eHyprcursorDataType::HC_DATA_PNG ;
399402
@@ -418,9 +421,10 @@ SCursorRawShapeDataC* CHyprcursorManager::getRawShapeDataC(const char* shape_) {
418421 resultingImages.push_back (i.get ());
419422 }
420423
421- data->hotspotX = shape->hotspotX ;
422- data->hotspotY = shape->hotspotY ;
423- data->type = shape->shapeType == SHAPE_PNG ? HC_DATA_PNG : HC_DATA_SVG ;
424+ data->hotspotX = shape->hotspotX ;
425+ data->hotspotY = shape->hotspotY ;
426+ data->nominalSize = shape->nominalSize ;
427+ data->type = shape->shapeType == SHAPE_PNG ? HC_DATA_PNG : HC_DATA_SVG ;
424428 break ;
425429 }
426430
@@ -450,8 +454,10 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
450454 bool sizeFound = false ;
451455
452456 if (shape->shapeType == SHAPE_PNG ) {
457+ const int IDEALSIDE = std::round (info.size / shape->nominalSize );
458+
453459 for (auto & image : impl->loadedShapes [shape.get ()].images ) {
454- if (image->side != info. size )
460+ if (image->side != IDEALSIDE )
455461 continue ;
456462
457463 sizeFound = true ;
@@ -465,7 +471,7 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
465471 SLoadedCursorImage* leader = nullptr ;
466472 int leaderVal = 1000000 ;
467473 for (auto & image : impl->loadedShapes [shape.get ()].images ) {
468- if (image->side < info. size )
474+ if (image->side < IDEALSIDE )
469475 continue ;
470476
471477 if (image->side > leaderVal)
@@ -477,7 +483,7 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
477483
478484 if (!leader) {
479485 for (auto & image : impl->loadedShapes [shape.get ()].images ) {
480- if (std::abs ((int )(image->side - info. size )) > leaderVal)
486+ if (std::abs ((int )(image->side - IDEALSIDE )) > leaderVal)
481487 continue ;
482488
483489 leaderVal = image->side ;
@@ -494,12 +500,16 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
494500
495501 Debug::log (HC_LOG_TRACE , logFn, " loadThemeStyle: png shape {} has {} frames" , shape->directory , FRAMES .size ());
496502
503+ const int PIXELSIDE = std::round (leader->side / shape->nominalSize );
504+
505+ Debug::log (HC_LOG_TRACE , logFn, " loadThemeStyle: png shape has nominal {:.2f}, pixel size will be {}x" , shape->nominalSize , PIXELSIDE );
506+
497507 for (auto & f : FRAMES ) {
498508 auto & newImage = impl->loadedShapes [shape.get ()].images .emplace_back (std::make_unique<SLoadedCursorImage>());
499509 newImage->artificial = true ;
500- newImage->side = info. size ;
501- newImage->artificialData = new char [info. size * info. size * 4 ];
502- newImage->cairoSurface = cairo_image_surface_create_for_data ((unsigned char *)newImage->artificialData , CAIRO_FORMAT_ARGB32 , info. size , info. size , info. size * 4 );
510+ newImage->side = PIXELSIDE ;
511+ newImage->artificialData = new char [PIXELSIDE * PIXELSIDE * 4 ];
512+ newImage->cairoSurface = cairo_image_surface_create_for_data ((unsigned char *)newImage->artificialData , CAIRO_FORMAT_ARGB32 , PIXELSIDE , PIXELSIDE , PIXELSIDE * 4 );
503513 newImage->delay = f->delay ;
504514
505515 const auto PCAIRO = cairo_create (newImage->cairoSurface );
@@ -513,12 +523,12 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
513523
514524 const auto PTN = cairo_pattern_create_for_surface (f->cairoSurface );
515525 cairo_pattern_set_extend (PTN , CAIRO_EXTEND_NONE );
516- const float scale = info. size / (float )f->side ;
526+ const float scale = PIXELSIDE / (float )f->side ;
517527 cairo_scale (PCAIRO , scale, scale);
518528 cairo_pattern_set_filter (PTN , shape->resizeAlgo == HC_RESIZE_BILINEAR ? CAIRO_FILTER_GOOD : CAIRO_FILTER_NEAREST );
519529 cairo_set_source (PCAIRO , PTN );
520530
521- cairo_rectangle (PCAIRO , 0 , 0 , info. size , info. size );
531+ cairo_rectangle (PCAIRO , 0 , 0 , PIXELSIDE , PIXELSIDE );
522532
523533 cairo_fill (PCAIRO );
524534 cairo_surface_flush (newImage->cairoSurface );
@@ -531,12 +541,16 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
531541
532542 Debug::log (HC_LOG_TRACE , logFn, " loadThemeStyle: svg shape {} has {} frames" , shape->directory , FRAMES .size ());
533543
544+ const int PIXELSIDE = std::round (info.size / shape->nominalSize );
545+
546+ Debug::log (HC_LOG_TRACE , logFn, " loadThemeStyle: svg shape has nominal {:.2f}, pixel size will be {}x" , shape->nominalSize , PIXELSIDE );
547+
534548 for (auto & f : FRAMES ) {
535549 auto & newImage = impl->loadedShapes [shape.get ()].images .emplace_back (std::make_unique<SLoadedCursorImage>());
536550 newImage->artificial = true ;
537- newImage->side = info. size ;
538- newImage->artificialData = new char [info. size * info. size * 4 ];
539- newImage->cairoSurface = cairo_image_surface_create_for_data ((unsigned char *)newImage->artificialData , CAIRO_FORMAT_ARGB32 , info. size , info. size , info. size * 4 );
551+ newImage->side = PIXELSIDE ;
552+ newImage->artificialData = new char [PIXELSIDE * PIXELSIDE * 4 ];
553+ newImage->cairoSurface = cairo_image_surface_create_for_data ((unsigned char *)newImage->artificialData , CAIRO_FORMAT_ARGB32 , PIXELSIDE , PIXELSIDE , PIXELSIDE * 4 );
540554 newImage->delay = f->delay ;
541555
542556 const auto PCAIRO = cairo_create (newImage->cairoSurface );
@@ -554,7 +568,7 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
554568 return false ;
555569 }
556570
557- RsvgRectangle rect = {0 , 0 , (double )info. size , (double )info. size };
571+ RsvgRectangle rect = {0 , 0 , (double )PIXELSIDE , (double )PIXELSIDE };
558572
559573 if (!rsvg_handle_render_document (handle, PCAIRO , &rect, &error)) {
560574 Debug::log (HC_LOG_ERR , logFn, " Failed rendering svg: {}" , error->message );
@@ -584,7 +598,7 @@ void CHyprcursorManager::cursorSurfaceStyleDone(const SCursorStyleInfo& info) {
584598 const bool isArtificial = e->artificial ;
585599
586600 // clean artificial rasters made for this
587- if (isArtificial && e->side == info.size )
601+ if (isArtificial && e->side == std::round ( info.size / shape-> nominalSize ) )
588602 return true ;
589603
590604 // clean invalid non-svg rasters
@@ -766,10 +780,11 @@ std::optional<std::string> CHyprcursorImplementation::loadTheme() {
766780 if (SHAPE ->images .empty ())
767781 return " meta invalid: no images for shape " + cursor.path ().stem ().string ();
768782
769- SHAPE ->directory = cursor.path ().stem ().string ();
770- SHAPE ->hotspotX = meta.parsedData .hotspotX ;
771- SHAPE ->hotspotY = meta.parsedData .hotspotY ;
772- SHAPE ->resizeAlgo = stringToAlgo (meta.parsedData .resizeAlgo );
783+ SHAPE ->directory = cursor.path ().stem ().string ();
784+ SHAPE ->hotspotX = meta.parsedData .hotspotX ;
785+ SHAPE ->hotspotY = meta.parsedData .hotspotY ;
786+ SHAPE ->nominalSize = meta.parsedData .nominalSize ;
787+ SHAPE ->resizeAlgo = stringToAlgo (meta.parsedData .resizeAlgo );
773788
774789 zip_discard (zip);
775790 }
0 commit comments