summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/layoutlib/bridge/src/android/animation/AnimatorInflater_Delegate.java59
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java210
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java79
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java2
4 files changed, 246 insertions, 104 deletions
diff --git a/tools/layoutlib/bridge/src/android/animation/AnimatorInflater_Delegate.java b/tools/layoutlib/bridge/src/android/animation/AnimatorInflater_Delegate.java
deleted file mode 100644
index 4475fa4..0000000
--- a/tools/layoutlib/bridge/src/android/animation/AnimatorInflater_Delegate.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2014 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 android.animation;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
-import android.content.res.Resources.Theme;
-import android.util.AttributeSet;
-
-/**
- * Delegate providing alternate implementation to static methods in {@link AnimatorInflater}.
- */
-public class AnimatorInflater_Delegate {
-
- @LayoutlibDelegate
- /*package*/ static Animator loadAnimator(Context context, int id)
- throws NotFoundException {
- return loadAnimator(context.getResources(), context.getTheme(), id);
- }
-
- @LayoutlibDelegate
- /*package*/ static Animator loadAnimator(Resources resources, Theme theme, int id)
- throws NotFoundException {
- return loadAnimator(resources, theme, id, 1);
- }
-
- @LayoutlibDelegate
- /*package*/ static Animator loadAnimator(Resources resources, Theme theme, int id,
- float pathErrorScale) throws NotFoundException {
- // This is a temporary fix to http://b.android.com/77865. This skips loading the
- // animation altogether.
- // TODO: Remove this override when Path.approximate() is supported.
- return new FakeAnimator();
- }
-
- @LayoutlibDelegate
- /*package*/ static ValueAnimator loadAnimator(Resources res, Theme theme,
- AttributeSet attrs, ValueAnimator anim, float pathErrorScale)
- throws NotFoundException {
- return AnimatorInflater.loadAnimator_Original(res, theme, attrs, anim, pathErrorScale);
- }
-}
diff --git a/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java
new file mode 100644
index 0000000..dd2978f
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java
@@ -0,0 +1,210 @@
+/*
+ * 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 android.graphics;
+
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+
+/**
+ * Delegate implementing the native methods of {@link android.graphics.PathMeasure}
+ * <p/>
+ * Through the layoutlib_create tool, the original native methods of PathMeasure have been
+ * replaced by
+ * calls to methods of the same name in this delegate class.
+ * <p/>
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between it
+ * and the original PathMeasure class.
+ *
+ * @see DelegateManager
+ */
+public final class PathMeasure_Delegate {
+ // ---- delegate manager ----
+ private static final DelegateManager<PathMeasure_Delegate> sManager =
+ new DelegateManager<PathMeasure_Delegate>(PathMeasure_Delegate.class);
+
+ // ---- delegate data ----
+ // This governs how accurate the approximation of the Path is.
+ private static final float PRECISION = 0.002f;
+
+ /**
+ * Array containing the path points components. There are three components for each point:
+ * <ul>
+ * <li>Fraction along the length of the path that the point resides</li>
+ * <li>The x coordinate of the point</li>
+ * <li>The y coordinate of the point</li>
+ * </ul>
+ */
+ private float mPathPoints[];
+ private long mNativePath;
+
+ private PathMeasure_Delegate(long native_path, boolean forceClosed) {
+ mNativePath = native_path;
+ if (forceClosed && mNativePath != 0) {
+ // Copy the path and call close
+ mNativePath = Path_Delegate.init2(native_path);
+ Path_Delegate.native_close(mNativePath);
+ }
+
+ mPathPoints =
+ mNativePath != 0 ? Path_Delegate.native_approximate(mNativePath, PRECISION) : null;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long native_create(long native_path, boolean forceClosed) {
+ return sManager.addNewDelegate(new PathMeasure_Delegate(native_path, forceClosed));
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void native_destroy(long native_instance) {
+ sManager.removeJavaReferenceFor(native_instance);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static boolean native_getPosTan(long native_instance, float distance, float pos[],
+ float tan[]) {
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+ "PathMeasure.getPostTan is not supported.", null, null);
+ return false;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static boolean native_getMatrix(long native_instance, float distance, long
+ native_matrix, int flags) {
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+ "PathMeasure.getMatrix is not supported.", null, null);
+ return false;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static boolean native_nextContour(long native_instance) {
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+ "PathMeasure.nextContour is not supported.", null, null);
+ return false;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void native_setPath(long native_instance, long native_path, boolean
+ forceClosed) {
+ PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance);
+ assert pathMeasure != null;
+
+ if (forceClosed && native_path != 0) {
+ // Copy the path and call close
+ native_path = Path_Delegate.init2(native_path);
+ Path_Delegate.native_close(native_path);
+ }
+ pathMeasure.mNativePath = native_path;
+ pathMeasure.mPathPoints = Path_Delegate.native_approximate(native_path, PRECISION);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static float native_getLength(long native_instance) {
+ PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance);
+ assert pathMeasure != null;
+
+ if (pathMeasure.mPathPoints == null) {
+ return 0;
+ }
+
+ float length = 0;
+ int nPoints = pathMeasure.mPathPoints.length / 3;
+ for (int i = 1; i < nPoints; i++) {
+ length += Point2D.distance(
+ pathMeasure.mPathPoints[(i - 1) * 3 + 1],
+ pathMeasure.mPathPoints[(i - 1) * 3 + 2],
+ pathMeasure.mPathPoints[i*3 + 1],
+ pathMeasure.mPathPoints[i*3 + 2]);
+ }
+
+ return length;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static boolean native_isClosed(long native_instance) {
+ PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance);
+ assert pathMeasure != null;
+
+ Path_Delegate path = Path_Delegate.getDelegate(pathMeasure.mNativePath);
+ if (path == null) {
+ return false;
+ }
+
+ PathIterator pathIterator = path.getJavaShape().getPathIterator(null);
+
+ int type = 0;
+ float segment[] = new float[6];
+ while (!pathIterator.isDone()) {
+ type = pathIterator.currentSegment(segment);
+ pathIterator.next();
+ }
+
+ // A path is a closed path if the last element is SEG_CLOSE
+ return type == PathIterator.SEG_CLOSE;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static boolean native_getSegment(long native_instance, float startD, float stopD,
+ long native_dst_path, boolean startWithMoveTo) {
+ if (startD < 0) {
+ startD = 0;
+ }
+
+ if (startD >= stopD) {
+ return false;
+ }
+
+ PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance);
+ assert pathMeasure != null;
+
+ if (pathMeasure.mPathPoints == null) {
+ return false;
+ }
+
+ float accLength = 0;
+ boolean isZeroLength = true; // Whether the output has zero length or not
+ int nPoints = pathMeasure.mPathPoints.length / 3;
+ for (int i = 0; i < nPoints; i++) {
+ float x = pathMeasure.mPathPoints[i * 3 + 1];
+ float y = pathMeasure.mPathPoints[i * 3 + 2];
+ if (accLength >= startD && accLength <= stopD) {
+ if (startWithMoveTo) {
+ startWithMoveTo = false;
+ Path_Delegate.native_moveTo(native_dst_path, x, y);
+ } else {
+ isZeroLength = false;
+ Path_Delegate.native_lineTo(native_dst_path, x, y);
+ }
+ }
+
+ if (i > 0) {
+ accLength += Point2D.distance(
+ pathMeasure.mPathPoints[(i - 1) * 3 + 1],
+ pathMeasure.mPathPoints[(i - 1) * 3 + 2],
+ pathMeasure.mPathPoints[i * 3 + 1],
+ pathMeasure.mPathPoints[i * 3 + 2]);
+ }
+ }
+
+ return !isZeroLength;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index 3c9a062..a2a53fe 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -36,6 +36,7 @@ import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
+import java.util.ArrayList;
/**
* Delegate implementing the native methods of android.graphics.Path
@@ -173,11 +174,8 @@ public final class Path_Delegate {
@LayoutlibDelegate
/*package*/ static boolean native_isEmpty(long nPath) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return true;
- }
+ return pathDelegate == null || pathDelegate.isEmpty();
- return pathDelegate.isEmpty();
}
@LayoutlibDelegate
@@ -488,54 +486,44 @@ public final class Path_Delegate {
@LayoutlibDelegate
/*package*/ static float[] native_approximate(long nPath, float error) {
- Bridge.getLog().warning(LayoutLog.TAG_UNSUPPORTED, "Path.approximate() not fully supported",
- null);
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return null;
}
- PathIterator pathIterator = pathDelegate.mPath.getPathIterator(null);
- float[] tmp = new float[6];
- float[] coords = new float[6];
- boolean isFirstPoint = true;
- while (!pathIterator.isDone()) {
- int type = pathIterator.currentSegment(tmp);
- switch (type) {
- case PathIterator.SEG_MOVETO:
- case PathIterator.SEG_LINETO:
- store(tmp, coords, 1, isFirstPoint);
- break;
- case PathIterator.SEG_QUADTO:
- store(tmp, coords, 2, isFirstPoint);
- break;
- case PathIterator.SEG_CUBICTO:
- store(tmp, coords, 3, isFirstPoint);
- break;
- case PathIterator.SEG_CLOSE:
- // No points returned.
+ // Get a FlatteningIterator
+ PathIterator iterator = pathDelegate.getJavaShape().getPathIterator(null, error);
+
+ float segment[] = new float[6];
+ float totalLength = 0;
+ ArrayList<Point2D.Float> points = new ArrayList<Point2D.Float>();
+ Point2D.Float previousPoint = null;
+ while (!iterator.isDone()) {
+ int type = iterator.currentSegment(segment);
+ Point2D.Float currentPoint = new Point2D.Float(segment[0], segment[1]);
+ // MoveTo shouldn't affect the length
+ if (previousPoint != null && type != PathIterator.SEG_MOVETO) {
+ totalLength += currentPoint.distance(previousPoint);
}
- isFirstPoint = false;
- pathIterator.next();
+ previousPoint = currentPoint;
+ points.add(currentPoint);
+ iterator.next();
}
- if (isFirstPoint) {
- // No points found
- return new float[0];
- } else {
- return coords;
- }
- }
- private static void store(float[] src, float[] dst, int count, boolean isFirst) {
- if (isFirst) {
- dst[0] = 0; // fraction
- dst[1] = src[0]; // abscissa
- dst[2] = src[1]; // ordinate
- }
- if (count > 1 || !isFirst) {
- dst[3] = 1;
- dst[4] = src[2 * count - 2];
- dst[5] = src[2 * count - 1];
+ int nPoints = points.size();
+ float[] result = new float[nPoints * 3];
+ previousPoint = null;
+ for (int i = 0; i < nPoints; i++) {
+ Point2D.Float point = points.get(i);
+ float distance = previousPoint != null ? (float) previousPoint.distance(point) : .0f;
+ result[i * 3] = distance / totalLength;
+ result[i * 3 + 1] = point.x;
+ result[i * 3 + 2] = point.y;
+
+ totalLength += distance;
+ previousPoint = point;
}
+
+ return result;
}
// ---- Private helper methods ----
@@ -735,6 +723,9 @@ public final class Path_Delegate {
*/
private void cubicTo(float x1, float y1, float x2, float y2,
float x3, float y3) {
+ if (isEmpty()) {
+ mPath.moveTo(0, 0);
+ }
mPath.curveTo(x1, y1, x2, y2, mLastX = x3, mLastY = y3);
}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 484240f..9244310 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -157,7 +157,6 @@ public final class CreateInfo implements ICreateInfo {
* The list of methods to rewrite as delegates.
*/
public final static String[] DELEGATE_METHODS = new String[] {
- "android.animation.AnimatorInflater#loadAnimator", // TODO: remove when Path.approximate() is supported.
"android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
"android.content.res.Resources$Theme#obtainStyledAttributes",
"android.content.res.Resources$Theme#resolveAttribute",
@@ -235,6 +234,7 @@ public final class CreateInfo implements ICreateInfo {
"android.graphics.Path",
"android.graphics.PathDashPathEffect",
"android.graphics.PathEffect",
+ "android.graphics.PathMeasure",
"android.graphics.PixelXorXfermode",
"android.graphics.PorterDuffColorFilter",
"android.graphics.PorterDuffXfermode",