1 /* 2 * Copyright (C) 2012 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.gallery3d.filtershow.imageshow; 18 19 import android.content.Context; 20 import android.graphics.Canvas; 21 import android.graphics.Color; 22 import android.graphics.Matrix; 23 import android.graphics.Paint; 24 import android.graphics.RadialGradient; 25 import android.graphics.Rect; 26 import android.graphics.RectF; 27 import android.graphics.Shader; 28 import android.util.Log; 29 30 import com.android.gallery3d.R; 31 32 public class EclipseControl { 33 private float mCenterX = Float.NaN; 34 private float mCenterY = 0; 35 private float mRadiusX = 200; 36 private float mRadiusY = 300; 37 private static int MIN_TOUCH_DIST = 80;// should be a resource & in dips 38 private static String LOGTAG = "EclipseControl"; 39 private float[] handlex = new float[9]; 40 private float[] handley = new float[9]; 41 private int mSliderColor; 42 private int mCenterDotSize = 40; 43 private float mDownX; 44 private float mDownY; 45 private float mDownCenterX; 46 private float mDownCenterY; 47 private float mDownRadiusX; 48 private float mDownRadiusY; 49 private Matrix mScrToImg; 50 51 private boolean mShowReshapeHandles = true; 52 public final static int HAN_CENTER = 0; 53 public final static int HAN_NORTH = 7; 54 public final static int HAN_NE = 8; 55 public final static int HAN_EAST = 1; 56 public final static int HAN_SE = 2; 57 public final static int HAN_SOUTH = 3; 58 public final static int HAN_SW = 4; 59 public final static int HAN_WEST = 5; 60 public final static int HAN_NW = 6; 61 private Rect mImageBounds; 62 EclipseControl(Context context)63 public EclipseControl(Context context) { 64 mSliderColor = Color.WHITE; 65 } 66 setRadius(float x, float y)67 public void setRadius(float x, float y) { 68 mRadiusX = x; 69 mRadiusY = y; 70 } 71 setCenter(float x, float y)72 public void setCenter(float x, float y) { 73 mCenterX = x; 74 mCenterY = y; 75 } 76 getCloseHandle(float x, float y)77 public int getCloseHandle(float x, float y) { 78 float min = Float.MAX_VALUE; 79 int handle = -1; 80 for (int i = 0; i < handlex.length; i++) { 81 float dx = handlex[i] - x; 82 float dy = handley[i] - y; 83 float dist = dx * dx + dy * dy; 84 if (dist < min) { 85 min = dist; 86 handle = i; 87 } 88 } 89 90 if (min < MIN_TOUCH_DIST * MIN_TOUCH_DIST) { 91 return handle; 92 } 93 for (int i = 0; i < handlex.length; i++) { 94 float dx = handlex[i] - x; 95 float dy = handley[i] - y; 96 float dist = (float) Math.sqrt(dx * dx + dy * dy); 97 } 98 99 return -1; 100 } 101 setScrImageInfo(Matrix scrToImg, Rect imageBounds)102 public void setScrImageInfo(Matrix scrToImg, Rect imageBounds) { 103 mScrToImg = scrToImg; 104 mImageBounds = new Rect(imageBounds); 105 } 106 centerIsOutside(float x1, float y1)107 private boolean centerIsOutside(float x1, float y1) { 108 return (!mImageBounds.contains((int) x1, (int) y1)); 109 } 110 actionDown(float x, float y, Oval oval)111 public void actionDown(float x, float y, Oval oval) { 112 float[] point = new float[]{ 113 x, y}; 114 mScrToImg.mapPoints(point); 115 mDownX = point[0]; 116 mDownY = point[1]; 117 mDownCenterX = oval.getCenterX(); 118 mDownCenterY = oval.getCenterY(); 119 mDownRadiusX = oval.getRadiusX(); 120 mDownRadiusY = oval.getRadiusY(); 121 } 122 123 actionMove(int handle, float x, float y, Oval oval)124 public void actionMove(int handle, float x, float y, Oval oval) { 125 float[] point = new float[]{ 126 x, y}; 127 mScrToImg.mapPoints(point); 128 x = point[0]; 129 y = point[1]; 130 131 // Test if the matrix is swapping x and y 132 point[0] = 0; 133 point[1] = 1; 134 mScrToImg.mapVectors(point); 135 boolean swapxy = (point[0] > 0.0f); 136 137 int sign = 1; 138 switch (handle) { 139 case HAN_CENTER: 140 float ctrdx = mDownX - mDownCenterX; 141 float ctrdy = mDownY - mDownCenterY; 142 if (centerIsOutside(x - ctrdx, y - ctrdy)) { 143 break; 144 } 145 oval.setCenter((x - ctrdx), (y - ctrdy)); 146 // setRepresentation(mVignetteRep); 147 break; 148 case HAN_NORTH: 149 sign = -1; 150 case HAN_SOUTH: 151 if (swapxy) { 152 float raddx = mDownRadiusY - Math.abs(mDownX - mDownCenterY); 153 oval.setRadiusY(Math.abs(x - oval.getCenterY() + sign * raddx)); 154 } else { 155 float raddy = mDownRadiusY - Math.abs(mDownY - mDownCenterY); 156 oval.setRadiusY(Math.abs(y - oval.getCenterY() + sign * raddy)); 157 } 158 break; 159 case HAN_EAST: 160 sign = -1; 161 case HAN_WEST: 162 if (swapxy) { 163 float raddy = mDownRadiusX - Math.abs(mDownY - mDownCenterX); 164 oval.setRadiusX(Math.abs(y - oval.getCenterX() + sign * raddy)); 165 } else { 166 float raddx = mDownRadiusX - Math.abs(mDownX - mDownCenterX); 167 oval.setRadiusX(Math.abs(x - oval.getCenterX() - sign * raddx)); 168 } 169 break; 170 case HAN_SE: 171 case HAN_NE: 172 case HAN_SW: 173 case HAN_NW: 174 float sin45 = (float) Math.sin(45); 175 float dr = (mDownRadiusX + mDownRadiusY) * sin45; 176 float ctr_dx = mDownX - mDownCenterX; 177 float ctr_dy = mDownY - mDownCenterY; 178 float downRad = Math.abs(ctr_dx) + Math.abs(ctr_dy) - dr; 179 float rx = oval.getRadiusX(); 180 float ry = oval.getRadiusY(); 181 float r = (Math.abs(rx) + Math.abs(ry)) * sin45; 182 float dx = x - oval.getCenterX(); 183 float dy = y - oval.getCenterY(); 184 float nr = Math.abs(Math.abs(dx) + Math.abs(dy) - downRad); 185 oval.setRadius((rx * nr / r), (ry * nr / r)); 186 187 break; 188 } 189 } 190 paintGrayPoint(Canvas canvas, float x, float y)191 public void paintGrayPoint(Canvas canvas, float x, float y) { 192 if (Float.isNaN(x)) { 193 return; 194 } 195 196 Paint paint = new Paint(); 197 198 paint.setStyle(Paint.Style.FILL); 199 paint.setColor(Color.BLUE); 200 int[] colors3 = new int[]{ 201 Color.GRAY, Color.LTGRAY, 0x66000000, 0}; 202 RadialGradient g = new RadialGradient(x, y, mCenterDotSize, colors3, new float[]{ 203 0, .3f, .31f, 1}, Shader.TileMode.CLAMP); 204 paint.setShader(g); 205 canvas.drawCircle(x, y, mCenterDotSize, paint); 206 } 207 paintPoint(Canvas canvas, float x, float y)208 public void paintPoint(Canvas canvas, float x, float y) { 209 if (Float.isNaN(x)) { 210 return; 211 } 212 213 Paint paint = new Paint(); 214 215 paint.setStyle(Paint.Style.FILL); 216 paint.setColor(Color.BLUE); 217 int[] colors3 = new int[]{ 218 mSliderColor, mSliderColor, 0x66000000, 0}; 219 RadialGradient g = new RadialGradient(x, y, mCenterDotSize, colors3, new float[]{ 220 0, .3f, .31f, 1}, Shader.TileMode.CLAMP); 221 paint.setShader(g); 222 canvas.drawCircle(x, y, mCenterDotSize, paint); 223 } 224 paintRadius(Canvas canvas, float cx, float cy, float rx, float ry)225 void paintRadius(Canvas canvas, float cx, float cy, float rx, float ry) { 226 if (Float.isNaN(cx)) { 227 return; 228 } 229 int mSliderColor = 0xFF33B5E5; 230 Paint paint = new Paint(); 231 RectF rect = new RectF(cx - rx, cy - ry, cx + rx, cy + ry); 232 paint.setAntiAlias(true); 233 paint.setStyle(Paint.Style.STROKE); 234 paint.setStrokeWidth(6); 235 paint.setColor(Color.BLACK); 236 paintOvallines(canvas, rect, paint, cx, cy, rx, ry); 237 238 paint.setStrokeWidth(3); 239 paint.setColor(Color.WHITE); 240 paintOvallines(canvas, rect, paint, cx, cy, rx, ry); 241 } 242 paintOvallines( Canvas canvas, RectF rect, Paint paint, float cx, float cy, float rx, float ry)243 public void paintOvallines( 244 Canvas canvas, RectF rect, Paint paint, float cx, float cy, float rx, float ry) { 245 canvas.drawOval(rect, paint); 246 float da = 4; 247 float arclen = da + da; 248 if (mShowReshapeHandles) { 249 paint.setStyle(Paint.Style.STROKE); 250 251 for (int i = 0; i < 361; i += 90) { 252 float dx = rx + 10; 253 float dy = ry + 10; 254 rect.left = cx - dx; 255 rect.top = cy - dy; 256 rect.right = cx + dx; 257 rect.bottom = cy + dy; 258 canvas.drawArc(rect, i - da, arclen, false, paint); 259 dx = rx - 10; 260 dy = ry - 10; 261 rect.left = cx - dx; 262 rect.top = cy - dy; 263 rect.right = cx + dx; 264 rect.bottom = cy + dy; 265 canvas.drawArc(rect, i - da, arclen, false, paint); 266 } 267 } 268 da *= 2; 269 paint.setStyle(Paint.Style.FILL); 270 271 for (int i = 45; i < 361; i += 90) { 272 double angle = Math.PI * i / 180.; 273 float x = cx + (float) (rx * Math.cos(angle)); 274 float y = cy + (float) (ry * Math.sin(angle)); 275 canvas.drawRect(x - da, y - da, x + da, y + da, paint); 276 } 277 paint.setStyle(Paint.Style.STROKE); 278 rect.left = cx - rx; 279 rect.top = cy - ry; 280 rect.right = cx + rx; 281 rect.bottom = cy + ry; 282 } 283 fillHandles(Canvas canvas, float cx, float cy, float rx, float ry)284 public void fillHandles(Canvas canvas, float cx, float cy, float rx, float ry) { 285 handlex[0] = cx; 286 handley[0] = cy; 287 int k = 1; 288 289 for (int i = 0; i < 360; i += 45) { 290 double angle = Math.PI * i / 180.; 291 292 float x = cx + (float) (rx * Math.cos(angle)); 293 float y = cy + (float) (ry * Math.sin(angle)); 294 handlex[k] = x; 295 handley[k] = y; 296 297 k++; 298 } 299 } 300 draw(Canvas canvas)301 public void draw(Canvas canvas) { 302 paintRadius(canvas, mCenterX, mCenterY, mRadiusX, mRadiusY); 303 fillHandles(canvas, mCenterX, mCenterY, mRadiusX, mRadiusY); 304 paintPoint(canvas, mCenterX, mCenterY); 305 } 306 isUndefined()307 public boolean isUndefined() { 308 return Float.isNaN(mCenterX); 309 } 310 setShowReshapeHandles(boolean showReshapeHandles)311 public void setShowReshapeHandles(boolean showReshapeHandles) { 312 this.mShowReshapeHandles = showReshapeHandles; 313 } 314 } 315