From e99f49733287deb49831d2f5d60838fa7147f9e3 Mon Sep 17 00:00:00 2001 From: Jiyoun Park Date: Fri, 6 Jul 2012 01:59:57 +0000 Subject: [PATCH] [els scroller] add debug code to measure smoothness of scroller it count standard deviation of scroll velocity and modify smooth algorithm SVN revision: 73388 --- legacy/elementary/config/default/base.src | 1 + legacy/elementary/config/illume/base.src | 1 + legacy/elementary/config/standard/base.src | 1 + legacy/elementary/src/lib/elm_config.c | 4 + legacy/elementary/src/lib/elm_priv.h | 1 + legacy/elementary/src/lib/els_scroller.c | 278 ++++++++++++++++----- 6 files changed, 221 insertions(+), 65 deletions(-) diff --git a/legacy/elementary/config/default/base.src b/legacy/elementary/config/default/base.src index bad7bf34fd..8043a8e4c4 100644 --- a/legacy/elementary/config/default/base.src +++ b/legacy/elementary/config/default/base.src @@ -13,6 +13,7 @@ group "Elm_Config" struct { value "zoom_friction" double: 0.5; value "thumbscroll_border_friction" double: 0.5; value "thumbscroll_sensitivity_friction" double: 0.25; + value "scroll_smooth_time_interval" double: 0.0; value "scroll_smooth_amount" double: 0.0; value "scroll_smooth_history_weight" double: 0.1; value "scroll_smooth_future_time" double: 0.0; diff --git a/legacy/elementary/config/illume/base.src b/legacy/elementary/config/illume/base.src index df2735ba3b..90a4113626 100644 --- a/legacy/elementary/config/illume/base.src +++ b/legacy/elementary/config/illume/base.src @@ -13,6 +13,7 @@ group "Elm_Config" struct { value "zoom_friction" double: 0.5; value "thumbscroll_border_friction" double: 0.5; value "thumbscroll_sensitivity_friction" double: 0.25; + value "scroll_smooth_time_interval" double: 0; value "scroll_smooth_amount" double: 1.0; value "scroll_smooth_history_weight" double: 0.1; value "scroll_smooth_future_time" double: 0.0; diff --git a/legacy/elementary/config/standard/base.src b/legacy/elementary/config/standard/base.src index 40d207d215..5566d10c59 100644 --- a/legacy/elementary/config/standard/base.src +++ b/legacy/elementary/config/standard/base.src @@ -13,6 +13,7 @@ group "Elm_Config" struct { value "zoom_friction" double: 0.5; value "thumbscroll_border_friction" double: 0.5; value "thumbscroll_sensitivity_friction" double: 0.25; + value "scroll_smooth_time_interval" double: 0.0; value "scroll_smooth_amount" double: 0.0; value "scroll_smooth_history_weight" double: 0.1; value "scroll_smooth_future_time" double: 0.0; diff --git a/legacy/elementary/src/lib/elm_config.c b/legacy/elementary/src/lib/elm_config.c index cb8ff678c2..56aa55ba1c 100644 --- a/legacy/elementary/src/lib/elm_config.c +++ b/legacy/elementary/src/lib/elm_config.c @@ -333,6 +333,7 @@ _desc_init(void) ELM_CONFIG_VAL(D, T, bring_in_scroll_friction, T_DOUBLE); ELM_CONFIG_VAL(D, T, zoom_friction, T_DOUBLE); ELM_CONFIG_VAL(D, T, thumbscroll_bounce_enable, T_UCHAR); + ELM_CONFIG_VAL(D, T, scroll_smooth_time_interval, T_DOUBLE); ELM_CONFIG_VAL(D, T, scroll_smooth_amount, T_DOUBLE); ELM_CONFIG_VAL(D, T, scroll_smooth_history_weight, T_DOUBLE); ELM_CONFIG_VAL(D, T, scroll_smooth_future_time, T_DOUBLE); @@ -1002,6 +1003,7 @@ _config_load(void) _elm_config->zoom_friction = 0.5; _elm_config->thumbscroll_border_friction = 0.5; _elm_config->thumbscroll_sensitivity_friction = 0.25; // magic number! just trial and error shows this makes it behave "nicer" and not run off at high speed all the time + _elm_config->scroll_smooth_time_interval = 0.008; _elm_config->scroll_smooth_amount = 1.0; _elm_config->scroll_smooth_history_weight = 0.3; _elm_config->scroll_smooth_future_time = 0.0; @@ -1408,6 +1410,8 @@ _env_get(void) _elm_config->thumbscroll_sensitivity_friction = friction; } + s = getenv("ELM_SCROLL_SMOOTH_TIME_INTERVAL"); + if (s) _elm_config->scroll_smooth_time_interval = atof(s); s = getenv("ELM_SCROLL_SMOOTH_AMOUNT"); if (s) _elm_config->scroll_smooth_amount = _elm_atof(s); s = getenv("ELM_SCROLL_SMOOTH_HISTORY_WEIGHT"); diff --git a/legacy/elementary/src/lib/elm_priv.h b/legacy/elementary/src/lib/elm_priv.h index ea2f4a16af..e405723fb2 100644 --- a/legacy/elementary/src/lib/elm_priv.h +++ b/legacy/elementary/src/lib/elm_priv.h @@ -136,6 +136,7 @@ struct _Elm_Config unsigned char thumbscroll_bounce_enable; double thumbscroll_border_friction; double thumbscroll_sensitivity_friction; + double scroll_smooth_time_interval; double scroll_smooth_amount; double scroll_smooth_history_weight; double scroll_smooth_future_time; diff --git a/legacy/elementary/src/lib/els_scroller.c b/legacy/elementary/src/lib/els_scroller.c index bf386d1f5e..520cf327a7 100644 --- a/legacy/elementary/src/lib/els_scroller.c +++ b/legacy/elementary/src/lib/els_scroller.c @@ -11,6 +11,151 @@ typedef struct _Smart_Data Smart_Data; #define EVTIME 1 //#define SCROLLDBG 1 +/* smoothness debug calls - for debugging how much smooth your app is */ +#define SMOOTHDBG 1 + +#ifdef SMOOTHDBG +#define SMOOTH_DEBUG_COUNT 100 +#define FPS 1/60 +typedef struct _smooth_debug_info smooth_debug_info; +struct _smooth_debug_info +{ + double t; + double dt; + Evas_Coord pos; + Evas_Coord dpos; + double vpos; +}; + +static smooth_debug_info smooth_x_history[SMOOTH_DEBUG_COUNT]; +static smooth_debug_info smooth_y_history[SMOOTH_DEBUG_COUNT]; +static int smooth_info_x_count = 0; +static int smooth_info_y_count = 0; +static double start_time = 0; +static int _els_scroller_smooth_debug = 0; + +void +_els_scroller_smooth_debug_init(void) +{ + start_time = ecore_time_get(); + smooth_info_x_count = 0; + smooth_info_y_count = 0; + + memset(&(smooth_x_history[0]), 0, sizeof(smooth_x_history[0]) * SMOOTH_DEBUG_COUNT); + memset(&(smooth_y_history[0]), 0, sizeof(smooth_y_history[0]) * SMOOTH_DEBUG_COUNT); + + return; +} + +void +_els_scroller_smooth_debug_shutdown(void) +{ + int i = 0; + int info_x_count = 0; + int info_y_count = 0; + double x_ave = 0, y_ave = 0; + double x_sum = 0, y_sum = 0; + double x_dev = 0, y_dev = 0; + double x_dev_sum = 0, y_dev_sum = 0; + + if (smooth_info_x_count >= SMOOTH_DEBUG_COUNT) + info_x_count = SMOOTH_DEBUG_COUNT; + else + info_x_count = smooth_info_x_count; + + if (smooth_info_y_count >= SMOOTH_DEBUG_COUNT) + info_y_count = SMOOTH_DEBUG_COUNT; + else + info_y_count = smooth_info_y_count; + + printf("\n\n<<< X-axis Smoothness >>>\n"); + printf("| Num | t(time) | dt | x | dx |vx(dx/1fps) |\n"); + + for (i = info_x_count -1; i >= 0; i--) + { + printf("| %4d | %1.6f | %1.6f | %4d | %4d | %9.3f |\n",info_x_count - i, + smooth_x_history[i].t, + smooth_x_history[i].dt, + smooth_x_history[i].pos, + smooth_x_history[i].dpos, + smooth_x_history[i].vpos); + if (i == info_x_count -1) continue; + x_sum += smooth_x_history[i].vpos; + } + x_ave = x_sum / (info_x_count - 1); + for (i = 0; i < info_x_count -1; i++) + { + x_dev_sum += (smooth_x_history[i].vpos - x_ave) * (smooth_x_history[i].vpos - x_ave); + } + x_dev = x_dev_sum / (info_x_count -1); + printf(" Standard deviation of X-axid velocity: %9.3f\n", sqrt(x_dev)); + + printf("\n\n<<< Y-axis Smoothness >>>\n"); + printf("| Num | t(time) | dt | y | dy |vy(dy/1fps) |\n"); + for (i = info_y_count -1; i >= 0; i--) + { + printf("| %4d | %1.6f | %1.6f | %4d | %4d | %9.3f |\n", info_y_count - i, + smooth_y_history[i].t, + smooth_y_history[i].dt, + smooth_y_history[i].pos, + smooth_y_history[i].dpos, + smooth_y_history[i].vpos); + if (i == info_y_count -1) continue; + y_sum += smooth_y_history[i].vpos; + } + y_ave = y_sum / (info_y_count - 1); + for (i = 0; i < info_y_count -1; i++) + { + y_dev_sum += (smooth_y_history[i].vpos - y_ave) * (smooth_y_history[i].vpos - y_ave); + } + y_dev = y_dev_sum / (info_y_count -1); + printf(" Standard deviation of Y-axid velocity: %9.3f\n", sqrt(y_dev)); +} + +void +_els_scroller_smooth_debug_movetime_add(int x, int y) +{ + double tim = 0; + static int bx = 0; + static int by = 0; + + tim = ecore_time_get(); + + if (bx != x) + { + smooth_info_x_count++; + memmove(&(smooth_x_history[1]), &(smooth_x_history[0]), sizeof(smooth_x_history[0]) * (SMOOTH_DEBUG_COUNT - 1)); + smooth_x_history[0].t = tim - start_time; + smooth_x_history[0].dt = smooth_x_history[0].t - smooth_x_history[1].t; + smooth_x_history[0].pos = x; + smooth_x_history[0].dpos = smooth_x_history[0].pos - smooth_x_history[1].pos; + + if (smooth_x_history[0].dpos >= 0) + smooth_x_history[0].vpos = (double)(smooth_x_history[0].dpos) / smooth_x_history[0].dt * FPS; + else + smooth_x_history[0].vpos = -((double)(smooth_x_history[0].dpos) / smooth_x_history[0].dt * FPS); + } + + if (by != y) + { + smooth_info_y_count++; + memmove(&(smooth_y_history[1]), &(smooth_y_history[0]), sizeof(smooth_y_history[0]) * (SMOOTH_DEBUG_COUNT - 1)); + smooth_y_history[0].t = tim - start_time; + smooth_y_history[0].dt = smooth_y_history[0].t - smooth_y_history[1].t; + smooth_y_history[0].pos = y; + smooth_y_history[0].dpos = smooth_y_history[0].pos - smooth_y_history[1].pos; + + if (smooth_y_history[0].dpos >= 0) + smooth_y_history[0].vpos = (double)(smooth_y_history[0].dpos) / smooth_y_history[0].dt * FPS; + else + smooth_y_history[0].vpos = -((double)(smooth_y_history[0].dpos) / smooth_y_history[0].dt * FPS); + } + + bx = x; + by = y; +} +#endif + struct _Smart_Data { Evas_Coord x, y, w, h; @@ -1719,6 +1864,12 @@ _smart_event_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSE sd = data; ev = event_info; + +#ifdef SMOOTHDBG + if (getenv("ELS_SCROLLER_SMOOTH_DEBUG")) _els_scroller_smooth_debug = 1; + if (_els_scroller_smooth_debug) _els_scroller_smooth_debug_init(); +#endif + // if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ; if (_elm_config->thumbscroll_enable) { @@ -1860,83 +2011,71 @@ _smart_hold_animator(void *data) fx = sd->down.hold_x; fy = sd->down.hold_y; - if (_elm_config->scroll_smooth_amount > 0.0) - { - int i, count = 0; - Evas_Coord basex = 0, basey = 0, x, y; - double dt, t, tdiff, tnow, twin; - struct - { - Evas_Coord x, y, dx, dy; - double t, dt; - } pos[60]; + if ((!sd->hold) && (!sd->freeze) && (_elm_config->scroll_smooth_time_interval > 0.0)) + { + int i, count = 0; //count for the real event number we have to deal with + int queue_size = 10; //for event queue size + int src_index = 0, dst_index = 0; + int xsum = 0, ysum = 0; + Evas_Coord x = 0, y = 0; + + struct { + Evas_Coord x, y; + double t; + } pos[queue_size]; + + double tdiff, tnow; + double time_interval = _elm_config->scroll_smooth_time_interval; + // FIXME: assume server and client have the same "timezone" + // (0 timepoint) for now. this needs to be figured out in advance + // though. tdiff = sd->down.hist.est_timestamp_diff; tnow = ecore_time_get() - tdiff; - t = tnow; - twin = _elm_config->scroll_smooth_time_window; - for (i = 0; i < 60; i++) + + for(i = 0; i < queue_size; i++) { - // oldest point is sd->down.history[i] - // newset is sd->down.history[0] - dt = t - sd->down.history[i].timestamp; - if (dt > twin) - { - i--; - break; - } x = sd->down.history[i].x; y = sd->down.history[i].y; + + //if there is no history value , we don't deal with it + //if there is better wat to know existance of history value , I will modify this code to it + if ( (x == 0) && (y == 0) ) + { + break; + } _down_coord_eval(sd, &x, &y); + + pos[i].x = x; + pos[i].y = y; + pos[i].t = tnow - sd->down.history[i].timestamp; + } + count = --i; + + // we only deal with smooth scroll there is enough history + for(i = 0; i < queue_size; i++) + { + if (src_index > count) break; if (i == 0) { - basex = x; - basey = y; + xsum = pos[i].x; + ysum = pos[i].y; + dst_index++; + continue; } - pos[i].x = x - basex; - pos[i].y = y - basey; - pos[i].t = - sd->down.history[i].timestamp - sd->down.history[0].timestamp; - count++; - } - count = i; - if (count >= 2) - { - double dtsum = 0.0, tadd, maxdt; - double dxsum = 0.0, dysum = 0.0, xsum = 0.0, ysum = 0.0; - - for (i = 0; i < (count - 1); i++) + while ((pos[src_index].t < time_interval * i) && (src_index <= count)) { - pos[i].dx = pos[i].x - pos[i + 1].x; - pos[i].dy = pos[i].y - pos[i + 1].y; - pos[i].dt = pos[i].t - pos[i + 1].t; - dxsum += pos[i].dx; - dysum += pos[i].dy; - dtsum += pos[i].dt; - xsum += pos[i].x; - ysum += pos[i].y; - } - maxdt = pos[i].t; - dxsum /= (double)i; - dysum /= (double)i; - dtsum /= (double)i; - xsum /= (double)i; - ysum /= (double)i; - tadd = tnow - sd->down.history[0].timestamp + _elm_config->scroll_smooth_future_time; - tadd = tadd - (maxdt / 2); -#define WEIGHT(n, o, v) n = (((double)o * (1.0 - v)) + ((double)n * v)) - WEIGHT(tadd, sd->down.hist.tadd, _elm_config->scroll_smooth_history_weight); - WEIGHT(dxsum, sd->down.hist.dxsum, _elm_config->scroll_smooth_history_weight); - WEIGHT(dysum, sd->down.hist.dysum, _elm_config->scroll_smooth_history_weight); - fx = basex + xsum + ((dxsum * tadd) / dtsum); - fy = basey + ysum + ((dysum * tadd) / dtsum); - sd->down.hist.tadd = tadd; - sd->down.hist.dxsum = dxsum; - sd->down.hist.dysum = dysum; - WEIGHT(fx, sd->down.hold_x, _elm_config->scroll_smooth_amount); - WEIGHT(fy, sd->down.hold_y, _elm_config->scroll_smooth_amount); + src_index++; } - // printf("%3.5f %i %i\n", ecore_time_get(), sd->down.hold_y, fy); + if (src_index <= count) + { + xsum += pos[src_index].x; + ysum += pos[src_index].y; + dst_index++; + } + } + fx = xsum / dst_index; + fy = ysum / dst_index; } elm_smart_scroller_child_pos_get(sd->smart_obj, &ox, &oy); @@ -1953,6 +2092,11 @@ _smart_hold_animator(void *data) oy = fy; } +#ifdef SMOOTHDBG + if (_els_scroller_smooth_debug) + _els_scroller_smooth_debug_movetime_add(ox, oy); +#endif + elm_smart_scroller_child_pos_set(sd->smart_obj, ox, oy); return ECORE_CALLBACK_RENEW; } @@ -1979,6 +2123,10 @@ _smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *ev Smart_Data *sd; Evas_Coord x = 0, y = 0, ox = 0, oy = 0; +#ifdef SMOOTHDBG + if (_els_scroller_smooth_debug) _els_scroller_smooth_debug_shutdown(); +#endif + sd = data; ev = event_info; sd->down.hold_parent = EINA_FALSE;