summaryrefslogtreecommitdiff
path: root/vcl/skia/gdiimpl.cxx
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2020-09-05 07:05:16 +0200
committerLuboš Luňák <l.lunak@collabora.com>2020-09-07 15:19:32 +0200
commit717ce6838b7ef0add1f9a9655e2b8c0bf60203f0 (patch)
tree0b887e4a06120dea3fff1788a337365d427441e8 /vcl/skia/gdiimpl.cxx
parent23762a704133051184850fc711e44bc9a112f59a (diff)
avoid temporary SkImage when merging bitmaps in Skia (tdf#136244)
The original idea was to create a temporary SkImage in order to first merge the bitmap and its alpha bitmap, otherwise scaling already while merging them could introduce artefacts because of smoothscaling the alpha. But SkShader use blends the bitmap and alpha values before the scaling, so this is actually not necessary. Change-Id: I4e351611e3c33530dd5326c542b0a191955b5109 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102068 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
Diffstat (limited to 'vcl/skia/gdiimpl.cxx')
-rw-r--r--vcl/skia/gdiimpl.cxx92
1 files changed, 24 insertions, 68 deletions
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 61f843dee609..652fea88f38e 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -1391,31 +1391,6 @@ void SkiaSalGraphicsImpl::invert(sal_uInt32 nPoints, const SalPoint* pPointArray
bool SkiaSalGraphicsImpl::drawEPS(long, long, long, long, void*, sal_uInt32) { return false; }
-static void drawBitmapToCanvas(const SkiaSalBitmap& bitmap, SkCanvas* canvas, const SkPaint& paint)
-{
- if (bitmap.PreferSkShader())
- {
- SkPaint paint2(paint);
- paint2.setShader(bitmap.GetSkShader());
- canvas->drawPaint(paint2);
- }
- else
- canvas->drawImage(bitmap.GetSkImage(), 0, 0, &paint);
-}
-
-static void drawAlphaBitmapToCanvas(const SkiaSalBitmap& bitmap, SkCanvas* canvas,
- const SkPaint& paint)
-{
- if (bitmap.PreferSkShader())
- {
- SkPaint paint2(paint);
- paint2.setShader(bitmap.GetAlphaSkShader());
- canvas->drawPaint(paint2);
- }
- else
- canvas->drawImage(bitmap.GetAlphaSkImage(), 0, 0, &paint);
-}
-
// Create SkImage from a bitmap and possibly an alpha mask (the usual VCL one-minus-alpha),
// with the given target size. Result will be possibly cached, unless disabled.
sk_sp<SkImage> SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitmap,
@@ -1477,54 +1452,35 @@ sk_sp<SkImage> SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma
assert(image->width() == targetSize.Width() && image->height() == targetSize.Height());
return image;
}
- // Combine bitmap + alpha bitmap into one temporary bitmap with alpha.
- // If scaling is needed, first apply the alpha, then scale, otherwise the scaling might affect the alpha values.
- if (alphaBitmap && targetSize != bitmap.GetSize())
+ sk_sp<SkSurface> tmpSurface = SkiaHelper::createSkSurface(targetSize);
+ if (!tmpSurface)
+ return nullptr;
+ SkCanvas* canvas = tmpSurface->getCanvas();
+ SkAutoCanvasRestore autoRestore(canvas, true);
+ SkPaint paint;
+ if (targetSize != bitmap.GetSize())
{
- sk_sp<SkSurface> mergedSurface = SkiaHelper::createSkSurface(bitmap.GetSize());
- if (!mergedSurface)
- return nullptr;
- SkPaint paint;
- paint.setBlendMode(SkBlendMode::kSrc); // copy as is, including alpha
- drawBitmapToCanvas(bitmap, mergedSurface->getCanvas(), paint);
- paint.setBlendMode(SkBlendMode::kDstOut); // VCL alpha is one-minus-alpha
- drawAlphaBitmapToCanvas(*alphaBitmap, mergedSurface->getCanvas(), paint);
- sk_sp<SkSurface> scaledSurface = SkiaHelper::createSkSurface(targetSize);
- if (!scaledSurface)
- return nullptr;
- paint.setBlendMode(SkBlendMode::kSrc); // copy as is, including alpha
+ SkMatrix matrix;
+ matrix.set(SkMatrix::kMScaleX, 1.0 * targetSize.Width() / bitmap.GetSize().Width());
+ matrix.set(SkMatrix::kMScaleY, 1.0 * targetSize.Height() / bitmap.GetSize().Height());
+ canvas->concat(matrix);
paint.setFilterQuality(kHigh_SkFilterQuality);
- scaledSurface->getCanvas()->drawImageRect(
- mergedSurface->makeImageSnapshot(),
- SkRect::MakeXYWH(0, 0, bitmap.GetSize().Width(), bitmap.GetSize().Height()),
- SkRect::MakeXYWH(0, 0, targetSize.Width(), targetSize.Height()), &paint);
- image = scaledSurface->makeImageSnapshot();
}
- else // No alpha or no scaling, scale directly.
+ if (alphaBitmap != nullptr)
{
- sk_sp<SkSurface> tmpSurface = SkiaHelper::createSkSurface(targetSize);
- if (!tmpSurface)
- return nullptr;
- SkCanvas* canvas = tmpSurface->getCanvas();
- SkAutoCanvasRestore autoRestore(canvas, true);
- SkPaint paint;
- if (targetSize != bitmap.GetSize())
- {
- SkMatrix matrix;
- matrix.set(SkMatrix::kMScaleX, 1.0 * targetSize.Width() / bitmap.GetSize().Width());
- matrix.set(SkMatrix::kMScaleY, 1.0 * targetSize.Height() / bitmap.GetSize().Height());
- canvas->concat(matrix);
- paint.setFilterQuality(kHigh_SkFilterQuality);
- }
- paint.setBlendMode(SkBlendMode::kSrc); // copy as is, including alpha
- drawBitmapToCanvas(bitmap, canvas, paint);
- if (alphaBitmap != nullptr)
- {
- paint.setBlendMode(SkBlendMode::kDstOut); // VCL alpha is one-minus-alpha
- drawAlphaBitmapToCanvas(*alphaBitmap, canvas, paint);
- }
- image = tmpSurface->makeImageSnapshot();
+ canvas->clear(SK_ColorTRANSPARENT);
+ paint.setShader(SkShaders::Blend(SkBlendMode::kDstOut, bitmap.GetSkShader(),
+ alphaBitmap->GetAlphaSkShader()));
+ canvas->drawPaint(paint);
}
+ else if (bitmap.PreferSkShader())
+ {
+ paint.setShader(bitmap.GetSkShader());
+ canvas->drawPaint(paint);
+ }
+ else
+ canvas->drawImage(bitmap.GetSkImage(), 0, 0, &paint);
+ image = tmpSurface->makeImageSnapshot();
SkiaHelper::addCachedImage(key, image);
return image;
}