handle Skia not drawing GPU-backend shader to a bitmap (tdf#145797)
[LibreOffice.git] / vcl / skia / osx / bitmap.cxx
blob16d32191a62702589e53a569e8f54de4b4e079a3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * Some of this code is based on Skia source code, covered by the following
10 * license notice (see readlicense_oo for the full license):
12 * Copyright 2016 Google Inc.
14 * Use of this source code is governed by a BSD-style license that can be
15 * found in the LICENSE file.
19 #include <skia/osx/bitmap.hxx>
21 #include <vcl/bitmapex.hxx>
22 #include <vcl/image.hxx>
24 #include <skia/salbmp.hxx>
25 #include <osx/saldata.hxx>
27 #include <SkBitmap.h>
28 #include <SkCanvas.h>
30 using namespace SkiaHelper;
32 namespace SkiaHelper
34 CGImageRef createCGImage(const Image& rImage)
36 BitmapEx bitmapEx(rImage.GetBitmapEx());
37 Bitmap bitmap(bitmapEx.GetBitmap());
39 if (bitmap.IsEmpty() || !bitmap.ImplGetSalBitmap())
40 return nullptr;
42 assert(dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get()) != nullptr);
43 SkiaSalBitmap* skiaBitmap = static_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
45 SkBitmap targetBitmap;
46 if (!targetBitmap.tryAllocPixels(
47 SkImageInfo::Make(bitmap.GetSizePixel().getWidth(), bitmap.GetSizePixel().getHeight(),
48 kRGBA_8888_SkColorType, kPremul_SkAlphaType)))
49 return nullptr;
50 SkPaint paint;
51 paint.setBlendMode(SkBlendMode::kSrc); // set as is
52 SkMatrix matrix; // The image is needed upside-down.
53 matrix.preTranslate(0, targetBitmap.height());
54 matrix.setConcat(matrix, SkMatrix::Scale(1, -1));
56 if (!bitmapEx.IsAlpha())
58 SkCanvas canvas(targetBitmap);
59 canvas.concat(matrix);
60 canvas.drawImage(skiaBitmap->GetSkImage(), 0, 0, SkSamplingOptions(), &paint);
62 else
64 AlphaMask alpha(bitmapEx.GetAlpha());
65 Bitmap alphaBitmap(alpha.GetBitmap());
66 assert(dynamic_cast<SkiaSalBitmap*>(alphaBitmap.ImplGetSalBitmap().get()) != nullptr);
67 SkiaSalBitmap* skiaAlpha
68 = static_cast<SkiaSalBitmap*>(alphaBitmap.ImplGetSalBitmap().get());
69 #if 0
70 // Drawing to a bitmap using a shader from a GPU-backed image fails silently.
71 // https://bugs.chromium.org/p/skia/issues/detail?id=12685
72 paint.setShader(SkShaders::Blend(SkBlendMode::kDstOut,
73 skiaBitmap->GetSkShader(SkSamplingOptions()),
74 skiaAlpha->GetAlphaSkShader(SkSamplingOptions())));
75 #else
76 sk_sp<SkImage> imB = skiaBitmap->GetSkImage()->makeNonTextureImage();
77 sk_sp<SkImage> imA = skiaAlpha->GetAlphaSkImage()->makeNonTextureImage();
78 paint.setShader(SkShaders::Blend(SkBlendMode::kDstOut, imB->makeShader(SkSamplingOptions()),
79 imA->makeShader(SkSamplingOptions())));
80 #endif
81 SkCanvas canvas(targetBitmap);
82 canvas.concat(matrix);
83 canvas.drawPaint(paint);
86 CGContextRef context = CGBitmapContextCreate(
87 targetBitmap.getAddr32(0, 0), targetBitmap.width(), targetBitmap.height(), 8,
88 targetBitmap.rowBytes(), GetSalData()->mxRGBSpace, kCGImageAlphaPremultipliedLast);
89 if (!context)
90 return nullptr;
91 CGImageRef screenImage = CGBitmapContextCreateImage(context);
92 CFRelease(context);
93 return screenImage;
97 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */