Do not merge

port stretchy from master
add pattern bg for effect #2
diff --git a/src/com/android/browser/MeshTracker.java b/src/com/android/browser/MeshTracker.java
new file mode 100644
index 0000000..8c9c00e
--- /dev/null
+++ b/src/com/android/browser/MeshTracker.java
@@ -0,0 +1,198 @@
+/*
+ * 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 com.android.browser;
+
+import android.graphics.Bitmap;
+import android.graphics.utils.BoundaryPatch;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.webkit.WebView;
+
+/*package*/ class MeshTracker extends WebView.DragTracker {
+
+    private static class Mesh {
+        private int mWhich;
+        private int mRows;
+        private int mCols;
+        private BoundaryPatch mPatch = new BoundaryPatch();
+        private float[] mCubics = new float[24];
+        private float[] mOrig = new float[24];
+        private float mStretchX, mStretchY;
+
+        Mesh(int which, int rows, int cols) {
+            mWhich = which;
+            mRows = rows;
+            mCols = cols;
+        }
+        
+        private void rebuildPatch() {
+            mPatch.setCubicBoundary(mCubics, 0, mRows, mCols);
+        }
+
+        private void setSize(float w, float h) {
+            float[] pts = mCubics;
+            float x1 = w*0.3333f;
+            float y1 = h*0.3333f;
+            float x2 = w*0.6667f;
+            float y2 = h*0.6667f;
+            pts[0*2+0] = 0;  pts[0*2+1] = 0;
+            pts[1*2+0] = x1; pts[1*2+1] = 0;
+            pts[2*2+0] = x2; pts[2*2+1] = 0;
+
+            pts[3*2+0] = w; pts[3*2+1] = 0;
+            pts[4*2+0] = w; pts[4*2+1] = y1;
+            pts[5*2+0] = w; pts[5*2+1] = y2;
+
+            pts[6*2+0] = w; pts[6*2+1] = h;
+            pts[7*2+0] = x2; pts[7*2+1] = h;
+            pts[8*2+0] = x1; pts[8*2+1] = h;
+
+            pts[9*2+0] = 0;  pts[9*2+1] = h;
+            pts[10*2+0] = 0; pts[10*2+1] = y2;
+            pts[11*2+0] = 0; pts[11*2+1] = y1;
+
+            System.arraycopy(pts, 0, mOrig, 0, 24);
+
+            // recall our stretcher
+            setStretch(mStretchX, mStretchY);
+        }
+
+        public void setBitmap(Bitmap bm) {
+            mPatch.setTexture(bm);
+            setSize(bm.getWidth(), bm.getHeight());
+        }
+
+        // first experimental behavior
+        private void doit1(float dx, float dy) {
+            final float scale = 0.75f;  // temper how far we actually move
+            dx *= scale;
+            dy *= scale;
+
+            int index;
+            if (dx < 0) {
+                index = 10;
+            } else {
+                index = 4;
+            }
+            mCubics[index*2 + 0] = mOrig[index*2 + 0] + dx;
+            mCubics[index*2 + 2] = mOrig[index*2 + 2] + dx;
+
+            if (dy < 0) {
+                index = 1;
+            } else {
+                index = 7;
+            }
+            mCubics[index*2 + 1] = mOrig[index*2 + 1] + dy;
+            mCubics[index*2 + 3] = mOrig[index*2 + 3] + dy;
+        }
+
+        private void doit2(float dx, float dy) {
+            final float scale = 0.4f;  // temper how far we actually move
+            dx *= scale;
+            dy *= scale;
+            final float cornerScale = 0.25f;
+
+            int index;
+            if (dx < 0) {
+                index = 4;
+            } else {
+                index = 10;
+            }
+            mCubics[index*2 + 0] = mOrig[index*2 + 0] + dx;
+            mCubics[index*2 + 2] = mOrig[index*2 + 2] + dx;
+            // corners
+            index -= 1;
+            mCubics[index*2 + 0] = mOrig[index*2 + 0] + dx * cornerScale;
+            index = (index + 3) % 12; // next corner
+            mCubics[index*2 + 0] = mOrig[index*2 + 0] + dx * cornerScale;
+
+            if (dy < 0) {
+                index = 7;
+            } else {
+                index = 1;
+            }
+            mCubics[index*2 + 1] = mOrig[index*2 + 1] + dy;
+            mCubics[index*2 + 3] = mOrig[index*2 + 3] + dy;
+            // corners
+            index -= 1;
+            mCubics[index*2 + 1] = mOrig[index*2 + 1] + dy * cornerScale;
+            index = (index + 3) % 12; // next corner
+            mCubics[index*2 + 1] = mOrig[index*2 + 1] + dy * cornerScale;
+        }
+
+        public void setStretch(float dx, float dy) {
+            mStretchX = dx;
+            mStretchY = dy;
+            switch (mWhich) {
+                case 1:
+                    doit1(dx, dy);
+                    break;
+                case 2:
+                    doit2(dx, dy);
+                    break;
+            }
+            rebuildPatch();
+        }
+
+        public void draw(Canvas canvas) {
+            mPatch.draw(canvas);
+        }
+    }
+
+    private Mesh mMesh;
+    private Bitmap mBitmap;
+    private int mWhich;
+    private Paint mBGPaint;
+
+    public MeshTracker(int which) {
+        mWhich = which;
+    }
+
+    public void setBGPaint(Paint paint) {
+        mBGPaint = paint;
+    }
+    
+    @Override public void onStartDrag(float x, float y) {
+        mMesh = new Mesh(mWhich, 16, 16);
+    }
+
+    @Override public void onBitmapChange(Bitmap bm) {
+        mBitmap = bm;
+        mMesh.setBitmap(bm);
+    }
+
+    @Override public boolean onStretchChange(float sx, float sy) {
+        mMesh.setStretch(-sx, -sy);
+        return true;
+    }
+
+    @Override public void onStopDrag() {
+        mMesh = null;
+    }
+
+    @Override public void onDraw(Canvas canvas) {
+        if (mWhich == 2) {
+            if (mBGPaint != null) {
+                canvas.drawPaint(mBGPaint);
+            } else {
+                canvas.drawColor(0xFF000000);
+            }
+        }
+        mMesh.draw(canvas);
+    }
+}
+