1 /* 2 Copyright (C) 2009-2010 Samsung Electronics 3 Copyright (C) 2009-2010 ProFUSION embedded systems 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Library General Public 7 License as published by the Free Software Foundation; either 8 version 2 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Library General Public License for more details. 14 15 You should have received a copy of the GNU Library General Public License 16 along with this library; see the file COPYING.LIB. If not, write to 17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 Boston, MA 02110-1301, USA. 19 */ 20 21 #include "config.h" 22 #include "ewk_view.h" 23 24 #include "ewk_logging.h" 25 26 #include <Evas.h> 27 #include <eina_safety_checks.h> 28 #include <ewk_tiled_backing_store.h> 29 30 static Ewk_View_Smart_Class _parent_sc = EWK_VIEW_SMART_CLASS_INIT_NULL; 31 32 static Eina_Bool _ewk_view_tiled_render_cb(void *data, Ewk_Tile *t, const Eina_Rectangle *area) 33 { 34 Ewk_View_Private_Data *priv = (Ewk_View_Private_Data*)data; 35 Eina_Rectangle r = {area->x + t->x, area->y + t->y, area->w, area->h}; 36 37 return ewk_view_paint_contents(priv, t->cairo, &r); 38 } 39 40 static void *_ewk_view_tiled_updates_process_pre(void *data, Evas_Object *o) 41 { 42 Ewk_View_Private_Data *priv = (Ewk_View_Private_Data*)data; 43 ewk_view_layout_if_needed_recursive(priv); 44 return 0; 45 } 46 47 static Evas_Object *_ewk_view_tiled_smart_backing_store_add(Ewk_View_Smart_Data *sd) 48 { 49 Evas_Object *bs = ewk_tiled_backing_store_add(sd->base.evas); 50 ewk_tiled_backing_store_render_cb_set 51 (bs, _ewk_view_tiled_render_cb, sd->_priv); 52 ewk_tiled_backing_store_updates_process_pre_set 53 (bs, _ewk_view_tiled_updates_process_pre, sd->_priv); 54 return bs; 55 } 56 57 static void 58 _ewk_view_tiled_contents_size_changed_cb(void *data, Evas_Object *o, void *event_info) 59 { 60 Evas_Coord *size = (Evas_Coord*)event_info; 61 Ewk_View_Smart_Data *sd = (Ewk_View_Smart_Data*)data; 62 63 ewk_tiled_backing_store_contents_resize 64 (sd->backing_store, size[0], size[1]); 65 } 66 67 static void _ewk_view_tiled_smart_add(Evas_Object *o) 68 { 69 Ewk_View_Smart_Data *sd; 70 71 _parent_sc.sc.add(o); 72 73 sd = (Ewk_View_Smart_Data*)evas_object_smart_data_get(o); 74 evas_object_smart_callback_add( 75 sd->main_frame, "contents,size,changed", 76 _ewk_view_tiled_contents_size_changed_cb, sd); 77 ewk_frame_paint_full_set(sd->main_frame, EINA_TRUE); 78 } 79 80 static Eina_Bool _ewk_view_tiled_smart_scrolls_process(Ewk_View_Smart_Data *sd) 81 { 82 const Ewk_Scroll_Request *sr; 83 const Ewk_Scroll_Request *sr_end; 84 size_t count; 85 Evas_Coord vw, vh; 86 87 ewk_frame_contents_size_get(sd->main_frame, &vw, &vh); 88 89 sr = ewk_view_scroll_requests_get(sd->_priv, &count); 90 sr_end = sr + count; 91 for (; sr < sr_end; sr++) { 92 if (sr->main_scroll) 93 ewk_tiled_backing_store_scroll_full_offset_add 94 (sd->backing_store, sr->dx, sr->dy); 95 else { 96 Evas_Coord sx, sy, sw, sh; 97 98 sx = sr->x; 99 sy = sr->y; 100 sw = sr->w; 101 sh = sr->h; 102 103 if (abs(sr->dx) >= sw || abs(sr->dy) >= sh) { 104 /* doubt webkit would be so stupid... */ 105 DBG("full page scroll %+03d,%+03d. convert to repaint %d,%d + %dx%d", 106 sr->dx, sr->dy, sx, sy, sw, sh); 107 ewk_view_repaint_add(sd->_priv, sx, sy, sw, sh); 108 continue; 109 } 110 111 if (sx + sw > vw) 112 sw = vw - sx; 113 if (sy + sh > vh) 114 sh = vh - sy; 115 116 if (sw < 0) 117 sw = 0; 118 if (sh < 0) 119 sh = 0; 120 121 if (!sw || !sh) 122 continue; 123 124 sx -= abs(sr->dx); 125 sy -= abs(sr->dy); 126 sw += abs(sr->dx); 127 sh += abs(sr->dy); 128 ewk_view_repaint_add(sd->_priv, sx, sy, sw, sh); 129 INF("using repaint for inner frame scolling!"); 130 } 131 } 132 133 return EINA_TRUE; 134 } 135 136 static Eina_Bool _ewk_view_tiled_smart_repaints_process(Ewk_View_Smart_Data *sd) 137 { 138 const Eina_Rectangle *pr, *pr_end; 139 size_t count; 140 int sx, sy; 141 142 ewk_frame_scroll_pos_get(sd->main_frame, &sx, &sy); 143 144 pr = ewk_view_repaints_get(sd->_priv, &count); 145 pr_end = pr + count; 146 for (; pr < pr_end; pr++) { 147 Eina_Rectangle r; 148 r.x = pr->x + sx; 149 r.y = pr->y + sy; 150 r.w = pr->w; 151 r.h = pr->h; 152 ewk_tiled_backing_store_update(sd->backing_store, &r); 153 } 154 ewk_tiled_backing_store_updates_process(sd->backing_store); 155 156 return EINA_TRUE; 157 } 158 159 static Eina_Bool _ewk_view_tiled_smart_contents_resize(Ewk_View_Smart_Data *sd, int w, int h) 160 { 161 ewk_tiled_backing_store_contents_resize(sd->backing_store, w, h); 162 return EINA_TRUE; 163 } 164 165 static Eina_Bool _ewk_view_tiled_smart_zoom_set(Ewk_View_Smart_Data *sd, float zoom, Evas_Coord cx, Evas_Coord cy) 166 { 167 Evas_Coord x, y, w, h; 168 Eina_Bool r; 169 r = ewk_tiled_backing_store_zoom_set(sd->backing_store, 170 &zoom, cx, cy, &x, &y); 171 if (!r) 172 return r; 173 ewk_tiled_backing_store_disabled_update_set(sd->backing_store, EINA_TRUE); 174 r = _parent_sc.zoom_set(sd, zoom, cx, cy); 175 ewk_frame_scroll_set(sd->main_frame, -x, -y); 176 ewk_frame_scroll_size_get(sd->main_frame, &w, &h); 177 ewk_tiled_backing_store_fix_offsets(sd->backing_store, w, h); 178 ewk_view_scrolls_process(sd); 179 evas_object_smart_calculate(sd->backing_store); 180 evas_object_smart_calculate(sd->self); 181 ewk_tiled_backing_store_disabled_update_set(sd->backing_store, EINA_FALSE); 182 return r; 183 } 184 185 static Eina_Bool _ewk_view_tiled_smart_zoom_weak_set(Ewk_View_Smart_Data *sd, float zoom, Evas_Coord cx, Evas_Coord cy) 186 { 187 return ewk_tiled_backing_store_zoom_weak_set(sd->backing_store, zoom, cx, cy); 188 } 189 190 static void _ewk_view_tiled_smart_zoom_weak_smooth_scale_set(Ewk_View_Smart_Data *sd, Eina_Bool smooth_scale) 191 { 192 ewk_tiled_backing_store_zoom_weak_smooth_scale_set(sd->backing_store, smooth_scale); 193 } 194 195 static void _ewk_view_tiled_smart_flush(Ewk_View_Smart_Data *sd) 196 { 197 ewk_tiled_backing_store_flush(sd->backing_store); 198 _parent_sc.flush(sd); 199 } 200 201 static Eina_Bool _ewk_view_tiled_smart_pre_render_region(Ewk_View_Smart_Data *sd, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, float zoom) 202 { 203 return ewk_tiled_backing_store_pre_render_region 204 (sd->backing_store, x, y, w, h, zoom); 205 } 206 207 static Eina_Bool _ewk_view_tiled_smart_pre_render_relative_radius(Ewk_View_Smart_Data *sd, unsigned int n, float zoom) 208 { 209 return ewk_tiled_backing_store_pre_render_relative_radius 210 (sd->backing_store, n, zoom); 211 } 212 213 static void _ewk_view_tiled_smart_pre_render_cancel(Ewk_View_Smart_Data *sd) 214 { 215 ewk_tiled_backing_store_pre_render_cancel(sd->backing_store); 216 } 217 218 static Eina_Bool _ewk_view_tiled_smart_disable_render(Ewk_View_Smart_Data *sd) 219 { 220 return ewk_tiled_backing_store_disable_render(sd->backing_store); 221 } 222 223 static Eina_Bool _ewk_view_tiled_smart_enable_render(Ewk_View_Smart_Data *sd) 224 { 225 return ewk_tiled_backing_store_enable_render(sd->backing_store); 226 } 227 228 /** 229 * Sets the smart class api using tiled backing store, enabling view 230 * to be inherited. 231 * 232 * @param api class definition to be set, all members with the 233 * exception of Evas_Smart_Class->data may be overridden. Must 234 * @b not be @c NULL. 235 * 236 * @note Evas_Smart_Class->data is used to implement type checking and 237 * is not supposed to be changed/overridden. If you need extra 238 * data for your smart class to work, just extend 239 * Ewk_View_Smart_Class instead. 240 * 241 * @return @c EINA_TRUE on success, @c EINA_FALSE on failure (probably 242 * version mismatch). 243 * 244 * @see ewk_view_base_smart_set() 245 */ 246 Eina_Bool ewk_view_tiled_smart_set(Ewk_View_Smart_Class *api) 247 { 248 if (!ewk_view_base_smart_set(api)) 249 return EINA_FALSE; 250 251 if (EINA_UNLIKELY(!_parent_sc.sc.add)) 252 ewk_view_base_smart_set(&_parent_sc); 253 254 api->sc.add = _ewk_view_tiled_smart_add; 255 256 api->backing_store_add = _ewk_view_tiled_smart_backing_store_add; 257 api->scrolls_process = _ewk_view_tiled_smart_scrolls_process; 258 api->repaints_process = _ewk_view_tiled_smart_repaints_process; 259 api->contents_resize = _ewk_view_tiled_smart_contents_resize; 260 api->zoom_set = _ewk_view_tiled_smart_zoom_set; 261 api->zoom_weak_set = _ewk_view_tiled_smart_zoom_weak_set; 262 api->zoom_weak_smooth_scale_set = _ewk_view_tiled_smart_zoom_weak_smooth_scale_set; 263 api->flush = _ewk_view_tiled_smart_flush; 264 api->pre_render_region = _ewk_view_tiled_smart_pre_render_region; 265 api->pre_render_relative_radius = _ewk_view_tiled_smart_pre_render_relative_radius; 266 api->pre_render_cancel = _ewk_view_tiled_smart_pre_render_cancel; 267 api->disable_render = _ewk_view_tiled_smart_disable_render; 268 api->enable_render = _ewk_view_tiled_smart_enable_render; 269 return EINA_TRUE; 270 } 271 272 static inline Evas_Smart *_ewk_view_tiled_smart_class_new(void) 273 { 274 static Ewk_View_Smart_Class api = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("EWK_View_Tiled"); 275 static Evas_Smart *smart = 0; 276 277 if (EINA_UNLIKELY(!smart)) { 278 ewk_view_tiled_smart_set(&api); 279 smart = evas_smart_class_new(&api.sc); 280 } 281 282 return smart; 283 } 284 285 /** 286 * Creates a new EFL WebKit View object using tiled backing store. 287 * 288 * View objects are the recommended way to deal with EFL WebKit as it 289 * abstracts the complex pieces of the process. 290 * 291 * This object is almost the same as the one returned by the ewk_view_add() 292 * function, but it uses the tiled backing store instead of the default 293 * backing store. 294 * 295 * @param e canvas where to create the view object. 296 * 297 * @return view object or @c NULL if errors. 298 * 299 * @see ewk_view_uri_set() 300 */ 301 Evas_Object *ewk_view_tiled_add(Evas *e) 302 { 303 return evas_object_smart_add(e, _ewk_view_tiled_smart_class_new()); 304 } 305 306 /** 307 * Get the cache of unused tiles used by this view. 308 * 309 * @param o view object to get cache. 310 * @return instance of "cache of unused tiles" or @c NULL on errors. 311 */ 312 Ewk_Tile_Unused_Cache *ewk_view_tiled_unused_cache_get(const Evas_Object *o) 313 { 314 Ewk_View_Smart_Data *sd = ewk_view_smart_data_get(o); 315 EINA_SAFETY_ON_NULL_RETURN_VAL(sd, 0); 316 return ewk_tiled_backing_store_tile_unused_cache_get(sd->backing_store); 317 } 318 319 /** 320 * Set the cache of unused tiles used by this view. 321 * 322 * @param o view object to get cache. 323 * @param cache instance of "cache of unused tiles". This can be used 324 * to share a single cache amongst different views. The tiles 325 * from one view will not be used by the other! This is just to 326 * limit the group with amount of unused memory. 327 * If @c NULL is provided, then a new cache is created. 328 */ 329 void ewk_view_tiled_unused_cache_set(Evas_Object *o, Ewk_Tile_Unused_Cache *cache) 330 { 331 Ewk_View_Smart_Data *sd = ewk_view_smart_data_get(o); 332 EINA_SAFETY_ON_NULL_RETURN(sd); 333 ewk_tiled_backing_store_tile_unused_cache_set(sd->backing_store, cache); 334 } 335 336 /** 337 * Set the function with the same name of the tiled backing store. 338 * @param o the tiled backing store object. 339 * @param flag value of the tiled backing store flag to set. 340 */ 341 void ewk_view_tiled_process_entire_queue_set(Evas_Object *o, Eina_Bool flag) 342 { 343 Ewk_View_Smart_Data *sd = ewk_view_smart_data_get(o); 344 EINA_SAFETY_ON_NULL_RETURN(sd); 345 ewk_tiled_backing_store_process_entire_queue_set(sd->backing_store, flag); 346 } 347