/* * 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 "include/core/SkData.h" #include "include/core/SkRefCnt.h" #include "include/core/SkString.h" #include "include/effects/SkRuntimeEffect.h" #include "include/private/base/SkAssert.h" #include "modules/skottie/src/Adapter.h" #include "modules/skottie/src/SkottiePriv.h" #include "modules/skottie/src/SkottieValue.h" #include "modules/skottie/src/effects/Effects.h" #include "modules/sksg/include/SkSGColorFilter.h" #include "modules/sksg/include/SkSGRenderNode.h" #include #include namespace skjson { class ArrayValue; } namespace skottie::internal { namespace { // Convert to black & white, based on input luminance and a threshold uniform. static constexpr char gThresholdSkSL[] = "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 threshold_effect() { static const SkRuntimeEffect* effect = SkRuntimeEffect::MakeForColorFilter(SkString(gThresholdSkSL), {}).effect.release(); SkASSERT(effect); return sk_ref_sp(effect); } class ThresholdAdapter final : public DiscardableAdapterBase { public: ThresholdAdapter(const skjson::ArrayValue& jprops, sk_sp 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; }; } // namespace sk_sp EffectBuilder::attachThresholdEffect(const skjson::ArrayValue& jprops, sk_sp layer) const { return fBuilder->attachDiscardableAdapter(jprops, std::move(layer), *fBuilder); } } // namespace skottie::internal