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

Commit 12bcbdc6 authored by Mike Reed's avatar Mike Reed
Browse files

Do not merge

port stretchy from master
parent 9f954cf2
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);
}