graph.mod 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  1. (* Copyright (C) 1987 Jensen & Partners International *)
  2. (*$N,V-,I-,R-,A-,S-*)
  3. IMPLEMENTATION MODULE Graph;
  4. IMPORT Lib, SYSTEM;
  5. TYPE
  6. tinyint = [0..7];
  7. bs = SET OF tinyint;
  8. bp = POINTER TO bs;
  9. HercMapType = ARRAY[0..(HercDepth DIV 4)-1] OF
  10. ARRAY[0..(HercWidth DIV 8)-1] OF bs;
  11. ATTMapType = ARRAY[0..(ATTDepth DIV 4)-1] OF
  12. ARRAY[0..(ATTWidth DIV 8)-1] OF bs;
  13. VAR
  14. HercBitMap : ARRAY[0..3] OF POINTER TO HercMapType;
  15. ATTBitMap : ARRAY[0..3] OF POINTER TO ATTMapType;
  16. EGAScreen [0A000H:0] : ARRAY[0..0] OF bs;
  17. (* == CGA specific routines == *)
  18. PROCEDURE CGAGraphMode;
  19. VAR r : SYSTEM.Registers;
  20. BEGIN
  21. r.AX := 5;
  22. Lib.Intr( r,10H );
  23. END CGAGraphMode;
  24. PROCEDURE CGATextMode;
  25. VAR r : SYSTEM.Registers;
  26. BEGIN
  27. r.AX := 3;
  28. Lib.Intr( r,10H );
  29. END CGATextMode;
  30. PROCEDURE CGAPlot(x,y:CARDINAL;c:CARDINAL);
  31. VAR
  32. off : CARDINAL;
  33. seg : CARDINAL;
  34. tmp : CARDINAL;
  35. BEGIN
  36. IF (x >= CGAWidth) OR (y >= CGADepth) THEN RETURN END;
  37. off := x >> 2;
  38. IF ODD(y) THEN INC( off, 2000H - 40 ) END;
  39. INC( y, y << 2 );
  40. INC( off, y << 3 );
  41. x := 3 - CARDINAL( BITSET(x) * BITSET(3) );
  42. x := x << 1;
  43. tmp := 0B800H; seg := tmp;
  44. [seg:off bp]^ := ( [seg:off bp]^ - bs(3<<x) ) + bs(c<<x);
  45. END CGAPlot;
  46. PROCEDURE CGAPoint(x,y:CARDINAL) : CARDINAL;
  47. VAR
  48. off : CARDINAL;
  49. seg : CARDINAL;
  50. tmp : CARDINAL;
  51. BEGIN
  52. IF (x >= CGAWidth) OR (y >= CGADepth) THEN RETURN MAX(CARDINAL) END;
  53. off := x >> 2;
  54. IF ODD(y) THEN INC( off, 2000H - 40 ) END;
  55. INC( y, y << 2 );
  56. INC( off, y << 3 );
  57. x := 3 - CARDINAL( BITSET(x) * BITSET(3) );
  58. x := x << 1;
  59. tmp := 0B800H; seg := tmp;
  60. RETURN CARDINAL( [seg:off bp]^ * bs(3<<x) ) >> x;
  61. END CGAPoint;
  62. PROCEDURE CGAHLine ( x,y,x2 : CARDINAL; c:CARDINAL );
  63. VAR
  64. off : CARDINAL;
  65. seg : CARDINAL;
  66. tmp : CARDINAL;
  67. n : CARDINAL;
  68. w : bs;
  69. mask : bs;
  70. fillc: SHORTCARD;
  71. BEGIN
  72. IF y > CGADepth-1 THEN RETURN END;
  73. IF INTEGER(x) >= INTEGER(CGAWidth) THEN RETURN END;
  74. IF INTEGER(x) < 0 THEN x := 0; END;
  75. IF x2 >= CGAWidth THEN x2 := CGAWidth-1 END;
  76. n := ( x2 - x ) + 1;
  77. off := x >> 2;
  78. IF ODD(y) THEN
  79. INC( off, 2000H - 40 );
  80. c := ( c >> 2 + c << 2 ) MOD 16;
  81. END;
  82. c := c + c * 16;
  83. INC( y, y << 2 );
  84. INC( off, y << 3 );
  85. x := 3 - CARDINAL( BITSET(x) * BITSET(3) );
  86. x := x << 1;
  87. tmp := 0B800H; seg := tmp;
  88. w := [seg:off bp]^;
  89. REPEAT
  90. mask := bs(3 << x);
  91. w := ( w - mask ) + bs(c)*mask;
  92. DEC(n);
  93. DEC(x,2);
  94. UNTIL (n=0) OR (x=CARDINAL(-2));
  95. [seg:off bp]^ := w;
  96. INC(off);
  97. Lib.Fill( [seg:off], n >> 2, SHORTCARD(c) );
  98. INC( off, n >> 2 );
  99. n := n MOD 4;
  100. x := 6;
  101. w := [seg:off bp]^;
  102. WHILE n <> 0 DO
  103. mask := bs(3 << x);
  104. w := ( w - mask ) + bs(c)*mask;
  105. DEC(n);
  106. DEC(x,2);
  107. END;
  108. [seg:off bp]^ := w;
  109. END CGAHLine;
  110. PROCEDURE InitCGA ;
  111. BEGIN
  112. Width := CGAWidth ;
  113. Depth := CGADepth ;
  114. NumColor := 4 ;
  115. TextMode := CGATextMode ;
  116. GraphMode := CGAGraphMode ;
  117. Plot := CGAPlot ;
  118. Point := CGAPoint ;
  119. HLine := CGAHLine ;
  120. END InitCGA ;
  121. (* == EGA/VGA specific routines == *)
  122. PROCEDURE EGAGraphMode; (* Also VGA *)
  123. VAR r : SYSTEM.Registers;
  124. BEGIN
  125. IF Depth=480 THEN r.AX := 12H ELSE r.AX := 10H END ;
  126. Lib.Intr( r,10H );
  127. END EGAGraphMode;
  128. PROCEDURE EGAPlot( x,y,c : CARDINAL); (* Also VGA *)
  129. VAR
  130. t:bs;
  131. p,b,s:CARDINAL;
  132. BEGIN
  133. IF (x < EGAWidth) AND (y < Depth) THEN
  134. b := 1 << (7-(x MOD 8));
  135. p := y*80+(x DIV 8);
  136. SYSTEM.Out( 3CEH,8);SYSTEM.Out( 3CFH,SHORTCARD(b));
  137. SYSTEM.Out( 3C4H,2);SYSTEM.Out( 3C5H,0FH);
  138. s := 0A000H;
  139. t := [s:p bp]^;
  140. [s:p bp]^ := bs{};
  141. SYSTEM.Out( 3C4H,2);SYSTEM.Out( 3C5H,SHORTCARD(c));
  142. [s:p bp]^ := bs{0..7};
  143. SYSTEM.Out( 3CEH,8);SYSTEM.Out( 3CFH,0FFH);
  144. SYSTEM.Out( 3C4H,2);SYSTEM.Out( 3C5H,0FH);
  145. END;
  146. END EGAPlot;
  147. PROCEDURE EGAPoint(x,y:CARDINAL) : CARDINAL; (* Also VGA *)
  148. VAR
  149. t:bs;
  150. p,b,s:CARDINAL;
  151. c:CARDINAL;
  152. BEGIN
  153. IF (x < EGAWidth) AND (y < Depth) THEN
  154. b := 1 << (7-(x MOD 8));
  155. p := y*80+(x DIV 8 );
  156. s := 0A000H;
  157. SYSTEM.Out( 3CEH, 4 ); (* read map sel *)
  158. SYSTEM.Out( 3CFH, 3 );
  159. t := [s:p bp]^;
  160. t := t * bs(b);
  161. c := CARDINAL( SHORTCARD(t) );
  162. SYSTEM.Out( 3CFH, 2 );
  163. t := [s:p bp]^;
  164. t := t * bs(b);
  165. c := c * 2 + CARDINAL( SHORTCARD(t) );
  166. SYSTEM.Out( 3CFH, 1 );
  167. t := [s:p bp]^;
  168. t := t * bs(b);
  169. c := c * 2 + CARDINAL( SHORTCARD(t) );
  170. SYSTEM.Out( 3CFH, 0 );
  171. t := [s:p bp]^;
  172. t := t * bs(b);
  173. c := c * 2 + CARDINAL( SHORTCARD(t) );
  174. c := c >> ( 7 - ( x MOD 8 ) );
  175. RETURN c;
  176. ELSE
  177. RETURN 0;
  178. END;
  179. END EGAPoint;
  180. PROCEDURE EGAHLine ( x,y,x2 : CARDINAL; c:CARDINAL ); (* Also VGA *)
  181. VAR c1,c2 : CARDINAL;
  182. BEGIN
  183. IF y > Depth-1 THEN RETURN END;
  184. IF INTEGER(x) >= INTEGER(EGAWidth) THEN RETURN END;
  185. IF INTEGER(x) < 0 THEN x := 0; END;
  186. IF x2 >= EGAWidth THEN x2 := EGAWidth-1 END;
  187. WHILE (x MOD 8 # 0) AND (x <= x2) DO
  188. EGAPlot( x , y , c ); INC( x );
  189. END;
  190. WHILE (x2 MOD 8 # 7) AND (x <= x2) DO
  191. EGAPlot( x2 , y , c ); DEC( x2 );
  192. END;
  193. IF INTEGER(x) > INTEGER(x2) THEN RETURN; END;
  194. SYSTEM.Out( 3CEH,8);SYSTEM.Out( 3CFH,0FFH);
  195. SYSTEM.Out( 3C4H,2);SYSTEM.Out( 3C5H,0FH);
  196. SYSTEM.Out( 3CEH,5);SYSTEM.Out( 3CFH,2);
  197. y := y*80;
  198. x := x DIV 8;
  199. x2 := x2 DIV 8;
  200. WHILE x <= x2 DO
  201. EGAScreen[y+x] := bs(c);
  202. INC( x );
  203. END;
  204. SYSTEM.Out( 3CEH,5);SYSTEM.Out( 3CFH,0);
  205. END EGAHLine;
  206. PROCEDURE InitEGA ;
  207. BEGIN
  208. Width := EGAWidth ;
  209. Depth := EGADepth ;
  210. NumColor := 16 ;
  211. TextMode := CGATextMode ;
  212. GraphMode := EGAGraphMode ;
  213. Plot := EGAPlot ;
  214. Point := EGAPoint ;
  215. HLine := EGAHLine ;
  216. END InitEGA ;
  217. PROCEDURE InitVGA ;
  218. BEGIN
  219. InitEGA ;
  220. Depth := VGADepth ; (* Width same as EGA *)
  221. END InitVGA ;
  222. (* == Hercules specific routines == *)
  223. PROCEDURE HercGraphMode;
  224. TYPE
  225. DataType = ARRAY[0..11] OF SHORTCARD ;
  226. CONST
  227. Data = DataType(35H,2DH,2EH,07H,5BH,02H,57H,57H,02H,03H,00H,00H);
  228. VAR
  229. I: CARDINAL;
  230. BEGIN
  231. SYSTEM.Out(3BFH,03H); (* Remove this if do NOT want to override
  232. the hercules text mode lock *)
  233. Lib.Delay(10);
  234. SYSTEM.Out(3B8H,02H);
  235. FOR I:= 0 TO 11 DO
  236. SYSTEM.Out(3B4H,SHORTCARD(I));
  237. SYSTEM.Out(3B5H,Data[I])
  238. END;
  239. Lib.WordFill([0B000H:0],4000H,0);
  240. Lib.Delay(500);
  241. SYSTEM.Out(3B8H,0AH)
  242. END HercGraphMode;
  243. PROCEDURE HercTextMode;
  244. TYPE
  245. DataType = ARRAY[0..11] OF SHORTCARD ;
  246. CONST
  247. Data = DataType(61H,50H,52H,0FH,19H,06H,19H,19H,02H,0DH,0BH,0CH);
  248. VAR
  249. I: CARDINAL;
  250. BEGIN
  251. SYSTEM.Out(3B8H,20H);
  252. FOR I:= 0 TO 11 DO
  253. SYSTEM.Out(3B4H,SHORTCARD(I));
  254. SYSTEM.Out(3B5H,Data[I])
  255. END;
  256. Lib.WordFill([0B000H:0],2000,720H);
  257. Lib.Delay(500);
  258. SYSTEM.Out(3B8H,28H)
  259. END HercTextMode;
  260. PROCEDURE HercPlot(x,y:CARDINAL;c:CARDINAL);
  261. BEGIN
  262. IF (x >= HercWidth) OR (y >= HercDepth) THEN RETURN END;
  263. IF c = 0 THEN
  264. EXCL(HercBitMap[y MOD 4]^[y >> 2][x >> 3], 7-(x MOD 8))
  265. ELSE
  266. INCL(HercBitMap[y MOD 4]^[y >> 2][x >> 3], 7-(x MOD 8))
  267. END
  268. END HercPlot;
  269. PROCEDURE HercPoint(x,y:CARDINAL) : CARDINAL;
  270. BEGIN
  271. IF (x >= HercWidth) OR (y >= HercDepth) THEN RETURN MAX(CARDINAL); END;
  272. RETURN CARDINAL(7-(x MOD 8) IN HercBitMap[y MOD 4]^[y >> 2][x >> 3])
  273. END HercPoint;
  274. PROCEDURE HercHLine ( x,y,x2 : CARDINAL; c:CARDINAL );
  275. VAR
  276. I : CARDINAL;
  277. MapNum : CARDINAL;
  278. Byte1 : CARDINAL;
  279. Byte2 : CARDINAL;
  280. Bitx : CARDINAL;
  281. Bitx2 : CARDINAL;
  282. Mask : bs;
  283. IMask : bs;
  284. BEGIN
  285. IF y > HercDepth-1 THEN RETURN END;
  286. IF INTEGER(x) >= INTEGER(HercWidth) THEN RETURN END;
  287. IF INTEGER(x) < 0 THEN x := 0; END;
  288. IF x2 >= HercWidth THEN x2 := HercWidth-1 END;
  289. IF c = 0 THEN
  290. (* No Mask needed *)
  291. ELSIF c MOD (HercNumColor+1) = 0 THEN
  292. Mask:= bs{0..7}
  293. ELSE
  294. Mask:= bs(0AAH >> CARDINAL(ODD(y)));
  295. END;
  296. MapNum := y MOD 4;
  297. y := y >> 2;
  298. Byte1 := x >> 3;
  299. Byte2 := x2 >> 3;
  300. Bitx := 7-(x MOD 8);
  301. Bitx2 := 7-(x2 MOD 8);
  302. IF c = 0 THEN
  303. IF Byte2 = Byte1 THEN
  304. HercBitMap[MapNum]^[y][Byte1]:=
  305. (HercBitMap[MapNum]^[y][Byte1] - bs{Bitx2..Bitx});
  306. ELSE
  307. HercBitMap[MapNum]^[y][Byte1]:=
  308. (HercBitMap[MapNum]^[y][Byte1] - bs{0..Bitx});
  309. IF Byte2-Byte1 > 1 THEN
  310. Lib.Fill(ADR(HercBitMap[MapNum]^[y][Byte1+1]),Byte2-Byte1-1,0)
  311. END;
  312. HercBitMap[MapNum]^[y][Byte2]:=
  313. (HercBitMap[MapNum]^[y][Byte2] - bs{Bitx2..7});
  314. END
  315. ELSE
  316. IF Byte2 = Byte1 THEN
  317. HercBitMap[MapNum]^[y][Byte1]:=
  318. ((HercBitMap[MapNum]^[y][Byte1]-bs{Bitx2..Bitx})
  319. + (Mask * bs{Bitx2..Bitx}));
  320. ELSE
  321. HercBitMap[MapNum]^[y][Byte1]:=
  322. ((HercBitMap[MapNum]^[y][Byte1]-bs{0..Bitx})
  323. + (Mask * bs{0..Bitx}));
  324. IF Byte2-Byte1 > 1 THEN
  325. Lib.Fill(ADR(HercBitMap[MapNum]^[y][Byte1+1]),Byte2-Byte1-1,
  326. Mask)
  327. END;
  328. HercBitMap[MapNum]^[y][Byte2]:=
  329. ((HercBitMap[MapNum]^[y][Byte2]-bs{Bitx2..7})
  330. + (Mask * bs{Bitx2..7}));
  331. END
  332. END
  333. END HercHLine;
  334. PROCEDURE InitHerc ;
  335. BEGIN
  336. Width := HercWidth ;
  337. Depth := HercDepth ;
  338. NumColor := 2 ;
  339. TextMode := HercTextMode ;
  340. GraphMode := HercGraphMode ;
  341. Plot := HercPlot ;
  342. Point := HercPoint ;
  343. HLine := HercHLine ;
  344. HercBitMap[0]:= [0B000H:0]; (* Initialise BitMap pointers *)
  345. HercBitMap[1]:= [0B000H:02000H];
  346. HercBitMap[2]:= [0B000H:04000H];
  347. HercBitMap[3]:= [0B000H:06000H];
  348. END InitHerc ;
  349. (* == AT&T 400 specific routines == *)
  350. PROCEDURE ATTGraphMode;
  351. VAR r : SYSTEM.Registers;
  352. BEGIN
  353. r.AX := 64;
  354. Lib.Intr( r,10H );
  355. END ATTGraphMode;
  356. PROCEDURE ATTPlot(x,y:CARDINAL;c:CARDINAL);
  357. BEGIN
  358. IF (x >= ATTWidth) OR (y >= ATTDepth) THEN RETURN END;
  359. IF c = 0 THEN
  360. EXCL(ATTBitMap[y MOD 4]^[y >> 2][x >> 3], 7-(x MOD 8))
  361. ELSE
  362. INCL(ATTBitMap[y MOD 4]^[y >> 2][x >> 3], 7-(x MOD 8))
  363. END
  364. END ATTPlot;
  365. PROCEDURE ATTPoint(x,y:CARDINAL) : CARDINAL;
  366. BEGIN
  367. IF (x >= ATTWidth) OR (y >= ATTDepth) THEN RETURN MAX(CARDINAL); END;
  368. RETURN CARDINAL(7-(x MOD 8) IN ATTBitMap[y MOD 4]^[y >> 2][x >> 3])
  369. END ATTPoint;
  370. PROCEDURE ATTHLine ( x,y,x2 : CARDINAL; c:CARDINAL );
  371. VAR
  372. I : CARDINAL;
  373. MapNum : CARDINAL;
  374. Byte1 : CARDINAL;
  375. Byte2 : CARDINAL;
  376. Bitx : CARDINAL;
  377. Bitx2 : CARDINAL;
  378. Mask : bs;
  379. BEGIN
  380. IF y > ATTDepth-1 THEN RETURN END;
  381. IF INTEGER(x) >= INTEGER(ATTWidth) THEN RETURN END;
  382. IF INTEGER(x) < 0 THEN x := 0; END;
  383. IF x2 >= ATTWidth THEN x2 := ATTWidth-1 END;
  384. IF c = 0 THEN
  385. (* No Mask needed *)
  386. ELSIF c MOD (ATTNumColor+1) = 0 THEN
  387. Mask:= bs{0..7}
  388. ELSE
  389. Mask:= bs(0AAH >> CARDINAL(ODD(y)));
  390. END;
  391. MapNum := y MOD 4;
  392. y := y >> 2;
  393. Byte1 := x >> 3;
  394. Byte2 := x2 >> 3;
  395. Bitx := 7-(x MOD 8);
  396. Bitx2 := 7-(x2 MOD 8);
  397. IF c = 0 THEN
  398. IF Byte2 = Byte1 THEN
  399. ATTBitMap[MapNum]^[y][Byte1]:=
  400. (ATTBitMap[MapNum]^[y][Byte1] - bs{Bitx2..Bitx});
  401. ELSE
  402. ATTBitMap[MapNum]^[y][Byte1]:=
  403. (ATTBitMap[MapNum]^[y][Byte1] - bs{0..Bitx});
  404. IF Byte2-Byte1 > 1 THEN
  405. Lib.Fill(ADR(ATTBitMap[MapNum]^[y][Byte1+1]),Byte2-Byte1-1,0)
  406. END;
  407. ATTBitMap[MapNum]^[y][Byte2]:=
  408. (ATTBitMap[MapNum]^[y][Byte2] - bs{Bitx2..7});
  409. END
  410. ELSE
  411. IF Byte2 = Byte1 THEN
  412. ATTBitMap[MapNum]^[y][Byte1]:=
  413. ((ATTBitMap[MapNum]^[y][Byte1]-bs{Bitx2..Bitx})
  414. + (Mask * bs{Bitx2..Bitx}));
  415. ELSE
  416. ATTBitMap[MapNum]^[y][Byte1]:=
  417. ((ATTBitMap[MapNum]^[y][Byte1]-bs{0..Bitx})
  418. + (Mask * bs{0..Bitx}));
  419. IF Byte2-Byte1 > 1 THEN
  420. Lib.Fill(ADR(ATTBitMap[MapNum]^[y][Byte1+1]),Byte2-Byte1-1,
  421. Mask)
  422. END;
  423. ATTBitMap[MapNum]^[y][Byte2]:=
  424. ((ATTBitMap[MapNum]^[y][Byte2]-bs{Bitx2..7})
  425. + (Mask * bs{Bitx2..7}));
  426. END
  427. END
  428. END ATTHLine;
  429. PROCEDURE InitATT ;
  430. BEGIN
  431. Width := ATTWidth ;
  432. Depth := ATTDepth ;
  433. NumColor := 2 ;
  434. TextMode := CGATextMode ;
  435. GraphMode := ATTGraphMode ;
  436. Plot := ATTPlot ;
  437. Point := ATTPoint ;
  438. HLine := ATTHLine ;
  439. ATTBitMap[0]:= [0B000H:8000H]; (* Initialise BitMap pointers *)
  440. ATTBitMap[1]:= [0B000H:0A000H];
  441. ATTBitMap[2]:= [0B000H:0C000H];
  442. ATTBitMap[3]:= [0B000H:0E000H];
  443. END InitATT ;
  444. (* ------ Device independant routines ------ *)
  445. PROCEDURE Line(x1,y1,x2,y2: CARDINAL; c: CARDINAL);
  446. VAR
  447. dx,dy,e,tmp : INTEGER;
  448. BEGIN
  449. IF x1 > x2 THEN (* ensure that x2 >= x1 *)
  450. tmp := x1; x1 := x2; x2 := tmp;
  451. tmp := y1; y1 := y2; y2 := tmp;
  452. END;
  453. dx := x2-x1;
  454. e := 0;
  455. IF y1 <= y2 THEN (* case where y increases *)
  456. dy := (y2-y1);
  457. IF dx >= dy THEN
  458. LOOP
  459. Plot( x1,y1,c );
  460. IF x1 = x2 THEN EXIT END;
  461. INC(x1);
  462. INC(e,dy);
  463. INC(e,dy);
  464. IF e > dx THEN
  465. DEC(e,dx);
  466. DEC(e,dx);
  467. INC(y1);
  468. END;
  469. END;
  470. ELSE
  471. LOOP
  472. Plot( x1,y1,c );
  473. IF y1 = y2 THEN EXIT END;
  474. INC(y1);
  475. INC(e,dx);
  476. INC(e,dx);
  477. IF e > dy THEN
  478. DEC(e,dy);
  479. DEC(e,dy);
  480. INC(x1);
  481. END;
  482. END;
  483. END;
  484. ELSE
  485. (* case where y decreases *)
  486. dy := (y1-y2);
  487. IF dx >= dy THEN
  488. LOOP
  489. Plot( x1,y1,c );
  490. IF x1 = x2 THEN EXIT END;
  491. INC(x1);
  492. INC(e,dy);
  493. INC(e,dy);
  494. IF e > dx THEN
  495. DEC(e,dx);
  496. DEC(e,dx);
  497. DEC(y1);
  498. END;
  499. END;
  500. ELSE
  501. LOOP
  502. Plot( x1,y1,c );
  503. IF y1 = y2 THEN EXIT END;
  504. DEC(y1);
  505. INC(e,dx);
  506. INC(e,dx);
  507. IF e > dy THEN
  508. DEC(e,dy);
  509. DEC(e,dy);
  510. INC(x1);
  511. END;
  512. END;
  513. END;
  514. END;
  515. END Line;
  516. CONST
  517. dx = 2;
  518. dy = 2;
  519. PROCEDURE Disc(x0,y0,r: CARDINAL; c: CARDINAL);
  520. VAR
  521. e : INTEGER;
  522. x,y : CARDINAL;
  523. BEGIN
  524. x := r; y := 0; e := 0;
  525. WHILE INTEGER(y) <= INTEGER(x) DO
  526. HLine(x0-x,y0+y,x0+x,c);
  527. HLine(x0-x,y0-y,x0+x,c);
  528. INC(y);
  529. INC(e,y*dy-1);
  530. IF e > INTEGER(x) THEN
  531. DEC(x);
  532. DEC(e,x*dx+1);
  533. HLine(x0-y,y0+x,x0+y,c);
  534. HLine(x0-y,y0-x,x0+y,c);
  535. END;
  536. END;
  537. END Disc;
  538. PROCEDURE Circle(x0,y0,r: CARDINAL; c: CARDINAL);
  539. VAR
  540. e : INTEGER;
  541. x,y : CARDINAL;
  542. BEGIN
  543. x := r; y := 0; e := 0;
  544. WHILE INTEGER(y) <= INTEGER(x) DO
  545. Plot(x0+x,y0+y,c);
  546. Plot(x0-x,y0+y,c);
  547. Plot(x0+x,y0-y,c);
  548. Plot(x0-x,y0-y,c);
  549. Plot(x0+y,y0+x,c);
  550. Plot(x0-y,y0+x,c);
  551. Plot(x0+y,y0-x,c);
  552. Plot(x0-y,y0-x,c);
  553. INC(y);
  554. INC(e,y*dy-1);
  555. IF e > INTEGER(x) THEN
  556. DEC(x);
  557. DEC(e,x*dx+1);
  558. END;
  559. END;
  560. END Circle;
  561. PROCEDURE Ellipse ( x0,y0 : CARDINAL ; (* center *)
  562. a0,b0 : CARDINAL ; (* semi-axes *)
  563. c : CARDINAL ; (* color *)
  564. fill : BOOLEAN ) ; (* wether filled *)
  565. VAR
  566. x,y : CARDINAL ;
  567. a,b : LONGINT ;
  568. asq,asq2,bsq,bsq2 : LONGINT ;
  569. d,dx,dy : LONGINT ;
  570. BEGIN
  571. x := 0 ;
  572. y := b0 ;
  573. a := LONGINT(a0) ;
  574. b := LONGINT(b0) ;
  575. asq := a*a ;
  576. asq2 := asq*2 ;
  577. bsq := b*b ;
  578. bsq2 := bsq*2 ;
  579. d := bsq-(asq*b)+(asq DIV 4) ;
  580. dx := 0 ;
  581. dy := asq2*b ;
  582. WHILE dx<dy DO
  583. IF fill THEN
  584. HLine(x0-x,y0+y,x0+x,c);
  585. HLine(x0-x,y0-y,x0+x,c);
  586. ELSE
  587. Plot(x0+x,y0+y,c) ;
  588. Plot(x0-x,y0+y,c) ;
  589. Plot(x0+x,y0-y,c) ;
  590. Plot(x0-x,y0-y,c) ;
  591. END ;
  592. IF d>0 THEN
  593. DEC(y) ;
  594. DEC(dy,asq2) ;
  595. DEC(d,dy) ;
  596. END ;
  597. INC(x) ;
  598. INC(dx,bsq2) ;
  599. INC(d,bsq+dx) ;
  600. END ;
  601. INC(d,(3*(asq-bsq)DIV 2-(dx+dy))DIV 2) ;
  602. WHILE INTEGER(y)>=0 DO
  603. IF fill THEN
  604. HLine(x0-x,y0+y,x0+x,c);
  605. HLine(x0-x,y0-y,x0+x,c);
  606. ELSE
  607. Plot(x0+x,y0+y,c) ;
  608. Plot(x0-x,y0+y,c) ;
  609. Plot(x0+x,y0-y,c) ;
  610. Plot(x0-x,y0-y,c) ;
  611. END ;
  612. IF d<0 THEN
  613. INC(x) ;
  614. INC(dx,bsq2) ;
  615. INC(d,dx) ;
  616. END ;
  617. DEC(y) ;
  618. DEC(dy,asq2) ;
  619. INC(d,asq-dy) ;
  620. END ;
  621. END Ellipse ;
  622. PROCEDURE Polygon(n: CARDINAL; px,py: ARRAY OF CARDINAL; c: CARDINAL);
  623. CONST
  624. MaxPts = 20;
  625. VAR
  626. y,miny,maxy,x0,y0,x1,y1,temp,i,edge,next_edge,active : INTEGER;
  627. xord : ARRAY [0..MaxPts] OF INTEGER;
  628. x : ARRAY [0..MaxPts] OF CARDINAL;
  629. e : ARRAY [0..MaxPts] OF INTEGER;
  630. PROCEDURE quicksort(l,r: INTEGER);
  631. VAR
  632. i,j,temp : INTEGER;
  633. key : CARDINAL;
  634. BEGIN
  635. WHILE ( l < r ) DO
  636. i := l; j := r; key := x[xord[j]];
  637. REPEAT
  638. WHILE ( i < j ) AND ( x[xord[i]] <= key ) DO i := i + 1 END;
  639. WHILE ( i < j ) AND ( key <= x[xord[j]] ) DO j := j - 1 END;
  640. IF i < j THEN
  641. temp := xord[i]; xord[i] := xord[j]; xord[j] := temp;
  642. END;
  643. UNTIL ( i >= j );
  644. temp := xord[i]; xord[i] := xord[r]; xord[r] := temp;
  645. IF (i-l < r-i) THEN
  646. quicksort( l, i-1 ); l := i+1;
  647. ELSE
  648. quicksort( i+1, r ); r := i-1;
  649. END;
  650. END;
  651. END quicksort;
  652. BEGIN
  653. IF n > MaxPts THEN n := MaxPts END;
  654. (* find extremal y points *)
  655. miny := py[0]; maxy := miny;
  656. FOR i := 0 TO n-1 DO
  657. IF INTEGER(py[i]) < miny THEN miny := py[i]; END;
  658. IF INTEGER(py[i]) > maxy THEN maxy := py[i]; END;
  659. END;
  660. FOR y := miny TO maxy DO
  661. active := -1;
  662. FOR edge := 0 TO n-1 DO
  663. IF edge = INTEGER(n-1) THEN next_edge := 0
  664. ELSE next_edge := edge + 1;
  665. END;
  666. x0 := px[edge]; y0 := py[edge];
  667. x1 := px[next_edge]; y1 := py[next_edge];
  668. IF y0 > y1 THEN temp := x0; x0 := x1; x1 := temp;
  669. temp := y0; y0 := y1; y1 := temp END;
  670. IF y = y0 THEN e[edge] := 0; x[edge] := x0
  671. ELSIF ( y0 <= y ) AND ( y <= y1 ) THEN
  672. IF x1 >= x0 THEN (* x increases with y *)
  673. INC( e[edge], 2*(x1-x0) );
  674. WHILE e[edge] > INTEGER(y1-y0) DO
  675. DEC( e[edge], 2*(y1-y0) ); INC(x[edge]);
  676. END;
  677. ELSE (* x decreases with y *)
  678. INC( e[edge], 2*(x0-x1) );
  679. WHILE e[edge] > INTEGER(y1-y0) DO
  680. DEC( e[edge], 2*(y1-y0) ); DEC(x[edge]);
  681. END;
  682. END;
  683. active := active + 1;
  684. xord[active] := edge;
  685. END;
  686. END;
  687. quicksort(0,active);
  688. i := 0;
  689. WHILE i < active DO
  690. HLine( x[xord[i]], y, x[xord[i+1]], c );
  691. i := i + 2;
  692. END;
  693. END; (* for y := .. *)
  694. END Polygon;
  695. (* - Auto reset to text mode
  696. VAR Continue:PROC;
  697. PROCEDURE Finish;
  698. BEGIN
  699. TextMode;
  700. Continue;
  701. END Finish;
  702. BEGIN
  703. Lib.Terminate( Finish, Continue );
  704. InitCGA ;
  705. END Gr.
  706. *)
  707. BEGIN
  708. InitCGA ; (* Change this for other adaptors *)
  709. END Graph.
  710.