Compiles
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java b/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
index 4b7ed78..d932b15 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
@@ -5,16 +5,12 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Typeface;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import androidx.annotation.FloatRange;
import androidx.annotation.IntDef;
import androidx.annotation.IntRange;
@@ -317,7 +313,7 @@
matrix.reset();
matrix.preScale(scale, scale);
- compositionLayer.draw(new WrappedCanvas(canvas), matrix, alpha, null, maskIdentityMatrix, matrix);
+ compositionLayer.draw(new WrappedCanvas(canvas), matrix, alpha, null, maskIdentityMatrix);
L.endSection("Drawable#draw");
if (extraScale > 1) {
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/canvas/ICanvas.java b/lottie/src/main/java/com/airbnb/lottie/animation/canvas/ICanvas.java
index 9f667ab..a836d28 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/canvas/ICanvas.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/canvas/ICanvas.java
@@ -22,6 +22,7 @@
boolean clipPath(Path path);
boolean clipRect(RectF rect);
void drawText(char[] text, int index, int count, float x, float y, Paint paint);
+ void drawRect(float left, float top, float right, float bottom, Paint paint);
void setMatrix(@Nullable Matrix matrix);
void concat(@Nullable Matrix matrix);
void drawBitmap(@NonNull Bitmap bitmap, Rect src, Rect dst, @Nullable Paint paint);
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/canvas/RecordedCanvas.java b/lottie/src/main/java/com/airbnb/lottie/animation/canvas/RecordedCanvas.java
index 7925899..cdcf230 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/canvas/RecordedCanvas.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/canvas/RecordedCanvas.java
@@ -147,6 +147,11 @@
}
@Override
+ public void drawRect(float left, float top, float right, float bottom, Paint paint) {
+ // TODO
+ }
+
+ @Override
public void setMatrix(@Nullable Matrix matrix) {
Log.d("Gabe", "setMatrix\t");
// TODO
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/canvas/WrappedCanvas.java b/lottie/src/main/java/com/airbnb/lottie/animation/canvas/WrappedCanvas.java
index c444465..8faba94 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/canvas/WrappedCanvas.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/canvas/WrappedCanvas.java
@@ -79,6 +79,11 @@
}
@Override
+ public void drawRect(float left, float top, float right, float bottom, Paint paint) {
+ canvas.drawRect(left, top, right, bottom, paint);
+ }
+
+ @Override
public void setMatrix(@Nullable Matrix matrix) {
canvas.setMatrix(matrix);
}
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java
index 98d8031..9cbae87 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java
@@ -144,7 +144,7 @@
}
@Override
- public void draw(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix) {
+ public void draw(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix) {
L.beginSection("StrokeContent#draw");
int alpha = (int) ((parentAlpha / 255f * opacityAnimation.getValue() / 100f) * 255);
paint.setAlpha(clamp(alpha, 0, 255));
@@ -166,7 +166,7 @@
if (pathGroup.trimPath != null) {
- applyTrimPath(canvas, pathGroup, parentMatrix, mask, maskMatrix, matteMatrix);
+ applyTrimPath(canvas, pathGroup, parentMatrix, mask, maskMatrix);
} else {
L.beginSection("StrokeContent#buildPath");
path.reset();
@@ -178,7 +178,7 @@
// Stroke has to use Canvas.clipPath so that it actually clips the stroke rather than creating
// a new path of the content combined with the stroke. Doing that would cause Lottie to draw a stroke
// on the mask edge that wasn't part of the original path.
- Path maskPath = mask.getMaskPath(path, maskMatrix, matteMatrix, parentMatrix, false);
+ Path maskPath = mask.getMaskPath(path, maskMatrix, false);
maskPath.computeBounds(maskBounds, false);
path.computeBounds(pathBounds, false);
pathBounds.inset(-strokeWidth, -strokeWidth);
@@ -198,7 +198,7 @@
L.endSection("StrokeContent#draw");
}
- private void applyTrimPath(ICanvas canvas, PathGroup pathGroup, Matrix parentMatrix, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix) {
+ private void applyTrimPath(ICanvas canvas, PathGroup pathGroup, Matrix parentMatrix, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix) {
L.beginSection("StrokeContent#applyTrimPath");
if (pathGroup.trimPath == null) {
L.endSection("StrokeContent#applyTrimPath");
@@ -238,7 +238,7 @@
float endValue = Math.min((endLength - totalLength) / length, 1);
Utils.applyTrimPathIfNeeded(trimPathPath, startValue, endValue, 0);
if (mask != null) {
- mask.applyToPath(path, maskMatrix, matteMatrix, parentMatrix);
+ mask.applyToPath(path, maskMatrix);
}
canvas.drawPath(trimPathPath, paint);
} else
@@ -247,7 +247,7 @@
// Do nothing
} else if (currentLength + length <= endLength && startLength < currentLength) {
if (mask != null) {
- mask.applyToPath(path, maskMatrix, matteMatrix, parentMatrix);
+ mask.applyToPath(path, maskMatrix);
}
canvas.drawPath(trimPathPath, paint);
} else {
@@ -265,7 +265,7 @@
}
Utils.applyTrimPathIfNeeded(trimPathPath, startValue, endValue, 0);
if (mask != null) {
- mask.applyToPath(path, maskMatrix, matteMatrix, parentMatrix);
+ mask.applyToPath(path, maskMatrix);
}
canvas.drawPath(trimPathPath, paint);
}
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/ContentGroup.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/ContentGroup.java
index 9cd4013..1d2e8bc 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/ContentGroup.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/ContentGroup.java
@@ -174,7 +174,7 @@
return paths;
}
- @Override public void draw(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix) {
+ @Override public void draw(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix) {
matrix.set(parentMatrix);
int alpha;
if (transformAnimation != null) {
@@ -189,7 +189,7 @@
for (int i = contents.size() - 1; i >= 0; i--) {
Object content = contents.get(i);
if (content instanceof DrawingContent) {
- ((DrawingContent) content).draw(canvas, matrix, alpha, mask, maskMatrix, matteMatrix);
+ ((DrawingContent) content).draw(canvas, matrix, alpha, mask, maskMatrix);
}
}
}
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/DrawingContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/DrawingContent.java
index b5a5410..69694d5 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/DrawingContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/DrawingContent.java
@@ -7,6 +7,6 @@
import com.airbnb.lottie.animation.keyframe.MaskKeyframeAnimation;
public interface DrawingContent extends Content {
- void draw(ICanvas canvas, Matrix parentMatrix, int alpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix);
+ void draw(ICanvas canvas, Matrix parentMatrix, int alpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix);
void getBounds(RectF outBounds, Matrix parentMatrix);
}
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java
index dd8b073..c9e295d 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java
@@ -74,7 +74,7 @@
return name;
}
- @Override public void draw(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix) {
+ @Override public void draw(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix) {
L.beginSection("FillContent#draw");
paint.setColor(colorAnimation.getValue());
int alpha = (int) ((parentAlpha / 255f * opacityAnimation.getValue() / 100f) * 255);
@@ -90,7 +90,7 @@
}
if (mask != null) {
- mask.applyToPath(path, maskMatrix, matteMatrix, parentMatrix);
+ mask.applyToPath(path, maskMatrix);
}
canvas.drawPath(path, paint);
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
index 65a01f3..0bf8996 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
@@ -95,7 +95,7 @@
}
}
- @Override public void draw(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix) {
+ @Override public void draw(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix) {
L.beginSection("GradientFillContent#draw");
path.reset();
for (int i = 0; i < paths.size(); i++) {
@@ -122,7 +122,7 @@
paint.setAlpha(clamp(alpha, 0, 255));
if (mask != null) {
- mask.applyToPath(path, maskMatrix, matteMatrix, parentMatrix);
+ mask.applyToPath(path, maskMatrix);
}
canvas.drawPath(path, paint);
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientStrokeContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientStrokeContent.java
index a4d963f..6db8e94 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientStrokeContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientStrokeContent.java
@@ -58,7 +58,7 @@
layer.addAnimation(endPointAnimation);
}
- @Override public void draw(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix) {
+ @Override public void draw(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix) {
getBounds(boundsRect, parentMatrix);
if (type == GradientType.Linear) {
paint.setShader(getLinearGradient());
@@ -66,7 +66,7 @@
paint.setShader(getRadialGradient());
}
- super.draw(canvas, parentMatrix, parentAlpha, mask, maskMatrix, matteMatrix);
+ super.draw(canvas, parentMatrix, parentAlpha, mask, maskMatrix);
}
@Override public String getName() {
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/RepeaterContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/RepeaterContent.java
index 9dbb840..58cfb01 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/RepeaterContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/RepeaterContent.java
@@ -102,7 +102,7 @@
return path;
}
- @Override public void draw(ICanvas canvas, Matrix parentMatrix, int alpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix) {
+ @Override public void draw(ICanvas canvas, Matrix parentMatrix, int alpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix) {
float copies = this.copies.getValue();
float offset = this.offset.getValue();
//noinspection ConstantConditions
@@ -113,7 +113,7 @@
matrix.set(parentMatrix);
matrix.preConcat(transform.getMatrixForRepeater(i + offset));
float newAlpha = alpha * MiscUtils.lerp(startOpacity, endOpacity, i / copies);
- contentGroup.draw(canvas, matrix, (int) newAlpha, mask, maskMatrix, parentMatrix);
+ contentGroup.draw(canvas, matrix, (int) newAlpha, mask, maskMatrix);
}
}
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/StrokeContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/StrokeContent.java
index 1cd69ed..40e9781 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/StrokeContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/StrokeContent.java
@@ -34,12 +34,12 @@
layer.addAnimation(colorAnimation);
}
- @Override public void draw(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix) {
+ @Override public void draw(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix) {
paint.setColor(colorAnimation.getValue());
if (colorFilterAnimation != null) {
paint.setColorFilter(colorFilterAnimation.getValue());
}
- super.draw(canvas, parentMatrix, parentAlpha, mask, maskMatrix, matteMatrix);
+ super.draw(canvas, parentMatrix, parentAlpha, mask, maskMatrix);
}
@Override public String getName() {
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/MaskKeyframeAnimation.java b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/MaskKeyframeAnimation.java
index 1746d37..82fbb36 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/MaskKeyframeAnimation.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/MaskKeyframeAnimation.java
@@ -3,15 +3,9 @@
import android.graphics.Matrix;
import android.graphics.Path;
-import android.graphics.RectF;
-import androidx.annotation.Nullable;
-import com.airbnb.lottie.animation.canvas.RecordedCanvas;
import com.airbnb.lottie.model.animatable.AnimatableIntegerValue;
import com.airbnb.lottie.model.content.Mask;
import com.airbnb.lottie.model.content.ShapeData;
-import com.airbnb.lottie.model.layer.BaseLayer;
-import com.airbnb.lottie.model.layer.Layer;
-import com.airbnb.lottie.utils.Utils;
import java.util.ArrayList;
import java.util.List;
@@ -24,14 +18,9 @@
* Reusable path for calculating masks.
*/
private final Path masksPath = new Path();
- private final Path mattesPath = new Path();
private final Path combinedPath = new Path();
private final Path addPath = new Path();
private final Path subtractPath = new Path();
- @Nullable
- public BaseLayer matteLayer;
- @Nullable
- private Layer.MatteType matteType;
public MaskKeyframeAnimation(List<Mask> masks) {
this.masks = masks;
@@ -44,11 +33,6 @@
}
}
- public void setMatteLayer(@Nullable BaseLayer matteLayer, Layer.MatteType matteType) {
- this.matteLayer = matteLayer;
- this.matteType = matteType;
- }
-
public List<Mask> getMasks() {
return masks;
}
@@ -61,12 +45,12 @@
return opacityAnimations;
}
- public void applyToPath(Path contentPath, Matrix maskMatrix, Matrix matteMatrix, Matrix parentMatrix) {
- getMaskPath(contentPath, maskMatrix, matteMatrix, parentMatrix, true);
+ public void applyToPath(Path contentPath, Matrix maskMatrix) {
+ getMaskPath(contentPath, maskMatrix, true);
}
- public Path getMaskPath(Path contentPath, Matrix maskMatrix, Matrix matteMatrix, Matrix parentMatrix, boolean applyToPath) {
- if (getMaskAnimations().isEmpty() && matteLayer == null) {
+ public Path getMaskPath(Path contentPath, Matrix maskMatrix, boolean applyToPath) {
+ if (getMaskAnimations().isEmpty()) {
return contentPath;
}
@@ -91,53 +75,7 @@
}
masksPath.close();
- mattesPath.reset();
-// mattesPath.setFillType(Path.FillType.WINDING);
- if (matteLayer != null && matteType != null) {
- RectF contentBounds = Utils.getBounds(contentPath);
- RecordedCanvas canvas = new RecordedCanvas((int) contentBounds.right, (int) contentBounds.bottom);
-
-
- matteLayer.draw(canvas, matteMatrix, 255, null, new Matrix(), new Matrix());
- List<Path> mattePaths = canvas.getPaths();
- if (matteType == Layer.MatteType.Add) {
- for (int i = 0; i < mattePaths.size(); i++) {
- Path mattePath = new Path(mattePaths.get(i));
- addPath.set(contentPath);
- addPath.op(mattePath, Path.Op.INTERSECT);
- mattesPath.op(addPath, Path.Op.UNION);
- }
- } else if (matteType == Layer.MatteType.Invert) {
- for (int i = 0; i < mattePaths.size(); i++) {
- Path mattePath = new Path(mattePaths.get(i));
- subtractPath.set(contentPath);
- mattePath.transform(matteMatrix);
- subtractPath.op(mattePath, Path.Op.DIFFERENCE);
- }
- if (mattesPath.isEmpty()) {
- mattesPath.addPath(subtractPath);
- } else {
- mattesPath.op(subtractPath, Path.Op.INTERSECT);
- }
-
-
-// subtractPath.set(contentPath);
-// subtractPath.op(mattePath, Path.Op.DIFFERENCE);
-// if (combinedPath.isEmpty()) {
-// combinedPath.addPath(contentPath);
-// }
-// combinedPath.op(subtractPath, Path.Op.INTERSECT);
- }
-
- }
-
- if (!masksPath.isEmpty() && !mattesPath.isEmpty()) {
- combinedPath.op(masksPath, mattesPath, Path.Op.INTERSECT);
- } else if (!masksPath.isEmpty()) {
- combinedPath.set(masksPath);
- } else if (mattesPath != null) {
- combinedPath.set(mattesPath);
- }
+ combinedPath.set(masksPath);
if (applyToPath) {
contentPath.set(combinedPath);
}
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
index 9bfacae..6f4fa41 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
@@ -1,6 +1,8 @@
package com.airbnb.lottie.model.layer;
+import android.annotation.SuppressLint;
import android.graphics.*;
+import android.os.Build;
import androidx.annotation.CallSuper;
import androidx.annotation.FloatRange;
import androidx.annotation.Nullable;
@@ -18,7 +20,6 @@
import com.airbnb.lottie.animation.keyframe.TransformKeyframeAnimation;
import com.airbnb.lottie.model.KeyPath;
import com.airbnb.lottie.model.KeyPathElement;
-import com.airbnb.lottie.model.content.Mask;
import com.airbnb.lottie.value.LottieValueCallback;
import java.util.ArrayList;
@@ -28,6 +29,15 @@
public abstract class BaseLayer
implements DrawingContent, PathContent, PathsContent, BaseKeyframeAnimation.AnimationListener, KeyPathElement {
+ /**
+ * These flags were in Canvas but they were deprecated and removed.
+ * TODO: test removing these on older versions of Android.
+ */
+ private static final int CLIP_SAVE_FLAG = 0x02;
+ private static final int CLIP_TO_LAYER_SAVE_FLAG = 0x10;
+ private static final int MATRIX_SAVE_FLAG = 0x01;
+ private static final int SAVE_FLAGS = CLIP_SAVE_FLAG | CLIP_TO_LAYER_SAVE_FLAG | MATRIX_SAVE_FLAG;
+
@Nullable
static BaseLayer forModel(
Layer layerModel, LottieDrawable drawable, LottieComposition composition) {
@@ -55,6 +65,12 @@
private final Path path = new Path();
private final Matrix matrix = new Matrix();
+ private final Paint contentPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final Paint mattePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final Paint clearPaint = new Paint();
+ private final RectF rect = new RectF();
+ private final RectF matteBoundsRect = new RectF();
+ private final RectF tempMaskBoundsRect = new RectF();
private final String drawTraceName;
final Matrix boundsMatrix = new Matrix();
final LottieDrawable lottieDrawable;
@@ -72,6 +88,12 @@
this.lottieDrawable = lottieDrawable;
this.layerModel = layerModel;
drawTraceName = layerModel.getName() + "#draw";
+ clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+ if (layerModel.getMatteType() == Layer.MatteType.Invert) {
+ mattePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+ } else {
+ mattePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
+ }
this.transform = layerModel.getTransform().createAnimation();
transform.addListener(this);
@@ -100,12 +122,6 @@
}
void setMatteLayer(@Nullable BaseLayer matteLayer) {
- if (mask != null) {
- mask.setMatteLayer(matteLayer, layerModel.getMatteType());
- } else {
- mask = new MaskKeyframeAnimation(Collections.<Mask>emptyList());
- mask.setMatteLayer(matteLayer, layerModel.getMatteType());
- }
this.matteLayer = matteLayer;
}
@@ -138,6 +154,17 @@
lottieDrawable.invalidateSelf();
}
+ @SuppressLint("WrongConstant")
+ private void saveLayerCompat(ICanvas canvas, RectF rect, Paint paint, boolean all) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+ // This method was deprecated in API level 26 and not recommended since 22, but its
+ // 2-parameter replacement is only available starting at API level 21.
+ canvas.saveLayer(rect, paint, all ? Canvas.ALL_SAVE_FLAG : SAVE_FLAGS);
+ } else {
+ canvas.saveLayer(rect, paint);
+ }
+ }
+
public void addAnimation(BaseKeyframeAnimation<?, ?> newAnimation) {
animations.add(newAnimation);
}
@@ -148,7 +175,7 @@
}
@Override
- public void draw(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix) {
+ public void draw(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix) {
L.beginSection(drawTraceName);
if (!visible) {
L.endSection(drawTraceName);
@@ -164,12 +191,53 @@
L.endSection("Layer#parentMatrix");
int alpha = (int)
((parentAlpha / 255f * (float) transform.getOpacity().getValue() / 100f) * 255);
- matrix.preConcat(transform.getMatrix());
- L.beginSection("Layer#drawLayer");
- // TODO: figure out the right mask to use.
MaskKeyframeAnimation layerMask = this.mask != null ? this.mask : mask;
- drawLayer(canvas, matrix, alpha, layerMask, matrix, matteMatrix);
+ if (!hasMatteOnThisLayer()) {
+ matrix.preConcat(transform.getMatrix());
+ L.beginSection("Layer#drawLayer");
+ drawLayer(canvas, matrix, alpha, layerMask, matrix);
+ L.endSection("Layer#drawLayer");
+ recordRenderTime(L.endSection(drawTraceName));
+ return;
+ }
+
+ L.beginSection("Layer#computeBounds");
+ rect.set(0, 0, 0, 0);
+ getBounds(rect, matrix);
+ intersectBoundsWithMatte(rect, matrix);
+
+ matrix.preConcat(transform.getMatrix());
+
+ rect.set(0, 0, canvas.getWidth(), canvas.getHeight());
+ L.endSection("Layer#computeBounds");
+
+ L.beginSection("Layer#saveLayer");
+ saveLayerCompat(canvas, rect, contentPaint, true);
+ L.endSection("Layer#saveLayer");
+
+ // Clear the off screen buffer. This is necessary for some phones.
+ clearCanvas(canvas);
+ L.beginSection("Layer#drawLayer");
+ drawLayer(canvas, matrix, alpha, layerMask, matrix);
L.endSection("Layer#drawLayer");
+
+ if (hasMatteOnThisLayer()) {
+ L.beginSection("Layer#drawMatte");
+ L.beginSection("Layer#saveLayer");
+ saveLayerCompat(canvas, rect, mattePaint, false);
+ L.endSection("Layer#saveLayer");
+ clearCanvas(canvas);
+ //noinspection ConstantConditions
+ matteLayer.draw(canvas, parentMatrix, alpha, layerMask, matrix);
+ L.beginSection("Layer#restoreLayer");
+ canvas.restore();
+ L.endSection("Layer#restoreLayer");
+ L.endSection("Layer#drawMatte");
+ }
+
+ L.beginSection("Layer#restoreLayer");
+ canvas.restore();
+ L.endSection("Layer#restoreLayer");
recordRenderTime(L.endSection(drawTraceName));
}
@@ -180,10 +248,35 @@
private void recordRenderTime(float ms) {
lottieDrawable.getComposition()
.getPerformanceTracker().recordRenderTime(layerModel.getName(), ms);
-
}
- abstract void drawLayer(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix);
+ private void clearCanvas(ICanvas canvas) {
+ L.beginSection("Layer#clearLayer");
+ // If we don't pad the clear draw, some phones leave a 1px border of the graphics buffer.
+ canvas.drawRect(rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1, clearPaint);
+ L.endSection("Layer#clearLayer");
+ }
+
+ private void intersectBoundsWithMatte(RectF rect, Matrix matrix) {
+ if (!hasMatteOnThisLayer()) {
+ return;
+ }
+ if (layerModel.getMatteType() == Layer.MatteType.Invert) {
+ // We can't trim the bounds if the mask is inverted since it extends all the way to the
+ // composition bounds.
+ return;
+ }
+ //noinspection ConstantConditions
+ matteLayer.getBounds(matteBoundsRect, matrix);
+ rect.set(
+ Math.max(rect.left, matteBoundsRect.left),
+ Math.max(rect.top, matteBoundsRect.top),
+ Math.min(rect.right, matteBoundsRect.right),
+ Math.min(rect.bottom, matteBoundsRect.bottom)
+ );
+ }
+
+ abstract void drawLayer(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix);
boolean hasMasksOnThisLayer() {
return mask != null && !mask.getMaskAnimations().isEmpty();
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java
index f5fba64..0d8ba44 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java
@@ -88,7 +88,7 @@
}
}
- @Override void drawLayer(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix) {
+ @Override void drawLayer(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix) {
L.beginSection("CompositionLayer#draw");
canvas.save();
newClipRect.set(0, 0, layerModel.getPreCompWidth(), layerModel.getPreCompHeight());
@@ -101,7 +101,7 @@
}
if (nonEmptyClip) {
BaseLayer layer = layers.get(i);
- layer.draw(canvas, parentMatrix, parentAlpha, mask, maskMatrix, parentMatrix);
+ layer.draw(canvas, parentMatrix, parentAlpha, mask, maskMatrix);
}
}
canvas.restore();
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/ImageLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/ImageLayer.java
index 3a6ffa4..33c48e0 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/ImageLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/ImageLayer.java
@@ -30,7 +30,7 @@
super(lottieDrawable, layerModel);
}
- @Override public void drawLayer(@NonNull ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix) {
+ @Override public void drawLayer(@NonNull ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix) {
Bitmap bitmap = getBitmap();
if (bitmap == null || bitmap.isRecycled()) {
return;
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/NullLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/NullLayer.java
index 4f9f80d..57c1ee8 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/NullLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/NullLayer.java
@@ -19,7 +19,7 @@
super(lottieDrawable, layerModel);
}
- @Override void drawLayer(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix) {
+ @Override void drawLayer(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix) {
// Do nothing.
}
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java
index 39a8356..1f96406 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java
@@ -32,8 +32,8 @@
contentGroup.setContents(Collections.<Content>emptyList(), Collections.<Content>emptyList());
}
- @Override void drawLayer(@NonNull ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix) {
- contentGroup.draw(canvas, parentMatrix, parentAlpha, mask, maskMatrix, matteMatrix);
+ @Override void drawLayer(@NonNull ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix) {
+ contentGroup.draw(canvas, parentMatrix, parentAlpha, mask, maskMatrix);
}
@Override public void getBounds(RectF outBounds, Matrix parentMatrix) {
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/SolidLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/SolidLayer.java
index daf3950..111d793 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/SolidLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/SolidLayer.java
@@ -38,7 +38,7 @@
paint.setColor(layerModel.getSolidColor());
}
- @Override public void drawLayer(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix) {
+ @Override public void drawLayer(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix) {
int backgroundAlpha = Color.alpha(layerModel.getSolidColor());
if (backgroundAlpha == 0) {
return;
@@ -72,7 +72,7 @@
if (mask != null) {
// TODO: use the right matte matrix
- mask.applyToPath(path, maskMatrix, parentMatrix, new Matrix());
+ mask.applyToPath(path, maskMatrix);
}
canvas.drawPath(path, paint);
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/TextLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/TextLayer.java
index 26b0a95..a73ee68 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/TextLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/TextLayer.java
@@ -1,6 +1,5 @@
package com.airbnb.lottie.model.layer;
-import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
@@ -95,7 +94,7 @@
return Collections.emptyList();
}
- @Override void drawLayer(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix, Matrix matteMatrix) {
+ @Override void drawLayer(ICanvas canvas, Matrix parentMatrix, int parentAlpha, @Nullable MaskKeyframeAnimation mask, Matrix maskMatrix) {
canvas.save();
if (!lottieDrawable.useTextGlyphs()) {
canvas.setMatrix(parentMatrix);
@@ -235,7 +234,7 @@
if (mask != null) {
// TODO: use the right matte matrix
- mask.applyToPath(path, maskMatrix, matteMatrix, new Matrix());
+ mask.applyToPath(path, maskMatrix);
}
canvas.drawPath(path, paint);