Loading core/java/android/view/ScaleGestureDetector.java +30 −13 Original line number Diff line number Diff line Loading @@ -147,12 +147,9 @@ public class ScaleGestureDetector { public ScaleGestureDetector(Context context, OnScaleGestureListener listener) { ViewConfiguration config = ViewConfiguration.get(context); DisplayMetrics metrics = context.getResources().getDisplayMetrics(); mContext = context; mListener = listener; mEdgeSlop = config.getScaledEdgeSlop(); mRightSlopEdge = metrics.widthPixels - mEdgeSlop; mBottomSlopEdge = metrics.heightPixels - mEdgeSlop; } public boolean onTouchEvent(MotionEvent event) { Loading @@ -165,6 +162,11 @@ public class ScaleGestureDetector { event.getPointerCount() >= 2) { // We have a new multi-finger gesture // as orientation can change, query the metrics in touch down DisplayMetrics metrics = mContext.getResources().getDisplayMetrics(); mRightSlopEdge = metrics.widthPixels - mEdgeSlop; mBottomSlopEdge = metrics.heightPixels - mEdgeSlop; // Be paranoid in case we missed an event reset(); Loading @@ -185,12 +187,16 @@ public class ScaleGestureDetector { final float x1 = getRawX(event, 1); final float y1 = getRawY(event, 1); boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || x1 < edgeSlop || y1 < edgeSlop; boolean p1sloppy = x0 > rightSlop || y0 > bottomSlop || x1 > rightSlop || y1 > bottomSlop; boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || x0 > rightSlop || y0 > bottomSlop; boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop || x1 > rightSlop || y1 > bottomSlop; if (p0sloppy) { if(p0sloppy && p1sloppy) { mFocusX = -1; mFocusY = -1; mSloppyGesture = true; } else if (p0sloppy) { mFocusX = event.getX(1); mFocusY = event.getY(1); mSloppyGesture = true; Loading @@ -211,12 +217,15 @@ public class ScaleGestureDetector { final float x1 = getRawX(event, 1); final float y1 = getRawY(event, 1); boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || x1 < edgeSlop || y1 < edgeSlop; boolean p1sloppy = x0 > rightSlop || y0 > bottomSlop || x1 > rightSlop || y1 > bottomSlop; boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || x0 > rightSlop || y0 > bottomSlop; boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop || x1 > rightSlop || y1 > bottomSlop; if (p0sloppy) { if(p0sloppy && p1sloppy) { mFocusX = -1; mFocusY = -1; } else if (p0sloppy) { mFocusX = event.getX(1); mFocusY = event.getY(1); } else if (p1sloppy) { Loading @@ -226,6 +235,14 @@ public class ScaleGestureDetector { mSloppyGesture = false; mGestureInProgress = mListener.onScaleBegin(this); } } else if ((action == MotionEvent.ACTION_POINTER_1_UP || action == MotionEvent.ACTION_POINTER_2_UP) && mSloppyGesture) { // Set focus point to the remaining finger int id = (((action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT) == 0) ? 1 : 0; mFocusX = event.getX(id); mFocusY = event.getY(id); } } else { // Transform gesture in progress - attempt to handle it 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 +267 −37 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 @@ -534,8 +536,10 @@ public class WebView extends AbsoluteLayout static int DEFAULT_SCALE_PERCENT; private float mDefaultScale; // set to true temporarily while the zoom control is being dragged // set to true temporarily during ScaleGesture triggered zoom private boolean mPreviewZoomOnly = false; // extra scale during zoom preview private float mPreviewExtraZoomScale = 1.0f; // computed scale and inverse, from mZoomWidth. private float mActualScale; Loading Loading @@ -2796,16 +2800,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 @@ -2817,11 +2812,34 @@ public class WebView extends AbsoluteLayout nativeRecordButtons(hasFocus() && hasWindowFocus(), mTouchMode == TOUCH_SHORTPRESS_START_MODE || mTrackballDown || mGotCenterDown, false); drawCoreAndCursorRing(canvas, mBackgroundColor, mDrawCursorRing); canvas.restoreToCount(saveCount); // use the DKGRAY as background when drawing zoom preview drawCoreAndCursorRing(canvas, mPreviewZoomOnly ? Color.DKGRAY : mBackgroundColor, mDrawCursorRing); } // Now draw the shadow. @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 (mPreviewZoomOnly) { // scale after canvas.save() so that the child, like titlebar, will // not be scaled. canvas.scale(mPreviewExtraZoomScale, mPreviewExtraZoomScale, mZoomCenterX + mScrollX, mZoomCenterY + mScrollY); } if (mTitleBar != null) { canvas.translate(0, (int) mTitleBar.getHeight()); } if (mDragTrackerHandler == null || !mDragTrackerHandler.draw(canvas)) { drawContent(canvas); } canvas.restoreToCount(saveCount); // Now draw the shadow, skip if it is in zoom preview mode. if ((mTitleBar != null && !mPreviewZoomOnly)) { int y = mScrollY + getVisibleTitleHeight(); int height = (int) (5f * getContext().getResources() .getDisplayMetrics().density); Loading Loading @@ -3726,6 +3744,8 @@ public class WebView extends AbsoluteLayout private class ScaleDetectorListener implements ScaleGestureDetector.OnScaleGestureListener { float mStartX, mStartY; public boolean onScaleBegin(ScaleGestureDetector detector) { // cancel the single touch handling cancelTouch(); Loading @@ -3739,6 +3759,9 @@ public class WebView extends AbsoluteLayout if (inEditingMode() && nativeFocusCandidateIsPassword()) { mWebTextView.setInPassword(false); } mPreviewExtraZoomScale = 1.0f; mStartX = detector.getFocusX(); mStartY = detector.getFocusY(); return true; } Loading @@ -3747,13 +3770,12 @@ public class WebView extends AbsoluteLayout mPreviewZoomOnly = false; mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX); mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY); float scale = mPreviewExtraZoomScale * mActualScale; // don't reflow when zoom in; when zoom out, do reflow if the // new scale is almost minimum scale; boolean reflowNow = (mActualScale - mMinZoomScale <= 0.01f) || ((mActualScale <= 0.8 * mTextWrapScale)); // force zoom after mPreviewZoomOnly is set to false so that the // new view size will be passed to the WebKit setNewZoomScale(mActualScale, reflowNow, true); boolean reflowNow = (scale - mMinZoomScale <= 0.01f) || ((scale <= 0.8 * mTextWrapScale)); setNewZoomScale(scale, reflowNow, false); // call invalidate() to draw without zoom filter invalidate(); } Loading @@ -3770,26 +3792,197 @@ public class WebView extends AbsoluteLayout } public boolean onScale(ScaleGestureDetector detector) { float currScale = mPreviewExtraZoomScale * mActualScale; float scale = (float) (Math.round(detector.getScaleFactor() * mActualScale * 100) / 100.0); if (Math.abs(scale - mActualScale) >= PREVIEW_SCALE_INCREMENT) { mPreviewZoomOnly = true; * currScale * 100) / 100.0); // limit the scale change per step if (scale > mActualScale) { scale = Math.min(scale, mActualScale * 1.25f); if (scale > currScale) { scale = Math.min(scale, currScale * 1.25f); } else { scale = Math.max(scale, mActualScale * 0.8f); // the preview scale can be 80% of mMinZoomScale for feedback scale = Math.max(Math.max(scale, currScale * 0.8f), mMinZoomScale * 0.8f); } if (Math.abs(scale - currScale) >= PREVIEW_SCALE_INCREMENT) { mPreviewZoomOnly = true; // FIXME: mZoomCenterX/Y need to be relative to mActualScale. // Ideally the focusX/Y should be a fixed point. But currently // it just returns the center of the two pointers. If only one // pointer is moving, the center is shifting. Currently we only // adjust it for zoom in case to get better result. if (mPreviewExtraZoomScale > 1.0f) { mZoomCenterX = mStartX - (mStartX - detector.getFocusX()) / mPreviewExtraZoomScale; mZoomCenterY = mStartY - (mStartY - detector.getFocusY()) / mPreviewExtraZoomScale; } else { mZoomCenterX = detector.getFocusX(); mZoomCenterY = detector.getFocusY(); setNewZoomScale(scale, false, false); } mPreviewExtraZoomScale = scale / mActualScale; invalidate(); return true; } return false; } } // 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 @@ -3801,18 +3994,39 @@ public class WebView extends AbsoluteLayout + mTouchMode); } int action; float x, y; long eventTime = ev.getEventTime(); // FIXME: we may consider to give WebKit an option to handle multi-touch // events later. if (mSupportMultiTouch && mMinZoomScale < mMaxZoomScale && ev.getPointerCount() > 1) { mLastTouchTime = ev.getEventTime(); return mScaleDetector.onTouchEvent(ev); if (mSupportMultiTouch && ev.getPointerCount() > 1) { mScaleDetector.onTouchEvent(ev); if (mScaleDetector.isInProgress()) { mLastTouchTime = eventTime; return true; } x = mScaleDetector.getFocusX(); y = mScaleDetector.getFocusY(); action = ev.getAction() & MotionEvent.ACTION_MASK; if (action == MotionEvent.ACTION_POINTER_DOWN) { cancelTouch(); action = MotionEvent.ACTION_DOWN; } else if (action == MotionEvent.ACTION_POINTER_UP) { // set mLastTouchX/Y to the remaining point mLastTouchX = x; mLastTouchY = y; } else if (action == MotionEvent.ACTION_MOVE) { // negative x or y indicate it is on the edge, skip it. if (x < 0 || y < 0) { return true; } } } else { action = ev.getAction(); x = ev.getX(); y = ev.getY(); } int action = ev.getAction(); float x = ev.getX(); float y = ev.getY(); long eventTime = ev.getEventTime(); // Due to the touch screen edge effect, a touch closer to the edge // always snapped to the edge. As getViewWidth() can be different from Loading Loading @@ -3888,6 +4102,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 +4263,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 +4278,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 +4357,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 core/jni/android/graphics/Typeface.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ static SkTypeface* Typeface_createFromTypeface(JNIEnv* env, jobject, SkTypeface* } static void Typeface_unref(JNIEnv* env, jobject obj, SkTypeface* face) { face->unref(); SkSafeUnref(face); } static int Typeface_getStyle(JNIEnv* env, jobject obj, SkTypeface* face) { Loading Loading
core/java/android/view/ScaleGestureDetector.java +30 −13 Original line number Diff line number Diff line Loading @@ -147,12 +147,9 @@ public class ScaleGestureDetector { public ScaleGestureDetector(Context context, OnScaleGestureListener listener) { ViewConfiguration config = ViewConfiguration.get(context); DisplayMetrics metrics = context.getResources().getDisplayMetrics(); mContext = context; mListener = listener; mEdgeSlop = config.getScaledEdgeSlop(); mRightSlopEdge = metrics.widthPixels - mEdgeSlop; mBottomSlopEdge = metrics.heightPixels - mEdgeSlop; } public boolean onTouchEvent(MotionEvent event) { Loading @@ -165,6 +162,11 @@ public class ScaleGestureDetector { event.getPointerCount() >= 2) { // We have a new multi-finger gesture // as orientation can change, query the metrics in touch down DisplayMetrics metrics = mContext.getResources().getDisplayMetrics(); mRightSlopEdge = metrics.widthPixels - mEdgeSlop; mBottomSlopEdge = metrics.heightPixels - mEdgeSlop; // Be paranoid in case we missed an event reset(); Loading @@ -185,12 +187,16 @@ public class ScaleGestureDetector { final float x1 = getRawX(event, 1); final float y1 = getRawY(event, 1); boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || x1 < edgeSlop || y1 < edgeSlop; boolean p1sloppy = x0 > rightSlop || y0 > bottomSlop || x1 > rightSlop || y1 > bottomSlop; boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || x0 > rightSlop || y0 > bottomSlop; boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop || x1 > rightSlop || y1 > bottomSlop; if (p0sloppy) { if(p0sloppy && p1sloppy) { mFocusX = -1; mFocusY = -1; mSloppyGesture = true; } else if (p0sloppy) { mFocusX = event.getX(1); mFocusY = event.getY(1); mSloppyGesture = true; Loading @@ -211,12 +217,15 @@ public class ScaleGestureDetector { final float x1 = getRawX(event, 1); final float y1 = getRawY(event, 1); boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || x1 < edgeSlop || y1 < edgeSlop; boolean p1sloppy = x0 > rightSlop || y0 > bottomSlop || x1 > rightSlop || y1 > bottomSlop; boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || x0 > rightSlop || y0 > bottomSlop; boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop || x1 > rightSlop || y1 > bottomSlop; if (p0sloppy) { if(p0sloppy && p1sloppy) { mFocusX = -1; mFocusY = -1; } else if (p0sloppy) { mFocusX = event.getX(1); mFocusY = event.getY(1); } else if (p1sloppy) { Loading @@ -226,6 +235,14 @@ public class ScaleGestureDetector { mSloppyGesture = false; mGestureInProgress = mListener.onScaleBegin(this); } } else if ((action == MotionEvent.ACTION_POINTER_1_UP || action == MotionEvent.ACTION_POINTER_2_UP) && mSloppyGesture) { // Set focus point to the remaining finger int id = (((action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT) == 0) ? 1 : 0; mFocusX = event.getX(id); mFocusY = event.getY(id); } } else { // Transform gesture in progress - attempt to handle it 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 +267 −37 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 @@ -534,8 +536,10 @@ public class WebView extends AbsoluteLayout static int DEFAULT_SCALE_PERCENT; private float mDefaultScale; // set to true temporarily while the zoom control is being dragged // set to true temporarily during ScaleGesture triggered zoom private boolean mPreviewZoomOnly = false; // extra scale during zoom preview private float mPreviewExtraZoomScale = 1.0f; // computed scale and inverse, from mZoomWidth. private float mActualScale; Loading Loading @@ -2796,16 +2800,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 @@ -2817,11 +2812,34 @@ public class WebView extends AbsoluteLayout nativeRecordButtons(hasFocus() && hasWindowFocus(), mTouchMode == TOUCH_SHORTPRESS_START_MODE || mTrackballDown || mGotCenterDown, false); drawCoreAndCursorRing(canvas, mBackgroundColor, mDrawCursorRing); canvas.restoreToCount(saveCount); // use the DKGRAY as background when drawing zoom preview drawCoreAndCursorRing(canvas, mPreviewZoomOnly ? Color.DKGRAY : mBackgroundColor, mDrawCursorRing); } // Now draw the shadow. @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 (mPreviewZoomOnly) { // scale after canvas.save() so that the child, like titlebar, will // not be scaled. canvas.scale(mPreviewExtraZoomScale, mPreviewExtraZoomScale, mZoomCenterX + mScrollX, mZoomCenterY + mScrollY); } if (mTitleBar != null) { canvas.translate(0, (int) mTitleBar.getHeight()); } if (mDragTrackerHandler == null || !mDragTrackerHandler.draw(canvas)) { drawContent(canvas); } canvas.restoreToCount(saveCount); // Now draw the shadow, skip if it is in zoom preview mode. if ((mTitleBar != null && !mPreviewZoomOnly)) { int y = mScrollY + getVisibleTitleHeight(); int height = (int) (5f * getContext().getResources() .getDisplayMetrics().density); Loading Loading @@ -3726,6 +3744,8 @@ public class WebView extends AbsoluteLayout private class ScaleDetectorListener implements ScaleGestureDetector.OnScaleGestureListener { float mStartX, mStartY; public boolean onScaleBegin(ScaleGestureDetector detector) { // cancel the single touch handling cancelTouch(); Loading @@ -3739,6 +3759,9 @@ public class WebView extends AbsoluteLayout if (inEditingMode() && nativeFocusCandidateIsPassword()) { mWebTextView.setInPassword(false); } mPreviewExtraZoomScale = 1.0f; mStartX = detector.getFocusX(); mStartY = detector.getFocusY(); return true; } Loading @@ -3747,13 +3770,12 @@ public class WebView extends AbsoluteLayout mPreviewZoomOnly = false; mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX); mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY); float scale = mPreviewExtraZoomScale * mActualScale; // don't reflow when zoom in; when zoom out, do reflow if the // new scale is almost minimum scale; boolean reflowNow = (mActualScale - mMinZoomScale <= 0.01f) || ((mActualScale <= 0.8 * mTextWrapScale)); // force zoom after mPreviewZoomOnly is set to false so that the // new view size will be passed to the WebKit setNewZoomScale(mActualScale, reflowNow, true); boolean reflowNow = (scale - mMinZoomScale <= 0.01f) || ((scale <= 0.8 * mTextWrapScale)); setNewZoomScale(scale, reflowNow, false); // call invalidate() to draw without zoom filter invalidate(); } Loading @@ -3770,26 +3792,197 @@ public class WebView extends AbsoluteLayout } public boolean onScale(ScaleGestureDetector detector) { float currScale = mPreviewExtraZoomScale * mActualScale; float scale = (float) (Math.round(detector.getScaleFactor() * mActualScale * 100) / 100.0); if (Math.abs(scale - mActualScale) >= PREVIEW_SCALE_INCREMENT) { mPreviewZoomOnly = true; * currScale * 100) / 100.0); // limit the scale change per step if (scale > mActualScale) { scale = Math.min(scale, mActualScale * 1.25f); if (scale > currScale) { scale = Math.min(scale, currScale * 1.25f); } else { scale = Math.max(scale, mActualScale * 0.8f); // the preview scale can be 80% of mMinZoomScale for feedback scale = Math.max(Math.max(scale, currScale * 0.8f), mMinZoomScale * 0.8f); } if (Math.abs(scale - currScale) >= PREVIEW_SCALE_INCREMENT) { mPreviewZoomOnly = true; // FIXME: mZoomCenterX/Y need to be relative to mActualScale. // Ideally the focusX/Y should be a fixed point. But currently // it just returns the center of the two pointers. If only one // pointer is moving, the center is shifting. Currently we only // adjust it for zoom in case to get better result. if (mPreviewExtraZoomScale > 1.0f) { mZoomCenterX = mStartX - (mStartX - detector.getFocusX()) / mPreviewExtraZoomScale; mZoomCenterY = mStartY - (mStartY - detector.getFocusY()) / mPreviewExtraZoomScale; } else { mZoomCenterX = detector.getFocusX(); mZoomCenterY = detector.getFocusY(); setNewZoomScale(scale, false, false); } mPreviewExtraZoomScale = scale / mActualScale; invalidate(); return true; } return false; } } // 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 @@ -3801,18 +3994,39 @@ public class WebView extends AbsoluteLayout + mTouchMode); } int action; float x, y; long eventTime = ev.getEventTime(); // FIXME: we may consider to give WebKit an option to handle multi-touch // events later. if (mSupportMultiTouch && mMinZoomScale < mMaxZoomScale && ev.getPointerCount() > 1) { mLastTouchTime = ev.getEventTime(); return mScaleDetector.onTouchEvent(ev); if (mSupportMultiTouch && ev.getPointerCount() > 1) { mScaleDetector.onTouchEvent(ev); if (mScaleDetector.isInProgress()) { mLastTouchTime = eventTime; return true; } x = mScaleDetector.getFocusX(); y = mScaleDetector.getFocusY(); action = ev.getAction() & MotionEvent.ACTION_MASK; if (action == MotionEvent.ACTION_POINTER_DOWN) { cancelTouch(); action = MotionEvent.ACTION_DOWN; } else if (action == MotionEvent.ACTION_POINTER_UP) { // set mLastTouchX/Y to the remaining point mLastTouchX = x; mLastTouchY = y; } else if (action == MotionEvent.ACTION_MOVE) { // negative x or y indicate it is on the edge, skip it. if (x < 0 || y < 0) { return true; } } } else { action = ev.getAction(); x = ev.getX(); y = ev.getY(); } int action = ev.getAction(); float x = ev.getX(); float y = ev.getY(); long eventTime = ev.getEventTime(); // Due to the touch screen edge effect, a touch closer to the edge // always snapped to the edge. As getViewWidth() can be different from Loading Loading @@ -3888,6 +4102,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 +4263,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 +4278,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 +4357,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
core/jni/android/graphics/Typeface.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ static SkTypeface* Typeface_createFromTypeface(JNIEnv* env, jobject, SkTypeface* } static void Typeface_unref(JNIEnv* env, jobject obj, SkTypeface* face) { face->unref(); SkSafeUnref(face); } static int Typeface_getStyle(JNIEnv* env, jobject obj, SkTypeface* face) { Loading