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