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.example.android.apis.graphics; 18 19 import android.app.Activity; 20 import android.content.Context; 21 import android.graphics.*; 22 import android.os.Bundle; 23 import android.view.Menu; 24 import android.view.MenuItem; 25 import android.view.MotionEvent; 26 import android.view.View; 27 28 public class FingerPaint extends GraphicsActivity 29 implements ColorPickerDialog.OnColorChangedListener { 30 31 @Override onCreate(Bundle savedInstanceState)32 protected void onCreate(Bundle savedInstanceState) { 33 super.onCreate(savedInstanceState); 34 setContentView(new MyView(this)); 35 36 mPaint = new Paint(); 37 mPaint.setAntiAlias(true); 38 mPaint.setDither(true); 39 mPaint.setColor(0xFFFF0000); 40 mPaint.setStyle(Paint.Style.STROKE); 41 mPaint.setStrokeJoin(Paint.Join.ROUND); 42 mPaint.setStrokeCap(Paint.Cap.ROUND); 43 mPaint.setStrokeWidth(12); 44 45 mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 46 0.4f, 6, 3.5f); 47 48 mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL); 49 } 50 51 private Paint mPaint; 52 private MaskFilter mEmboss; 53 private MaskFilter mBlur; 54 colorChanged(int color)55 public void colorChanged(int color) { 56 mPaint.setColor(color); 57 } 58 59 public class MyView extends View { 60 61 private static final float MINP = 0.25f; 62 private static final float MAXP = 0.75f; 63 64 private Bitmap mBitmap; 65 private Canvas mCanvas; 66 private Path mPath; 67 private Paint mBitmapPaint; 68 MyView(Context c)69 public MyView(Context c) { 70 super(c); 71 72 mBitmap = Bitmap.createBitmap(320, 480, Bitmap.Config.ARGB_8888); 73 mCanvas = new Canvas(mBitmap); 74 mPath = new Path(); 75 mBitmapPaint = new Paint(Paint.DITHER_FLAG); 76 } 77 78 @Override onSizeChanged(int w, int h, int oldw, int oldh)79 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 80 super.onSizeChanged(w, h, oldw, oldh); 81 } 82 83 @Override onDraw(Canvas canvas)84 protected void onDraw(Canvas canvas) { 85 canvas.drawColor(0xFFAAAAAA); 86 87 canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); 88 89 canvas.drawPath(mPath, mPaint); 90 } 91 92 private float mX, mY; 93 private static final float TOUCH_TOLERANCE = 4; 94 touch_start(float x, float y)95 private void touch_start(float x, float y) { 96 mPath.reset(); 97 mPath.moveTo(x, y); 98 mX = x; 99 mY = y; 100 } touch_move(float x, float y)101 private void touch_move(float x, float y) { 102 float dx = Math.abs(x - mX); 103 float dy = Math.abs(y - mY); 104 if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { 105 mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2); 106 mX = x; 107 mY = y; 108 } 109 } touch_up()110 private void touch_up() { 111 mPath.lineTo(mX, mY); 112 // commit the path to our offscreen 113 mCanvas.drawPath(mPath, mPaint); 114 // kill this so we don't double draw 115 mPath.reset(); 116 } 117 118 @Override onTouchEvent(MotionEvent event)119 public boolean onTouchEvent(MotionEvent event) { 120 float x = event.getX(); 121 float y = event.getY(); 122 123 switch (event.getAction()) { 124 case MotionEvent.ACTION_DOWN: 125 touch_start(x, y); 126 invalidate(); 127 break; 128 case MotionEvent.ACTION_MOVE: 129 touch_move(x, y); 130 invalidate(); 131 break; 132 case MotionEvent.ACTION_UP: 133 touch_up(); 134 invalidate(); 135 break; 136 } 137 return true; 138 } 139 } 140 141 private static final int COLOR_MENU_ID = Menu.FIRST; 142 private static final int EMBOSS_MENU_ID = Menu.FIRST + 1; 143 private static final int BLUR_MENU_ID = Menu.FIRST + 2; 144 private static final int ERASE_MENU_ID = Menu.FIRST + 3; 145 private static final int SRCATOP_MENU_ID = Menu.FIRST + 4; 146 147 @Override onCreateOptionsMenu(Menu menu)148 public boolean onCreateOptionsMenu(Menu menu) { 149 super.onCreateOptionsMenu(menu); 150 151 menu.add(0, COLOR_MENU_ID, 0, "Color").setShortcut('3', 'c'); 152 menu.add(0, EMBOSS_MENU_ID, 0, "Emboss").setShortcut('4', 's'); 153 menu.add(0, BLUR_MENU_ID, 0, "Blur").setShortcut('5', 'z'); 154 menu.add(0, ERASE_MENU_ID, 0, "Erase").setShortcut('5', 'z'); 155 menu.add(0, SRCATOP_MENU_ID, 0, "SrcATop").setShortcut('5', 'z'); 156 157 /**** Is this the mechanism to extend with filter effects? 158 Intent intent = new Intent(null, getIntent().getData()); 159 intent.addCategory(Intent.CATEGORY_ALTERNATIVE); 160 menu.addIntentOptions( 161 Menu.ALTERNATIVE, 0, 162 new ComponentName(this, NotesList.class), 163 null, intent, 0, null); 164 *****/ 165 return true; 166 } 167 168 @Override onPrepareOptionsMenu(Menu menu)169 public boolean onPrepareOptionsMenu(Menu menu) { 170 super.onPrepareOptionsMenu(menu); 171 return true; 172 } 173 174 @Override onOptionsItemSelected(MenuItem item)175 public boolean onOptionsItemSelected(MenuItem item) { 176 mPaint.setXfermode(null); 177 mPaint.setAlpha(0xFF); 178 179 switch (item.getItemId()) { 180 case COLOR_MENU_ID: 181 new ColorPickerDialog(this, this, mPaint.getColor()).show(); 182 return true; 183 case EMBOSS_MENU_ID: 184 if (mPaint.getMaskFilter() != mEmboss) { 185 mPaint.setMaskFilter(mEmboss); 186 } else { 187 mPaint.setMaskFilter(null); 188 } 189 return true; 190 case BLUR_MENU_ID: 191 if (mPaint.getMaskFilter() != mBlur) { 192 mPaint.setMaskFilter(mBlur); 193 } else { 194 mPaint.setMaskFilter(null); 195 } 196 return true; 197 case ERASE_MENU_ID: 198 mPaint.setXfermode(new PorterDuffXfermode( 199 PorterDuff.Mode.CLEAR)); 200 return true; 201 case SRCATOP_MENU_ID: 202 mPaint.setXfermode(new PorterDuffXfermode( 203 PorterDuff.Mode.SRC_ATOP)); 204 mPaint.setAlpha(0x80); 205 return true; 206 } 207 return super.onOptionsItemSelected(item); 208 } 209 } 210