mi_fllarc.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. /* This file is part of the GNU libxmi package.
  2. Copyright (C) 1985, 1986, 1987, 1988, 1989, X Consortium. For an
  3. associated permission notice, see the accompanying file README-X.
  4. GNU enhancements Copyright (C) 1998, 1999, 2000, 2005, Free Software
  5. Foundation, Inc.
  6. The GNU libxmi package is free software. You may redistribute it
  7. and/or modify it under the terms of the GNU General Public License as
  8. published by the Free Software foundation; either version 2, or (at your
  9. option) any later version.
  10. The GNU libxmi package is distributed in the hope that it will be
  11. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. General Public License for more details.
  14. You should have received a copy of the GNU General Public License along
  15. with the GNU plotutils package; see the file COPYING. If not, write to
  16. the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
  17. Boston, MA 02110-1301, USA. */
  18. /* Original author unknown (Bob Scheifler?).
  19. Hacked by Robert S. Maier, 1998-1999. */
  20. /* This module provides the function miFillArcs_internal(), which fills a
  21. poly-arc. All painting goes through the low-level MI_PAINT_SPANS()
  22. macro. */
  23. #include "sys-defines.h"
  24. #include "extern.h"
  25. #include "xmi.h"
  26. #include "mi_spans.h"
  27. #include "mi_gc.h"
  28. #include "mi_api.h"
  29. #include "mi_fllarc.h"
  30. #define QUADRANT (90 * 64)
  31. #define HALFCIRCLE (180 * 64)
  32. #define QUADRANT3 (270 * 64)
  33. /* trig functions, angle specified in 1/64 degrees */
  34. #define Dsin(d) sin((double)d*(M_PI/11520.0))
  35. #define Dcos(d) cos((double)d*(M_PI/11520.0))
  36. /* internal functions that do painting of pixels */
  37. static void miFillArcSliceD (miPaintedSet *paintedSet, const miGC *pGC, const miArc *arc);
  38. static void miFillArcSliceI (miPaintedSet *paintedSet, const miGC *pGC, const miArc *arc);
  39. static void miFillEllipseD (miPaintedSet *paintedSet, const miGC *pGC, const miArc *arc);
  40. static void miFillEllipseI (miPaintedSet *paintedSet, const miGC *pGC, const miArc *arc);
  41. /* internal functions that don't do painting of pixels */
  42. static void miEllipseAngleToSlope (int angle, unsigned int width, unsigned int height, int *dxp, int *dyp, double *d_dxp, double *d_dyp);
  43. static void miFillArcDSetup (const miArc *arc, miFillArcD *info);
  44. static void miFillArcSetup (const miArc *arc, miFillArc *info);
  45. static void miFillArcSliceSetup (const miGC *pGC, const miArc *arc, miArcSlice *slice);
  46. static void miGetArcEdge (const miArc *arc, miSliceEdge *edge, int k, bool top, bool left);
  47. static void miGetPieEdge (const miArc *arc, int angle, miSliceEdge *edge, bool top, bool left);
  48. static void
  49. miFillArcSetup (const miArc *arc, miFillArc *info)
  50. {
  51. info->y = arc->height >> 1;
  52. info->dy = arc->height & 1;
  53. info->yorg = arc->y + info->y;
  54. info->dx = arc->width & 1;
  55. info->xorg = arc->x + (int)(arc->width >> 1) + info->dx;
  56. info->dx = 1 - info->dx;
  57. if (arc->width == arc->height) /* circular arc */
  58. {
  59. /* (2x - 2xorg)^2 = d^2 - (2y - 2yorg)^2 */
  60. /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */
  61. info->ym = 8;
  62. info->xm = 8;
  63. info->yk = info->y << 3;
  64. if (!info->dx)
  65. {
  66. info->xk = 0;
  67. info->e = -1;
  68. }
  69. else
  70. {
  71. info->y++;
  72. info->yk += 4;
  73. info->xk = -4;
  74. info->e = - (info->y << 3);
  75. }
  76. }
  77. else /* non-circular arc */
  78. {
  79. /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */
  80. /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */
  81. info->ym = (arc->width * arc->width) << 3;
  82. info->xm = (arc->height * arc->height) << 3;
  83. info->yk = info->y * info->ym;
  84. if (!info->dy)
  85. info->yk -= info->ym >> 1;
  86. if (!info->dx)
  87. {
  88. info->xk = 0;
  89. info->e = - (info->xm >> 3);
  90. }
  91. else
  92. {
  93. info->y++;
  94. info->yk += info->ym;
  95. info->xk = -(info->xm >> 1);
  96. info->e = info->xk - info->yk;
  97. }
  98. }
  99. }
  100. static void
  101. miFillArcDSetup (const miArc *arc, miFillArcD *info)
  102. {
  103. /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */
  104. /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */
  105. info->y = arc->height >> 1;
  106. info->dy = arc->height & 1;
  107. info->yorg = arc->y + info->y;
  108. info->dx = arc->width & 1;
  109. info->xorg = arc->x + (int)(arc->width >> 1) + info->dx;
  110. info->dx = 1 - info->dx;
  111. info->ym = ((double)arc->width) * (arc->width * 8);
  112. info->xm = ((double)arc->height) * (arc->height * 8);
  113. info->yk = info->y * info->ym;
  114. if (!info->dy)
  115. info->yk -= (0.5 * info->ym);
  116. if (!info->dx)
  117. {
  118. info->xk = 0;
  119. info->e = - (0.125 * info->xm);
  120. }
  121. else
  122. {
  123. info->y++;
  124. info->yk += info->ym;
  125. info->xk = -0.5 * info->xm;
  126. info->e = info->xk - info->yk;
  127. }
  128. }
  129. static void
  130. miGetArcEdge (const miArc *arc, miSliceEdge *edge, int k, bool top, bool left)
  131. {
  132. int xady, y;
  133. y = arc->height >> 1;
  134. if ((arc->width & 1) == 0)
  135. y++;
  136. if (!top)
  137. {
  138. y = -y;
  139. if (arc->height & 1)
  140. y--;
  141. }
  142. xady = k + y * edge->dx;
  143. if (xady <= 0)
  144. edge->x = - ((-xady) / edge->dy + 1);
  145. else
  146. edge->x = (xady - 1) / edge->dy;
  147. edge->e = xady - edge->x * edge->dy;
  148. if ((top && (edge->dx < 0)) || (!top && (edge->dx > 0)))
  149. edge->e = edge->dy - edge->e + 1;
  150. if (left)
  151. edge->x++;
  152. edge->x += arc->x + (int)(arc->width >> 1);
  153. if (edge->dx > 0)
  154. {
  155. edge->deltax = 1;
  156. edge->stepx = edge->dx / edge->dy;
  157. edge->dx = edge->dx % edge->dy;
  158. }
  159. else
  160. {
  161. edge->deltax = -1;
  162. edge->stepx = - ((-edge->dx) / edge->dy);
  163. edge->dx = (-edge->dx) % edge->dy;
  164. }
  165. if (!top)
  166. {
  167. edge->deltax = -edge->deltax;
  168. edge->stepx = -edge->stepx;
  169. }
  170. }
  171. static void
  172. miEllipseAngleToSlope (int angle, unsigned int width, unsigned int height, int *dxp, int *dyp, double *d_dxp, double *d_dyp)
  173. {
  174. int dx, dy;
  175. double d_dx, d_dy, scale;
  176. bool negative_dx, negative_dy;
  177. switch (angle)
  178. {
  179. case 0:
  180. *dxp = -1;
  181. *dyp = 0;
  182. if (d_dxp)
  183. {
  184. *d_dxp = 0.5 * (int)width;
  185. *d_dyp = 0;
  186. }
  187. break;
  188. case QUADRANT:
  189. *dxp = 0;
  190. *dyp = 1;
  191. if (d_dxp)
  192. {
  193. *d_dxp = 0;
  194. *d_dyp = -0.5 * (int)height;
  195. }
  196. break;
  197. case HALFCIRCLE:
  198. *dxp = 1;
  199. *dyp = 0;
  200. if (d_dxp)
  201. {
  202. *d_dxp = -0.5 * (int)width;
  203. *d_dyp = 0;
  204. }
  205. break;
  206. case QUADRANT3:
  207. *dxp = 0;
  208. *dyp = -1;
  209. if (d_dxp)
  210. {
  211. *d_dxp = 0;
  212. *d_dyp = 0.5 * (int)height;
  213. }
  214. break;
  215. default: /* angle is not 0, 90, 180, or 270 */
  216. d_dx = Dcos(angle) * (int)width;
  217. d_dy = Dsin(angle) * (int)height;
  218. if (d_dxp)
  219. {
  220. *d_dxp = 0.5 * d_dx;
  221. *d_dyp = -0.5 * d_dy;
  222. }
  223. negative_dx = false;
  224. if (d_dx < 0.0)
  225. {
  226. d_dx = -d_dx;
  227. negative_dx = true;
  228. }
  229. negative_dy = false;
  230. if (d_dy < 0.0)
  231. {
  232. d_dy = -d_dy;
  233. negative_dy = true;
  234. }
  235. scale = d_dx;
  236. if (d_dy > d_dx)
  237. scale = d_dy;
  238. dx = IFLOOR((d_dx * 32768) / scale + 0.5);
  239. if (negative_dx)
  240. dx = -dx;
  241. *dxp = dx;
  242. dy = IFLOOR((d_dy * 32768) / scale + 0.5);
  243. if (negative_dy)
  244. dy = -dy;
  245. *dyp = dy;
  246. break;
  247. }
  248. }
  249. static void
  250. miGetPieEdge (const miArc *arc, int angle, miSliceEdge *edge, bool top, bool left)
  251. {
  252. int k;
  253. int dx, dy;
  254. /* why no signdx, signdy? */
  255. miEllipseAngleToSlope (angle, arc->width, arc->height, &dx, &dy, NULL, NULL);
  256. if (dy == 0)
  257. {
  258. edge->x = left ? INT_MIN : INT_MAX;
  259. edge->stepx = 0;
  260. edge->e = 0;
  261. edge->dx = -1;
  262. return;
  263. }
  264. if (dx == 0)
  265. {
  266. edge->x = arc->x + (int)(arc->width >> 1);
  267. if (left && (arc->width & 1))
  268. edge->x++;
  269. else if (!left && !(arc->width & 1))
  270. edge->x--;
  271. edge->stepx = 0;
  272. edge->e = 0;
  273. edge->dx = -1;
  274. return;
  275. }
  276. if (dy < 0)
  277. {
  278. dx = -dx;
  279. dy = -dy;
  280. }
  281. k = (arc->height & 1) ? dx : 0;
  282. if (arc->width & 1)
  283. k += dy;
  284. edge->dx = dx << 1;
  285. edge->dy = dy << 1;
  286. miGetArcEdge (arc, edge, k, top, left);
  287. }
  288. static void
  289. miFillArcSliceSetup (const miGC *pGC, const miArc *arc, miArcSlice *slice)
  290. {
  291. int angle1, angle2;
  292. angle1 = arc->angle1;
  293. if (arc->angle2 < 0)
  294. {
  295. angle2 = angle1;
  296. angle1 += arc->angle2;
  297. }
  298. else
  299. angle2 = angle1 + arc->angle2;
  300. while (angle1 < 0)
  301. angle1 += FULLCIRCLE;
  302. while (angle1 >= FULLCIRCLE)
  303. angle1 -= FULLCIRCLE;
  304. while (angle2 < 0)
  305. angle2 += FULLCIRCLE;
  306. while (angle2 >= FULLCIRCLE)
  307. angle2 -= FULLCIRCLE;
  308. slice->min_top_y = 0;
  309. slice->max_top_y = arc->height >> 1;
  310. slice->min_bot_y = 1 - (arc->height & 1);
  311. slice->max_bot_y = slice->max_top_y - 1;
  312. slice->flip_top = false;
  313. slice->flip_bot = false;
  314. switch (pGC->arcMode)
  315. {
  316. case MI_ARC_CHORD: /* chord filling, not pie slice */
  317. default:
  318. {
  319. double w2, h2, x1, y1, x2, y2, dx, dy, scale;
  320. int signdx, signdy, y, k;
  321. bool isInt1 = true, isInt2 = true;
  322. w2 = 0.5 * (double)arc->width;
  323. h2 = 0.5 * (double)arc->height;
  324. if ((angle1 == 0) || (angle1 == HALFCIRCLE))
  325. {
  326. x1 = angle1 ? -w2 : w2;
  327. y1 = 0.0;
  328. }
  329. else if ((angle1 == QUADRANT) || (angle1 == QUADRANT3))
  330. {
  331. x1 = 0.0;
  332. y1 = (angle1 == QUADRANT) ? h2 : -h2;
  333. }
  334. else
  335. {
  336. isInt1 = false;
  337. x1 = Dcos(angle1) * w2;
  338. y1 = Dsin(angle1) * h2;
  339. }
  340. if ((angle2 == 0) || (angle2 == HALFCIRCLE))
  341. {
  342. x2 = angle2 ? -w2 : w2;
  343. y2 = 0.0;
  344. }
  345. else if ((angle2 == QUADRANT) || (angle2 == QUADRANT3))
  346. {
  347. x2 = 0.0;
  348. y2 = (angle2 == QUADRANT) ? h2 : -h2;
  349. }
  350. else
  351. {
  352. isInt2 = false;
  353. x2 = Dcos(angle2) * w2;
  354. y2 = Dsin(angle2) * h2;
  355. }
  356. dx = x2 - x1;
  357. dy = y2 - y1;
  358. if (arc->height & 1)
  359. {
  360. y1 -= 0.5;
  361. y2 -= 0.5;
  362. }
  363. if (arc->width & 1)
  364. {
  365. x1 += 0.5;
  366. x2 += 0.5;
  367. }
  368. if (dy < 0.0)
  369. {
  370. dy = -dy;
  371. signdy = -1;
  372. }
  373. else
  374. signdy = 1;
  375. if (dx < 0.0)
  376. {
  377. dx = -dx;
  378. signdx = -1;
  379. }
  380. else
  381. signdx = 1;
  382. if (isInt1 && isInt2)
  383. {
  384. slice->edge1.dx = (int)(dx * 2);
  385. slice->edge1.dy = (int)(dy * 2);
  386. }
  387. else
  388. {
  389. scale = (dx > dy) ? dx : dy;
  390. slice->edge1.dx = IFLOOR((dx * 32768) / scale + .5);
  391. slice->edge1.dy = IFLOOR((dy * 32768) / scale + .5);
  392. }
  393. if (!slice->edge1.dy)
  394. {
  395. if (signdx < 0)
  396. {
  397. y = IFLOOR(y1 + 1.0);
  398. if (y >= 0)
  399. {
  400. slice->min_top_y = y;
  401. slice->min_bot_y = arc->height;
  402. }
  403. else
  404. {
  405. slice->max_bot_y = -y - (arc->height & 1);
  406. }
  407. }
  408. else
  409. {
  410. y = IFLOOR(y1);
  411. if (y >= 0)
  412. slice->max_top_y = y;
  413. else
  414. {
  415. slice->min_top_y = arc->height;
  416. slice->min_bot_y = -y - (arc->height & 1);
  417. }
  418. }
  419. slice->edge1_top = true;
  420. slice->edge1.x = INT_MAX;
  421. slice->edge1.stepx = 0;
  422. slice->edge1.e = 0;
  423. slice->edge1.dx = -1;
  424. slice->edge2 = slice->edge1;
  425. slice->edge2_top = false;
  426. }
  427. else if (!slice->edge1.dx)
  428. {
  429. if (signdy < 0)
  430. x1 -= 1.0;
  431. slice->edge1.x = ICEIL(x1);
  432. slice->edge1_top = (signdy < 0 ? true : false);
  433. slice->edge1.x += arc->x + (int)(arc->width >> 1);
  434. slice->edge1.stepx = 0;
  435. slice->edge1.e = 0;
  436. slice->edge1.dx = -1;
  437. slice->edge2_top = (slice->edge1_top ? false : true);
  438. slice->edge2 = slice->edge1;
  439. }
  440. else
  441. {
  442. if (signdx < 0)
  443. slice->edge1.dx = -slice->edge1.dx;
  444. if (signdy < 0)
  445. slice->edge1.dx = -slice->edge1.dx;
  446. k = ICEIL(((x1 + x2) * slice->edge1.dy - (y1 + y2) * slice->edge1.dx) / 2.0);
  447. slice->edge2.dx = slice->edge1.dx;
  448. slice->edge2.dy = slice->edge1.dy;
  449. slice->edge1_top = (signdy < 0 ? true : false);
  450. slice->edge2_top = (slice->edge1_top ? false : true);
  451. miGetArcEdge(arc, &slice->edge1, k,
  452. slice->edge1_top, (slice->edge1_top ? false : true));
  453. miGetArcEdge(arc, &slice->edge2, k,
  454. slice->edge2_top, slice->edge2_top);
  455. }
  456. }
  457. break;
  458. case MI_ARC_PIE_SLICE: /* pie slice filling, not chord */
  459. slice->edge1_top = (angle1 < HALFCIRCLE ? true : false);
  460. slice->edge2_top = (angle2 <= HALFCIRCLE ? true : false);
  461. if ((angle2 == 0) || (angle1 == HALFCIRCLE))
  462. {
  463. if (angle2 ? slice->edge2_top : slice->edge1_top)
  464. slice->min_top_y = slice->min_bot_y;
  465. else
  466. slice->min_top_y = arc->height;
  467. slice->min_bot_y = 0;
  468. }
  469. else if ((angle1 == 0) || (angle2 == HALFCIRCLE))
  470. {
  471. slice->min_top_y = slice->min_bot_y;
  472. if (angle1 ? slice->edge1_top : slice->edge2_top)
  473. slice->min_bot_y = (int)arc->height;
  474. else
  475. slice->min_bot_y = 0;
  476. }
  477. else if (slice->edge1_top == slice->edge2_top)
  478. {
  479. if (angle2 < angle1)
  480. {
  481. slice->flip_top = slice->edge1_top;
  482. slice->flip_bot = (slice->edge1_top ? false : true);
  483. }
  484. else if (slice->edge1_top)
  485. {
  486. slice->min_top_y = 1;
  487. slice->min_bot_y = (int)arc->height;
  488. }
  489. else
  490. {
  491. slice->min_bot_y = 0;
  492. slice->min_top_y = (int)arc->height;
  493. }
  494. }
  495. miGetPieEdge(arc, angle1, &slice->edge1,
  496. slice->edge1_top, (slice->edge1_top ? false : true));
  497. miGetPieEdge(arc, angle2, &slice->edge2,
  498. slice->edge2_top, slice->edge2_top);
  499. break;
  500. }
  501. }
  502. #define ADDSPANS(pts_upper, pts_lower, wids_upper, wids_lower, x, y, slw, e, xk, xorg, yorg, dy) \
  503. pts_upper->x = xorg - x; \
  504. pts_upper->y = yorg - y; \
  505. *wids_upper = (unsigned int)slw; \
  506. pts_upper++; \
  507. wids_upper++; \
  508. if (MIFILLARCLOWER(e, xk, y, dy, slw)) \
  509. { \
  510. pts_lower->x = xorg - x; \
  511. pts_lower->y = yorg + y + dy; \
  512. pts_lower--; \
  513. *wids_lower-- = (unsigned int)slw; \
  514. }
  515. static void
  516. miFillEllipseI (miPaintedSet *paintedSet, const miGC *pGC, const miArc *arc)
  517. {
  518. int x, y, e;
  519. int yk, xk, ym, xm, dx, dy, xorg, yorg;
  520. int slw;
  521. miFillArc info;
  522. miPoint *points_upper, *points_lower, *pts_upper, *pts_lower;
  523. unsigned int *widths_upper, *widths_lower, *wids_upper, *wids_lower;
  524. int numUpperSpans, numLowerSpans;
  525. points_upper = (miPoint *)mi_xmalloc (sizeof(miPoint) * arc->height);
  526. widths_upper = (unsigned int *)mi_xmalloc (sizeof(unsigned int) * arc->height);
  527. pts_upper = points_upper;
  528. wids_upper = widths_upper;
  529. points_lower = (miPoint *)mi_xmalloc (sizeof(miPoint) * arc->height);
  530. widths_lower = (unsigned int *)mi_xmalloc (sizeof(unsigned int) * arc->height);
  531. pts_lower = points_lower + (arc->height - 1); /* begin at end, will decr */
  532. wids_lower = widths_lower + (arc->height - 1);
  533. miFillArcSetup(arc, &info);
  534. MIFILLARCSETUP(info, x, y, e, xk, xm, yk, ym, dx, dy, xorg, yorg);
  535. while (y > 0)
  536. /* add an upper and maybe a lower span (resp. growing downward, upward) */
  537. {
  538. MIFILLARCSTEP(x, y, e, xk, xm, yk, ym, dx, slw); /* y-- */
  539. ADDSPANS(pts_upper, pts_lower, wids_upper, wids_lower, x, y, slw, e, xk, xorg, yorg, dy);
  540. }
  541. numUpperSpans = pts_upper - points_upper;
  542. numLowerSpans = points_lower + (arc->height - 1) - pts_lower;
  543. if (numUpperSpans > 0)
  544. MI_PAINT_SPANS(paintedSet, pGC->pixels[1], numUpperSpans, points_upper, widths_upper)
  545. if (numLowerSpans > 0)
  546. MI_COPY_AND_PAINT_SPANS(paintedSet, pGC->pixels[1], numLowerSpans, pts_lower + 1, wids_lower + 1)
  547. free (points_lower);
  548. free (widths_lower);
  549. }
  550. static void
  551. miFillEllipseD (miPaintedSet *paintedSet, const miGC *pGC, const miArc *arc)
  552. {
  553. int x, y;
  554. int xorg, yorg, dx, dy, slw;
  555. double e, yk, xk, ym, xm;
  556. miFillArcD info;
  557. miPoint *points_upper, *points_lower, *pts_upper, *pts_lower;
  558. unsigned int *widths_upper, *widths_lower, *wids_upper, *wids_lower;
  559. int numUpperSpans, numLowerSpans;
  560. points_upper = (miPoint *)mi_xmalloc (sizeof(miPoint) * arc->height);
  561. widths_upper = (unsigned int *)mi_xmalloc (sizeof(unsigned int) * arc->height);
  562. pts_upper = points_upper;
  563. wids_upper = widths_upper;
  564. points_lower = (miPoint *)mi_xmalloc (sizeof(miPoint) * arc->height);
  565. widths_lower = (unsigned int *)mi_xmalloc (sizeof(unsigned int) * arc->height);
  566. pts_lower = points_lower + (arc->height - 1); /* begin at end, will decr */
  567. wids_lower = widths_lower + (arc->height - 1);
  568. miFillArcDSetup(arc, &info);
  569. MIFILLARCSETUP(info, x, y, e, xk, xm, yk, ym, dx, dy, xorg, yorg);
  570. while (y > 0)
  571. /* add an upper and maybe a lower span (resp. growing downward, upward) */
  572. {
  573. MIFILLARCSTEP(x, y, e, xk, xm, yk, ym, dx, slw); /* y-- */
  574. ADDSPANS(pts_upper, pts_lower, wids_upper, wids_lower, x, y, slw, e, xk, xorg, yorg, dy);
  575. }
  576. numUpperSpans = pts_upper - points_upper;
  577. numLowerSpans = points_lower + (arc->height - 1) - pts_lower;
  578. if (numUpperSpans > 0)
  579. MI_PAINT_SPANS(paintedSet, pGC->pixels[1], numUpperSpans, points_upper, widths_upper)
  580. if (numLowerSpans > 0)
  581. MI_COPY_AND_PAINT_SPANS(paintedSet, pGC->pixels[1], numLowerSpans, pts_lower + 1, wids_lower + 1)
  582. free (points_lower);
  583. free (widths_lower);
  584. }
  585. #define ADDSPAN(pts, wids, lower, l, r, ya) \
  586. if (r >= l) \
  587. { \
  588. pts->x = l; \
  589. pts->y = ya; \
  590. *wids = (unsigned int)(r - l + 1); \
  591. if (lower) \
  592. { pts--; wids--; } \
  593. else \
  594. { pts++; wids++; } \
  595. }
  596. #define ADDSLICESPANS(pts, wids, lower, xl, xr, xorg, ya, flip) \
  597. if (!flip) \
  598. { \
  599. ADDSPAN(pts, wids, lower, xl, xr, ya) \
  600. } \
  601. else \
  602. { \
  603. int xc; \
  604. xc = xorg - x; \
  605. ADDSPAN(pts, wids, lower, xc, xr, ya) \
  606. xc += (slw - 1); \
  607. ADDSPAN(pts, wids, lower, xl, xc, ya) \
  608. }
  609. static void
  610. miFillArcSliceI (miPaintedSet *paintedSet, const miGC *pGC, const miArc *arc)
  611. {
  612. int yk, xk, ym, xm, dx, dy, xorg, yorg, slw, orig_slw;
  613. int x, y, e;
  614. miFillArc info;
  615. miArcSlice slice;
  616. int ya, xl, xr;
  617. miPoint *points_upper, *points_lower, *pts_upper, *pts_lower;
  618. unsigned int *widths_upper, *widths_lower, *wids_upper, *wids_lower;
  619. int numUpperSpans, numLowerSpans;
  620. miFillArcSetup (arc, &info);
  621. miFillArcSliceSetup (pGC, arc, &slice);
  622. MIFILLARCSETUP(info, x, y, e, xk, xm, yk, ym, dx, dy, xorg, yorg);
  623. slw = (int)arc->height;
  624. if (slice.flip_top || slice.flip_bot)
  625. slw += (int)(arc->height >> 1) + 1;
  626. orig_slw = slw;
  627. points_upper = (miPoint *)mi_xmalloc (sizeof(miPoint) * slw);
  628. widths_upper = (unsigned int *)mi_xmalloc (sizeof(unsigned int) * slw);
  629. pts_upper = points_upper;
  630. wids_upper = widths_upper;
  631. points_lower = (miPoint *)mi_xmalloc (sizeof(miPoint) * slw);
  632. widths_lower = (unsigned int *)mi_xmalloc (sizeof(unsigned int) * slw);
  633. pts_lower = points_lower + (slw - 1); /* begin at end, will decrement */
  634. wids_lower = widths_lower + (slw - 1);
  635. while (y > 0)
  636. {
  637. MIFILLARCSTEP(x, y, e, xk, xm, yk, ym, dx, slw); /* y-- */
  638. MIARCSLICESTEP(slice.edge1);
  639. MIARCSLICESTEP(slice.edge2);
  640. if (MIFILLSLICEUPPER(y, slice))
  641. /* add an `upper' span (growing downward) */
  642. {
  643. bool lower = false;
  644. ya = yorg - y;
  645. MIARCSLICEUPPER(xl, xr, slice, slw)
  646. ADDSLICESPANS(pts_upper, wids_upper, lower, xl, xr, xorg, ya, slice.flip_top)
  647. }
  648. if (MIFILLSLICELOWER(y, slice))
  649. /* add a `lower' span (growing upward) */
  650. {
  651. bool lower = true;
  652. ya = yorg + y + dy;
  653. MIARCSLICELOWER(xl, xr, slice, slw)
  654. ADDSLICESPANS(pts_lower, wids_lower, lower, xl, xr, xorg, ya, slice.flip_bot)
  655. }
  656. }
  657. numUpperSpans = pts_upper - points_upper;
  658. numLowerSpans = points_lower + (orig_slw - 1) - pts_lower;
  659. if (numUpperSpans > 0)
  660. MI_PAINT_SPANS(paintedSet, pGC->pixels[1], numUpperSpans, points_upper, widths_upper)
  661. if (numLowerSpans > 0)
  662. MI_COPY_AND_PAINT_SPANS(paintedSet, pGC->pixels[1], numLowerSpans, pts_lower + 1, wids_lower + 1)
  663. free (points_lower);
  664. free (widths_lower);
  665. }
  666. static void
  667. miFillArcSliceD (miPaintedSet *paintedSet, const miGC *pGC, const miArc *arc)
  668. {
  669. int x, y;
  670. int dx, dy, xorg, yorg, slw, orig_slw;
  671. double e, yk, xk, ym, xm;
  672. miFillArcD info;
  673. miArcSlice slice;
  674. int ya, xl, xr;
  675. miPoint *points_upper, *points_lower, *pts_upper, *pts_lower;
  676. unsigned int *widths_upper, *widths_lower, *wids_upper, *wids_lower;
  677. int numUpperSpans, numLowerSpans;
  678. miFillArcDSetup (arc, &info);
  679. miFillArcSliceSetup (pGC, arc, &slice);
  680. MIFILLARCSETUP(info, x, y, e, xk, xm, yk, ym, dx, dy, xorg, yorg);
  681. slw = (int)arc->height;
  682. if (slice.flip_top || slice.flip_bot)
  683. slw += (int)(arc->height >> 1) + 1;
  684. orig_slw = slw;
  685. points_upper = (miPoint *)mi_xmalloc (sizeof(miPoint) * slw);
  686. widths_upper = (unsigned int *)mi_xmalloc (sizeof(unsigned int) * slw);
  687. pts_upper = points_upper;
  688. wids_upper = widths_upper;
  689. points_lower = (miPoint *)mi_xmalloc (sizeof(miPoint) * slw);
  690. widths_lower = (unsigned int *)mi_xmalloc (sizeof(unsigned int) * slw);
  691. pts_lower = points_lower + (slw - 1); /* begin at end, will decrement */
  692. wids_lower = widths_lower + (slw - 1);
  693. while (y > 0)
  694. {
  695. MIFILLARCSTEP(x, y, e, xk, xm, yk, ym, dx, slw); /* y-- */
  696. MIARCSLICESTEP(slice.edge1);
  697. MIARCSLICESTEP(slice.edge2);
  698. if (MIFILLSLICEUPPER(y, slice))
  699. /* add an `upper' span (growing downward) */
  700. {
  701. bool lower = false;
  702. ya = yorg - y;
  703. MIARCSLICEUPPER(xl, xr, slice, slw)
  704. ADDSLICESPANS(pts_upper, wids_upper, lower, xl, xr, xorg, ya, slice.flip_top)
  705. }
  706. if (MIFILLSLICELOWER(y, slice))
  707. /* add a `lower' span (growing upward) */
  708. {
  709. bool lower = true;
  710. ya = yorg + y + dy;
  711. MIARCSLICELOWER(xl, xr, slice, slw)
  712. ADDSLICESPANS(pts_lower, wids_lower, lower, xl, xr, xorg, ya, slice.flip_bot)
  713. }
  714. }
  715. numUpperSpans = pts_upper - points_upper;
  716. numLowerSpans = points_lower + (orig_slw - 1) - pts_lower;
  717. if (numUpperSpans > 0)
  718. MI_PAINT_SPANS(paintedSet, pGC->pixels[1], numUpperSpans, points_upper, widths_upper)
  719. if (numLowerSpans > 0)
  720. MI_COPY_AND_PAINT_SPANS(paintedSet, pGC->pixels[1], numLowerSpans, pts_lower + 1, wids_lower + 1)
  721. free (points_lower);
  722. free (widths_lower);
  723. }
  724. void
  725. miFillArcs_internal (miPaintedSet *paintedSet, const miGC *pGC, int narcs, const miArc *parcs)
  726. {
  727. int i;
  728. const miArc *arc;
  729. for (i = narcs, arc = parcs; --i >= 0; arc++)
  730. {
  731. if (MI_FILLED_ARC_IS_EMPTY(arc))
  732. continue;
  733. if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE))
  734. {
  735. if (MI_CAN_FILL_ARC(arc))
  736. /* circle; or width, height <= 800 */
  737. miFillEllipseI (paintedSet, pGC, arc);
  738. else
  739. miFillEllipseD (paintedSet, pGC, arc);
  740. }
  741. else
  742. {
  743. if (MI_CAN_FILL_ARC(arc))
  744. /* circle; or width, height <= 800 */
  745. miFillArcSliceI (paintedSet, pGC, arc);
  746. else
  747. miFillArcSliceD (paintedSet, pGC, arc);
  748. }
  749. }
  750. }