Merge "Do not merge" into eclair

This commit is contained in:
Mike Reed
2010-01-20 18:32:32 -08:00
committed by Android (Google) Code Review
4 changed files with 406 additions and 11 deletions

View File

@@ -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;

View File

@@ -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;
@@ -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,
@@ -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.
@@ -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()) {
@@ -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: {
@@ -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(),
@@ -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
@@ -4131,6 +4307,10 @@ public class WebView extends AbsoluteLayout
break;
}
case MotionEvent.ACTION_CANCEL: {
if (mDragTrackerHandler != null) {
mDragTrackerHandler.stopDrag();
mDragTrackerHandler = null;
}
cancelTouch();
break;
}

View File

@@ -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() {
@@ -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) \
@@ -976,7 +1015,8 @@ int register_android_graphics_Canvas(JNIEnv* env) {
int result;
REG(env, "android/graphics/Canvas", gCanvasMethods);
REG(env, "android/graphics/utils/BoundaryPatch", gBoundaryPatchMethods);
return result;
}

View 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);
}