dc.c 48 KB

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