-
-
Notifications
You must be signed in to change notification settings - Fork 5.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Apply blend modes on layer level and add Multiply blend mode #2519
Conversation
BlendModeCompat is designed to use either a BlendMode (added in Android Q) or PorterDuff.Mode (always available). Our support for Lottie blend modes did not include Multiply due to a slightly different formula between the PorterDuff and BlendMode variants. However, we did include support for Screen, which suffers from a similar behavior. Therefore, we are not breaking any consistency by including Multiply too, and including it provides benefits in terms of more complete support, as Multiply is a foundational blend mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
"Proper" MULTIPLY seems to have been added in Android Q, so use the older MODULATE with a slight hack to ensure proper rendering in our usecase.
lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
Outdated
Show resolved
Hide resolved
@gpeal Thanks for the review! Addressed comment. Let me know if there's anything else you see that needs improvement! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the investigative work here!
This commit improves blend mode support in lottie-android in two ways:
Applying blend modes on layer level
The Lottie format defines blend modes as attributes on a layer. However, lottie-android is presently applying the layer blend modes on a solid color fill only. Notably, this causes any stroked or gradient-filled shapes or image layers to blend incorrectly, such as in this file:
stroke-blending-test.json
(The file contains a filled + stroked shape that renders as a pink square on other platforms, but renders with a visible stroke on lottie-android since its blend mode is applied only on the fill.)
Instead, we move this decision to
BaseLayer
by analogy to transparent layer handling, which is closer to how the format specifies the property and fixes these cases.Multiply support
BlendModeCompat
is designed to resolve to either aBlendMode
(added in Android Q, supporting most modern blend modes) orPorterDuff.Mode
(always available, but a smaller choice of modes as it is mostly focused on alpha compositing).We use
BlendModeCompat
to support Lottie layer blend modes (bm
key) to ensure compatibility on all platforms. For consistency, we don't support values which don't have aPorterDuff.Mode
equivalent.Our support for Lottie blend modes did not include Multiply due to a slightly different behavior between the
PorterDuff.MULTIPLY
(exposed asBlendModeCompat.MODULATE
) andBlendModeCompat.MULTIPLY
variants. Namely, the formula used forPorterDuff.MODULATE
, combined with alpha-premultiplication done by Skia, means that a layer with an alpha < 1.0 and multiply blend mode will also darken the destination:(Multiply-blended layers with < 1.0 alpha on the left, Screen-blended layers with < 1.0 alpha on the right)
However, what we can do instead is clear the canvas with a solid white color instead of transparent before drawing the layer's contents as normal. When blending the resulting bitmap over an opaque background using
PorterDuff.MULTIPLY
(i.e.BlendModeCompat.MODULATE
), the end result will be as if we had usedBlendModeCompat.MULTIPLY
, since all-1.0 (white) is a multiplication identity:This PR implements the latter solution and adds a consistent support for the Multiply blend mode for all Android versions.
Test file used: blendmode-tests-multiply+screen+bg.zip