PageRenderTime 50ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/rel-1.3.35/Examples/GIFPlot/Lib/frame.c

#
C | 924 lines | 590 code | 152 blank | 182 comment | 141 complexity | 4e4111073b69a40b55b9b82b914347ab MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
  1. /* -----------------------------------------------------------------------------
  2. * frame.c
  3. *
  4. * Frame buffer management
  5. *
  6. * Author(s) : David Beazley (beazley@cs.uchicago.edu)
  7. * Copyright (C) 1995-1996
  8. *
  9. * See the file LICENSE for information on usage and redistribution.
  10. * ----------------------------------------------------------------------------- */
  11. #define FRAME
  12. #include "gifplot.h"
  13. #include <float.h>
  14. /* ------------------------------------------------------------------------
  15. FrameBuffer *new_FrameBuffer(int width, int height)
  16. Creates a new framebuffer for storing data.
  17. ------------------------------------------------------------------------ */
  18. FrameBuffer *new_FrameBuffer(unsigned int width, unsigned int height) {
  19. FrameBuffer *f;
  20. int FrameBuffer_resize(FrameBuffer *f, int width, int height);
  21. /* Create a new frame buffer */
  22. f = (FrameBuffer *) malloc(sizeof(FrameBuffer));
  23. f->pixels = (Pixel **) 0;
  24. f->zbuffer = (Zvalue **) 0;
  25. /* Set its size */
  26. if (FrameBuffer_resize(f, width, height) == -1) {
  27. free((char *) f);
  28. return (FrameBuffer *) 0;
  29. }
  30. f->xmin = 0;
  31. f->ymin = 0;
  32. f->xmax = width;
  33. f->ymax = height;
  34. return f;
  35. }
  36. /* ------------------------------------------------------------------------
  37. void delete_FrameBuffer(FrameBuffer *f)
  38. Destroys the given framebuffer
  39. ------------------------------------------------------------------------ */
  40. void delete_FrameBuffer(FrameBuffer *f) {
  41. if (f) {
  42. if (f->pixels) {
  43. free((char *) f->pixels[0]);
  44. free((char *) f->pixels);
  45. }
  46. if (f->zbuffer) {
  47. free((char *) f->zbuffer[0]);
  48. free((char *) f->zbuffer);
  49. }
  50. free((char *)f);
  51. }
  52. }
  53. /* ------------------------------------------------------------------------
  54. int *FrameBuffer_resize(FrameBuffer *f, int width, int height)
  55. Resize the given framebuffer. Returns 0 on success, -1 on failure.
  56. ------------------------------------------------------------------------ */
  57. int FrameBuffer_resize(FrameBuffer *f, int width, int height) {
  58. int i;
  59. if ((f) && (width > 0) && (height > 0)) {
  60. if (f->pixels) {
  61. free((char *)f->pixels[0]);
  62. free((char *)f->pixels);
  63. }
  64. f->pixels = (Pixel **) malloc (height*sizeof(Pixel *));
  65. if (!f->pixels) return -1;
  66. f->pixels[0] = (Pixel *) malloc(height*width*sizeof(Pixel));
  67. if (!f->pixels[0]) {
  68. free((char *)f->pixels);
  69. return -1;
  70. }
  71. for (i = 0; i < height; i++)
  72. f->pixels[i] = f->pixels[0] + i*width;
  73. f->width = width;
  74. f->height = height;
  75. if (f->zbuffer) {
  76. FrameBuffer_zresize(f,width,height);
  77. }
  78. return 0;
  79. } else {
  80. return -1;
  81. }
  82. }
  83. /* ------------------------------------------------------------------------
  84. void FrameBuffer_clear(FrameBuffer *f, Pixel color)
  85. Clears the current FrameBuffer
  86. ------------------------------------------------------------------------ */
  87. void FrameBuffer_clear(FrameBuffer *f, Pixel color) {
  88. Pixel *p;
  89. unsigned int i;
  90. p = &f->pixels[0][0];
  91. for (i = 0; i < f->width*f->height; i++, p++)
  92. *p = color;
  93. }
  94. /* ------------------------------------------------------------------------
  95. void FrameBuffer_plot(FrameBuffer *f, int x1, int y1, Pixel color)
  96. Plots a point and does a bounds check.
  97. ------------------------------------------------------------------------ */
  98. void FrameBuffer_plot(FrameBuffer *f, int x1, int y1, Pixel color) {
  99. if ((x1 < f->xmin) || (x1 >= f->xmax) || (y1 < f->ymin) || (y1 >= f->ymax))
  100. return;
  101. f->pixels[y1][x1] = color;
  102. }
  103. /* ------------------------------------------------------------------------
  104. FrameBuffer_horizontal(Framebuffer *f, int xmin, int xmax, int y, Pixel color)
  105. Draw a horizontal line (clipped)
  106. ------------------------------------------------------------------------ */
  107. void FrameBuffer_horizontal(FrameBuffer *f, int xmin, int xmax, int y, Pixel color) {
  108. Pixel *p;
  109. int i;
  110. if ((y < f->ymin) || (y >= f->ymax)) return;
  111. if (xmin < f->xmin) xmin = f->xmin;
  112. if (xmax >= f->xmax) xmax = f->xmax - 1;
  113. p = &f->pixels[y][xmin];
  114. for (i = xmin; i <= xmax; i++, p++)
  115. *p = color;
  116. }
  117. /* ------------------------------------------------------------------------
  118. FrameBuffer_horizontalinterp(Framebuffer *f, int xmin, int xmax, int y,
  119. Pixel c1, Pixel c2)
  120. Draw a horizontal line (clipped) with color interpolation.
  121. ------------------------------------------------------------------------ */
  122. void FrameBuffer_horizontalinterp(FrameBuffer *f, int xmin, int xmax, int y,
  123. Pixel c1, Pixel c2) {
  124. Pixel *p;
  125. int i;
  126. double mc;
  127. int x1;
  128. if ((y < f->ymin) || (y >= f->ymax)) return;
  129. x1 = xmin;
  130. if (xmin < f->xmin) xmin = f->xmin;
  131. if (xmax >= f->xmax) xmax = f->xmax - 1;
  132. if (xmax < f->xmin) return;
  133. if (xmin >= f->xmax) return;
  134. if (xmin != xmax)
  135. mc = (double)(c2 - c1)/(double) (xmax - xmin);
  136. else
  137. mc = 0.0;
  138. p = &f->pixels[y][xmin];
  139. for (i = xmin; i <= xmax; i++, p++)
  140. *p = (Pixel) (mc*(i-x1) + c1);
  141. }
  142. /* ------------------------------------------------------------------------
  143. FrameBuffer_vertical(Framebuffer *f, int xmin, int xmax, int y, Pixel color)
  144. Draw a Vertical line (clipped)
  145. ------------------------------------------------------------------------ */
  146. void FrameBuffer_vertical(FrameBuffer *f, int ymin, int ymax, int x, Pixel color) {
  147. Pixel *p;
  148. int i;
  149. if ((x < f->xmin) || (x >= f->xmax)) return;
  150. if (ymax < f->ymin) return;
  151. if (ymin > f->ymax) return;
  152. if (ymin < f->ymin) ymin = f->ymin;
  153. if (ymax >= f->ymax) ymax = f->ymax - 1;
  154. p = &f->pixels[ymin][x];
  155. for (i = 0; i <= (ymax - ymin); i++, p+=f->width)
  156. *p = color;
  157. }
  158. /* ------------------------------------------------------------------------
  159. void FrameBuffer_box(FrameBuffer *f, int x1, int y1, int x2, int y2, Pixel color)
  160. Makes an outline box.
  161. ------------------------------------------------------------------------ */
  162. void FrameBuffer_box(FrameBuffer *f, int x1, int y1, int x2, int y2, Pixel color) {
  163. int xt, yt;
  164. /* Make sure points are in correct order */
  165. if (x2 < x1) {
  166. xt = x2;
  167. x2 = x1;
  168. x1 = xt;
  169. }
  170. if (y2 < y1) {
  171. yt = y2;
  172. y2 = y1;
  173. y1 = yt;
  174. }
  175. /* Draw lower edge */
  176. FrameBuffer_horizontal(f,x1,x2,y1,color);
  177. /* Draw upper edge */
  178. FrameBuffer_horizontal(f,x1,x2,y2,color);
  179. /* Draw left side */
  180. FrameBuffer_vertical(f,y1,y2,x1,color);
  181. /* Draw right side */
  182. FrameBuffer_vertical(f,y1,y2,x2,color);
  183. }
  184. /* ------------------------------------------------------------------------
  185. void FrameBuffer_solidbox(FrameBuffer *f, int x1, int y1, int x2, int y2, Pixel color)
  186. Makes an solid box.
  187. ------------------------------------------------------------------------ */
  188. void FrameBuffer_solidbox(FrameBuffer *f, int x1, int y1, int x2, int y2, Pixel color) {
  189. int xt, yt;
  190. /* Make sure points are in correct order */
  191. if (x2 < x1) {
  192. xt = x2;
  193. x2 = x1;
  194. x1 = xt;
  195. }
  196. if (y2 < y1) {
  197. yt = y2;
  198. y2 = y1;
  199. y1 = yt;
  200. }
  201. /* Now perform some clipping */
  202. if (y1 < f->ymin) y1 = f->ymin;
  203. if (y2 >= f->ymax) y2 = f->ymax - 1;
  204. /* Fill it in using horizontal lines */
  205. for (yt = y1; yt <= y2; yt++)
  206. FrameBuffer_horizontal(f,x1,x2,yt,color);
  207. }
  208. /* ------------------------------------------------------------------------
  209. void FrameBuffer_interpbox(FrameBuffer *f, int x1, int y1, int x2, int y2
  210. Pixel c1, Pixel c2, Pixel c3, Pixel c4)
  211. Makes a box with interpolated color. Colors are assigned as follows :
  212. (x1,y1) = c1
  213. (x1,y2) = c2
  214. (x2,y1) = c3
  215. (x2,y2) = c4
  216. ------------------------------------------------------------------------ */
  217. void FrameBuffer_interpbox(FrameBuffer *f, int x1, int y1, int x2, int y2,
  218. Pixel c1, Pixel c2, Pixel c3, Pixel c4) {
  219. int xt, yt;
  220. Pixel ct;
  221. double mc1,mc2;
  222. int ystart;
  223. /* Make sure points are in correct order */
  224. if (x2 < x1) {
  225. xt = x2;
  226. x2 = x1;
  227. x1 = xt;
  228. ct = c1;
  229. c1 = c3;
  230. c3 = ct;
  231. ct = c2;
  232. c2 = c4;
  233. c4 = ct;
  234. }
  235. if (y2 < y1) {
  236. yt = y2;
  237. y2 = y1;
  238. y1 = yt;
  239. ct = c1;
  240. c1 = c2;
  241. c2 = ct;
  242. ct = c3;
  243. c3 = c4;
  244. c4 = ct;
  245. }
  246. /* Now perform some clipping */
  247. ystart = y1;
  248. mc1 = (double) (c2 - c1)/(double) (y2 - y1);
  249. mc2 = (double) (c4 - c3)/(double) (y2 - y1);
  250. if (y1 < f->ymin) y1 = f->ymin;
  251. if (y2 >= f->ymax) y2 = f->ymax - 1;
  252. /* Fill it in using horizontal lines */
  253. for (yt = y1; yt <= y2; yt++)
  254. FrameBuffer_horizontalinterp(f,x1,x2,yt,(Pixel) ((mc1*(yt - ystart)) + c1),
  255. (Pixel) ((mc2*(yt-ystart))+c3));
  256. }
  257. /* ---------------------------------------------------------------------------
  258. FrameBuffer_line(FrameBuffer *f, int x1, int y1, int x2, int y2, color)
  259. Draws a line on the framebuffer using the Bresenham line algorithm. The
  260. line is clipped to fit within the current view window.
  261. ---------------------------------------------------------------------------- */
  262. void FrameBuffer_line(FrameBuffer *f, int x1, int y1, int x2, int y2, Pixel c) {
  263. int dx,dy,dxneg,dyneg, inc1,inc2,di;
  264. int x, y, xpixels, ypixels, xt, yt;
  265. Pixel *p;
  266. double m;
  267. int end1 = 0, end2 = 0;
  268. /* Need to figure out where in the heck this line is */
  269. dx = x2 - x1;
  270. dy = y2 - y1;
  271. if (dx == 0) {
  272. /* Draw a Vertical Line */
  273. if (y1 < y2)
  274. FrameBuffer_vertical(f,y1,y2,x1,c);
  275. else
  276. FrameBuffer_vertical(f,y2,y1,x1,c);
  277. return;
  278. }
  279. if (dy == 0) {
  280. /* Draw a Horizontal Line */
  281. if (x1 < x2)
  282. FrameBuffer_horizontal(f,x1,x2,y1,c);
  283. else
  284. FrameBuffer_horizontal(f,x2,x1,y1,c);
  285. return;
  286. }
  287. /* Figure out where in the heck these lines are using the
  288. Cohen-Sutherland Line Clipping Scheme. */
  289. end1 = ((x1 - f->xmin) < 0) |
  290. (((f->xmax- 1 - x1) < 0) << 1) |
  291. (((y1 - f->ymin) < 0) << 2) |
  292. (((f->ymax-1 - y1) < 0) << 3);
  293. end2 = ((x2 - f->xmin) < 0) |
  294. (((f->xmax-1 - x2) < 0) << 1) |
  295. (((y2 - f->ymin) < 0) << 2) |
  296. (((f->ymax-1 - y2) < 0) << 3);
  297. if (end1 & end2) return; /* Nope : Not visible */
  298. /* Make sure points have a favorable orientation */
  299. if (x1 > x2) {
  300. xt = x1;
  301. x1 = x2;
  302. x2 = xt;
  303. yt = y1;
  304. y1 = y2;
  305. y2 = yt;
  306. }
  307. /* Clip against the boundaries */
  308. m = (y2 - y1)/(double) (x2-x1);
  309. if (x1 < f->xmin) {
  310. y1 = (int) ((f->xmin - x1)*m + y1);
  311. x1 = (int) f->xmin;
  312. }
  313. if (x2 >= f->xmax) {
  314. y2 = (int) ((f->xmax -1 -x1)*m + y1);
  315. x2 = (int) (f->xmax - 1);
  316. }
  317. if (y1 > y2) {
  318. xt = x1;
  319. x1 = x2;
  320. x2 = xt;
  321. yt = y1;
  322. y1 = y2;
  323. y2 = yt;
  324. }
  325. m = 1/m;
  326. if (y1 < f->ymin) {
  327. x1 = (int) ((f->ymin - y1)*m + x1);
  328. y1 = (int) f->ymin;
  329. }
  330. if (y2 >= f->ymax) {
  331. x2 = (int) ((f->ymax-1-y1)*m + x1);
  332. y2 = (int) (f->ymax-1);
  333. }
  334. if ((x1 < f->xmin) || (x1 >= f->xmax) || (y1 < f->ymin) || (y1 >= f->ymax) ||
  335. (x2 < f->xmin) || (x2 >= f->xmax) || (y2 < f->ymin) || (y2 >= f->ymax)) return;
  336. dx = x2 - x1;
  337. dy = y2 - y1;
  338. xpixels = f->width;
  339. ypixels = f->height;
  340. dxneg = (dx < 0) ? 1 : 0;
  341. dyneg = (dy < 0) ? 1 : 0;
  342. dx = abs(dx);
  343. dy = abs(dy);
  344. if (dx >= dy) {
  345. /* Slope between -1 and 1. */
  346. if (dxneg) {
  347. x = x1;
  348. y = y1;
  349. x1 = x2;
  350. y1 = y2;
  351. x2 = x;
  352. y2 = y;
  353. dyneg = !dyneg;
  354. }
  355. inc1 = 2*dy;
  356. inc2 = 2*(dy-dx);
  357. di = 2*dy-dx;
  358. /* Draw a line using x as independent variable */
  359. p = &f->pixels[y1][x1];
  360. x = x1;
  361. while (x <= x2) {
  362. *(p++) = c;
  363. if (di < 0) {
  364. di = di + inc1;
  365. } else {
  366. if (dyneg) {
  367. p = p - xpixels;
  368. di = di + inc2;
  369. } else {
  370. p = p + xpixels;
  371. di = di + inc2;
  372. }
  373. }
  374. x++;
  375. }
  376. } else {
  377. /* Slope < -1 or > 1 */
  378. if (dyneg) {
  379. x = x1;
  380. y = y1;
  381. x1 = x2;
  382. y1 = y2;
  383. x2 = x;
  384. y2 = y;
  385. dxneg = !dxneg;
  386. }
  387. inc1 = 2*dx;
  388. inc2 = 2*(dx-dy);
  389. di = 2*dx-dy;
  390. /* Draw a line using y as independent variable */
  391. p = &f->pixels[y1][x1];
  392. y = y1;
  393. while (y <= y2) {
  394. *p = c;
  395. p = p + xpixels;
  396. if (di < 0) {
  397. di = di + inc1;
  398. } else {
  399. if (dxneg) {
  400. p = p - 1;
  401. di = di + inc2;
  402. } else {
  403. p = p + 1;
  404. di = di + inc2;
  405. }
  406. }
  407. y++;
  408. }
  409. }
  410. }
  411. /* -------------------------------------------------------------------------
  412. FrameBuffer_circle(FrameBuffer f, int xc, int yc, int radius, Pixel c)
  413. Create an outline circle
  414. ------------------------------------------------------------------------- */
  415. #define plot_circle(x,y,c) \
  416. if ((x >= xmin) && (x < xmax) && \
  417. (y >= ymin) && (y < ymax)) \
  418. pixels[y][x] = c;
  419. void FrameBuffer_circle(FrameBuffer *f, int xc, int yc, int radius, Pixel c) {
  420. int xpixels, ypixels, x, y, p;
  421. int xmin, ymin, xmax, ymax;
  422. Pixel **pixels;
  423. if (radius <= 0) return;
  424. xpixels = f->width;
  425. ypixels = f->height;
  426. pixels = f->pixels;
  427. xmin = f->xmin;
  428. ymin = f->ymin;
  429. xmax = f->xmax;
  430. ymax = f->ymax;
  431. x = 0;
  432. y = radius;
  433. p = 3-2*radius;
  434. while (x <= y) {
  435. plot_circle(xc+x,yc+y,c);
  436. plot_circle(xc-x,yc+y,c);
  437. plot_circle(xc+x,yc-y,c);
  438. plot_circle(xc-x,yc-y,c);
  439. plot_circle(xc+y,yc+x,c);
  440. plot_circle(xc-y,yc+x,c);
  441. plot_circle(xc+y,yc-x,c);
  442. plot_circle(xc-y,yc-x,c);
  443. if (p < 0) p = p + 4*x + 6;
  444. else {
  445. p = p + 4*(x-y) + 10;
  446. y = y -1;
  447. }
  448. x++;
  449. }
  450. }
  451. /* -------------------------------------------------------------------------
  452. FrameBuffer_solidcircle(FrameBuffer f, int xc, int yc, int radius, Pixel c)
  453. Create an filled circle
  454. ------------------------------------------------------------------------- */
  455. #define fill_circle(x,y,c) \
  456. x1 = xc - x; \
  457. x2 = xc + x; \
  458. FrameBuffer_horizontal(f,x1,x2,y,c);
  459. void FrameBuffer_solidcircle(FrameBuffer *f, int xc, int yc, int radius, Pixel c) {
  460. int xpixels, ypixels, x, y, p;
  461. int x1,x2;
  462. int xmin, ymin, xmax, ymax;
  463. Pixel **pixels;
  464. if (radius <= 0) return;
  465. xpixels = f->width;
  466. ypixels = f->height;
  467. pixels = f->pixels;
  468. xmin = f->xmin;
  469. ymin = f->ymin;
  470. xmax = f->xmax;
  471. ymax = f->ymax;
  472. x = 0;
  473. y = radius;
  474. p = 3-2*radius;
  475. while (x <= y) {
  476. fill_circle(x,yc+y,c);
  477. fill_circle(x,yc-y,c);
  478. fill_circle(y,yc+x,c);
  479. fill_circle(y,yc-x,c);
  480. if (p < 0) p = p + 4*x + 6;
  481. else {
  482. p = p + 4*(x-y) + 10;
  483. y = y -1;
  484. }
  485. x++;
  486. }
  487. }
  488. /* ------------------------------------------------------------------------
  489. void FrameBuffer_setclip(f,xmin,ymin,xmax,ymax)
  490. Set clipping region for plotting
  491. ------------------------------------------------------------------------ */
  492. void FrameBuffer_setclip(FrameBuffer *f, int xmin, int ymin, int xmax, int ymax) {
  493. if (xmin >= xmax) return;
  494. if (ymin >= ymax) return;
  495. if (xmin < 0) xmin = 0;
  496. if (ymin < 0) ymin = 0;
  497. if (xmax > (int) f->width) xmax = f->width;
  498. if (ymax > (int) f->height) ymax = f->height;
  499. f->xmin = xmin;
  500. f->ymin = ymin;
  501. f->xmax = xmax;
  502. f->ymax = ymax;
  503. }
  504. /* ------------------------------------------------------------------------
  505. void FrameBuffer_noclip(f)
  506. Disable clipping region
  507. ------------------------------------------------------------------------ */
  508. void FrameBuffer_noclip(FrameBuffer *f) {
  509. f->xmin = 0;
  510. f->ymin = 0;
  511. f->xmax = f->width;
  512. f->ymax = f->height;
  513. }
  514. /* ------------------------------------------------------------------------
  515. FrameBuffer_zresize(FrameBuffer *f, int width, int height)
  516. This function resizes the framebuffer's zbuffer. If none exist, it
  517. creates a new one.
  518. ------------------------------------------------------------------------ */
  519. void FrameBuffer_zresize(FrameBuffer *f, int width, int height) {
  520. int i;
  521. if (f->zbuffer) {
  522. free((char *)f->zbuffer[0]);
  523. free((char *)f->zbuffer);
  524. }
  525. f->zbuffer = (Zvalue **) malloc(height*sizeof(Zvalue *));
  526. f->zbuffer[0] = (Zvalue *) malloc(height*width*sizeof(Zvalue));
  527. for (i = 0; i < height; i++)
  528. f->zbuffer[i] = f->zbuffer[0]+i*width;
  529. }
  530. /* ------------------------------------------------------------------------
  531. FrameBuffer_zclear(FrameBuffer *f)
  532. Clears the z-buffer for a particular frame. Sets all of the z-values to
  533. ZMIN.
  534. ------------------------------------------------------------------------- */
  535. void FrameBuffer_zclear(FrameBuffer *f) {
  536. unsigned int i,j;
  537. if (f) {
  538. if (f->zbuffer) {
  539. for (i = 0; i < f->width; i++)
  540. for (j = 0; j < f->height; j++)
  541. f->zbuffer[j][i] = ZMIN;
  542. }
  543. }
  544. }
  545. /* -------------------------------------------------------------------------
  546. FrameBuffer_solidtriangle(FrameBuffer *f, int tx1, int ty2,
  547. int tx2, int ty2,
  548. int tx3, int ty3, Pixel color)
  549. This function draws a 2D filled triangle.
  550. General idea :
  551. 1. Transform the three points into screen coordinates
  552. 2. Order three points vertically on screen.
  553. 3. Check for degenerate cases (where 3 points are colinear).
  554. 4. Fill in the resulting triangle using horizontal lines.
  555. -------------------------------------------------------------------------- */
  556. void FrameBuffer_solidtriangle(FrameBuffer *f, int tx1, int ty1,
  557. int tx2, int ty2,
  558. int tx3, int ty3, Pixel color) {
  559. int tempx, tempy;
  560. double m1,m2,m3;
  561. int y;
  562. int ix1, ix2;
  563. /* Figure out which point has the greatest "y" value */
  564. if (ty2 > ty1) { /* Swap points 1 and 2 if 2 is higher */
  565. tempx = tx1;
  566. tempy = ty1;
  567. tx1 = tx2;
  568. ty1 = ty2;
  569. tx2 = tempx;
  570. ty2 = tempy;
  571. }
  572. if (ty3 > ty1) { /* Swap points 1 and 3 if 3 is higher */
  573. tempx = tx1;
  574. tempy = ty1;
  575. tx1 = tx3;
  576. ty1 = ty3;
  577. tx3 = tempx;
  578. ty3 = tempy;
  579. }
  580. if (ty3 > ty2) { /* Swap points 2 and 3 if 3 is higher */
  581. tempx = tx2;
  582. tempy = ty2;
  583. tx2 = tx3;
  584. ty2 = ty3;
  585. tx3 = tempx;
  586. ty3 = tempy;
  587. }
  588. /* Points are now order so that t_1 is the highest point, t_2 is the
  589. middle point, and t_3 is the lowest point */
  590. /* Check for degenerate cases here */
  591. if ((ty1 == ty2) && (ty2 == ty3)) {
  592. /* Points are aligned horizontally. Handle as a special case */
  593. /* Just draw three lines using the outline color */
  594. FrameBuffer_line(f,tx1,ty1,tx2,ty2,color);
  595. FrameBuffer_line(f,tx1,ty1,tx3,ty3,color);
  596. FrameBuffer_line(f,tx2,ty2,tx3,ty3,color);
  597. } else {
  598. if (ty2 < ty1) {
  599. /* First process line segments between (x1,y1)-(x2,y2)
  600. And between (x1,y1),(x3,y3) */
  601. m1 = (double) (tx2 - tx1)/(double) (ty2 - ty1);
  602. m2 = (double) (tx3 - tx1)/(double) (ty3 - ty1);
  603. y = ty1;
  604. while (y >= ty2) {
  605. /* Calculate x values from slope */
  606. ix1 = (int) (m1*(y-ty1)+0.5) + tx1;
  607. ix2 = (int) (m2*(y-ty1)+0.5) + tx1;
  608. if (ix1 > ix2)
  609. FrameBuffer_horizontal(f,ix2,ix1,y,color);
  610. else
  611. FrameBuffer_horizontal(f,ix1,ix2,y,color);
  612. y--;
  613. }
  614. }
  615. if (ty3 < ty2) {
  616. /* Draw lower half of the triangle */
  617. m2 = (double) (tx3 - tx1)/(double) (ty3 - ty1);
  618. m3 = (double) (tx3 - tx2)/(double)(ty3 - ty2);
  619. y = ty2;
  620. while (y >= ty3) {
  621. ix1 = (int) (m3*(y-ty2)+0.5)+tx2;
  622. ix2 = (int) (m2*(y-ty1)+0.5)+tx1;
  623. if (ix1 > ix2)
  624. FrameBuffer_horizontal(f,ix2,ix1,y,color);
  625. else
  626. FrameBuffer_horizontal(f,ix1,ix2,y,color);
  627. y--;
  628. }
  629. }
  630. }
  631. }
  632. /* -------------------------------------------------------------------------
  633. FrameBuffer_interptriangle(FrameBuffer *f,
  634. int tx1, int ty2, Pixel c1,
  635. int tx2, int ty2, Pixel c2,
  636. int tx3, int ty3, Pixel c3)
  637. This function draws a filled triangle with color
  638. interpolation.
  639. General idea :
  640. 1. Transform the three points into screen coordinates
  641. 2. Order three points vertically on screen.
  642. 3. Check for degenerate cases (where 3 points are colinear).
  643. 4. Fill in the resulting triangle using horizontal lines.
  644. 5. Colors are interpolated between end points
  645. -------------------------------------------------------------------------- */
  646. void FrameBuffer_interptriangle(FrameBuffer *f,
  647. int tx1, int ty1, Pixel c1,
  648. int tx2, int ty2, Pixel c2,
  649. int tx3, int ty3, Pixel c3) {
  650. int tempx, tempy;
  651. double m1,m2,m3;
  652. double mc1,mc2,mc3;
  653. Pixel ic1,ic2,tempc;
  654. int y;
  655. int ix1, ix2;
  656. /* Figure out which point has the greatest "y" value */
  657. if (ty2 > ty1) { /* Swap points 1 and 2 if 2 is higher */
  658. tempx = tx1;
  659. tempy = ty1;
  660. tempc = c1;
  661. tx1 = tx2;
  662. ty1 = ty2;
  663. c1 = c2;
  664. tx2 = tempx;
  665. ty2 = tempy;
  666. c2 = tempc;
  667. }
  668. if (ty3 > ty1) { /* Swap points 1 and 3 if 3 is higher */
  669. tempx = tx1;
  670. tempy = ty1;
  671. tempc = c1;
  672. tx1 = tx3;
  673. ty1 = ty3;
  674. c1 = c3;
  675. tx3 = tempx;
  676. ty3 = tempy;
  677. c3 = tempc;
  678. }
  679. if (ty3 > ty2) { /* Swap points 2 and 3 if 3 is higher */
  680. tempx = tx2;
  681. tempy = ty2;
  682. tempc = c2;
  683. tx2 = tx3;
  684. ty2 = ty3;
  685. c2 = c3;
  686. tx3 = tempx;
  687. ty3 = tempy;
  688. c3 = tempc;
  689. }
  690. /* Points are now order so that t_1 is the highest point, t_2 is the
  691. middle point, and t_3 is the lowest point */
  692. /* Check for degenerate cases here */
  693. if ((ty1 == ty2) && (ty2 == ty3)) {
  694. /* Points are aligned horizontally. Handle as a special case */
  695. /* Just draw three lines using the outline color */
  696. if (tx2 > tx1)
  697. FrameBuffer_horizontalinterp(f,tx1,tx2,ty1,c1,c2);
  698. else
  699. FrameBuffer_horizontalinterp(f,tx2,tx1,ty1,c2,c1);
  700. if (tx3 > tx1)
  701. FrameBuffer_horizontalinterp(f,tx1,tx3,ty1,c1,c3);
  702. else
  703. FrameBuffer_horizontalinterp(f,tx3,tx1,ty1,c3,c1);
  704. if (tx3 > tx2)
  705. FrameBuffer_horizontalinterp(f,tx2,tx3,ty2,c2,c3);
  706. else
  707. FrameBuffer_horizontalinterp(f,tx3,tx2,ty2,c3,c2);
  708. } else {
  709. /* First process line segments between (x1,y1)-(x2,y2)
  710. And between (x1,y1),(x3,y3) */
  711. if (ty2 < ty1) {
  712. m1 = (double) (tx2 - tx1)/(double) (ty2 - ty1);
  713. m2 = (double) (tx3 - tx1)/(double) (ty3 - ty1);
  714. mc1 = (c2 - c1)/(double) (ty2 - ty1);
  715. mc2 = (c3 - c1)/(double) (ty3 - ty1);
  716. y = ty1;
  717. while (y >= ty2) {
  718. /* Calculate x values from slope */
  719. ix1 = (int) (m1*(y-ty1)+0.5) + tx1;
  720. ix2 = (int) (m2*(y-ty1)+0.5) + tx1;
  721. ic1 = (int) (mc1*(y-ty1) + c1);
  722. ic2 = (int) (mc2*(y-ty1) + c1);
  723. if (ix1 > ix2)
  724. FrameBuffer_horizontalinterp(f,ix2,ix1,y,ic2,ic1);
  725. else
  726. FrameBuffer_horizontalinterp(f,ix1,ix2,y,ic1,ic2);
  727. y--;
  728. }
  729. }
  730. if (ty3 < ty2) {
  731. /* Draw lower half of the triangle */
  732. m2 = (double) (tx3 - tx1)/(double) (ty3 - ty1);
  733. mc2 = (c3 - c1)/(double) (ty3 - ty1);
  734. m3 = (double) (tx3 - tx2)/(double)(ty3 - ty2);
  735. mc3 = (c3 - c2)/(double) (ty3 - ty2);
  736. y = ty2;
  737. while (y >= ty3) {
  738. ix1 = (int) (m3*(y-ty2)+0.5)+tx2;
  739. ix2 = (int) (m2*(y-ty1)+0.5)+tx1;
  740. ic1 = (int) (mc3*(y-ty2)+c2);
  741. ic2 = (int) (mc2*(y-ty1)+c1);
  742. if (ix1 > ix2)
  743. FrameBuffer_horizontalinterp(f,ix2,ix1,y,ic2,ic1);
  744. else
  745. FrameBuffer_horizontalinterp(f,ix1,ix2,y,ic1,ic2);
  746. y--;
  747. }
  748. }
  749. }
  750. }