/* void notify(in nsITimer timer); */ NS_IMETHODIMP imgContainer::Notify(nsITimer *timer) { // Note that as long as the image is animated, it will not be discarded, // so this should never happen... nsresult rv = RestoreDiscardedData(); NS_ENSURE_SUCCESS(rv, rv); // This should never happen since the timer is only set up in StartAnimation() // after mAnim is checked to exist. NS_ENSURE_TRUE(mAnim, NS_ERROR_UNEXPECTED); NS_ASSERTION(mAnim->timer == timer, "imgContainer::Notify() called with incorrect timer"); if (!mAnim->animating || !mAnim->timer) return NS_OK; nsCOMPtr<imgIContainerObserver> observer(do_QueryReferent(mObserver)); if (!observer) { // the imgRequest that owns us is dead, we should die now too. StopAnimation(); return NS_OK; } if (mNumFrames == 0) return NS_OK; gfxIImageFrame *nextFrame = nsnull; PRInt32 previousFrameIndex = mAnim->currentAnimationFrameIndex; PRInt32 nextFrameIndex = mAnim->currentAnimationFrameIndex + 1; PRInt32 timeout = 0; // If we're done decoding the next frame, go ahead and display it now and // reinit the timer with the next frame's delay time. // currentDecodingFrameIndex is not set until the second frame has // finished decoding (see EndFrameDecode) if (mAnim->doneDecoding || (nextFrameIndex < mAnim->currentDecodingFrameIndex)) { if (mNumFrames == nextFrameIndex) { // End of Animation // If animation mode is "loop once", it's time to stop animating if (mAnimationMode == kLoopOnceAnimMode || mLoopCount == 0) { StopAnimation(); return NS_OK; } else { // We may have used compositingFrame to build a frame, and then copied // it back into mFrames[..]. If so, delete composite to save memory if (mAnim->compositingFrame && mAnim->lastCompositedFrameIndex == -1) mAnim->compositingFrame = nsnull; } nextFrameIndex = 0; if (mLoopCount > 0) mLoopCount--; } if (!(nextFrame = mFrames[nextFrameIndex])) { // something wrong with the next frame, skip it mAnim->currentAnimationFrameIndex = nextFrameIndex; mAnim->timer->SetDelay(100); return NS_OK; } nextFrame->GetTimeout(&timeout); } else if (nextFrameIndex == mAnim->currentDecodingFrameIndex) { // Uh oh, the frame we want to show is currently being decoded (partial) // Wait a bit and try again mAnim->timer->SetDelay(100); return NS_OK; } else { // (nextFrameIndex > currentDecodingFrameIndex) // We shouldn't get here. However, if we are requesting a frame // that hasn't been decoded yet, go back to the last frame decoded NS_WARNING("imgContainer::Notify() Frame is passed decoded frame"); nextFrameIndex = mAnim->currentDecodingFrameIndex; if (!(nextFrame = mFrames[nextFrameIndex])) { // something wrong with the next frame, skip it mAnim->currentAnimationFrameIndex = nextFrameIndex; mAnim->timer->SetDelay(100); return NS_OK; } nextFrame->GetTimeout(&timeout); } if (timeout > 0) mAnim->timer->SetDelay(timeout); else StopAnimation(); nsIntRect dirtyRect; gfxIImageFrame *frameToUse = nsnull; if (nextFrameIndex == 0) { frameToUse = nextFrame; dirtyRect = mAnim->firstFrameRefreshArea; } else { gfxIImageFrame *prevFrame = mFrames[previousFrameIndex]; if (!prevFrame) return NS_OK; // Change frame and announce it if (NS_FAILED(DoComposite(&frameToUse, &dirtyRect, prevFrame, nextFrame, nextFrameIndex))) { // something went wrong, move on to next NS_WARNING("imgContainer::Notify(): Composing Frame Failed\n"); mAnim->currentAnimationFrameIndex = nextFrameIndex; return NS_OK; } } // Set currentAnimationFrameIndex at the last possible moment mAnim->currentAnimationFrameIndex = nextFrameIndex; // Refreshes the screen observer->FrameChanged(this, frameToUse, &dirtyRect); return NS_OK; }
EFFECTEXEC(frame,tags,PPTBase,EffectBase) { ULONG sig, rc, *args; BOOL quit = FALSE, reallyrexx = FALSE; FRAME *newframe = NULL, *with = NULL; struct gFixRectMessage gfr = {0}; ULONG fc, wc; struct Values *av; D(bug(MYNAME": Exec()\n")); /* * Defaults */ v.ratio = 128; v.method = Direct; v.bounds.Top = v.bounds.Left = ~0; v.bounds.Width = 200; v.bounds.Height = 100; v.tile = FALSE; if( av = GetOptions(MYNAME) ) { v = *av; } /* * Copy to local variables */ BGUIBase = PPTBase->lb_BGUI; IntuitionBase = (struct IntuitionBase *)PPTBase->lb_Intuition; DOSBase = PPTBase->lb_DOS; SysBase = PPTBase->lb_Sys; /* * Parse AREXX message, which has to exist. * BUG: If necessary, should wait for D&D from the main window. * BUG: Should make sanity checks! */ args = (ULONG *) TagData( PPTX_RexxArgs, tags ); if( args ) { /* WITH */ if( args[0] ) { with = FindFrame( (ID) PEEKL(args[0]) ); if(!with) { SetErrorMsg(frame,"Unknown frame ID for WITH parameter"); return NULL; } } /* TOP */ if( args[1] ) { gfr.y = (WORD) PEEKL(args[1]); reallyrexx = TRUE; } /* LEFT */ if( args[2] ) { gfr.x = (WORD) PEEKL(args[2]); reallyrexx = TRUE; } /* METHOD */ if( args[3] ) { int i; for( i = 0; method_labels[i]; i++ ) { if(stricmp( method_labels[i], (char *)args[3] ) == 0 ) { v.method = i; reallyrexx = TRUE; break; } } } /* RATIO */ if( v.method == Mix ) { if( args[4] ) { v.ratio = PEEKL( args[4] ); } else { SetErrorCode(frame,PERR_INVALIDARGS); } } /* TILE */ if( args[5] ) { v.tile = TRUE; } else { v.tile = FALSE; } } else { SetErrorMsg(frame,"Image compositing can be used with Drag&Drop (or REXX) only"); return NULL; } /* * Make some sanity checks */ if( frame->pix->width < with->pix->width || frame->pix->height < with->pix->height ) { SetErrorMsg(frame,"You cannot composite a larger picture on a smaller one!"); return NULL; } fc = frame->pix->colorspace; wc = with->pix->colorspace; if( ! (wc == fc || (fc == CS_ARGB && wc == CS_RGB) || (fc == CS_RGB && wc == CS_ARGB ))) { SetErrorMsg(frame, "Only images of the same color space can be composited"); return NULL; } gfr.dim.Left = 0; gfr.dim.Top = 0; gfr.dim.Height = with->pix->height; gfr.dim.Width = with->pix->width; /* * Open window and start parsing */ if( reallyrexx == FALSE ) { if( GimmeWindow(frame, with, PPTBase) ) { ULONG sigmask, gimask = 0L; GetAttr( WINDOW_SigMask, Win, &sigmask ); StartInput(frame, GINP_FIXED_RECT, (struct PPTMessage *) &gfr); gimask = (1 << PPTBase->mport->mp_SigBit); while( !quit ) { sig = Wait( sigmask|gimask|SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_F ); if( sig & SIGBREAKF_CTRL_C ) { D(bug("BREAK!\n")); SetErrorCode( frame, PERR_BREAK ); quit = TRUE; break; } if( sig & SIGBREAKF_CTRL_F ) { WindowToFront(win); ActivateWindow(win); } if( sig & gimask ) { struct gFixRectMessage *pmsg; if(pmsg = (struct gFixRectMessage *)GetMsg( PPTBase->mport )) { if( pmsg->msg.code == PPTMSG_FIXED_RECT ) { D(bug("User picked a point @ (%d,%d)\n",pmsg->x, pmsg->y)); gfr.x = pmsg->x; gfr.y = pmsg->y; // SetGadgetAttrs( ( struct Gadget *)OKButton, win, NULL, GA_Disabled, FALSE ); } ReplyMsg( (struct Message *)pmsg ); } } if( sig & sigmask ) { while( (rc = HandleEvent( Win )) != WMHI_NOMORE ) { ULONG t; switch(rc) { case GID_OK: GetAttr( CYC_Active, Method, (ULONG *)&v.method ); GetAttr( SLIDER_Level, Ratio, &v.ratio ); /* * Save the window attributes for later retrieval. */ GetAttr( WINDOW_Bounds, Win, (ULONG *) &v.bounds ); GetAttr( GA_Selected, Tile, &t ); StopInput( frame ); v.tile = (BOOL) t; WindowClose(Win); newframe = DoComposite( frame, with, &gfr, v.method, (WORD) v.ratio, v.tile, PPTBase ); quit = TRUE; break; case GID_CANCEL: quit = TRUE; StopInput( frame ); break; } } } } } } else { /* gfr is already set up */ newframe = DoComposite( frame, with, &gfr, v.method, (WORD) v.ratio, v.tile, PPTBase ); } if(Win) DisposeObject(Win); if( newframe ) { PutOptions( MYNAME, &v, sizeof(struct Values) ); } D(bug("Returning %08X...\n",newframe)); return newframe; }