Skip to content

Commit

Permalink
Add generalized Lottie Feature Flags API (#2512)
Browse files Browse the repository at this point in the history
Currently there are individual methods for enabling and disabling Merge Paths in Lottie. This PR aims to generalize these functions as we consider adding more features guarded behind opt-in flags.
  • Loading branch information
jbeta51 authored Jul 3, 2024
1 parent 99b0683 commit c4cb225
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import androidx.compose.ui.unit.IntSize
import com.airbnb.lottie.AsyncUpdates
import com.airbnb.lottie.LottieComposition
import com.airbnb.lottie.LottieDrawable
import com.airbnb.lottie.LottieFeatureFlag
import com.airbnb.lottie.RenderMode
import kotlin.math.roundToInt

Expand Down Expand Up @@ -114,7 +115,7 @@ fun LottieAnimation(
matrix.preTranslate(translation.x.toFloat(), translation.y.toFloat())
matrix.preScale(scale.scaleX, scale.scaleY)

drawable.enableMergePathsForKitKatAndAbove(enableMergePaths)
drawable.enableFeatureFlag(LottieFeatureFlag.MergePathsApi19, enableMergePaths)
drawable.setSafeMode(safeMode)
drawable.renderMode = renderMode
drawable.asyncUpdates = asyncUpdates
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import androidx.compose.ui.unit.IntSize
import com.airbnb.lottie.AsyncUpdates
import com.airbnb.lottie.LottieComposition
import com.airbnb.lottie.LottieDrawable
import com.airbnb.lottie.LottieFeatureFlag
import com.airbnb.lottie.RenderMode
import kotlin.math.roundToInt

Expand Down Expand Up @@ -104,7 +105,7 @@ class LottiePainter internal constructor(
matrix.reset()
matrix.preScale(intSize.width / compositionSize.width, intSize.height / compositionSize.height)

drawable.enableMergePathsForKitKatAndAbove(enableMergePaths)
drawable.enableFeatureFlag(LottieFeatureFlag.MergePathsApi19, enableMergePaths)
drawable.renderMode = renderMode
drawable.asyncUpdates = asyncUpdates
drawable.composition = composition
Expand Down
22 changes: 20 additions & 2 deletions lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
Original file line number Diff line number Diff line change
Expand Up @@ -403,14 +403,32 @@ public void setUseCompositionFrameRate(boolean useCompositionFrameRate) {
* instead of using merge paths.
*/
public void enableMergePathsForKitKatAndAbove(boolean enable) {
lottieDrawable.enableMergePathsForKitKatAndAbove(enable);
lottieDrawable.enableFeatureFlag(LottieFeatureFlag.MergePathsApi19, enable);
}

/**
* Returns whether merge paths are enabled for KitKat and above.
*/
public boolean isMergePathsEnabledForKitKatAndAbove() {
return lottieDrawable.isMergePathsEnabledForKitKatAndAbove();
return lottieDrawable.isFeatureFlagEnabled(LottieFeatureFlag.MergePathsApi19);
}

/**
* Enable the specified feature for this LottieView.
* <p>
* Features guarded by LottieFeatureFlags are experimental or only supported by a subset of API levels.
* Please ensure that the animation supported by the enabled feature looks acceptable across all
* targeted API levels.
*/
public void enableFeatureFlag(LottieFeatureFlag flag, boolean enable) {
lottieDrawable.enableFeatureFlag(flag, enable);
}

/**
* Returns whether the specified feature is enabled.
*/
public boolean isFeatureFlagEnabled(LottieFeatureFlag flag) {
return lottieDrawable.isFeatureFlagEnabled(flag);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
Expand Down
41 changes: 29 additions & 12 deletions lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ private enum OnVisibleAction {
FontAssetDelegate fontAssetDelegate;
@Nullable
TextDelegate textDelegate;
private boolean enableMergePaths;
private final LottieFeatureFlags lottieFeatureFlags = new LottieFeatureFlags();
private boolean maintainOriginalImageBounds = false;
private boolean clipToCompositionBounds = true;
@Nullable
Expand Down Expand Up @@ -285,34 +285,51 @@ public boolean hasMatte() {
return compositionLayer != null && compositionLayer.hasMatte();
}

@Deprecated
public boolean enableMergePathsForKitKatAndAbove() {
return enableMergePaths;
return lottieFeatureFlags.isFlagEnabled(LottieFeatureFlag.MergePathsApi19);
}

/**
* Enable this to get merge path support for devices running KitKat (19) and above.
* Deprecated: Use enableFeatureFlag(LottieFeatureFlags.FeatureFlag.MergePathsApi19, enable)
* <p>
* Merge paths currently don't work if the the operand shape is entirely contained within the
* first shape. If you need to cut out one shape from another shape, use an even-odd fill type
* instead of using merge paths.
*/
@Deprecated
public void enableMergePathsForKitKatAndAbove(boolean enable) {
if (enableMergePaths == enable) {
return;
boolean changed = lottieFeatureFlags.enableFlag(LottieFeatureFlag.MergePathsApi19, enable);
if (composition != null && changed) {
buildCompositionLayer();
}
}

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
Logger.warning("Merge paths are not supported pre-Kit Kat.");
return;
}
enableMergePaths = enable;
if (composition != null) {
/**
* @deprecated Replaced by {@link #enableFeatureFlag(LottieFeatureFlag, boolean)}
*/
@Deprecated
public boolean isMergePathsEnabledForKitKatAndAbove() {
return lottieFeatureFlags.isFlagEnabled(LottieFeatureFlag.MergePathsApi19);
}

/**
* Enable the specified feature for this drawable.
* <p>
* Features guarded by LottieFeatureFlags are experimental or only supported by a subset of API levels.
* Please ensure that the animation supported by the enabled feature looks acceptable across all
* targeted API levels.
*/
public void enableFeatureFlag(LottieFeatureFlag flag, boolean enable) {
boolean changed = lottieFeatureFlags.enableFlag(flag, enable);
if (composition != null && changed) {
buildCompositionLayer();
}
}

public boolean isMergePathsEnabledForKitKatAndAbove() {
return enableMergePaths;
public boolean isFeatureFlagEnabled(LottieFeatureFlag flag) {
return lottieFeatureFlags.isFlagEnabled(flag);
}

/**
Expand Down
18 changes: 18 additions & 0 deletions lottie/src/main/java/com/airbnb/lottie/LottieFeatureFlag.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.airbnb.lottie;

import android.os.Build;

public enum LottieFeatureFlag {
/**
* Merge paths currently don't work if the the operand shape is entirely contained within the
* first shape. If you need to cut out one shape from another shape, use an even-odd fill type
* instead of using merge paths.
*/
MergePathsApi19(Build.VERSION_CODES.KITKAT);

public final int minRequiredSdkVersion;

LottieFeatureFlag(int minRequiredSdkVersion) {
this.minRequiredSdkVersion = minRequiredSdkVersion;
}
}
34 changes: 34 additions & 0 deletions lottie/src/main/java/com/airbnb/lottie/LottieFeatureFlags.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.airbnb.lottie;

import android.annotation.SuppressLint;
import android.os.Build;

import com.airbnb.lottie.utils.Logger;

import java.util.HashSet;

class LottieFeatureFlags {

private final HashSet<LottieFeatureFlag> enabledFlags = new HashSet<>();

/**
* Returns true if the flag was changed.
*/
@SuppressLint("DefaultLocale")
public boolean enableFlag(LottieFeatureFlag flag, boolean enable) {
if (enable) {
if (Build.VERSION.SDK_INT < flag.minRequiredSdkVersion) {
Logger.warning(String.format("%s is not supported pre SDK %d", flag.name(), flag.minRequiredSdkVersion));
return false;
}
return enabledFlags.add(flag);
} else {
return enabledFlags.remove(flag);
}
}

public boolean isFlagEnabled(LottieFeatureFlag flag) {
return enabledFlags.contains(flag);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import com.airbnb.lottie.LottieComposition;
import com.airbnb.lottie.LottieDrawable;
import com.airbnb.lottie.LottieFeatureFlag;
import com.airbnb.lottie.animation.content.Content;
import com.airbnb.lottie.animation.content.MergePathsContent;
import com.airbnb.lottie.model.layer.BaseLayer;
Expand Down Expand Up @@ -60,7 +61,7 @@ public boolean isHidden() {
}

@Override @Nullable public Content toContent(LottieDrawable drawable, LottieComposition composition, BaseLayer layer) {
if (!drawable.enableMergePathsForKitKatAndAbove()) {
if (!drawable.isFeatureFlagEnabled(LottieFeatureFlag.MergePathsApi19)) {
Logger.warning("Animation contains merge paths but they are disabled.");
return null;
}
Expand Down

0 comments on commit c4cb225

Please sign in to comment.