LINE.C 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  11. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
  12. */
  13. #include <stdlib.h>
  14. #include "pa_enabl.h"
  15. #include "mem.h"
  16. #include "gr.h"
  17. #include "grdef.h"
  18. #include "fix.h"
  19. #include "clip.h"
  20. #if defined(POLY_ACC)
  21. #include "poly_acc.h"
  22. #endif
  23. extern void gr_modex_line();
  24. int modex_line_vertincr;
  25. int modex_line_incr1;
  26. int modex_line_incr2;
  27. int modex_line_x1;
  28. int modex_line_y1;
  29. int modex_line_x2;
  30. int modex_line_y2;
  31. ubyte modex_line_Color;
  32. /*
  33. Symmetric Double Step Line Algorithm
  34. by Brian Wyvill
  35. from "Graphics Gems", Academic Press, 1990
  36. */
  37. /* non-zero flag indicates the pixels needing EXCHG back. */
  38. void plot(int x,int y,int flag)
  39. { if (flag)
  40. gr_upixel(y, x);
  41. else
  42. gr_upixel(x, y);
  43. }
  44. int gr_hline(int x1, int x2, int y)
  45. { int i;
  46. if (x1 > x2) EXCHG(x1,x2);
  47. for (i=x1; i<=x2; i++ )
  48. gr_upixel( i, y );
  49. return 0;
  50. }
  51. int gr_vline(int y1, int y2, int x)
  52. { int i;
  53. if (y1 > y2) EXCHG(y1,y2);
  54. for (i=y1; i<=y2; i++ )
  55. gr_upixel( x, i );
  56. return 0;
  57. }
  58. void gr_universal_uline(int a1, int b1, int a2, int b2)
  59. {
  60. int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left;
  61. int x1, y1;
  62. int sign_x = 1, sign_y = 1, step, reverse, i;
  63. if (a1==a2) {
  64. gr_vline(b1,b2,a1);
  65. return;
  66. }
  67. if (b1==b2) {
  68. gr_hline(a1,a2,b1);
  69. return;
  70. }
  71. dx = a2 - a1;
  72. dy = b2 - b1;
  73. if (dx < 0) {
  74. sign_x = -1;
  75. dx *= -1;
  76. }
  77. if (dy < 0) {
  78. sign_y = -1;
  79. dy *= -1;
  80. }
  81. /* decide increment sign by the slope sign */
  82. if (sign_x == sign_y)
  83. step = 1;
  84. else
  85. step = -1;
  86. if (dy > dx) { /* chooses axis of greatest movement (make * dx) */
  87. EXCHG(a1, b1);
  88. EXCHG(a2, b2);
  89. EXCHG(dx, dy);
  90. reverse = 1;
  91. } else
  92. reverse = 0;
  93. /* note error check for dx==0 should be included here */
  94. if (a1 > a2) { /* start from the smaller coordinate */
  95. x = a2;
  96. y = b2;
  97. x1 = a1;
  98. y1 = b1;
  99. } else {
  100. x = a1;
  101. y = b1;
  102. x1 = a2;
  103. y1 = b2;
  104. }
  105. /* Note dx=n implies 0 - n or (dx+1) pixels to be set */
  106. /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */
  107. /* In fact (dx-1)/4 as 2 pixels are already plottted */
  108. xend = (dx - 1) / 4;
  109. pixels_left = (dx - 1) % 4; /* number of pixels left over at the
  110. * end */
  111. plot(x, y, reverse);
  112. plot(x1, y1, reverse); /* plot first two points */
  113. incr2 = 4 * dy - 2 * dx;
  114. if (incr2 < 0) { /* slope less than 1/2 */
  115. c = 2 * dy;
  116. incr1 = 2 * c;
  117. D = incr1 - dx;
  118. for (i = 0; i < xend; i++) { /* plotting loop */
  119. ++x;
  120. --x1;
  121. if (D < 0) {
  122. /* pattern 1 forwards */
  123. plot(x, y, reverse);
  124. plot(++x, y, reverse);
  125. /* pattern 1 backwards */
  126. plot(x1, y1, reverse);
  127. plot(--x1, y1, reverse);
  128. D += incr1;
  129. } else {
  130. if (D < c) {
  131. /* pattern 2 forwards */
  132. plot(x, y, reverse);
  133. plot(++x, y += step, reverse);
  134. /* pattern 2 backwards */
  135. plot(x1, y1, reverse);
  136. plot(--x1, y1 -= step, reverse);
  137. } else {
  138. /* pattern 3 forwards */
  139. plot(x, y += step, reverse);
  140. plot(++x, y, reverse);
  141. /* pattern 3 backwards */
  142. plot(x1, y1 -= step, reverse);
  143. plot(--x1, y1, reverse);
  144. }
  145. D += incr2;
  146. }
  147. } /* end for */
  148. /* plot last pattern */
  149. if (pixels_left) {
  150. if (D < 0) {
  151. plot(++x, y, reverse); /* pattern 1 */
  152. if (pixels_left > 1)
  153. plot(++x, y, reverse);
  154. if (pixels_left > 2)
  155. plot(--x1, y1, reverse);
  156. } else {
  157. if (D < c) {
  158. plot(++x, y, reverse); /* pattern 2 */
  159. if (pixels_left > 1)
  160. plot(++x, y += step, reverse);
  161. if (pixels_left > 2)
  162. plot(--x1, y1, reverse);
  163. } else {
  164. /* pattern 3 */
  165. plot(++x, y += step, reverse);
  166. if (pixels_left > 1)
  167. plot(++x, y, reverse);
  168. if (pixels_left > 2)
  169. plot(--x1, y1 -= step, reverse);
  170. }
  171. }
  172. } /* end if pixels_left */
  173. }
  174. /* end slope < 1/2 */
  175. else { /* slope greater than 1/2 */
  176. c = 2 * (dy - dx);
  177. incr1 = 2 * c;
  178. D = incr1 + dx;
  179. for (i = 0; i < xend; i++) {
  180. ++x;
  181. --x1;
  182. if (D > 0) {
  183. /* pattern 4 forwards */
  184. plot(x, y += step, reverse);
  185. plot(++x, y += step, reverse);
  186. /* pattern 4 backwards */
  187. plot(x1, y1 -= step, reverse);
  188. plot(--x1, y1 -= step, reverse);
  189. D += incr1;
  190. } else {
  191. if (D < c) {
  192. /* pattern 2 forwards */
  193. plot(x, y, reverse);
  194. plot(++x, y += step, reverse);
  195. /* pattern 2 backwards */
  196. plot(x1, y1, reverse);
  197. plot(--x1, y1 -= step, reverse);
  198. } else {
  199. /* pattern 3 forwards */
  200. plot(x, y += step, reverse);
  201. plot(++x, y, reverse);
  202. /* pattern 3 backwards */
  203. plot(x1, y1 -= step, reverse);
  204. plot(--x1, y1, reverse);
  205. }
  206. D += incr2;
  207. }
  208. } /* end for */
  209. /* plot last pattern */
  210. if (pixels_left) {
  211. if (D > 0) {
  212. plot(++x, y += step, reverse); /* pattern 4 */
  213. if (pixels_left > 1)
  214. plot(++x, y += step, reverse);
  215. if (pixels_left > 2)
  216. plot(--x1, y1 -= step, reverse);
  217. } else {
  218. if (D < c) {
  219. plot(++x, y, reverse); /* pattern 2 */
  220. if (pixels_left > 1)
  221. plot(++x, y += step, reverse);
  222. if (pixels_left > 2)
  223. plot(--x1, y1, reverse);
  224. } else {
  225. /* pattern 3 */
  226. plot(++x, y += step, reverse);
  227. if (pixels_left > 1)
  228. plot(++x, y, reverse);
  229. if (pixels_left > 2) {
  230. if (D > c) /* step 3 */
  231. plot(--x1, y1 -= step, reverse);
  232. else /* step 2 */
  233. plot(--x1, y1, reverse);
  234. }
  235. }
  236. }
  237. }
  238. }
  239. }
  240. //unclipped version just calls clipping version for now
  241. int gr_uline(fix _a1, fix _b1, fix _a2, fix _b2)
  242. {
  243. int a1,b1,a2,b2;
  244. a1 = f2i(_a1); b1 = f2i(_b1); a2 = f2i(_a2); b2 = f2i(_b2);
  245. switch(TYPE)
  246. {
  247. case BM_LINEAR:
  248. #ifndef MACINTOSH
  249. gr_linear_line( a1, b1, a2, b2 );
  250. #else
  251. gr_universal_uline( a1, b1, a2, b2 );
  252. #endif
  253. return 0;
  254. case BM_MODEX:
  255. modex_line_x1 = a1+XOFFSET;
  256. modex_line_y1 = b1+YOFFSET;
  257. modex_line_x2 = a2+XOFFSET;
  258. modex_line_y2 = b2+YOFFSET;
  259. modex_line_Color = grd_curcanv->cv_color;
  260. gr_modex_line();
  261. return 0;
  262. default:
  263. gr_universal_uline( a1, b1, a2, b2 );
  264. return 0;
  265. }
  266. }
  267. // Returns 0 if drawn with no clipping, 1 if drawn but clipped, and
  268. // 2 if not drawn at all.
  269. int gr_line(fix a1, fix b1, fix a2, fix b2)
  270. {
  271. int x1, y1, x2, y2;
  272. int clipped=0;
  273. x1 = i2f(MINX);
  274. y1 = i2f(MINY);
  275. x2 = i2f(MAXX);
  276. y2 = i2f(MAXY);
  277. CLIPLINE(a1,b1,a2,b2,x1,y1,x2,y2,return 2,clipped=1, FSCALE );
  278. #if defined(MACINTOSH)
  279. if ( PAEnabled )
  280. pa_draw_line( a1, b1, a2, b2 );
  281. else
  282. #endif
  283. gr_uline( a1, b1, a2, b2 );
  284. return clipped;
  285. }