blob: 4214de842506231983940f1a1356e8bbce6e957c [file] [log] [blame]
package com.airbnb.lottie;
import android.annotation.TargetApi;
import android.graphics.Path;
import android.os.Build;
import java.util.ArrayList;
import java.util.List;
@TargetApi(Build.VERSION_CODES.KITKAT)
class MergePathsContent implements PathContent {
private final Path firstPath = new Path();
private final Path remainderPath = new Path();
private final Path path = new Path();
private final List<PathContent> pathContents = new ArrayList<>();
private final MergePaths mergePaths;
MergePathsContent(MergePaths mergePaths) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
throw new IllegalStateException("Merge paths are not supported pre-KitKat.");
}
this.mergePaths = mergePaths;
}
void addContentIfNeeded(Content content) {
if (content instanceof PathContent) {
pathContents.add((PathContent) content);
}
}
@Override public void setContents(List<Content> contentsBefore, List<Content> contentsAfter) {
for (int i = 0; i < pathContents.size(); i++) {
pathContents.get(i).setContents(contentsBefore, contentsAfter);
}
}
@Override public Path getPath() {
path.reset();
switch (mergePaths.getMode()) {
case Merge:
addPaths();
break;
case Add:
opFirstPathWithRest(Path.Op.UNION);
break;
case Subtract:
opFirstPathWithRest(Path.Op.REVERSE_DIFFERENCE);
break;
case Intersect:
opFirstPathWithRest(Path.Op.INTERSECT);
break;
case ExcludeIntersections:
opFirstPathWithRest(Path.Op.XOR);
break;
}
return path;
}
private void addPaths() {
for (int i = 0; i < pathContents.size(); i++) {
path.addPath(pathContents.get(i).getPath());
}
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private void opFirstPathWithRest(Path.Op op) {
remainderPath.reset();
firstPath.reset();
for (int i = pathContents.size() - 1; i >= 1; i--) {
PathContent content = pathContents.get(i);
if (content instanceof ContentGroup) {
List<PathContent> pathList = ((ContentGroup) content).getPathList();
for (int j = pathList.size() - 1; j >= 0; j--) {
Path path = pathList.get(j).getPath();
path.transform(((ContentGroup) content).getTransformationMatrix());
this.remainderPath.addPath(path);
}
} else {
remainderPath.addPath(content.getPath());
}
}
PathContent lastContent = pathContents.get(0);
if (lastContent instanceof ContentGroup) {
List<PathContent> pathList = ((ContentGroup) lastContent).getPathList();
for (int j = 0; j < pathList.size(); j++) {
Path path = pathList.get(j).getPath();
path.transform(((ContentGroup) lastContent).getTransformationMatrix());
this.firstPath.addPath(path);
}
} else {
firstPath.set(lastContent.getPath());
}
path.op(firstPath, remainderPath, op);
}
}