NekoX/TMessagesProj/src/main/java/org/telegram/ui/Components/PathAnimator.java

181 lines
7.2 KiB
Java

/*
* This is the source code of Telegram for Android v. 6.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2020.
*/
package org.telegram.ui.Components;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.FileLog;
import java.util.ArrayList;
public class PathAnimator {
private Path path = new Path();
private float pathTime = -1;
private float scale;
private float tx;
private float ty;
private float durationScale;
private ArrayList<KeyFrame> keyFrames = new ArrayList<>();
private static class KeyFrame {
public ArrayList<Object> commands = new ArrayList<>();
public float time;
}
private static class MoveTo {
public float x;
public float y;
}
private static class LineTo {
public float x;
public float y;
}
private static class CurveTo {
public float x;
public float y;
public float x1;
public float y1;
public float x2;
public float y2;
}
public PathAnimator(float sc, float x, float y, float dsc) {
scale = sc;
tx = x;
ty = y;
durationScale = dsc;
}
public float getDurationScale() {
return durationScale;
}
public void addSvgKeyFrame(String svg, float ms) {
if (svg == null) {
return;
}
try {
KeyFrame keyFrame = new KeyFrame();
keyFrame.time = ms * durationScale;
String[] args = svg.split(" ");
for (int a = 0; a < args.length; a++) {
switch (args[a].charAt(0)) {
case 'M': {
MoveTo moveTo = new MoveTo();
moveTo.x = (Float.parseFloat(args[a + 1]) + tx) * scale;
moveTo.y = (Float.parseFloat(args[a + 2]) + ty) * scale;
keyFrame.commands.add(moveTo);
a += 2;
break;
}
case 'C': {
CurveTo curveTo = new CurveTo();
curveTo.x1 = (Float.parseFloat(args[a + 1]) + tx) * scale;
curveTo.y1 = (Float.parseFloat(args[a + 2]) + ty) * scale;
curveTo.x2 = (Float.parseFloat(args[a + 3]) + tx) * scale;
curveTo.y2 = (Float.parseFloat(args[a + 4]) + ty) * scale;
curveTo.x = (Float.parseFloat(args[a + 5]) + tx) * scale;
curveTo.y = (Float.parseFloat(args[a + 6]) + ty) * scale;
keyFrame.commands.add(curveTo);
a += 6;
break;
}
case 'L': {
LineTo lineTo = new LineTo();
lineTo.x = (Float.parseFloat(args[a + 1]) + tx) * scale;
lineTo.y = (Float.parseFloat(args[a + 2]) + ty) * scale;
keyFrame.commands.add(lineTo);
a += 2;
break;
}
}
}
keyFrames.add(keyFrame);
} catch (Exception e) {
FileLog.e(e);
}
}
public void draw(Canvas canvas, Paint paint, float time) {
if (pathTime != time) {
pathTime = time;
KeyFrame startKeyFrame = null;
KeyFrame endKeyFrame = null;
for (int a = 0, N = keyFrames.size(); a < N; a++) {
KeyFrame keyFrame = keyFrames.get(a);
if ((startKeyFrame == null || startKeyFrame.time < keyFrame.time) && keyFrame.time <= time) {
startKeyFrame = keyFrame;
}
if ((endKeyFrame == null || endKeyFrame.time > keyFrame.time) && keyFrame.time >= time) {
endKeyFrame = keyFrame;
}
}
if (endKeyFrame == startKeyFrame) {
startKeyFrame = null;
}
if (startKeyFrame != null && endKeyFrame == null) {
endKeyFrame = startKeyFrame;
startKeyFrame = null;
}
if (endKeyFrame == null || startKeyFrame != null && startKeyFrame.commands.size() != endKeyFrame.commands.size()) {
return;
}
path.reset();
for (int a = 0, N = endKeyFrame.commands.size(); a < N; a++) {
Object startCommand = startKeyFrame != null ? startKeyFrame.commands.get(a) : null;
Object endCommand = endKeyFrame.commands.get(a);
if (startCommand != null && startCommand.getClass() != endCommand.getClass()) {
return;
}
float progress;
if (startKeyFrame != null) {
progress = (time - startKeyFrame.time) / (endKeyFrame.time - startKeyFrame.time);
} else {
progress = 1.0f;
}
if (endCommand instanceof MoveTo) {
MoveTo end = (MoveTo) endCommand;
MoveTo start = (MoveTo) startCommand;
if (start != null) {
path.moveTo(AndroidUtilities.dpf2(start.x + (end.x - start.x) * progress), AndroidUtilities.dpf2(start.y + (end.y - start.y) * progress));
} else {
path.moveTo(AndroidUtilities.dpf2(end.x), AndroidUtilities.dpf2(end.y));
}
} else if (endCommand instanceof LineTo) {
LineTo end = (LineTo) endCommand;
LineTo start = (LineTo) startCommand;
if (start != null) {
path.lineTo(AndroidUtilities.dpf2(start.x + (end.x - start.x) * progress), AndroidUtilities.dpf2(start.y + (end.y - start.y) * progress));
} else {
path.lineTo(AndroidUtilities.dpf2(end.x), AndroidUtilities.dpf2(end.y));
}
} else if (endCommand instanceof CurveTo) {
CurveTo end = (CurveTo) endCommand;
CurveTo start = (CurveTo) startCommand;
if (start != null) {
path.cubicTo(AndroidUtilities.dpf2(start.x1 + (end.x1 - start.x1) * progress), AndroidUtilities.dpf2(start.y1 + (end.y1 - start.y1) * progress),
AndroidUtilities.dpf2(start.x2 + (end.x2 - start.x2) * progress), AndroidUtilities.dpf2(start.y2 + (end.y2 - start.y2) * progress),
AndroidUtilities.dpf2(start.x + (end.x - start.x) * progress), AndroidUtilities.dpf2(start.y + (end.y - start.y) * progress));
} else {
path.cubicTo(AndroidUtilities.dpf2(end.x1), AndroidUtilities.dpf2(end.y1), AndroidUtilities.dpf2(end.x2), AndroidUtilities.dpf2(end.y2), AndroidUtilities.dpf2(end.x), AndroidUtilities.dpf2(end.y));
}
}
}
path.close();
}
canvas.drawPath(path, paint);
}
}