Skip to content

Commit

Permalink
Added the ability to outline masks and mattes (#1658)
Browse files Browse the repository at this point in the history
  • Loading branch information
gpeal authored Oct 25, 2020
1 parent 8a10f96 commit d0f006f
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class LottieTest {
snapshotProdAnimations()
testNightMode()
testApplyOpacityToLayer()
testOutlineMasksAndMattes()
snapshotter.finalizeReportAndUpload()
}
}
Expand Down Expand Up @@ -983,6 +984,16 @@ class LottieTest {
}
}

private suspend fun testOutlineMasksAndMattes() {
withFilmStripView(
"Tests/Masks.json",
"Outline Masks and Mattes",
"Enabled"
) { filmStripView ->
filmStripView.setOutlineMasksAndMattes(true)
}
}

private suspend fun withDrawable(assetName: String, snapshotName: String, snapshotVariant: String, callback: (LottieDrawable) -> Unit) {
val result = LottieCompositionFactory.fromAssetSync(application, assetName)
val composition = result.value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ class PlayerFragment : BaseMvRxFragment(R.layout.player_fragment) {
binding.controlBarPlayerControls.lottieVersionView.animateVisible(!it)
}

binding.controlBar.masksAndMattesToggle.setOnClickListener { viewModel.toggleOutlineMasksAndMattes() }
viewModel.selectSubscribe(PlayerState::outlineMasksAndMattes) {
binding.controlBar.masksAndMattesToggle.isActivated = it
binding.animationView.setOutlineMasksAndMattes(it)
}

binding.controlBar.backgroundColorToggle.setOnClickListener { viewModel.toggleBackgroundColorVisible() }
binding.controlBarBackgroundColor.closeBackgroundColorButton.setOnClickListener { viewModel.setBackgroundColorVisible(false) }
viewModel.selectSubscribe(PlayerState::backgroundColorVisible) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ data class PlayerState(
val controlsVisible: Boolean = true,
val controlBarVisible: Boolean = true,
val renderGraphVisible: Boolean = false,
val outlineMasksAndMattes: Boolean = false,
val borderVisible: Boolean = false,
val backgroundColorVisible: Boolean = false,
val scaleVisible: Boolean = false,
Expand Down Expand Up @@ -64,6 +65,8 @@ class PlayerViewModel(

fun toggleRenderGraphVisible() = setState { copy(renderGraphVisible = !renderGraphVisible) }

fun toggleOutlineMasksAndMattes() = setState { copy(outlineMasksAndMattes = !outlineMasksAndMattes) }

fun toggleBorderVisible() = setState { copy(borderVisible = !borderVisible) }

fun toggleBackgroundColorVisible() = setState { copy(backgroundColorVisible = !backgroundColorVisible) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,8 @@ class FilmStripView @JvmOverloads constructor(
fun setApplyingOpacityToLayersEnabled(isApplyingOpacityToLayersEnabled: Boolean) {
animationViews.forEach { it.setApplyingOpacityToLayersEnabled(isApplyingOpacityToLayersEnabled) }
}

fun setOutlineMasksAndMattes(outline: Boolean) {
animationViews.forEach { it.setOutlineMasksAndMattes(outline) }
}
}
10 changes: 10 additions & 0 deletions LottieSample/src/main/res/drawable/ic_show_masks_and_mattes.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M3,5h2L5,3c-1.1,0 -2,0.9 -2,2zM3,13h2v-2L3,11v2zM7,21h2v-2L7,19v2zM3,9h2L5,7L3,7v2zM13,3h-2v2h2L13,3zM19,3v2h2c0,-1.1 -0.9,-2 -2,-2zM5,21v-2L3,19c0,1.1 0.9,2 2,2zM3,17h2v-2L3,15v2zM9,3L7,3v2h2L9,3zM11,21h2v-2h-2v2zM19,13h2v-2h-2v2zM19,21c1.1,0 2,-0.9 2,-2h-2v2zM19,9h2L21,7h-2v2zM19,17h2v-2h-2v2zM15,21h2v-2h-2v2zM15,5h2L17,3h-2v2zM7,17h10L17,7L7,7v10zM9,9h6v6L9,15L9,9z"/>
</vector>
5 changes: 5 additions & 0 deletions LottieSample/src/main/res/layout/control_bar.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
style="@style/ControlBarItem"
app:src="@drawable/ic_chart"
app:text="@string/control_bar_render_graph" />
<com.airbnb.lottie.samples.views.ControlBarItemToggleView
android:id="@+id/masksAndMattesToggle"
style="@style/ControlBarItem"
app:src="@drawable/ic_show_masks_and_mattes"
app:text="@string/control_bar_masks_and_mattes" />
<com.airbnb.lottie.samples.views.ControlBarItemToggleView
android:id="@+id/warningsButton"
style="@style/ControlBarItem" />
Expand Down
1 change: 1 addition & 0 deletions LottieSample/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
<string name="control_bar_hardware_acceleration">Hardware Acceleration</string>
<string name="control_bar_render_graph">Render Graph</string>
<string name="control_bar_scale">Scale</string>
<string name="control_bar_masks_and_mattes">Outline Masks</string>
<string name="control_bar_trim">Trim</string>
<string name="control_bar_speed">Speed</string>
<string name="control_bar_key_paths">Show KeyPaths</string>
Expand Down
10 changes: 10 additions & 0 deletions lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,16 @@ public void setCacheComposition(boolean cacheComposition) {
this.cacheComposition = cacheComposition;
}

/**
* Enable this to debug slow animations by outlining masks and mattes. The performance overhead of the masks and mattes will
* be proportional to the surface area of all of the masks/mattes combined.
*
* DO NOT leave this enabled in production.
*/
public void setOutlineMasksAndMattes(boolean outline) {
lottieDrawable.setOutlineMasksAndMattes(outline);
}

/**
* Sets the animation from a file in the raw directory.
* This will load and deserialize the file asynchronously.
Expand Down
17 changes: 17 additions & 0 deletions lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public void onAnimationUpdate(ValueAnimator animation) {
private CompositionLayer compositionLayer;
private int alpha = 255;
private boolean performanceTrackingEnabled;
private boolean outlineMasksAndMattes;
private boolean isApplyingOpacityToLayersEnabled;
private boolean isExtraScaleEnabled = true;
/**
Expand Down Expand Up @@ -249,6 +250,19 @@ public void setPerformanceTrackingEnabled(boolean enabled) {
}
}

/**
* Enable this to debug slow animations by outlining masks and mattes. The performance overhead of the masks and mattes will
* be proportional to the surface area of all of the masks/mattes combined.
*
* DO NOT leave this enabled in production.
*/
void setOutlineMasksAndMattes(boolean outline) {
outlineMasksAndMattes = outline;
if (compositionLayer != null) {
compositionLayer.setOutlineMasksAndMattes(outline);
}
}

@Nullable
public PerformanceTracker getPerformanceTracker() {
if (composition != null) {
Expand Down Expand Up @@ -296,6 +310,9 @@ public boolean isApplyingOpacityToLayersEnabled() {
private void buildCompositionLayer() {
compositionLayer = new CompositionLayer(
this, LayerParser.parse(composition), composition.getLayers(), composition);
if (outlineMasksAndMattes) {
compositionLayer.setOutlineMasksAndMattes(true);
}
}

public void clearComposition() {
Expand Down
33 changes: 26 additions & 7 deletions lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ static BaseLayer forModel(
final TransformKeyframeAnimation transform;
private boolean visible = true;

private boolean outlineMasksAndMattes;
@Nullable private Paint outlineMasksAndMattesPaint;

BaseLayer(LottieDrawable lottieDrawable, Layer layerModel) {
this.lottieDrawable = lottieDrawable;
this.layerModel = layerModel;
Expand Down Expand Up @@ -125,6 +128,19 @@ static BaseLayer forModel(
setupInOutAnimations();
}

/**
* Enable this to debug slow animations by outlining masks and mattes. The performance overhead of the masks and mattes will
* be proportional to the surface area of all of the masks/mattes combined.
*
* DO NOT leave this enabled in production.
*/
void setOutlineMasksAndMattes(boolean outline) {
if (outline && outlineMasksAndMattesPaint == null) {
outlineMasksAndMattesPaint = new LPaint();
}
outlineMasksAndMattes = outline;
}

@Override
public void onValueChanged() {
invalidateSelf();
Expand Down Expand Up @@ -229,13 +245,6 @@ public void draw(Canvas canvas, Matrix parentMatrix, int parentAlpha) {
L.beginSection("Layer#computeBounds");
getBounds(rect, matrix, false);

// Uncomment this to draw matte outlines.
/* Paint paint = new LPaint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
canvas.drawRect(rect, paint); */

intersectBoundsWithMatte(rect, parentMatrix);

matrix.preConcat(transform.getMatrix());
Expand Down Expand Up @@ -282,6 +291,16 @@ public void draw(Canvas canvas, Matrix parentMatrix, int parentAlpha) {
L.endSection("Layer#restoreLayer");
}

if (outlineMasksAndMattes && outlineMasksAndMattesPaint != null) {
outlineMasksAndMattesPaint.setStyle(Paint.Style.STROKE);
outlineMasksAndMattesPaint.setColor(0xFFFC2803);
outlineMasksAndMattesPaint.setStrokeWidth(4);
canvas.drawRect(rect, outlineMasksAndMattesPaint);
outlineMasksAndMattesPaint.setStyle(Paint.Style.FILL);
outlineMasksAndMattesPaint.setColor(0x50EBEBEB);
canvas.drawRect(rect, outlineMasksAndMattesPaint);
}

recordRenderTime(L.endSection(drawTraceName));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ public CompositionLayer(LottieDrawable lottieDrawable, Layer layerModel, List<La
}
}

@Override public void setOutlineMasksAndMattes(boolean outline) {
super.setOutlineMasksAndMattes(outline);
for (BaseLayer layer : layers) {
layer.setOutlineMasksAndMattes(outline);
}
}

@Override void drawLayer(Canvas canvas, Matrix parentMatrix, int parentAlpha) {
L.beginSection("CompositionLayer#draw");
newClipRect.set(0, 0, layerModel.getPreCompWidth(), layerModel.getPreCompHeight());
Expand Down

0 comments on commit d0f006f

Please sign in to comment.