dc_client.c 13 KB

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