Home | History | Annotate | Download | only in imageshow
      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