/* * 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 functions used to implement MandelVroom's * pan command. It seems to have a bug when resizing pictures slightly * smaller. */ #include "mandp.h" static int ScrollHotX, ScrollHotY; UBYTE ScrollOn = 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 ScrollPictCmd(Msg) struct IntuiMessage *Msg; { struct Window *Window; static struct Picture *Pict; Window = Msg->IDCMPWindow; Pict = (struct Picture *) Window->UserData; switch( Msg->Class ) { case NEWSIZE: if (CurPict && (CurPict->Flags & SCROLL_HAPPENED)) { MoveClipImage(CurPict); } break; case MENUPICK: switch( SUBNUM(Msg->Code) ) { case SETSCROLL: State = SCROLLPICTSTATE; ThrowTask(CurPict); if ( ! (CurPict->Flags & SCROLL_HAPPENED)) { if ( AllocScrollTemp(CurPict) == UNSUCCESSFUL ) { return; } SaveInitialImage(CurPict); } CurPict->Flags |= SCROLL_HAPPENED; SetToPointer(); break; case GENSCROLL: if (CurPict && CurPict->Flags & SCROLL_HAPPENED) { Generate(CurPict); } break; case CANCELSCROLL: ReColor(CurPict); break; } break; case MOUSEBUTTONS: switch( Msg->Code ) { case SELECTDOWN: /* start drag */ if (Pict == NULL || Pict != CurPict) { return; } ScrollHotX = MouseX - CurPict->ImageLoc.Left; ScrollHotY = MouseY - CurPict->ImageLoc.Top; Scroll( CurPict); ModifyIDCMP(Window, Window->IDCMPFlags | MOUSEMOVE); break; case SELECTUP: /* stop slide */ ModifyIDCMP(Window, Window->IDCMPFlags & ~MOUSEMOVE); break; } break; case MOUSEMOVE: Scroll( CurPict); break; } } SaveInitialImage(Pict) struct Picture *Pict; { #ifdef SAFEBLIT SafeClipBlit(Pict->Window, Pict->LeftMarg, Pict->TopMarg, TempWind, 0, 0, Pict->CountX, Pict->CountY, 0xc0, __LINE__); #else ClipBlit(Pict->Window->RPort, Pict->LeftMarg, Pict->TopMarg, &Pict->ScrollRp, 0, 0, Pict->CountX, Pict->CountY, 0xc0); #endif } Scroll( Pict ) struct Picture *Pict; { CalcNewLoc(Pict,MouseX,MouseY); /* figure out location of new image */ MoveClipImage(Pict); } CalcNewLoc(Pict, MouseX, MouseY) register struct Picture *Pict; int MouseX, MouseY; { /* set new ImageLoc */ Pict->ImageLoc.Top = MouseY - ScrollHotY; Pict->ImageLoc.Left = MouseX - ScrollHotX; Pict->ImageLoc.Bot = Pict->ImageLoc.Top + Pict->CountY; Pict->ImageLoc.Right = Pict->ImageLoc.Left + Pict->CountX; } MoveClipImage(Pict) register struct Picture *Pict; { struct Window *Window; struct RastPort *wind_Rp, *tmp_Rp; register int POLeft, PORight, POTop, POBot; struct Rect SaveRect; struct Rect DispRect; Window = Pict->Window; SaveRect = Pict->ClipImage; /* struct assign */ DispRect.Left = Pict->LeftMarg; DispRect.Top = Pict->TopMarg; DispRect.Right = Window->Width - Pict->RightMarg - 1; DispRect.Bot = Window->Height - Pict->BotMarg - 1; if (Pict->ImageLoc.Left > DispRect.Right || Pict->ImageLoc.Top > DispRect.Bot || Pict->ImageLoc.Right < DispRect.Left || Pict->ImageLoc.Bot < DispRect.Top ) { return; } if (Pict->ImageLoc.Left < DispRect.Left) { Pict->ClipImage.Left = DispRect.Left; POLeft = -Pict->ImageLoc.Left + Pict->LeftMarg; } else { Pict->ClipImage.Left = Pict->ImageLoc.Left; POLeft = 0; } if (Pict->ImageLoc.Top < DispRect.Top) { Pict->ClipImage.Top = DispRect.Top; POTop = -Pict->ImageLoc.Top + Pict->TopMarg; } else { Pict->ClipImage.Top = Pict->ImageLoc.Top; POTop = 0; } if (Pict->ImageLoc.Right <= DispRect.Right) { Pict->ClipImage.Right = Pict->ImageLoc.Right; PORight = Pict->CountX-1; } else { Pict->ClipImage.Right = DispRect.Right; PORight = DispRect.Right - Pict->ImageLoc.Left; } if (Pict->ImageLoc.Bot <= DispRect.Bot) { Pict->ClipImage.Bot = Pict->ImageLoc.Bot; POBot = Pict->CountY - 1; } else { Pict->ClipImage.Bot = DispRect.Bot; POBot = DispRect.Bot - Pict->ImageLoc.Top; } wind_Rp = Window->RPort; #ifdef TEMPWINDOW tmp_Rp = TempWind->RPort; #else tmp_Rp = &Pict->ScrollRp; #endif if (POLeft < PORight && POTop < POBot) { /* Now copy temp rastport data to window */ #ifdef SAFEBLIT SafeClipBlit(TempWind, POLeft, POTop, Window, Pict->ClipImage.Left, Pict->ClipImage.Top, PORight - POLeft + 1, POBot - POTop + 1, 0xc0, __LINE__); #else ClipBlit(tmp_Rp, POLeft, POTop, wind_Rp, Pict->ClipImage.Left, Pict->ClipImage.Top, PORight - POLeft + 1, POBot - POTop + 1, 0xc0); #endif #if 0 printf("l %d t %d r %d b %d\n",POLeft, POTop, PORight, POBot); printf("width %d height %d\n", PORight - POLeft + 1, POBot - POTop + 1); #endif } Pict->DataClip.Left = POLeft; Pict->DataClip.Right = PORight; Pict->DataClip.Top = POTop; Pict->DataClip.Bot = POBot; /* Undraw the old picture */ SetAPen(wind_Rp, 0); if (Pict->ClipImage.Left > SaveRect.Left) { FillCheck(Window, SaveRect.Left, SaveRect.Top, Pict->ClipImage.Left, SaveRect.Bot); } else if (Pict->ClipImage.Right < SaveRect.Right) { FillCheck(Window, Pict->ClipImage.Right, Pict->ClipImage.Top, SaveRect.Right, SaveRect.Bot); } if (Pict->ClipImage.Top > SaveRect.Top) { FillCheck(Window, SaveRect.Left, SaveRect.Top, SaveRect.Right, Pict->ClipImage.Top); } else if (Pict->ClipImage.Bot < SaveRect.Bot) { FillCheck(Window, SaveRect.Left, Pict->ClipImage.Bot, SaveRect.Right, SaveRect.Bot); } } FillCheck(Window,src_x,src_y,dst_x,dst_y) struct Window *Window; int src_x,src_y,dst_x,dst_y; { if (src_x < 0 || src_x > Window->Width) { #ifdef DEBUG printf("Bad Fill src_x %d Width %d\n", src_x,Window->Width); #endif return; } if (src_y < 0 || src_y > Window->Height) { #ifdef DEBUG printf("Bad Fill src_y %d Height %d\n", src_y,Window->Height); #endif return; } if (dst_x < 0 || dst_x > Window->Width) { #ifdef DEBUG printf("Bad Fill dst_x %d Width %d\n", dst_x,Window->Width); #endif return; } if (dst_y < 0 || dst_y > Window->Height) { #ifdef DEBUG printf("Bad Fill dst_y %d Height %d\n", dst_y,Window->Height); #endif return; } if (src_x > dst_x) { #ifdef DEBUG printf("inverted rect fill\n"); #endif return; } if (src_y > dst_y) { #ifdef DEBUG printf("end for end flipped rect fill\n"); #endif return; } RectFill(Window->RPort, src_x,src_y,dst_x,dst_y); } AllocScrollTemp( Pict ) register struct Picture *Pict; { LONG Plane; PLANEPTR t; extern struct MenuItem ScrollSub[]; static ScrollInited; extern struct NewScreen NewScreen; if ( !ScrollOn ) return; #ifdef TEMPWINDOW NewTemp.Width = Pict->Window->Width; NewTemp.Height = Pict->Window->Height; NewTemp.LeftEdge = NewScreen.Width - NewTemp.Width-2; NewTemp.TopEdge = 0; NewTemp.Screen = screen; TempWind = OpenWindow( &NewTemp ); /*WindowToBack( TempWind );*/ return( SUCCESSFUL ); #else if ( Pict->ScrollRp.BitMap == NULL ) { InitRastPort( &Pict->ScrollRp ); Pict->ScrollRp.BitMap = &Pict->ScrollBitMap; } InitBitMap( &Pict->ScrollBitMap, (long) NewScreen.Depth, Pict->CountX, Pict->CountY); for (Plane = 0; Plane < NewScreen.Depth; Plane++) { t = (PLANEPTR) AllocRaster(Pict->CountX, Pict->CountY); Pict->ScrollBitMap.Planes[Plane] = (PLANEPTR) t; if (t == NULL) { FreeScrollTemp( Pict ); return(UNSUCCESSFUL); } } return(SUCCESSFUL); #endif } FreeScrollTemp( Pict ) struct Picture *Pict; { LONG Plane; if (Pict->Flags & SCROLL_HAPPENED) { #ifdef TEMPWINDOW CloseWindow( TempWind ); #else for (Plane = 0; Plane < Pict->ScrollBitMap.Depth; Plane++) { if (Pict->ScrollBitMap.Planes[Plane]) { FreeRaster( (char *) Pict->ScrollBitMap.Planes[Plane], Pict->CountX,Pict->CountY); Pict->ScrollBitMap.Planes[Plane] = NULL; } } #endif } ResetScrollRects(Pict); } ResetScrollRects(Pict) struct Picture *Pict; { Pict->Flags &= ~SCROLL_HAPPENED; Pict->ImageLoc.Left = Pict->LeftMarg; Pict->ImageLoc.Top = Pict->TopMarg; Pict->ImageLoc.Right = Pict->LeftMarg + Pict->CountX - 1; Pict->ImageLoc.Bot = Pict->TopMarg + Pict->CountY - 1; Pict->ClipImage = Pict->ImageLoc; /* struct assignment */ } #ifdef SAFEBLIT static 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 ScrollComplex(Pict) struct Picture *Pict; { int left, top; int count_x, count_y; SHORT *NewCounts; count_x = Pict->Window->Width - Pict->LeftMarg - Pict->RightMarg; count_y = Pict->Window->Height - Pict->BotMarg - Pict->TopMarg; NewCounts = (SHORT *) safeAllocMem(count_x*count_y*sizeof(SHORT),MEMF_CLEAR); if (NewCounts == NULL) { DispErrMsg("Can't scroll. Out of RAM.",0); return; } ScrollData(Pict, NewCounts, count_x, count_y); FreeCounts( Pict ); left = Pict->ImageLoc.Left - Pict->LeftMarg; top = Pict->ImageLoc.Top - Pict->TopMarg; Pict->RealLow -= Pict->RealGap * left; Pict->ImagLow -= Pict->ImagGap * top; Pict->RealHigh = Pict->RealLow + Pict->RealGap * count_x; Pict->ImagHigh = Pict->ImagLow + Pict->ImagGap * count_y; FreeScrollTemp(Pict); Pict->Counts = NewCounts; Pict->CountX = count_x; Pict->CountY = count_y; Pict->CountsSize = count_x * count_y * sizeof(*Pict->Counts); Pict->CurLine = 0; } ScrollData(Pict, NewCounts, width, height) register struct Picture *Pict; SHORT *NewCounts; int width, height; { int sr,sc; register SHORT *s_rowp, *d_rowp, *sp, *dp; s_rowp = Pict->Counts + Pict->DataClip.Top * Pict->CountX; d_rowp = NewCounts + (Pict->ClipImage.Top-Pict->TopMarg) * width; for (sr = Pict->DataClip.Top; sr < Pict->DataClip.Bot; sr++) { dp = d_rowp + Pict->ClipImage.Left - Pict->LeftMarg; sp = s_rowp + Pict->DataClip.Left; for (sc = Pict->DataClip.Left; sc < Pict->DataClip.Right; sc++) { *dp++ = *sp++; } s_rowp += Pict->CountX; d_rowp += width; } }