Loading core/java/android/webkit/DebugFlags.java +2 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,8 @@ class DebugFlags { public static final boolean CALLBACK_PROXY = false; public static final boolean COOKIE_MANAGER = false; public static final boolean COOKIE_SYNC_MANAGER = false; public static final boolean DRAG_TRACKER = false; public static final String DRAG_TRACKER_LOGTAG = "skia"; public static final boolean FRAME_LOADER = false; public static final boolean J_WEB_CORE_JAVA_BRIDGE = false;// HIGHLY VERBOSE public static final boolean LOAD_LISTENER = false; Loading core/java/android/webkit/WebView.java +190 −10 Original line number Diff line number Diff line Loading @@ -200,6 +200,8 @@ public class WebView extends AbsoluteLayout implements ViewTreeObserver.OnGlobalFocusChangeListener, ViewGroup.OnHierarchyChangeListener { // enable debug output for drag trackers private static final boolean DEBUG_DRAG_TRACKER = false; // if AUTO_REDRAW_HACK is true, then the CALL key will toggle redrawing // the screen all-the-time. Good for profiling our drawing code static private final boolean AUTO_REDRAW_HACK = false; Loading Loading @@ -2796,16 +2798,7 @@ public class WebView extends AbsoluteLayout return super.drawChild(canvas, child, drawingTime); } @Override protected void onDraw(Canvas canvas) { // if mNativeClass is 0, the WebView has been destroyed. Do nothing. if (mNativeClass == 0) { return; } int saveCount = canvas.save(); if (mTitleBar != null) { canvas.translate(0, (int) mTitleBar.getHeight()); } private void drawContent(Canvas canvas) { // Update the buttons in the picture, so when we draw the picture // to the screen, they are in the correct state. // Tell the native side if user is a) touching the screen, Loading @@ -2818,6 +2811,21 @@ public class WebView extends AbsoluteLayout mTouchMode == TOUCH_SHORTPRESS_START_MODE || mTrackballDown || mGotCenterDown, false); drawCoreAndCursorRing(canvas, mBackgroundColor, mDrawCursorRing); } @Override protected void onDraw(Canvas canvas) { // if mNativeClass is 0, the WebView has been destroyed. Do nothing. if (mNativeClass == 0) { return; } int saveCount = canvas.save(); if (mTitleBar != null) { canvas.translate(0, (int) mTitleBar.getHeight()); } if (mDragTrackerHandler == null || !mDragTrackerHandler.draw(canvas)) { drawContent(canvas); } canvas.restoreToCount(saveCount); // Now draw the shadow. Loading Loading @@ -3790,6 +3798,162 @@ public class WebView extends AbsoluteLayout } } // if the page can scroll <= this value, we won't allow the drag tracker // to have any effect. private static final int MIN_SCROLL_AMOUNT_TO_DISABLE_DRAG_TRACKER = 4; private class DragTrackerHandler { private final DragTracker mProxy; private final float mStartY, mStartX; private final float mMinDY, mMinDX; private final float mMaxDY, mMaxDX; private float mCurrStretchY, mCurrStretchX; private int mSX, mSY; public DragTrackerHandler(float x, float y, DragTracker proxy) { mProxy = proxy; int docBottom = computeVerticalScrollRange() + getTitleHeight(); int viewTop = getScrollY(); int viewBottom = viewTop + getHeight(); mStartY = y; mMinDY = -viewTop; mMaxDY = docBottom - viewBottom; if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, " dragtracker y= " + y + " up/down= " + mMinDY + " " + mMaxDY); } int docRight = computeHorizontalScrollRange(); int viewLeft = getScrollX(); int viewRight = viewLeft + getWidth(); mStartX = x; mMinDX = -viewLeft; mMaxDX = docRight - viewRight; mProxy.onStartDrag(x, y); // ensure we buildBitmap at least once mSX = -99999; } private float computeStretch(float delta, float min, float max) { float stretch = 0; if (max - min > MIN_SCROLL_AMOUNT_TO_DISABLE_DRAG_TRACKER) { if (delta < min) { stretch = delta - min; } else if (delta > max) { stretch = delta - max; } } return stretch; } public void dragTo(float x, float y) { float sy = computeStretch(mStartY - y, mMinDY, mMaxDY); float sx = computeStretch(mStartX - x, mMinDX, mMaxDX); if (mCurrStretchX != sx || mCurrStretchY != sy) { mCurrStretchX = sx; mCurrStretchY = sy; if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, "---- stretch " + sx + " " + sy); } if (mProxy.onStretchChange(sx, sy)) { invalidate(); } } } public void stopDrag() { if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, "----- stopDrag"); } mProxy.onStopDrag(); } private int hiddenHeightOfTitleBar() { return getTitleHeight() - getVisibleTitleHeight(); } // need a way to know if 565 or 8888 is the right config for // capturing the display and giving it to the drag proxy private Bitmap.Config offscreenBitmapConfig() { // hard code 565 for now return Bitmap.Config.RGB_565; } /* If the tracker draws, then this returns true, otherwise it will return false, and draw nothing. */ public boolean draw(Canvas canvas) { if (mCurrStretchX != 0 || mCurrStretchY != 0) { int sx = getScrollX(); int sy = getScrollY() - hiddenHeightOfTitleBar(); if (mSX != sx || mSY != sy) { buildBitmap(sx, sy); mSX = sx; mSY = sy; } int count = canvas.save(Canvas.MATRIX_SAVE_FLAG); canvas.translate(sx, sy); mProxy.onDraw(canvas); canvas.restoreToCount(count); return true; } if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, " -- draw false " + mCurrStretchX + " " + mCurrStretchY); } return false; } private void buildBitmap(int sx, int sy) { int w = getWidth(); int h = getViewHeight(); Bitmap bm = Bitmap.createBitmap(w, h, offscreenBitmapConfig()); Canvas canvas = new Canvas(bm); canvas.translate(-sx, -sy); drawContent(canvas); if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, "--- buildBitmap " + sx + " " + sy + " " + w + " " + h); } mProxy.onBitmapChange(bm); } } /** @hide */ public static class DragTracker { public void onStartDrag(float x, float y) {} public boolean onStretchChange(float sx, float sy) { // return true to have us inval the view return false; } public void onStopDrag() {} public void onBitmapChange(Bitmap bm) {} public void onDraw(Canvas canvas) {} } /** @hide */ public DragTracker getDragTracker() { return mDragTracker; } /** @hide */ public void setDragTracker(DragTracker tracker) { mDragTracker = tracker; } private DragTracker mDragTracker; private DragTrackerHandler mDragTrackerHandler; @Override public boolean onTouchEvent(MotionEvent ev) { if (mNativeClass == 0 || !isClickable() || !isLongClickable()) { Loading Loading @@ -3888,6 +4052,10 @@ public class WebView extends AbsoluteLayout } // Remember where the motion event started startTouch(x, y, eventTime); if (mDragTracker != null) { mDragTrackerHandler = new DragTrackerHandler(x, y, mDragTracker); } break; } case MotionEvent.ACTION_MOVE: { Loading Loading @@ -4045,6 +4213,10 @@ public class WebView extends AbsoluteLayout } } if (mDragTrackerHandler != null) { mDragTrackerHandler.dragTo(x, y); } if (done) { // keep the scrollbar on the screen even there is no scroll awakenScrollBars(ViewConfiguration.getScrollDefaultDelay(), Loading @@ -4056,6 +4228,10 @@ public class WebView extends AbsoluteLayout break; } case MotionEvent.ACTION_UP: { if (mDragTrackerHandler != null) { mDragTrackerHandler.stopDrag(); mDragTrackerHandler = null; } mLastTouchUpTime = eventTime; switch (mTouchMode) { case TOUCH_DOUBLE_TAP_MODE: // double tap Loading Loading @@ -4131,6 +4307,10 @@ public class WebView extends AbsoluteLayout break; } case MotionEvent.ACTION_CANCEL: { if (mDragTrackerHandler != null) { mDragTrackerHandler.stopDrag(); mDragTrackerHandler = null; } cancelTouch(); break; } Loading core/jni/android/graphics/Canvas.cpp +41 −1 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 @@ -965,6 +968,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); int vertCount = rows * cols; AutoJavaFloatArray vertsArray(env, jverts, vertCount * 4); SkPoint* verts = (SkPoint*)vertsArray.ptr(); SkPoint* texs = verts + vertCount; int idxCount = (rows - 1) * (cols - 1) * 6; AutoJavaShortArray idxArray(env, jidx, idxCount); 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 +1015,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 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/java/android/webkit/DebugFlags.java +2 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,8 @@ class DebugFlags { public static final boolean CALLBACK_PROXY = false; public static final boolean COOKIE_MANAGER = false; public static final boolean COOKIE_SYNC_MANAGER = false; public static final boolean DRAG_TRACKER = false; public static final String DRAG_TRACKER_LOGTAG = "skia"; public static final boolean FRAME_LOADER = false; public static final boolean J_WEB_CORE_JAVA_BRIDGE = false;// HIGHLY VERBOSE public static final boolean LOAD_LISTENER = false; Loading
core/java/android/webkit/WebView.java +190 −10 Original line number Diff line number Diff line Loading @@ -200,6 +200,8 @@ public class WebView extends AbsoluteLayout implements ViewTreeObserver.OnGlobalFocusChangeListener, ViewGroup.OnHierarchyChangeListener { // enable debug output for drag trackers private static final boolean DEBUG_DRAG_TRACKER = false; // if AUTO_REDRAW_HACK is true, then the CALL key will toggle redrawing // the screen all-the-time. Good for profiling our drawing code static private final boolean AUTO_REDRAW_HACK = false; Loading Loading @@ -2796,16 +2798,7 @@ public class WebView extends AbsoluteLayout return super.drawChild(canvas, child, drawingTime); } @Override protected void onDraw(Canvas canvas) { // if mNativeClass is 0, the WebView has been destroyed. Do nothing. if (mNativeClass == 0) { return; } int saveCount = canvas.save(); if (mTitleBar != null) { canvas.translate(0, (int) mTitleBar.getHeight()); } private void drawContent(Canvas canvas) { // Update the buttons in the picture, so when we draw the picture // to the screen, they are in the correct state. // Tell the native side if user is a) touching the screen, Loading @@ -2818,6 +2811,21 @@ public class WebView extends AbsoluteLayout mTouchMode == TOUCH_SHORTPRESS_START_MODE || mTrackballDown || mGotCenterDown, false); drawCoreAndCursorRing(canvas, mBackgroundColor, mDrawCursorRing); } @Override protected void onDraw(Canvas canvas) { // if mNativeClass is 0, the WebView has been destroyed. Do nothing. if (mNativeClass == 0) { return; } int saveCount = canvas.save(); if (mTitleBar != null) { canvas.translate(0, (int) mTitleBar.getHeight()); } if (mDragTrackerHandler == null || !mDragTrackerHandler.draw(canvas)) { drawContent(canvas); } canvas.restoreToCount(saveCount); // Now draw the shadow. Loading Loading @@ -3790,6 +3798,162 @@ public class WebView extends AbsoluteLayout } } // if the page can scroll <= this value, we won't allow the drag tracker // to have any effect. private static final int MIN_SCROLL_AMOUNT_TO_DISABLE_DRAG_TRACKER = 4; private class DragTrackerHandler { private final DragTracker mProxy; private final float mStartY, mStartX; private final float mMinDY, mMinDX; private final float mMaxDY, mMaxDX; private float mCurrStretchY, mCurrStretchX; private int mSX, mSY; public DragTrackerHandler(float x, float y, DragTracker proxy) { mProxy = proxy; int docBottom = computeVerticalScrollRange() + getTitleHeight(); int viewTop = getScrollY(); int viewBottom = viewTop + getHeight(); mStartY = y; mMinDY = -viewTop; mMaxDY = docBottom - viewBottom; if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, " dragtracker y= " + y + " up/down= " + mMinDY + " " + mMaxDY); } int docRight = computeHorizontalScrollRange(); int viewLeft = getScrollX(); int viewRight = viewLeft + getWidth(); mStartX = x; mMinDX = -viewLeft; mMaxDX = docRight - viewRight; mProxy.onStartDrag(x, y); // ensure we buildBitmap at least once mSX = -99999; } private float computeStretch(float delta, float min, float max) { float stretch = 0; if (max - min > MIN_SCROLL_AMOUNT_TO_DISABLE_DRAG_TRACKER) { if (delta < min) { stretch = delta - min; } else if (delta > max) { stretch = delta - max; } } return stretch; } public void dragTo(float x, float y) { float sy = computeStretch(mStartY - y, mMinDY, mMaxDY); float sx = computeStretch(mStartX - x, mMinDX, mMaxDX); if (mCurrStretchX != sx || mCurrStretchY != sy) { mCurrStretchX = sx; mCurrStretchY = sy; if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, "---- stretch " + sx + " " + sy); } if (mProxy.onStretchChange(sx, sy)) { invalidate(); } } } public void stopDrag() { if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, "----- stopDrag"); } mProxy.onStopDrag(); } private int hiddenHeightOfTitleBar() { return getTitleHeight() - getVisibleTitleHeight(); } // need a way to know if 565 or 8888 is the right config for // capturing the display and giving it to the drag proxy private Bitmap.Config offscreenBitmapConfig() { // hard code 565 for now return Bitmap.Config.RGB_565; } /* If the tracker draws, then this returns true, otherwise it will return false, and draw nothing. */ public boolean draw(Canvas canvas) { if (mCurrStretchX != 0 || mCurrStretchY != 0) { int sx = getScrollX(); int sy = getScrollY() - hiddenHeightOfTitleBar(); if (mSX != sx || mSY != sy) { buildBitmap(sx, sy); mSX = sx; mSY = sy; } int count = canvas.save(Canvas.MATRIX_SAVE_FLAG); canvas.translate(sx, sy); mProxy.onDraw(canvas); canvas.restoreToCount(count); return true; } if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, " -- draw false " + mCurrStretchX + " " + mCurrStretchY); } return false; } private void buildBitmap(int sx, int sy) { int w = getWidth(); int h = getViewHeight(); Bitmap bm = Bitmap.createBitmap(w, h, offscreenBitmapConfig()); Canvas canvas = new Canvas(bm); canvas.translate(-sx, -sy); drawContent(canvas); if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, "--- buildBitmap " + sx + " " + sy + " " + w + " " + h); } mProxy.onBitmapChange(bm); } } /** @hide */ public static class DragTracker { public void onStartDrag(float x, float y) {} public boolean onStretchChange(float sx, float sy) { // return true to have us inval the view return false; } public void onStopDrag() {} public void onBitmapChange(Bitmap bm) {} public void onDraw(Canvas canvas) {} } /** @hide */ public DragTracker getDragTracker() { return mDragTracker; } /** @hide */ public void setDragTracker(DragTracker tracker) { mDragTracker = tracker; } private DragTracker mDragTracker; private DragTrackerHandler mDragTrackerHandler; @Override public boolean onTouchEvent(MotionEvent ev) { if (mNativeClass == 0 || !isClickable() || !isLongClickable()) { Loading Loading @@ -3888,6 +4052,10 @@ public class WebView extends AbsoluteLayout } // Remember where the motion event started startTouch(x, y, eventTime); if (mDragTracker != null) { mDragTrackerHandler = new DragTrackerHandler(x, y, mDragTracker); } break; } case MotionEvent.ACTION_MOVE: { Loading Loading @@ -4045,6 +4213,10 @@ public class WebView extends AbsoluteLayout } } if (mDragTrackerHandler != null) { mDragTrackerHandler.dragTo(x, y); } if (done) { // keep the scrollbar on the screen even there is no scroll awakenScrollBars(ViewConfiguration.getScrollDefaultDelay(), Loading @@ -4056,6 +4228,10 @@ public class WebView extends AbsoluteLayout break; } case MotionEvent.ACTION_UP: { if (mDragTrackerHandler != null) { mDragTrackerHandler.stopDrag(); mDragTrackerHandler = null; } mLastTouchUpTime = eventTime; switch (mTouchMode) { case TOUCH_DOUBLE_TAP_MODE: // double tap Loading Loading @@ -4131,6 +4307,10 @@ public class WebView extends AbsoluteLayout break; } case MotionEvent.ACTION_CANCEL: { if (mDragTrackerHandler != null) { mDragTrackerHandler.stopDrag(); mDragTrackerHandler = null; } cancelTouch(); break; } Loading
core/jni/android/graphics/Canvas.cpp +41 −1 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 @@ -965,6 +968,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); int vertCount = rows * cols; AutoJavaFloatArray vertsArray(env, jverts, vertCount * 4); SkPoint* verts = (SkPoint*)vertsArray.ptr(); SkPoint* texs = verts + vertCount; int idxCount = (rows - 1) * (cols - 1) * 6; AutoJavaShortArray idxArray(env, jidx, idxCount); 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 +1015,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
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); }