dc.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209
  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->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. 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. 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. rtgui_dc_draw_mono_bmp(dc, x, y, 8, h, data);
  176. }
  177. void rtgui_dc_draw_word(struct rtgui_dc*dc, int x, int y, int h, const rt_uint8_t* data)
  178. {
  179. rtgui_dc_draw_mono_bmp(dc, x, y, 16, h, data);
  180. }
  181. void rtgui_dc_draw_shaded_rect(struct rtgui_dc* dc, rtgui_rect_t* rect,
  182. rtgui_color_t c1, rtgui_color_t c2)
  183. {
  184. RT_ASSERT(dc != RT_NULL);
  185. RTGUI_DC_FC(dc) = c1;
  186. rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2);
  187. rtgui_dc_draw_hline(dc, rect->x1 + 1, rect->x2, rect->y1);
  188. RTGUI_DC_FC(dc) = c2;
  189. rtgui_dc_draw_vline(dc, rect->x2, rect->y1, rect->y2);
  190. rtgui_dc_draw_hline(dc, rect->x1, rect->x2 + 1, rect->y2);
  191. }
  192. void rtgui_dc_draw_border(struct rtgui_dc* dc, rtgui_rect_t* rect, int flag)
  193. {
  194. rtgui_rect_t r;
  195. rtgui_color_t color;
  196. if (dc == RT_NULL) return ;
  197. /* save old color */
  198. color = RTGUI_DC_FC(dc);
  199. r = *rect;
  200. switch (flag)
  201. {
  202. case RTGUI_BORDER_RAISE:
  203. rtgui_dc_draw_shaded_rect(dc, &r, high_light, black);
  204. rtgui_rect_inflate(&r, -1);
  205. rtgui_dc_draw_shaded_rect(dc, &r, light_grey, dark_grey);
  206. break;
  207. case RTGUI_BORDER_SUNKEN:
  208. rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
  209. rtgui_rect_inflate(&r, -1);
  210. rtgui_dc_draw_shaded_rect(dc, &r, black, light_grey);
  211. break;
  212. case RTGUI_BORDER_BOX:
  213. rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
  214. rtgui_rect_inflate(&r, -1);
  215. rtgui_dc_draw_shaded_rect(dc, &r, high_light, dark_grey);
  216. break;
  217. case RTGUI_BORDER_STATIC:
  218. rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
  219. break;
  220. case RTGUI_BORDER_EXTRA:
  221. RTGUI_DC_FC(dc) = light_grey;
  222. rtgui_dc_draw_rect(dc, &r);
  223. break;
  224. case RTGUI_BORDER_SIMPLE:
  225. RTGUI_DC_FC(dc) = black;
  226. rtgui_dc_draw_rect(dc, &r);
  227. break;
  228. default:
  229. break;
  230. }
  231. /* restore color */
  232. RTGUI_DC_FC(dc) = color;
  233. }
  234. void rtgui_dc_draw_horizontal_line(struct rtgui_dc* dc, int x1, int x2, int y)
  235. {
  236. rtgui_color_t color;
  237. if (dc == RT_NULL) return ;
  238. /* save old color */
  239. color = RTGUI_DC_FC(dc);
  240. RTGUI_DC_FC(dc) = dark_grey;
  241. rtgui_dc_draw_hline(dc, x1, x2, y);
  242. y ++;
  243. RTGUI_DC_FC(dc) = high_light;
  244. rtgui_dc_draw_hline(dc, x1, x2, y);
  245. /* restore color */
  246. RTGUI_DC_FC(dc) = color;
  247. }
  248. void rtgui_dc_draw_vertical_line(struct rtgui_dc* dc, int x, int y1, int y2)
  249. {
  250. rtgui_color_t color;
  251. if (dc == RT_NULL) return ;
  252. /* save old color */
  253. color = RTGUI_DC_FC(dc);
  254. RTGUI_DC_FC(dc) = dark_grey;
  255. rtgui_dc_draw_hline(dc, x, y1, y2);
  256. x ++;
  257. RTGUI_DC_FC(dc) = high_light;
  258. rtgui_dc_draw_hline(dc, x, y1, y2);
  259. /* restore color */
  260. RTGUI_DC_FC(dc) = color;
  261. }
  262. void rtgui_dc_draw_arrow(struct rtgui_dc* dc, rtgui_rect_t* rect, int kind)
  263. {
  264. rt_int32_t i;
  265. rt_int32_t x1, y1, x2, y2;
  266. rtgui_rect_t r = {0, 0, 0, 0};
  267. static const rt_uint8_t ARROW_WIDTH = 7;
  268. static const rt_uint8_t ARROW_LENGTH = 4;
  269. x1 = y1 = 0;
  270. switch (kind)
  271. {
  272. case RTGUI_ARRAW_UP:
  273. case RTGUI_ARRAW_DOWN:
  274. r.x2 = ARROW_WIDTH;
  275. r.y2 = ARROW_LENGTH;
  276. break;
  277. case RTGUI_ARRAW_LEFT:
  278. case RTGUI_ARRAW_RIGHT:
  279. r.x2 = ARROW_LENGTH;
  280. r.y2 = ARROW_WIDTH;
  281. break;
  282. }
  283. rtgui_rect_moveto_align(rect, &r, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL);
  284. switch (kind)
  285. {
  286. case RTGUI_ARRAW_UP:
  287. x1 = r.x1 + (ARROW_WIDTH - 1)/2;;
  288. y1 = r.y1;
  289. break;
  290. case RTGUI_ARRAW_DOWN:
  291. x1 = r.x1 + (ARROW_WIDTH - 1)/2;
  292. y1 = r.y1 + ARROW_LENGTH - 1;
  293. break;
  294. case RTGUI_ARRAW_LEFT:
  295. x1 = r.x1;
  296. y1 = r.y1 + (ARROW_WIDTH - 1)/2;
  297. break;
  298. case RTGUI_ARRAW_RIGHT:
  299. x1 = r.x1 + ARROW_LENGTH - 1;
  300. y1 = r.y1 + (ARROW_WIDTH - 1)/2;
  301. break;
  302. default:
  303. return;
  304. }
  305. x2 = x1;
  306. y2 = y1;
  307. for (i = 0; i < ARROW_LENGTH; i++)
  308. {
  309. rtgui_dc_draw_line(dc, x1, y1, x2, y2);
  310. switch (kind)
  311. {
  312. case RTGUI_ARRAW_UP:
  313. x1 --;
  314. x2 ++;
  315. y1 ++;
  316. y2 ++;
  317. break;
  318. case RTGUI_ARRAW_DOWN:
  319. x1 --;
  320. x2 ++;
  321. y1 --;
  322. y2 --;
  323. break;
  324. case RTGUI_ARRAW_LEFT:
  325. y1 --;
  326. y2 ++;
  327. x1 ++;
  328. x2 ++;
  329. break;
  330. case RTGUI_ARRAW_RIGHT:
  331. y1 --;
  332. y2 ++;
  333. x1 --;
  334. x2 --;
  335. break;
  336. }
  337. }
  338. }
  339. void rtgui_dc_draw_polygon(struct rtgui_dc* dc, const int *vx, const int *vy, int count)
  340. {
  341. int i;
  342. const int *x1, *y1, *x2, *y2;
  343. /*
  344. * Sanity check
  345. */
  346. if (count < 3) return;
  347. /*
  348. * Pointer setup
  349. */
  350. x1 = x2 = vx;
  351. y1 = y2 = vy;
  352. x2++;
  353. y2++;
  354. /*
  355. * Draw
  356. */
  357. for (i = 1; i < count; i++)
  358. {
  359. rtgui_dc_draw_line(dc, *x1, *y1, *x2, *y2);
  360. x1 = x2;
  361. y1 = y2;
  362. x2++;
  363. y2++;
  364. }
  365. rtgui_dc_draw_line(dc, *x1, *y1, *vx, *vy);
  366. }
  367. static int _int_compare(const void *a, const void *b)
  368. {
  369. return (*(const int *) a) - (*(const int *) b);
  370. }
  371. void rtgui_dc_fill_polygon(struct rtgui_dc* dc, const int* vx, const int* vy, int count)
  372. {
  373. int i;
  374. int y, xa, xb;
  375. int miny, maxy;
  376. int x1, y1;
  377. int x2, y2;
  378. int ind1, ind2;
  379. int ints;
  380. int *poly_ints = RT_NULL;
  381. /*
  382. * Sanity check number of edges
  383. */
  384. if (count < 3) return;
  385. /*
  386. * Allocate temp array, only grow array
  387. */
  388. poly_ints = (int *) rt_malloc(sizeof(int) * count);
  389. if (poly_ints == RT_NULL) return ; /* no memory, failed */
  390. /*
  391. * Determine Y maximal
  392. */
  393. miny = vy[0];
  394. maxy = vy[0];
  395. for (i = 1; (i < count); i++)
  396. {
  397. if (vy[i] < miny) miny = vy[i];
  398. else if (vy[i] > maxy) maxy = vy[i];
  399. }
  400. /*
  401. * Draw, scanning y
  402. */
  403. for (y = miny; (y <= maxy); y++) {
  404. ints = 0;
  405. for (i = 0; (i < count); i++) {
  406. if (!i) {
  407. ind1 = count - 1;
  408. ind2 = 0;
  409. } else {
  410. ind1 = i - 1;
  411. ind2 = i;
  412. }
  413. y1 = vy[ind1];
  414. y2 = vy[ind2];
  415. if (y1 < y2) {
  416. x1 = vx[ind1];
  417. x2 = vx[ind2];
  418. } else if (y1 > y2) {
  419. y2 = vy[ind1];
  420. y1 = vy[ind2];
  421. x2 = vx[ind1];
  422. x1 = vx[ind2];
  423. } else {
  424. continue;
  425. }
  426. if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) )
  427. {
  428. poly_ints[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
  429. }
  430. }
  431. qsort(poly_ints, ints, sizeof(int), _int_compare);
  432. for (i = 0; (i < ints); i += 2)
  433. {
  434. xa = poly_ints[i] + 1;
  435. xa = (xa >> 16) + ((xa & 32768) >> 15);
  436. xb = poly_ints[i+1] - 1;
  437. xb = (xb >> 16) + ((xb & 32768) >> 15);
  438. rtgui_dc_draw_hline(dc, xa, xb, y);
  439. }
  440. }
  441. }
  442. #if 1
  443. void rtgui_dc_draw_circle(struct rtgui_dc *dc,
  444. int xCenter, int yCenter, int radius)
  445. {
  446. int x =0;
  447. int y = radius;
  448. int p = 1-radius;
  449. rtgui_dc_draw_point(dc,xCenter+x,yCenter+y);
  450. rtgui_dc_draw_point(dc,xCenter-x,yCenter+y);
  451. rtgui_dc_draw_point(dc,xCenter+x,yCenter-y);
  452. rtgui_dc_draw_point(dc,xCenter-x,yCenter-y);
  453. rtgui_dc_draw_point(dc,xCenter+y,yCenter+x);
  454. rtgui_dc_draw_point(dc,xCenter-y,yCenter+x);
  455. rtgui_dc_draw_point(dc,xCenter+y,yCenter-x);
  456. rtgui_dc_draw_point(dc,xCenter-y,yCenter-x);
  457. while(x<y){
  458. x++;
  459. if(p<0)
  460. p+=2*x+1;
  461. else{
  462. y--;
  463. p+=2*(x-y)+1;
  464. }
  465. rtgui_dc_draw_point(dc,xCenter+x,yCenter+y);
  466. rtgui_dc_draw_point(dc,xCenter-x,yCenter+y);
  467. rtgui_dc_draw_point(dc,xCenter+x,yCenter-y);
  468. rtgui_dc_draw_point(dc,xCenter-x,yCenter-y);
  469. rtgui_dc_draw_point(dc,xCenter+y,yCenter+x);
  470. rtgui_dc_draw_point(dc,xCenter-y,yCenter+x);
  471. rtgui_dc_draw_point(dc,xCenter+y,yCenter-x);
  472. rtgui_dc_draw_point(dc,xCenter-y,yCenter-x);
  473. }
  474. }
  475. #else
  476. void rtgui_dc_draw_circle(struct rtgui_dc* dc, int x, int y, int r)
  477. {
  478. rt_int16_t cx = 0;
  479. rt_int16_t cy = r;
  480. rt_int16_t df = 1 - r;
  481. rt_int16_t d_e = 3;
  482. rt_int16_t d_se = -2 * r + 5;
  483. rt_int16_t xpcx, xmcx, xpcy, xmcy;
  484. rt_int16_t ypcy, ymcy, ypcx, ymcx;
  485. /*
  486. * sanity check radius
  487. */
  488. if (r < 0) return ;
  489. /* special case for r=0 - draw a point */
  490. if (r == 0) rtgui_dc_draw_point(dc, x, y);
  491. /*
  492. * draw circle
  493. */
  494. do
  495. {
  496. ypcy = y + cy;
  497. ymcy = y - cy;
  498. if (cx > 0)
  499. {
  500. xpcx = x + cx;
  501. xmcx = x - cx;
  502. rtgui_dc_draw_point(dc, xmcx, ypcy);
  503. rtgui_dc_draw_point(dc, xpcx, ypcy);
  504. rtgui_dc_draw_point(dc, xmcx, ymcy);
  505. rtgui_dc_draw_point(dc, xpcx, ymcy);
  506. }
  507. else
  508. {
  509. rtgui_dc_draw_point(dc, x, ymcy);
  510. rtgui_dc_draw_point(dc, x, ypcy);
  511. }
  512. xpcy = x + cy;
  513. xmcy = x - cy;
  514. if ((cx > 0) && (cx != cy))
  515. {
  516. ypcx = y + cx;
  517. ymcx = y - cx;
  518. rtgui_dc_draw_point(dc, xmcy, ypcx);
  519. rtgui_dc_draw_point(dc, xpcy, ypcx);
  520. rtgui_dc_draw_point(dc, xmcy, ymcx);
  521. rtgui_dc_draw_point(dc, xpcy, ymcx);
  522. }
  523. else if (cx == 0)
  524. {
  525. rtgui_dc_draw_point(dc, xmcy, y);
  526. rtgui_dc_draw_point(dc, xpcy, y);
  527. }
  528. /*
  529. * Update
  530. */
  531. if (df < 0)
  532. {
  533. df += d_e;
  534. d_e += 2;
  535. d_se += 2;
  536. }
  537. else
  538. {
  539. df += d_se;
  540. d_e += 2;
  541. d_se += 4;
  542. cy--;
  543. }
  544. cx++;
  545. }while (cx <= cy);
  546. }
  547. #endif
  548. void rtgui_dc_fill_circle(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t r)
  549. {
  550. rt_int16_t cx = 0;
  551. rt_int16_t cy = r;
  552. rt_int16_t ocx = (rt_int16_t) 0xffff;
  553. rt_int16_t ocy = (rt_int16_t) 0xffff;
  554. rt_int16_t df = 1 - r;
  555. rt_int16_t d_e = 3;
  556. rt_int16_t d_se = -2 * r + 5;
  557. rt_int16_t xpcx, xmcx, xpcy, xmcy;
  558. rt_int16_t ypcy, ymcy, ypcx, ymcx;
  559. /*
  560. * Sanity check radius
  561. */
  562. if (r < 0) return;
  563. /*
  564. * Special case for r=0 - draw a point
  565. */
  566. if (r == 0)
  567. {
  568. rtgui_dc_draw_point(dc, x, y);
  569. return ;
  570. }
  571. /*
  572. * Draw
  573. */
  574. do {
  575. xpcx = x + cx;
  576. xmcx = x - cx;
  577. xpcy = x + cy;
  578. xmcy = x - cy;
  579. if (ocy != cy) {
  580. if (cy > 0) {
  581. ypcy = y + cy;
  582. ymcy = y - cy;
  583. rtgui_dc_draw_hline(dc, xmcx, xpcx, ypcy);
  584. rtgui_dc_draw_hline(dc, xmcx, xpcx, ymcy);
  585. } else {
  586. rtgui_dc_draw_hline(dc, xmcx, xpcx, y);
  587. }
  588. ocy = cy;
  589. }
  590. if (ocx != cx) {
  591. if (cx != cy) {
  592. if (cx > 0) {
  593. ypcx = y + cx;
  594. ymcx = y - cx;
  595. rtgui_dc_draw_hline(dc, xmcy, xpcy, ymcx);
  596. rtgui_dc_draw_hline(dc, xmcy, xpcy, ypcx);
  597. } else {
  598. rtgui_dc_draw_hline(dc, xmcy, xpcy, y);
  599. }
  600. }
  601. ocx = cx;
  602. }
  603. /*
  604. * Update
  605. */
  606. if (df < 0) {
  607. df += d_e;
  608. d_e += 2;
  609. d_se += 2;
  610. } else {
  611. df += d_se;
  612. d_e += 2;
  613. d_se += 4;
  614. cy--;
  615. }
  616. cx++;
  617. } while (cx <= cy);
  618. }
  619. 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)
  620. {
  621. rt_int16_t cx = 0;
  622. rt_int16_t cy = r;
  623. rt_int16_t df = 1 - r;
  624. rt_int16_t d_e = 3;
  625. rt_int16_t d_se = -2 * r + 5;
  626. rt_int16_t xpcx, xmcx, xpcy, xmcy;
  627. rt_int16_t ypcy, ymcy, ypcx, ymcx;
  628. rt_uint8_t drawoct;
  629. int startoct, endoct, oct, stopval_start, stopval_end;
  630. double temp;
  631. stopval_start = 0;
  632. stopval_end = 0;
  633. temp = 0;
  634. /* Sanity check radius */
  635. if (r < 0) return ;
  636. /* Special case for r=0 - draw a point */
  637. if (r == 0)
  638. {
  639. rtgui_dc_draw_point(dc, x, y);
  640. return;
  641. }
  642. /* Fixup angles */
  643. start = start % 360;
  644. end = end % 360;
  645. /*
  646. * Draw arc
  647. */
  648. // Octant labelling
  649. //
  650. // \ 5 | 6 /
  651. // \ | /
  652. // 4 \ | / 7
  653. // \|/
  654. //------+------ +x
  655. // /|\
  656. // 3 / | \ 0
  657. // / | \
  658. // / 2 | 1 \
  659. // +y
  660. drawoct = 0; // 0x00000000
  661. // whether or not to keep drawing a given octant.
  662. // For example: 0x00111100 means we're drawing in octants 2-5
  663. // 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0.
  664. while (start < 0) start += 360;
  665. while (end < 0) end += 360;
  666. start %= 360;
  667. end %= 360;
  668. // now, we find which octants we're drawing in.
  669. startoct = start / 45;
  670. endoct = end / 45;
  671. oct = startoct - 1; // we increment as first step in loop
  672. //stopval_start, stopval_end; // what values of cx to stop at.
  673. do {
  674. oct = (oct + 1) % 8;
  675. if (oct == startoct)
  676. {
  677. // need to compute stopval_start for this octant. Look at picture above if this is unclear
  678. switch (oct)
  679. {
  680. case 0:
  681. case 3:
  682. temp = sin(start * M_PI / 180);
  683. break;
  684. case 1:
  685. case 6:
  686. temp = cos(start * M_PI / 180);
  687. break;
  688. case 2:
  689. case 5:
  690. temp = -cos(start * M_PI / 180);
  691. break;
  692. case 4:
  693. case 7:
  694. temp = -sin(start * M_PI / 180);
  695. break;
  696. }
  697. temp *= r;
  698. stopval_start = (int)temp; // always round down.
  699. // This isn't arbitrary, but requires graph paper to explain well.
  700. // The basic idea is that we're always changing drawoct after we draw, so we
  701. // stop immediately after we render the last sensible pixel at x = ((int)temp).
  702. // and whether to draw in this octant initially
  703. if (oct % 2) drawoct |= (1 << oct); // this is basically like saying drawoct[oct] = true, if drawoct were a bool array
  704. else drawoct &= 255 - (1 << oct); // this is basically like saying drawoct[oct] = false
  705. }
  706. if (oct == endoct)
  707. {
  708. // need to compute stopval_end for this octant
  709. switch (oct)
  710. {
  711. case 0:
  712. case 3:
  713. temp = sin(end * M_PI / 180);
  714. break;
  715. case 1:
  716. case 6:
  717. temp = cos(end * M_PI / 180);
  718. break;
  719. case 2:
  720. case 5:
  721. temp = -cos(end * M_PI / 180);
  722. break;
  723. case 4:
  724. case 7:
  725. temp = -sin(end * M_PI / 180);
  726. break;
  727. }
  728. temp *= r;
  729. stopval_end = (int)temp;
  730. // and whether to draw in this octant initially
  731. if (startoct == endoct)
  732. {
  733. // note: we start drawing, stop, then start again in this case
  734. // otherwise: we only draw in this octant, so initialize it to false, it will get set back to true
  735. if (start > end)
  736. {
  737. // unfortunately, if we're in the same octant and need to draw over the whole circle,
  738. // we need to set the rest to true, because the while loop will end at the bottom.
  739. drawoct = 255;
  740. }
  741. else
  742. {
  743. drawoct &= 255 - (1 << oct);
  744. }
  745. }
  746. else if (oct % 2) drawoct &= 255 - (1 << oct);
  747. else drawoct |= (1 << oct);
  748. } else if (oct != startoct) { // already verified that it's != endoct
  749. drawoct |= (1 << oct); // draw this entire segment
  750. }
  751. } while (oct != endoct);
  752. // so now we have what octants to draw and when to draw them. all that's left is the actual raster code.
  753. do
  754. {
  755. ypcy = y + cy;
  756. ymcy = y - cy;
  757. if (cx > 0)
  758. {
  759. xpcx = x + cx;
  760. xmcx = x - cx;
  761. // always check if we're drawing a certain octant before adding a pixel to that octant.
  762. if (drawoct & 4) rtgui_dc_draw_point(dc, xmcx, ypcy); // drawoct & 4 = 22; drawoct[2]
  763. if (drawoct & 2) rtgui_dc_draw_point(dc, xpcx, ypcy);
  764. if (drawoct & 32) rtgui_dc_draw_point(dc, xmcx, ymcy);
  765. if (drawoct & 64) rtgui_dc_draw_point(dc, xpcx, ymcy);
  766. }
  767. else
  768. {
  769. if (drawoct & 6) rtgui_dc_draw_point(dc, x, ypcy); // 4 + 2; drawoct[2] || drawoct[1]
  770. if (drawoct & 96) rtgui_dc_draw_point(dc, x, ymcy); // 32 + 64
  771. }
  772. xpcy = x + cy;
  773. xmcy = x - cy;
  774. if (cx > 0 && cx != cy)
  775. {
  776. ypcx = y + cx;
  777. ymcx = y - cx;
  778. if (drawoct & 8) rtgui_dc_draw_point(dc, xmcy, ypcx);
  779. if (drawoct & 1) rtgui_dc_draw_point(dc, xpcy, ypcx);
  780. if (drawoct & 16) rtgui_dc_draw_point(dc, xmcy, ymcx);
  781. if (drawoct & 128) rtgui_dc_draw_point(dc, xpcy, ymcx);
  782. }
  783. else if (cx == 0)
  784. {
  785. if (drawoct & 24) rtgui_dc_draw_point(dc, xmcy, y); // 8 + 16
  786. if (drawoct & 129) rtgui_dc_draw_point(dc, xpcy, y); // 1 + 128
  787. }
  788. /*
  789. * Update whether we're drawing an octant
  790. */
  791. if (stopval_start == cx)
  792. {
  793. // works like an on-off switch because start & end may be in the same octant.
  794. if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
  795. else drawoct |= (1 << startoct);
  796. }
  797. if (stopval_end == cx)
  798. {
  799. if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
  800. else drawoct |= (1 << endoct);
  801. }
  802. /*
  803. * Update pixels
  804. */
  805. if (df < 0)
  806. {
  807. df += d_e;
  808. d_e += 2;
  809. d_se += 2;
  810. }
  811. else
  812. {
  813. df += d_se;
  814. d_e += 2;
  815. d_se += 4;
  816. cy--;
  817. }
  818. cx++;
  819. } while (cx <= cy);
  820. }
  821. 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)
  822. {
  823. int ix, iy;
  824. int h, i, j, k;
  825. int oh, oi, oj, ok;
  826. int xmh, xph, ypk, ymk;
  827. int xmi, xpi, ymj, ypj;
  828. int xmj, xpj, ymi, ypi;
  829. int xmk, xpk, ymh, yph;
  830. /*
  831. * Sanity check radii
  832. */
  833. if ((rx < 0) || (ry < 0)) return;
  834. /*
  835. * Special case for rx=0 - draw a vline
  836. */
  837. if (rx == 0)
  838. {
  839. rtgui_dc_draw_vline(dc, x, y - ry, y + ry);
  840. return;
  841. }
  842. /*
  843. * Special case for ry=0 - draw a hline
  844. */
  845. if (ry == 0)
  846. {
  847. rtgui_dc_draw_hline(dc, x - rx, x + rx, y);
  848. return;
  849. }
  850. /*
  851. * Init vars
  852. */
  853. oh = oi = oj = ok = 0xFFFF;
  854. if (rx > ry)
  855. {
  856. ix = 0;
  857. iy = rx * 64;
  858. do
  859. {
  860. h = (ix + 32) >> 6;
  861. i = (iy + 32) >> 6;
  862. j = (h * ry) / rx;
  863. k = (i * ry) / rx;
  864. if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j))
  865. {
  866. xph = x + h;
  867. xmh = x - h;
  868. if (k > 0)
  869. {
  870. ypk = y + k;
  871. ymk = y - k;
  872. rtgui_dc_draw_point(dc, xmh, ypk);
  873. rtgui_dc_draw_point(dc, xph, ypk);
  874. rtgui_dc_draw_point(dc, xmh, ymk);
  875. rtgui_dc_draw_point(dc, xph, ymk);
  876. }
  877. else
  878. {
  879. rtgui_dc_draw_point(dc, xmh, y);
  880. rtgui_dc_draw_point(dc, xph, y);
  881. }
  882. ok = k;
  883. xpi = x + i;
  884. xmi = x - i;
  885. if (j > 0)
  886. {
  887. ypj = y + j;
  888. ymj = y - j;
  889. rtgui_dc_draw_point(dc, xmi, ypj);
  890. rtgui_dc_draw_point(dc, xpi, ypj);
  891. rtgui_dc_draw_point(dc, xmi, ymj);
  892. rtgui_dc_draw_point(dc, xpi, ymj);
  893. }
  894. else
  895. {
  896. rtgui_dc_draw_point(dc, xmi, y);
  897. rtgui_dc_draw_point(dc, xpi, y);
  898. }
  899. oj = j;
  900. }
  901. ix = ix + iy / rx;
  902. iy = iy - ix / rx;
  903. } while (i > h);
  904. }
  905. else
  906. {
  907. ix = 0;
  908. iy = ry * 64;
  909. do
  910. {
  911. h = (ix + 32) >> 6;
  912. i = (iy + 32) >> 6;
  913. j = (h * rx) / ry;
  914. k = (i * rx) / ry;
  915. if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h)))
  916. {
  917. xmj = x - j;
  918. xpj = x + j;
  919. if (i > 0)
  920. {
  921. ypi = y + i;
  922. ymi = y - i;
  923. rtgui_dc_draw_point(dc, xmj, ypi);
  924. rtgui_dc_draw_point(dc, xpj, ypi);
  925. rtgui_dc_draw_point(dc, xmj, ymi);
  926. rtgui_dc_draw_point(dc, xpj, ymi);
  927. }
  928. else
  929. {
  930. rtgui_dc_draw_point(dc, xmj, y);
  931. rtgui_dc_draw_point(dc, xpj, y);
  932. }
  933. oi = i;
  934. xmk = x - k;
  935. xpk = x + k;
  936. if (h > 0)
  937. {
  938. yph = y + h;
  939. ymh = y - h;
  940. rtgui_dc_draw_point(dc, xmk, yph);
  941. rtgui_dc_draw_point(dc, xpk, yph);
  942. rtgui_dc_draw_point(dc, xmk, ymh);
  943. rtgui_dc_draw_point(dc, xpk, ymh);
  944. }
  945. else
  946. {
  947. rtgui_dc_draw_point(dc, xmk, y);
  948. rtgui_dc_draw_point(dc, xpk, y);
  949. }
  950. oh = h;
  951. }
  952. ix = ix + iy / ry;
  953. iy = iy - ix / ry;
  954. } while (i > h);
  955. }
  956. }
  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. rtgui_dc_draw_hline(dc, x - rx, x + rx, y);
  977. return;
  978. }
  979. /*
  980. * Init vars
  981. */
  982. oh = oi = oj = ok = 0xFFFF;
  983. /*
  984. * Draw
  985. */
  986. if (rx > ry) {
  987. ix = 0;
  988. iy = rx * 64;
  989. do {
  990. h = (ix + 32) >> 6;
  991. i = (iy + 32) >> 6;
  992. j = (h * ry) / rx;
  993. k = (i * ry) / rx;
  994. if ((ok != k) && (oj != k)) {
  995. xph = x + h;
  996. xmh = x - h;
  997. if (k > 0) {
  998. rtgui_dc_draw_hline(dc, xmh, xph, y + k);
  999. rtgui_dc_draw_hline(dc, xmh, xph, y - k);
  1000. } else {
  1001. rtgui_dc_draw_hline(dc, xmh, xph, y);
  1002. }
  1003. ok = k;
  1004. }
  1005. if ((oj != j) && (ok != j) && (k != j)) {
  1006. xmi = x - i;
  1007. xpi = x + i;
  1008. if (j > 0) {
  1009. rtgui_dc_draw_hline(dc, xmi, xpi, y + j);
  1010. rtgui_dc_draw_hline(dc, xmi, xpi, y - j);
  1011. } else {
  1012. rtgui_dc_draw_hline(dc, xmi, xpi, y);
  1013. }
  1014. oj = j;
  1015. }
  1016. ix = ix + iy / rx;
  1017. iy = iy - ix / rx;
  1018. } while (i > h);
  1019. } else {
  1020. ix = 0;
  1021. iy = ry * 64;
  1022. do {
  1023. h = (ix + 32) >> 6;
  1024. i = (iy + 32) >> 6;
  1025. j = (h * rx) / ry;
  1026. k = (i * rx) / ry;
  1027. if ((oi != i) && (oh != i)) {
  1028. xmj = x - j;
  1029. xpj = x + j;
  1030. if (i > 0) {
  1031. rtgui_dc_draw_hline(dc, xmj, xpj, y + i);
  1032. rtgui_dc_draw_hline(dc, xmj, xpj, y - i);
  1033. } else {
  1034. rtgui_dc_draw_hline(dc, xmj, xpj, y);
  1035. }
  1036. oi = i;
  1037. }
  1038. if ((oh != h) && (oi != h) && (i != h)) {
  1039. xmk = x - k;
  1040. xpk = x + k;
  1041. if (h > 0) {
  1042. rtgui_dc_draw_hline(dc, xmk, xpk, y + h);
  1043. rtgui_dc_draw_hline(dc, xmk, xpk, y - h);
  1044. } else {
  1045. rtgui_dc_draw_hline(dc, xmk, xpk, y);
  1046. }
  1047. oh = h;
  1048. }
  1049. ix = ix + iy / ry;
  1050. iy = iy - ix / ry;
  1051. } while (i > h);
  1052. }
  1053. }
  1054. void rtgui_dc_draw_focus_rect(struct rtgui_dc* dc, rtgui_rect_t* rect)
  1055. {
  1056. int i;
  1057. for (i = rect->x1; i <= rect->x2; i += 2)
  1058. {
  1059. rtgui_dc_draw_point(dc, i, rect->y1);
  1060. rtgui_dc_draw_point(dc, i, rect->y2);
  1061. }
  1062. for (i = rect->y1; i <= rect->y2; i += 2)
  1063. {
  1064. rtgui_dc_draw_point(dc, rect->x1, i);
  1065. rtgui_dc_draw_point(dc, rect->x2, i);
  1066. }
  1067. }