static void invalidateView(Evas_Object* webView) { Evas_Coord width, height; Evas_Object* mainFrame = ewk_view_frame_main_get(webView); if (mainFrame && ewk_frame_contents_size_get(mainFrame, &width, &height)) { WebCore::Page* page = EWKPrivate::corePage(webView); if (page) page->mainFrame()->view()->invalidateRect(WebCore::IntRect(0, 0, width, height)); } }
static Eina_Bool _ewk_view_tiled_smart_scrolls_process(Ewk_View_Smart_Data* smartData) { const Ewk_Scroll_Request* scrollRequest; const Ewk_Scroll_Request* endOfScrollRequest; size_t count; Evas_Coord contentsWidth, contentsHeight; ewk_frame_contents_size_get(smartData->main_frame, &contentsWidth, &contentsHeight); scrollRequest = ewk_view_scroll_requests_get(smartData->_priv, &count); endOfScrollRequest = scrollRequest + count; for (; scrollRequest < endOfScrollRequest; scrollRequest++) { if (scrollRequest->main_scroll) ewk_tiled_backing_store_scroll_full_offset_add (smartData->backing_store, scrollRequest->dx, scrollRequest->dy); else { Evas_Coord scrollX, scrollY, scrollWidth, scrollHeight; scrollX = scrollRequest->x; scrollY = scrollRequest->y; scrollWidth = scrollRequest->w; scrollHeight = scrollRequest->h; if (abs(scrollRequest->dx) >= scrollWidth || abs(scrollRequest->dy) >= scrollHeight) { /* doubt webkit would be so stupid... */ DBG("full page scroll %+03d,%+03d. convert to repaint %d,%d + %dx%d", scrollRequest->dx, scrollRequest->dy, scrollX, scrollY, scrollWidth, scrollHeight); ewk_view_repaint_add(smartData->_priv, scrollX, scrollY, scrollWidth, scrollHeight); continue; } if (scrollX + scrollWidth > contentsWidth) scrollWidth = contentsWidth - scrollX; if (scrollY + scrollHeight > contentsHeight) scrollHeight = contentsHeight - scrollY; if (scrollWidth < 0) scrollWidth = 0; if (scrollHeight < 0) scrollHeight = 0; if (!scrollWidth || !scrollHeight) continue; scrollX -= abs(scrollRequest->dx); scrollY -= abs(scrollRequest->dy); scrollWidth += abs(scrollRequest->dx); scrollHeight += abs(scrollRequest->dy); ewk_view_repaint_add(smartData->_priv, scrollX, scrollY, scrollWidth, scrollHeight); INF("using repaint for inner frame scolling!"); } } return true; }
static Eina_Bool _ewk_view_tiled_smart_scrolls_process(Ewk_View_Smart_Data *sd) { const Ewk_Scroll_Request *sr; const Ewk_Scroll_Request *sr_end; size_t count; Evas_Coord vw, vh; ewk_frame_contents_size_get(sd->main_frame, &vw, &vh); sr = ewk_view_scroll_requests_get(sd->_priv, &count); sr_end = sr + count; for (; sr < sr_end; sr++) { if (sr->main_scroll) ewk_tiled_backing_store_scroll_full_offset_add (sd->backing_store, sr->dx, sr->dy); else { Evas_Coord sx, sy, sw, sh; sx = sr->x; sy = sr->y; sw = sr->w; sh = sr->h; if (abs(sr->dx) >= sw || abs(sr->dy) >= sh) { /* doubt webkit would be so stupid... */ DBG("full page scroll %+03d,%+03d. convert to repaint %d,%d + %dx%d", sr->dx, sr->dy, sx, sy, sw, sh); ewk_view_repaint_add(sd->_priv, sx, sy, sw, sh); continue; } if (sx + sw > vw) sw = vw - sx; if (sy + sh > vh) sh = vh - sy; if (sw < 0) sw = 0; if (sh < 0) sh = 0; if (!sw || !sh) continue; sx -= abs(sr->dx); sy -= abs(sr->dy); sw += abs(sr->dx); sh += abs(sr->dy); ewk_view_repaint_add(sd->_priv, sx, sy, sw, sh); INF("using repaint for inner frame scolling!"); } } return EINA_TRUE; }
static Eina_Bool _ewk_view_tiled_smart_scrolls_process(Ewk_View_Smart_Data* smartData) { const Ewk_Scroll_Request* scrollRequest; const Ewk_Scroll_Request* endOfScrollRequest; size_t count; Evas_Coord contentsWidth, contentsHeight; ewk_frame_contents_size_get(smartData->main_frame, &contentsWidth, &contentsHeight); scrollRequest = ewk_view_scroll_requests_get(smartData->_priv, &count); endOfScrollRequest = scrollRequest + count; for (; scrollRequest < endOfScrollRequest; scrollRequest++) ewk_tiled_backing_store_scroll_full_offset_add(smartData->backing_store, scrollRequest->dx, scrollRequest->dy); return true; }
static void _ewk_view_single_smart_resize(Evas_Object *o, Evas_Coord w, Evas_Coord h) { Ewk_View_Smart_Data *sd = (Ewk_View_Smart_Data*)evas_object_smart_data_get(o); _parent_sc.sc.resize(o, w, h); // these should be queued and processed in calculate as well! evas_object_image_size_set(sd->backing_store, w, h); if (sd->animated_zoom.zoom.current < 0.00001) { Evas_Object *clip = evas_object_clip_get(sd->backing_store); Evas_Coord x, y, cw, ch; evas_object_image_fill_set(sd->backing_store, 0, 0, w, h); evas_object_geometry_get(sd->backing_store, &x, &y, 0, 0); evas_object_move(clip, x, y); ewk_frame_contents_size_get(sd->main_frame, &cw, &ch); if (w > cw) w = cw; if (h > ch) h = ch; evas_object_resize(clip, w, h); } }
static void _ewk_view_single_smart_resize(Evas_Object* ewkView, Evas_Coord width, Evas_Coord height) { Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(ewkView)); _parent_sc.sc.resize(ewkView, width, height); if (!smartData) return; // these should be queued and processed in calculate as well! evas_object_image_size_set(smartData->backing_store, width, height); if (smartData->animated_zoom.zoom.current < 0.00001) { Evas_Object* clip = evas_object_clip_get(smartData->backing_store); Evas_Coord x, y, cw, ch; evas_object_image_fill_set(smartData->backing_store, 0, 0, width, height); evas_object_geometry_get(smartData->backing_store, &x, &y, 0, 0); evas_object_move(clip, x, y); ewk_frame_contents_size_get(smartData->main_frame, &cw, &ch); if (width > cw) width = cw; if (height > ch) height = ch; evas_object_resize(clip, width, height); } }
static Eina_Bool _ewk_view_single_smart_zoom_weak_set(Ewk_View_Smart_Data *sd, float zoom, Evas_Coord cx, Evas_Coord cy) { // TODO: review float scale = zoom / sd->animated_zoom.zoom.start; Evas_Coord w = sd->view.w * scale; Evas_Coord h = sd->view.h * scale; Evas_Coord dx, dy, cw, ch; Evas_Object *clip = evas_object_clip_get(sd->backing_store); ewk_frame_contents_size_get(sd->main_frame, &cw, &ch); if (sd->view.w > 0 && sd->view.h > 0) { dx = (w * (sd->view.w - cx)) / sd->view.w; dy = (h * (sd->view.h - cy)) / sd->view.h; } else { dx = 0; dy = 0; } evas_object_image_fill_set(sd->backing_store, cx + dx, cy + dy, w, h); if (sd->view.w > 0 && sd->view.h > 0) { dx = ((sd->view.w - w) * cx) / sd->view.w; dy = ((sd->view.h - h) * cy) / sd->view.h; } else { dx = 0; dy = 0; } evas_object_move(clip, sd->view.x + dx, sd->view.y + dy); if (cw < sd->view.w) w = cw * scale; if (ch < sd->view.h) h = ch * scale; evas_object_resize(clip, w, h); return EINA_TRUE; }
static Eina_Bool _ewk_view_single_smart_repaints_process(Ewk_View_Smart_Data* smartData) { if (smartData->animated_zoom.zoom.current < 0.00001) { Evas_Object* clip = evas_object_clip_get(smartData->backing_store); // reset effects of zoom_weak_set() evas_object_image_fill_set(smartData->backing_store, 0, 0, smartData->view.w, smartData->view.h); evas_object_move(clip, smartData->view.x, smartData->view.y); Evas_Coord width = smartData->view.w; Evas_Coord height = smartData->view.h; Evas_Coord centerWidth, centerHeight; ewk_frame_contents_size_get(smartData->main_frame, ¢erWidth, ¢erHeight); if (width > centerWidth) width = centerWidth; if (height > centerHeight) height = centerHeight; evas_object_resize(clip, width, height); } Evas_Coord imageWidth, imageHeight; evas_object_image_size_get(smartData->backing_store, &imageWidth, &imageHeight); Eina_Tiler* tiler = eina_tiler_new(imageWidth, imageHeight); if (!tiler) { ERR("could not create tiler %dx%d", imageWidth, imageHeight); return false; } ewk_view_layout_if_needed_recursive(smartData->_priv); size_t count; const Eina_Rectangle* paintRequest = ewk_view_repaints_pop(smartData->_priv, &count); const Eina_Rectangle* paintRequestEnd = paintRequest + count; for (; paintRequest < paintRequestEnd; paintRequest++) eina_tiler_rect_add(tiler, paintRequest); Eina_Iterator* iterator = eina_tiler_iterator_new(tiler); if (!iterator) { ERR("could not get iterator for tiler"); eina_tiler_free(tiler); return false; } #if USE(TILED_BACKING_STORE) WebCore::Frame* mainFrame = EWKPrivate::coreFrame(smartData->main_frame); if (mainFrame && mainFrame->tiledBackingStore()) mainFrame->tiledBackingStore()->coverWithTilesIfNeeded(); #endif Ewk_Paint_Context* context = ewk_paint_context_from_image_new(smartData->backing_store); ewk_paint_context_save(context); Eina_Rectangle* rect; EINA_ITERATOR_FOREACH(iterator, rect) { ewk_view_paint(smartData->_priv, context, rect); evas_object_image_data_update_add(smartData->backing_store, rect->x, rect->y, rect->w, rect->h); }
/* calculates one good zoom level to fit given hit test result */ static float _view_zoom_fits_hit(View_Smart_Data *sd, const Ewk_Hit_Test *hit_test) { Evas_Coord x, y; /* hit test point */ Evas_Coord bx, by, bw, bh, bw1, bw2, bh1, bh2; /* bounding box */ Evas_Coord vx, vy, vw, vh, vw1, vw2, vh1, vh2; /* visible content */ Evas_Coord cw, ch; float zx, zy, z, old_zoom, zx1, zx2, zy1, zy2; if (!hit_test) return 0.0; old_zoom = ewk_frame_page_zoom_get(sd->base.main_frame); /* save some typing */ x = hit_test->x; y = hit_test->y; bx = hit_test->bounding_box.x; by = hit_test->bounding_box.y; bw = hit_test->bounding_box.w; bh = hit_test->bounding_box.h; if ((bw <= 0) || (bh <= 0)) return 0.0; ewk_frame_visible_content_geometry_get (sd->base.main_frame, EINA_FALSE, &vx, &vy, &vw, &vh); if ((vw <= 0) || (vh <= 0)) return 0.0; ewk_frame_contents_size_get(sd->base.main_frame, &cw, &ch); if ((cw <= 0) || (ch <= 0)) return 0.0; /* split width of left and right parts from hit test position */ bw1 = x - bx; bw2 = bw - bw1; /* split height of top and bottom parts from hit test position */ bh1 = y - by; bh2 = bh - bh1; /* split size of viewport as well. We'll use this as the available space */ vw1 = x - vx; vw2 = vw - vw1; vh1 = y - vy; vh2 = vh - vh1; /* check if we can add padding around those sizes, "adding" if possible * (we actually subtract as adding a pad is removing available space) */ if (vw1 > ZOOM_AUTO_PADDING) vw1 -= ZOOM_AUTO_PADDING; if (vw2 > ZOOM_AUTO_PADDING) vw2 -= ZOOM_AUTO_PADDING; if (vh1 > ZOOM_AUTO_PADDING) vh1 -= ZOOM_AUTO_PADDING; if (vh2 > ZOOM_AUTO_PADDING) vh2 -= ZOOM_AUTO_PADDING; /* check individual zoom to fit each part */ zx1 = (bw1 > 0) ? (vw1 / (float)bw1) : 0.0; zx2 = (bw2 > 0) ? (vw2 / (float)bw2) : 0.0; zy1 = (bh1 > 0) ? (vh1 / (float)bh1) : 0.0; zy2 = (bh2 > 0) ? (vh2 / (float)bh2) : 0.0; if ((zx1 >= ZOOM_AUTO_MIN_DIFFERENCE) && (zx2 >= ZOOM_AUTO_MIN_DIFFERENCE)) zx = (zx1 < zx2) ? zx1 : zx2; else if (zx1 >= ZOOM_AUTO_MIN_DIFFERENCE) zx = zx1; else zx = zx2; if ((zy1 >= ZOOM_AUTO_MIN_DIFFERENCE) && (zy2 >= ZOOM_AUTO_MIN_DIFFERENCE)) zy = (zy1 < zy2) ? zy1 : zy2; else if (zy1 >= ZOOM_AUTO_MIN_DIFFERENCE) zy = zy1; else zy = zy2; if ((zx >= ZOOM_AUTO_MIN_DIFFERENCE) && (zy >= ZOOM_AUTO_MIN_DIFFERENCE)) z = (zx < zy) ? zx : zy; else if (zx >= ZOOM_AUTO_MIN_DIFFERENCE) z = zx; else z = zy; /* zoom will make contents be smaller than viewport, limit it */ if (((int)(z * old_zoom * cw) < vw) || ((int)(z * old_zoom * ch) < vh)) { float ac = cw / (float)ch; float av = vw / (float)vh; if (ac < av) z = vw / (float)cw; else z = vh / (float)ch; } #if 0 /* debug */ printf(">>> fit: center=%3d,%3d box=%3d,%3d+%3dx%3d\n" " x: %3d = %3d + %3d, %3d = %3d + %3d, %2.4f %2.4f -> %2.4f\n" " y: %3d = %3d + %3d, %3d = %3d + %3d, %2.4f %2.4f -> %2.4f\n" " final: %2.4f %2.4f (old=%0.3f, difference=%0.3f)\n" " contents: %4dx%4d -> %4dx%4d\n" "\n", x, y, bx, by, bw, bh, bw, bw1, bw2, vw, vw1, vw2, zx1, zx2, zx, bh, bh1, bh2, vh, vh1, vh2, zy1, zy2, zy, z, old_zoom * z, old_zoom, fabs(old_zoom - z), cw, ch, (int)(z * old_zoom * cw), (int)(z * old_zoom * ch)); #endif z *= old_zoom; if (z < ZOOM_AUTO_MIN) z = ZOOM_AUTO_MIN; else if (z > ZOOM_AUTO_MAX) z = ZOOM_AUTO_MAX; if (fabs(old_zoom - z) < ZOOM_AUTO_MIN_DIFFERENCE) return 0.0; return z; }
static Eina_Bool _ewk_view_single_smart_repaints_process(Ewk_View_Smart_Data *sd) { Ewk_View_Paint_Context *ctxt; Evas_Coord ow, oh; void *pixels; Eina_Rectangle r = {0, 0, 0, 0}; const Eina_Rectangle *pr; const Eina_Rectangle *pr_end; Eina_Tiler *tiler; Eina_Iterator *itr; cairo_status_t status; cairo_surface_t *surface; cairo_format_t format; cairo_t *cairo; size_t count; Eina_Bool ret = EINA_TRUE; if (sd->animated_zoom.zoom.current < 0.00001) { Evas_Object *clip = evas_object_clip_get(sd->backing_store); Evas_Coord w, h, cw, ch; // reset effects of zoom_weak_set() evas_object_image_fill_set (sd->backing_store, 0, 0, sd->view.w, sd->view.h); evas_object_move(clip, sd->view.x, sd->view.y); w = sd->view.w; h = sd->view.h; ewk_frame_contents_size_get(sd->main_frame, &cw, &ch); if (w > cw) w = cw; if (h > ch) h = ch; evas_object_resize(clip, w, h); } pixels = evas_object_image_data_get(sd->backing_store, 1); evas_object_image_size_get(sd->backing_store, &ow, &oh); if (sd->bg_color.a < 255) format = CAIRO_FORMAT_ARGB32; else format = CAIRO_FORMAT_RGB24; surface = cairo_image_surface_create_for_data ((unsigned char*)pixels, format, ow, oh, ow * 4); status = cairo_surface_status(surface); if (status != CAIRO_STATUS_SUCCESS) { ERR("could not create surface from data %dx%d: %s", ow, oh, cairo_status_to_string(status)); ret = EINA_FALSE; goto error_cairo_surface; } cairo = cairo_create(surface); status = cairo_status(cairo); if (status != CAIRO_STATUS_SUCCESS) { ERR("could not create cairo from surface %dx%d: %s", ow, oh, cairo_status_to_string(status)); ret = EINA_FALSE; goto error_cairo; } ctxt = ewk_view_paint_context_new(sd->_priv, cairo); if (!ctxt) { ERR("could not create paint context"); ret = EINA_FALSE; goto error_paint_context; } tiler = eina_tiler_new(ow, oh); if (!tiler) { ERR("could not create tiler %dx%d", ow, oh); ret = EINA_FALSE; goto error_tiler; } pr = ewk_view_repaints_get(sd->_priv, &count); pr_end = pr + count; for (; pr < pr_end; pr++) eina_tiler_rect_add(tiler, pr); itr = eina_tiler_iterator_new(tiler); if (!itr) { ERR("could not get iterator for tiler"); ret = EINA_FALSE; goto error_iterator; } int sx, sy; ewk_frame_scroll_pos_get(sd->main_frame, &sx, &sy); EINA_ITERATOR_FOREACH(itr, r) { Eina_Rectangle scrolled_rect = { r.x + sx, r.y + sy, r.w, r.h }; ewk_view_paint_context_save(ctxt); if ((sx) || (sy)) ewk_view_paint_context_translate(ctxt, -sx, -sy); ewk_view_paint_context_clip(ctxt, &scrolled_rect); ewk_view_paint_context_paint_contents(ctxt, &scrolled_rect); ewk_view_paint_context_restore(ctxt); evas_object_image_data_update_add (sd->backing_store, r.x, r.y, r.w, r.h); }
static Eina_Bool _ewk_view_tiled_smart_pre_render_start(Ewk_View_Smart_Data* smartData) { int contentWidth, contentHeight; ewk_frame_contents_size_get(smartData->main_frame, &contentWidth, &contentHeight); int viewX, viewY, viewWidth, viewHeight; ewk_frame_visible_content_geometry_get(smartData->main_frame, false, &viewX, &viewY, &viewWidth, &viewHeight); if (viewWidth <= 0 || viewHeight <= 0 || contentWidth <= 0 || contentHeight <= 0) return false; if (viewWidth >= contentWidth && viewHeight >= contentHeight) return false; int previousViewX, previousViewY; previousViewX = smartData->previousView.x; previousViewY = smartData->previousView.y; if (previousViewX < 0 || previousViewX > contentWidth || previousViewY < 0 || previousViewY > contentHeight) previousViewX = previousViewY = 0; float currentViewZoom = ewk_view_zoom_get(smartData->self); // pre-render works when two conditions are met. // zoom has been changed. // and the view has been moved more than tile size. if (abs(previousViewX - viewX) < defaultTileWidth && abs(previousViewY - viewY) < defaultTileHeigth && smartData->previousView.zoom == currentViewZoom) { return false; } // store previous view position and zoom. smartData->previousView.x = viewX; smartData->previousView.y = viewY; smartData->previousView.zoom = currentViewZoom; // cancelling previous pre-rendering list if exists. ewk_view_pre_render_cancel(smartData->self); Ewk_Tile_Unused_Cache* tileUnusedCache = ewk_view_tiled_unused_cache_get(smartData->self); int maxMemory = ewk_tile_unused_cache_max_get(tileUnusedCache); if (maxMemory <= viewWidth * viewHeight * EWK_ARGB_BYTES_SIZE) return false; Eina_Rectangle viewRect = {viewX, viewY, viewWidth, viewHeight}; Eina_Rectangle contentRect = {0, 0, contentWidth, contentHeight}; // get a base render rect. const int contentMemory = contentWidth * contentHeight * EWK_ARGB_BYTES_SIZE; // get render rect's width and height. Eina_Rectangle renderRect; if (maxMemory > contentMemory) renderRect = contentRect; else { // Make a base rectangle as big as possible with using maxMemory. // and then reshape the base rectangle to fit to contents. const int baseSize = static_cast<int>(sqrt(maxMemory / 4.0f)); const float widthRate = (viewRect.w + (defaultTileWidth * 2)) / static_cast<float>(baseSize); const float heightRate = baseSize / static_cast<float>(contentHeight); const float rectRate = std::max(widthRate, heightRate); renderRect.w = static_cast<int>(baseSize * rectRate); renderRect.h = static_cast<int>(baseSize / rectRate); renderRect.x = viewRect.x + (viewRect.w / 2) - (renderRect.w / 2); renderRect.y = viewRect.y + (viewRect.h / 2) - (renderRect.h / 2); // reposition of renderRect, if the renderRect overlapped the content rect, this code moves the renderRect inside the content rect. int collisionSide = _ewk_view_tiled_rect_collision_check(renderRect, contentRect); if (collisionSide > 0) _ewk_view_tiled_rect_collision_resolve(collisionSide, &renderRect, contentRect); // check abnormal render rect if (renderRect.x < 0) renderRect.x = 0; if (renderRect.y < 0) renderRect.y = 0; if (renderRect.w > contentWidth) renderRect.w = contentWidth; if (renderRect.h > contentHeight) renderRect.h = contentHeight; } // enqueue tiles into tiled backing store in spiral order. ewk_tiled_backing_store_pre_render_spiral_queue(smartData->backing_store, &viewRect, &renderRect, maxMemory, currentViewZoom); return true; }
static Eina_Bool _ewk_view_single_smart_repaints_process(Ewk_View_Smart_Data* smartData) { Ewk_View_Paint_Context* context; Evas_Coord ow, oh; void* pixels; Eina_Rectangle* rect; const Eina_Rectangle* pr; const Eina_Rectangle* pr_end; Eina_Tiler* tiler; Eina_Iterator* iterator; cairo_status_t status; cairo_surface_t* surface; cairo_format_t format; cairo_t* cairo; size_t count; Eina_Bool result = true; if (smartData->animated_zoom.zoom.current < 0.00001) { Evas_Object* clip = evas_object_clip_get(smartData->backing_store); Evas_Coord width, height, centerWidth, centerHeight; // reset effects of zoom_weak_set() evas_object_image_fill_set (smartData->backing_store, 0, 0, smartData->view.w, smartData->view.h); evas_object_move(clip, smartData->view.x, smartData->view.y); width = smartData->view.w; height = smartData->view.h; ewk_frame_contents_size_get(smartData->main_frame, ¢erWidth, ¢erHeight); if (width > centerWidth) width = centerWidth; if (height > centerHeight) height = centerHeight; evas_object_resize(clip, width, height); } pixels = evas_object_image_data_get(smartData->backing_store, 1); evas_object_image_size_get(smartData->backing_store, &ow, &oh); format = CAIRO_FORMAT_ARGB32; surface = cairo_image_surface_create_for_data (static_cast<unsigned char*>(pixels), format, ow, oh, ow * 4); status = cairo_surface_status(surface); if (status != CAIRO_STATUS_SUCCESS) { ERR("could not create surface from data %dx%d: %s", ow, oh, cairo_status_to_string(status)); result = false; goto error_cairo_surface; } cairo = cairo_create(surface); status = cairo_status(cairo); if (status != CAIRO_STATUS_SUCCESS) { ERR("could not create cairo from surface %dx%d: %s", ow, oh, cairo_status_to_string(status)); result = false; goto error_cairo; } context = ewk_view_paint_context_new(smartData->_priv, cairo); if (!context) { ERR("could not create paint context"); result = false; goto error_paint_context; } tiler = eina_tiler_new(ow, oh); if (!tiler) { ERR("could not create tiler %dx%d", ow, oh); result = false; goto error_tiler; } ewk_view_layout_if_needed_recursive(smartData->_priv); pr = ewk_view_repaints_pop(smartData->_priv, &count); pr_end = pr + count; for (; pr < pr_end; pr++) eina_tiler_rect_add(tiler, pr); iterator = eina_tiler_iterator_new(tiler); if (!iterator) { ERR("could not get iterator for tiler"); result = false; goto error_iterator; } int scrollX, scrollY; ewk_frame_scroll_pos_get(smartData->main_frame, &scrollX, &scrollY); EINA_ITERATOR_FOREACH(iterator, rect) { Eina_Rectangle scrolled_rect = { rect->x + scrollX, rect->y + scrollY, rect->w, rect->h }; ewk_view_paint_context_save(context); if ((scrollX) || (scrollY)) ewk_view_paint_context_translate(context, -scrollX, -scrollY); ewk_view_paint_context_clip(context, &scrolled_rect); ewk_view_paint_context_paint_contents(context, &scrolled_rect); ewk_view_paint_context_restore(context); evas_object_image_data_update_add (smartData->backing_store, rect->x, rect->y, rect->w, rect->h); }