am 10d32a33: Merge change I16dc1411 into eclair-mr2
Merge commit '10d32a338d5400786e784a0d6f51b53acea76b44' into eclair-mr2-plus-aosp * commit '10d32a338d5400786e784a0d6f51b53acea76b44': add boundary patch
This commit is contained in:
@@ -27,6 +27,9 @@
|
|||||||
#include "SkShader.h"
|
#include "SkShader.h"
|
||||||
#include "SkTemplates.h"
|
#include "SkTemplates.h"
|
||||||
|
|
||||||
|
#include "SkBoundaryPatch.h"
|
||||||
|
#include "SkMeshUtils.h"
|
||||||
|
|
||||||
#define TIME_DRAWx
|
#define TIME_DRAWx
|
||||||
|
|
||||||
static uint32_t get_thread_msec() {
|
static uint32_t get_thread_msec() {
|
||||||
@@ -861,8 +864,6 @@ public:
|
|||||||
*matrix = canvas->getTotalMatrix();
|
*matrix = canvas->getTotalMatrix();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static JNINativeMethod gCanvasMethods[] = {
|
static JNINativeMethod gCanvasMethods[] = {
|
||||||
{"finalizer", "(I)V", (void*) SkCanvasGlue::finalizer},
|
{"finalizer", "(I)V", (void*) SkCanvasGlue::finalizer},
|
||||||
@@ -965,6 +966,42 @@ static JNINativeMethod gCanvasMethods[] = {
|
|||||||
{"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches}
|
{"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static void BoundaryPatch_computeCubic(JNIEnv* env, jobject, jfloatArray jpts,
|
||||||
|
int texW, int texH, int rows, int cols,
|
||||||
|
jfloatArray jverts, jshortArray jidx) {
|
||||||
|
AutoJavaFloatArray ptsArray(env, jpts, 24, kRO_JNIAccess);
|
||||||
|
|
||||||
|
int vertCount = rows * cols;
|
||||||
|
AutoJavaFloatArray vertsArray(env, jverts, vertCount * 4, kRW_JNIAccess);
|
||||||
|
SkPoint* verts = (SkPoint*)vertsArray.ptr();
|
||||||
|
SkPoint* texs = verts + vertCount;
|
||||||
|
|
||||||
|
int idxCount = (rows - 1) * (cols - 1) * 6;
|
||||||
|
AutoJavaShortArray idxArray(env, jidx, idxCount, kRW_JNIAccess);
|
||||||
|
uint16_t* idx = (uint16_t*)idxArray.ptr(); // cast from int16_t*
|
||||||
|
|
||||||
|
SkCubicBoundary cubic;
|
||||||
|
memcpy(cubic.fPts, ptsArray.ptr(), 12 * sizeof(SkPoint));
|
||||||
|
|
||||||
|
SkBoundaryPatch patch;
|
||||||
|
patch.setBoundary(&cubic);
|
||||||
|
// generate our verts
|
||||||
|
patch.evalPatch(verts, rows, cols);
|
||||||
|
|
||||||
|
SkMeshIndices mesh;
|
||||||
|
// generate our texs and idx
|
||||||
|
mesh.init(texs, idx, texW, texH, rows, cols);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JNINativeMethod gBoundaryPatchMethods[] = {
|
||||||
|
{"nativeComputeCubicPatch", "([FIIII[F[S)V",
|
||||||
|
(void*)BoundaryPatch_computeCubic },
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include <android_runtime/AndroidRuntime.h>
|
#include <android_runtime/AndroidRuntime.h>
|
||||||
|
|
||||||
#define REG(env, name, array) \
|
#define REG(env, name, array) \
|
||||||
@@ -976,6 +1013,7 @@ int register_android_graphics_Canvas(JNIEnv* env) {
|
|||||||
int result;
|
int result;
|
||||||
|
|
||||||
REG(env, "android/graphics/Canvas", gCanvasMethods);
|
REG(env, "android/graphics/Canvas", gCanvasMethods);
|
||||||
|
REG(env, "android/graphics/utils/BoundaryPatch", gBoundaryPatchMethods);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ bool GraphicsJNI::hasException(JNIEnv *env) {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
|
AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
|
||||||
int minLength)
|
int minLength, JNIAccess access)
|
||||||
: fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
|
: fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
|
||||||
SkASSERT(env);
|
SkASSERT(env);
|
||||||
if (array) {
|
if (array) {
|
||||||
@@ -66,11 +66,12 @@ AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
|
|||||||
}
|
}
|
||||||
fPtr = env->GetFloatArrayElements(array, NULL);
|
fPtr = env->GetFloatArrayElements(array, NULL);
|
||||||
}
|
}
|
||||||
|
fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoJavaFloatArray::~AutoJavaFloatArray() {
|
AutoJavaFloatArray::~AutoJavaFloatArray() {
|
||||||
if (fPtr) {
|
if (fPtr) {
|
||||||
fEnv->ReleaseFloatArrayElements(fArray, fPtr, 0);
|
fEnv->ReleaseFloatArrayElements(fArray, fPtr, fReleaseMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +95,7 @@ AutoJavaIntArray::~AutoJavaIntArray() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array,
|
AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array,
|
||||||
int minLength)
|
int minLength, JNIAccess access)
|
||||||
: fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
|
: fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
|
||||||
SkASSERT(env);
|
SkASSERT(env);
|
||||||
if (array) {
|
if (array) {
|
||||||
@@ -104,11 +105,12 @@ AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array,
|
|||||||
}
|
}
|
||||||
fPtr = env->GetShortArrayElements(array, NULL);
|
fPtr = env->GetShortArrayElements(array, NULL);
|
||||||
}
|
}
|
||||||
|
fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoJavaShortArray::~AutoJavaShortArray() {
|
AutoJavaShortArray::~AutoJavaShortArray() {
|
||||||
if (fPtr) {
|
if (fPtr) {
|
||||||
fEnv->ReleaseShortArrayElements(fArray, fPtr, 0);
|
fEnv->ReleaseShortArrayElements(fArray, fPtr, fReleaseMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,9 +80,15 @@ private:
|
|||||||
bool fReportSizeToVM;
|
bool fReportSizeToVM;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum JNIAccess {
|
||||||
|
kRO_JNIAccess,
|
||||||
|
kRW_JNIAccess
|
||||||
|
};
|
||||||
|
|
||||||
class AutoJavaFloatArray {
|
class AutoJavaFloatArray {
|
||||||
public:
|
public:
|
||||||
AutoJavaFloatArray(JNIEnv* env, jfloatArray array, int minLength = 0);
|
AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
|
||||||
|
int minLength = 0, JNIAccess = kRW_JNIAccess);
|
||||||
~AutoJavaFloatArray();
|
~AutoJavaFloatArray();
|
||||||
|
|
||||||
float* ptr() const { return fPtr; }
|
float* ptr() const { return fPtr; }
|
||||||
@@ -93,6 +99,7 @@ private:
|
|||||||
jfloatArray fArray;
|
jfloatArray fArray;
|
||||||
float* fPtr;
|
float* fPtr;
|
||||||
int fLen;
|
int fLen;
|
||||||
|
int fReleaseMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AutoJavaIntArray {
|
class AutoJavaIntArray {
|
||||||
@@ -112,7 +119,8 @@ private:
|
|||||||
|
|
||||||
class AutoJavaShortArray {
|
class AutoJavaShortArray {
|
||||||
public:
|
public:
|
||||||
AutoJavaShortArray(JNIEnv* env, jshortArray array, int minLength = 0);
|
AutoJavaShortArray(JNIEnv* env, jshortArray array,
|
||||||
|
int minLength = 0, JNIAccess = kRW_JNIAccess);
|
||||||
~AutoJavaShortArray();
|
~AutoJavaShortArray();
|
||||||
|
|
||||||
jshort* ptr() const { return fPtr; }
|
jshort* ptr() const { return fPtr; }
|
||||||
@@ -123,6 +131,7 @@ private:
|
|||||||
jshortArray fArray;
|
jshortArray fArray;
|
||||||
jshort* fPtr;
|
jshort* fPtr;
|
||||||
int fLen;
|
int fLen;
|
||||||
|
int fReleaseMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AutoJavaByteArray {
|
class AutoJavaByteArray {
|
||||||
|
|||||||
173
graphics/java/android/graphics/utils/BoundaryPatch.java
Normal file
173
graphics/java/android/graphics/utils/BoundaryPatch.java
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 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.utils;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapShader;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Shader;
|
||||||
|
import android.graphics.Xfermode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class BoundaryPatch {
|
||||||
|
private Paint mPaint;
|
||||||
|
private Bitmap mTexture;
|
||||||
|
private int mRows;
|
||||||
|
private int mCols;
|
||||||
|
private float[] mCubicPoints;
|
||||||
|
private boolean mDirty;
|
||||||
|
// these are the computed output of the native code
|
||||||
|
private float[] mVerts;
|
||||||
|
private short[] mIndices;
|
||||||
|
|
||||||
|
public BoundaryPatch() {
|
||||||
|
mRows = mCols = 2; // default minimum
|
||||||
|
mCubicPoints = new float[24];
|
||||||
|
mPaint = new Paint();
|
||||||
|
mPaint.setDither(true);
|
||||||
|
mPaint.setFilterBitmap(true);
|
||||||
|
mDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the boundary to be 4 cubics. This takes a single array of floats,
|
||||||
|
* and picks up the 12 pairs starting at offset, and treats them as
|
||||||
|
* the x,y coordinates of the cubic control points. The points wrap around
|
||||||
|
* a patch, as follows. For documentation purposes, pts[i] will mean the
|
||||||
|
* x,y pair of floats, as if pts[] were an array of "points".
|
||||||
|
*
|
||||||
|
* Top: pts[0..3]
|
||||||
|
* Right: pts[3..6]
|
||||||
|
* Bottom: pts[6..9]
|
||||||
|
* Right: pts[9..11], pts[0]
|
||||||
|
*
|
||||||
|
* The coordinates are copied from the input array, so subsequent changes
|
||||||
|
* to pts[] will not be reflected in the boundary.
|
||||||
|
*
|
||||||
|
* @param pts The src array of x,y pairs for the boundary cubics
|
||||||
|
* @param offset The index into pts of the first pair
|
||||||
|
* @param rows The number of points across to approximate the boundary.
|
||||||
|
* Must be >= 2, though very large values may slow down drawing
|
||||||
|
* @param cols The number of points down to approximate the boundary.
|
||||||
|
* Must be >= 2, though very large values may slow down drawing
|
||||||
|
*/
|
||||||
|
public void setCubicBoundary(float[] pts, int offset, int rows, int cols) {
|
||||||
|
if (rows < 2 || cols < 2) {
|
||||||
|
throw new RuntimeException("rows and cols must be >= 2");
|
||||||
|
}
|
||||||
|
System.arraycopy(pts, offset, mCubicPoints, 0, 24);
|
||||||
|
if (mRows != rows || mCols != cols) {
|
||||||
|
mRows = rows;
|
||||||
|
mCols = cols;
|
||||||
|
}
|
||||||
|
mDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference a bitmap texture to be mapped onto the patch.
|
||||||
|
*/
|
||||||
|
public void setTexture(Bitmap texture) {
|
||||||
|
if (mTexture != texture) {
|
||||||
|
if (mTexture == null ||
|
||||||
|
mTexture.getWidth() != texture.getWidth() ||
|
||||||
|
mTexture.getHeight() != texture.getHeight()) {
|
||||||
|
// need to recompute texture coordinates
|
||||||
|
mDirty = true;
|
||||||
|
}
|
||||||
|
mTexture = texture;
|
||||||
|
mPaint.setShader(new BitmapShader(texture,
|
||||||
|
Shader.TileMode.CLAMP,
|
||||||
|
Shader.TileMode.CLAMP));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the paint flags for the patch
|
||||||
|
*/
|
||||||
|
public int getPaintFlags() {
|
||||||
|
return mPaint.getFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the paint flags for the patch
|
||||||
|
*/
|
||||||
|
public void setPaintFlags(int flags) {
|
||||||
|
mPaint.setFlags(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the xfermode for the patch
|
||||||
|
*/
|
||||||
|
public void setXfermode(Xfermode mode) {
|
||||||
|
mPaint.setXfermode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the alpha for the patch
|
||||||
|
*/
|
||||||
|
public void setAlpha(int alpha) {
|
||||||
|
mPaint.setAlpha(alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the patch onto the canvas.
|
||||||
|
*
|
||||||
|
* setCubicBoundary() and setTexture() must be called before drawing.
|
||||||
|
*/
|
||||||
|
public void draw(Canvas canvas) {
|
||||||
|
if (mDirty) {
|
||||||
|
buildCache();
|
||||||
|
mDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cut the count in half, since mVerts.length is really the length of
|
||||||
|
// the verts[] and tex[] arrays combined
|
||||||
|
// (tex[] are stored after verts[])
|
||||||
|
int vertCount = mVerts.length >> 1;
|
||||||
|
canvas.drawVertices(Canvas.VertexMode.TRIANGLES, vertCount,
|
||||||
|
mVerts, 0, mVerts, vertCount, null, 0,
|
||||||
|
mIndices, 0, mIndices.length,
|
||||||
|
mPaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildCache() {
|
||||||
|
// we need mRows * mCols points, for verts and another set for textures
|
||||||
|
// so *2 for going from points -> floats, and *2 for verts and textures
|
||||||
|
int vertCount = mRows * mCols * 4;
|
||||||
|
if (mVerts == null || mVerts.length != vertCount) {
|
||||||
|
mVerts = new float[vertCount];
|
||||||
|
}
|
||||||
|
|
||||||
|
int indexCount = (mRows - 1) * (mCols - 1) * 6;
|
||||||
|
if (mIndices == null || mIndices.length != indexCount) {
|
||||||
|
mIndices = new short[indexCount];
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeComputeCubicPatch(mCubicPoints,
|
||||||
|
mTexture.getWidth(), mTexture.getHeight(),
|
||||||
|
mRows, mCols, mVerts, mIndices);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native
|
||||||
|
void nativeComputeCubicPatch(float[] cubicPoints,
|
||||||
|
int texW, int texH, int rows, int cols,
|
||||||
|
float[] verts, short[] indices);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user