diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2020-09-05 07:05:16 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2020-09-07 15:19:32 +0200 |
commit | 717ce6838b7ef0add1f9a9655e2b8c0bf60203f0 (patch) | |
tree | 0b887e4a06120dea3fff1788a337365d427441e8 /vcl/skia/gdiimpl.cxx | |
parent | 23762a704133051184850fc711e44bc9a112f59a (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.cxx | 92 |
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; } |