Loading core/jni/android/graphics/Canvas.cpp +40 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,9 @@ #include "SkShader.h" #include "SkTemplates.h" #include "SkBoundaryPatch.h" #include "SkMeshUtils.h" #define TIME_DRAWx static uint32_t get_thread_msec() { Loading Loading @@ -862,8 +865,6 @@ public: } }; /////////////////////////////////////////////////////////////////////////////// static JNINativeMethod gCanvasMethods[] = { {"finalizer", "(I)V", (void*) SkCanvasGlue::finalizer}, {"initRaster","(I)I", (void*) SkCanvasGlue::initRaster}, Loading Loading @@ -965,6 +966,42 @@ static JNINativeMethod gCanvasMethods[] = { {"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> #define REG(env, name, array) \ Loading @@ -976,6 +1013,7 @@ int register_android_graphics_Canvas(JNIEnv* env) { int result; REG(env, "android/graphics/Canvas", gCanvasMethods); REG(env, "android/graphics/utils/BoundaryPatch", gBoundaryPatchMethods); return result; } Loading core/jni/android/graphics/Graphics.cpp +6 −4 Original line number Diff line number Diff line Loading @@ -56,7 +56,7 @@ bool GraphicsJNI::hasException(JNIEnv *env) { /////////////////////////////////////////////////////////////////////////////// AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array, int minLength) int minLength, JNIAccess access) : fEnv(env), fArray(array), fPtr(NULL), fLen(0) { SkASSERT(env); if (array) { Loading @@ -66,11 +66,12 @@ AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array, } fPtr = env->GetFloatArrayElements(array, NULL); } fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0; } AutoJavaFloatArray::~AutoJavaFloatArray() { if (fPtr) { fEnv->ReleaseFloatArrayElements(fArray, fPtr, 0); fEnv->ReleaseFloatArrayElements(fArray, fPtr, fReleaseMode); } } Loading @@ -94,7 +95,7 @@ AutoJavaIntArray::~AutoJavaIntArray() { } AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array, int minLength) int minLength, JNIAccess access) : fEnv(env), fArray(array), fPtr(NULL), fLen(0) { SkASSERT(env); if (array) { Loading @@ -104,11 +105,12 @@ AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array, } fPtr = env->GetShortArrayElements(array, NULL); } fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0; } AutoJavaShortArray::~AutoJavaShortArray() { if (fPtr) { fEnv->ReleaseShortArrayElements(fArray, fPtr, 0); fEnv->ReleaseShortArrayElements(fArray, fPtr, fReleaseMode); } } Loading core/jni/android/graphics/GraphicsJNI.h +11 −2 Original line number Diff line number Diff line Loading @@ -80,9 +80,15 @@ private: bool fReportSizeToVM; }; enum JNIAccess { kRO_JNIAccess, kRW_JNIAccess }; class AutoJavaFloatArray { public: AutoJavaFloatArray(JNIEnv* env, jfloatArray array, int minLength = 0); AutoJavaFloatArray(JNIEnv* env, jfloatArray array, int minLength = 0, JNIAccess = kRW_JNIAccess); ~AutoJavaFloatArray(); float* ptr() const { return fPtr; } Loading @@ -93,6 +99,7 @@ private: jfloatArray fArray; float* fPtr; int fLen; int fReleaseMode; }; class AutoJavaIntArray { Loading @@ -112,7 +119,8 @@ private: class AutoJavaShortArray { public: AutoJavaShortArray(JNIEnv* env, jshortArray array, int minLength = 0); AutoJavaShortArray(JNIEnv* env, jshortArray array, int minLength = 0, JNIAccess = kRW_JNIAccess); ~AutoJavaShortArray(); jshort* ptr() const { return fPtr; } Loading @@ -123,6 +131,7 @@ private: jshortArray fArray; jshort* fPtr; int fLen; int fReleaseMode; }; class AutoJavaByteArray { Loading graphics/java/android/graphics/utils/BoundaryPatch.java 0 → 100644 +173 −0 Original line number Diff line number Diff line /* * 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); } Loading
core/jni/android/graphics/Canvas.cpp +40 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,9 @@ #include "SkShader.h" #include "SkTemplates.h" #include "SkBoundaryPatch.h" #include "SkMeshUtils.h" #define TIME_DRAWx static uint32_t get_thread_msec() { Loading Loading @@ -862,8 +865,6 @@ public: } }; /////////////////////////////////////////////////////////////////////////////// static JNINativeMethod gCanvasMethods[] = { {"finalizer", "(I)V", (void*) SkCanvasGlue::finalizer}, {"initRaster","(I)I", (void*) SkCanvasGlue::initRaster}, Loading Loading @@ -965,6 +966,42 @@ static JNINativeMethod gCanvasMethods[] = { {"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> #define REG(env, name, array) \ Loading @@ -976,6 +1013,7 @@ int register_android_graphics_Canvas(JNIEnv* env) { int result; REG(env, "android/graphics/Canvas", gCanvasMethods); REG(env, "android/graphics/utils/BoundaryPatch", gBoundaryPatchMethods); return result; } Loading
core/jni/android/graphics/Graphics.cpp +6 −4 Original line number Diff line number Diff line Loading @@ -56,7 +56,7 @@ bool GraphicsJNI::hasException(JNIEnv *env) { /////////////////////////////////////////////////////////////////////////////// AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array, int minLength) int minLength, JNIAccess access) : fEnv(env), fArray(array), fPtr(NULL), fLen(0) { SkASSERT(env); if (array) { Loading @@ -66,11 +66,12 @@ AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array, } fPtr = env->GetFloatArrayElements(array, NULL); } fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0; } AutoJavaFloatArray::~AutoJavaFloatArray() { if (fPtr) { fEnv->ReleaseFloatArrayElements(fArray, fPtr, 0); fEnv->ReleaseFloatArrayElements(fArray, fPtr, fReleaseMode); } } Loading @@ -94,7 +95,7 @@ AutoJavaIntArray::~AutoJavaIntArray() { } AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array, int minLength) int minLength, JNIAccess access) : fEnv(env), fArray(array), fPtr(NULL), fLen(0) { SkASSERT(env); if (array) { Loading @@ -104,11 +105,12 @@ AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array, } fPtr = env->GetShortArrayElements(array, NULL); } fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0; } AutoJavaShortArray::~AutoJavaShortArray() { if (fPtr) { fEnv->ReleaseShortArrayElements(fArray, fPtr, 0); fEnv->ReleaseShortArrayElements(fArray, fPtr, fReleaseMode); } } Loading
core/jni/android/graphics/GraphicsJNI.h +11 −2 Original line number Diff line number Diff line Loading @@ -80,9 +80,15 @@ private: bool fReportSizeToVM; }; enum JNIAccess { kRO_JNIAccess, kRW_JNIAccess }; class AutoJavaFloatArray { public: AutoJavaFloatArray(JNIEnv* env, jfloatArray array, int minLength = 0); AutoJavaFloatArray(JNIEnv* env, jfloatArray array, int minLength = 0, JNIAccess = kRW_JNIAccess); ~AutoJavaFloatArray(); float* ptr() const { return fPtr; } Loading @@ -93,6 +99,7 @@ private: jfloatArray fArray; float* fPtr; int fLen; int fReleaseMode; }; class AutoJavaIntArray { Loading @@ -112,7 +119,8 @@ private: class AutoJavaShortArray { public: AutoJavaShortArray(JNIEnv* env, jshortArray array, int minLength = 0); AutoJavaShortArray(JNIEnv* env, jshortArray array, int minLength = 0, JNIAccess = kRW_JNIAccess); ~AutoJavaShortArray(); jshort* ptr() const { return fPtr; } Loading @@ -123,6 +131,7 @@ private: jshortArray fArray; jshort* fPtr; int fLen; int fReleaseMode; }; class AutoJavaByteArray { Loading
graphics/java/android/graphics/utils/BoundaryPatch.java 0 → 100644 +173 −0 Original line number Diff line number Diff line /* * 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); }