dc_client.c 13 KB

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