/* * Copyright (C) 2007 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.graphicslab; import java.util.Map; import android.app.Activity; import android.content.Context; import android.graphics.*; import android.graphics.utils.*; import android.os.Bundle; import android.os.SystemClock; import android.view.*; public class GraphicsLab extends Activity { public GraphicsLab() {} private int mCurrView = 1; public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(new SampleView(this)); // setTitle("Graphics Lab"); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch(keyCode) { case KeyEvent.KEYCODE_DPAD_CENTER: if (mCurrView == 1) { setContentView(new SampleView2(this)); mCurrView = 2; } else { setContentView(new SampleView(this)); mCurrView = 1; } } return super.onKeyDown(keyCode, event); } private static class SampleView2 extends View { private static final int ROWS = 16; private static final int COLS = 16; private static final int UNSTRETCH_MSEC = 250; private Interpolator mInterp; private BoundaryPatch mPatch; private float[] mCubics; private float[] mOrig = new float[24]; private Paint mPaint0; private Paint mPaint1; private int mCurrIndex = -1; private float mPrevX; private float mPrevY; public SampleView2(Context context) { super(context); setFocusable(true); Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.news_img); mPatch = new BoundaryPatch(); mPatch.setTexture(bm); float unit = 90; mCubics = new float[] { 0, 0, 1, 0, 2, 0, 3, 0, 3, 1, 3, 2, 3, 3, 2, 3, 1, 3, 0, 3, 0, 2, 0, 1 }; for (int i = 0; i < 24; i++) { mCubics[i] *= 90; mCubics[i] += 20; } rebuildPatch(); mPaint0 = new Paint(); mPaint0.setAntiAlias(true); mPaint0.setStrokeWidth(12); mPaint0.setStrokeCap(Paint.Cap.ROUND); mPaint1 = new Paint(mPaint0); mPaint1.setColor(0xFFFFFFFF); mPaint1.setStrokeWidth(10); } @Override protected void onSizeChanged(int nw, int nh, int ow, int oh) { float[] pts = mCubics; float x1 = nw*0.3333f; float y1 = nh*0.3333f; float x2 = nw*0.6667f; float y2 = nh*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] = nw; pts[3*2+1] = 0; pts[4*2+0] = nw; pts[4*2+1] = y1; pts[5*2+0] = nw; pts[5*2+1] = y2; pts[6*2+0] = nw; pts[6*2+1] = nh; pts[7*2+0] = x2; pts[7*2+1] = nh; pts[8*2+0] = x1; pts[8*2+1] = nh; pts[9*2+0] = 0; pts[9*2+1] = nh; 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); rebuildPatch(); } @Override protected void onDraw(Canvas canvas) { if (mInterp != null) { int now = (int)SystemClock.uptimeMillis(); Interpolator.Result result = mInterp.timeToValues(now, mCubics); if (result != Interpolator.Result.NORMAL) { mInterp = null; } else { invalidate(); } rebuildPatch(); } mPatch.draw(canvas); } private void rebuildPatch() { mPatch.setCubicBoundary(mCubics, 0, ROWS, COLS); } @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: System.arraycopy(mOrig, 0, mCubics, 0, 24); mPrevX = x; mPrevY = y; break; case MotionEvent.ACTION_MOVE: { float scale = 1.5f; float dx = (x - mPrevX) * scale; float dy = (y - mPrevY) * 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; rebuildPatch(); invalidate(); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: { int start = (int)SystemClock.uptimeMillis(); mInterp = new Interpolator(24); mInterp.setKeyFrame(0, start, mCubics, new float[] { 0, 0.5f, 0.5f, 1 }); mInterp.setKeyFrame(1, start + UNSTRETCH_MSEC, mOrig ); invalidate(); } break; } return true; } } private static class SampleView extends View { private static final int ROWS = 16; private static final int COLS = 16; private BoundaryPatch mPatch; private float[] mCubics; private float[] mOrig = new float[24]; private Paint mPaint0; private Paint mPaint1; private int mCurrIndex = -1; private float mPrevX; private float mPrevY; public SampleView(Context context) { super(context); setFocusable(true); Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.beach); mPatch = new BoundaryPatch(); mPatch.setTexture(bm); float unit = 90; mCubics = new float[] { 0, 0, 1, 0, 2, 0, 3, 0, 3, 1, 3, 2, 3, 3, 2, 3, 1, 3, 0, 3, 0, 2, 0, 1 }; for (int i = 0; i < 24; i++) { mCubics[i] *= 90; mCubics[i] += 20; } rebuildPatch(); mPaint0 = new Paint(); mPaint0.setAntiAlias(true); mPaint0.setStrokeWidth(12); mPaint0.setStrokeCap(Paint.Cap.ROUND); mPaint1 = new Paint(mPaint0); mPaint1.setColor(0xFFFFFFFF); mPaint1.setStrokeWidth(10); } @Override protected void onDraw(Canvas canvas) { canvas.drawColor(0xFFCCCCCC); mPatch.draw(canvas); canvas.drawPoints(mCubics, mPaint0); canvas.drawPoints(mCubics, mPaint1); } private void rebuildPatch() { mPatch.setCubicBoundary(mCubics, 0, ROWS, COLS); } private int findPtIndex(float x, float y) { final float tolerance = 25; final float[] pts = mCubics; for (int i = 0; i < (pts.length >> 1); i++) { if (Math.abs(pts[i*2 + 0] - x) <= tolerance && Math.abs(pts[i*2 + 1] - y) <= tolerance) { return i*2; } } return -1; } private void offsetPts(float dx, float dy) { final float[] pts = mCubics; for (int i = 0; i < (pts.length >> 1); i++) { pts[i*2 + 0] += dx; pts[i*2 + 1] += dy; } rebuildPatch(); } @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mCurrIndex = findPtIndex(x, y); mPrevX = x; mPrevY = y; break; case MotionEvent.ACTION_MOVE: if (mCurrIndex >= 0) { mCubics[mCurrIndex + 0] = x; mCubics[mCurrIndex + 1] = y; mPatch.setCubicBoundary(mCubics, 0, ROWS, COLS); } else { offsetPts(x - mPrevX, y - mPrevY); mPrevX = x; mPrevY = y; } invalidate(); break; } return true; } } }