(FILECREATED "25-Apr-85 15:15:31" {ICE}<TURNER>LISP>ACE>ACE-PRIM.;7 10254  

      changes to:  (FNS ACE.SCAN.BITMAPS ACE.MAX.REGIONS ACE.PICK.BEST.REGION ACE.SCAN.PRIMBLOCKS 
			ACE.FETCH.BLOCK)

      previous date: "24-Jan-85 13:42:48" {ICE}<TURNER>LISP>ACE>ACE-PRIM.;5)


(* Copyright (c)  by NIL. All rights reserved.)

(PRETTYCOMPRINT ACE-PRIMCOMS)

(RPAQQ ACE-PRIMCOMS ((* COMPILER STUFF)
		     (VARS ACE.PIXPERWORD ACE.BITMAP.MASK)
		     (* LOW LEVEL COMPILER FNS)
		     (FNS ACE.COMPILE.FRAME ACE.EXTRACT)
		     (* REGION MAXING ROUTINES)
		     (FNS ACE.MAX.REGIONS ACE.PICK.BEST.REGION ACE.COMPUTE.AREA)
		     (* LOW LEVEL BITMAP COMPARISON)
		     (FNS ACE.SCAN.BITMAPS ACE.SCAN.PRIMBLOCKS ACE.FETCH.BLOCK)))



(* COMPILER STUFF)


(RPAQQ ACE.PIXPERWORD 16)

(RPAQ ACE.BITMAP.MASK (READARRAY 16 (QUOTE SMALLPOSP) 0))
(65535 32768 49152 57344 61440 63488 64512 65024 65280 65408 65472 65504 65520 65528 65532 65534 NIL
)



(* LOW LEVEL COMPILER FNS)

(DEFINEQ

(ACE.COMPILE.FRAME
  [LAMBDA (BM.ORIG BM.CHANGED VERTICAL.BLOCK THRESHOLD)      (* PmT " 8-Jan-85 13:23")
                                                             (* MAIN ENTRY POINT FOR DIFFERENTIAL BITMAP COMPILING)
                                                             (* WARNING: NO ERROR CHECKING DONE FROM HERE DOWN!)
                                                             (* RETURNS A FRAMEPATCH LIST OF ACTUAL BITMAP CHANGES)
                                                             (* RETURN FORMAT: ((BM X . Y) 
							     (BM X . Y) ...))
    (PROG (CHANGES)
          (SETQ CHANGES (ACE.SCAN.BITMAPS BM.ORIG BM.CHANGED VERTICAL.BLOCK))
          (AND CHANGES (SETQ CHANGES (ACE.MAX.REGIONS CHANGES THRESHOLD)))
          (SETQ CHANGES (ACE.EXTRACT CHANGES BM.CHANGED))
          (RETURN CHANGES])

(ACE.EXTRACT
  [LAMBDA (REGIONS BITMAP)                                   (* PmT " 3-Jan-85 18:00")
                                                             (* TAKES LIST OF REGIONS OF CHANGED AREAS AND MAKES 
							     INTO ACTUAL FRAMEPATCH LIST BY EXTRACTING FROM NEW BM)
    (PROG (TEMP.BITMAP LEFT BOTTOM WIDTH HEIGHT (FRAMEBLITLIST (CONS)))
          [COND
	    ((NULL REGIONS)
	      NIL)
	    (T (for X in REGIONS
		  do (SETQ LEFT (fetch (REGION LEFT) of X))
		     (SETQ BOTTOM (fetch (REGION BOTTOM) of X))
		     (SETQ WIDTH (fetch (REGION WIDTH) of X))
		     (SETQ HEIGHT (fetch (REGION HEIGHT) of X))
		     (SETQ TEMP.BITMAP (BITMAPCREATE WIDTH HEIGHT 1))
		     (BITBLT BITMAP LEFT BOTTOM TEMP.BITMAP 0 0 WIDTH HEIGHT (QUOTE INPUT)
			     (QUOTE REPLACE))
		     (NCONC1 FRAMEBLITLIST (create ACE.BLIT
						   BITMAP ← TEMP.BITMAP
						   XCOOR ← LEFT
						   YCOOR ← BOTTOM]
          (RETURN (CDR FRAMEBLITLIST])
)



(* REGION MAXING ROUTINES)

(DEFINEQ

(ACE.MAX.REGIONS
  [LAMBDA (REGIONS THRESHOLD)                                (* PmT "25-Apr-85 14:36")

          (* Merges the changed regions picked out by ACE.SCAN.BITMAPS; REGIONS are small areas of change, THRESHOLD specifies
	  how much bitmap area must by "good" for a combination (i.e. 100 -
	  THRESHOLD is how much space may be wasted in combining two REGIONS); Both ARGS required!)

                                                             (* RETURNS A LIST OF (REGION REGION ...))
    (PROG (BEST.POSS)
      LOOP(COND
	    [(IGREATERP (LENGTH REGIONS)
			1)
	      (SETQ BEST.POSS (ACE.PICK.BEST.REGION REGIONS))
	      (COND
		((IGEQ (CADDR BEST.POSS)
		       THRESHOLD)
		  (NCONC1 REGIONS (CONS (UNIONREGIONS (CAAR BEST.POSS)
						      (CAADR BEST.POSS))
					(CADDR BEST.POSS)))
		  (DREMOVE (CAR BEST.POSS)
			   REGIONS)
		  (DREMOVE (CADR BEST.POSS)
			   REGIONS))
		(T (GO DONE]
	    (T (GO DONE)))
          (GO LOOP)
      DONE(RETURN (for X in REGIONS collect (CAR X])

(ACE.PICK.BEST.REGION
  [LAMBDA (REGIONS)                                          (* PmT "25-Apr-85 14:42")

          (* SLOWest part of animation! Selects the most efficient (i.e. least amount of wasted space resulting from combining
	  two regions) combination of two regions from REGIONS; First tries to find 100% match up; failing that goes for 
	  highest efficiency)


    (PROG (EFFICIENCY BEST.SO.FAR)
          [COND
	    [(for X in REGIONS
		thereis (AND (EQP (CDR X)
				  100)
			     (for Y in (CDR (MEMB X REGIONS))
				thereis
				 (AND (EQP (CDR Y)
					   100)
				      [OR [AND (EQP (fetch (REGION LEFT) of (CAR X))
						    (fetch (REGION LEFT) of (CAR Y)))
					       (OR [EQP (fetch (REGION BOTTOM) of (CAR Y))
							(ADD1 (fetch (REGION TOP)
								 of (CAR X]
						   (EQP (ADD1 (fetch (REGION TOP)
								 of (CAR Y)))
							(fetch (REGION BOTTOM) of (CAR X]
					  (AND (EQP (fetch (REGION BOTTOM) of (CAR X))
						    (fetch (REGION BOTTOM) of (CAR Y)))
					       (OR [EQP (fetch (REGION LEFT) of (CAR Y))
							(ADD1 (fetch (REGION RIGHT)
								 of (CAR X]
						   (EQP (ADD1 (fetch (REGION RIGHT)
								 of (CAR Y)))
							(fetch (REGION LEFT) of (CAR X]
				      (SETQ BEST.SO.FAR (LIST X Y 100]
	    (T (SETQ BEST.SO.FAR (QUOTE (NIL NIL -1)))
	       (for X in REGIONS do (for Y in (CDR (MEMB X REGIONS))
				       do ((SETQ EFFICIENCY (IQUOTIENT
					       [ITIMES 100 (IPLUS (ACE.COMPUTE.AREA (CAR X)
										    (CDR X))
								  (ACE.COMPUTE.AREA (CAR Y)
										    (CDR Y]
					       (ACE.COMPUTE.AREA (UNIONREGIONS (CAR X)
									       (CAR Y))
								 100)))
					   (AND (IGREATERP EFFICIENCY (CADDR BEST.SO.FAR))
						(SETQ BEST.SO.FAR (LIST X Y EFFICIENCY]
          (RETURN BEST.SO.FAR])

(ACE.COMPUTE.AREA
  [LAMBDA (REGION EFF)                                       (* PmT "27-Sep-84 16:02")
    (IQUOTIENT (ITIMES (ffetch (REGION WIDTH) of REGION)
		       (ffetch (REGION HEIGHT) of REGION)
		       EFF)
	       100])
)



(* LOW LEVEL BITMAP COMPARISON)

(DEFINEQ

(ACE.SCAN.BITMAPS
  [LAMBDA (BM.ORIG BM.NEW BLOCKINGHEIGHT)                    (* PmT "25-Apr-85 15:14")

          (* Compares BM.ORIG and BM.NEW in one word (ACE.PIXPERWORD bits; 16) by BLOCKINGHEIGHT rectangles.
	  Note masking when get to last word in bitmap and compression of region below ACE.PIXPERWORD 
	  (16); All ARGS required; BM.ORIG and BM.NEW must have the same dimensions!)

                                                             (* RETURNS A LIST OF TYPE (REGION . 100))
    (PROG [TEMP.ENTRY (BM.WIDTH (ffetch BITMAPWIDTH of BM.ORIG))
		      (CHANGED.REGIONS (CONS))
		      (RASTERWIDTH (SUB1 (ffetch BITMAPRASTERWIDTH of BM.ORIG)))
		      (HEIGHT (SUB1 (ffetch BITMAPHEIGHT of BM.ORIG)))
		      (ALLMASK (ELT ACE.BITMAP.MASK 0))
		      (PARTIALMASK (ELT ACE.BITMAP.MASK (IMOD (ffetch BITMAPWIDTH of BM.ORIG)
							      ACE.PIXPERWORD]
          [while (ILESSP Y HEIGHT) bind (Y ← 0)
	     do [for HORZ.BLOCK from 0 to RASTERWIDTH
		   do (AND [SETQ TEMP.ENTRY (COND
			       ((EQP HORZ.BLOCK RASTERWIDTH)
				 (ACE.SCAN.PRIMBLOCKS BM.ORIG BM.NEW HORZ.BLOCK Y BLOCKINGHEIGHT 
						      PARTIALMASK))
			       (T (ACE.SCAN.PRIMBLOCKS BM.ORIG BM.NEW HORZ.BLOCK Y BLOCKINGHEIGHT 
						       ALLMASK]
			   (NCONC1 CHANGED.REGIONS (CONS [CREATEREGION (ITIMES HORZ.BLOCK 
									       ACE.PIXPERWORD)
								       (CAR TEMP.ENTRY)
								       (IMIN ACE.PIXPERWORD
									     (IDIFFERENCE
									       BM.WIDTH
									       (ITIMES HORZ.BLOCK 
										   ACE.PIXPERWORD)))
								       (ADD1 (IDIFFERENCE
									       (CDR TEMP.ENTRY)
									       (CAR TEMP.ENTRY]
							 100]
		(SETQ Y (IPLUS Y BLOCKINGHEIGHT))
		(SETQ BLOCKINGHEIGHT (IMIN BLOCKINGHEIGHT (ADD1 (IDIFFERENCE HEIGHT Y]
          (RETURN (CDR CHANGED.REGIONS])

(ACE.SCAN.PRIMBLOCKS
  [LAMBDA (BM1 BM2 WORDOFFSET Y0 BLOCKH MASK)                (* PmT "25-Apr-85 14:49")

          (* Does the actual comparison of primitive areas in the two bitmaps BM1 and BM2 ; WORDOFFSET is the raster word 
	  offset; Y0 is the low scanline and (IPLUS Y0 BLOCKH) is the hi one; MASK is usually $FFFF, otherwise it is used to 
	  ignore extra bits trailing off the end of the last raster word)


    (PROG [TEMP1 (MAXY (SUB1 (IPLUS Y0 BLOCKH]
          [SETQ TEMP1 (for Y from Y0 to MAXY
			 thereis (NOT (EQP (LOGAND (LOGXOR (ACE.FETCH.BLOCK BM1 WORDOFFSET Y)
							   (ACE.FETCH.BLOCK BM2 WORDOFFSET Y))
						   MASK)
					   0]
          (RETURN (AND TEMP1 (CONS TEMP1 (for Y from MAXY to TEMP1 by -1
					    thereis (NOT (EQP (LOGAND (LOGXOR (ACE.FETCH.BLOCK BM1 
										       WORDOFFSET Y)
									      (ACE.FETCH.BLOCK BM2 
										       WORDOFFSET Y))
								      MASK)
							      0])

(ACE.FETCH.BLOCK
  [LAMBDA (BITMAP WORDOFFSET VERTICAL)                       (* PmT "25-Apr-85 14:59")
                                                             (* Nabs a word from bitmap on line VERTICAL with word 
							     offset WORDOFFSET)
    (\GETBASE (\ADDBASE (ffetch BITMAPBASE of BITMAP)
			(ITIMES (IDIFFERENCE (ffetch BITMAPHEIGHT of BITMAP)
					     (ADD1 VERTICAL))
				(ffetch BITMAPRASTERWIDTH of BITMAP)))
	      WORDOFFSET])
)
(DECLARE: DONTCOPY
  (FILEMAP (NIL (991 2968 (ACE.COMPILE.FRAME 1001 . 1895) (ACE.EXTRACT 1897 . 2966)) (3004 6597 (
ACE.MAX.REGIONS 3014 . 4147) (ACE.PICK.BEST.REGION 4149 . 6328) (ACE.COMPUTE.AREA 6330 . 6595)) (6638 
10232 (ACE.SCAN.BITMAPS 6648 . 8653) (ACE.SCAN.PRIMBLOCKS 8655 . 9718) (ACE.FETCH.BLOCK 9720 . 10230))
)))
STOP