rdd@walt.cc.utexas.edu (Robert Dorsett) (11/26/89)
I have a fragment of code from the May 1985 Software Supplement that does a good job imitating Finder-style zooming. Problem is, it uses a variable called "Deskport," which I've been hard-pressed to identify (LSC 3.0). Instead of using it, I'm simply doing an openport, then trashing the temporary port at the end of the zoom routine. Following are the Lisa Pascal fragment and my translation of it. I'd appreciate any comments on this "DeskPort" variable, as well as ways to stay "clean." --------------------------------- cut here --------------------------------- /* fragment/zoom.pas */ PROCEDURE ZoomRect(VAR smallRect,bigRect: Rect; zoomUp: BOOLEAN); { Given two rectangles in global coords, interpolate one into the other, } { making a zooming rectangle image on the screen. The rectangles and the } { screen image are not altered } CONST zoomSteps = 16; VAR rect1,rect2,rect3,rect4: Rect; i,j: INTEGER; savePort: GrafPtr; fract,factor,one: Fixed; { reals are too slow } FUNCTION Blend(smallCoord,bigCoord: INTEGER): INTEGER; VAR smallFix,bigFix,tempFix: Fixed; BEGIN smallFix:=one * smallCoord; { scale up to fixed point } bigFix :=one * bigCoord; tempFix :=FixMul(fract,bigFix) + FixMul(one-fract,smallFix); Blend :=FixRound(tempFix); END; BEGIN GetPort(savePort); SetPort(deskPort); PenPat(gray); PenMode(notPatXor); one:=65536; { fixed point 'const' } IF zoomUp THEN BEGIN rect1:=smallRect; factor:=FixRatio(6,5); { make bigger each time } fract:=FixRatio(541,10000); { 5/6 ^16 = 0.540877 } END ELSE BEGIN rect1:=bigRect; factor:=FixRatio(5,6); { make smaller each time } fract:=one; { start full size } END; rect2:=rect1; rect3:=rect1; FrameRect(rect1); { draw initial image } FOR i:=1 TO zoomSteps DO BEGIN rect4.left :=Blend(smallRect.left,bigRect.left); rect4.right :=Blend(smallRect.right,bigRect.right); rect4.top :=Blend(smallRect.top,bigRect.top); rect4.bottom :=Blend(smallRect.bottom,bigRect.bottom); FrameRect(rect4); { draw newest } FrameRect(rect1); { erase oldest } rect1:=rect2; rect2:=rect3; rect3:=rect4; fract:=FixMul(fract,factor); { bump interpolation fraction } END; FrameRect(rect1); { erase final image } FrameRect(rect2); FrameRect(rect3); PenNormal; SetPort(savePort); END; ----------------------------------- cut here --------------------------------- /* Zoom.c */ /* Given two rectangles in global coords, interpolate one into the other, */ /* making a zooming rectangle image on the screen. The rectangles and the */ /* screen image are not altered */ /* from the 5/5/85 software supplement. */ #define zoomSteps 16 int Blend(smallCoord,bigCoord,one,fract) int smallCoord,bigCoord; fixed one; fixed fract; { fixed smallFix,bigFix,tempFix; smallFix=one * smallCoord; /* scale up to fixed point */ bigFix =one * bigCoord; tempFix =FixMul(fract,bigFix) + FixMul(one-fract,smallFix); return(FixRound(tempFix)); } void ZoomRect(r1,r2,zoomUp) rect *r1; rect *r2; int zoomUp; { rect rect1,rect2,rect3,rect4; int i,j; grafptr savePort; fixed fract,factor,one; /* reals are too slow */ rect smallRect,bigRect; grafport tempport; smallRect=(*r1); bigRect=(*r2); GetPort(&savePort); OpenPort(&tempport); PenPat(gray); PenMode(notPatXor); one=65536; /* fixed point 'const' */ if (zoomUp) { rect1=smallRect; factor=FixRatio(6,5); /* make bigger each time */ fract=FixRatio(541,10000); /* 5/6 ^16 = 0.540877 */ } else { rect1=bigRect; factor=FixRatio(5,6); /* make smaller each time */ fract=one; /* start full size */ }; rect2=rect1; rect3=rect1; FrameRect(&rect1); /* draw initial image */ for (i=1; i<=zoomSteps; ++i) { rect4.left =Blend(smallRect.left,bigRect.left,one,fract); rect4.right =Blend(smallRect.right,bigRect.right,one,fract); rect4.top =Blend(smallRect.top,bigRect.top,one,fract); rect4.bottom =Blend(smallRect.bottom,bigRect.bottom,one,fract); FrameRect(&rect4); /* draw newest */ FrameRect(&rect1); /* erase oldest */ rect1=rect2; rect2=rect3; rect3=rect4; fract=FixMul(fract,factor); /* bump interpolation fraction */ }; FrameRect(&rect1); /* erase final image */ FrameRect(&rect2); FrameRect(&rect3); PenNormal(); ClosePort(&tempport); SetPort(savePort); }