1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14
15package org.robolectric.shadows;
16
17import static android.os.Build.VERSION_CODES.N;
18import static org.robolectric.shadows.ShadowVirtualRefBasePtr.get;
19import static org.robolectric.shadows.ShadowVirtualRefBasePtr.put;
20
21import android.graphics.drawable.VectorDrawable;
22import java.nio.ByteBuffer;
23import java.nio.ByteOrder;
24import org.robolectric.annotation.Implementation;
25import org.robolectric.annotation.Implements;
26
27@Implements(value = VectorDrawable.class, minSdk = N)
28public class ShadowVectorDrawable extends ShadowDrawable {
29  //  private static native long nCreateTree(long rootGroupPtr);
30//  private static native long nCreateTreeFromCopy(long treeToCopy, long rootGroupPtr);
31//  private static native void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
32//                                                      float viewportHeight);
33//  private static native boolean nSetRootAlpha(long rendererPtr, float alpha);
34//  private static native float nGetRootAlpha(long rendererPtr);
35//  private static native void nSetAllowCaching(long rendererPtr, boolean allowCaching);
36//
37//  private static native int nDraw(long rendererPtr, long canvasWrapperPtr,
38//                                  long colorFilterPtr, Rect bounds, boolean needsMirroring, boolean canReuseCache);
39
40  private static final int STROKE_WIDTH_INDEX = 0;
41  private static final int STROKE_COLOR_INDEX = 1;
42  private static final int STROKE_ALPHA_INDEX = 2;
43  private static final int FILL_COLOR_INDEX = 3;
44  private static final int FILL_ALPHA_INDEX = 4;
45  private static final int TRIM_PATH_START_INDEX = 5;
46  private static final int TRIM_PATH_END_INDEX = 6;
47  private static final int TRIM_PATH_OFFSET_INDEX = 7;
48  private static final int STROKE_LINE_CAP_INDEX = 8;
49  private static final int STROKE_LINE_JOIN_INDEX = 9;
50  private static final int STROKE_MITER_LIMIT_INDEX = 10;
51  private static final int FILL_TYPE_INDEX = 11;
52  private static final int TOTAL_PROPERTY_COUNT = 12;
53
54  private static class Path implements Cloneable {
55    float strokeWidth;
56    int strokeColor;
57    float strokeAlpha;
58    int fillColor;
59    float fillAlpha;
60    float trimPathStart;
61    float trimPathEnd;
62    float trimPathOffset;
63    int strokeLineCap;
64    int strokeLineJoin;
65    float strokeMiterLimit;
66    int fillType;
67
68    @Override
69    protected Object clone() {
70      try {
71        return super.clone();
72      } catch (CloneNotSupportedException e) {
73        throw new RuntimeException(e);
74      }
75    }
76  }
77
78  private static Path getPath(long pathPtr) {
79    return get(pathPtr, Path.class);
80  }
81
82
83  @Implementation
84  public static long nCreateFullPath() {
85    return put(new Path());
86  }
87
88  @Implementation
89  public static long nCreateFullPath(long nativeFullPathPtr) {
90    return put(getPath(nativeFullPathPtr).clone());
91  }
92
93  @Implementation
94  public static boolean nGetFullPathProperties(long pathPtr, byte[] properties,
95                                               int length) {
96    if (length != TOTAL_PROPERTY_COUNT * 4) return false;
97
98    Path path = getPath(pathPtr);
99    ByteBuffer propertiesBB = ByteBuffer.wrap(properties);
100    propertiesBB.order(ByteOrder.nativeOrder());
101    propertiesBB.putFloat(STROKE_WIDTH_INDEX * 4, path.strokeWidth);
102    propertiesBB.putInt(STROKE_COLOR_INDEX * 4, path.strokeColor);
103    propertiesBB.putFloat(STROKE_ALPHA_INDEX * 4, path.strokeAlpha);
104    propertiesBB.putInt(FILL_COLOR_INDEX * 4, path.fillColor);
105    propertiesBB.putFloat(FILL_ALPHA_INDEX * 4, path.fillAlpha);
106    propertiesBB.putFloat(TRIM_PATH_START_INDEX * 4, path.trimPathStart);
107    propertiesBB.putFloat(TRIM_PATH_END_INDEX * 4, path.trimPathEnd);
108    propertiesBB.putFloat(TRIM_PATH_OFFSET_INDEX * 4, path.trimPathOffset);
109    propertiesBB.putInt(STROKE_LINE_CAP_INDEX * 4, path.strokeLineCap);
110    propertiesBB.putInt(STROKE_LINE_JOIN_INDEX * 4, path.strokeLineJoin);
111    propertiesBB.putFloat(STROKE_MITER_LIMIT_INDEX * 4, path.strokeMiterLimit);
112    propertiesBB.putInt(FILL_TYPE_INDEX * 4, path.fillType);
113
114    return true;
115  }
116
117  @Implementation
118  public static void nUpdateFullPathProperties(long pathPtr, float strokeWidth,
119                                               int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
120                                               float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
121                                               int strokeLineJoin, int fillType) {
122    Path path = getPath(pathPtr);
123    path.strokeWidth = strokeWidth;
124    path.strokeColor = strokeColor;
125    path.strokeAlpha = strokeAlpha;
126    path.fillColor = fillColor;
127    path.fillAlpha = fillAlpha;
128    path.trimPathStart = trimPathStart;
129    path.trimPathEnd = trimPathEnd;
130    path.trimPathOffset = trimPathOffset;
131    path.strokeLineCap = strokeLineCap;
132    path.strokeLineJoin = strokeLineJoin;
133    path.strokeMiterLimit = strokeMiterLimit;
134    path.fillType = fillType;
135  }
136
137//  @Implementation
138//  public static void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr) {
139//
140//  }
141//
142//  @Implementation
143//  public static void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr) {
144//
145//  }
146//
147//  private static native long nCreateClipPath();
148//  private static native long nCreateClipPath(long clipPathPtr);
149
150
151  static class Group implements Cloneable {
152    float rotation;
153    float pivotX;
154    float pivotY;
155    float scaleX;
156    float scaleY;
157    float translateX;
158    float translateY;
159
160    @Override
161    protected Object clone() {
162      try {
163        return super.clone();
164      } catch (CloneNotSupportedException e) {
165        throw new RuntimeException(e);
166      }
167    }
168  }
169
170  private static Group getGroup(long groupPtr) {
171    return get(groupPtr, Group.class);
172  }
173
174  @Implementation
175  public static long nCreateGroup() {
176    return put(new Group());
177  }
178
179  @Implementation
180  public static long nCreateGroup(long groupPtr) {
181    return put(getGroup(groupPtr).clone());
182  }
183
184//  public static void nSetName(long nodePtr, String name) {
185//  }
186
187  @Implementation
188  public static boolean nGetGroupProperties(long groupPtr, float[] properties,
189                                            int length) {
190    if (length != 7) return false;
191    Group group = getGroup(groupPtr);
192    properties[0] = group.rotation;
193    properties[1] = group.pivotX;
194    properties[2] = group.pivotY;
195    properties[3] = group.scaleX;
196    properties[4] = group.scaleY;
197    properties[5] = group.translateX;
198    properties[6] = group.translateY;
199    return true;
200  }
201
202  @Implementation
203  public static void nUpdateGroupProperties(long groupPtr, float rotate, float pivotX,
204                                            float pivotY, float scaleX, float scaleY, float translateX, float translateY) {
205    Group group = getGroup(groupPtr);
206    group.rotation = rotate;
207    group.pivotX = pivotX;
208    group.pivotY = pivotY;
209    group.scaleX = scaleX;
210    group.scaleY = scaleY;
211    group.translateX = translateX;
212    group.translateY = translateY;
213  }
214
215//  private static native void nAddChild(long groupPtr, long nodePtr);
216//  private static native void nSetPathString(long pathPtr, String pathString, int length);
217//
218//  /**
219//   * The setters and getters below for paths and groups are here temporarily, and will be
220//   * removed once the animation in AVD is replaced with RenderNodeAnimator, in which case the
221//   * animation will modify these properties in native. By then no JNI hopping would be necessary
222//   * for VD during animation, and these setters and getters will be obsolete.
223//   */
224//  // Setters and getters during animation.
225//  private static native float nGetRotation(long groupPtr);
226//  private static native void nSetRotation(long groupPtr, float rotation);
227//  private static native float nGetPivotX(long groupPtr);
228//  private static native void nSetPivotX(long groupPtr, float pivotX);
229//  private static native float nGetPivotY(long groupPtr);
230//  private static native void nSetPivotY(long groupPtr, float pivotY);
231//  private static native float nGetScaleX(long groupPtr);
232//  private static native void nSetScaleX(long groupPtr, float scaleX);
233//  private static native float nGetScaleY(long groupPtr);
234//  private static native void nSetScaleY(long groupPtr, float scaleY);
235//  private static native float nGetTranslateX(long groupPtr);
236//  private static native void nSetTranslateX(long groupPtr, float translateX);
237//  private static native float nGetTranslateY(long groupPtr);
238//  private static native void nSetTranslateY(long groupPtr, float translateY);
239//
240//  // Setters and getters for VPath during animation.
241//  private static native void nSetPathData(long pathPtr, long pathDataPtr);
242//  private static native float nGetStrokeWidth(long pathPtr);
243//  private static native void nSetStrokeWidth(long pathPtr, float width);
244//  private static native int nGetStrokeColor(long pathPtr);
245//  private static native void nSetStrokeColor(long pathPtr, int strokeColor);
246//  private static native float nGetStrokeAlpha(long pathPtr);
247//  private static native void nSetStrokeAlpha(long pathPtr, float alpha);
248//  private static native int nGetFillColor(long pathPtr);
249//  private static native void nSetFillColor(long pathPtr, int fillColor);
250//  private static native float nGetFillAlpha(long pathPtr);
251//  private static native void nSetFillAlpha(long pathPtr, float fillAlpha);
252//  private static native float nGetTrimPathStart(long pathPtr);
253//  private static native void nSetTrimPathStart(long pathPtr, float trimPathStart);
254//  private static native float nGetTrimPathEnd(long pathPtr);
255//  private static native void nSetTrimPathEnd(long pathPtr, float trimPathEnd);
256//  private static native float nGetTrimPathOffset(long pathPtr);
257//  private static native void nSetTrimPathOffset(long pathPtr, float trimPathOffset);
258
259}