123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- (* ETH Oberon, Copyright 2001 ETH Zuerich Institut fuer Computersysteme, ETH Zentrum, CH-8092 Zuerich.
- Refer to the "General ETH Oberon System Source License" contract available at: http://www.oberon.ethz.ch/ *)
- MODULE Bitmaps IN Oberon; (** non-portable *)
- (* as 20.02.99, ported to Shark Oberon *)
- (* to do:
- o get rid of buffer
- o ASSERT bounds everywhere
- *)
- IMPORT SYSTEM, Display;
- CONST
- BufSize = 10000H;
- Assembler = TRUE;
- TYPE
- Bitmap* = POINTER TO BitmapDesc;
- BitmapDesc* = RECORD (* cf. Display.DisplayBlock *)
- width*, height*, depth*: INTEGER; (* offset 0, 2, 4 *)
- wth*, size: LONGINT; (* offset 8, 12 *)
- address*: ADDRESS; (* offset 16 *)
- END;
- Buffer = RECORD bytes: ARRAY BufSize OF CHAR END;
- VAR
- buffer: POINTER TO Buffer;
- PROCEDURE Define*(B: Bitmap; width, height, depth: INTEGER; address: ADDRESS);
- BEGIN
- B.width := width;
- B.wth := width;
- B.height := height;
- B.depth := depth;
- B.address := address;
- B.size := LONG(width)*height
- END Define;
- PROCEDURE Get*(B: Bitmap; X, Y: INTEGER): INTEGER;
- VAR ofs: LONGINT; ch: CHAR;
- BEGIN
- ofs := Y*B.wth + X; ASSERT((ofs >= 0) & (ofs < B.size));
- SYSTEM.GET(B.address + ofs, ch);
- RETURN ORD(ch)
- END Get;
- PROCEDURE Clear*(B: Bitmap);
- VAR adr: ADDRESS; size: LONGINT;
- BEGIN
- size := B.size; adr := B.address;
- WHILE size >= 4 DO
- SYSTEM.PUT(adr, SYSTEM.VAL(LONGINT, 0));
- INC(adr, 4); DEC(size, 4)
- END;
- WHILE size > 0 DO SYSTEM.PUT(adr, 0X); INC(adr); DEC(size) END
- END Clear;
- PROCEDURE Dot*(B: Bitmap; col, X, Y, mode: INTEGER);
- VAR adr: ADDRESS; ch: CHAR;
- BEGIN
- adr := Y*B.wth + X; ASSERT((adr >= 0) & (adr < B.size));
- INC(adr, B.address);
- IF mode = Display.invert THEN
- SYSTEM.GET(adr, ch);
- SYSTEM.PUT(adr, CHR(SYSTEM.VAL(LONGINT,
- SYSTEM.VAL(SET, LONG(ORD(ch))) / SYSTEM.VAL(SET, LONG(col)))))
- ELSE
- SYSTEM.PUT(adr, CHR(col))
- END
- END Dot;
- PROCEDURE CopyBlock0(n, w: LONGINT; adr: ADDRESS; buf: ADDRESS; width: LONGINT; from: BOOLEAN);
- BEGIN
- IF from THEN
- REPEAT SYSTEM.MOVE(adr, buf, w); DEC(n); INC(adr, width); INC(buf, w) UNTIL n = 0
- ELSE
- REPEAT SYSTEM.MOVE(buf, adr, w); DEC(n); INC(adr, width); INC(buf, w) UNTIL n = 0
- END
- END CopyBlock0;
- PROCEDURE CopyBlock*(sB, dB: Bitmap; SX, SY, W, H, DX, DY, mode: INTEGER);
- VAR SourceWth, DestWth, sx, sy, w, h, dx, dy, w0, h0, dx0, dy0, src, dst, n, bufLines: LONGINT;
- BEGIN (* only the destination block is clipped *)
- SourceWth := sB.wth; DestWth := dB.wth;
- sx := SX; sy := SY; w := W; h := H; dx := DX; dy := DY;
- w0 := w; h0 := h; dx0 := dx; dy0 := dy;
- IF dx < 0 THEN dx := 0; DEC(w, dx-dx0) END;
- IF dy < 0 THEN dy := 0; DEC(h, dy-dy0) END;
- IF (w > 0) & (h > 0) & (w <= w0) & (h <= h0) THEN
- IF dx+w-1 > dB.width-1 THEN DEC(w, dx+w-1 - (dB.width-1)) END;
- IF dy+h-1 > dB.height-1 THEN DEC(h, dy+h-1 - (dB.height-1)) END;
- IF (w > 0) & (h > 0) & (w <= w0) & (h <= h0) THEN
- src := sy*SourceWth + sx; ASSERT((src >= 0) & (src < sB.size));
- dst := dy*DestWth + dx; ASSERT((dst >= 0) & (dst < dB.size));
- bufLines := BufSize DIV w; (* lines to copy at a time *)
- IF bufLines > h THEN bufLines := h END;
- (* adjust direction for overlap *)
- IF (dy-h+1 < sy) & (sy < dy) THEN (* start at bottom *)
- n := h-bufLines;
- INC(src, SourceWth*n); INC(dst, DestWth*n);
- REPEAT
- CopyBlock0(bufLines, w, sB.address+src, ADDRESSOF(buffer.bytes[0]), SourceWth, TRUE);
- CopyBlock0(bufLines, w, dB.address+dst, ADDRESSOF(buffer.bytes[0]), DestWth, FALSE);
- DEC(h, bufLines);
- IF bufLines > h THEN bufLines := h END;
- DEC(src, bufLines * SourceWth); DEC(dst, bufLines * DestWth)
- UNTIL h = 0
- ELSE (* start at top *)
- REPEAT
- CopyBlock0(bufLines, w, sB.address+src, ADDRESSOF(buffer.bytes[0]), SourceWth, TRUE);
- CopyBlock0(bufLines, w, dB.address+dst, ADDRESSOF(buffer.bytes[0]), DestWth, FALSE);
- INC(src, bufLines * SourceWth); INC(dst, bufLines * DestWth);
- DEC(h, bufLines);
- IF bufLines > h THEN bufLines := h END
- UNTIL h = 0
- END
- END
- END
- END CopyBlock;
- PROCEDURE CopyPattern0(ofs: LONGINT; src, dst: ADDRESS; w, col, mode: LONGINT);
- VAR ch: CHAR; m, i: LONGINT; s: SET;
- BEGIN
- IF mode = Display.invert THEN
- REPEAT (* loop over w pixels *)
- SYSTEM.GET(src, ch);
- i := ofs; (* start bit *)
- m := 8; (* stop bit *)
- IF m > ofs+w THEN m := ofs+w END;
- REPEAT (* loop over bits *)
- IF ODD(ASH(ORD(ch), -i)) THEN (* pixel on *)
- SYSTEM.GET(dst, SYSTEM.VAL(CHAR, s));
- SYSTEM.PUT(dst, CHR(SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, col) / s)))
- END;
- INC(dst); INC(i)
- UNTIL i = m;
- INC(src); DEC(w, m-ofs); ofs := 0
- UNTIL w = 0
- ELSE (* paint, replace *)
- REPEAT (* loop over w pixels *)
- SYSTEM.GET(src, ch);
- i := ofs; (* start bit *)
- m := 8; (* stop bit *)
- IF m > ofs+w THEN m := ofs+w END;
- REPEAT (* loop over bits *)
- IF ODD(ASH(ORD(ch), -i)) THEN (* pixel on *)
- (* paint & replace *)
- SYSTEM.PUT(dst, CHR(col))
- ELSIF mode = Display.replace THEN (* pixel off *)
- SYSTEM.PUT(dst, CHR(Display.BG))
- ELSE (* skip *)
- END;
- INC(dst); INC(i)
- UNTIL i = m;
- INC(src); DEC(w, m-ofs); ofs := 0
- UNTIL w = 0
- END;
- END CopyPattern0;
- PROCEDURE CopyPattern1(B: Bitmap; src: ADDRESS; x, y, w, col, mode: LONGINT);
- VAR ch: CHAR; m, i: LONGINT;
- BEGIN
- IF (y < 0) OR (y > B.height-1) THEN RETURN END;
- REPEAT (* loop over w pixels *)
- SYSTEM.GET(src, ch);
- i := 0; (* start bit *)
- m := 8; (* stop bit *)
- IF m > w THEN m := w END;
- REPEAT (* loop over bits *)
- IF ODD(ASH(ORD(ch), -i)) THEN (* pixel on *)
- Dot(B,SHORT(col), SHORT(x), SHORT(y), SHORT(mode))
- ELSIF mode = Display.replace THEN (* pixel off *)
- Dot(B,Display.BG, SHORT(x), SHORT(y), Display.replace)
- ELSE (* skip *)
- END;
- INC(x); INC(i)
- UNTIL i = m;
- INC(src); DEC(w, m)
- UNTIL w = 0
- END CopyPattern1;
- PROCEDURE CopyPattern*(B: Bitmap; col: INTEGER; pat: Display.Pattern; X, Y, mode: INTEGER);
- VAR x, y, x2, y2, w, w0, h: LONGINT; src, dst: ADDRESS; ch: CHAR;
- BEGIN
- SYSTEM.GET(pat, ch); w := ORD(ch);
- SYSTEM.GET(pat+1, ch); h := ORD(ch);
- IF (w > 0) & (h > 0) THEN
- x := X; y := Y; x2 := x+w-1; y2 := y+h-1; (* (x,y) bottom left & (x2,y2) top right *)
- src := pat+2; (* first line of pattern *)
- w0 := (w+7) DIV 8; (* bytes in pattern line *)
- IF (x >= 0) & (y >= 0) & (x2 < B.width) & (y2 < B.height) THEN (* fully visible - common case *)
- dst := y * B.wth + x + B.address;
- REPEAT (* loop over h lines *)
- CopyPattern0(0, src, dst, w, col, mode);
- DEC(h); INC(dst, B.wth); INC(src, w0)
- UNTIL h = 0
- ELSIF (x2 >= 0) & (y2 >= 0) & (x < B.width) & (y < B.height) THEN (* partially visible *)
- REPEAT (* loop over h lines *)
- CopyPattern1(B, src, x, y, w, col, mode);
- INC(y); INC(src, w0); DEC(h)
- UNTIL h = 0
- ELSE (* invisible *)
- END
- END
- END CopyPattern;
- PROCEDURE ReplConst*(B: Bitmap; col, X, Y, W, H, mode: INTEGER);
- VAR addr, addr0: ADDRESS; pat, w: LONGINT; s: SET;
- BEGIN
- addr := B.address + B.wth*Y + X;
- pat := col + ASH(col, 8) + ASH(col, 16) + ASH(col, 24);
- IF mode = Display.invert THEN
- WHILE H > 0 DO w := W; addr0 := addr;
- WHILE w # 0 DO
- SYSTEM.GET(addr0, SYSTEM.VAL(CHAR,s));
- SYSTEM.PUT(addr0, CHR(SYSTEM.VAL(LONGINT, s/SYSTEM.VAL(SET, col))));
- DEC(w); INC(addr0)
- END;
- INC(addr, B.wth); DEC(H)
- END
- ELSE
- WHILE H > 0 DO w := W; addr0 := addr;
- WHILE w # 0 DO SYSTEM.PUT(addr0, CHR(col)); DEC(w); INC(addr0) END;
- INC(addr, B.wth); DEC(H)
- END
- END;
- END ReplConst;
- PROCEDURE FillPattern0(ofs: LONGINT; src, dst: ADDRESS; w, pw, col, mode: LONGINT);
- VAR ch: CHAR; m, i: LONGINT; src0: ADDRESS; left: LONGINT; s: SET;
- BEGIN
- left := pw-ofs; (* pixels left to do in pattern *)
- src0 := src; INC(src, ofs DIV 8); ofs := ofs MOD 8; (* start position *)
- IF mode = Display.invert THEN
- REPEAT (* loop over w pixels *)
- SYSTEM.GET(src, ch);
- i := ofs; (* start bit *)
- m := 8; (* stop bit *)
- IF m > ofs+left THEN m := ofs+left END; (* max left times *)
- IF m > ofs+w THEN m := ofs+w END; (* max w times *)
- REPEAT (* loop over bits *)
- IF ODD(ASH(ORD(ch), -i)) THEN (* pixel on *)
- SYSTEM.GET(dst, SYSTEM.VAL(CHAR, s));
- SYSTEM.PUT(dst, CHR(SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, col) / s)))
- END;
- INC(dst); INC(i)
- UNTIL i = m;
- INC(src); DEC(left, m-ofs); DEC(w, m-ofs); ofs := 0;
- IF left = 0 THEN src := src0; left := pw END (* wrap to start of pattern *)
- UNTIL w = 0
- ELSIF mode = Display.paint THEN
- REPEAT (* loop over w pixels *)
- SYSTEM.GET(src, ch);
- i := ofs; (* start bit *)
- m := 8; (* stop bit *)
- IF m > ofs+left THEN m := ofs+left END; (* max left times *)
- IF m > ofs+w THEN m := ofs+w END; (* max w times *)
- REPEAT (* loop over bits *)
- IF ODD(ASH(ORD(ch), -i)) THEN (* pixel on *)
- SYSTEM.PUT(dst, CHR(col))
- END;
- INC(dst); INC(i)
- UNTIL i = m;
- INC(src); DEC(left, m-ofs); DEC(w, m-ofs); ofs := 0;
- IF left = 0 THEN src := src0; left := pw END (* wrap to start of pattern *)
- UNTIL w = 0
- ELSE (* replace *)
- REPEAT (* loop over w pixels *)
- SYSTEM.GET(src, ch);
- i := ofs; (* start bit *)
- m := 8; (* stop bit *)
- IF m > ofs+left THEN m := ofs+left END; (* max left times *)
- IF m > ofs+w THEN m := ofs+w END; (* max w times *)
- REPEAT (* loop over bits *)
- IF ODD(ASH(ORD(ch), -i)) THEN (* pixel on *)
- SYSTEM.PUT(dst, CHR(col))
- ELSE (* pixel off *)
- SYSTEM.PUT(dst, CHR(Display.BG))
- END;
- INC(dst); INC(i)
- UNTIL i = m;
- INC(src); DEC(left, m-ofs); DEC(w, m-ofs); ofs := 0;
- IF left = 0 THEN src := src0; left := pw END (* wrap to start of pattern *)
- UNTIL w = 0
- END
- END FillPattern0;
- PROCEDURE ReplPattern*(B: Bitmap; col: INTEGER; pat: LONGINT; X, Y, W, H, mode: INTEGER);
- VAR px, pw, ph, x, y, x2, y2, w, w0, h: LONGINT; src0, src, dst: ADDRESS; ch: CHAR;
- BEGIN
- x := X; y := Y; w := W; h := H;
- x2 := x+w-1; y2 := y+h-1; (* (x,y) bottom left & (x2,y2) top right *)
- IF (w > 0) & (h > 0) THEN
- SYSTEM.GET(pat, ch); pw := ORD(ch);
- SYSTEM.GET(pat+1, ch); ph := ORD(ch);
- IF (pw > 0) & (ph > 0) THEN
- INC(pat, 2); (* adr of bitmap *)
- w0 := (pw+7) DIV 8; (* bytes in pattern line *)
- src0 := pat + (ph-1)*w0; (* last line of pattern *)
- src := pat; (* start line of pattern *)
- px := x MOD pw; (* start pixel offset *)
- dst := y * B.wth + x + B.address;
- REPEAT (* loop over h lines *)
- FillPattern0(px, src, dst, w, pw, col, mode);
- DEC(h); INC(dst, B.wth);
- IF src = src0 THEN src := pat ELSE INC(src, w0) END
- UNTIL h = 0
- END
- END
- END ReplPattern;
- PROCEDURE DisplayBlock*(B: Bitmap; SX, SY, W, H, DX, DY, mode: INTEGER; VAR colortable: ARRAY OF LONGINT (* fof *));
- BEGIN
- Display.DisplayBlock(B, SX, SY, W, H, DX, DY, mode,colortable);
- END DisplayBlock;
- PROCEDURE GetPix*(VAR addr: ADDRESS; VAR buf: SYSTEM.BYTE; depth: INTEGER);
- VAR s1, s2, s3: SHORTINT;
- BEGIN
- IF depth = 8 THEN SYSTEM.GET(addr, buf); INC(addr)
- ELSIF depth = 4 THEN
- SYSTEM.GET(addr, s1); INC(addr); SYSTEM.GET(addr, s2); INC(addr); buf := s2*16 + (s1 MOD 16)
- ELSE (* depth = 1 *)
- s1 := 0; s2 := 0;
- WHILE s1 < 8 DO SYSTEM.GET(addr, s3); INC(addr); INC(s1); s2 := s2*2 + s3 MOD 2 END; buf := s2
- END;
- END GetPix;
- PROCEDURE PutPix*(VAR addr: ADDRESS; border: ADDRESS; buf: SYSTEM.BYTE; depth: INTEGER);
- VAR s1: SHORTINT;
- BEGIN
- IF (depth = 8) & (addr < border) THEN SYSTEM.PUT(addr, buf); INC(addr)
- ELSIF depth = 4 THEN
- IF addr < border THEN SYSTEM.PUT(addr, SYSTEM.VAL(SHORTINT, buf) MOD 16); INC(addr) END;
- IF addr < border THEN SYSTEM.PUT(addr, SYSTEM.VAL(SHORTINT, buf) DIV 16 MOD 16); INC(addr) END;
- ELSE (* depth = 1 *)
- s1 := 0;
- WHILE s1 < 8 DO
- IF addr < border THEN
- IF ODD(SYSTEM.VAL(SHORTINT, buf)) THEN SYSTEM.PUT(addr, 15) ELSE SYSTEM.PUT(addr, 0) END
- END;
- INC(s1); INC(addr); buf := SYSTEM.VAL(SHORTINT, buf) DIV 2;
- END
- END;
- END PutPix;
- PROCEDURE -Copy0(src, dst: ADDRESS; hx, sw2, dw2: LONGINT);
- CODE {SYSTEM.AMD64}
- POP EDX ; dw2
- POP ECX ; sw2
- POP EBX ; hx
- POP RDI ; dst
- POP RSI ; src
- MOV EAX, EDX
- SHR EAX, 1
- PUSH EAX ; count
- for:
- MOV AL, [RSI]
- MOV [RDI], AL
- JMP while1
- while0:
- INC RSI
- SUB EBX, EDX
- while1:
- CMP EBX, 0
- JG while0
- INC RDI
- ADD EBX, ECX
- DEC DWORD [RSP]
- JNZ for
- POP EAX
- END Copy0;
- PROCEDURE Copy*(sB, dB: Bitmap; SX, SY, SW, SH, DX, DY, DW, DH, mode: INTEGER);
- VAR hx, hy, DW2, SW2: LONGINT; src, dst: ADDRESS; i: LONGINT; dy: INTEGER; ch: CHAR;
- BEGIN
- IF (SX >= 0) & (SY >= 0) & (SX+SW <= sB.width) & (SY+SH <= sB.height) &
- (DX >= 0) & (DY >= 0) & (DX+DW <= dB.width) & (DY+DH <= dB.height) &
- (SW > 0) & (SH > 0) & (DW > 0) & (DH > 0) THEN
- dy := DY + DH; DW2 := 2 * DW; SW2 := 2 * SW;
- hy := 2*SH - DH;
- WHILE DY < dy DO
- IF Assembler THEN
- Copy0(sB.address + SY*sB.wth + SX, dB.address + DY*dB.wth + DX, 2*SW - DW, SW2, DW2)
- ELSE
- hx := 2*SW - DW;
- src := sB.address + SY*sB.wth + SX;
- dst := dB.address + DY*dB.wth + DX;
- FOR i := 1 TO DW DO
- SYSTEM.GET(src, ch); SYSTEM.PUT(dst, ch);
- WHILE hx > 0 DO INC(src); DEC(hx, DW2) END;
- INC(dst); INC(hx, SW2)
- END
- END;
- WHILE hy > 0 DO INC(SY); hy := hy - 2 * DH END;
- INC(DY); hy := hy + 2*SH
- END
- ELSE
- HALT(99)
- END
- END Copy;
- PROCEDURE PutLine*(B: Bitmap; VAR data: ARRAY OF INTEGER; X, Y, W: INTEGER);
- VAR dst, src: ADDRESS; i: LONGINT; ch: CHAR;
- BEGIN
- IF (X >= 0) & (X+W <= B.width) & (Y >= 0) & (Y < B.height) & (W <= LEN(data)) THEN
- src := ADDRESSOF(data[0]); dst := B.address + Y*B.wth + X; i := W;
- WHILE i > 0 DO
- SYSTEM.GET(src, ch); SYSTEM.PUT(dst, ch);
- INC(src, 2); INC(dst);
- DEC(i)
- END
- ELSE
- HALT(99)
- END
- END PutLine;
- PROCEDURE GetLine*(B: Bitmap; VAR data: ARRAY OF INTEGER; X, Y, W: INTEGER);
- VAR dst, src: ADDRESS; i: LONGINT; ch: CHAR;
- BEGIN
- IF (X >= 0) & (X+W <= B.width) & (Y >= 0) & (Y < B.height) & (W <= LEN(data)) THEN
- dst := ADDRESSOF(data[0]); src := B.address + Y*B.wth + X; i := W;
- WHILE i > 0 DO
- SYSTEM.GET(src, ch); SYSTEM.PUT(dst, ORD(ch));
- INC(src); INC(dst, 2);
- DEC(i)
- END
- ELSE
- HALT(99)
- END
- END GetLine;
- BEGIN
- NEW(buffer)
- END Bitmaps.
|