1 #include "efl_canvas_gesture_private.h"
2 
3 #define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_ZOOM_CLASS
4 
5 static void
_reset_recognizer(Efl_Canvas_Gesture_Recognizer_Zoom_Data * pd)6 _reset_recognizer(Efl_Canvas_Gesture_Recognizer_Zoom_Data *pd)
7 {
8    memset(&pd->zoom_st, 0, sizeof(Efl_Gesture_Touch_Point_Data));
9    memset(&pd->zoom_st1, 0, sizeof(Efl_Gesture_Touch_Point_Data));
10    memset(&pd->zoom_mv, 0, sizeof(Efl_Gesture_Touch_Point_Data));
11    memset(&pd->zoom_mv1, 0, sizeof(Efl_Gesture_Touch_Point_Data));
12    pd->zoom_base = 0;
13    pd->zoom_step = pd->next_step = pd->zoom_finger_factor = pd->zoom_distance_tolerance = 0;
14    pd->calc_temp = EINA_FALSE;
15 }
16 
17 #define memset do not use memset to reset zoom data, use _reset_recognizer
18 
19 static double
_zoom_compute(Efl_Canvas_Gesture_Recognizer_Zoom_Data * pd,Efl_Canvas_Gesture_Zoom_Data * zd,Evas_Coord xx1,Evas_Coord yy1,Evas_Coord xx2,Evas_Coord yy2,double zoom_finger_factor)20 _zoom_compute(Efl_Canvas_Gesture_Recognizer_Zoom_Data *pd,
21               Efl_Canvas_Gesture_Zoom_Data *zd,
22               Evas_Coord xx1,
23               Evas_Coord yy1,
24               Evas_Coord xx2,
25               Evas_Coord yy2,
26               double zoom_finger_factor)
27 {
28    double rt = 1.0, zoom_distance_tolerance = pd->zoom_distance_tolerance;
29    //TODO: Enable below code if the zoom momentum is need
30    //unsigned int tm_end = (pd->zoom_mv.cur.timestamp > pd->zoom_mv1.cur.timestamp) ?
31    //   pd->zoom_mv.cur.timestamp : pd->zoom_mv1.cur.timestamp;
32 
33    int x, y; //Hot spot
34    Evas_Coord diam = _finger_gap_length_get(xx1, yy1, xx2, yy2,
35                                             &x, &y);
36 
37    zd->radius = diam / 2.0;
38 
39    if (!pd->zoom_base)
40      {
41         pd->zoom_base = diam;
42         return zd->zoom;
43      }
44 
45    if (EINA_DBL_NONZERO(zoom_distance_tolerance)) /* zoom tolerance <> ZERO, means
46                                     * zoom action NOT started yet */
47      {
48         /* avoid jump with zoom value when break tolerance */
49         if (diam < (pd->zoom_base - pd->zoom_distance_tolerance))
50           {
51              pd->zoom_base -= pd->zoom_distance_tolerance;
52              pd->zoom_distance_tolerance = 0;
53           }
54 
55         /* avoid jump with zoom value when break tolerance */
56         if (diam > (pd->zoom_base + pd->zoom_distance_tolerance))
57           {
58              pd->zoom_base += pd->zoom_distance_tolerance;
59              pd->zoom_distance_tolerance = 0;
60           }
61 
62         return rt;
63      }
64 
65    /* We use factor only on the difference between gap-base   */
66    /* if gap=120, base=100, we get ((120-100)/100)=0.2*factor */
67    rt = ((1.0) + ((((float)diam - (float)pd->zoom_base) /
68                    (float)pd->zoom_base) * zoom_finger_factor));
69 
70    //TODO: Enable below code if the zoom momentum is need
71    /* Momentum: zoom per second: */
72    //zd->momentum = _zoom_momentum_get(st, tm_end, rt);
73 
74    return rt;
75 }
76 
77 EOLIAN static const Efl_Class *
_efl_canvas_gesture_recognizer_zoom_efl_canvas_gesture_recognizer_type_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Gesture_Recognizer_Zoom_Data * pd EINA_UNUSED)78 _efl_canvas_gesture_recognizer_zoom_efl_canvas_gesture_recognizer_type_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Recognizer_Zoom_Data *pd EINA_UNUSED)
79 {
80    return EFL_CANVAS_GESTURE_ZOOM_CLASS;
81 }
82 
83 EOLIAN static Efl_Canvas_Gesture_Recognizer_Result
_efl_canvas_gesture_recognizer_zoom_efl_canvas_gesture_recognizer_recognize(Eo * obj,Efl_Canvas_Gesture_Recognizer_Zoom_Data * pd,Efl_Canvas_Gesture * gesture,Efl_Object * watched,Efl_Canvas_Gesture_Touch * event)84 _efl_canvas_gesture_recognizer_zoom_efl_canvas_gesture_recognizer_recognize(Eo *obj,
85                                                                             Efl_Canvas_Gesture_Recognizer_Zoom_Data *pd,
86                                                                             Efl_Canvas_Gesture *gesture,
87                                                                             Efl_Object *watched,
88                                                                             Efl_Canvas_Gesture_Touch *event)
89 {
90    Eina_Value *val;
91    unsigned char zoom_finger_enable;
92    unsigned char glayer_continues_enable;
93    Efl_Canvas_Gesture_Recognizer_Result result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
94    Efl_Canvas_Gesture_Zoom_Data *zd = efl_data_scope_get(gesture, EFL_CANVAS_GESTURE_ZOOM_CLASS);
95    Efl_Canvas_Gesture_Touch_Data *td = efl_data_scope_get(event, EFL_CANVAS_GESTURE_TOUCH_CLASS);
96    Efl_Canvas_Gesture_Recognizer_Data *rd = efl_data_scope_get(obj, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS);
97    double zoom_distance_tolerance = pd->zoom_distance_tolerance;
98 
99    //FIXME: Wheel zoom test first here.
100 
101    val = _recognizer_config_get(obj, "glayer_continues_enable");
102    if (val) eina_value_get(val, &glayer_continues_enable);
103    else glayer_continues_enable = 1;
104 
105    val = _recognizer_config_get(obj, "glayer_zoom_finger_enable");
106    if (val) eina_value_get(val, &zoom_finger_enable);
107    else zoom_finger_enable = 1;
108 
109    val = _recognizer_config_get(obj, "glayer_zoom_finger_factor");
110    if (val) eina_value_get(val, &pd->zoom_finger_factor);
111    else pd->zoom_finger_factor = 1.0;
112 
113    rd->continues = EINA_TRUE;
114 
115    if (!EINA_DBL_NONZERO(zoom_distance_tolerance) && !pd->calc_temp)
116      {
117         pd->calc_temp = EINA_TRUE;
118         val = _recognizer_config_get(obj, "glayer_zoom_distance_tolerance");
119         if (val) eina_value_get(val, &pd->zoom_distance_tolerance);
120         else pd->zoom_distance_tolerance = 1.0;
121 
122         pd->zoom_distance_tolerance *= pd->finger_size;
123      }
124 
125    switch (efl_gesture_touch_state_get(event))
126      {
127       case EFL_GESTURE_TOUCH_STATE_UPDATE:
128       {
129          if ((!glayer_continues_enable) && (!pd->zoom_st.cur.timestamp))
130            {
131               return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
132            }
133          EINA_FALLTHROUGH;
134       }
135 
136       case EFL_GESTURE_TOUCH_STATE_BEGIN:
137       {
138          if (td->touch_down > 2)
139            {
140               _reset_recognizer(pd);
141               if (efl_gesture_state_get(gesture) == EFL_GESTURE_STATE_CANCELED)
142                 return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
143               return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
144            }
145          if (td->touch_down == 1)
146            {
147               return EFL_GESTURE_RECOGNIZER_RESULT_MAYBE;
148            }
149 
150          if (!pd->zoom_st.cur.timestamp)   /* Now scan touched-devices list
151                                             * and find other finger */
152            {
153               if (!_event_multi_touch_get(event))
154                 return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
155 
156               const Efl_Gesture_Touch_Point_Data *p1 = efl_gesture_touch_data_get(event, 0);
157               const Efl_Gesture_Touch_Point_Data *p2 = efl_gesture_touch_data_get(event, 1);
158 
159               memcpy(&pd->zoom_st, p2, sizeof(Efl_Gesture_Touch_Point_Data));
160               memcpy(&pd->zoom_st1, p1, sizeof(Efl_Gesture_Touch_Point_Data));
161 
162               memcpy(&pd->zoom_mv, p2, sizeof(Efl_Gesture_Touch_Point_Data));
163               memcpy(&pd->zoom_mv1, p1, sizeof(Efl_Gesture_Touch_Point_Data));
164 
165               int x, y;  //Hot spot
166               zd->zoom = 1.0;
167               pd->zoom_base = _finger_gap_length_get(pd->zoom_st1.cur.pos.x,
168                                                      pd->zoom_st1.cur.pos.y,
169                                                      pd->zoom_st.cur.pos.x,
170                                                      pd->zoom_st.cur.pos.y,
171                                                      &x, &y);
172 
173               zd->radius = pd->zoom_base / 2.0;
174 
175               if ((efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_STARTED) &&
176                   (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_UPDATED))
177                 return EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
178 
179               return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
180            }
181 
182          const Efl_Gesture_Touch_Point_Data *p2 = efl_gesture_touch_data_get(event, 1);
183          if (p2->id == pd->zoom_mv.id)
184            memcpy(&pd->zoom_mv, p2, sizeof(Efl_Gesture_Touch_Point_Data));
185          else if (p2->id == pd->zoom_mv1.id)
186            memcpy(&pd->zoom_mv1, p2, sizeof(Efl_Gesture_Touch_Point_Data));
187 
188          zd->zoom = _zoom_compute(pd, zd, pd->zoom_mv.cur.pos.x,
189                                   pd->zoom_mv.cur.pos.y, pd->zoom_mv1.cur.pos.x,
190                                   pd->zoom_mv1.cur.pos.y, pd->zoom_finger_factor);
191 
192          if (!EINA_DBL_NONZERO(zoom_distance_tolerance))
193            {
194               double d = zd->zoom - pd->next_step;
195 
196               if (d < 0.0) d = (-d);
197 
198               if (d >= pd->zoom_step)
199                 {
200                    pd->next_step = zd->zoom;
201 
202                    return EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
203                 }
204            }
205 
206          return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
207       }
208 
209       case EFL_GESTURE_TOUCH_STATE_END:
210       {
211          /* no gesture was started, so no gesture should be detected */
212          if ((td->touch_down == 0) || (!pd->zoom_st.cur.timestamp))
213            {
214               rd->continues = EINA_FALSE;
215 
216               _reset_recognizer(pd);
217               efl_gesture_manager_recognizer_cleanup(efl_provider_find(obj, EFL_CANVAS_GESTURE_MANAGER_CLASS), obj, watched);
218 
219               return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
220            }
221          if ((pd->zoom_base) && EINA_DBL_EQ(pd->zoom_distance_tolerance, 0))
222            {
223               _reset_recognizer(pd);
224 
225               return EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
226            }
227 
228          if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE)
229            {
230               _reset_recognizer(pd);
231 
232               return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
233            }
234       }
235 
236       default:
237 
238         break;
239      }
240 
241    return result;
242 }
243 
244 #include "efl_canvas_gesture_recognizer_zoom.eo.c"
245