1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.graphicslab; 18 19 import java.util.Map; 20 21 import android.app.Activity; 22 import android.content.Context; 23 import android.graphics.*; 24 import android.graphics.utils.*; 25 import android.os.Bundle; 26 import android.os.SystemClock; 27 import android.view.*; 28 29 public class GraphicsLab extends Activity { 30 public GraphicsLab() {} 31 32 private int mCurrView = 1; 33 34 public void onCreate(Bundle icicle) { 35 super.onCreate(icicle); 36 setContentView(new SampleView(this)); 37 // setTitle("Graphics Lab"); 38 } 39 40 @Override 41 public boolean onKeyDown(int keyCode, KeyEvent event) { 42 switch(keyCode) { 43 case KeyEvent.KEYCODE_DPAD_CENTER: 44 if (mCurrView == 1) { 45 setContentView(new SampleView2(this)); 46 mCurrView = 2; 47 } else { 48 setContentView(new SampleView(this)); 49 mCurrView = 1; 50 } 51 } 52 return super.onKeyDown(keyCode, event); 53 } 54 55 private static class SampleView2 extends View { 56 private static final int ROWS = 16; 57 private static final int COLS = 16; 58 private static final int UNSTRETCH_MSEC = 250; 59 60 private Interpolator mInterp; 61 private BoundaryPatch mPatch; 62 private float[] mCubics; 63 private float[] mOrig = new float[24]; 64 private Paint mPaint0; 65 private Paint mPaint1; 66 private int mCurrIndex = -1; 67 private float mPrevX; 68 private float mPrevY; 69 70 public SampleView2(Context context) { 71 super(context); 72 setFocusable(true); 73 74 Bitmap bm = BitmapFactory.decodeResource(getResources(), 75 R.drawable.news_img); 76 77 mPatch = new BoundaryPatch(); 78 mPatch.setTexture(bm); 79 80 float unit = 90; 81 mCubics = new float[] { 82 0, 0, 1, 0, 2, 0, 83 3, 0, 3, 1, 3, 2, 84 3, 3, 2, 3, 1, 3, 85 0, 3, 0, 2, 0, 1 86 }; 87 for (int i = 0; i < 24; i++) { 88 mCubics[i] *= 90; 89 mCubics[i] += 20; 90 } 91 rebuildPatch(); 92 93 mPaint0 = new Paint(); 94 mPaint0.setAntiAlias(true); 95 mPaint0.setStrokeWidth(12); 96 mPaint0.setStrokeCap(Paint.Cap.ROUND); 97 mPaint1 = new Paint(mPaint0); 98 mPaint1.setColor(0xFFFFFFFF); 99 mPaint1.setStrokeWidth(10); 100 } 101 102 @Override 103 protected void onSizeChanged(int nw, int nh, int ow, int oh) { 104 float[] pts = mCubics; 105 float x1 = nw*0.3333f; 106 float y1 = nh*0.3333f; 107 float x2 = nw*0.6667f; 108 float y2 = nh*0.6667f; 109 pts[0*2+0] = 0; pts[0*2+1] = 0; 110 pts[1*2+0] = x1; pts[1*2+1] = 0; 111 pts[2*2+0] = x2; pts[2*2+1] = 0; 112 113 pts[3*2+0] = nw; pts[3*2+1] = 0; 114 pts[4*2+0] = nw; pts[4*2+1] = y1; 115 pts[5*2+0] = nw; pts[5*2+1] = y2; 116 117 pts[6*2+0] = nw; pts[6*2+1] = nh; 118 pts[7*2+0] = x2; pts[7*2+1] = nh; 119 pts[8*2+0] = x1; pts[8*2+1] = nh; 120 121 pts[9*2+0] = 0; pts[9*2+1] = nh; 122 pts[10*2+0] = 0; pts[10*2+1] = y2; 123 pts[11*2+0] = 0; pts[11*2+1] = y1; 124 125 System.arraycopy(pts, 0, mOrig, 0, 24); 126 rebuildPatch(); 127 } 128 129 @Override protected void onDraw(Canvas canvas) { 130 if (mInterp != null) { 131 int now = (int)SystemClock.uptimeMillis(); 132 Interpolator.Result result = mInterp.timeToValues(now, mCubics); 133 if (result != Interpolator.Result.NORMAL) { 134 mInterp = null; 135 } else { 136 invalidate(); 137 } 138 rebuildPatch(); 139 } 140 mPatch.draw(canvas); 141 } 142 143 private void rebuildPatch() { 144 mPatch.setCubicBoundary(mCubics, 0, ROWS, COLS); 145 } 146 147 @Override public boolean onTouchEvent(MotionEvent event) { 148 float x = event.getX(); 149 float y = event.getY(); 150 switch (event.getAction()) { 151 case MotionEvent.ACTION_DOWN: 152 System.arraycopy(mOrig, 0, mCubics, 0, 24); 153 mPrevX = x; 154 mPrevY = y; 155 break; 156 case MotionEvent.ACTION_MOVE: { 157 float scale = 1.5f; 158 float dx = (x - mPrevX) * scale; 159 float dy = (y - mPrevY) * scale; 160 int index; 161 162 if (dx < 0) { 163 index = 10; 164 } else { 165 index = 4; 166 } 167 mCubics[index*2 + 0] = mOrig[index*2 + 0] + dx; 168 mCubics[index*2 + 2] = mOrig[index*2 + 2] + dx; 169 170 if (dy < 0) { 171 index = 1; 172 } else { 173 index = 7; 174 } 175 mCubics[index*2 + 1] = mOrig[index*2 + 1] + dy; 176 mCubics[index*2 + 3] = mOrig[index*2 + 3] + dy; 177 178 rebuildPatch(); 179 invalidate(); 180 } break; 181 case MotionEvent.ACTION_UP: 182 case MotionEvent.ACTION_CANCEL: { 183 int start = (int)SystemClock.uptimeMillis(); 184 mInterp = new Interpolator(24); 185 mInterp.setKeyFrame(0, start, mCubics, 186 new float[] { 0, 0.5f, 0.5f, 1 }); 187 mInterp.setKeyFrame(1, start + UNSTRETCH_MSEC, mOrig 188 ); 189 invalidate(); 190 } break; 191 } 192 return true; 193 } 194 } 195 196 private static class SampleView extends View { 197 private static final int ROWS = 16; 198 private static final int COLS = 16; 199 200 private BoundaryPatch mPatch; 201 private float[] mCubics; 202 private float[] mOrig = new float[24]; 203 private Paint mPaint0; 204 private Paint mPaint1; 205 private int mCurrIndex = -1; 206 private float mPrevX; 207 private float mPrevY; 208 209 public SampleView(Context context) { 210 super(context); 211 setFocusable(true); 212 213 Bitmap bm = BitmapFactory.decodeResource(getResources(), 214 R.drawable.beach); 215 216 mPatch = new BoundaryPatch(); 217 mPatch.setTexture(bm); 218 219 float unit = 90; 220 mCubics = new float[] { 221 0, 0, 1, 0, 2, 0, 222 3, 0, 3, 1, 3, 2, 223 3, 3, 2, 3, 1, 3, 224 0, 3, 0, 2, 0, 1 225 }; 226 for (int i = 0; i < 24; i++) { 227 mCubics[i] *= 90; 228 mCubics[i] += 20; 229 } 230 rebuildPatch(); 231 232 mPaint0 = new Paint(); 233 mPaint0.setAntiAlias(true); 234 mPaint0.setStrokeWidth(12); 235 mPaint0.setStrokeCap(Paint.Cap.ROUND); 236 mPaint1 = new Paint(mPaint0); 237 mPaint1.setColor(0xFFFFFFFF); 238 mPaint1.setStrokeWidth(10); 239 } 240 241 @Override protected void onDraw(Canvas canvas) { 242 canvas.drawColor(0xFFCCCCCC); 243 mPatch.draw(canvas); 244 canvas.drawPoints(mCubics, mPaint0); 245 canvas.drawPoints(mCubics, mPaint1); 246 } 247 248 private void rebuildPatch() { 249 mPatch.setCubicBoundary(mCubics, 0, ROWS, COLS); 250 } 251 252 private int findPtIndex(float x, float y) { 253 final float tolerance = 25; 254 final float[] pts = mCubics; 255 for (int i = 0; i < (pts.length >> 1); i++) { 256 if (Math.abs(pts[i*2 + 0] - x) <= tolerance && 257 Math.abs(pts[i*2 + 1] - y) <= tolerance) { 258 return i*2; 259 } 260 } 261 return -1; 262 } 263 264 private void offsetPts(float dx, float dy) { 265 final float[] pts = mCubics; 266 for (int i = 0; i < (pts.length >> 1); i++) { 267 pts[i*2 + 0] += dx; 268 pts[i*2 + 1] += dy; 269 } 270 rebuildPatch(); 271 } 272 273 @Override public boolean onTouchEvent(MotionEvent event) { 274 float x = event.getX(); 275 float y = event.getY(); 276 switch (event.getAction()) { 277 case MotionEvent.ACTION_DOWN: 278 mCurrIndex = findPtIndex(x, y); 279 mPrevX = x; 280 mPrevY = y; 281 break; 282 case MotionEvent.ACTION_MOVE: 283 if (mCurrIndex >= 0) { 284 mCubics[mCurrIndex + 0] = x; 285 mCubics[mCurrIndex + 1] = y; 286 mPatch.setCubicBoundary(mCubics, 0, ROWS, COLS); 287 } else { 288 offsetPts(x - mPrevX, y - mPrevY); 289 mPrevX = x; 290 mPrevY = y; 291 } 292 invalidate(); 293 break; 294 } 295 return true; 296 } 297 } 298 } 299 300