123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- (* 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 Snapshot IN Oberon; (** portable *) (* Native *)
- (**
- jm 10.7.95 / pjm 17.10.97
- Snapshot.Viewer * Make snapshot of viewer
- Snapshot.Document * Make snapshot of document
- Snapshot.Gadget * Make snapshot of marked gadget
- Snapshot.InsertViewer * Insert snapshot of viewer at caret
- Snapshot.InsertDocument * Insert snapshot of document at caret
- Snapshot.InsertGadget * Insert snapshot of marked gadget
- Snapshot.Screen Make snapshot of the screen
- *)
- (* known bugs: truecolor/hicolor is very slow *)
- IMPORT SYSTEM, Display, Display3, Effects, Objects, Oberon, Pictures, Gadgets,
- Documents, Viewers, Rembrandt, RembrandtDocs, Machine IN A2;
- TYPE
- PositionMsg = RECORD (Display.FrameMsg)
- FX, FY, FW, FH: INTEGER;
- END;
- VAR
- GetPixel: PROCEDURE (x, y: LONGINT): LONGINT;
- handle: Objects.Handler;
- base, maxy: LONGINT;
- pal: ARRAY 256 OF RECORD
- r, g, b: LONGINT
- END;
- rm, gm, bm, rs, gs: LONGINT;
- PROCEDURE CopyBlock(p: Pictures.Picture; x, y, w, h: INTEGER);
- VAR xi, yi: INTEGER;
- BEGIN
- FOR xi := x TO x+w-1 DO
- FOR yi := y TO y+h-1 DO
- Pictures.Dot(p, SHORT(GetPixel(xi, yi)), xi-x, yi-y, Display.replace)
- END
- END
- END CopyBlock;
- PROCEDURE InitPal(p: Pictures.Picture);
- VAR i, r, g, b: INTEGER;
- BEGIN
- FOR i := 0 TO 255 DO
- Pictures.GetColor(p, i, r, g, b);
- pal[i].r := r DIV (256 DIV rm);
- pal[i].g := g DIV (256 DIV gm);
- pal[i].b := b DIV (256 DIV bm)
- END
- END InitPal;
- PROCEDURE Border(obj: Rembrandt.Frame; flag: BOOLEAN);
- VAR M: Objects.AttrMsg;
- BEGIN
- M.id := Objects.set; M.class := Objects.Bool; M.b := flag; M.name := "Border"; M.res := -1;
- obj.handle(obj, M)
- END Border;
- (* Make a snapshot of any visual gadget. *)
- PROCEDURE SnapFrame*(F: Gadgets.Frame; VAR P: Pictures.Picture);
- VAR dlink: Objects.Object; D: Display.DisplayMsg; O: Display3.OverlapMsg;
- BEGIN
- Effects.OpenMenu(0, 0, F.W, F.H);
- D.id := Display.full; D.device := Display.screen;
- D.x := -F.X; D.y := -F.Y;
- dlink := F.dlink;
- O.M := NIL; O.res := -1; Objects.Stamp(O); F.handle(F, O); F.dlink := NIL;
- IF O.res >= 0 THEN
- D.res := -1; F.handle(F, D);
- F.dlink := dlink;
- NEW(P); Pictures.Create(P, F.W, F.H, 8);
- InitPal(P);
- CopyBlock(P, 0, 0, F.W, F.H)
- ELSE
- P := NIL
- END;
- Effects.CloseMenu
- END SnapFrame;
- PROCEDURE Viewer*;
- VAR V: Viewers.Viewer; P: Pictures.Picture;
- BEGIN
- V := Oberon.MarkedViewer();
- IF V # NIL THEN
- Oberon.RemoveMarks(V.X, V.Y, V.W, V.H);
- NEW(P); Pictures.Create(P, V.W, V.H, 8);
- InitPal(P);
- CopyBlock(P, V.X, V.Y, V.W, V.H);
- RembrandtDocs.OpenPict(P, "Snapshot.Pict")
- END
- END Viewer;
- PROCEDURE InsertViewer*;
- VAR V: Viewers.Viewer; P: Pictures.Picture; obj: Rembrandt.Frame;
- BEGIN
- V := Oberon.MarkedViewer();
- IF V # NIL THEN
- Oberon.RemoveMarks(V.X, V.Y, V.W, V.H);
- NEW(P); Pictures.Create(P, V.W, V.H, 8);
- InitPal(P);
- CopyBlock(P, V.X, V.Y, V.W, V.H);
- NEW(obj); Rembrandt.NewP(obj, P); Border(obj, FALSE);
- Gadgets.Integrate(obj);
- END
- END InsertViewer;
- PROCEDURE NewHandler(obj: Objects.Object; VAR M: Objects.ObjMsg);
- BEGIN
- WITH obj: Display.Frame DO
- IF M IS PositionMsg THEN
- WITH M: PositionMsg DO
- IF M.res < 0 THEN
- M.FX := M.x + obj.X; M.FY := M.y + obj.Y; M.FW := obj.W; M.FH := obj.H;
- M.res := 0
- END
- END
- ELSE handle(obj, M)
- END
- END
- END NewHandler;
- PROCEDURE Document*;
- VAR D: Documents.Document; M: PositionMsg; P: Pictures.Picture;
- BEGIN
- D := Documents.MarkedDoc();
- IF D # NIL THEN
- handle := D.handle;
- D.handle := NewHandler;
- M.F := D; Display.Broadcast(M);
- D.handle := handle;
- Oberon.RemoveMarks(M.FX, M.FY, M.FW, M.FH);
- NEW(P); Pictures.Create(P, M.FW, M.FH, 8);
- InitPal(P);
- CopyBlock(P, M.FX, M.FY, M.FW, M.FH);
- RembrandtDocs.OpenPict(P, "Snapshot.Pict")
- END
- END Document;
- PROCEDURE Gadget*;
- VAR D: Display.Frame; M: PositionMsg; P: Pictures.Picture;
- BEGIN
- D := Oberon.MarkedFrame();
- IF D # NIL THEN
- handle := D.handle;
- D.handle := NewHandler;
- M.F := D; Display.Broadcast(M);
- D.handle := handle;
- Oberon.RemoveMarks(M.FX, M.FY, M.FW, M.FH);
- NEW(P); Pictures.Create(P, M.FW, M.FH, 8);
- InitPal(P);
- CopyBlock(P, M.FX, M.FY, M.FW, M.FH);
- RembrandtDocs.OpenPict(P, "Snapshot.Pict")
- END
- END Gadget;
- PROCEDURE InsertDocument*;
- VAR D: Documents.Document; M: PositionMsg; P: Pictures.Picture; obj: Rembrandt.Frame;
- BEGIN
- D := Documents.MarkedDoc();
- IF D # NIL THEN
- handle := D.handle;
- D.handle := NewHandler;
- M.F := D; Display.Broadcast(M);
- D.handle := handle;
- Oberon.RemoveMarks(M.FX, M.FY, M.FW, M.FH);
- NEW(P); Pictures.Create(P, M.FW, M.FH, 8);
- InitPal(P);
- CopyBlock(P, M.FX, M.FY, M.FW, M.FH);
- NEW(obj); Rembrandt.NewP(obj, P); Border(obj, FALSE);
- Gadgets.Integrate(obj);
- END
- END InsertDocument;
- PROCEDURE InsertGadget*;
- VAR D: Display.Frame; M: PositionMsg; P: Pictures.Picture; obj: Rembrandt.Frame;
- BEGIN
- D := Oberon.MarkedFrame();
- IF D # NIL THEN
- handle := D.handle;
- D.handle := NewHandler;
- M.F := D; Display.Broadcast(M);
- D.handle := handle;
- Oberon.RemoveMarks(M.FX, M.FY, M.FW, M.FH);
- NEW(P); Pictures.Create(P, M.FW, M.FH, 8);
- InitPal(P);
- CopyBlock(P, M.FX, M.FY, M.FW, M.FH);
- NEW(obj); Rembrandt.NewP(obj, P); Border(obj, FALSE);
- Gadgets.Integrate(obj);
- END
- END InsertGadget;
- PROCEDURE Screen*;
- VAR
- P: Pictures.Picture;
- x, y: LONGINT;
- r, g, b, i: INTEGER;
- BEGIN
- NEW(P); Pictures.Create(P, Display.Width, Display.Height, 8);
- FOR i := 0 TO 255 DO
- Display.GetColor(i, r, g, b);
- Pictures.SetColor(P, i, r, g, b)
- END;
- FOR x := 0 TO Display.Width-1 DO
- FOR y := 0 TO Display.Height-1 DO
- Pictures.Dot(P, SHORT(GetPixel(x, y)), SHORT(x), SHORT(y), Display.replace)
- END
- END;
- RembrandtDocs.OpenPict(P, "Snapshot.Pict")
- END Screen;
- PROCEDURE BankGetPixelPlane(x, y: LONGINT): LONGINT; (* harry *)
- VAR offset, mask, col: LONGINT; pg: SET; byte: CHAR;
- BEGIN
- offset := y*80 + (x DIV 8); (* Setup the video page *)
- pg := SYSTEM.VAL(SET, offset DIV 10000H) * {0..3};
- pg := pg + LSH(pg, 4);
- Machine.Portout8(3CDH, CHR(SYSTEM.VAL(LONGINT, pg)));
- offset := offset MOD 10000H;
- mask := LSH(80H, -(x MOD 8));
- Machine.Portout8(3CEH, 8X); (* Select bit *)
- Machine.Portout8(3CFH, CHR(mask));
- col := 0; INC(offset, base);
- Machine.Portout8(3CEH, 4X); (* Select plane 0 *)
- Machine.Portout8(3CFH, 0X);
- SYSTEM.GET(offset, byte);
- IF SYSTEM.VAL(SET, byte) * SYSTEM.VAL(SET, mask) # {} THEN INC(col, 1) END;
- Machine.Portout8(3CEH, 4X); (* Select plane 1 *)
- Machine.Portout8(3CFH, 1X);
- SYSTEM.GET(offset, byte);
- IF SYSTEM.VAL(SET, byte) * SYSTEM.VAL(SET, mask) # {} THEN INC(col, 2) END;
- Machine.Portout8(3CEH, 4X); (* Select plane 2 *)
- Machine.Portout8(3CFH, 2X);
- SYSTEM.GET(offset, byte);
- IF SYSTEM.VAL(SET, byte) * SYSTEM.VAL(SET, mask) # {} THEN INC(col, 4) END;
- Machine.Portout8(3CEH, 4X); (* Select plane 3 *)
- Machine.Portout8(3CFH, 3X);
- SYSTEM.GET(offset, byte);
- IF SYSTEM.VAL(SET, byte) * SYSTEM.VAL(SET, mask) # {} THEN INC(col, 8) END;
- RETURN col
- END BankGetPixelPlane;
- PROCEDURE BankGetPixel(x, y: LONGINT): LONGINT; (* harry *)
- VAR offset: LONGINT; byte: CHAR; pg: SET;
- BEGIN
- offset := y*Display.Width + x;
- pg := SYSTEM.VAL(SET, offset DIV 10000H) * {0..3};
- pg := pg + LSH(pg, 4);
- Machine.Portout8(3CDH, CHR(SYSTEM.VAL(LONGINT, pg)));
- SYSTEM.GET(base + offset MOD 010000H, byte);
- RETURN ORD(byte)
- END BankGetPixel;
- PROCEDURE LinearGetPixel(x, y: LONGINT): LONGINT;
- VAR ch: CHAR;
- BEGIN
- SYSTEM.GET(base + (maxy-y) * Display.Width + x, ch);
- RETURN ORD(ch)
- END LinearGetPixel;
- PROCEDURE TransferGetPixel8(x, y: LONGINT): LONGINT;
- VAR buf: ARRAY 4 OF CHAR;
- BEGIN
- Display.TransferBlock(buf, 0, 0, x, y, 1, 1, Display.get);
- RETURN ORD(buf[0])
- END TransferGetPixel8;
- PROCEDURE TransferGetPixel(x, y: LONGINT): LONGINT; (* very slow! *)
- TYPE Arr4 = ARRAY 4 OF CHAR;
- VAR col, r, g, b, r1, g1, b1, i, j, d, m: LONGINT;
- BEGIN
- Display.TransferBlock(SYSTEM.VAL(Arr4, col), 0, 0, x, y, 1, 1, Display.get);
- r := ASH(col, rs) MOD rm;
- g := ASH(col, gs) MOD gm;
- b := col MOD bm;
- m := MAX(LONGINT);
- FOR i := 0 TO 255 DO
- r1 := pal[i].r - r; g1 := pal[i].g - g; b1 := pal[i].b - b;
- d := r1*r1 + g1*g1 + b1*b1;
- IF d < m THEN j := i; m := d END
- END;
- RETURN j
- END TransferGetPixel;
- PROCEDURE Init;
- VAR format: LONGINT;
- BEGIN
- rm := 256; gm := 256; bm := 256;
- maxy := Display.Height-1;
- GetPixel := NIL;
- format := Display.TransferFormat(0);
- IF format = Display.index8 THEN
- GetPixel := TransferGetPixel8
- ELSIF format # Display.unknown THEN
- CASE format OF
- |Display.color555: rm := 32; gm := 32; bm := 32; rs := -10; gs := -5
- |Display.color565: rm := 32; gm := 64; bm := 32; rs := -11; gs := -5
- |Display.color664: rm := 64; gm := 64; bm := 16; rs := -10; gs := -4
- |Display.color888, Display.color8888: rm := 256; gm := 256; bm := 256; rs := -16; gs := -8
- END;
- GetPixel := TransferGetPixel
- ELSE
- base := Display.Map(0);
- IF (base > 0) & (base < 1000000H) THEN
- IF Display.Width = 640 THEN GetPixel := BankGetPixelPlane
- ELSE GetPixel := BankGetPixel
- END
- ELSIF base # 0 THEN
- GetPixel := LinearGetPixel
- ELSE
- (* skip *)
- END
- END
- END Init;
- BEGIN
- Init
- END Snapshot.
- Snapshot.Screen
- Snapshot.Gadget *
|