From http://www.jwz.org/xscreensaver/xscreensaver-5.39.tar.gz
[xscreensaver] / hacks / analogtv.c
index 28930c5ef91c791359b8c993662c61bc00bc8b2e..e3af6f2be287c7419b06f3b10a79d274466e4c7e 100644 (file)
@@ -1,4 +1,4 @@
-/* analogtv, Copyright (c) 2003, 2004 Trevor Blackwell <tlb@tlb.org>
+/* analogtv, Copyright (c) 2003-2018 Trevor Blackwell <tlb@tlb.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
    - removed unusable hashnoise code
  */
 
+/*
+  2016-10-09, Dave Odell <dmo2118@gmail.com>:
+  Updated for new xshm.c.
+*/
+
 #ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else /* !HAVE_JWXYZ */
@@ -80,6 +85,8 @@
 #include "yarandom.h"
 #include "grabscreen.h"
 #include "visual.h"
+#include "font-retry.h"
+#include "ximage-loader.h"
 
 /* #define DEBUG 1 */
 
@@ -217,8 +224,8 @@ analogtv_set_defaults(analogtv *it, char *prefix)
 
 #ifdef DEBUG
   printf("analogtv: prefix=%s\n",prefix);
-  printf("  use: shm=%d cmap=%d color=%d\n",
-         it->use_shm,it->use_cmap,it->use_color);
+  printf("  use: cmap=%d color=%d\n",
+         it->use_cmap,it->use_color);
   printf("  controls: tint=%g color=%g brightness=%g contrast=%g\n",
          it->tint_control, it->color_control, it->brightness_control,
          it->contrast_control);
@@ -228,8 +235,8 @@ analogtv_set_defaults(analogtv *it, char *prefix)
          it->horiz_desync, it->flutter_horiz_desync);
   printf("  hashnoise rpm: %g\n",
          it->hashnoise_rpm);
-  printf("  vis: %d %d %d\n",
-         it->visclass, it->visbits, it->visdepth);
+  printf("  vis: %d %d\n",
+         it->visclass, it->visdepth);
   printf("  shift: %d-%d %d-%d %d-%d\n",
          it->red_invprec,it->red_shift,
          it->green_invprec,it->green_shift,
@@ -262,15 +269,7 @@ static void
 analogtv_free_image(analogtv *it)
 {
   if (it->image) {
-    if (it->use_shm) {
-#ifdef HAVE_XSHM_EXTENSION
-      destroy_xshm_image(it->dpy, it->image, &it->shm_info);
-#endif
-    } else {
-      thread_free(it->image->data);
-      it->image->data = NULL;
-      XDestroyImage(it->image);
-    }
+    destroy_xshm_image(it->dpy, it->image, &it->shm_info);
     it->image=NULL;
   }
 }
@@ -280,31 +279,14 @@ analogtv_alloc_image(analogtv *it)
 {
   /* On failure, it->image is NULL. */
 
-  unsigned bits_per_pixel = get_bits_per_pixel(it->dpy, it->xgwa.depth);
+  unsigned bits_per_pixel = visual_pixmap_depth(it->screen, it->xgwa.visual);
   unsigned align = thread_memory_alignment(it->dpy) * 8 - 1;
   /* Width is in bits. */
   unsigned width = (it->usewidth * bits_per_pixel + align) & ~align;
 
-  if (it->use_shm) {
-#ifdef HAVE_XSHM_EXTENSION
-    it->image=create_xshm_image(it->dpy, it->xgwa.visual, it->xgwa.depth, ZPixmap, 0,
-                                &it->shm_info,
-                                width / bits_per_pixel, it->useheight);
-#endif
-    if (!it->image) it->use_shm=0;
-  }
-  if (!it->image) {
-    it->image = XCreateImage(it->dpy, it->xgwa.visual, it->xgwa.depth, ZPixmap, 0, 0,
-                             it->usewidth, it->useheight, 8, width / 8);
-    if (it->image) {
-      if(thread_malloc((void **)&it->image->data, it->dpy,
-                       it->image->height * it->image->bytes_per_line)) {
-        it->image->data = NULL;
-        XDestroyImage(it->image);
-        it->image = NULL;
-      }
-    }
-  }
+  it->image=create_xshm_image(it->dpy, it->xgwa.visual, it->xgwa.depth,
+                              ZPixmap, &it->shm_info,
+                              width / bits_per_pixel, it->useheight);
 
   if (it->image) {
     memset (it->image->data, 0, it->image->height * it->image->bytes_per_line);
@@ -325,7 +307,8 @@ analogtv_configure(analogtv *it)
   /* If the window is very small, don't let the image we draw get lower
      than the actual TV resolution (266x200.)
 
-     If the aspect ratio of the window is close to a 4:3 or 16:9 ratio,
+     If the aspect ratio of the window is close to a 4:3 or 16:9 ratio --
+     or if it is a completely weird aspect ratio --
      then scale the image to exactly fill the window.
 
      Otherwise, center the image either horizontally or vertically,
@@ -337,6 +320,8 @@ analogtv_configure(analogtv *it)
   float percent = 0.15;
   float min_ratio =  4.0 / 3.0 * (1 - percent);
   float max_ratio = 16.0 / 9.0 * (1 + percent);
+  float crazy_min_ratio = 10;
+  float crazy_max_ratio = 1/crazy_min_ratio;
   float ratio;
   float height_snap=0.025;
 
@@ -390,6 +375,20 @@ analogtv_configure(analogtv *it)
 # endif
     }
 
+  if (ratio < crazy_min_ratio || ratio > crazy_max_ratio)
+    {
+      if (ratio < crazy_min_ratio)
+        hlim = it->xgwa.height;
+      else
+        wlim = it->xgwa.width;
+# ifdef DEBUG
+      fprintf (stderr,
+               "size: aspect: %dx%d in %dx%d (%.3f < %.3f < %.3f)\n",
+               wlim, hlim, it->xgwa.width, it->xgwa.height,
+               min_ratio, ratio, max_ratio);
+# endif
+    }
+
 
   height_diff = ((hlim + ANALOGTV_VISLINES/2) % ANALOGTV_VISLINES) - ANALOGTV_VISLINES/2;
   if (height_diff != 0 && abs(height_diff) < hlim * height_snap)
@@ -508,18 +507,11 @@ analogtv_allocate(Display *dpy, Window window)
 
   it->n_colors=0;
 
-#ifdef HAVE_XSHM_EXTENSION
-  it->use_shm=1;
-#else
-  it->use_shm=0;
-#endif
-
   XGetWindowAttributes (it->dpy, it->window, &it->xgwa);
 
   it->screen=it->xgwa.screen;
   it->colormap=it->xgwa.colormap;
-  it->visclass=it->xgwa.visual->class;
-  it->visbits=it->xgwa.visual->bits_per_rgb;
+  it->visclass=visual_class(it->xgwa.screen, it->xgwa.visual);
   it->visdepth=it->xgwa.depth;
   if (it->visclass == TrueColor || it->visclass == DirectColor) {
     if (get_integer_resource (it->dpy, "use_cmap", "Integer")) {
@@ -538,9 +530,8 @@ analogtv_allocate(Display *dpy, Window window)
     it->use_color=0;
   }
 
-  it->red_mask=it->xgwa.visual->red_mask;
-  it->green_mask=it->xgwa.visual->green_mask;
-  it->blue_mask=it->xgwa.visual->blue_mask;
+  visual_rgb_masks (it->xgwa.screen, it->xgwa.visual,
+                    &it->red_mask, &it->green_mask, &it->blue_mask);
   it->red_shift=it->red_invprec=-1;
   it->green_shift=it->green_invprec=-1;
   it->blue_shift=it->blue_invprec=-1;
@@ -599,15 +590,7 @@ void
 analogtv_release(analogtv *it)
 {
   if (it->image) {
-    if (it->use_shm) {
-#ifdef HAVE_XSHM_EXTENSION
-      destroy_xshm_image(it->dpy, it->image, &it->shm_info);
-#endif
-    } else {
-      thread_free(it->image->data);
-      it->image->data = NULL;
-      XDestroyImage(it->image);
-    }
+    destroy_xshm_image(it->dpy, it->image, &it->shm_info);
     it->image=NULL;
   }
   if (it->gc) XFreeGC(it->dpy, it->gc);
@@ -1963,20 +1946,11 @@ analogtv_draw(analogtv *it, double noiselevel,
   }
 
   if (overall_bot > overall_top) {
-    if (it->use_shm) {
-#ifdef HAVE_XSHM_EXTENSION
-      XShmPutImage(it->dpy, it->window, it->gc, it->image,
+    put_xshm_image(it->dpy, it->window, it->gc, it->image,
                    0, overall_top,
                    it->screen_xo, it->screen_yo+overall_top,
                    it->usewidth, overall_bot - overall_top,
-                   False);
-#endif
-    } else {
-      XPutImage(it->dpy, it->window, it->gc, it->image,
-                0, overall_top,
-                it->screen_xo, it->screen_yo+overall_top,
-                it->usewidth, overall_bot - overall_top);
-    }
+                   &it->shm_info);
   }
 
 #ifdef DEBUG
@@ -2200,10 +2174,10 @@ analogtv_reception_update(analogtv_reception *rec)
 }
 
 
-/* jwz: since MacOS doesn't have "6x10", I dumped this font to an XBM...
+/* jwz: since MacOS doesn't have "6x10", I dumped this font to a PNG...
  */
 
-#include "images/6x10font.xbm"
+#include "images/gen/6x10font_png.h"
 
 void
 analogtv_make_font(Display *dpy, Window window, analogtv_font *f,
@@ -2223,18 +2197,40 @@ analogtv_make_font(Display *dpy, Window window, analogtv_font *f,
 
   if (fontname && !strcmp (fontname, "6x10")) {
 
-    text_pm = XCreatePixmapFromBitmapData (dpy, window,
-                                           (char *) font6x10_bits,
-                                           font6x10_width,
-                                           font6x10_height,
-                                           1, 0, 1);
-    f->text_im = XGetImage(dpy, text_pm, 0, 0, font6x10_width, font6x10_height,
-                           1, XYPixmap);
-    XFreePixmap(dpy, text_pm);
+    int pix_w, pix_h;
+    XWindowAttributes xgwa;
+    Pixmap m = 0;
+    Pixmap p = image_data_to_pixmap (dpy, window,
+                                     _6x10font_png, sizeof(_6x10font_png),
+                                     &pix_w, &pix_h, &m);
+    XImage *im = XGetImage (dpy, p, 0, 0, pix_w, pix_h, ~0L, ZPixmap);
+    XImage *mm = XGetImage (dpy, m, 0, 0, pix_w, pix_h, 1, XYPixmap);
+    unsigned long black = BlackPixelOfScreen (DefaultScreenOfDisplay (dpy));
+    int x, y;
+
+    XFreePixmap (dpy, p);
+    XFreePixmap (dpy, m);
+    if (pix_w != 256*7) abort();
+    if (pix_h != 10) abort();
+
+    XGetWindowAttributes (dpy, window, &xgwa);
+    f->text_im = XCreateImage (dpy, xgwa.visual, 1, XYBitmap, 0, 0,
+                               pix_w, pix_h, 8, 0);
+    f->text_im->data = malloc (f->text_im->bytes_per_line * f->text_im->height);
+
+    /* Convert deep image to 1 bit */
+    for (y = 0; y < pix_h; y++)
+      for (x = 0; x < pix_w; x++)
+        XPutPixel (f->text_im, x, y,
+                   (XGetPixel (mm, x, y)
+                    ? XGetPixel (im, x, y) == black
+                    : 0));
+    XDestroyImage (im);
+    XDestroyImage (mm);
 
   } else if (fontname) {
 
-    font = XLoadQueryFont (dpy, fontname);
+    font = load_font_retry (dpy, fontname);
     if (!font) {
       fprintf(stderr, "analogtv: can't load font %s\n", fontname);
       abort();