BIOS.Oberon.Snapshot.Mod 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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 Snapshot IN Oberon; (** portable *) (* Native *)
  4. (**
  5. jm 10.7.95 / pjm 17.10.97
  6. Snapshot.Viewer * Make snapshot of viewer
  7. Snapshot.Document * Make snapshot of document
  8. Snapshot.Gadget * Make snapshot of marked gadget
  9. Snapshot.InsertViewer * Insert snapshot of viewer at caret
  10. Snapshot.InsertDocument * Insert snapshot of document at caret
  11. Snapshot.InsertGadget * Insert snapshot of marked gadget
  12. Snapshot.Screen Make snapshot of the screen
  13. *)
  14. (* known bugs: truecolor/hicolor is very slow *)
  15. IMPORT SYSTEM, Display, Display3, Effects, Objects, Oberon, Pictures, Gadgets,
  16. Documents, Viewers, Rembrandt, RembrandtDocs, Machine IN A2;
  17. TYPE
  18. PositionMsg = RECORD (Display.FrameMsg)
  19. FX, FY, FW, FH: INTEGER;
  20. END;
  21. VAR
  22. GetPixel: PROCEDURE (x, y: LONGINT): LONGINT;
  23. handle: Objects.Handler;
  24. base, maxy: LONGINT;
  25. pal: ARRAY 256 OF RECORD
  26. r, g, b: LONGINT
  27. END;
  28. rm, gm, bm, rs, gs: LONGINT;
  29. PROCEDURE CopyBlock(p: Pictures.Picture; x, y, w, h: INTEGER);
  30. VAR xi, yi: INTEGER;
  31. BEGIN
  32. FOR xi := x TO x+w-1 DO
  33. FOR yi := y TO y+h-1 DO
  34. Pictures.Dot(p, SHORT(GetPixel(xi, yi)), xi-x, yi-y, Display.replace)
  35. END
  36. END
  37. END CopyBlock;
  38. PROCEDURE InitPal(p: Pictures.Picture);
  39. VAR i, r, g, b: INTEGER;
  40. BEGIN
  41. FOR i := 0 TO 255 DO
  42. Pictures.GetColor(p, i, r, g, b);
  43. pal[i].r := r DIV (256 DIV rm);
  44. pal[i].g := g DIV (256 DIV gm);
  45. pal[i].b := b DIV (256 DIV bm)
  46. END
  47. END InitPal;
  48. PROCEDURE Border(obj: Rembrandt.Frame; flag: BOOLEAN);
  49. VAR M: Objects.AttrMsg;
  50. BEGIN
  51. M.id := Objects.set; M.class := Objects.Bool; M.b := flag; M.name := "Border"; M.res := -1;
  52. obj.handle(obj, M)
  53. END Border;
  54. (* Make a snapshot of any visual gadget. *)
  55. PROCEDURE SnapFrame*(F: Gadgets.Frame; VAR P: Pictures.Picture);
  56. VAR dlink: Objects.Object; D: Display.DisplayMsg; O: Display3.OverlapMsg;
  57. BEGIN
  58. Effects.OpenMenu(0, 0, F.W, F.H);
  59. D.id := Display.full; D.device := Display.screen;
  60. D.x := -F.X; D.y := -F.Y;
  61. dlink := F.dlink;
  62. O.M := NIL; O.res := -1; Objects.Stamp(O); F.handle(F, O); F.dlink := NIL;
  63. IF O.res >= 0 THEN
  64. D.res := -1; F.handle(F, D);
  65. F.dlink := dlink;
  66. NEW(P); Pictures.Create(P, F.W, F.H, 8);
  67. InitPal(P);
  68. CopyBlock(P, 0, 0, F.W, F.H)
  69. ELSE
  70. P := NIL
  71. END;
  72. Effects.CloseMenu
  73. END SnapFrame;
  74. PROCEDURE Viewer*;
  75. VAR V: Viewers.Viewer; P: Pictures.Picture;
  76. BEGIN
  77. V := Oberon.MarkedViewer();
  78. IF V # NIL THEN
  79. Oberon.RemoveMarks(V.X, V.Y, V.W, V.H);
  80. NEW(P); Pictures.Create(P, V.W, V.H, 8);
  81. InitPal(P);
  82. CopyBlock(P, V.X, V.Y, V.W, V.H);
  83. RembrandtDocs.OpenPict(P, "Snapshot.Pict")
  84. END
  85. END Viewer;
  86. PROCEDURE InsertViewer*;
  87. VAR V: Viewers.Viewer; P: Pictures.Picture; obj: Rembrandt.Frame;
  88. BEGIN
  89. V := Oberon.MarkedViewer();
  90. IF V # NIL THEN
  91. Oberon.RemoveMarks(V.X, V.Y, V.W, V.H);
  92. NEW(P); Pictures.Create(P, V.W, V.H, 8);
  93. InitPal(P);
  94. CopyBlock(P, V.X, V.Y, V.W, V.H);
  95. NEW(obj); Rembrandt.NewP(obj, P); Border(obj, FALSE);
  96. Gadgets.Integrate(obj);
  97. END
  98. END InsertViewer;
  99. PROCEDURE NewHandler(obj: Objects.Object; VAR M: Objects.ObjMsg);
  100. BEGIN
  101. WITH obj: Display.Frame DO
  102. IF M IS PositionMsg THEN
  103. WITH M: PositionMsg DO
  104. IF M.res < 0 THEN
  105. M.FX := M.x + obj.X; M.FY := M.y + obj.Y; M.FW := obj.W; M.FH := obj.H;
  106. M.res := 0
  107. END
  108. END
  109. ELSE handle(obj, M)
  110. END
  111. END
  112. END NewHandler;
  113. PROCEDURE Document*;
  114. VAR D: Documents.Document; M: PositionMsg; P: Pictures.Picture;
  115. BEGIN
  116. D := Documents.MarkedDoc();
  117. IF D # NIL THEN
  118. handle := D.handle;
  119. D.handle := NewHandler;
  120. M.F := D; Display.Broadcast(M);
  121. D.handle := handle;
  122. Oberon.RemoveMarks(M.FX, M.FY, M.FW, M.FH);
  123. NEW(P); Pictures.Create(P, M.FW, M.FH, 8);
  124. InitPal(P);
  125. CopyBlock(P, M.FX, M.FY, M.FW, M.FH);
  126. RembrandtDocs.OpenPict(P, "Snapshot.Pict")
  127. END
  128. END Document;
  129. PROCEDURE Gadget*;
  130. VAR D: Display.Frame; M: PositionMsg; P: Pictures.Picture;
  131. BEGIN
  132. D := Oberon.MarkedFrame();
  133. IF D # NIL THEN
  134. handle := D.handle;
  135. D.handle := NewHandler;
  136. M.F := D; Display.Broadcast(M);
  137. D.handle := handle;
  138. Oberon.RemoveMarks(M.FX, M.FY, M.FW, M.FH);
  139. NEW(P); Pictures.Create(P, M.FW, M.FH, 8);
  140. InitPal(P);
  141. CopyBlock(P, M.FX, M.FY, M.FW, M.FH);
  142. RembrandtDocs.OpenPict(P, "Snapshot.Pict")
  143. END
  144. END Gadget;
  145. PROCEDURE InsertDocument*;
  146. VAR D: Documents.Document; M: PositionMsg; P: Pictures.Picture; obj: Rembrandt.Frame;
  147. BEGIN
  148. D := Documents.MarkedDoc();
  149. IF D # NIL THEN
  150. handle := D.handle;
  151. D.handle := NewHandler;
  152. M.F := D; Display.Broadcast(M);
  153. D.handle := handle;
  154. Oberon.RemoveMarks(M.FX, M.FY, M.FW, M.FH);
  155. NEW(P); Pictures.Create(P, M.FW, M.FH, 8);
  156. InitPal(P);
  157. CopyBlock(P, M.FX, M.FY, M.FW, M.FH);
  158. NEW(obj); Rembrandt.NewP(obj, P); Border(obj, FALSE);
  159. Gadgets.Integrate(obj);
  160. END
  161. END InsertDocument;
  162. PROCEDURE InsertGadget*;
  163. VAR D: Display.Frame; M: PositionMsg; P: Pictures.Picture; obj: Rembrandt.Frame;
  164. BEGIN
  165. D := Oberon.MarkedFrame();
  166. IF D # NIL THEN
  167. handle := D.handle;
  168. D.handle := NewHandler;
  169. M.F := D; Display.Broadcast(M);
  170. D.handle := handle;
  171. Oberon.RemoveMarks(M.FX, M.FY, M.FW, M.FH);
  172. NEW(P); Pictures.Create(P, M.FW, M.FH, 8);
  173. InitPal(P);
  174. CopyBlock(P, M.FX, M.FY, M.FW, M.FH);
  175. NEW(obj); Rembrandt.NewP(obj, P); Border(obj, FALSE);
  176. Gadgets.Integrate(obj);
  177. END
  178. END InsertGadget;
  179. PROCEDURE Screen*;
  180. VAR
  181. P: Pictures.Picture;
  182. x, y: LONGINT;
  183. r, g, b, i: INTEGER;
  184. BEGIN
  185. NEW(P); Pictures.Create(P, Display.Width, Display.Height, 8);
  186. FOR i := 0 TO 255 DO
  187. Display.GetColor(i, r, g, b);
  188. Pictures.SetColor(P, i, r, g, b)
  189. END;
  190. FOR x := 0 TO Display.Width-1 DO
  191. FOR y := 0 TO Display.Height-1 DO
  192. Pictures.Dot(P, SHORT(GetPixel(x, y)), SHORT(x), SHORT(y), Display.replace)
  193. END
  194. END;
  195. RembrandtDocs.OpenPict(P, "Snapshot.Pict")
  196. END Screen;
  197. PROCEDURE BankGetPixelPlane(x, y: LONGINT): LONGINT; (* harry *)
  198. VAR offset, mask, col: LONGINT; pg: SET; byte: CHAR;
  199. BEGIN
  200. offset := y*80 + (x DIV 8); (* Setup the video page *)
  201. pg := SYSTEM.VAL(SET, offset DIV 10000H) * {0..3};
  202. pg := pg + LSH(pg, 4);
  203. Machine.Portout8(3CDH, CHR(SYSTEM.VAL(LONGINT, pg)));
  204. offset := offset MOD 10000H;
  205. mask := LSH(80H, -(x MOD 8));
  206. Machine.Portout8(3CEH, 8X); (* Select bit *)
  207. Machine.Portout8(3CFH, CHR(mask));
  208. col := 0; INC(offset, base);
  209. Machine.Portout8(3CEH, 4X); (* Select plane 0 *)
  210. Machine.Portout8(3CFH, 0X);
  211. SYSTEM.GET(offset, byte);
  212. IF SYSTEM.VAL(SET, byte) * SYSTEM.VAL(SET, mask) # {} THEN INC(col, 1) END;
  213. Machine.Portout8(3CEH, 4X); (* Select plane 1 *)
  214. Machine.Portout8(3CFH, 1X);
  215. SYSTEM.GET(offset, byte);
  216. IF SYSTEM.VAL(SET, byte) * SYSTEM.VAL(SET, mask) # {} THEN INC(col, 2) END;
  217. Machine.Portout8(3CEH, 4X); (* Select plane 2 *)
  218. Machine.Portout8(3CFH, 2X);
  219. SYSTEM.GET(offset, byte);
  220. IF SYSTEM.VAL(SET, byte) * SYSTEM.VAL(SET, mask) # {} THEN INC(col, 4) END;
  221. Machine.Portout8(3CEH, 4X); (* Select plane 3 *)
  222. Machine.Portout8(3CFH, 3X);
  223. SYSTEM.GET(offset, byte);
  224. IF SYSTEM.VAL(SET, byte) * SYSTEM.VAL(SET, mask) # {} THEN INC(col, 8) END;
  225. RETURN col
  226. END BankGetPixelPlane;
  227. PROCEDURE BankGetPixel(x, y: LONGINT): LONGINT; (* harry *)
  228. VAR offset: LONGINT; byte: CHAR; pg: SET;
  229. BEGIN
  230. offset := y*Display.Width + x;
  231. pg := SYSTEM.VAL(SET, offset DIV 10000H) * {0..3};
  232. pg := pg + LSH(pg, 4);
  233. Machine.Portout8(3CDH, CHR(SYSTEM.VAL(LONGINT, pg)));
  234. SYSTEM.GET(base + offset MOD 010000H, byte);
  235. RETURN ORD(byte)
  236. END BankGetPixel;
  237. PROCEDURE LinearGetPixel(x, y: LONGINT): LONGINT;
  238. VAR ch: CHAR;
  239. BEGIN
  240. SYSTEM.GET(base + (maxy-y) * Display.Width + x, ch);
  241. RETURN ORD(ch)
  242. END LinearGetPixel;
  243. PROCEDURE TransferGetPixel8(x, y: LONGINT): LONGINT;
  244. VAR buf: ARRAY 4 OF CHAR;
  245. BEGIN
  246. Display.TransferBlock(buf, 0, 0, x, y, 1, 1, Display.get);
  247. RETURN ORD(buf[0])
  248. END TransferGetPixel8;
  249. PROCEDURE TransferGetPixel(x, y: LONGINT): LONGINT; (* very slow! *)
  250. TYPE Arr4 = ARRAY 4 OF CHAR;
  251. VAR col, r, g, b, r1, g1, b1, i, j, d, m: LONGINT;
  252. BEGIN
  253. Display.TransferBlock(SYSTEM.VAL(Arr4, col), 0, 0, x, y, 1, 1, Display.get);
  254. r := ASH(col, rs) MOD rm;
  255. g := ASH(col, gs) MOD gm;
  256. b := col MOD bm;
  257. m := MAX(LONGINT);
  258. FOR i := 0 TO 255 DO
  259. r1 := pal[i].r - r; g1 := pal[i].g - g; b1 := pal[i].b - b;
  260. d := r1*r1 + g1*g1 + b1*b1;
  261. IF d < m THEN j := i; m := d END
  262. END;
  263. RETURN j
  264. END TransferGetPixel;
  265. PROCEDURE Init;
  266. VAR format: LONGINT;
  267. BEGIN
  268. rm := 256; gm := 256; bm := 256;
  269. maxy := Display.Height-1;
  270. GetPixel := NIL;
  271. format := Display.TransferFormat(0);
  272. IF format = Display.index8 THEN
  273. GetPixel := TransferGetPixel8
  274. ELSIF format # Display.unknown THEN
  275. CASE format OF
  276. |Display.color555: rm := 32; gm := 32; bm := 32; rs := -10; gs := -5
  277. |Display.color565: rm := 32; gm := 64; bm := 32; rs := -11; gs := -5
  278. |Display.color664: rm := 64; gm := 64; bm := 16; rs := -10; gs := -4
  279. |Display.color888, Display.color8888: rm := 256; gm := 256; bm := 256; rs := -16; gs := -8
  280. END;
  281. GetPixel := TransferGetPixel
  282. ELSE
  283. base := Display.Map(0);
  284. IF (base > 0) & (base < 1000000H) THEN
  285. IF Display.Width = 640 THEN GetPixel := BankGetPixelPlane
  286. ELSE GetPixel := BankGetPixel
  287. END
  288. ELSIF base # 0 THEN
  289. GetPixel := LinearGetPixel
  290. ELSE
  291. (* skip *)
  292. END
  293. END
  294. END Init;
  295. BEGIN
  296. Init
  297. END Snapshot.
  298. Snapshot.Screen
  299. Snapshot.Gadget *