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 63 public EclipseControl(Context context) { 64 mSliderColor = Color.WHITE; 65 } 66 67 public void setRadius(float x, float y) { 68 mRadiusX = x; 69 mRadiusY = y; 70 } 71 72 public void setCenter(float x, float y) { 73 mCenterX = x; 74 mCenterY = y; 75 } 76 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 102 public void setScrImageInfo(Matrix scrToImg, Rect imageBounds) { 103 mScrToImg = scrToImg; 104 mImageBounds = new Rect(imageBounds); 105 } 106 107 private boolean centerIsOutside(float x1, float y1) { 108 return (!mImageBounds.contains((int) x1, (int) y1)); 109 } 110 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 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 191 public void paintGrayPoint(Canvas canvas, float x, float y) { 192 if (x == Float.NaN) { 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 208 public void paintPoint(Canvas canvas, float x, float y) { 209 if (x == Float.NaN) { 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 225 void paintRadius(Canvas canvas, float cx, float cy, float rx, float ry) { 226 if (cx == Float.NaN) { 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 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 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 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 307 public boolean isUndefined() { 308 return Float.isNaN(mCenterX); 309 } 310 311 public void setShowReshapeHandles(boolean showReshapeHandles) { 312 this.mShowReshapeHandles = showReshapeHandles; 313 } 314 } 315