From http://www.jwz.org/xscreensaver/xscreensaver-5.39.tar.gz
[xscreensaver] / hacks / analogtv.c
index c26c315c3aab7a8ce746d759438119b62153d848..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
  *
  * 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
  */
 
    - removed unusable hashnoise code
  */
 
-#ifdef HAVE_COCOA
+/*
+  2016-10-09, Dave Odell <dmo2118@gmail.com>:
+  Updated for new xshm.c.
+*/
+
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 # include "jwxyz.h"
-#else /* !HAVE_COCOA */
+#else /* !HAVE_JWXYZ */
 # include <X11/Xlib.h>
 # include <X11/Xutil.h>
 #endif
 # include <X11/Xlib.h>
 # include <X11/Xutil.h>
 #endif
@@ -80,6 +85,8 @@
 #include "yarandom.h"
 #include "grabscreen.h"
 #include "visual.h"
 #include "yarandom.h"
 #include "grabscreen.h"
 #include "visual.h"
+#include "font-retry.h"
+#include "ximage-loader.h"
 
 /* #define DEBUG 1 */
 
 
 /* #define DEBUG 1 */
 
@@ -217,8 +224,8 @@ analogtv_set_defaults(analogtv *it, char *prefix)
 
 #ifdef DEBUG
   printf("analogtv: prefix=%s\n",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);
   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);
          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,
   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) {
 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;
   }
 }
     it->image=NULL;
   }
 }
@@ -280,31 +279,14 @@ analogtv_alloc_image(analogtv *it)
 {
   /* On failure, it->image is NULL. */
 
 {
   /* 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;
 
   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);
 
   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 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,
      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 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;
 
   float ratio;
   float height_snap=0.025;
 
@@ -344,7 +329,7 @@ analogtv_configure(analogtv *it)
   wlim = it->xgwa.width;
   ratio = wlim / (float) hlim;
 
   wlim = it->xgwa.width;
   ratio = wlim / (float) hlim;
 
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   /* Fill the whole iPhone screen, even though that distorts the image. */
   min_ratio = 0;
   max_ratio = 10;
   /* Fill the whole iPhone screen, even though that distorts the image. */
   min_ratio = 0;
   max_ratio = 10;
@@ -390,9 +375,23 @@ analogtv_configure(analogtv *it)
 # endif
     }
 
 # 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;
 
   height_diff = ((hlim + ANALOGTV_VISLINES/2) % ANALOGTV_VISLINES) - ANALOGTV_VISLINES/2;
-  if (height_diff != 0 && fabs(height_diff) < hlim * height_snap)
+  if (height_diff != 0 && abs(height_diff) < hlim * height_snap)
     {
       hlim -= height_diff;
     }
     {
       hlim -= height_diff;
     }
@@ -508,18 +507,11 @@ analogtv_allocate(Display *dpy, Window window)
 
   it->n_colors=0;
 
 
   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;
   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")) {
   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->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;
   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) {
 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);
     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 (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,
                    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
   }
 
 #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,
 
 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")) {
 
 
   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) {
 
 
   } 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();
     if (!font) {
       fprintf(stderr, "analogtv: can't load font %s\n", fontname);
       abort();