diff options
author | Patrick Luby <guibmacdev@gmail.com> | 2025-01-06 19:58:14 -0500 |
---|---|---|
committer | Patrick Luby <guibomacdev@gmail.com> | 2025-01-07 13:29:43 +0100 |
commit | 7ef881c76e656ece71cf6d1d472757edf5c1ff44 (patch) | |
tree | 7a30fc212c732cfba28a530753660132fd80da11 /vcl | |
parent | 2f870ac44b28963b5f116c3f70fb697fab0317cc (diff) |
tdf#161480 use BmpScaleFlag::NearestNeighbor when upscaling on macOS
On macOS, due to Retina window scaling, it is very common to
have Skia surfaces that are 2 times the size of their respective
output device sizes so upscaling is often the default state.
But when upscaling bitmaps on macOS with either Skia/Metal or
Skia/Raster, some distortion to color and/or alpha values is
introduced and only BmpScaleFlag::NearestNeighbor will upscale
the bitmap correctly.
Change-Id: I9cf02d3acace82751fa6e114aaecf23cbbb85c65
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/179848
Tested-by: Jenkins
Reviewed-by: Patrick Luby <guibomacdev@gmail.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/skia/gdiimpl.hxx | 9 | ||||
-rw-r--r-- | vcl/inc/skia/utils.hxx | 24 |
2 files changed, 29 insertions, 4 deletions
diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index c261e4af97c1..9ed245e7c696 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -292,7 +292,10 @@ protected: void performDrawPolyPolygon(const basegfx::B2DPolyPolygon& polygon, double transparency, bool useAA); - BmpScaleFlag goodScalingQuality() const { return SkiaHelper::goodScalingQuality(isGPU()); } + BmpScaleFlag goodScalingQuality(bool isUpscale = false) const + { + return SkiaHelper::goodScalingQuality(isGPU(), isUpscale); + } SkSamplingOptions makeSamplingOptions(const SalTwoRect& rPosAry, int scalingFactor, int srcScalingFactor = 1) { @@ -300,7 +303,9 @@ protected: } SkSamplingOptions makeSamplingOptions(const SkMatrix& matrix, int scalingFactor) { - return SkiaHelper::makeSamplingOptions(goodScalingQuality(), matrix, scalingFactor); + bool isUpscale = (matrix.getScaleX() > 1.0 || matrix.getScaleY() > 1.0); + return SkiaHelper::makeSamplingOptions(goodScalingQuality(isUpscale), matrix, + scalingFactor); } // Create SkPaint to use when drawing to the surface. It is not to be used diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index 37aedfb2165a..08d3ad4da44e 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -159,8 +159,23 @@ inline bool isUnitTestRunning(const char* name = nullptr) // In that case use only BmpScaleFlag::Default, which is bilinear+mipmap, // which should be good enough (and that's what the "super" bitmap scaling // algorithm done by VCL does as well). -inline BmpScaleFlag goodScalingQuality(bool isGPU) +inline BmpScaleFlag goodScalingQuality(bool isGPU, bool isUpscale = false) { +#ifdef MACOSX + // tdf#161480 use BmpScaleFlag::NearestNeighbor when upscaling on macOS + // On macOS, due to Retina window scaling, it is very common to + // have Skia surfaces that are 2 times the size of their respective + // output device sizes so upscaling is often the default state. + // But when upscaling bitmaps on macOS with either Skia/Metal or + // Skia/Raster, some distortion to color and/or alpha values is + // introduced and only BmpScaleFlag::NearestNeighbor will upscale + // the bitmap correctly. + if (isUpscale) + return BmpScaleFlag::NearestNeighbor; +#else + (void)isUpscale; +#endif + return isGPU ? BmpScaleFlag::BestQuality : BmpScaleFlag::Default; } @@ -235,7 +250,12 @@ inline SkSamplingOptions makeSamplingOptions(const SalTwoRect& rPosAry, int scal if (srcScalingFactor != 1) srcSize *= srcScalingFactor; if (srcSize != destSize) - return makeSamplingOptions(goodScalingQuality(isGPU), srcSize, destSize, 1); + { + bool isUpscale + = (srcSize.Width() < destSize.Width() || srcSize.Height() < destSize.Height()); + BmpScaleFlag scalingType = goodScalingQuality(isGPU, isUpscale); + return makeSamplingOptions(scalingType, srcSize, destSize, 1); + } return SkSamplingOptions(); // none } |