summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorPatrick Luby <guibmacdev@gmail.com>2025-01-06 19:58:14 -0500
committerPatrick Luby <guibomacdev@gmail.com>2025-01-07 13:29:43 +0100
commit7ef881c76e656ece71cf6d1d472757edf5c1ff44 (patch)
tree7a30fc212c732cfba28a530753660132fd80da11 /vcl
parent2f870ac44b28963b5f116c3f70fb697fab0317cc (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.hxx9
-rw-r--r--vcl/inc/skia/utils.hxx24
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
}