dc.c 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226
  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. void rtgui_dc_destory(struct rtgui_dc* dc)
  19. {
  20. if (dc == RT_NULL) return;
  21. dc->fini(dc);
  22. rtgui_free(dc);
  23. }
  24. /*
  25. * draw a point on dc
  26. */
  27. void rtgui_dc_draw_point(struct rtgui_dc* dc, int x, int y)
  28. {
  29. if (dc == RT_NULL) return;
  30. dc->draw_point(dc, x, y);
  31. }
  32. #if 0
  33. void rtgui_dc_draw_point_alpha(struct rtgui_dc* dc, int x, int y, rt_uint8_t alpha)
  34. {
  35. if (dc == RT_NULL || alpha == 0xff) return;
  36. if (dc->draw_point_alpha != RT_NULL)
  37. dc->draw_point_alpha(dc, x, y, alpha);
  38. else
  39. {
  40. rtgui_color_t color;
  41. /* soft alpha bending */
  42. color = dc->get_color(dc, int x, int y);
  43. dc->draw_point(dc, x, y);
  44. }
  45. }
  46. #endif
  47. /*
  48. * draw a vertical line on dc
  49. */
  50. void rtgui_dc_draw_vline(struct rtgui_dc* dc, int x, int y1, int y2)
  51. {
  52. if (dc == RT_NULL) return;
  53. dc->draw_vline(dc, x, y1, y2);
  54. }
  55. /*
  56. * draw a horizontal line on dc
  57. */
  58. void rtgui_dc_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y)
  59. {
  60. if (dc == RT_NULL) return;
  61. dc->draw_hline(dc, x1, x2, y);
  62. }
  63. void rtgui_dc_draw_line (struct rtgui_dc* dc, int x1, int y1, int x2, int y2)
  64. {
  65. if (dc == RT_NULL) return;
  66. if (y1 == y2)
  67. {
  68. rtgui_dc_draw_hline(dc, x1, x2, y1);
  69. }
  70. else if (x1 == x2)
  71. {
  72. rtgui_dc_draw_vline(dc, x1, y1, y2);
  73. }
  74. else
  75. {
  76. int dx, dy, sdx, sdy, dxabs, dyabs, x, y, px, py;
  77. register rt_base_t i;
  78. /* rtgui_rect_t rect; */
  79. dx = x2 - x1; /* the horizontal distance of the line */
  80. dy = y2 - y1; /* the vertical distance of the line */
  81. #define rtgui_sgn(x) ((x<0)?-1:((x>0)?1:0)) /* macro to return the sign of a number */
  82. #define rtgui_abs(x) ((x)>=0? (x):-(x)) /* macro to return the absolute value */
  83. dxabs = rtgui_abs(dx);
  84. dyabs = rtgui_abs(dy);
  85. sdx = rtgui_sgn(dx);
  86. sdy = rtgui_sgn(dy);
  87. x = dyabs >> 1;
  88. y = dxabs >> 1;
  89. px = x1;
  90. py = y1;
  91. if(dxabs >= dyabs) /* the line is more horizontal than vertical */
  92. {
  93. for(i = 0; i < dxabs; i++)
  94. {
  95. y += dyabs;
  96. if(y >= dxabs)
  97. {
  98. y -= dxabs;
  99. py += sdy;
  100. }
  101. px += sdx;
  102. /* draw this point */
  103. dc->draw_point(dc, px, py);
  104. }
  105. }
  106. else /* the line is more vertical than horizontal */
  107. {
  108. for(i = 0; i < dyabs; i++)
  109. {
  110. x += dxabs;
  111. if(x >= dyabs)
  112. {
  113. x -= dyabs;
  114. px += sdx;
  115. }
  116. py += sdy;
  117. /* draw this point */
  118. dc->draw_point(dc, px, py);
  119. }
  120. }
  121. }
  122. }
  123. #if 0
  124. /* AA Line */
  125. #define AAlevels 256
  126. #define AAbits 8
  127. int rtgui_dc_draw_line_aa(struct rtgui_dc* dc, rt_int16_t x1, rt_int16_t y1, rt_int16_t x2, rt_int16_t y2)
  128. {
  129. Sint32 xx0, yy0, xx1, yy1;
  130. int result;
  131. rt_uint32_t intshift, erracc, erradj;
  132. rt_uint32_t erracctmp, wgt, wgtcompmask;
  133. int dx, dy, tmp, xdir, y0p1, x0pxdir;
  134. /*
  135. * Keep on working with 32bit numbers
  136. */
  137. xx0 = x1;
  138. yy0 = y1;
  139. xx1 = x2;
  140. yy1 = y2;
  141. /*
  142. * Reorder points if required
  143. */
  144. if (yy0 > yy1)
  145. {
  146. tmp = yy0;
  147. yy0 = yy1;
  148. yy1 = tmp;
  149. tmp = xx0;
  150. xx0 = xx1;
  151. xx1 = tmp;
  152. }
  153. /*
  154. * Calculate distance
  155. */
  156. dx = xx1 - xx0;
  157. dy = yy1 - yy0;
  158. /*
  159. * Adjust for negative dx and set xdir
  160. */
  161. if (dx >= 0)
  162. {
  163. xdir = 1;
  164. }
  165. else
  166. {
  167. xdir = -1;
  168. dx = (-dx);
  169. }
  170. /*
  171. * Check for special cases
  172. */
  173. if (dx == 0)
  174. {
  175. /*
  176. * Vertical line
  177. */
  178. rtgui_dc_draw_vline(dc, x1, y1, y2);
  179. return ;
  180. }
  181. else if (dy == 0)
  182. {
  183. /*
  184. * Horizontal line
  185. */
  186. rtgui_dc_draw_hline(dc, x1, x2, y1);
  187. return ;
  188. }
  189. else if (dx == dy)
  190. {
  191. /*
  192. * Diagonal line
  193. */
  194. rtgui_dc_draw_line(dc, x1, y1, x2, y2);
  195. return ;
  196. }
  197. /*
  198. * Zero accumulator
  199. */
  200. erracc = 0;
  201. /*
  202. * # of bits by which to shift erracc to get intensity level
  203. */
  204. intshift = 32 - AAbits;
  205. /*
  206. * Mask used to flip all bits in an intensity weighting
  207. */
  208. wgtcompmask = AAlevels - 1;
  209. /*
  210. * Draw the initial pixel in the foreground color
  211. */
  212. rtgui_dc_draw_point(dc, x1, y1);
  213. /*
  214. * x-major or y-major?
  215. */
  216. if (dy > dx)
  217. {
  218. /*
  219. * y-major. Calculate 16-bit fixed point fractional part of a pixel that
  220. * X advances every time Y advances 1 pixel, truncating the result so that
  221. * we won't overrun the endpoint along the X axis
  222. */
  223. /*
  224. * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
  225. */
  226. erradj = ((dx << 16) / dy) << 16;
  227. /*
  228. * draw all pixels other than the first and last
  229. */
  230. x0pxdir = xx0 + xdir;
  231. while (--dy)
  232. {
  233. erracctmp = erracc;
  234. erracc += erradj;
  235. if (erracc <= erracctmp)
  236. {
  237. /*
  238. * rollover in error accumulator, x coord advances
  239. */
  240. xx0 = x0pxdir;
  241. x0pxdir += xdir;
  242. }
  243. yy0++; /* y-major so always advance Y */
  244. /*
  245. * the AAbits most significant bits of erracc give us the intensity
  246. * weighting for this pixel, and the complement of the weighting for
  247. * the paired pixel.
  248. */
  249. wgt = (erracc >> intshift) & 255;
  250. rtgui_dc_draw_point_alpha (dc, xx0, yy0, 255 - wgt);
  251. rtgui_dc_draw_point_alpha (dc, x0pxdir, yy0, wgt);
  252. }
  253. }
  254. else
  255. {
  256. /*
  257. * x-major line. Calculate 16-bit fixed-point fractional part of a pixel
  258. * that Y advances each time X advances 1 pixel, truncating the result so
  259. * that we won't overrun the endpoint along the X axis.
  260. */
  261. /*
  262. * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
  263. */
  264. erradj = ((dy << 16) / dx) << 16;
  265. /*
  266. * draw all pixels other than the first and last
  267. */
  268. y0p1 = yy0 + 1;
  269. while (--dx)
  270. {
  271. erracctmp = erracc;
  272. erracc += erradj;
  273. if (erracc <= erracctmp)
  274. {
  275. /*
  276. * Accumulator turned over, advance y
  277. */
  278. yy0 = y0p1;
  279. y0p1++;
  280. }
  281. xx0 += xdir; /* x-major so always advance X */
  282. /*
  283. * the AAbits most significant bits of erracc give us the intensity
  284. * weighting for this pixel, and the complement of the weighting for
  285. * the paired pixel.
  286. */
  287. wgt = (erracc >> intshift) & 255;
  288. rtgui_dc_draw_point_alpha (dc, xx0, yy0, 255 - wgt);
  289. rtgui_dc_draw_point_alpha (dc, xx0, y0p1, wgt);
  290. }
  291. }
  292. /*
  293. * Draw final pixel, always exactly intersected by the line and doesn't
  294. * need to be weighted.
  295. */
  296. rtgui_dc_draw_point(dc, x2, y2);
  297. }
  298. #endif
  299. void rtgui_dc_draw_rect (struct rtgui_dc* dc, struct rtgui_rect* rect)
  300. {
  301. rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y1);
  302. rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y2 - 1);
  303. rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2);
  304. rtgui_dc_draw_vline(dc, rect->x2 - 1, rect->y1, rect->y2);
  305. }
  306. void rtgui_dc_fill_rect (struct rtgui_dc* dc, struct rtgui_rect* rect)
  307. {
  308. if (dc == RT_NULL) return;
  309. dc->fill_rect(dc, rect);
  310. }
  311. void rtgui_dc_blit(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect)
  312. {
  313. if (dc == RT_NULL || dest == RT_NULL || rect == RT_NULL) return;
  314. dc->blit(dc, dc_point, dest, rect);
  315. }
  316. void rtgui_dc_draw_text (struct rtgui_dc* dc, const rt_uint8_t* text, struct rtgui_rect* rect)
  317. {
  318. rt_uint32_t len;
  319. struct rtgui_font *font;
  320. #ifdef RTGUI_USING_FONTHZ
  321. struct rtgui_font *gb2312_font;
  322. #endif
  323. struct rtgui_rect text_rect;
  324. RT_ASSERT(dc != RT_NULL);
  325. font = rtgui_dc_get_font(dc);
  326. if (font == RT_NULL)
  327. {
  328. /* use system default font */
  329. font = rtgui_font_default();
  330. }
  331. #ifdef RTGUI_USING_FONTHZ
  332. gb2312_font = rtgui_font_refer("hz", font->height);
  333. if (gb2312_font == RT_NULL)
  334. {
  335. gb2312_font = rtgui_font_refer("hz", 16);
  336. }
  337. #endif
  338. /* text align */
  339. rtgui_font_get_metrics(font, text, &text_rect);
  340. rtgui_rect_moveto_align(rect, &text_rect, rtgui_dc_get_textalign(dc));
  341. #ifdef RTGUI_USING_FONTHZ
  342. while (*text)
  343. {
  344. len = 0;
  345. while (*(text + len) < 0x80 && *(text + len)) len ++;
  346. if (len > 0)
  347. {
  348. rtgui_font_draw(font, dc, text, len, &text_rect);
  349. text += len;
  350. }
  351. len = 0;
  352. while (*(text + len) > 0x80) len ++;
  353. if (len > 0)
  354. {
  355. rtgui_font_draw(gb2312_font, dc, text, len, &text_rect);
  356. text += len;
  357. }
  358. }
  359. rtgui_font_derefer(gb2312_font);
  360. #else
  361. len = strlen((const char*)text);
  362. rtgui_font_draw(font, dc, text, len, &text_rect);
  363. #endif
  364. }
  365. void rtgui_dc_set_color(struct rtgui_dc* dc, rtgui_color_t color)
  366. {
  367. if (dc != RT_NULL)
  368. {
  369. dc->set_color(dc, color);
  370. }
  371. }
  372. rtgui_color_t rtgui_dc_get_color(struct rtgui_dc* dc)
  373. {
  374. if (dc != RT_NULL)
  375. {
  376. return dc->get_color(dc);
  377. }
  378. return white;
  379. }
  380. void rtgui_dc_set_font(struct rtgui_dc* dc, rtgui_font_t* font)
  381. {
  382. if (dc != RT_NULL)
  383. {
  384. dc->set_font(dc, font);
  385. }
  386. }
  387. rtgui_font_t* rtgui_dc_get_font(struct rtgui_dc* dc)
  388. {
  389. if (dc != RT_NULL)
  390. {
  391. return dc->get_font(dc);
  392. }
  393. return RT_NULL;
  394. }
  395. void rtgui_dc_set_textalign(struct rtgui_dc* dc, rt_int32_t align)
  396. {
  397. if (dc != RT_NULL)
  398. {
  399. dc->set_textalign(dc, align);
  400. }
  401. }
  402. rt_int32_t rtgui_dc_get_textalign(struct rtgui_dc* dc)
  403. {
  404. if (dc != RT_NULL)
  405. {
  406. return dc->get_textalign(dc);
  407. }
  408. return RTGUI_ALIGN_NOT;
  409. }
  410. rt_bool_t rtgui_dc_get_visible(struct rtgui_dc* dc)
  411. {
  412. if (dc != RT_NULL)
  413. {
  414. return dc->get_visible(dc);
  415. }
  416. return RT_FALSE;
  417. }
  418. void rtgui_dc_draw_shaded_rect(struct rtgui_dc* dc, rtgui_rect_t* rect,
  419. rtgui_color_t c1, rtgui_color_t c2)
  420. {
  421. RT_ASSERT(dc != RT_NULL);
  422. rtgui_dc_set_color(dc, c1);
  423. rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2);
  424. rtgui_dc_draw_hline(dc, rect->x1 + 1, rect->x2, rect->y1);
  425. rtgui_dc_set_color(dc, c2);
  426. rtgui_dc_draw_vline(dc, rect->x2, rect->y1, rect->y2);
  427. rtgui_dc_draw_hline(dc, rect->x1, rect->x2 + 1, rect->y2);
  428. }
  429. void rtgui_dc_draw_border(struct rtgui_dc* dc, rtgui_rect_t* rect, int flag)
  430. {
  431. rtgui_rect_t r;
  432. rtgui_color_t color;
  433. if (dc == RT_NULL) return ;
  434. /* save old color */
  435. color = rtgui_dc_get_color(dc);
  436. r = *rect;
  437. switch (flag)
  438. {
  439. case RTGUI_BORDER_RAISE:
  440. rtgui_dc_draw_shaded_rect(dc, &r, high_light, black);
  441. rtgui_rect_inflate(&r, -1);
  442. rtgui_dc_draw_shaded_rect(dc, &r, light_grey, dark_grey);
  443. break;
  444. case RTGUI_BORDER_SUNKEN:
  445. rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
  446. rtgui_rect_inflate(&r, -1);
  447. rtgui_dc_draw_shaded_rect(dc, &r, black, light_grey);
  448. break;
  449. case RTGUI_BORDER_BOX:
  450. rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
  451. rtgui_rect_inflate(&r, -1);
  452. rtgui_dc_draw_shaded_rect(dc, &r, high_light, dark_grey);
  453. break;
  454. case RTGUI_BORDER_STATIC:
  455. rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
  456. break;
  457. case RTGUI_BORDER_EXTRA:
  458. rtgui_dc_set_color(dc, light_grey);
  459. rtgui_dc_draw_rect(dc, &r);
  460. break;
  461. case RTGUI_BORDER_SIMPLE:
  462. rtgui_dc_set_color(dc, black);
  463. rtgui_dc_draw_rect(dc, &r);
  464. break;
  465. default:
  466. break;
  467. }
  468. /* restore color */
  469. rtgui_dc_set_color(dc, color);
  470. }
  471. void rtgui_dc_draw_horizontal_line(struct rtgui_dc* dc, int x1, int x2, int y)
  472. {
  473. rtgui_color_t color;
  474. if (dc == RT_NULL) return ;
  475. /* save old color */
  476. color = rtgui_dc_get_color(dc);
  477. rtgui_dc_set_color(dc, dark_grey);
  478. rtgui_dc_draw_hline(dc, x1, x2, y);
  479. y ++;
  480. rtgui_dc_set_color(dc, high_light);
  481. rtgui_dc_draw_hline(dc, x1, x2, y);
  482. /* restore color */
  483. rtgui_dc_set_color(dc, color);
  484. }
  485. void rtgui_dc_draw_vertical_line(struct rtgui_dc* dc, int x, int y1, int y2)
  486. {
  487. rtgui_color_t color;
  488. if (dc == RT_NULL) return ;
  489. /* save old color */
  490. color = rtgui_dc_get_color(dc);
  491. rtgui_dc_set_color(dc, dark_grey);
  492. rtgui_dc_draw_hline(dc, x, y1, y2);
  493. x ++;
  494. rtgui_dc_set_color(dc, high_light);
  495. rtgui_dc_draw_hline(dc, x, y1, y2);
  496. /* restore color */
  497. rtgui_dc_set_color(dc, color);
  498. }
  499. void rtgui_dc_draw_arrow(struct rtgui_dc* dc, rtgui_rect_t* rect, int kind)
  500. {
  501. rt_int32_t i;
  502. rt_int32_t x1, y1, x2, y2;
  503. rtgui_rect_t r = {0, 0, 0, 0};
  504. static const rt_uint8_t ARROW_WIDTH = 7;
  505. static const rt_uint8_t ARROW_LENGTH = 4;
  506. x1 = y1 = 0;
  507. switch (kind)
  508. {
  509. case RTGUI_ARRAW_UP:
  510. case RTGUI_ARRAW_DOWN:
  511. r.x2 = ARROW_WIDTH;
  512. r.y2 = ARROW_LENGTH;
  513. break;
  514. case RTGUI_ARRAW_LEFT:
  515. case RTGUI_ARRAW_RIGHT:
  516. r.x2 = ARROW_LENGTH;
  517. r.y2 = ARROW_WIDTH;
  518. break;
  519. }
  520. rtgui_rect_moveto_align(rect, &r, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL);
  521. switch (kind)
  522. {
  523. case RTGUI_ARRAW_UP:
  524. x1 = r.x1 + (ARROW_WIDTH - 1)/2;;
  525. y1 = r.y1;
  526. break;
  527. case RTGUI_ARRAW_DOWN:
  528. x1 = r.x1 + (ARROW_WIDTH - 1)/2;
  529. y1 = r.y1 + ARROW_LENGTH - 1;
  530. break;
  531. case RTGUI_ARRAW_LEFT:
  532. x1 = r.x1;
  533. y1 = r.y1 + (ARROW_WIDTH - 1)/2;
  534. break;
  535. case RTGUI_ARRAW_RIGHT:
  536. x1 = r.x1 + ARROW_LENGTH - 1;
  537. y1 = r.y1 + (ARROW_WIDTH - 1)/2;
  538. break;
  539. default:
  540. return;
  541. }
  542. x2 = x1;
  543. y2 = y1;
  544. for (i = 0; i < ARROW_LENGTH; i++)
  545. {
  546. rtgui_dc_draw_line(dc, x1, y1, x2, y2);
  547. switch (kind)
  548. {
  549. case RTGUI_ARRAW_UP:
  550. x1 --;
  551. x2 ++;
  552. y1 ++;
  553. y2 ++;
  554. break;
  555. case RTGUI_ARRAW_DOWN:
  556. x1 --;
  557. x2 ++;
  558. y1 --;
  559. y2 --;
  560. break;
  561. case RTGUI_ARRAW_LEFT:
  562. y1 --;
  563. y2 ++;
  564. x1 ++;
  565. x2 ++;
  566. break;
  567. case RTGUI_ARRAW_RIGHT:
  568. y1 --;
  569. y2 ++;
  570. x1 --;
  571. x2 --;
  572. break;
  573. }
  574. }
  575. }
  576. void rtgui_dc_draw_polygon(struct rtgui_dc* dc, const int *vx, const int *vy, int count)
  577. {
  578. int i;
  579. const int *x1, *y1, *x2, *y2;
  580. /*
  581. * Sanity check
  582. */
  583. if (count < 3) return;
  584. /*
  585. * Pointer setup
  586. */
  587. x1 = x2 = vx;
  588. y1 = y2 = vy;
  589. x2++;
  590. y2++;
  591. /*
  592. * Draw
  593. */
  594. for (i = 1; i < count; i++)
  595. {
  596. rtgui_dc_draw_line(dc, *x1, *y1, *x2, *y2);
  597. x1 = x2;
  598. y1 = y2;
  599. x2++;
  600. y2++;
  601. }
  602. rtgui_dc_draw_line(dc, *x1, *y1, *vx, *vy);
  603. }
  604. static int _int_compare(const void *a, const void *b)
  605. {
  606. return (*(const int *) a) - (*(const int *) b);
  607. }
  608. void rtgui_dc_fill_polygon(struct rtgui_dc* dc, const int* vx, const int* vy, int count)
  609. {
  610. int i;
  611. int y, xa, xb;
  612. int miny, maxy;
  613. int x1, y1;
  614. int x2, y2;
  615. int ind1, ind2;
  616. int ints;
  617. int *poly_ints = RT_NULL;
  618. /*
  619. * Sanity check number of edges
  620. */
  621. if (count < 3) return;
  622. /*
  623. * Allocate temp array, only grow array
  624. */
  625. poly_ints = (int *) rt_malloc(sizeof(int) * count);
  626. if (poly_ints == RT_NULL) return ; /* no memory, failed */
  627. /*
  628. * Determine Y maximal
  629. */
  630. miny = vy[0];
  631. maxy = vy[0];
  632. for (i = 1; (i < count); i++)
  633. {
  634. if (vy[i] < miny) miny = vy[i];
  635. else if (vy[i] > maxy) maxy = vy[i];
  636. }
  637. /*
  638. * Draw, scanning y
  639. */
  640. for (y = miny; (y <= maxy); y++) {
  641. ints = 0;
  642. for (i = 0; (i < count); i++) {
  643. if (!i) {
  644. ind1 = count - 1;
  645. ind2 = 0;
  646. } else {
  647. ind1 = i - 1;
  648. ind2 = i;
  649. }
  650. y1 = vy[ind1];
  651. y2 = vy[ind2];
  652. if (y1 < y2) {
  653. x1 = vx[ind1];
  654. x2 = vx[ind2];
  655. } else if (y1 > y2) {
  656. y2 = vy[ind1];
  657. y1 = vy[ind2];
  658. x2 = vx[ind1];
  659. x1 = vx[ind2];
  660. } else {
  661. continue;
  662. }
  663. if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) )
  664. {
  665. poly_ints[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
  666. }
  667. }
  668. qsort(poly_ints, ints, sizeof(int), _int_compare);
  669. for (i = 0; (i < ints); i += 2)
  670. {
  671. xa = poly_ints[i] + 1;
  672. xa = (xa >> 16) + ((xa & 32768) >> 15);
  673. xb = poly_ints[i+1] - 1;
  674. xb = (xb >> 16) + ((xb & 32768) >> 15);
  675. rtgui_dc_draw_hline(dc, xa, xb, y);
  676. }
  677. }
  678. }
  679. void rtgui_dc_draw_circle(struct rtgui_dc* dc, int x, int y, int r)
  680. {
  681. rt_int16_t cx = 0;
  682. rt_int16_t cy = r;
  683. rt_int16_t df = 1 - r;
  684. rt_int16_t d_e = 3;
  685. rt_int16_t d_se = -2 * r + 5;
  686. rt_int16_t xpcx, xmcx, xpcy, xmcy;
  687. rt_int16_t ypcy, ymcy, ypcx, ymcx;
  688. /*
  689. * sanity check radius
  690. */
  691. if (r < 0) return ;
  692. /* special case for r=0 - draw a point */
  693. if (r == 0) rtgui_dc_draw_point(dc, x, y);
  694. /*
  695. * draw circle
  696. */
  697. do
  698. {
  699. ypcy = y + cy;
  700. ymcy = y - cy;
  701. if (cx > 0)
  702. {
  703. xpcx = x + cx;
  704. xmcx = x - cx;
  705. rtgui_dc_draw_point(dc, xmcx, ypcy);
  706. rtgui_dc_draw_point(dc, xpcx, ypcy);
  707. rtgui_dc_draw_point(dc, xmcx, ymcy);
  708. rtgui_dc_draw_point(dc, xpcx, ymcy);
  709. }
  710. else
  711. {
  712. rtgui_dc_draw_point(dc, x, ymcy);
  713. rtgui_dc_draw_point(dc, x, ypcy);
  714. }
  715. xpcy = x + cy;
  716. xmcy = x - cy;
  717. if ((cx > 0) && (cx != cy))
  718. {
  719. ypcx = y + cx;
  720. ymcx = y - cx;
  721. rtgui_dc_draw_point(dc, xmcy, ypcx);
  722. rtgui_dc_draw_point(dc, xpcy, ypcx);
  723. rtgui_dc_draw_point(dc, xmcy, ymcx);
  724. rtgui_dc_draw_point(dc, xpcy, ymcx);
  725. }
  726. else if (cx == 0)
  727. {
  728. rtgui_dc_draw_point(dc, xmcy, y);
  729. rtgui_dc_draw_point(dc, xpcy, y);
  730. }
  731. /*
  732. * Update
  733. */
  734. if (df < 0)
  735. {
  736. df += d_e;
  737. d_e += 2;
  738. d_se += 2;
  739. }
  740. else
  741. {
  742. df += d_se;
  743. d_e += 2;
  744. d_se += 4;
  745. cy--;
  746. }
  747. cx++;
  748. }while (cx <= cy);
  749. }
  750. void rtgui_dc_fill_circle(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t r)
  751. {
  752. rt_int16_t cx = 0;
  753. rt_int16_t cy = r;
  754. rt_int16_t ocx = (rt_int16_t) 0xffff;
  755. rt_int16_t ocy = (rt_int16_t) 0xffff;
  756. rt_int16_t df = 1 - r;
  757. rt_int16_t d_e = 3;
  758. rt_int16_t d_se = -2 * r + 5;
  759. rt_int16_t xpcx, xmcx, xpcy, xmcy;
  760. rt_int16_t ypcy, ymcy, ypcx, ymcx;
  761. /*
  762. * Sanity check radius
  763. */
  764. if (r < 0) return;
  765. /*
  766. * Special case for r=0 - draw a point
  767. */
  768. if (r == 0)
  769. {
  770. rtgui_dc_draw_point(dc, x, y);
  771. return ;
  772. }
  773. /*
  774. * Draw
  775. */
  776. do {
  777. xpcx = x + cx;
  778. xmcx = x - cx;
  779. xpcy = x + cy;
  780. xmcy = x - cy;
  781. if (ocy != cy) {
  782. if (cy > 0) {
  783. ypcy = y + cy;
  784. ymcy = y - cy;
  785. rtgui_dc_draw_hline(dc, xmcx, xpcx, ypcy);
  786. rtgui_dc_draw_hline(dc, xmcx, xpcx, ymcy);
  787. } else {
  788. rtgui_dc_draw_hline(dc, xmcx, xpcx, y);
  789. }
  790. ocy = cy;
  791. }
  792. if (ocx != cx) {
  793. if (cx != cy) {
  794. if (cx > 0) {
  795. ypcx = y + cx;
  796. ymcx = y - cx;
  797. rtgui_dc_draw_hline(dc, xmcy, xpcy, ymcx);
  798. rtgui_dc_draw_hline(dc, xmcy, xpcy, ypcx);
  799. } else {
  800. rtgui_dc_draw_hline(dc, xmcy, xpcy, y);
  801. }
  802. }
  803. ocx = cx;
  804. }
  805. /*
  806. * Update
  807. */
  808. if (df < 0) {
  809. df += d_e;
  810. d_e += 2;
  811. d_se += 2;
  812. } else {
  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. }
  1068. void rtgui_dc_get_rect(struct rtgui_dc*dc, rtgui_rect_t* rect)
  1069. {
  1070. if (dc != RT_NULL && rect != RT_NULL)
  1071. {
  1072. dc->get_rect(dc, rect);
  1073. }
  1074. }