dc.c 26 KB

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