static gboolean gtk_mng_view_expose (GtkWidget * widget, GdkEventExpose * event) { FUNCTION_ENTRY(); g_return_val_if_fail (IS_GTK_MNG_VIEW (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); if (GTK_WIDGET_REALIZED (widget)) { GdkRectangle dummy; GdkRectangle rectangle; GtkMngView * mng_view; mng_view = GTK_MNG_VIEW (widget); dummy.x = dummy.y = 0; dummy.width = mng_view->width; dummy.height = mng_view->height; if (gdk_rectangle_intersect (&dummy, &event->area, &rectangle)) gtk_mng_view_paint (mng_view, &rectangle); mng_display_resume(mng_view->MNG_handle); } FUNCTION_EXIT(); return FALSE; }
/* DestroyStream gets called after the file has finished loading, */ static NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason) { PluginInstance* This; if(!instance) return NPERR_INVALID_INSTANCE_ERROR; This = (PluginInstance*) instance->pdata; // if(reason==NPRES_DONE) { This->filesize = This->bytesloaded; This->loadstate = STATE_LOADED; // } if(reason!=NPRES_DONE) { set_error(This,"Image load failed or was canceled (%d)",(int)reason); This->needresume=0; if(This->timer_set) { KillTimer(This->fhWnd,1); This->timer_set=0; } return NPERR_NO_ERROR; } #ifdef MNGPLG_TRACE fprintf(tracefile,"NPP_DestroyStream reason=%d needresume=%d\n",reason,This->needresume); #endif if(This->needresume) { This->needresume=0; // handle_read_error(This, mng_read_resume(This->mng) ); handle_read_error(This, mng_display_resume(This->mng) ); // This->needresume=0; } return NPERR_NO_ERROR; }
/** ** Display a MNG ** ** @param x X coordinate ** @param y Y coordinate */ void Mng::Draw(int x, int y) { if (ticks <= GetTicks()) { mng_display_resume(handle); } #ifndef USE_OPENGL SDL_Rect rect = {x, y, surface->w, surface->h}; SDL_BlitSurface(surface, NULL, TheScreen, &rect); #else GLint sx = x; GLint ex = sx + surface->w; GLint sy = y; GLint ey = sy + surface->h; glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2i(sx, sy); glTexCoord2f(0.0f, texture_height); glVertex2i(sx, ey); glTexCoord2f(texture_width, texture_height); glVertex2i(ex, ey); glTexCoord2f(texture_width, 0.0f); glVertex2i(ex, sy); glEnd(); #endif }
/** ** Display a MNG ** ** @param x X coordinate ** @param y Y coordinate */ void Mng::Draw(int x, int y) { if (ticks <= GetTicks()) { mng_display_resume(handle); } #if defined(USE_OPENGL) || defined(USE_GLES) if (UseOpenGL) { GLint sx = x; GLint ex = sx + surface->w; GLint sy = y; GLint ey = sy + surface->h; #ifdef USE_GLES float texCoord[] = { 0.0f, 0.0f, texture_width, 0.0f, 0.0f, texture_height, texture_width, texture_height }; float vertex[] = { 2.0f / (GLfloat)Video.Width *sx - 1.0f, -2.0f / (GLfloat)Video.Height *sy + 1.0f, 2.0f / (GLfloat)Video.Width *ex - 1.0f, -2.0f / (GLfloat)Video.Height *sy + 1.0f, 2.0f / (GLfloat)Video.Width *sx - 1.0f, -2.0f / (GLfloat)Video.Height *ey + 1.0f, 2.0f / (GLfloat)Video.Width *ex - 1.0f, -2.0f / (GLfloat)Video.Height *ey + 1.0f }; glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, texCoord); glVertexPointer(2, GL_FLOAT, 0, vertex); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); #endif #ifdef USE_OPENGL glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2i(sx, sy); glTexCoord2f(0.0f, texture_height); glVertex2i(sx, ey); glTexCoord2f(texture_width, texture_height); glVertex2i(ex, ey); glTexCoord2f(texture_width, 0.0f); glVertex2i(ex, sy); glEnd(); #endif } else #endif { SDL_Rect rect = {x, y, surface->w, surface->h}; SDL_BlitSurface(surface, NULL, TheScreen, &rect); } }
static int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer) { PluginInstance* This; #ifdef MNGPLG_TRACE fprintf(tracefile,"NPP_Write offs=%d len=%d\n",offset,len); #endif if(!instance) return -1; This = (PluginInstance*) instance->pdata; if(!This) return -1; if(len<1) return len; if(offset+len > (int)This->bytesalloc) { // oops, overflowed our memory buffer This->bytesalloc += ALLOC_CHUNK_SIZE; if(This->mngdata) { This->mngdata=realloc(This->mngdata, This->bytesalloc); } else { // first time This->mngdata=malloc(This->bytesalloc); } if(!This->mngdata) { warn(This,"Cannot allocate memory for image (%d,%d,%p",offset,len,buffer); return -1; } } // now we should have enough room to copy the data to memory CopyMemory(&This->mngdata[offset],buffer,len); This->bytesloaded = offset+len; // now, check if it's time to call mng_read_resume if(This->needresume && (This->bytesloaded >= (This->libmngpos + This->byteswanted)) ) { This->needresume=0; // handle_read_error(This, mng_read_resume(This->mng) ); #ifdef MNGPLG_TRACE fprintf(tracefile,"NPP_Write display_resume bytesloaded=%d libmngpos=%d byteswanted=%d\n", This->bytesloaded,This->libmngpos,This->byteswanted); #endif handle_read_error(This, mng_display_resume(This->mng) ); } return len; // The number of bytes accepted -- we always accept them all. }
mng_retcode mng_render_proportional(mng_handle mngh, int progress) { mng_anim *mng = mng_get_userdata(mngh); mng_retcode ret = MNG_NOERROR; int frame_num, current_frame; frame_num = ((progress * mng->num_frames) / FBSPL_PROGRESS_MAX) + 1; if (!mng->displayed_first) { ret = mng_display(mngh); mng->displayed_first = 1; } if (mng->num_frames == 0 && mng->displayed_first) return MNG_NOERROR; if (frame_num > mng->num_frames) frame_num = mng->num_frames; current_frame = mng_get_currentframe(mngh); if (current_frame == frame_num) return ret; /* Don't bother freezing if the next frame is just n+1. mng_display_resume * will do this case by default, and it saves us from the horrid hack * below. */ if (frame_num != current_frame + 1) { mng_display_freeze(mngh); /* XXX: hack! workaround what seems to be a bug in libmng - it won't * actually repaint the canvas if you wind an animation "forwards" * using goframe, only backwards, so go to the end of the animation first. */ mng_display_goframe(mngh, mng->num_frames); if (frame_num != mng->num_frames) mng_display_goframe(mngh, frame_num); } ret = mng_display_resume(mngh); if (ret == MNG_NEEDTIMERWAIT || ret == MNG_NOERROR) return ret; print_mng_error(mngh, "mng_display failed"); return ret; }
bool CMNGAnimation::ReadNextFrame(RGBA* frame_buffer) { if (m_first_display) { mng_display(m_stream); m_first_display = false; } else { if (mng_display_resume(m_stream) != MNG_NEEDTIMERWAIT) { mng_display_reset(m_stream); // repeat } } // convert the buffers into frame_buffer memcpy(frame_buffer, m_frame_buffer, m_width * m_height * sizeof(RGBA)); return true; }
static mng_bool mng_refresh_callback (mng_handle mng_h, mng_uint32 x, mng_uint32 y, mng_uint32 width, mng_uint32 height) { FUNCTION_ENTRY(); GtkMngView * mng_view; mng_view = GTK_MNG_VIEW (mng_get_userdata (mng_h)); mng_display_resume (mng_h); gtk_widget_queue_draw_area (GTK_WIDGET (mng_get_userdata (mng_h)), x, y, width, height); return MNG_TRUE; if (GTK_WIDGET_REALIZED (mng_view)) { GdkRectangle rectangle; rectangle.x = x; rectangle.y = y; rectangle.width = width; rectangle.height = height; gtk_mng_view_paint (mng_view, &rectangle); } static int bs_count = 0; bs_count++; printf("bs_paint count %d\n", bs_count); printf("mng_get_starttime %d\n", mng_get_starttime (mng_h)); printf("mng_get_runtime %d\n", mng_get_runtime (mng_h)); printf("mng_get_currentframe %d\n", mng_get_currentframe (mng_h)); printf("mng_get_currentlayer %d\n", mng_get_currentlayer (mng_h)); printf("mng_get_currentplaytime %d\n", mng_get_currentplaytime (mng_h)); printf("mng_get_totalframes %d\n", mng_get_totalframes (mng_h)); printf("mng_get_totallayers %d\n", mng_get_totallayers (mng_h)); printf("mng_get_totalplaytime %d\n", mng_get_totalplaytime (mng_h)); FUNCTION_EXIT(); return MNG_TRUE; }
bool ImageJngFile::Animate (csTicks time, csRect* dirtyrect) { if (dirtyrect) dirtyrect->MakeEmpty (); if (!handle) return false; if (!doWait) return false; ImageJngFile::dirtyrect = dirtyrect; // Prevent very slow updates if the elapsed time is too big. if (time > 500) time = 500; bool updated = false; total_time_elapsed += time; time_elapsed += time; while (doWait && (timer <= time_elapsed)) { time_elapsed -= timer; doWait = (mng_display_resume (handle) == MNG_NEEDTIMERWAIT); updated = true; } if (updated) { if (csPackRGBA::IsRGBpixelSane()) { memcpy (databuf->GetData(), NewImage, Width * Height * sizeof (csRGBpixel)); } else { csRGBpixel *rgbImage = csPackRGBA::CopyUnpackRGBAtoRGBpixel ( NewImage, Width*Height); ConvertFromRGBA (rgbImage); } } return updated; }
mng_retcode mng_render_next(mng_handle mngh) { mng_anim *mng = mng_get_userdata(mngh); mng_retcode ret; int last_frame = 0; /* last_frame = mng_get_currentframe(mngh) == mng->num_frames; FIXME */ if (!mng->displayed_first) { ret = mng_display(mngh); if (ret == MNG_NOERROR || ret == MNG_NEEDTIMERWAIT) mng->displayed_first = 1; } else ret = mng_display_resume(mngh); if (last_frame) return MNG_NOERROR; if (ret == MNG_NEEDTIMERWAIT || ret == MNG_NOERROR) return ret; print_mng_error(mngh, "mng_display failed"); return ret; }
static gboolean gtk_mng_view_animator (GtkMngView * mng_view) { FUNCTION_ENTRY(); mng_retcode retcode; retcode = mng_display_resume (mng_view->MNG_handle); if (retcode == MNG_NOERROR) { mng_view->timeout_ID = 0; FUNCTION_EXIT(); return FALSE; } else if (retcode == MNG_NEEDTIMERWAIT) { FUNCTION_EXIT(); return FALSE; } else g_warning ("mng_display_resume() return not good value %d", retcode); FUNCTION_EXIT(); return FALSE; }
bool ImageJngFile::Load (uint8 *iBuffer, size_t iSize) { mng_retcode retcode; const int magicSize = 8; const char magicMNG[] = "\x8aMNG\x0d\x0a\x1a\x0a"; const char magicJNG[] = "\x8bJNG\x0d\x0a\x1a\x0a"; // check for magic JNG/MNG bytes. If not correct, we can skip // messing around w/ libmng entirely. if ((iSize < 8) || ((memcmp ((void*)iBuffer, (void*)&magicMNG, magicSize)) && (memcmp ((void*)iBuffer, (void*)&magicJNG, magicSize)))) { return false; } handle = mng_initialize (mng_ptr(this), cb_alloc, cb_free, MNG_NULL); if (!handle) { Report (object_reg, CS_REPORTER_SEVERITY_WARNING, "failed to initialize libmng"); return false; } buffer = iBuffer; bufptr = buffer; bufferSize = iSize; if ((mng_setcb_openstream (handle, cb_openstream) != MNG_NOERROR) || (mng_setcb_closestream (handle, cb_closestream) != MNG_NOERROR) || (mng_setcb_readdata (handle, cb_readdata) != MNG_NOERROR) || (mng_setcb_processheader(handle, cb_processheader) != MNG_NOERROR) || (mng_setcb_getcanvasline(handle, cb_getcanvasline) != MNG_NOERROR) || (mng_setcb_refresh(handle, cb_imagerefresh) != MNG_NOERROR) || (mng_setcb_gettickcount(handle, cb_gettickcount) != MNG_NOERROR) || (mng_setcb_settimer(handle, cb_settimer) != MNG_NOERROR)) { ReportLibmngError (object_reg, handle, "failed to set libmng callbacks"); mng_cleanup (&handle); return false; } retcode = mng_read (handle); if (retcode != MNG_NOERROR) { if (retcode != MNG_INVALIDSIG) // maybe its just not an jng/mng... ReportLibmngError (object_reg, handle, "failed to read data"); mng_cleanup (&handle); return false; } // Don't read PNGs if (mng_get_sigtype (handle) == mng_it_png) { delete[] NewImage; mng_cleanup (&handle); return false; } // Even on still images, libmng issues timer requests. // so, as long as the requests are 'immediate' we continue // displaying. If a delay is requested we end loading. timer = 2; retcode = mng_display (handle); while ((retcode == MNG_NEEDTIMERWAIT) && (timer <= 1)) { retcode = mng_display_resume (handle); } if ((retcode != MNG_NOERROR) && (retcode != MNG_NEEDTIMERWAIT)) { ReportLibmngError (object_reg, handle, "failed to display data"); mng_cleanup (&handle); return false; } doWait = (retcode == MNG_NEEDTIMERWAIT); animated = doWait; if (NewImage) { csRGBpixel *rgbImage = csPackRGBA::CopyUnpackRGBAtoRGBpixel (NewImage, Width*Height); ConvertFromRGBA (rgbImage); // Subsequent images may contain alpha, so don't check if (!doWait) CheckAlpha(); } if (mng_get_sigtype (handle) != mng_it_mng) { delete[] NewImage; NewImage = 0; mng_cleanup (&handle); handle = 0; } return true; }
static FIBITMAP * DLL_CALLCONV Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { mng_handle hmng = NULL; if (handle != NULL) { try { // allocate our stream data structure mngstuff *mymng = (mngstuff *)data; // set up the mng decoder for our stream hmng = mng_initialize(mymng, mymngalloc, mymngfree, MNG_NULL); if (hmng == MNG_NULL) { throw "could not initialize libmng"; } // set the colorprofile, lcms uses this mng_set_srgb(hmng, MNG_TRUE ); // set white as background color WORD wRed, wGreen, wBlue; wRed = wGreen = wBlue = (255 << 8) + 255; mng_set_bgcolor(hmng, wRed, wGreen, wBlue); // if PNG Background is available, use it mng_set_usebkgd(hmng, MNG_TRUE ); // no need to store chunks mng_set_storechunks(hmng, MNG_FALSE); // no need to wait: straight reading mng_set_suspensionmode(hmng, MNG_FALSE); // set the callbacks mng_setcb_errorproc(hmng, mymngerror); mng_setcb_openstream(hmng, mymngopenstream); mng_setcb_closestream(hmng, mymngclosestream); mng_setcb_readdata(hmng, mymngreadstream); mng_setcb_processheader(hmng, mymngprocessheader); mng_setcb_getcanvasline(hmng, mymnggetcanvasline); mng_setcb_refresh(hmng, mymngrefresh); mng_setcb_gettickcount(hmng, mymnggetticks); mng_setcb_settimer(hmng, mymngsettimer); // read in the bitmap mng_readdisplay(hmng); // read all bitmaps int retval = MNG_NOERROR; mng_datap pData = (mng_datap)hmng; while(pData->bReading) { retval = mng_display_resume(hmng); if((retval == MNG_NEEDTIMERWAIT) || (retval == MNG_FUNCTIONINVALID)) break; } // temp store the newly created bitmap FIBITMAP *bitmap = mymng->bitmap; // cleanup and return the temp stored bitmap mng_cleanup(&hmng); return bitmap; } catch (const char *message) { FIBITMAP *bitmap = ((mngstuff *)mng_get_userdata(hmng))->bitmap; if(bitmap) { FreeImage_Unload(bitmap); } mng_cleanup(&hmng); FreeImage_OutputMessageProc(s_format_id, message); } } return NULL; }
/** * \brief MPlayer callback: Fill buffer from MNG stream. * \param[in] demuxer demuxer structure * \param[in] ds demuxer stream * \return \p 1 on success, \p 0 on error */ static int demux_mng_fill_buffer(demuxer_t * demuxer, demux_stream_t * ds) { mng_priv_t * mng_priv = demuxer->priv; mng_handle h_mng = mng_priv->h_mng; mng_retcode mng_ret; demux_packet_t * dp; // exit if animation is finished if (mng_priv->finished) return 0; // advance animation to requested next show time while (mng_priv->anim_cur_time_ms + mng_priv->anim_frame_duration_ms <= mng_priv->show_next_time_ms && !mng_priv->finished) { // advance global and animation time mng_priv->global_time_ms += mng_priv->anim_frame_duration_ms; mng_priv->anim_cur_time_ms += mng_priv->anim_frame_duration_ms; // Clear variable MNG library will write number of milliseconds to // (via settimer callback). mng_priv->timer_ms = 0; // get next image from MNG library if (mng_priv->displaying) mng_ret = mng_display_resume(h_mng); // resume displaying MNG data // to canvas else mng_ret = mng_display(h_mng); // start displaying MNG data to canvas if (mng_ret && mng_ret != MNG_NEEDTIMERWAIT) { mp_msg(MSGT_DEMUX, MSGL_ERR, "demux_mng: could not display MNG data to canvas: " "mng_retcode %d\n", mng_ret); return 0; } mng_priv->displaying = 1; // mng_display() has been called now mng_priv->finished = mng_ret == 0; // animation is finished iff // mng_display() returned 0 // save current frame duration mng_priv->anim_frame_duration_ms = mng_priv->timer_ms < 1 ? 1 : mng_priv->timer_ms; } // while (mng_priv->anim_cur_time_ms + ... // create a new demuxer packet dp = new_demux_packet(mng_priv->height * mng_priv->width * 4); // copy image data into demuxer packet memcpy(dp->buffer, mng_priv->canvas, mng_priv->height * mng_priv->width * 4); // set current show time to requested show time mng_priv->show_cur_time_ms = mng_priv->show_next_time_ms; // get time of next frame to show mng_priv->show_next_time_ms = mng_priv->anim_cur_time_ms + mng_priv->anim_frame_duration_ms; // Set position and timing information in demuxer video and demuxer packet. // - Time must be time of next frame and always be > 0 for the variable // frame time mechanism (GIF, MATROSKA, MNG) in video.c to work. demuxer->video->dpos++; dp->pts = (float)mng_priv->show_next_time_ms / 1000.0f + MNG_START_PTS; dp->pos = stream_tell(demuxer->stream); ds_add_packet(demuxer->video, dp); return 1; }
int main(int argc, char *argv[]) { int fbdev,c,option_index; unsigned int alpha; struct fb_var_screeninfo var; /* Check which console we're running on */ init_consoles(); /* allocate our stream data structure */ mng = (mngstuff *) calloc(1, sizeof(*mng)); if (mng == NULL) { fprintf(stderr, "could not allocate stream structure.\n"); exit(0); } alpha = 100; mng->alpha = 100; mng->fbx = 15; mng->fby = 15; mng->background = NULL; while (1) { static struct option long_options[] = { {"help", 0, 0, 'h'}, {"verbose", 0, 0, 'v'}, {"alpha", 1, 0, 'a'}, {"buffered", 0, 0, 'b'}, {"signal", 0, 0, 's'}, {"delta", 0, 0, 'd'}, {"position", 0, 0, 'p'}, {"version", 0, 0, 'V'}, {"start-console",0,0,'S'}, {"console",1,0,'c'}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, "a:x:y:bh?vsd:pVSc:", long_options, &option_index); if (c == -1) break; switch (c) { case 'a': alpha = atoi(optarg); if (alpha > 100) alpha = 100; mng->alpha = alpha; break; case 'x': mng->fbx = atoi(optarg); break; case 'y': mng->fby = atoi(optarg); break; case 'd': delta = atoi(optarg); break; case '?': case 'h': usage(argv[0]); exit(0); case 'v': verbose = 1; break; case 's': waitsignal = 1; break; case 'b': buffered = 1; break; case 'p': dynpos = 1; break; case 'V': version(); exit(0); case 'c': start_console=atoi(optarg); case 'S': sconly=1; break; default: break; } } if (optind >= argc) { printf("Which files do you want to play?\n"); exit(0); } //init_consoles(); /* Initialize framebuffer */ fbdev = open("/dev/fb0", O_RDWR); if (fbdev < 0) { fprintf(stderr, "error while opening framebuffer.\n"); exit(fbdev); } ioctl(fbdev, FBIOGET_VSCREENINFO, &var); mng->fbwidth = var.xres; mng->fbheight = var.yres; mng->fbbpp = var.bits_per_pixel; mng->display = mmap(NULL, var.xres * var.yres * (var.bits_per_pixel >> 3), PROT_WRITE | PROT_READ, MAP_SHARED, fbdev, 0); /* arrange to call the shutdown routine before we exit */ atexit(&cleanup); while (optind < argc) { // leftover arguements are filenames. mng->filename = argv[optind++]; /* set up the mng decoder for our stream */ mng->mng = mng_initialize(mng, mngalloc, mngfree, MNG_NULL); if (mng->mng == MNG_NULL) { fprintf(stderr, "could not initialize libmng.\n"); exit(1); } /* set the callbacks */ mng_setcb_errorproc(mng->mng, mngerror); mng_setcb_openstream(mng->mng, mngopenstream); mng_setcb_closestream(mng->mng, mngclosestream); mng_setcb_readdata(mng->mng, mngreadstream); mng_setcb_gettickcount(mng->mng, mnggetticks); mng_setcb_settimer(mng->mng, mngsettimer); mng_setcb_processheader(mng->mng, mngprocessheader); mng_setcb_getcanvasline(mng->mng, mnggetcanvasline); mng_setcb_refresh(mng->mng, mngrefresh); /* FIXME: should check for errors here */ signal(SIGINT, sigint_handler); signal(SIGTERM, sigterm_handler); mng_readdisplay(mng->mng); /* loop though the frames */ while (mng->delay && run) { mdelay(mng->delay); mng->delay = 0; mng_display_resume(mng->mng); if (run == 2) { if (mng->alpha == 0) run = 0; mng->alpha -= delta; if (mng->alpha < 0) mng->alpha = 0; } } if (waitsignal && optind < argc) { signal(SIGUSR1, sigusr1_handler); run = 1; while (run) { sleep(2); } } memset(mng->copybuffer, 0, 4 * mng->width * mng->height); run = 1; mng->alpha = alpha; if (optind == argc) { /* last file */ restore_area(); } } /* cleanup and quit */ return mngquit(mng->mng); }
static void ContextMenu(PluginInstance *This, HWND hwnd) { int cmd; HMENU menu; POINT pt; unsigned char buf[MAX_PATH], buf2[200]; pt.x=0; pt.y=0; GetCursorPos(&pt); // create context menu dynamically menu=CreatePopupMenu(); if(This->errorflag) { AppendMenu(menu,MF_ENABLED,ID_SHOWERROR,"SHOW ERROR MESSAGE"); AppendMenu(menu,MF_SEPARATOR,0,NULL); } AppendMenu(menu,(This->loadstate>=STATE_LOADED?MF_ENABLED:MF_GRAYED),ID_SAVEAS,"Save Image &As..."); AppendMenu(menu,(This->lpdib?MF_ENABLED:MF_GRAYED),ID_COPYIMAGE,"&Copy Image"); AppendMenu(menu,MF_ENABLED,ID_COPYURL,"Cop&y Image Location"); if(This->islink) { AppendMenu(menu,MF_ENABLED,ID_COPYLINKLOC,"Copy Link Location"); } url2filename(buf,This->url); escapeformenu(buf); if(lstrlen(buf)) { wsprintf(buf2,"View Image (%s)",buf); } else { wsprintf(buf2,"View Image"); } AppendMenu(menu,MF_ENABLED,ID_VIEWIMAGE,buf2); AppendMenu(menu,MF_SEPARATOR,0,NULL); // AppendMenu(menu,(This->mng?MF_ENABLED:MF_GRAYED),ID_STOPANIM,"Stop Animation"); AppendMenu(menu,(This->mng?MF_ENABLED:MF_GRAYED)| (This->frozen?MF_CHECKED:MF_UNCHECKED),ID_FREEZE,"&Freeze Animation"); // AppendMenu(menu,(This->mng?MF_ENABLED:MF_GRAYED),ID_RESTARTANIM,"Restart Animation"); AppendMenu(menu,MF_SEPARATOR,0,NULL); AppendMenu(menu,MF_ENABLED,ID_PROPERTIES,"Properties..."); AppendMenu(menu,MF_ENABLED,ID_ABOUT,"About MNG Plug-in..."); cmd=TrackPopupMenuEx(menu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_NONOTIFY|TPM_RETURNCMD| TPM_RIGHTBUTTON,pt.x,pt.y,hwnd,NULL); DestroyMenu(menu); switch(cmd) { case ID_STOPANIM: if(This->mng) { KillTimer(This->fhWnd,1); This->timer_set=0; mng_display_freeze(This->mng); } break; case ID_FREEZE: This->frozen = !This->frozen; if(This->frozen) { KillTimer(This->fhWnd,1); This->timer_set=0; mng_display_freeze(This->mng); } else { handle_read_error(This, mng_display_resume(This->mng) ); } break; case ID_RESTARTANIM: if(!This->frozen) { KillTimer(This->fhWnd,1); This->timer_set=0; mng_display_freeze(This->mng); } This->frozen=1; mng_display_reset(This->mng); This->frozen=0; handle_read_error(This, mng_display_resume(This->mng) ); break; case ID_SAVEAS: SaveImage(This); break; case ID_COPYIMAGE: if(This->lpdib) { CopyToClipboard(This,(unsigned char*)This->lpdib,This->dibsize,CF_DIB); } else { warn(This,"No image to copy"); } break; case ID_COPYURL: CopyToClipboard(This,This->url,lstrlen(This->url)+1,CF_TEXT); break; case ID_COPYLINKLOC: if(This->islink) { CopyToClipboard(This,This->linkurl,lstrlen(This->linkurl)+1,CF_TEXT); } break; case ID_VIEWIMAGE: if(lstrlen(This->url)) NPN_GetURL(This->instance,This->url,"_self"); break; case ID_PROPERTIES: PropDialog(This); break; case ID_ABOUT: AboutDialog(This); break; case ID_SHOWERROR: display_last_error(This); break; } }
/*+++++++++++++++++++++++++++++++++++++++++++++++++ * PluginWindowProc * Handle the Windows window-event loop. +++++++++++++++++++++++++++++++++++++++++++++++++*/ static LRESULT CALLBACK PluginWindowProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { PluginInstance* This; HDC hdc; RECT rect; This = (PluginInstance*) GetProp(hWnd, gInstanceLookupString); if(!This) return DefWindowProc( hWnd, Msg, wParam, lParam); switch(Msg) { case WM_ERASEBKGND: { HBRUSH br; hdc= (HDC)wParam; if(This->bkgdbrush) br=This->bkgdbrush; else br=GetStockObject(GRAY_BRUSH); GetClientRect(hWnd,&rect); FillRect(hdc,&rect,br); return 1; } case WM_HSCROLL: case WM_VSCROLL: scrollmsg(This,Msg,(int)(LOWORD(wParam)),(short int)(HIWORD(wParam))); return 0; case WM_SIZE: find_window_size(This); set_scrollbars(This); return 0; case WM_CONTEXTMENU: case WM_RBUTTONUP: ContextMenu(This, hWnd); return 0; case WM_SETCURSOR: if(LOWORD(lParam)==HTCLIENT) { if(This->islink) { SetCursor(This->linkcursor); return 1; } } break; case WM_LBUTTONDOWN: SetCapture(This->fhWnd); This->mouse_captured=1; if(This->dynamicmng && This->mng && !This->errorflag) { DynamicMNG_FireEvent(This,4,MAKEPOINTS(lParam)); } return 0; case WM_LBUTTONUP: { RECT rc; POINT pt; if(This->mouse_captured) { ReleaseCapture(); This->mouse_captured=0; } if(This->dynamicmng && This->mng && !This->errorflag) { DynamicMNG_FireEvent(This,5,MAKEPOINTS(lParam)); } // if mouse is not over image, don't follow links, etc. GetWindowRect(This->fhWnd,&rc); GetCursorPos(&pt); if(!PtInRect(&rc,pt)) return 0; if(This->islink) { NPN_GetURL(This->instance,This->linkurl,This->linktarget); return 0; } else if(This->errorflag) { display_last_error(This); } } return 0; case WM_MOUSEMOVE: if(This->dynamicmng && This->mng && This->lpdib && !This->errorflag) { POINTS pos; int overimage; pos=MAKEPOINTS(lParam); overimage=0; if(pos.x>=0 && pos.x<This->lpdibinfo->biWidth && pos.y>=0 && pos.y<This->lpdibinfo->biHeight) { overimage=1; } if(overimage) { if(This->mouse_over_mng) { // mouse is still over image: mouse move event DynamicMNG_FireEvent(This,2,pos); // 2=mouse move } else { // mouse wasn't over the image but now it is: mouse-enter event DynamicMNG_FireEvent(This,1,pos); // mouse enter } } else { // mouse not now over image if(This->mouse_over_mng) { // ... but it used to be pos.x=0; pos.y=0; DynamicMNG_FireEvent(This,3,pos); // 3=mouse leave } } This->mouse_over_mng=overimage; // remember for next time if(This->mouse_over_mng && (This->dynamicmng==1) ) { #define MOUSE_POLL_INTERVAL 100 // milliseconds SetTimer(This->fhWnd,2,MOUSE_POLL_INTERVAL,NULL); This->timer2_set=0; } } return 0; case WM_PAINT: { PAINTSTRUCT paintStruct; HDC hdc; RECT rect2; hdc = BeginPaint( hWnd, &paintStruct ); SetWindowOrgEx(hdc,This->xscrollpos,This->yscrollpos,NULL); GetClientRect(hWnd,&rect); if(This) { if(This->errorflag || !This->lpdib) { SelectObject(hdc,hfontMsg); Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom); rect2.left=rect.left+2; rect2.top=rect.top+2; rect2.right=rect.right-2; rect2.bottom=rect.bottom-2; if(This->errorflag) { DrawText(hdc,"MNG PLUG-IN ERROR!",-1,&rect2,DT_LEFT|DT_WORDBREAK); } else { if(This->loadstate>=STATE_LOADING) { DrawText(hdc,"MNG image loading...",-1,&rect2,DT_LEFT|DT_WORDBREAK); } else { DrawText(hdc,"MNG plug-in",-1,&rect2,DT_LEFT|DT_WORDBREAK); } } } else if(This->lpdib) { StretchDIBits(hdc, 0,0,This->lpdibinfo->biWidth,This->lpdibinfo->biHeight, 0,0,This->lpdibinfo->biWidth,This->lpdibinfo->biHeight, &((BYTE*)(This->lpdib))[sizeof(BITMAPINFOHEADER)], (LPBITMAPINFO)This->lpdib,DIB_RGB_COLORS,SRCCOPY); } } EndPaint( hWnd, &paintStruct ); } return 0; case WM_TIMER: switch(wParam) { case 1: // the main animation timer KillTimer(hWnd,1); This->timer_set=0; #ifdef MNGPLG_TRACE fprintf(tracefile,"WM_TIMER display_resume bytesloaded=%d\n",This->bytesloaded); #endif if(This->mng) { if(!This->needresume) { handle_read_error(This, mng_display_resume(This->mng) ); } } return 0; case 2: // timer for polling mouse position { RECT rc; POINT pt; POINTS pos; GetWindowRect(hWnd,&rc); GetCursorPos(&pt); if(!PtInRect(&rc,pt)) { KillTimer(hWnd,2); pos.x=0; pos.y=0; DynamicMNG_FireEvent(This,3,pos); // 3=mouse leave This->mouse_over_mng=0; } } return 0; } break; } /* Forward unprocessed messages on to their original destination * (the window proc we replaced) */ return This->fDefaultWindowProc(hWnd, Msg, wParam, lParam); }