Draw.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187
  1. /*
  2. * The Python Imaging Library.
  3. * $Id$
  4. *
  5. * a simple drawing package for the Imaging library
  6. *
  7. * history:
  8. * 1996-04-13 fl Created.
  9. * 1996-04-30 fl Added transforms and polygon support.
  10. * 1996-08-12 fl Added filled polygons.
  11. * 1996-11-05 fl Fixed float/int confusion in polygon filler
  12. * 1997-07-04 fl Support 32-bit images (C++ would have been nice)
  13. * 1998-09-09 fl Eliminated qsort casts; improved rectangle clipping
  14. * 1998-09-10 fl Fixed fill rectangle to include lower edge (!)
  15. * 1998-12-29 fl Added arc, chord, and pieslice primitives
  16. * 1999-01-10 fl Added some level 2 ("arrow") stuff (experimental)
  17. * 1999-02-06 fl Added bitmap primitive
  18. * 1999-07-26 fl Eliminated a compiler warning
  19. * 1999-07-31 fl Pass ink as void* instead of int
  20. * 2002-12-10 fl Added experimental RGBA-on-RGB drawing
  21. * 2004-09-04 fl Support simple wide lines (no joins)
  22. * 2005-05-25 fl Fixed line width calculation
  23. *
  24. * Copyright (c) 1996-2006 by Fredrik Lundh
  25. * Copyright (c) 1997-2006 by Secret Labs AB.
  26. *
  27. * See the README file for information on usage and redistribution.
  28. */
  29. /* FIXME: support fill/outline attribute for all filled shapes */
  30. /* FIXME: support zero-winding fill */
  31. /* FIXME: add drawing context, support affine transforms */
  32. /* FIXME: support clip window (and mask?) */
  33. #include "Imaging.h"
  34. #include <math.h>
  35. #define CEIL(v) (int) ceil(v)
  36. #define FLOOR(v) ((v) >= 0.0 ? (int) (v) : (int) floor(v))
  37. #define INK8(ink) (*(UINT8*)ink)
  38. /*
  39. * Rounds around zero (up=away from zero, down=torwards zero)
  40. * This guarantees that ROUND_UP|DOWN(f) == -ROUND_UP|DOWN(-f)
  41. */
  42. #define ROUND_UP(f) ((int) ((f) >= 0.0 ? floor((f) + 0.5F) : -floor(fabs(f) + 0.5F)))
  43. #define ROUND_DOWN(f) ((int) ((f) >= 0.0 ? ceil((f) - 0.5F) : -ceil(fabs(f) - 0.5F)))
  44. /* -------------------------------------------------------------------- */
  45. /* Primitives */
  46. /* -------------------------------------------------------------------- */
  47. typedef struct {
  48. /* edge descriptor for polygon engine */
  49. int d;
  50. int x0, y0;
  51. int xmin, ymin, xmax, ymax;
  52. float dx;
  53. } Edge;
  54. /* Type used in "polygon*" functions */
  55. typedef void (*hline_handler)(Imaging, int, int, int, int);
  56. static inline void
  57. point8(Imaging im, int x, int y, int ink)
  58. {
  59. if (x >= 0 && x < im->xsize && y >= 0 && y < im->ysize) {
  60. if (strncmp(im->mode, "I;16", 4) == 0) {
  61. im->image8[y][x*2] = (UINT8) ink;
  62. im->image8[y][x*2+1] = (UINT8) ink;
  63. } else {
  64. im->image8[y][x] = (UINT8) ink;
  65. }
  66. }
  67. }
  68. static inline void
  69. point32(Imaging im, int x, int y, int ink)
  70. {
  71. if (x >= 0 && x < im->xsize && y >= 0 && y < im->ysize)
  72. im->image32[y][x] = ink;
  73. }
  74. static inline void
  75. point32rgba(Imaging im, int x, int y, int ink)
  76. {
  77. unsigned int tmp1;
  78. if (x >= 0 && x < im->xsize && y >= 0 && y < im->ysize) {
  79. UINT8* out = (UINT8*) im->image[y]+x*4;
  80. UINT8* in = (UINT8*) &ink;
  81. out[0] = BLEND(in[3], out[0], in[0], tmp1);
  82. out[1] = BLEND(in[3], out[1], in[1], tmp1);
  83. out[2] = BLEND(in[3], out[2], in[2], tmp1);
  84. }
  85. }
  86. static inline void
  87. hline8(Imaging im, int x0, int y0, int x1, int ink)
  88. {
  89. int tmp, pixelwidth;
  90. if (y0 >= 0 && y0 < im->ysize) {
  91. if (x0 > x1)
  92. tmp = x0, x0 = x1, x1 = tmp;
  93. if (x0 < 0)
  94. x0 = 0;
  95. else if (x0 >= im->xsize)
  96. return;
  97. if (x1 < 0)
  98. return;
  99. else if (x1 >= im->xsize)
  100. x1 = im->xsize-1;
  101. if (x0 <= x1) {
  102. pixelwidth = strncmp(im->mode, "I;16", 4) == 0 ? 2 : 1;
  103. memset(im->image8[y0] + x0 * pixelwidth, (UINT8) ink,
  104. (x1 - x0 + 1) * pixelwidth);
  105. }
  106. }
  107. }
  108. static inline void
  109. hline32(Imaging im, int x0, int y0, int x1, int ink)
  110. {
  111. int tmp;
  112. INT32* p;
  113. if (y0 >= 0 && y0 < im->ysize) {
  114. if (x0 > x1)
  115. tmp = x0, x0 = x1, x1 = tmp;
  116. if (x0 < 0)
  117. x0 = 0;
  118. else if (x0 >= im->xsize)
  119. return;
  120. if (x1 < 0)
  121. return;
  122. else if (x1 >= im->xsize)
  123. x1 = im->xsize-1;
  124. p = im->image32[y0];
  125. while (x0 <= x1)
  126. p[x0++] = ink;
  127. }
  128. }
  129. static inline void
  130. hline32rgba(Imaging im, int x0, int y0, int x1, int ink)
  131. {
  132. int tmp;
  133. unsigned int tmp1;
  134. if (y0 >= 0 && y0 < im->ysize) {
  135. if (x0 > x1)
  136. tmp = x0, x0 = x1, x1 = tmp;
  137. if (x0 < 0)
  138. x0 = 0;
  139. else if (x0 >= im->xsize)
  140. return;
  141. if (x1 < 0)
  142. return;
  143. else if (x1 >= im->xsize)
  144. x1 = im->xsize-1;
  145. if (x0 <= x1) {
  146. UINT8* out = (UINT8*) im->image[y0]+x0*4;
  147. UINT8* in = (UINT8*) &ink;
  148. while (x0 <= x1) {
  149. out[0] = BLEND(in[3], out[0], in[0], tmp1);
  150. out[1] = BLEND(in[3], out[1], in[1], tmp1);
  151. out[2] = BLEND(in[3], out[2], in[2], tmp1);
  152. x0++; out += 4;
  153. }
  154. }
  155. }
  156. }
  157. static inline void
  158. line8(Imaging im, int x0, int y0, int x1, int y1, int ink)
  159. {
  160. int i, n, e;
  161. int dx, dy;
  162. int xs, ys;
  163. /* normalize coordinates */
  164. dx = x1-x0;
  165. if (dx < 0)
  166. dx = -dx, xs = -1;
  167. else
  168. xs = 1;
  169. dy = y1-y0;
  170. if (dy < 0)
  171. dy = -dy, ys = -1;
  172. else
  173. ys = 1;
  174. n = (dx > dy) ? dx : dy;
  175. if (dx == 0)
  176. /* vertical */
  177. for (i = 0; i < dy; i++) {
  178. point8(im, x0, y0, ink);
  179. y0 += ys;
  180. }
  181. else if (dy == 0)
  182. /* horizontal */
  183. for (i = 0; i < dx; i++) {
  184. point8(im, x0, y0, ink);
  185. x0 += xs;
  186. }
  187. else if (dx > dy) {
  188. /* bresenham, horizontal slope */
  189. n = dx;
  190. dy += dy;
  191. e = dy - dx;
  192. dx += dx;
  193. for (i = 0; i < n; i++) {
  194. point8(im, x0, y0, ink);
  195. if (e >= 0) {
  196. y0 += ys;
  197. e -= dx;
  198. }
  199. e += dy;
  200. x0 += xs;
  201. }
  202. } else {
  203. /* bresenham, vertical slope */
  204. n = dy;
  205. dx += dx;
  206. e = dx - dy;
  207. dy += dy;
  208. for (i = 0; i < n; i++) {
  209. point8(im, x0, y0, ink);
  210. if (e >= 0) {
  211. x0 += xs;
  212. e -= dy;
  213. }
  214. e += dx;
  215. y0 += ys;
  216. }
  217. }
  218. }
  219. static inline void
  220. line32(Imaging im, int x0, int y0, int x1, int y1, int ink)
  221. {
  222. int i, n, e;
  223. int dx, dy;
  224. int xs, ys;
  225. /* normalize coordinates */
  226. dx = x1-x0;
  227. if (dx < 0)
  228. dx = -dx, xs = -1;
  229. else
  230. xs = 1;
  231. dy = y1-y0;
  232. if (dy < 0)
  233. dy = -dy, ys = -1;
  234. else
  235. ys = 1;
  236. n = (dx > dy) ? dx : dy;
  237. if (dx == 0)
  238. /* vertical */
  239. for (i = 0; i < dy; i++) {
  240. point32(im, x0, y0, ink);
  241. y0 += ys;
  242. }
  243. else if (dy == 0)
  244. /* horizontal */
  245. for (i = 0; i < dx; i++) {
  246. point32(im, x0, y0, ink);
  247. x0 += xs;
  248. }
  249. else if (dx > dy) {
  250. /* bresenham, horizontal slope */
  251. n = dx;
  252. dy += dy;
  253. e = dy - dx;
  254. dx += dx;
  255. for (i = 0; i < n; i++) {
  256. point32(im, x0, y0, ink);
  257. if (e >= 0) {
  258. y0 += ys;
  259. e -= dx;
  260. }
  261. e += dy;
  262. x0 += xs;
  263. }
  264. } else {
  265. /* bresenham, vertical slope */
  266. n = dy;
  267. dx += dx;
  268. e = dx - dy;
  269. dy += dy;
  270. for (i = 0; i < n; i++) {
  271. point32(im, x0, y0, ink);
  272. if (e >= 0) {
  273. x0 += xs;
  274. e -= dy;
  275. }
  276. e += dx;
  277. y0 += ys;
  278. }
  279. }
  280. }
  281. static inline void
  282. line32rgba(Imaging im, int x0, int y0, int x1, int y1, int ink)
  283. {
  284. int i, n, e;
  285. int dx, dy;
  286. int xs, ys;
  287. /* normalize coordinates */
  288. dx = x1-x0;
  289. if (dx < 0)
  290. dx = -dx, xs = -1;
  291. else
  292. xs = 1;
  293. dy = y1-y0;
  294. if (dy < 0)
  295. dy = -dy, ys = -1;
  296. else
  297. ys = 1;
  298. n = (dx > dy) ? dx : dy;
  299. if (dx == 0)
  300. /* vertical */
  301. for (i = 0; i < dy; i++) {
  302. point32rgba(im, x0, y0, ink);
  303. y0 += ys;
  304. }
  305. else if (dy == 0)
  306. /* horizontal */
  307. for (i = 0; i < dx; i++) {
  308. point32rgba(im, x0, y0, ink);
  309. x0 += xs;
  310. }
  311. else if (dx > dy) {
  312. /* bresenham, horizontal slope */
  313. n = dx;
  314. dy += dy;
  315. e = dy - dx;
  316. dx += dx;
  317. for (i = 0; i < n; i++) {
  318. point32rgba(im, x0, y0, ink);
  319. if (e >= 0) {
  320. y0 += ys;
  321. e -= dx;
  322. }
  323. e += dy;
  324. x0 += xs;
  325. }
  326. } else {
  327. /* bresenham, vertical slope */
  328. n = dy;
  329. dx += dx;
  330. e = dx - dy;
  331. dy += dy;
  332. for (i = 0; i < n; i++) {
  333. point32rgba(im, x0, y0, ink);
  334. if (e >= 0) {
  335. x0 += xs;
  336. e -= dy;
  337. }
  338. e += dx;
  339. y0 += ys;
  340. }
  341. }
  342. }
  343. static int
  344. x_cmp(const void *x0, const void *x1)
  345. {
  346. float diff = *((float*)x0) - *((float*)x1);
  347. if (diff < 0)
  348. return -1;
  349. else if (diff > 0)
  350. return 1;
  351. else
  352. return 0;
  353. }
  354. /*
  355. * Filled polygon draw function using scan line algorithm.
  356. */
  357. static inline int
  358. polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill,
  359. hline_handler hline)
  360. {
  361. Edge** edge_table;
  362. float* xx;
  363. int edge_count = 0;
  364. int ymin = im->ysize - 1;
  365. int ymax = 0;
  366. int i;
  367. if (n <= 0) {
  368. return 0;
  369. }
  370. /* Initialize the edge table and find polygon boundaries */
  371. /* malloc check ok, using calloc */
  372. edge_table = calloc(n, sizeof(Edge*));
  373. if (!edge_table) {
  374. return -1;
  375. }
  376. for (i = 0; i < n; i++) {
  377. /* This causes the pixels of horizontal edges to be drawn twice :(
  378. * but without it there are inconsistencies in ellipses */
  379. if (e[i].ymin == e[i].ymax) {
  380. (*hline)(im, e[i].xmin, e[i].ymin, e[i].xmax, ink);
  381. continue;
  382. }
  383. if (ymin > e[i].ymin) {
  384. ymin = e[i].ymin;
  385. }
  386. if (ymax < e[i].ymax) {
  387. ymax = e[i].ymax;
  388. }
  389. edge_table[edge_count++] = (e + i);
  390. }
  391. if (ymin < 0) {
  392. ymin = 0;
  393. }
  394. if (ymax > im->ysize) {
  395. ymax = im->ysize;
  396. }
  397. /* Process the edge table with a scan line searching for intersections */
  398. /* malloc check ok, using calloc */
  399. xx = calloc(edge_count * 2, sizeof(float));
  400. if (!xx) {
  401. free(edge_table);
  402. return -1;
  403. }
  404. for (; ymin <= ymax; ymin++) {
  405. int j = 0;
  406. for (i = 0; i < edge_count; i++) {
  407. Edge* current = edge_table[i];
  408. if (ymin >= current->ymin && ymin <= current->ymax) {
  409. xx[j++] = (ymin - current->y0) * current->dx + current->x0;
  410. }
  411. /* Needed to draw consistent polygons */
  412. if (ymin == current->ymax && ymin < ymax) {
  413. xx[j] = xx[j - 1];
  414. j++;
  415. }
  416. }
  417. qsort(xx, j, sizeof(float), x_cmp);
  418. for (i = 1; i < j; i += 2) {
  419. (*hline)(im, ROUND_UP(xx[i - 1]), ymin, ROUND_DOWN(xx[i]), ink);
  420. }
  421. }
  422. free(xx);
  423. free(edge_table);
  424. return 0;
  425. }
  426. static inline int
  427. polygon8(Imaging im, int n, Edge *e, int ink, int eofill)
  428. {
  429. return polygon_generic(im, n, e, ink, eofill, hline8);
  430. }
  431. static inline int
  432. polygon32(Imaging im, int n, Edge *e, int ink, int eofill)
  433. {
  434. return polygon_generic(im, n, e, ink, eofill, hline32);
  435. }
  436. static inline int
  437. polygon32rgba(Imaging im, int n, Edge *e, int ink, int eofill)
  438. {
  439. return polygon_generic(im, n, e, ink, eofill, hline32rgba);
  440. }
  441. static inline void
  442. add_edge(Edge *e, int x0, int y0, int x1, int y1)
  443. {
  444. /* printf("edge %d %d %d %d\n", x0, y0, x1, y1); */
  445. if (x0 <= x1)
  446. e->xmin = x0, e->xmax = x1;
  447. else
  448. e->xmin = x1, e->xmax = x0;
  449. if (y0 <= y1)
  450. e->ymin = y0, e->ymax = y1;
  451. else
  452. e->ymin = y1, e->ymax = y0;
  453. if (y0 == y1) {
  454. e->d = 0;
  455. e->dx = 0.0;
  456. } else {
  457. e->dx = ((float)(x1-x0)) / (y1-y0);
  458. if (y0 == e->ymin)
  459. e->d = 1;
  460. else
  461. e->d = -1;
  462. }
  463. e->x0 = x0;
  464. e->y0 = y0;
  465. }
  466. typedef struct {
  467. void (*point)(Imaging im, int x, int y, int ink);
  468. void (*hline)(Imaging im, int x0, int y0, int x1, int ink);
  469. void (*line)(Imaging im, int x0, int y0, int x1, int y1, int ink);
  470. int (*polygon)(Imaging im, int n, Edge *e, int ink, int eofill);
  471. } DRAW;
  472. DRAW draw8 = { point8, hline8, line8, polygon8 };
  473. DRAW draw32 = { point32, hline32, line32, polygon32 };
  474. DRAW draw32rgba = { point32rgba, hline32rgba, line32rgba, polygon32rgba };
  475. /* -------------------------------------------------------------------- */
  476. /* Interface */
  477. /* -------------------------------------------------------------------- */
  478. #define DRAWINIT()\
  479. if (im->image8) {\
  480. draw = &draw8;\
  481. ink = INK8(ink_);\
  482. } else {\
  483. draw = (op) ? &draw32rgba : &draw32; \
  484. memcpy(&ink, ink_, sizeof(ink)); \
  485. }
  486. int
  487. ImagingDrawPoint(Imaging im, int x0, int y0, const void* ink_, int op)
  488. {
  489. DRAW* draw;
  490. INT32 ink;
  491. DRAWINIT();
  492. draw->point(im, x0, y0, ink);
  493. return 0;
  494. }
  495. int
  496. ImagingDrawLine(Imaging im, int x0, int y0, int x1, int y1, const void* ink_,
  497. int op)
  498. {
  499. DRAW* draw;
  500. INT32 ink;
  501. DRAWINIT();
  502. draw->line(im, x0, y0, x1, y1, ink);
  503. return 0;
  504. }
  505. int
  506. ImagingDrawWideLine(Imaging im, int x0, int y0, int x1, int y1,
  507. const void* ink_, int width, int op)
  508. {
  509. DRAW* draw;
  510. INT32 ink;
  511. int dx, dy;
  512. double big_hypotenuse, small_hypotenuse, ratio_max, ratio_min;
  513. int dxmin, dxmax, dymin, dymax;
  514. Edge e[4];
  515. DRAWINIT();
  516. dx = x1-x0;
  517. dy = y1-y0;
  518. if (dx == 0 && dy == 0) {
  519. draw->point(im, x0, y0, ink);
  520. return 0;
  521. }
  522. big_hypotenuse = sqrt((double) (dx*dx + dy*dy));
  523. small_hypotenuse = (width - 1) / 2.0;
  524. ratio_max = ROUND_UP(small_hypotenuse) / big_hypotenuse;
  525. ratio_min = ROUND_DOWN(small_hypotenuse) / big_hypotenuse;
  526. dxmin = ROUND_DOWN(ratio_min * dy);
  527. dxmax = ROUND_DOWN(ratio_max * dy);
  528. dymin = ROUND_DOWN(ratio_min * dx);
  529. dymax = ROUND_DOWN(ratio_max * dx);
  530. {
  531. int vertices[4][2] = {
  532. {x0 - dxmin, y0 + dymax},
  533. {x1 - dxmin, y1 + dymax},
  534. {x1 + dxmax, y1 - dymin},
  535. {x0 + dxmax, y0 - dymin}
  536. };
  537. add_edge(e+0, vertices[0][0], vertices[0][1], vertices[1][0], vertices[1][1]);
  538. add_edge(e+1, vertices[1][0], vertices[1][1], vertices[2][0], vertices[2][1]);
  539. add_edge(e+2, vertices[2][0], vertices[2][1], vertices[3][0], vertices[3][1]);
  540. add_edge(e+3, vertices[3][0], vertices[3][1], vertices[0][0], vertices[0][1]);
  541. draw->polygon(im, 4, e, ink, 0);
  542. }
  543. return 0;
  544. }
  545. int
  546. ImagingDrawRectangle(Imaging im, int x0, int y0, int x1, int y1,
  547. const void* ink_, int fill, int width, int op)
  548. {
  549. int i;
  550. int y;
  551. int tmp;
  552. DRAW* draw;
  553. INT32 ink;
  554. DRAWINIT();
  555. if (y0 > y1)
  556. tmp = y0, y0 = y1, y1 = tmp;
  557. if (fill) {
  558. if (y0 < 0)
  559. y0 = 0;
  560. else if (y0 >= im->ysize)
  561. return 0;
  562. if (y1 < 0)
  563. return 0;
  564. else if (y1 > im->ysize)
  565. y1 = im->ysize;
  566. for (y = y0; y <= y1; y++)
  567. draw->hline(im, x0, y, x1, ink);
  568. } else {
  569. /* outline */
  570. if (width == 0) {
  571. width = 1;
  572. }
  573. for (i = 0; i < width; i++) {
  574. draw->hline(im, x0, y0+i, x1, ink);
  575. draw->hline(im, x0, y1-i, x1, ink);
  576. draw->line(im, x1-i, y0, x1-i, y1, ink);
  577. draw->line(im, x0+i, y1, x0+i, y0, ink);
  578. }
  579. }
  580. return 0;
  581. }
  582. int
  583. ImagingDrawPolygon(Imaging im, int count, int* xy, const void* ink_,
  584. int fill, int op)
  585. {
  586. int i, n;
  587. DRAW* draw;
  588. INT32 ink;
  589. if (count <= 0)
  590. return 0;
  591. DRAWINIT();
  592. if (fill) {
  593. /* Build edge list */
  594. /* malloc check ok, using calloc */
  595. Edge* e = calloc(count, sizeof(Edge));
  596. if (!e) {
  597. (void) ImagingError_MemoryError();
  598. return -1;
  599. }
  600. for (i = n = 0; i < count-1; i++)
  601. add_edge(&e[n++], xy[i+i], xy[i+i+1], xy[i+i+2], xy[i+i+3]);
  602. if (xy[i+i] != xy[0] || xy[i+i+1] != xy[1])
  603. add_edge(&e[n++], xy[i+i], xy[i+i+1], xy[0], xy[1]);
  604. draw->polygon(im, n, e, ink, 0);
  605. free(e);
  606. } else {
  607. /* Outline */
  608. for (i = 0; i < count-1; i++)
  609. draw->line(im, xy[i+i], xy[i+i+1], xy[i+i+2], xy[i+i+3], ink);
  610. draw->line(im, xy[i+i], xy[i+i+1], xy[0], xy[1], ink);
  611. }
  612. return 0;
  613. }
  614. int
  615. ImagingDrawBitmap(Imaging im, int x0, int y0, Imaging bitmap, const void* ink,
  616. int op)
  617. {
  618. return ImagingFill2(
  619. im, ink, bitmap,
  620. x0, y0, x0 + bitmap->xsize, y0 + bitmap->ysize
  621. );
  622. }
  623. /* -------------------------------------------------------------------- */
  624. /* standard shapes */
  625. #define ARC 0
  626. #define CHORD 1
  627. #define PIESLICE 2
  628. static void
  629. ellipsePoint(int cx, int cy, int w, int h,
  630. float i, int *x, int *y)
  631. {
  632. float i_cos, i_sin;
  633. float x_f, y_f;
  634. double modf_int;
  635. i_cos = cos(i*M_PI/180);
  636. i_sin = sin(i*M_PI/180);
  637. x_f = (i_cos * w/2) + cx;
  638. y_f = (i_sin * h/2) + cy;
  639. if (modf(x_f, &modf_int) == 0.5) {
  640. *x = i_cos > 0 ? FLOOR(x_f) : CEIL(x_f);
  641. } else {
  642. *x = FLOOR(x_f + 0.5);
  643. }
  644. if (modf(y_f, &modf_int) == 0.5) {
  645. *y = i_sin > 0 ? FLOOR(y_f) : CEIL(y_f);
  646. } else {
  647. *y = FLOOR(y_f + 0.5);
  648. }
  649. }
  650. static int
  651. ellipse(Imaging im, int x0, int y0, int x1, int y1,
  652. float start, float end, const void* ink_, int fill,
  653. int width, int mode, int op)
  654. {
  655. float i;
  656. int inner;
  657. int n;
  658. int maxEdgeCount;
  659. int w, h;
  660. int x, y;
  661. int cx, cy;
  662. int lx = 0, ly = 0;
  663. int sx = 0, sy = 0;
  664. int lx_inner = 0, ly_inner = 0;
  665. int sx_inner = 0, sy_inner = 0;
  666. DRAW* draw;
  667. INT32 ink;
  668. Edge* e;
  669. DRAWINIT();
  670. while (end < start)
  671. end += 360;
  672. if (end - start > 360) {
  673. // no need to go in loops
  674. end = start + 361;
  675. }
  676. w = x1 - x0;
  677. h = y1 - y0;
  678. if (w <= 0 || h <= 0)
  679. return 0;
  680. cx = (x0 + x1) / 2;
  681. cy = (y0 + y1) / 2;
  682. if (!fill && width <= 1) {
  683. for (i = start; i < end+1; i++) {
  684. if (i > end) {
  685. i = end;
  686. }
  687. ellipsePoint(cx, cy, w, h, i, &x, &y);
  688. if (i != start)
  689. draw->line(im, lx, ly, x, y, ink);
  690. else
  691. sx = x, sy = y;
  692. lx = x, ly = y;
  693. }
  694. if (i != start) {
  695. if (mode == PIESLICE) {
  696. if (x != cx || y != cy) {
  697. draw->line(im, x, y, cx, cy, ink);
  698. draw->line(im, cx, cy, sx, sy, ink);
  699. }
  700. } else if (mode == CHORD) {
  701. if (x != sx || y != sy)
  702. draw->line(im, x, y, sx, sy, ink);
  703. }
  704. }
  705. } else {
  706. inner = (mode == ARC || !fill) ? 1 : 0;
  707. // Build edge list
  708. // malloc check UNDONE, FLOAT?
  709. maxEdgeCount = ceil(end - start);
  710. if (inner) {
  711. maxEdgeCount *= 2;
  712. }
  713. maxEdgeCount += 3;
  714. e = calloc(maxEdgeCount, sizeof(Edge));
  715. if (!e) {
  716. ImagingError_MemoryError();
  717. return -1;
  718. }
  719. // Outer circle
  720. n = 0;
  721. for (i = start; i < end+1; i++) {
  722. if (i > end) {
  723. i = end;
  724. }
  725. ellipsePoint(cx, cy, w, h, i, &x, &y);
  726. if (i == start) {
  727. sx = x, sy = y;
  728. } else {
  729. add_edge(&e[n++], lx, ly, x, y);
  730. }
  731. lx = x, ly = y;
  732. }
  733. if (n == 0)
  734. return 0;
  735. if (inner) {
  736. // Inner circle
  737. x0 += width - 1;
  738. y0 += width - 1;
  739. x1 -= width - 1;
  740. y1 -= width - 1;
  741. w = x1 - x0;
  742. h = y1 - y0;
  743. if (w <= 0 || h <= 0) {
  744. // ARC with no gap in the middle is a PIESLICE
  745. mode = PIESLICE;
  746. inner = 0;
  747. } else {
  748. for (i = start; i < end+1; i++) {
  749. if (i > end) {
  750. i = end;
  751. }
  752. ellipsePoint(cx, cy, w, h, i, &x, &y);
  753. if (i == start)
  754. sx_inner = x, sy_inner = y;
  755. else
  756. add_edge(&e[n++], lx_inner, ly_inner, x, y);
  757. lx_inner = x, ly_inner = y;
  758. }
  759. }
  760. }
  761. if (end - start < 360) {
  762. // Close polygon
  763. if (mode == PIESLICE) {
  764. if (x != cx || y != cy) {
  765. add_edge(&e[n++], sx, sy, cx, cy);
  766. add_edge(&e[n++], cx, cy, lx, ly);
  767. if (inner) {
  768. ImagingDrawWideLine(im, sx, sy, cx, cy, &ink, width, op);
  769. ImagingDrawWideLine(im, cx, cy, lx, ly, &ink, width, op);
  770. }
  771. }
  772. } else if (mode == CHORD) {
  773. add_edge(&e[n++], sx, sy, lx, ly);
  774. if (inner) {
  775. add_edge(&e[n++], sx_inner, sy_inner, lx_inner, ly_inner);
  776. }
  777. } else if (mode == ARC) {
  778. add_edge(&e[n++], sx, sy, sx_inner, sy_inner);
  779. add_edge(&e[n++], lx, ly, lx_inner, ly_inner);
  780. }
  781. }
  782. draw->polygon(im, n, e, ink, 0);
  783. free(e);
  784. }
  785. return 0;
  786. }
  787. int
  788. ImagingDrawArc(Imaging im, int x0, int y0, int x1, int y1,
  789. float start, float end, const void* ink, int width, int op)
  790. {
  791. return ellipse(im, x0, y0, x1, y1, start, end, ink, 0, width, ARC, op);
  792. }
  793. int
  794. ImagingDrawChord(Imaging im, int x0, int y0, int x1, int y1,
  795. float start, float end, const void* ink, int fill,
  796. int width, int op)
  797. {
  798. return ellipse(im, x0, y0, x1, y1, start, end, ink, fill, width, CHORD, op);
  799. }
  800. int
  801. ImagingDrawEllipse(Imaging im, int x0, int y0, int x1, int y1,
  802. const void* ink, int fill, int width, int op)
  803. {
  804. return ellipse(im, x0, y0, x1, y1, 0, 360, ink, fill, width, CHORD, op);
  805. }
  806. int
  807. ImagingDrawPieslice(Imaging im, int x0, int y0, int x1, int y1,
  808. float start, float end, const void* ink, int fill,
  809. int width, int op)
  810. {
  811. return ellipse(im, x0, y0, x1, y1, start, end, ink, fill, width, PIESLICE, op);
  812. }
  813. /* -------------------------------------------------------------------- */
  814. /* experimental level 2 ("arrow") graphics stuff. this implements
  815. portions of the arrow api on top of the Edge structure. the
  816. semantics are ok, except that "curve" flattens the bezier curves by
  817. itself */
  818. struct ImagingOutlineInstance {
  819. float x0, y0;
  820. float x, y;
  821. int count;
  822. Edge *edges;
  823. int size;
  824. };
  825. ImagingOutline
  826. ImagingOutlineNew(void)
  827. {
  828. ImagingOutline outline;
  829. outline = calloc(1, sizeof(struct ImagingOutlineInstance));
  830. if (!outline)
  831. return (ImagingOutline) ImagingError_MemoryError();
  832. outline->edges = NULL;
  833. outline->count = outline->size = 0;
  834. ImagingOutlineMove(outline, 0, 0);
  835. return outline;
  836. }
  837. void
  838. ImagingOutlineDelete(ImagingOutline outline)
  839. {
  840. if (!outline)
  841. return;
  842. if (outline->edges)
  843. free(outline->edges);
  844. free(outline);
  845. }
  846. static Edge*
  847. allocate(ImagingOutline outline, int extra)
  848. {
  849. Edge* e;
  850. if (outline->count + extra > outline->size) {
  851. /* expand outline buffer */
  852. outline->size += extra + 25;
  853. if (!outline->edges) {
  854. /* malloc check ok, uses calloc for overflow */
  855. e = calloc(outline->size, sizeof(Edge));
  856. } else {
  857. if (outline->size > INT_MAX / sizeof(Edge)) {
  858. return NULL;
  859. }
  860. /* malloc check ok, overflow checked above */
  861. e = realloc(outline->edges, outline->size * sizeof(Edge));
  862. }
  863. if (!e)
  864. return NULL;
  865. outline->edges = e;
  866. }
  867. e = outline->edges + outline->count;
  868. outline->count += extra;
  869. return e;
  870. }
  871. int
  872. ImagingOutlineMove(ImagingOutline outline, float x0, float y0)
  873. {
  874. outline->x = outline->x0 = x0;
  875. outline->y = outline->y0 = y0;
  876. return 0;
  877. }
  878. int
  879. ImagingOutlineLine(ImagingOutline outline, float x1, float y1)
  880. {
  881. Edge* e;
  882. e = allocate(outline, 1);
  883. if (!e)
  884. return -1; /* out of memory */
  885. add_edge(e, (int) outline->x, (int) outline->y, (int) x1, (int) y1);
  886. outline->x = x1;
  887. outline->y = y1;
  888. return 0;
  889. }
  890. int
  891. ImagingOutlineCurve(ImagingOutline outline, float x1, float y1,
  892. float x2, float y2, float x3, float y3)
  893. {
  894. Edge* e;
  895. int i;
  896. float xo, yo;
  897. #define STEPS 32
  898. e = allocate(outline, STEPS);
  899. if (!e)
  900. return -1; /* out of memory */
  901. xo = outline->x;
  902. yo = outline->y;
  903. /* flatten the bezier segment */
  904. for (i = 1; i <= STEPS; i++) {
  905. float t = ((float) i) / STEPS;
  906. float t2 = t*t;
  907. float t3 = t2*t;
  908. float u = 1.0F - t;
  909. float u2 = u*u;
  910. float u3 = u2*u;
  911. float x = outline->x*u3 + 3*(x1*t*u2 + x2*t2*u) + x3*t3 + 0.5;
  912. float y = outline->y*u3 + 3*(y1*t*u2 + y2*t2*u) + y3*t3 + 0.5;
  913. add_edge(e++, xo, yo, (int) x, (int) y);
  914. xo = x, yo = y;
  915. }
  916. outline->x = xo;
  917. outline->y = yo;
  918. return 0;
  919. }
  920. int
  921. ImagingOutlineClose(ImagingOutline outline)
  922. {
  923. if (outline->x == outline->x0 && outline->y == outline->y0)
  924. return 0;
  925. return ImagingOutlineLine(outline, outline->x0, outline->y0);
  926. }
  927. int
  928. ImagingOutlineTransform(ImagingOutline outline, double a[6])
  929. {
  930. Edge *eIn;
  931. Edge *eOut;
  932. int i, n;
  933. int x0, y0, x1, y1;
  934. int X0, Y0, X1, Y1;
  935. double a0 = a[0]; double a1 = a[1]; double a2 = a[2];
  936. double a3 = a[3]; double a4 = a[4]; double a5 = a[5];
  937. eIn = outline->edges;
  938. n = outline->count;
  939. /* FIXME: ugly! */
  940. outline->edges = NULL;
  941. outline->count = outline->size = 0;
  942. eOut = allocate(outline, n);
  943. if (!eOut) {
  944. outline->edges = eIn;
  945. outline->count = outline->size = n;
  946. ImagingError_MemoryError();
  947. return -1;
  948. }
  949. for (i = 0; i < n; i++) {
  950. x0 = eIn->x0;
  951. y0 = eIn->y0;
  952. /* FIXME: ouch! */
  953. if (eIn->x0 == eIn->xmin)
  954. x1 = eIn->xmax;
  955. else
  956. x1 = eIn->xmin;
  957. if (eIn->y0 == eIn->ymin)
  958. y1 = eIn->ymax;
  959. else
  960. y1 = eIn->ymin;
  961. /* full moon tonight! if this doesn't work, you may need to
  962. upgrade your compiler (make sure you have the right service
  963. pack) */
  964. X0 = (int) (a0*x0 + a1*y0 + a2);
  965. Y0 = (int) (a3*x0 + a4*y0 + a5);
  966. X1 = (int) (a0*x1 + a1*y1 + a2);
  967. Y1 = (int) (a3*x1 + a4*y1 + a5);
  968. add_edge(eOut, X0, Y0, X1, Y1);
  969. eIn++;
  970. eOut++;
  971. }
  972. free(eIn);
  973. return 0;
  974. }
  975. int
  976. ImagingDrawOutline(Imaging im, ImagingOutline outline, const void* ink_,
  977. int fill, int op)
  978. {
  979. DRAW* draw;
  980. INT32 ink;
  981. DRAWINIT();
  982. draw->polygon(im, outline->count, outline->edges, ink, 0);
  983. return 0;
  984. }