dc.c 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950
  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. break;
  1491. }
  1492. case RTGUI_DC_BUFFER:
  1493. {
  1494. struct rtgui_dc_buffer *dc_buffer;
  1495. dc_buffer = (struct rtgui_dc_buffer *)dc;
  1496. rtgui_rect_init(rect, 0, 0, dc_buffer->width, dc_buffer->height);
  1497. break;
  1498. }
  1499. }
  1500. return;
  1501. }
  1502. RTM_EXPORT(rtgui_dc_get_rect);
  1503. rt_uint8_t rtgui_dc_get_pixel_format(struct rtgui_dc *dc)
  1504. {
  1505. rt_uint8_t pixel_fmt;
  1506. RT_ASSERT(dc != RT_NULL);
  1507. switch (dc->type)
  1508. {
  1509. case RTGUI_DC_CLIENT:
  1510. case RTGUI_DC_HW:
  1511. {
  1512. struct rtgui_graphic_driver *hw_driver;
  1513. hw_driver = rtgui_graphic_driver_get_default();
  1514. pixel_fmt = hw_driver->pixel_format;
  1515. break;
  1516. }
  1517. case RTGUI_DC_BUFFER:
  1518. {
  1519. struct rtgui_dc_buffer *dc_buffer;
  1520. dc_buffer = (struct rtgui_dc_buffer *)dc;
  1521. pixel_fmt = dc_buffer->pixel_format;
  1522. break;
  1523. }
  1524. default:
  1525. RT_ASSERT(0);
  1526. }
  1527. return pixel_fmt;
  1528. }
  1529. RTM_EXPORT(rtgui_dc_get_pixel_format);
  1530. void rtgui_dc_logic_to_device(struct rtgui_dc *dc, struct rtgui_point *point)
  1531. {
  1532. switch (dc->type)
  1533. {
  1534. case RTGUI_DC_CLIENT:
  1535. {
  1536. rtgui_widget_t *owner;
  1537. /* get owner */
  1538. owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type);
  1539. point->x += owner->extent.x1;
  1540. point->y += owner->extent.y1;
  1541. break;
  1542. }
  1543. case RTGUI_DC_HW:
  1544. {
  1545. rtgui_widget_t *owner;
  1546. struct rtgui_dc_hw *dc_hw;
  1547. dc_hw = (struct rtgui_dc_hw *) dc;
  1548. owner = dc_hw->owner;
  1549. point->x += owner->extent.x1;
  1550. point->y += owner->extent.y1;
  1551. break;
  1552. }
  1553. case RTGUI_DC_BUFFER: /* no conversion */
  1554. break;
  1555. }
  1556. }
  1557. RTM_EXPORT(rtgui_dc_logic_to_device);
  1558. void rtgui_dc_rect_to_device(struct rtgui_dc *dc, struct rtgui_rect *rect)
  1559. {
  1560. switch (dc->type)
  1561. {
  1562. case RTGUI_DC_CLIENT:
  1563. {
  1564. rtgui_widget_t *owner;
  1565. /* get owner */
  1566. owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type);
  1567. rtgui_rect_move(rect, owner->extent.x1, owner->extent.y1);
  1568. break;
  1569. }
  1570. case RTGUI_DC_HW:
  1571. {
  1572. rtgui_widget_t *owner;
  1573. struct rtgui_dc_hw *dc_hw;
  1574. dc_hw = (struct rtgui_dc_hw *) dc;
  1575. owner = dc_hw->owner;
  1576. rtgui_rect_move(rect, owner->extent.x1, owner->extent.y1);
  1577. break;
  1578. }
  1579. case RTGUI_DC_BUFFER: /* no conversion */
  1580. break;
  1581. }
  1582. }
  1583. RTM_EXPORT(rtgui_dc_rect_to_device);
  1584. extern struct rt_mutex cursor_mutex;
  1585. extern void rtgui_mouse_show_cursor(void);
  1586. extern void rtgui_mouse_hide_cursor(void);
  1587. struct rtgui_dc *rtgui_dc_begin_drawing(rtgui_widget_t *owner)
  1588. {
  1589. struct rtgui_dc *dc;
  1590. struct rtgui_widget *widget;
  1591. struct rtgui_win *win;
  1592. RT_ASSERT(owner != RT_NULL);
  1593. win = owner->toplevel;
  1594. if (win == RT_NULL)
  1595. return RT_NULL;
  1596. if (!(win->flag & RTGUI_WIN_FLAG_ACTIVATE) &&
  1597. (win->outer_clip.extents.x1 == win->outer_clip.extents.x2 ||
  1598. win->outer_clip.extents.y1 == win->outer_clip.extents.y2))
  1599. return RT_NULL;
  1600. /* increase drawing count */
  1601. if (win->drawing == 0)
  1602. {
  1603. memset(&(win->drawing_rect), 0x0, sizeof(struct rtgui_rect));
  1604. }
  1605. win->drawing ++;
  1606. /* always drawing on the virtual mode */
  1607. if (rtgui_graphic_driver_is_vmode() == RT_FALSE)
  1608. {
  1609. /* set the initial visible as true */
  1610. RTGUI_WIDGET_DC_SET_VISIBLE(owner);
  1611. /* check the visible of widget */
  1612. widget = owner;
  1613. while (widget != RT_NULL)
  1614. {
  1615. if (RTGUI_WIDGET_IS_HIDE(widget))
  1616. {
  1617. RTGUI_WIDGET_DC_SET_UNVISIBLE(owner);
  1618. win->drawing --;
  1619. return RT_NULL;
  1620. }
  1621. widget = widget->parent;
  1622. }
  1623. }
  1624. rtgui_screen_lock(RT_WAITING_FOREVER);
  1625. /* create client or hardware DC */
  1626. if ((rtgui_region_is_flat(&owner->clip) == RT_EOK) &&
  1627. rtgui_rect_is_equal(&(owner->extent), &(owner->clip.extents)) == RT_EOK)
  1628. dc = rtgui_dc_hw_create(owner);
  1629. else
  1630. dc = rtgui_dc_client_create(owner);
  1631. if (dc == RT_NULL)
  1632. {
  1633. /* restore drawing counter */
  1634. win->drawing--;
  1635. rtgui_screen_unlock();
  1636. }
  1637. else if (win->drawing == 1 && rtgui_graphic_driver_is_vmode() == RT_FALSE)
  1638. {
  1639. #ifdef RTGUI_USING_MOUSE_CURSOR
  1640. rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER);
  1641. rtgui_mouse_hide_cursor();
  1642. #endif
  1643. if (! RTGUI_IS_WINTITLE(win))
  1644. {
  1645. /* send draw begin to server */
  1646. struct rtgui_event_update_begin eupdate;
  1647. RTGUI_EVENT_UPDATE_BEGIN_INIT(&(eupdate));
  1648. eupdate.rect = RTGUI_WIDGET(win)->extent;
  1649. rtgui_server_post_event((struct rtgui_event *)&eupdate, sizeof(eupdate));
  1650. }
  1651. }
  1652. return dc;
  1653. }
  1654. RTM_EXPORT(rtgui_dc_begin_drawing);
  1655. void rtgui_dc_end_drawing(struct rtgui_dc *dc, rt_bool_t update)
  1656. {
  1657. struct rtgui_widget *owner;
  1658. struct rtgui_win *win;
  1659. RT_ASSERT(dc != RT_NULL);
  1660. /* get owner */
  1661. if (dc->type == RTGUI_DC_CLIENT)
  1662. owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type);
  1663. else if (dc->type == RTGUI_DC_HW)
  1664. owner = ((struct rtgui_dc_hw *)dc)->owner;
  1665. else return ; /* bad DC type */
  1666. /* get window */
  1667. win = owner->toplevel;
  1668. /* union drawing rect */
  1669. rtgui_rect_union(&(owner->extent_visiable), &(win->drawing_rect));
  1670. /* decrease drawing counter */
  1671. win->drawing--;
  1672. if (win->drawing == 0)
  1673. {
  1674. /* notify window to handle window update done */
  1675. if (RTGUI_OBJECT(win)->event_handler)
  1676. {
  1677. struct rtgui_event_win_update_end ewin_update;
  1678. RTGUI_EVENT_WIN_UPDATE_END_INIT(&(ewin_update));
  1679. ewin_update.rect = win->drawing_rect;
  1680. RTGUI_OBJECT(win)->event_handler(RTGUI_OBJECT(win), (struct rtgui_event *)&ewin_update);
  1681. }
  1682. if (rtgui_graphic_driver_is_vmode() == RT_FALSE && win->update == 0 && update)
  1683. {
  1684. #ifdef RTGUI_USING_MOUSE_CURSOR
  1685. rt_mutex_release(&cursor_mutex);
  1686. /* show cursor */
  1687. rtgui_mouse_show_cursor();
  1688. #endif
  1689. if (RTGUI_IS_WINTITLE(win))
  1690. {
  1691. /* update screen */
  1692. rtgui_graphic_driver_screen_update(rtgui_graphic_driver_get_default(),
  1693. &(owner->extent));
  1694. }
  1695. else
  1696. {
  1697. /* send to server for window update */
  1698. struct rtgui_event_update_end eupdate;
  1699. RTGUI_EVENT_UPDATE_END_INIT(&(eupdate));
  1700. eupdate.rect = owner->extent;
  1701. rtgui_server_post_event((struct rtgui_event *)&eupdate, sizeof(eupdate));
  1702. }
  1703. }
  1704. }
  1705. dc->engine->fini(dc);
  1706. rtgui_screen_unlock();
  1707. }
  1708. RTM_EXPORT(rtgui_dc_end_drawing);