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