dc.c 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964
  1. /*
  2. * File : dc.c
  3. * This file is part of RT-Thread GUI Engine
  4. * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2009-10-16 Bernard first version
  23. * 2010-09-20 richard modified rtgui_dc_draw_round_rect
  24. * 2010-09-27 Bernard fix draw_mono_bmp issue
  25. * 2011-04-25 Bernard fix fill polygon issue, which found by loveic
  26. */
  27. /* for sin/cos etc */
  28. #include <math.h>
  29. #include <rtgui/dc.h>
  30. #include <rtgui/rtgui_system.h>
  31. #include <rtgui/rtgui_server.h>
  32. #include <rtgui/widgets/window.h>
  33. #include <rtgui/widgets/title.h>
  34. #include <string.h> /* for strlen */
  35. #include <stdlib.h> /* fir qsort */
  36. static int _int_compare(const void *a, const void *b)
  37. {
  38. return (*(const int *) a) - (*(const int *) b);
  39. }
  40. void rtgui_dc_destory(struct rtgui_dc *dc)
  41. {
  42. if (dc == RT_NULL) return;
  43. dc->engine->fini(dc);
  44. rtgui_free(dc);
  45. }
  46. RTM_EXPORT(rtgui_dc_destory);
  47. void rtgui_dc_draw_line(struct rtgui_dc *dc, int x1, int y1, int x2, int y2)
  48. {
  49. if (dc == RT_NULL) return;
  50. if (y1 == y2)
  51. {
  52. rtgui_dc_draw_hline(dc, x1, x2, y1);
  53. }
  54. else if (x1 == x2)
  55. {
  56. rtgui_dc_draw_vline(dc, x1, y1, y2);
  57. }
  58. else
  59. {
  60. int dx, dy, sdx, sdy, dxabs, dyabs, x, y, px, py;
  61. register rt_base_t i;
  62. /* rtgui_rect_t rect; */
  63. dx = x2 - x1; /* the horizontal distance of the line */
  64. dy = y2 - y1; /* the vertical distance of the line */
  65. #define rtgui_sgn(x) ((x<0)?-1:((x>0)?1:0)) /* macro to return the sign of a number */
  66. dxabs = _UI_ABS(dx);
  67. dyabs = _UI_ABS(dy);
  68. sdx = rtgui_sgn(dx);
  69. sdy = rtgui_sgn(dy);
  70. x = dyabs >> 1;
  71. y = dxabs >> 1;
  72. px = x1;
  73. py = y1;
  74. if (dxabs >= dyabs) /* the line is more horizontal than vertical */
  75. {
  76. for (i = 0; i < dxabs; i++)
  77. {
  78. y += dyabs;
  79. if (y >= dxabs)
  80. {
  81. y -= dxabs;
  82. py += sdy;
  83. }
  84. px += sdx;
  85. /* draw this point */
  86. rtgui_dc_draw_point(dc, px, py);
  87. }
  88. }
  89. else /* the line is more vertical than horizontal */
  90. {
  91. for (i = 0; i < dyabs; i++)
  92. {
  93. x += dxabs;
  94. if (x >= dyabs)
  95. {
  96. x -= dyabs;
  97. px += sdx;
  98. }
  99. py += sdy;
  100. /* draw this point */
  101. rtgui_dc_draw_point(dc, px, py);
  102. }
  103. }
  104. }
  105. }
  106. RTM_EXPORT(rtgui_dc_draw_line);
  107. void rtgui_dc_draw_horizontal_line(struct rtgui_dc *dc, int x1, int x2, int y)
  108. {
  109. rtgui_color_t color;
  110. if (dc == RT_NULL) return ;
  111. /* save old color */
  112. color = RTGUI_DC_FC(dc);
  113. RTGUI_DC_FC(dc) = dark_grey;
  114. rtgui_dc_draw_hline(dc, x1, x2, y);
  115. y ++;
  116. RTGUI_DC_FC(dc) = high_light;
  117. rtgui_dc_draw_hline(dc, x1, x2, y);
  118. /* restore color */
  119. RTGUI_DC_FC(dc) = color;
  120. }
  121. RTM_EXPORT(rtgui_dc_draw_horizontal_line);
  122. void rtgui_dc_draw_vertical_line(struct rtgui_dc *dc, int x, int y1, int y2)
  123. {
  124. rtgui_color_t color;
  125. if (dc == RT_NULL) return ;
  126. /* save old color */
  127. color = RTGUI_DC_FC(dc);
  128. RTGUI_DC_FC(dc) = dark_grey;
  129. rtgui_dc_draw_vline(dc, x, y1, y2);
  130. x ++;
  131. RTGUI_DC_FC(dc) = high_light;
  132. rtgui_dc_draw_vline(dc, x, y1, y2);
  133. /* restore color */
  134. RTGUI_DC_FC(dc) = color;
  135. }
  136. RTM_EXPORT(rtgui_dc_draw_vertical_line);
  137. void rtgui_dc_draw_rect(struct rtgui_dc *dc, struct rtgui_rect *rect)
  138. {
  139. rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y1);
  140. rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y2 - 1);
  141. rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2);
  142. rtgui_dc_draw_vline(dc, rect->x2 - 1, rect->y1, rect->y2);
  143. }
  144. RTM_EXPORT(rtgui_dc_draw_rect);
  145. void rtgui_dc_fill_rect_forecolor(struct rtgui_dc *dc, struct rtgui_rect *rect)
  146. {
  147. rtgui_color_t save_color;
  148. /*save the background color of dc*/
  149. save_color = RTGUI_DC_BC(dc);
  150. /*set the background color to fore color*/
  151. RTGUI_DC_BC(dc) = RTGUI_DC_FC(dc);
  152. dc->engine->fill_rect(dc, rect);
  153. /*restore the background color of dc*/
  154. RTGUI_DC_BC(dc) = save_color;
  155. }
  156. RTM_EXPORT(rtgui_dc_fill_rect_forecolor);
  157. void rtgui_dc_draw_round_rect(struct rtgui_dc *dc, struct rtgui_rect *rect, int r)
  158. {
  159. RT_ASSERT(((rect->x2 - rect->x1) / 2 >= r) && ((rect->y2 - rect->y1) / 2 >= r));
  160. if (r < 0)
  161. {
  162. return;
  163. }
  164. if (r == 0)
  165. {
  166. rtgui_dc_draw_rect(dc, rect);
  167. return;
  168. }
  169. if (((rect->x2 - rect->x1) / 2 >= r) && ((rect->y2 - rect->y1) / 2 >= r))
  170. {
  171. rtgui_dc_draw_arc(dc, rect->x1 + r, rect->y1 + r, r, 180, 270);
  172. rtgui_dc_draw_arc(dc, rect->x2 - r, rect->y1 + r, r, 270, 360);
  173. rtgui_dc_draw_arc(dc, rect->x1 + r, rect->y2 - r, r, 90, 180);
  174. rtgui_dc_draw_arc(dc, rect->x2 - r, rect->y2 - r, r, 0, 90);
  175. rtgui_dc_draw_hline(dc, rect->x1 + r, rect->x2 - r, rect->y1);
  176. rtgui_dc_draw_hline(dc, rect->x1 + r, rect->x2 - r, rect->y2);
  177. rtgui_dc_draw_vline(dc, rect->x1, rect->y1 + r, rect->y2 - r);
  178. rtgui_dc_draw_vline(dc, rect->x2, rect->y1 + r, rect->y2 - r);
  179. }
  180. }
  181. RTM_EXPORT(rtgui_dc_draw_round_rect);
  182. void rtgui_dc_fill_round_rect(struct rtgui_dc *dc, struct rtgui_rect *rect, int r)
  183. {
  184. struct rtgui_rect rect_temp;
  185. RT_ASSERT(((rect->x2 - rect->x1) / 2 >= r) && ((rect->y2 - rect->y1) / 2 >= r));
  186. if (((rect->x2 - rect->x1) / 2 >= r) && ((rect->y2 - rect->y1) / 2 >= r))
  187. {
  188. rect_temp.x1 = rect->x1 + r;
  189. rect_temp.y1 = rect->y1;
  190. rect_temp.x2 = rect->x2 - r;
  191. rect_temp.y2 = rect->y2;
  192. rtgui_dc_fill_rect_forecolor(dc, &rect_temp);//fill rect with foreground
  193. rect_temp.x1 = rect->x1;
  194. rect_temp.y1 = rect->y1 + r;
  195. rect_temp.x2 = rect->x1 + r;
  196. rect_temp.y2 = rect->y2 - r;
  197. rtgui_dc_fill_rect_forecolor(dc, &rect_temp);//fill rect with foreground
  198. rect_temp.x1 = rect->x2 - r;
  199. rect_temp.y1 = rect->y1 + r;
  200. rect_temp.x2 = rect->x2;
  201. rect_temp.y2 = rect->y2 - r;
  202. rtgui_dc_fill_rect_forecolor(dc, &rect_temp);//fill rect with foreground
  203. rtgui_dc_fill_circle(dc, rect->x1 + r, rect->y1 + r, r);
  204. rtgui_dc_fill_circle(dc, rect->x2 - r, rect->y2 - r, r);
  205. rtgui_dc_fill_circle(dc, rect->x2 - r, rect->y1 + r, r);
  206. rtgui_dc_fill_circle(dc, rect->x1 + r, rect->y2 - r, r);
  207. }
  208. }
  209. RTM_EXPORT(rtgui_dc_fill_round_rect);
  210. void rtgui_dc_draw_shaded_rect(struct rtgui_dc *dc, rtgui_rect_t *rect,
  211. rtgui_color_t c1, rtgui_color_t c2)
  212. {
  213. RT_ASSERT(dc != RT_NULL);
  214. RTGUI_DC_FC(dc) = c1;
  215. rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2);
  216. rtgui_dc_draw_hline(dc, rect->x1 + 1, rect->x2, rect->y1);
  217. RTGUI_DC_FC(dc) = c2;
  218. rtgui_dc_draw_vline(dc, rect->x2 - 1, rect->y1, rect->y2);
  219. rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y2 - 1);
  220. }
  221. RTM_EXPORT(rtgui_dc_draw_shaded_rect);
  222. void rtgui_dc_fill_gradient_rectv(struct rtgui_dc *dc, rtgui_rect_t *rect,
  223. rtgui_color_t c1, rtgui_color_t c2)
  224. {
  225. int y, step;
  226. rtgui_color_t fc;
  227. RT_ASSERT(dc != RT_NULL);
  228. RT_ASSERT(rect != RT_NULL);
  229. step = rtgui_rect_height(*rect);
  230. fc = RTGUI_DC_FC(dc);
  231. for (y = rect->y1; y < rect->y2; y++)
  232. {
  233. RTGUI_DC_FC(dc) = RTGUI_ARGB(((int)RTGUI_RGB_A(c2) - RTGUI_RGB_A(c1)) * (y - rect->y1) / step + RTGUI_RGB_A(c1),
  234. ((int)RTGUI_RGB_R(c2) - RTGUI_RGB_R(c1)) * (y - rect->y1) / step + RTGUI_RGB_R(c1),
  235. ((int)RTGUI_RGB_G(c2) - RTGUI_RGB_G(c1)) * (y - rect->y1) / step + RTGUI_RGB_G(c1),
  236. ((int)RTGUI_RGB_B(c2) - RTGUI_RGB_B(c1)) * (y - rect->y1) / step + RTGUI_RGB_B(c1));
  237. rtgui_dc_draw_hline(dc, rect->x1, rect->x2, y);
  238. }
  239. RTGUI_DC_FC(dc) = fc;
  240. }
  241. RTM_EXPORT(rtgui_dc_fill_gradient_rectv);
  242. void rtgui_dc_draw_focus_rect(struct rtgui_dc *dc, rtgui_rect_t *rect)
  243. {
  244. int x, y;
  245. for (x = rect->x1; x < rect->x2 - 1; x += 2)
  246. {
  247. rtgui_dc_draw_point(dc, x, rect->y1);
  248. rtgui_dc_draw_point(dc, x, rect->y2 - 1);
  249. }
  250. for (y = rect->y1; y < rect->y2; y += 2)
  251. {
  252. rtgui_dc_draw_point(dc, rect->x1, y);
  253. rtgui_dc_draw_point(dc, rect->x2 - 1, y);
  254. }
  255. }
  256. RTM_EXPORT(rtgui_dc_draw_focus_rect);
  257. void rtgui_dc_draw_text(struct rtgui_dc *dc, const char *text, struct rtgui_rect *rect)
  258. {
  259. rt_uint32_t len;
  260. struct rtgui_font *font;
  261. RT_ASSERT(dc != RT_NULL);
  262. font = RTGUI_DC_FONT(dc);
  263. if (font == RT_NULL)
  264. {
  265. /* use system default font */
  266. font = rtgui_font_default();
  267. }
  268. len = strlen((const char *)text);
  269. if (len == 0)
  270. return;
  271. rtgui_font_draw(font, dc, text, len, rect);
  272. }
  273. RTM_EXPORT(rtgui_dc_draw_text);
  274. void rtgui_dc_draw_text_stroke(struct rtgui_dc *dc, const char *text, struct rtgui_rect *rect,
  275. rtgui_color_t color_stroke, rtgui_color_t color_core)
  276. {
  277. int x, y;
  278. rtgui_rect_t r;
  279. rtgui_color_t fc;
  280. RT_ASSERT(dc != RT_NULL);
  281. fc = RTGUI_DC_FC(dc);
  282. RTGUI_DC_FC(dc) = color_stroke;
  283. for (x = -1; x < 2; x++)
  284. {
  285. for (y = -1; y < 2; y++)
  286. {
  287. r = *rect;
  288. rtgui_rect_move(&r, x, y);
  289. rtgui_dc_draw_text(dc, text, &r);
  290. }
  291. }
  292. RTGUI_DC_FC(dc) = color_core;
  293. rtgui_dc_draw_text(dc, text, rect);
  294. RTGUI_DC_FC(dc) = fc;
  295. }
  296. RTM_EXPORT(rtgui_dc_draw_text_stroke);
  297. /*
  298. * draw a monochrome color bitmap data
  299. */
  300. void rtgui_dc_draw_mono_bmp(struct rtgui_dc *dc, int x, int y, int w, int h, const rt_uint8_t *data)
  301. {
  302. int i, j, k;
  303. /* get word bytes */
  304. w = (w + 7) / 8;
  305. /* draw mono bitmap data */
  306. for (i = 0; i < h; i ++)
  307. for (j = 0; j < w; j++)
  308. for (k = 0; k < 8; k++)
  309. if (((data[i * w + j] >> (7 - k)) & 0x01) != 0)
  310. rtgui_dc_draw_point(dc, x + 8 * j + k, y + i);
  311. }
  312. RTM_EXPORT(rtgui_dc_draw_mono_bmp);
  313. void rtgui_dc_draw_byte(struct rtgui_dc *dc, int x, int y, int h, const rt_uint8_t *data)
  314. {
  315. rtgui_dc_draw_mono_bmp(dc, x, y, 8, h, data);
  316. }
  317. RTM_EXPORT(rtgui_dc_draw_byte);
  318. void rtgui_dc_draw_word(struct rtgui_dc *dc, int x, int y, int h, const rt_uint8_t *data)
  319. {
  320. rtgui_dc_draw_mono_bmp(dc, x, y, 16, h, data);
  321. }
  322. RTM_EXPORT(rtgui_dc_draw_word);
  323. void rtgui_dc_draw_border(struct rtgui_dc *dc, rtgui_rect_t *rect, int flag)
  324. {
  325. rtgui_rect_t r;
  326. rtgui_color_t color;
  327. if (dc == RT_NULL) return ;
  328. /* save old color */
  329. color = RTGUI_DC_FC(dc);
  330. r = *rect;
  331. switch (flag)
  332. {
  333. case RTGUI_BORDER_RAISE:
  334. rtgui_dc_draw_shaded_rect(dc, &r, high_light, black);
  335. rtgui_rect_inflate(&r, -1);
  336. rtgui_dc_draw_shaded_rect(dc, &r, light_grey, dark_grey);
  337. break;
  338. case RTGUI_BORDER_SUNKEN:
  339. rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
  340. rtgui_rect_inflate(&r, -1);
  341. rtgui_dc_draw_shaded_rect(dc, &r, black, light_grey);
  342. break;
  343. case RTGUI_BORDER_BOX:
  344. rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
  345. rtgui_rect_inflate(&r, -1);
  346. rtgui_dc_draw_shaded_rect(dc, &r, high_light, dark_grey);
  347. break;
  348. case RTGUI_BORDER_STATIC:
  349. rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
  350. break;
  351. case RTGUI_BORDER_EXTRA:
  352. RTGUI_DC_FC(dc) = light_grey;
  353. rtgui_dc_draw_rect(dc, &r);
  354. break;
  355. case RTGUI_BORDER_SIMPLE:
  356. RTGUI_DC_FC(dc) = black;
  357. rtgui_dc_draw_rect(dc, &r);
  358. break;
  359. default:
  360. break;
  361. }
  362. /* restore color */
  363. RTGUI_DC_FC(dc) = color;
  364. }
  365. RTM_EXPORT(rtgui_dc_draw_border);
  366. void rtgui_dc_draw_polygon(struct rtgui_dc *dc, const int *vx, const int *vy, int count)
  367. {
  368. int i;
  369. const int *x1, *y1, *x2, *y2;
  370. /*
  371. * Sanity check
  372. */
  373. if (count < 3) return;
  374. /*
  375. * Pointer setup
  376. */
  377. x1 = x2 = vx;
  378. y1 = y2 = vy;
  379. x2++;
  380. y2++;
  381. /*
  382. * Draw
  383. */
  384. for (i = 1; i < count; i++)
  385. {
  386. rtgui_dc_draw_line(dc, *x1, *y1, *x2, *y2);
  387. x1 = x2;
  388. y1 = y2;
  389. x2++;
  390. y2++;
  391. }
  392. rtgui_dc_draw_line(dc, *x1, *y1, *vx, *vy);
  393. }
  394. RTM_EXPORT(rtgui_dc_draw_polygon);
  395. void rtgui_dc_fill_polygon(struct rtgui_dc *dc, const int *vx, const int *vy, int count)
  396. {
  397. int i;
  398. int y, xa, xb;
  399. int miny, maxy;
  400. int x1, y1;
  401. int x2, y2;
  402. int ind1, ind2;
  403. int ints;
  404. int *poly_ints = RT_NULL;
  405. /*
  406. * Sanity check number of edges
  407. */
  408. if (count < 3) return;
  409. /*
  410. * Allocate temp array, only grow array
  411. */
  412. poly_ints = (int *) rtgui_malloc(sizeof(int) * count);
  413. if (poly_ints == RT_NULL) return ; /* no memory, failed */
  414. /*
  415. * Determine Y maximal
  416. */
  417. miny = vy[0];
  418. maxy = vy[0];
  419. for (i = 1; (i < count); i++)
  420. {
  421. if (vy[i] < miny) miny = vy[i];
  422. else if (vy[i] > maxy) maxy = vy[i];
  423. }
  424. /*
  425. * Draw, scanning y
  426. */
  427. for (y = miny; (y <= maxy); y++)
  428. {
  429. ints = 0;
  430. for (i = 0; (i < count); i++)
  431. {
  432. if (!i)
  433. {
  434. ind1 = count - 1;
  435. ind2 = 0;
  436. }
  437. else
  438. {
  439. ind1 = i - 1;
  440. ind2 = i;
  441. }
  442. y1 = vy[ind1];
  443. y2 = vy[ind2];
  444. if (y1 < y2)
  445. {
  446. x1 = vx[ind1];
  447. x2 = vx[ind2];
  448. }
  449. else if (y1 > y2)
  450. {
  451. y2 = vy[ind1];
  452. y1 = vy[ind2];
  453. x2 = vx[ind1];
  454. x1 = vx[ind2];
  455. }
  456. else
  457. {
  458. continue;
  459. }
  460. if (((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)))
  461. {
  462. poly_ints[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
  463. }
  464. }
  465. qsort(poly_ints, ints, sizeof(int), _int_compare);
  466. for (i = 0; (i < ints); i += 2)
  467. {
  468. xa = poly_ints[i] + 1;
  469. xa = (xa >> 16) + ((xa & 32768) >> 15);
  470. xb = poly_ints[i + 1] - 1;
  471. xb = (xb >> 16) + ((xb & 32768) >> 15);
  472. rtgui_dc_draw_hline(dc, xa, xb, y);
  473. }
  474. }
  475. /* release memory */
  476. rtgui_free(poly_ints);
  477. }
  478. RTM_EXPORT(rtgui_dc_fill_polygon);
  479. void rtgui_dc_draw_circle(struct rtgui_dc *dc, int x, int y, int r)
  480. {
  481. rtgui_dc_draw_ellipse(dc, x, y, r, r);
  482. }
  483. RTM_EXPORT(rtgui_dc_draw_circle);
  484. enum
  485. {
  486. QUARTER_BTM,
  487. QUARTER_BTM_LEFT,
  488. QUARTER_BTM_RIGHT,
  489. QUARTER_TOP,
  490. QUARTER_TOP_LEFT,
  491. QUARTER_TOP_RIGHT,
  492. QUARTER_FULL,
  493. };
  494. static void _fill_quarter_circle(struct rtgui_dc *dc,
  495. rt_int16_t ox, rt_int16_t oy,
  496. rt_int16_t rad, int quadrant)
  497. {
  498. /* Midpoint circle algorithm. */
  499. int dk, x, y;
  500. dk = 1 - rad;
  501. x = 0;
  502. y = rad;
  503. while (x <= y)
  504. {
  505. switch (quadrant)
  506. {
  507. case QUARTER_BTM:
  508. rtgui_dc_draw_hline(dc, ox - x, ox + x, oy + y);
  509. rtgui_dc_draw_hline(dc, ox - y, ox + y, oy + x);
  510. break;
  511. case QUARTER_BTM_LEFT:
  512. rtgui_dc_draw_hline(dc, ox, ox + x, oy + y);
  513. rtgui_dc_draw_hline(dc, ox, ox + y, oy + x);
  514. break;
  515. case QUARTER_BTM_RIGHT:
  516. rtgui_dc_draw_hline(dc, ox, ox - x, oy + y);
  517. rtgui_dc_draw_hline(dc, ox, ox - y, oy + x);
  518. break;
  519. case QUARTER_TOP_RIGHT:
  520. rtgui_dc_draw_hline(dc, ox, ox - x, oy - y);
  521. rtgui_dc_draw_hline(dc, ox, ox - y, oy - x);
  522. break;
  523. case QUARTER_TOP_LEFT:
  524. rtgui_dc_draw_hline(dc, ox, ox + x, oy - y);
  525. rtgui_dc_draw_hline(dc, ox, ox + y, oy - x);
  526. break;
  527. case QUARTER_TOP:
  528. rtgui_dc_draw_hline(dc, ox - x, ox + x, oy - y);
  529. rtgui_dc_draw_hline(dc, ox - y, ox + y, oy - x);
  530. break;
  531. case QUARTER_FULL:
  532. rtgui_dc_draw_hline(dc, ox - x, ox + x, oy + y);
  533. rtgui_dc_draw_hline(dc, ox - y, ox + y, oy + x);
  534. rtgui_dc_draw_hline(dc, ox - x, ox + x, oy - y);
  535. rtgui_dc_draw_hline(dc, ox - y, ox + y, oy - x);
  536. break;
  537. default:
  538. RT_ASSERT(0);
  539. };
  540. if (dk > 0)
  541. {
  542. y--;
  543. dk += 2 * (x - y) + 5;
  544. }
  545. else
  546. {
  547. dk += 2 * x + 3;
  548. }
  549. x++;
  550. }
  551. }
  552. void rtgui_dc_fill_circle(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r)
  553. {
  554. /*
  555. * Sanity check radius
  556. */
  557. if (r < 0)
  558. return;
  559. /*
  560. * Special case for r=0 - draw a point
  561. */
  562. if (r == 0)
  563. {
  564. rtgui_dc_draw_point(dc, x, y);
  565. return;
  566. }
  567. _fill_quarter_circle(dc, x, y, r, QUARTER_FULL);
  568. }
  569. RTM_EXPORT(rtgui_dc_fill_circle);
  570. void rtgui_dc_draw_arc(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r, rt_int16_t start, rt_int16_t end)
  571. {
  572. rt_int16_t cx = 0;
  573. rt_int16_t cy = r;
  574. rt_int16_t df = 1 - r;
  575. rt_int16_t d_e = 3;
  576. rt_int16_t d_se = -2 * r + 5;
  577. rt_int16_t xpcx, xmcx, xpcy, xmcy;
  578. rt_int16_t ypcy, ymcy, ypcx, ymcx;
  579. rt_uint8_t drawoct;
  580. int startoct, endoct, oct, stopval_start, stopval_end;
  581. double temp;
  582. stopval_start = 0;
  583. stopval_end = 0;
  584. temp = 0;
  585. /* Sanity check radius */
  586. if (r < 0) return ;
  587. /* Special case for r=0 - draw a point */
  588. if (r == 0)
  589. {
  590. rtgui_dc_draw_point(dc, x, y);
  591. return;
  592. }
  593. /*
  594. * Draw arc
  595. * Octant labelling
  596. *
  597. * \ 5 | 6 /
  598. * \ | /
  599. * 4 \ | / 7
  600. * \|/
  601. *------+------ +x
  602. * /|\
  603. * 3 / | \ 0
  604. * / | \
  605. * / 2 | 1 \
  606. * +y
  607. */
  608. drawoct = 0; // 0x00000000
  609. // whether or not to keep drawing a given octant.
  610. // For example: 0x00111100 means we're drawing in octants 2-5
  611. // 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0.
  612. while (start < 0) start += 360;
  613. while (end < 0) end += 360;
  614. /* Fixup angles */
  615. start = start % 360;
  616. end = end % 360;
  617. // now, we find which octants we're drawing in.
  618. startoct = start / 45;
  619. endoct = end / 45;
  620. oct = startoct - 1; // we increment as first step in loop
  621. //stopval_start, stopval_end; // what values of cx to stop at.
  622. do
  623. {
  624. oct = (oct + 1) % 8;
  625. if (oct == startoct)
  626. {
  627. // need to compute stopval_start for this octant. Look at picture above if this is unclear
  628. switch (oct)
  629. {
  630. case 0:
  631. case 3:
  632. temp = sin(start * M_PI / 180);
  633. break;
  634. case 1:
  635. case 6:
  636. temp = cos(start * M_PI / 180);
  637. break;
  638. case 2:
  639. case 5:
  640. temp = -cos(start * M_PI / 180);
  641. break;
  642. case 4:
  643. case 7:
  644. temp = -sin(start * M_PI / 180);
  645. break;
  646. }
  647. temp *= r;
  648. stopval_start = (int)temp; // always round down.
  649. // This isn't arbitrary, but requires graph paper to explain well.
  650. // The basic idea is that we're always changing drawoct after we draw, so we
  651. // stop immediately after we render the last sensible pixel at x = ((int)temp).
  652. // and whether to draw in this octant initially
  653. if (oct % 2) drawoct |= (1 << oct); // this is basically like saying drawoct[oct] = true, if drawoct were a bool array
  654. else drawoct &= 255 - (1 << oct); // this is basically like saying drawoct[oct] = false
  655. }
  656. if (oct == endoct)
  657. {
  658. // need to compute stopval_end for this octant
  659. switch (oct)
  660. {
  661. case 0:
  662. case 3:
  663. temp = sin(end * M_PI / 180);
  664. break;
  665. case 1:
  666. case 6:
  667. temp = cos(end * M_PI / 180);
  668. break;
  669. case 2:
  670. case 5:
  671. temp = -cos(end * M_PI / 180);
  672. break;
  673. case 4:
  674. case 7:
  675. temp = -sin(end * M_PI / 180);
  676. break;
  677. }
  678. temp *= r;
  679. stopval_end = (int)temp;
  680. // and whether to draw in this octant initially
  681. if (startoct == endoct)
  682. {
  683. // note: we start drawing, stop, then start again in this case
  684. // otherwise: we only draw in this octant, so initialize it to false, it will get set back to true
  685. if (start > end)
  686. {
  687. // unfortunately, if we're in the same octant and need to draw over the whole circle,
  688. // we need to set the rest to true, because the while loop will end at the bottom.
  689. drawoct = 255;
  690. }
  691. else
  692. {
  693. drawoct &= 255 - (1 << oct);
  694. }
  695. }
  696. else if (oct % 2) drawoct &= 255 - (1 << oct);
  697. else drawoct |= (1 << oct);
  698. }
  699. else if (oct != startoct) // already verified that it's != endoct
  700. {
  701. drawoct |= (1 << oct); // draw this entire segment
  702. }
  703. }
  704. while (oct != endoct);
  705. // so now we have what octants to draw and when to draw them. all that's left is the actual raster code.
  706. do
  707. {
  708. ypcy = y + cy;
  709. ymcy = y - cy;
  710. if (cx > 0)
  711. {
  712. xpcx = x + cx;
  713. xmcx = x - cx;
  714. // always check if we're drawing a certain octant before adding a pixel to that octant.
  715. if (drawoct & 4) rtgui_dc_draw_point(dc, xmcx, ypcy); // drawoct & 4 = 22; drawoct[2]
  716. if (drawoct & 2) rtgui_dc_draw_point(dc, xpcx, ypcy);
  717. if (drawoct & 32) rtgui_dc_draw_point(dc, xmcx, ymcy);
  718. if (drawoct & 64) rtgui_dc_draw_point(dc, xpcx, ymcy);
  719. }
  720. else
  721. {
  722. if (drawoct & 6) rtgui_dc_draw_point(dc, x, ypcy); // 4 + 2; drawoct[2] || drawoct[1]
  723. if (drawoct & 96) rtgui_dc_draw_point(dc, x, ymcy); // 32 + 64
  724. }
  725. xpcy = x + cy;
  726. xmcy = x - cy;
  727. if (cx > 0 && cx != cy)
  728. {
  729. ypcx = y + cx;
  730. ymcx = y - cx;
  731. if (drawoct & 8) rtgui_dc_draw_point(dc, xmcy, ypcx);
  732. if (drawoct & 1) rtgui_dc_draw_point(dc, xpcy, ypcx);
  733. if (drawoct & 16) rtgui_dc_draw_point(dc, xmcy, ymcx);
  734. if (drawoct & 128) rtgui_dc_draw_point(dc, xpcy, ymcx);
  735. }
  736. else if (cx == 0)
  737. {
  738. if (drawoct & 24) rtgui_dc_draw_point(dc, xmcy, y); // 8 + 16
  739. if (drawoct & 129) rtgui_dc_draw_point(dc, xpcy, y); // 1 + 128
  740. }
  741. /*
  742. * Update whether we're drawing an octant
  743. */
  744. if (stopval_start == cx)
  745. {
  746. // works like an on-off switch because start & end may be in the same octant.
  747. if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
  748. else drawoct |= (1 << startoct);
  749. }
  750. if (stopval_end == cx)
  751. {
  752. if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
  753. else drawoct |= (1 << endoct);
  754. }
  755. /*
  756. * Update pixels
  757. */
  758. if (df < 0)
  759. {
  760. df += d_e;
  761. d_e += 2;
  762. d_se += 2;
  763. }
  764. else
  765. {
  766. df += d_se;
  767. d_e += 2;
  768. d_se += 4;
  769. cy--;
  770. }
  771. cx++;
  772. }
  773. while (cx <= cy);
  774. }
  775. RTM_EXPORT(rtgui_dc_draw_arc);
  776. void rtgui_dc_draw_annulus(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r1, rt_int16_t r2, rt_int16_t start, rt_int16_t end)
  777. {
  778. rt_int16_t start_x, start_y;
  779. rt_int16_t end_x, end_y;
  780. double temp;
  781. rt_int16_t temp_val = 0;
  782. /* Sanity check radius */
  783. if ((r1 < 0) || (r2 < 0)) return ;
  784. /* Special case for r=0 - draw a point */
  785. if ((r1 == 0) && (r2 == 0))
  786. {
  787. rtgui_dc_draw_point(dc, x, y);
  788. return;
  789. }
  790. while (start < 0) start += 360;
  791. while (end < 0) end += 360;
  792. rtgui_dc_draw_arc(dc, x, y, r1, start, end);
  793. rtgui_dc_draw_arc(dc, x, y, r2, start, end);
  794. temp = cos(start * M_PI / 180);
  795. temp_val = (int)(temp * r1);
  796. start_x = x + temp_val;
  797. temp_val = (int)(temp * r2);
  798. end_x = x + temp_val;
  799. temp = sin(start * M_PI / 180);
  800. temp_val = (int)(temp * r1);
  801. start_y = y + temp_val;
  802. temp_val = (int)(temp * r2);
  803. end_y = y + temp_val;
  804. rtgui_dc_draw_line(dc, start_x, start_y, end_x, end_y);
  805. temp = cos(end * M_PI / 180);
  806. temp_val = (int)(temp * r1);
  807. start_x = x + temp_val;
  808. temp_val = (int)(temp * r2);
  809. end_x = x + temp_val;
  810. temp = sin(end * M_PI / 180);
  811. temp_val = (int)(temp * r1);
  812. start_y = y + temp_val;
  813. temp_val = (int)(temp * r2);
  814. end_y = y + temp_val;
  815. rtgui_dc_draw_line(dc, start_x, start_y, end_x, end_y);
  816. }
  817. RTM_EXPORT(rtgui_dc_draw_annulus);
  818. void rtgui_dc_draw_ellipse(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry)
  819. {
  820. int ix, iy;
  821. int h, i, j, k;
  822. int oh, oi, oj, ok;
  823. int xmh, xph, ypk, ymk;
  824. int xmi, xpi, ymj, ypj;
  825. int xmj, xpj, ymi, ypi;
  826. int xmk, xpk, ymh, yph;
  827. /*
  828. * Sanity check radii
  829. */
  830. if ((rx < 0) || (ry < 0)) return;
  831. /*
  832. * Special case for rx=0 - draw a vline
  833. */
  834. if (rx == 0)
  835. {
  836. rtgui_dc_draw_vline(dc, x, y - ry, y + ry);
  837. return;
  838. }
  839. /*
  840. * Special case for ry=0 - draw a hline
  841. */
  842. if (ry == 0)
  843. {
  844. rtgui_dc_draw_hline(dc, x - rx, x + rx, y);
  845. return;
  846. }
  847. /*
  848. * Init vars
  849. */
  850. oh = oi = oj = ok = 0xFFFF;
  851. if (rx > ry)
  852. {
  853. ix = 0;
  854. iy = rx * 64;
  855. do
  856. {
  857. h = (ix + 32) >> 6;
  858. i = (iy + 32) >> 6;
  859. j = (h * ry) / rx;
  860. k = (i * ry) / rx;
  861. if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j))
  862. {
  863. xph = x + h;
  864. xmh = x - h;
  865. if (k > 0)
  866. {
  867. ypk = y + k;
  868. ymk = y - k;
  869. rtgui_dc_draw_point(dc, xmh, ypk);
  870. rtgui_dc_draw_point(dc, xph, ypk);
  871. rtgui_dc_draw_point(dc, xmh, ymk);
  872. rtgui_dc_draw_point(dc, xph, ymk);
  873. }
  874. else
  875. {
  876. rtgui_dc_draw_point(dc, xmh, y);
  877. rtgui_dc_draw_point(dc, xph, y);
  878. }
  879. ok = k;
  880. xpi = x + i;
  881. xmi = x - i;
  882. if (j > 0)
  883. {
  884. ypj = y + j;
  885. ymj = y - j;
  886. rtgui_dc_draw_point(dc, xmi, ypj);
  887. rtgui_dc_draw_point(dc, xpi, ypj);
  888. rtgui_dc_draw_point(dc, xmi, ymj);
  889. rtgui_dc_draw_point(dc, xpi, ymj);
  890. }
  891. else
  892. {
  893. rtgui_dc_draw_point(dc, xmi, y);
  894. rtgui_dc_draw_point(dc, xpi, y);
  895. }
  896. oj = j;
  897. }
  898. ix = ix + iy / rx;
  899. iy = iy - ix / rx;
  900. }
  901. while (i > h);
  902. }
  903. else
  904. {
  905. ix = 0;
  906. iy = ry * 64;
  907. do
  908. {
  909. h = (ix + 32) >> 6;
  910. i = (iy + 32) >> 6;
  911. j = (h * rx) / ry;
  912. k = (i * rx) / ry;
  913. if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h)))
  914. {
  915. xmj = x - j;
  916. xpj = x + j;
  917. if (i > 0)
  918. {
  919. ypi = y + i;
  920. ymi = y - i;
  921. rtgui_dc_draw_point(dc, xmj, ypi);
  922. rtgui_dc_draw_point(dc, xpj, ypi);
  923. rtgui_dc_draw_point(dc, xmj, ymi);
  924. rtgui_dc_draw_point(dc, xpj, ymi);
  925. }
  926. else
  927. {
  928. rtgui_dc_draw_point(dc, xmj, y);
  929. rtgui_dc_draw_point(dc, xpj, y);
  930. }
  931. oi = i;
  932. xmk = x - k;
  933. xpk = x + k;
  934. if (h > 0)
  935. {
  936. yph = y + h;
  937. ymh = y - h;
  938. rtgui_dc_draw_point(dc, xmk, yph);
  939. rtgui_dc_draw_point(dc, xpk, yph);
  940. rtgui_dc_draw_point(dc, xmk, ymh);
  941. rtgui_dc_draw_point(dc, xpk, ymh);
  942. }
  943. else
  944. {
  945. rtgui_dc_draw_point(dc, xmk, y);
  946. rtgui_dc_draw_point(dc, xpk, y);
  947. }
  948. oh = h;
  949. }
  950. ix = ix + iy / ry;
  951. iy = iy - ix / ry;
  952. }
  953. while (i > h);
  954. }
  955. }
  956. RTM_EXPORT(rtgui_dc_draw_ellipse);
  957. void rtgui_dc_fill_ellipse(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry)
  958. {
  959. int ix, iy;
  960. int h, i, j, k;
  961. int oh, oi, oj, ok;
  962. int xmh, xph;
  963. int xmi, xpi;
  964. int xmj, xpj;
  965. int xmk, xpk;
  966. /*
  967. * Special case for rx=0 - draw a vline
  968. */
  969. if (rx == 0)
  970. {
  971. rtgui_dc_draw_vline(dc, x, y - ry, y + ry);
  972. return;
  973. }
  974. /* special case for ry=0 - draw a hline */
  975. if (ry == 0)
  976. {
  977. rtgui_dc_draw_hline(dc, x - rx, x + rx, y);
  978. return;
  979. }
  980. /*
  981. * Init vars
  982. */
  983. oh = oi = oj = ok = 0xFFFF;
  984. /*
  985. * Draw
  986. */
  987. if (rx > ry)
  988. {
  989. ix = 0;
  990. iy = rx * 64;
  991. do
  992. {
  993. h = (ix + 32) >> 6;
  994. i = (iy + 32) >> 6;
  995. j = (h * ry) / rx;
  996. k = (i * ry) / rx;
  997. if ((ok != k) && (oj != k))
  998. {
  999. xph = x + h;
  1000. xmh = x - h;
  1001. if (k > 0)
  1002. {
  1003. rtgui_dc_draw_hline(dc, xmh, xph, y + k);
  1004. rtgui_dc_draw_hline(dc, xmh, xph, y - k);
  1005. }
  1006. else
  1007. {
  1008. rtgui_dc_draw_hline(dc, xmh, xph, y);
  1009. }
  1010. ok = k;
  1011. }
  1012. if ((oj != j) && (ok != j) && (k != j))
  1013. {
  1014. xmi = x - i;
  1015. xpi = x + i;
  1016. if (j > 0)
  1017. {
  1018. rtgui_dc_draw_hline(dc, xmi, xpi, y + j);
  1019. rtgui_dc_draw_hline(dc, xmi, xpi, y - j);
  1020. }
  1021. else
  1022. {
  1023. rtgui_dc_draw_hline(dc, xmi, xpi, y);
  1024. }
  1025. oj = j;
  1026. }
  1027. ix = ix + iy / rx;
  1028. iy = iy - ix / rx;
  1029. }
  1030. while (i > h);
  1031. }
  1032. else
  1033. {
  1034. ix = 0;
  1035. iy = ry * 64;
  1036. do
  1037. {
  1038. h = (ix + 32) >> 6;
  1039. i = (iy + 32) >> 6;
  1040. j = (h * rx) / ry;
  1041. k = (i * rx) / ry;
  1042. if ((oi != i) && (oh != i))
  1043. {
  1044. xmj = x - j;
  1045. xpj = x + j;
  1046. if (i > 0)
  1047. {
  1048. rtgui_dc_draw_hline(dc, xmj, xpj, y + i);
  1049. rtgui_dc_draw_hline(dc, xmj, xpj, y - i);
  1050. }
  1051. else
  1052. {
  1053. rtgui_dc_draw_hline(dc, xmj, xpj, y);
  1054. }
  1055. oi = i;
  1056. }
  1057. if ((oh != h) && (oi != h) && (i != h))
  1058. {
  1059. xmk = x - k;
  1060. xpk = x + k;
  1061. if (h > 0)
  1062. {
  1063. rtgui_dc_draw_hline(dc, xmk, xpk, y + h);
  1064. rtgui_dc_draw_hline(dc, xmk, xpk, y - h);
  1065. }
  1066. else
  1067. {
  1068. rtgui_dc_draw_hline(dc, xmk, xpk, y);
  1069. }
  1070. oh = h;
  1071. }
  1072. ix = ix + iy / ry;
  1073. iy = iy - ix / ry;
  1074. }
  1075. while (i > h);
  1076. }
  1077. }
  1078. RTM_EXPORT(rtgui_dc_fill_ellipse);
  1079. void rtgui_dc_draw_pie(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rad, rt_int16_t start, rt_int16_t end)
  1080. {
  1081. double angle, start_angle, end_angle;
  1082. double deltaAngle;
  1083. double dr;
  1084. int numpoints, i;
  1085. int *vx, *vy;
  1086. /* Sanity check radii */
  1087. if (rad < 0) return ;
  1088. /*
  1089. * Fixup angles
  1090. */
  1091. start = start % 360;
  1092. end = end % 360;
  1093. /*
  1094. * Special case for rad=0 - draw a point
  1095. */
  1096. if (rad == 0)
  1097. {
  1098. rtgui_dc_draw_point(dc, x, y);
  1099. return;
  1100. }
  1101. /*
  1102. * Variable setup
  1103. */
  1104. dr = (double) rad;
  1105. deltaAngle = 3.0 / dr;
  1106. start_angle = (double) start * (2.0 * M_PI / 360.0);
  1107. end_angle = (double) end * (2.0 * M_PI / 360.0);
  1108. if (start > end)
  1109. {
  1110. end_angle += (2.0 * M_PI);
  1111. }
  1112. /* We will always have at least 2 points */
  1113. numpoints = 2;
  1114. /* Count points (rather than calculating it) */
  1115. angle = start_angle;
  1116. while (angle < end_angle)
  1117. {
  1118. angle += deltaAngle;
  1119. numpoints++;
  1120. }
  1121. /* Allocate combined vertex array */
  1122. vx = vy = (int *) rtgui_malloc(2 * sizeof(int) * numpoints);
  1123. if (vx == RT_NULL) return ;
  1124. /* Update point to start of vy */
  1125. vy += numpoints;
  1126. /* Center */
  1127. vx[0] = x;
  1128. vy[0] = y;
  1129. /* First vertex */
  1130. angle = start_angle;
  1131. vx[1] = x + (int)(dr * cos(angle));
  1132. vy[1] = y + (int)(dr * sin(angle));
  1133. if (numpoints < 3)
  1134. {
  1135. rtgui_dc_draw_line(dc, vx[0], vy[0], vx[1], vy[1]);
  1136. }
  1137. else
  1138. {
  1139. /* Calculate other vertices */
  1140. i = 2;
  1141. angle = start_angle;
  1142. while (angle < end_angle)
  1143. {
  1144. angle += deltaAngle;
  1145. if (angle > end_angle)
  1146. {
  1147. angle = end_angle;
  1148. }
  1149. vx[i] = x + (int)(dr * cos(angle));
  1150. vy[i] = y + (int)(dr * sin(angle));
  1151. i++;
  1152. }
  1153. /* Draw */
  1154. rtgui_dc_draw_polygon(dc, vx, vy, numpoints);
  1155. }
  1156. /* Free combined vertex array */
  1157. rtgui_free(vx);
  1158. return;
  1159. }
  1160. RTM_EXPORT(rtgui_dc_draw_pie);
  1161. /*
  1162. * Octant labelling
  1163. *
  1164. * \ 5 | 6 /
  1165. * \ | /
  1166. * 4 \ | / 7
  1167. * \|/
  1168. *------+------ +x
  1169. * /|\
  1170. * 3 / | \ 0
  1171. * / | \
  1172. * / 2 | 1 \
  1173. * +y
  1174. */
  1175. static void _draw_octant(struct rtgui_dc *dc,
  1176. rt_int16_t ox, rt_int16_t oy,
  1177. rt_int16_t y1, rt_int16_t y2, rt_int16_t x, int oct)
  1178. {
  1179. switch (oct % 8)
  1180. {
  1181. case 0:
  1182. rtgui_dc_draw_line(dc, ox + x, oy + y1, ox + x, oy + y2);
  1183. break;
  1184. case 1:
  1185. /* Ugly hack to get the edge right. */
  1186. y2 += 1;
  1187. y1 += 1;
  1188. x -= 1;
  1189. rtgui_dc_draw_line(dc, ox + y1, oy + x, ox + y2, oy + x);
  1190. break;
  1191. case 2:
  1192. y2 -= 1;
  1193. y1 -= 1;
  1194. x -= 1;
  1195. rtgui_dc_draw_line(dc, ox - y2, oy + x, ox - y1, oy + x);
  1196. break;
  1197. case 3:
  1198. x -= 1;
  1199. rtgui_dc_draw_line(dc, ox - x, oy + y1, ox - x, oy + y2);
  1200. break;
  1201. case 4:
  1202. x -= 1;
  1203. rtgui_dc_draw_line(dc, ox - x, oy - y2, ox - x, oy - y1);
  1204. break;
  1205. case 5:
  1206. y2 -= 1;
  1207. y1 -= 1;
  1208. rtgui_dc_draw_line(dc, ox - y2, oy - x, ox - y1, oy - x);
  1209. break;
  1210. case 6:
  1211. y2 += 1;
  1212. y1 += 1;
  1213. rtgui_dc_draw_line(dc, ox + y1, oy - x, ox + y2, oy - x);
  1214. break;
  1215. case 7:
  1216. rtgui_dc_draw_line(dc, ox + x, oy - y2, ox + x, oy - y1);
  1217. break;
  1218. };
  1219. }
  1220. static void _fill_small_pie(struct rtgui_dc *dc,
  1221. rt_int16_t ox, rt_int16_t oy,
  1222. rt_int16_t rad, rt_int16_t start, rt_int16_t end,
  1223. int oct)
  1224. {
  1225. /* Midpoint circle algorithm. */
  1226. int dk, x, y;
  1227. /* Start X, end X, */
  1228. rt_int16_t sx, ex, ty, my;
  1229. enum {ST_NONE, ST_ARC, ST_TRI} st;
  1230. RT_ASSERT(0 <= start && start <= 45);
  1231. RT_ASSERT(0 <= end && end <= 45);
  1232. if (start == end)
  1233. return;
  1234. RT_ASSERT(start < end);
  1235. RT_ASSERT(rad > 0);
  1236. /* cos(90 - start) == sin(start) */
  1237. sx = rad * sin(start * M_PI / 180);
  1238. ex = rad * sin(end * M_PI / 180);
  1239. dk = 1 - rad;
  1240. x = 0;
  1241. y = rad;
  1242. st = ST_NONE;
  1243. my = ex;
  1244. while (x <= y)
  1245. {
  1246. rt_int16_t lx;
  1247. if (x < sx)
  1248. {
  1249. }
  1250. else if (x == sx)
  1251. {
  1252. /* Start point. */
  1253. st = ST_ARC;
  1254. ty = y;
  1255. }
  1256. else if (x <= ex)
  1257. {
  1258. /* Between the pie. */
  1259. RT_ASSERT(st == ST_ARC);
  1260. }
  1261. else /* x > ex */
  1262. {
  1263. /* End. */
  1264. st = ST_TRI;
  1265. my = y;
  1266. break;
  1267. }
  1268. /* Drawing. */
  1269. if (st == ST_ARC)
  1270. {
  1271. lx = y * sx / ty;
  1272. /* Change from math coordinate to plot coordinate. */
  1273. _draw_octant(dc, ox, oy, lx, x, y, oct);
  1274. }
  1275. /* Midpoint increment. */
  1276. if (dk > 0)
  1277. {
  1278. y--;
  1279. dk += 2 * (x - y) + 5;
  1280. }
  1281. else
  1282. {
  1283. dk += 2 * x + 3;
  1284. }
  1285. x++;
  1286. }
  1287. /* Draw bottom part. */
  1288. for (; y >= 0; y--)
  1289. {
  1290. rt_int16_t lx, rx;
  1291. lx = y * sx / ty;
  1292. rx = y * ex / my;
  1293. _draw_octant(dc, ox, oy, lx, rx, y, oct);
  1294. }
  1295. }
  1296. void rtgui_dc_fill_pie(struct rtgui_dc *dc,
  1297. rt_int16_t x, rt_int16_t y, rt_int16_t rad,
  1298. rt_int16_t start, rt_int16_t end)
  1299. {
  1300. /* Sanity check radii */
  1301. if (rad < 0)
  1302. return;
  1303. if (rad == 0)
  1304. {
  1305. rtgui_dc_draw_point(dc, x, y);
  1306. return;
  1307. }
  1308. if (end - start >= 360)
  1309. {
  1310. rtgui_dc_fill_circle(dc, x, y, rad);
  1311. return;
  1312. }
  1313. if (start == end)
  1314. return;
  1315. /*
  1316. * Fixup angles
  1317. */
  1318. while (start < 0)
  1319. {
  1320. start += 360;
  1321. end += 360;
  1322. }
  1323. while (start >= 360)
  1324. {
  1325. start -= 360;
  1326. end -= 360;
  1327. }
  1328. if (end < start)
  1329. end += 360;
  1330. while (start / 45 != end / 45)
  1331. {
  1332. /* The start and end are not in the same piece. */
  1333. if ((start / 45) % 2)
  1334. {
  1335. _fill_small_pie(dc, x, y, rad,
  1336. 0, 45 - start % 45, start / 45);
  1337. start += 45 - start % 45;
  1338. }
  1339. else
  1340. {
  1341. _fill_small_pie(dc, x, y, rad,
  1342. start % 45, 45, start / 45);
  1343. start += 45 - start % 45;
  1344. }
  1345. }
  1346. if ((start / 45) % 2)
  1347. {
  1348. _fill_small_pie(dc, x, y, rad,
  1349. 90 - end % 90, 90 - start % 90, start / 45);
  1350. }
  1351. else
  1352. {
  1353. _fill_small_pie(dc, x, y, rad,
  1354. start % 45, end % 45, start / 45);
  1355. }
  1356. return;
  1357. }
  1358. RTM_EXPORT(rtgui_dc_fill_pie);
  1359. /*
  1360. * set gc of dc
  1361. */
  1362. void rtgui_dc_set_gc(struct rtgui_dc *dc, rtgui_gc_t *gc)
  1363. {
  1364. RT_ASSERT(dc != RT_NULL);
  1365. switch (dc->type)
  1366. {
  1367. case RTGUI_DC_CLIENT:
  1368. {
  1369. rtgui_widget_t *owner;
  1370. /* get owner */
  1371. owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type);
  1372. owner->gc = *gc;
  1373. break;
  1374. }
  1375. case RTGUI_DC_HW:
  1376. {
  1377. struct rtgui_dc_hw *dc_hw;
  1378. dc_hw = (struct rtgui_dc_hw *) dc;
  1379. RT_ASSERT(dc_hw->owner != RT_NULL);
  1380. dc_hw->owner->gc = *gc;
  1381. break;
  1382. }
  1383. case RTGUI_DC_BUFFER:
  1384. {
  1385. struct rtgui_dc_buffer *dc_buffer;
  1386. dc_buffer = (struct rtgui_dc_buffer *)dc;
  1387. dc_buffer->gc = *gc;
  1388. break;
  1389. }
  1390. }
  1391. }
  1392. RTM_EXPORT(rtgui_dc_set_gc);
  1393. /*
  1394. * get gc of dc
  1395. */
  1396. rtgui_gc_t *rtgui_dc_get_gc(struct rtgui_dc *dc)
  1397. {
  1398. rtgui_gc_t *gc = RT_NULL;
  1399. RT_ASSERT(dc != RT_NULL);
  1400. switch (dc->type)
  1401. {
  1402. case RTGUI_DC_CLIENT:
  1403. {
  1404. rtgui_widget_t *owner;
  1405. /* get owner */
  1406. owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type);
  1407. gc = &owner->gc;
  1408. break;
  1409. }
  1410. case RTGUI_DC_HW:
  1411. {
  1412. struct rtgui_dc_hw *dc_hw;
  1413. dc_hw = (struct rtgui_dc_hw *) dc;
  1414. RT_ASSERT(dc_hw->owner != RT_NULL);
  1415. gc = &dc_hw->owner->gc;
  1416. break;
  1417. }
  1418. case RTGUI_DC_BUFFER:
  1419. {
  1420. struct rtgui_dc_buffer *dc_buffer;
  1421. dc_buffer = (struct rtgui_dc_buffer *)dc;
  1422. gc = &dc_buffer->gc;
  1423. break;
  1424. }
  1425. }
  1426. return gc;
  1427. }
  1428. RTM_EXPORT(rtgui_dc_get_gc);
  1429. /*
  1430. * get visible status of dc
  1431. */
  1432. rt_bool_t rtgui_dc_get_visible(struct rtgui_dc *dc)
  1433. {
  1434. rt_bool_t result = RT_TRUE;
  1435. RT_ASSERT(dc != RT_NULL);
  1436. if (rtgui_graphic_driver_is_vmode())
  1437. return RT_TRUE;
  1438. switch (dc->type)
  1439. {
  1440. case RTGUI_DC_CLIENT:
  1441. {
  1442. rtgui_widget_t *owner;
  1443. /* get owner */
  1444. owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type);
  1445. if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) result = RT_FALSE;
  1446. break;
  1447. }
  1448. case RTGUI_DC_HW:
  1449. {
  1450. struct rtgui_dc_hw *dc_hw;
  1451. dc_hw = (struct rtgui_dc_hw *) dc;
  1452. if (!RTGUI_WIDGET_IS_DC_VISIBLE(dc_hw->owner)) result = RT_FALSE;
  1453. break;
  1454. }
  1455. default:
  1456. /* use default value */
  1457. break;
  1458. }
  1459. return result;
  1460. }
  1461. RTM_EXPORT(rtgui_dc_get_visible);
  1462. /*
  1463. * get rect of dc
  1464. */
  1465. void rtgui_dc_get_rect(struct rtgui_dc *dc, rtgui_rect_t *rect)
  1466. {
  1467. RT_ASSERT(dc != RT_NULL);
  1468. switch (dc->type)
  1469. {
  1470. case RTGUI_DC_CLIENT:
  1471. {
  1472. rtgui_widget_t *owner;
  1473. /* get owner */
  1474. owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type);
  1475. /* we should return the clipped rectangular information */
  1476. rect->x1 = owner->clip.extents.x1 - owner->extent.x1;
  1477. rect->y1 = owner->clip.extents.y1 - owner->extent.y1;
  1478. rect->x2 = rect->x1 + owner->clip.extents.x2 - owner->clip.extents.x1;
  1479. rect->y2 = rect->y1 + owner->clip.extents.y2 - owner->clip.extents.y1;
  1480. // rtgui_widget_get_rect(owner, rect);
  1481. break;
  1482. }
  1483. case RTGUI_DC_HW:
  1484. {
  1485. rtgui_widget_t *owner;
  1486. struct rtgui_dc_hw *dc_hw;
  1487. dc_hw = (struct rtgui_dc_hw *) dc;
  1488. owner = dc_hw->owner;
  1489. rtgui_widget_get_rect(owner, rect);
  1490. if (owner->extent.x1 + rect->x2 > dc_hw->hw_driver->width)
  1491. rect->x2 = dc_hw->hw_driver->width - owner->extent.x1;
  1492. if (owner->extent.y1 + rect->y2 > dc_hw->hw_driver->height)
  1493. rect->y2 = dc_hw->hw_driver->height - owner->extent.y1;
  1494. break;
  1495. }
  1496. case RTGUI_DC_BUFFER:
  1497. {
  1498. struct rtgui_dc_buffer *dc_buffer;
  1499. dc_buffer = (struct rtgui_dc_buffer *)dc;
  1500. rtgui_rect_init(rect, 0, 0, dc_buffer->width, dc_buffer->height);
  1501. break;
  1502. }
  1503. }
  1504. return;
  1505. }
  1506. RTM_EXPORT(rtgui_dc_get_rect);
  1507. rt_uint8_t rtgui_dc_get_pixel_format(struct rtgui_dc *dc)
  1508. {
  1509. rt_uint8_t pixel_fmt;
  1510. RT_ASSERT(dc != RT_NULL);
  1511. switch (dc->type)
  1512. {
  1513. case RTGUI_DC_CLIENT:
  1514. case RTGUI_DC_HW:
  1515. {
  1516. struct rtgui_graphic_driver *hw_driver;
  1517. hw_driver = rtgui_graphic_driver_get_default();
  1518. pixel_fmt = hw_driver->pixel_format;
  1519. break;
  1520. }
  1521. case RTGUI_DC_BUFFER:
  1522. {
  1523. struct rtgui_dc_buffer *dc_buffer;
  1524. dc_buffer = (struct rtgui_dc_buffer *)dc;
  1525. pixel_fmt = dc_buffer->pixel_format;
  1526. break;
  1527. }
  1528. default:
  1529. RT_ASSERT(0);
  1530. }
  1531. return pixel_fmt;
  1532. }
  1533. RTM_EXPORT(rtgui_dc_get_pixel_format);
  1534. void rtgui_dc_logic_to_device(struct rtgui_dc *dc, struct rtgui_point *point)
  1535. {
  1536. switch (dc->type)
  1537. {
  1538. case RTGUI_DC_CLIENT:
  1539. {
  1540. rtgui_widget_t *owner;
  1541. /* get owner */
  1542. owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type);
  1543. point->x += owner->extent.x1;
  1544. point->y += owner->extent.y1;
  1545. break;
  1546. }
  1547. case RTGUI_DC_HW:
  1548. {
  1549. rtgui_widget_t *owner;
  1550. struct rtgui_dc_hw *dc_hw;
  1551. dc_hw = (struct rtgui_dc_hw *) dc;
  1552. owner = dc_hw->owner;
  1553. point->x += owner->extent.x1;
  1554. point->y += owner->extent.y1;
  1555. break;
  1556. }
  1557. case RTGUI_DC_BUFFER: /* no conversion */
  1558. break;
  1559. }
  1560. }
  1561. RTM_EXPORT(rtgui_dc_logic_to_device);
  1562. void rtgui_dc_rect_to_device(struct rtgui_dc *dc, struct rtgui_rect *rect)
  1563. {
  1564. switch (dc->type)
  1565. {
  1566. case RTGUI_DC_CLIENT:
  1567. {
  1568. rtgui_widget_t *owner;
  1569. /* get owner */
  1570. owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type);
  1571. rtgui_rect_move(rect, owner->extent.x1, owner->extent.y1);
  1572. break;
  1573. }
  1574. case RTGUI_DC_HW:
  1575. {
  1576. rtgui_widget_t *owner;
  1577. struct rtgui_dc_hw *dc_hw;
  1578. dc_hw = (struct rtgui_dc_hw *) dc;
  1579. owner = dc_hw->owner;
  1580. rtgui_rect_move(rect, owner->extent.x1, owner->extent.y1);
  1581. break;
  1582. }
  1583. case RTGUI_DC_BUFFER: /* no conversion */
  1584. break;
  1585. }
  1586. }
  1587. RTM_EXPORT(rtgui_dc_rect_to_device);
  1588. extern struct rt_mutex cursor_mutex;
  1589. extern void rtgui_mouse_show_cursor(void);
  1590. extern void rtgui_mouse_hide_cursor(void);
  1591. struct rtgui_dc *rtgui_dc_begin_drawing(rtgui_widget_t *owner)
  1592. {
  1593. struct rtgui_dc *dc;
  1594. struct rtgui_widget *widget, *parent;
  1595. struct rtgui_win *win;
  1596. RT_ASSERT(owner != RT_NULL);
  1597. win = owner->toplevel;
  1598. if (win == RT_NULL)
  1599. return RT_NULL;
  1600. parent = (struct rtgui_widget *)win;
  1601. if (!(win->flag & RTGUI_WIN_FLAG_ACTIVATE) &&
  1602. (win->outer_clip.extents.x1 == win->outer_clip.extents.x2 ||
  1603. win->outer_clip.extents.y1 == win->outer_clip.extents.y2))
  1604. return RT_NULL;
  1605. if (!(win->flag & RTGUI_WIN_FLAG_ACTIVATE) &&
  1606. (parent->clip.extents.x1 == parent->clip.extents.x2 ||
  1607. parent->clip.extents.y1 == parent->clip.extents.y2))
  1608. return RT_NULL;
  1609. /* increase drawing count */
  1610. if (win->drawing == 0)
  1611. {
  1612. memset(&(win->drawing_rect), 0x0, sizeof(struct rtgui_rect));
  1613. }
  1614. win->drawing ++;
  1615. /* always drawing on the virtual mode */
  1616. if (rtgui_graphic_driver_is_vmode() == RT_FALSE)
  1617. {
  1618. /* set the initial visible as true */
  1619. RTGUI_WIDGET_DC_SET_VISIBLE(owner);
  1620. /* check the visible of widget */
  1621. widget = owner;
  1622. while (widget != RT_NULL)
  1623. {
  1624. if (RTGUI_WIDGET_IS_HIDE(widget))
  1625. {
  1626. RTGUI_WIDGET_DC_SET_UNVISIBLE(owner);
  1627. win->drawing --;
  1628. return RT_NULL;
  1629. }
  1630. widget = widget->parent;
  1631. }
  1632. }
  1633. rtgui_screen_lock(RT_WAITING_FOREVER);
  1634. /* create client or hardware DC */
  1635. if ((rtgui_region_is_flat(&owner->clip) == RT_EOK) &&
  1636. rtgui_rect_is_equal(&(owner->extent), &(owner->clip.extents)) == RT_EOK)
  1637. dc = rtgui_dc_hw_create(owner);
  1638. else
  1639. dc = rtgui_dc_client_create(owner);
  1640. if (dc == RT_NULL)
  1641. {
  1642. /* restore drawing counter */
  1643. win->drawing--;
  1644. rtgui_screen_unlock();
  1645. }
  1646. else if (win->drawing == 1 && rtgui_graphic_driver_is_vmode() == RT_FALSE)
  1647. {
  1648. #ifdef RTGUI_USING_MOUSE_CURSOR
  1649. rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER);
  1650. rtgui_mouse_hide_cursor();
  1651. #endif
  1652. if (! RTGUI_IS_WINTITLE(win))
  1653. {
  1654. /* send draw begin to server */
  1655. struct rtgui_event_update_begin eupdate;
  1656. RTGUI_EVENT_UPDATE_BEGIN_INIT(&(eupdate));
  1657. eupdate.rect = RTGUI_WIDGET(win)->extent;
  1658. rtgui_server_post_event((struct rtgui_event *)&eupdate, sizeof(eupdate));
  1659. }
  1660. }
  1661. return dc;
  1662. }
  1663. RTM_EXPORT(rtgui_dc_begin_drawing);
  1664. void rtgui_dc_end_drawing(struct rtgui_dc *dc, rt_bool_t update)
  1665. {
  1666. struct rtgui_widget *owner;
  1667. struct rtgui_win *win;
  1668. RT_ASSERT(dc != RT_NULL);
  1669. /* get owner */
  1670. if (dc->type == RTGUI_DC_CLIENT)
  1671. owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type);
  1672. else if (dc->type == RTGUI_DC_HW)
  1673. owner = ((struct rtgui_dc_hw *)dc)->owner;
  1674. else return ; /* bad DC type */
  1675. /* get window */
  1676. win = owner->toplevel;
  1677. /* union drawing rect */
  1678. rtgui_rect_union(&(owner->extent_visiable), &(win->drawing_rect));
  1679. /* decrease drawing counter */
  1680. win->drawing--;
  1681. if (win->drawing == 0)
  1682. {
  1683. /* notify window to handle window update done */
  1684. if (RTGUI_OBJECT(win)->event_handler)
  1685. {
  1686. struct rtgui_event_win_update_end ewin_update;
  1687. RTGUI_EVENT_WIN_UPDATE_END_INIT(&(ewin_update));
  1688. ewin_update.rect = win->drawing_rect;
  1689. RTGUI_OBJECT(win)->event_handler(RTGUI_OBJECT(win), (struct rtgui_event *)&ewin_update);
  1690. }
  1691. if (rtgui_graphic_driver_is_vmode() == RT_FALSE && win->update == 0 && update)
  1692. {
  1693. #ifdef RTGUI_USING_MOUSE_CURSOR
  1694. rt_mutex_release(&cursor_mutex);
  1695. /* show cursor */
  1696. rtgui_mouse_show_cursor();
  1697. #endif
  1698. if (RTGUI_IS_WINTITLE(win))
  1699. {
  1700. /* update screen */
  1701. rtgui_graphic_driver_screen_update(rtgui_graphic_driver_get_default(),
  1702. &(owner->extent));
  1703. }
  1704. else
  1705. {
  1706. /* send to server for window update */
  1707. struct rtgui_event_update_end eupdate;
  1708. RTGUI_EVENT_UPDATE_END_INIT(&(eupdate));
  1709. eupdate.rect = owner->extent;
  1710. rtgui_server_post_event((struct rtgui_event *)&eupdate, sizeof(eupdate));
  1711. }
  1712. }
  1713. }
  1714. dc->engine->fini(dc);
  1715. rtgui_screen_unlock();
  1716. }
  1717. RTM_EXPORT(rtgui_dc_end_drawing);