1/*
2 * Copyright (C) 2013 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.graphics.Canvas;
21import android.graphics.Matrix;
22import android.util.AttributeSet;
23import android.view.MotionEvent;
24
25import com.android.gallery3d.filtershow.editors.EditorVignette;
26import com.android.gallery3d.filtershow.filters.FilterVignetteRepresentation;
27
28public class ImageVignette extends ImageShow {
29    private static final String LOGTAG = "ImageVignette";
30
31    private FilterVignetteRepresentation mVignetteRep;
32    private EditorVignette mEditorVignette;
33    private OvalSpaceAdapter mScreenOval = new OvalSpaceAdapter();
34    private int mActiveHandle = -1;
35
36    EclipseControl mElipse;
37
38    public ImageVignette(Context context) {
39        super(context);
40        mElipse = new EclipseControl(context);
41    }
42
43    public ImageVignette(Context context, AttributeSet attrs) {
44        super(context, attrs);
45        mElipse = new EclipseControl(context);
46    }
47
48    static class OvalSpaceAdapter implements Oval {
49        private Oval mOval;
50        Matrix mToScr;
51        Matrix mToImage;
52        int mImgWidth;
53        int mImgHeight;
54        float[] mTmp = new float[2];
55        float mTmpRadiusX;
56        float mTmpRadiusY;
57
58        public void setImageOval(Oval oval) {
59            mOval = oval;
60        }
61
62        public void setTransform(Matrix toScr, Matrix toImage, int imgWidth, int imgHeight) {
63            mToScr = toScr;
64            mToImage = toImage;
65            mImgWidth = imgWidth;
66            mImgHeight = imgHeight;
67            mTmpRadiusX = getRadiusX();
68            mTmpRadiusY = getRadiusY();
69        }
70
71        @Override
72        public void setCenter(float x, float y) {
73            mTmp[0] = x;
74            mTmp[1] = y;
75            mToImage.mapPoints(mTmp);
76            mOval.setCenter(mTmp[0] / mImgWidth, mTmp[1] / mImgHeight);
77        }
78
79        @Override
80        public void setRadius(float w, float h) {
81            mTmp[0] = mTmpRadiusX = w;
82            mTmp[1] = mTmpRadiusY = h;
83            mToImage.mapVectors(mTmp);
84            mOval.setRadius(mTmp[0] / mImgWidth, mTmp[1] / mImgHeight);
85        }
86
87        @Override
88        public float getCenterX() {
89            mTmp[0] = mOval.getCenterX() * mImgWidth;
90            mTmp[1] = mOval.getCenterY() * mImgHeight;
91            mToScr.mapPoints(mTmp);
92
93            return mTmp[0];
94        }
95
96        @Override
97        public float getCenterY() {
98            mTmp[0] = mOval.getCenterX() * mImgWidth;
99            mTmp[1] = mOval.getCenterY() * mImgHeight;
100            mToScr.mapPoints(mTmp);
101            return mTmp[1];
102        }
103
104        @Override
105        public float getRadiusX() {
106            mTmp[0] = mOval.getRadiusX() * mImgWidth;
107            mTmp[1] = mOval.getRadiusY() * mImgHeight;
108            mToScr.mapVectors(mTmp);
109            return Math.abs(mTmp[0]);
110        }
111
112        @Override
113        public float getRadiusY() {
114            mTmp[0] = mOval.getRadiusX() * mImgWidth;
115            mTmp[1] = mOval.getRadiusY() * mImgHeight;
116            mToScr.mapVectors(mTmp);
117            return Math.abs(mTmp[1]);
118        }
119
120        @Override
121        public void setRadiusY(float y) {
122            mTmp[0] = mTmpRadiusX;
123            mTmp[1] = mTmpRadiusY = y;
124            mToImage.mapVectors(mTmp);
125            mOval.setRadiusX(mTmp[0] / mImgWidth);
126            mOval.setRadiusY(mTmp[1] / mImgHeight);
127        }
128
129        @Override
130        public void setRadiusX(float x) {
131            mTmp[0] = mTmpRadiusX = x;
132            mTmp[1] = mTmpRadiusY;
133            mToImage.mapVectors(mTmp);
134            mOval.setRadiusX(mTmp[0] / mImgWidth);
135            mOval.setRadiusY(mTmp[1] / mImgHeight);
136        }
137    }
138
139    @Override
140    public boolean onTouchEvent(MotionEvent event) {
141        int w = MasterImage.getImage().getOriginalBounds().width();
142        int h = MasterImage.getImage().getOriginalBounds().height();
143        int mask = event.getActionMasked();
144        if (mActiveHandle == -1) {
145            if (MotionEvent.ACTION_DOWN != mask) {
146                return super.onTouchEvent(event);
147            }
148            if (event.getPointerCount() == 1) {
149                mActiveHandle = mElipse.getCloseHandle(event.getX(), event.getY());
150            }
151            if (mActiveHandle == -1) {
152                return super.onTouchEvent(event);
153            }
154        } else {
155            switch (mask) {
156                case MotionEvent.ACTION_UP:
157                    mActiveHandle = -1;
158                    break;
159                case MotionEvent.ACTION_DOWN:
160                    break;
161            }
162        }
163        float x = event.getX();
164        float y = event.getY();
165
166        mElipse.setScrImageInfo(new Matrix(),
167                MasterImage.getImage().getOriginalBounds());
168
169        boolean didComputeEllipses = false;
170        switch (mask) {
171            case (MotionEvent.ACTION_DOWN):
172                mElipse.actionDown(x, y, mScreenOval);
173                break;
174            case (MotionEvent.ACTION_UP):
175            case (MotionEvent.ACTION_MOVE):
176
177                mElipse.actionMove(mActiveHandle, x, y, mScreenOval);
178                setRepresentation(mVignetteRep);
179                didComputeEllipses = true;
180                break;
181        }
182        if (!didComputeEllipses) {
183            computeEllipses();
184        }
185        invalidate();
186        return true;
187    }
188
189    public void setRepresentation(FilterVignetteRepresentation vignetteRep) {
190        mVignetteRep = vignetteRep;
191        mScreenOval.setImageOval(mVignetteRep);
192        computeEllipses();
193    }
194
195    public void computeEllipses() {
196        if (mVignetteRep == null) {
197            return;
198        }
199        float w = MasterImage.getImage().getOriginalBounds().width();
200        float h = MasterImage.getImage().getOriginalBounds().height();
201        Matrix toImg = getScreenToImageMatrix(false);
202        Matrix toScr = new Matrix();
203        toImg.invert(toScr);
204        mScreenOval.setTransform(toScr, toImg, (int) w, (int) h);
205
206        mElipse.setCenter(mScreenOval.getCenterX(), mScreenOval.getCenterY());
207        mElipse.setRadius(mScreenOval.getRadiusX(), mScreenOval.getRadiusY());
208
209        mEditorVignette.commitLocalRepresentation();
210    }
211
212    public void setEditor(EditorVignette editorVignette) {
213        mEditorVignette = editorVignette;
214    }
215
216    @Override
217    public void onSizeChanged(int w, int h, int oldw, int oldh) {
218        super.onSizeChanged(w, h, oldw, oldh);
219        computeEllipses();
220    }
221
222    @Override
223    public void onDraw(Canvas canvas) {
224        super.onDraw(canvas);
225        if (mVignetteRep == null) {
226            return;
227        }
228        float w = MasterImage.getImage().getOriginalBounds().width();
229        float h = MasterImage.getImage().getOriginalBounds().height();
230        Matrix toImg = getScreenToImageMatrix(false);
231        Matrix toScr = new Matrix();
232        toImg.invert(toScr);
233        mScreenOval.setTransform(toScr, toImg, (int) w, (int) h);
234        mElipse.setCenter(mScreenOval.getCenterX(), mScreenOval.getCenterY());
235        mElipse.setRadius(mScreenOval.getRadiusX(), mScreenOval.getRadiusY());
236
237        mElipse.draw(canvas);
238    }
239
240}
241