dc.c 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223
  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. void rtgui_dc_destory(struct rtgui_dc* dc)
  17. {
  18. if (dc == RT_NULL) return;
  19. dc->fini(dc);
  20. rtgui_free(dc);
  21. }
  22. /*
  23. * draw a point on dc
  24. */
  25. void rtgui_dc_draw_point(struct rtgui_dc* dc, int x, int y)
  26. {
  27. if (dc == RT_NULL) return;
  28. dc->draw_point(dc, x, y);
  29. }
  30. #if 0
  31. void rtgui_dc_draw_point_alpha(struct rtgui_dc* dc, int x, int y, rt_uint8_t alpha)
  32. {
  33. if (dc == RT_NULL || alpha == 0xff) return;
  34. if (dc->draw_point_alpha != RT_NULL)
  35. dc->draw_point_alpha(dc, x, y, alpha);
  36. else
  37. {
  38. rtgui_color_t color;
  39. /* soft alpha bending */
  40. color = dc->get_color(dc, int x, int y);
  41. dc->draw_point(dc, x, y);
  42. }
  43. }
  44. #endif
  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. #if 0
  122. /* AA Line */
  123. #define AAlevels 256
  124. #define AAbits 8
  125. 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)
  126. {
  127. Sint32 xx0, yy0, xx1, yy1;
  128. int result;
  129. rt_uint32_t intshift, erracc, erradj;
  130. rt_uint32_t erracctmp, wgt, wgtcompmask;
  131. int dx, dy, tmp, xdir, y0p1, x0pxdir;
  132. /*
  133. * Keep on working with 32bit numbers
  134. */
  135. xx0 = x1;
  136. yy0 = y1;
  137. xx1 = x2;
  138. yy1 = y2;
  139. /*
  140. * Reorder points if required
  141. */
  142. if (yy0 > yy1)
  143. {
  144. tmp = yy0;
  145. yy0 = yy1;
  146. yy1 = tmp;
  147. tmp = xx0;
  148. xx0 = xx1;
  149. xx1 = tmp;
  150. }
  151. /*
  152. * Calculate distance
  153. */
  154. dx = xx1 - xx0;
  155. dy = yy1 - yy0;
  156. /*
  157. * Adjust for negative dx and set xdir
  158. */
  159. if (dx >= 0)
  160. {
  161. xdir = 1;
  162. }
  163. else
  164. {
  165. xdir = -1;
  166. dx = (-dx);
  167. }
  168. /*
  169. * Check for special cases
  170. */
  171. if (dx == 0)
  172. {
  173. /*
  174. * Vertical line
  175. */
  176. rtgui_dc_draw_vline(dc, x1, y1, y2);
  177. return ;
  178. }
  179. else if (dy == 0)
  180. {
  181. /*
  182. * Horizontal line
  183. */
  184. rtgui_dc_draw_hline(dc, x1, x2, y1);
  185. return ;
  186. }
  187. else if (dx == dy)
  188. {
  189. /*
  190. * Diagonal line
  191. */
  192. rtgui_dc_draw_line(dc, x1, y1, x2, y2);
  193. return ;
  194. }
  195. /*
  196. * Zero accumulator
  197. */
  198. erracc = 0;
  199. /*
  200. * # of bits by which to shift erracc to get intensity level
  201. */
  202. intshift = 32 - AAbits;
  203. /*
  204. * Mask used to flip all bits in an intensity weighting
  205. */
  206. wgtcompmask = AAlevels - 1;
  207. /*
  208. * Draw the initial pixel in the foreground color
  209. */
  210. rtgui_dc_draw_point(dc, x1, y1);
  211. /*
  212. * x-major or y-major?
  213. */
  214. if (dy > dx)
  215. {
  216. /*
  217. * y-major. Calculate 16-bit fixed point fractional part of a pixel that
  218. * X advances every time Y advances 1 pixel, truncating the result so that
  219. * we won't overrun the endpoint along the X axis
  220. */
  221. /*
  222. * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
  223. */
  224. erradj = ((dx << 16) / dy) << 16;
  225. /*
  226. * draw all pixels other than the first and last
  227. */
  228. x0pxdir = xx0 + xdir;
  229. while (--dy)
  230. {
  231. erracctmp = erracc;
  232. erracc += erradj;
  233. if (erracc <= erracctmp)
  234. {
  235. /*
  236. * rollover in error accumulator, x coord advances
  237. */
  238. xx0 = x0pxdir;
  239. x0pxdir += xdir;
  240. }
  241. yy0++; /* y-major so always advance Y */
  242. /*
  243. * the AAbits most significant bits of erracc give us the intensity
  244. * weighting for this pixel, and the complement of the weighting for
  245. * the paired pixel.
  246. */
  247. wgt = (erracc >> intshift) & 255;
  248. rtgui_dc_draw_point_alpha (dc, xx0, yy0, 255 - wgt);
  249. rtgui_dc_draw_point_alpha (dc, x0pxdir, yy0, wgt);
  250. }
  251. }
  252. else
  253. {
  254. /*
  255. * x-major line. Calculate 16-bit fixed-point fractional part of a pixel
  256. * that Y advances each time X advances 1 pixel, truncating the result so
  257. * that we won't overrun the endpoint along the X axis.
  258. */
  259. /*
  260. * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
  261. */
  262. erradj = ((dy << 16) / dx) << 16;
  263. /*
  264. * draw all pixels other than the first and last
  265. */
  266. y0p1 = yy0 + 1;
  267. while (--dx)
  268. {
  269. erracctmp = erracc;
  270. erracc += erradj;
  271. if (erracc <= erracctmp)
  272. {
  273. /*
  274. * Accumulator turned over, advance y
  275. */
  276. yy0 = y0p1;
  277. y0p1++;
  278. }
  279. xx0 += xdir; /* x-major so always advance X */
  280. /*
  281. * the AAbits most significant bits of erracc give us the intensity
  282. * weighting for this pixel, and the complement of the weighting for
  283. * the paired pixel.
  284. */
  285. wgt = (erracc >> intshift) & 255;
  286. rtgui_dc_draw_point_alpha (dc, xx0, yy0, 255 - wgt);
  287. rtgui_dc_draw_point_alpha (dc, xx0, y0p1, wgt);
  288. }
  289. }
  290. /*
  291. * Draw final pixel, always exactly intersected by the line and doesn't
  292. * need to be weighted.
  293. */
  294. rtgui_dc_draw_point(dc, x2, y2);
  295. }
  296. #endif
  297. void rtgui_dc_draw_rect (struct rtgui_dc* dc, struct rtgui_rect* rect)
  298. {
  299. rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y1);
  300. rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y2 - 1);
  301. rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2);
  302. rtgui_dc_draw_vline(dc, rect->x2 - 1, rect->y1, rect->y2);
  303. }
  304. void rtgui_dc_fill_rect (struct rtgui_dc* dc, struct rtgui_rect* rect)
  305. {
  306. if (dc == RT_NULL) return;
  307. dc->fill_rect(dc, rect);
  308. }
  309. void rtgui_dc_blit(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect)
  310. {
  311. if (dc == RT_NULL || dest == RT_NULL || rect == RT_NULL) return;
  312. dc->blit(dc, dc_point, dest, rect);
  313. }
  314. void rtgui_dc_draw_text (struct rtgui_dc* dc, const rt_uint8_t* text, struct rtgui_rect* rect)
  315. {
  316. rt_uint32_t len;
  317. struct rtgui_font *font;
  318. #ifdef RTGUI_USING_FONTHZ
  319. struct rtgui_font *gb2312_font;
  320. #endif
  321. struct rtgui_rect text_rect;
  322. RT_ASSERT(dc != RT_NULL);
  323. font = rtgui_dc_get_font(dc);
  324. if (font == RT_NULL)
  325. {
  326. /* use system default font */
  327. font = rtgui_font_default();
  328. }
  329. #ifdef RTGUI_USING_FONTHZ
  330. gb2312_font = rtgui_font_refer("hz", font->height);
  331. if (gb2312_font == RT_NULL)
  332. {
  333. gb2312_font = rtgui_font_refer("hz", 16);
  334. }
  335. #endif
  336. /* text align */
  337. rtgui_font_get_metrics(font, text, &text_rect);
  338. rtgui_rect_moveto_align(rect, &text_rect, rtgui_dc_get_textalign(dc));
  339. #ifdef RTGUI_USING_FONTHZ
  340. while (*text)
  341. {
  342. len = 0;
  343. while (*(text + len) < 0x80 && *(text + len)) len ++;
  344. if (len > 0)
  345. {
  346. rtgui_font_draw(font, dc, text, len, &text_rect);
  347. text += len;
  348. }
  349. len = 0;
  350. while (*(text + len) > 0x80) len ++;
  351. if (len > 0)
  352. {
  353. rtgui_font_draw(gb2312_font, dc, text, len, &text_rect);
  354. text += len;
  355. }
  356. }
  357. rtgui_font_derefer(gb2312_font);
  358. #else
  359. len = strlen(text);
  360. rtgui_font_draw(font, dc, text, len, &text_rect);
  361. #endif
  362. }
  363. void rtgui_dc_set_color(struct rtgui_dc* dc, rtgui_color_t color)
  364. {
  365. if (dc != RT_NULL)
  366. {
  367. dc->set_color(dc, color);
  368. }
  369. }
  370. rtgui_color_t rtgui_dc_get_color(struct rtgui_dc* dc)
  371. {
  372. if (dc != RT_NULL)
  373. {
  374. return dc->get_color(dc);
  375. }
  376. return white;
  377. }
  378. void rtgui_dc_set_font(struct rtgui_dc* dc, rtgui_font_t* font)
  379. {
  380. if (dc != RT_NULL)
  381. {
  382. dc->set_font(dc, font);
  383. }
  384. }
  385. rtgui_font_t* rtgui_dc_get_font(struct rtgui_dc* dc)
  386. {
  387. if (dc != RT_NULL)
  388. {
  389. return dc->get_font(dc);
  390. }
  391. return RT_NULL;
  392. }
  393. void rtgui_dc_set_textalign(struct rtgui_dc* dc, rt_int32_t align)
  394. {
  395. if (dc != RT_NULL)
  396. {
  397. dc->set_textalign(dc, align);
  398. }
  399. }
  400. rt_int32_t rtgui_dc_get_textalign(struct rtgui_dc* dc)
  401. {
  402. if (dc != RT_NULL)
  403. {
  404. return dc->get_textalign(dc);
  405. }
  406. return RTGUI_ALIGN_NOT;
  407. }
  408. rt_bool_t rtgui_dc_get_visible(struct rtgui_dc* dc)
  409. {
  410. if (dc != RT_NULL)
  411. {
  412. return dc->get_visible(dc);
  413. }
  414. return RT_FALSE;
  415. }
  416. void rtgui_dc_draw_shaded_rect(struct rtgui_dc* dc, rtgui_rect_t* rect,
  417. rtgui_color_t c1, rtgui_color_t c2)
  418. {
  419. RT_ASSERT(dc != RT_NULL);
  420. rtgui_dc_set_color(dc, c1);
  421. rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2);
  422. rtgui_dc_draw_hline(dc, rect->x1 + 1, rect->x2, rect->y1);
  423. rtgui_dc_set_color(dc, c2);
  424. rtgui_dc_draw_vline(dc, rect->x2, rect->y1, rect->y2);
  425. rtgui_dc_draw_hline(dc, rect->x1, rect->x2 + 1, rect->y2);
  426. }
  427. void rtgui_dc_draw_border(struct rtgui_dc* dc, rtgui_rect_t* rect, int flag)
  428. {
  429. rtgui_rect_t r;
  430. rtgui_color_t color;
  431. if (dc == RT_NULL) return ;
  432. /* save old color */
  433. color = rtgui_dc_get_color(dc);
  434. r = *rect;
  435. switch (flag)
  436. {
  437. case RTGUI_BORDER_RAISE:
  438. rtgui_dc_draw_shaded_rect(dc, &r, high_light, black);
  439. rtgui_rect_inflate(&r, -1);
  440. rtgui_dc_draw_shaded_rect(dc, &r, light_grey, dark_grey);
  441. break;
  442. case RTGUI_BORDER_SUNKEN:
  443. rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
  444. rtgui_rect_inflate(&r, -1);
  445. rtgui_dc_draw_shaded_rect(dc, &r, black, light_grey);
  446. break;
  447. case RTGUI_BORDER_BOX:
  448. rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
  449. rtgui_rect_inflate(&r, -1);
  450. rtgui_dc_draw_shaded_rect(dc, &r, high_light, dark_grey);
  451. break;
  452. case RTGUI_BORDER_STATIC:
  453. rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
  454. break;
  455. case RTGUI_BORDER_EXTRA:
  456. rtgui_dc_set_color(dc, light_grey);
  457. rtgui_dc_draw_rect(dc, &r);
  458. break;
  459. case RTGUI_BORDER_SIMPLE:
  460. rtgui_dc_set_color(dc, black);
  461. rtgui_dc_draw_rect(dc, &r);
  462. break;
  463. default:
  464. break;
  465. }
  466. /* restore color */
  467. rtgui_dc_set_color(dc, color);
  468. }
  469. void rtgui_dc_draw_horizontal_line(struct rtgui_dc* dc, int x1, int x2, int y)
  470. {
  471. rtgui_color_t color;
  472. if (dc == RT_NULL) return ;
  473. /* save old color */
  474. color = rtgui_dc_get_color(dc);
  475. rtgui_dc_set_color(dc, dark_grey);
  476. rtgui_dc_draw_hline(dc, x1, x2, y);
  477. y ++;
  478. rtgui_dc_set_color(dc, high_light);
  479. rtgui_dc_draw_hline(dc, x1, x2, y);
  480. /* restore color */
  481. rtgui_dc_set_color(dc, color);
  482. }
  483. void rtgui_dc_draw_vertical_line(struct rtgui_dc* dc, int x, int y1, int y2)
  484. {
  485. rtgui_color_t color;
  486. if (dc == RT_NULL) return ;
  487. /* save old color */
  488. color = rtgui_dc_get_color(dc);
  489. rtgui_dc_set_color(dc, dark_grey);
  490. rtgui_dc_draw_hline(dc, x, y1, y2);
  491. x ++;
  492. rtgui_dc_set_color(dc, high_light);
  493. rtgui_dc_draw_hline(dc, x, y1, y2);
  494. /* restore color */
  495. rtgui_dc_set_color(dc, color);
  496. }
  497. void rtgui_dc_draw_arrow(struct rtgui_dc* dc, rtgui_rect_t* rect, int kind)
  498. {
  499. rt_int32_t i;
  500. rt_int32_t x1, y1, x2, y2;
  501. rtgui_rect_t r = {0, 0, 0, 0};
  502. static const rt_uint8_t ARROW_WIDTH = 7;
  503. static const rt_uint8_t ARROW_LENGTH = 4;
  504. x1 = y1 = 0;
  505. switch (kind)
  506. {
  507. case RTGUI_ARRAW_UP:
  508. case RTGUI_ARRAW_DOWN:
  509. r.x2 = ARROW_WIDTH;
  510. r.y2 = ARROW_LENGTH;
  511. break;
  512. case RTGUI_ARRAW_LEFT:
  513. case RTGUI_ARRAW_RIGHT:
  514. r.x2 = ARROW_LENGTH;
  515. r.y2 = ARROW_WIDTH;
  516. break;
  517. }
  518. rtgui_rect_moveto_align(rect, &r, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL);
  519. switch (kind)
  520. {
  521. case RTGUI_ARRAW_UP:
  522. x1 = r.x1 + (ARROW_WIDTH - 1)/2;;
  523. y1 = r.y1;
  524. break;
  525. case RTGUI_ARRAW_DOWN:
  526. x1 = r.x1 + (ARROW_WIDTH - 1)/2;
  527. y1 = r.y1 + ARROW_LENGTH - 1;
  528. break;
  529. case RTGUI_ARRAW_LEFT:
  530. x1 = r.x1;
  531. y1 = r.y1 + (ARROW_WIDTH - 1)/2;
  532. break;
  533. case RTGUI_ARRAW_RIGHT:
  534. x1 = r.x1 + ARROW_LENGTH - 1;
  535. y1 = r.y1 + (ARROW_WIDTH - 1)/2;
  536. break;
  537. default:
  538. return;
  539. }
  540. x2 = x1;
  541. y2 = y1;
  542. for (i = 0; i < ARROW_LENGTH; i++)
  543. {
  544. rtgui_dc_draw_line(dc, x1, y1, x2, y2);
  545. switch (kind)
  546. {
  547. case RTGUI_ARRAW_UP:
  548. x1 --;
  549. x2 ++;
  550. y1 ++;
  551. y2 ++;
  552. break;
  553. case RTGUI_ARRAW_DOWN:
  554. x1 --;
  555. x2 ++;
  556. y1 --;
  557. y2 --;
  558. break;
  559. case RTGUI_ARRAW_LEFT:
  560. y1 --;
  561. y2 ++;
  562. x1 ++;
  563. x2 ++;
  564. break;
  565. case RTGUI_ARRAW_RIGHT:
  566. y1 --;
  567. y2 ++;
  568. x1 --;
  569. x2 --;
  570. break;
  571. }
  572. }
  573. }
  574. void rtgui_dc_draw_polygon(struct rtgui_dc* dc, const int *vx, const int *vy, int count)
  575. {
  576. int i;
  577. const int *x1, *y1, *x2, *y2;
  578. /*
  579. * Sanity check
  580. */
  581. if (count < 3) return;
  582. /*
  583. * Pointer setup
  584. */
  585. x1 = x2 = vx;
  586. y1 = y2 = vy;
  587. x2++;
  588. y2++;
  589. /*
  590. * Draw
  591. */
  592. for (i = 1; i < count; i++)
  593. {
  594. rtgui_dc_draw_line(dc, *x1, *y1, *x2, *y2);
  595. x1 = x2;
  596. y1 = y2;
  597. x2++;
  598. y2++;
  599. }
  600. rtgui_dc_draw_line(dc, *x1, *y1, *vx, *vy);
  601. }
  602. static int _int_compare(const void *a, const void *b)
  603. {
  604. return (*(const int *) a) - (*(const int *) b);
  605. }
  606. void rtgui_dc_fill_polygon(struct rtgui_dc* dc, const int* vx, const int* vy, int count)
  607. {
  608. int i;
  609. int y, xa, xb;
  610. int miny, maxy;
  611. int x1, y1;
  612. int x2, y2;
  613. int ind1, ind2;
  614. int ints;
  615. int *poly_ints = RT_NULL;
  616. /*
  617. * Sanity check number of edges
  618. */
  619. if (count < 3) return;
  620. /*
  621. * Allocate temp array, only grow array
  622. */
  623. poly_ints = (int *) rt_malloc(sizeof(int) * count);
  624. if (poly_ints == RT_NULL) return ; /* no memory, failed */
  625. /*
  626. * Determine Y maximal
  627. */
  628. miny = vy[0];
  629. maxy = vy[0];
  630. for (i = 1; (i < count); i++)
  631. {
  632. if (vy[i] < miny) miny = vy[i];
  633. else if (vy[i] > maxy) maxy = vy[i];
  634. }
  635. /*
  636. * Draw, scanning y
  637. */
  638. for (y = miny; (y <= maxy); y++) {
  639. ints = 0;
  640. for (i = 0; (i < count); i++) {
  641. if (!i) {
  642. ind1 = count - 1;
  643. ind2 = 0;
  644. } else {
  645. ind1 = i - 1;
  646. ind2 = i;
  647. }
  648. y1 = vy[ind1];
  649. y2 = vy[ind2];
  650. if (y1 < y2) {
  651. x1 = vx[ind1];
  652. x2 = vx[ind2];
  653. } else if (y1 > y2) {
  654. y2 = vy[ind1];
  655. y1 = vy[ind2];
  656. x2 = vx[ind1];
  657. x1 = vx[ind2];
  658. } else {
  659. continue;
  660. }
  661. if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) )
  662. {
  663. poly_ints[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
  664. }
  665. }
  666. qsort(poly_ints, ints, sizeof(int), _int_compare);
  667. for (i = 0; (i < ints); i += 2)
  668. {
  669. xa = poly_ints[i] + 1;
  670. xa = (xa >> 16) + ((xa & 32768) >> 15);
  671. xb = poly_ints[i+1] - 1;
  672. xb = (xb >> 16) + ((xb & 32768) >> 15);
  673. rtgui_dc_draw_hline(dc, xa, xb, y);
  674. }
  675. }
  676. }
  677. void rtgui_dc_draw_circle(struct rtgui_dc* dc, int x, int y, int r)
  678. {
  679. rt_int16_t cx = 0;
  680. rt_int16_t cy = r;
  681. rt_int16_t df = 1 - r;
  682. rt_int16_t d_e = 3;
  683. rt_int16_t d_se = -2 * r + 5;
  684. rt_int16_t xpcx, xmcx, xpcy, xmcy;
  685. rt_int16_t ypcy, ymcy, ypcx, ymcx;
  686. /*
  687. * sanity check radius
  688. */
  689. if (r < 0) return ;
  690. /* special case for r=0 - draw a point */
  691. if (r == 0) rtgui_dc_draw_point(dc, x, y);
  692. /*
  693. * draw circle
  694. */
  695. do
  696. {
  697. ypcy = y + cy;
  698. ymcy = y - cy;
  699. if (cx > 0)
  700. {
  701. xpcx = x + cx;
  702. xmcx = x - cx;
  703. rtgui_dc_draw_point(dc, xmcx, ypcy);
  704. rtgui_dc_draw_point(dc, xpcx, ypcy);
  705. rtgui_dc_draw_point(dc, xmcx, ymcy);
  706. rtgui_dc_draw_point(dc, xpcx, ymcy);
  707. }
  708. else
  709. {
  710. rtgui_dc_draw_point(dc, x, ymcy);
  711. rtgui_dc_draw_point(dc, x, ypcy);
  712. }
  713. xpcy = x + cy;
  714. xmcy = x - cy;
  715. if ((cx > 0) && (cx != cy))
  716. {
  717. ypcx = y + cx;
  718. ymcx = y - cx;
  719. rtgui_dc_draw_point(dc, xmcy, ypcx);
  720. rtgui_dc_draw_point(dc, xpcy, ypcx);
  721. rtgui_dc_draw_point(dc, xmcy, ymcx);
  722. rtgui_dc_draw_point(dc, xpcy, ymcx);
  723. }
  724. else if (cx == 0)
  725. {
  726. rtgui_dc_draw_point(dc, xmcy, y);
  727. rtgui_dc_draw_point(dc, xpcy, y);
  728. }
  729. /*
  730. * Update
  731. */
  732. if (df < 0)
  733. {
  734. df += d_e;
  735. d_e += 2;
  736. d_se += 2;
  737. }
  738. else
  739. {
  740. df += d_se;
  741. d_e += 2;
  742. d_se += 4;
  743. cy--;
  744. }
  745. cx++;
  746. }while (cx <= cy);
  747. }
  748. void rtgui_dc_fill_circle(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t r)
  749. {
  750. rt_int16_t cx = 0;
  751. rt_int16_t cy = r;
  752. rt_int16_t ocx = (rt_int16_t) 0xffff;
  753. rt_int16_t ocy = (rt_int16_t) 0xffff;
  754. rt_int16_t df = 1 - r;
  755. rt_int16_t d_e = 3;
  756. rt_int16_t d_se = -2 * r + 5;
  757. rt_int16_t xpcx, xmcx, xpcy, xmcy;
  758. rt_int16_t ypcy, ymcy, ypcx, ymcx;
  759. /*
  760. * Sanity check radius
  761. */
  762. if (r < 0) return;
  763. /*
  764. * Special case for r=0 - draw a point
  765. */
  766. if (r == 0)
  767. {
  768. rtgui_dc_draw_point(dc, x, y);
  769. return ;
  770. }
  771. /*
  772. * Draw
  773. */
  774. do {
  775. xpcx = x + cx;
  776. xmcx = x - cx;
  777. xpcy = x + cy;
  778. xmcy = x - cy;
  779. if (ocy != cy) {
  780. if (cy > 0) {
  781. ypcy = y + cy;
  782. ymcy = y - cy;
  783. rtgui_dc_draw_hline(dc, xmcx, xpcx, ypcy);
  784. rtgui_dc_draw_hline(dc, xmcx, xpcx, ymcy);
  785. } else {
  786. rtgui_dc_draw_hline(dc, xmcx, xpcx, y);
  787. }
  788. ocy = cy;
  789. }
  790. if (ocx != cx) {
  791. if (cx != cy) {
  792. if (cx > 0) {
  793. ypcx = y + cx;
  794. ymcx = y - cx;
  795. rtgui_dc_draw_hline(dc, xmcy, xpcy, ymcx);
  796. rtgui_dc_draw_hline(dc, xmcy, xpcy, ypcx);
  797. } else {
  798. rtgui_dc_draw_hline(dc, xmcy, xpcy, y);
  799. }
  800. }
  801. ocx = cx;
  802. }
  803. /*
  804. * Update
  805. */
  806. if (df < 0) {
  807. df += d_e;
  808. d_e += 2;
  809. d_se += 2;
  810. } else {
  811. df += d_se;
  812. d_e += 2;
  813. d_se += 4;
  814. cy--;
  815. }
  816. cx++;
  817. } while (cx <= cy);
  818. }
  819. 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)
  820. {
  821. int ix, iy;
  822. int h, i, j, k;
  823. int oh, oi, oj, ok;
  824. int xmh, xph, ypk, ymk;
  825. int xmi, xpi, ymj, ypj;
  826. int xmj, xpj, ymi, ypi;
  827. int xmk, xpk, ymh, yph;
  828. /*
  829. * Sanity check radii
  830. */
  831. if ((rx < 0) || (ry < 0)) return;
  832. /*
  833. * Special case for rx=0 - draw a vline
  834. */
  835. if (rx == 0)
  836. {
  837. rtgui_dc_draw_vline(dc, x, y - ry, y + ry);
  838. return;
  839. }
  840. /*
  841. * Special case for ry=0 - draw a hline
  842. */
  843. if (ry == 0)
  844. {
  845. rtgui_dc_draw_hline(dc, x - rx, x + rx, y);
  846. return;
  847. }
  848. /*
  849. * Init vars
  850. */
  851. oh = oi = oj = ok = 0xFFFF;
  852. if (rx > ry)
  853. {
  854. ix = 0;
  855. iy = rx * 64;
  856. do
  857. {
  858. h = (ix + 32) >> 6;
  859. i = (iy + 32) >> 6;
  860. j = (h * ry) / rx;
  861. k = (i * ry) / rx;
  862. if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j))
  863. {
  864. xph = x + h;
  865. xmh = x - h;
  866. if (k > 0)
  867. {
  868. ypk = y + k;
  869. ymk = y - k;
  870. rtgui_dc_draw_point(dc, xmh, ypk);
  871. rtgui_dc_draw_point(dc, xph, ypk);
  872. rtgui_dc_draw_point(dc, xmh, ymk);
  873. rtgui_dc_draw_point(dc, xph, ymk);
  874. }
  875. else
  876. {
  877. rtgui_dc_draw_point(dc, xmh, y);
  878. rtgui_dc_draw_point(dc, xph, y);
  879. }
  880. ok = k;
  881. xpi = x + i;
  882. xmi = x - i;
  883. if (j > 0)
  884. {
  885. ypj = y + j;
  886. ymj = y - j;
  887. rtgui_dc_draw_point(dc, xmi, ypj);
  888. rtgui_dc_draw_point(dc, xpi, ypj);
  889. rtgui_dc_draw_point(dc, xmi, ymj);
  890. rtgui_dc_draw_point(dc, xpi, ymj);
  891. }
  892. else
  893. {
  894. rtgui_dc_draw_point(dc, xmi, y);
  895. rtgui_dc_draw_point(dc, xpi, y);
  896. }
  897. oj = j;
  898. }
  899. ix = ix + iy / rx;
  900. iy = iy - ix / rx;
  901. } while (i > h);
  902. }
  903. else
  904. {
  905. ix = 0;
  906. iy = ry * 64;
  907. do
  908. {
  909. h = (ix + 32) >> 6;
  910. i = (iy + 32) >> 6;
  911. j = (h * rx) / ry;
  912. k = (i * rx) / ry;
  913. if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h)))
  914. {
  915. xmj = x - j;
  916. xpj = x + j;
  917. if (i > 0)
  918. {
  919. ypi = y + i;
  920. ymi = y - i;
  921. rtgui_dc_draw_point(dc, xmj, ypi);
  922. rtgui_dc_draw_point(dc, xpj, ypi);
  923. rtgui_dc_draw_point(dc, xmj, ymi);
  924. rtgui_dc_draw_point(dc, xpj, ymi);
  925. }
  926. else
  927. {
  928. rtgui_dc_draw_point(dc, xmj, y);
  929. rtgui_dc_draw_point(dc, xpj, y);
  930. }
  931. oi = i;
  932. xmk = x - k;
  933. xpk = x + k;
  934. if (h > 0)
  935. {
  936. yph = y + h;
  937. ymh = y - h;
  938. rtgui_dc_draw_point(dc, xmk, yph);
  939. rtgui_dc_draw_point(dc, xpk, yph);
  940. rtgui_dc_draw_point(dc, xmk, ymh);
  941. rtgui_dc_draw_point(dc, xpk, ymh);
  942. }
  943. else
  944. {
  945. rtgui_dc_draw_point(dc, xmk, y);
  946. rtgui_dc_draw_point(dc, xpk, y);
  947. }
  948. oh = h;
  949. }
  950. ix = ix + iy / ry;
  951. iy = iy - ix / ry;
  952. } while (i > h);
  953. }
  954. }
  955. 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)
  956. {
  957. int ix, iy;
  958. int h, i, j, k;
  959. int oh, oi, oj, ok;
  960. int xmh, xph;
  961. int xmi, xpi;
  962. int xmj, xpj;
  963. int xmk, xpk;
  964. /*
  965. * Special case for rx=0 - draw a vline
  966. */
  967. if (rx == 0)
  968. {
  969. rtgui_dc_draw_vline(dc, x, y - ry, y + ry);
  970. return;
  971. }
  972. /* special case for ry=0 - draw a hline */
  973. if (ry == 0) {
  974. rtgui_dc_draw_hline(dc, x - rx, x + rx, y);
  975. return;
  976. }
  977. /*
  978. * Init vars
  979. */
  980. oh = oi = oj = ok = 0xFFFF;
  981. /*
  982. * Draw
  983. */
  984. if (rx > ry) {
  985. ix = 0;
  986. iy = rx * 64;
  987. do {
  988. h = (ix + 32) >> 6;
  989. i = (iy + 32) >> 6;
  990. j = (h * ry) / rx;
  991. k = (i * ry) / rx;
  992. if ((ok != k) && (oj != k)) {
  993. xph = x + h;
  994. xmh = x - h;
  995. if (k > 0) {
  996. rtgui_dc_draw_hline(dc, xmh, xph, y + k);
  997. rtgui_dc_draw_hline(dc, xmh, xph, y - k);
  998. } else {
  999. rtgui_dc_draw_hline(dc, xmh, xph, y);
  1000. }
  1001. ok = k;
  1002. }
  1003. if ((oj != j) && (ok != j) && (k != j)) {
  1004. xmi = x - i;
  1005. xpi = x + i;
  1006. if (j > 0) {
  1007. rtgui_dc_draw_hline(dc, xmi, xpi, y + j);
  1008. rtgui_dc_draw_hline(dc, xmi, xpi, y - j);
  1009. } else {
  1010. rtgui_dc_draw_hline(dc, xmi, xpi, y);
  1011. }
  1012. oj = j;
  1013. }
  1014. ix = ix + iy / rx;
  1015. iy = iy - ix / rx;
  1016. } while (i > h);
  1017. } else {
  1018. ix = 0;
  1019. iy = ry * 64;
  1020. do {
  1021. h = (ix + 32) >> 6;
  1022. i = (iy + 32) >> 6;
  1023. j = (h * rx) / ry;
  1024. k = (i * rx) / ry;
  1025. if ((oi != i) && (oh != i)) {
  1026. xmj = x - j;
  1027. xpj = x + j;
  1028. if (i > 0) {
  1029. rtgui_dc_draw_hline(dc, xmj, xpj, y + i);
  1030. rtgui_dc_draw_hline(dc, xmj, xpj, y - i);
  1031. } else {
  1032. rtgui_dc_draw_hline(dc, xmj, xpj, y);
  1033. }
  1034. oi = i;
  1035. }
  1036. if ((oh != h) && (oi != h) && (i != h)) {
  1037. xmk = x - k;
  1038. xpk = x + k;
  1039. if (h > 0) {
  1040. rtgui_dc_draw_hline(dc, xmk, xpk, y + h);
  1041. rtgui_dc_draw_hline(dc, xmk, xpk, y - h);
  1042. } else {
  1043. rtgui_dc_draw_hline(dc, xmk, xpk, y);
  1044. }
  1045. oh = h;
  1046. }
  1047. ix = ix + iy / ry;
  1048. iy = iy - ix / ry;
  1049. } while (i > h);
  1050. }
  1051. }
  1052. void rtgui_dc_draw_focus_rect(struct rtgui_dc* dc, rtgui_rect_t* rect)
  1053. {
  1054. int i;
  1055. for (i = rect->x1; i <= rect->x2; i += 2)
  1056. {
  1057. rtgui_dc_draw_point(dc, i, rect->y1);
  1058. rtgui_dc_draw_point(dc, i, rect->y2);
  1059. }
  1060. for (i = rect->y1; i <= rect->y2; i += 2)
  1061. {
  1062. rtgui_dc_draw_point(dc, rect->x1, i);
  1063. rtgui_dc_draw_point(dc, rect->x2, i);
  1064. }
  1065. }
  1066. void rtgui_dc_get_rect(struct rtgui_dc*dc, rtgui_rect_t* rect)
  1067. {
  1068. if (dc != RT_NULL && rect != RT_NULL)
  1069. {
  1070. dc->get_rect(dc, rect);
  1071. }
  1072. }