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