ladybird/Libraries/LibGfx/SkiaUtils.cpp
Aliaksandr Kalenik b86eec4a27 LibGfx: Keep ImmutableBitmap source data context-neutral
With the SkImage cache extracted, ImmutableBitmap no longer needs to
hold a SkiaBackendContext, an SkImage, or an SkBitmap. Reduce it to just
the source pixels (a Bitmap or YUVData) and a color space, so the sam
ImmutableBitmap can be consumed by any Skia context without
coordination.

Per-context locking and ensure_sk_image() are no longer needed and go
away with this change; the cache rebuilds an SkImage from the source
data the first time each bitmap is drawn against a context.
2026-05-04 20:12:21 +02:00

123 lines
5.3 KiB
C++

/*
* Copyright (c) 2024, Lucien Fiorini <lucienfiorini@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Assertions.h>
#include <LibGfx/Bitmap.h>
#include <LibGfx/ColorSpace.h>
#include <LibGfx/Filter.h>
#include <LibGfx/FilterImpl.h>
#include <LibGfx/SkiaUtils.h>
#include <core/SkBitmap.h>
#include <core/SkBlender.h>
#include <core/SkColorSpace.h>
#include <core/SkImage.h>
#include <core/SkImageFilter.h>
#include <core/SkString.h>
#include <effects/SkRuntimeEffect.h>
namespace Gfx {
SkPath to_skia_path(Path const& path)
{
return static_cast<PathImplSkia const&>(path.impl()).sk_path();
}
sk_sp<SkImageFilter> to_skia_image_filter(Gfx::Filter const& filter)
{
return filter.impl().filter;
}
sk_sp<SkImage> sk_image_from_bitmap(Bitmap const& bitmap, ColorSpace const& color_space)
{
auto info = SkImageInfo::Make(bitmap.width(), bitmap.height(), to_skia_color_type(bitmap.format()), to_skia_alpha_type(bitmap.format(), bitmap.alpha_type()), color_space.color_space<sk_sp<SkColorSpace>>());
SkBitmap sk_bitmap;
sk_bitmap.installPixels(info, const_cast<void*>(static_cast<void const*>(bitmap.scanline(0))), bitmap.pitch());
sk_bitmap.setImmutable();
return sk_bitmap.asImage();
}
sk_sp<SkBlender> to_skia_blender(Gfx::CompositingAndBlendingOperator compositing_and_blending_operator)
{
switch (compositing_and_blending_operator) {
case CompositingAndBlendingOperator::Normal:
return SkBlender::Mode(SkBlendMode::kSrcOver);
case CompositingAndBlendingOperator::Multiply:
return SkBlender::Mode(SkBlendMode::kMultiply);
case CompositingAndBlendingOperator::Screen:
return SkBlender::Mode(SkBlendMode::kScreen);
case CompositingAndBlendingOperator::Overlay:
return SkBlender::Mode(SkBlendMode::kOverlay);
case CompositingAndBlendingOperator::Darken:
return SkBlender::Mode(SkBlendMode::kDarken);
case CompositingAndBlendingOperator::Lighten:
return SkBlender::Mode(SkBlendMode::kLighten);
case CompositingAndBlendingOperator::ColorDodge:
return SkBlender::Mode(SkBlendMode::kColorDodge);
case CompositingAndBlendingOperator::ColorBurn:
return SkBlender::Mode(SkBlendMode::kColorBurn);
case CompositingAndBlendingOperator::HardLight:
return SkBlender::Mode(SkBlendMode::kHardLight);
case CompositingAndBlendingOperator::SoftLight:
return SkBlender::Mode(SkBlendMode::kSoftLight);
case CompositingAndBlendingOperator::Difference:
return SkBlender::Mode(SkBlendMode::kDifference);
case CompositingAndBlendingOperator::Exclusion:
return SkBlender::Mode(SkBlendMode::kExclusion);
case CompositingAndBlendingOperator::Hue:
return SkBlender::Mode(SkBlendMode::kHue);
case CompositingAndBlendingOperator::Saturation:
return SkBlender::Mode(SkBlendMode::kSaturation);
case CompositingAndBlendingOperator::Color:
return SkBlender::Mode(SkBlendMode::kColor);
case CompositingAndBlendingOperator::Luminosity:
return SkBlender::Mode(SkBlendMode::kLuminosity);
case CompositingAndBlendingOperator::Clear:
return SkBlender::Mode(SkBlendMode::kClear);
case CompositingAndBlendingOperator::Copy:
return SkBlender::Mode(SkBlendMode::kSrc);
case CompositingAndBlendingOperator::SourceOver:
return SkBlender::Mode(SkBlendMode::kSrcOver);
case CompositingAndBlendingOperator::DestinationOver:
return SkBlender::Mode(SkBlendMode::kDstOver);
case CompositingAndBlendingOperator::SourceIn:
return SkBlender::Mode(SkBlendMode::kSrcIn);
case CompositingAndBlendingOperator::DestinationIn:
return SkBlender::Mode(SkBlendMode::kDstIn);
case CompositingAndBlendingOperator::SourceOut:
return SkBlender::Mode(SkBlendMode::kSrcOut);
case CompositingAndBlendingOperator::DestinationOut:
return SkBlender::Mode(SkBlendMode::kDstOut);
case CompositingAndBlendingOperator::SourceATop:
return SkBlender::Mode(SkBlendMode::kSrcATop);
case CompositingAndBlendingOperator::DestinationATop:
return SkBlender::Mode(SkBlendMode::kDstATop);
case CompositingAndBlendingOperator::Xor:
return SkBlender::Mode(SkBlendMode::kXor);
case CompositingAndBlendingOperator::Lighter:
return SkBlender::Mode(SkBlendMode::kPlus);
case CompositingAndBlendingOperator::PlusDarker:
// https://drafts.fxtf.org/compositing/#porterduffcompositingoperators_plus_darker
// FIXME: This does not match the spec, however it looks like Safari, the only popular browser supporting this operator.
return SkRuntimeEffect::MakeForBlender(SkString(R"(
vec4 main(vec4 source, vec4 destination) {
return saturate(saturate(destination.a + source.a) - saturate(destination.a - destination) - saturate(source.a - source));
}
)"))
.effect->makeBlender(nullptr);
case CompositingAndBlendingOperator::PlusLighter:
// https://drafts.fxtf.org/compositing/#porterduffcompositingoperators_plus_lighter
return SkRuntimeEffect::MakeForBlender(SkString(R"(
vec4 main(vec4 source, vec4 destination) {
return saturate(source + destination);
}
)"))
.effect->makeBlender(nullptr);
default:
VERIFY_NOT_REACHED();
}
}
}