Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ed62560f authored by George Mount's avatar George Mount Committed by Android (Google) Code Review
Browse files

Merge "Add Path trimming."

parents 94f71949 7fe03a26
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -9712,6 +9712,8 @@ package android.graphics {
    method public void toggleInverseFillType();
    method public void transform(android.graphics.Matrix, android.graphics.Path);
    method public void transform(android.graphics.Matrix);
    method public void trim(float, float, float);
    method public void trim(float, float, float, android.graphics.Path);
  }
  public static final class Path.Direction extends java.lang.Enum {
+50 −2
Original line number Diff line number Diff line
@@ -268,7 +268,6 @@ public:
         return Op(*p1, *p2, op, r);
     }


    typedef SkPoint (*bezierCalculation)(float t, const SkPoint* points);

    static void addMove(std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths,
@@ -396,6 +395,8 @@ public:
                addMove(segmentPoints, lengths, points[0]);
                break;
            case SkPath::kClose_Verb:
                addLine(segmentPoints, lengths, points[0]);
                break;
            case SkPath::kLine_Verb:
                addLine(segmentPoints, lengths, points[1]);
                break;
@@ -445,7 +446,7 @@ public:
        float totalLength = lengths.back();

        int approximationIndex = 0;
        for (int i = 0; i < numPoints; i++) {
        for (size_t i = 0; i < numPoints; i++) {
            const SkPoint& point = segmentPoints[i];
            approximation[approximationIndex++] = lengths[i] / totalLength;
            approximation[approximationIndex++] = point.x();
@@ -457,6 +458,51 @@ public:
        delete[] approximation;
        return result;
    }

    static SkPathMeasure* trim(JNIEnv* env, jobject clazz, SkPath* inPath, SkPath* outPath,
            SkPathMeasure* pathMeasure, jfloat trimStart, jfloat trimEnd, jfloat trimOffset) {
        if (trimStart == 0 && trimEnd == 1) {
            if (outPath != NULL) {
                *outPath = *inPath;
            }
            return pathMeasure;
        }

        bool modifyPath = (outPath == NULL);
        if (modifyPath) {
            outPath = new SkPath();
        } else {
            outPath->reset();
        }
        if (pathMeasure == NULL) {
            pathMeasure = new SkPathMeasure(*inPath, false);
        }
        float length = pathMeasure->getLength();
        float start = (trimStart + trimOffset) * length;
        float end = (trimEnd + trimOffset) * length;

        if (end > length && start <= length) {
            pathMeasure->getSegment(start, length, outPath, true);
            pathMeasure->getSegment(0, end - length, outPath, true);
        } else {
            if (start > length) {
                start -= length;
                end -= length;
            }
            pathMeasure->getSegment(start, end, outPath, true);
        }
        if (modifyPath) {
            delete pathMeasure;
            pathMeasure = NULL;
            *inPath = *outPath;
            delete outPath;
        }
        return pathMeasure;
    }

    static void destroyMeasure(JNIEnv* env, jobject clazz, SkPathMeasure* measure) {
        delete measure;
    }
};

static JNINativeMethod methods[] = {
@@ -499,6 +545,8 @@ static JNINativeMethod methods[] = {
    {"native_transform","(II)V", (void*) SkPathGlue::transform__Matrix},
    {"native_op","(IIII)Z", (void*) SkPathGlue::op},
    {"native_approximate", "(IF)[F", (void*) SkPathGlue::approximate},
    {"native_destroyMeasure","(I)V", (void*) SkPathGlue::destroyMeasure},
    {"native_trim","(IIIFFF)I", (void*) SkPathGlue::trim},
};

int register_android_graphics_Path(JNIEnv* env) {
+117 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ public class Path {
     * @hide
     */
    public final int mNativePath;
    private int mNativePathMeasure;

    /**
     * @hide
@@ -76,6 +77,14 @@ public class Path {
        final FillType fillType = getFillType();
        native_reset(mNativePath);
        setFillType(fillType);
        clearMeasure();
    }

    private void clearMeasure() {
        if (mNativePathMeasure != 0) {
            native_destroyMeasure(mNativePathMeasure);
            mNativePathMeasure = 0;
        }
    }

    /**
@@ -87,6 +96,7 @@ public class Path {
        mLastDirection = null;
        if (rects != null) rects.setEmpty();
        native_rewind(mNativePath);
        clearMeasure();
    }

    /** Replace the contents of this with the contents of src.
@@ -95,6 +105,7 @@ public class Path {
        if (this != src) {
            isSimplePath = src.isSimplePath;
            native_set(mNativePath, src.mNativePath);
            clearMeasure();
        }
    }

@@ -223,6 +234,7 @@ public class Path {
     */
    public void setFillType(FillType ft) {
        native_setFillType(mNativePath, ft.nativeInt);
        clearMeasure();
    }
    
    /**
@@ -242,6 +254,7 @@ public class Path {
        int ft = native_getFillType(mNativePath);
        ft ^= 2;
        native_setFillType(mNativePath, ft);
        clearMeasure();
    }
    
    /**
@@ -298,6 +311,7 @@ public class Path {
     */
    public void moveTo(float x, float y) {
        native_moveTo(mNativePath, x, y);
        clearMeasure();
    }

    /**
@@ -312,6 +326,7 @@ public class Path {
     */
    public void rMoveTo(float dx, float dy) {
        native_rMoveTo(mNativePath, dx, dy);
        clearMeasure();
    }

    /**
@@ -325,6 +340,7 @@ public class Path {
    public void lineTo(float x, float y) {
        isSimplePath = false;
        native_lineTo(mNativePath, x, y);
        clearMeasure();
    }

    /**
@@ -340,6 +356,7 @@ public class Path {
    public void rLineTo(float dx, float dy) {
        isSimplePath = false;
        native_rLineTo(mNativePath, dx, dy);
        clearMeasure();
    }

    /**
@@ -355,6 +372,7 @@ public class Path {
    public void quadTo(float x1, float y1, float x2, float y2) {
        isSimplePath = false;
        native_quadTo(mNativePath, x1, y1, x2, y2);
        clearMeasure();
    }

    /**
@@ -374,6 +392,7 @@ public class Path {
    public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
        isSimplePath = false;
        native_rQuadTo(mNativePath, dx1, dy1, dx2, dy2);
        clearMeasure();
    }

    /**
@@ -392,6 +411,7 @@ public class Path {
                        float x3, float y3) {
        isSimplePath = false;
        native_cubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
        clearMeasure();
    }

    /**
@@ -403,6 +423,7 @@ public class Path {
                         float x3, float y3) {
        isSimplePath = false;
        native_rCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
        clearMeasure();
    }

    /**
@@ -422,6 +443,7 @@ public class Path {
                      boolean forceMoveTo) {
        isSimplePath = false;
        native_arcTo(mNativePath, oval, startAngle, sweepAngle, forceMoveTo);
        clearMeasure();
    }
    
    /**
@@ -438,6 +460,7 @@ public class Path {
    public void arcTo(RectF oval, float startAngle, float sweepAngle) {
        isSimplePath = false;
        native_arcTo(mNativePath, oval, startAngle, sweepAngle, false);
        clearMeasure();
    }
    
    /**
@@ -447,6 +470,7 @@ public class Path {
    public void close() {
        isSimplePath = false;
        native_close(mNativePath);
        clearMeasure();
    }

    /**
@@ -489,6 +513,7 @@ public class Path {
        }
        detectSimplePath(rect.left, rect.top, rect.right, rect.bottom, dir);
        native_addRect(mNativePath, rect, dir.nativeInt);
        clearMeasure();
    }

    /**
@@ -503,6 +528,7 @@ public class Path {
    public void addRect(float left, float top, float right, float bottom, Direction dir) {
        detectSimplePath(left, top, right, bottom, dir);
        native_addRect(mNativePath, left, top, right, bottom, dir.nativeInt);
        clearMeasure();
    }

    /**
@@ -517,6 +543,7 @@ public class Path {
        }
        isSimplePath = false;
        native_addOval(mNativePath, oval, dir.nativeInt);
        clearMeasure();
    }

    /**
@@ -530,6 +557,7 @@ public class Path {
    public void addCircle(float x, float y, float radius, Direction dir) {
        isSimplePath = false;
        native_addCircle(mNativePath, x, y, radius, dir.nativeInt);
        clearMeasure();
    }

    /**
@@ -545,6 +573,7 @@ public class Path {
        }
        isSimplePath = false;
        native_addArc(mNativePath, oval, startAngle, sweepAngle);
        clearMeasure();
    }

    /**
@@ -561,6 +590,7 @@ public class Path {
        }
        isSimplePath = false;
        native_addRoundRect(mNativePath, rect, rx, ry, dir.nativeInt);
        clearMeasure();
    }
    
    /**
@@ -581,6 +611,7 @@ public class Path {
        }
        isSimplePath = false;
        native_addRoundRect(mNativePath, rect, radii, dir.nativeInt);
        clearMeasure();
    }
    
    /**
@@ -592,6 +623,7 @@ public class Path {
    public void addPath(Path src, float dx, float dy) {
        isSimplePath = false;
        native_addPath(mNativePath, src.mNativePath, dx, dy);
        clearMeasure();
    }

    /**
@@ -602,6 +634,7 @@ public class Path {
    public void addPath(Path src) {
        isSimplePath = false;
        native_addPath(mNativePath, src.mNativePath);
        clearMeasure();
    }

    /**
@@ -612,6 +645,7 @@ public class Path {
    public void addPath(Path src, Matrix matrix) {
        if (!src.isSimplePath) isSimplePath = false;
        native_addPath(mNativePath, src.mNativePath, matrix.native_instance);
        clearMeasure();
    }

    /**
@@ -629,6 +663,11 @@ public class Path {
            dst.isSimplePath = false;
        }
        native_offset(mNativePath, dx, dy, dstNative);
        if (dst != null) {
            dst.clearMeasure();
        } else {
            clearMeasure();
        }
    }

    /**
@@ -640,6 +679,7 @@ public class Path {
    public void offset(float dx, float dy) {
        isSimplePath = false;
        native_offset(mNativePath, dx, dy);
        clearMeasure();
    }

    /**
@@ -651,6 +691,7 @@ public class Path {
    public void setLastPoint(float dx, float dy) {
        isSimplePath = false;
        native_setLastPoint(mNativePath, dx, dy);
        clearMeasure();
    }

    /**
@@ -668,6 +709,11 @@ public class Path {
            dstNative = dst.mNativePath;
        }
        native_transform(mNativePath, matrix.native_instance, dstNative);
        if (dst != null) {
            dst.clearMeasure();
        } else {
            clearMeasure();
        }
    }

    /**
@@ -678,10 +724,14 @@ public class Path {
    public void transform(Matrix matrix) {
        isSimplePath = false;
        native_transform(mNativePath, matrix.native_instance);
        clearMeasure();
    }

    protected void finalize() throws Throwable {
        try {
            if (mNativePathMeasure != 0) {
                native_destroyMeasure(mNativePathMeasure);
            }
            finalizer(mNativePath);
        } finally {
            super.finalize();
@@ -714,6 +764,70 @@ public class Path {
        return native_approximate(mNativePath, acceptableError);
    }

    /**
     * Modifies the <code>Path</code> by extracting a portion of it.
     * The portion of the <code>Path</code> used is between <code>trimStart</code> and
     * <code>trimEnd</code> with the value offset by <code>trimOffset</code>. When
     * <code>trimOffset</code> added to <code>trimEnd</code> is greater than 1, the
     * trimmed portion "wraps" to the start of the <code>Path</code>.
     * <p>For example, if <code>Path</code> is a circle and <code>trimStart</code> is 0
     * and <code>trimEnd</code> is 0.5, the resulting <code>Path</code> is the arc of
     * a semicircle. If <code>trimOffset</code> is set to 0.75, the arc will start at
     * 3/4 of the circle and continue to the end of the circle, then start again at the
     * beginning of the circle and end at 1/4 of the way around. It will appear as if
     * the semicircle arc wrapped around the <code>Path</code> start and end.</p>
     * @param trimStart A number between 0 and <code>trimEnd</code> indicating the fraction of the
     *                  <code>Path</code> to start. A value of 0 trims nothing from the start.
     * @param trimEnd A number between <code>trimStart</code> and 1 indicating the fraction of the
     *                <code>Path</code> to end. A value of 1 trims nothing from the end.
     * @param trimOffset A fraction between 0 and 1 indicating the offset of the trimmed
     *                   portion of the <code>Path</code>.
     * @see #trim(float, float, float, Path)
     */
    public void trim(float trimStart, float trimEnd, float trimOffset) {
        trim(trimStart, trimEnd, trimOffset, null);
    }

    /**
     * Extracts a portion of the <code>Path</code> and writes it to <code>dst</code>.
     * The portion of the <code>Path</code> used is between <code>trimStart</code> and
     * <code>trimEnd</code> with the value offset by <code>trimOffset</code>. When
     * <code>trimOffset</code> added to <code>trimEnd</code> is greater than 1, the
     * trimmed portion "wraps" to the start of the <code>Path</code>.
     * <p>For example, if <code>Path</code> is a circle and <code>trimStart</code> is 0
     * and <code>trimEnd</code> is 0.5, the resulting <code>Path</code> is the arc of
     * a semicircle. If <code>trimOffset</code> is set to 0.75, the arc will start at
     * 3/4 of the circle and continue to the end of the circle, then start again at the
     * beginning of the circle and end at 1/4 of the way around. It will appear as if
     * the semicircle arc wrapped around the <code>Path</code> start and end.</p>
     * @param trimStart A number between 0 and <code>trimEnd</code> indicating the fraction of the
     *                  <code>Path</code> to start. A value of 0 trims nothing from the start.
     * @param trimEnd A number between <code>trimStart</code> and 1 indicating the fraction of the
     *                <code>Path</code> to end. A value of 1 trims nothing from the end.
     * @param trimOffset A fraction between 0 and 1 indicating the offset of the trimmed
     *                   portion of the <code>Path</code>.
     * @param dst The trimmed <code>Path</code> is written here. If <code>dst</code> is null,
     *            then the original <code>Path</code> is modified.
     * @see #trim(float, float, float)
     */
    public void trim(float trimStart, float trimEnd, float trimOffset, Path dst) {
        if (trimStart > 1 || trimEnd > 1 || trimOffset > 1
                || trimStart < 0 || trimEnd < 0 || trimOffset < 0) {
            throw new IllegalArgumentException("trim must be between 0 and 1");
        }
        if (trimStart > trimEnd) {
            throw new IllegalArgumentException("trim end cannot be less than start");
        }
        int dstNative = 0;
        if (dst != null) {
            dstNative = dst.mNativePath;
            dst.isSimplePath = false;
            dst.clearMeasure();
        }
        mNativePathMeasure = native_trim(mNativePath, dstNative, mNativePathMeasure,
                trimStart, trimEnd, trimOffset);
    }

    private static native int init1();
    private static native int init2(int nPath);
    private static native void native_reset(int nPath);
@@ -761,4 +875,7 @@ public class Path {
    private static native boolean native_op(int path1, int path2, int op, int result);
    private static native void finalizer(int nPath);
    private static native float[] native_approximate(int nPath, float error);
    private static native int native_trim(int nPath, int nTargetPath, int nPathMeasure,
            float trimStart, float trimEnd, float trimOffset);
    private static native void native_destroyMeasure(int nPathMeasure);
}