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