blob: 340516091c3870583d0fa4571235814d527aa071 [file] [log] [blame]
/*
* Copyright 2021 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "modules/skottie/src/effects/Effects.h"
#include "include/effects/SkRuntimeEffect.h"
#include "modules/skottie/src/Adapter.h"
#include "modules/skottie/src/SkottieJson.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/sksg/include/SkSGColorFilter.h"
namespace skottie::internal {
namespace {
// Convert to black & white, based on input luminance and a threshold uniform.
static constexpr char gThresholdSkSL[] = R"(
uniform half t;
half4 main(half4 color) {
half4 c = unpremul(color);
half lum = dot(c.rgb, half3(0.2126, 0.7152, 0.0722)),
bw = step(t, lum);
return bw.xxx1 * c.a;
}
)";
static sk_sp<SkRuntimeEffect> threshold_effect() {
static const SkRuntimeEffect* effect =
SkRuntimeEffect::Make(SkString(gThresholdSkSL), {}).effect.release();
SkASSERT(effect);
return sk_ref_sp(effect);
}
class ThresholdAdapter final : public DiscardableAdapterBase<ThresholdAdapter,
sksg::ExternalColorFilter> {
public:
ThresholdAdapter(const skjson::ArrayValue& jprops,
sk_sp<sksg::RenderNode> layer,
const AnimationBuilder& abuilder)
: INHERITED(sksg::ExternalColorFilter::Make(std::move(layer)))
{
enum : size_t {
kLevel_Index = 0,
};
EffectBinder(jprops, abuilder, this).bind(kLevel_Index, fLevel);
}
private:
void onSync() override {
auto cf =
threshold_effect()->makeColorFilter(SkData::MakeWithCopy(&fLevel, sizeof(fLevel)));
this->node()->setColorFilter(std::move(cf));
}
ScalarValue fLevel = 0;
using INHERITED = DiscardableAdapterBase<ThresholdAdapter, sksg::ExternalColorFilter>;
};
} // namespace
sk_sp<sksg::RenderNode> EffectBuilder::attachThresholdEffect(const skjson::ArrayValue& jprops,
sk_sp<sksg::RenderNode> layer) const {
return fBuilder->attachDiscardableAdapter<ThresholdAdapter>(jprops,
std::move(layer),
*fBuilder);
}
} // namespace skottie::internal