@@ -424,6 +424,14 @@ namespace {
424424 return targets;
425425 }
426426
427+ [[nodiscard]] int scaleLogicalFloor (int logical, double scale) {
428+ return static_cast <int >(std::floor (static_cast <double >(logical) * scale));
429+ }
430+
431+ [[nodiscard]] int scaleLogicalCeil (int logical, double scale) {
432+ return static_cast <int >(std::ceil (static_cast <double >(logical) * scale));
433+ }
434+
427435 [[nodiscard]] std::optional<ScreencopyImage>
428436 composeGlobalRegion (LogicalRect globalRegion, std::vector<GlobalRegionPiece> pieces) {
429437 if (globalRegion.width <= 0 || globalRegion.height <= 0 || pieces.empty ()) {
@@ -446,10 +454,8 @@ namespace {
446454 });
447455 }
448456
449- const auto scaled = [canvasScale](int logical) { return static_cast <int >(std::lround (logical * canvasScale)); };
450-
451- const int canvasWidth = scaled (globalRegion.width );
452- const int canvasHeight = scaled (globalRegion.height );
457+ const int canvasWidth = scaleLogicalCeil (globalRegion.width , canvasScale);
458+ const int canvasHeight = scaleLogicalCeil (globalRegion.height , canvasScale);
453459 if (canvasWidth <= 0 || canvasHeight <= 0 ) {
454460 return std::nullopt ;
455461 }
@@ -462,10 +468,12 @@ namespace {
462468 for (auto & piece : pieces) {
463469 const int globalPieceX = piece.output ->logicalX + piece.localRegion .x ;
464470 const int globalPieceY = piece.output ->logicalY + piece.localRegion .y ;
465- const int destX = scaled (globalPieceX - globalRegion.x );
466- const int destY = scaled (globalPieceY - globalRegion.y );
467- const int targetWidth = scaled (piece.localRegion .width );
468- const int targetHeight = scaled (piece.localRegion .height );
471+ const int offsetX = globalPieceX - globalRegion.x ;
472+ const int offsetY = globalPieceY - globalRegion.y ;
473+ const int destX = scaleLogicalFloor (offsetX, canvasScale);
474+ const int destY = scaleLogicalFloor (offsetY, canvasScale);
475+ const int targetWidth = scaleLogicalCeil (offsetX + piece.localRegion .width , canvasScale) - destX;
476+ const int targetHeight = scaleLogicalCeil (offsetY + piece.localRegion .height , canvasScale) - destY;
469477 if (!resampleRgbaImage (piece.image , targetWidth, targetHeight)) {
470478 return std::nullopt ;
471479 }
@@ -507,19 +515,28 @@ namespace {
507515 minLogicalY = std::min (minLogicalY, frame.output ->logicalY );
508516 }
509517
510- const auto scaled = [canvasScale](int logical) { return static_cast <int >(std::lround (logical * canvasScale)); };
518+ const auto outputPixelRect = [canvasScale, minLogicalX, minLogicalY](const WaylandOutput& output) {
519+ const int offsetX = output.logicalX - minLogicalX;
520+ const int offsetY = output.logicalY - minLogicalY;
521+ const int x = scaleLogicalFloor (offsetX, canvasScale);
522+ const int y = scaleLogicalFloor (offsetY, canvasScale);
523+ return LogicalRect{
524+ .x = x,
525+ .y = y,
526+ .width = scaleLogicalCeil (offsetX + output.logicalWidth , canvasScale) - x,
527+ .height = scaleLogicalCeil (offsetY + output.logicalHeight , canvasScale) - y,
528+ };
529+ };
511530
512531 int canvasWidth = 0 ;
513532 int canvasHeight = 0 ;
514533 for (auto & frame : frames) {
515- const auto * out = frame.output ;
516- const int targetWidth = scaled (out->logicalWidth );
517- const int targetHeight = scaled (out->logicalHeight );
518- if (!resampleRgbaImage (frame.image , targetWidth, targetHeight)) {
534+ const LogicalRect pixelRect = outputPixelRect (*frame.output );
535+ if (!resampleRgbaImage (frame.image , pixelRect.width , pixelRect.height )) {
519536 return std::nullopt ;
520537 }
521- canvasWidth = std::max (canvasWidth, scaled (out-> logicalX - minLogicalX) + targetWidth );
522- canvasHeight = std::max (canvasHeight, scaled (out-> logicalY - minLogicalY) + targetHeight );
538+ canvasWidth = std::max (canvasWidth, pixelRect. x + pixelRect. width );
539+ canvasHeight = std::max (canvasHeight, pixelRect. y + pixelRect. height );
523540 }
524541
525542 if (canvasWidth <= 0 || canvasHeight <= 0 ) {
@@ -532,8 +549,8 @@ namespace {
532549 canvas.rgba .assign (static_cast <std::size_t >(canvasWidth) * static_cast <std::size_t >(canvasHeight) * 4U , 0 );
533550
534551 for (const auto & frame : frames) {
535- const auto * out = frame.output ;
536- blitOpaqueRgba (canvas, scaled (out-> logicalX - minLogicalX), scaled (out-> logicalY - minLogicalY) , frame.image );
552+ const LogicalRect pixelRect = outputPixelRect (* frame.output ) ;
553+ blitOpaqueRgba (canvas, pixelRect. x , pixelRect. y , frame.image );
537554 }
538555
539556 return canvas;
0 commit comments