[skottie] Add support for text animator blur
In adition to transforms/opacity/etc, text animators can target per-glyph opacity. Change-Id: I6ab63a6e49a64beaf63fc955f0b672a5b8ba84ba Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272886 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
This commit is contained in:
parent
cc5415a8ce
commit
9642b31a71
@ -38,6 +38,9 @@ class Transform;
|
|||||||
namespace skottie {
|
namespace skottie {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
// Close-enough to AE.
|
||||||
|
static constexpr float kBlurSizeToSigma = 0.3f;
|
||||||
|
|
||||||
class TextAdapter;
|
class TextAdapter;
|
||||||
class TransformAdapter2D;
|
class TransformAdapter2D;
|
||||||
class TransformAdapter3D;
|
class TransformAdapter3D;
|
||||||
|
@ -60,9 +60,7 @@ private:
|
|||||||
fDropShadow->setOffset(SkVector::Make( fDistance * SkScalarCos(rad),
|
fDropShadow->setOffset(SkVector::Make( fDistance * SkScalarCos(rad),
|
||||||
-fDistance * SkScalarSin(rad)));
|
-fDistance * SkScalarSin(rad)));
|
||||||
|
|
||||||
// Close enough to AE.
|
const auto sigma = fSoftness * kBlurSizeToSigma;
|
||||||
static constexpr SkScalar kSoftnessToSigmaFactor = 0.3f;
|
|
||||||
const auto sigma = fSoftness * kSoftnessToSigmaFactor;
|
|
||||||
fDropShadow->setSigma(SkVector::Make(sigma, sigma));
|
fDropShadow->setSigma(SkVector::Make(sigma, sigma));
|
||||||
|
|
||||||
fDropShadow->setMode(SkToBool(fShdwOnly)
|
fDropShadow->setMode(SkToBool(fShdwOnly)
|
||||||
|
@ -56,9 +56,7 @@ private:
|
|||||||
const auto dim_index = SkTPin<size_t>(static_cast<size_t>(fDimensions),
|
const auto dim_index = SkTPin<size_t>(static_cast<size_t>(fDimensions),
|
||||||
1, SK_ARRAY_COUNT(kDimensionsMap)) - 1;
|
1, SK_ARRAY_COUNT(kDimensionsMap)) - 1;
|
||||||
|
|
||||||
// Close enough to AE.
|
const auto sigma = fBlurriness * kBlurSizeToSigma;
|
||||||
static constexpr SkScalar kBlurrinessToSigmaFactor = 0.3f;
|
|
||||||
const auto sigma = fBlurriness * kBlurrinessToSigmaFactor;
|
|
||||||
|
|
||||||
fBlur->setSigma({ sigma * kDimensionsMap[dim_index].x(),
|
fBlur->setSigma({ sigma * kDimensionsMap[dim_index].x(),
|
||||||
sigma * kDimensionsMap[dim_index].y() });
|
sigma * kDimensionsMap[dim_index].y() });
|
||||||
|
@ -48,8 +48,7 @@ protected:
|
|||||||
fMaskSigma = 0;
|
fMaskSigma = 0;
|
||||||
fMaskFilter = nullptr;
|
fMaskFilter = nullptr;
|
||||||
} else {
|
} else {
|
||||||
static constexpr float kFeatherToSigma = 0.3f; // close enough to AE
|
fMaskSigma = std::max(fFeather, 0.0f) * kBlurSizeToSigma;
|
||||||
fMaskSigma = std::max(fFeather, 0.0f) * kFeatherToSigma;
|
|
||||||
|
|
||||||
// The gradient is inverted between non-blurred and blurred (latter requires dstOut).
|
// The gradient is inverted between non-blurred and blurred (latter requires dstOut).
|
||||||
const SkColor c0 = fMaskSigma > 0 ? 0xffffffff : 0x00000000,
|
const SkColor c0 = fMaskSigma > 0 ? 0xffffffff : 0x00000000,
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "modules/sksg/include/SkSGGroup.h"
|
#include "modules/sksg/include/SkSGGroup.h"
|
||||||
#include "modules/sksg/include/SkSGPaint.h"
|
#include "modules/sksg/include/SkSGPaint.h"
|
||||||
#include "modules/sksg/include/SkSGRect.h"
|
#include "modules/sksg/include/SkSGRect.h"
|
||||||
|
#include "modules/sksg/include/SkSGRenderEffect.h"
|
||||||
#include "modules/sksg/include/SkSGText.h"
|
#include "modules/sksg/include/SkSGText.h"
|
||||||
#include "modules/sksg/include/SkSGTransform.h"
|
#include "modules/sksg/include/SkSGTransform.h"
|
||||||
|
|
||||||
@ -69,6 +70,7 @@ sk_sp<TextAdapter> TextAdapter::Make(const skjson::ObjectValue& jlayer,
|
|||||||
|
|
||||||
for (const skjson::ObjectValue* janimator : *janimators) {
|
for (const skjson::ObjectValue* janimator : *janimators) {
|
||||||
if (auto animator = TextAnimator::Make(janimator, abuilder, adapter.get())) {
|
if (auto animator = TextAnimator::Make(janimator, abuilder, adapter.get())) {
|
||||||
|
adapter->fHasBlur |= animator->hasBlur();
|
||||||
adapter->fAnimators.push_back(std::move(animator));
|
adapter->fAnimators.push_back(std::move(animator));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,6 +127,12 @@ void TextAdapter::addFragment(const Shaper::Fragment& frag) {
|
|||||||
? sksg::Group::Make(std::move(draws))
|
? sksg::Group::Make(std::move(draws))
|
||||||
: std::move(draws[0]);
|
: std::move(draws[0]);
|
||||||
|
|
||||||
|
if (fHasBlur) {
|
||||||
|
// Optional blur effect.
|
||||||
|
rec.fBlur = sksg::BlurImageFilter::Make();
|
||||||
|
draws_node = sksg::ImageFilterEffect::Make(std::move(draws_node), rec.fBlur);
|
||||||
|
}
|
||||||
|
|
||||||
fRoot->addChild(sksg::TransformEffect::Make(std::move(draws_node), rec.fMatrixNode));
|
fRoot->addChild(sksg::TransformEffect::Make(std::move(draws_node), rec.fMatrixNode));
|
||||||
fFragments.push_back(std::move(rec));
|
fFragments.push_back(std::move(rec));
|
||||||
}
|
}
|
||||||
@ -307,6 +315,9 @@ void TextAdapter::pushPropsToFragment(const TextAnimator::ResolvedProps& props,
|
|||||||
if (rec.fStrokeColorNode) {
|
if (rec.fStrokeColorNode) {
|
||||||
rec.fStrokeColorNode->setColor(scale_alpha(props.stroke_color, props.opacity));
|
rec.fStrokeColorNode->setColor(scale_alpha(props.stroke_color, props.opacity));
|
||||||
}
|
}
|
||||||
|
if (rec.fBlur) {
|
||||||
|
rec.fBlur->setSigma(props.blur * kBlurSizeToSigma);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextAdapter::adjustLineTracking(const TextAnimator::ModulatorBuffer& buf,
|
void TextAdapter::adjustLineTracking(const TextAnimator::ModulatorBuffer& buf,
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
class SkFontMgr;
|
class SkFontMgr;
|
||||||
|
|
||||||
namespace sksg {
|
namespace sksg {
|
||||||
|
class BlurImageFilter;
|
||||||
class Group;
|
class Group;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Matrix;
|
class Matrix;
|
||||||
@ -50,6 +51,7 @@ private:
|
|||||||
sk_sp<sksg::Matrix<SkM44>> fMatrixNode;
|
sk_sp<sksg::Matrix<SkM44>> fMatrixNode;
|
||||||
sk_sp<sksg::Color> fFillColorNode,
|
sk_sp<sksg::Color> fFillColorNode,
|
||||||
fStrokeColorNode;
|
fStrokeColorNode;
|
||||||
|
sk_sp<sksg::BlurImageFilter> fBlur;
|
||||||
};
|
};
|
||||||
|
|
||||||
void reshape();
|
void reshape();
|
||||||
@ -89,6 +91,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
TextValueTracker fText;
|
TextValueTracker fText;
|
||||||
|
bool fHasBlur = false; // tracks whether any animator targets blur
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
@ -123,6 +123,9 @@ TextAnimator::ResolvedProps TextAnimator::modulateProps(const ResolvedProps& pro
|
|||||||
modulated_props.scale *= SkV3{1,1,1} +
|
modulated_props.scale *= SkV3{1,1,1} +
|
||||||
(ValueTraits<VectorValue>::As<SkV3>(fTextProps.scale) * 0.01f - SkV3{1,1,1}) * amount;
|
(ValueTraits<VectorValue>::As<SkV3>(fTextProps.scale) * 0.01f - SkV3{1,1,1}) * amount;
|
||||||
|
|
||||||
|
// ... as does blur
|
||||||
|
modulated_props.blur += ValueTraits<VectorValue>::As<SkVector>(fTextProps.blur) * amount;
|
||||||
|
|
||||||
const auto lerp_color = [](SkColor c0, SkColor c1, float t) {
|
const auto lerp_color = [](SkColor c0, SkColor c1, float t) {
|
||||||
const auto c0_4f = SkNx_cast<float>(Sk4b::Load(&c0)),
|
const auto c0_4f = SkNx_cast<float>(Sk4b::Load(&c0)),
|
||||||
c1_4f = SkNx_cast<float>(Sk4b::Load(&c1)),
|
c1_4f = SkNx_cast<float>(Sk4b::Load(&c1)),
|
||||||
@ -167,6 +170,7 @@ TextAnimator::TextAnimator(std::vector<sk_sp<RangeSelector>>&& selectors,
|
|||||||
|
|
||||||
fHasFillColor = acontainer->bind(*abuilder, jprops["fc"], &fTextProps.fill_color );
|
fHasFillColor = acontainer->bind(*abuilder, jprops["fc"], &fTextProps.fill_color );
|
||||||
fHasStrokeColor = acontainer->bind(*abuilder, jprops["sc"], &fTextProps.stroke_color);
|
fHasStrokeColor = acontainer->bind(*abuilder, jprops["sc"], &fTextProps.stroke_color);
|
||||||
|
fHasBlur = acontainer->bind(*abuilder, jprops["bl"], &fTextProps.blur );
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
@ -35,7 +35,8 @@ public:
|
|||||||
VectorValue position,
|
VectorValue position,
|
||||||
scale = { 100, 100, 100 },
|
scale = { 100, 100, 100 },
|
||||||
fill_color,
|
fill_color,
|
||||||
stroke_color;
|
stroke_color,
|
||||||
|
blur;
|
||||||
// unlike pos/scale which are animated vectors, rotation is separated in each dimension.
|
// unlike pos/scale which are animated vectors, rotation is separated in each dimension.
|
||||||
SkV3 rotation = { 0, 0, 0 };
|
SkV3 rotation = { 0, 0, 0 };
|
||||||
ScalarValue opacity = 100,
|
ScalarValue opacity = 100,
|
||||||
@ -50,6 +51,7 @@ public:
|
|||||||
tracking = 0;
|
tracking = 0;
|
||||||
SkColor fill_color = SK_ColorTRANSPARENT,
|
SkColor fill_color = SK_ColorTRANSPARENT,
|
||||||
stroke_color = SK_ColorTRANSPARENT;
|
stroke_color = SK_ColorTRANSPARENT;
|
||||||
|
SkVector blur = { 0, 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AnimatedPropsModulator {
|
struct AnimatedPropsModulator {
|
||||||
@ -76,6 +78,8 @@ public:
|
|||||||
|
|
||||||
void modulateProps(const DomainMaps&, ModulatorBuffer&) const;
|
void modulateProps(const DomainMaps&, ModulatorBuffer&) const;
|
||||||
|
|
||||||
|
bool hasBlur() const { return fHasBlur; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TextAnimator(std::vector<sk_sp<RangeSelector>>&&,
|
TextAnimator(std::vector<sk_sp<RangeSelector>>&&,
|
||||||
const skjson::ObjectValue&,
|
const skjson::ObjectValue&,
|
||||||
@ -88,7 +92,8 @@ private:
|
|||||||
|
|
||||||
AnimatedProps fTextProps;
|
AnimatedProps fTextProps;
|
||||||
bool fHasFillColor : 1,
|
bool fHasFillColor : 1,
|
||||||
fHasStrokeColor : 1;
|
fHasStrokeColor : 1,
|
||||||
|
fHasBlur : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
1
resources/skottie/skottie-text-blur.json
Normal file
1
resources/skottie/skottie-text-blur.json
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user