SubwayTooter-Android-App/_Emoji/src/main/java/com/android/ide/common/vectordrawable/VdPath.java

267 lines
9.0 KiB
Java

/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ide.common.vectordrawable;
import java.awt.geom.Path2D;
import java.util.Arrays;
/**
* Used to represent one VectorDrawble's path element.
*/
class VdPath extends VdElement{
Node[] mNode = null;
int mStrokeColor = 0;
int mFillColor = 0;
float mStrokeWidth = 0;
float mRotate = 0;
float mShiftX = 0;
float mShiftY = 0;
float mRotateX = 0;
float mRotateY = 0;
float trimPathStart = 0;
float trimPathEnd = 1;
float trimPathOffset = 0;
int mStrokeLineCap = -1;
int mStrokeLineJoin = -1;
float mStrokeMiterlimit = -1;
boolean mClip = false;
float mStrokeOpacity = Float.NaN;
float mFillOpacity = Float.NaN;
float mTrimPathStart = 0;
float mTrimPathEnd = 1;
float mTrimPathOffset = 0;
public void toPath(Path2D path) {
path.reset();
if (mNode != null) {
VdNodeRender.creatPath(mNode, path);
}
}
public static class Node {
char type;
float[] params;
public Node(char type, float[] params) {
this.type = type;
this.params = params;
}
public Node(Node n) {
this.type = n.type;
this.params = Arrays.copyOf(n.params, n.params.length);
}
public static String NodeListToString(Node[] nodes) {
String s = "";
for (int i = 0; i < nodes.length; i++) {
Node n = nodes[i];
s += n.type;
int len = n.params.length;
for (int j = 0; j < len; j++) {
if (j > 0) {
s += ((j & 1) == 1) ? "," : " ";
}
// To avoid trailing zeros like 17.0, use this trick
float value = n.params[j];
if (value == (long) value) {
s += String.valueOf((long) value);
} else {
s += String.valueOf(value);
}
}
}
return s;
}
public static void transform(float a,
float b,
float c,
float d,
float e,
float f,
Node[] nodes) {
float[] pre = new float[2];
for (int i = 0; i < nodes.length; i++) {
nodes[i].transform(a, b, c, d, e, f, pre);
}
}
public void transform(float a,
float b,
float c,
float d,
float e,
float f,
float[] pre) {
int incr = 0;
float[] tempParams;
float[] origParams;
switch (type) {
case 'z':
case 'Z':
return;
case 'M':
case 'L':
case 'T':
incr = 2;
pre[0] = params[params.length - 2];
pre[1] = params[params.length - 1];
for (int i = 0; i < params.length; i += incr) {
matrix(a, b, c, d, e, f, i, i + 1);
}
break;
case 'm':
case 'l':
case 't':
incr = 2;
pre[0] += params[params.length - 2];
pre[1] += params[params.length - 1];
for (int i = 0; i < params.length; i += incr) {
matrix(a, b, c, d, 0, 0, i, i + 1);
}
break;
case 'h':
type = 'l';
pre[0] += params[params.length - 1];
tempParams = new float[params.length * 2];
origParams = params;
params = tempParams;
for (int i = 0; i < params.length; i += 2) {
params[i] = origParams[i / 2];
params[i + 1] = 0;
matrix(a, b, c, d, 0, 0, i, i + 1);
}
break;
case 'H':
type = 'L';
pre[0] = params[params.length - 1];
tempParams = new float[params.length * 2];
origParams = params;
params = tempParams;
for (int i = 0; i < params.length; i += 2) {
params[i] = origParams[i / 2];
params[i + 1] = pre[1];
matrix(a, b, c, d, e, f, i, i + 1);
}
break;
case 'v':
pre[1] += params[params.length - 1];
type = 'l';
tempParams = new float[params.length * 2];
origParams = params;
params = tempParams;
for (int i = 0; i < params.length; i += 2) {
params[i] = 0;
params[i + 1] = origParams[i / 2];
matrix(a, b, c, d, 0, 0, i, i + 1);
}
break;
case 'V':
type = 'L';
pre[1] = params[params.length - 1];
tempParams = new float[params.length * 2];
origParams = params;
params = tempParams;
for (int i = 0; i < params.length; i += 2) {
params[i] = pre[0];
params[i + 1] = origParams[i / 2];
matrix(a, b, c, d, e, f, i, i + 1);
}
break;
case 'C':
case 'S':
case 'Q':
pre[0] = params[params.length - 2];
pre[1] = params[params.length - 1];
for (int i = 0; i < params.length; i += 2) {
matrix(a, b, c, d, e, f, i, i + 1);
}
break;
case 's':
case 'q':
case 'c':
pre[0] += params[params.length - 2];
pre[1] += params[params.length - 1];
for (int i = 0; i < params.length; i += 2) {
matrix(a, b, c, d, 0, 0, i, i + 1);
}
break;
case 'a':
incr = 7;
pre[0] += params[params.length - 2];
pre[1] += params[params.length - 1];
for (int i = 0; i < params.length; i += incr) {
matrix(a, b, c, d, 0, 0, i, i + 1);
double ang = Math.toRadians(params[i + 2]);
params[i + 2] = (float) Math.toDegrees(ang + Math.atan2(b, d));
matrix(a, b, c, d, 0, 0, i + 5, i + 6);
}
break;
case 'A':
incr = 7;
pre[0] = params[params.length - 2];
pre[1] = params[params.length - 1];
for (int i = 0; i < params.length; i += incr) {
matrix(a, b, c, d, e, f, i, i + 1);
double ang = Math.toRadians(params[i + 2]);
params[i + 2] = (float) Math.toDegrees(ang + Math.atan2(b, d));
matrix(a, b, c, d, e, f, i + 5, i + 6);
}
break;
}
}
void matrix(float a,
float b,
float c,
float d,
float e,
float f,
int offx,
int offy) {
float inx = (offx < 0) ? 1 : params[offx];
float iny = (offy < 0) ? 1 : params[offy];
float x = inx * a + iny * c + e;
float y = inx * b + iny * d + f;
if (offx >= 0) {
params[offx] = x;
}
if (offy >= 0) {
params[offy] = y;
}
}
}
public VdPath() {
mName = this.toString(); // to ensure paths have unique names
}
/**
* TODO: support rotation attribute for stroke width
*/
public void transform(float a, float b, float c, float d, float e, float f) {
mStrokeWidth *= Math.hypot(a + b, c + d);
Node.transform(a, b, c, d, e, f, mNode);
}
}