AMD64.Oberon.Bitmaps.Mod 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. (* ETH Oberon, Copyright 2001 ETH Zuerich Institut fuer Computersysteme, ETH Zentrum, CH-8092 Zuerich.
  2. Refer to the "General ETH Oberon System Source License" contract available at: http://www.oberon.ethz.ch/ *)
  3. MODULE Bitmaps IN Oberon; (** non-portable *)
  4. (* as 20.02.99, ported to Shark Oberon *)
  5. (* to do:
  6. o get rid of buffer
  7. o ASSERT bounds everywhere
  8. *)
  9. IMPORT SYSTEM, Display;
  10. CONST
  11. BufSize = 10000H;
  12. Assembler = TRUE;
  13. TYPE
  14. Bitmap* = POINTER TO BitmapDesc;
  15. BitmapDesc* = RECORD (* cf. Display.DisplayBlock *)
  16. width*, height*, depth*: INTEGER; (* offset 0, 2, 4 *)
  17. wth*, size: LONGINT; (* offset 8, 12 *)
  18. address*: ADDRESS; (* offset 16 *)
  19. END;
  20. Buffer = RECORD bytes: ARRAY BufSize OF CHAR END;
  21. VAR
  22. buffer: POINTER TO Buffer;
  23. PROCEDURE Define*(B: Bitmap; width, height, depth: INTEGER; address: ADDRESS);
  24. BEGIN
  25. B.width := width;
  26. B.wth := width;
  27. B.height := height;
  28. B.depth := depth;
  29. B.address := address;
  30. B.size := LONG(width)*height
  31. END Define;
  32. PROCEDURE Get*(B: Bitmap; X, Y: INTEGER): INTEGER;
  33. VAR ofs: LONGINT; ch: CHAR;
  34. BEGIN
  35. ofs := Y*B.wth + X; ASSERT((ofs >= 0) & (ofs < B.size));
  36. SYSTEM.GET(B.address + ofs, ch);
  37. RETURN ORD(ch)
  38. END Get;
  39. PROCEDURE Clear*(B: Bitmap);
  40. VAR adr: ADDRESS; size: LONGINT;
  41. BEGIN
  42. size := B.size; adr := B.address;
  43. WHILE size >= 4 DO
  44. SYSTEM.PUT(adr, SYSTEM.VAL(LONGINT, 0));
  45. INC(adr, 4); DEC(size, 4)
  46. END;
  47. WHILE size > 0 DO SYSTEM.PUT(adr, 0X); INC(adr); DEC(size) END
  48. END Clear;
  49. PROCEDURE Dot*(B: Bitmap; col, X, Y, mode: INTEGER);
  50. VAR adr: ADDRESS; ch: CHAR;
  51. BEGIN
  52. adr := Y*B.wth + X; ASSERT((adr >= 0) & (adr < B.size));
  53. INC(adr, B.address);
  54. IF mode = Display.invert THEN
  55. SYSTEM.GET(adr, ch);
  56. SYSTEM.PUT(adr, CHR(SYSTEM.VAL(LONGINT,
  57. SYSTEM.VAL(SET, LONG(ORD(ch))) / SYSTEM.VAL(SET, LONG(col)))))
  58. ELSE
  59. SYSTEM.PUT(adr, CHR(col))
  60. END
  61. END Dot;
  62. PROCEDURE CopyBlock0(n, w: LONGINT; adr: ADDRESS; buf: ADDRESS; width: LONGINT; from: BOOLEAN);
  63. BEGIN
  64. IF from THEN
  65. REPEAT SYSTEM.MOVE(adr, buf, w); DEC(n); INC(adr, width); INC(buf, w) UNTIL n = 0
  66. ELSE
  67. REPEAT SYSTEM.MOVE(buf, adr, w); DEC(n); INC(adr, width); INC(buf, w) UNTIL n = 0
  68. END
  69. END CopyBlock0;
  70. PROCEDURE CopyBlock*(sB, dB: Bitmap; SX, SY, W, H, DX, DY, mode: INTEGER);
  71. VAR SourceWth, DestWth, sx, sy, w, h, dx, dy, w0, h0, dx0, dy0, src, dst, n, bufLines: LONGINT;
  72. BEGIN (* only the destination block is clipped *)
  73. SourceWth := sB.wth; DestWth := dB.wth;
  74. sx := SX; sy := SY; w := W; h := H; dx := DX; dy := DY;
  75. w0 := w; h0 := h; dx0 := dx; dy0 := dy;
  76. IF dx < 0 THEN dx := 0; DEC(w, dx-dx0) END;
  77. IF dy < 0 THEN dy := 0; DEC(h, dy-dy0) END;
  78. IF (w > 0) & (h > 0) & (w <= w0) & (h <= h0) THEN
  79. IF dx+w-1 > dB.width-1 THEN DEC(w, dx+w-1 - (dB.width-1)) END;
  80. IF dy+h-1 > dB.height-1 THEN DEC(h, dy+h-1 - (dB.height-1)) END;
  81. IF (w > 0) & (h > 0) & (w <= w0) & (h <= h0) THEN
  82. src := sy*SourceWth + sx; ASSERT((src >= 0) & (src < sB.size));
  83. dst := dy*DestWth + dx; ASSERT((dst >= 0) & (dst < dB.size));
  84. bufLines := BufSize DIV w; (* lines to copy at a time *)
  85. IF bufLines > h THEN bufLines := h END;
  86. (* adjust direction for overlap *)
  87. IF (dy-h+1 < sy) & (sy < dy) THEN (* start at bottom *)
  88. n := h-bufLines;
  89. INC(src, SourceWth*n); INC(dst, DestWth*n);
  90. REPEAT
  91. CopyBlock0(bufLines, w, sB.address+src, ADDRESSOF(buffer.bytes[0]), SourceWth, TRUE);
  92. CopyBlock0(bufLines, w, dB.address+dst, ADDRESSOF(buffer.bytes[0]), DestWth, FALSE);
  93. DEC(h, bufLines);
  94. IF bufLines > h THEN bufLines := h END;
  95. DEC(src, bufLines * SourceWth); DEC(dst, bufLines * DestWth)
  96. UNTIL h = 0
  97. ELSE (* start at top *)
  98. REPEAT
  99. CopyBlock0(bufLines, w, sB.address+src, ADDRESSOF(buffer.bytes[0]), SourceWth, TRUE);
  100. CopyBlock0(bufLines, w, dB.address+dst, ADDRESSOF(buffer.bytes[0]), DestWth, FALSE);
  101. INC(src, bufLines * SourceWth); INC(dst, bufLines * DestWth);
  102. DEC(h, bufLines);
  103. IF bufLines > h THEN bufLines := h END
  104. UNTIL h = 0
  105. END
  106. END
  107. END
  108. END CopyBlock;
  109. PROCEDURE CopyPattern0(ofs: LONGINT; src, dst: ADDRESS; w, col, mode: LONGINT);
  110. VAR ch: CHAR; m, i: LONGINT; s: SET;
  111. BEGIN
  112. IF mode = Display.invert THEN
  113. REPEAT (* loop over w pixels *)
  114. SYSTEM.GET(src, ch);
  115. i := ofs; (* start bit *)
  116. m := 8; (* stop bit *)
  117. IF m > ofs+w THEN m := ofs+w END;
  118. REPEAT (* loop over bits *)
  119. IF ODD(ASH(ORD(ch), -i)) THEN (* pixel on *)
  120. SYSTEM.GET(dst, SYSTEM.VAL(CHAR, s));
  121. SYSTEM.PUT(dst, CHR(SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, col) / s)))
  122. END;
  123. INC(dst); INC(i)
  124. UNTIL i = m;
  125. INC(src); DEC(w, m-ofs); ofs := 0
  126. UNTIL w = 0
  127. ELSE (* paint, replace *)
  128. REPEAT (* loop over w pixels *)
  129. SYSTEM.GET(src, ch);
  130. i := ofs; (* start bit *)
  131. m := 8; (* stop bit *)
  132. IF m > ofs+w THEN m := ofs+w END;
  133. REPEAT (* loop over bits *)
  134. IF ODD(ASH(ORD(ch), -i)) THEN (* pixel on *)
  135. (* paint & replace *)
  136. SYSTEM.PUT(dst, CHR(col))
  137. ELSIF mode = Display.replace THEN (* pixel off *)
  138. SYSTEM.PUT(dst, CHR(Display.BG))
  139. ELSE (* skip *)
  140. END;
  141. INC(dst); INC(i)
  142. UNTIL i = m;
  143. INC(src); DEC(w, m-ofs); ofs := 0
  144. UNTIL w = 0
  145. END;
  146. END CopyPattern0;
  147. PROCEDURE CopyPattern1(B: Bitmap; src: ADDRESS; x, y, w, col, mode: LONGINT);
  148. VAR ch: CHAR; m, i: LONGINT;
  149. BEGIN
  150. IF (y < 0) OR (y > B.height-1) THEN RETURN END;
  151. REPEAT (* loop over w pixels *)
  152. SYSTEM.GET(src, ch);
  153. i := 0; (* start bit *)
  154. m := 8; (* stop bit *)
  155. IF m > w THEN m := w END;
  156. REPEAT (* loop over bits *)
  157. IF ODD(ASH(ORD(ch), -i)) THEN (* pixel on *)
  158. Dot(B,SHORT(col), SHORT(x), SHORT(y), SHORT(mode))
  159. ELSIF mode = Display.replace THEN (* pixel off *)
  160. Dot(B,Display.BG, SHORT(x), SHORT(y), Display.replace)
  161. ELSE (* skip *)
  162. END;
  163. INC(x); INC(i)
  164. UNTIL i = m;
  165. INC(src); DEC(w, m)
  166. UNTIL w = 0
  167. END CopyPattern1;
  168. PROCEDURE CopyPattern*(B: Bitmap; col: INTEGER; pat: Display.Pattern; X, Y, mode: INTEGER);
  169. VAR x, y, x2, y2, w, w0, h: LONGINT; src, dst: ADDRESS; ch: CHAR;
  170. BEGIN
  171. SYSTEM.GET(pat, ch); w := ORD(ch);
  172. SYSTEM.GET(pat+1, ch); h := ORD(ch);
  173. IF (w > 0) & (h > 0) THEN
  174. x := X; y := Y; x2 := x+w-1; y2 := y+h-1; (* (x,y) bottom left & (x2,y2) top right *)
  175. src := pat+2; (* first line of pattern *)
  176. w0 := (w+7) DIV 8; (* bytes in pattern line *)
  177. IF (x >= 0) & (y >= 0) & (x2 < B.width) & (y2 < B.height) THEN (* fully visible - common case *)
  178. dst := y * B.wth + x + B.address;
  179. REPEAT (* loop over h lines *)
  180. CopyPattern0(0, src, dst, w, col, mode);
  181. DEC(h); INC(dst, B.wth); INC(src, w0)
  182. UNTIL h = 0
  183. ELSIF (x2 >= 0) & (y2 >= 0) & (x < B.width) & (y < B.height) THEN (* partially visible *)
  184. REPEAT (* loop over h lines *)
  185. CopyPattern1(B, src, x, y, w, col, mode);
  186. INC(y); INC(src, w0); DEC(h)
  187. UNTIL h = 0
  188. ELSE (* invisible *)
  189. END
  190. END
  191. END CopyPattern;
  192. PROCEDURE ReplConst*(B: Bitmap; col, X, Y, W, H, mode: INTEGER);
  193. VAR addr, addr0: ADDRESS; pat, w: LONGINT; s: SET;
  194. BEGIN
  195. addr := B.address + B.wth*Y + X;
  196. pat := col + ASH(col, 8) + ASH(col, 16) + ASH(col, 24);
  197. IF mode = Display.invert THEN
  198. WHILE H > 0 DO w := W; addr0 := addr;
  199. WHILE w # 0 DO
  200. SYSTEM.GET(addr0, SYSTEM.VAL(CHAR,s));
  201. SYSTEM.PUT(addr0, CHR(SYSTEM.VAL(LONGINT, s/SYSTEM.VAL(SET, col))));
  202. DEC(w); INC(addr0)
  203. END;
  204. INC(addr, B.wth); DEC(H)
  205. END
  206. ELSE
  207. WHILE H > 0 DO w := W; addr0 := addr;
  208. WHILE w # 0 DO SYSTEM.PUT(addr0, CHR(col)); DEC(w); INC(addr0) END;
  209. INC(addr, B.wth); DEC(H)
  210. END
  211. END;
  212. END ReplConst;
  213. PROCEDURE FillPattern0(ofs: LONGINT; src, dst: ADDRESS; w, pw, col, mode: LONGINT);
  214. VAR ch: CHAR; m, i: LONGINT; src0: ADDRESS; left: LONGINT; s: SET;
  215. BEGIN
  216. left := pw-ofs; (* pixels left to do in pattern *)
  217. src0 := src; INC(src, ofs DIV 8); ofs := ofs MOD 8; (* start position *)
  218. IF mode = Display.invert THEN
  219. REPEAT (* loop over w pixels *)
  220. SYSTEM.GET(src, ch);
  221. i := ofs; (* start bit *)
  222. m := 8; (* stop bit *)
  223. IF m > ofs+left THEN m := ofs+left END; (* max left times *)
  224. IF m > ofs+w THEN m := ofs+w END; (* max w times *)
  225. REPEAT (* loop over bits *)
  226. IF ODD(ASH(ORD(ch), -i)) THEN (* pixel on *)
  227. SYSTEM.GET(dst, SYSTEM.VAL(CHAR, s));
  228. SYSTEM.PUT(dst, CHR(SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, col) / s)))
  229. END;
  230. INC(dst); INC(i)
  231. UNTIL i = m;
  232. INC(src); DEC(left, m-ofs); DEC(w, m-ofs); ofs := 0;
  233. IF left = 0 THEN src := src0; left := pw END (* wrap to start of pattern *)
  234. UNTIL w = 0
  235. ELSIF mode = Display.paint THEN
  236. REPEAT (* loop over w pixels *)
  237. SYSTEM.GET(src, ch);
  238. i := ofs; (* start bit *)
  239. m := 8; (* stop bit *)
  240. IF m > ofs+left THEN m := ofs+left END; (* max left times *)
  241. IF m > ofs+w THEN m := ofs+w END; (* max w times *)
  242. REPEAT (* loop over bits *)
  243. IF ODD(ASH(ORD(ch), -i)) THEN (* pixel on *)
  244. SYSTEM.PUT(dst, CHR(col))
  245. END;
  246. INC(dst); INC(i)
  247. UNTIL i = m;
  248. INC(src); DEC(left, m-ofs); DEC(w, m-ofs); ofs := 0;
  249. IF left = 0 THEN src := src0; left := pw END (* wrap to start of pattern *)
  250. UNTIL w = 0
  251. ELSE (* replace *)
  252. REPEAT (* loop over w pixels *)
  253. SYSTEM.GET(src, ch);
  254. i := ofs; (* start bit *)
  255. m := 8; (* stop bit *)
  256. IF m > ofs+left THEN m := ofs+left END; (* max left times *)
  257. IF m > ofs+w THEN m := ofs+w END; (* max w times *)
  258. REPEAT (* loop over bits *)
  259. IF ODD(ASH(ORD(ch), -i)) THEN (* pixel on *)
  260. SYSTEM.PUT(dst, CHR(col))
  261. ELSE (* pixel off *)
  262. SYSTEM.PUT(dst, CHR(Display.BG))
  263. END;
  264. INC(dst); INC(i)
  265. UNTIL i = m;
  266. INC(src); DEC(left, m-ofs); DEC(w, m-ofs); ofs := 0;
  267. IF left = 0 THEN src := src0; left := pw END (* wrap to start of pattern *)
  268. UNTIL w = 0
  269. END
  270. END FillPattern0;
  271. PROCEDURE ReplPattern*(B: Bitmap; col: INTEGER; pat: LONGINT; X, Y, W, H, mode: INTEGER);
  272. VAR px, pw, ph, x, y, x2, y2, w, w0, h: LONGINT; src0, src, dst: ADDRESS; ch: CHAR;
  273. BEGIN
  274. x := X; y := Y; w := W; h := H;
  275. x2 := x+w-1; y2 := y+h-1; (* (x,y) bottom left & (x2,y2) top right *)
  276. IF (w > 0) & (h > 0) THEN
  277. SYSTEM.GET(pat, ch); pw := ORD(ch);
  278. SYSTEM.GET(pat+1, ch); ph := ORD(ch);
  279. IF (pw > 0) & (ph > 0) THEN
  280. INC(pat, 2); (* adr of bitmap *)
  281. w0 := (pw+7) DIV 8; (* bytes in pattern line *)
  282. src0 := pat + (ph-1)*w0; (* last line of pattern *)
  283. src := pat; (* start line of pattern *)
  284. px := x MOD pw; (* start pixel offset *)
  285. dst := y * B.wth + x + B.address;
  286. REPEAT (* loop over h lines *)
  287. FillPattern0(px, src, dst, w, pw, col, mode);
  288. DEC(h); INC(dst, B.wth);
  289. IF src = src0 THEN src := pat ELSE INC(src, w0) END
  290. UNTIL h = 0
  291. END
  292. END
  293. END ReplPattern;
  294. PROCEDURE DisplayBlock*(B: Bitmap; SX, SY, W, H, DX, DY, mode: INTEGER; VAR colortable: ARRAY OF LONGINT (* fof *));
  295. BEGIN
  296. Display.DisplayBlock(B, SX, SY, W, H, DX, DY, mode,colortable);
  297. END DisplayBlock;
  298. PROCEDURE GetPix*(VAR addr: ADDRESS; VAR buf: SYSTEM.BYTE; depth: INTEGER);
  299. VAR s1, s2, s3: SHORTINT;
  300. BEGIN
  301. IF depth = 8 THEN SYSTEM.GET(addr, buf); INC(addr)
  302. ELSIF depth = 4 THEN
  303. SYSTEM.GET(addr, s1); INC(addr); SYSTEM.GET(addr, s2); INC(addr); buf := s2*16 + (s1 MOD 16)
  304. ELSE (* depth = 1 *)
  305. s1 := 0; s2 := 0;
  306. WHILE s1 < 8 DO SYSTEM.GET(addr, s3); INC(addr); INC(s1); s2 := s2*2 + s3 MOD 2 END; buf := s2
  307. END;
  308. END GetPix;
  309. PROCEDURE PutPix*(VAR addr: ADDRESS; border: ADDRESS; buf: SYSTEM.BYTE; depth: INTEGER);
  310. VAR s1: SHORTINT;
  311. BEGIN
  312. IF (depth = 8) & (addr < border) THEN SYSTEM.PUT(addr, buf); INC(addr)
  313. ELSIF depth = 4 THEN
  314. IF addr < border THEN SYSTEM.PUT(addr, SYSTEM.VAL(SHORTINT, buf) MOD 16); INC(addr) END;
  315. IF addr < border THEN SYSTEM.PUT(addr, SYSTEM.VAL(SHORTINT, buf) DIV 16 MOD 16); INC(addr) END;
  316. ELSE (* depth = 1 *)
  317. s1 := 0;
  318. WHILE s1 < 8 DO
  319. IF addr < border THEN
  320. IF ODD(SYSTEM.VAL(SHORTINT, buf)) THEN SYSTEM.PUT(addr, 15) ELSE SYSTEM.PUT(addr, 0) END
  321. END;
  322. INC(s1); INC(addr); buf := SYSTEM.VAL(SHORTINT, buf) DIV 2;
  323. END
  324. END;
  325. END PutPix;
  326. PROCEDURE -Copy0(src, dst: ADDRESS; hx, sw2, dw2: LONGINT);
  327. CODE {SYSTEM.AMD64}
  328. POP EDX ; dw2
  329. POP ECX ; sw2
  330. POP EBX ; hx
  331. POP RDI ; dst
  332. POP RSI ; src
  333. MOV EAX, EDX
  334. SHR EAX, 1
  335. PUSH EAX ; count
  336. for:
  337. MOV AL, [RSI]
  338. MOV [RDI], AL
  339. JMP while1
  340. while0:
  341. INC RSI
  342. SUB EBX, EDX
  343. while1:
  344. CMP EBX, 0
  345. JG while0
  346. INC RDI
  347. ADD EBX, ECX
  348. DEC DWORD [RSP]
  349. JNZ for
  350. POP EAX
  351. END Copy0;
  352. PROCEDURE Copy*(sB, dB: Bitmap; SX, SY, SW, SH, DX, DY, DW, DH, mode: INTEGER);
  353. VAR hx, hy, DW2, SW2: LONGINT; src, dst: ADDRESS; i: LONGINT; dy: INTEGER; ch: CHAR;
  354. BEGIN
  355. IF (SX >= 0) & (SY >= 0) & (SX+SW <= sB.width) & (SY+SH <= sB.height) &
  356. (DX >= 0) & (DY >= 0) & (DX+DW <= dB.width) & (DY+DH <= dB.height) &
  357. (SW > 0) & (SH > 0) & (DW > 0) & (DH > 0) THEN
  358. dy := DY + DH; DW2 := 2 * DW; SW2 := 2 * SW;
  359. hy := 2*SH - DH;
  360. WHILE DY < dy DO
  361. IF Assembler THEN
  362. Copy0(sB.address + SY*sB.wth + SX, dB.address + DY*dB.wth + DX, 2*SW - DW, SW2, DW2)
  363. ELSE
  364. hx := 2*SW - DW;
  365. src := sB.address + SY*sB.wth + SX;
  366. dst := dB.address + DY*dB.wth + DX;
  367. FOR i := 1 TO DW DO
  368. SYSTEM.GET(src, ch); SYSTEM.PUT(dst, ch);
  369. WHILE hx > 0 DO INC(src); DEC(hx, DW2) END;
  370. INC(dst); INC(hx, SW2)
  371. END
  372. END;
  373. WHILE hy > 0 DO INC(SY); hy := hy - 2 * DH END;
  374. INC(DY); hy := hy + 2*SH
  375. END
  376. ELSE
  377. HALT(99)
  378. END
  379. END Copy;
  380. PROCEDURE PutLine*(B: Bitmap; VAR data: ARRAY OF INTEGER; X, Y, W: INTEGER);
  381. VAR dst, src: ADDRESS; i: LONGINT; ch: CHAR;
  382. BEGIN
  383. IF (X >= 0) & (X+W <= B.width) & (Y >= 0) & (Y < B.height) & (W <= LEN(data)) THEN
  384. src := ADDRESSOF(data[0]); dst := B.address + Y*B.wth + X; i := W;
  385. WHILE i > 0 DO
  386. SYSTEM.GET(src, ch); SYSTEM.PUT(dst, ch);
  387. INC(src, 2); INC(dst);
  388. DEC(i)
  389. END
  390. ELSE
  391. HALT(99)
  392. END
  393. END PutLine;
  394. PROCEDURE GetLine*(B: Bitmap; VAR data: ARRAY OF INTEGER; X, Y, W: INTEGER);
  395. VAR dst, src: ADDRESS; i: LONGINT; ch: CHAR;
  396. BEGIN
  397. IF (X >= 0) & (X+W <= B.width) & (Y >= 0) & (Y < B.height) & (W <= LEN(data)) THEN
  398. dst := ADDRESSOF(data[0]); src := B.address + Y*B.wth + X; i := W;
  399. WHILE i > 0 DO
  400. SYSTEM.GET(src, ch); SYSTEM.PUT(dst, ORD(ch));
  401. INC(src); INC(dst, 2);
  402. DEC(i)
  403. END
  404. ELSE
  405. HALT(99)
  406. END
  407. END GetLine;
  408. BEGIN
  409. NEW(buffer)
  410. END Bitmaps.