diff options
Diffstat (limited to 'tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java')
-rw-r--r-- | tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java | 210 |
1 files changed, 210 insertions, 0 deletions
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; + } +} |