1
0

dc.c 35 KB

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