home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / jËzyki_programowania / oberon / system / pictures.mod (.txt) < prev    next >
Oberon Text  |  1977-12-31  |  35KB  |  922 lines

  1. Syntax10.Scn.Fnt
  2. ParcElems
  3. Alloc
  4. Syntax24b.Scn.Fnt
  5. StampElems
  6. Alloc
  7. 27 May 96
  8. Syntax10b.Scn.Fnt
  9. Syntax10i.Scn.Fnt
  10. Syntax20b.Scn.Fnt
  11. Syntax16b.Scn.Fnt
  12. (* AMIGA *)
  13. MODULE Pictures; (* cn, RD 
  14. IMPORT
  15.     SYSTEM,Amiga,Files,E:=AmigaExec,G:=AmigaGraphics,I:=AmigaIntuition,Kernel,AmigaLayers, O:=Console;
  16. CONST
  17.     black*=0; white*=15;
  18.     replace*=0; (* The new graphical object completely replaces whatever was before in the destination area. *)
  19.     paint*=1; (* The new graphical object is added to whatever was before in the dertination area. *)
  20.     invert*=2; (* The new graphical object inverts whatever was before in the dertination area. The color specifies, which planes are affected (inverted) and which aren't *)
  21.     PictFileId*=  - 4093;
  22.     BitMapPtr=POINTER TO G.BitMap;
  23.     LayerPtr=POINTER TO G.Layer;
  24.     RastPortPtr=POINTER TO G.RastPort;
  25.     WindowPtr=POINTER TO I.Window;
  26.     ScreenPtr=POINTER TO I.Screen;
  27.     ColMem=ARRAY 256 OF RECORD r, g, b: CHAR END;
  28.     Pattern*=LONGINT;
  29.     Picture*=POINTER TO PictureDesc;
  30.     Notifier*=PROCEDURE (P: Picture; X, Y, W, H : INTEGER);
  31.     PictureDesc*=RECORD
  32.         width*,height*,depth*:INTEGER;
  33.         XOff, YOff: INTEGER;
  34.         notify*:Notifier;
  35.         bitMap:G.BitMap; (* Used only in CreateLayer, FreeLayer; V<39*)
  36.         bitMapPtr:G.BitMapPtr; (* Used only in CreateLayer, FreeLayer; V>=39*)
  37.         layer:G.LayerPtr;
  38.         layerInfo: G.LayerInfoPtr; (* Used only in CreateLayer, FreeLayer *)
  39.         rp*: G.RastPortPtr;
  40.         pal: ColMem;
  41.         oldCol:INTEGER;
  42.         oldMode:INTEGER
  43.     END ;
  44.     Frame*=POINTER TO FrameDesc;
  45.     FrameMsg*=RECORD END;
  46.     Handler*=PROCEDURE (f: Frame; VAR msg: FrameMsg);
  47.     FrameDesc*=RECORD
  48.         dsc*, next*: Frame;
  49.         X*, Y*, W*, H*: INTEGER;
  50.         handle*: Handler
  51.     END;
  52.     PatternNode=POINTER TO RECORD
  53.         p: Amiga.PatternInfoPtr;
  54.         next: PatternNode
  55.     END;
  56.     dots*: Pattern;
  57.     ToPrint*: Picture;
  58.     rev: ARRAY 16 OF INTEGER;
  59.     defaultPicture:Picture;
  60.     nofCols:INTEGER;
  61.     patternRoot:PatternNode;
  62.     gfxBase:LONGINT;
  63.     swap: ARRAY 256 OF SYSTEM.BYTE;
  64.     DispColBuffer: ColMem;
  65. PROCEDURE SetDisplayColor*(col, red, green, blue: INTEGER); (*col < 0: overlay color not supported on the Amiga*)
  66.     Set the RGB values for a screen color.
  67.     scr:ScreenPtr;
  68.     win: WindowPtr;
  69. BEGIN
  70.     IF Amiga.ModifyColors & (col<nofCols) & (col>=0) THEN
  71.         win := SYSTEM.VAL(WindowPtr, Amiga.window);
  72.         scr := SYSTEM.VAL(ScreenPtr, win.wScreen);
  73.         IF G.gfxVersion<39 THEN
  74.             G.SetRGB4(
  75.                 SYSTEM.VAL(G.ViewPortPtr,SYSTEM.ADR(scr.viewPort)),(col MOD nofCols)+Amiga.ColorOffset,
  76.                 red DIV 16, green DIV 16,blue DIV 16)
  77.         ELSE
  78.             G.SetRGB32(
  79.                 SYSTEM.VAL(G.ViewPortPtr,SYSTEM.ADR(scr.viewPort)),(col MOD nofCols)+Amiga.ColorOffset,
  80.                 SYSTEM.LSH(LONG(red),24),SYSTEM.LSH(LONG(green),24),SYSTEM.LSH(LONG(blue),24)
  81.         END
  82. END SetDisplayColor;
  83. PROCEDURE GetDisplayColor*(col: INTEGER; VAR red, green, blue: INTEGER);
  84.     Return the RGB values for a screen color.
  85.     long:LONGINT;
  86.     rgbTable:RECORD r,g,b:LONGINT END;
  87.     scr:ScreenPtr;
  88.     win: WindowPtr;
  89. BEGIN
  90.     win := SYSTEM.VAL(WindowPtr, Amiga.window);
  91.     scr:=SYSTEM.VAL(ScreenPtr, win.wScreen);
  92.     IF G.gfxVersion<39 THEN
  93.         long:=G.GetRGB4(scr.viewPort.colorMap,(col MOD nofCols)+Amiga.ColorOffset);
  94.         red:=SHORT(long DIV 256 MOD 16)*17;
  95.         green:=SHORT(long DIV 16 MOD 16)*17;
  96.         blue:=SHORT(long MOD 16)*17
  97.     ELSE
  98.         G.GetRGB32(scr.viewPort.colorMap,(col MOD nofCols)+Amiga.ColorOffset,1,rgbTable);
  99.         red:=SHORT(SYSTEM.LSH(rgbTable.r,-24));
  100.         green:=SHORT(SYSTEM.LSH(rgbTable.g,-24));
  101.         blue:=SHORT(SYSTEM.LSH(rgbTable.b,-24))
  102. END GetDisplayColor;
  103. PROCEDURE ColorsToScreen(m: ColMem);
  104.     Copy colors from ColMem to screen
  105.     VAR i: INTEGER;
  106. BEGIN
  107.     FOR i:=0 TO nofCols-1 DO
  108.         SetDisplayColor(i, ORD(m[i].r), ORD(m[i].g), ORD(m[i].b))
  109.     END;
  110. END ColorsToScreen;
  111. PROCEDURE GetScreenColors(VAR m: ColMem);
  112.     Copy screen colors to ColMem
  113.     VAR i, r, g, b: INTEGER;
  114. BEGIN
  115.     FOR i:=0 TO nofCols-1 DO
  116.         GetDisplayColor(i, r, g, b);
  117.         m[i].r:=CHR(r); m[i].g:=CHR(g); m[i].b:=CHR(b)
  118.     END;
  119. END GetScreenColors;
  120. PROCEDURE UseOberonColors*(p: Picture);
  121.     Store current screen colors to DispColBuffer and copy colors of Picture p to screen
  122. BEGIN
  123.     GetScreenColors(DispColBuffer);
  124.     ColorsToScreen(p.pal)
  125. END UseOberonColors;
  126. PROCEDURE UseBufferedColors*;
  127.     Copy colors from DispColBuffer to screen
  128. BEGIN
  129.     ColorsToScreen(DispColBuffer)
  130. END UseBufferedColors;
  131. PROCEDURE InitLayer(pic:Picture);
  132.     Precondition: pic has already initialized depth, width and height fields.
  133.     Creates bitmap and layer.
  134.     VAR i:INTEGER;
  135.         l: LayerPtr;
  136.         rp: RastPortPtr;
  137. BEGIN
  138.     pic.layer:=0;
  139.     IF G.gfxVersion>=39 THEN
  140.         rp:=SYSTEM.VAL(RastPortPtr, defaultPicture.rp);
  141.         pic.bitMapPtr:=G.AllocBitMap(pic.width, pic.height, Amiga.Depth, {G.bmbClear}, rp.bitMap);
  142.             IF pic.bitMapPtr=0 THEN HALT(60) END;
  143.         pic.layerInfo:=AmigaLayers.NewLayerInfo();
  144.             IF pic.layerInfo=0 THEN HALT(65) END;
  145.         pic.layer:=AmigaLayers.CreateUpfrontLayer(
  146.             pic.layerInfo,pic.bitMapPtr,0,0,pic.width-1,pic.height-1,{G.layerSimple,G.layerBackdrop},0
  147.     ELSE
  148.         G.InitBitMap(pic.bitMap,Amiga.Depth,pic.width,pic.height);
  149.         i := 0;
  150.         WHILE i<Amiga.Depth DO
  151.             pic.bitMap.planes[i]:=G.AllocRaster(pic.width,pic.height);
  152.                 IF pic.bitMap.planes[i]=0 THEN HALT(60) END;
  153.             INC(i)
  154.         END;
  155.         pic.layerInfo:=AmigaLayers.NewLayerInfo();
  156.             IF pic.layerInfo=0 THEN HALT(60) END;
  157.         pic.layer:=AmigaLayers.CreateUpfrontLayer(
  158.             pic.layerInfo,SYSTEM.ADR(pic.bitMap),0,0,pic.width-1,pic.height-1,{G.layerSimple,G.layerBackdrop},0
  159.     END;
  160.     IF pic.layer=0 THEN HALT(70) END;
  161.     l:=SYSTEM.VAL(LayerPtr,pic.layer);
  162.     pic.rp:=l.rp;
  163. END InitLayer;
  164. PROCEDURE WindowToPicture*(window:I.WindowPtr; VAR pic:Picture);
  165.     Using this procedure you can create a picture which represents a windows
  166.     contents. This procedure is only intended for use by Display.
  167.     NOTE:
  168.         never reuse this picture in a Pictures.Create call!
  169.     bm:BitMapPtr;
  170.     i:INTEGER;
  171.     rp:RastPortPtr;
  172.     w:WindowPtr;
  173. BEGIN
  174.     w:=SYSTEM.VAL(WindowPtr,window);
  175.     NEW(pic);
  176.     pic.width:=w.width-w.borderLeft-w.borderRight;
  177.     pic.height:=w.height-w.borderTop-w.borderBottom;
  178.     pic.XOff:=w.borderLeft; pic.YOff:=w.borderTop;
  179.     pic.rp:=w.rPort;
  180.     rp:=SYSTEM.VAL(RastPortPtr,w.rPort);
  181.     bm:=SYSTEM.VAL(BitMapPtr,rp.bitMap);
  182.     pic.depth:=bm.depth;
  183.     pic.notify:=NIL;
  184.     FOR i:=0 TO pic.depth-1 DO
  185.         pic.bitMap.planes[i]:=0; (* Used only in CreateLayer, FreeLayer *)
  186.     END;
  187.     pic.layer:=w.wLayer;
  188.     pic.layerInfo:=0; (* Used only in CreateLayer, FreeLayer *)
  189.     pic.oldCol:=-1;
  190.     pic.oldMode:=-1;
  191.     defaultPicture:=pic; (* Remember Oberon screen for DisplayBlock. I hate Pictures/Display! cn *)
  192. END WindowToPicture;
  193. PROCEDURE FreeLayer(pic:Picture);
  194.     Free layer and bitmap.
  195.     i:INTEGER;
  196. BEGIN
  197.     IF pic.layer#0 THEN
  198.         ASSERT(AmigaLayers.DeleteLayer(pic.layer));
  199.         pic.layer:=0;
  200.         G.WaitBlit()
  201.     END;
  202.     IF pic.layerInfo#0 THEN AmigaLayers.DisposeLayerInfo(pic.layerInfo); pic.layerInfo:=0 END;
  203.     IF G.gfxVersion>=39 THEN
  204.         G.FreeBitMap(pic.bitMapPtr)
  205.     ELSE
  206.         i := 0;
  207.         WHILE i<Amiga.Depth DO
  208.             IF pic.bitMap.planes[i] # 0 THEN
  209.                 G.FreeRaster(pic.bitMap.planes[i],pic.width,pic.height);
  210.                 pic.bitMap.planes[i] := 0
  211.             END;
  212.             INC(i)
  213.         END
  214.     END;
  215.     pic.oldCol:=-1;
  216.     pic.oldMode:=-1;
  217.     pic.depth:=0;
  218.     pic.width:=0;
  219.     pic.height:=0
  220. END FreeLayer;
  221. PROCEDURE Finalize(obj: SYSTEM.PTR);
  222. BEGIN
  223.     FreeLayer(SYSTEM.VAL(Picture,obj))
  224. END Finalize;
  225. PROCEDURE Address*(P: Picture): LONGINT;
  226.     Not supported at the Amiga, returns 0
  227.     This PROCEDURE has a side effect. It stores the Picture in ToPrint.
  228.     It is used for Printing Pictures.
  229. BEGIN
  230.     ToPrint:=P;
  231.     RETURN 0
  232. END Address;
  233. PROCEDURE SetDrawMode(pic:Picture; col, mode: INTEGER);
  234.     Ckeck old DrawModes (Mode, Color) and set new, if changed
  235.     Every PROCEDURE drawing to a Picture has to call this
  236.     WriteMsk has to be changed if mode changes to invert or (in mode invert) the color changes
  237.     drMode: SHORTINT;
  238.     rpPtr:RastPortPtr;
  239. BEGIN
  240.     IF pic.oldMode # mode THEN                (* Set Drawing Mode *)
  241.         CASE mode OF
  242.         |    replace:
  243.                 drMode := G.jam2;
  244.                 IF pic.oldMode=invert THEN
  245.                     IF G.gfxVersion>=39 THEN
  246.                         G.SetWriteMask(pic.rp,nofCols-1)
  247.                     ELSE
  248.                         rpPtr:=SYSTEM.VAL(RastPortPtr, pic.rp);
  249.                         rpPtr.mask := SYSTEM.VAL(SHORTINT, CHR(nofCols-1))
  250.                     END;
  251.                     G.SetAPen(pic.rp, col)
  252.                 END
  253.         |    paint:
  254.                 drMode := G.jam1;
  255.                 IF pic.oldMode=invert THEN
  256.                     IF G.gfxVersion>=39 THEN
  257.                         G.SetWriteMask(pic.rp, nofCols-1)
  258.                     ELSE
  259.                         rpPtr:=SYSTEM.VAL(RastPortPtr, pic.rp);
  260.                         rpPtr.mask := SYSTEM.VAL(SHORTINT, CHR(nofCols-1))
  261.                     END;
  262.                     G.SetAPen(pic.rp, col)
  263.                 END
  264.         |    invert:
  265.                 drMode := G.complement;
  266.                 IF pic.oldCol=col THEN
  267.                     IF G.gfxVersion>=39 THEN
  268.                         G.SetWriteMask(pic.rp, col)
  269.                     ELSE
  270.                         rpPtr:=SYSTEM.VAL(RastPortPtr, pic.rp);
  271.                         rpPtr.mask := SYSTEM.VAL(SHORTINT, CHR(col))
  272.                     END
  273.                 END
  274.         END;
  275.         pic.oldMode := mode;
  276.         G.SetDrMd(pic.rp, drMode)
  277.     END;
  278.     IF pic.oldCol # col THEN                        (* Set Drawing Color *)
  279.         pic.oldCol := col;
  280.         IF mode=invert THEN
  281.             IF G.gfxVersion>=39 THEN
  282.                 G.SetWriteMask(pic.rp, col)
  283.             ELSE
  284.                 rpPtr:=SYSTEM.VAL(RastPortPtr, pic.rp);
  285.                 rpPtr.mask := SYSTEM.VAL(SHORTINT, CHR(col))
  286.             END
  287.         ELSE
  288.             G.SetAPen(pic.rp, col+Amiga.ColorOffset)
  289.         END
  290. END SetDrawMode;
  291. PROCEDURE CopyBlock*(sP, dP: Picture; SX, SY, W, H, DX, DY, mode: INTEGER);
  292.     Copy a rectangular area within the display to another place. This procedure assumes, that any single
  293.     area does not cross the boundary between primary and secondary screen.
  294.     VAR minterm: CHAR;
  295. BEGIN
  296.     IF (W <= 0) OR (H <= 0) THEN RETURN END;
  297.     SetDrawMode(dP, dP.oldCol, mode); (* only to set mask *)
  298.     CASE mode OF
  299.     | replace: minterm:=0C0X  (* dest:=BC + B~C *)
  300.     | paint: minterm:=0E0X  (* dest:=BC + ~BC + B~C *)
  301.     | invert: minterm:=60X  (* dest:=B~C + ~BC *)
  302.     END;
  303.     G.ClipBlit(sP.rp, SX+sP.XOff, sP.height-SY(*-1*)-H+sP.YOff,
  304.                     dP.rp, DX+dP.XOff, dP.height-DY(*-1*)-H+dP.YOff, W, H, minterm)
  305. END CopyBlock;
  306. PROCEDURE CopyBlockC*(sP, dP:Picture; f: Frame; SX, SY, W, H, DX, DY, mode: INTEGER);
  307.     As CopyBlock, but the destination area is clipped against the Frame boundary.
  308.     VAR dx, dy: INTEGER;
  309. BEGIN
  310.     IF (W <= 0) OR (H <= 0) THEN RETURN END;
  311.     dx := f.X-DX;
  312.     IF dx > 0 THEN INC(SX, dx); DX := f.X; DEC(W, dx) END;
  313.     dx := DX+W-(f.X+f.W);
  314.     IF dx > 0 THEN DEC(W, dx) END;
  315.     dy := f.Y-DY;
  316.     IF dy > 0 THEN INC(SY, dy); DY := f.Y; DEC(H, dy) END;
  317.     dy := DY+H-(f.Y+f.H);
  318.     IF dy > 0 THEN DEC(H, dy) END;
  319.     IF (W > 0) & (H > 0) THEN CopyBlock(sP, dP, SX, SY, W, H, DX, DY, mode) END
  320. END CopyBlockC;
  321. PROCEDURE AdjustPointer(wordIn,bitIn:LONGINT; VAR wordStart:LONGINT; VAR bitOffset:INTEGER);
  322. Given a base address and a bit offset from this address, a new start and offset are computed such, that the new start is word aligned, and the offset is in the range 0..15.
  323. BEGIN
  324.     wordStart:=wordIn+bitIn DIV 8;
  325.     bitOffset:=SHORT(bitIn MOD 8);
  326.     IF ODD(wordStart) THEN
  327.         DEC(wordStart);
  328.         INC(bitOffset,8)
  329. END AdjustPointer;
  330. PROCEDURE copyPattern(pic:Picture; col: INTEGER; pat: Pattern; X, Y, dx, dy, w, h, mode: INTEGER);
  331.     Routine used by CopyPattern and CopyPatternC. It will copy a pattern into the designated destination
  332.     area. This routines is able to extract an arbitrary rectangular region from the origin pattern.
  333.     p: Amiga.PatternInfoPtr;
  334.     wordStart:LONGINT;
  335.     bitOffset:INTEGER;
  336. BEGIN
  337.     col:=col MOD nofCols;
  338.     SetDrawMode(pic, col, mode);
  339.     p := SYSTEM.VAL( Amiga.PatternInfoPtr, pat);
  340.     w := p.w+w; h := p.h+h;
  341.     IF (w > 0) & (h > 0) THEN
  342.         AdjustPointer(p.data+dy*p.modulo,dx+p.offset,wordStart,bitOffset);
  343.         G.BltTemplate(wordStart, bitOffset, p.modulo, pic.rp, X+pic.XOff, pic.height-Y-h+pic.YOff, w, h)
  344. END copyPattern;
  345. PROCEDURE CopyPattern*(pic:Picture; col: INTEGER; pat: Pattern; X, Y, mode: INTEGER);
  346.     Copy a pattern to the specified location.
  347. BEGIN copyPattern(pic, col, pat, X, Y, 0, 0, 0, 0, mode)
  348. END CopyPattern;
  349. PROCEDURE CopyPatternC*(pic:Picture; f: Frame; col: INTEGER; pat: Pattern; X, Y, mode: INTEGER);
  350.     As CopyPattern, but clips the pattern against the frame boundary.
  351.     dx, sx, dy, sy, w, h: INTEGER; p: Amiga.PatternInfoPtr;
  352. BEGIN
  353.     p := SYSTEM.VAL(Amiga.PatternInfoPtr, pat);
  354.     dx := f.X-X; sx := 0; sy := 0; w := p.w; h := p.h;
  355.     IF dx > 0 THEN sx := dx; X := f.X; DEC(w, dx) END;
  356.     dx := X+w-(f.X+f.W);
  357.     IF dx > 0 THEN DEC(w, dx) END;
  358.     dy := f.Y-Y;
  359.     IF dy > 0 THEN Y := f.Y; DEC(h, dy) END;    (* don't adjust sy offset here. *)
  360.     dy := Y+h-(f.Y+f.H);
  361.     IF dy > 0 THEN sy := dy; DEC(h, dy) END;    (* adjust sy offset here, because of Amiga display model *)
  362.     copyPattern(pic, col, pat, X, Y, sx, sy, w-p.w, h-p.h, mode)
  363. END CopyPatternC;
  364. PROCEDURE Dot*(pic:Picture; col: INTEGER; X, Y, mode: INTEGER);
  365.     Change a single pixel.
  366. BEGIN
  367.     col:=col MOD nofCols;
  368.     SetDrawMode(pic, col, mode);
  369.     IF G.WritePixel(pic.rp, X+pic.XOff, pic.height-Y-1+pic.YOff) THEN END;
  370. END Dot;
  371. PROCEDURE DotC*(pic:Picture; f: Frame; col: INTEGER; X, Y, mode: INTEGER);
  372.      As Dot, but the the pixel is only written, if contained within the frame boundary.
  373. BEGIN
  374.     IF (X >= f.X) & (X < f.X+f.W) & (Y >= f.Y) & (Y < f.Y+f.H) THEN Dot(pic, col, X, Y, mode) END
  375. END DotC;
  376. PROCEDURE Get*(P: Picture; X, Y: INTEGER): INTEGER;
  377.     Don't yet know what this is for.
  378.     col:INTEGER;
  379.     rpPtr:RastPortPtr;
  380. BEGIN
  381.     IF (X<0) OR (X>=P.width) OR (Y<0) OR (Y>=P.height) THEN RETURN black END ;
  382.     IF P.oldMode=invert THEN
  383.         P.oldMode:=replace;
  384.         IF G.gfxVersion>=39 THEN
  385.             G.SetWriteMask(P.rp, nofCols-1)
  386.         ELSE
  387.             rpPtr:=SYSTEM.VAL(RastPortPtr, P.rp);
  388.             rpPtr.mask := SYSTEM.VAL(SHORTINT, CHR(nofCols-1))
  389.         END;
  390.         G.SetDrMd( P.rp, replace)
  391.     END;
  392.     col:=G.ReadPixel(P.rp,X+P.XOff,P.height-Y-1+P.YOff);
  393.     RETURN col-Amiga.ColorOffset
  394. END Get;
  395. PROCEDURE Copy*(sP, dP: Picture; xs, ys, ws, hs, xd, yd, wd, hd, mode: INTEGER);
  396.     Used to produce a scaled copy of a Picture
  397.     VAR hx, hy, wd2, ws2: LONGINT; dx, dy, xso, xdo: INTEGER;
  398. BEGIN
  399.     dy:=yd + hd;  dx:=xd + wd; xso:=xs; xdo:=xd; wd2:=2*wd; ws2:=2*ws;
  400.     hy:=2*hs - hd;
  401.     WHILE yd < dy DO
  402.         hx:=2*ws - wd; xd:=xdo; xs:=xso;
  403.         WHILE xd < dx DO
  404.             Dot(dP, Get(sP, xs, ys), xd, yd, mode);
  405.             WHILE hx > 0 DO INC(xs); DEC(hx, wd2) END;
  406.             INC(xd); INC(hx, ws2)
  407.         END ;
  408.         WHILE hy > 0 DO INC(ys); hy:=hy - 2*hd END;
  409.         INC(yd); hy:=hy + 2*hs
  410. END Copy;
  411. PROCEDURE ReplConst*(pic: Picture; col, X, Y, W, H, mode: INTEGER);
  412.     Generate a rectangle with the specified color and paint mode.
  413. BEGIN
  414.     IF (W <= 0) OR (H <= 0) THEN RETURN END;
  415.     col:=col MOD nofCols;
  416.     SetDrawMode(pic, col, mode);
  417.     G.RectFill(pic.rp, X+pic.XOff, pic.height-Y-H+pic.YOff, X+W-1+pic.XOff, pic.height-Y-1+pic.YOff)
  418. END ReplConst;
  419. PROCEDURE ReplConstC*(pic: Picture; f: Frame; col: INTEGER; X, Y, W, H, mode: INTEGER);
  420.     As ReplConst, but the rectangle is clipped against the frame boundary.
  421.         dx, dy: INTEGER;
  422. BEGIN
  423.     IF (W <= 0) OR (H <= 0) THEN RETURN END;
  424.     dx := f.X-X;
  425.     IF dx > 0 THEN X := f.X; DEC(W, dx) END;
  426.     dx := X+W-(f.X+f.W);
  427.     IF dx > 0 THEN DEC(W, dx) END;
  428.     dy := f.Y-Y;
  429.     IF dy > 0 THEN Y := f.Y; DEC(H, dy) END;
  430.     dy := Y+H-(f.Y+f.H);
  431.     IF dy > 0 THEN DEC(H, dy) END;
  432.     IF (W >0) & (H > 0) THEN ReplConst(pic,col, X, Y, W, H, mode) END
  433. END ReplConstC;
  434. PROCEDURE ReplPattern*(pic: Picture; col: INTEGER; pat: Pattern; X, Y, W, H, mode: INTEGER);
  435.     Fill the specified area with the pattern.
  436.     x, y, w, h, X1, Y1: INTEGER; p: Amiga.PatternInfoPtr;
  437.     wordStart:LONGINT;
  438.     bitOffset:INTEGER;
  439. BEGIN
  440.     col:=col MOD nofCols;
  441.     SetDrawMode(pic, col, mode);
  442.     p := SYSTEM.VAL(Amiga.PatternInfoPtr, pat);
  443.     X1 := X+W; Y1 := Y+H; y := Y;
  444.     WHILE y < Y1 DO
  445.         IF y+p.h > Y1 THEN h := Y1-y ELSE h := p.h END;
  446.         x := X;
  447.         WHILE x < X1 DO
  448.             IF x+p.w > X1 THEN w := X1-x ELSE w := p.w END;
  449.             AdjustPointer(p.data+(p.h-h)*p.modulo,p.offset,wordStart,bitOffset);
  450.             G.BltTemplate(wordStart, bitOffset, p.modulo, pic.rp, x+pic.XOff, pic.height-y-h+pic.YOff, w, h);
  451.             x := x+p.w
  452.         END;
  453.         y := y+p.h
  454. END ReplPattern;
  455. PROCEDURE Min(x, y: INTEGER): INTEGER;
  456. BEGIN IF x < y THEN RETURN x ELSE RETURN y END
  457. END Min;
  458. PROCEDURE Max(x, y: INTEGER): INTEGER;
  459. BEGIN IF x > y THEN RETURN x ELSE RETURN y END
  460. END Max;
  461. PROCEDURE ReplPatternC*(pic:Picture; f: Frame; col: INTEGER; pat: Pattern; X, Y, W, H, X0, Y0, mode: INTEGER);
  462. (* Replicates a pattern pat within the block (X, Y, W, H), clipped against F. The pattern origin is X0, Y0; i.e. for each
  463.     completely visible occurrence of the pattern pat the following holds: ((x - X0) MOD w = 0) & ((y-Y0) MOD h = 0)
  464.     where (x, y) denotes the left and bottom corner, and (w, h) the size of the pattern. *)
  465.     rectangle: G.Rectangle; region, oldRegion: G.RegionPtr; p: Amiga.PatternInfoPtr;
  466.     dx, dy: INTEGER;
  467. BEGIN
  468.     IF (W <= 0) OR (H <= 0) THEN RETURN END;
  469.     region := G.NewRegion();
  470.     rectangle.minX := Max(f.X, X)+pic.XOff; rectangle.maxX := Min(f.X+f.W-1, X+W-1)+pic.XOff;
  471.     rectangle.minY := Max(pic.height-f.Y-f.H, pic.height-Y-H)+pic.YOff;
  472.     rectangle.maxY := Min(pic.height-f.Y-1, pic.height-Y-1)+pic.YOff;
  473.     IF G.OrRectRegion(region, SYSTEM.ADR(rectangle)) THEN
  474.         p := SYSTEM.VAL(Amiga.PatternInfoPtr, pat);
  475.         dx := (X-X0) MOD p.w; dy := (Y-Y0) MOD p.h;
  476.         oldRegion := AmigaLayers.InstallClipRegion(pic.layer, region);
  477.         ReplPattern(pic, col, pat, X-dx, Y-dy, W+dx, H+dy, mode);
  478.         region := AmigaLayers.InstallClipRegion(pic.layer, oldRegion);
  479.         G.DisposeRegion(region)
  480. END ReplPatternC;
  481. PROCEDURE Update*(P: Picture; X, Y , W, H: INTEGER);
  482. BEGIN
  483.     IF P.notify # NIL THEN P.notify(P, X, Y, W, H) END
  484. END Update;
  485. PROCEDURE DisplayBlock*(P: Picture; X, Y, W, H, DX, DY, mode: INTEGER);
  486.     I assume, this copies the picture to the screen.
  487. BEGIN
  488.     IF defaultPicture=NIL THEN
  489.         HALT(54)
  490.     ELSE
  491.         CopyBlock(P,defaultPicture,X,Y,W,H,DX,DY,mode)
  492. END DisplayBlock;
  493. PROCEDURE ReadInt(VAR R: Files.Rider; VAR i: INTEGER);
  494. VAR hi: SHORTINT; lo: CHAR; li: LONGINT;
  495. BEGIN
  496.     Files.Read(R, lo); Files.Read(R, hi); li:=ORD(lo) + 256*hi; i:=SHORT(li)
  497. END ReadInt;
  498. PROCEDURE WriteInt(VAR R: Files.Rider; i: INTEGER);
  499. BEGIN
  500.     Files.Write(R, CHR(i MOD 256)); Files.Write(R, CHR(i DIV 256 MOD 256))
  501. END WriteInt;
  502. PROCEDURE ReadPal(VAR R: Files.Rider; P: Picture; nofcol: LONGINT);
  503.     col:LONGINT;
  504. BEGIN
  505.     FOR col:=0 TO nofcol-1 DO
  506.         Files.Read(R, P.pal[col].r); Files.Read(R, P.pal[col].g); Files.Read(R, P.pal[col].b)
  507. END ReadPal;
  508. PROCEDURE WritePal(VAR R: Files.Rider; P: Picture; nofcol: LONGINT);
  509. VAR col: LONGINT;
  510. BEGIN
  511.     FOR col:=0 TO nofcol-1 DO
  512.         Files.Write(R, P.pal[col].r); Files.Write(R, P.pal[col].g); Files.Write(R, P.pal[col].b)
  513. END WritePal;
  514. PROCEDURE Define(P: Picture; width, height, depth: INTEGER);    (* set width, height, depth, next, pixmap *)
  515. BEGIN
  516.     IF (P.width # width) OR (P.height # height) OR (P.depth # depth) OR (P.layer=0) THEN
  517.         IF (width=0) OR (height=0) OR (depth=0) THEN HALT(50) END ;
  518.         IF P.layer # 0 THEN FreeLayer(P) ELSE Kernel.RegisterObject(P, Finalize) END ;
  519.         P.width:=width; P.height:=height; P.depth:=depth;
  520.         InitLayer(P);
  521.         IF P.layer=0 THEN HALT(40) END;
  522.         P.oldCol:=-1;
  523.         P.oldMode:=-1;
  524.         P.XOff:=0; P.YOff:=0;
  525. END Define;
  526. PROCEDURE ReadData(VAR R: Files.Rider; P: Picture; exp, map, rv: BOOLEAN);
  527.     Load run length encoded picture.
  528.     ch,ch1:CHAR;
  529.     k:INTEGER;
  530.     x,y,yoff:INTEGER;
  531.     width, height, depth: INTEGER;
  532.     m:ARRAY 256 OF CHAR;
  533.     r:G.RastPortPtr;
  534.     rptr:RastPortPtr;
  535.     bptr:BitMapPtr;
  536.     bpr: LONGINT;
  537.     planes: ARRAY 8 OF LONGINT;
  538.     (* faster Version of Dot, only for ReadData *)
  539.     PROCEDURE NDot(col, X, Y: INTEGER);
  540.     BEGIN
  541.         IF P.oldCol # col THEN P.oldCol := col; G.SetAPen(r, col+Amiga.ColorOffset) END;
  542.         IF G.WritePixel(r, X, P.height-Y-1) THEN END
  543.     END NDot;
  544.     PROCEDURE Unpack(p: LONGINT);
  545.         i: INTEGER;
  546.         pixel: INTEGER;
  547.     BEGIN
  548.         i:=8;
  549.         REPEAT
  550.             IF ODD(p) THEN pixel:=white ELSE pixel:=black END;
  551.             NDot(pixel,x,yoff-y-1); INC(x); p:=ASH(p,-1); DEC(i)
  552.         UNTIL (i=0) OR (x=width)
  553.     END Unpack;
  554.     (* new unpack writes data direct to the planes *)
  555.     PROCEDURE Unpack(p: INTEGER);
  556.         VAR
  557.             offset, count: LONGINT;
  558.             b: SYSTEM.BYTE;
  559.     BEGIN
  560.         b:=swap[p];
  561.         offset:=y*bpr+ASH(x,-3);
  562.         IF Amiga.OberonDepth<5 THEN
  563.             FOR count:=0 TO Amiga.OberonDepth-1 DO
  564.                 SYSTEM.PUT(planes[count]+offset, b)
  565.             END
  566.         ELSE
  567.             FOR count:=0 TO 3 DO
  568.                 SYSTEM.PUT(planes[count]+offset, b)
  569.             END;
  570.             FOR count:=4 TO Amiga.OberonDepth-1 DO
  571.                 SYSTEM.PUT(planes[count]+offset, 0X)
  572.             END
  573.         END;
  574.         INC(x, 8)
  575.     END Unpack;
  576. BEGIN
  577.     r:=P.rp; Dot(P, 0, 0, 0, replace); (* needed for new Dot *)
  578.     rptr:=SYSTEM.VAL(RastPortPtr, r);
  579.     depth:=P.depth;
  580.     height:=P.height;
  581.     width:=P.width;
  582.     yoff:=P.height-1;
  583.     IF depth=1 THEN (* install everythink for new Unpack *)
  584.         rptr:=SYSTEM.VAL(RastPortPtr, r);
  585.         bptr:=SYSTEM.VAL(BitMapPtr, rptr.bitMap);
  586.         bpr:=bptr.bytesPerRow;
  587.         FOR k:=0 TO Amiga.OberonDepth DO
  588.             planes[k]:=SYSTEM.VAL(LONGINT, bptr.planes[k])
  589.         END
  590.     END;
  591.     IF map THEN
  592.         (*WHILE k < 256 DO m[k] := CHR((k MOD 2)*15); INC(k) END ;
  593.         m[12] := CHR(15); m[13] := CHR(0); m[14] := CHR(15)*)
  594.         x:=SHORT(ASH(1,depth));m[0]:=0X;
  595.         FOR k:=1 TO 255 DO
  596.             m[k]:=CHR(k MOD x);
  597.             IF m[k]=0X THEN m[k]:=0FX END
  598.         END
  599.     END;
  600.     y:=0;
  601.     FOR y:=0 TO height-1 DO
  602.         x:=0;
  603.         WHILE x<width  DO
  604.             Files.Read(R,ch);
  605.             k:=ORD(ch);
  606.             IF k<128 THEN
  607.                 REPEAT
  608.                     Files.Read(R,ch);
  609.                     IF exp THEN
  610.                         ch1:=CHR(ORD(ch) MOD 16);
  611.                         ch:=CHR(ORD(ch) DIV 16);
  612.                         IF map THEN
  613.                             ch1:=m[ORD(ch1)];
  614.                             ch:=m[ORD(ch)]
  615.                         END;
  616.                         NDot(ORD(ch1),x,yoff-y);
  617.                         INC(x)
  618.                     ELSIF map THEN
  619.                         ch:=m[ORD(ch)]
  620.                     ELSIF rv THEN
  621.                         ch:=CHR(rev[ORD(ch) DIV 16]+rev[ORD(ch) MOD 16]*16)
  622.                     END;
  623.                     IF x<width THEN
  624.                         IF (depth=1) & ~map THEN
  625.                             Unpack(ORD(ch))
  626.                         ELSE
  627.                             NDot(ORD(ch),x,yoff-y);
  628.                             INC(x)
  629.                         END
  630.                     END ;
  631.                     DEC(k)
  632.                 UNTIL k<0
  633.             ELSE
  634.                 k:=257-k;
  635.                 Files.Read(R, ch);
  636.                 IF exp THEN
  637.                     ch1:=CHR(ORD(ch) MOD 16);
  638.                     ch:=CHR(ORD(ch) DIV 16);
  639.                     IF map THEN
  640.                         ch1:=m[ORD(ch1)];
  641.                         ch:=m[ORD(ch)]
  642.                     END
  643.                 ELSIF map THEN
  644.                     ch:=m[ORD(ch)]
  645.                 ELSIF rv THEN
  646.                     ch:=CHR(rev[ORD(ch) DIV 16]+rev[ORD(ch) MOD 16]*16)
  647.                 END ;
  648.                 REPEAT
  649.                     IF exp THEN
  650.                         NDot(ORD(ch1),x,yoff-y);
  651.                         INC(x)
  652.                     END;
  653.                     IF x < width THEN
  654.                         IF (depth=1) & ~map THEN
  655.                             Unpack(ORD(ch))
  656.                         ELSE
  657.                             NDot(ORD(ch),x,yoff-y);
  658.                             INC(x)
  659.                         END
  660.                     END;
  661.                     DEC(k)
  662.                 UNTIL k<1
  663.             END
  664.         END
  665.     END;
  666.     G.SetWriteMask(P.rp, 0)
  667. END ReadData;
  668. PROCEDURE Load*(P: Picture; F: Files.File; pos: LONGINT; VAR len: LONGINT);
  669.     Load a pictures which was identified as starting with a PictFileId.
  670.     expand,map:BOOLEAN;
  671.     R:Files.Rider;
  672.     width,height,depth:INTEGER;
  673. BEGIN
  674.     Files.Set(R,F,pos); ReadInt(R,width); ReadInt(R,height); ReadInt(R,depth);
  675.     ReadPal(R,P,ASH(1,depth)); (* RGB-Werte der Originalfarben laden *)
  676.     expand:=FALSE;
  677.     map:=FALSE;
  678.     IF depth=4 THEN (* Ceres color picture *)
  679.         expand:=TRUE;
  680.         map:=Amiga.OberonDepth#4;
  681.         depth:=Amiga.OberonDepth
  682.     ELSIF depth>Amiga.OberonDepth THEN
  683.         map:=TRUE;
  684.         depth:=Amiga.OberonDepth
  685.     END ;
  686.     (* IF (depth#Amiga.Depth) & (depth#1) THEN HALT(43) END; *)
  687.     Define(P,width,height,depth);
  688.     ReadData(R,P,expand,map,FALSE);
  689.     len:=Files.Pos(R)-pos
  690. END Load;
  691. PROCEDURE Store*(P: Picture; F: Files.File; pos: LONGINT; VAR len: LONGINT);
  692.     stores picture to run length encoded file F   (including tag)
  693.     a, b, x, y, width, height, depth, oridepth: INTEGER;
  694.     j: LONGINT;
  695.     h: CHAR;
  696.     buf: ARRAY 129 OF CHAR;
  697.     R: Files.Rider;
  698.     PROCEDURE Pack(): CHAR;
  699.         VAR i, j, p: INTEGER;
  700.     BEGIN
  701.         i:=8; j:=1; p:=0;
  702.         REPEAT
  703.             IF Get(P, x, P.height-y-1)#black THEN INC(p, j) END;
  704.             INC(x); j:=j*2; DEC(i)
  705.         UNTIL (i=0) OR (x=width);
  706.         RETURN CHR(p)
  707.     END Pack;
  708.     (* store pictures with 4 planes in Ceres 4 colors-format *)
  709.     PROCEDURE PackColor(): CHAR;
  710.         VAR ch, ch1: INTEGER;
  711.     BEGIN
  712.         ch:=Get(P, x, P.height-y-1)-Amiga.ColorOffset; INC(x);
  713.         ch1:=Get(P, x, P.height-y-1)-Amiga.ColorOffset; INC(x);
  714.         RETURN CHR(ch+ch1*16)
  715.     END PackColor;
  716. BEGIN
  717.     width:=P.width; height:=P.height; oridepth:=P.depth;
  718.     (* only store as 1, 4 or 8 Plane Pict *)
  719.     depth:=oridepth;
  720.     IF (oridepth=2) OR (oridepth=3) THEN depth:=4 END;
  721.     IF (oridepth>4) & (oridepth<7) THEN depth:=8 END;
  722.     Files.Set(R, F, pos); WriteInt(R, PictFileId);
  723.     WriteInt(R, width); WriteInt(R, height); WriteInt(R, depth);
  724.     WritePal(R, P, ASH(1, depth));
  725.     (* fill Colortabel with 0 *)
  726.     IF depth#oridepth THEN
  727.         FOR j:=1 TO (ASH(1, depth)-ASH(1, oridepth))*3 DO
  728.             Files.Write(R, CHR(0))
  729.         END
  730.     END;
  731.     y:=0;
  732.     WHILE height > 0 DO x:=0; a:=0;
  733.         j:=1; buf[0]:=0X;
  734.         IF depth=1 THEN h:=Pack()
  735.         ELSIF depth=4 THEN h:=PackColor()
  736.         ELSE h:=CHR(Get(P, x, P.height-y-1)); INC(x)
  737.         END ;
  738.         b:=1; buf[j]:=h;
  739.         WHILE x < width DO
  740.             IF depth=1 THEN h:=Pack()
  741.             ELSIF depth=4 THEN h:=PackColor()
  742.             ELSE h:=CHR(Get(P, x, P.height-y-1)); INC(x)
  743.             END;
  744.             IF ((b - a) < 127) & ((buf[0]=0X) OR ((h=buf[j]) & (j=1)) OR ((h # buf[j]) & (j  > 1))) THEN (* same run *)
  745.                 IF h # buf[j] THEN INC(SYSTEM.VAL(SHORTINT, buf[0])); INC(j); buf[j]:=h
  746.                 ELSE DEC(SYSTEM.VAL(SHORTINT, buf[0])) END
  747.             ELSE (* new run *)
  748.                 IF (buf[j]=h) & (b - a # 127) THEN DEC(SYSTEM.VAL(SHORTINT, buf[0])); Files.WriteBytes(R, buf, j); buf[0]:=0FFX
  749.                 ELSE Files.WriteBytes(R, buf, j + 1); buf[0]:=0X END ;
  750.                 j:=1; buf[j]:=h; a:=b
  751.             END ;
  752.             INC(b)
  753.         END ;
  754.         Files.WriteBytes(R, buf, j + 1);
  755.         DEC(height); INC(y)
  756.     END ;
  757.     len:=Files.Pos(R) - pos
  758. END Store;
  759. PROCEDURE Create*(P: Picture; width, height, depth: INTEGER);
  760.     Create a picture with the requested size. The main work is done
  761.     in Define. This only clears the picture area and the color
  762.     palette.
  763.     col: INTEGER;
  764. BEGIN
  765.     Define(P, width, height, depth);
  766.     ReplConst(P, black, 0, 0, P.width, P.height, replace);
  767.     FOR col:=0 TO 255 DO P.pal[col].r:=0X; P.pal[col].g:=0X; P.pal[col].b:=0X END
  768. END Create;
  769. PROCEDURE Open*(P: Picture; name: ARRAY OF CHAR);
  770.     Load a file into a picture.
  771.     F:Files.File;
  772.     R:Files.Rider;
  773.     len: LONGINT;
  774.     x, d: INTEGER;
  775.     dname: ARRAY 64 OF CHAR;
  776. BEGIN
  777.     F:=Files.Old(name);
  778.     IF F#NIL THEN
  779.         Files.Set(R,F,0);
  780.         x:=0;
  781.         ReadInt(R,x);
  782.         IF x=0 THEN (* MacPaint format *)
  783.             Define(P,576,720,1);
  784.             Files.Set(R,F,Files.Pos(R)+510);
  785.             ReadData(R,P,FALSE,FALSE,TRUE)
  786.         ELSIF x=PictFileId THEN
  787.             Load(P,F,2,len)
  788.         ELSIF x=07F7H THEN (* Skipping System3 File-Header *)
  789.             Files.ReadString(R, dname); Files.ReadInt(R, d); Files.ReadInt(R, d); Files.ReadInt(R, d); Files.ReadInt(R, d);
  790.             Files.ReadInt(R, x);
  791.             IF x=PictFileId THEN
  792.                 Load(P, F, Files.Pos(R), len)
  793.             ELSE
  794.                 O.Str("System3-File, Unknown format");O.Ln
  795.             END
  796.         ELSE
  797.             O.Str("Unknown format");O.Ln
  798.         END
  799.     ELSE
  800.         O.Str("Pictures.Open: "); O.Str(name); O.Str(" failed"); O.Ln;
  801.         Create(P,Amiga.Width*5 DIV 8 -20,Amiga.Height-80,Amiga.OberonDepth)
  802. END Open;
  803. PROCEDURE SetColor*(P:Picture; col,red,green,blue:INTEGER);
  804.     Change the RGB values of a palette entry.
  805. BEGIN
  806.     IF (col<nofCols) & (col>=0) THEN
  807.         P.pal[col].r:=CHR(red); P.pal[col].g:=CHR(green); P.pal[col].b:=CHR(blue)
  808. END SetColor;
  809. PROCEDURE GetColor*(P: Picture; col: INTEGER; VAR red, green, blue: INTEGER);
  810.     Retrieve the RGB values of a palette entry.
  811. BEGIN
  812.     IF (col<nofCols) & (col>=0) THEN
  813.         red:=ORD(P.pal[col].r); green:=ORD(P.pal[col].g); blue:=ORD(P.pal[col].b)
  814. END GetColor;
  815. PROCEDURE NewPattern*(VAR image: ARRAY OF SET; w, h: INTEGER): Pattern;
  816. (* Allocates a new pattern with width w and height h. The i-th pattern line from bottom (increasing y-value)
  817.     corresponds to the image entries (i+1)*lineLen .. (i+2)*lineLen-1, where lineLen = (w+31) DIV 32.
  818.     The set elements describe the pixels from left to right (increasing x-value). *)
  819. CONST header=4;
  820.         ch: CHAR; src, dest: LONGINT; byte, bytesPerRow, i, size: LONGINT;
  821.         pattern: Amiga.PatternInfoPtr; patNode: PatternNode;
  822. BEGIN
  823.     Amiga.Assert((0<w) & (w<=32) & (0<h),"Illegal pattern size");
  824.     NEW(pattern); pattern.w := SHORT(w); pattern.h := SHORT(h); pattern.modulo := 2*((w+15) DIV 16);
  825.     NEW(patNode); patNode.next := patternRoot; patternRoot := patNode;
  826.     patNode.p := pattern;    (* to insert pattern into global list for GC *)
  827.     size := pattern.modulo*h;
  828.     IF Amiga.ChipMemPool#0 THEN
  829.         pattern.data:=E.AllocPooled(Amiga.ChipMemPool, size)
  830.     ELSE
  831.         pattern.data := E.AllocMem(size, {E.memChip})
  832.     END;
  833.     pattern.offset:=0;
  834.     bytesPerRow := (w + 7) DIV 8;
  835.     src := SYSTEM.ADR(image)+header+3; dest := pattern.data+pattern.modulo*(h-1);
  836.     FOR i := 0 TO h-1 DO
  837.         FOR byte := 1 TO bytesPerRow DO
  838.             SYSTEM.GET(src, ch); SYSTEM.PUT(dest, swap[ORD(ch)]);
  839.             DEC(src); INC(dest)
  840.         END;
  841.         DEC(dest, bytesPerRow+pattern.modulo);
  842.         INC(src, bytesPerRow+4)
  843.     END;
  844.     RETURN SYSTEM.VAL(Pattern,pattern)
  845. END NewPattern;
  846. PROCEDURE Line*(pic:Picture; f:Frame; col, X0, Y0, X1, Y1, mode: INTEGER);
  847. (* Draws a line from (X0, Y0) to (X1, Y1) inclusive, clipped against F.  For all line points (x, y) the following holds
  848. always: (min(X0, X1) <= x) & (x <= max(X0, X1) & (min(Y0, Y0) <= y) & (y <= max(Y0, Y1). *)
  849.     rectangle: G.Rectangle;
  850.     region,oldRegion: G.RegionPtr;
  851. BEGIN
  852.     col:=col MOD nofCols;
  853.     SetDrawMode(pic, col, mode);
  854.     region := G.NewRegion();
  855.     rectangle.minX := f.X; rectangle.maxX := f.X+f.W-1;
  856.     rectangle.minY := pic.height-f.Y-f.H; rectangle.maxY := rectangle.minY+f.H-1;
  857.     IF G.OrRectRegion(region, SYSTEM.ADR(rectangle)) THEN
  858.         oldRegion := AmigaLayers.InstallClipRegion(pic.layer, region);
  859.         G.Move(pic.rp,X0+pic.XOff,pic.height-Y0-1+pic.YOff);
  860.         G.Draw(pic.rp,X1+pic.XOff,pic.height-Y1-1+pic.YOff);
  861.         region := AmigaLayers.InstallClipRegion(pic.layer, oldRegion);
  862.         G.DisposeRegion(region)
  863. END Line;
  864. PROCEDURE Ellipse*(pic:Picture; f:Frame; col, X, Y, A, B, mode: INTEGER);
  865. (* Draws an ellipse with center (X, Y) and radii A and B, clipped against F. For all ellipse points (x, y)  the following holds
  866.     always: (X-A <= x) & (x < X+A) & (Y-B <= y) & (y < Y+B). When A = B the resulting ellipse has the same shape
  867.     as the corresponding circle with R = A. *)
  868.     rectangle: G.Rectangle;
  869.     region,oldRegion: G.RegionPtr;
  870. BEGIN
  871.     col:=col MOD nofCols;
  872.     SetDrawMode(pic, col, mode);
  873.     region := G.NewRegion();
  874.     rectangle.minX := f.X; rectangle.maxX := f.X+f.W-1;
  875.     rectangle.minY := pic.height-f.Y-f.H; rectangle.maxY := rectangle.minY+f.H-1;
  876.     IF G.OrRectRegion(region, SYSTEM.ADR(rectangle)) THEN
  877.         oldRegion := AmigaLayers.InstallClipRegion(pic.layer, region);
  878.         G.DrawEllipse(pic.rp,X+pic.XOff,pic.height-Y-1+pic.YOff,A,B);
  879.         region := AmigaLayers.InstallClipRegion(pic.layer, oldRegion);
  880.         G.DisposeRegion(region)
  881. END Ellipse;
  882. PROCEDURE Circle*(pic:Picture; f:Frame; col, X, Y, R, mode: INTEGER);
  883. (* Draws a circle with center (X, Y) and radius R, clipped against F. For all circle points (x, y)  the following holds always:
  884.     (X-R <= x) & (x < X+R) & (Y-R <= y) & (y < Y+R). *)
  885. BEGIN
  886.     Ellipse(pic,f,col,X,Y,R,R,mode)
  887. END Circle;
  888. PROCEDURE AmigaText*(P:Picture; font:G.TextFontPtr; VAR text: ARRAY OF CHAR; count, x, y, col, mode: INTEGER);
  889.     Print text with Amiga font
  890. BEGIN
  891.     SetDrawMode(P, col, mode);
  892.     G.Move(P.rp, x+P.XOff, P.height-y-1+P.YOff);
  893.     G.SetFont(P.rp, font);
  894.     G.Text(P.rp, text, count)
  895. END AmigaText;
  896. PROCEDURE Init;
  897.     im: ARRAY 17 OF SET;
  898.     k: INTEGER;
  899. BEGIN
  900.     defaultPicture:=NIL;
  901.     nofCols:=SHORT(ASH(1, Amiga.OberonDepth));
  902.     FOR k:=0 TO 255 DO
  903.         swap[k]:=Amiga.SwapBits(CHR(k))
  904.     END;
  905.     patternRoot:=NIL;
  906.     rev[0]:=0; rev[1]:=8; rev[2]:=4; rev[3]:=12;
  907.     rev[4]:=2; rev[5]:=10; rev[6]:=6; rev[7]:=14;
  908.     rev[8]:=1; rev[9]:=9; rev[10]:=5; rev[11]:=13;
  909.     rev[12]:=3; rev[13]:=11; rev[14]:=7; rev[15]:=15;
  910.     im[1]:={};
  911.     im[2]:={1..7,9..15}; im[3]:=im[2]; im[4]:=im[2]; im[5]:=im[2];
  912.     im[6]:=im[2]; im[7]:=im[2]; im[8]:=im[2]; im[9]:=im[1];
  913.     im[10]:=im[2]; im[11]:=im[2]; im[12]:=im[2]; im[13]:=im[2];
  914.     im[14]:=im[2]; im[15]:=im[2]; im[16]:=im[2];
  915.     dots:=NewPattern(im, 16, 16)
  916. END Init;
  917. BEGIN
  918.     gfxBase:=E.OpenLibrary(G.graphicsName,37);
  919.     IF gfxBase=0 THEN HALT(99) END;
  920.     Init
  921. END Pictures.
  922.