[comp.sys.mac.programmer] Animation for zooming rectangles...

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);
}