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 17package com.android.gallery3d.filtershow.imageshow; 18 19import android.content.Context; 20import android.content.res.Resources; 21import android.graphics.Canvas; 22import android.graphics.Color; 23import android.graphics.DashPathEffect; 24import android.graphics.Matrix; 25import android.graphics.Paint; 26import android.graphics.RadialGradient; 27import android.graphics.Rect; 28import android.graphics.Shader; 29 30import com.android.gallery3d.R; 31 32public class GradControl { 33 private float mPoint1X = Float.NaN; // used to flag parameters have not been set 34 private float mPoint1Y = 0; 35 private float mPoint2X = 200; 36 private float mPoint2Y = 300; 37 private int mMinTouchDist = 80;// should be a resource & in dips 38 39 private float[] handlex = new float[3]; 40 private float[] handley = new float[3]; 41 private int mSliderColor; 42 private int mCenterDotSize; 43 private float mDownX; 44 private float mDownY; 45 private float mDownPoint1X; 46 private float mDownPoint1Y; 47 private float mDownPoint2X; 48 private float mDownPoint2Y; 49 Rect mImageBounds; 50 int mImageHeight; 51 private Matrix mScrToImg; 52 Paint mPaint = new Paint(); 53 DashPathEffect mDash = new DashPathEffect(new float[]{30, 30}, 0); 54 private boolean mShowReshapeHandles = true; 55 public final static int HAN_CENTER = 0; 56 public final static int HAN_NORTH = 2; 57 public final static int HAN_SOUTH = 1; 58 private int[] mPointColorPatern; 59 private int[] mGrayPointColorPatern; 60 private float[] mPointRadialPos = new float[]{0, .3f, .31f, 1}; 61 private int mLineColor; 62 private int mlineShadowColor; 63 64 public GradControl(Context context) { 65 66 Resources res = context.getResources(); 67 mCenterDotSize = (int) res.getDimension(R.dimen.gradcontrol_dot_size); 68 mMinTouchDist = (int) res.getDimension(R.dimen.gradcontrol_min_touch_dist); 69 int grayPointCenterColor = res.getColor(R.color.gradcontrol_graypoint_center); 70 int grayPointEdgeColor = res.getColor(R.color.gradcontrol_graypoint_edge); 71 int pointCenterColor = res.getColor(R.color.gradcontrol_point_center); 72 int pointEdgeColor = res.getColor(R.color.gradcontrol_point_edge); 73 int pointShadowStartColor = res.getColor(R.color.gradcontrol_point_shadow_start); 74 int pointShadowEndColor = res.getColor(R.color.gradcontrol_point_shadow_end); 75 mPointColorPatern = new int[]{ 76 pointCenterColor, pointEdgeColor, pointShadowStartColor, pointShadowEndColor}; 77 mGrayPointColorPatern = new int[]{ 78 grayPointCenterColor, grayPointEdgeColor, pointShadowStartColor, pointShadowEndColor}; 79 mSliderColor = Color.WHITE; 80 mLineColor = res.getColor(R.color.gradcontrol_line_color); 81 mlineShadowColor = res.getColor(R.color.gradcontrol_line_shadow); 82 } 83 84 public void setPoint2(float x, float y) { 85 mPoint2X = x; 86 mPoint2Y = y; 87 } 88 89 public void setPoint1(float x, float y) { 90 mPoint1X = x; 91 mPoint1Y = y; 92 } 93 94 public int getCloseHandle(float x, float y) { 95 float min = Float.MAX_VALUE; 96 int handle = -1; 97 for (int i = 0; i < handlex.length; i++) { 98 float dx = handlex[i] - x; 99 float dy = handley[i] - y; 100 float dist = dx * dx + dy * dy; 101 if (dist < min) { 102 min = dist; 103 handle = i; 104 } 105 } 106 107 if (min < mMinTouchDist * mMinTouchDist) { 108 return handle; 109 } 110 for (int i = 0; i < handlex.length; i++) { 111 float dx = handlex[i] - x; 112 float dy = handley[i] - y; 113 float dist = (float) Math.sqrt(dx * dx + dy * dy); 114 } 115 116 return -1; 117 } 118 119 public void setScrImageInfo(Matrix scrToImg, Rect imageBounds) { 120 mScrToImg = scrToImg; 121 mImageBounds = new Rect(imageBounds); 122 } 123 124 private boolean centerIsOutside(float x1, float y1, float x2, float y2) { 125 return (!mImageBounds.contains((int) ((x1 + x2) / 2), (int) ((y1 + y2) / 2))); 126 } 127 128 public void actionDown(float x, float y, Line line) { 129 float[] point = new float[]{ 130 x, y}; 131 mScrToImg.mapPoints(point); 132 mDownX = point[0]; 133 mDownY = point[1]; 134 mDownPoint1X = line.getPoint1X(); 135 mDownPoint1Y = line.getPoint1Y(); 136 mDownPoint2X = line.getPoint2X(); 137 mDownPoint2Y = line.getPoint2Y(); 138 } 139 140 public void actionMove(int handle, float x, float y, Line line) { 141 float[] point = new float[]{ 142 x, y}; 143 mScrToImg.mapPoints(point); 144 x = point[0]; 145 y = point[1]; 146 147 // Test if the matrix is swapping x and y 148 point[0] = 0; 149 point[1] = 1; 150 mScrToImg.mapVectors(point); 151 boolean swapxy = (point[0] > 0.0f); 152 153 int sign = 1; 154 155 float dx = x - mDownX; 156 float dy = y - mDownY; 157 switch (handle) { 158 case HAN_CENTER: 159 if (centerIsOutside(mDownPoint1X + dx, mDownPoint1Y + dy, 160 mDownPoint2X + dx, mDownPoint2Y + dy)) { 161 break; 162 } 163 line.setPoint1(mDownPoint1X + dx, mDownPoint1Y + dy); 164 line.setPoint2(mDownPoint2X + dx, mDownPoint2Y + dy); 165 break; 166 case HAN_SOUTH: 167 if (centerIsOutside(mDownPoint1X + dx, mDownPoint1Y + dy, 168 mDownPoint2X, mDownPoint2Y)) { 169 break; 170 } 171 line.setPoint1(mDownPoint1X + dx, mDownPoint1Y + dy); 172 break; 173 case HAN_NORTH: 174 if (centerIsOutside(mDownPoint1X, mDownPoint1Y, 175 mDownPoint2X + dx, mDownPoint2Y + dy)) { 176 break; 177 } 178 line.setPoint2(mDownPoint2X + dx, mDownPoint2Y + dy); 179 break; 180 } 181 } 182 183 public void paintGrayPoint(Canvas canvas, float x, float y) { 184 if (isUndefined()) { 185 return; 186 } 187 188 Paint paint = new Paint(); 189 paint.setStyle(Paint.Style.FILL); 190 RadialGradient g = new RadialGradient(x, y, mCenterDotSize, mGrayPointColorPatern, 191 mPointRadialPos, Shader.TileMode.CLAMP); 192 paint.setShader(g); 193 canvas.drawCircle(x, y, mCenterDotSize, paint); 194 } 195 196 public void paintPoint(Canvas canvas, float x, float y) { 197 if (isUndefined()) { 198 return; 199 } 200 201 Paint paint = new Paint(); 202 paint.setStyle(Paint.Style.FILL); 203 RadialGradient g = new RadialGradient(x, y, mCenterDotSize, mPointColorPatern, 204 mPointRadialPos, Shader.TileMode.CLAMP); 205 paint.setShader(g); 206 canvas.drawCircle(x, y, mCenterDotSize, paint); 207 } 208 209 void paintLines(Canvas canvas, float p1x, float p1y, float p2x, float p2y) { 210 if (isUndefined()) { 211 return; 212 } 213 214 mPaint.setAntiAlias(true); 215 mPaint.setStyle(Paint.Style.STROKE); 216 217 mPaint.setStrokeWidth(6); 218 mPaint.setColor(mlineShadowColor); 219 mPaint.setPathEffect(mDash); 220 paintOvallines(canvas, mPaint, p1x, p1y, p2x, p2y); 221 222 mPaint.setStrokeWidth(3); 223 mPaint.setColor(mLineColor); 224 mPaint.setPathEffect(mDash); 225 paintOvallines(canvas, mPaint, p1x, p1y, p2x, p2y); 226 } 227 228 public void paintOvallines( 229 Canvas canvas, Paint paint, float p1x, float p1y, float p2x, float p2y) { 230 231 232 233 canvas.drawLine(p1x, p1y, p2x, p2y, paint); 234 235 float cx = (p1x + p2x) / 2; 236 float cy = (p1y + p2y) / 2; 237 float dx = p1x - p2x; 238 float dy = p1y - p2y; 239 float len = (float) Math.sqrt(dx * dx + dy * dy); 240 dx *= 2048 / len; 241 dy *= 2048 / len; 242 243 canvas.drawLine(p1x + dy, p1y - dx, p1x - dy, p1y + dx, paint); 244 canvas.drawLine(p2x + dy, p2y - dx, p2x - dy, p2y + dx, paint); 245 } 246 247 public void fillHandles(Canvas canvas, float p1x, float p1y, float p2x, float p2y) { 248 float cx = (p1x + p2x) / 2; 249 float cy = (p1y + p2y) / 2; 250 handlex[0] = cx; 251 handley[0] = cy; 252 handlex[1] = p1x; 253 handley[1] = p1y; 254 handlex[2] = p2x; 255 handley[2] = p2y; 256 257 } 258 259 public void draw(Canvas canvas) { 260 paintLines(canvas, mPoint1X, mPoint1Y, mPoint2X, mPoint2Y); 261 fillHandles(canvas, mPoint1X, mPoint1Y, mPoint2X, mPoint2Y); 262 paintPoint(canvas, mPoint2X, mPoint2Y); 263 paintPoint(canvas, mPoint1X, mPoint1Y); 264 paintPoint(canvas, (mPoint1X + mPoint2X) / 2, (mPoint1Y + mPoint2Y) / 2); 265 } 266 267 public boolean isUndefined() { 268 return Float.isNaN(mPoint1X); 269 } 270 271 public void setShowReshapeHandles(boolean showReshapeHandles) { 272 this.mShowReshapeHandles = showReshapeHandles; 273 } 274} 275