Re: Progressive updates for image window of Windows console app
"Russell Lang" <[email protected]> Fri, 13 Aug 2004 17:07:20 +1000
| Newsgroups | gmane.comp.printing.ghostscript.patches |
|---|---|
| Message-ID | <411CF548.7034.4AC7381@localhost> |
Ray, Here is one more update, I hope the final. It is variation on the previous timer code, but the timer is not restarted unless the timer interval is 2x the current timer interval. It will also restart the timer if it finds that the refreshes become faster, although this is unlikely to happen in normal use. The timer is stopped by a sync, to avoid having the timer pinging while ghostscript is idle. Russell Log Message: Enable progressive updates for the image window of the MS-Windows ghostscript command line program. Change update method to use a Windows timer. DETAILS: In the MS-Windows GUI executable (i.e. text window managed by ghostscript rather than using a system console window), the image window is progressively updated every second or so as each page is drawn. The console executable did not do this. The update code for both GUI and console executables is changed to use a timer. The display update code is called whenever particular device drawing operations happen, and if a timer is not already running, it starts a timer. The window is refresed when the timer elapses. The minimum update interval is shortened from 1s to 100ms. The time to refresh the window is measured, and the update interval may be increased to make sure that updates account for no more than 10% of processing. The update interval is decreased if subsequent updates are much quicker. The timer is stopped by any sync. > From: "Russell Lang" <[email protected]> > To: [email protected] > Date: Fri, 09 Jul 2004 20:57:53 +1000 > Subject: Re: [gs-code-review] Progressive updates for image window of Windows > > --Message-Boundary-208 > Content-type: text/plain; charset=US-ASCII > Content-transfer-encoding: 7BIT > Content-description: Mail message body > > Ray, > > I've modified the code to use a timer as preferred by Igor. > The code is cleaner. > > Log Message: > Enable progressive updates for the image window of > the MS-Windows ghostscript command line program. > Change update method to use a Windows timer. > > DETAILS: > In the MS-Windows GUI executable (i.e. text window managed by > ghostscript rather than using a system console window), the image > window is progressively updated every second or so as each page > is drawn. The console executable did not do this. > > The update code for both GUI and console executables is changed > to use a timer. The display update code is called whenever > particular device drawing operations happen, and if a timer is > not already running, it starts a timer. If the timer elapses, > a sync is generated to refresh the window. The timer is stopped > by any sync, either from the timer or GS. > The update interval is shortened from 1s to 100ms, > and this is adjusted to make sure updates account for > no more than 10% of processing. > > > > Date: Fri, 09 Jul 2004 00:24:49 -0700 > > From: Ray Johnston <[email protected]> > > To: [email protected] > > CC: [email protected] > > Subject: Re: [gs-code-review] Progressive updates for image window of Windows > > > > Russell, > > > > I think that this approach is fine. I realize that Igor's > > suggestion of a timer is more elegant, but don't want to place > > a burden on you (as the primary developer of the display code). > > > > If Igor wants to submit a patch to change to the timer, more > > power to him. I expect him to put that to code-review so you > > will have a chance to comment. > > > > One request (if you feel like it) is to change the minimum > > update time to 0.2 seconds -- which requires using wMilliseconds > > from the SYSTEMTIME. I had done this patch a while ago locally, > > but lost it when it got too outdated. > > > > If you want to make the additional change to 0.2 millisecond > > minimum time update, please go ahead and commit after testing > > (I don't think additional c-r is needed). Otherwise commit as > > is (and maybe I will change to 0.2 second updates) > > > > Regards, > > Ray diff -u l:/cvs/gs/src/dwimg.c src/dwimg.c --- l:/cvs/gs/src/dwimg.c Sat Jul 03 10:51:14 2004 +++ src/dwimg.c Fri Aug 13 06:48:17 2004 @@ -123,8 +123,7 @@ img->handle = handle; img->device = device; - img->update_interval = 1; - memset(&img->update_time, 0, sizeof(img->update_time)); + img->update_interval = 100; /* milliseconds */ img->hmutex = INVALID_HANDLE_VALUE; @@ -528,50 +527,75 @@ void image_poll(IMAGE *img) { - /* Update the display periodically while Ghostscript is drawing */ - SYSTEMTIME t1; - SYSTEMTIME t2; - int delta; if ((img->bmih.biWidth == 0) || (img->bmih.biHeight == 0)) return; + img->pending_update = 1; + if (img->update_timer == 0) { + img->update_timer = 1; + img->update_timer_interval = img->update_interval; + SetTimer(img->hwnd, img->update_timer, img->update_interval, NULL); + } +} - GetSystemTime(&t1); - delta = (t1.wSecond - img->update_time.wSecond) + - (t1.wMinute - img->update_time.wMinute) * 60 + - (t1.wHour - img->update_time.wHour) * 3600; - if (img->update_interval < 1) - img->update_interval = 1; /* seconds */ - if (delta < 0) - img->update_time = t1; - else if (delta > img->update_interval) { - /* redraw window */ - image_sync(img); +/* Redraw the window, making sure that periodic updates don't take too long. */ +void +image_update_now(IMAGE *img) +{ + SYSTEMTIME t1; + SYSTEMTIME t2; + int delta; + if ( !IsWindow(img->hwnd) ) /* some clod closed the window */ + create_window(img); + if ( !IsIconic(img->hwnd) ) { /* redraw window */ + GetSystemTime(&t1); + InvalidateRect(img->hwnd, NULL, 1); + UpdateWindow(img->hwnd); + GetSystemTime(&t2); /* Make sure the update interval is at least 10 times * what it takes to paint the window */ - GetSystemTime(&t2); delta = (t2.wSecond - t1.wSecond)*1000 + (t2.wMilliseconds - t1.wMilliseconds); if (delta < 0) - delta += 60000; /* delta = time to redraw */ - if (delta > img->update_interval * 100) - img->update_interval = delta/100; - img->update_time = t2; + delta += 60000; + delta *= 10; + if (delta > img->update_interval) + img->update_interval = delta; + + if (img->update_timer) { + /* Stop timer if time to redraw differs wildly from + * current timer. It will be restarted with new interval + * if needed, when image_poll() called again. + */ + if (delta > 2*img->update_timer_interval) { + img->update_interval = delta; + KillTimer(img->hwnd, img->update_timer); + img->update_timer = 0; + } + else if ((delta < img->update_timer_interval / 4) && + (img->update_timer_interval / 2 > 100)) { + img->update_interval = img->update_timer_interval / 2; + KillTimer(img->hwnd, img->update_timer); + img->update_timer = 0; + } + } } } + void image_sync(IMAGE *img) { - if ( !IsWindow(img->hwnd) ) /* some clod closed the window */ - create_window(img); - - if ( !IsIconic(img->hwnd) ) { /* redraw window */ - InvalidateRect(img->hwnd, NULL, 1); - UpdateWindow(img->hwnd); + if (img->update_timer) { + /* stop timer when nothing is happening */ + KillTimer(img->hwnd, img->update_timer); + img->update_timer = 0; } + img->pending_sync = 0; + image_update_now(img); image_separations(img); + img->pending_update = 0; } @@ -1300,6 +1324,9 @@ WriteConsoleInput(hStdin, &ir, 1, &dwWritten); } return 0; + case WM_TIMER: + image_update_now(img); + return 0; case WM_PAINT: { int sx,sy,wx,wy,dx,dy; diff -u l:/cvs/gs/src/dwimg.h src/dwimg.h --- l:/cvs/gs/src/dwimg.h Sat Jul 03 10:51:14 2004 +++ src/dwimg.h Fri Aug 13 06:17:32 2004 @@ -51,8 +51,11 @@ IMAGE_DEVICEN devicen[IMAGE_DEVICEN_MAX]; /* periodic redrawing */ - SYSTEMTIME update_time; - int update_interval; + UINT update_timer; + int update_timer_interval; /* milliseconds of current timer */ + int update_interval; /* milliseconds for next timer */ + int pending_update; /* We have asked for periodic updates */ + int pending_sync; /* We have asked for a SYNC */ /* Window scrolling stuff */ int cxClient, cyClient; diff -u l:/cvs/gs/src/dwmainc.c src/dwmainc.c --- l:/cvs/gs/src/dwmainc.c Wed Jul 07 09:33:19 2004 +++ src/dwmainc.c Fri Aug 13 06:15:37 2004 @@ -90,6 +90,7 @@ #define DISPLAY_SIZE WM_USER+103 #define DISPLAY_SYNC WM_USER+104 #define DISPLAY_PAGE WM_USER+105 +#define DISPLAY_UPDATE WM_USER+106 /* #define DISPLAY_DEBUG @@ -124,6 +125,9 @@ case DISPLAY_PAGE: image_page((IMAGE *)msg.lParam); break; + case DISPLAY_UPDATE: + image_poll((IMAGE *)msg.lParam); + break; default: TranslateMessage(&msg); DispatchMessage(&msg); @@ -220,8 +224,10 @@ fprintf(stdout, "display_sync(0x%x, 0x%x)\n", handle, device); #endif img = image_find(handle, device); - if (img) + if (img && !img->pending_sync) { + img->pending_sync = 1; PostThreadMessage(thread_id, DISPLAY_SYNC, 0, (LPARAM)img); + } return 0; } @@ -241,10 +247,12 @@ int display_update(void *handle, void *device, int x, int y, int w, int h) { - /* Unneeded for polling - we are running Windows on another thread. */ - /* Eventually we will add code here which provides progressive - * update of the display during rendering. - */ + IMAGE *img; + img = image_find(handle, device); + if (img && !img->pending_update && !img->pending_sync) { + img->pending_update = 1; + PostThreadMessage(thread_id, DISPLAY_UPDATE, 0, (LPARAM)img); + } return 0; } _______________________________________________ gs-code-review mailing list [email protected] http://www.ghostscript.com/mailman/listinfo/gs-code-review