/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Some of this code is based on Skia source code, covered by the following * license notice (see readlicense_oo for the full license): * * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * */ #include #include #include #include #include #include #include #include using namespace SkiaHelper; namespace SkiaHelper { CGImageRef createCGImage(const Image& rImage) { BitmapEx bitmapEx(rImage.GetBitmapEx()); Bitmap bitmap(bitmapEx.GetBitmap()); if (bitmap.IsEmpty() || !bitmap.ImplGetSalBitmap()) return nullptr; assert(dynamic_cast(bitmap.ImplGetSalBitmap().get()) != nullptr); SkiaSalBitmap* skiaBitmap = static_cast(bitmap.ImplGetSalBitmap().get()); SkBitmap targetBitmap; if (!targetBitmap.tryAllocPixels( SkImageInfo::Make(bitmap.GetSizePixel().getWidth(), bitmap.GetSizePixel().getHeight(), kRGBA_8888_SkColorType, kPremul_SkAlphaType))) return nullptr; SkPaint paint; paint.setBlendMode(SkBlendMode::kSrc); // set as is SkMatrix matrix; // The image is needed upside-down. matrix.preTranslate(0, targetBitmap.height()); matrix.setConcat(matrix, SkMatrix::Scale(1, -1)); if (!bitmapEx.IsAlpha()) { SkCanvas canvas(targetBitmap); canvas.concat(matrix); canvas.drawImage(skiaBitmap->GetSkImage(), 0, 0, SkSamplingOptions(), &paint); } else { AlphaMask alpha(bitmapEx.GetAlphaMask()); // tdf#156854 invert alpha mask for macOS native menu item images // At the time of this change, only the AquaSalMenu class calls this // function so it should be safe to invert the alpha mask here. alpha.Invert(); Bitmap alphaBitmap(alpha.GetBitmap()); assert(dynamic_cast(alphaBitmap.ImplGetSalBitmap().get()) != nullptr); SkiaSalBitmap* skiaAlpha = static_cast(alphaBitmap.ImplGetSalBitmap().get()); #if 0 // Drawing to a bitmap using a shader from a GPU-backed image fails silently. // https://bugs.chromium.org/p/skia/issues/detail?id=12685 paint.setShader(SkShaders::Blend(SkBlendMode::kDstOut, skiaBitmap->GetSkShader(SkSamplingOptions()), skiaAlpha->GetAlphaSkShader(SkSamplingOptions()))); #else sk_sp imB = skiaBitmap->GetSkImage()->makeNonTextureImage(); sk_sp imA = skiaAlpha->GetAlphaSkImage()->makeNonTextureImage(); paint.setShader(SkShaders::Blend(SkBlendMode::kDstOut, imB->makeShader(SkSamplingOptions()), imA->makeShader(SkSamplingOptions()))); #endif SkCanvas canvas(targetBitmap); canvas.concat(matrix); canvas.drawPaint(paint); } CGContextRef context = CGBitmapContextCreate( targetBitmap.getAddr32(0, 0), targetBitmap.width(), targetBitmap.height(), 8, targetBitmap.rowBytes(), GetSalData()->mxRGBSpace, kCGImageAlphaPremultipliedLast); if (!context) return nullptr; CGImageRef screenImage = CGBitmapContextCreateImage(context); CFRelease(context); return screenImage; } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */