Home | History | Annotate | Download | only in ewk
      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