Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a66baccc authored by Mike Reed's avatar Mike Reed Committed by Android (Google) Code Review
Browse files

Merge "Do not merge" into eclair

parents d1da5fa2 12bcbdc6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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;
+190 −10
Original line number Diff line number Diff line
@@ -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;
            }
+41 −1
Original line number Diff line number Diff line
@@ -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,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;
}
+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);
}