dc_client.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  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 <panel.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. #define _int_swap(x, y) do {x ^= y; y ^= x; x ^= y;} while (0)
  42. struct rtgui_dc* rtgui_dc_begin_drawing(PVOID wdt)
  43. {
  44. rtgui_widget_t *owner = (rtgui_widget_t*)wdt;
  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)return RT_NULL;
  90. dc = RTGUI_WIDGET_DC(owner);
  91. /* set init visible as true */
  92. RTGUI_WIDGET_DC_SET_VISIBLE(owner);
  93. /* check widget visible */
  94. widget = owner;
  95. while (widget != RT_NULL)
  96. {
  97. if (RTGUI_WIDGET_IS_HIDE(widget))
  98. {
  99. RTGUI_WIDGET_DC_SET_UNVISIBLE(owner);
  100. break;
  101. }
  102. widget = widget->parent;
  103. }
  104. return dc;
  105. }
  106. static rt_bool_t rtgui_dc_client_fini(struct rtgui_dc* dc)
  107. {
  108. // rtgui_widget_t* owner;
  109. //
  110. // if (dc == RT_NULL || dc->type != RTGUI_DC_CLIENT) return RT_FALSE;
  111. //
  112. // /* get owner */
  113. // owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type);
  114. // if(RTGUI_WIDGET_IS_DC_VISIBLE(owner))
  115. // {
  116. // /* send to server to end drawing */
  117. // rtgui_event_update_t eupdate;
  118. // RTGUI_EVENT_UPDATE_INIT(&(eupdate));
  119. // eupdate.rect = owner->extent;
  120. //
  121. // rtgui_thread_send(rtgui_thread_get_server(), (struct rtgui_event*)&eupdate, sizeof(eupdate));
  122. // }
  123. return RT_TRUE;
  124. }
  125. /*
  126. * draw a logic point on device
  127. */
  128. static void rtgui_dc_client_draw_point(struct rtgui_dc* self, int x, int y)
  129. {
  130. rtgui_rect_t rect;
  131. rtgui_widget_t *owner;
  132. if (self == RT_NULL) return;
  133. /* get owner */
  134. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  135. if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return;
  136. x = x + owner->extent.x1;
  137. y = y + owner->extent.y1;
  138. if (rtgui_region_contains_point(&(owner->clip), x, y, &rect) == RT_EOK)
  139. {
  140. /* draw this point */
  141. hw_driver->set_pixel(&(owner->gc.foreground), x, y);
  142. }
  143. }
  144. static void rtgui_dc_client_draw_color_point(struct rtgui_dc* self, int x, int y, rtgui_color_t color)
  145. {
  146. rtgui_rect_t rect;
  147. rtgui_widget_t *owner;
  148. if (self == RT_NULL) return;
  149. /* get owner */
  150. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  151. if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return;
  152. x = x + owner->extent.x1;
  153. y = y + owner->extent.y1;
  154. if (rtgui_region_contains_point(&(owner->clip), x, y, &rect) == RT_EOK)
  155. {
  156. /* draw this point */
  157. hw_driver->set_pixel(&color, x, y);
  158. }
  159. }
  160. /*
  161. * draw a logic vertical line on device
  162. */
  163. static void rtgui_dc_client_draw_vline(struct rtgui_dc* self, int x, int y1, int y2)
  164. {
  165. register rt_base_t index;
  166. rtgui_widget_t *owner;
  167. if (self == RT_NULL) return;
  168. /* get owner */
  169. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  170. if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return;
  171. x = x + owner->extent.x1;
  172. y1 = y1 + owner->extent.y1;
  173. y2 = y2 + owner->extent.y1;
  174. if (y1 > y2) _int_swap(y1, y2);
  175. if (owner->clip.data == RT_NULL)
  176. {
  177. rtgui_rect_t* prect;
  178. prect = &(owner->clip.extents);
  179. /* calculate vline intersect */
  180. if (prect->x1 > x || prect->x2 <= x) return;
  181. if (prect->y2 <= y1 || prect->y1 > y2) return;
  182. if (prect->y1 > y1) y1 = prect->y1;
  183. if (prect->y2 < y2) y2 = prect->y2;
  184. /* draw vline */
  185. hw_driver->draw_vline(&(owner->gc.foreground), x, y1, y2);
  186. }
  187. else for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
  188. {
  189. rtgui_rect_t* prect;
  190. register rt_base_t draw_y1, draw_y2;
  191. prect = ((rtgui_rect_t *)(owner->clip.data + index + 1));
  192. draw_y1 = y1;
  193. draw_y2 = y2;
  194. /* calculate vline clip */
  195. if (prect->x1 > x || prect->x2 <= x) continue;
  196. if (prect->y2 <= y1 || prect->y1 > y2) continue;
  197. if (prect->y1 > y1) draw_y1 = prect->y1;
  198. if (prect->y2 < y2) draw_y2 = prect->y2;
  199. /* draw vline */
  200. hw_driver->draw_vline(&(owner->gc.foreground), x, draw_y1, draw_y2);
  201. }
  202. }
  203. /*
  204. * draw a logic horizontal line on device
  205. */
  206. static void rtgui_dc_client_draw_hline(struct rtgui_dc* self, int x1, int x2, int y)
  207. {
  208. register rt_base_t index;
  209. rtgui_widget_t *owner;
  210. if (self == RT_NULL) return;
  211. /* get owner */
  212. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  213. if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return;
  214. /* convert logic to device */
  215. x1 = x1 + owner->extent.x1;
  216. x2 = x2 + owner->extent.x1;
  217. if (x1 > x2) _int_swap(x1, x2);
  218. y = y + owner->extent.y1;
  219. if (owner->clip.data == RT_NULL)
  220. {
  221. rtgui_rect_t* prect;
  222. prect = &(owner->clip.extents);
  223. /* calculate vline intersect */
  224. if (prect->y1 > y || prect->y2 <= y ) return;
  225. if (prect->x2 <= x1 || prect->x1 > x2) return;
  226. if (prect->x1 > x1) x1 = prect->x1;
  227. if (prect->x2 < x2) x2 = prect->x2;
  228. /* draw hline */
  229. hw_driver->draw_hline(&(owner->gc.foreground), x1, x2, y);
  230. }
  231. else for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
  232. {
  233. rtgui_rect_t* prect;
  234. register rt_base_t draw_x1, draw_x2;
  235. prect = ((rtgui_rect_t *)(owner->clip.data + index + 1));
  236. draw_x1 = x1;
  237. draw_x2 = x2;
  238. /* calculate hline clip */
  239. if (prect->y1 > y || prect->y2 <= y ) continue;
  240. if (prect->x2 <= x1 || prect->x1 > x2) continue;
  241. if (prect->x1 > x1) draw_x1 = prect->x1;
  242. if (prect->x2 < x2) draw_x2 = prect->x2;
  243. /* draw hline */
  244. hw_driver->draw_hline(&(owner->gc.foreground), draw_x1, draw_x2, y);
  245. }
  246. }
  247. static void rtgui_dc_client_fill_rect (struct rtgui_dc* self, struct rtgui_rect* rect)
  248. {
  249. rtgui_color_t foreground;
  250. register rt_base_t index;
  251. rtgui_widget_t *owner;
  252. if (self == RT_NULL) return;
  253. /* get owner */
  254. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  255. if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return;
  256. /* save foreground color */
  257. foreground = owner->gc.foreground;
  258. /* set background color as foreground color */
  259. owner->gc.foreground = owner->gc.background;
  260. /* fill rect */
  261. for (index = rect->y1; index < rect->y2; index ++)
  262. {
  263. rtgui_dc_client_draw_hline(self, rect->x1, rect->x2, index);
  264. }
  265. /* restore foreground color */
  266. owner->gc.foreground = foreground;
  267. }
  268. static void rtgui_dc_client_blit_line (struct rtgui_dc* self, int x1, int x2, int y, rt_uint8_t* line_data)
  269. {
  270. register rt_base_t index;
  271. rtgui_widget_t *owner;
  272. if (self == RT_NULL) return;
  273. /* get owner */
  274. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  275. if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return;
  276. /* convert logic to device */
  277. x1 = x1 + owner->extent.x1;
  278. x2 = x2 + owner->extent.x1;
  279. if (x1 > x2) _int_swap(x1, x2);
  280. y = y + owner->extent.y1;
  281. if (rtgui_region_is_flat(&(owner->clip)) == RT_EOK)
  282. {
  283. rtgui_rect_t* prect;
  284. prect = &(owner->clip.extents);
  285. /* calculate vline intersect */
  286. if (prect->y1 > y || prect->y2 <= y ) return;
  287. if (prect->x2 <= x1 || prect->x1 > x2) return;
  288. if (prect->x1 > x1) x1 = prect->x1;
  289. if (prect->x2 < x2) x2 = prect->x2;
  290. /* draw hline */
  291. hw_driver->draw_raw_hline(line_data, x1, x2, y);
  292. }
  293. else for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
  294. {
  295. rtgui_rect_t* prect;
  296. register rt_base_t draw_x1, draw_x2;
  297. prect = ((rtgui_rect_t *)(owner->clip.data + index + 1));
  298. draw_x1 = x1;
  299. draw_x2 = x2;
  300. /* calculate hline clip */
  301. if (prect->y1 > y || prect->y2 <= y ) continue;
  302. if (prect->x2 <= x1 || prect->x1 > x2) continue;
  303. if (prect->x1 > x1) draw_x1 = prect->x1;
  304. if (prect->x2 < x2) draw_x2 = prect->x2;
  305. /* draw hline */
  306. hw_driver->draw_raw_hline(line_data + (draw_x1 - x1) * hw_driver->byte_per_pixel, draw_x1, draw_x2, y);
  307. }
  308. }
  309. static void rtgui_dc_client_blit(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect)
  310. {
  311. /* not blit in hardware dc */
  312. return ;
  313. }
  314. static void rtgui_dc_client_set_gc(struct rtgui_dc* self, rtgui_gc_t *gc)
  315. {
  316. rtgui_widget_t *owner;
  317. if (self == RT_NULL) return;
  318. /* get owner */
  319. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  320. owner->gc = *gc;
  321. }
  322. static rtgui_gc_t* rtgui_dc_client_get_gc(struct rtgui_dc* self)
  323. {
  324. rtgui_widget_t *owner;
  325. RT_ASSERT(self != RT_NULL);
  326. /* get owner */
  327. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  328. return &(owner->gc);
  329. }
  330. static rt_bool_t rtgui_dc_client_get_visible(struct rtgui_dc* self)
  331. {
  332. rtgui_widget_t *owner;
  333. if (self == RT_NULL) return RT_FALSE;
  334. /* get owner */
  335. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  336. if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return RT_FALSE;
  337. return RT_TRUE;
  338. }
  339. static void rtgui_dc_client_get_rect(struct rtgui_dc* self, rtgui_rect_t* rect)
  340. {
  341. rtgui_widget_t *owner;
  342. if (self == RT_NULL) return;
  343. /* get owner */
  344. owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
  345. rtgui_widget_get_rect(owner, rect);
  346. }