dc_client.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. /*
  2. * File : dc_client.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2009-10-16 Bernard first version
  13. * 2010-08-09 Bernard rename hardware dc to client dc
  14. */
  15. #include <rtgui/dc.h>
  16. #include <rtgui/dc_hw.h>
  17. #include <rtgui/dc_client.h>
  18. #include <rtgui/driver.h>
  19. #include <rtgui/rtgui_system.h>
  20. #include <rtgui/widgets/view.h>
  21. #include <rtgui/widgets/window.h>
  22. #include <rtgui/widgets/workbench.h>
  23. #include <rtgui/widgets/title.h>
  24. static void rtgui_dc_client_draw_point(struct rtgui_dc* dc, int x, int y);
  25. static void rtgui_dc_client_draw_color_point(struct rtgui_dc* dc, int x, int y, rtgui_color_t color);
  26. static void rtgui_dc_client_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y);
  27. static void rtgui_dc_client_draw_vline(struct rtgui_dc* dc, int x, int y1, int y2);
  28. static void rtgui_dc_client_fill_rect (struct rtgui_dc* dc, rtgui_rect_t* rect);
  29. static void rtgui_dc_client_blit (struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect);
  30. static void rtgui_dc_client_set_gc (struct rtgui_dc* dc, rtgui_gc_t *gc);
  31. static rtgui_gc_t *rtgui_dc_client_get_gc (struct rtgui_dc* dc);
  32. static rt_bool_t rtgui_dc_client_fini(struct rtgui_dc* dc);
  33. static rt_bool_t rtgui_dc_client_get_visible(struct rtgui_dc* dc);
  34. static void rtgui_dc_client_get_rect(struct rtgui_dc* dc, rtgui_rect_t* rect);
  35. #define hw_driver (rtgui_graphic_driver_get_default())
  36. #define dc_set_foreground(c) dc->gc.foreground = c
  37. #define dc_set_background(c) dc->gc.background = c
  38. struct rtgui_dc* rtgui_dc_begin_drawing(rtgui_widget_t* owner)
  39. {
  40. if (rtgui_region_is_flat(&owner->clip))
  41. {
  42. /* use hardware DC */
  43. return rtgui_dc_hw_create(owner);
  44. }
  45. return rtgui_dc_client_create(owner);
  46. }
  47. void rtgui_dc_end_drawing(struct rtgui_dc* dc)
  48. {
  49. dc->engine->fini(dc);
  50. }
  51. const struct rtgui_dc_engine dc_client_engine =
  52. {
  53. rtgui_dc_client_draw_point,
  54. rtgui_dc_client_draw_color_point,
  55. rtgui_dc_client_draw_vline,
  56. rtgui_dc_client_draw_hline,
  57. rtgui_dc_client_fill_rect,
  58. rtgui_dc_client_blit,
  59. rtgui_dc_client_set_gc,
  60. rtgui_dc_client_get_gc,
  61. rtgui_dc_client_get_visible,
  62. rtgui_dc_client_get_rect,
  63. rtgui_dc_client_fini,
  64. };
  65. void rtgui_dc_client_init(rtgui_widget_t* owner)
  66. {
  67. struct rtgui_dc* dc;
  68. RT_ASSERT(owner != RT_NULL);
  69. dc = RTGUI_WIDGET_DC(owner);
  70. dc->type = RTGUI_DC_CLIENT;
  71. dc->engine = &dc_client_engine;
  72. }
  73. extern struct rt_mutex cursor_mutex;
  74. extern void rtgui_mouse_show_cursor(void);
  75. extern void rtgui_mouse_hide_cursor(void);
  76. struct rtgui_dc* rtgui_dc_client_create(rtgui_widget_t* owner)
  77. {
  78. struct rtgui_dc* dc;
  79. rtgui_widget_t* widget;
  80. /* adjudge owner */
  81. if (owner == RT_NULL || owner->toplevel == RT_NULL) return RT_NULL;
  82. if (!RTGUI_IS_TOPLEVEL(owner->toplevel)) return RT_NULL;
  83. dc = RTGUI_WIDGET_DC(owner);
  84. /* set init visible as true */
  85. RTGUI_WIDGET_DC_SET_VISIBLE(owner);
  86. /* check widget visible */
  87. widget = owner;
  88. while (widget != RT_NULL)
  89. {
  90. if (RTGUI_WIDGET_IS_HIDE(widget))
  91. {
  92. RTGUI_WIDGET_DC_SET_UNVISIBLE(owner);
  93. break;
  94. }
  95. widget = widget->parent;
  96. }
  97. if (RTGUI_IS_WINTITLE(owner->toplevel))
  98. {
  99. rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);
  100. top->drawing ++;
  101. if (top->drawing == 1)
  102. {
  103. #ifdef RTGUI_USING_MOUSE_CURSOR
  104. #ifdef __WIN32__
  105. rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER);
  106. rt_kprintf("hide cursor\n");
  107. rtgui_mouse_hide_cursor();
  108. #else
  109. /* hide cursor */
  110. rtgui_mouse_hide_cursor();
  111. #endif
  112. #endif
  113. }
  114. }
  115. else if (RTGUI_IS_WORKBENCH(owner->toplevel) ||
  116. RTGUI_IS_WIN(owner->toplevel))
  117. {
  118. rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);
  119. top->drawing ++;
  120. if (top->drawing == 1)
  121. {
  122. #ifdef __WIN32__
  123. #ifdef RTGUI_USING_MOUSE_CURSOR
  124. rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER);
  125. rt_kprintf("hide cursor\n");
  126. rtgui_mouse_hide_cursor();
  127. #endif
  128. #else
  129. /* send draw begin to server */
  130. struct rtgui_event_update_begin eupdate;
  131. RTGUI_EVENT_UPDATE_BEGIN_INIT(&(eupdate));
  132. eupdate.rect = RTGUI_WIDGET(top)->extent;
  133. rtgui_thread_send(top->server, (struct rtgui_event*)&eupdate, sizeof(eupdate));
  134. #endif
  135. }
  136. }
  137. return dc;
  138. }
  139. static rt_bool_t rtgui_dc_client_fini(struct rtgui_dc* dc)
  140. {
  141. rtgui_widget_t* owner;
  142. if (dc == RT_NULL || dc->type != RTGUI_DC_CLIENT) return RT_FALSE;
  143. /* get owner */
  144. owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type);
  145. if (RTGUI_IS_WINTITLE(owner->toplevel))
  146. {
  147. /* update title extent */
  148. rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);
  149. top->drawing --;
  150. if ((top->drawing == 0) && RTGUI_WIDGET_IS_DC_VISIBLE(owner))
  151. {
  152. #ifdef __WIN32__
  153. #ifdef RTGUI_USING_MOUSE_CURSOR
  154. rt_mutex_release(&cursor_mutex);
  155. /* show cursor */
  156. rtgui_mouse_show_cursor();
  157. rt_kprintf("show cursor\n");
  158. #endif
  159. /* update screen */
  160. hw_driver->screen_update(&(owner->extent));
  161. #else
  162. #ifdef RTGUI_USING_MOUSE_CURSOR
  163. /* show cursor */
  164. rtgui_mouse_show_cursor();
  165. #endif
  166. /* update screen */
  167. hw_driver->screen_update(&(owner->extent));
  168. #endif
  169. }
  170. }
  171. else if (RTGUI_IS_WORKBENCH(owner->toplevel) ||
  172. RTGUI_IS_WIN(owner->toplevel))
  173. {
  174. rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);
  175. top->drawing --;
  176. if ((top->drawing == 0) && RTGUI_WIDGET_IS_DC_VISIBLE(owner))
  177. {
  178. #ifdef __WIN32__
  179. #ifdef RTGUI_USING_MOUSE_CURSOR
  180. rt_mutex_release(&cursor_mutex);
  181. /* show cursor */
  182. rtgui_mouse_show_cursor();
  183. rt_kprintf("show cursor\n");
  184. #endif
  185. /* update screen */
  186. hw_driver->screen_update(&(owner->extent));
  187. #else
  188. /* send to server to end drawing */
  189. struct rtgui_event_update_end eupdate;
  190. RTGUI_EVENT_UPDATE_END_INIT(&(eupdate));
  191. eupdate.rect = owner->extent;
  192. rtgui_thread_send(top->server, (struct rtgui_event*)&eupdate, sizeof(eupdate));
  193. #endif
  194. }
  195. }
  196. return RT_TRUE;
  197. }
  198. /*
  199. * draw a logic point on device
  200. */
  201. static void rtgui_dc_client_draw_point(struct rtgui_dc* self, int x, int y)
  202. {
  203. rtgui_rect_t rect;
  204. rtgui_widget_t *owner;
  205. if (self == RT_NULL) return;
  206. /* get owner */
  207. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  208. if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return;
  209. x = x + owner->extent.x1;
  210. y = y + owner->extent.y1;
  211. if (rtgui_region_contains_point(&(owner->clip), x, y, &rect) == RT_EOK)
  212. {
  213. /* draw this point */
  214. hw_driver->set_pixel(&(owner->gc.foreground), x, y);
  215. }
  216. }
  217. static void rtgui_dc_client_draw_color_point(struct rtgui_dc* self, int x, int y, rtgui_color_t color)
  218. {
  219. rtgui_rect_t rect;
  220. rtgui_widget_t *owner;
  221. if (self == RT_NULL) return;
  222. /* get owner */
  223. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  224. if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return;
  225. x = x + owner->extent.x1;
  226. y = y + owner->extent.y1;
  227. if (rtgui_region_contains_point(&(owner->clip), x, y, &rect) == RT_EOK)
  228. {
  229. /* draw this point */
  230. hw_driver->set_pixel(&color, x, y);
  231. }
  232. }
  233. /*
  234. * draw a logic vertical line on device
  235. */
  236. static void rtgui_dc_client_draw_vline(struct rtgui_dc* self, int x, int y1, int y2)
  237. {
  238. register rt_base_t index;
  239. rtgui_widget_t *owner;
  240. if (self == RT_NULL) return;
  241. /* get owner */
  242. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  243. if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return;
  244. x = x + owner->extent.x1;
  245. y1 = y1 + owner->extent.y1;
  246. y2 = y2 + owner->extent.y1;
  247. if (owner->clip.data == RT_NULL)
  248. {
  249. rtgui_rect_t* prect;
  250. prect = &(owner->clip.extents);
  251. /* calculate vline intersect */
  252. if (prect->x1 > x || prect->x2 <= x) return;
  253. if (prect->y2 <= y1 || prect->y1 > y2) return;
  254. if (prect->y1 > y1) y1 = prect->y1;
  255. if (prect->y2 < y2) y2 = prect->y2;
  256. /* draw vline */
  257. hw_driver->draw_vline(&(owner->gc.foreground), x, y1, y2);
  258. }
  259. else for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
  260. {
  261. rtgui_rect_t* prect;
  262. register rt_base_t draw_y1, draw_y2;
  263. prect = ((rtgui_rect_t *)(owner->clip.data + index + 1));
  264. draw_y1 = y1;
  265. draw_y2 = y2;
  266. /* calculate vline clip */
  267. if (prect->x1 > x || prect->x2 <= x) continue;
  268. if (prect->y2 <= y1 || prect->y1 > y2) continue;
  269. if (prect->y1 > y1) draw_y1 = prect->y1;
  270. if (prect->y2 < y2) draw_y2 = prect->y2;
  271. /* draw vline */
  272. hw_driver->draw_vline(&(owner->gc.foreground), x, draw_y1, draw_y2);
  273. }
  274. }
  275. /*
  276. * draw a logic horizontal line on device
  277. */
  278. static void rtgui_dc_client_draw_hline(struct rtgui_dc* self, int x1, int x2, int y)
  279. {
  280. register rt_base_t index;
  281. rtgui_widget_t *owner;
  282. if (self == RT_NULL) return;
  283. /* get owner */
  284. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  285. if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return;
  286. /* convert logic to device */
  287. x1 = x1 + owner->extent.x1;
  288. x2 = x2 + owner->extent.x1;
  289. y = y + owner->extent.y1;
  290. if (owner->clip.data == RT_NULL)
  291. {
  292. rtgui_rect_t* prect;
  293. prect = &(owner->clip.extents);
  294. /* calculate vline intersect */
  295. if (prect->y1 > y || prect->y2 <= y ) return;
  296. if (prect->x2 <= x1 || prect->x1 > x2) return;
  297. if (prect->x1 > x1) x1 = prect->x1;
  298. if (prect->x2 < x2) x2 = prect->x2;
  299. /* draw hline */
  300. hw_driver->draw_hline(&(owner->gc.foreground), x1, x2, y);
  301. }
  302. else for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
  303. {
  304. rtgui_rect_t* prect;
  305. register rt_base_t draw_x1, draw_x2;
  306. prect = ((rtgui_rect_t *)(owner->clip.data + index + 1));
  307. draw_x1 = x1;
  308. draw_x2 = x2;
  309. /* calculate hline clip */
  310. if (prect->y1 > y || prect->y2 <= y ) continue;
  311. if (prect->x2 <= x1 || prect->x1 > x2) continue;
  312. if (prect->x1 > x1) draw_x1 = prect->x1;
  313. if (prect->x2 < x2) draw_x2 = prect->x2;
  314. /* draw hline */
  315. hw_driver->draw_hline(&(owner->gc.foreground), draw_x1, draw_x2, y);
  316. }
  317. }
  318. static void rtgui_dc_client_fill_rect (struct rtgui_dc* self, struct rtgui_rect* rect)
  319. {
  320. rtgui_color_t foreground;
  321. register rt_base_t index;
  322. rtgui_widget_t *owner;
  323. if (self == RT_NULL) return;
  324. /* get owner */
  325. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  326. if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return;
  327. /* save foreground color */
  328. foreground = owner->gc.foreground;
  329. /* set background color as foreground color */
  330. owner->gc.foreground = owner->gc.background;
  331. /* fill rect */
  332. for (index = rect->y1; index < rect->y2; index ++)
  333. {
  334. rtgui_dc_client_draw_hline(self, rect->x1, rect->x2, index);
  335. }
  336. /* restore foreground color */
  337. owner->gc.foreground = foreground;
  338. }
  339. static void rtgui_dc_client_blit(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect)
  340. {
  341. /* not blit in hardware dc */
  342. return ;
  343. }
  344. static void rtgui_dc_client_set_gc(struct rtgui_dc* self, rtgui_gc_t *gc)
  345. {
  346. rtgui_widget_t *owner;
  347. if (self == RT_NULL) return;
  348. /* get owner */
  349. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  350. owner->gc = *gc;
  351. }
  352. static rtgui_gc_t* rtgui_dc_client_get_gc(struct rtgui_dc* self)
  353. {
  354. rtgui_widget_t *owner;
  355. if (self == RT_NULL)
  356. {
  357. rt_kprintf("why!!\n");
  358. return RT_NULL;
  359. }
  360. /* get owner */
  361. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  362. return &(owner->gc);
  363. }
  364. static rt_bool_t rtgui_dc_client_get_visible(struct rtgui_dc* self)
  365. {
  366. rtgui_widget_t *owner;
  367. if (self == RT_NULL) return RT_FALSE;
  368. /* get owner */
  369. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  370. if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return RT_FALSE;
  371. return RT_TRUE;
  372. }
  373. static void rtgui_dc_client_get_rect(struct rtgui_dc* self, rtgui_rect_t* rect)
  374. {
  375. rtgui_widget_t *owner;
  376. if (self == RT_NULL) return;
  377. /* get owner */
  378. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  379. rtgui_widget_get_rect(owner, rect);
  380. }
  381. void rtgui_dc_client_draw_raw_hline(struct rtgui_dc* self, rt_uint8_t* raw_ptr, int x1, int x2, int y)
  382. {
  383. register rt_base_t index;
  384. rtgui_widget_t *owner;
  385. if (self == RT_NULL) return;
  386. /* get owner */
  387. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  388. if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return;
  389. /* convert logic to device */
  390. x1 = x1 + owner->extent.x1;
  391. x2 = x2 + owner->extent.x1;
  392. y = y + owner->extent.y1;
  393. if (owner->clip.data == RT_NULL)
  394. {
  395. rtgui_rect_t* prect;
  396. prect = &(owner->clip.extents);
  397. /* calculate hline intersect */
  398. if (prect->y1 > y || prect->y2 <= y ) return;
  399. if (prect->x2 <= x1 || prect->x1 > x2) return;
  400. if (prect->x1 > x1) x1 = prect->x1;
  401. if (prect->x2 < x2) x2 = prect->x2;
  402. /* draw raw hline */
  403. hw_driver->draw_raw_hline(raw_ptr, x1, x2, y);
  404. }
  405. else for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
  406. {
  407. rtgui_rect_t* prect;
  408. register rt_base_t draw_x1, draw_x2;
  409. prect = ((rtgui_rect_t *)(owner->clip.data + index + 1));
  410. draw_x1 = x1;
  411. draw_x2 = x2;
  412. /* calculate hline clip */
  413. if (prect->y1 > y || prect->y2 <= y ) continue;
  414. if (prect->x2 <= x1 || prect->x1 > x2) continue;
  415. if (prect->x1 > x1) draw_x1 = prect->x1;
  416. if (prect->x2 < x2) draw_x2 = prect->x2;
  417. /* draw raw hline */
  418. hw_driver->draw_raw_hline(raw_ptr + (draw_x1 - x1) * hw_driver->byte_per_pixel, draw_x1, draw_x2, y);
  419. }
  420. }