aboutsummaryrefslogtreecommitdiffhomepage
path: root/modules
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2018-06-29 13:05:03 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-06-29 17:40:27 +0000
commit8deab3ac1eefdb2135281d74c9497a326b186c2e (patch)
tree370821aab7f808cc41e87a9dfcb7bfe31beb09a3 /modules
parent9a7517725e042c3a15b1fc82440363678112333d (diff)
[skottie] Fix 'subtract' masks
Empirically, AE applies subtract masks as inverted intersect masks: it applies the opacity *outside* the mask geometry. Adjust the masking logic accordingly. TBR= Change-Id: If8d9dedbed9ce01b623b6c86ea91e494823d5dc5 Reviewed-on: https://skia-review.googlesource.com/138580 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
Diffstat (limited to 'modules')
-rw-r--r--modules/skottie/src/Skottie.cpp62
1 files changed, 43 insertions, 19 deletions
diff --git a/modules/skottie/src/Skottie.cpp b/modules/skottie/src/Skottie.cpp
index a4c796c869..5c0ed97b4d 100644
--- a/modules/skottie/src/Skottie.cpp
+++ b/modules/skottie/src/Skottie.cpp
@@ -945,18 +945,28 @@ private:
}
};
-SkBlendMode MaskBlendMode(char mode) {
+struct MaskInfo {
+ SkBlendMode fBlendMode;
+ bool fInvertGeometry;
+};
+
+const MaskInfo* GetMaskInfo(char mode) {
+ static constexpr MaskInfo k_add_info = { SkBlendMode::kSrcOver , false };
+ static constexpr MaskInfo k_int_info = { SkBlendMode::kSrcIn , false };
+ // AE 'subtract' is the same as 'intersect' + inverted geometry
+ // (draws the opacity-adjusted paint *outside* the shape).
+ static constexpr MaskInfo k_sub_info = { SkBlendMode::kSrcIn , true };
+ static constexpr MaskInfo k_dif_info = { SkBlendMode::kDifference, false };
+
switch (mode) {
- case 'a': return SkBlendMode::kSrcOver; // Additive
- case 's': return SkBlendMode::kExclusion; // Subtract
- case 'i': return SkBlendMode::kDstIn; // Intersect
- case 'l': return SkBlendMode::kLighten; // Lighten
- case 'd': return SkBlendMode::kDarken; // Darken
- case 'f': return SkBlendMode::kDifference; // Difference
+ case 'a': return &k_add_info;
+ case 'f': return &k_dif_info;
+ case 'i': return &k_int_info;
+ case 's': return &k_sub_info;
default: break;
}
- return SkBlendMode::kSrcOver;
+ return nullptr;
}
sk_sp<sksg::RenderNode> AttachMask(const skjson::ArrayValue* jmask,
@@ -977,26 +987,40 @@ sk_sp<sksg::RenderNode> AttachMask(const skjson::ArrayValue* jmask,
for (const skjson::ObjectValue* m : *jmask) {
if (!m) continue;
- auto mask_path = AttachPath((*m)["pt"], ctx);
- if (!mask_path) {
- LogFail(*m, "Could not parse mask path");
+ SkString mode;
+ if (!Parse<SkString>((*m)["mode"], &mode) || mode.size() != 1) {
+ LogFail((*m)["mode"], "Invalid mask mode");
+ continue;
+ }
+
+ if (mode[0] == 'n') {
+ // "None" masks have no effect.
continue;
}
- mask_path->setFillType(ParseDefault<bool>((*m)["inv"], false)
- ? SkPath::kInverseWinding_FillType
- : SkPath::kWinding_FillType);
+ const auto* mask_info = GetMaskInfo(mode[0]);
+ if (!mask_info) {
+ LOG("?? Unsupported mask mode: '%c'\n", mode[0]);
+ continue;
+ }
- SkString mode;
- if (!Parse<SkString>((*m)["mode"], &mode) ||
- mode.size() != 1 ||
- !strcmp(mode.c_str(), "n")) { // "None" masks have no effect.
+ auto mask_path = AttachPath((*m)["pt"], ctx);
+ if (!mask_path) {
+ LogFail(*m, "Could not parse mask path");
continue;
}
+ // "inv" is cumulative with mask info fInvertGeometry
+ const auto inverted =
+ (mask_info->fInvertGeometry != ParseDefault<bool>((*m)["inv"], false));
+ mask_path->setFillType(inverted ? SkPath::kInverseWinding_FillType
+ : SkPath::kWinding_FillType);
+
auto mask_paint = sksg::Color::Make(SK_ColorBLACK);
mask_paint->setAntiAlias(true);
- mask_paint->setBlendMode(MaskBlendMode(mode.c_str()[0]));
+ // First mask in the stack initializes the mask buffer.
+ mask_paint->setBlendMode(mask_stack.empty() ? SkBlendMode::kSrc
+ : mask_info->fBlendMode);
has_opacity |= BindProperty<ScalarValue>((*m)["o"], &ctx->fAnimators,
[mask_paint](const ScalarValue& o) {