/* * MandelVroom 2.0 * * (c) Copyright 1987,1989 Kevin L. Clague, San Jose, CA * * All rights reserved. * * Permission is hereby granted to distribute this program's source * executable, and documentation for non-comercial purposes, so long as the * copyright notices are not removed from the sources, executable or * documentation. This program may not be distributed for a profit without * the express written consent of the author Kevin L. Clague. * * This program is not in the public domain. * * Fred Fish is expressly granted permission to distribute this program's * source and executable as part of the "Fred Fish freely redistributable * Amiga software library." * * Permission is expressly granted for this program and it's source to be * distributed as part of the Amicus Amiga software disks, and the * First Amiga User Group's Hot Mix disks. * * contents: this file contains the code that implements the lens effect * (pixelized expansion) when zooming in. * */ #include "mandp.h" /* Lens algorithm: * * Initialization - Create RastPort and BitMap as a work area * * Lens Expansion - * Phase 1 (Horizontal Expansion) * 1. Working from left side of NavBox to Right * 2. expand one verticle line from NavBox into temp rastport. * 3. duplicate the line in temp rastport to expansion width * 4. Continue for enough lines to fill the temp rastport * * Phase 2 (Verticle Expansion) * 1. Working from top of temp rastport to bottom * 2. expand one horizontal line from temp rastport into Lens * window rastport. * 3. duplicate the line in Lens window rastport to expansion height * 4. Continue for enough lines in the temp rastport */ /* These structures are used to hold horizontally expanded view of lenz expansion */ static struct RastPort LensRp; static struct BitMap LensBitMap; static LONG LensWidth, LensHeight; UBYTE LensOK; UBYTE LensOn = 1; #ifdef TEMPWINDOW #define SAFEBLIT static struct NewWindow NewTemp = { 0,12, /* start position */ 80,80, /* width, height */ (UBYTE) 0, (UBYTE) NORMALPEN, MOUSEBUTTONS, /* IDCMP flags */ /* MandWind flags */ WINDOWDRAG | NOCAREREFRESH | SMART_REFRESH, (struct Gadget *) NULL, /* first gadget */ (struct Image *) NULL, /* user checkmark */ (UBYTE *) NULL, /* Title */ (struct Screen *) NULL, /* pointer to screen */ (struct BitMap *) NULL, /* pointer to superbitmap */ 20,20,-1,-1, /* sizing */ CUSTOMSCREEN /* type of screen */ }; static struct Window *TempWind; #endif AllocLensTemp( Pict ) register struct Picture *Pict; { LONG Plane; PLANEPTR t; extern struct MenuItem LensSub[]; static LensInited; extern struct NewScreen NewScreen; if ( !LensOn ) return; if (LensOK == 1) return; if (Pict == Pict->DrawPict) return; #ifdef TEMPWINDOW NewTemp.Width = Pict->Window->Width; NewTemp.Height = Pict->DrawPict->Window->Height; NewTemp.LeftEdge = NewScreen.Width - NewTemp.Width-2; NewTemp.TopEdge = 0; NewTemp.Screen = screen; TempWind = OpenWindow( &NewTemp ); /*WindowToBack( TempWind );*/ LensOK = TempWind != NULL; #else if ( ! LensInited ) { InitRastPort( &LensRp ); LensRp.BitMap = &LensBitMap; LensInited = 1; } LensWidth = Pict->Window->Width; LensHeight = Pict->DrawPict->Window->Height; InitBitMap( &LensBitMap, (long) NewScreen.Depth, LensWidth, LensHeight); for (Plane = 0; Plane < NewScreen.Depth; Plane++) { t = (PLANEPTR) AllocRaster(LensWidth,LensHeight); LensBitMap.Planes[Plane] = (PLANEPTR) t; if (t == NULL) { FreeLensTemp( ); return; } } LensOK = 1; #endif } FreeLensTemp( ) { LONG Plane; if (LensOK) { #ifdef TEMPWINDOW CloseWindow( TempWind ); #else for (Plane = 0; Plane < LensBitMap.Depth; Plane++) { if (LensBitMap.Planes[Plane]) { FreeRaster( (char *) LensBitMap.Planes[Plane], LensWidth, LensHeight); LensBitMap.Planes[Plane] = NULL; } } #endif LensOK = 0; } } #ifdef SAFEBLIT SafeClipBlit( src_Wind, src_x, src_y, dst_Wind, dst_x, dst_y, width, height, min_terms, line_no ) struct Window *src_Wind, *dst_Wind; LONG src_x, src_y, dst_x, dst_y, width, height, min_terms; LONG line_no; { if (src_x < 0 || src_x > src_Wind->Width) { printf("Line %d Bad blit src_x %d Width %d\n", line_no,src_x,src_Wind->Width); return; } if (src_y < 0 || src_y > src_Wind->Height) { printf("Line %d Bad blit src_y %d Height %d\n", line_no, src_y,src_Wind->Height); return; } if (width < 1 || width > src_Wind->Width) { printf("Line %d Bad blit width %d\n",line_no, width); return; } if (src_x + width > src_Wind->Width) { printf("Line %d Blit outside %d Width %d \n", line_no,src_x+width,src_Wind->Width); return; } if (height < 1 || height > src_Wind->Height) { printf("Line %d Bad blit height %d\n",line_no,height); return; } if (src_y + height > src_Wind->Height) { printf("Line %d Blit outside %d Height %d \n", line_no,src_y+height,src_Wind->Height); return; } ClipBlit( src_Wind->RPort, src_x, src_y, dst_Wind->RPort, dst_x, dst_y, width, height, min_terms); } #endif /* Do Lens effect using temporary rastort, ClipBlit() with exponential expansion */ Lens( Pict ) register struct Picture *Pict; { struct Picture *DrawPict; LONG ExpFactor; LONG MaxHeight,MaxWidth; LONG SrcPos, SrcMax; LONG DstPos, DstMax; LONG EOL; LONG NextPos, AccPos; LONG AccExp; LONG FirstSrc,FirstDst,NumOnes; static LONG OldLeft,OldTop,OldExp; LONG Top,Left,Bot,t; struct Window *src_Wind,*dst_Wind; struct RastPort *src_Rp, *dst_Rp, *tmp_Rp; DrawPict = Pict->DrawPict; if (DrawPict == NULL) return; CloseZoomBoxList( Pict ); src_Wind = DrawPict->Window; dst_Wind = Pict->Window; src_Rp = src_Wind->RPort; dst_Rp = dst_Wind->RPort; if (src_Rp == dst_Rp) return; #ifdef TEMPWINDOW tmp_Rp = TempWind->RPort; #else tmp_Rp = &LensRp; #endif if ( !LensOK ) return; #ifndef TEMPWINDOW SetRast( tmp_Rp, (long) NORMALPEN ); #endif /* turn the Nav Box upside down, so the bit map is not inverted */ Top = Pict->NavTop; Bot = Pict->NavBot; Left = Pict->NavLeft; if (Bot < Top) { t = Bot; Bot = Top; Top = t; } if (Pict->NavRight < Left) { Left = Pict->NavRight; } /* Do Horizontal Expansion into a temporary bitmap */ /* src = DrawPict */ /* dst = Pict */ MaxHeight = Bot - Top + 1; if (MaxHeight == 0) return; DstPos = 0; DstMax = dst_Wind->Width - Pict->LeftMarg - Pict->RightMarg; SrcMax = src_Wind->Width - DrawPict->RightMarg; #define SHIFT_FACTOR 8 AccExp = ((dst_Wind->Height - Pict->TopMarg - Pict->BotMarg) << SHIFT_FACTOR) / MaxHeight; if (OldLeft == Left && OldTop == Top && OldExp == AccExp) return; Pict->Flags |= LENS_DISPLAYED; OldLeft = Left; OldTop = Top; OldExp = AccExp; AccPos = DstPos << SHIFT_FACTOR; EOL = 0; NumOnes = 0; for (SrcPos = Left; SrcPos < SrcMax && ! EOL; SrcPos++) { AccPos += AccExp; NextPos = AccPos >> SHIFT_FACTOR; ExpFactor = NextPos - DstPos; /* Accumulate adjacent single line blits */ if (ExpFactor == 1) { if (NumOnes == 0) { FirstSrc = SrcPos; FirstDst = DstPos; } NumOnes++; } else { /* Copy accumulated adjcent single line copies */ if (NumOnes > 0) { #ifndef SAFEBLIT ClipBlit( src_Rp, FirstSrc, (long) Top, tmp_Rp, FirstDst, 0, NumOnes, MaxHeight, (long) 0xc0 ); #else SafeClipBlit( src_Wind, FirstSrc, Top, TempWind, FirstDst, 0, NumOnes, MaxHeight, 0xc0, __LINE__ ); #endif NumOnes = 0; } if (ExpFactor > 1) { register LONG WrkPos, WrkOff, Last, DstExp; /* Expand Pattern exponentially */ WrkPos = DstPos + 1; WrkOff = 1; Last = 0; DstExp = 1; /* Copy First line */ #ifndef SAFEBLIT ClipBlit( src_Rp, SrcPos, (long) Top, tmp_Rp, DstPos, 0, (long) 1, MaxHeight, (long) 0xc0 ); #else SafeClipBlit( src_Wind, SrcPos, Top, TempWind, DstPos, 0, 1, MaxHeight, 0xc0, __LINE__); #endif /* Now expand it exponentially */ do { if ( WrkOff + DstExp >= ExpFactor ) { Last = 1; DstExp = ExpFactor - WrkOff; } if ( WrkPos + DstExp >= DstMax ) { Last = 1; EOL = 1; DstExp = DstMax - WrkPos; } if (DstExp) { #ifndef SAFEBLIT ClipBlit( tmp_Rp, DstPos, 0, tmp_Rp, WrkPos, 0, DstExp, MaxHeight, (long) 0xc0 ); #else SafeClipBlit( TempWind, DstPos, 0, TempWind, WrkPos, 0, DstExp, MaxHeight, 0xc0, __LINE__); #endif WrkPos += DstExp; WrkOff += DstExp; DstExp <<= 1; } } while ( ! Last ); } } if ((DstPos = NextPos) >= DstMax) EOL = 1; } if (NumOnes > 0) { #ifndef SAFEBLIT ClipBlit( src_Rp, FirstSrc, (long) Top, tmp_Rp, FirstDst, 0, NumOnes, MaxHeight, (long) 0xc0 ); #else SafeClipBlit( src_Wind, FirstSrc, Top, TempWind, FirstDst, 0, NumOnes, MaxHeight, 0xc0, __LINE__); #endif } NumOnes = 0; ZoomBox( Pict ); /* src = DrawPict */ /* dst = Pict */ /* Do Verticle Expansion */ MaxWidth = dst_Wind->Width - Pict->LeftMarg - Pict->RightMarg; DstPos = Pict->TopMarg; DstMax = dst_Wind->Height - Pict->BotMarg; SrcMax = src_Wind->Height; EOL = 0; AccPos = DstPos << SHIFT_FACTOR; for (SrcPos = 0; SrcPos < SrcMax && !EOL; SrcPos++) { AccPos += AccExp; NextPos = AccPos >> SHIFT_FACTOR; ExpFactor = NextPos - DstPos; /* Accumulate adjacent single line blits */ if (ExpFactor == 1) { if (NumOnes == 0) { FirstSrc = SrcPos; FirstDst = DstPos; } NumOnes++; } else { /* Copy accumulated adjacent single line copies */ if (NumOnes > 0) { #ifndef SAFEBLIT ClipBlit( tmp_Rp, 0, FirstSrc, dst_Rp, Pict->LeftMarg, FirstDst, MaxWidth, NumOnes, (long) 0xc0 ); #else SafeClipBlit( TempWind, 0, FirstSrc, dst_Wind, Pict->LeftMarg, FirstDst, MaxWidth, NumOnes, 0xc0, __LINE__); #endif NumOnes = 0; } if ( ExpFactor > 1 ) { register LONG WrkPos, WrkOff, Last, DstExp; /* Expand Pattern exponentially */ WrkPos = DstPos + 1; WrkOff = 1; Last = 0; DstExp = 1; /* Copy First Horizontal Line */ #ifndef SAFEBLIT ClipBlit( tmp_Rp, 0, SrcPos, dst_Rp, Pict->LeftMarg, DstPos, MaxWidth, (long) 1, (long) 0xc0 ); #else SafeClipBlit( TempWind, 0, SrcPos, dst_Wind, Pict->LeftMarg, DstPos, MaxWidth, 1, 0xc0, __LINE__ ); #endif do { if ( WrkOff + DstExp >= ExpFactor ) { Last = 1; DstExp = ExpFactor - WrkOff; } if ( WrkPos + DstExp >= DstMax ) { Last = 1; EOL = 1; DstExp = DstMax - WrkPos; } if (DstExp) { #ifndef SAFEBLIT ClipBlit( dst_Rp, Pict->LeftMarg, DstPos, dst_Rp, Pict->LeftMarg, WrkPos, MaxWidth, DstExp, (long) 0xc0 ); #else SafeClipBlit( dst_Wind, Pict->LeftMarg, DstPos, dst_Wind, Pict->LeftMarg, WrkPos, MaxWidth, DstExp, 0xc0, __LINE__ ); #endif WrkPos += DstExp; WrkOff += DstExp; DstExp <<= 1; } } while ( ! Last ); } } if ((DstPos = NextPos) >= DstMax) EOL = 1; } /* Copy accumulated adjacent single line copies */ if (NumOnes > 0) { #ifndef SAFEBLIT ClipBlit( tmp_Rp, 0, FirstSrc, dst_Rp, Pict->LeftMarg, FirstDst, MaxWidth,NumOnes, (long) 0xc0 ); #else SafeClipBlit( TempWind, 0, FirstSrc, dst_Wind, Pict->LeftMarg, FirstDst, MaxWidth, NumOnes, 0xc0, __LINE__ ); #endif } ZoomBox( Pict ); } CloseZoomBoxList( Pict ) register struct Picture *Pict; { register struct Node *zNode; register struct Picture *ClosePict; struct Picture *PictAddr(); zNode = Pict->zList.lh_Head; while ( zNode->ln_Succ ) { ClosePict = PictAddr( zNode ); if (Pict != ClosePict) { CloseZoomBox(ClosePict); } zNode = zNode->ln_Succ; } }