267 lines
9.0 KiB
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);
|
|
}
|
|
}
|