dc_client.c 14 KB

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