ImageDraw.java revision a4f38c0f8f70c998391780b672eea5d5e49277c7
1
2package com.android.gallery3d.filtershow.imageshow;
3
4import android.content.Context;
5import android.content.res.Resources;
6import android.graphics.Bitmap;
7import android.graphics.BitmapFactory;
8import android.graphics.BitmapShader;
9import android.graphics.Canvas;
10import android.graphics.Color;
11import android.graphics.Matrix;
12import android.graphics.Paint;
13import android.graphics.PorterDuff;
14import android.graphics.PorterDuffColorFilter;
15import android.graphics.RectF;
16import android.graphics.Shader;
17import android.graphics.drawable.Drawable;
18import android.graphics.drawable.NinePatchDrawable;
19import android.os.Handler;
20import android.util.AttributeSet;
21import android.view.MotionEvent;
22
23import com.android.gallery3d.R;
24import com.android.gallery3d.filtershow.editors.EditorDraw;
25import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation;
26import com.android.gallery3d.filtershow.filters.ImageFilterDraw;
27
28public class ImageDraw extends ImageShow {
29
30    private static final String LOGTAG = "ImageDraw";
31    private int mCurrentColor = Color.RED;
32    final static float INITAL_STROKE_RADIUS = 40;
33    private float mCurrentSize = INITAL_STROKE_RADIUS;
34    private byte mType = 0;
35    private FilterDrawRepresentation mFRep;
36    private EditorDraw mEditorDraw;
37    private long mTimeout;
38    private Paint mCheckerdPaint = makeCheckedPaint();
39    private Paint mShadowPaint = new Paint();
40    private Paint mIconPaint = new Paint();
41    private Paint mBorderPaint = new Paint();
42    private Handler mHandler;
43    private FilterDrawRepresentation.StrokeData mTmpStrokData =
44            new FilterDrawRepresentation.StrokeData();
45    private Bitmap mBitmap;
46    private float mDisplayRound;
47    private float mDisplayBorder;
48    private int DISPLAY_TIME = 500;
49    private Matrix mRotateToScreen = new Matrix();
50    private Matrix mToOrig;
51    private int mBorderColor;
52    private int mBorderShadowSize;
53    private NinePatchDrawable mShadow;
54
55    Runnable mUpdateRunnable = new Runnable() {
56        @Override
57        public void run() {
58           invalidate();
59        }
60    };
61
62
63    public ImageDraw(Context context, AttributeSet attrs) {
64        super(context, attrs);
65        resetParameter();
66        setupConstants(context);
67        setupTimer();
68    }
69
70    public ImageDraw(Context context) {
71        super(context);
72        resetParameter();
73        setupConstants(context);
74        setupTimer();
75    }
76
77    private void setupConstants(Context context){
78        Resources res = context.getResources();
79        mDisplayRound = res.getDimensionPixelSize(R.dimen.draw_rect_round);
80        mDisplayBorder = res.getDimensionPixelSize(R.dimen.draw_rect_border);
81        mBorderShadowSize = res.getDimensionPixelSize(R.dimen.draw_rect_shadow);
82        float edge = res.getDimensionPixelSize(R.dimen.draw_rect_border_edge);
83
84        mBorderColor = res.getColor(R.color.draw_rect_border);
85        mBorderPaint.setColor(mBorderColor);
86        mBorderPaint.setStyle(Paint.Style.STROKE);
87        mBorderPaint.setStrokeWidth(edge);
88        mShadowPaint.setStyle(Paint.Style.FILL);
89        mShadowPaint.setColor(Color.BLACK);
90        mShadowPaint.setShadowLayer(mBorderShadowSize,mBorderShadowSize,
91                mBorderShadowSize,Color.BLACK);
92        mShadow = (NinePatchDrawable) res.getDrawable(R.drawable.geometry_shadow);
93    }
94
95    public void setEditor(EditorDraw editorDraw) {
96        mEditorDraw = editorDraw;
97    }
98
99    public void setFilterDrawRepresentation(FilterDrawRepresentation fr) {
100        mFRep = fr;
101        mTmpStrokData =
102                new FilterDrawRepresentation.StrokeData();
103    }
104
105    public Drawable getIcon(Context context) {
106
107        return null;
108    }
109
110    @Override
111    public void resetParameter() {
112        if (mFRep != null) {
113            mFRep.clear();
114        }
115    }
116
117    public void setColor(int color) {
118        mCurrentColor = color;
119    }
120
121    public void setSize(int size) {
122        mCurrentSize = size;
123    }
124
125    public void setStyle(byte style) {
126        mType = (byte) (style % ImageFilterDraw.NUMBER_OF_STYLES);
127    }
128
129    public int getStyle() {
130        return mType;
131    }
132
133    public int getSize() {
134        return (int) mCurrentSize;
135    }
136
137    float[] mTmpPoint = new float[2]; // so we do not malloc
138    @Override
139    public boolean onTouchEvent(MotionEvent event) {
140        if (event.getPointerCount() > 1) {
141            boolean ret = super.onTouchEvent(event);
142            if (mFRep.getCurrentDrawing() != null) {
143                mFRep.clearCurrentSection();
144                mEditorDraw.commitLocalRepresentation();
145            }
146            return ret;
147        }
148        if (event.getAction() != MotionEvent.ACTION_DOWN) {
149            if (mFRep.getCurrentDrawing() == null) {
150                return super.onTouchEvent(event);
151            }
152        }
153
154        if (event.getAction() == MotionEvent.ACTION_DOWN) {
155            calcScreenMapping();
156            mTmpPoint[0] = event.getX();
157            mTmpPoint[1] = event.getY();
158            mToOrig.mapPoints(mTmpPoint);
159            mFRep.startNewSection( mTmpPoint[0], mTmpPoint[1]);
160        }
161
162        if (event.getAction() == MotionEvent.ACTION_MOVE) {
163
164            int historySize = event.getHistorySize();
165            for (int h = 0; h < historySize; h++) {
166                int p = 0;
167                {
168                    mTmpPoint[0] = event.getHistoricalX(p, h);
169                    mTmpPoint[1] = event.getHistoricalY(p, h);
170                    mToOrig.mapPoints(mTmpPoint);
171                    mFRep.addPoint(mTmpPoint[0], mTmpPoint[1]);
172                }
173            }
174        }
175
176        if (event.getAction() == MotionEvent.ACTION_UP) {
177            mTmpPoint[0] = event.getX();
178            mTmpPoint[1] = event.getY();
179            mToOrig.mapPoints(mTmpPoint);
180            mFRep.endSection(mTmpPoint[0], mTmpPoint[1]);
181        }
182        mEditorDraw.commitLocalRepresentation();
183        invalidate();
184        return true;
185    }
186
187    private void calcScreenMapping() {
188        mToOrig = getScreenToImageMatrix(true);
189        mToOrig.invert(mRotateToScreen);
190    }
191
192    private static Paint makeCheckedPaint(){
193        int[] colors = new int[16 * 16];
194        for (int i = 0; i < colors.length; i++) {
195            int y = i / (16 * 8);
196            int x = (i / 8) % 2;
197            colors[i] = (x == y) ? 0xFF777777 : 0xFF222222;
198        }
199        Bitmap bitmap = Bitmap.createBitmap(colors, 16, 16, Bitmap.Config.ARGB_8888);
200        BitmapShader bs = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
201        Paint p = new Paint();
202        p.setShader(bs);
203        return p;
204    }
205
206    private void setupTimer() {
207        mHandler = new Handler(getActivity().getMainLooper());
208    }
209
210    private void scheduleWakeup(int delay) {
211        mHandler.removeCallbacks(mUpdateRunnable);
212        mHandler.postDelayed(mUpdateRunnable, delay);
213    }
214
215    public Bitmap getBrush(int brushid) {
216        Bitmap bitmap;
217        BitmapFactory.Options opt = new BitmapFactory.Options();
218        opt.inPreferredConfig = Bitmap.Config.ALPHA_8;
219        bitmap = BitmapFactory.decodeResource(getActivity().getResources(), brushid, opt);
220        bitmap = bitmap.extractAlpha();
221
222        return bitmap;
223    }
224
225    public Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) {
226        Matrix m = new Matrix();
227        m.setScale(dstWidth / (float) src.getWidth(), dstHeight / (float) src.getHeight());
228        Bitmap result = Bitmap.createBitmap(dstWidth, dstHeight, src.getConfig());
229        Canvas canvas = new Canvas(result);
230
231        Paint paint = new Paint();
232        paint.setFilterBitmap(filter);
233        canvas.drawBitmap(src, m, paint);
234
235        return result;
236
237    }
238
239    public void displayDrawLook() {
240        if (mFRep == null) {
241            return;
242        }
243        int color = mTmpStrokData.mColor;
244        byte type = mTmpStrokData.mType;
245        float radius = mTmpStrokData.mRadius;
246        mFRep.fillStrokeParameters(mTmpStrokData);
247        if (type != mTmpStrokData.mType || radius != mTmpStrokData.mRadius) {
248            mBitmap = getBrush(mEditorDraw.getBrushIcon(mTmpStrokData.mType));
249            float size = mRotateToScreen.mapRadius(mTmpStrokData.mRadius) * 2;
250            mBitmap = createScaledBitmap(mBitmap, (int) size, (int) size, true);
251        }
252
253        if (color == mTmpStrokData.mColor
254                && type == mTmpStrokData.mType
255                && radius == mTmpStrokData.mRadius) {
256            return;
257        }
258
259        mTimeout = DISPLAY_TIME + System.currentTimeMillis();
260        scheduleWakeup(DISPLAY_TIME);
261    }
262
263    public void drawLook(Canvas canvas) {
264        if (mFRep == null) {
265            return;
266        }
267        int cw = canvas.getWidth();
268        int ch = canvas.getHeight();
269        int centerx = cw / 2;
270        int centery = ch / 2;
271
272        mFRep.fillStrokeParameters(mTmpStrokData);
273        mIconPaint.setAntiAlias(true);
274        mIconPaint.setColor(mTmpStrokData.mColor);
275
276        mIconPaint.setColorFilter(new PorterDuffColorFilter(mTmpStrokData.mColor,
277                PorterDuff.Mode.MULTIPLY));
278        float rad = mRotateToScreen.mapRadius(mTmpStrokData.mRadius);
279        RectF rec = new RectF();
280        rec.set(centerx - mDisplayBorder - rad,
281                centery - mDisplayBorder - rad,
282                centerx + mDisplayBorder + rad,
283                centery + mDisplayBorder + rad);
284        mShadow.setBounds((int) (mBorderShadowSize + rec.left),
285                (int) (mBorderShadowSize + rec.top),
286                (int) (mBorderShadowSize + rec.right),
287                (int) (mBorderShadowSize + rec.bottom));
288        mShadow.draw(canvas);
289        canvas.drawRoundRect(rec, mDisplayRound, mDisplayRound, mCheckerdPaint);
290        canvas.drawRoundRect(rec, mDisplayRound, mDisplayRound, mBorderPaint);
291        canvas.drawBitmap(mBitmap,
292                centerx - mBitmap.getWidth() / 2,
293                centery - mBitmap.getHeight() / 2, mIconPaint);
294    }
295
296    @Override
297    public void onDraw(Canvas canvas) {
298        super.onDraw(canvas);
299        calcScreenMapping();
300        if (System.currentTimeMillis() < mTimeout) {
301            drawLook(canvas);
302        }
303    }
304
305}
306