dc.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  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. */
  14. #include <rtgui/dc.h>
  15. #include <rtgui/rtgui_system.h>
  16. #include <string.h> /* for strlen */
  17. #include <stdlib.h> /* fir qsort */
  18. /* for sin/cos etc */
  19. #include <math.h>
  20. #ifndef M_PI
  21. #define M_PI 3.14159265358979323846
  22. #endif
  23. void rtgui_dc_destory(struct rtgui_dc* dc)
  24. {
  25. if (dc == RT_NULL) return;
  26. dc->engine->fini(dc);
  27. rtgui_free(dc);
  28. }
  29. void rtgui_dc_draw_line (struct rtgui_dc* dc, int x1, int y1, int x2, int y2)
  30. {
  31. if (dc == RT_NULL) return;
  32. if (y1 == y2)
  33. {
  34. rtgui_dc_draw_hline(dc, x1, x2, y1);
  35. }
  36. else if (x1 == x2)
  37. {
  38. rtgui_dc_draw_vline(dc, x1, y1, y2);
  39. }
  40. else
  41. {
  42. int dx, dy, sdx, sdy, dxabs, dyabs, x, y, px, py;
  43. register rt_base_t i;
  44. /* rtgui_rect_t rect; */
  45. dx = x2 - x1; /* the horizontal distance of the line */
  46. dy = y2 - y1; /* the vertical distance of the line */
  47. #define rtgui_sgn(x) ((x<0)?-1:((x>0)?1:0)) /* macro to return the sign of a number */
  48. #define rtgui_abs(x) ((x)>=0? (x):-(x)) /* macro to return the absolute value */
  49. dxabs = rtgui_abs(dx);
  50. dyabs = rtgui_abs(dy);
  51. sdx = rtgui_sgn(dx);
  52. sdy = rtgui_sgn(dy);
  53. x = dyabs >> 1;
  54. y = dxabs >> 1;
  55. px = x1;
  56. py = y1;
  57. if(dxabs >= dyabs) /* the line is more horizontal than vertical */
  58. {
  59. for(i = 0; i < dxabs; i++)
  60. {
  61. y += dyabs;
  62. if(y >= dxabs)
  63. {
  64. y -= dxabs;
  65. py += sdy;
  66. }
  67. px += sdx;
  68. /* draw this point */
  69. rtgui_dc_draw_point(dc, px, py);
  70. }
  71. }
  72. else /* the line is more vertical than horizontal */
  73. {
  74. for(i = 0; i < dyabs; i++)
  75. {
  76. x += dxabs;
  77. if(x >= dyabs)
  78. {
  79. x -= dyabs;
  80. px += sdx;
  81. }
  82. py += sdy;
  83. /* draw this point */
  84. rtgui_dc_draw_point(dc, px, py);
  85. }
  86. }
  87. }
  88. }
  89. void rtgui_dc_draw_rect (struct rtgui_dc* dc, struct rtgui_rect* rect)
  90. {
  91. rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y1);
  92. rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y2 - 1);
  93. rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2);
  94. rtgui_dc_draw_vline(dc, rect->x2 - 1, rect->y1, rect->y2);
  95. }
  96. void rtgui_dc_draw_round_rect(struct rtgui_dc* dc, struct rtgui_rect* rect)
  97. {
  98. int r = 3;
  99. rtgui_dc_draw_arc(dc, rect->x1 + r, rect->y1 + r, r, 180, 270);
  100. rtgui_dc_draw_arc(dc, rect->x2 - r, rect->y1 + r, r, 270, 360);
  101. rtgui_dc_draw_arc(dc, rect->x1 + r, rect->y2 - r, r, 90, 180);
  102. rtgui_dc_draw_arc(dc, rect->x2 - r, rect->y2 - r, r, 0, 90);
  103. rtgui_dc_draw_hline(dc, rect->x1 + r, rect->x2 - r, rect->y1);
  104. rtgui_dc_draw_hline(dc, rect->x1 + r, rect->x2 - r, rect->y2);
  105. rtgui_dc_draw_vline(dc, rect->x1, rect->y1 + r, rect->y2 - r);
  106. rtgui_dc_draw_vline(dc, rect->x2, rect->y1 + r, rect->y2 - r);
  107. }
  108. void rtgui_dc_draw_text (struct rtgui_dc* dc, const char* text, struct rtgui_rect* rect)
  109. {
  110. rt_uint32_t len;
  111. struct rtgui_font *font;
  112. #ifdef RTGUI_USING_FONTHZ
  113. struct rtgui_font *gb2312_font;
  114. #endif
  115. struct rtgui_rect text_rect;
  116. RT_ASSERT(dc != RT_NULL);
  117. font = RTGUI_DC_FONT(dc);
  118. if (font == RT_NULL)
  119. {
  120. /* use system default font */
  121. font = rtgui_font_default();
  122. }
  123. #ifdef RTGUI_USING_FONTHZ
  124. gb2312_font = rtgui_font_refer("hz", font->height);
  125. if (gb2312_font == RT_NULL)
  126. {
  127. gb2312_font = rtgui_font_refer("hz", 16);
  128. }
  129. #endif
  130. /* text align */
  131. rtgui_font_get_metrics(font, text, &text_rect);
  132. rtgui_rect_moveto_align(rect, &text_rect, RTGUI_DC_TEXTALIGN(dc));
  133. #ifdef RTGUI_USING_FONTHZ
  134. while (*text)
  135. {
  136. len = 0;
  137. while (((rt_uint8_t)*(text + len)) < 0x80 && *(text + len)) len ++;
  138. if (len > 0)
  139. {
  140. rtgui_font_draw(font, dc, text, len, &text_rect);
  141. text += len;
  142. }
  143. len = 0;
  144. while (((rt_uint8_t)*(text + len)) > 0x80) len ++;
  145. if (len > 0)
  146. {
  147. rtgui_font_draw(gb2312_font, dc, text, len, &text_rect);
  148. text += len;
  149. }
  150. }
  151. rtgui_font_derefer(gb2312_font);
  152. #else
  153. len = strlen((const char*)text);
  154. rtgui_font_draw(font, dc, text, len, &text_rect);
  155. #endif
  156. }
  157. /*
  158. * draw a monochrome color bitmap data
  159. */
  160. void rtgui_dc_draw_mono_bmp(struct rtgui_dc* dc, int x, int y, int w, int h, const rt_uint8_t* data)
  161. {
  162. int word_bytes;
  163. int i, j, k;
  164. /* get word bytes */
  165. word_bytes = (w + 7)/8;
  166. /* draw mono bitmap data */
  167. for (i = 0; i < h; i ++)
  168. for (j = 0; j < word_bytes; j++)
  169. for (k = 0; k < 8; k++)
  170. if ( ((data[i*2 + j] >> (7-k)) & 0x01) != 0)
  171. rtgui_dc_draw_point(dc, x + 8*j + k, y + i);
  172. }
  173. void rtgui_dc_draw_byte(struct rtgui_dc*dc, int x, int y, int h, const rt_uint8_t* data)
  174. {
  175. int i, k;
  176. /* draw byte */
  177. for (i=0; i < h; i ++)
  178. {
  179. for (k=0; k < 8; k++)
  180. {
  181. if (((data[i] >> (7-k)) & 0x01) != 0)
  182. {
  183. rtgui_dc_draw_point(dc, x + k, y + i);
  184. }
  185. }
  186. }
  187. }
  188. void rtgui_dc_draw_word(struct rtgui_dc*dc, int x, int y, int h, const rt_uint8_t* data)
  189. {
  190. int i, j, k;
  191. /* draw word */
  192. for (i=0; i < h; i ++)
  193. {
  194. for (j=0; j < 2; j++)
  195. for (k=0; k < 8; k++)
  196. {
  197. if (((data[i * 2 + j] >> (7-k)) & 0x01) != 0)
  198. {
  199. rtgui_dc_draw_point(dc, x + 8*j + k, y + i);
  200. }
  201. }
  202. }
  203. }
  204. void rtgui_dc_draw_shaded_rect(struct rtgui_dc* dc, rtgui_rect_t* rect,
  205. rtgui_color_t c1, rtgui_color_t c2)
  206. {
  207. RT_ASSERT(dc != RT_NULL);
  208. RTGUI_DC_FC(dc) = c1;
  209. rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2);
  210. rtgui_dc_draw_hline(dc, rect->x1 + 1, rect->x2, rect->y1);
  211. RTGUI_DC_FC(dc) = c2;
  212. rtgui_dc_draw_vline(dc, rect->x2, rect->y1, rect->y2);
  213. rtgui_dc_draw_hline(dc, rect->x1, rect->x2 + 1, rect->y2);
  214. }
  215. void rtgui_dc_draw_border(struct rtgui_dc* dc, rtgui_rect_t* rect, int flag)
  216. {
  217. rtgui_rect_t r;
  218. rtgui_color_t color;
  219. if (dc == RT_NULL) return ;
  220. /* save old color */
  221. color = RTGUI_DC_FC(dc);
  222. r = *rect;
  223. switch (flag)
  224. {
  225. case RTGUI_BORDER_RAISE:
  226. rtgui_dc_draw_shaded_rect(dc, &r, high_light, black);
  227. rtgui_rect_inflate(&r, -1);
  228. rtgui_dc_draw_shaded_rect(dc, &r, light_grey, dark_grey);
  229. break;
  230. case RTGUI_BORDER_SUNKEN:
  231. rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
  232. rtgui_rect_inflate(&r, -1);
  233. rtgui_dc_draw_shaded_rect(dc, &r, black, light_grey);
  234. break;
  235. case RTGUI_BORDER_BOX:
  236. rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
  237. rtgui_rect_inflate(&r, -1);
  238. rtgui_dc_draw_shaded_rect(dc, &r, high_light, dark_grey);
  239. break;
  240. case RTGUI_BORDER_STATIC:
  241. rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
  242. break;
  243. case RTGUI_BORDER_EXTRA:
  244. RTGUI_DC_FC(dc) = light_grey;
  245. rtgui_dc_draw_rect(dc, &r);
  246. break;
  247. case RTGUI_BORDER_SIMPLE:
  248. RTGUI_DC_FC(dc) = black;
  249. rtgui_dc_draw_rect(dc, &r);
  250. break;
  251. default:
  252. break;
  253. }
  254. /* restore color */
  255. RTGUI_DC_FC(dc) = color;
  256. }
  257. void rtgui_dc_draw_horizontal_line(struct rtgui_dc* dc, int x1, int x2, int y)
  258. {
  259. rtgui_color_t color;
  260. if (dc == RT_NULL) return ;
  261. /* save old color */
  262. color = RTGUI_DC_FC(dc);
  263. RTGUI_DC_FC(dc) = dark_grey;
  264. rtgui_dc_draw_hline(dc, x1, x2, y);
  265. y ++;
  266. RTGUI_DC_FC(dc) = high_light;
  267. rtgui_dc_draw_hline(dc, x1, x2, y);
  268. /* restore color */
  269. RTGUI_DC_FC(dc) = color;
  270. }
  271. void rtgui_dc_draw_vertical_line(struct rtgui_dc* dc, int x, int y1, int y2)
  272. {
  273. rtgui_color_t color;
  274. if (dc == RT_NULL) return ;
  275. /* save old color */
  276. color = RTGUI_DC_FC(dc);
  277. RTGUI_DC_FC(dc) = dark_grey;
  278. rtgui_dc_draw_hline(dc, x, y1, y2);
  279. x ++;
  280. RTGUI_DC_FC(dc) = high_light;
  281. rtgui_dc_draw_hline(dc, x, y1, y2);
  282. /* restore color */
  283. RTGUI_DC_FC(dc) = color;
  284. }
  285. void rtgui_dc_draw_polygon(struct rtgui_dc* dc, const int *vx, const int *vy, int count)
  286. {
  287. int i;
  288. const int *x1, *y1, *x2, *y2;
  289. /*
  290. * Sanity check
  291. */
  292. if (count < 3) return;
  293. /*
  294. * Pointer setup
  295. */
  296. x1 = x2 = vx;
  297. y1 = y2 = vy;
  298. x2++;
  299. y2++;
  300. /*
  301. * Draw
  302. */
  303. for (i = 1; i < count; i++)
  304. {
  305. rtgui_dc_draw_line(dc, *x1, *y1, *x2, *y2);
  306. x1 = x2;
  307. y1 = y2;
  308. x2++;
  309. y2++;
  310. }
  311. rtgui_dc_draw_line(dc, *x1, *y1, *vx, *vy);
  312. }
  313. static int _int_compare(const void *a, const void *b)
  314. {
  315. return (*(const int *) a) - (*(const int *) b);
  316. }
  317. void rtgui_dc_fill_polygon(struct rtgui_dc* dc, const int* vx, const int* vy, int count)
  318. {
  319. int i;
  320. int y, xa, xb;
  321. int miny, maxy;
  322. int x1, y1;
  323. int x2, y2;
  324. int ind1, ind2;
  325. int ints;
  326. int *poly_ints = RT_NULL;
  327. /*
  328. * Sanity check number of edges
  329. */
  330. if (count < 3) return;
  331. /*
  332. * Allocate temp array, only grow array
  333. */
  334. poly_ints = (int *) rt_malloc(sizeof(int) * count);
  335. if (poly_ints == RT_NULL) return ; /* no memory, failed */
  336. /*
  337. * Determine Y maximal
  338. */
  339. miny = vy[0];
  340. maxy = vy[0];
  341. for (i = 1; (i < count); i++)
  342. {
  343. if (vy[i] < miny) miny = vy[i];
  344. else if (vy[i] > maxy) maxy = vy[i];
  345. }
  346. /*
  347. * Draw, scanning y
  348. */
  349. for (y = miny; (y <= maxy); y++) {
  350. ints = 0;
  351. for (i = 0; (i < count); i++) {
  352. if (!i) {
  353. ind1 = count - 1;
  354. ind2 = 0;
  355. } else {
  356. ind1 = i - 1;
  357. ind2 = i;
  358. }
  359. y1 = vy[ind1];
  360. y2 = vy[ind2];
  361. if (y1 < y2) {
  362. x1 = vx[ind1];
  363. x2 = vx[ind2];
  364. } else if (y1 > y2) {
  365. y2 = vy[ind1];
  366. y1 = vy[ind2];
  367. x2 = vx[ind1];
  368. x1 = vx[ind2];
  369. } else {
  370. continue;
  371. }
  372. if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) )
  373. {
  374. poly_ints[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
  375. }
  376. }
  377. qsort(poly_ints, ints, sizeof(int), _int_compare);
  378. for (i = 0; (i < ints); i += 2)
  379. {
  380. xa = poly_ints[i] + 1;
  381. xa = (xa >> 16) + ((xa & 32768) >> 15);
  382. xb = poly_ints[i+1] - 1;
  383. xb = (xb >> 16) + ((xb & 32768) >> 15);
  384. rtgui_dc_draw_hline(dc, xa, xb, y);
  385. }
  386. }
  387. }
  388. void rtgui_dc_draw_circle(struct rtgui_dc* dc, int x, int y, int r)
  389. {
  390. rt_int16_t cx = 0;
  391. rt_int16_t cy = r;
  392. rt_int16_t df = 1 - r;
  393. rt_int16_t d_e = 3;
  394. rt_int16_t d_se = -2 * r + 5;
  395. rt_int16_t xpcx, xmcx, xpcy, xmcy;
  396. rt_int16_t ypcy, ymcy, ypcx, ymcx;
  397. /*
  398. * sanity check radius
  399. */
  400. if (r < 0) return ;
  401. /* special case for r=0 - draw a point */
  402. if (r == 0) rtgui_dc_draw_point(dc, x, y);
  403. /*
  404. * draw circle
  405. */
  406. do
  407. {
  408. ypcy = y + cy;
  409. ymcy = y - cy;
  410. if (cx > 0)
  411. {
  412. xpcx = x + cx;
  413. xmcx = x - cx;
  414. rtgui_dc_draw_point(dc, xmcx, ypcy);
  415. rtgui_dc_draw_point(dc, xpcx, ypcy);
  416. rtgui_dc_draw_point(dc, xmcx, ymcy);
  417. rtgui_dc_draw_point(dc, xpcx, ymcy);
  418. }
  419. else
  420. {
  421. rtgui_dc_draw_point(dc, x, ymcy);
  422. rtgui_dc_draw_point(dc, x, ypcy);
  423. }
  424. xpcy = x + cy;
  425. xmcy = x - cy;
  426. if ((cx > 0) && (cx != cy))
  427. {
  428. ypcx = y + cx;
  429. ymcx = y - cx;
  430. rtgui_dc_draw_point(dc, xmcy, ypcx);
  431. rtgui_dc_draw_point(dc, xpcy, ypcx);
  432. rtgui_dc_draw_point(dc, xmcy, ymcx);
  433. rtgui_dc_draw_point(dc, xpcy, ymcx);
  434. }
  435. else if (cx == 0)
  436. {
  437. rtgui_dc_draw_point(dc, xmcy, y);
  438. rtgui_dc_draw_point(dc, xpcy, y);
  439. }
  440. /*
  441. * Update
  442. */
  443. if (df < 0)
  444. {
  445. df += d_e;
  446. d_e += 2;
  447. d_se += 2;
  448. }
  449. else
  450. {
  451. df += d_se;
  452. d_e += 2;
  453. d_se += 4;
  454. cy--;
  455. }
  456. cx++;
  457. }while (cx <= cy);
  458. }
  459. void rtgui_dc_fill_circle(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t r)
  460. {
  461. rt_int16_t cx = 0;
  462. rt_int16_t cy = r;
  463. rt_int16_t ocx = (rt_int16_t) 0xffff;
  464. rt_int16_t ocy = (rt_int16_t) 0xffff;
  465. rt_int16_t df = 1 - r;
  466. rt_int16_t d_e = 3;
  467. rt_int16_t d_se = -2 * r + 5;
  468. rt_int16_t xpcx, xmcx, xpcy, xmcy;
  469. rt_int16_t ypcy, ymcy, ypcx, ymcx;
  470. /*
  471. * Sanity check radius
  472. */
  473. if (r < 0) return;
  474. /*
  475. * Special case for r=0 - draw a point
  476. */
  477. if (r == 0)
  478. {
  479. rtgui_dc_draw_point(dc, x, y);
  480. return ;
  481. }
  482. /*
  483. * Draw
  484. */
  485. do {
  486. xpcx = x + cx;
  487. xmcx = x - cx;
  488. xpcy = x + cy;
  489. xmcy = x - cy;
  490. if (ocy != cy) {
  491. if (cy > 0) {
  492. ypcy = y + cy;
  493. ymcy = y - cy;
  494. rtgui_dc_draw_hline(dc, xmcx, xpcx, ypcy);
  495. rtgui_dc_draw_hline(dc, xmcx, xpcx, ymcy);
  496. } else {
  497. rtgui_dc_draw_hline(dc, xmcx, xpcx, y);
  498. }
  499. ocy = cy;
  500. }
  501. if (ocx != cx) {
  502. if (cx != cy) {
  503. if (cx > 0) {
  504. ypcx = y + cx;
  505. ymcx = y - cx;
  506. rtgui_dc_draw_hline(dc, xmcy, xpcy, ymcx);
  507. rtgui_dc_draw_hline(dc, xmcy, xpcy, ypcx);
  508. } else {
  509. rtgui_dc_draw_hline(dc, xmcy, xpcy, y);
  510. }
  511. }
  512. ocx = cx;
  513. }
  514. /*
  515. * Update
  516. */
  517. if (df < 0) {
  518. df += d_e;
  519. d_e += 2;
  520. d_se += 2;
  521. } else {
  522. df += d_se;
  523. d_e += 2;
  524. d_se += 4;
  525. cy--;
  526. }
  527. cx++;
  528. } while (cx <= cy);
  529. }
  530. 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)
  531. {
  532. rt_int16_t cx = 0;
  533. rt_int16_t cy = r;
  534. rt_int16_t df = 1 - r;
  535. rt_int16_t d_e = 3;
  536. rt_int16_t d_se = -2 * r + 5;
  537. rt_int16_t xpcx, xmcx, xpcy, xmcy;
  538. rt_int16_t ypcy, ymcy, ypcx, ymcx;
  539. rt_uint8_t drawoct;
  540. int startoct, endoct, oct, stopval_start, stopval_end;
  541. double temp;
  542. stopval_start = 0;
  543. stopval_end = 0;
  544. temp = 0;
  545. /* Sanity check radius */
  546. if (r < 0) return ;
  547. /* Special case for r=0 - draw a point */
  548. if (r == 0)
  549. {
  550. rtgui_dc_draw_point(dc, x, y);
  551. return;
  552. }
  553. /* Fixup angles */
  554. start = start % 360;
  555. end = end % 360;
  556. /*
  557. * Draw arc
  558. */
  559. // Octant labelling
  560. //
  561. // \ 5 | 6 /
  562. // \ | /
  563. // 4 \ | / 7
  564. // \|/
  565. //------+------ +x
  566. // /|\
  567. // 3 / | \ 0
  568. // / | \
  569. // / 2 | 1 \
  570. // +y
  571. drawoct = 0; // 0x00000000
  572. // whether or not to keep drawing a given octant.
  573. // For example: 0x00111100 means we're drawing in octants 2-5
  574. // 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0.
  575. while (start < 0) start += 360;
  576. while (end < 0) end += 360;
  577. start %= 360;
  578. end %= 360;
  579. // now, we find which octants we're drawing in.
  580. startoct = start / 45;
  581. endoct = end / 45;
  582. oct = startoct - 1; // we increment as first step in loop
  583. //stopval_start, stopval_end; // what values of cx to stop at.
  584. do {
  585. oct = (oct + 1) % 8;
  586. if (oct == startoct)
  587. {
  588. // need to compute stopval_start for this octant. Look at picture above if this is unclear
  589. switch (oct)
  590. {
  591. case 0:
  592. case 3:
  593. temp = sin(start * M_PI / 180);
  594. break;
  595. case 1:
  596. case 6:
  597. temp = cos(start * M_PI / 180);
  598. break;
  599. case 2:
  600. case 5:
  601. temp = -cos(start * M_PI / 180);
  602. break;
  603. case 4:
  604. case 7:
  605. temp = -sin(start * M_PI / 180);
  606. break;
  607. }
  608. temp *= r;
  609. stopval_start = (int)temp; // always round down.
  610. // This isn't arbitrary, but requires graph paper to explain well.
  611. // The basic idea is that we're always changing drawoct after we draw, so we
  612. // stop immediately after we render the last sensible pixel at x = ((int)temp).
  613. // and whether to draw in this octant initially
  614. if (oct % 2) drawoct |= (1 << oct); // this is basically like saying drawoct[oct] = true, if drawoct were a bool array
  615. else drawoct &= 255 - (1 << oct); // this is basically like saying drawoct[oct] = false
  616. }
  617. if (oct == endoct)
  618. {
  619. // need to compute stopval_end for this octant
  620. switch (oct)
  621. {
  622. case 0:
  623. case 3:
  624. temp = sin(end * M_PI / 180);
  625. break;
  626. case 1:
  627. case 6:
  628. temp = cos(end * M_PI / 180);
  629. break;
  630. case 2:
  631. case 5:
  632. temp = -cos(end * M_PI / 180);
  633. break;
  634. case 4:
  635. case 7:
  636. temp = -sin(end * M_PI / 180);
  637. break;
  638. }
  639. temp *= r;
  640. stopval_end = (int)temp;
  641. // and whether to draw in this octant initially
  642. if (startoct == endoct)
  643. {
  644. // note: we start drawing, stop, then start again in this case
  645. // otherwise: we only draw in this octant, so initialize it to false, it will get set back to true
  646. if (start > end)
  647. {
  648. // unfortunately, if we're in the same octant and need to draw over the whole circle,
  649. // we need to set the rest to true, because the while loop will end at the bottom.
  650. drawoct = 255;
  651. }
  652. else
  653. {
  654. drawoct &= 255 - (1 << oct);
  655. }
  656. }
  657. else if (oct % 2) drawoct &= 255 - (1 << oct);
  658. else drawoct |= (1 << oct);
  659. } else if (oct != startoct) { // already verified that it's != endoct
  660. drawoct |= (1 << oct); // draw this entire segment
  661. }
  662. } while (oct != endoct);
  663. // so now we have what octants to draw and when to draw them. all that's left is the actual raster code.
  664. do
  665. {
  666. ypcy = y + cy;
  667. ymcy = y - cy;
  668. if (cx > 0)
  669. {
  670. xpcx = x + cx;
  671. xmcx = x - cx;
  672. // always check if we're drawing a certain octant before adding a pixel to that octant.
  673. if (drawoct & 4) rtgui_dc_draw_point(dc, xmcx, ypcy); // drawoct & 4 = 22; drawoct[2]
  674. if (drawoct & 2) rtgui_dc_draw_point(dc, xpcx, ypcy);
  675. if (drawoct & 32) rtgui_dc_draw_point(dc, xmcx, ymcy);
  676. if (drawoct & 64) rtgui_dc_draw_point(dc, xpcx, ymcy);
  677. }
  678. else
  679. {
  680. if (drawoct & 6) rtgui_dc_draw_point(dc, x, ypcy); // 4 + 2; drawoct[2] || drawoct[1]
  681. if (drawoct & 96) rtgui_dc_draw_point(dc, x, ymcy); // 32 + 64
  682. }
  683. xpcy = x + cy;
  684. xmcy = x - cy;
  685. if (cx > 0 && cx != cy)
  686. {
  687. ypcx = y + cx;
  688. ymcx = y - cx;
  689. if (drawoct & 8) rtgui_dc_draw_point(dc, xmcy, ypcx);
  690. if (drawoct & 1) rtgui_dc_draw_point(dc, xpcy, ypcx);
  691. if (drawoct & 16) rtgui_dc_draw_point(dc, xmcy, ymcx);
  692. if (drawoct & 128) rtgui_dc_draw_point(dc, xpcy, ymcx);
  693. }
  694. else if (cx == 0)
  695. {
  696. if (drawoct & 24) rtgui_dc_draw_point(dc, xmcy, y); // 8 + 16
  697. if (drawoct & 129) rtgui_dc_draw_point(dc, xpcy, y); // 1 + 128
  698. }
  699. /*
  700. * Update whether we're drawing an octant
  701. */
  702. if (stopval_start == cx)
  703. {
  704. // works like an on-off switch because start & end may be in the same octant.
  705. if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
  706. else drawoct |= (1 << startoct);
  707. }
  708. if (stopval_end == cx)
  709. {
  710. if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
  711. else drawoct |= (1 << endoct);
  712. }
  713. /*
  714. * Update pixels
  715. */
  716. if (df < 0)
  717. {
  718. df += d_e;
  719. d_e += 2;
  720. d_se += 2;
  721. }
  722. else
  723. {
  724. df += d_se;
  725. d_e += 2;
  726. d_se += 4;
  727. cy--;
  728. }
  729. cx++;
  730. } while (cx <= cy);
  731. }
  732. 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)
  733. {
  734. int ix, iy;
  735. int h, i, j, k;
  736. int oh, oi, oj, ok;
  737. int xmh, xph, ypk, ymk;
  738. int xmi, xpi, ymj, ypj;
  739. int xmj, xpj, ymi, ypi;
  740. int xmk, xpk, ymh, yph;
  741. /*
  742. * Sanity check radii
  743. */
  744. if ((rx < 0) || (ry < 0)) return;
  745. /*
  746. * Special case for rx=0 - draw a vline
  747. */
  748. if (rx == 0)
  749. {
  750. rtgui_dc_draw_vline(dc, x, y - ry, y + ry);
  751. return;
  752. }
  753. /*
  754. * Special case for ry=0 - draw a hline
  755. */
  756. if (ry == 0)
  757. {
  758. rtgui_dc_draw_hline(dc, x - rx, x + rx, y);
  759. return;
  760. }
  761. /*
  762. * Init vars
  763. */
  764. oh = oi = oj = ok = 0xFFFF;
  765. if (rx > ry)
  766. {
  767. ix = 0;
  768. iy = rx * 64;
  769. do
  770. {
  771. h = (ix + 32) >> 6;
  772. i = (iy + 32) >> 6;
  773. j = (h * ry) / rx;
  774. k = (i * ry) / rx;
  775. if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j))
  776. {
  777. xph = x + h;
  778. xmh = x - h;
  779. if (k > 0)
  780. {
  781. ypk = y + k;
  782. ymk = y - k;
  783. rtgui_dc_draw_point(dc, xmh, ypk);
  784. rtgui_dc_draw_point(dc, xph, ypk);
  785. rtgui_dc_draw_point(dc, xmh, ymk);
  786. rtgui_dc_draw_point(dc, xph, ymk);
  787. }
  788. else
  789. {
  790. rtgui_dc_draw_point(dc, xmh, y);
  791. rtgui_dc_draw_point(dc, xph, y);
  792. }
  793. ok = k;
  794. xpi = x + i;
  795. xmi = x - i;
  796. if (j > 0)
  797. {
  798. ypj = y + j;
  799. ymj = y - j;
  800. rtgui_dc_draw_point(dc, xmi, ypj);
  801. rtgui_dc_draw_point(dc, xpi, ypj);
  802. rtgui_dc_draw_point(dc, xmi, ymj);
  803. rtgui_dc_draw_point(dc, xpi, ymj);
  804. }
  805. else
  806. {
  807. rtgui_dc_draw_point(dc, xmi, y);
  808. rtgui_dc_draw_point(dc, xpi, y);
  809. }
  810. oj = j;
  811. }
  812. ix = ix + iy / rx;
  813. iy = iy - ix / rx;
  814. } while (i > h);
  815. }
  816. else
  817. {
  818. ix = 0;
  819. iy = ry * 64;
  820. do
  821. {
  822. h = (ix + 32) >> 6;
  823. i = (iy + 32) >> 6;
  824. j = (h * rx) / ry;
  825. k = (i * rx) / ry;
  826. if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h)))
  827. {
  828. xmj = x - j;
  829. xpj = x + j;
  830. if (i > 0)
  831. {
  832. ypi = y + i;
  833. ymi = y - i;
  834. rtgui_dc_draw_point(dc, xmj, ypi);
  835. rtgui_dc_draw_point(dc, xpj, ypi);
  836. rtgui_dc_draw_point(dc, xmj, ymi);
  837. rtgui_dc_draw_point(dc, xpj, ymi);
  838. }
  839. else
  840. {
  841. rtgui_dc_draw_point(dc, xmj, y);
  842. rtgui_dc_draw_point(dc, xpj, y);
  843. }
  844. oi = i;
  845. xmk = x - k;
  846. xpk = x + k;
  847. if (h > 0)
  848. {
  849. yph = y + h;
  850. ymh = y - h;
  851. rtgui_dc_draw_point(dc, xmk, yph);
  852. rtgui_dc_draw_point(dc, xpk, yph);
  853. rtgui_dc_draw_point(dc, xmk, ymh);
  854. rtgui_dc_draw_point(dc, xpk, ymh);
  855. }
  856. else
  857. {
  858. rtgui_dc_draw_point(dc, xmk, y);
  859. rtgui_dc_draw_point(dc, xpk, y);
  860. }
  861. oh = h;
  862. }
  863. ix = ix + iy / ry;
  864. iy = iy - ix / ry;
  865. } while (i > h);
  866. }
  867. }
  868. 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)
  869. {
  870. int ix, iy;
  871. int h, i, j, k;
  872. int oh, oi, oj, ok;
  873. int xmh, xph;
  874. int xmi, xpi;
  875. int xmj, xpj;
  876. int xmk, xpk;
  877. /*
  878. * Special case for rx=0 - draw a vline
  879. */
  880. if (rx == 0)
  881. {
  882. rtgui_dc_draw_vline(dc, x, y - ry, y + ry);
  883. return;
  884. }
  885. /* special case for ry=0 - draw a hline */
  886. if (ry == 0) {
  887. rtgui_dc_draw_hline(dc, x - rx, x + rx, y);
  888. return;
  889. }
  890. /*
  891. * Init vars
  892. */
  893. oh = oi = oj = ok = 0xFFFF;
  894. /*
  895. * Draw
  896. */
  897. if (rx > ry) {
  898. ix = 0;
  899. iy = rx * 64;
  900. do {
  901. h = (ix + 32) >> 6;
  902. i = (iy + 32) >> 6;
  903. j = (h * ry) / rx;
  904. k = (i * ry) / rx;
  905. if ((ok != k) && (oj != k)) {
  906. xph = x + h;
  907. xmh = x - h;
  908. if (k > 0) {
  909. rtgui_dc_draw_hline(dc, xmh, xph, y + k);
  910. rtgui_dc_draw_hline(dc, xmh, xph, y - k);
  911. } else {
  912. rtgui_dc_draw_hline(dc, xmh, xph, y);
  913. }
  914. ok = k;
  915. }
  916. if ((oj != j) && (ok != j) && (k != j)) {
  917. xmi = x - i;
  918. xpi = x + i;
  919. if (j > 0) {
  920. rtgui_dc_draw_hline(dc, xmi, xpi, y + j);
  921. rtgui_dc_draw_hline(dc, xmi, xpi, y - j);
  922. } else {
  923. rtgui_dc_draw_hline(dc, xmi, xpi, y);
  924. }
  925. oj = j;
  926. }
  927. ix = ix + iy / rx;
  928. iy = iy - ix / rx;
  929. } while (i > h);
  930. } else {
  931. ix = 0;
  932. iy = ry * 64;
  933. do {
  934. h = (ix + 32) >> 6;
  935. i = (iy + 32) >> 6;
  936. j = (h * rx) / ry;
  937. k = (i * rx) / ry;
  938. if ((oi != i) && (oh != i)) {
  939. xmj = x - j;
  940. xpj = x + j;
  941. if (i > 0) {
  942. rtgui_dc_draw_hline(dc, xmj, xpj, y + i);
  943. rtgui_dc_draw_hline(dc, xmj, xpj, y - i);
  944. } else {
  945. rtgui_dc_draw_hline(dc, xmj, xpj, y);
  946. }
  947. oi = i;
  948. }
  949. if ((oh != h) && (oi != h) && (i != h)) {
  950. xmk = x - k;
  951. xpk = x + k;
  952. if (h > 0) {
  953. rtgui_dc_draw_hline(dc, xmk, xpk, y + h);
  954. rtgui_dc_draw_hline(dc, xmk, xpk, y - h);
  955. } else {
  956. rtgui_dc_draw_hline(dc, xmk, xpk, y);
  957. }
  958. oh = h;
  959. }
  960. ix = ix + iy / ry;
  961. iy = iy - ix / ry;
  962. } while (i > h);
  963. }
  964. }
  965. void rtgui_dc_draw_focus_rect(struct rtgui_dc* dc, rtgui_rect_t* rect)
  966. {
  967. int i;
  968. for (i = rect->x1; i <= rect->x2; i += 2)
  969. {
  970. rtgui_dc_draw_point(dc, i, rect->y1);
  971. rtgui_dc_draw_point(dc, i, rect->y2);
  972. }
  973. for (i = rect->y1; i <= rect->y2; i += 2)
  974. {
  975. rtgui_dc_draw_point(dc, rect->x1, i);
  976. rtgui_dc_draw_point(dc, rect->x2, i);
  977. }
  978. }