Re: Progressive updates for image window of Windows console app

"Russell Lang" <[email protected]> Fri, 09 Jul 2004 20:57:53 +1000
Newsgroups gmane.comp.printing.ghostscript.patches
Message-ID <40EF06D1.5466.B4F19560@localhost>
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 Jul 09 10:49:35 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,46 @@
 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;
-
-    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);
-
-	/* 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;
+    img->pending_update = 1;
+    if (img->update_timer == 0) {
+	img->update_timer = 1;
+	SetTimer(img->hwnd, img->update_timer, img->update_interval, NULL);
     }
 }
 
 void
 image_sync(IMAGE *img)
 {
+    SYSTEMTIME t1;
+    SYSTEMTIME t2;
+    int delta;
+    if (img->update_timer) {
+	KillTimer(img->hwnd, img->update_timer);
+        img->update_timer = 0;
+    }
+    img->pending_sync = 0;
     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
+	 */
+	delta = (t2.wSecond - t1.wSecond)*1000 + 
+		(t2.wMilliseconds - t1.wMilliseconds);
+	if (delta < 0)
+	    delta += 60000;
+	if (delta*10 > img->update_interval)
+	    img->update_interval = delta*10;
     }
     image_separations(img);
+    img->pending_update = 0;
 }
 
 
@@ -1300,6 +1295,9 @@
 		    WriteConsoleInput(hStdin, &ir, 1, &dwWritten); 
 	    }
 	    return 0;
+	case WM_TIMER:
+	    image_sync(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 Jul 09 10:03:14 2004
@@ -51,8 +51,10 @@
     IMAGE_DEVICEN devicen[IMAGE_DEVICEN_MAX];
 
     /* periodic redrawing */
-    SYSTEMTIME update_time;
-    int update_interval;
+    UINT update_timer;
+    int update_interval;	/* milliseconds */
+    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 Jul 09 10:32:39 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