altos/draw: Split out draw test scaffolding from lco-test.c
authorKeith Packard <keithp@keithp.com>
Mon, 27 Feb 2023 02:49:47 +0000 (18:49 -0800)
committerKeith Packard <keithp@keithp.com>
Mon, 27 Feb 2023 02:49:47 +0000 (18:49 -0800)
Allows it to be reused.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/draw/frame.c
src/draw/lco-test.c
src/draw/test-frame.c [new file with mode: 0644]

index 84b30b36797e8f1a6fad16bd184327f19cb4bd65..45cca1052e84aee9251c2b2213642ffb8003c5f3 100644 (file)
@@ -183,7 +183,17 @@ MatchLineStyle(char *s)
     return LineSolid;
 }
 
+void
+HandleButtonPress(Display *dpy, Window win, GC gc, XEvent *ev);
+
+void
+HandleButtonRelease(Display *dpy, Window win, GC gc, XEvent *ev);
+
+void
+HandleMotionNotify(Display *dpy, Window win, GC gc, XEvent *ev);
+
 #ifdef TRACK_POINTER
+
 #define PASS_BUTTONS
 typedef struct _Position {
     int        seen;
@@ -192,10 +202,16 @@ typedef struct _Position {
     int        end_x, end_y;
 } PositionRec, *PositionPtr;
 
-PositionRec positions[5];
+void
+Draw(Display *dpy, Window win, GC gc, PositionRec positions[5]);
 
 void
-UpdatePositions (state, x, y)
+Undraw(Display *dpy, Window win, GC gc, PositionRec positions[5]);
+
+PositionRec current_positions[5];
+
+static void
+UpdatePositions (unsigned state, int x, int y)
 {
     int        i;
 
@@ -203,69 +219,53 @@ UpdatePositions (state, x, y)
     for (i = 0; i < 5; i++)
     {
        if (state & (1 << i)) {
-           positions[i].cur_x = x;
-           positions[i].cur_y = y;
+           current_positions[i].cur_x = x;
+           current_positions[i].cur_y = y;
        }
     }
 }
 
 void
-HandleButtonPress (dpy, win, gc, ev)
-    Display *dpy;
-    Window  win;
-    GC     gc;
-    XEvent  *ev;
+HandleButtonPress (Display *dpy, Window win, GC gc, XEvent *ev)
 {
     XButtonEvent    *bev = (XButtonEvent *) ev;
 
-    Undraw (dpy, win, gc, positions);
-    positions[bev->button - 1].seen = 1;
-    positions[bev->button - 1].start_x = bev->x;
-    positions[bev->button - 1].start_y = bev->y;
-    positions[bev->button - 1].cur_x = bev->x;
-    positions[bev->button - 1].cur_y = bev->y;
-    positions[bev->button - 1].end_x = bev->x;
-    positions[bev->button - 1].end_y = bev->y;
+    Undraw (dpy, win, gc, current_positions);
+    current_positions[bev->button - 1].seen = 1;
+    current_positions[bev->button - 1].start_x = bev->x;
+    current_positions[bev->button - 1].start_y = bev->y;
+    current_positions[bev->button - 1].cur_x = bev->x;
+    current_positions[bev->button - 1].cur_y = bev->y;
+    current_positions[bev->button - 1].end_x = bev->x;
+    current_positions[bev->button - 1].end_y = bev->y;
     UpdatePositions (bev->state, bev->x, bev->y);
-    Draw (dpy, win, gc, positions);
+    Draw (dpy, win, gc, current_positions);
 }
 
 void
-HandleButtonRelease (dpy, win, gc, ev)
-    Display *dpy;
-    Window  win;
-    GC     gc;
-    XEvent  *ev;
+HandleButtonRelease (Display *dpy, Window win, GC gc, XEvent *ev)
 {
     XButtonEvent    *bev = (XButtonEvent *) ev;
 
-    Undraw (dpy, win, gc, positions);
+    Undraw (dpy, win, gc, current_positions);
     UpdatePositions (bev->state, bev->x, bev->y);
-    positions[bev->button - 1].end_x = bev->x;
-    positions[bev->button - 1].end_y = bev->y;
-    Draw (dpy, win, gc, positions);
+    current_positions[bev->button - 1].end_x = bev->x;
+    current_positions[bev->button - 1].end_y = bev->y;
+    Draw (dpy, win, gc, current_positions);
 }
 
 void
-HandleMotionNotify (dpy, win, gc, ev)
-    Display *dpy;
-    Window  win;
-    GC     gc;
-    XEvent  *ev;
+HandleMotionNotify (Display *dpy, Window win, GC gc, XEvent *ev)
 {
     XMotionEvent    *mev = (XMotionEvent *) ev;
 
-    Undraw (dpy, win, gc, positions);
+    Undraw (dpy, win, gc, current_positions);
     UpdatePositions (mev->state, mev->x, mev->y);
-    Draw (dpy, win, gc, positions);
+    Draw (dpy, win, gc, current_positions);
 }
 
-void
-DisplayPositions (dpy, win, gc, positions)
-    Display        *dpy;
-    Window         win;
-    GC             gc;
-    PositionRec            positions[5];
+static inline void
+DisplayPositions (Display *dpy, Window win, GC gc, PositionRec positions[5])
 {
     static char        text[1024];
     static int hastext;
@@ -274,10 +274,10 @@ DisplayPositions (dpy, win, gc, positions)
     int                dir, font_ascent, font_descent;
     XCharStruct        overall;
 
-    XTextExtents (default_font , text, strlen(text),
+    XTextExtents (default_font, text, (int) strlen(text),
            &dir, &font_ascent, &font_descent, &overall);
     if (hastext)
-       XClearArea (dpy, win, 0, 0, overall.width, font_ascent + font_descent, False);
+           XClearArea (dpy, win, 0, 0, (unsigned) overall.width, (unsigned) (font_ascent + font_descent), False);
     pos = 0;
     for (i = 0; i < 5; i++)
     {
@@ -288,7 +288,7 @@ DisplayPositions (dpy, win, gc, positions)
            sprintf (text + pos, "%1d: (%4d,%4d),(%4d,%4d)",
                i, positions[i].start_x, positions[i].start_y,
                positions[i].cur_x, positions[i].cur_y);
-           pos = strlen (text);
+           pos = (int) strlen (text);
        }
     }
     XDrawString (dpy, win, gc, 0, font_ascent, text, pos);
@@ -366,6 +366,9 @@ int     screen;
 int    current_timeout = TIMEOUT;
 #endif
 
+void
+Setup(Display *dpy, Window win);
+
 void
 HandleExpose(Display *dpy, Window win, GC gc);
 
@@ -466,6 +469,9 @@ main (int argc, char **argv)
     int                has_fg_pixel = 0, has_bg_pixel = 0;
     int                has_colormap = 0;
     unsigned long   gc_mask;
+#ifndef PASS_KEYS
+    char       quit_string[10];
+#endif
     unsigned long   window_mask;
 
     if (!rop_name)
index 0221fbb9a71a07fe4ca00c06ed98793b5524b2a7..02d2b5decf0a4f926efad3ed0ccf5c9096da2f96 100644 (file)
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-#define IMAGE_SCALE    8
-#define WIDTH  128
-#define HEIGHT 64
-
-#define IMAGE_WIDTH    (WIDTH * IMAGE_SCALE)
-#define IMAGE_HEIGHT   (HEIGHT * IMAGE_SCALE)
-
-#define DEFAULT_WIDTH  IMAGE_WIDTH
-#define DEFAULT_HEIGHT IMAGE_HEIGHT
-
 #define TIMEOUT        50
 
 #define PASS_KEYS
-#include "frame.c"
-#include "ao_draw.h"
-
-#define STRIDE ((WIDTH + 31) / 32)
-
-static uint32_t bits[STRIDE * HEIGHT];
-
-static struct ao_bitmap fb = {
-       .base = bits,
-       .stride = STRIDE,
-       .width = WIDTH,
-       .height = HEIGHT
-};
+#include "test-frame.c"
 
 #define BIG_FONT FrutigerLT_Roman_64_font
 #define VOLT_FONT FrutigerLT_Roman_64_font
@@ -118,10 +96,6 @@ static const float pad_volts = 12.3f;
 static const float lco_volts = 4.1f;
 static const int rssi = -30;
 
-#define IMAGE_STRIDE   ((IMAGE_WIDTH + 31) / 32)
-
-static uint32_t image_bits[IMAGE_STRIDE * IMAGE_HEIGHT];
-
 static int     boxes[] = { 1, 2, 3, 5, 8, 11, 13, 17, 19, 23, 29, 31, 37, 62, 97 };
 
 static int     max_box = 97;
@@ -241,26 +215,7 @@ void HandleExpose(Display *dpy, Window win, GC gc)
                break;
        }
 
-       XImage *source_image = XCreateImage(dpy, visual, 1, XYBitmap, 0, (char *) bits, WIDTH, HEIGHT, 32, STRIDE*4);
-       XImage *image = XCreateImage(dpy, visual, 1, XYBitmap, 0, (char *) image_bits, IMAGE_WIDTH, IMAGE_HEIGHT, 32, IMAGE_STRIDE * 4);
-       int ix, iy;
-       int dx, dy;
-
-       for (iy = 0; iy < HEIGHT; iy++) {
-               for (ix = 0; ix < WIDTH; ix++) {
-                       unsigned long bit = XGetPixel(source_image, ix, iy);
-                       for (dy = 0; dy < IMAGE_SCALE; dy++) {
-
-                               for (dx = 0; dx < IMAGE_SCALE; dx++) {
-                                       XPutPixel(image, ix * IMAGE_SCALE + dx, iy * IMAGE_SCALE + dy, bit);
-                               }
-                       }
-               }
-       }
-       XSetForeground(dpy, gc, WhitePixel(dpy, screen));
-       XSetBackground(dpy, gc, BlackPixel(dpy, screen));
-       XPutImage(dpy, win, gc, image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
-       free(image);
+       DoDisplay(dpy, win, gc);
 }
 
 void
diff --git a/src/draw/test-frame.c b/src/draw/test-frame.c
new file mode 100644 (file)
index 0000000..3b764eb
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright © 2023 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#define IMAGE_SCALE    8
+#define WIDTH  128
+#define HEIGHT 64
+
+#define IMAGE_WIDTH    (WIDTH * IMAGE_SCALE)
+#define IMAGE_HEIGHT   (HEIGHT * IMAGE_SCALE)
+#define IMAGE_STRIDE   ((IMAGE_WIDTH + 31) / 32)
+
+#define DEFAULT_WIDTH  IMAGE_WIDTH
+#define DEFAULT_HEIGHT IMAGE_HEIGHT
+
+#define PASS_SETUP
+
+#include "frame.c"
+#include "ao_draw.h"
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <X11/extensions/XShm.h>
+
+#define STRIDE ((WIDTH + 31) / 32)
+
+static uint32_t bits[STRIDE * HEIGHT];
+
+static struct ao_bitmap fb = {
+       .base = bits,
+       .stride = STRIDE,
+       .width = WIDTH,
+       .height = HEIGHT
+};
+
+static XImage *shm_image;
+static XImage *nonshm_image;
+static XShmSegmentInfo shm_info;
+
+void
+Setup(Display *dpy, Window win)
+{
+       (void) win;
+       if (XShmQueryExtension(dpy)) {
+               shm_image = XShmCreateImage(dpy, visual, (unsigned) depth, ZPixmap, NULL, &shm_info, IMAGE_WIDTH, IMAGE_HEIGHT);
+               shm_info.shmid = shmget(IPC_PRIVATE, (size_t) (shm_image->bytes_per_line * shm_image->height), IPC_CREAT|0777);
+               shm_info.shmaddr = shm_image->data = shmat(shm_info.shmid, 0, 0);
+               shm_info.readOnly = True;
+               XShmAttach(dpy, &shm_info);
+       } else {
+               nonshm_image = XCreateImage(dpy, visual, (unsigned) depth, ZPixmap, 0, NULL,
+                                    IMAGE_WIDTH, IMAGE_HEIGHT, 32, IMAGE_STRIDE * 4);
+               nonshm_image->data = calloc((size_t) nonshm_image->bytes_per_line, (size_t) nonshm_image->height);
+       }
+}
+
+static void
+DoDisplay(Display *dpy, Window win, GC gc)
+{
+       int             ix, iy, ib;
+       int             dx, dy;
+       XImage          *image;
+       uint32_t        *w, *scan, d;
+       unsigned long   white = WhitePixel(dpy, screen);
+       unsigned long   black = BlackPixel(dpy, screen);
+
+       if (shm_image)
+               image = shm_image;
+       else
+               image = nonshm_image;
+
+       scan = bits;
+       for (iy = 0; iy < HEIGHT; iy++) {
+               w = scan;
+               scan += STRIDE;
+               for (ix = 0; ix < WIDTH; ix += 32) {
+                       d = *w++;
+                       for (ib = 0; ib < 32 && ix + ib < WIDTH; ib++) {
+                               unsigned long p = d & 1 ? white : black;
+                               d >>= 1;
+                               for (dy = 0; dy < IMAGE_SCALE; dy++) {
+
+                                       for (dx = 0; dx < IMAGE_SCALE; dx++) {
+                                               XPutPixel(image, (ix + ib) * IMAGE_SCALE + dx, iy * IMAGE_SCALE + dy, p);
+                                       }
+                               }
+                       }
+               }
+       }
+       if (shm_image)
+               XShmPutImage(dpy, win, gc, image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, False);
+       else
+               XPutImage(dpy, win, gc, image, 0, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
+}