ewk_view_single.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /*
  2. Copyright (C) 2009-2010 ProFUSION embedded systems
  3. Copyright (C) 2009-2010 Samsung Electronics
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public License
  13. along with this library; see the file COPYING.LIB. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. Boston, MA 02110-1301, USA.
  16. */
  17. #include "config.h"
  18. #include "ewk_view.h"
  19. #include "TiledBackingStore.h"
  20. #include "ewk_frame_private.h"
  21. #include "ewk_private.h"
  22. #include "ewk_view_private.h"
  23. #include <Ecore_Evas.h>
  24. #include <Evas.h>
  25. #include <eina_safety_checks.h>
  26. #include <string.h>
  27. #if ENABLE(INSPECTOR)
  28. #include "InspectorController.h"
  29. #include "Page.h"
  30. #endif
  31. static Ewk_View_Smart_Class _parent_sc = EWK_VIEW_SMART_CLASS_INIT_NULL;
  32. static void _ewk_view_single_on_del(void* data, Evas*, Evas_Object*, void*)
  33. {
  34. Evas_Object* clip = (Evas_Object*)data;
  35. evas_object_del(clip);
  36. }
  37. static void _ewk_view_single_smart_add(Evas_Object* ewkView)
  38. {
  39. Ewk_View_Smart_Data* smartData;
  40. _parent_sc.sc.add(ewkView);
  41. smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(ewkView));
  42. if (!smartData)
  43. return;
  44. Evas_Object* clip = evas_object_rectangle_add(smartData->base.evas);
  45. evas_object_show(clip);
  46. evas_object_event_callback_add
  47. (smartData->backing_store, EVAS_CALLBACK_DEL, _ewk_view_single_on_del, clip);
  48. }
  49. static Evas_Object* _ewk_view_single_smart_backing_store_add(Ewk_View_Smart_Data* smartData)
  50. {
  51. Evas_Object* bs = evas_object_image_add(smartData->base.evas);
  52. EINA_SAFETY_ON_NULL_RETURN_VAL(bs, 0);
  53. const Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(smartData->base.evas);
  54. const char* engine = ecore_evas_engine_name_get(ecoreEvas);
  55. if (!strncmp(engine, "opengl_x11", strlen("opengl_x11")))
  56. evas_object_image_content_hint_set(bs, EVAS_IMAGE_CONTENT_HINT_DYNAMIC);
  57. evas_object_image_alpha_set(bs, false);
  58. evas_object_image_smooth_scale_set(bs, smartData->zoom_weak_smooth_scale);
  59. return bs;
  60. }
  61. static void _ewk_view_single_smart_resize(Evas_Object* ewkView, Evas_Coord width, Evas_Coord height)
  62. {
  63. Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(ewkView));
  64. _parent_sc.sc.resize(ewkView, width, height);
  65. if (!smartData)
  66. return;
  67. // these should be queued and processed in calculate as well!
  68. evas_object_image_size_set(smartData->backing_store, width, height);
  69. if (smartData->animated_zoom.zoom.current < 0.00001) {
  70. Evas_Object* clip = evas_object_clip_get(smartData->backing_store);
  71. Evas_Coord x, y, cw, ch;
  72. evas_object_image_fill_set(smartData->backing_store, 0, 0, width, height);
  73. evas_object_geometry_get(smartData->backing_store, &x, &y, 0, 0);
  74. evas_object_move(clip, x, y);
  75. ewk_frame_contents_size_get(smartData->main_frame, &cw, &ch);
  76. if (width > cw)
  77. width = cw;
  78. if (height > ch)
  79. height = ch;
  80. evas_object_resize(clip, width, height);
  81. }
  82. }
  83. static inline void _ewk_view_screen_move(uint32_t* image, size_t destinationX, size_t destinationY, size_t sourceX, size_t sourceY, size_t copyWidth, size_t copyHeight, size_t imageWidth)
  84. {
  85. uint32_t* sourceBegin = image + (imageWidth * sourceY) + sourceX;
  86. uint32_t* destinationBegin = image + (imageWidth * destinationY) + destinationX;
  87. size_t copyLength = copyWidth * 4;
  88. const int moveLineUpDown = sourceY >= destinationY ? 1 : -1;
  89. int startHeight = sourceY >= destinationY ? 0 : copyHeight - 1;
  90. uint32_t* source, * destination;
  91. if ((destinationX > sourceX && destinationX < sourceX + copyWidth)
  92. || (destinationX < sourceX && destinationX + copyWidth > sourceX)) {
  93. for (size_t i = 0; i < copyHeight; i++) {
  94. source = sourceBegin + (imageWidth * startHeight);
  95. destination = destinationBegin + (imageWidth * startHeight);
  96. startHeight = startHeight + moveLineUpDown;
  97. memmove(destination, source, copyLength);
  98. }
  99. } else {
  100. for (size_t i = 0; i < copyHeight; i++) {
  101. source = sourceBegin + (imageWidth * startHeight);
  102. destination = destinationBegin + (imageWidth * startHeight);
  103. startHeight = startHeight + moveLineUpDown;
  104. memcpy(destination, source, copyLength);
  105. }
  106. }
  107. }
  108. static inline void _ewk_view_single_scroll_process_single(Ewk_View_Smart_Data* smartData, void* pixels, Evas_Coord width, Evas_Coord height, const WebCore::IntSize& scrollOffset, const WebCore::IntRect& rectToScroll)
  109. {
  110. int scrollX = rectToScroll.x();
  111. int scrollY = rectToScroll.y();
  112. int scrollWidth = rectToScroll.width();
  113. int scrollHeight = rectToScroll.height();
  114. DBG("%d,%d + %d,%d %+03d,%+03d, store: %p %dx%d",
  115. scrollX, scrollY, scrollWidth, scrollHeight, scrollOffset.width(), scrollOffset.height(), pixels, width, height);
  116. if (abs(scrollOffset.width()) >= scrollWidth || abs(scrollOffset.height()) >= scrollHeight) {
  117. ewk_view_repaint_add(smartData->_priv, scrollX, scrollY, scrollWidth, scrollHeight);
  118. return;
  119. }
  120. if (scrollX < 0) {
  121. scrollWidth += scrollX;
  122. scrollX = 0;
  123. }
  124. if (scrollY < 0) {
  125. scrollHeight += scrollY;
  126. scrollY = 0;
  127. }
  128. if (scrollX + scrollWidth > width)
  129. scrollWidth = width - scrollX;
  130. if (scrollY + scrollHeight > height)
  131. scrollHeight = height - scrollY;
  132. if (scrollWidth <= 0 || scrollHeight <= 0)
  133. return;
  134. int sourceX = scrollOffset.width() < 0 ? abs(scrollOffset.width()) : 0;
  135. int sourceY = scrollOffset.height() < 0 ? abs(scrollOffset.height()) : 0;
  136. int destinationX = scrollOffset.width() < 0 ? 0 : scrollOffset.width();
  137. int destinationY = scrollOffset.height() < 0 ? 0 : scrollOffset.height();
  138. int copyWidth = scrollWidth - abs(scrollOffset.width());
  139. int copyHeight = scrollHeight - abs(scrollOffset.height());
  140. if (scrollOffset.width() || scrollOffset.height()) {
  141. _ewk_view_screen_move(static_cast<uint32_t*>(pixels), destinationX, destinationY, sourceX, sourceY, copyWidth, copyHeight, width);
  142. evas_object_image_data_update_add(smartData->backing_store, destinationX, destinationY, copyWidth, copyHeight);
  143. }
  144. Eina_Rectangle verticalUpdate;
  145. verticalUpdate.x = destinationX ? 0 : copyWidth - 1;
  146. verticalUpdate.y = 0;
  147. verticalUpdate.w = abs(scrollOffset.width());
  148. verticalUpdate.h = scrollHeight;
  149. if (verticalUpdate.w && verticalUpdate.h)
  150. ewk_view_repaint_add(smartData->_priv, verticalUpdate.x, verticalUpdate.y, verticalUpdate.w, verticalUpdate.h);
  151. Eina_Rectangle horizontalUpdate;
  152. horizontalUpdate.x = destinationX;
  153. horizontalUpdate.y = destinationY ? 0 : copyHeight - 1;
  154. horizontalUpdate.w = copyWidth;
  155. horizontalUpdate.h = abs(scrollOffset.height());
  156. if (horizontalUpdate.w && horizontalUpdate.h)
  157. ewk_view_repaint_add(smartData->_priv, horizontalUpdate.x, horizontalUpdate.y, horizontalUpdate.w, horizontalUpdate.h);
  158. }
  159. static Eina_Bool _ewk_view_single_smart_scrolls_process(Ewk_View_Smart_Data* smartData)
  160. {
  161. Evas_Coord imageWidth, imageHeight;
  162. void* pixels = evas_object_image_data_get(smartData->backing_store, 1);
  163. evas_object_image_size_get(smartData->backing_store, &imageWidth, &imageHeight);
  164. const WTF::Vector<WebCore::IntSize>& scrollOffset = ewk_view_scroll_offsets_get(smartData->_priv);
  165. const WTF::Vector<WebCore::IntRect>& rectsToScroll = ewk_view_scroll_rects_get(smartData->_priv);
  166. for (size_t i = 0; i < scrollOffset.size(); ++i)
  167. _ewk_view_single_scroll_process_single(smartData, pixels, imageWidth, imageHeight, scrollOffset[i], rectsToScroll[i]);
  168. evas_object_image_data_set(smartData->backing_store, pixels);
  169. return true;
  170. }
  171. static Eina_Bool _ewk_view_single_smart_repaints_process(Ewk_View_Smart_Data* smartData)
  172. {
  173. if (smartData->animated_zoom.zoom.current < 0.00001) {
  174. Evas_Object* clip = evas_object_clip_get(smartData->backing_store);
  175. // reset effects of zoom_weak_set()
  176. evas_object_image_fill_set(smartData->backing_store, 0, 0, smartData->view.w, smartData->view.h);
  177. evas_object_move(clip, smartData->view.x, smartData->view.y);
  178. Evas_Coord width = smartData->view.w;
  179. Evas_Coord height = smartData->view.h;
  180. Evas_Coord centerWidth, centerHeight;
  181. ewk_frame_contents_size_get(smartData->main_frame, &centerWidth, &centerHeight);
  182. if (width > centerWidth)
  183. width = centerWidth;
  184. if (height > centerHeight)
  185. height = centerHeight;
  186. evas_object_resize(clip, width, height);
  187. }
  188. Evas_Coord imageWidth, imageHeight;
  189. evas_object_image_size_get(smartData->backing_store, &imageWidth, &imageHeight);
  190. Eina_Tiler* tiler = eina_tiler_new(imageWidth, imageHeight);
  191. if (!tiler) {
  192. ERR("could not create tiler %dx%d", imageWidth, imageHeight);
  193. return false;
  194. }
  195. ewk_view_layout_if_needed_recursive(smartData->_priv);
  196. size_t count;
  197. const Eina_Rectangle* paintRequest = ewk_view_repaints_pop(smartData->_priv, &count);
  198. const Eina_Rectangle* paintRequestEnd = paintRequest + count;
  199. for (; paintRequest < paintRequestEnd; paintRequest++)
  200. eina_tiler_rect_add(tiler, paintRequest);
  201. Eina_Iterator* iterator = eina_tiler_iterator_new(tiler);
  202. if (!iterator) {
  203. ERR("could not get iterator for tiler");
  204. eina_tiler_free(tiler);
  205. return false;
  206. }
  207. #if USE(TILED_BACKING_STORE)
  208. WebCore::Frame* mainFrame = EWKPrivate::coreFrame(smartData->main_frame);
  209. if (mainFrame && mainFrame->tiledBackingStore())
  210. mainFrame->tiledBackingStore()->coverWithTilesIfNeeded();
  211. #endif
  212. Ewk_Paint_Context* context = ewk_paint_context_from_image_new(smartData->backing_store);
  213. ewk_paint_context_save(context);
  214. Eina_Rectangle* rect;
  215. EINA_ITERATOR_FOREACH(iterator, rect) {
  216. ewk_view_paint(smartData->_priv, context, rect);
  217. evas_object_image_data_update_add(smartData->backing_store, rect->x, rect->y, rect->w, rect->h);
  218. }
  219. #if ENABLE(INSPECTOR)
  220. WebCore::Page* page = EWKPrivate::corePage(smartData->self);
  221. if (page) {
  222. WebCore::InspectorController* controller = page->inspectorController();
  223. if (controller->highlightedNode())
  224. controller->drawHighlight(*context->graphicContext);
  225. }
  226. #endif
  227. ewk_paint_context_restore(context);
  228. ewk_paint_context_free(context);
  229. eina_tiler_free(tiler);
  230. eina_iterator_free(iterator);
  231. return true;
  232. }
  233. static Eina_Bool _ewk_view_single_smart_zoom_weak_set(Ewk_View_Smart_Data* smartData, float zoom, Evas_Coord centerX, Evas_Coord centerY)
  234. {
  235. // TODO: review
  236. float scale = zoom / smartData->animated_zoom.zoom.start;
  237. Evas_Coord w = smartData->view.w * scale;
  238. Evas_Coord h = smartData->view.h * scale;
  239. Evas_Coord dx, dy, cw, ch;
  240. Evas_Object* clip = evas_object_clip_get(smartData->backing_store);
  241. ewk_frame_contents_size_get(smartData->main_frame, &cw, &ch);
  242. if (smartData->view.w > 0 && smartData->view.h > 0) {
  243. dx = (w * (smartData->view.w - centerX)) / smartData->view.w;
  244. dy = (h * (smartData->view.h - centerY)) / smartData->view.h;
  245. } else {
  246. dx = 0;
  247. dy = 0;
  248. }
  249. evas_object_image_fill_set(smartData->backing_store, centerX + dx, centerY + dy, w, h);
  250. if (smartData->view.w > 0 && smartData->view.h > 0) {
  251. dx = ((smartData->view.w - w) * centerX) / smartData->view.w;
  252. dy = ((smartData->view.h - h) * centerY) / smartData->view.h;
  253. } else {
  254. dx = 0;
  255. dy = 0;
  256. }
  257. evas_object_move(clip, smartData->view.x + dx, smartData->view.y + dy);
  258. if (cw < smartData->view.w)
  259. w = cw * scale;
  260. if (ch < smartData->view.h)
  261. h = ch * scale;
  262. evas_object_resize(clip, w, h);
  263. return true;
  264. }
  265. static void _ewk_view_single_smart_zoom_weak_smooth_scale_set(Ewk_View_Smart_Data* smartData, Eina_Bool smooth_scale)
  266. {
  267. evas_object_image_smooth_scale_set(smartData->backing_store, smooth_scale);
  268. }
  269. static void _ewk_view_single_smart_bg_color_set(Ewk_View_Smart_Data* smartData, unsigned char /*red*/, unsigned char /*green*/, unsigned char /*blue*/, unsigned char alpha)
  270. {
  271. evas_object_image_alpha_set(smartData->backing_store, alpha < 255);
  272. }
  273. Eina_Bool ewk_view_single_smart_set(Ewk_View_Smart_Class* api)
  274. {
  275. if (!ewk_view_base_smart_set(api))
  276. return false;
  277. if (EINA_UNLIKELY(!_parent_sc.sc.add))
  278. ewk_view_base_smart_set(&_parent_sc);
  279. api->sc.add = _ewk_view_single_smart_add;
  280. api->sc.resize = _ewk_view_single_smart_resize;
  281. api->backing_store_add = _ewk_view_single_smart_backing_store_add;
  282. api->scrolls_process = _ewk_view_single_smart_scrolls_process;
  283. api->repaints_process = _ewk_view_single_smart_repaints_process;
  284. api->zoom_weak_set = _ewk_view_single_smart_zoom_weak_set;
  285. api->zoom_weak_smooth_scale_set = _ewk_view_single_smart_zoom_weak_smooth_scale_set;
  286. api->bg_color_set = _ewk_view_single_smart_bg_color_set;
  287. return true;
  288. }
  289. static inline Evas_Smart* _ewk_view_single_smart_class_new(void)
  290. {
  291. static Ewk_View_Smart_Class api = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION(ewkViewSingleName);
  292. static Evas_Smart* smart = 0;
  293. if (EINA_UNLIKELY(!smart)) {
  294. ewk_view_single_smart_set(&api);
  295. smart = evas_smart_class_new(&api.sc);
  296. }
  297. return smart;
  298. }
  299. Evas_Object* ewk_view_single_add(Evas* canvas)
  300. {
  301. return evas_object_smart_add(canvas, _ewk_view_single_smart_class_new());
  302. }