Add path ops API
Path ops can be used to combine two paths instances in a single path object. The following operations can be used: - Difference - Reverse difference - Union - XOR - Intersection To use the API: Path p1 = createCircle(); Path p2 = createRect(); Path result = new Path(); result.op(p1, p2, Path.Op.DIFFERENCE); This code will subtract the rectangle from the circle and generate the resulting path in "result." Change-Id: Ic25244665b6691a7df0b0002a09da73d937b553b
This commit is contained in:
@@ -9432,6 +9432,8 @@ package android.graphics {
|
||||
method public void moveTo(float, float);
|
||||
method public void offset(float, float, android.graphics.Path);
|
||||
method public void offset(float, float);
|
||||
method public boolean op(android.graphics.Path, android.graphics.Path.Op);
|
||||
method public boolean op(android.graphics.Path, android.graphics.Path, android.graphics.Path.Op);
|
||||
method public void quadTo(float, float, float, float);
|
||||
method public void rCubicTo(float, float, float, float, float, float);
|
||||
method public void rLineTo(float, float);
|
||||
@@ -9463,6 +9465,16 @@ package android.graphics {
|
||||
enum_constant public static final android.graphics.Path.FillType WINDING;
|
||||
}
|
||||
|
||||
public static final class Path.Op extends java.lang.Enum {
|
||||
method public static android.graphics.Path.Op valueOf(java.lang.String);
|
||||
method public static final android.graphics.Path.Op[] values();
|
||||
enum_constant public static final android.graphics.Path.Op DIFFERENCE;
|
||||
enum_constant public static final android.graphics.Path.Op INTERSECT;
|
||||
enum_constant public static final android.graphics.Path.Op REVERSE_DIFFERENCE;
|
||||
enum_constant public static final android.graphics.Path.Op UNION;
|
||||
enum_constant public static final android.graphics.Path.Op XOR;
|
||||
}
|
||||
|
||||
public class PathDashPathEffect extends android.graphics.PathEffect {
|
||||
ctor public PathDashPathEffect(android.graphics.Path, float, float, android.graphics.PathDashPathEffect.Style);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
|
||||
#include "SkPath.h"
|
||||
#include "pathops/SkPathOps.h"
|
||||
|
||||
#include <Caches.h>
|
||||
|
||||
@@ -67,8 +68,7 @@ public:
|
||||
return obj->getFillType();
|
||||
}
|
||||
|
||||
static void setFillType(JNIEnv* env, jobject clazz, SkPath* path,
|
||||
SkPath::FillType ft) {
|
||||
static void setFillType(JNIEnv* env, jobject clazz, SkPath* path, SkPath::FillType ft) {
|
||||
path->setFillType(ft);
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ public:
|
||||
}
|
||||
|
||||
static void addRoundRectXY(JNIEnv* env, jobject clazz, SkPath* obj, jobject rect,
|
||||
jfloat rx, jfloat ry, SkPath::Direction dir) {
|
||||
jfloat rx, jfloat ry, SkPath::Direction dir) {
|
||||
SkRect rect_;
|
||||
GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
|
||||
SkScalar rx_ = SkFloatToScalar(rx);
|
||||
@@ -209,7 +209,7 @@ public:
|
||||
}
|
||||
|
||||
static void addRoundRect8(JNIEnv* env, jobject, SkPath* obj, jobject rect,
|
||||
jfloatArray array, SkPath::Direction dir) {
|
||||
jfloatArray array, SkPath::Direction dir) {
|
||||
SkRect rect_;
|
||||
GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
|
||||
AutoJavaFloatArray afa(env, array, 8);
|
||||
@@ -261,7 +261,10 @@ public:
|
||||
static void transform__Matrix(JNIEnv* env, jobject clazz, SkPath* obj, SkMatrix* matrix) {
|
||||
obj->transform(*matrix);
|
||||
}
|
||||
|
||||
|
||||
static jboolean op(JNIEnv* env, jobject clazz, SkPath* p1, SkPath* p2, SkPathOp op, SkPath* r) {
|
||||
return Op(*p1, *p2, op, r);
|
||||
}
|
||||
};
|
||||
|
||||
static JNINativeMethod methods[] = {
|
||||
@@ -301,7 +304,8 @@ static JNINativeMethod methods[] = {
|
||||
{"native_offset","(IFF)V", (void*) SkPathGlue::offset__FF},
|
||||
{"native_setLastPoint","(IFF)V", (void*) SkPathGlue::setLastPoint},
|
||||
{"native_transform","(III)V", (void*) SkPathGlue::transform__MatrixPath},
|
||||
{"native_transform","(II)V", (void*) SkPathGlue::transform__Matrix}
|
||||
{"native_transform","(II)V", (void*) SkPathGlue::transform__Matrix},
|
||||
{"native_op","(IIII)Z", (void*) SkPathGlue::op}
|
||||
};
|
||||
|
||||
int register_android_graphics_Path(JNIEnv* env) {
|
||||
|
||||
@@ -103,21 +103,106 @@ public class Path {
|
||||
}
|
||||
}
|
||||
|
||||
/** Enum for the ways a path may be filled
|
||||
*/
|
||||
/**
|
||||
* The logical operations that can be performed when combining two paths.
|
||||
*
|
||||
* @see #op(Path, android.graphics.Path.Op)
|
||||
* @see #op(Path, Path, android.graphics.Path.Op)
|
||||
*/
|
||||
public enum Op {
|
||||
/**
|
||||
* Subtract the second path from the first path.
|
||||
*/
|
||||
DIFFERENCE,
|
||||
/**
|
||||
* Intersect the two paths.
|
||||
*/
|
||||
INTERSECT,
|
||||
/**
|
||||
* Union (inclusive-or) the two paths.
|
||||
*/
|
||||
UNION,
|
||||
/**
|
||||
* Exclusive-or the two paths.
|
||||
*/
|
||||
XOR,
|
||||
/**
|
||||
* Subtract the first path from the second path.
|
||||
*/
|
||||
REVERSE_DIFFERENCE
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this path to the result of applying the Op to this path and the specified path.
|
||||
* The resulting path will be constructed from non-overlapping contours.
|
||||
* The curve order is reduced where possible so that cubics may be turned
|
||||
* into quadratics, and quadratics maybe turned into lines.
|
||||
*
|
||||
* @param path The second operand (for difference, the subtrahend)
|
||||
*
|
||||
* @return True if operation succeeded, false otherwise and this path remains unmodified.
|
||||
*
|
||||
* @see Op
|
||||
* @see #op(Path, Path, android.graphics.Path.Op)
|
||||
*/
|
||||
public boolean op(Path path, Op op) {
|
||||
return op(this, path, op);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this path to the result of applying the Op to the two specified paths.
|
||||
* The resulting path will be constructed from non-overlapping contours.
|
||||
* The curve order is reduced where possible so that cubics may be turned
|
||||
* into quadratics, and quadratics maybe turned into lines.
|
||||
*
|
||||
* @param path1 The first operand (for difference, the minuend)
|
||||
* @param path2 The second operand (for difference, the subtrahend)
|
||||
*
|
||||
* @return True if operation succeeded, false otherwise and this path remains unmodified.
|
||||
*
|
||||
* @see Op
|
||||
* @see #op(Path, android.graphics.Path.Op)
|
||||
*/
|
||||
public boolean op(Path path1, Path path2, Op op) {
|
||||
if (native_op(path1.mNativePath, path2.mNativePath, op.ordinal(), this.mNativePath)) {
|
||||
isSimplePath = false;
|
||||
rects = null;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum for the ways a path may be filled.
|
||||
*/
|
||||
public enum FillType {
|
||||
// these must match the values in SkPath.h
|
||||
/**
|
||||
* Specifies that "inside" is computed by a non-zero sum of signed
|
||||
* edge crossings.
|
||||
*/
|
||||
WINDING (0),
|
||||
/**
|
||||
* Specifies that "inside" is computed by an odd number of edge
|
||||
* crossings.
|
||||
*/
|
||||
EVEN_ODD (1),
|
||||
/**
|
||||
* Same as {@link #WINDING}, but draws outside of the path, rather than inside.
|
||||
*/
|
||||
INVERSE_WINDING (2),
|
||||
/**
|
||||
* Same as {@link #EVEN_ODD}, but draws outside of the path, rather than inside.
|
||||
*/
|
||||
INVERSE_EVEN_ODD(3);
|
||||
|
||||
FillType(int ni) {
|
||||
nativeInt = ni;
|
||||
}
|
||||
|
||||
final int nativeInt;
|
||||
}
|
||||
|
||||
|
||||
// these must be in the same order as their native values
|
||||
static final FillType[] sFillTypeArray = {
|
||||
FillType.WINDING,
|
||||
@@ -644,24 +729,20 @@ public class Path {
|
||||
private static native void native_addRect(int nPath, float left, float top,
|
||||
float right, float bottom, int dir);
|
||||
private static native void native_addOval(int nPath, RectF oval, int dir);
|
||||
private static native void native_addCircle(int nPath, float x, float y,
|
||||
float radius, int dir);
|
||||
private static native void native_addCircle(int nPath, float x, float y, float radius, int dir);
|
||||
private static native void native_addArc(int nPath, RectF oval,
|
||||
float startAngle, float sweepAngle);
|
||||
private static native void native_addRoundRect(int nPath, RectF rect,
|
||||
float rx, float ry, int dir);
|
||||
private static native void native_addRoundRect(int nPath, RectF r,
|
||||
float[] radii, int dir);
|
||||
private static native void native_addPath(int nPath, int src, float dx,
|
||||
float dy);
|
||||
private static native void native_addRoundRect(int nPath, RectF r, float[] radii, int dir);
|
||||
private static native void native_addPath(int nPath, int src, float dx, float dy);
|
||||
private static native void native_addPath(int nPath, int src);
|
||||
private static native void native_addPath(int nPath, int src, int matrix);
|
||||
private static native void native_offset(int nPath, float dx, float dy,
|
||||
int dst_path);
|
||||
private static native void native_offset(int nPath, float dx, float dy, int dst_path);
|
||||
private static native void native_offset(int nPath, float dx, float dy);
|
||||
private static native void native_setLastPoint(int nPath, float dx, float dy);
|
||||
private static native void native_transform(int nPath, int matrix,
|
||||
int dst_path);
|
||||
private static native void native_transform(int nPath, int matrix, int dst_path);
|
||||
private static native void native_transform(int nPath, int matrix);
|
||||
private static native boolean native_op(int path1, int path2, int op, int result);
|
||||
private static native void finalizer(int nPath);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,16 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="PathOpsActivity"
|
||||
android:label="Path/Ops"
|
||||
android:theme="@android:style/Theme.Holo.Light">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="com.android.test.hwui.TEST" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="AssetsAtlasActivity"
|
||||
android:label="Atlas/Framework"
|
||||
@@ -735,7 +745,7 @@
|
||||
android:name="PathsCacheActivity"
|
||||
android:label="Path/Cache">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<action android:name="android.intent.action.MAIN" />`
|
||||
<category android:name="com.android.test.hwui.TEST" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.test.hwui;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public class PathOpsActivity extends Activity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
final PathsView view = new PathsView(this);
|
||||
setContentView(view);
|
||||
}
|
||||
|
||||
public static class PathsView extends View {
|
||||
private final Paint mPaint;
|
||||
private Path[] mPaths;
|
||||
private float mSize;
|
||||
|
||||
|
||||
public PathsView(Context c) {
|
||||
super(c);
|
||||
|
||||
mPaint = new Paint();
|
||||
mPaint.setAntiAlias(true);
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
mPaint.setColor(Color.RED);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
|
||||
Path.Op[] ops = Path.Op.values();
|
||||
mPaths = new Path[ops.length];
|
||||
|
||||
mSize = w / (ops.length * 2.0f);
|
||||
|
||||
Path p1 = new Path();
|
||||
p1.addRect(0.0f, 0.0f, mSize, mSize, Path.Direction.CW);
|
||||
|
||||
Path p2 = new Path();
|
||||
p2.addCircle(mSize, mSize, mSize / 2.0f, Path.Direction.CW);
|
||||
|
||||
for (int i = 0; i < ops.length; i++) {
|
||||
mPaths[i] = new Path();
|
||||
if (!mPaths[i].op(p1, p2, ops[i])) {
|
||||
Log.d("PathOps", ops[i].name() + " failed!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
canvas.translate(mSize * 0.2f, getHeight() / 2.0f);
|
||||
for (Path path : mPaths) {
|
||||
canvas.drawPath(path, mPaint);
|
||||
canvas.translate(mSize * 1.8f, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user