From http://www.jwz.org/xscreensaver/xscreensaver-5.40.tar.gz master
authorZygo Blaxell <zblaxell@waya.furryterror.org>
Mon, 13 Aug 2018 16:54:16 +0000 (12:54 -0400)
committerZygo Blaxell <zblaxell@waya.furryterror.org>
Mon, 13 Aug 2018 16:59:21 +0000 (12:59 -0400)
-rw-rw-r-- 1 zblaxell zblaxell 12248135 Aug 12 19:49 xscreensaver-5.40.tar.gz
82c7433fe008e6ea9ab8683cf3325a673b8a8233  xscreensaver-5.40.tar.gz

124 files changed:
OSX/README
OSX/SaverRunner.plist
OSX/Updater.plist
OSX/XScreenSaver.plist
OSX/bindist.rtf
OSX/build-fntable.pl
OSX/grabclient-osx.m
OSX/iSaverRunner.plist
OSX/ios-function-table.m
OSX/updates.xml
OSX/xscreensaver.xcodeproj/project.pbxproj
README
android/Makefile
android/README
android/build.gradle
android/gradle/wrapper/gradle-wrapper.properties
android/xscreensaver/.idea/caches/build_file_checksums.ser
android/xscreensaver/.idea/libraries/Gradle__android_arch_core_common_1_1_0_jar.xml [new file with mode: 0644]
android/xscreensaver/.idea/libraries/Gradle__android_arch_core_runtime_1_1_0.xml [new file with mode: 0644]
android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_common_1_1_0_jar.xml [new file with mode: 0644]
android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_livedata_core_1_1_0.xml [new file with mode: 0644]
android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_runtime_1_1_0.xml [new file with mode: 0644]
android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_viewmodel_1_1_0.xml [new file with mode: 0644]
android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_annotations_27_1_1_jar.xml [new file with mode: 0644]
android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_compat_27_1_1.xml [new file with mode: 0644]
android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_core_ui_27_1_1.xml [new file with mode: 0644]
android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_core_utils_27_1_1.xml [new file with mode: 0644]
android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_fragment_27_1_1.xml [new file with mode: 0644]
android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_media_compat_27_1_1.xml [new file with mode: 0644]
android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_v4_27_1_1.xml [new file with mode: 0644]
android/xscreensaver/.idea/misc.xml
android/xscreensaver/.idea/workspace.xml
android/xscreensaver/build.gradle
android/xscreensaver/jni/Android.mk
android/xscreensaver/jni/Application.mk
android/xscreensaver/src/org/jwz/xscreensaver/Activity.java
android/xscreensaver/src/org/jwz/xscreensaver/jwxyz.java
android/xscreensaver/xscreensaver.iml
configure
configure.in
driver/Makefile.in
driver/XScreenSaver.ad.in
driver/XScreenSaver_ad.h
driver/xscreensaver-getimage-file
driver/xscreensaver-getimage.c
hacks/Makefile.in
hacks/analogtv.c
hacks/analogtv.h
hacks/bsod.c
hacks/compile_axp.com
hacks/compile_decc.com
hacks/config/README
hacks/config/apple2.xml
hacks/config/bsod.xml
hacks/config/cubestorm.xml
hacks/config/dymaxionmap.xml
hacks/config/filmleader.xml [new file with mode: 0644]
hacks/config/glitchpeg.xml [new file with mode: 0644]
hacks/config/glplanet.xml
hacks/config/m6502.xml
hacks/config/maze3d.xml
hacks/config/pong.xml
hacks/config/tessellimage.xml
hacks/config/vfeedback.xml [new file with mode: 0644]
hacks/config/xanalogtv.xml
hacks/filmleader.c [new file with mode: 0644]
hacks/filmleader.man [new file with mode: 0644]
hacks/glitchpeg.c [new file with mode: 0644]
hacks/glitchpeg.man [new file with mode: 0644]
hacks/glx/Makefile.in
hacks/glx/crumbler.c
hacks/glx/cubestorm.c
hacks/glx/dnalogo.c
hacks/glx/dymaxionmap-coords.c [new file with mode: 0644]
hacks/glx/dymaxionmap-coords.h [new file with mode: 0644]
hacks/glx/dymaxionmap.c
hacks/glx/dymaxionmap.man
hacks/glx/glplanet.c
hacks/glx/glplanet.man
hacks/glx/noof.c
hacks/glx/quasicrystal.c
hacks/glx/quickhull.c
hacks/glx/sonar-icmp.c
hacks/glx/zalgo.txt
hacks/images/Makefile
hacks/images/Makefile.in [new file with mode: 0644]
hacks/images/dymaxionmap.png [deleted file]
hacks/images/earth_flat.png [new file with mode: 0644]
hacks/images/testcard_bbcf.png [new file with mode: 0644]
hacks/images/testcard_pm5544.png [new file with mode: 0644]
hacks/images/testcard_rca.png [new file with mode: 0644]
hacks/interference.c
hacks/recanim.c
hacks/recanim.h
hacks/screenhackI.h
hacks/tessellimage.c
hacks/testx11.c
hacks/vfeedback.c [new file with mode: 0644]
hacks/vfeedback.man [new file with mode: 0644]
hacks/xanalogtv.c
hacks/xflame.c
hacks/ximage-loader.c
hacks/ximage-loader.h
jwxyz/jwxyz-android.c
jwxyz/jwxyz-cocoa.m
jwxyz/jwxyz-common.c
jwxyz/jwxyz-gl.c
jwxyz/jwxyz-image.c
jwxyz/jwxyz.h
jwxyz/jwxyz.m
jwxyz/jwxyzI.h
jwxyz/jwzgles.c
jwxyz/jwzglesI.h
po/POTFILES.in
setup.com
utils/Makefile.in
utils/colorbars.c
utils/font-retry.c
utils/font-retry.h
utils/utf8wc.c
utils/version.h
utils/visual-gl.c
utils/xft.c
xscreensaver.spec

index acf589b2f61c675dc4efafb6747b5a1c6955fb47..0799995abc7dd03babf5759ddf9840326f9013e8 100644 (file)
@@ -18,25 +18,25 @@ ridiculously long list of steps!
   3: Delete the dangerball.c and dangerball.xml files from Build Phases.
   4: Delete the "DangerBall copy-Info.plist" file that got created.
   5: Delete the "DangerBall copy-Info.plist" from the Build Settings too.
-  6: -
-  7: Manage Schemes, rename "DangerBall Copy".
-  8: Move to the right place in the list.
-  9: Scheme / Run / Info: Executable: SaverTester.app.
- 10: Scheme / Run / Arguments: set SELECTED_SAVER environment variable.
- 11: File / Add Files / the new .c and .xml.
- 12: Select each file in the left pane; see Target Membership in the right
    pane and add them to the new target, and to "XScreenSaver-iOS".
13: Re-order them in the file list.
- 14: In target "All Savers (OpenGL)" add the new target as Build Phases /
+  6: Manage Schemes, rename "DangerBall Copy".
+  7: Move to the right place in the list.
+  8: Scheme / Run / Info: Executable: SaverTester.app.
+  9: Scheme / Run / Arguments: set SELECTED_SAVER environment variable.
+ 10: File / Add Files / the new .c and .xml.
+ 11: Re-order them in the file list. This will bring up an Options dialog.
+     Add To Targets: the new target, and "XScreenSaver-iOS".
12: The files might not have moved. This means Xcode is gonna crash soon.
    It will repair itself after.
+ 13: In target "All Savers (OpenGL)" add the new target as Build Phases /
      Target Dependency.
- 15: In target "XScreenSaver-iOS", reorder new files in Build Phases /
+ 14: In target "XScreenSaver-iOS", reorder new files in Build Phases /
      "Copy" and "Compile", since they showed up in a random place.
- 16: In target "XScreenSaver-iOS", add "-DUSE_GL" to the new file's options.
- 17: Put a 200x150 screen shot in ~/www/xscreensaver/screenshots/
- 18: ln -s ../../src/xscreensaver/OSX/build/Debug/NEW.saver \
+ 15: In target "XScreenSaver-iOS", add "-DUSE_GL" to the new file's options.
+ 16: Put a 200x150 screen shot in ~/www/xscreensaver/screenshots/
+ 17: ln -s ../../src/xscreensaver/OSX/build/Debug/NEW.saver \
            ~/Library/Screen\ Savers/
- 19: git add xscreensaver.xcodeproj/xcuserdata/*/xcschemes/*.xcscheme
20: Don't forget to create a man page from the XML with xml2man.pl,
+ 18: git add xscreensaver.xcodeproj/xcuserdata/*/xcschemes/*.xcscheme
19: Don't forget to create a man page from the XML with xml2man.pl,
      and update Makefile.in.
- 21: Make a video: -record-animation 3600 -delay 1 -geom 1920x1080+128+64
+ 20: Make a video: -record-animation 3600 -delay 1 -geom 1920x1080+128+64
      ./upload-video.pl NAME
index 502164354aa6397335bfa702582da5800e5117f0..3ad0ce71e82b42d34ffeed868b1eadac1fad0682 100644 (file)
@@ -7,7 +7,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>CFBundleIconFile</key>
        <string>SaverRunner</string>
        <key>CFBundleIdentifier</key>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>NSHumanReadableCopyright</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>NSMainNibFile</key>
        <string>SaverRunner</string>
        <key>NSPrincipalClass</key>
index 00e6b1bd170abe8ac524d1f9649e638cc5bf3268..fd3b17652cc367f1fb3a58dc162c3b7c89cd7466 100644 (file)
@@ -9,7 +9,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>CFBundleIconFile</key>
        <string>SaverRunner</string>
        <key>CFBundleIdentifier</key>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>LSUIElement</key>
        <true/>
        <key>NSHumanReadableCopyright</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>NSMainNibFile</key>
        <string>Updater</string>
        <key>NSPrincipalClass</key>
index 23e1eb67725b44f321ae647e5119f7e1d7e0e17f..34172952ca7289b1f7875d33939e52f4d4e44d01 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>LSMinimumSystemVersion</key>
        <string>10.8</string>
        <key>NSMainNibFile</key>
index a1e749d627c82ef4e73611170334f64d4e621c1e..9d8243188358423925bc7bd1da0a61f7079acf1c 100644 (file)
@@ -16,8 +16,8 @@
 \b0 by Jamie Zawinski\
 and many others\
 \
-version 5.39\
-12-Apr-2018\
+version 5.40\
+12-Aug-2018\
 \
 {\field{\*\fldinst{HYPERLINK "https://www.jwz.org/xscreensaver/"}}{\fldrslt \cf2 \ul \ulc2 https://www.jwz.org/xscreensaver/}}\
 \pard\pardeftab720
index dc69dfecc7468f036caf80c7619b057a6b04140c..c93343cf747a0fded5dcdfcdb93f4daac67637f4 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright © 2012-2015 Jamie Zawinski <jwz@jwz.org>
+# Copyright © 2012-2018 Jamie Zawinski <jwz@jwz.org>
 #
 # Permission to use, copy, modify, distribute, and sell this software and its
 # documentation for any purpose is hereby granted without fee, provided that
@@ -23,7 +23,7 @@ require 5;
 use strict;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.5 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.6 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 1;
 
@@ -31,6 +31,7 @@ my $verbose = 1;
 #
 my %disable = (
    'extrusion'         => 1,
+   'glitchpeg'         => 1,
    'lcdscrub'          => 1,
    'lockward'          => 1,
    'webcollage'                => 1,
index 045039d3762bc9aed0d4cf2980f4c138cfd7eadf..7bfdcb4fa811b0e921dbd585f571b2422e4e39c2 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992-2017 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2018 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -342,6 +342,7 @@ osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable,
                                      (NSString *)kCGWindowNumber]).intValue;
       }
     }
+    CFRelease (L);
   }
 
   // Grab a screen shot of those windows below this one
index 517380e858a86303ec2b484ba65698f84238a363..4604e9d331c21924a2ee9a3e5657ac71c404f867 100644 (file)
@@ -9,7 +9,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>CFBundleIcons</key>
        <dict/>
        <key>CFBundleIcons~ipad</key>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>LSRequiresIPhoneOS</key>
        <true/>
        <key>NSHumanReadableCopyright</key>
-       <string>5.39</string>
+       <string>5.40</string>
        <key>NSMainNibFile</key>
        <string>iSaverRunner</string>
        <key>UIAppFonts</key>
index 3fb284a251ff80053795cf6baa1effda85fe5b24..fcb2808488fe1916acd357a7899ba17b9c57171c 100644 (file)
@@ -1,5 +1,5 @@
 /* Generated file, do not edit.
-   Created: Tue Apr 10 17:04:05 2018 by build-fntable.pl 1.5.
+   Created: Sat Aug  4 21:35:23 2018 by build-fntable.pl 1.6.
  */
 
 #import <Foundation/Foundation.h>
@@ -75,6 +75,7 @@ extern struct xscreensaver_function_table
  euler2d_xscreensaver_function_table,
  fadeplot_xscreensaver_function_table,
  fiberlamp_xscreensaver_function_table,
+ filmleader_xscreensaver_function_table,
  fireworkx_xscreensaver_function_table,
  flame_xscreensaver_function_table,
  flipflop_xscreensaver_function_table,
@@ -217,6 +218,7 @@ extern struct xscreensaver_function_table
  unicrud_xscreensaver_function_table,
  unknownpleasures_xscreensaver_function_table,
  vermiculate_xscreensaver_function_table,
+ vfeedback_xscreensaver_function_table,
  vigilance_xscreensaver_function_table,
  voronoi_xscreensaver_function_table,
  wander_xscreensaver_function_table,
@@ -312,6 +314,7 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&euler2d_xscreensaver_function_table], @"euler2d",
        [NSValue valueWithPointer:&fadeplot_xscreensaver_function_table], @"fadeplot",
        [NSValue valueWithPointer:&fiberlamp_xscreensaver_function_table], @"fiberlamp",
+       [NSValue valueWithPointer:&filmleader_xscreensaver_function_table], @"filmleader",
        [NSValue valueWithPointer:&fireworkx_xscreensaver_function_table], @"fireworkx",
        [NSValue valueWithPointer:&flame_xscreensaver_function_table], @"flame",
        [NSValue valueWithPointer:&flipflop_xscreensaver_function_table], @"flipflop",
@@ -454,6 +457,7 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&unicrud_xscreensaver_function_table], @"unicrud",
        [NSValue valueWithPointer:&unknownpleasures_xscreensaver_function_table], @"unknownpleasures",
        [NSValue valueWithPointer:&vermiculate_xscreensaver_function_table], @"vermiculate",
+       [NSValue valueWithPointer:&vfeedback_xscreensaver_function_table], @"vfeedback",
        [NSValue valueWithPointer:&vigilance_xscreensaver_function_table], @"vigilance",
        [NSValue valueWithPointer:&voronoi_xscreensaver_function_table], @"voronoi",
        [NSValue valueWithPointer:&wander_xscreensaver_function_table], @"wander",
index 2581d5cd8265c7ebc1b10b0aeb2a442eda40d197..a4733a6f8f384781ed1939a74fe90abb2235b2d4 100644 (file)
@@ -7,6 +7,17 @@
   <link>https://www.jwz.org/xscreensaver/updates.xml</link>
   <description>Updates to xscreensaver.</description>
   <language>en</language>
+  <item>
+   <title>Version 5.39</title>
+   <link>https://www.jwz.org/xscreensaver/xscreensaver-5.39.dmg</link>
+   <description><![CDATA[&bull; New hacks, 'razzledazzle', 'peepers', 'crumbler' and `maze3d'. <BR>&bull; More heuristics for using RSS feeds as image sources. <BR>&bull; Android: Image loading works. <BR>&bull; Built-in image assets are now PNG instead of XPM or XBM. <BR>&bull; X11: Better font-loading fallback heuristics on systems with a terrible selection of installed fonts. <BR>&bull; macOS: Retina display-related bug fixes.]]></description>
+   <pubDate>Thu, 12 Apr 2018 13:00:37 -0700</pubDate>
+   <enclosure url="https://www.jwz.org/xscreensaver/xscreensaver-5.39.dmg"
+    sparkle:version="5.39"
+    sparkle:dsaSignature="MC0CFCNqDWYNT+EDQXEpi0SAxySC77A+AhUArqhfa7sp5J8cXq42u5uFmBOQiFA="
+    length="32888133"
+    type="application/octet-stream" />
+  </item>
   <item>
    <title>Version 5.38</title>
    <link>https://www.jwz.org/xscreensaver/xscreensaver-5.38.dmg</link>
     length="52481386"
     type="application/octet-stream" />
   </item>
-  <item>
-   <title>Version 5.36</title>
-   <link>https://www.jwz.org/xscreensaver/xscreensaver-5.36.dmg</link>
-   <description><![CDATA[&bull; New hacks, `discoball', `cubetwist', `cubestack', `splodesic' and `hexstrut'. <BR>&bull; macOS: loading image files works in `dymaxionmap', `glplanet', `lavalite', `pulsar', `gleidescope' and `extrusion'. <BR>&bull; Several new programs in `m6502'. <BR>&bull; `rotzoomer -mode circle'. <BR>&bull; Better titles in `photopile'.]]></description>
-   <pubDate>Mon, 10 Oct 2016 19:59:35 -0700</pubDate>
-   <enclosure url="https://www.jwz.org/xscreensaver/xscreensaver-5.36.dmg"
-    sparkle:version="5.36"
-    sparkle:dsaSignature="MC0CFE0PgizuGmjl0jbR0M5eu1KLU/XhAhUAj/D/h9i70tfjBehPoCxMoBakBSA="
-    length="52105511"
-    type="application/octet-stream" />
-  </item>
   <item>
    <title>Version 5.34</title>
    <link>https://www.jwz.org/xscreensaver/xscreensaver-5.34.dmg</link>
index ecd80f842b644a8485d998bcafe8f7ebaa6964f7..f5e98b81dd906ecb3a6e89d45eb9476a03925fe4 100644 (file)
                                AF77796509B6604A00EA3033 /* PBXTargetDependency */,
                                AF77796309B6604A00EA3033 /* PBXTargetDependency */,
                                AF77796109B6604A00EA3033 /* PBXTargetDependency */,
+                               AFD77E7A20C241BE00A3638D /* PBXTargetDependency */,
                                AF77795F09B6604A00EA3033 /* PBXTargetDependency */,
                                AF77795D09B6604A00EA3033 /* PBXTargetDependency */,
                                AF77795B09B6604A00EA3033 /* PBXTargetDependency */,
                                AF77795909B6604A00EA3033 /* PBXTargetDependency */,
                                AF77795709B6604A00EA3033 /* PBXTargetDependency */,
+                               AFA6AB1120999A9A006D2685 /* PBXTargetDependency */,
                                AF77795509B6604A00EA3033 /* PBXTargetDependency */,
                                AF77795309B6604900EA3033 /* PBXTargetDependency */,
                                AF77795109B6604900EA3033 /* PBXTargetDependency */,
                                AF7778F309B6604600EA3033 /* PBXTargetDependency */,
                                AF7778F109B6604600EA3033 /* PBXTargetDependency */,
                                AF7778EF09B6604600EA3033 /* PBXTargetDependency */,
+                               AF5ECEC92116B31F00069433 /* PBXTargetDependency */,
                                AF7778ED09B6604600EA3033 /* PBXTargetDependency */,
                                AFA33B8F0B0585A4002B0E7D /* PBXTargetDependency */,
                                AFA33BCF0B0587B2002B0E7D /* PBXTargetDependency */,
                AF3EC991203517AE00180A35 /* peepers.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF3EC98F203517AD00180A35 /* peepers.xml */; };
                AF3EC993203517CC00180A35 /* peepers.c in Sources */ = {isa = PBXBuildFile; fileRef = AF3EC992203517CC00180A35 /* peepers.c */; };
                AF3EC994203517CC00180A35 /* peepers.c in Sources */ = {isa = PBXBuildFile; fileRef = AF3EC992203517CC00180A35 /* peepers.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
+               AF3FAD8F20C242DA00680000 /* analogtv.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9D4CFA09B5AC94006E59CF /* analogtv.c */; };
                AF41E959201D49DB0098E253 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF41E95B201D49DB0098E253 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
                AF41E95C201D49DB0098E253 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
                AF4A3464102A5A0E00A81B2A /* surfaces.c in Sources */ = {isa = PBXBuildFile; fileRef = AF4A3463102A5A0E00A81B2A /* surfaces.c */; };
                AF4A6692191F7CAE00C74753 /* xscreensaver-getimage-file in Resources */ = {isa = PBXBuildFile; fileRef = AF0FAF1209CA712600EE1051 /* xscreensaver-getimage-file */; };
                AF4A8CA010B609B50074B062 /* xscreensaver-getimage-file in Resources */ = {isa = PBXBuildFile; fileRef = AF0FAF1209CA712600EE1051 /* xscreensaver-getimage-file */; };
+               AF4C300E208569AA00BE1DEF /* dymaxionmap-coords.c in Sources */ = {isa = PBXBuildFile; fileRef = AF4C300D208569A900BE1DEF /* dymaxionmap-coords.c */; };
+               AF4C300F208569AA00BE1DEF /* dymaxionmap-coords.c in Sources */ = {isa = PBXBuildFile; fileRef = AF4C300D208569A900BE1DEF /* dymaxionmap-coords.c */; };
                AF4FD6EC0CE7A486005EE58E /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF4FD7010CE7A577005EE58E /* lockward.c in Sources */ = {isa = PBXBuildFile; fileRef = AF4FD7000CE7A577005EE58E /* lockward.c */; };
                AF4FD7030CE7A5BC005EE58E /* lockward.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF4FD7020CE7A5BC005EE58E /* lockward.xml */; };
                AF5C9B121A0CCF4E00B0147A /* cityflow.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF5C9B0F1A0CCF4E00B0147A /* cityflow.xml */; };
                AF5C9B131A0CCF4E00B0147A /* cityflow.c in Sources */ = {isa = PBXBuildFile; fileRef = AF5C9B101A0CCF4E00B0147A /* cityflow.c */; };
                AF5C9B141A0CCF4E00B0147A /* cityflow.c in Sources */ = {isa = PBXBuildFile; fileRef = AF5C9B101A0CCF4E00B0147A /* cityflow.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
+               AF5ECEB02116B1A400069433 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF5ECEB12116B1A400069433 /* analogtv.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9D4CFA09B5AC94006E59CF /* analogtv.c */; };
+               AF5ECEB42116B1A400069433 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF5ECEB52116B1A400069433 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF5ECEB62116B1A400069433 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF5ECEB72116B1A400069433 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF5ECEB82116B1A400069433 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF5ECEB92116B1A400069433 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF5ECEBA2116B1A400069433 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF5ECEC32116B2CC00069433 /* vfeedback.c in Sources */ = {isa = PBXBuildFile; fileRef = AF5ECEC22116B2CC00069433 /* vfeedback.c */; };
+               AF5ECEC42116B2CC00069433 /* vfeedback.c in Sources */ = {isa = PBXBuildFile; fileRef = AF5ECEC22116B2CC00069433 /* vfeedback.c */; };
+               AF5ECEC62116B2FE00069433 /* vfeedback.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF5ECEC52116B2FE00069433 /* vfeedback.xml */; };
+               AF5ECEC72116B2FE00069433 /* vfeedback.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF5ECEC52116B2FE00069433 /* vfeedback.xml */; };
                AF6048FB157C07C600CA21E4 /* jwzgles.c in Sources */ = {isa = PBXBuildFile; fileRef = AF6048F8157C07C600CA21E4 /* jwzgles.c */; };
                AF6048FC157C07C600CA21E4 /* jwzgles.h in Headers */ = {isa = PBXBuildFile; fileRef = AF6048F9157C07C600CA21E4 /* jwzgles.h */; };
                AF6048FD157C07C600CA21E4 /* jwzglesI.h in Headers */ = {isa = PBXBuildFile; fileRef = AF6048FA157C07C600CA21E4 /* jwzglesI.h */; };
                AF939AD320351BFD0032DD23 /* font-retry.c in Sources */ = {isa = PBXBuildFile; fileRef = AF939AD220351BFC0032DD23 /* font-retry.c */; };
                AF939AD52038C0050032DD23 /* luximr.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AF939AD42038C0040032DD23 /* luximr.ttf */; };
                AF939AD72038C5F00032DD23 /* luximr.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AF939AD42038C0040032DD23 /* luximr.ttf */; };
+               AF95C30420999B3E001924BE /* xscreensaver-getimage-file in Resources */ = {isa = PBXBuildFile; fileRef = AF0FAF1209CA712600EE1051 /* xscreensaver-getimage-file */; };
                AF975734099C317000B05160 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF97573F099C31BB00B05160 /* imsmap.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC258CA0988A468000655EE /* imsmap.xml */; };
                AF975741099C31DD00B05160 /* imsmap.c in Sources */ = {isa = PBXBuildFile; fileRef = AF975740099C31DD00B05160 /* imsmap.c */; };
                AFA5638F0993980D00F3E977 /* timetunnel.c in Sources */ = {isa = PBXBuildFile; fileRef = AFA5638E0993980D00F3E977 /* timetunnel.c */; };
                AFA563B8099398F700F3E977 /* juggler3d.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC258D10988A468000655EE /* juggler3d.xml */; };
                AFA563BA0993991300F3E977 /* juggler3d.c in Sources */ = {isa = PBXBuildFile; fileRef = AFA563B90993991300F3E977 /* juggler3d.c */; };
+               AFA6AAF720999950006D2685 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFA6AAF920999950006D2685 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFA6AAFA20999950006D2685 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFA6AAFB20999950006D2685 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFA6AAFC20999950006D2685 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFA6AAFD20999950006D2685 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFA6AAFE20999950006D2685 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFA6AAFF20999950006D2685 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFA6AB0D20999A60006D2685 /* glitchpeg.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFA6AB0C20999A60006D2685 /* glitchpeg.xml */; };
+               AFA6AB0F20999A7B006D2685 /* glitchpeg.c in Sources */ = {isa = PBXBuildFile; fileRef = AFA6AB0E20999A7B006D2685 /* glitchpeg.c */; };
                AFAA6B451773F07800DE720C /* ios-function-table.m in Sources */ = {isa = PBXBuildFile; fileRef = AFAA6B441773F07700DE720C /* ios-function-table.m */; };
                AFAAE38E207D6343007A515C /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AFAAE390207D6343007A515C /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
                AFD573630997411200BA26F7 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AFD573700997418D00BA26F7 /* strange.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC2591D0988A469000655EE /* strange.xml */; };
                AFD57372099741A200BA26F7 /* strange.c in Sources */ = {isa = PBXBuildFile; fileRef = AFD57371099741A200BA26F7 /* strange.c */; };
+               AFD77E6220C23F8600A3638D /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFD77E6420C23F8600A3638D /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFD77E6520C23F8600A3638D /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFD77E6620C23F8600A3638D /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFD77E6720C23F8600A3638D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFD77E6820C23F8600A3638D /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFD77E6920C23F8600A3638D /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFD77E6A20C23F8600A3638D /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFD77E7320C2418000A3638D /* filmleader.c in Sources */ = {isa = PBXBuildFile; fileRef = AFD77E7220C2417F00A3638D /* filmleader.c */; };
+               AFD77E7420C2418000A3638D /* filmleader.c in Sources */ = {isa = PBXBuildFile; fileRef = AFD77E7220C2417F00A3638D /* filmleader.c */; };
+               AFD77E7520C2418000A3638D /* filmleader.c in Sources */ = {isa = PBXBuildFile; fileRef = AFD77E7220C2417F00A3638D /* filmleader.c */; };
+               AFD77E7720C2419600A3638D /* filmleader.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFD77E7620C2419600A3638D /* filmleader.xml */; };
+               AFD77E7820C2419600A3638D /* filmleader.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFD77E7620C2419600A3638D /* filmleader.xml */; };
                AFD9D5BE201E686B0070E99D /* ships.c in Sources */ = {isa = PBXBuildFile; fileRef = AFD9D5BD201E686A0070E99D /* ships.c */; };
                AFD9D5BF201E686B0070E99D /* ships.c in Sources */ = {isa = PBXBuildFile; fileRef = AFD9D5BD201E686A0070E99D /* ships.c */; };
                AFD9D5C0201E686B0070E99D /* ships.c in Sources */ = {isa = PBXBuildFile; fileRef = AFD9D5BD201E686A0070E99D /* ships.c */; };
                        remoteGlobalIDString = AF5C9AF91A0CCE6E00B0147A;
                        remoteInfo = Cityflow;
                };
+               AF5ECEAB2116B1A400069433 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF5ECEC82116B31F00069433 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF5ECEA92116B1A400069433;
+                       remoteInfo = VFeedback;
+               };
                AF633C031EE0BA6F00AB33BD /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
                        remoteInfo = jwxyz;
                };
+               AFA6AAF220999950006D2685 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFA6AB1020999A9A006D2685 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFA6AAF020999950006D2685;
+                       remoteInfo = GlitchPEG;
+               };
                AFAAE389207D6343007A515C /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
                        remoteInfo = jwxyz;
                };
+               AFD77E5D20C23F8600A3638D /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFD77E7920C241BE00A3638D /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFD77E5B20C23F8600A3638D;
+                       remoteInfo = FilmLeader;
+               };
                AFDA6590178A52B70070D24B /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                AF4A345D102A593600A81B2A /* Surfaces.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Surfaces.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF4A3461102A59EB00A81B2A /* surfaces.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = surfaces.xml; sourceTree = "<group>"; };
                AF4A3463102A5A0E00A81B2A /* surfaces.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = surfaces.c; path = hacks/glx/surfaces.c; sourceTree = "<group>"; };
+               AF4C300D208569A900BE1DEF /* dymaxionmap-coords.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "dymaxionmap-coords.c"; path = "hacks/glx/dymaxionmap-coords.c"; sourceTree = "<group>"; };
                AF4FD6FA0CE7A486005EE58E /* Lockward.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Lockward.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF4FD7000CE7A577005EE58E /* lockward.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = lockward.c; path = hacks/glx/lockward.c; sourceTree = "<group>"; };
                AF4FD7020CE7A5BC005EE58E /* lockward.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = lockward.xml; sourceTree = "<group>"; };
                AF5C9B0D1A0CCE6E00B0147A /* Cityflow.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Cityflow.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF5C9B0F1A0CCF4E00B0147A /* cityflow.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = cityflow.xml; sourceTree = "<group>"; };
                AF5C9B101A0CCF4E00B0147A /* cityflow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cityflow.c; path = hacks/glx/cityflow.c; sourceTree = "<group>"; };
+               AF5ECEC02116B1A400069433 /* VFeedback.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = VFeedback.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF5ECEC22116B2CC00069433 /* vfeedback.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vfeedback.c; path = hacks/vfeedback.c; sourceTree = "<group>"; };
+               AF5ECEC52116B2FE00069433 /* vfeedback.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = vfeedback.xml; sourceTree = "<group>"; };
                AF6048F8157C07C600CA21E4 /* jwzgles.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = jwzgles.c; path = ../jwxyz/jwzgles.c; sourceTree = "<group>"; };
                AF6048F9157C07C600CA21E4 /* jwzgles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jwzgles.h; path = ../jwxyz/jwzgles.h; sourceTree = "<group>"; };
                AF6048FA157C07C600CA21E4 /* jwzglesI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jwzglesI.h; path = ../jwxyz/jwzglesI.h; sourceTree = "<group>"; };
                AFA5638E0993980D00F3E977 /* timetunnel.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = timetunnel.c; path = hacks/glx/timetunnel.c; sourceTree = "<group>"; };
                AFA563B6099398BB00F3E977 /* Juggler3D.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Juggler3D.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AFA563B90993991300F3E977 /* juggler3d.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = juggler3d.c; path = hacks/glx/juggler3d.c; sourceTree = "<group>"; };
+               AFA6AB0520999950006D2685 /* GlitchPEG.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GlitchPEG.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFA6AB0C20999A60006D2685 /* glitchpeg.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = glitchpeg.xml; sourceTree = "<group>"; };
+               AFA6AB0E20999A7B006D2685 /* glitchpeg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = glitchpeg.c; path = hacks/glitchpeg.c; sourceTree = "<group>"; };
                AFAA6B441773F07700DE720C /* ios-function-table.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ios-function-table.m"; sourceTree = "<group>"; };
                AFAAE39C207D6343007A515C /* Maze3D.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Maze3D.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AFAAE39E207D6420007A515C /* maze3d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = maze3d.c; path = hacks/glx/maze3d.c; sourceTree = "<group>"; };
                AFD5730C099702C800BA26F7 /* julia.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = julia.c; path = hacks/julia.c; sourceTree = "<group>"; };
                AFD5736D0997411200BA26F7 /* Strange.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Strange.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AFD57371099741A200BA26F7 /* strange.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = strange.c; path = hacks/strange.c; sourceTree = "<group>"; };
+               AFD77E7020C23F8600A3638D /* FilmLeader.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FilmLeader.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFD77E7220C2417F00A3638D /* filmleader.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = filmleader.c; path = hacks/filmleader.c; sourceTree = "<group>"; };
+               AFD77E7620C2419600A3638D /* filmleader.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = filmleader.xml; sourceTree = "<group>"; };
                AFD9D5BD201E686A0070E99D /* ships.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ships.c; path = hacks/glx/ships.c; sourceTree = "<group>"; };
                AFDA11211934424D003D397F /* aligned_malloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = aligned_malloc.c; path = utils/aligned_malloc.c; sourceTree = "<group>"; };
                AFDA11221934424D003D397F /* aligned_malloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = aligned_malloc.h; path = utils/aligned_malloc.h; sourceTree = "<group>"; };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF5ECEB32116B1A400069433 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF5ECEB42116B1A400069433 /* libjwxyz.a in Frameworks */,
+                               AF5ECEB52116B1A400069433 /* ScreenSaver.framework in Frameworks */,
+                               AF5ECEB62116B1A400069433 /* QuartzCore.framework in Frameworks */,
+                               AF5ECEB72116B1A400069433 /* Cocoa.framework in Frameworks */,
+                               AF5ECEB82116B1A400069433 /* Carbon.framework in Frameworks */,
+                               AF5ECEB92116B1A400069433 /* OpenGL.framework in Frameworks */,
+                               AF5ECEBA2116B1A400069433 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF633C091EE0BA6F00AB33BD /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFA6AAF820999950006D2685 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFA6AAF920999950006D2685 /* libjwxyz.a in Frameworks */,
+                               AFA6AAFA20999950006D2685 /* ScreenSaver.framework in Frameworks */,
+                               AFA6AAFB20999950006D2685 /* QuartzCore.framework in Frameworks */,
+                               AFA6AAFC20999950006D2685 /* Cocoa.framework in Frameworks */,
+                               AFA6AAFD20999950006D2685 /* Carbon.framework in Frameworks */,
+                               AFA6AAFE20999950006D2685 /* OpenGL.framework in Frameworks */,
+                               AFA6AAFF20999950006D2685 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFAAE38F207D6343007A515C /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFD77E6320C23F8600A3638D /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFD77E6420C23F8600A3638D /* libjwxyz.a in Frameworks */,
+                               AFD77E6520C23F8600A3638D /* ScreenSaver.framework in Frameworks */,
+                               AFD77E6620C23F8600A3638D /* QuartzCore.framework in Frameworks */,
+                               AFD77E6720C23F8600A3638D /* Cocoa.framework in Frameworks */,
+                               AFD77E6820C23F8600A3638D /* Carbon.framework in Frameworks */,
+                               AFD77E6920C23F8600A3638D /* OpenGL.framework in Frameworks */,
+                               AFD77E6A20C23F8600A3638D /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFDA6596178A52B70070D24B /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                                AF3EC98D2035154C00180A35 /* Peepers.saver */,
                                AFC5CFEB2044AA23004CEB5E /* Crumbler.saver */,
                                AFAAE39C207D6343007A515C /* Maze3D.saver */,
+                               AFA6AB0520999950006D2685 /* GlitchPEG.saver */,
+                               AFD77E7020C23F8600A3638D /* FilmLeader.saver */,
+                               AF5ECEC02116B1A400069433 /* VFeedback.saver */,
                        );
                        name = Products;
                        path = ..;
                                AF9D490709B536F7006E59CF /* distort.c */,
                                AF477605099DA097001F091E /* epicycle.c */,
                                AF975A83099C6B4900B05160 /* eruption.c */,
+                               AFD77E7220C2417F00A3638D /* filmleader.c */,
                                AF975AEE099C6F1700B05160 /* fireworkx.c */,
                                AF477496099D8A53001F091E /* flame.c */,
                                AF4777A4099DBB11001F091E /* fluidballs.c */,
                                AFBF893D0E41D930006A2D66 /* fps.h */,
                                AFBF89B10E424036006A2D66 /* fpsI.h */,
                                AF4773B4099D6778001F091E /* fuzzyflakes.c */,
+                               AFA6AB0E20999A7B006D2685 /* glitchpeg.c */,
                                AF64268E09A19542000F4CD4 /* goop.c */,
                                AF480C21098E28EF00FB32B8 /* greynetic.c */,
                                AF477266099D5768001F091E /* halftone.c */,
                                AF476FF0099D1713001F091E /* truchet.c */,
                                AF9D497F09B541E5006E59CF /* twang.c */,
                                AF477704099DAF3F001F091E /* vermiculate.c */,
+                               AF5ECEC22116B2CC00069433 /* vfeedback.c */,
                                AF477192099D4864001F091E /* wander.c */,
                                AFA33C0A0B058E6B002B0E7D /* webcollage */,
                                AFA33BAE0B0585F7002B0E7D /* webcollage-cocoa.m */,
                                AF241F81107C38DF00046A84 /* dropshadow.c */,
                                AF241F82107C38DF00046A84 /* dropshadow.h */,
                                AFEC23E41CB6EBC400DE138F /* dymaxionmap.c */,
+                               AF4C300D208569A900BE1DEF /* dymaxionmap-coords.c */,
                                AF7778C109B65C6A00EA3033 /* e_textures.h */,
                                AFA55E2509935F2B00F3E977 /* endgame.c */,
                                AFACE88A1CC83578008B24CD /* energystream.c */,
                                AFC258A00988A468000655EE /* extrusion.xml */,
                                AFC258A10988A468000655EE /* fadeplot.xml */,
                                AFC258A20988A468000655EE /* fiberlamp.xml */,
+                               AFD77E7620C2419600A3638D /* filmleader.xml */,
                                AFC258A40988A468000655EE /* fireworkx.xml */,
                                AFC258A50988A468000655EE /* flag.xml */,
                                AFC258A60988A468000655EE /* flame.xml */,
                                AFC258B50988A468000655EE /* gleidescope.xml */,
                                AFC258B60988A468000655EE /* glforestfire.xml */,
                                AFC258B70988A468000655EE /* glhanoi.xml */,
+                               AFA6AB0C20999A60006D2685 /* glitchpeg.xml */,
                                AFC258B80988A468000655EE /* glknots.xml */,
                                AFC258B90988A468000655EE /* glmatrix.xml */,
                                AFC258BA0988A468000655EE /* glplanet.xml */,
                                AFC2592A0988A469000655EE /* vines.xml */,
                                AF46E9E61CBBA3F900240FBC /* unicrud.xml */,
                                AFDA65A3178A541A0070D24B /* unknownpleasures.xml */,
+                               AF5ECEC52116B2FE00069433 /* vfeedback.xml */,
                                AF633C181EE0BC4900AB33BD /* vigilance.xml */,
                                AF0DCA610C4CBB8E00D76972 /* voronoi.xml */,
                                AFC2592B0988A469000655EE /* wander.xml */,
                        productReference = AF5C9B0D1A0CCE6E00B0147A /* Cityflow.saver */;
                        productType = "com.apple.product-type.bundle";
                };
+               AF5ECEA92116B1A400069433 /* VFeedback */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF5ECEBD2116B1A400069433 /* Build configuration list for PBXNativeTarget "VFeedback" */;
+                       buildPhases = (
+                               AF5ECEAC2116B1A400069433 /* Resources */,
+                               AF5ECEAF2116B1A400069433 /* Sources */,
+                               AF5ECEB32116B1A400069433 /* Frameworks */,
+                               AF5ECEBB2116B1A400069433 /* Rez */,
+                               AF5ECEBC2116B1A400069433 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF5ECEAA2116B1A400069433 /* PBXTargetDependency */,
+                       );
+                       name = VFeedback;
+                       productName = XAnalogTV;
+                       productReference = AF5ECEC02116B1A400069433 /* VFeedback.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AF633C011EE0BA6F00AB33BD /* Vigilance */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AF633C131EE0BA6F00AB33BD /* Build configuration list for PBXNativeTarget "Vigilance" */;
                        productReference = AFA563B6099398BB00F3E977 /* Juggler3D.saver */;
                        productType = "com.apple.product-type.bundle";
                };
+               AFA6AAF020999950006D2685 /* GlitchPEG */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFA6AB0220999950006D2685 /* Build configuration list for PBXNativeTarget "GlitchPEG" */;
+                       buildPhases = (
+                               AFA6AAF320999950006D2685 /* Resources */,
+                               AFA6AAF520999950006D2685 /* Sources */,
+                               AFA6AAF820999950006D2685 /* Frameworks */,
+                               AFA6AB0020999950006D2685 /* Rez */,
+                               AFA6AB0120999950006D2685 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFA6AAF120999950006D2685 /* PBXTargetDependency */,
+                       );
+                       name = GlitchPEG;
+                       productName = Attraction;
+                       productReference = AFA6AB0520999950006D2685 /* GlitchPEG.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AFAAE387207D6343007A515C /* Maze3D */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AFAAE399207D6343007A515C /* Build configuration list for PBXNativeTarget "Maze3D" */;
                        productReference = AFD5736D0997411200BA26F7 /* Strange.saver */;
                        productType = "com.apple.product-type.bundle";
                };
+               AFD77E5B20C23F8600A3638D /* FilmLeader */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFD77E6D20C23F8600A3638D /* Build configuration list for PBXNativeTarget "FilmLeader" */;
+                       buildPhases = (
+                               AFD77E5E20C23F8600A3638D /* Resources */,
+                               AFD77E6020C23F8600A3638D /* Sources */,
+                               AFD77E6320C23F8600A3638D /* Frameworks */,
+                               AFD77E6B20C23F8600A3638D /* Rez */,
+                               AFD77E6C20C23F8600A3638D /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFD77E5C20C23F8600A3638D /* PBXTargetDependency */,
+                       );
+                       name = FilmLeader;
+                       productName = Attraction;
+                       productReference = AFD77E7020C23F8600A3638D /* FilmLeader.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AFDA658E178A52B70070D24B /* Unknown Pleasures */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AFDA659E178A52B70070D24B /* Build configuration list for PBXNativeTarget "Unknown Pleasures" */;
                29B97313FDCFA39411CA2CEA /* Project object */ = {
                        isa = PBXProject;
                        attributes = {
-                               LastUpgradeCheck = 0930;
+                               LastUpgradeCheck = 0940;
                                TargetAttributes = {
                                        AF08398F09930B6B00277BE9 = {
                                                DevelopmentTeam = 4627ATJELP;
                                        AF5C9AF91A0CCE6E00B0147A = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
+                                       AF5ECEA92116B1A400069433 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
                                        AF633C011EE0BA6F00AB33BD = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
                                        AFA563A4099398BB00F3E977 = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
+                                       AFA6AAF020999950006D2685 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
                                        AFAAE387207D6343007A515C = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
                                        AFD5735D0997411200BA26F7 = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
+                                       AFD77E5B20C23F8600A3638D = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
                                        AFDA658E178A52B70070D24B = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
                                AF9D48F409B535DA006E59CF /* Distort */,
                                AF4775F2099DA030001F091E /* Epicycle */,
                                AF975A6C099C6AB200B05160 /* Eruption */,
+                               AFD77E5B20C23F8600A3638D /* FilmLeader */,
                                AF975AD7099C6EB100B05160 /* Fireworkx */,
                                AF477483099D89E4001F091E /* Flame */,
                                AF477790099DBA90001F091E /* FluidBalls */,
                                AF77787F09B6563500EA3033 /* FontGlide */,
                                AF47739A099D6648001F091E /* FuzzyFlakes */,
+                               AFA6AAF020999950006D2685 /* GlitchPEG */,
                                AF64267B09A194B0000F4CD4 /* Goop */,
                                AF975C3D099C8DCF00B05160 /* Greynetic */,
                                AF477253099D5717001F091E /* Halftone */,
                                AF476FDA099D1686001F091E /* Truchet */,
                                AF9D496C09B5411D006E59CF /* Twang */,
                                AF4776F1099DAE7A001F091E /* Vermiculate */,
+                               AF5ECEA92116B1A400069433 /* VFeedback */,
                                AF47717F099D4803001F091E /* Wander */,
                                AFA3392E0B058505002B0E7D /* WebCollage */,
                                AFA33C020B058E17002B0E7D /* webcollage-perl */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF5ECEAC2116B1A400069433 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF5ECEC62116B2FE00069433 /* vfeedback.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF633C041EE0BA6F00AB33BD /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                                AF21078A1FD23D2800B61EA9 /* esper.xml in Resources */,
                                AF918AEE158FC53D002B5D1E /* euler2d.xml in Resources */,
                                AF918AF0158FC53D002B5D1E /* fadeplot.xml in Resources */,
+                               AFD77E7820C2419600A3638D /* filmleader.xml in Resources */,
                                AF918AF1158FC53D002B5D1E /* fiberlamp.xml in Resources */,
                                AF918AF2158FC53D002B5D1E /* fireworkx.xml in Resources */,
                                AF918AF4158FC53D002B5D1E /* flame.xml in Resources */,
                                AF46E9EA1CBBA42F00240FBC /* unicrud.xml in Resources */,
                                AFDA65A6178A541A0070D24B /* unknownpleasures.xml in Resources */,
                                AF918B80158FC53E002B5D1E /* vermiculate.xml in Resources */,
+                               AF5ECEC72116B2FE00069433 /* vfeedback.xml in Resources */,
                                AF633C1A1EE0BC5500AB33BD /* vigilance.xml in Resources */,
                                AF918B83158FC53E002B5D1E /* voronoi.xml in Resources */,
                                AF918B84158FC53E002B5D1E /* wander.xml in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFA6AAF320999950006D2685 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF95C30420999B3E001924BE /* xscreensaver-getimage-file in Resources */,
+                               AFA6AB0D20999A60006D2685 /* glitchpeg.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFAAE38A207D6343007A515C /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFD77E5E20C23F8600A3638D /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFD77E7720C2419600A3638D /* filmleader.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFDA6591178A52B70070D24B /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF5ECEBB2116B1A400069433 /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF633C111EE0BA6F00AB33BD /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFA6AB0020999950006D2685 /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFAAE397207D6343007A515C /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFD77E6B20C23F8600A3638D /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFDA659C178A52B70070D24B /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AF5ECEBC2116B1A400069433 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
+                       showEnvVarsInLog = 0;
+               };
                AF633C121EE0BA6F00AB33BD /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AFA6AB0120999950006D2685 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
+                       showEnvVarsInLog = 0;
+               };
                AFAAE398207D6343007A515C /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AFD77E6C20C23F8600A3638D /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
+                       showEnvVarsInLog = 0;
+               };
                AFDA659D178A52B70070D24B /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                                AF4808C6098C3BDF00FB32B8 /* erase.c in Sources */,
                                AF4808C7098C3BE600FB32B8 /* hsv.c in Sources */,
                                AFBF893E0E41D930006A2D66 /* fps.c in Sources */,
+                               AFD77E7320C2418000A3638D /* filmleader.c in Sources */,
                                AFBF89AF0E423FC3006A2D66 /* fps-gl.c in Sources */,
                                5501D1961DBDCC3D00624BE9 /* xshm.c in Sources */,
                                AF4808C8098C3BE800FB32B8 /* InvertedSlider.m in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF5ECEAF2116B1A400069433 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF5ECEB02116B1A400069433 /* XScreenSaverSubclass.m in Sources */,
+                               AF5ECEC32116B2CC00069433 /* vfeedback.c in Sources */,
+                               AF5ECEB12116B1A400069433 /* analogtv.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF633C061EE0BA6F00AB33BD /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                                AF918A06158FC38A002B5D1E /* euler2d.c in Sources */,
                                AF918A07158FC38A002B5D1E /* fadeplot.c in Sources */,
                                AF918A08158FC38A002B5D1E /* fiberlamp.c in Sources */,
+                               AFD77E7520C2418000A3638D /* filmleader.c in Sources */,
                                AF9189B5158FC311002B5D1E /* fireworkx.c in Sources */,
                                AF9189B6158FC334002B5D1E /* flame.c in Sources */,
                                AF918A0A158FC38A002B5D1E /* flow.c in Sources */,
                                AF918A19158FC38A002B5D1E /* pacman_ai.c in Sources */,
                                AF918A1A158FC38A002B5D1E /* pacman_level.c in Sources */,
                                AF9189D4158FC334002B5D1E /* pedal.c in Sources */,
+                               AF4C300F208569AA00BE1DEF /* dymaxionmap-coords.c in Sources */,
                                AF9189D5158FC334002B5D1E /* penetrate.c in Sources */,
                                AF9189D6158FC334002B5D1E /* petri.c in Sources */,
                                AF9189D7158FC334002B5D1E /* phosphor.c in Sources */,
                                AF9189EF158FC35D002B5D1E /* truchet.c in Sources */,
                                AF9189F0158FC35D002B5D1E /* twang.c in Sources */,
                                AF9189F1158FC35D002B5D1E /* vermiculate.c in Sources */,
+                               AF5ECEC42116B2CC00069433 /* vfeedback.c in Sources */,
                                AF9189F2158FC35D002B5D1E /* wander.c in Sources */,
                                AF9189F3158FC35E002B5D1E /* whirlwindwarp.c in Sources */,
                                AF9189F5158FC35E002B5D1E /* wormhole.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFA6AAF520999950006D2685 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFA6AAF720999950006D2685 /* XScreenSaverSubclass.m in Sources */,
+                               AFA6AB0F20999A7B006D2685 /* glitchpeg.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFAAE38C207D6343007A515C /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFD77E6020C23F8600A3638D /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF3FAD8F20C242DA00680000 /* analogtv.c in Sources */,
+                               AFD77E7420C2418000A3638D /* filmleader.c in Sources */,
+                               AFD77E6220C23F8600A3638D /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFDA6593178A52B70070D24B /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                                AFEC23E61CB6EC0400DE138F /* dymaxionmap.c in Sources */,
                                AFEC23D41CB6EAE100DE138F /* XScreenSaverSubclass.m in Sources */,
+                               AF4C300E208569AA00BE1DEF /* dymaxionmap-coords.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        target = AF5C9AF91A0CCE6E00B0147A /* Cityflow */;
                        targetProxy = AF5C9B151A0CCF8000B0147A /* PBXContainerItemProxy */;
                };
+               AF5ECEAA2116B1A400069433 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF5ECEAB2116B1A400069433 /* PBXContainerItemProxy */;
+               };
+               AF5ECEC92116B31F00069433 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF5ECEA92116B1A400069433 /* VFeedback */;
+                       targetProxy = AF5ECEC82116B31F00069433 /* PBXContainerItemProxy */;
+               };
                AF633C021EE0BA6F00AB33BD /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        targetProxy = AFA563A6099398BB00F3E977 /* PBXContainerItemProxy */;
                };
+               AFA6AAF120999950006D2685 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFA6AAF220999950006D2685 /* PBXContainerItemProxy */;
+               };
+               AFA6AB1120999A9A006D2685 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFA6AAF020999950006D2685 /* GlitchPEG */;
+                       targetProxy = AFA6AB1020999A9A006D2685 /* PBXContainerItemProxy */;
+               };
                AFAAE388207D6343007A515C /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        targetProxy = AFD5735F0997411200BA26F7 /* PBXContainerItemProxy */;
                };
+               AFD77E5C20C23F8600A3638D /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFD77E5D20C23F8600A3638D /* PBXContainerItemProxy */;
+               };
+               AFD77E7A20C241BE00A3638D /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFD77E5B20C23F8600A3638D /* FilmLeader */;
+                       targetProxy = AFD77E7920C241BE00A3638D /* PBXContainerItemProxy */;
+               };
                AFDA658F178A52B70070D24B /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        };
                        name = Release;
                };
+               AF5ECEBE2116B1A400069433 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF5ECEBF2116B1A400069433 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
                AF633C141EE0BA6F00AB33BD /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        };
                        name = Release;
                };
+               AFA6AB0320999950006D2685 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AFA6AB0420999950006D2685 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
                AFAAE39A207D6343007A515C /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        };
                        name = Release;
                };
+               AFD77E6E20C23F8600A3638D /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AFD77E6F20C23F8600A3638D /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
                AFDA659F178A52B70070D24B /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AF5ECEBD2116B1A400069433 /* Build configuration list for PBXNativeTarget "VFeedback" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF5ECEBE2116B1A400069433 /* Debug */,
+                               AF5ECEBF2116B1A400069433 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AF633C131EE0BA6F00AB33BD /* Build configuration list for PBXNativeTarget "Vigilance" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AFA6AB0220999950006D2685 /* Build configuration list for PBXNativeTarget "GlitchPEG" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFA6AB0320999950006D2685 /* Debug */,
+                               AFA6AB0420999950006D2685 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AFAAE399207D6343007A515C /* Build configuration list for PBXNativeTarget "Maze3D" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AFD77E6D20C23F8600A3638D /* Build configuration list for PBXNativeTarget "FilmLeader" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFD77E6E20C23F8600A3638D /* Debug */,
+                               AFD77E6F20C23F8600A3638D /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AFDA659E178A52B70070D24B /* Build configuration list for PBXNativeTarget "Unknown Pleasures" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
diff --git a/README b/README
index 9d6e4272ab9776477e91b2d62cf1e3908e0251c4..af3f94903cc6a1e3bc3ac89cfeec16381cfbefce 100644 (file)
--- a/README
+++ b/README
@@ -46,6 +46,18 @@ XScreenSaver has an extensive manual -- please read it!
 
 ===============================================================================
 
+5.40   * New hacks, 'filmleader', 'vfeedback'.
+       * New hack, 'glitchpeg' (X11 and macOS only).
+       * GLPlanet blends between day and night maps at the dusk terminator.
+       * DymaxionMap can display arbitrary map images, and animate sunlight
+          across the flattened globe.
+       * Tessellimage can draw either Delaunay or Voronoi tilings.
+       * XAnalogTV includes test cards.
+       * Android: These hacks work now: 'blitspin', 'bumps', 'cityflow',
+         'endgame', 'esper', 'flipscreen3d', 'gleidescope', 'glslideshow',
+         'jigglypuff', 'queens', 'tessellimage', 'xanalogtv', 'xmatrix',
+         'zoom'.
+
 5.39   * New hacks, 'razzledazzle', 'peepers', 'crumbler' and `maze3d'.
        * More heuristics for using RSS feeds as image sources.
        * Android: Image loading works.
index bd5d15dfc39aee4384fe89c4eb278af89a813c69..f0d5da0185bbcdeafdac47eb01c97e113dd0eefd 100644 (file)
@@ -49,6 +49,7 @@ export ANDROID_HACKS=         \
        binaryring              \
        blaster                 \
        blinkbox                \
+       blitspin                \
        blocktube               \
        boing                   \
        bouboule                \
@@ -57,10 +58,12 @@ export ANDROID_HACKS=               \
        boxfit                  \
        braid                   \
        bsod                    \
+       bumps                   \
        cage                    \
        ccurve                  \
        celtic                  \
        circuit                 \
+       cityflow                \
        cloudlife               \
        companioncube           \
        compass                 \
@@ -87,16 +90,20 @@ export ANDROID_HACKS=               \
        dnalogo                 \
        drift                   \
        dymaxionmap             \
+       endgame                 \
        energystream            \
        engine                  \
        epicycle                \
        eruption                \
+       esper                   \
        euler2d                 \
        fadeplot                \
        fiberlamp               \
+       filmleader              \
        fireworkx               \
        flame                   \
        flipflop                \
+       flipscreen3d            \
        flow                    \
        fluidballs              \
        flyingtoasters          \
@@ -108,11 +115,13 @@ export ANDROID_HACKS=             \
        gflux                   \
        glblur                  \
        glcells                 \
+       gleidescope             \
        glhanoi                 \
        glknots                 \
        glmatrix                \
        glplanet                \
        glschool                \
+       glslideshow             \
        glsnake                 \
        gltext                  \
        goop                    \
@@ -131,6 +140,7 @@ export ANDROID_HACKS=               \
        interaggregate          \
        interference            \
        intermomentary          \
+       jigglypuff              \
        jigsaw                  \
        julia                   \
        kaleidescope            \
@@ -172,6 +182,7 @@ export ANDROID_HACKS=               \
        pulsar                  \
        pyro                    \
        quasicrystal            \
+       queens                  \
        raverhoop               \
        razzledazzle            \
        rd-bomb                 \
@@ -192,6 +203,7 @@ export ANDROID_HACKS=               \
        spheremonics            \
        splitflap               \
        splodesic               \
+       spotlight               \
        squiral                 \
        stairs                  \
        stonerview              \
@@ -201,6 +213,7 @@ export ANDROID_HACKS=               \
        surfaces                \
        swirl                   \
        tangram                 \
+       tessellimage            \
        thornbird               \
        timetunnel              \
        topblock                \
@@ -210,17 +223,21 @@ export ANDROID_HACKS=             \
        twang                   \
        unknownpleasures        \
        vermiculate             \
+       vfeedback               \
        vigilance               \
        voronoi                 \
        wander                  \
        whirlwindwarp           \
        winduprobot             \
        wormhole                \
+       xanalogtv               \
        xflame                  \
        xjack                   \
        xlyap                   \
+       xmatrix                 \
        xrayswarm               \
        xspirograph             \
+       zoom                    \
 
 
 # These don't work well enough to turn on by default:
@@ -228,19 +245,10 @@ export ANDROID_HACKS=             \
 ANDROID_TODO=                  \
        antinspect              \
        barcode                 \
-       blitspin                \
-       bumps                   \
        carousel                \
-       cityflow                \
-       endgame                 \
-       esper                   \
-       flipscreen3d            \
        fliptext                \
        fontglide               \
-       gleidescope             \
-       glslideshow             \
        halftone                \
-       jigglypuff              \
        juggler3d               \
        molecule                \
        pedal                   \
@@ -248,17 +256,11 @@ ANDROID_TODO=                     \
        photopile               \
        polyominoes             \
        qix                     \
-       queens                  \
        speedmine               \
-       spotlight               \
        starfish                \
        starwars                \
-       tessellimage            \
        testx11                 \
        unicrud                 \
-       xanalogtv               \
-       xmatrix                 \
-       zoom                    \
 
 
 # Download and resize images from jwz.org.
@@ -367,7 +369,7 @@ $(KEYSTORE):
        keytool -genkey -v -keystore $@ \
        -alias xscreensaver -keyalg RSA -keysize 2048 -validity 10000
 
-APK_DIR       = xscreensaver/build/outputs/apk/
+APK_DIR       = xscreensaver/build/outputs/apk/release/
 APK_UNSIGNED  = $(APK_DIR)xscreensaver-release-unsigned.apk
 APK_UNALIGNED = $(APK_DIR)xscreensaver-release-unaligned.apk
 APK_SIGNED    = $(APK_DIR)xscreensaver-release.apk
index c5b00c18401b255a8111a372b1a964e1a99615ff..2843296548b6cae41058a01b737c578e0f4ca360 100644 (file)
@@ -151,58 +151,39 @@ TODO list, and known bugs:
     box does not.
 
   antinspect   renders incorrectly
-  antmaze      crashes emulator, sometimes
-  antspotlight crashes emulator, sometimes
   apple2       text, images into pixmaps doesn't work
-  atlantis     crashes emulator, sometimes
   barcode      pixmaps
-  blitspin     images
   bsod         pixmaps, XCopyArea problems
-  bumps                images
-  carousel     images
+  carousel     images are corrupted
   cityflow     shading is wrong
   endgame      insanely slow
   engine       text
-  esper                images, text
-  flipflop     images
-  flipscreen3d images
+  esper                images don't load, no text
   fliptext     text
   fontglide    text
-  gflux                images
   glblur       grayscale instead of color
-  gleidescope  images
-  glslideshow  images
   halftone     XFillArc crash
-  halo         some extra triangles show up
   jigglypuff   incredibly slow
-  jigsaw       images
   juggler3d    blank
   maze         lines are not the same thickness (aliased?)
-  mirrorblob   images
   molecule     blank
-  mountain     polygons
-  munch                XOR
-  noseguy      text; images flicker to black and white
-  pacman       launches really slowly
+  noseguy      text; images
+  pacman       images; launches really slowly
   pedal                polygons
   phosphor     text; pixmaps
-  photopile    images; pixmaps
+  photopile    text; images don't display
   polyhedra    text
   polyominoes  pixmaps
   qix          polygons
-  queens       blank
-  slip         images
+  queens       insanely slow
   sonar                does icmp work?
   speedmine    polygons
   splitflap    super slow
-  spotlight    pixmaps
+  spotlight    blank
   starfish     polygons
   starwars     text
-  tessellimage pixmaps
-  twang                background should be black
   unicrud      pixmaps
   winduprobot  dome is not transparent
   xanalogtv    pixmaps
   xflame       draws only upper left corner
-  xmatrix      super slow, glitch on first screen
-  zoom         pixmaps
+  xmatrix      pretty slow
index 613cb90828eeabee648c2141d5abcf46302b5f05..648cc3210ab29a00aa2a70cd6a0fc2dec44d31ed 100644 (file)
@@ -2,17 +2,23 @@
 buildscript {
     repositories {
         jcenter()
+        google()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:2.1.0'
+        classpath 'com.android.tools.build:gradle:3.1.2'
     }
 
-    // This allows versions of Gradle past 2.9 to be used with the Gradle
-    // Android plugin.
-    // https://discuss.gradle.org/t/gradle-thinks-2-10-is-less-than-2-2-when-resolving-plugins/13434/2
-//    System.properties['com.android.build.gradle.overrideVersionCheck'] = 'true';
 }
 
+allprojects {
+  repositories {
+    maven { url 'https://maven.google.com' }
+    jcenter()
+    google()
+  }
+}
+
+
 task clean(type: Delete) {
     delete('./build')
 }
index 729f41b70bf2b7a765f1f90c701c6ef5cb1c9fab..0ac000f59d2084939cd0192e7fe589d4758013e7 100644 (file)
@@ -1,6 +1,6 @@
-#Sun Jun 12 14:20:28 PDT 2016
+#Sat Feb 10 21:20:31 PST 2018
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-bin.zip
index 9e196d6986c074210333084a1427e76a05975fb7..bc8f00c653bd31d53e3eff5e684e8fba834820d9 100644 (file)
Binary files a/android/xscreensaver/.idea/caches/build_file_checksums.ser and b/android/xscreensaver/.idea/caches/build_file_checksums.ser differ
diff --git a/android/xscreensaver/.idea/libraries/Gradle__android_arch_core_common_1_1_0_jar.xml b/android/xscreensaver/.idea/libraries/Gradle__android_arch_core_common_1_1_0_jar.xml
new file mode 100644 (file)
index 0000000..9869803
--- /dev/null
@@ -0,0 +1,11 @@
+<component name="libraryTable">
+  <library name="Gradle: android.arch.core:common:1.1.0@jar">
+    <CLASSES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.core/common/1.1.0/8007981f7d7540d89cd18471b8e5dcd2b4f99167/common-1.1.0.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.core/common/1.1.0/f211e8f994b67f7ae2a1bc06e4f7b974ec72ee50/common-1.1.0-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__android_arch_core_runtime_1_1_0.xml b/android/xscreensaver/.idea/libraries/Gradle__android_arch_core_runtime_1_1_0.xml
new file mode 100644 (file)
index 0000000..03529f7
--- /dev/null
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+  <library name="Gradle: android.arch.core:runtime-1.1.0">
+    <CLASSES>
+      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/runtime-1.1.0.aar/66eddde487cc032a22af511624a2dc1d/jars/classes.jar!/" />
+      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/runtime-1.1.0.aar/66eddde487cc032a22af511624a2dc1d/res" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.core/runtime/1.1.0/62944187d3ae3e7a4644b50da4e7b63c605a696/runtime-1.1.0-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_common_1_1_0_jar.xml b/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_common_1_1_0_jar.xml
new file mode 100644 (file)
index 0000000..29c0049
--- /dev/null
@@ -0,0 +1,11 @@
+<component name="libraryTable">
+  <library name="Gradle: android.arch.lifecycle:common:1.1.0@jar">
+    <CLASSES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.lifecycle/common/1.1.0/edf3f7bfb84a7521d0599efa3b0113a0ee90f85/common-1.1.0.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.lifecycle/common/1.1.0/72f6113534923e49e8c032107ca638b97775c61b/common-1.1.0-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_livedata_core_1_1_0.xml b/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_livedata_core_1_1_0.xml
new file mode 100644 (file)
index 0000000..c43180e
--- /dev/null
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+  <library name="Gradle: android.arch.lifecycle:livedata-core-1.1.0">
+    <CLASSES>
+      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/livedata-core-1.1.0.aar/01d9f7cf052a887e242d3ac9bccb130e/res" />
+      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/livedata-core-1.1.0.aar/01d9f7cf052a887e242d3ac9bccb130e/jars/classes.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.lifecycle/livedata-core/1.1.0/300f89e645a95de0bdc6d8833beeee6e3045df06/livedata-core-1.1.0-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_runtime_1_1_0.xml b/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_runtime_1_1_0.xml
new file mode 100644 (file)
index 0000000..6031fb9
--- /dev/null
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+  <library name="Gradle: android.arch.lifecycle:runtime-1.1.0">
+    <CLASSES>
+      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/runtime-1.1.0.aar/625fea47a711c4db819aa2d6df929100/jars/classes.jar!/" />
+      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/runtime-1.1.0.aar/625fea47a711c4db819aa2d6df929100/res" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.lifecycle/runtime/1.1.0/a4b0d6b8e8f51c8f95d5a0641f81ffc13ab406c7/runtime-1.1.0-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_viewmodel_1_1_0.xml b/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_viewmodel_1_1_0.xml
new file mode 100644 (file)
index 0000000..11a24fb
--- /dev/null
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+  <library name="Gradle: android.arch.lifecycle:viewmodel-1.1.0">
+    <CLASSES>
+      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/viewmodel-1.1.0.aar/0c933938d5403a08c5e3efe386ac2b02/res" />
+      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/viewmodel-1.1.0.aar/0c933938d5403a08c5e3efe386ac2b02/jars/classes.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.lifecycle/viewmodel/1.1.0/e4c0c5d65f92ccad0b0148ac2f01b540ac7a711e/viewmodel-1.1.0-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_annotations_27_1_1_jar.xml b/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_annotations_27_1_1_jar.xml
new file mode 100644 (file)
index 0000000..1517ad9
--- /dev/null
@@ -0,0 +1,11 @@
+<component name="libraryTable">
+  <library name="Gradle: com.android.support:support-annotations:27.1.1@jar">
+    <CLASSES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-annotations/27.1.1/39ded76b5e1ce1c5b2688e1d25cdc20ecee32007/support-annotations-27.1.1.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-annotations/27.1.1/46bebf5bd40146178cb33c7678f3782a09dea6e4/support-annotations-27.1.1-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_compat_27_1_1.xml b/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_compat_27_1_1.xml
new file mode 100644 (file)
index 0000000..fba52e8
--- /dev/null
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+  <library name="Gradle: com.android.support:support-compat-27.1.1">
+    <CLASSES>
+      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-compat-27.1.1.aar/64b85698f5c1a639182eb49d0126a2d0/res" />
+      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-compat-27.1.1.aar/64b85698f5c1a639182eb49d0126a2d0/jars/classes.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-compat/27.1.1/fe233277b6eae25ce5b2afab6daf55d73c86f0b9/support-compat-27.1.1-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_core_ui_27_1_1.xml b/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_core_ui_27_1_1.xml
new file mode 100644 (file)
index 0000000..3ccece0
--- /dev/null
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+  <library name="Gradle: com.android.support:support-core-ui-27.1.1">
+    <CLASSES>
+      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-core-ui-27.1.1.aar/b432dca2f3c4bd72e4ef10511d8d2ba5/res" />
+      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-core-ui-27.1.1.aar/b432dca2f3c4bd72e4ef10511d8d2ba5/jars/classes.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-core-ui/27.1.1/266c369a3227be5afec33e11c964472269ff2a7c/support-core-ui-27.1.1-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_core_utils_27_1_1.xml b/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_core_utils_27_1_1.xml
new file mode 100644 (file)
index 0000000..69d23f2
--- /dev/null
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+  <library name="Gradle: com.android.support:support-core-utils-27.1.1">
+    <CLASSES>
+      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-core-utils-27.1.1.aar/0980a98a9ec854145d292239910611d4/jars/classes.jar!/" />
+      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-core-utils-27.1.1.aar/0980a98a9ec854145d292239910611d4/res" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-core-utils/27.1.1/8fb37fd2f8dbc23482865700d2c340ae030ea561/support-core-utils-27.1.1-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_fragment_27_1_1.xml b/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_fragment_27_1_1.xml
new file mode 100644 (file)
index 0000000..8eb356f
--- /dev/null
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+  <library name="Gradle: com.android.support:support-fragment-27.1.1">
+    <CLASSES>
+      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-fragment-27.1.1.aar/c39b8c3b0b8a6fd39d4cf14a5ed4d9a8/jars/classes.jar!/" />
+      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-fragment-27.1.1.aar/c39b8c3b0b8a6fd39d4cf14a5ed4d9a8/res" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-fragment/27.1.1/94732bda44fba11302c58e459b7c1f47e7521bf9/support-fragment-27.1.1-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_media_compat_27_1_1.xml b/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_media_compat_27_1_1.xml
new file mode 100644 (file)
index 0000000..c577eba
--- /dev/null
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+  <library name="Gradle: com.android.support:support-media-compat-27.1.1">
+    <CLASSES>
+      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-media-compat-27.1.1.aar/68a94910a2befb2c6cb37bd04aa2aa39/res" />
+      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-media-compat-27.1.1.aar/68a94910a2befb2c6cb37bd04aa2aa39/jars/classes.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-media-compat/27.1.1/3ab3f968d7cd675d2f97e67a3e9fc0ac63618f46/support-media-compat-27.1.1-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_v4_27_1_1.xml b/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_v4_27_1_1.xml
new file mode 100644 (file)
index 0000000..10d3108
--- /dev/null
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+  <library name="Gradle: com.android.support:support-v4-27.1.1">
+    <CLASSES>
+      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-v4-27.1.1.aar/4063a17c1f54cf7b4dd719a35d318e61/res" />
+      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-v4-27.1.1.aar/4063a17c1f54cf7b4dd719a35d318e61/jars/classes.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES>
+      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-v4/27.1.1/5b8f86fea035328fc9e8c660773037a3401ce25f/support-v4-27.1.1-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>
\ No newline at end of file
index 37a750962da6f2b31810e85c8acae1081de7f58c..c0f68eddd7c4423a9fa05d6a53e9d1eb7e9c8c14 100644 (file)
@@ -1,6 +1,31 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+  <component name="NullableNotNullManager">
+    <option name="myDefaultNullable" value="android.support.annotation.Nullable" />
+    <option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
+    <option name="myNullables">
+      <value>
+        <list size="5">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
+          <item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
+          <item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
+          <item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
+        </list>
+      </value>
+    </option>
+    <option name="myNotNulls">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
+        </list>
+      </value>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/build/classes" />
   </component>
   <component name="ProjectType">
index d70761229b3091213a9384ff001457e65d7d8ed3..1dedd643543eb1ca76b34fa57ecd27eecf31f114 100644 (file)
   <component name="FavoritesManager">
     <favorites_list name="xscreensaver" />
   </component>
+  <component name="FileEditorManager">
+    <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
+      <file leaf-file-name="gradle-wrapper.properties" pinned="false" current-in-tab="true">
+        <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="90">
+              <caret line="6" column="0" lean-forward="false" selection-start-line="6" selection-start-column="0" selection-end-line="6" selection-end-column="0" />
+              <folding />
+            </state>
+          </provider>
+        </entry>
+      </file>
+    </leaf>
+  </component>
   <component name="GradleLocalSettings">
     <option name="myGradleHomes">
       <map>
-        <entry key="$PROJECT_DIR$" value="$USER_HOME$/.gradle/wrapper/dists/gradle-2.14.1-bin/2r579t5wehc7ew5kc8vfqezww/gradle-2.14.1" />
+        <entry key="$PROJECT_DIR$" value="$USER_HOME$/.gradle/wrapper/dists/gradle-4.8-bin/divx0s2uj4thofgytb7gf9fsi/gradle-4.8" />
       </map>
     </option>
     <option name="myGradleVersions">
       <map>
-        <entry key="$PROJECT_DIR$" value="2.14.1" />
+        <entry key="$PROJECT_DIR$" value="4.8" />
       </map>
     </option>
     <option name="availableProjects">
           </key>
           <value>
             <list>
-              <ExternalProjectPojo>
-                <option name="name" value=":xscreensaver" />
-                <option name="path" value="$PROJECT_DIR$" />
-              </ExternalProjectPojo>
               <ExternalProjectPojo>
                 <option name="name" value="android" />
                 <option name="path" value="$PROJECT_DIR$/.." />
               </ExternalProjectPojo>
+              <ExternalProjectPojo>
+                <option name="name" value=":xscreensaver" />
+                <option name="path" value="$PROJECT_DIR$" />
+              </ExternalProjectPojo>
             </list>
           </value>
         </entry>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="dependencyInsight" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the dependent components of components in root project 'android'. [incubating]" />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="dependentComponents" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="distClean" />
                 <option name="name" value="help" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
-                <option name="description" value="Initializes a new Gradle build. [incubating]" />
+                <option name="description" value="Initializes a new Gradle build." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="init" />
               </ExternalTaskPojo>
                 <option name="name" value="tasks" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
-                <option name="description" value="Generates Gradle wrapper files. [incubating]" />
+                <option name="description" value="Generates Gradle wrapper files." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="wrapper" />
               </ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="buildNeeded" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="bundleAppClassesDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="bundleAppClassesDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="bundleAppClassesDebugUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="bundleAppClassesRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="bundleAppClassesReleaseUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="bundleDebugAndroidTestResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="bundleDebugResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="bundleReleaseResources" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Runs all checks." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="checkReleaseManifest" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Deletes the build cache directory." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="cleanBuildCache" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="compileDebugAidl" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="connectedDebugAndroidTest" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="consumeConfigAttr" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="createDebugCompatibleScreenManifests" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="createReleaseCompatibleScreenManifests" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Installs and runs instrumentation tests using all Device Providers." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="downloadNeededDrawables" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="extractProguardFiles" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="generateDebugAndroidTestAssets" />
                 <option name="name" value="generateReleaseSources" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
+                <option name="description" value="Installs the Debug build." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="incrementalDebugAndroidTestJavaCompilationSafeguard" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="incrementalDebugJavaCompilationSafeguard" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="incrementalDebugUnitTestJavaCompilationSafeguard" />
+                <option name="name" value="installDebug" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
+                <option name="description" value="Installs the android (on device) tests for the Debug build." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="incrementalReleaseJavaCompilationSafeguard" />
+                <option name="name" value="installDebugAndroidTest" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="incrementalReleaseUnitTestJavaCompilationSafeguard" />
+                <option name="name" value="javaPreCompileDebug" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
-                <option name="description" value="Installs the Debug build." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="installDebug" />
+                <option name="name" value="javaPreCompileDebugAndroidTest" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
-                <option name="description" value="Installs the android (on device) tests for the Debug build." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="installDebugAndroidTest" />
+                <option name="name" value="javaPreCompileDebugUnitTest" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="jarDebugClasses" />
+                <option name="name" value="javaPreCompileRelease" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="jarReleaseClasses" />
+                <option name="name" value="javaPreCompileReleaseUnitTest" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Runs lint on all variants." />
                 <option name="name" value="lintRelease" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
-                <option name="description" value="Runs lint on just the fatal issues in the Release build." />
+                <option name="description" value="Runs lint on just the fatal issues in the release build." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="lintVitalRelease" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="mainApkListPersistenceDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="mainApkListPersistenceDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="mainApkListPersistenceRelease" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="mergeDebugAndroidTestAssets" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="perlClean" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="platformAttrExtractor" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="preBuild" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="prePackageMarkerForDebug" />
+                <option name="name" value="preReleaseBuild" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="prePackageMarkerForDebugAndroidTest" />
+                <option name="name" value="preReleaseUnitTestBuild" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="prePackageMarkerForRelease" />
+                <option name="name" value="prepareLintJar" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preReleaseBuild" />
+                <option name="name" value="preparePUBLISHED_DEXDebugAndroidTestForPublishing" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preReleaseUnitTestBuild" />
+                <option name="name" value="preparePUBLISHED_DEXDebugForPublishing" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="prepareDebugAndroidTestDependencies" />
+                <option name="name" value="preparePUBLISHED_DEXReleaseForPublishing" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="prepareDebugDependencies" />
+                <option name="name" value="preparePUBLISHED_JAVA_RESDebugAndroidTestForPublishing" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="prepareDebugUnitTestDependencies" />
+                <option name="name" value="preparePUBLISHED_JAVA_RESDebugForPublishing" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="prepareReleaseDependencies" />
+                <option name="name" value="preparePUBLISHED_JAVA_RESReleaseForPublishing" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="prepareReleaseUnitTestDependencies" />
+                <option name="name" value="preparePUBLISHED_NATIVE_LIBSDebugAndroidTestForPublishing" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="preparePUBLISHED_NATIVE_LIBSDebugForPublishing" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="preparePUBLISHED_NATIVE_LIBSReleaseForPublishing" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="processReleaseUnitTestJavaRes" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="reportBuildArtifactsDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="reportBuildArtifactsRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="resolveConfigAttr" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Displays the signing info for each variant." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
                 <option name="name" value="sourceSets" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="splitsDiscoveryTaskDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="splitsDiscoveryTaskRelease" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Run unit tests for all variants." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformClassesWithDexForDebug" />
+                <option name="name" value="transformClassesWithDexBuilderForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="transformClassesWithDexBuilderForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="transformClassesWithDexBuilderForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="transformDexArchiveWithDexMergerForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="transformDexArchiveWithDexMergerForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="transformDexArchiveWithDexMergerForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="transformDexArchiveWithExternalLibsDexMergerForDebug" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformClassesWithDexForDebugAndroidTest" />
+                <option name="name" value="transformDexArchiveWithExternalLibsDexMergerForDebugAndroidTest" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformClassesWithDexForRelease" />
+                <option name="name" value="transformDexArchiveWithExternalLibsDexMergerForRelease" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformNative_libsWithMergeJniLibsForDebug" />
+                <option name="name" value="transformNativeLibsWithMergeJniLibsForDebug" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformNative_libsWithMergeJniLibsForDebugAndroidTest" />
+                <option name="name" value="transformNativeLibsWithMergeJniLibsForDebugAndroidTest" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformNative_libsWithMergeJniLibsForRelease" />
+                <option name="name" value="transformNativeLibsWithMergeJniLibsForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="transformNativeLibsWithStripDebugSymbolForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="transformNativeLibsWithStripDebugSymbolForRelease" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="validateDebugSigning" />
+                <option name="name" value="validateSigningDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="validateSigningDebugAndroidTest" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="zipalignDebug" />
+                <option name="name" value="writeDebugApplicationId" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
+                <option name="name" value="writeReleaseApplicationId" />
               </ExternalTaskPojo>
             </list>
           </value>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="projects" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="bundleAppClassesRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="validateSigningDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformClassesWithDexBuilderForDebug" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="assembleReleaseUnitTest" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareDebugDependencies" />
+                <option name="name" value="bundleReleaseResources" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="lintDebug" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preparePUBLISHED_JAVA_RESReleaseForPublishing" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="reportBuildArtifactsRelease" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="assembleDebugUnitTest" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prePackageMarkerForDebug" />
+                <option name="name" value="createReleaseCompatibleScreenManifests" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Creates a version of android.jar that's suitable for unit tests." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="model" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preparePUBLISHED_DEXReleaseForPublishing" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="bundleAppClassesDebug" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Displays the tasks runnable from project ':xscreensaver'." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="incrementalDebugJavaCompilationSafeguard" />
+                <option name="name" value="bundleDebugAndroidTestResources" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Runs all device checks using Device Providers and Test Servers." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="processDebugResources" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNativeLibsWithStripDebugSymbolForRelease" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Runs lint on all variants." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prePackageMarkerForRelease" />
+                <option name="name" value="transformClassesWithDexBuilderForRelease" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="generateDebugResources" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="bundleAppClassesReleaseUnitTest" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="compileDebugJavaWithJavac" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mainApkListPersistenceDebugAndroidTest" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Assembles and tests this project and all projects it depends on." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="testReleaseUnitTest" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Deletes the build cache directory." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="cleanBuildCache" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="compileDebugAndroidTestShaders" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformNative_libsWithMergeJniLibsForDebugAndroidTest" />
+                <option name="name" value="preparePUBLISHED_JAVA_RESDebugAndroidTestForPublishing" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prePackageMarkerForDebugAndroidTest" />
+                <option name="name" value="preDebugAndroidTestBuild" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformClassesWithDexForDebug" />
+                <option name="name" value="processDebugAndroidTestJavaRes" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preDebugAndroidTestBuild" />
+                <option name="name" value="processReleaseUnitTestJavaRes" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugAndroidTestJavaRes" />
+                <option name="name" value="reportBuildArtifactsDebug" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processReleaseUnitTestJavaRes" />
+                <option name="name" value="transformDexArchiveWithExternalLibsDexMergerForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="javaPreCompileDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="splitsDiscoveryTaskDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="bundleAppClassesDebugUnitTest" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Uninstalls the Release build." />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareDebugAndroidTestDependencies" />
+                <option name="name" value="checkReleaseManifest" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="incrementalDebugAndroidTestJavaCompilationSafeguard" />
+                <option name="name" value="javaPreCompileDebugUnitTest" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="checkReleaseManifest" />
+                <option name="name" value="compileDebugAndroidTestSources" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestSources" />
+                <option name="name" value="createDebugCompatibleScreenManifests" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preparePUBLISHED_NATIVE_LIBSReleaseForPublishing" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareReleaseDependencies" />
+                <option name="name" value="prepareLintJar" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="mergeDebugAndroidTestAssets" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preparePUBLISHED_NATIVE_LIBSDebugForPublishing" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="processReleaseManifest" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="incrementalReleaseUnitTestJavaCompilationSafeguard" />
+                <option name="name" value="transformDexArchiveWithDexMergerForRelease" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="preReleaseBuild" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
-                <option name="description" value="Assembles all variants of all applications and secondary packages." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assemble" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="incrementalDebugUnitTestJavaCompilationSafeguard" />
+                <option name="name" value="writeDebugApplicationId" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
+                <option name="description" value="Assembles all variants of all applications and secondary packages." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="incrementalReleaseJavaCompilationSafeguard" />
+                <option name="name" value="assemble" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Displays a help message." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="installDebugAndroidTest" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mainApkListPersistenceDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformClassesWithDexBuilderForDebugAndroidTest" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="mergeDebugAssets" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="javaPreCompileReleaseUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preparePUBLISHED_DEXDebugAndroidTestForPublishing" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="javaPreCompileRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="splitsDiscoveryTaskRelease" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Runs all device checks on currently connected devices." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="connectedDebugAndroidTest" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformDexArchiveWithDexMergerForDebug" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Uninstall all applications." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="uninstallAll" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNativeLibsWithMergeJniLibsForDebug" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Assembles all the Test applications." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="zipalignDebug" />
+                <option name="name" value="preparePUBLISHED_DEXDebugForPublishing" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformNative_libsWithMergeJniLibsForDebug" />
+                <option name="name" value="packageRelease" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="packageRelease" />
+                <option name="name" value="validateSigningDebug" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="generateDebugAndroidTestResValues" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mainApkListPersistenceRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNativeLibsWithMergeJniLibsForDebugAndroidTest" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="mergeReleaseShaders" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="compileDebugUnitTestSources" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNativeLibsWithMergeJniLibsForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformDexArchiveWithExternalLibsDexMergerForDebugAndroidTest" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="generateDebugSources" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformClassesWithDexForDebugAndroidTest" />
+                <option name="name" value="extractProguardFiles" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="assembleDebugAndroidTest" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preparePUBLISHED_JAVA_RESDebugForPublishing" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="objlibClean" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestAssets" />
+                <option name="name" value="consumeConfigAttr" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseJavaWithJavac" />
+                <option name="name" value="generateDebugAndroidTestAssets" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="jarReleaseClasses" />
+                <option name="name" value="compileReleaseJavaWithJavac" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="downloadNeededDrawables" />
               </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareReleaseUnitTestDependencies" />
-              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Run unit tests for all variants." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugNdk" />
+                <option name="name" value="transformNativeLibsWithStripDebugSymbolForDebug" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformNative_libsWithMergeJniLibsForRelease" />
+                <option name="name" value="compileDebugNdk" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="validateDebugSigning" />
+                <option name="name" value="javaPreCompileDebug" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Run unit tests for the debug build." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="connectedAndroidTest" />
               </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="jarDebugClasses" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformClassesWithDexForRelease" />
-              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Installs the Debug build." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="generateDebugAssets" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformDexArchiveWithDexMergerForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the dependent components of components in project ':xscreensaver'. [incubating]" />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="dependentComponents" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Displays all buildscript dependencies declared in project ':xscreensaver'." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="perlBuild" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="bundleDebugResources" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="mergeReleaseAssets" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareDebugUnitTestDependencies" />
+                <option name="name" value="preparePUBLISHED_NATIVE_LIBSDebugAndroidTestForPublishing" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="generateReleaseResources" />
               </ExternalTaskPojo>
               <ExternalTaskPojo>
-                <option name="description" value="Runs lint on just the fatal issues in the Release build." />
+                <option name="description" value="Runs lint on just the fatal issues in the release build." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="lintVitalRelease" />
               </ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="ndkBuild" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="platformAttrExtractor" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Uninstalls the Debug build." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="mergeDebugAndroidTestShaders" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="bundleAppClassesDebugAndroidTest" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Deletes the build directory." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="generateDebugBuildConfig" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformDexArchiveWithExternalLibsDexMergerForDebug" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="description" value="Assembles and tests this project." />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="assembleRelease" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="resolveConfigAttr" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="compileDebugAndroidTestRenderscript" />
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="processDebugManifest" />
               </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="writeReleaseApplicationId" />
+              </ExternalTaskPojo>
               <ExternalTaskPojo>
                 <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
                 <option name="name" value="packageDebugAndroidTest" />
                       <ExternalModuleBuildClasspathPojo>
                         <option name="entries">
                           <list>
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/2.1.0/bcae59215a7b71367ece66de0bfaff6441102aea/gradle-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/2.1.0/6d96b336cb51a348725e6c366aefd74682dce465/gradle-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-core/2.1.0/12d90ede4c6ff93959a30d181acfb2187539b24c/gradle-core-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-core/2.1.0/527d4386755e742b500df6cc2f2b0dc2bb798dfe/gradle-core-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/2.1.0/a14517f422e5925ebc2e9388bf064b657f5da2a9/builder-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/2.1.0/525d7c91bd7acccecba4a6a4e611b772b0824f21/builder-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint/25.1.0/a40d910d75e4af864e82e557acd43d9083138aed/lint-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint/25.1.0/2bc7dab70d203eebda02f12b20a6170c190f6b29/lint-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/transform-api/2.0.0-deprecated-use-gradle-api/e4075c49e16e086140fe40eea56b2de7516874ee/transform-api-2.0.0-deprecated-use-gradle-api-sources.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/3.1.2/1608fa49add4d13366db7844998c6e59711f7e2a/gradle-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-core/3.1.2/ccab33656c1baa6514d88f4d9356db19d0e9823b/gradle-core-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/bundletool/0.1.0-alpha01/f7c303e37818223bd98566fcbea29aa0964c4d06/bundletool-0.1.0-alpha01.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/3.1.2/133b1f665104f0ebf01f71b61e4794385d7b5f1b/builder-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-gradle-api/26.1.2/8c54aedfe9da66e64402de04883cee083c127a3b/lint-gradle-api-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-api/3.1.2/427e25639a55911cadcf70657c9b2ded2ad6af2b/gradle-api-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/compilerCommon/3.1.2/be65c11ded4242932046f23ecfa5c7ccb0e98f46/compilerCommon-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jre8/1.2.0/505f55b9619bbc5f5e26c77427dd24a6a441eef1/kotlin-stdlib-jre8-1.2.0.jar" />
                             <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/transform-api/2.0.0-deprecated-use-gradle-api/85bee1acea9e27152b920746c68133b30b11431/transform-api-2.0.0-deprecated-use-gradle-api.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-api/2.1.0/238ff26e6c5e1dde40ab10140f4b993c86dde46f/gradle-api-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-api/2.1.0/f3278f0caee0382a1cc3dfccd08d7981b1d69013/gradle-api-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/compilerCommon/2.1.0/cf1a00b7904387dd88d86e337fd868f35cf309c6/compilerCommon-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/compilerCommon/2.1.0/92d114064b10fde26f5363c6d965767852b42828/compilerCommon-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm/5.0.3/f0f24f6666c1a15c7e202e91610476bd4ce59368/asm-5.0.3-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm/5.0.3/dcc2193db20e19e1feca8b1240dbbc4e190824fa/asm-5.0.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-commons/5.0.3/f0f24f6666c1a15c7e202e91610476bd4ce59368/asm-commons-5.0.3-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-commons/5.0.3/a7111830132c7f87d08fe48cb0ca07630f8cb91c/asm-commons-5.0.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-gradle/5.2.1/3c40c65126d6ec2289e8ca46aca7cdb5f818e545/proguard-gradle-5.2.1-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-gradle/5.2.1/5e9956c050fd84fa043517e77c4c0ff175a6b002/proguard-gradle-5.2.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jacoco/org.jacoco.core/0.7.4.201502262128/b6356a696e396a348a673237eee1f496ef75b4b1/org.jacoco.core-0.7.4.201502262128-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jacoco/org.jacoco.core/0.7.4.201502262128/31482f50411a3a5769b6c78fa9b97ba731c205e7/org.jacoco.core-0.7.4.201502262128.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/antlr/3.5.2/92c9bde32f0b1092507701b2b302af84534eb9b8/antlr-3.5.2-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/antlr/3.5.2/c4a65c950bfc3e7d04309c515b2177c00baf7764/antlr-3.5.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-model/2.1.0/dc5ea2e27b4e47f48981219953eb3d04614e11d7/builder-model-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-model/2.1.0/a3aa281eebfdb2f9f13b73c754648ad434f515ab/builder-model-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-test-api/2.1.0/7c14fa5a32fe9ee3ea2d0cb18abe6d4f606c8fdd/builder-test-api-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-test-api/2.1.0/b3b98fa0514c5e7301233db9586317a8aeda2aa0/builder-test-api-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdklib/25.1.0/71b43c88ec5dcdd5877046ccf9883e5e7873ad21/sdklib-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdklib/25.1.0/aad711bbb11a5d987e2f7894ca47531ef7152ae/sdklib-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdk-common/25.1.0/a230a919f707559c6d77e4eec61fc63a6e304c35/sdk-common-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdk-common/25.1.0/54053c7fe667b737870d3fa509b0d3c53eccb7f/sdk-common-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/common/25.1.0/976d89ae1b2a91229d3839e7f6c992027c695289/common-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/common/25.1.0/f28e33233e0d20119a04256036324ac2aba3426d/common-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/manifest-merger/25.1.0/cb6f914d62bbd2463f52db63d41f5164e6c8a4ab/manifest-merger-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/manifest-merger/25.1.0/db4c07f151804f5091156fe128312d817535126a/manifest-merger-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.ddms/ddmlib/25.1.0/4c3a6baefa41aa1ffa0886e3024e9ef5dc7ff440/ddmlib-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.ddms/ddmlib/25.1.0/7aae7364ea2a1d632fd86938bd71b1078930bd2c/ddmlib-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.jack/jack-api/0.10.0/93c3b096c028929ae9ec7414bd8da03b4feb6893/jack-api-0.10.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.jack/jack-api/0.10.0/f44f53e8f713714f9a1bf9b2cabfea3584b00878/jack-api-0.10.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.jill/jill-api/0.10.0/86d40c97b995035915303e5aa051980b9ec2d252/jill-api-0.10.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.jill/jill-api/0.10.0/7dfd6360ae4af1e171ec67b92e0cf065d59eef19/jill-api-0.10.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup/javawriter/2.5.0/1b2a0925ff06220c0261b6fd468183cd9e9a9a47/javawriter-2.5.0-sources.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm/5.1/5ef31c4fe953b1fd00b8a88fa1d6820e8785bb45/asm-5.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-analysis/5.1/6d1bf8989fc7901f868bee3863c44f21aa63d110/asm-analysis-5.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-commons/5.1/25d8a575034dd9cfcb375a39b5334f0ba9c8474e/asm-commons-5.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-util/5.1/b60e33a6bd0d71831e0c249816d01e6c1dd90a47/asm-util-5.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.jopt-simple/jopt-simple/4.9/ee9e9eaa0a35360dcfeac129ff4923215fd65904/jopt-simple-4.9.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-gradle/5.3.3/ad23a0505f58d0dfc95bb1472decc397460406c9/proguard-gradle-5.3.3.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.auto.value/auto-value/1.5.2/1b94ab7ec707e2220a0d1a7517488d1843236345/auto-value-1.5.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/22.0/3564ef3803de51fb0530a8377ec6100b33b0d073/guava-22.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.protobuf/protobuf-java/3.4.0/b32aba0cbe737a4ca953f71688725972e3ee927c/protobuf-java-3.4.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.protobuf/protobuf-java-util/3.4.0/96aba8ab71c16018c6adf66771ce15c6491bc0fe/protobuf-java-util-3.4.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.errorprone/error_prone_annotations/2.1.2/6dcc08f90f678ac33e5ef78c3c752b6f59e63e0c/error_prone_annotations-2.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/aapt2-proto/0.1.0/d1eb93a21a8d3590c3bfac574a8b6dffb2dbd21c/aapt2-proto-0.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-model/3.1.2/4504b655fa8fe72302020ca9a2387f3f23fbfb57/builder-model-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-test-api/3.1.2/ffb00b786822df6538377a90df9f2d11c022efc3/builder-test-api-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdklib/26.1.2/94697a9dff499b64b6e101bedb89a89825150af/sdklib-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdk-common/26.1.2/2cf773af3fb0e1bbd56a80fc6903a9d2a40a248/sdk-common-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/common/26.1.2/c31bbd68c51ed0ef3b8d7cdd5615acf762473887/common-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/manifest-merger/26.1.2/79f398427650c76f0c66c89f10e4886a1fe68c26/manifest-merger-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.ddms/ddmlib/26.1.2/1d423e621fb5c89fed13e41d0ed026cf5d8d7e7b/ddmlib-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.analytics-library/protos/26.1.2/ba53bcde9703b2bf9871128952dce844c5d743fa/protos-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.analytics-library/shared/26.1.2/bc21fe64fdaa64e59672e7d546d373f430e7557c/shared-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.analytics-library/tracker/26.1.2/2d2260da92e50ac072f89d60a596d03aab3a8757/tracker-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/apksig/3.1.2/5af360dd30015a9a47c8ab0af0e6b05f64760edc/apksig-3.1.2.jar" />
                             <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup/javawriter/2.5.0/81241ff7078ef14f42ea2a8995fa09c096256e6b/javawriter-2.5.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcpkix-jdk15on/1.48/8cff777fce5ef53cc35fa569faa8d12faaf34a78/bcpkix-jdk15on-1.48-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcpkix-jdk15on/1.48/28b7614b908a47844bb27e3c94b45b6893656265/bcpkix-jdk15on-1.48.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcprov-jdk15on/1.48/3824866f059053c43b118eb5a067ea1800d8c913/bcprov-jdk15on-1.48-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcprov-jdk15on/1.48/960dea7c9181ba0b17e8bab0c06a43f0a5f04e65/bcprov-jdk15on-1.48.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-tree/5.0.3/f0f24f6666c1a15c7e202e91610476bd4ce59368/asm-tree-5.0.3-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-tree/5.0.3/287749b48ba7162fb67c93a026d690b29f410bed/asm-tree-5.0.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-checks/25.1.0/8354137d4322117aa4d3a5adf9f9e4d40132edc2/lint-checks-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-checks/25.1.0/8527298ca77202032b16b729bd1849e44f445adc/lint-checks-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.eclipse.jdt.core.compiler/ecj/4.4.2/903e8c2cb521cc91636eccae66b8594435516ff5/ecj-4.4.2-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.eclipse.jdt.core.compiler/ecj/4.4.2/71d67f5bab9465ec844596ef844f40902ae25392/ecj-4.4.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/annotations/25.1.0/7958014f149e08ebae7b1ac01db1277e4024f119/annotations-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/annotations/25.1.0/6fdec5fc3e0b5a7b1a5866d9e8910d9bc4ceee4f/annotations-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/17.0/7ca0efbeb87ca845b5d7a0ac9c21a4b7b95f7b28/guava-17.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/17.0/9c6ef172e8de35fd8d4d8783e4821e57cdef7445/guava-17.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/baseLibrary/2.1.0/64e4170bf3ec7442ae462921a3650e5e0ece9a02/baseLibrary-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/baseLibrary/2.1.0/a7aeef173c4e5b104ec04f146f8e8f9debde1c5e/baseLibrary-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4/4.5/d61f0b719751a2823a1d4e2d206406488d52276d/antlr4-4.5-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4/4.5/a0e860e317147848e69ac145bc5196901a9993bf/antlr4-4.5.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-io/commons-io/2.4/f2d8698c46d1167ff24b06a840a87d91a02db891/commons-io-2.4-sources.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcpkix-jdk15on/1.56/4648af70268b6fdb24674fb1fd7c1fcc73db1231/bcpkix-jdk15on-1.56.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcprov-jdk15on/1.56/a153c6f9744a3e9dd6feab5e210e1c9861362ec7/bcprov-jdk15on-1.56.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-tree/5.1/87b38c12a0ea645791ead9d3e74ae5268d1d6c34/asm-tree-5.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/it.unimi.dsi/fastutil/7.2.0/5ad3a2bb04143f70aa0765fc29fc29571a7d6b34/fastutil-7.2.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.googlecode.json-simple/json-simple/1.1/5e303a03d04e6788dddfa3655272580ae0fc13bb/json-simple-1.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-reflect/1.2.0/4bbda3b5425aa38a9f6960468a29c5ef3e8a28c9/kotlin-reflect-1.2.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/baseLibrary/3.1.2/1b6a1add6a577708b62737dc31c479549f77750d/baseLibrary-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/antlr4/4.5.3/f35db7e4b2446e4174ba6a73db7bd6b3e6bb5da1/antlr4-4.5.3.jar" />
                             <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-io/commons-io/2.4/b1b6ea3b7e4aa4f492509a4952029cd8e48019ad/commons-io-2.4.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.googlecode.juniversalchardet/juniversalchardet/1.0.3/77979eaa98f90806f984155f44f63cc1fb60ac25/juniversalchardet-1.0.3-sources.jar" />
                             <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.googlecode.juniversalchardet/juniversalchardet/1.0.3/cd49678784c46aa8789c060538e0154013bb421b/juniversalchardet-1.0.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-base/5.2.1/22f9a8800c87aaf25282bbfcf8384246246063c2/proguard-base-5.2.1-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-base/5.2.1/4f61348b4e7c943b85679dcb697f3a5fc3101921/proguard-base-5.2.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-debug-all/5.0.1/78ebb2694324283f3120aa3ed52465b22fab8a4a/asm-debug-all-5.0.1-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-debug-all/5.0.1/f69b5f7d96cec0d448acf1c1a266584170c9643b/asm-debug-all-5.0.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/antlr-runtime/3.5.2/5214ea45dd20d3a2e4caa6f1ad2248ad107e0daf/antlr-runtime-3.5.2-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/antlr-runtime/3.5.2/cd9cd41361c155f3af0f653009dcecb08d8b4afd/antlr-runtime-3.5.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/ST4/4.0.8/6f23134f1c98dfce77f85defda31bfbce3e2a4ac/ST4-4.0.8-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/ST4/4.0.8/a1c55e974f8a94d78e2348fa6ff63f4fa1fae64/ST4-4.0.8.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.layoutlib/layoutlib-api/25.1.0/7ba341716c182b760141e06c8173d75ccc185264/layoutlib-api-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.layoutlib/layoutlib-api/25.1.0/26620cea0540ae08e4d19c71f1e779e04c6c545a/layoutlib-api-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/dvlib/25.1.0/8a149c12efb0be65f91a1ca28c2c3148adf95141/dvlib-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/dvlib/25.1.0/ca582735b513a64217f39fccb7ea9285e7e0e23d/dvlib-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/repository/25.1.0/4e998d02971f2a9c17195f9d1b9385ee3baad35f/repository-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/repository/25.1.0/cb53d8e728e092299f9d62fc7c8e34567d882616/repository-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.gson/gson/2.2.4/a6dc5db8a12928e583bd3f23e72d3ab611ecd58f/gson-2.2.4-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.gson/gson/2.2.4/a60a5e993c98c864010053cb901b7eab25306568/gson-2.2.4.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-compress/1.8.1/3caea4421428752206c7a94c3e3097f0c47f1bb8/commons-compress-1.8.1-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-compress/1.8.1/a698750c16740fd5b3871425f4cb3bbaa87f529d/commons-compress-1.8.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpclient/4.1.1/42f6189003f355107f53b937770092517de69710/httpclient-4.1.1-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpclient/4.1.1/3d1d918f32709e33ba7ddb2c4e8d1c543ebe713e/httpclient-4.1.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpmime/4.1/3ac83213baeab2b21fde6c0bf47ed68ea3e6a8da/httpmime-4.1-sources.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup/javapoet/1.8.0/e858dc62ef484048540d27d36f3ec2177a3fa9b1/javapoet-1.8.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.gson/gson/2.7/751f548c85fa49f330cecbb1875893f971b33c4e/gson-2.7.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/annotations/26.1.2/4f4e0ee71b9ccaa4a70cc86e40fb84ada2ed99a3/annotations-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-base/5.3.3/988b6b0636ce343d4962b3b37f6319dcc6e99a61/proguard-base-5.3.3.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.layoutlib/layoutlib-api/26.1.2/3697abf628d30042c1082ea846454dfd1e8da3e/layoutlib-api-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/dvlib/26.1.2/eb39925fee6e726468fc10344ec988c086301ed7/dvlib-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/repository/26.1.2/c8209ccb8ee0e5e3f293fd71d2a827f440ab811c/repository-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-compress/1.12/84caa68576e345eb5e7ae61a0e5a9229eb100d7b/commons-compress-1.12.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpclient/4.2.6/e4ca30a6a3a075053a61c6fc850d2432dc012ba7/httpclient-4.2.6.jar" />
                             <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpmime/4.1/9ba2dcdf94ce35c8a8e9bff242db0618ca932e92/httpmime-4.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.kxml/kxml2/2.3.0/309cd2cff7260e465792fda3dcbb063b730d8050/kxml2-2.3.0-sources.jar" />
                             <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.kxml/kxml2/2.3.0/ccbc77a5fd907ef863c29f3596c6f54ffa4e9442/kxml2-2.3.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.0/a8671cf4a536fd8e1983d6111be4e3720db66ab7/lint-api-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.0/ee915d21b52ee1c5884173c044c19cef14e5c623/lint-api-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-analysis/5.0.3/f0f24f6666c1a15c7e202e91610476bd4ce59368/asm-analysis-5.0.3-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-analysis/5.0.3/c7126aded0e8e13fed5f913559a0dd7b770a10f3/asm-analysis-5.0.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4-runtime/4.5/61495cea98c9c63b16b87ae4e79b7e478405e40b/antlr4-runtime-4.5-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4-runtime/4.5/5067478827a98f5ab77d9fc577903edc57af3da4/antlr4-runtime-4.5.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4-annotations/4.5/8d24c9255a970c3c85fc5c88dfe9d4e8627d56e2/antlr4-annotations-4.5-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4-annotations/4.5/2c5996120a0ac690de575bd8ac36250e6720a6b8/antlr4-annotations-4.5.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.intellij/annotations/12.0/4943118f12f706a8820f73529fcb8f5853bc0fed/annotations-12.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.intellij/annotations/12.0/bbcf6448f6d40abe506e2c83b70a3e8bfd2b4539/annotations-12.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpcore/4.1/1fdf61e5ba87e0e4676c22677e0b2fe3a05c2fd8/httpcore-4.1-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpcore/4.1/33fc26c02f8043ab0ede19eadc8c9885386b255c/httpcore-4.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.1.1/f3f156cbff0e0fb0d64bfce31a352cce4a33bc19/commons-logging-1.1.1-sources.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.sun.activation/javax.activation/1.2.0/bf744c1e2776ed1de3c55c8dac1057ec331ef744/javax.activation-1.2.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-runtime/2.2.11/65510afc78679e347b0d774617a97fedac94f8/jaxb-runtime-2.2.11.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.jimfs/jimfs/1.1/8fbd0579dc68aba6186935cc1bee21d2f3e7ec1c/jimfs-1.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpcore/4.2.5/472f0f5f8dba5d1962cb9d7739feed739a31c30d/httpcore-4.2.5.jar" />
                             <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.1.1/5043bfebc3db072ed80fbd362e7caf00e885d8ae/commons-logging-1.1.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-codec/commons-codec/1.4/5310da9f90e843883309e9e0bf5950faa79882a0/commons-codec-1.4-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-codec/commons-codec/1.4/4216af16d38465bbab0f3dff8efa14204f7a399a/commons-codec-1.4.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.external.lombok/lombok-ast/0.2.3/b4f90836c51edefa4a38c97877b709ed2c15ee32/lombok-ast-0.2.3-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.external.lombok/lombok-ast/0.2.3/528b6f8bde3157f17530aa366631f2aad2a6cf9/lombok-ast-0.2.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.abego.treelayout/org.abego.treelayout.core/1.0.1/6e1dd6f6efdb453c7b8ba35726c63fbf50cd7142/org.abego.treelayout.core-1.0.1-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.abego.treelayout/org.abego.treelayout.core/1.0.1/e31e79cba7a5414cf18fa69f3f0a2cf9ee997b61/org.abego.treelayout.core-1.0.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-codec/commons-codec/1.6/b7f0fc8f61ecadeb3695f0b9464755eee44374d4/commons-codec-1.6.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.2.0/25eb440d6eeb9fc60299121020fe726eb2100d03/kotlin-stdlib-1.2.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-core/2.2.11/f5745049f5fb9cb9d9b5f513c207727f475983e9/jaxb-core-2.2.11.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jvnet.staxex/stax-ex/1.7.7/18bed5a0da27a6b43efe01282f2dc911b1cb3a72/stax-ex-1.7.7.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.sun.xml.fastinfoset/FastInfoset/1.2.13/98f56b9354e27bd2941cc5d461344e240ae51ae/FastInfoset-1.2.13.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jre7/1.2.0/ec8b969e26fbcf2265a4d1a1539c4d1d4c5af380/kotlin-stdlib-jre7-1.2.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.findbugs/jsr305/1.3.9/40719ea6961c0cb6afaeb6a921eaa1f6afd4cfdf/jsr305-1.3.9.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.j2objc/j2objc-annotations/1.1/976d8d30bebc251db406f2bdb3eb01962b5685b3/j2objc-annotations-1.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.codehaus.mojo/animal-sniffer-annotations/1.14/775b7e22fb10026eed3f86e8dc556dfafe35f2d5/animal-sniffer-annotations-1.14.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/javax.xml.bind/jaxb-api/2.2.12-b140109.1041/7ed0e0d01198614194d56dfb03d9d95aa311824c/jaxb-api-2.2.12-b140109.1041.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/txw2/2.2.11/2df047d8c187a62f2177bf6013f1f9786cdfc8a2/txw2-2.2.11.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.sun.istack/istack-commons-runtime/2.21/c969d8f15c467f0ef7d7b04889afbe7b5d48e22f/istack-commons-runtime-2.21.jar" />
                           </list>
                         </option>
                         <option name="path" value="$PROJECT_DIR$/.." />
                       <ExternalModuleBuildClasspathPojo>
                         <option name="entries">
                           <list>
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/2.1.0/bcae59215a7b71367ece66de0bfaff6441102aea/gradle-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/2.1.0/6d96b336cb51a348725e6c366aefd74682dce465/gradle-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-core/2.1.0/12d90ede4c6ff93959a30d181acfb2187539b24c/gradle-core-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-core/2.1.0/527d4386755e742b500df6cc2f2b0dc2bb798dfe/gradle-core-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/2.1.0/a14517f422e5925ebc2e9388bf064b657f5da2a9/builder-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/2.1.0/525d7c91bd7acccecba4a6a4e611b772b0824f21/builder-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint/25.1.0/a40d910d75e4af864e82e557acd43d9083138aed/lint-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint/25.1.0/2bc7dab70d203eebda02f12b20a6170c190f6b29/lint-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/transform-api/2.0.0-deprecated-use-gradle-api/e4075c49e16e086140fe40eea56b2de7516874ee/transform-api-2.0.0-deprecated-use-gradle-api-sources.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/3.1.2/1608fa49add4d13366db7844998c6e59711f7e2a/gradle-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-core/3.1.2/ccab33656c1baa6514d88f4d9356db19d0e9823b/gradle-core-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/bundletool/0.1.0-alpha01/f7c303e37818223bd98566fcbea29aa0964c4d06/bundletool-0.1.0-alpha01.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/3.1.2/133b1f665104f0ebf01f71b61e4794385d7b5f1b/builder-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-gradle-api/26.1.2/8c54aedfe9da66e64402de04883cee083c127a3b/lint-gradle-api-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-api/3.1.2/427e25639a55911cadcf70657c9b2ded2ad6af2b/gradle-api-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/compilerCommon/3.1.2/be65c11ded4242932046f23ecfa5c7ccb0e98f46/compilerCommon-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jre8/1.2.0/505f55b9619bbc5f5e26c77427dd24a6a441eef1/kotlin-stdlib-jre8-1.2.0.jar" />
                             <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/transform-api/2.0.0-deprecated-use-gradle-api/85bee1acea9e27152b920746c68133b30b11431/transform-api-2.0.0-deprecated-use-gradle-api.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-api/2.1.0/238ff26e6c5e1dde40ab10140f4b993c86dde46f/gradle-api-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-api/2.1.0/f3278f0caee0382a1cc3dfccd08d7981b1d69013/gradle-api-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/compilerCommon/2.1.0/cf1a00b7904387dd88d86e337fd868f35cf309c6/compilerCommon-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/compilerCommon/2.1.0/92d114064b10fde26f5363c6d965767852b42828/compilerCommon-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm/5.0.3/f0f24f6666c1a15c7e202e91610476bd4ce59368/asm-5.0.3-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm/5.0.3/dcc2193db20e19e1feca8b1240dbbc4e190824fa/asm-5.0.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-commons/5.0.3/f0f24f6666c1a15c7e202e91610476bd4ce59368/asm-commons-5.0.3-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-commons/5.0.3/a7111830132c7f87d08fe48cb0ca07630f8cb91c/asm-commons-5.0.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-gradle/5.2.1/3c40c65126d6ec2289e8ca46aca7cdb5f818e545/proguard-gradle-5.2.1-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-gradle/5.2.1/5e9956c050fd84fa043517e77c4c0ff175a6b002/proguard-gradle-5.2.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jacoco/org.jacoco.core/0.7.4.201502262128/b6356a696e396a348a673237eee1f496ef75b4b1/org.jacoco.core-0.7.4.201502262128-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jacoco/org.jacoco.core/0.7.4.201502262128/31482f50411a3a5769b6c78fa9b97ba731c205e7/org.jacoco.core-0.7.4.201502262128.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/antlr/3.5.2/92c9bde32f0b1092507701b2b302af84534eb9b8/antlr-3.5.2-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/antlr/3.5.2/c4a65c950bfc3e7d04309c515b2177c00baf7764/antlr-3.5.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-model/2.1.0/dc5ea2e27b4e47f48981219953eb3d04614e11d7/builder-model-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-model/2.1.0/a3aa281eebfdb2f9f13b73c754648ad434f515ab/builder-model-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-test-api/2.1.0/7c14fa5a32fe9ee3ea2d0cb18abe6d4f606c8fdd/builder-test-api-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-test-api/2.1.0/b3b98fa0514c5e7301233db9586317a8aeda2aa0/builder-test-api-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdklib/25.1.0/71b43c88ec5dcdd5877046ccf9883e5e7873ad21/sdklib-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdklib/25.1.0/aad711bbb11a5d987e2f7894ca47531ef7152ae/sdklib-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdk-common/25.1.0/a230a919f707559c6d77e4eec61fc63a6e304c35/sdk-common-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdk-common/25.1.0/54053c7fe667b737870d3fa509b0d3c53eccb7f/sdk-common-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/common/25.1.0/976d89ae1b2a91229d3839e7f6c992027c695289/common-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/common/25.1.0/f28e33233e0d20119a04256036324ac2aba3426d/common-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/manifest-merger/25.1.0/cb6f914d62bbd2463f52db63d41f5164e6c8a4ab/manifest-merger-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/manifest-merger/25.1.0/db4c07f151804f5091156fe128312d817535126a/manifest-merger-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.ddms/ddmlib/25.1.0/4c3a6baefa41aa1ffa0886e3024e9ef5dc7ff440/ddmlib-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.ddms/ddmlib/25.1.0/7aae7364ea2a1d632fd86938bd71b1078930bd2c/ddmlib-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.jack/jack-api/0.10.0/93c3b096c028929ae9ec7414bd8da03b4feb6893/jack-api-0.10.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.jack/jack-api/0.10.0/f44f53e8f713714f9a1bf9b2cabfea3584b00878/jack-api-0.10.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.jill/jill-api/0.10.0/86d40c97b995035915303e5aa051980b9ec2d252/jill-api-0.10.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.jill/jill-api/0.10.0/7dfd6360ae4af1e171ec67b92e0cf065d59eef19/jill-api-0.10.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup/javawriter/2.5.0/1b2a0925ff06220c0261b6fd468183cd9e9a9a47/javawriter-2.5.0-sources.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm/5.1/5ef31c4fe953b1fd00b8a88fa1d6820e8785bb45/asm-5.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-analysis/5.1/6d1bf8989fc7901f868bee3863c44f21aa63d110/asm-analysis-5.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-commons/5.1/25d8a575034dd9cfcb375a39b5334f0ba9c8474e/asm-commons-5.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-util/5.1/b60e33a6bd0d71831e0c249816d01e6c1dd90a47/asm-util-5.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.jopt-simple/jopt-simple/4.9/ee9e9eaa0a35360dcfeac129ff4923215fd65904/jopt-simple-4.9.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-gradle/5.3.3/ad23a0505f58d0dfc95bb1472decc397460406c9/proguard-gradle-5.3.3.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.auto.value/auto-value/1.5.2/1b94ab7ec707e2220a0d1a7517488d1843236345/auto-value-1.5.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/22.0/3564ef3803de51fb0530a8377ec6100b33b0d073/guava-22.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.protobuf/protobuf-java/3.4.0/b32aba0cbe737a4ca953f71688725972e3ee927c/protobuf-java-3.4.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.protobuf/protobuf-java-util/3.4.0/96aba8ab71c16018c6adf66771ce15c6491bc0fe/protobuf-java-util-3.4.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.errorprone/error_prone_annotations/2.1.2/6dcc08f90f678ac33e5ef78c3c752b6f59e63e0c/error_prone_annotations-2.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/aapt2-proto/0.1.0/d1eb93a21a8d3590c3bfac574a8b6dffb2dbd21c/aapt2-proto-0.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-model/3.1.2/4504b655fa8fe72302020ca9a2387f3f23fbfb57/builder-model-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-test-api/3.1.2/ffb00b786822df6538377a90df9f2d11c022efc3/builder-test-api-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdklib/26.1.2/94697a9dff499b64b6e101bedb89a89825150af/sdklib-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdk-common/26.1.2/2cf773af3fb0e1bbd56a80fc6903a9d2a40a248/sdk-common-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/common/26.1.2/c31bbd68c51ed0ef3b8d7cdd5615acf762473887/common-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/manifest-merger/26.1.2/79f398427650c76f0c66c89f10e4886a1fe68c26/manifest-merger-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.ddms/ddmlib/26.1.2/1d423e621fb5c89fed13e41d0ed026cf5d8d7e7b/ddmlib-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.analytics-library/protos/26.1.2/ba53bcde9703b2bf9871128952dce844c5d743fa/protos-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.analytics-library/shared/26.1.2/bc21fe64fdaa64e59672e7d546d373f430e7557c/shared-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.analytics-library/tracker/26.1.2/2d2260da92e50ac072f89d60a596d03aab3a8757/tracker-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/apksig/3.1.2/5af360dd30015a9a47c8ab0af0e6b05f64760edc/apksig-3.1.2.jar" />
                             <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup/javawriter/2.5.0/81241ff7078ef14f42ea2a8995fa09c096256e6b/javawriter-2.5.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcpkix-jdk15on/1.48/8cff777fce5ef53cc35fa569faa8d12faaf34a78/bcpkix-jdk15on-1.48-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcpkix-jdk15on/1.48/28b7614b908a47844bb27e3c94b45b6893656265/bcpkix-jdk15on-1.48.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcprov-jdk15on/1.48/3824866f059053c43b118eb5a067ea1800d8c913/bcprov-jdk15on-1.48-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcprov-jdk15on/1.48/960dea7c9181ba0b17e8bab0c06a43f0a5f04e65/bcprov-jdk15on-1.48.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-tree/5.0.3/f0f24f6666c1a15c7e202e91610476bd4ce59368/asm-tree-5.0.3-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-tree/5.0.3/287749b48ba7162fb67c93a026d690b29f410bed/asm-tree-5.0.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-checks/25.1.0/8354137d4322117aa4d3a5adf9f9e4d40132edc2/lint-checks-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-checks/25.1.0/8527298ca77202032b16b729bd1849e44f445adc/lint-checks-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.eclipse.jdt.core.compiler/ecj/4.4.2/903e8c2cb521cc91636eccae66b8594435516ff5/ecj-4.4.2-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.eclipse.jdt.core.compiler/ecj/4.4.2/71d67f5bab9465ec844596ef844f40902ae25392/ecj-4.4.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/annotations/25.1.0/7958014f149e08ebae7b1ac01db1277e4024f119/annotations-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/annotations/25.1.0/6fdec5fc3e0b5a7b1a5866d9e8910d9bc4ceee4f/annotations-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/17.0/7ca0efbeb87ca845b5d7a0ac9c21a4b7b95f7b28/guava-17.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/17.0/9c6ef172e8de35fd8d4d8783e4821e57cdef7445/guava-17.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/baseLibrary/2.1.0/64e4170bf3ec7442ae462921a3650e5e0ece9a02/baseLibrary-2.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/baseLibrary/2.1.0/a7aeef173c4e5b104ec04f146f8e8f9debde1c5e/baseLibrary-2.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4/4.5/d61f0b719751a2823a1d4e2d206406488d52276d/antlr4-4.5-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4/4.5/a0e860e317147848e69ac145bc5196901a9993bf/antlr4-4.5.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-io/commons-io/2.4/f2d8698c46d1167ff24b06a840a87d91a02db891/commons-io-2.4-sources.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcpkix-jdk15on/1.56/4648af70268b6fdb24674fb1fd7c1fcc73db1231/bcpkix-jdk15on-1.56.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcprov-jdk15on/1.56/a153c6f9744a3e9dd6feab5e210e1c9861362ec7/bcprov-jdk15on-1.56.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-tree/5.1/87b38c12a0ea645791ead9d3e74ae5268d1d6c34/asm-tree-5.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/it.unimi.dsi/fastutil/7.2.0/5ad3a2bb04143f70aa0765fc29fc29571a7d6b34/fastutil-7.2.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.googlecode.json-simple/json-simple/1.1/5e303a03d04e6788dddfa3655272580ae0fc13bb/json-simple-1.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-reflect/1.2.0/4bbda3b5425aa38a9f6960468a29c5ef3e8a28c9/kotlin-reflect-1.2.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/baseLibrary/3.1.2/1b6a1add6a577708b62737dc31c479549f77750d/baseLibrary-3.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/antlr4/4.5.3/f35db7e4b2446e4174ba6a73db7bd6b3e6bb5da1/antlr4-4.5.3.jar" />
                             <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-io/commons-io/2.4/b1b6ea3b7e4aa4f492509a4952029cd8e48019ad/commons-io-2.4.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.googlecode.juniversalchardet/juniversalchardet/1.0.3/77979eaa98f90806f984155f44f63cc1fb60ac25/juniversalchardet-1.0.3-sources.jar" />
                             <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.googlecode.juniversalchardet/juniversalchardet/1.0.3/cd49678784c46aa8789c060538e0154013bb421b/juniversalchardet-1.0.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-base/5.2.1/22f9a8800c87aaf25282bbfcf8384246246063c2/proguard-base-5.2.1-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-base/5.2.1/4f61348b4e7c943b85679dcb697f3a5fc3101921/proguard-base-5.2.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-debug-all/5.0.1/78ebb2694324283f3120aa3ed52465b22fab8a4a/asm-debug-all-5.0.1-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-debug-all/5.0.1/f69b5f7d96cec0d448acf1c1a266584170c9643b/asm-debug-all-5.0.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/antlr-runtime/3.5.2/5214ea45dd20d3a2e4caa6f1ad2248ad107e0daf/antlr-runtime-3.5.2-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/antlr-runtime/3.5.2/cd9cd41361c155f3af0f653009dcecb08d8b4afd/antlr-runtime-3.5.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/ST4/4.0.8/6f23134f1c98dfce77f85defda31bfbce3e2a4ac/ST4-4.0.8-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/ST4/4.0.8/a1c55e974f8a94d78e2348fa6ff63f4fa1fae64/ST4-4.0.8.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.layoutlib/layoutlib-api/25.1.0/7ba341716c182b760141e06c8173d75ccc185264/layoutlib-api-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.layoutlib/layoutlib-api/25.1.0/26620cea0540ae08e4d19c71f1e779e04c6c545a/layoutlib-api-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/dvlib/25.1.0/8a149c12efb0be65f91a1ca28c2c3148adf95141/dvlib-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/dvlib/25.1.0/ca582735b513a64217f39fccb7ea9285e7e0e23d/dvlib-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/repository/25.1.0/4e998d02971f2a9c17195f9d1b9385ee3baad35f/repository-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/repository/25.1.0/cb53d8e728e092299f9d62fc7c8e34567d882616/repository-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.gson/gson/2.2.4/a6dc5db8a12928e583bd3f23e72d3ab611ecd58f/gson-2.2.4-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.gson/gson/2.2.4/a60a5e993c98c864010053cb901b7eab25306568/gson-2.2.4.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-compress/1.8.1/3caea4421428752206c7a94c3e3097f0c47f1bb8/commons-compress-1.8.1-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-compress/1.8.1/a698750c16740fd5b3871425f4cb3bbaa87f529d/commons-compress-1.8.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpclient/4.1.1/42f6189003f355107f53b937770092517de69710/httpclient-4.1.1-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpclient/4.1.1/3d1d918f32709e33ba7ddb2c4e8d1c543ebe713e/httpclient-4.1.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpmime/4.1/3ac83213baeab2b21fde6c0bf47ed68ea3e6a8da/httpmime-4.1-sources.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup/javapoet/1.8.0/e858dc62ef484048540d27d36f3ec2177a3fa9b1/javapoet-1.8.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.gson/gson/2.7/751f548c85fa49f330cecbb1875893f971b33c4e/gson-2.7.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/annotations/26.1.2/4f4e0ee71b9ccaa4a70cc86e40fb84ada2ed99a3/annotations-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-base/5.3.3/988b6b0636ce343d4962b3b37f6319dcc6e99a61/proguard-base-5.3.3.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.layoutlib/layoutlib-api/26.1.2/3697abf628d30042c1082ea846454dfd1e8da3e/layoutlib-api-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/dvlib/26.1.2/eb39925fee6e726468fc10344ec988c086301ed7/dvlib-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/repository/26.1.2/c8209ccb8ee0e5e3f293fd71d2a827f440ab811c/repository-26.1.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-compress/1.12/84caa68576e345eb5e7ae61a0e5a9229eb100d7b/commons-compress-1.12.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpclient/4.2.6/e4ca30a6a3a075053a61c6fc850d2432dc012ba7/httpclient-4.2.6.jar" />
                             <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpmime/4.1/9ba2dcdf94ce35c8a8e9bff242db0618ca932e92/httpmime-4.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.kxml/kxml2/2.3.0/309cd2cff7260e465792fda3dcbb063b730d8050/kxml2-2.3.0-sources.jar" />
                             <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.kxml/kxml2/2.3.0/ccbc77a5fd907ef863c29f3596c6f54ffa4e9442/kxml2-2.3.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.0/a8671cf4a536fd8e1983d6111be4e3720db66ab7/lint-api-25.1.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.0/ee915d21b52ee1c5884173c044c19cef14e5c623/lint-api-25.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-analysis/5.0.3/f0f24f6666c1a15c7e202e91610476bd4ce59368/asm-analysis-5.0.3-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-analysis/5.0.3/c7126aded0e8e13fed5f913559a0dd7b770a10f3/asm-analysis-5.0.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4-runtime/4.5/61495cea98c9c63b16b87ae4e79b7e478405e40b/antlr4-runtime-4.5-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4-runtime/4.5/5067478827a98f5ab77d9fc577903edc57af3da4/antlr4-runtime-4.5.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4-annotations/4.5/8d24c9255a970c3c85fc5c88dfe9d4e8627d56e2/antlr4-annotations-4.5-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4-annotations/4.5/2c5996120a0ac690de575bd8ac36250e6720a6b8/antlr4-annotations-4.5.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.intellij/annotations/12.0/4943118f12f706a8820f73529fcb8f5853bc0fed/annotations-12.0-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.intellij/annotations/12.0/bbcf6448f6d40abe506e2c83b70a3e8bfd2b4539/annotations-12.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpcore/4.1/1fdf61e5ba87e0e4676c22677e0b2fe3a05c2fd8/httpcore-4.1-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpcore/4.1/33fc26c02f8043ab0ede19eadc8c9885386b255c/httpcore-4.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.1.1/f3f156cbff0e0fb0d64bfce31a352cce4a33bc19/commons-logging-1.1.1-sources.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.sun.activation/javax.activation/1.2.0/bf744c1e2776ed1de3c55c8dac1057ec331ef744/javax.activation-1.2.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-runtime/2.2.11/65510afc78679e347b0d774617a97fedac94f8/jaxb-runtime-2.2.11.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.jimfs/jimfs/1.1/8fbd0579dc68aba6186935cc1bee21d2f3e7ec1c/jimfs-1.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpcore/4.2.5/472f0f5f8dba5d1962cb9d7739feed739a31c30d/httpcore-4.2.5.jar" />
                             <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.1.1/5043bfebc3db072ed80fbd362e7caf00e885d8ae/commons-logging-1.1.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-codec/commons-codec/1.4/5310da9f90e843883309e9e0bf5950faa79882a0/commons-codec-1.4-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-codec/commons-codec/1.4/4216af16d38465bbab0f3dff8efa14204f7a399a/commons-codec-1.4.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.external.lombok/lombok-ast/0.2.3/b4f90836c51edefa4a38c97877b709ed2c15ee32/lombok-ast-0.2.3-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.external.lombok/lombok-ast/0.2.3/528b6f8bde3157f17530aa366631f2aad2a6cf9/lombok-ast-0.2.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.abego.treelayout/org.abego.treelayout.core/1.0.1/6e1dd6f6efdb453c7b8ba35726c63fbf50cd7142/org.abego.treelayout.core-1.0.1-sources.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.abego.treelayout/org.abego.treelayout.core/1.0.1/e31e79cba7a5414cf18fa69f3f0a2cf9ee997b61/org.abego.treelayout.core-1.0.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-codec/commons-codec/1.6/b7f0fc8f61ecadeb3695f0b9464755eee44374d4/commons-codec-1.6.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.2.0/25eb440d6eeb9fc60299121020fe726eb2100d03/kotlin-stdlib-1.2.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-core/2.2.11/f5745049f5fb9cb9d9b5f513c207727f475983e9/jaxb-core-2.2.11.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jvnet.staxex/stax-ex/1.7.7/18bed5a0da27a6b43efe01282f2dc911b1cb3a72/stax-ex-1.7.7.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.sun.xml.fastinfoset/FastInfoset/1.2.13/98f56b9354e27bd2941cc5d461344e240ae51ae/FastInfoset-1.2.13.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jre7/1.2.0/ec8b969e26fbcf2265a4d1a1539c4d1d4c5af380/kotlin-stdlib-jre7-1.2.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.findbugs/jsr305/1.3.9/40719ea6961c0cb6afaeb6a921eaa1f6afd4cfdf/jsr305-1.3.9.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.j2objc/j2objc-annotations/1.1/976d8d30bebc251db406f2bdb3eb01962b5685b3/j2objc-annotations-1.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.codehaus.mojo/animal-sniffer-annotations/1.14/775b7e22fb10026eed3f86e8dc556dfafe35f2d5/animal-sniffer-annotations-1.14.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/javax.xml.bind/jaxb-api/2.2.12-b140109.1041/7ed0e0d01198614194d56dfb03d9d95aa311824c/jaxb-api-2.2.12-b140109.1041.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/txw2/2.2.11/2df047d8c187a62f2177bf6013f1f9786cdfc8a2/txw2-2.2.11.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.sun.istack/istack-commons-runtime/2.21/c969d8f15c467f0ef7d7b04889afbe7b5d48e22f/istack-commons-runtime-2.21.jar" />
                           </list>
                         </option>
                         <option name="path" value="$PROJECT_DIR$" />
                   </entry>
                 </map>
               </option>
-              <option name="name" value="xscreensaver" />
+              <option name="name" value="android" />
               <option name="projectBuildClasspath">
                 <list>
                   <option value="$PROJECT_DIR$/buildSrc/src/main/java" />
     </option>
   </component>
   <component name="ProjectFrameBounds">
-    <option name="x" value="91" />
-    <option name="y" value="23" />
+    <option name="x" value="90" />
+    <option name="y" value="24" />
     <option name="width" value="1339" />
     <option name="height" value="859" />
   </component>
   <component name="ProjectView">
-    <navigator currentView="AndroidView" proportions="" version="1">
+    <navigator currentView="Scope" currentSubView="Project Files" proportions="" version="1">
       <flattenPackages />
       <showMembers />
       <showModules />
       <foldersAlwaysOnTop value="true" />
     </navigator>
     <panes>
-      <pane id="ProjectPane" />
-      <pane id="Scratches" />
       <pane id="AndroidView">
         <subPane>
           <expand>
           <select />
         </subPane>
       </pane>
-      <pane id="Scope" />
       <pane id="PackagesPane" />
+      <pane id="Scratches" />
+      <pane id="ProjectPane" />
+      <pane id="Scope">
+        <subPane subId="Project Files">
+          <expand>
+            <path>
+              <item name="Root" type="cbb8eebc:String" user="Root" />
+              <item name="android" type="cbb8eebc:String" user="android" />
+            </path>
+            <path>
+              <item name="Root" type="cbb8eebc:String" user="Root" />
+              <item name="android" type="cbb8eebc:String" user="android" />
+              <item name="$PROJECT_DIR$/.." type="cbb8eebc:String" user="$PROJECT_DIR$/.." />
+            </path>
+            <path>
+              <item name="Root" type="cbb8eebc:String" user="Root" />
+              <item name="android" type="cbb8eebc:String" user="android" />
+              <item name="$PROJECT_DIR$/.." type="cbb8eebc:String" user="$PROJECT_DIR$/.." />
+              <item name="gradle/wrapper" type="cbb8eebc:String" user="gradle/wrapper" />
+            </path>
+          </expand>
+          <select />
+        </subPane>
+      </pane>
     </panes>
   </component>
   <component name="PropertiesComponent">
     <property name="SearchEverywhereHistoryKey" value="sdk manager&#9;ACTION&#9;WelcomeScreen.RunAndroidSdkManager" />
     <property name="last_opened_file_path" value="$PROJECT_DIR$" />
     <property name="show.do.not.ask.upgrade.gradle.plugin" value="2.1.0" />
-    <property name="com.android.tools.idea.instantapp.provision.ProvisionBeforeRunTaskProvider.myTimeStamp" value="1523151319009" />
+    <property name="com.android.tools.idea.instantapp.provision.ProvisionBeforeRunTaskProvider.myTimeStamp" value="1533959035566" />
+    <property name="device.picker.selection" value="Nexus_5_8.1" />
   </component>
   <component name="RunDashboard">
     <option name="ruleStates">
     <servers />
   </component>
   <component name="ToolWindowManager">
-    <frame x="91" y="23" width="1339" height="859" extended-state="0" />
+    <frame x="90" y="24" width="1339" height="859" extended-state="0" />
     <layout>
       <window_info id="Android Profiler" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
       <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
       <window_info id="Image Layers" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
       <window_info id="Build Variants" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="true" content_ui="tabs" />
       <window_info id="Capture Analysis" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
-      <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.32928476" sideWeight="0.5057826" order="7" side_tool="true" content_ui="tabs" />
+      <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32928476" sideWeight="0.5312259" order="7" side_tool="true" content_ui="tabs" />
       <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
       <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
       <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
       <window_info id="Captures" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
       <window_info id="Capture Tool" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
       <window_info id="Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
-      <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.2544333" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
-      <window_info id="Build" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.32928476" sideWeight="0.49421743" order="8" side_tool="false" content_ui="tabs" />
+      <window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.2544333" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
+      <window_info id="Build" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32928476" sideWeight="0.47185814" order="8" side_tool="false" content_ui="tabs" />
+      <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.32928476" sideWeight="0.49421743" order="1" side_tool="false" content_ui="tabs" />
       <window_info id="Gradle" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
       <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
       <window_info id="Device File Explorer" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="true" content_ui="tabs" />
       <window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.32839838" sideWeight="0.49730146" order="7" side_tool="false" content_ui="tabs" />
       <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
       <window_info id="Gradle Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
-      <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32968238" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
     </layout>
   </component>
   <component name="Vcs.Log.UiProperties">
     <breakpoint-manager />
     <watches-manager />
   </component>
+  <component name="editorHistoryManager">
+    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="0">
+          <caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="0">
+          <caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="0">
+          <caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="0">
+          <caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="0">
+          <caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="90">
+          <caret line="6" column="0" lean-forward="false" selection-start-line="6" selection-start-column="0" selection-end-line="6" selection-end-column="0" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+  </component>
 </project>
\ No newline at end of file
index 6d1151ff1016792efdd3ea96d84aa81e287e9a13..f0ff9a3e7b5a0624cc19985a797692089e961bc4 100644 (file)
@@ -2,11 +2,12 @@ apply plugin: 'android'
 
 dependencies {
     compile fileTree(include: '*.jar', dir: 'libs')
+    compile "com.android.support:support-v4:27.1.1"
 }
 
 android {
-    compileSdkVersion 21
-    buildToolsVersion "21.1.2"
+    compileSdkVersion 27
+    buildToolsVersion "27.0.3"
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_7
         targetCompatibility JavaVersion.VERSION_1_7
@@ -26,7 +27,7 @@ android {
         }
 
         // Move the tests to tests/java, tests/res, etc...
-        instrumentTest.setRoot('tests')
+        androidTest.setRoot('tests')
 
         // Move the build types to build-types/<type>
         // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
@@ -96,7 +97,7 @@ android {
 
     defaultConfig {
         minSdkVersion 15
-        targetSdkVersion 21
+        targetSdkVersion 27
     }
     productFlavors {
     }
index 28005793fe6d77cf2617795a1a60d2e1709b0f83..1e20a83e369f4fa9de535301d68ab733bdbeaa0b 100644 (file)
@@ -69,6 +69,7 @@ LOCAL_SRC_FILES += \
     hacks/glx/cow_tail.c \
     hacks/glx/cow_udder.c \
     hacks/glx/dolphin.c \
+    hacks/glx/dymaxionmap-coords.c \
     hacks/glx/gllist.c \
     hacks/glx/glschool_alg.c \
     hacks/glx/glschool_gl.c \
index a7aa11b6cae19fc6d8e7b00c0ad9bdedf6aa1aad..d3f543677285b4dd7fa7b1236ae11f1578c717f5 100644 (file)
@@ -2,5 +2,6 @@
 APP_ABI := $(shell echo $$APP_ABI)
 APP_STL := stlport_static
 APP_PLATFORM := android-14
-# ^^ this can be increased
+# ^^ APP_PLATFORM is minimum API version supported
+# https://android.googlesource.com/platform/ndk/+/master/docs/user/common_problems.md#target-api-set-higher-than-device-api
 
index 1209c1b7da49a2d1c4f84096ed9758641100880f..ac0ab4c10b13cc9a713a8594897dda6ce5ca54db 100644 (file)
@@ -24,15 +24,25 @@ import android.os.Build;
 import android.os.Bundle;
 import android.view.View;
 import android.provider.Settings;
+import android.Manifest;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.ContextCompat;
+import android.os.Build;
+import android.content.pm.PackageManager;
 
 public class Activity extends android.app.Activity
   implements View.OnClickListener {
 
+  private boolean wallpaperButtonClicked, daydreamButtonClicked;
+  private final static int MY_REQ_READ_EXTERNAL_STORAGE = 271828;
+
   @Override
   protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     // openList();
     setContentView(R.layout.activity_xscreensaver);
+    wallpaperButtonClicked = false;
+    daydreamButtonClicked = false;
 
     findViewById(R.id.apply_wallpaper).setOnClickListener(this);
     findViewById(R.id.apply_daydream).setOnClickListener(this);
@@ -42,10 +52,18 @@ public class Activity extends android.app.Activity
   public void onClick(View v) {
     switch (v.getId()) {
     case R.id.apply_wallpaper:
-      startActivity(new Intent(WallpaperManager.ACTION_LIVE_WALLPAPER_CHOOSER));
+      wallpaperButtonClicked();
       break;
-
     case R.id.apply_daydream:
+      daydreamButtonClicked();
+      break;
+    }
+  }
+
+  // synchronized when dealing with wallpaper state - perhaps can
+  // narrow down more
+  private synchronized void withProceed() {
+    if (daydreamButtonClicked) {
       String action;
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
         action = Settings.ACTION_DREAM_SETTINGS;
@@ -53,7 +71,99 @@ public class Activity extends android.app.Activity
         action = Settings.ACTION_DISPLAY_SETTINGS;
       }
       startActivity(new Intent(action));
-      break;
+    } else if (wallpaperButtonClicked) {
+      startActivity(new Intent(WallpaperManager.ACTION_LIVE_WALLPAPER_CHOOSER));
+    }
+  }
+
+  private void wallpaperButtonClicked() {
+      wallpaperButtonClicked = true;
+      checkPermission();
+  }
+
+  private void daydreamButtonClicked() {
+      daydreamButtonClicked = true;
+      checkPermission();
+  }
+
+  void checkPermission() {
+      // RES introduced in API 16
+      String permission = Manifest.permission.READ_EXTERNAL_STORAGE;
+      if (havePermission(permission)) {
+          withProceed();
+      } else {
+          noPermission(permission);
+      }
+  }
+
+  private void noPermission(String permission) {
+      int myRequestCode;
+      myRequestCode = MY_REQ_READ_EXTERNAL_STORAGE;
+
+      if (permissionsDeniedRationale(permission)) {
+          showDeniedRationale();
+      } else {
+          requestPermission(permission, myRequestCode);
+      }
+  }
+
+  private boolean permissionsDeniedRationale(String permission) {
+      boolean rationale = ActivityCompat.shouldShowRequestPermissionRationale(this,
+                permission);
+      return rationale;
+  }
+
+  private void requestPermission(String permission, int myRequestCode) {
+      ActivityCompat.requestPermissions(this,
+              new String[]{permission},
+              myRequestCode);
+
+      // myRequestCode is an app-defined int constant.
+      // The callback method gets the result of the request.
+  }
+
+  // TODO: This method should be asynchronous, and not block the thread
+  private void showDeniedRationale() {
+    withProceed();
+  }
+
+  boolean havePermission(String permission) {
+
+      if (Build.VERSION.SDK_INT < 16) {
+          return true;
+      }
+
+      if (permissionGranted(permission)) {
+          return true;
+      }
+
+      return false;
+  }
+
+  private boolean permissionGranted(String permission) {
+        boolean check = ContextCompat.checkSelfPermission(this, permission) ==
+                PackageManager.PERMISSION_GRANTED;
+      return check;
+  }
+
+  public void proceedIfPermissionGranted(int[] grantResults) {
+
+      // If request is cancelled, the result arrays are empty.
+      if (grantResults.length > 0
+              && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+          withProceed();
+      } else if (grantResults.length > 0) {
+          withProceed();
+      }
+  }
+
+  @Override
+  public void onRequestPermissionsResult(int requestCode,
+        String permissions[], int[] grantResults) {
+    switch (requestCode) {
+      case MY_REQ_READ_EXTERNAL_STORAGE:
+          proceedIfPermissionGranted(grantResults);
     }
   }
+
 }
index 8ca6af40588b0fcbb8e8affa8d826f48aa0036d8..a22a26d40c9ed708f604c4a333a05405f1c39d79 100644 (file)
@@ -57,6 +57,11 @@ import android.media.ExifInterface;
 import org.jwz.xscreensaver.TTFAnalyzer;
 import android.util.Log;
 import android.view.Surface;
+import android.Manifest;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.ContextCompat;
+import android.os.Build;
+import android.content.pm.PackageManager;
 
 public class jwxyz
   implements GestureDetector.OnGestureListener,
@@ -100,6 +105,8 @@ public class jwxyz
   public final static int FONT_FACE   = 1;
   public final static int FONT_RANDOM = 2;
 
+  public final static int MY_REQ_READ_EXTERNAL_STORAGE = 271828;
+
   private long nativeRunningHackPtr;
 
   private String hack;
@@ -627,6 +634,38 @@ public class jwxyz
   }
 
 
+  boolean havePermission(String permission) {
+
+        if (Build.VERSION.SDK_INT < 16) {
+            return true;
+        }
+
+        if (permissionGranted(permission)) {
+            return true;
+        }
+
+        return false;
+  }
+
+
+  private boolean permissionGranted(String permission) {
+        boolean check = ContextCompat.checkSelfPermission(app, permission) ==
+                PackageManager.PERMISSION_GRANTED;
+        return check;
+  }
+
+  public Object[] checkThenLoadRandomImage (int target_width, int target_height,
+                                   boolean rotate_p) {
+      // RES introduced in API 16
+      String permission = Manifest.permission.READ_EXTERNAL_STORAGE;
+
+        if (havePermission(permission)) {
+            return loadRandomImage(target_width,target_height,rotate_p);
+        } else {
+            return null;
+        }
+  }
+
   public Object[] loadRandomImage (int target_width, int target_height,
                                    boolean rotate_p) {
 
index 9478b133cbb7b5fbc3c5a4c5ef4462bf7afd059c..dd9566c331d3160cad57ee727b41ad4259134d59 100644 (file)
     <output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
     <exclude-output />
     <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/test/debug" isTestSource="true" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/res" type="java-resource" />
       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/resources" type="java-resource" />
       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/assets" type="java-resource" />
       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/java" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/rs" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/shaders" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/res" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/resources" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/assets" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/aidl" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/rs" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/shaders" isTestSource="true" />
       <sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
       <sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
       <sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
       <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
       <sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
       <sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
+      <sourceFolder url="file://$MODULE_DIR$/tests/res" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/tests/resources" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/tests/assets" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/tests/aidl" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/tests/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/tests/rs" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/tests/shaders" isTestSource="true" />
       <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
       <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
     </content>
-    <orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />
+    <orderEntry type="jdk" jdkName="Android API 27 Platform" jdkType="Android SDK" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-v4-27.1.1" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.1.0@jar" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-fragment-27.1.1" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-annotations:27.1.1@jar" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.core:runtime-1.1.0" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-compat-27.1.1" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.lifecycle:viewmodel-1.1.0" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata-core-1.1.0" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-media-compat-27.1.1" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-core-ui-27.1.1" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.core:common:1.1.0@jar" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-core-utils-27.1.1" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime-1.1.0" level="project" />
   </component>
 </module>
\ No newline at end of file
index 38da6107e0ed226981282f4398a29317f2cabd28..2ac1b1b5660777ff9fc5e6e45864e99f76f0c2a0 100755 (executable)
--- a/configure
+++ b/configure
@@ -16114,7 +16114,7 @@ APPDEFAULTS=$ac_x_app_defaults
 
 
 
-ac_config_files="$ac_config_files Makefile utils/Makefile jwxyz/Makefile hacks/Makefile hacks/glx/Makefile po/Makefile.in driver/Makefile driver/xscreensaver.pam driver/xscreensaver-demo.glade2 driver/XScreenSaver.ad"
+ac_config_files="$ac_config_files Makefile utils/Makefile jwxyz/Makefile hacks/Makefile hacks/images/Makefile hacks/glx/Makefile po/Makefile.in driver/Makefile driver/xscreensaver.pam driver/xscreensaver-demo.glade2 driver/XScreenSaver.ad"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -16825,6 +16825,7 @@ do
     "utils/Makefile") CONFIG_FILES="$CONFIG_FILES utils/Makefile" ;;
     "jwxyz/Makefile") CONFIG_FILES="$CONFIG_FILES jwxyz/Makefile" ;;
     "hacks/Makefile") CONFIG_FILES="$CONFIG_FILES hacks/Makefile" ;;
+    "hacks/images/Makefile") CONFIG_FILES="$CONFIG_FILES hacks/images/Makefile" ;;
     "hacks/glx/Makefile") CONFIG_FILES="$CONFIG_FILES hacks/glx/Makefile" ;;
     "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;;
     "driver/Makefile") CONFIG_FILES="$CONFIG_FILES driver/Makefile" ;;
index 68928a098b9d8e9dd03a82a409e918fffb05b09e..d439bb5cbd72af7b5f366933c42e6774e46d02d2 100644 (file)
@@ -4142,6 +4142,7 @@ AC_OUTPUT(Makefile
           utils/Makefile
           jwxyz/Makefile
           hacks/Makefile
+          hacks/images/Makefile
           hacks/glx/Makefile
           po/Makefile.in
           driver/Makefile
index 1f490f672d5bd787e78121f57534dfc78c851292..55effece66ae7f8194a7eaae91fde289214857fc 100644 (file)
@@ -157,7 +157,7 @@ SAVER_UTIL_SRCS     = $(UTILS_SRC)/fade.c $(UTILS_SRC)/overlay.c \
                  $(DEMO_UTIL_SRCS)
 SAVER_UTIL_OBJS        = $(UTILS_BIN)/fade.o $(UTILS_BIN)/overlay.o \
                  $(UTILS_BIN)/logo.o $(UTILS_BIN)/yarandom.o \
-                 $(UTILS_BIN)/minixpm.o $(UTILS_SRC)/font-retry.o \
+                 $(UTILS_BIN)/minixpm.o $(UTILS_BIN)/font-retry.o \
                  $(DEMO_UTIL_OBJS)
 
 GETIMG_SRCS_1  = xscreensaver-getimage.c
index 932c0fe22bb1f1953681427c64cf47e1a489dccb..f4e29d41843bd08853ef809cb528bead01385131 100644 (file)
@@ -4,8 +4,8 @@
 !            a screen saver and locker for the X window system
 !                            by Jamie Zawinski
 !
-!                              version 5.39
-!                              12-Apr-2018
+!                              version 5.40
+!                              12-Aug-2018
 !
 ! See "man xscreensaver" for more info.  The latest version is always
 ! available at https://www.jwz.org/xscreensaver/
@@ -384,9 +384,12 @@ GetViewPortIsFullOfLies: False
 @GL_KLUDGE@ GL:                                esper -root                                 \n\
 @GL_KLUDGE@ GL:                                vigilance -root                             \n\
 @GL_KLUDGE@ GL:                                crumbler -root                              \n\
+                               filmleader -root                            \n\
+                               glitchpeg -root                             \n\
 @GL_KLUDGE@ GL:                                maze3d -root                                \n\
 @GL_KLUDGE@ GL:                                peepers -root                               \n\
-@GL_KLUDGE@ GL:                                razzledazzle -root                          \n
+@GL_KLUDGE@ GL:                                razzledazzle -root                          \n\
+                               vfeedback -root                             \n
 
 
 
@@ -484,6 +487,7 @@ XScreenSaver.bourneShell:           /bin/sh
 *hacks.energystream.name:   EnergyStream
 *hacks.euler2d.name:        Euler2D
 *hacks.fadeplot.name:       FadePlot
+*hacks.filmleader.name:     FilmLeader
 *hacks.flipflop.name:       FlipFlop
 *hacks.flipscreen3d.name:   FlipScreen3D
 *hacks.fliptext.name:       FlipText
@@ -495,6 +499,7 @@ XScreenSaver.bourneShell:           /bin/sh
 *hacks.gflux.name:          GFlux
 *hacks.gleidescope.name:    Gleidescope
 *hacks.glforestfire.name:   GLForestFire
+*hacks.glitchpeg.name:      GlitchPEG
 *hacks.hyperball.name:      HyperBall
 *hacks.hypercube.name:      HyperCube
 *hacks.ifs.name:            IFS
@@ -537,6 +542,7 @@ XScreenSaver.bourneShell:           /bin/sh
 *hacks.topblock.name:       TopBlock
 *hacks.tronbit.name:        TronBit
 *hacks.unknownpleasures.name:UnknownPleasures
+*hacks.vfeedback.name:      VFeedback
 *hacks.vidwhacker.name:     VidWhacker
 *hacks.webcollage.name:     WebCollage
 *hacks.whirlwindwarp.name:  WhirlWindWarp
index 171d9b094a379a03b2d50f645f366d9758dc2cc8..cd4976edfb1683865dce10bafc25af5ce0100c27 100644 (file)
   GL:                          esper -root                                 \\n\
   GL:                          vigilance -root                             \\n\
   GL:                          crumbler -root                              \\n\
+                               filmleader -root                            \\n\
+                               glitchpeg -root                             \\n\
   GL:                          maze3d -root                                \\n\
   GL:                          peepers -root                               \\n\
-  GL:                          razzledazzle -root                          \\n",
+  GL:                          razzledazzle -root                          \\n\
+                               vfeedback -root                             \\n",
 "XScreenSaver.pointerPollTime:         0:00:05",
 "XScreenSaver.pointerHysteresis:               10",
 "XScreenSaver.initialDelay:            0:00:00",
 "*hacks.energystream.name:   EnergyStream",
 "*hacks.euler2d.name:        Euler2D",
 "*hacks.fadeplot.name:       FadePlot",
+"*hacks.filmleader.name:     FilmLeader",
 "*hacks.flipflop.name:       FlipFlop",
 "*hacks.flipscreen3d.name:   FlipScreen3D",
 "*hacks.fliptext.name:       FlipText",
 "*hacks.gflux.name:          GFlux",
 "*hacks.gleidescope.name:    Gleidescope",
 "*hacks.glforestfire.name:   GLForestFire",
+"*hacks.glitchpeg.name:      GlitchPEG",
 "*hacks.hyperball.name:      HyperBall",
 "*hacks.hypercube.name:      HyperCube",
 "*hacks.ifs.name:            IFS",
 "*hacks.topblock.name:       TopBlock",
 "*hacks.tronbit.name:        TronBit",
 "*hacks.unknownpleasures.name:UnknownPleasures",
+"*hacks.vfeedback.name:      VFeedback",
 "*hacks.vidwhacker.name:     VidWhacker",
 "*hacks.webcollage.name:     WebCollage",
 "*hacks.whirlwindwarp.name:  WhirlWindWarp",
index 6335d931e8cb4dced2ffffc8cacd1a75052d0f20..ba1ef308ab9d56e3e90d42293123e624a19fc13e 100755 (executable)
@@ -53,7 +53,7 @@ BEGIN { eval 'use LWP::Simple;' }
 
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.46 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.52 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 
@@ -103,6 +103,7 @@ my $nondir_re = '\.(' . join("|", @nondir_extensions) . ')$';
 # JPEG, GIF, and PNG files that are are smaller than this are rejected:
 # this is so that you can use an image directory that contains both big
 # images and thumbnails, and have it only select the big versions.
+# But, if all of your images are smaller than this, all will be rejected.
 #
 my $min_image_width  = 500;
 my $min_image_height = 500;
@@ -117,6 +118,10 @@ my $stat_count = 0;            # number of files/dirs stat'ed
 my $skip_count_unstat = 0;  # number of files skipped without stat'ing
 my $skip_count_stat = 0;    # number of files skipped after stat
 
+my $config_file = $ENV{HOME} . "/.xscreensaver";
+my $image_directory = undef;
+
+
 sub find_all_files($);
 sub find_all_files($) {
   my ($dir) = @_;
@@ -451,7 +456,7 @@ sub parse_feed($) {
   # malicious images really do exist, so for xscreensaver-getimage-file,
   # let's actually require that SSL be installed properly.
 
-
+  print STDERR "$progname: loading $url\n" if ($verbose);
   my $body = (LWP::Simple::get($url) || '');
 
   if ($body !~ m@^\s*<(\?xml|rss)\b@si) {
@@ -563,12 +568,19 @@ sub parse_feed($) {
       }
     }
 
-    # Then look for <description>... with an <img src="..."> inside.
+    # Then look for <content:encoded> or <description>... with an
+    # <img src="..."> inside. If more than one image, take the first.
     #
-    if (! $iurl) {
-      foreach my $link ($item =~ m@<description[^<>]*>(.*?)</description>@gsi) {
+    foreach my $t ('content:encoded', 'description') {
+      last if $iurl;
+      foreach my $link ($item =~ m@<$t[^<>]*>(.*?)</$t>@gsi) {
         last if $iurl;
-        my $desc = html_unquote($1);
+        my $desc = $1;
+        if ($desc =~ m@<!\[CDATA\[\s*(.*?)\s*\]\]>@gs) {
+          $desc = $1;
+        } else {
+          $desc = html_unquote($desc);
+        }
         my ($href) = ($desc =~ m@<IMG[^<>]*\bSRC=[\"\']?([^\"\'<>]+)@si);
         $iurl = html_unquote($href) if ($href);
         # If IMG SRC has a bogus extension, pretend it's a JPEG.
@@ -577,10 +589,6 @@ sub parse_feed($) {
       }
     }
 
-    # Could also do <content:encoded>, but the above probably covers all
-    # of the real-world possibilities.
-
-
     # Find a unique ID for this image, to defeat image farms.
     # First look for <id>...</id>
     ($id) = ($item =~ m!<ID\b[^<>]*>\s*([^<>]+?)\s*</ID>!si) unless $id;
@@ -817,7 +825,8 @@ sub mirror_feed($) {
     closedir $dirh;
 
     if ($count <= 0) {
-      print STDERR "$progname: no files in cache of $url\n" if ($verbose);
+      print STDERR "$progname: no image files in cache of $url\n"
+        if ($verbose);
       $poll_p = 1;
     }
   }
@@ -842,9 +851,16 @@ sub mirror_feed($) {
     my @urls = parse_feed ($url);
     print STDERR "$progname: " . ($#urls + 1) . " images\n"
       if ($verbose > 1);
+    my %seen_src_urls;
     foreach my $p (@urls) {
       my ($furl, $id) = @$p;
       $furl = expand_url ($furl, $url);
+
+      # No need to download the same image twice, even if it was in the feed
+      # multiple times under different GUIDs.
+      next if ($seen_src_urls{$furl});
+      $seen_src_urls{$furl} = 1;
+
       my $f = download_image ($furl, $id, $dir);
       next unless $f;
       $files{$f} = 1;    # Got it, don't delete
@@ -956,25 +972,40 @@ sub find_random_file($) {
   write_cache ($dir);
 
   if ($#all_files < 0) {
-    print STDERR "$progname: no files in $dir\n";
+    print STDERR "$progname: no image files in $dir\n";
     exit 1;
   }
 
   my $max_tries = 50;
-  for (my $i = 0; $i < $max_tries; $i++) {
-
-    my $n = int (rand ($#all_files + 1));
-    my $file = $all_files[$n];
-    if (large_enough_p ($file)) {
-      if (! $url) {
-        $file =~ s@^\Q$dir/@@so || die;  # remove $dir from front
+  my $total_files = @all_files;
+  my $sparse_p = ($total_files < 20);
+
+  # If the directory has a lot of files in it:
+  #   Make a pass through looking for hirez files (assume some are thumbs);
+  #   If we found none, then, select any other file at random.
+  # Otherwise if there are a small number of files:
+  #   Just select one at random (in case there's like, just one hirez).
+
+  for (my $check_size_p = $sparse_p ? 0 : 1;
+       $check_size_p >= 0; $check_size_p--) {
+
+    for (my $i = 0; $i < $max_tries; $i++) {
+      my $n = int (rand ($total_files));
+      my $file = $all_files[$n];
+      if (!$check_size_p || large_enough_p ($file)) {
+        if (! $url) {
+          $file =~ s@^\Q$dir/@@so || die;  # remove $dir from front
+        }
+        return $file;
       }
-      return $file;
     }
   }
 
-  print STDERR "$progname: no suitable images in $dir " .
-               "(after $max_tries tries)\n";
+  print STDERR "$progname: no suitable images in " . ($url || $dir) . " -- " .
+               ($total_files <= $max_tries
+                ? "all $total_files images"
+                : "$max_tries of $total_files images") .
+               " are smaller than ${min_image_width}x${min_image_height}.\n";
 
   # If we got here, blow away the cache.  Maybe it's stale.
   unlink $cache_file_name if $cache_file_name;
@@ -1119,6 +1150,81 @@ sub image_file_size($) {
 }
 
 
+# Reads the prefs we use from ~/.xscreensaver
+#
+sub get_x11_prefs() {
+  my $got_any_p = 0;
+
+  if (open (my $in, '<', $config_file)) {
+    print STDERR "$progname: reading $config_file\n" if ($verbose > 1);
+    local $/ = undef;  # read entire file
+    my $body = <$in>;
+    close $in;
+    $got_any_p = get_x11_prefs_1 ($body);
+
+  } elsif ($verbose > 1) {
+    print STDERR "$progname: $config_file: $!\n";
+  }
+
+  if (! $got_any_p && defined ($ENV{DISPLAY})) {
+    # We weren't able to read settings from the .xscreensaver file.
+    # Fall back to any settings in the X resource database
+    # (/usr/X11R6/lib/X11/app-defaults/XScreenSaver)
+    #
+    print STDERR "$progname: reading X resources\n" if ($verbose > 1);
+    my $body = `appres XScreenSaver xscreensaver -1`;
+    $got_any_p = get_x11_prefs_1 ($body);
+  }
+}
+
+
+sub get_x11_prefs_1($) {
+  my ($body) = @_;
+
+  my $got_any_p = 0;
+  $body =~ s@\\\n@@gs;
+  $body =~ s@^[ \t]*#[^\n]*$@@gm;
+
+  if ($body =~ m/^[.*]*imageDirectory:[ \t]*([^\s]+)\s*$/im) {
+    $image_directory = $1;
+    $got_any_p = 1;
+  }
+  return $got_any_p;
+}
+
+
+sub get_cocoa_prefs($) {
+  my ($id) = @_;
+  print STDERR "$progname: reading Cocoa prefs: \"$id\"\n" if ($verbose > 1);
+  my $v = get_cocoa_pref_1 ($id, "imageDirectory");
+  $v = '~/Pictures' unless defined ($v);  # Match default in XScreenSaverView
+  $image_directory = $v if defined ($v);
+}
+
+
+sub get_cocoa_pref_1($$) {
+  my ($id, $key) = @_;
+  # make sure there's nothing stupid/malicious in either string.
+  $id  =~ s/[^-a-z\d. ]/_/gsi;
+  $key =~ s/[^-a-z\d. ]/_/gsi;
+  my $cmd = "defaults -currentHost read \"$id\" \"$key\"";
+
+  print STDERR "$progname: executing $cmd\n"
+    if ($verbose > 3);
+
+  my $val = `$cmd 2>/dev/null`;
+  $val =~ s/^\s+//s;
+  $val =~ s/\s+$//s;
+
+  print STDERR "$progname: Cocoa: $id $key = \"$val\"\n"
+    if ($verbose > 2);
+
+  $val = undef if ($val =~ m/^$/s);
+
+  return $val;
+}
+
+
 sub error($) {
   my ($err) = @_;
   print STDERR "$progname: $err\n";
@@ -1126,7 +1232,7 @@ sub error($) {
 }
 
 sub usage() {
-  print STDERR "usage: $progname [--verbose] directory-or-feed-url\n\n" .
+  print STDERR "usage: $progname [--verbose] [ directory-or-feed-url ]\n\n" .
   "       Prints the name of a randomly-selected image file.  The directory\n" .
   "       is searched recursively.  Images smaller than " .
          "${min_image_width}x${min_image_height} are excluded.\n" .
@@ -1138,7 +1244,8 @@ sub usage() {
 }
 
 sub main() {
-  my $dir = undef;
+  my $cocoa_id = undef;
+  my $abs_p = 0;
 
   while ($_ = $ARGV[0]) {
     shift @ARGV;
@@ -1149,28 +1256,59 @@ sub main() {
     elsif (m/^--?no-spotlight$/s) { $use_spotlight_p = 0; }
     elsif (m/^--?cache$/s)        { $cache_p = 1; }
     elsif (m/^--?no-?cache$/s)    { $cache_p = 0; }
+    elsif (m/^--?cocoa$/)         { $cocoa_id = shift @ARGV; }
+    elsif (m/^--?abs(olute)?$/)   { $abs_p = 1; }
     elsif (m/^-./)                { usage; }
-    elsif (!defined($dir))        { $dir = $_; }
+    elsif (!defined($image_directory)) { $image_directory = $_; }
     else                          { usage; }
   }
 
-  usage unless (defined($dir));
+  # Most hacks (X11 and Cocoa) pass a --directory value on the command line,
+  # but if they don't, look it up from the resources.  Currently this only
+  # happens with "glitchpeg" which invokes xscreensaver-getimage-file
+  # directly instead of going through the traditional path.
+  #
+  if (! $image_directory) {
+    if (!defined ($cocoa_id)) {
+      # see OSX/XScreenSaverView.m
+      $cocoa_id = $ENV{XSCREENSAVER_CLASSPATH};
+    }
+
+    if (defined ($cocoa_id)) {
+      get_cocoa_prefs($cocoa_id);
+      error ("no imageDirectory in $cocoa_id") unless $image_directory;
+    } else {
+      get_x11_prefs();
+      error ("no imageDirectory in X11 resources") unless $image_directory;
+    }
+  }
+
+  usage unless (defined($image_directory));
 
-  $dir =~ s@^feed:@http:@si;
+  $image_directory =~ s@^feed:@http:@si;
 
-  if ($dir =~ m/^https?:/si) {
+  if ($image_directory =~ m/^https?:/si) {
     # ok
   } else {
-    $dir =~ s@^~/@$ENV{HOME}/@s;     # allow literal "~/"
-    $dir =~ s@/+$@@s;             # omit trailing /
+    $image_directory =~ s@^~/@$ENV{HOME}/@s;     # allow literal "~/"
+    $image_directory =~ s@/+$@@s;               # omit trailing /
 
-    if (! -d $dir) {
-      print STDERR "$progname: $dir: not a directory or URL\n";
+    if (! -d $image_directory) {
+      print STDERR "$progname: $image_directory not a directory or URL\n";
       usage;
     }
   }
 
-  my $file = find_random_file ($dir);
+  my $file = find_random_file ($image_directory);
+
+  # With --absolute return fully qualified paths instead of relative to --dir.
+  if ($abs_p &&
+      $file !~ m@^/@ &&
+      $image_directory =~ m@^/@s) {
+    $file = "$image_directory/$file";
+    $file =~ s@//+@/@gs;
+  }
+
   print STDOUT "$file\n";
 }
 
index b9715aec49720fc2b42e6be5b3d96d6a212961d0..092540d478695bc297a1ffd5b209ef33ea7a87ec 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2001-2016 by Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2001-2018 by Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -316,9 +316,11 @@ static void
 colorbars (Screen *screen, Visual *visual, Drawable drawable, Colormap cmap)
 {
   Pixmap mask = 0;
+  unsigned long *pixels; /* ignored - unfreed */
+  int npixels;
   Pixmap logo = xscreensaver_logo (screen, visual, drawable, cmap,
                                    BlackPixelOfScreen (screen),
-                                   0, 0, &mask, True);
+                                   &pixels, &npixels, &mask, True);
   draw_colorbars (screen, visual, drawable, cmap, 0, 0, 0, 0, logo, mask);
   XFreePixmap (DisplayOfScreen (screen), logo);
   XFreePixmap (DisplayOfScreen (screen), mask);
index 6089af80569db48968428ba4314918b7270a48c6..45568728a094158206a02d96089f3ae0e428c055 100644 (file)
@@ -64,6 +64,7 @@ TEXT_LIBS     = @PTY_LIBS@
 
 UTILS_SRC      = $(srcdir)/../utils
 UTILS_BIN      = ../utils
+HACK_BIN       = .
 
 INCLUDES_1     = -I. -I$(srcdir) -I$(UTILS_SRC) -I..
 INCLUDES       = $(INCLUDES_1) @INCLUDES@
@@ -89,7 +90,7 @@ UTIL_OBJS     = $(UTILS_BIN)/alpha.o $(UTILS_BIN)/colors.o \
                  $(UTILS_BIN)/textclient.o $(UTILS_BIN)/aligned_malloc.o \
                  $(UTILS_BIN)/thread_util.o $(UTILS_BIN)/pow2.o \
                  $(UTILS_BIN)/xft.o $(UTILS_BIN)/utf8wc.o \
-                 $(UTILS_BIN)/font-retry.o
+                 $(UTILS_BIN)/font-retry-xft.o
 
 SRCS           = attraction.c blitspin.c bouboule.c braid.c bubbles.c \
                  bubbles-default.c decayscreen.c deco.c drift.c flag.c \
@@ -114,13 +115,14 @@ SRCS              = attraction.c blitspin.c bouboule.c braid.c bubbles.c \
                  euler2d.c juggle.c polyominoes.c thornbird.c fluidballs.c \
                  anemone.c halftone.c metaballs.c eruption.c popsquares.c \
                  barcode.c piecewise.c cloudlife.c fontglide.c apple2.c \
-                 apple2-main.c analogtv.c xanalogtv.c pong.c wormhole.c \
-                 pacman.c pacman_ai.c pacman_level.c \
+                 apple2-main.c analogtv.c xanalogtv.c pong.c filmleader.c \
+                 wormhole.c pacman.c pacman_ai.c pacman_level.c \
                  fuzzyflakes.c anemotaxis.c memscroller.c substrate.c \
                  intermomentary.c fireworkx.c fiberlamp.c \
                  boxfit.c interaggregate.c celtic.c cwaves.c m6502.c \
                  asm6502.c abstractile.c lcdscrub.c hexadrop.c \
                  tessellimage.c delaunay.c recanim.c binaryring.c \
+                 glitchpeg.c vfeedback.c \
                  webcollage-cocoa.m webcollage-helper-cocoa.m testx11.c
 SCRIPTS                = vidwhacker webcollage ljlatest
 
@@ -154,14 +156,14 @@ OBJS              = attraction.o blitspin.o bouboule.o braid.o bubbles.o \
                  euler2d.o juggle.o polyominoes.o thornbird.o fluidballs.o \
                  anemone.o halftone.o metaballs.o eruption.o popsquares.o \
                  barcode.o piecewise.o cloudlife.o fontglide.o apple2.o \
-                 apple2-main.o analogtv.o xanalogtv.o pong.o wormhole.o \
-                 pacman.o pacman_ai.o pacman_level.o \
+                 apple2-main.o analogtv.o xanalogtv.o pong.o filmleader.o \
+                 wormhole.o pacman.o pacman_ai.o pacman_level.o \
                  fuzzyflakes.o anemotaxis.o memscroller.o substrate.o \
                  intermomentary.o fireworkx.o fiberlamp.o boxfit.o \
                  interaggregate.o celtic.o cwaves.o webcollage-cocoa.o \
                  webcollage-helper-cocoa.o m6502.o asm6502.o abstractile.o \
                  lcdscrub.o hexadrop.o tessellimage.o delaunay.o recanim.o \
-                 binaryring.o testx11.o
+                 binaryring.o glitchpeg.o vfeedback.o testx11.o
 
 EXES           = attraction blitspin bouboule braid decayscreen deco \
                  drift flame galaxy grav greynetic halo \
@@ -179,11 +181,11 @@ EXES              = attraction blitspin bouboule braid decayscreen deco \
                  speedmine vermiculate twang apollonian euler2d \
                  polyominoes thornbird  fluidballs anemone halftone \
                  metaballs eruption popsquares barcode piecewise cloudlife \
-                 fontglide apple2 xanalogtv pong  wormhole \
+                 fontglide apple2 xanalogtv pong filmleader wormhole \
                  pacman fuzzyflakes anemotaxis memscroller substrate \
                  intermomentary fireworkx fiberlamp boxfit interaggregate \
                  celtic cwaves m6502 abstractile lcdscrub hexadrop \
-                 tessellimage binaryring \
+                 tessellimage binaryring glitchpeg vfeedback \
                  @JPEG_EXES@
 JPEG_EXES      = webcollage-helper
 
@@ -193,7 +195,7 @@ RETIRED_EXES        = ant bubbles critical flag forest hyperball hypercube laser \
 
 HACK_OBJS_1    = fps.o $(UTILS_BIN)/resources.o $(UTILS_BIN)/visual.o \
                  $(UTILS_BIN)/usleep.o $(UTILS_BIN)/yarandom.o \
-                 $(UTILS_BIN)/utf8wc.o $(UTILS_BIN)/font-retry.o \
+                 $(UTILS_BIN)/utf8wc.o $(UTILS_BIN)/font-retry-xft.o \
                  @XMU_OBJS@ @XFT_OBJS@ @ANIM_OBJS@
 HACK_OBJS      = screenhack.o $(HACK_OBJS_1)
 XLOCK_OBJS     = screenhack.o xlockmore.o $(COLOR_OBJS) $(HACK_OBJS_1) \
@@ -236,12 +238,13 @@ MEN               = anemone.man apollonian.man attraction.man \
                  xrayswarm.man xspirograph.man \
                  zoom.man halftone.man eruption.man metaballs.man \
                  barcode.man piecewise.man cloudlife.man ljlatest.man \
-                 fontglide.man apple2.man xanalogtv.man pong.man \
-                 wormhole.man pacman.man fuzzyflakes.man \
+                 fontglide.man apple2.man xanalogtv.man filmleader.man \
+                 pong.man wormhole.man pacman.man fuzzyflakes.man \
                  anemotaxis.man memscroller.man substrate.man \
                  intermomentary.man fireworkx.man fiberlamp.man boxfit.man \
                  interaggregate.man celtic.man cwaves.man abstractile.man \
-                 lcdscrub.man hexadrop.man tessellimage.man binaryring.man
+                 lcdscrub.man hexadrop.man tessellimage.man binaryring.man \
+                 glitchpeg.man vfeedback.man
 
 RETIRED_MEN    = ant.man bubbles.man critical.man flag.man forest.man \
                  laser.man lightning.man lisa.man lissie.man lmorph.man \
@@ -523,7 +526,7 @@ $(UTILS_BIN)/textclient.o:  $(UTILS_SRC)/textclient.c
 $(UTILS_BIN)/aligned_malloc.o: $(UTILS_SRC)/aligned_malloc.c
 $(UTILS_BIN)/thread_util.o:    $(UTILS_SRC)/thread_util.c
 $(UTILS_BIN)/pow2.o:           $(UTILS_SRC)/pow2.c
-$(UTILS_BIN)/font-retry.o:     $(UTILS_SRC)/font-retry.c
+$(UTILS_BIN)/font-retry-xft.o: $(UTILS_SRC)/font-retry.c
 
 $(UTIL_OBJS):
        cd $(UTILS_BIN) ; \
@@ -565,7 +568,7 @@ test-utf8wc: $(UTILS_SRC)/utf8wc.c
        -o $@ -DSELFTEST $<
 
 # Make sure the images have been packaged. This is the first one hit:
-$(srcdir)/images/gen/nose-f1_png.h:
+$(HACK_BIN)/images/gen/nose-f1_png.h:
        cd $(srcdir)/images && $(MAKE)
 
 # The rules for those hacks which follow the `screenhack.c' API.
@@ -868,6 +871,16 @@ hexadrop:  hexadrop.o      $(HACK_OBJS) $(COL)
 tessellimage:  tessellimage.o  delaunay.o $(HACK_OBJS) $(GRAB)
        $(CC_HACK) -o $@ $@.o   delaunay.o $(HACK_OBJS) $(GRAB) $(HACK_LIBS)
 
+glitchpeg:     glitchpeg.o     $(HACK_OBJS) $(PNG)
+       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(PNG) $(PNG_LIBS)
+
+filmleader:    filmleader.o    $(HACK_OBJS) $(ATV) $(GRAB) $(PNG)
+       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(ATV) $(GRAB) $(PNG) $(PNG_LIBS) $(HACK_LIBS) $(THRL)
+
+vfeedback:     vfeedback.o     $(HACK_OBJS) $(ATV) $(GRAB) $(PNG)
+       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(ATV) $(GRAB) $(PNG) $(PNG_LIBS) $(HACK_LIBS) $(THRL)
+
+
 testx11:       testx11.o       glx/rotator.o $(HACK_OBJS) $(COL) $(PNG) $(BARS) $(ERASE)
        $(CC_HACK) -o $@ $@.o   glx/rotator.o $(HACK_OBJS) $(COL) $(PNG) $(BARS) $(ERASE) $(PNG_LIBS)
 
@@ -1011,6 +1024,7 @@ webcollage-helper: webcollage-helper.o
 
 abstractile.o: ../config.h
 abstractile.o: $(srcdir)/fps.h
+abstractile.o: $(srcdir)/recanim.h
 abstractile.o: $(srcdir)/screenhackI.h
 abstractile.o: $(srcdir)/screenhack.h
 abstractile.o: $(UTILS_SRC)/colors.h
@@ -1036,6 +1050,7 @@ analogtv.o: $(UTILS_SRC)/yarandom.h
 analogtv.o: $(srcdir)/ximage-loader.h
 anemone.o: ../config.h
 anemone.o: $(srcdir)/fps.h
+anemone.o: $(srcdir)/recanim.h
 anemone.o: $(srcdir)/screenhackI.h
 anemone.o: $(srcdir)/screenhack.h
 anemone.o: $(UTILS_SRC)/colors.h
@@ -1049,6 +1064,7 @@ anemone.o: $(UTILS_SRC)/xdbe.h
 anemone.o: $(UTILS_SRC)/yarandom.h
 anemotaxis.o: ../config.h
 anemotaxis.o: $(srcdir)/fps.h
+anemotaxis.o: $(srcdir)/recanim.h
 anemotaxis.o: $(srcdir)/screenhackI.h
 anemotaxis.o: $(srcdir)/screenhack.h
 anemotaxis.o: $(UTILS_SRC)/colors.h
@@ -1063,6 +1079,7 @@ anemotaxis.o: $(UTILS_SRC)/yarandom.h
 ant.o: $(srcdir)/automata.h
 ant.o: ../config.h
 ant.o: $(srcdir)/fps.h
+ant.o: $(srcdir)/recanim.h
 ant.o: $(srcdir)/screenhackI.h
 ant.o: $(UTILS_SRC)/colors.h
 ant.o: $(UTILS_SRC)/erase.h
@@ -1077,6 +1094,7 @@ ant.o: $(srcdir)/xlockmoreI.h
 ant.o: $(srcdir)/xlockmore.h
 apollonian.o: ../config.h
 apollonian.o: $(srcdir)/fps.h
+apollonian.o: $(srcdir)/recanim.h
 apollonian.o: $(srcdir)/screenhackI.h
 apollonian.o: $(UTILS_SRC)/colors.h
 apollonian.o: $(UTILS_SRC)/erase.h
@@ -1093,6 +1111,7 @@ apple2-main.o: $(srcdir)/analogtv.h
 apple2-main.o: $(srcdir)/apple2.h
 apple2-main.o: ../config.h
 apple2-main.o: $(srcdir)/fps.h
+apple2-main.o: $(srcdir)/recanim.h
 apple2-main.o: $(srcdir)/screenhackI.h
 apple2-main.o: $(srcdir)/screenhack.h
 apple2-main.o: $(UTILS_SRC)/aligned_malloc.h
@@ -1113,6 +1132,7 @@ apple2.o: $(srcdir)/apple2.h
 apple2.o: ../config.h
 apple2.o: $(srcdir)/fps.h
 apple2.o: $(srcdir)/images/gen/apple2font_png.h
+apple2.o: $(srcdir)/recanim.h
 apple2.o: $(srcdir)/screenhackI.h
 apple2.o: $(UTILS_SRC)/aligned_malloc.h
 apple2.o: $(UTILS_SRC)/colors.h
@@ -1131,6 +1151,7 @@ asm6502.o: ../config.h
 asm6502.o: $(UTILS_SRC)/yarandom.h
 attraction.o: ../config.h
 attraction.o: $(srcdir)/fps.h
+attraction.o: $(srcdir)/recanim.h
 attraction.o: $(srcdir)/screenhackI.h
 attraction.o: $(srcdir)/screenhack.h
 attraction.o: $(UTILS_SRC)/colors.h
@@ -1144,6 +1165,7 @@ attraction.o: $(UTILS_SRC)/visual.h
 attraction.o: $(UTILS_SRC)/yarandom.h
 barcode.o: ../config.h
 barcode.o: $(srcdir)/fps.h
+barcode.o: $(srcdir)/recanim.h
 barcode.o: $(srcdir)/screenhackI.h
 barcode.o: $(srcdir)/screenhack.h
 barcode.o: $(UTILS_SRC)/colors.h
@@ -1156,6 +1178,7 @@ barcode.o: $(UTILS_SRC)/visual.h
 barcode.o: $(UTILS_SRC)/yarandom.h
 binaryring.o: ../config.h
 binaryring.o: $(srcdir)/fps.h
+binaryring.o: $(srcdir)/recanim.h
 binaryring.o: $(srcdir)/screenhackI.h
 binaryring.o: $(srcdir)/screenhack.h
 binaryring.o: $(UTILS_SRC)/colors.h
@@ -1168,6 +1191,7 @@ binaryring.o: $(UTILS_SRC)/visual.h
 binaryring.o: $(UTILS_SRC)/yarandom.h
 blaster.o: ../config.h
 blaster.o: $(srcdir)/fps.h
+blaster.o: $(srcdir)/recanim.h
 blaster.o: $(srcdir)/screenhackI.h
 blaster.o: $(srcdir)/screenhack.h
 blaster.o: $(UTILS_SRC)/colors.h
@@ -1181,6 +1205,7 @@ blaster.o: $(UTILS_SRC)/yarandom.h
 blitspin.o: ../config.h
 blitspin.o: $(srcdir)/fps.h
 blitspin.o: $(srcdir)/images/gen/som_png.h
+blitspin.o: $(srcdir)/recanim.h
 blitspin.o: $(srcdir)/screenhackI.h
 blitspin.o: $(srcdir)/screenhack.h
 blitspin.o: $(UTILS_SRC)/colors.h
@@ -1195,6 +1220,7 @@ blitspin.o: $(UTILS_SRC)/yarandom.h
 blitspin.o: $(srcdir)/ximage-loader.h
 bouboule.o: ../config.h
 bouboule.o: $(srcdir)/fps.h
+bouboule.o: $(srcdir)/recanim.h
 bouboule.o: $(srcdir)/screenhackI.h
 bouboule.o: $(UTILS_SRC)/colors.h
 bouboule.o: $(UTILS_SRC)/erase.h
@@ -1209,6 +1235,7 @@ bouboule.o: $(srcdir)/xlockmoreI.h
 bouboule.o: $(srcdir)/xlockmore.h
 boxfit.o: ../config.h
 boxfit.o: $(srcdir)/fps.h
+boxfit.o: $(srcdir)/recanim.h
 boxfit.o: $(srcdir)/screenhackI.h
 boxfit.o: $(srcdir)/screenhack.h
 boxfit.o: $(UTILS_SRC)/colors.h
@@ -1222,6 +1249,7 @@ boxfit.o: $(UTILS_SRC)/yarandom.h
 boxfit.o: $(srcdir)/ximage-loader.h
 braid.o: ../config.h
 braid.o: $(srcdir)/fps.h
+braid.o: $(srcdir)/recanim.h
 braid.o: $(srcdir)/screenhackI.h
 braid.o: $(UTILS_SRC)/colors.h
 braid.o: $(UTILS_SRC)/erase.h
@@ -1249,6 +1277,7 @@ bsod.o: $(srcdir)/images/gen/mac_png.h
 bsod.o: $(srcdir)/images/gen/osx_10_2_png.h
 bsod.o: $(srcdir)/images/gen/osx_10_3_png.h
 bsod.o: $(srcdir)/images/gen/ransomware_png.h
+bsod.o: $(srcdir)/recanim.h
 bsod.o: $(srcdir)/screenhackI.h
 bsod.o: $(srcdir)/screenhack.h
 bsod.o: $(UTILS_SRC)/aligned_malloc.h
@@ -1313,6 +1342,7 @@ bubbles-default.o: $(UTILS_SRC)/yarandom.h
 bubbles.o: $(srcdir)/bubbles.h
 bubbles.o: ../config.h
 bubbles.o: $(srcdir)/fps.h
+bubbles.o: $(srcdir)/recanim.h
 bubbles.o: $(srcdir)/screenhackI.h
 bubbles.o: $(srcdir)/screenhack.h
 bubbles.o: $(UTILS_SRC)/colors.h
@@ -1326,6 +1356,7 @@ bubbles.o: $(UTILS_SRC)/yarandom.h
 bubbles.o: $(srcdir)/ximage-loader.h
 bumps.o: ../config.h
 bumps.o: $(srcdir)/fps.h
+bumps.o: $(srcdir)/recanim.h
 bumps.o: $(srcdir)/screenhackI.h
 bumps.o: $(srcdir)/screenhack.h
 bumps.o: $(UTILS_SRC)/colors.h
@@ -1339,6 +1370,7 @@ bumps.o: $(UTILS_SRC)/xshm.h
 bumps.o: $(UTILS_SRC)/yarandom.h
 ccurve.o: ../config.h
 ccurve.o: $(srcdir)/fps.h
+ccurve.o: $(srcdir)/recanim.h
 ccurve.o: $(srcdir)/screenhackI.h
 ccurve.o: $(srcdir)/screenhack.h
 ccurve.o: $(UTILS_SRC)/colors.h
@@ -1352,6 +1384,7 @@ ccurve.o: $(UTILS_SRC)/visual.h
 ccurve.o: $(UTILS_SRC)/yarandom.h
 celtic.o: ../config.h
 celtic.o: $(srcdir)/fps.h
+celtic.o: $(srcdir)/recanim.h
 celtic.o: $(srcdir)/screenhackI.h
 celtic.o: $(srcdir)/screenhack.h
 celtic.o: $(UTILS_SRC)/colors.h
@@ -1365,6 +1398,7 @@ celtic.o: $(UTILS_SRC)/visual.h
 celtic.o: $(UTILS_SRC)/yarandom.h
 cloudlife.o: ../config.h
 cloudlife.o: $(srcdir)/fps.h
+cloudlife.o: $(srcdir)/recanim.h
 cloudlife.o: $(srcdir)/screenhackI.h
 cloudlife.o: $(srcdir)/screenhack.h
 cloudlife.o: $(UTILS_SRC)/colors.h
@@ -1377,6 +1411,7 @@ cloudlife.o: $(UTILS_SRC)/visual.h
 cloudlife.o: $(UTILS_SRC)/yarandom.h
 compass.o: ../config.h
 compass.o: $(srcdir)/fps.h
+compass.o: $(srcdir)/recanim.h
 compass.o: $(srcdir)/screenhackI.h
 compass.o: $(srcdir)/screenhack.h
 compass.o: $(UTILS_SRC)/colors.h
@@ -1390,6 +1425,7 @@ compass.o: $(UTILS_SRC)/xdbe.h
 compass.o: $(UTILS_SRC)/yarandom.h
 coral.o: ../config.h
 coral.o: $(srcdir)/fps.h
+coral.o: $(srcdir)/recanim.h
 coral.o: $(srcdir)/screenhackI.h
 coral.o: $(srcdir)/screenhack.h
 coral.o: $(UTILS_SRC)/colors.h
@@ -1403,6 +1439,7 @@ coral.o: $(UTILS_SRC)/visual.h
 coral.o: $(UTILS_SRC)/yarandom.h
 critical.o: ../config.h
 critical.o: $(srcdir)/fps.h
+critical.o: $(srcdir)/recanim.h
 critical.o: $(srcdir)/screenhackI.h
 critical.o: $(srcdir)/screenhack.h
 critical.o: $(UTILS_SRC)/colors.h
@@ -1416,6 +1453,7 @@ critical.o: $(UTILS_SRC)/visual.h
 critical.o: $(UTILS_SRC)/yarandom.h
 crystal.o: ../config.h
 crystal.o: $(srcdir)/fps.h
+crystal.o: $(srcdir)/recanim.h
 crystal.o: $(srcdir)/screenhackI.h
 crystal.o: $(UTILS_SRC)/colors.h
 crystal.o: $(UTILS_SRC)/erase.h
@@ -1430,6 +1468,7 @@ crystal.o: $(srcdir)/xlockmoreI.h
 crystal.o: $(srcdir)/xlockmore.h
 cwaves.o: ../config.h
 cwaves.o: $(srcdir)/fps.h
+cwaves.o: $(srcdir)/recanim.h
 cwaves.o: $(srcdir)/screenhackI.h
 cwaves.o: $(srcdir)/screenhack.h
 cwaves.o: $(UTILS_SRC)/colors.h
@@ -1443,6 +1482,7 @@ cwaves.o: $(UTILS_SRC)/yarandom.h
 cwaves.o: $(srcdir)/ximage-loader.h
 cynosure.o: ../config.h
 cynosure.o: $(srcdir)/fps.h
+cynosure.o: $(srcdir)/recanim.h
 cynosure.o: $(srcdir)/screenhackI.h
 cynosure.o: $(srcdir)/screenhack.h
 cynosure.o: $(UTILS_SRC)/colors.h
@@ -1455,6 +1495,7 @@ cynosure.o: $(UTILS_SRC)/visual.h
 cynosure.o: $(UTILS_SRC)/yarandom.h
 decayscreen.o: ../config.h
 decayscreen.o: $(srcdir)/fps.h
+decayscreen.o: $(srcdir)/recanim.h
 decayscreen.o: $(srcdir)/screenhackI.h
 decayscreen.o: $(srcdir)/screenhack.h
 decayscreen.o: $(UTILS_SRC)/colors.h
@@ -1467,6 +1508,7 @@ decayscreen.o: $(UTILS_SRC)/visual.h
 decayscreen.o: $(UTILS_SRC)/yarandom.h
 deco.o: ../config.h
 deco.o: $(srcdir)/fps.h
+deco.o: $(srcdir)/recanim.h
 deco.o: $(srcdir)/screenhackI.h
 deco.o: $(srcdir)/screenhack.h
 deco.o: $(UTILS_SRC)/colors.h
@@ -1481,6 +1523,7 @@ delaunay.o: ../config.h
 delaunay.o: $(srcdir)/delaunay.h
 deluxe.o: ../config.h
 deluxe.o: $(srcdir)/fps.h
+deluxe.o: $(srcdir)/recanim.h
 deluxe.o: $(srcdir)/screenhackI.h
 deluxe.o: $(srcdir)/screenhack.h
 deluxe.o: $(UTILS_SRC)/alpha.h
@@ -1496,6 +1539,7 @@ deluxe.o: $(UTILS_SRC)/yarandom.h
 demon.o: $(srcdir)/automata.h
 demon.o: ../config.h
 demon.o: $(srcdir)/fps.h
+demon.o: $(srcdir)/recanim.h
 demon.o: $(srcdir)/screenhackI.h
 demon.o: $(UTILS_SRC)/colors.h
 demon.o: $(UTILS_SRC)/erase.h
@@ -1510,6 +1554,7 @@ demon.o: $(srcdir)/xlockmoreI.h
 demon.o: $(srcdir)/xlockmore.h
 discrete.o: ../config.h
 discrete.o: $(srcdir)/fps.h
+discrete.o: $(srcdir)/recanim.h
 discrete.o: $(srcdir)/screenhackI.h
 discrete.o: $(UTILS_SRC)/colors.h
 discrete.o: $(UTILS_SRC)/erase.h
@@ -1524,6 +1569,7 @@ discrete.o: $(srcdir)/xlockmoreI.h
 discrete.o: $(srcdir)/xlockmore.h
 distort.o: ../config.h
 distort.o: $(srcdir)/fps.h
+distort.o: $(srcdir)/recanim.h
 distort.o: $(srcdir)/screenhackI.h
 distort.o: $(srcdir)/screenhack.h
 distort.o: $(UTILS_SRC)/colors.h
@@ -1537,6 +1583,7 @@ distort.o: $(UTILS_SRC)/xshm.h
 distort.o: $(UTILS_SRC)/yarandom.h
 drift.o: ../config.h
 drift.o: $(srcdir)/fps.h
+drift.o: $(srcdir)/recanim.h
 drift.o: $(srcdir)/screenhackI.h
 drift.o: $(UTILS_SRC)/colors.h
 drift.o: $(UTILS_SRC)/erase.h
@@ -1551,6 +1598,7 @@ drift.o: $(srcdir)/xlockmoreI.h
 drift.o: $(srcdir)/xlockmore.h
 epicycle.o: ../config.h
 epicycle.o: $(srcdir)/fps.h
+epicycle.o: $(srcdir)/recanim.h
 epicycle.o: $(srcdir)/screenhackI.h
 epicycle.o: $(srcdir)/screenhack.h
 epicycle.o: $(UTILS_SRC)/colors.h
@@ -1564,6 +1612,7 @@ epicycle.o: $(UTILS_SRC)/visual.h
 epicycle.o: $(UTILS_SRC)/yarandom.h
 eruption.o: ../config.h
 eruption.o: $(srcdir)/fps.h
+eruption.o: $(srcdir)/recanim.h
 eruption.o: $(srcdir)/screenhackI.h
 eruption.o: $(srcdir)/screenhack.h
 eruption.o: $(UTILS_SRC)/colors.h
@@ -1576,6 +1625,7 @@ eruption.o: $(UTILS_SRC)/visual.h
 eruption.o: $(UTILS_SRC)/yarandom.h
 euler2d.o: ../config.h
 euler2d.o: $(srcdir)/fps.h
+euler2d.o: $(srcdir)/recanim.h
 euler2d.o: $(srcdir)/screenhackI.h
 euler2d.o: $(UTILS_SRC)/colors.h
 euler2d.o: $(UTILS_SRC)/erase.h
@@ -1590,6 +1640,7 @@ euler2d.o: $(srcdir)/xlockmoreI.h
 euler2d.o: $(srcdir)/xlockmore.h
 fadeplot.o: ../config.h
 fadeplot.o: $(srcdir)/fps.h
+fadeplot.o: $(srcdir)/recanim.h
 fadeplot.o: $(srcdir)/screenhackI.h
 fadeplot.o: $(UTILS_SRC)/colors.h
 fadeplot.o: $(UTILS_SRC)/erase.h
@@ -1604,6 +1655,7 @@ fadeplot.o: $(srcdir)/xlockmoreI.h
 fadeplot.o: $(srcdir)/xlockmore.h
 fiberlamp.o: ../config.h
 fiberlamp.o: $(srcdir)/fps.h
+fiberlamp.o: $(srcdir)/recanim.h
 fiberlamp.o: $(srcdir)/screenhackI.h
 fiberlamp.o: $(UTILS_SRC)/colors.h
 fiberlamp.o: $(UTILS_SRC)/erase.h
@@ -1616,8 +1668,27 @@ fiberlamp.o: $(UTILS_SRC)/visual.h
 fiberlamp.o: $(UTILS_SRC)/yarandom.h
 fiberlamp.o: $(srcdir)/xlockmoreI.h
 fiberlamp.o: $(srcdir)/xlockmore.h
+filmleader.o: $(srcdir)/analogtv.h
+filmleader.o: ../config.h
+filmleader.o: $(srcdir)/fps.h
+filmleader.o: $(srcdir)/recanim.h
+filmleader.o: $(srcdir)/screenhackI.h
+filmleader.o: $(srcdir)/screenhack.h
+filmleader.o: $(UTILS_SRC)/aligned_malloc.h
+filmleader.o: $(UTILS_SRC)/colors.h
+filmleader.o: $(UTILS_SRC)/font-retry.h
+filmleader.o: $(UTILS_SRC)/grabscreen.h
+filmleader.o: $(UTILS_SRC)/hsv.h
+filmleader.o: $(UTILS_SRC)/resources.h
+filmleader.o: $(UTILS_SRC)/thread_util.h
+filmleader.o: $(UTILS_SRC)/usleep.h
+filmleader.o: $(UTILS_SRC)/visual.h
+filmleader.o: $(UTILS_SRC)/xft.h
+filmleader.o: $(UTILS_SRC)/xshm.h
+filmleader.o: $(UTILS_SRC)/yarandom.h
 fireworkx.o: ../config.h
 fireworkx.o: $(srcdir)/fps.h
+fireworkx.o: $(srcdir)/recanim.h
 fireworkx.o: $(srcdir)/screenhackI.h
 fireworkx.o: $(srcdir)/screenhack.h
 fireworkx.o: $(UTILS_SRC)/colors.h
@@ -1631,6 +1702,7 @@ fireworkx.o: $(UTILS_SRC)/yarandom.h
 flag.o: ../config.h
 flag.o: $(srcdir)/fps.h
 flag.o: $(srcdir)/images/gen/bob_png.h
+flag.o: $(srcdir)/recanim.h
 flag.o: $(srcdir)/screenhackI.h
 flag.o: $(UTILS_SRC)/colors.h
 flag.o: $(UTILS_SRC)/erase.h
@@ -1646,6 +1718,7 @@ flag.o: $(srcdir)/xlockmoreI.h
 flag.o: $(srcdir)/xlockmore.h
 flame.o: ../config.h
 flame.o: $(srcdir)/fps.h
+flame.o: $(srcdir)/recanim.h
 flame.o: $(srcdir)/screenhackI.h
 flame.o: $(srcdir)/screenhack.h
 flame.o: $(UTILS_SRC)/colors.h
@@ -1658,6 +1731,7 @@ flame.o: $(UTILS_SRC)/visual.h
 flame.o: $(UTILS_SRC)/yarandom.h
 flow.o: ../config.h
 flow.o: $(srcdir)/fps.h
+flow.o: $(srcdir)/recanim.h
 flow.o: $(srcdir)/screenhackI.h
 flow.o: $(UTILS_SRC)/colors.h
 flow.o: $(UTILS_SRC)/erase.h
@@ -1672,6 +1746,7 @@ flow.o: $(srcdir)/xlockmoreI.h
 flow.o: $(srcdir)/xlockmore.h
 fluidballs.o: ../config.h
 fluidballs.o: $(srcdir)/fps.h
+fluidballs.o: $(srcdir)/recanim.h
 fluidballs.o: $(srcdir)/screenhackI.h
 fluidballs.o: $(srcdir)/screenhack.h
 fluidballs.o: $(UTILS_SRC)/colors.h
@@ -1685,6 +1760,7 @@ fluidballs.o: $(UTILS_SRC)/xdbe.h
 fluidballs.o: $(UTILS_SRC)/yarandom.h
 fontglide.o: ../config.h
 fontglide.o: $(srcdir)/fps.h
+fontglide.o: $(srcdir)/recanim.h
 fontglide.o: $(srcdir)/screenhackI.h
 fontglide.o: $(srcdir)/screenhack.h
 fontglide.o: $(UTILS_SRC)/colors.h
@@ -1701,6 +1777,7 @@ fontglide.o: $(UTILS_SRC)/xft.h
 fontglide.o: $(UTILS_SRC)/yarandom.h
 forest.o: ../config.h
 forest.o: $(srcdir)/fps.h
+forest.o: $(srcdir)/recanim.h
 forest.o: $(srcdir)/screenhackI.h
 forest.o: $(UTILS_SRC)/colors.h
 forest.o: $(UTILS_SRC)/erase.h
@@ -1716,6 +1793,7 @@ forest.o: $(srcdir)/xlockmore.h
 fps.o: ../config.h
 fps.o: $(srcdir)/fpsI.h
 fps.o: $(srcdir)/fps.h
+fps.o: $(srcdir)/recanim.h
 fps.o: $(srcdir)/screenhackI.h
 fps.o: $(UTILS_SRC)/colors.h
 fps.o: $(UTILS_SRC)/font-retry.h
@@ -1727,6 +1805,7 @@ fps.o: $(UTILS_SRC)/visual.h
 fps.o: $(UTILS_SRC)/yarandom.h
 fuzzyflakes.o: ../config.h
 fuzzyflakes.o: $(srcdir)/fps.h
+fuzzyflakes.o: $(srcdir)/recanim.h
 fuzzyflakes.o: $(srcdir)/screenhackI.h
 fuzzyflakes.o: $(srcdir)/screenhack.h
 fuzzyflakes.o: $(UTILS_SRC)/colors.h
@@ -1739,6 +1818,7 @@ fuzzyflakes.o: $(UTILS_SRC)/visual.h
 fuzzyflakes.o: $(UTILS_SRC)/yarandom.h
 galaxy.o: ../config.h
 galaxy.o: $(srcdir)/fps.h
+galaxy.o: $(srcdir)/recanim.h
 galaxy.o: $(srcdir)/screenhackI.h
 galaxy.o: $(UTILS_SRC)/colors.h
 galaxy.o: $(UTILS_SRC)/erase.h
@@ -1751,8 +1831,23 @@ galaxy.o: $(UTILS_SRC)/visual.h
 galaxy.o: $(UTILS_SRC)/yarandom.h
 galaxy.o: $(srcdir)/xlockmoreI.h
 galaxy.o: $(srcdir)/xlockmore.h
+glitchpeg.o: ../config.h
+glitchpeg.o: $(srcdir)/fps.h
+glitchpeg.o: $(srcdir)/recanim.h
+glitchpeg.o: $(srcdir)/screenhackI.h
+glitchpeg.o: $(srcdir)/screenhack.h
+glitchpeg.o: $(UTILS_SRC)/colors.h
+glitchpeg.o: $(UTILS_SRC)/font-retry.h
+glitchpeg.o: $(UTILS_SRC)/grabscreen.h
+glitchpeg.o: $(UTILS_SRC)/hsv.h
+glitchpeg.o: $(UTILS_SRC)/resources.h
+glitchpeg.o: $(UTILS_SRC)/usleep.h
+glitchpeg.o: $(UTILS_SRC)/visual.h
+glitchpeg.o: $(UTILS_SRC)/yarandom.h
+glitchpeg.o: $(srcdir)/ximage-loader.h
 goop.o: ../config.h
 goop.o: $(srcdir)/fps.h
+goop.o: $(srcdir)/recanim.h
 goop.o: $(srcdir)/screenhackI.h
 goop.o: $(srcdir)/screenhack.h
 goop.o: $(UTILS_SRC)/alpha.h
@@ -1767,6 +1862,7 @@ goop.o: $(UTILS_SRC)/visual.h
 goop.o: $(UTILS_SRC)/yarandom.h
 grav.o: ../config.h
 grav.o: $(srcdir)/fps.h
+grav.o: $(srcdir)/recanim.h
 grav.o: $(srcdir)/screenhackI.h
 grav.o: $(UTILS_SRC)/colors.h
 grav.o: $(UTILS_SRC)/erase.h
@@ -1781,6 +1877,7 @@ grav.o: $(srcdir)/xlockmoreI.h
 grav.o: $(srcdir)/xlockmore.h
 greynetic.o: ../config.h
 greynetic.o: $(srcdir)/fps.h
+greynetic.o: $(srcdir)/recanim.h
 greynetic.o: $(srcdir)/screenhackI.h
 greynetic.o: $(srcdir)/screenhack.h
 greynetic.o: $(UTILS_SRC)/colors.h
@@ -1793,6 +1890,7 @@ greynetic.o: $(UTILS_SRC)/visual.h
 greynetic.o: $(UTILS_SRC)/yarandom.h
 halftone.o: ../config.h
 halftone.o: $(srcdir)/fps.h
+halftone.o: $(srcdir)/recanim.h
 halftone.o: $(srcdir)/screenhackI.h
 halftone.o: $(srcdir)/screenhack.h
 halftone.o: $(UTILS_SRC)/colors.h
@@ -1805,6 +1903,7 @@ halftone.o: $(UTILS_SRC)/visual.h
 halftone.o: $(UTILS_SRC)/yarandom.h
 halo.o: ../config.h
 halo.o: $(srcdir)/fps.h
+halo.o: $(srcdir)/recanim.h
 halo.o: $(srcdir)/screenhackI.h
 halo.o: $(srcdir)/screenhack.h
 halo.o: $(UTILS_SRC)/colors.h
@@ -1817,6 +1916,7 @@ halo.o: $(UTILS_SRC)/visual.h
 halo.o: $(UTILS_SRC)/yarandom.h
 helix.o: ../config.h
 helix.o: $(srcdir)/fps.h
+helix.o: $(srcdir)/recanim.h
 helix.o: $(srcdir)/screenhackI.h
 helix.o: $(srcdir)/screenhack.h
 helix.o: $(UTILS_SRC)/colors.h
@@ -1830,6 +1930,7 @@ helix.o: $(UTILS_SRC)/visual.h
 helix.o: $(UTILS_SRC)/yarandom.h
 hexadrop.o: ../config.h
 hexadrop.o: $(srcdir)/fps.h
+hexadrop.o: $(srcdir)/recanim.h
 hexadrop.o: $(srcdir)/screenhackI.h
 hexadrop.o: $(srcdir)/screenhack.h
 hexadrop.o: $(UTILS_SRC)/colors.h
@@ -1842,6 +1943,7 @@ hexadrop.o: $(UTILS_SRC)/visual.h
 hexadrop.o: $(UTILS_SRC)/yarandom.h
 hopalong.o: ../config.h
 hopalong.o: $(srcdir)/fps.h
+hopalong.o: $(srcdir)/recanim.h
 hopalong.o: $(srcdir)/screenhackI.h
 hopalong.o: $(UTILS_SRC)/colors.h
 hopalong.o: $(UTILS_SRC)/erase.h
@@ -1856,6 +1958,7 @@ hopalong.o: $(srcdir)/xlockmoreI.h
 hopalong.o: $(srcdir)/xlockmore.h
 hyperball.o: ../config.h
 hyperball.o: $(srcdir)/fps.h
+hyperball.o: $(srcdir)/recanim.h
 hyperball.o: $(srcdir)/screenhackI.h
 hyperball.o: $(srcdir)/screenhack.h
 hyperball.o: $(UTILS_SRC)/colors.h
@@ -1868,6 +1971,7 @@ hyperball.o: $(UTILS_SRC)/visual.h
 hyperball.o: $(UTILS_SRC)/yarandom.h
 hypercube.o: ../config.h
 hypercube.o: $(srcdir)/fps.h
+hypercube.o: $(srcdir)/recanim.h
 hypercube.o: $(srcdir)/screenhackI.h
 hypercube.o: $(srcdir)/screenhack.h
 hypercube.o: $(UTILS_SRC)/colors.h
@@ -1880,6 +1984,7 @@ hypercube.o: $(UTILS_SRC)/visual.h
 hypercube.o: $(UTILS_SRC)/yarandom.h
 ifs.o: ../config.h
 ifs.o: $(srcdir)/fps.h
+ifs.o: $(srcdir)/recanim.h
 ifs.o: $(srcdir)/screenhackI.h
 ifs.o: $(srcdir)/screenhack.h
 ifs.o: $(UTILS_SRC)/colors.h
@@ -1892,6 +1997,7 @@ ifs.o: $(UTILS_SRC)/visual.h
 ifs.o: $(UTILS_SRC)/yarandom.h
 imsmap.o: ../config.h
 imsmap.o: $(srcdir)/fps.h
+imsmap.o: $(srcdir)/recanim.h
 imsmap.o: $(srcdir)/screenhackI.h
 imsmap.o: $(srcdir)/screenhack.h
 imsmap.o: $(UTILS_SRC)/colors.h
@@ -1904,6 +2010,7 @@ imsmap.o: $(UTILS_SRC)/visual.h
 imsmap.o: $(UTILS_SRC)/yarandom.h
 interaggregate.o: ../config.h
 interaggregate.o: $(srcdir)/fps.h
+interaggregate.o: $(srcdir)/recanim.h
 interaggregate.o: $(srcdir)/screenhackI.h
 interaggregate.o: $(srcdir)/screenhack.h
 interaggregate.o: $(UTILS_SRC)/colors.h
@@ -1916,6 +2023,7 @@ interaggregate.o: $(UTILS_SRC)/visual.h
 interaggregate.o: $(UTILS_SRC)/yarandom.h
 interference.o: ../config.h
 interference.o: $(srcdir)/fps.h
+interference.o: $(srcdir)/recanim.h
 interference.o: $(srcdir)/screenhackI.h
 interference.o: $(srcdir)/screenhack.h
 interference.o: $(UTILS_SRC)/aligned_malloc.h
@@ -1932,6 +2040,7 @@ interference.o: $(UTILS_SRC)/xshm.h
 interference.o: $(UTILS_SRC)/yarandom.h
 intermomentary.o: ../config.h
 intermomentary.o: $(srcdir)/fps.h
+intermomentary.o: $(srcdir)/recanim.h
 intermomentary.o: $(srcdir)/screenhackI.h
 intermomentary.o: $(srcdir)/screenhack.h
 intermomentary.o: $(UTILS_SRC)/colors.h
@@ -1944,6 +2053,7 @@ intermomentary.o: $(UTILS_SRC)/visual.h
 intermomentary.o: $(UTILS_SRC)/yarandom.h
 juggle.o: ../config.h
 juggle.o: $(srcdir)/fps.h
+juggle.o: $(srcdir)/recanim.h
 juggle.o: $(srcdir)/screenhackI.h
 juggle.o: $(UTILS_SRC)/colors.h
 juggle.o: $(UTILS_SRC)/erase.h
@@ -1958,6 +2068,7 @@ juggle.o: $(srcdir)/xlockmoreI.h
 juggle.o: $(srcdir)/xlockmore.h
 julia.o: ../config.h
 julia.o: $(srcdir)/fps.h
+julia.o: $(srcdir)/recanim.h
 julia.o: $(srcdir)/screenhackI.h
 julia.o: $(UTILS_SRC)/colors.h
 julia.o: $(UTILS_SRC)/erase.h
@@ -1972,6 +2083,7 @@ julia.o: $(srcdir)/xlockmoreI.h
 julia.o: $(srcdir)/xlockmore.h
 kaleidescope.o: ../config.h
 kaleidescope.o: $(srcdir)/fps.h
+kaleidescope.o: $(srcdir)/recanim.h
 kaleidescope.o: $(srcdir)/screenhackI.h
 kaleidescope.o: $(srcdir)/screenhack.h
 kaleidescope.o: $(UTILS_SRC)/colors.h
@@ -1985,6 +2097,7 @@ kaleidescope.o: $(UTILS_SRC)/visual.h
 kaleidescope.o: $(UTILS_SRC)/yarandom.h
 kumppa.o: ../config.h
 kumppa.o: $(srcdir)/fps.h
+kumppa.o: $(srcdir)/recanim.h
 kumppa.o: $(srcdir)/screenhackI.h
 kumppa.o: $(srcdir)/screenhack.h
 kumppa.o: $(UTILS_SRC)/colors.h
@@ -1998,6 +2111,7 @@ kumppa.o: $(UTILS_SRC)/xdbe.h
 kumppa.o: $(UTILS_SRC)/yarandom.h
 laser.o: ../config.h
 laser.o: $(srcdir)/fps.h
+laser.o: $(srcdir)/recanim.h
 laser.o: $(srcdir)/screenhackI.h
 laser.o: $(UTILS_SRC)/colors.h
 laser.o: $(UTILS_SRC)/erase.h
@@ -2012,6 +2126,7 @@ laser.o: $(srcdir)/xlockmoreI.h
 laser.o: $(srcdir)/xlockmore.h
 lcdscrub.o: ../config.h
 lcdscrub.o: $(srcdir)/fps.h
+lcdscrub.o: $(srcdir)/recanim.h
 lcdscrub.o: $(srcdir)/screenhackI.h
 lcdscrub.o: $(srcdir)/screenhack.h
 lcdscrub.o: $(UTILS_SRC)/colors.h
@@ -2024,6 +2139,7 @@ lcdscrub.o: $(UTILS_SRC)/visual.h
 lcdscrub.o: $(UTILS_SRC)/yarandom.h
 lightning.o: ../config.h
 lightning.o: $(srcdir)/fps.h
+lightning.o: $(srcdir)/recanim.h
 lightning.o: $(srcdir)/screenhackI.h
 lightning.o: $(UTILS_SRC)/colors.h
 lightning.o: $(UTILS_SRC)/erase.h
@@ -2038,6 +2154,7 @@ lightning.o: $(srcdir)/xlockmoreI.h
 lightning.o: $(srcdir)/xlockmore.h
 lisa.o: ../config.h
 lisa.o: $(srcdir)/fps.h
+lisa.o: $(srcdir)/recanim.h
 lisa.o: $(srcdir)/screenhackI.h
 lisa.o: $(UTILS_SRC)/colors.h
 lisa.o: $(UTILS_SRC)/erase.h
@@ -2052,6 +2169,7 @@ lisa.o: $(srcdir)/xlockmoreI.h
 lisa.o: $(srcdir)/xlockmore.h
 lissie.o: ../config.h
 lissie.o: $(srcdir)/fps.h
+lissie.o: $(srcdir)/recanim.h
 lissie.o: $(srcdir)/screenhackI.h
 lissie.o: $(UTILS_SRC)/colors.h
 lissie.o: $(UTILS_SRC)/erase.h
@@ -2066,6 +2184,7 @@ lissie.o: $(srcdir)/xlockmoreI.h
 lissie.o: $(srcdir)/xlockmore.h
 lmorph.o: ../config.h
 lmorph.o: $(srcdir)/fps.h
+lmorph.o: $(srcdir)/recanim.h
 lmorph.o: $(srcdir)/screenhackI.h
 lmorph.o: $(srcdir)/screenhack.h
 lmorph.o: $(UTILS_SRC)/colors.h
@@ -2079,6 +2198,7 @@ lmorph.o: $(UTILS_SRC)/yarandom.h
 loop.o: $(srcdir)/automata.h
 loop.o: ../config.h
 loop.o: $(srcdir)/fps.h
+loop.o: $(srcdir)/recanim.h
 loop.o: $(srcdir)/screenhackI.h
 loop.o: $(UTILS_SRC)/colors.h
 loop.o: $(UTILS_SRC)/erase.h
@@ -2096,6 +2216,7 @@ m6502.o: $(srcdir)/asm6502.h
 m6502.o: ../config.h
 m6502.o: $(srcdir)/fps.h
 m6502.o: m6502.h
+m6502.o: $(srcdir)/recanim.h
 m6502.o: $(srcdir)/screenhackI.h
 m6502.o: $(srcdir)/screenhack.h
 m6502.o: $(UTILS_SRC)/aligned_malloc.h
@@ -2113,6 +2234,7 @@ maze.o: ../config.h
 maze.o: $(srcdir)/fps.h
 maze.o: $(srcdir)/images/gen/logo-180_png.h
 maze.o: $(srcdir)/images/gen/logo-50_png.h
+maze.o: $(srcdir)/recanim.h
 maze.o: $(srcdir)/screenhackI.h
 maze.o: $(srcdir)/screenhack.h
 maze.o: $(UTILS_SRC)/colors.h
@@ -2127,6 +2249,7 @@ maze.o: $(UTILS_SRC)/yarandom.h
 maze.o: $(srcdir)/ximage-loader.h
 memscroller.o: ../config.h
 memscroller.o: $(srcdir)/fps.h
+memscroller.o: $(srcdir)/recanim.h
 memscroller.o: $(srcdir)/screenhackI.h
 memscroller.o: $(srcdir)/screenhack.h
 memscroller.o: $(UTILS_SRC)/colors.h
@@ -2140,6 +2263,7 @@ memscroller.o: $(UTILS_SRC)/xshm.h
 memscroller.o: $(UTILS_SRC)/yarandom.h
 metaballs.o: ../config.h
 metaballs.o: $(srcdir)/fps.h
+metaballs.o: $(srcdir)/recanim.h
 metaballs.o: $(srcdir)/screenhackI.h
 metaballs.o: $(srcdir)/screenhack.h
 metaballs.o: $(UTILS_SRC)/colors.h
@@ -2152,6 +2276,7 @@ metaballs.o: $(UTILS_SRC)/visual.h
 metaballs.o: $(UTILS_SRC)/yarandom.h
 moire2.o: ../config.h
 moire2.o: $(srcdir)/fps.h
+moire2.o: $(srcdir)/recanim.h
 moire2.o: $(srcdir)/screenhackI.h
 moire2.o: $(srcdir)/screenhack.h
 moire2.o: $(UTILS_SRC)/colors.h
@@ -2165,6 +2290,7 @@ moire2.o: $(UTILS_SRC)/xdbe.h
 moire2.o: $(UTILS_SRC)/yarandom.h
 moire.o: ../config.h
 moire.o: $(srcdir)/fps.h
+moire.o: $(srcdir)/recanim.h
 moire.o: $(srcdir)/screenhackI.h
 moire.o: $(srcdir)/screenhack.h
 moire.o: $(UTILS_SRC)/colors.h
@@ -2178,6 +2304,7 @@ moire.o: $(UTILS_SRC)/xshm.h
 moire.o: $(UTILS_SRC)/yarandom.h
 mountain.o: ../config.h
 mountain.o: $(srcdir)/fps.h
+mountain.o: $(srcdir)/recanim.h
 mountain.o: $(srcdir)/screenhackI.h
 mountain.o: $(UTILS_SRC)/colors.h
 mountain.o: $(UTILS_SRC)/erase.h
@@ -2192,6 +2319,7 @@ mountain.o: $(srcdir)/xlockmoreI.h
 mountain.o: $(srcdir)/xlockmore.h
 munch.o: ../config.h
 munch.o: $(srcdir)/fps.h
+munch.o: $(srcdir)/recanim.h
 munch.o: $(srcdir)/screenhackI.h
 munch.o: $(srcdir)/screenhack.h
 munch.o: $(UTILS_SRC)/colors.h
@@ -2204,6 +2332,7 @@ munch.o: $(UTILS_SRC)/visual.h
 munch.o: $(UTILS_SRC)/yarandom.h
 nerverot.o: ../config.h
 nerverot.o: $(srcdir)/fps.h
+nerverot.o: $(srcdir)/recanim.h
 nerverot.o: $(srcdir)/screenhackI.h
 nerverot.o: $(srcdir)/screenhack.h
 nerverot.o: $(UTILS_SRC)/colors.h
@@ -2224,6 +2353,7 @@ noseguy.o: $(srcdir)/images/gen/nose-l1_png.h
 noseguy.o: $(srcdir)/images/gen/nose-l2_png.h
 noseguy.o: $(srcdir)/images/gen/nose-r1_png.h
 noseguy.o: $(srcdir)/images/gen/nose-r2_png.h
+noseguy.o: $(srcdir)/recanim.h
 noseguy.o: $(srcdir)/screenhackI.h
 noseguy.o: $(srcdir)/screenhack.h
 noseguy.o: $(UTILS_SRC)/colors.h
@@ -2242,6 +2372,7 @@ pacman_ai.o: $(srcdir)/fps.h
 pacman_ai.o: $(srcdir)/pacman_ai.h
 pacman_ai.o: $(srcdir)/pacman.h
 pacman_ai.o: $(srcdir)/pacman_level.h
+pacman_ai.o: $(srcdir)/recanim.h
 pacman_ai.o: $(srcdir)/screenhackI.h
 pacman_ai.o: $(UTILS_SRC)/colors.h
 pacman_ai.o: $(UTILS_SRC)/erase.h
@@ -2258,6 +2389,7 @@ pacman_level.o: ../config.h
 pacman_level.o: $(srcdir)/fps.h
 pacman_level.o: $(srcdir)/pacman.h
 pacman_level.o: $(srcdir)/pacman_level.h
+pacman_level.o: $(srcdir)/recanim.h
 pacman_level.o: $(srcdir)/screenhackI.h
 pacman_level.o: $(UTILS_SRC)/colors.h
 pacman_level.o: $(UTILS_SRC)/erase.h
@@ -2276,6 +2408,7 @@ pacman.o: $(srcdir)/images/gen/pacman_png.h
 pacman.o: $(srcdir)/pacman_ai.h
 pacman.o: $(srcdir)/pacman.h
 pacman.o: $(srcdir)/pacman_level.h
+pacman.o: $(srcdir)/recanim.h
 pacman.o: $(srcdir)/screenhackI.h
 pacman.o: $(UTILS_SRC)/colors.h
 pacman.o: $(UTILS_SRC)/erase.h
@@ -2291,6 +2424,7 @@ pacman.o: $(srcdir)/xlockmoreI.h
 pacman.o: $(srcdir)/xlockmore.h
 pedal.o: ../config.h
 pedal.o: $(srcdir)/fps.h
+pedal.o: $(srcdir)/recanim.h
 pedal.o: $(srcdir)/screenhackI.h
 pedal.o: $(srcdir)/screenhack.h
 pedal.o: $(UTILS_SRC)/colors.h
@@ -2304,6 +2438,7 @@ pedal.o: $(UTILS_SRC)/visual.h
 pedal.o: $(UTILS_SRC)/yarandom.h
 penetrate.o: ../config.h
 penetrate.o: $(srcdir)/fps.h
+penetrate.o: $(srcdir)/recanim.h
 penetrate.o: $(srcdir)/screenhackI.h
 penetrate.o: $(srcdir)/screenhack.h
 penetrate.o: $(UTILS_SRC)/colors.h
@@ -2316,6 +2451,7 @@ penetrate.o: $(UTILS_SRC)/visual.h
 penetrate.o: $(UTILS_SRC)/yarandom.h
 penrose.o: ../config.h
 penrose.o: $(srcdir)/fps.h
+penrose.o: $(srcdir)/recanim.h
 penrose.o: $(srcdir)/screenhackI.h
 penrose.o: $(UTILS_SRC)/colors.h
 penrose.o: $(UTILS_SRC)/erase.h
@@ -2330,6 +2466,7 @@ penrose.o: $(srcdir)/xlockmoreI.h
 penrose.o: $(srcdir)/xlockmore.h
 petri.o: ../config.h
 petri.o: $(srcdir)/fps.h
+petri.o: $(srcdir)/recanim.h
 petri.o: $(srcdir)/screenhackI.h
 petri.o: $(srcdir)/screenhack.h
 petri.o: $(UTILS_SRC)/colors.h
@@ -2344,6 +2481,7 @@ petri.o: $(UTILS_SRC)/yarandom.h
 phosphor.o: ../config.h
 phosphor.o: $(srcdir)/fps.h
 phosphor.o: $(srcdir)/images/gen/6x10font_png.h
+phosphor.o: $(srcdir)/recanim.h
 phosphor.o: $(srcdir)/screenhackI.h
 phosphor.o: $(srcdir)/screenhack.h
 phosphor.o: $(UTILS_SRC)/colors.h
@@ -2359,6 +2497,7 @@ phosphor.o: $(UTILS_SRC)/yarandom.h
 phosphor.o: $(srcdir)/ximage-loader.h
 piecewise.o: ../config.h
 piecewise.o: $(srcdir)/fps.h
+piecewise.o: $(srcdir)/recanim.h
 piecewise.o: $(srcdir)/screenhackI.h
 piecewise.o: $(srcdir)/screenhack.h
 piecewise.o: $(UTILS_SRC)/colors.h
@@ -2372,6 +2511,7 @@ piecewise.o: $(UTILS_SRC)/xdbe.h
 piecewise.o: $(UTILS_SRC)/yarandom.h
 polyominoes.o: ../config.h
 polyominoes.o: $(srcdir)/fps.h
+polyominoes.o: $(srcdir)/recanim.h
 polyominoes.o: $(srcdir)/screenhackI.h
 polyominoes.o: $(UTILS_SRC)/colors.h
 polyominoes.o: $(UTILS_SRC)/erase.h
@@ -2387,6 +2527,7 @@ polyominoes.o: $(srcdir)/xlockmore.h
 pong.o: $(srcdir)/analogtv.h
 pong.o: ../config.h
 pong.o: $(srcdir)/fps.h
+pong.o: $(srcdir)/recanim.h
 pong.o: $(srcdir)/screenhackI.h
 pong.o: $(srcdir)/screenhack.h
 pong.o: $(UTILS_SRC)/aligned_malloc.h
@@ -2402,6 +2543,7 @@ pong.o: $(UTILS_SRC)/xshm.h
 pong.o: $(UTILS_SRC)/yarandom.h
 popsquares.o: ../config.h
 popsquares.o: $(srcdir)/fps.h
+popsquares.o: $(srcdir)/recanim.h
 popsquares.o: $(srcdir)/screenhackI.h
 popsquares.o: $(srcdir)/screenhack.h
 popsquares.o: $(UTILS_SRC)/colors.h
@@ -2415,6 +2557,7 @@ popsquares.o: $(UTILS_SRC)/xdbe.h
 popsquares.o: $(UTILS_SRC)/yarandom.h
 pyro.o: ../config.h
 pyro.o: $(srcdir)/fps.h
+pyro.o: $(srcdir)/recanim.h
 pyro.o: $(srcdir)/screenhackI.h
 pyro.o: $(srcdir)/screenhack.h
 pyro.o: $(UTILS_SRC)/colors.h
@@ -2427,6 +2570,7 @@ pyro.o: $(UTILS_SRC)/visual.h
 pyro.o: $(UTILS_SRC)/yarandom.h
 qix.o: ../config.h
 qix.o: $(srcdir)/fps.h
+qix.o: $(srcdir)/recanim.h
 qix.o: $(srcdir)/screenhackI.h
 qix.o: $(srcdir)/screenhack.h
 qix.o: $(UTILS_SRC)/alpha.h
@@ -2440,6 +2584,7 @@ qix.o: $(UTILS_SRC)/visual.h
 qix.o: $(UTILS_SRC)/yarandom.h
 rd-bomb.o: ../config.h
 rd-bomb.o: $(srcdir)/fps.h
+rd-bomb.o: $(srcdir)/recanim.h
 rd-bomb.o: $(srcdir)/screenhackI.h
 rd-bomb.o: $(srcdir)/screenhack.h
 rd-bomb.o: $(UTILS_SRC)/colors.h
@@ -2465,6 +2610,7 @@ recanim.o: $(UTILS_SRC)/visual.h
 recanim.o: $(UTILS_SRC)/yarandom.h
 ripples.o: ../config.h
 ripples.o: $(srcdir)/fps.h
+ripples.o: $(srcdir)/recanim.h
 ripples.o: $(srcdir)/screenhackI.h
 ripples.o: $(srcdir)/screenhack.h
 ripples.o: $(UTILS_SRC)/colors.h
@@ -2478,6 +2624,7 @@ ripples.o: $(UTILS_SRC)/xshm.h
 ripples.o: $(UTILS_SRC)/yarandom.h
 rocks.o: ../config.h
 rocks.o: $(srcdir)/fps.h
+rocks.o: $(srcdir)/recanim.h
 rocks.o: $(srcdir)/screenhackI.h
 rocks.o: $(srcdir)/screenhack.h
 rocks.o: $(UTILS_SRC)/colors.h
@@ -2490,6 +2637,7 @@ rocks.o: $(UTILS_SRC)/visual.h
 rocks.o: $(UTILS_SRC)/yarandom.h
 rorschach.o: ../config.h
 rorschach.o: $(srcdir)/fps.h
+rorschach.o: $(srcdir)/recanim.h
 rorschach.o: $(srcdir)/screenhackI.h
 rorschach.o: $(srcdir)/screenhack.h
 rorschach.o: $(UTILS_SRC)/colors.h
@@ -2503,6 +2651,7 @@ rorschach.o: $(UTILS_SRC)/visual.h
 rorschach.o: $(UTILS_SRC)/yarandom.h
 rotor.o: ../config.h
 rotor.o: $(srcdir)/fps.h
+rotor.o: $(srcdir)/recanim.h
 rotor.o: $(srcdir)/screenhackI.h
 rotor.o: $(UTILS_SRC)/colors.h
 rotor.o: $(UTILS_SRC)/erase.h
@@ -2517,6 +2666,7 @@ rotor.o: $(srcdir)/xlockmoreI.h
 rotor.o: $(srcdir)/xlockmore.h
 rotzoomer.o: ../config.h
 rotzoomer.o: $(srcdir)/fps.h
+rotzoomer.o: $(srcdir)/recanim.h
 rotzoomer.o: $(srcdir)/screenhackI.h
 rotzoomer.o: $(srcdir)/screenhack.h
 rotzoomer.o: $(UTILS_SRC)/colors.h
@@ -2545,6 +2695,7 @@ screenhack.o: $(UTILS_SRC)/xmu.h
 screenhack.o: $(UTILS_SRC)/yarandom.h
 shadebobs.o: ../config.h
 shadebobs.o: $(srcdir)/fps.h
+shadebobs.o: $(srcdir)/recanim.h
 shadebobs.o: $(srcdir)/screenhackI.h
 shadebobs.o: $(srcdir)/screenhack.h
 shadebobs.o: $(UTILS_SRC)/colors.h
@@ -2557,6 +2708,7 @@ shadebobs.o: $(UTILS_SRC)/visual.h
 shadebobs.o: $(UTILS_SRC)/yarandom.h
 sierpinski.o: ../config.h
 sierpinski.o: $(srcdir)/fps.h
+sierpinski.o: $(srcdir)/recanim.h
 sierpinski.o: $(srcdir)/screenhackI.h
 sierpinski.o: $(UTILS_SRC)/colors.h
 sierpinski.o: $(UTILS_SRC)/erase.h
@@ -2571,6 +2723,7 @@ sierpinski.o: $(srcdir)/xlockmoreI.h
 sierpinski.o: $(srcdir)/xlockmore.h
 slidescreen.o: ../config.h
 slidescreen.o: $(srcdir)/fps.h
+slidescreen.o: $(srcdir)/recanim.h
 slidescreen.o: $(srcdir)/screenhackI.h
 slidescreen.o: $(srcdir)/screenhack.h
 slidescreen.o: $(UTILS_SRC)/colors.h
@@ -2583,6 +2736,7 @@ slidescreen.o: $(UTILS_SRC)/visual.h
 slidescreen.o: $(UTILS_SRC)/yarandom.h
 slip.o: ../config.h
 slip.o: $(srcdir)/fps.h
+slip.o: $(srcdir)/recanim.h
 slip.o: $(srcdir)/screenhackI.h
 slip.o: $(UTILS_SRC)/colors.h
 slip.o: $(UTILS_SRC)/erase.h
@@ -2597,6 +2751,7 @@ slip.o: $(srcdir)/xlockmoreI.h
 slip.o: $(srcdir)/xlockmore.h
 speedmine.o: ../config.h
 speedmine.o: $(srcdir)/fps.h
+speedmine.o: $(srcdir)/recanim.h
 speedmine.o: $(srcdir)/screenhackI.h
 speedmine.o: $(srcdir)/screenhack.h
 speedmine.o: $(UTILS_SRC)/colors.h
@@ -2610,6 +2765,7 @@ speedmine.o: $(UTILS_SRC)/visual.h
 speedmine.o: $(UTILS_SRC)/yarandom.h
 sphere.o: ../config.h
 sphere.o: $(srcdir)/fps.h
+sphere.o: $(srcdir)/recanim.h
 sphere.o: $(srcdir)/screenhackI.h
 sphere.o: $(UTILS_SRC)/colors.h
 sphere.o: $(UTILS_SRC)/erase.h
@@ -2624,6 +2780,7 @@ sphere.o: $(srcdir)/xlockmoreI.h
 sphere.o: $(srcdir)/xlockmore.h
 spiral.o: ../config.h
 spiral.o: $(srcdir)/fps.h
+spiral.o: $(srcdir)/recanim.h
 spiral.o: $(srcdir)/screenhackI.h
 spiral.o: $(UTILS_SRC)/colors.h
 spiral.o: $(UTILS_SRC)/erase.h
@@ -2638,6 +2795,7 @@ spiral.o: $(srcdir)/xlockmoreI.h
 spiral.o: $(srcdir)/xlockmore.h
 spotlight.o: ../config.h
 spotlight.o: $(srcdir)/fps.h
+spotlight.o: $(srcdir)/recanim.h
 spotlight.o: $(srcdir)/screenhackI.h
 spotlight.o: $(srcdir)/screenhack.h
 spotlight.o: $(UTILS_SRC)/colors.h
@@ -2650,6 +2808,7 @@ spotlight.o: $(UTILS_SRC)/visual.h
 spotlight.o: $(UTILS_SRC)/yarandom.h
 squiral.o: ../config.h
 squiral.o: $(srcdir)/fps.h
+squiral.o: $(srcdir)/recanim.h
 squiral.o: $(srcdir)/screenhackI.h
 squiral.o: $(srcdir)/screenhack.h
 squiral.o: $(UTILS_SRC)/colors.h
@@ -2663,6 +2822,7 @@ squiral.o: $(UTILS_SRC)/visual.h
 squiral.o: $(UTILS_SRC)/yarandom.h
 starfish.o: ../config.h
 starfish.o: $(srcdir)/fps.h
+starfish.o: $(srcdir)/recanim.h
 starfish.o: $(srcdir)/screenhackI.h
 starfish.o: $(srcdir)/screenhack.h
 starfish.o: $(UTILS_SRC)/colors.h
@@ -2676,6 +2836,7 @@ starfish.o: $(UTILS_SRC)/visual.h
 starfish.o: $(UTILS_SRC)/yarandom.h
 strange.o: ../config.h
 strange.o: $(srcdir)/fps.h
+strange.o: $(srcdir)/recanim.h
 strange.o: $(srcdir)/screenhackI.h
 strange.o: $(UTILS_SRC)/aligned_malloc.h
 strange.o: $(UTILS_SRC)/colors.h
@@ -2694,6 +2855,7 @@ strange.o: $(srcdir)/xlockmoreI.h
 strange.o: $(srcdir)/xlockmore.h
 substrate.o: ../config.h
 substrate.o: $(srcdir)/fps.h
+substrate.o: $(srcdir)/recanim.h
 substrate.o: $(srcdir)/screenhackI.h
 substrate.o: $(srcdir)/screenhack.h
 substrate.o: $(UTILS_SRC)/colors.h
@@ -2706,6 +2868,7 @@ substrate.o: $(UTILS_SRC)/visual.h
 substrate.o: $(UTILS_SRC)/yarandom.h
 swirl.o: ../config.h
 swirl.o: $(srcdir)/fps.h
+swirl.o: $(srcdir)/recanim.h
 swirl.o: $(srcdir)/screenhackI.h
 swirl.o: $(UTILS_SRC)/colors.h
 swirl.o: $(UTILS_SRC)/erase.h
@@ -2721,6 +2884,7 @@ swirl.o: $(srcdir)/xlockmoreI.h
 swirl.o: $(srcdir)/xlockmore.h
 t3d.o: ../config.h
 t3d.o: $(srcdir)/fps.h
+t3d.o: $(srcdir)/recanim.h
 t3d.o: $(srcdir)/screenhackI.h
 t3d.o: $(srcdir)/screenhack.h
 t3d.o: $(UTILS_SRC)/colors.h
@@ -2734,6 +2898,7 @@ t3d.o: $(UTILS_SRC)/yarandom.h
 tessellimage.o: ../config.h
 tessellimage.o: $(srcdir)/delaunay.h
 tessellimage.o: $(srcdir)/fps.h
+tessellimage.o: $(srcdir)/recanim.h
 tessellimage.o: $(srcdir)/screenhackI.h
 tessellimage.o: $(srcdir)/screenhack.h
 tessellimage.o: $(UTILS_SRC)/colors.h
@@ -2748,6 +2913,7 @@ testx11.o: ../config.h
 testx11.o: $(srcdir)/fps.h
 testx11.o: $(srcdir)/glx/rotator.h
 testx11.o: $(srcdir)/images/gen/logo-180_png.h
+testx11.o: $(srcdir)/recanim.h
 testx11.o: $(srcdir)/screenhackI.h
 testx11.o: $(srcdir)/screenhack.h
 testx11.o: $(UTILS_SRC)/colorbars.h
@@ -2763,6 +2929,7 @@ testx11.o: $(UTILS_SRC)/yarandom.h
 testx11.o: $(srcdir)/ximage-loader.h
 thornbird.o: ../config.h
 thornbird.o: $(srcdir)/fps.h
+thornbird.o: $(srcdir)/recanim.h
 thornbird.o: $(srcdir)/screenhackI.h
 thornbird.o: $(UTILS_SRC)/colors.h
 thornbird.o: $(UTILS_SRC)/erase.h
@@ -2777,6 +2944,7 @@ thornbird.o: $(srcdir)/xlockmoreI.h
 thornbird.o: $(srcdir)/xlockmore.h
 triangle.o: ../config.h
 triangle.o: $(srcdir)/fps.h
+triangle.o: $(srcdir)/recanim.h
 triangle.o: $(srcdir)/screenhackI.h
 triangle.o: $(UTILS_SRC)/colors.h
 triangle.o: $(UTILS_SRC)/erase.h
@@ -2791,6 +2959,7 @@ triangle.o: $(srcdir)/xlockmoreI.h
 triangle.o: $(srcdir)/xlockmore.h
 truchet.o: ../config.h
 truchet.o: $(srcdir)/fps.h
+truchet.o: $(srcdir)/recanim.h
 truchet.o: $(srcdir)/screenhackI.h
 truchet.o: $(srcdir)/screenhack.h
 truchet.o: $(UTILS_SRC)/colors.h
@@ -2803,6 +2972,7 @@ truchet.o: $(UTILS_SRC)/visual.h
 truchet.o: $(UTILS_SRC)/yarandom.h
 twang.o: ../config.h
 twang.o: $(srcdir)/fps.h
+twang.o: $(srcdir)/recanim.h
 twang.o: $(srcdir)/screenhackI.h
 twang.o: $(srcdir)/screenhack.h
 twang.o: $(UTILS_SRC)/colors.h
@@ -2816,6 +2986,7 @@ twang.o: $(UTILS_SRC)/xshm.h
 twang.o: $(UTILS_SRC)/yarandom.h
 vermiculate.o: ../config.h
 vermiculate.o: $(srcdir)/fps.h
+vermiculate.o: $(srcdir)/recanim.h
 vermiculate.o: $(srcdir)/screenhackI.h
 vermiculate.o: $(srcdir)/screenhack.h
 vermiculate.o: $(UTILS_SRC)/colors.h
@@ -2826,8 +2997,26 @@ vermiculate.o: $(UTILS_SRC)/resources.h
 vermiculate.o: $(UTILS_SRC)/usleep.h
 vermiculate.o: $(UTILS_SRC)/visual.h
 vermiculate.o: $(UTILS_SRC)/yarandom.h
+vfeedback.o: $(srcdir)/analogtv.h
+vfeedback.o: ../config.h
+vfeedback.o: $(srcdir)/fps.h
+vfeedback.o: $(srcdir)/recanim.h
+vfeedback.o: $(srcdir)/screenhackI.h
+vfeedback.o: $(srcdir)/screenhack.h
+vfeedback.o: $(UTILS_SRC)/aligned_malloc.h
+vfeedback.o: $(UTILS_SRC)/colors.h
+vfeedback.o: $(UTILS_SRC)/font-retry.h
+vfeedback.o: $(UTILS_SRC)/grabscreen.h
+vfeedback.o: $(UTILS_SRC)/hsv.h
+vfeedback.o: $(UTILS_SRC)/resources.h
+vfeedback.o: $(UTILS_SRC)/thread_util.h
+vfeedback.o: $(UTILS_SRC)/usleep.h
+vfeedback.o: $(UTILS_SRC)/visual.h
+vfeedback.o: $(UTILS_SRC)/xshm.h
+vfeedback.o: $(UTILS_SRC)/yarandom.h
 vines.o: ../config.h
 vines.o: $(srcdir)/fps.h
+vines.o: $(srcdir)/recanim.h
 vines.o: $(srcdir)/screenhackI.h
 vines.o: $(UTILS_SRC)/colors.h
 vines.o: $(UTILS_SRC)/erase.h
@@ -2842,6 +3031,7 @@ vines.o: $(srcdir)/xlockmoreI.h
 vines.o: $(srcdir)/xlockmore.h
 wander.o: ../config.h
 wander.o: $(srcdir)/fps.h
+wander.o: $(srcdir)/recanim.h
 wander.o: $(srcdir)/screenhackI.h
 wander.o: $(srcdir)/screenhack.h
 wander.o: $(UTILS_SRC)/colors.h
@@ -2855,6 +3045,7 @@ wander.o: $(UTILS_SRC)/visual.h
 wander.o: $(UTILS_SRC)/yarandom.h
 webcollage-cocoa.o: ../config.h
 webcollage-cocoa.o: $(srcdir)/fps.h
+webcollage-cocoa.o: $(srcdir)/recanim.h
 webcollage-cocoa.o: $(srcdir)/screenhackI.h
 webcollage-cocoa.o: $(srcdir)/screenhack.h
 webcollage-cocoa.o: $(UTILS_SRC)/colors.h
@@ -2868,6 +3059,7 @@ webcollage-cocoa.o: $(UTILS_SRC)/yarandom.h
 webcollage-helper.o: ../config.h
 whirlwindwarp.o: ../config.h
 whirlwindwarp.o: $(srcdir)/fps.h
+whirlwindwarp.o: $(srcdir)/recanim.h
 whirlwindwarp.o: $(srcdir)/screenhackI.h
 whirlwindwarp.o: $(srcdir)/screenhack.h
 whirlwindwarp.o: $(UTILS_SRC)/colors.h
@@ -2881,6 +3073,7 @@ whirlwindwarp.o: $(UTILS_SRC)/visual.h
 whirlwindwarp.o: $(UTILS_SRC)/yarandom.h
 whirlygig.o: ../config.h
 whirlygig.o: $(srcdir)/fps.h
+whirlygig.o: $(srcdir)/recanim.h
 whirlygig.o: $(srcdir)/screenhackI.h
 whirlygig.o: $(srcdir)/screenhack.h
 whirlygig.o: $(UTILS_SRC)/colors.h
@@ -2894,6 +3087,7 @@ whirlygig.o: $(UTILS_SRC)/xdbe.h
 whirlygig.o: $(UTILS_SRC)/yarandom.h
 wormhole.o: ../config.h
 wormhole.o: $(srcdir)/fps.h
+wormhole.o: $(srcdir)/recanim.h
 wormhole.o: $(srcdir)/screenhackI.h
 wormhole.o: $(srcdir)/screenhack.h
 wormhole.o: $(UTILS_SRC)/colors.h
@@ -2906,6 +3100,7 @@ wormhole.o: $(UTILS_SRC)/visual.h
 wormhole.o: $(UTILS_SRC)/yarandom.h
 worm.o: ../config.h
 worm.o: $(srcdir)/fps.h
+worm.o: $(srcdir)/recanim.h
 worm.o: $(srcdir)/screenhackI.h
 worm.o: $(UTILS_SRC)/colors.h
 worm.o: $(UTILS_SRC)/erase.h
@@ -2921,6 +3116,11 @@ worm.o: $(srcdir)/xlockmore.h
 xanalogtv.o: $(srcdir)/analogtv.h
 xanalogtv.o: ../config.h
 xanalogtv.o: $(srcdir)/fps.h
+xanalogtv.o: $(srcdir)/images/gen/logo-180_png.h
+xanalogtv.o: $(srcdir)/images/gen/testcard_bbcf_png.h
+xanalogtv.o: $(srcdir)/images/gen/testcard_pm5544_png.h
+xanalogtv.o: $(srcdir)/images/gen/testcard_rca_png.h
+xanalogtv.o: $(srcdir)/recanim.h
 xanalogtv.o: $(srcdir)/screenhackI.h
 xanalogtv.o: $(srcdir)/screenhack.h
 xanalogtv.o: $(UTILS_SRC)/aligned_malloc.h
@@ -2928,7 +3128,6 @@ xanalogtv.o: $(UTILS_SRC)/colors.h
 xanalogtv.o: $(UTILS_SRC)/font-retry.h
 xanalogtv.o: $(UTILS_SRC)/grabscreen.h
 xanalogtv.o: $(UTILS_SRC)/hsv.h
-xanalogtv.o: $(UTILS_SRC)/images/logo-50.xpm
 xanalogtv.o: $(UTILS_SRC)/resources.h
 xanalogtv.o: $(UTILS_SRC)/thread_util.h
 xanalogtv.o: $(UTILS_SRC)/usleep.h
@@ -2939,6 +3138,7 @@ xanalogtv.o: $(srcdir)/ximage-loader.h
 xflame.o: ../config.h
 xflame.o: $(srcdir)/fps.h
 xflame.o: $(srcdir)/images/gen/bob_png.h
+xflame.o: $(srcdir)/recanim.h
 xflame.o: $(srcdir)/screenhackI.h
 xflame.o: $(srcdir)/screenhack.h
 xflame.o: $(UTILS_SRC)/colors.h
@@ -2955,6 +3155,7 @@ ximage-loader.o: ../config.h
 ximage-loader.o: $(srcdir)/ximage-loader.h
 xjack.o: ../config.h
 xjack.o: $(srcdir)/fps.h
+xjack.o: $(srcdir)/recanim.h
 xjack.o: $(srcdir)/screenhackI.h
 xjack.o: $(srcdir)/screenhack.h
 xjack.o: $(UTILS_SRC)/colors.h
@@ -2967,6 +3168,7 @@ xjack.o: $(UTILS_SRC)/visual.h
 xjack.o: $(UTILS_SRC)/yarandom.h
 xlockmore.o: ../config.h
 xlockmore.o: $(srcdir)/fps.h
+xlockmore.o: $(srcdir)/recanim.h
 xlockmore.o: $(srcdir)/screenhackI.h
 xlockmore.o: $(srcdir)/screenhack.h
 xlockmore.o: $(UTILS_SRC)/colors.h
@@ -2981,6 +3183,7 @@ xlockmore.o: $(UTILS_SRC)/yarandom.h
 xlockmore.o: $(srcdir)/xlockmoreI.h
 xlyap.o: ../config.h
 xlyap.o: $(srcdir)/fps.h
+xlyap.o: $(srcdir)/recanim.h
 xlyap.o: $(srcdir)/screenhackI.h
 xlyap.o: $(srcdir)/screenhack.h
 xlyap.o: $(UTILS_SRC)/colors.h
@@ -2997,6 +3200,7 @@ xmatrix.o: $(srcdir)/images/gen/matrix1b_png.h
 xmatrix.o: $(srcdir)/images/gen/matrix1_png.h
 xmatrix.o: $(srcdir)/images/gen/matrix2b_png.h
 xmatrix.o: $(srcdir)/images/gen/matrix2_png.h
+xmatrix.o: $(srcdir)/recanim.h
 xmatrix.o: $(srcdir)/screenhackI.h
 xmatrix.o: $(srcdir)/screenhack.h
 xmatrix.o: $(UTILS_SRC)/colors.h
@@ -3011,6 +3215,7 @@ xmatrix.o: $(UTILS_SRC)/yarandom.h
 xmatrix.o: $(srcdir)/ximage-loader.h
 xrayswarm.o: ../config.h
 xrayswarm.o: $(srcdir)/fps.h
+xrayswarm.o: $(srcdir)/recanim.h
 xrayswarm.o: $(srcdir)/screenhackI.h
 xrayswarm.o: $(srcdir)/screenhack.h
 xrayswarm.o: $(UTILS_SRC)/colors.h
@@ -3024,6 +3229,7 @@ xrayswarm.o: $(UTILS_SRC)/yarandom.h
 xscreensaver-sgigl.o: $(UTILS_SRC)/vroot.h
 xspirograph.o: ../config.h
 xspirograph.o: $(srcdir)/fps.h
+xspirograph.o: $(srcdir)/recanim.h
 xspirograph.o: $(srcdir)/screenhackI.h
 xspirograph.o: $(srcdir)/screenhack.h
 xspirograph.o: $(UTILS_SRC)/colors.h
@@ -3043,6 +3249,7 @@ xsublim.o: $(UTILS_SRC)/vroot.h
 xsublim.o: $(UTILS_SRC)/yarandom.h
 zoom.o: ../config.h
 zoom.o: $(srcdir)/fps.h
+zoom.o: $(srcdir)/recanim.h
 zoom.o: $(srcdir)/screenhackI.h
 zoom.o: $(srcdir)/screenhack.h
 zoom.o: $(UTILS_SRC)/colors.h
index e3af6f2be287c7419b06f3b10a79d274466e4c7e..fd7f504c68d705614c57552405044932694b7b6b 100644 (file)
@@ -568,6 +568,9 @@ analogtv_allocate(Display *dpy, Window window)
                                     "background", "Background");
 
   it->gc = XCreateGC(it->dpy, it->window, GCBackground, &gcv);
+# ifdef HAVE_JWXYZ
+  jwxyz_XSetAntiAliasing (it->dpy, it->gc, False);
+# endif
   XSetWindowBackground(it->dpy, it->window, gcv.background);
   XClearWindow(dpy,window);
 
@@ -1983,10 +1986,16 @@ analogtv_input_allocate()
   This takes a screen image and encodes it as a video camera would,
   including all the bandlimiting and YIQ modulation.
   This isn't especially tuned for speed.
+
+  xoff, yoff: top left corner of rendered image, in window pixels.
+  w, h: scaled size of rendered image, in window pixels.
+  mask: BlackPixel means don't render (it's not full alpha)
 */
 
 int
-analogtv_load_ximage(analogtv *it, analogtv_input *input, XImage *pic_im)
+analogtv_load_ximage(analogtv *it, analogtv_input *input,
+                     XImage *pic_im, XImage *mask_im,
+                     int xoff, int yoff, int target_w, int target_h)
 {
   int i,x,y;
   int img_w,img_h;
@@ -1995,14 +2004,24 @@ analogtv_load_ximage(analogtv *it, analogtv_input *input, XImage *pic_im)
   int fqx[4],fqy[4];
   XColor col1[ANALOGTV_PIC_LEN];
   XColor col2[ANALOGTV_PIC_LEN];
+  char mask[ANALOGTV_PIC_LEN];
   int multiq[ANALOGTV_PIC_LEN+4];
+  unsigned long black = 0; /* not BlackPixelOfScreen (it->xgwa.screen); */
+
+  int x_length=ANALOGTV_PIC_LEN;
   int y_overscan=5; /* overscan this much top and bottom */
   int y_scanlength=ANALOGTV_VISLINES+2*y_overscan;
 
-  img_w=pic_im->width;
-  img_h=pic_im->height;
+  if (target_w > 0) x_length     = x_length     * target_w / it->xgwa.width;
+  if (target_h > 0) y_scanlength = y_scanlength * target_h / it->xgwa.height;
+
+  img_w = pic_im->width;
+  img_h = pic_im->height;
   
-  for (i=0; i<ANALOGTV_PIC_LEN+4; i++) {
+  xoff = ANALOGTV_PIC_LEN  * xoff / it->xgwa.width;
+  yoff = ANALOGTV_VISLINES * yoff / it->xgwa.height;
+
+  for (i=0; i<x_length+4; i++) {
     double phase=90.0-90.0*i;
     double ampl=1.0;
     multiq[i]=(int)(-cos(3.1415926/180.0*(phase-303)) * 4096.0 * ampl);
@@ -2012,21 +2031,27 @@ analogtv_load_ximage(analogtv *it, analogtv_input *input, XImage *pic_im)
     int picy1=(y*img_h)/y_scanlength;
     int picy2=(y*img_h + y_scanlength/2)/y_scanlength;
 
-    for (x=0; x<ANALOGTV_PIC_LEN; x++) {
-      int picx=(x*img_w)/ANALOGTV_PIC_LEN;
+    for (x=0; x<x_length; x++) {
+      int picx=(x*img_w)/x_length;
       col1[x].pixel=XGetPixel(pic_im, picx, picy1);
       col2[x].pixel=XGetPixel(pic_im, picx, picy2);
+      if (mask_im)
+        mask[x] = (XGetPixel(mask_im, picx, picy1) != black);
+      else
+        mask[x] = 1;
     }
-    XQueryColors(it->dpy, it->colormap, col1, ANALOGTV_PIC_LEN);
-    XQueryColors(it->dpy, it->colormap, col2, ANALOGTV_PIC_LEN);
-
+    XQueryColors(it->dpy, it->colormap, col1, x_length);
+    XQueryColors(it->dpy, it->colormap, col2, x_length);
     for (i=0; i<7; i++) fyx[i]=fyy[i]=0;
     for (i=0; i<4; i++) fix[i]=fiy[i]=fqx[i]=fqy[i]=0.0;
 
-    for (x=0; x<ANALOGTV_PIC_LEN; x++) {
+    for (x=0; x<x_length; x++) {
       int rawy,rawi,rawq;
       int filty,filti,filtq;
       int composite;
+
+      if (!mask[x]) continue;
+
       /* Compute YIQ as:
            y=0.30 r + 0.59 g + 0.11 b
            i=0.60 r - 0.28 g - 0.32 b
@@ -2078,7 +2103,8 @@ analogtv_load_ximage(analogtv *it, analogtv_input *input, XImage *pic_im)
       composite = ((composite*100)>>14) + ANALOGTV_BLACK_LEVEL;
       if (composite>125) composite=125;
       if (composite<0) composite=0;
-      input->signal[y-y_overscan+ANALOGTV_TOP][x+ANALOGTV_PIC_START] = composite;
+
+      input->signal[y-y_overscan+ANALOGTV_TOP+yoff][x+ANALOGTV_PIC_START+xoff] = composite;
     }
   }
 
@@ -2243,6 +2269,9 @@ analogtv_make_font(Display *dpy, Window window, analogtv_font *f,
     gcv.background=0;
     gcv.font=font->fid;
     gc=XCreateGC(dpy, text_pm, GCFont|GCBackground|GCForeground, &gcv);
+# ifdef HAVE_JWXYZ
+  jwxyz_XSetAntiAliasing (dpy, gc, False);
+# endif
 
     XSetForeground(dpy, gc, 0);
     XFillRectangle(dpy, text_pm, gc, 0, 0, 256*f->char_w, f->char_h);
@@ -2400,115 +2429,3 @@ analogtv_draw_string_centered(analogtv_input *input, analogtv_font *f,
 
   analogtv_draw_string(input, f, s, x, y, ntsc);
 }
-
-
-static const char hextonib[128] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                   0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
-                                   0, 10,11,12,13,14,15,0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                   0, 10,11,12,13,14,15,0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
-/*
-  Much of this function was adapted from logo.c
- */
-void
-analogtv_draw_xpm(analogtv *tv, analogtv_input *input,
-                  const char * const *xpm, int left, int top)
-{
-  int xpmw,xpmh;
-  int x,y,tvx,tvy,i;
-  int rawy,rawi,rawq;
-  int ncolors, nbytes;
-  char dummyc;
-  struct {
-    int r; int g; int b;
-  } cmap[256];
-
-
-  if (4 != sscanf ((const char *) *xpm,
-                   "%d %d %d %d %c",
-                   &xpmw, &xpmh, &ncolors, &nbytes, &dummyc))
-    abort();
-  if (ncolors < 1 || ncolors > 255)
-    abort();
-  if (nbytes != 1) /* a serious limitation */
-    abort();
-  xpm++;
-
-  for (i = 0; i < ncolors; i++) {
-    const char *line = *xpm;
-    int colori = ((unsigned char)*line++)&0xff;
-    while (*line)
-      {
-        int r, g, b;
-        char which;
-        while (*line == ' ' || *line == '\t')
-          line++;
-        which = *line++;
-        if (which != 'c' && which != 'm')
-          abort();
-        while (*line == ' ' || *line == '\t')
-          line++;
-        if (!strncasecmp(line, "None", 4))
-          {
-            r = g = b = -1;
-            line += 4;
-          }
-        else
-          {
-            if (*line == '#')
-              line++;
-            r = (hextonib[(int) line[0]] << 4) | hextonib[(int) line[1]];
-            line += 2;
-            g = (hextonib[(int) line[0]] << 4) | hextonib[(int) line[1]];
-            line += 2;
-            b = (hextonib[(int) line[0]] << 4) | hextonib[(int) line[1]];
-            line += 2;
-          }
-
-        if (which == 'c')
-          {
-            cmap[colori].r = r;
-            cmap[colori].g = g;
-            cmap[colori].b = b;
-          }
-      }
-
-    xpm++;
-  }
-
-  for (y=0; y<xpmh; y++) {
-    const char *line = *xpm++;
-    tvy=y+top;
-    if (tvy<ANALOGTV_TOP || tvy>=ANALOGTV_BOT) continue;
-
-    for (x=0; x<xpmw; x++) {
-      int cbyte=((unsigned char)line[x])&0xff;
-      int ntsc[4];
-      tvx=x*4+left;
-      if (tvx<ANALOGTV_PIC_START || tvx+4>ANALOGTV_PIC_END) continue;
-
-      rawy=( 5*cmap[cbyte].r + 11*cmap[cbyte].g + 2*cmap[cbyte].b) / 64;
-      rawi=(10*cmap[cbyte].r -  4*cmap[cbyte].g - 5*cmap[cbyte].b) / 64;
-      rawq=( 3*cmap[cbyte].r -  8*cmap[cbyte].g + 5*cmap[cbyte].b) / 64;
-
-      ntsc[0]=rawy+rawq;
-      ntsc[1]=rawy-rawi;
-      ntsc[2]=rawy-rawq;
-      ntsc[3]=rawy+rawi;
-
-      for (i=0; i<4; i++) {
-        if (ntsc[i]>ANALOGTV_WHITE_LEVEL) ntsc[i]=ANALOGTV_WHITE_LEVEL;
-        if (ntsc[i]<ANALOGTV_BLACK_LEVEL) ntsc[i]=ANALOGTV_BLACK_LEVEL;
-      }
-
-      input->signal[tvy][tvx+0]= ntsc[(tvx+0)&3];
-      input->signal[tvy][tvx+1]= ntsc[(tvx+1)&3];
-      input->signal[tvy][tvx+2]= ntsc[(tvx+2)&3];
-      input->signal[tvy][tvx+3]= ntsc[(tvx+3)&3];
-    }
-  }
-}
index ed3ce340bb184362b3da02f433fef405daa227f4..e3170f1d2590d1eb029fc953b1987df3eb9bdc96 100644 (file)
@@ -1,4 +1,4 @@
-/* analogtv, Copyright (c) 2003-2016 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
@@ -252,7 +252,9 @@ void analogtv_setup_sync(analogtv_input *input, int do_cb, int do_ssavi);
 void analogtv_draw(analogtv *it, double noiselevel,
                    const analogtv_reception *const *recs, unsigned rec_count);
 
-int analogtv_load_ximage(analogtv *it, analogtv_input *input, XImage *pic_im);
+int analogtv_load_ximage(analogtv *it, analogtv_input *input,
+                         XImage *pic_im, XImage *mask_im,
+                         int xoff, int yoff, int width, int height);
 
 void analogtv_reception_update(analogtv_reception *inp);
 
@@ -285,8 +287,6 @@ void analogtv_draw_string(analogtv_input *input, analogtv_font *f,
                           char *s, int x, int y, int ntsc[4]);
 void analogtv_draw_string_centered(analogtv_input *input, analogtv_font *f,
                                    char *s, int x, int y, int ntsc[4]);
-void analogtv_draw_xpm(analogtv *tv, analogtv_input *input,
-                       const char * const *xpm, int left, int top);
 
 int analogtv_handle_events (analogtv *it);
 
@@ -305,6 +305,15 @@ int analogtv_handle_events (analogtv *it);
 # define ANALOGTV_DEF_CONTRAST "400"
 #endif
 
+/* Brightness: useful range is around -75 to 100.
+   Contrast:   useful range is around 0 - 500.
+   Color:      useful range is around +/- 500.
+   Tint:       range is mod 360.
+
+   The values in the 'analogtv' struct are the resource divided by 100.0,
+   except for tint, which is exact.
+ */
+
 #define ANALOGTV_DEFAULTS \
   "*TVColor:         70", \
   "*TVTint:          5",  \
@@ -314,6 +323,7 @@ int analogtv_handle_events (analogtv *it);
   "*use_cmap:        0",  \
   "*geometry:       800x600", \
   "*fpsSolid:       True", \
+  "*lowrez:         True", \
   THREAD_DEFAULTS \
   ANALOGTV_DEFAULTS_SHM
 
index 46225e5dd13cb975c21d56ef057f739f39604f3a..ff6c359fdd092114cf4def7a7b6611838c977447 100644 (file)
@@ -1533,6 +1533,7 @@ windows_ransomware (Display *dpy, Window window)
     "Dunning-Krugerrands",
     "Dunning-Krugerrands",
     "gift certificates",
+    "Creepto-Currency",
     "secret sauce",
     "Tribbles",
   };
index c07a51a1e11fee17d16f5531541e0177f5b9d3bd..c50e0f96d74698788c64f9352c5f3fd1d2f2277c 100644 (file)
@@ -41,6 +41,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) EULER2D.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FADEPLOT.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FIBERLAMP.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FILMLEADER.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FIREWORKX.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FLAG.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FLAME.C
@@ -51,6 +52,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FPS.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FUZZYFLAKES.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) GALAXY.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) GLITCHPEG.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) GOOP.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) GRAV.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) GREYNETIC.C
@@ -130,6 +132,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) TRUCHET.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) TWANG.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) VERMICULATE.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) VFEEDBACK.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) VINES.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) WANDER.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) WEBCOLLAGE-COCOA.M
index c07a51a1e11fee17d16f5531541e0177f5b9d3bd..c50e0f96d74698788c64f9352c5f3fd1d2f2277c 100644 (file)
@@ -41,6 +41,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) EULER2D.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FADEPLOT.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FIBERLAMP.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FILMLEADER.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FIREWORKX.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FLAG.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FLAME.C
@@ -51,6 +52,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FPS.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) FUZZYFLAKES.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) GALAXY.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) GLITCHPEG.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) GOOP.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) GRAV.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) GREYNETIC.C
@@ -130,6 +132,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) TRUCHET.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) TWANG.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) VERMICULATE.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) VFEEDBACK.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) VINES.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) WANDER.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) WEBCOLLAGE-COCOA.M
index 82656aeed19324222ea7245a6c400cf4cf79e24c..9771a89ca58c7e2ba2c92bce2db6317230b15832 100644 (file)
@@ -4,8 +4,8 @@
             a screen saver and locker for the X window system
                             by Jamie Zawinski
 
-                              version 5.39
-                               12-Apr-2018
+                              version 5.40
+                               12-Aug-2018
 
                      https://www.jwz.org/xscreensaver/
 
index e48fc2ce8875b8a6ee2ef434aa41ebbbe0793349..4084bc9637b59b6c16be8c4ba3fa84290694c66b 100644 (file)
    <vgroup>
     <number id="tvcolor" type="slider" arg="-tv-color %"
             _label="Color Knob" _low-label="Low" _high-label="High"
-            low="0" high="1000" default="70"/>
+            low="0" high="400" default="70"/>
     <number id="tvtint" type="slider" arg="-tv-tint %"
             _label="Tint Knob" _low-label="Low" _high-label="High"
-            low="0" high="100" default="5"/>
+            low="0" high="360" default="5"/>
     <number id="tvbrightness" type="slider" arg="-tv-brightness %"
             _label="Brightness Knob" _low-label="Low" _high-label="High"
-            low="0" high="200" default="150"/>
+            low="-75.0" high="100.0" default="3.0"/>
     <number id="tvcontrast" type="slider" arg="-tv-contrast %"
             _label="Contrast Knob" _low-label="Low" _high-label="High"
-            low="0" high="1500" default="1000"/>
+            low="0" high="500" default="150"/>
    </vgroup>
   </hgroup>
 
index ea3d07cb13aafbd24575e9d427a76840a3987809..ef18e2128b91cd3d5a209f1f1c76cd9aae2cf856 100644 (file)
    <vgroup>
     <number id="tvcolor" type="slider" arg="-tv-color %"
             _label="Color Knob" _low-label="Low" _high-label="High"
-            low="0" high="1000" default="70"/>
+            low="0" high="400" default="70"/>
     <number id="tvtint" type="slider" arg="-tv-tint %"
             _label="Tint Knob" _low-label="Low" _high-label="High"
-            low="0" high="100" default="5"/>
+            low="0" high="360" default="5"/>
    </vgroup>
    <vgroup>
     <number id="tvbrightness" type="slider" arg="-tv-brightness %"
             _label="Brightness Knob" _low-label="Low" _high-label="High"
-            low="0" high="200" default="150"/>
+            low="-75.0" high="100.0" default="3.0"/>
     <number id="tvcontrast" type="slider" arg="-tv-contrast %"
             _label="Contrast Knob" _low-label="Low" _high-label="High"
-            low="0" high="1500" default="1000"/>
+            low="0" high="500" default="150"/>
    </vgroup>
   </hgroup>
 -->
index daad604b2e195444fc2b41e06e3c696485eeb581..533d710a0a247a5c2d5cde123c9e17711a58011a 100644 (file)
@@ -6,27 +6,39 @@
 
   <video href="https://www.youtube.com/watch?v=enuZbkMiqCE"/>
 
-  <number id="delay" type="slider" arg="-delay %"
-          _label="Frame rate" _low-label="Low" _high-label="High"
-          low="0" high="100000" default="30000"
-          convert="invert"/>
-
-  <number id="speed" type="slider" arg="-speed %"
-          _label="Speed" _low-label="Slow" _high-label="Fast"
-          low="0.01" high="5.0" default="1.0"/>
-
-  <number id="count" type="slider" arg="-count %"
-          _label="Cubes" _low-label="Few" _high-label="Many"
-          low="1" high="20" default="4"/>
-
-  <number id="thickness" type="slider" arg="-thickness %"
-          _label="Struts" _low-label="Thin" _high-label="Thick"
-          low="0.01" high="1.0" default="0.06"/>
-
   <hgroup>
-   <boolean id="wander" _label="Wander"    arg-unset="-no-wander"/>
-   <boolean id="spin"   _label="Spin"      arg-unset="-no-spin"/>
-   <boolean id="wire"   _label="Wireframe" arg-set="-wireframe"/>
+   <vgroup>
+    <number id="delay" type="slider" arg="-delay %"
+            _label="Frame rate" _low-label="Low" _high-label="High"
+            low="0" high="100000" default="30000"
+            convert="invert"/>
+
+    <number id="speed" type="slider" arg="-speed %"
+            _label="Speed" _low-label="Slow" _high-label="Fast"
+            low="0.01" high="5.0" default="1.0"/>
+
+    <number id="count" type="slider" arg="-count %"
+            _label="Cubes" _low-label="Few" _high-label="Many"
+            low="1" high="20" default="4"/>
+
+   </vgroup>
+   <vgroup>
+
+    <number id="length" type="slider" arg="-length %"
+            _label="Length" _low-label="Short" _high-label="Long"
+            low="20" high="1000" default="200"/>
+
+    <number id="thickness" type="slider" arg="-thickness %"
+            _label="Struts" _low-label="Thin" _high-label="Thick"
+            low="0.01" high="1.0" default="0.06"/>
+
+    <hgroup>
+     <boolean id="wander" _label="Wander"    arg-unset="-no-wander"/>
+     <boolean id="spin"   _label="Spin"      arg-unset="-no-spin"/>
+     <boolean id="wire"   _label="Wireframe" arg-set="-wireframe"/>
+    </hgroup>
+
+   </vgroup>
   </hgroup>
 
   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
index c5dbb82333f7f510da478c30ebcbb9c8a906edcf..6f846c7075bb69cec9059adfc6f026c2fb121258 100644 (file)
@@ -4,41 +4,75 @@
 
   <command arg="-root"/>
 
-  <video href="https://www.youtube.com/watch?v=I-LwEg8-340"/>
+  <video href="https://www.youtube.com/watch?v=4LnO0UiccGs"/>
 
-  <number id="delay" type="slider" arg="-delay %"
-          _label="Frame rate" _low-label="Low" _high-label="High"
-          low="0" high="100000" default="20000"
-          convert="invert"/>
-
-  <number id="speed" type="slider" arg="-speed %"
-          _label="Animation speed" _low-label="Slow" _high-label="Fast"
-          low="0.05" high="10.0" default="1.0"/>
+  <hgroup>
+   <vgroup>
+    <number id="delay" type="slider" arg="-delay %"
+            _label="Frame rate" _low-label="Low" _high-label="High"
+            low="0" high="100000" default="20000"
+            convert="invert"/>
+    <number id="speed" type="slider" arg="-speed %"
+            _label="Animation speed" _low-label="Slow" _high-label="Fast"
+            low="0.05" high="10.0" default="1.0"/>
+   </vgroup>
+   <vgroup>
 
-  <!-- #### -no-texture -->
+    <hgroup>
+     <select id="map">
+      <option id="flat"  _label="Flat map"/>
+      <option id="day"   _label="Satellite map" arg-set="-image BUILTIN_SAT"/>
+     </select>
 
-  <file id="bitmap" _label="Image file" arg="-image %"/>
+     <!-- <file id="image" _label="Image file" arg="-image %"/> -->
+    </hgroup>
 
-  <hgroup>
-   <boolean id="wander" _label="Wander"    arg-unset="-no-wander"/>
-   <boolean id="roll"   _label="Roll"      arg-unset="-no-roll"/>
-   <boolean id="stars"  _label="Stars"     arg-unset="-no-stars"/>
+    <number id="frames" type="slider" arg="-frames %"
+            _label="Day / night smoothness" _low-label="Low" _high-label="High"
+            low="24" high="1440" default="720"/>
+   </vgroup>
   </hgroup>
-
   <hgroup>
-   <boolean id="wire"    _label="Wireframe"       arg-set="-wireframe"/>
-   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
-  </hgroup>
 
-  <xscreensaver-updater />
+   <vgroup>
+    <hgroup>
+     <boolean id="stars"  _label="Stars"       arg-unset="-no-stars"/>
+     <boolean id="grid"   _label="Lat / Long"  arg-unset="-no-grid"/>
+     <boolean id="wander" _label="Wander"    arg-unset="-no-wander"/>
+     <boolean id="roll"   _label="Roll"      arg-unset="-no-roll"/>
+     <boolean id="wire"    _label="Wireframe"       arg-set="-wireframe"/>
+     <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+    </hgroup>
+
+    <xscreensaver-updater />
+
+   </vgroup>
+  </hgroup>
 
   <_description>
 Buckminster Fuller's map of the Earth projected onto the surface of
 an unfolded icosahedron.  It depicts the Earth's continents as one
 island, or nearly contiguous land masses.
 
+This screen saver animates the progression of the dusk terminator across
+the flattened globe. It includes both satellite and flat-colored map
+imagery, and can load and convert other Equirectangular-projected maps.
+
+"Dymaxion Map" and "The Fuller Projection Map" are trademarks of
+The Buckminster Fuller Institute.
+
+The original Dymaxion Map image is copyright 1982 by
+The Buckminster Fuller Institute. (This program does not use their
+imagery, only similar trigonometry.)
+
+The Dymaxion Map was covered by now-expired US Patent 2,393,676
+(Richard Buckminster Fuller, 1946).
+
 https://en.wikipedia.org/wiki/Dymaxion_map
 https://en.wikipedia.org/wiki/Buckminster_Fuller
+https://en.wikipedia.org/wiki/List_of_map_projections
+https://en.wikipedia.org/wiki/Cahill%E2%80%93Keyes_projection
+https://en.wikipedia.org/wiki/Waterman_butterfly_projection
 
 Written by Jamie Zawinski; 2016.
   </_description>
diff --git a/hacks/config/filmleader.xml b/hacks/config/filmleader.xml
new file mode 100644 (file)
index 0000000..02b4fd7
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="filmleader" _label="FilmLeader">
+
+  <command arg="-root"/>
+
+  <video href="https://www.youtube.com/watch?v=Cng7hmsuLo0"/>
+
+  <hgroup>
+   <vgroup>
+    <number id="tvcolor" type="slider" arg="-tv-color %"
+            _label="Color Knob" _low-label="Low" _high-label="High"
+            low="0" high="400" default="70"/>
+    <number id="tvtint" type="slider" arg="-tv-tint %"
+            _label="Tint Knob" _low-label="Low" _high-label="High"
+            low="0" high="360" default="5"/>
+    <number id="noise" type="slider" arg="-noise %"
+            _label="Noise" _low-label="Low" _high-label="High"
+            low="0.0" high="0.2" default="0.04"/>
+   </vgroup>
+   <vgroup>
+    <number id="tvbrightness" type="slider" arg="-tv-brightness %"
+            _label="Brightness Knob" _low-label="Low" _high-label="High"
+            low="-75.0" high="100.0" default="3.0"/>
+    <number id="tvcontrast" type="slider" arg="-tv-contrast %"
+            _label="Contrast Knob" _low-label="Low" _high-label="High"
+            low="0" high="500" default="150"/>
+    <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+   </vgroup>
+  </hgroup>
+
+  <xscreensaver-updater />
+
+  <_description>
+Displays a looping countdown based on the SMPTE Universal Film leader
+on a simulation of an old analog television.
+
+https://en.wikipedia.org/wiki/Film_leader
+
+Written by Jamie Zawinski; 2018.
+  </_description>
+</screensaver>
diff --git a/hacks/config/glitchpeg.xml b/hacks/config/glitchpeg.xml
new file mode 100644 (file)
index 0000000..f53777c
--- /dev/null
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="glitchpeg" _label="GlitchPEG">
+
+  <command arg="-root"/>
+
+  <video href="https://www.youtube.com/watch?v=Xl5vKJ65_xM"/>
+
+  <hgroup>
+   <vgroup>
+    <number id="delay" type="slider" arg="-delay %"
+            _label="Frame rate" _low-label="Low" _high-label="High"
+            low="0" high="100000" default="30000"
+            convert="invert"/>
+
+    <number id="duration" type="slider" arg="-duration %"
+            _label="Duration" _low-label="1 second" _high-label="10 minutes"
+            low="1" high="600" default="120"/>
+
+    <number id="count" type="slider" arg="-count %"
+            _label="Glitchiness" _low-label="Low" _high-label="High"
+            low="1" high="1024" default="100"/>
+
+   </vgroup>
+
+   <vgroup>
+    <xscreensaver-image />
+    <xscreensaver-updater />
+   </vgroup>
+  </hgroup>
+
+  <_description>
+Loads an image, corrupts it, and then displays the corrupted version,
+several times a second.  After a while, finds a new image to corrupt.
+
+Written by Jamie Zawinski; 2018.
+  </_description>
+</screensaver>
index 877cdfa88d46877bd59670957201485e459c5947..5714b7af7b6a540bde7ece23f6ce3799e5185fe6 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="https://www.youtube.com/watch?v=hXZquXPG4pg"/>
+  <video href="https://www.youtube.com/watch?v=ohcJ1bVkLZ4"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
   <xscreensaver-updater />
 
   <_description>
-The Earth, bouncing around in space.
+The Earth, bouncing around in space, rendered with satellite imagery
+of the planet in both sunlight and darkness.
 
-If you would like it to display a different planet, the texture maps
-that come with "ssystem" work well.
+If you would like it to display a different planet, any pair of
+Equirectangular-projected maps will work.  The maps that come with
+"ssystem" work well.
 
 Written by David Konerding and Jamie Zawinski; 1998.
   </_description>
index dcde3cb138d7a6f2640e3081a2dd015fde634360..5738921d104a63b5025248207d1a0049e3085f4a 100644 (file)
             low="5.0" high="120.0" default="30.0" />
     <number id="tvcolor" type="slider" arg="-tv-color %"
             _label="Color Knob" _low-label="Low" _high-label="High"
-            low="0" high="1000" default="70"/>
+            low="0" high="400" default="70"/>
     <number id="tvtint" type="slider" arg="-tv-tint %"
             _label="Tint Knob" _low-label="Low" _high-label="High"
-            low="0" high="100" default="5"/>
+            low="0" high="360" default="5"/>
    </vgroup>
    <vgroup>
     <number id="ips" type="slider" arg="-ips %"
             low="500" high="120000" default="15000" />
     <number id="tvbrightness" type="slider" arg="-tv-brightness %"
             _label="Brightness Knob" _low-label="Low" _high-label="High"
-            low="0" high="200" default="150"/>
+            low="-75.0" high="100.0" default="3.0"/>
     <number id="tvcontrast" type="slider" arg="-tv-contrast %"
             _label="Contrast Knob" _low-label="Low" _high-label="High"
-            low="0" high="1500" default="1000"/>
+            low="0" high="500" default="150"/>
    </vgroup>
   </hgroup>
 
index 99f0dcd66c4d486d4885dfbe5260c64bcdb9a6e2..ac578daf83df6b0c88860c839a4ea0fcac9713c9 100755 (executable)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=VTAwxTVdyLc"/>
+  <video href="https://www.youtube.com/watch?v=VTAwxTVdyLc"/>
 
   <number id="speed" type="slider" arg="-speed %"
           _label="Speed" _low-label="Slow" _high-label="Fast"
index 3db1ff5c798d4fe36bb6fc706b952028799d0ec0..6ae353a256a562443a8c4655f8316972bb49c475 100644 (file)
    <vgroup>
     <number id="tvbrightness" type="slider" arg="-tv-brightness %"
             _label="Brightness Knob" _low-label="Low" _high-label="High"
-            low="0" high="200" default="150"/>
-
+            low="-75.0" high="100.0" default="3.0"/>
     <number id="tvcontrast" type="slider" arg="-tv-contrast %"
             _label="Contrast Knob" _low-label="Low" _high-label="High"
-            low="0" high="1500" default="1000"/>
+            low="0" high="500" default="150"/>
    </vgroup>
   </hgroup>
 
index 78b44e98f78167634e552a1dedf94dd1a438eebc..f6e1a3caf4cddf5e860deff65993d33c51def44e 100644 (file)
     <number id="depth" type="slider" arg="-max-depth %"
             _label="Complexity" _low-label="Shallow" _high-label="Deep"
             low="1000" high="100000" default="30000"/>
-
    </vgroup>
 
    <vgroup>
+
+    <select id="mode">
+     <option id="random" _label="Delaunay or voronoi"/>
+     <option _label="Delaunay" arg-set="-mode delaunay"/>
+     <option _label="Voronoi"  arg-set="-mode voronoi"/>
+    </select>
+
     <xscreensaver-image />
 
     <boolean id="fill"    _label="Fill screen" arg-unset="-no-fill-screen"/>
   </hgroup>
 
   <_description>
-Converts an image to triangles using Delaunay tessellation, and
-animates the result at various depths.
+Converts an image to triangles using Delaunay tessellation, or to
+polygons using Voronoi tesselation, and animates the result at
+various depths.
 
-More triangles are allocated to visually complex parts of the image.
+More polygons are allocated to visually complex parts of the image.
 This is accomplished by first computing the first derivative of the
 image: the distance between each pixel and its neighbors (which is
-essentially edge detection or embossing).  Then the Delaunay control
-points are chosen by selecting those pixels whose distance value is
-above a certain threshold: those are the pixels that have the largest
-change in color/brightness.
+essentially edge detection or embossing).  Then the Delaunay or
+Voronoi control points are chosen by selecting those pixels whose
+distance value is above a certain threshold: those are the pixels that
+have the largest change in color/brightness.
 
 https://en.wikipedia.org/wiki/Delaunay_triangulation
+https://en.wikipedia.org/wiki/Voronoi_diagram
+https://en.wikipedia.org/wiki/Tessellation
 
 Written by Jamie Zawinski; 2014.
   </_description>
diff --git a/hacks/config/vfeedback.xml b/hacks/config/vfeedback.xml
new file mode 100644 (file)
index 0000000..2accd19
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="vfeedback" _label="VFeedback">
+
+  <command arg="-root"/>
+
+  <video href="https://www.youtube.com/watch?v=I_MkW0CW4QM"/>
+
+  <hgroup>
+   <vgroup>
+    <number id="tvcolor" type="slider" arg="-tv-color %"
+            _label="Color Knob" _low-label="Low" _high-label="High"
+            low="0" high="400" default="70"/>
+    <number id="tvtint" type="slider" arg="-tv-tint %"
+            _label="Tint Knob" _low-label="Low" _high-label="High"
+            low="0" high="360" default="5"/>
+    <number id="noise" type="slider" arg="-noise %"
+            _label="Noise" _low-label="Low" _high-label="High"
+            low="0.0" high="0.2" default="0.02"/>
+   </vgroup>
+   <vgroup>
+    <number id="tvbrightness" type="slider" arg="-tv-brightness %"
+            _label="Brightness Knob" _low-label="Low" _high-label="High"
+            low="-75.0" high="100.0" default="1.5"/>
+    <number id="tvcontrast" type="slider" arg="-tv-contrast %"
+            _label="Contrast Knob" _low-label="Low" _high-label="High"
+            low="0" high="500" default="150"/>
+    <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+   </vgroup>
+  </hgroup>
+
+  <xscreensaver-updater />
+
+  <_description>
+Simulates video feedback: pointing a video camera at an NTSC television.
+
+Written by Jamie Zawinski; 2018.
+  </_description>
+</screensaver>
index 3de067f47c4f804a2022f7d08cc37e93787ebc8f..5064ca10da06475f52c4f5637d9e01fb4b7d92b7 100644 (file)
@@ -6,23 +6,29 @@
 
   <video href="https://www.youtube.com/watch?v=VmM1KkFsry0"/>
 
-  <xscreensaver-image />
-
-  <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+  <hgroup>
+   <vgroup>
+    <xscreensaver-image />
+   </vgroup>
+   <vgroup>
+    <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+    <boolean id="colorbars" _label="Colorbars only" arg-set="-colorbars-only"/>
+   </vgroup>
+  </hgroup>
 
   <hgroup>
    <vgroup>
     <number id="tvcolor" type="slider" arg="-tv-color %"
             _label="Color Knob" _low-label="Low" _high-label="High"
-            low="0" high="1000" default="70"/>
+            low="0" high="400" default="70"/>
     <number id="tvtint" type="slider" arg="-tv-tint %"
             _label="Tint Knob" _low-label="Low" _high-label="High"
-            low="0" high="100" default="5"/>
+            low="0" high="360" default="5"/>
    </vgroup>
    <vgroup>
     <number id="tvbrightness" type="slider" arg="-tv-brightness %"
             _label="Brightness Knob" _low-label="Low" _high-label="High"
-            low="0" high="200" default="150"/>
+            low="-75.0" high="100.0" default="3.0"/>
     <number id="tvcontrast" type="slider" arg="-tv-contrast %"
             _label="Contrast Knob" _low-label="Low" _high-label="High"
             low="0" high="1500" default="1000"/>
diff --git a/hacks/filmleader.c b/hacks/filmleader.c
new file mode 100644 (file)
index 0000000..ef021e1
--- /dev/null
@@ -0,0 +1,571 @@
+/* filmleader, Copyright (c) 2018 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ *
+ * Simulate an SMPTE Universal Film Leader playing on an analog television.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include "xft.h" /* before screenhack.h */
+
+#include "screenhack.h"
+#include "analogtv.h"
+
+#include <time.h>
+
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+struct state {
+  Display *dpy;
+  Window window;
+  XWindowAttributes xgwa;
+  int w, h;
+  unsigned long bg, text_color, ring_color, trace_color;
+  XftColor xft_text_color_1, xft_text_color_2;
+
+  XftFont *font, *font2, *font3;
+  XftDraw *xftdraw;
+  Pixmap pix;
+  GC gc;
+  double start, last_time;
+  double value;
+  int stop;
+  double noise;
+  analogtv *tv;
+  analogtv_input *inp;
+  analogtv_reception rec;
+  Bool button_down_p;
+};
+
+
+static void *
+filmleader_init (Display *dpy, Window window)
+{
+  struct state *st = (struct state *) calloc (1, sizeof(*st));
+  XGCValues gcv;
+
+  st->dpy = dpy;
+  st->window = window;
+  st->tv = analogtv_allocate (st->dpy, st->window);
+  analogtv_set_defaults (st->tv, "");
+  st->tv->need_clear = 1;
+  st->inp = analogtv_input_allocate();
+  analogtv_setup_sync (st->inp, 1, 0);
+  st->rec.input = st->inp;
+  st->rec.level = 2.0;
+  st->tv->use_color = 1;
+  st->rec.level = pow(frand(1.0), 3.0) * 2.0 + 0.05;
+  st->rec.ofs = random() % ANALOGTV_SIGNAL_LEN;
+  st->tv->powerup = 0;
+
+  st->rec.multipath = 0.0;
+  st->tv->color_control += frand(0.3);
+  st->noise = get_float_resource (st->dpy, "noise", "Float");
+  st->value = 18;  /* Leave time for powerup */
+  st->stop = 2 + (random() % 5);
+  XGetWindowAttributes (dpy, window, &st->xgwa);
+
+  /* Let's render it into a 16:9 pixmap, since that's what most screens are
+     these days.  That means the circle will be squashed on 4:3 screens. */
+  {
+    double r = 16/9.0;
+
+# ifdef HAVE_MOBILE
+    /* analogtv.c always fills whole screen on mobile, so use screen aspect. */
+    r = st->xgwa.width / (double) st->xgwa.height;
+    if (r < 1) r = 1/r;
+# endif
+
+    st->w = 712;
+    st->h = st->w / r;
+  }
+
+  if (st->xgwa.width < st->xgwa.height)
+    {
+      int swap = st->w;
+      st->w = st->h;
+      st->h = swap;
+    }
+
+  st->pix = XCreatePixmap (dpy, window,
+                           st->w > st->h ? st->w : st->h,
+                           st->w > st->h ? st->w : st->h,
+                           st->xgwa.depth);
+  st->gc = XCreateGC (dpy, st->pix, 0, &gcv);
+
+  st->xftdraw = XftDrawCreate (dpy, st->pix, st->xgwa.visual,
+                               st->xgwa.colormap);
+  st->font = load_xft_font_retry (dpy, screen_number (st->xgwa.screen),
+                                  get_string_resource (dpy, "numberFont",
+                                                       "Font"));
+  st->font2 = load_xft_font_retry (dpy, screen_number (st->xgwa.screen),
+                                   get_string_resource (dpy, "numberFont2",
+                                                        "Font"));
+  st->font3 = load_xft_font_retry (dpy, screen_number (st->xgwa.screen),
+                                   get_string_resource (dpy, "numberFont3",
+                                                        "Font"));
+
+  st->bg = get_pixel_resource (dpy, st->xgwa.colormap,
+                               "textBackground", "Background");
+  st->text_color = get_pixel_resource (dpy, st->xgwa.colormap,
+                                       "textColor", "Foreground");
+  st->ring_color = get_pixel_resource (dpy, st->xgwa.colormap,
+                                       "ringColor", "Foreground");
+  st->trace_color = get_pixel_resource (dpy, st->xgwa.colormap,
+                                        "traceColor", "Foreground");
+
+  XftColorAllocName (dpy, st->xgwa.visual, st->xgwa.colormap,
+                     get_string_resource (dpy, "textColor", "Foreground"),
+                     &st->xft_text_color_1);
+  XftColorAllocName (dpy, st->xgwa.visual, st->xgwa.colormap,
+                     get_string_resource (dpy, "textBackground", "Background"),
+                     &st->xft_text_color_2);
+
+  return st;
+}
+
+
+static double
+double_time (void)
+{
+  struct timeval now;
+# ifdef GETTIMEOFDAY_TWO_ARGS
+  struct timezone tzp;
+  gettimeofday(&now, &tzp);
+# else
+  gettimeofday(&now);
+# endif
+
+  return (now.tv_sec + ((double) now.tv_usec * 0.000001));
+}
+
+
+static unsigned long
+filmleader_draw (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
+  const analogtv_reception *rec = &st->rec;
+  double then = double_time(), now, timedelta;
+  XImage *img;
+  int i, x, y, w2, h2;
+  XGlyphInfo extents;
+  int lbearing, rbearing, ascent, descent;
+  char s[20];
+  double r = 1 - (st->value - (int) st->value);
+  int ivalue = st->value;
+  XftFont *xftfont;
+  XftColor *xftcolor;
+
+  /* You may ask, why use Xft for this instead of the much simpler XDrawString?
+     Well, for some reason, XLoadQueryFont is giving me horribly-scaled bitmap
+     fonts, but Xft works properly. So perhaps in This Modern World, if one
+     expects large fonts to work, one must use Xft instead of Xlib?
+
+     Everything is terrible.
+   */
+
+  const struct { double t; int k, f; const char * const s[4]; } blurbs[] = {
+    {  9.1, 3, 1, { "PICTURE", "  START", 0, 0 }},
+    { 10.0, 2, 1, { "    16", "SOUND", "START", 0 }},
+    { 10.5, 2, 1, { "    32", "SOUND", "START", 0 }},
+    { 11.6, 2, 0, { "PICTURE", "COMPANY", "SERIES", 0 }},
+    { 11.7, 2, 0, { "XSCRNSAVER", 0, 0, 0 }},
+    { 11.9, 2, 0, { "REEL No.", "PROD No.", "PLAY DATE", 0 }},
+    { 12.2, 0, 0, { "    SMPTE     ", "UNIVERSAL", "   LEADER", 0 }},
+    { 12.3, 0, 1, { "X           ", "X", "X", "X" }},
+    { 12.4, 0, 0, { "    SMPTE     ", "UNIVERSAL", "   LEADER", 0 }},
+    { 12.5, 3, 1, { "PICTURE", 0, 0, 0 }},
+    { 12.7, 3, 1, { "HEAD", 0, 0, 0 }},
+    { 12.8, 2, 1, { "OOOO", 0, "ASPECT", "TYPE OF" }},
+    { 12.9, 2, 0, { "SOUND", 0, "RATIO", 0 }},
+    { 13.2, 1, 1, { "                  ", "PICTURE", 0, 0 }},
+    { 13.3, 1, 0, { "REEL No.      ", "COLOR", 0, 0 }},
+    { 13.4, 1, 0, { "LENGTH        ", 0, 0, "ROLL" }},
+    { 13.5, 1, 0, { "SUBJECT", 0, 0, 0 }},
+    { 13.9, 1, 1, { "     \342\206\221", "SPLICE", " HERE", 0 }},
+  };
+
+  for (i = 0; i < countof(blurbs); i++)
+    {
+      if (st->value >= blurbs[i].t && st->value <= blurbs[i].t + 1/15.0)
+        {
+          int line_height;
+          int j;
+          xftfont = (blurbs[i].f == 1 ? st->font2 :
+                     blurbs[i].f == 2 ? st->font : st->font3);
+
+          XSetForeground (dpy, st->gc, 
+                          blurbs[i].k == 3 ? st->bg : st->text_color);
+          XFillRectangle (dpy, st->pix, st->gc, 0, 0, st->w, st->h);
+          XSetForeground (dpy, st->gc,
+                          blurbs[i].k == 3 ? st->text_color : st->bg);
+          xftcolor = (blurbs[i].k == 3 ? 
+                      &st->xft_text_color_1 : &st->xft_text_color_2);
+
+          /* The height of a string of spaces is 0... */
+          XftTextExtentsUtf8 (dpy, xftfont, (FcChar8 *) "My", 2, &extents);
+          line_height = extents.height;
+
+          XftTextExtentsUtf8 (dpy, xftfont, (FcChar8 *)
+                              blurbs[i].s[0], strlen(blurbs[i].s[0]),
+                              &extents);
+          lbearing = -extents.x;
+          rbearing = extents.width - extents.x;
+          ascent   = extents.y;
+          descent  = extents.height - extents.y;
+
+          x = (st->w - rbearing) / 2;
+          y = st->h * 0.1 + ascent;
+
+          for (j = 0; j < countof(blurbs[i].s); j++)
+            {
+              if (blurbs[i].s[j])
+                XftDrawStringUtf8 (st->xftdraw, xftcolor, xftfont, x, y,
+                                   (FcChar8 *) blurbs[i].s[j],
+                                   strlen(blurbs[i].s[j]));
+
+              y += line_height * 1.5;
+
+              if (blurbs[i].s[j])
+                {
+                  XftTextExtentsUtf8 (dpy, xftfont, (FcChar8 *)
+                                      blurbs[i].s[0], strlen(blurbs[i].s[j]),
+                                      &extents);
+                  lbearing = -extents.x;
+                  rbearing = extents.width - extents.x;
+                  ascent   = extents.y;
+                  descent  = extents.height - extents.y;
+                }
+            }
+
+          if (blurbs[i].k == 2)  /* Rotate clockwise and flip */
+            {
+              int wh = st->w < st->h ? st->w : st->h;
+              XImage *img1 = XGetImage (dpy, st->pix,
+                                        (st->w - wh) / 2,
+                                        (st->h - wh) / 2,
+                                        wh, wh, ~0L, ZPixmap);
+              XImage *img2 = XCreateImage (dpy, st->xgwa.visual,
+                                           st->xgwa.depth, ZPixmap, 0, 0,
+                                           wh, wh, 32, 0);
+              img2->data = malloc (img2->bytes_per_line * img2->height);
+              for (y = 0; y < wh; y++)
+                for (x = 0; x < wh; x++)
+                  XPutPixel (img2, y, x, XGetPixel (img1, x, y));
+              XSetForeground (dpy, st->gc, 
+                              blurbs[i].k == 3 ? st->bg : st->text_color);
+              XFillRectangle (dpy, st->pix, st->gc, 0, 0, st->w, st->h);
+              XPutImage (dpy, st->pix, st->gc, img2,
+                         0, 0,
+                         (st->w - wh) / 2,
+                         (st->h - wh) / 2,
+                         wh, wh);
+              XDestroyImage (img1);
+              XDestroyImage (img2);
+            }
+          else if (blurbs[i].k == 1)  /* Flip vertically */
+            {
+              XImage *img1 = XGetImage (dpy, st->pix, 0, 0,
+                                        st->w, st->h, ~0L, ZPixmap);
+              XImage *img2 = XCreateImage (dpy, st->xgwa.visual,
+                                           st->xgwa.depth, ZPixmap, 0, 0,
+                                           st->w, st->h, 32, 0);
+              img2->data = malloc (img2->bytes_per_line * img2->height);
+              for (y = 0; y < img2->height; y++)
+                for (x = 0; x < img2->width; x++)
+                  XPutPixel (img2, x, img2->height-y-1,
+                             XGetPixel (img1, x, y));
+              XPutImage (dpy, st->pix, st->gc, img2, 0, 0, 0, 0, st->w, st->h);
+              XDestroyImage (img1);
+              XDestroyImage (img2);
+            }
+
+          goto DONE;
+        }
+    }
+
+  if (st->value < 2.0 || st->value >= 9.0)     /* Black screen */
+    {
+      XSetForeground (dpy, st->gc, st->text_color);
+      XFillRectangle (dpy, st->pix, st->gc, 0, 0, st->w, st->h);
+      goto DONE;
+    }
+
+  XSetForeground (dpy, st->gc, st->bg);
+  XFillRectangle (dpy, st->pix, st->gc, 0, 0, st->w, st->h);
+
+  if (r > 1/30.0)                              /* Sweep line and background */
+    {
+      x = st->w/2 + st->w * cos (M_PI * 2 * r - M_PI/2);
+      y = st->h/2 + st->h * sin (M_PI * 2 * r - M_PI/2);
+
+      XSetForeground (dpy, st->gc, st->trace_color);
+      XFillArc (dpy, st->pix, st->gc,
+                -st->w, -st->h, st->w*3, st->h*3,
+                90*64,
+                90*64 - ((r + 0.25) * 360*64));
+
+      XSetForeground (dpy, st->gc, st->text_color);
+      XSetLineAttributes (dpy, st->gc, 1, LineSolid, CapRound, JoinRound);
+      XDrawLine (dpy, st->pix, st->gc, st->w/2, st->h/2, x, y);
+  
+      XSetForeground (dpy, st->gc, st->text_color);
+      XSetLineAttributes (dpy, st->gc, 2, LineSolid, CapRound, JoinRound);
+      XDrawLine (dpy, st->pix, st->gc, st->w/2, 0, st->w/2, st->h);
+      XDrawLine (dpy, st->pix, st->gc, 0, st->h/2, st->w, st->h/2);
+    }
+
+  /* Big number */
+
+  s[0] = (char) (ivalue + '0');
+  xftfont = st->font;
+  xftcolor = &st->xft_text_color_1;
+  XftTextExtentsUtf8 (dpy, xftfont, (FcChar8 *) s, 1, &extents);
+  lbearing = -extents.x;
+  rbearing = extents.width - extents.x;
+  ascent   = extents.y;
+  descent  = extents.height - extents.y;
+
+  x = (st->w - (rbearing + lbearing)) / 2;
+  y = (st->h + (ascent - descent)) / 2;
+  XftDrawStringUtf8 (st->xftdraw, xftcolor, xftfont, x, y, (FcChar8 *) s, 1);
+
+  /* Annotations on 7 and 4 */
+
+  if ((st->value >= 7.75 && st->value <= 7.85) ||
+      (st->value >= 4.00 && st->value <= 4.25))
+    {
+      XSetForeground (dpy, st->gc, st->ring_color);
+      xftcolor = &st->xft_text_color_2;
+      xftfont = st->font2;
+
+      s[0] = (ivalue == 4 ? 'C' : 'M');
+      s[1] = 0;
+
+      XftTextExtentsUtf8 (dpy, xftfont, (FcChar8 *) s, strlen(s), &extents);
+      lbearing = -extents.x;
+      rbearing = extents.width - extents.x;
+      ascent   = extents.y;
+      descent  = extents.height - extents.y;
+
+      x = st->w * 0.1;
+      y = st->h * 0.1 + ascent;
+      XftDrawStringUtf8 (st->xftdraw, xftcolor, xftfont, x, y,
+                         (FcChar8 *) s, strlen(s));
+      x = st->w * 0.9 - (rbearing + lbearing);
+      XftDrawStringUtf8 (st->xftdraw, xftcolor, xftfont, x, y,
+                         (FcChar8 *) s, strlen(s));
+
+      s[0] = (ivalue == 4 ? 'F' : '3');
+      s[1] = (ivalue == 4 ? 0   : '5');
+      s[2] = 0;
+
+      XftTextExtentsUtf8 (dpy, xftfont, (FcChar8 *) s, strlen(s), &extents);
+      lbearing = -extents.x;
+      rbearing = extents.width - extents.x;
+      ascent   = extents.y;
+      descent  = extents.height - extents.y;
+
+      x = st->w * 0.1;
+      y = st->h * 0.95;
+      XftDrawStringUtf8 (st->xftdraw, xftcolor, xftfont, x, y, 
+                         (FcChar8 *) s, strlen(s));
+      x = st->w * 0.9 - (rbearing + lbearing);
+      XftDrawStringUtf8 (st->xftdraw, xftcolor, xftfont, x, y,
+                         (FcChar8 *) s, strlen(s));
+    }
+
+  if (r > 1/30.0)                              /* Two rings around number */
+    {
+      double r2 = st->w / (double) st->h;
+      double ss = 1;
+
+      if (st->xgwa.width < st->xgwa.height)
+        ss = 0.5;
+
+      XSetForeground (dpy, st->gc, st->ring_color);
+      XSetLineAttributes (dpy, st->gc, st->w * 0.025,
+                          LineSolid, CapRound, JoinRound);
+
+      w2 = st->w * 0.8 * ss / r2;
+      h2 = st->h * 0.8 * ss;
+      x = (st->w - w2) / 2;
+      y = (st->h - h2) / 2;
+      XDrawArc (dpy, st->pix, st->gc, x, y, w2, h2, 0, 360*64);
+
+      w2 = w2 * 0.8;
+      h2 = h2 * 0.8;
+      x = (st->w - w2) / 2;
+      y = (st->h - h2) / 2;
+      XDrawArc (dpy, st->pix, st->gc, x, y, w2, h2, 0, 360*64);
+    }
+
+ DONE:
+
+  img = XGetImage (dpy, st->pix, 0, 0, st->w, st->h, ~0L, ZPixmap);
+
+  analogtv_load_ximage (st->tv, st->rec.input, img, 0, 0, 0, 0, 0);
+  analogtv_reception_update (&st->rec);
+  analogtv_draw (st->tv, st->noise, &rec, 1);
+
+  XDestroyImage (img);
+
+  now = double_time();
+  timedelta = (1 / 29.97) - (now - then);
+
+  if (! st->button_down_p)
+    {
+      if (st->last_time == 0)
+        st->start = then;
+      else
+        st->value -= then - st->last_time;
+
+      if (st->value <= 0 ||
+          (r > 0.9 && st->value <= st->stop))
+        {
+          st->value = (random() % 20) ? 8.9 : 15;
+          st->stop = ((random() % 50) ? 2 : 1) + (random() % 5);
+
+          if (st->value > 9)   /* Spin the knobs again */
+            {
+              st->rec.level = pow(frand(1.0), 3.0) * 2.0 + 0.05;
+              st->rec.ofs = random() % ANALOGTV_SIGNAL_LEN;
+              st->tv->color_control += frand(0.3) - 0.15;
+            }
+        }
+    }
+
+  st->tv->powerup = then - st->start;
+  st->last_time = then;
+
+  return timedelta > 0 ? timedelta * 1000000 : 0;
+}
+
+
+static void
+filmleader_reshape (Display *dpy, Window window, void *closure, 
+                    unsigned int w, unsigned int h)
+{
+  struct state *st = (struct state *) closure;
+  analogtv_reconfigure (st->tv);
+  XGetWindowAttributes (dpy, window, &st->xgwa);
+
+  if ((st->w > st->h) != (st->xgwa.width > st->xgwa.height))
+    {
+      int swap = st->w;
+      st->w = st->h;
+      st->h = swap;
+    }
+}
+
+
+static Bool
+filmleader_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+  struct state *st = (struct state *) closure;
+  if (event->xany.type == ButtonPress)
+    {
+      st->button_down_p = True;
+      return True;
+    }
+  else if (event->xany.type == ButtonRelease)
+    {
+      st->button_down_p = False;
+      return True;
+    }
+  else if (screenhack_event_helper (dpy, window, event))
+    {
+      st->value = 15;
+      st->rec.level = pow(frand(1.0), 3.0) * 2.0 + 0.05;
+      st->rec.ofs = random() % ANALOGTV_SIGNAL_LEN;
+      st->tv->color_control += frand(0.3) - 0.15;
+      return True;
+    }
+  else if (event->xany.type == KeyPress)
+    {
+      KeySym keysym;
+      char c = 0;
+      XLookupString (&event->xkey, &c, 1, &keysym, 0);
+      if (c >= '2' && c <= '8')
+        {
+          st->value = (c - '0') + (st->value - (int) st->value);
+          return True;
+        }
+    }
+
+  return False;
+}
+
+
+static void
+filmleader_free (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
+  analogtv_release (st->tv);
+  XftDrawDestroy (st->xftdraw);
+  XftColorFree(dpy, st->xgwa.visual, st->xgwa.colormap, &st->xft_text_color_1);
+  XftColorFree(dpy, st->xgwa.visual, st->xgwa.colormap, &st->xft_text_color_2);
+  XFreePixmap (dpy, st->pix);
+  XFreeGC (dpy, st->gc);
+  free (st);
+}
+
+
+static const char *filmleader_defaults [] = {
+
+  ".background:  #000000",
+
+# ifdef HAVE_MOBILE
+
+  "*textBackground: #444488",  /* Need much higher contrast for some reason */
+  "*textColor:      #000033",
+  "*ringColor:      #DDDDFF",
+  "*traceColor:     #222244",
+
+# else /* X11 or Cocoa */
+
+  "*textBackground: #9999DD",
+  "*textColor:      #000015",
+  "*ringColor:      #DDDDFF",
+  "*traceColor:     #555577",
+
+# endif
+
+# ifdef USE_IPHONE
+
+  "*numberFont:  Helvetica Bold 120",
+  "*numberFont2: Helvetica 36",
+  "*numberFont3: Helvetica 28",
+
+# else /* X11, Cocoa or Android */
+
+  "*numberFont:  -*-helvetica-bold-r-*-*-*-1700-*-*-*-*-*-*",
+  "*numberFont2: -*-helvetica-medium-r-*-*-*-500-*-*-*-*-*-*",
+  "*numberFont3: -*-helvetica-medium-r-*-*-*-360-*-*-*-*-*-*",
+
+# endif
+
+
+  "*noise:       0.04",
+  ANALOGTV_DEFAULTS
+  "*geometry: 1280x720",
+  0
+};
+
+static XrmOptionDescRec filmleader_options [] = {
+  { "-noise",           ".noise",     XrmoptionSepArg, 0 },
+  ANALOGTV_OPTIONS
+  { 0, 0, 0, 0 }
+};
+
+XSCREENSAVER_MODULE ("FilmLeader", filmleader)
diff --git a/hacks/filmleader.man b/hacks/filmleader.man
new file mode 100644 (file)
index 0000000..4a98270
--- /dev/null
@@ -0,0 +1,69 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+filmleader - screen saver.
+.SH SYNOPSIS
+.B filmleader
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-tv-color \fInumber\fP]
+[\-tv-tint \fInumber\fP]
+[\-noise \fInumber\fP]
+[\-tv-brightness \fInumber\fP]
+[\-tv-contrast \fInumber\fP]
+[\-fps]
+.SH DESCRIPTION
+Displays a looping countdown based on the SMPTE Universal Film leader on a
+simulation of an old analog television.
+.SH OPTIONS
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-tv-color \fInumber\fP
+Color Knob.  0 - 1000. Default: 70.
+.TP 8
+.B \-tv-tint \fInumber\fP
+Tint Knob.  0 - 100.  Default: 5.
+.TP 8
+.B \-noise \fInumber\fP
+Noise. 0.0 - 0.2.  Default: 0.04.
+.TP 8
+.B \-tv-brightness \fInumber\fP
+Brightness Knob.  0 - 200.  Default: 150.
+.TP 8
+.B \-tv-contrast \fInumber\fP
+Contrast Knob. 0 - 1500.  Default: 1000.
+.TP 8
+.B \-fps | \-no-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2018 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski.
diff --git a/hacks/glitchpeg.c b/hacks/glitchpeg.c
new file mode 100644 (file)
index 0000000..4f3b052
--- /dev/null
@@ -0,0 +1,440 @@
+/* glitchpeg, Copyright (c) 2018 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ *
+ * Insert errors into an image file, then display the corrupted result.
+ *
+ * This only works on X11 and MacOS because iOS and Android don't have
+ * access to the source files of images, only the decoded image data.
+ */
+
+#include "screenhack.h"
+#include "ximage-loader.h"
+
+#ifndef HAVE_JWXYZ
+# include <X11/Intrinsic.h>   /* for XtInputId, etc */
+#endif
+
+#include <sys/stat.h>
+
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+struct state {
+  Display *dpy;
+  Window window;
+  GC gc;
+  XWindowAttributes xgwa;
+  int delay;
+  int count;
+  int duration;
+  time_t start_time;
+  unsigned char *image_data; unsigned long image_size;
+  XtInputId pipe_id;
+  FILE *pipe;
+  Bool button_down_p;
+};
+
+
+static Bool
+bigendian (void)
+{
+  union { int i; char c[sizeof(int)]; } u;
+  u.i = 1;
+  return !u.c[0];
+}
+
+
+/* Given a bitmask, returns the position and width of the field.
+   Duplicated from ximage-loader.c.
+ */
+static void
+decode_mask (unsigned long mask, unsigned long *pos_ret,
+             unsigned long *size_ret)
+{
+  int i;
+  for (i = 0; i < 32; i++)
+    if (mask & (1L << i))
+      {
+        int j = 0;
+        *pos_ret = i;
+        for (; i < 32; i++, j++)
+          if (! (mask & (1L << i)))
+            break;
+        *size_ret = j;
+        return;
+      }
+}
+
+
+/* Renders a scaled, cropped version of the RGBA XImage onto the window.
+ */
+static void
+draw_image (Display *dpy, Window window, Visual *v, GC gc, 
+            int w, int h, int depth, XImage *in)
+{
+  XImage *out;
+  int x, y, w2, h2, xoff, yoff;
+  double xs, ys, s;
+
+  unsigned long crpos=0, cgpos=0, cbpos=0, capos=0; /* bitfield positions */
+  unsigned long srpos=0, sgpos=0, sbpos=0;
+  unsigned long srmsk=0, sgmsk=0, sbmsk=0;
+  unsigned long srsiz=0, sgsiz=0, sbsiz=0;
+
+# ifdef HAVE_JWXYZ
+  // BlackPixel has alpha: 0xFF000000.
+  unsigned long black = BlackPixelOfScreen (DefaultScreenOfDisplay (dpy));
+#else
+  unsigned long black = 0;
+# endif
+
+  xs = in->width  / (double) w;
+  ys = in->height / (double) h;
+  s = (xs > ys ? ys : xs);
+  w2 = in->width  / s;
+  h2 = in->height / s;
+  xoff = (w - w2) / 2;
+  yoff = (h - h2) / 2;
+
+  /* Create a new image in the depth and bit-order of the server. */
+  out = XCreateImage (dpy, v, depth, ZPixmap, 0, 0, w, h, 8, 0);
+  out->bitmap_bit_order = in->bitmap_bit_order;
+  out->byte_order = in->byte_order;
+
+  out->bitmap_bit_order = BitmapBitOrder (dpy);
+  out->byte_order = ImageByteOrder (dpy);
+
+  out->data = (char *) malloc (out->height * out->bytes_per_line);
+  if (!out->data) abort();
+
+  /* Find the server's color masks.
+     We could cache this and just do it once, but it's a small number
+     of instructions compared to the per-pixel operations happening next.
+   */
+  srmsk = out->red_mask;
+  sgmsk = out->green_mask;
+  sbmsk = out->blue_mask;
+
+  if (!(srmsk && sgmsk && sbmsk)) abort();  /* No server color masks? */
+
+  decode_mask (srmsk, &srpos, &srsiz);
+  decode_mask (sgmsk, &sgpos, &sgsiz);
+  decode_mask (sbmsk, &sbpos, &sbsiz);
+
+  /* 'in' is RGBA in client endianness.  Convert to what the server wants. */
+  if (bigendian())
+    crpos = 24, cgpos = 16, cbpos =  8, capos =  0;
+  else
+    crpos =  0, cgpos =  8, cbpos = 16, capos = 24;
+
+  /* Iterate the destination rectangle and pull in the corresponding
+     scaled and cropped source pixel, or black. Nearest-neighbor is fine.
+   */
+  for (y = 0; y < out->height; y++)
+    {
+      int iy = (out->height - y - yoff - 1) * s;
+      for (x = 0; x < out->width; x++)
+        {
+          int ix = (x - xoff) * s;
+          unsigned long p = (ix >= 0 && ix < in->width &&
+                             iy >= 0 && iy < in->height
+                             ? XGetPixel (in, ix, iy)
+                             : black);
+       /* unsigned char a = (p >> capos) & 0xFF; */
+          unsigned char b = (p >> cbpos) & 0xFF;
+          unsigned char g = (p >> cgpos) & 0xFF;
+          unsigned char r = (p >> crpos) & 0xFF;
+          XPutPixel (out, x, y, ((r << srpos) |
+                                 (g << sgpos) |
+                                 (b << sbpos) |
+                                 black));
+        }
+    }
+
+  XPutImage (dpy, window, gc, out, 0, 0, 0, 0, out->width, out->height);
+  XDestroyImage (out);
+}
+
+
+# define BACKSLASH(c) \
+  (! ((c >= 'a' && c <= 'z') || \
+      (c >= 'A' && c <= 'Z') || \
+      (c >= '0' && c <= '9') || \
+      c == '.' || c == '_' || c == '-' || c == '+' || c == '/'))
+
+/* Gets the name of an image file to load by running xscreensaver-getimage-file
+   at the end of a pipe.  This can be very slow!
+   Duplicated from utils/grabclient.c
+ */
+static FILE *
+open_image_name_pipe (void)
+{
+  char *s;
+
+  /* /bin/sh on OS X 10.10 wipes out the PATH. */
+  const char *path = getenv("PATH");
+  char *cmd = s = malloc (strlen(path) * 2 + 100);
+  strcpy (s, "/bin/sh -c 'export PATH=");
+  s += strlen (s);
+  while (*path) {
+    char c = *path++;
+    if (BACKSLASH(c)) *s++ = '\\';
+    *s++ = c;
+  }
+  strcpy (s, "; ");
+  s += strlen (s);
+
+  strcpy (s, "xscreensaver-getimage-file --name --absolute");
+  s += strlen (s);
+
+  strcpy (s, "'");
+  s += strlen (s);
+
+  *s = 0;
+
+  FILE *pipe = popen (cmd, "r");
+  free (cmd);
+  return pipe;
+}
+
+
+/* Duplicated from utils/grabclient.c */
+static void
+xscreensaver_getimage_file_cb (XtPointer closure, int *source, XtInputId *id)
+{
+  /* This is not called from a signal handler, so doing stuff here is fine.
+   */
+  struct state *st = (struct state *) closure;
+  char buf[10240];
+  char *file = buf;
+  FILE *fp;
+  struct stat stat;
+  int n;
+  unsigned char *s;
+  int L;
+
+  *buf = 0;
+  fgets (buf, sizeof(buf)-1, st->pipe);
+  pclose (st->pipe);
+  st->pipe = 0;
+  XtRemoveInput (st->pipe_id);
+  st->pipe_id = 0;
+
+  /* strip trailing newline */
+  L = strlen(buf);
+  while (L > 0 && (buf[L-1] == '\r' || buf[L-1] == '\n'))
+    buf[--L] = 0;
+
+  fp = fopen (file, "r");
+  if (! fp)
+    {
+      fprintf (stderr, "%s: unable to read %s\n", progname, file);
+      return;
+    }
+
+  if (fstat (fileno (fp), &stat))
+    {
+      fprintf (stderr, "%s: %s: stat failed\n", progname, file);
+      return;
+    }
+
+  if (st->image_data) free (st->image_data);
+  st->image_size = stat.st_size;
+  st->image_data = malloc (st->image_size);
+  
+  s = st->image_data;
+  do {
+    n = fread (s, 1, st->image_data + st->image_size - s, fp);
+    if (n > 0) s += n;
+  } while (n > 0);
+
+  fclose (fp);
+
+  /* fprintf (stderr, "loaded %s (%lu)\n", file, st->image_size); */
+
+  st->start_time = time((time_t *) 0);
+}
+
+
+static void *
+glitchpeg_init (Display *dpy, Window window)
+{
+  struct state *st = (struct state *) calloc (1, sizeof(*st));
+  XGCValues gcv;
+
+  st->dpy = dpy;
+  st->window = window;
+  st->gc = XCreateGC (dpy, window, 0, &gcv);
+
+  XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
+
+  st->delay = get_integer_resource (st->dpy, "delay", "Integer");
+  if (st->delay < 1) st->delay = 1;
+
+  st->duration = get_integer_resource (st->dpy, "duration", "Integer");
+  if (st->duration < 0) st->duration = 0;
+
+  st->count = get_integer_resource (st->dpy, "count", "Integer");
+  if (st->count < 1) st->count = 1;
+
+  XClearWindow (st->dpy, st->window);
+
+  return st;
+}
+
+
+static unsigned long
+glitchpeg_draw (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
+
+  if ((!st->image_data ||
+       time((time_t *) 0) >= st->start_time + st->duration) &&
+      !st->pipe)
+    {
+      /* Time to reload */
+      st->pipe = open_image_name_pipe();
+      st->pipe_id =
+        XtAppAddInput (XtDisplayToApplicationContext (dpy), 
+                       fileno (st->pipe),
+                       (XtPointer) (XtInputReadMask | XtInputExceptMask),
+                       xscreensaver_getimage_file_cb, (XtPointer) st);
+    }
+
+  if (st->image_data && !st->button_down_p)
+    {
+      int n;
+      XImage *image;
+      unsigned char *glitched = malloc (st->image_size);
+      int nn = random() % st->count;
+      if (nn <= 0) nn = 1;
+
+      memcpy (glitched, st->image_data, st->image_size);
+
+      for (n = 0; n < nn; n++)
+        {
+          int start = 255;
+          int end = st->image_size - 255;
+          int size = end - start;
+          Bool byte_p = True;  /* random() % 100; */
+          if (size <= 100) break;
+          if (byte_p)
+            {
+              int i = start + (random() % size);
+              if (!(random() % 10))
+                /* Take one random byte and randomize it. */
+                glitched[i] = random() % 0xFF; 
+              else
+                /* Take one random byte and add 5% to it. */
+                glitched[i] += 
+                  (1 + (random() % 0x0C)) * ((random() & 1) ? 1 : -1);
+            }
+          else
+            {
+              /* Take two randomly-sized chunks of the file and swap them.
+                 This tends to just destroy the image.  Doesn't look good. */
+              int s2 = 2 + size * 0.05;
+              char *swap = malloc (s2);
+              int start1 = start + (random() % (size - s2));
+              int start2 = start + (random() % (size - s2));
+              memcpy (glitched + start1, swap, s2);
+              memmove (glitched + start2, glitched + start1, s2);
+              memcpy (swap, glitched + start2, s2);
+              free (swap);
+            }
+        }
+
+      image = image_data_to_ximage (dpy, st->xgwa.visual,
+                                    glitched, st->image_size);
+      free (glitched);
+
+      if (image)  /* Might be null if decode fails */
+        {
+          draw_image (dpy, window, st->xgwa.visual, st->gc,
+                      st->xgwa.width, st->xgwa.height, st->xgwa.depth,
+                      image);
+          XDestroyImage (image);
+        }
+    }
+
+  return st->delay;
+}
+
+
+static void
+glitchpeg_reshape (Display *dpy, Window window, void *closure, 
+                 unsigned int w, unsigned int h)
+{
+  struct state *st = (struct state *) closure;
+  XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
+}
+
+
+static Bool
+glitchpeg_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+  struct state *st = (struct state *) closure;
+  if (event->xany.type == ButtonPress)
+    {
+      st->button_down_p = True;
+      return True;
+    }
+  else if (event->xany.type == ButtonRelease)
+    {
+      st->button_down_p = False;
+      return True;
+    }
+  else if (screenhack_event_helper (dpy, window, event))
+    {
+      st->start_time = 0;  /* reload */
+      return True;
+    }
+
+  return False;
+}
+
+
+static void
+glitchpeg_free (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
+  XFreeGC (dpy, st->gc);
+  if (st->pipe_id) XtRemoveInput (st->pipe_id);
+  if (st->pipe) fclose (st->pipe);
+  if (st->image_data) free (st->image_data);
+  free (st);
+}
+
+
+static const char *glitchpeg_defaults [] = {
+  ".background:                        black",
+  ".foreground:                        white",
+  ".lowrez:                     True",
+  "*fpsSolid:                  true",
+  "*delay:                     30000",
+  "*duration:                  120",
+  "*count:                     100",
+  "*grabDesktopImages:         False",   /* HAVE_JWXYZ */
+  "*chooseRandomImages:                True",    /* HAVE_JWXYZ */
+#ifdef HAVE_MOBILE
+  "*ignoreRotation:             True",
+  "*rotateImages:               True",
+#endif
+  0
+};
+
+static XrmOptionDescRec glitchpeg_options [] = {
+  { "-delay",          ".delay",               XrmoptionSepArg, 0 },
+  { "-duration",       ".duration",            XrmoptionSepArg, 0 },
+  { "-count",          ".count",               XrmoptionSepArg, 0 },
+  { 0, 0, 0, 0 }
+};
+
+XSCREENSAVER_MODULE ("GlitchPEG", glitchpeg)
diff --git a/hacks/glitchpeg.man b/hacks/glitchpeg.man
new file mode 100644 (file)
index 0000000..ca80165
--- /dev/null
@@ -0,0 +1,79 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+glitchpeg - glitched image screen saver.
+.SH SYNOPSIS
+.B glitchpeg
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fInumber\fP]
+[\-duration \fInumber\fP]
+[\-count \fInumber\fP]
+.SH DESCRIPTION
+Loads an image, corrupts it, and then displays the corrupted version,
+several times a second. After a while, finds a new image to corrupt.
+
+It glitches the image by altering random bytes in the compressed image
+file before de-compressing it. This creates interesting visual effects
+on JPEG files, but doesn't work well on PNG files, since PNG contains
+checksums that detect simple corruption.
+.SH OPTIONS
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 30000 (0.03 seconds).
+.TP 8
+.B \-duration \fInumber\fP
+How many seconds before loading a new image.  Default: 120.
+.TP 8
+.B \-count \fInumber\fP
+Number of glitches to introduce per iteration. Default: 100.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SECURITY
+Because this program is feeding intentionally-invalid data into your
+operating system's image-decoding libraries, it is possible that it
+may crash as a result of that corrupted data.  
+
+That should not be possible -- but it might be.
+
+Please note that if this happens, that indicates a serious security
+bug in your system's image libraries!  It likely means that your
+libraries are susceptible to buffer overflow attacks or similar, which
+can lead to remote code execution.  You should report that bug to the
+maintainers of those image libraries.
+
+In the context of xscreensaver, when configured to load only local
+image files, this should not be a direct security concern: this screen
+saver crashing will not affect the xscreensaver daemon and will not
+unlock your screen.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2018 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski.
index bbd07f38651b41c29f86d6e454f2ae436bab6ba8..e3fa617cf771a49bdd13156194eaecc828551544 100644 (file)
@@ -68,7 +68,7 @@ JWXYZ_SRC     = $(HACK_SRC)/../jwxyz
 UTILS_BIN      = $(HACK_BIN)/../utils
 JWXYZ_BIN      = $(HACK_BIN)/../jwxyz
 
-INCLUDES_1     = -I. -I$(srcdir) -I$(UTILS_SRC) -I$(JWXYZ_SRC) -I$(HACK_SRC) -I../..
+INCLUDES_1     = -I. -I$(srcdir) -I$(UTILS_SRC) -I$(JWXYZ_SRC) -I$(HACK_SRC) -I$(HACK_BIN) -I../..
 INCLUDES       = $(INCLUDES_1) @INCLUDES@
 
 UTILDIR_OBJS   = $(UTILS_BIN)/colors.o $(UTILS_BIN)/grabclient.o \
@@ -128,10 +128,11 @@ SRCS              = xscreensaver-gl-helper.c normals.c erase-gl.c fps-gl.c \
                  quasicrystal.c unknownpleasures.c geodesic.c geodesicgears.c \
                  projectiveplane.c winduprobot.c robot.c robot-wireframe.c \
                  cityflow.c romanboy.c splitflap.c splitflap_obj.c \
-                 dymaxionmap.c unicrud.c energystream.c raverhoop.c \
-                 hydrostat.c discoball.c cubetwist.c cubestack.c splodesic.c \
-                 hexstrut.c vigilance.c seccam.c esper.c razzledazzle.c \
-                 ships.c peepers.c crumbler.c quickhull.c maze3d.c
+                 dymaxionmap.c dymaxionmap-coords.c unicrud.c energystream.c \
+                 raverhoop.c hydrostat.c discoball.c cubetwist.c cubestack.c \
+                 splodesic.c hexstrut.c vigilance.c seccam.c esper.c \
+                 razzledazzle.c ships.c peepers.c crumbler.c quickhull.c \
+                 maze3d.c
 
 OBJS           = xscreensaver-gl-helper.o normals.o erase-gl.o fps-gl.o \
                  atlantis.o b_draw.o b_lockglue.o b_sphere.o bubble3d.o \
@@ -174,10 +175,11 @@ OBJS              = xscreensaver-gl-helper.o normals.o erase-gl.o fps-gl.o \
                  quasicrystal.o unknownpleasures.o geodesic.o geodesicgears.o \
                  projectiveplane.o winduprobot.o robot.o robot-wireframe.o \
                  cityflow.o romanboy.o splitflap.o splitflap_obj.o \
-                 dymaxionmap.o unicrud.o energystream.o raverhoop.o \
-                 hydrostat.o discoball.o cubetwist.o cubestack.o splodesic.o \
-                 hexstrut.o vigilance.o seccam.o esper.o razzledazzle.o \
-                 ships.o peepers.o crumbler.o quickhull.o maze3d.o
+                 dymaxionmap.o dymaxionmap-coords.o unicrud.o energystream.o \
+                 raverhoop.o hydrostat.o discoball.o cubetwist.o cubestack.o \
+                 splodesic.o hexstrut.o vigilance.o seccam.o esper.o \
+                 razzledazzle.o ships.o peepers.o crumbler.o quickhull.o \
+                 maze3d.o
 
 GL_EXES                = cage gears moebius pipes sproingies stairs superquadrics \
                  morph3d rubik atlantis lament bubble3d glplanet pulsar \
@@ -223,7 +225,7 @@ HACK_OBJS   = $(JWZGLES_OBJS) $(HACK_BIN)/screenhack.o @ANIM_OBJS@ \
                  $(UTILS_BIN)/colors.o $(UTILS_BIN)/async_netdb.o \
                  $(UTILS_BIN)/aligned_malloc.o $(UTILS_BIN)/thread_util.o \
                  $(UTILS_BIN)/utf8wc.o $(UTILS_BIN)/pow2.o \
-                 $(UTILS_BIN)/font-retry.o
+                 $(UTILS_BIN)/font-retry-xft.o
 
 HDRS           = atlantis.h bubble3d.h buildlwo.h e_textures.h \
                  grab-ximage.h tube.h sphere.h boxed.h \
@@ -235,7 +237,7 @@ HDRS                = atlantis.h bubble3d.h buildlwo.h e_textures.h \
                  sproingies.h extrusion.h glschool.h glschool_gl.h \
                  glschool_alg.h topblock.h involute.h teapot.h sonar.h \
                  dropshadow.h starwars.h teapot2.h dnapizza.h curlicue.h \
-                 quickhull.h
+                 quickhull.h dymaxionmap-coords.h
 GL_MEN         = atlantis.man boxed.man bubble3d.man cage.man circuit.man \
                  cubenetic.man dangerball.man engine.man extrusion.man \
                  flipscreen3d.man gears.man gflux.man \
@@ -510,7 +512,7 @@ $(UTILS_BIN)/aligned_malloc.o:      $(UTILS_SRC)/aligned_malloc.c
 $(UTILS_BIN)/thread_util.o:    $(UTILS_SRC)/thread_util.c
 $(UTILS_BIN)/spline.o:         $(UTILS_SRC)/spline.c
 $(UTILS_BIN)/pow2.o:           $(UTILS_SRC)/pow2.c
-$(UTILS_BIN)/font-retry.o:     $(UTILS_SRC)/font-retry.c
+$(UTILS_BIN)/font-retry-xft.o: $(UTILS_SRC)/font-retry.c
 $(HACK_BIN)/screenhack.o:      $(HACK_SRC)/screenhack.c
 $(HACK_BIN)/xlockmore.o:       $(HACK_SRC)/xlockmore.c
 $(HACK_BIN)/fps.o:             $(HACK_SRC)/fps.c
@@ -528,8 +530,8 @@ $(HACKDIR_OBJS):
        $(CC) -c $(INCLUDES) $(DEFS) $(CPPFLAGS) $(CFLAGS) $(X_CFLAGS) $<
 
 # Make sure the images have been packaged. This is the first one hit:
-$(srcdir)/../images/gen/wood_png.h:
-       cd $(srcdir)/../images && $(MAKE)
+../images/gen/wood_png.h:
+       cd ../images && $(MAKE)
 
 # How to build the "xscreensaver-gl-helper" program, that lets the daemon
 # know which visual is the right one for GL programs.
@@ -620,8 +622,9 @@ PLANET_OBJS=sphere.o $(PNG) $(HACK_TRACK_OBJS)
 glplanet:      glplanet.o      $(PLANET_OBJS)
        $(CC_HACK) -o $@ $@.o   $(PLANET_OBJS) $(PNG_LIBS)
 
-dymaxionmap: dymaxionmap.o normals.o $(PLANET_OBJS)
-       $(CC_HACK) -o $@ $@.o   normals.o $(PLANET_OBJS) $(PNG_LIBS)
+DYMAXIOBJS=dymaxionmap-coords.o normals.o $(PLANET_OBJS)
+dymaxionmap:   dymaxionmap.o   $(DYMAXIOBJS)
+       $(CC_HACK) -o $@ $@.o   $(DYMAXIOBJS) $(PNG_LIBS)
 
 pulsar:                pulsar.o        $(HACK_OBJS) $(PNG)
        $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(PNG) $(PNG_LIBS)
@@ -1001,6 +1004,7 @@ maze3d:   maze3d.o                 $(PNG) $(HACK_TRACK_OBJS)
 antinspect.o: ../../config.h
 antinspect.o: $(HACK_SRC)/fps.h
 antinspect.o: $(srcdir)/gltrackball.h
+antinspect.o: $(HACK_SRC)/recanim.h
 antinspect.o: $(HACK_SRC)/screenhackI.h
 antinspect.o: $(srcdir)/sphere.h
 antinspect.o: $(UTILS_SRC)/colors.h
@@ -1018,6 +1022,7 @@ antmaze.o: $(srcdir)/ants.h
 antmaze.o: ../../config.h
 antmaze.o: $(HACK_SRC)/fps.h
 antmaze.o: $(srcdir)/gltrackball.h
+antmaze.o: $(HACK_SRC)/recanim.h
 antmaze.o: $(srcdir)/rotator.h
 antmaze.o: $(HACK_SRC)/screenhackI.h
 antmaze.o: $(srcdir)/sphere.h
@@ -1038,6 +1043,7 @@ antspotlight.o: ../../config.h
 antspotlight.o: $(HACK_SRC)/fps.h
 antspotlight.o: $(srcdir)/gltrackball.h
 antspotlight.o: $(srcdir)/grab-ximage.h
+antspotlight.o: $(HACK_SRC)/recanim.h
 antspotlight.o: $(srcdir)/rotator.h
 antspotlight.o: $(HACK_SRC)/screenhackI.h
 antspotlight.o: $(srcdir)/sphere.h
@@ -1057,6 +1063,7 @@ atlantis.o: $(srcdir)/atlantis.h
 atlantis.o: ../../config.h
 atlantis.o: $(HACK_SRC)/fps.h
 atlantis.o: $(HACK_SRC)/images/gen/sea-texture_png.h
+atlantis.o: $(HACK_SRC)/recanim.h
 atlantis.o: $(HACK_SRC)/screenhackI.h
 atlantis.o: $(UTILS_SRC)/colors.h
 atlantis.o: $(UTILS_SRC)/erase.h
@@ -1078,6 +1085,7 @@ atunnel.o: $(HACK_SRC)/images/gen/tunnel2_png.h
 atunnel.o: $(HACK_SRC)/images/gen/tunnel3_png.h
 atunnel.o: $(HACK_SRC)/images/gen/tunnel4_png.h
 atunnel.o: $(HACK_SRC)/images/gen/tunnel5_png.h
+atunnel.o: $(HACK_SRC)/recanim.h
 atunnel.o: $(HACK_SRC)/screenhackI.h
 atunnel.o: $(srcdir)/tunnel_draw.h
 atunnel.o: $(UTILS_SRC)/colors.h
@@ -1095,6 +1103,7 @@ atunnel.o: $(HACK_SRC)/xlockmore.h
 b_draw.o: $(srcdir)/bubble3d.h
 b_draw.o: ../../config.h
 b_draw.o: $(HACK_SRC)/fps.h
+b_draw.o: $(HACK_SRC)/recanim.h
 b_draw.o: $(HACK_SRC)/screenhackI.h
 b_draw.o: $(UTILS_SRC)/colors.h
 b_draw.o: $(UTILS_SRC)/erase.h
@@ -1108,6 +1117,7 @@ b_draw.o: $(UTILS_SRC)/yarandom.h
 b_draw.o: $(HACK_SRC)/xlockmoreI.h
 blinkbox.o: ../../config.h
 blinkbox.o: $(HACK_SRC)/fps.h
+blinkbox.o: $(HACK_SRC)/recanim.h
 blinkbox.o: $(HACK_SRC)/screenhackI.h
 blinkbox.o: $(srcdir)/sphere.h
 blinkbox.o: $(UTILS_SRC)/colors.h
@@ -1124,6 +1134,7 @@ blinkbox.o: $(HACK_SRC)/xlockmore.h
 b_lockglue.o: $(srcdir)/bubble3d.h
 b_lockglue.o: ../../config.h
 b_lockglue.o: $(HACK_SRC)/fps.h
+b_lockglue.o: $(HACK_SRC)/recanim.h
 b_lockglue.o: $(HACK_SRC)/screenhackI.h
 b_lockglue.o: $(UTILS_SRC)/colors.h
 b_lockglue.o: $(UTILS_SRC)/erase.h
@@ -1139,6 +1150,7 @@ b_lockglue.o: $(HACK_SRC)/xlockmore.h
 blocktube.o: ../../config.h
 blocktube.o: $(HACK_SRC)/fps.h
 blocktube.o: $(HACK_SRC)/images/gen/blocktube_png.h
+blocktube.o: $(HACK_SRC)/recanim.h
 blocktube.o: $(HACK_SRC)/screenhackI.h
 blocktube.o: $(UTILS_SRC)/colors.h
 blocktube.o: $(UTILS_SRC)/erase.h
@@ -1155,6 +1167,7 @@ blocktube.o: $(HACK_SRC)/xlockmore.h
 boing.o: ../../config.h
 boing.o: $(HACK_SRC)/fps.h
 boing.o: $(srcdir)/gltrackball.h
+boing.o: $(HACK_SRC)/recanim.h
 boing.o: $(HACK_SRC)/screenhackI.h
 boing.o: $(UTILS_SRC)/colors.h
 boing.o: $(UTILS_SRC)/erase.h
@@ -1171,6 +1184,7 @@ bouncingcow.o: ../../config.h
 bouncingcow.o: $(HACK_SRC)/fps.h
 bouncingcow.o: $(srcdir)/gllist.h
 bouncingcow.o: $(srcdir)/gltrackball.h
+bouncingcow.o: $(HACK_SRC)/recanim.h
 bouncingcow.o: $(srcdir)/rotator.h
 bouncingcow.o: $(HACK_SRC)/screenhackI.h
 bouncingcow.o: $(UTILS_SRC)/colors.h
@@ -1188,6 +1202,7 @@ bouncingcow.o: $(HACK_SRC)/xlockmore.h
 boxed.o: $(srcdir)/boxed.h
 boxed.o: ../../config.h
 boxed.o: $(HACK_SRC)/fps.h
+boxed.o: $(HACK_SRC)/recanim.h
 boxed.o: $(HACK_SRC)/screenhackI.h
 boxed.o: $(UTILS_SRC)/colors.h
 boxed.o: $(UTILS_SRC)/erase.h
@@ -1203,6 +1218,7 @@ boxed.o: $(HACK_SRC)/xlockmore.h
 b_sphere.o: $(srcdir)/bubble3d.h
 b_sphere.o: ../../config.h
 b_sphere.o: $(HACK_SRC)/fps.h
+b_sphere.o: $(HACK_SRC)/recanim.h
 b_sphere.o: $(HACK_SRC)/screenhackI.h
 b_sphere.o: $(UTILS_SRC)/colors.h
 b_sphere.o: $(UTILS_SRC)/erase.h
@@ -1217,6 +1233,7 @@ b_sphere.o: $(HACK_SRC)/xlockmoreI.h
 bubble3d.o: $(srcdir)/bubble3d.h
 bubble3d.o: ../../config.h
 bubble3d.o: $(HACK_SRC)/fps.h
+bubble3d.o: $(HACK_SRC)/recanim.h
 bubble3d.o: $(HACK_SRC)/screenhackI.h
 bubble3d.o: $(UTILS_SRC)/colors.h
 bubble3d.o: $(UTILS_SRC)/erase.h
@@ -1233,6 +1250,7 @@ buildlwo.o: ../../config.h
 cage.o: ../../config.h
 cage.o: $(HACK_SRC)/fps.h
 cage.o: $(HACK_SRC)/images/gen/wood_png.h
+cage.o: $(HACK_SRC)/recanim.h
 cage.o: $(HACK_SRC)/screenhackI.h
 cage.o: $(UTILS_SRC)/colors.h
 cage.o: $(UTILS_SRC)/erase.h
@@ -1250,6 +1268,7 @@ carousel.o: ../../config.h
 carousel.o: $(HACK_SRC)/fps.h
 carousel.o: $(srcdir)/gltrackball.h
 carousel.o: $(srcdir)/grab-ximage.h
+carousel.o: $(HACK_SRC)/recanim.h
 carousel.o: $(srcdir)/rotator.h
 carousel.o: $(HACK_SRC)/screenhackI.h
 carousel.o: $(srcdir)/texfont.h
@@ -1268,6 +1287,7 @@ chessmodels.o: $(srcdir)/chessmodels.h
 chessmodels.o: ../../config.h
 circuit.o: ../../config.h
 circuit.o: $(HACK_SRC)/fps.h
+circuit.o: $(HACK_SRC)/recanim.h
 circuit.o: $(HACK_SRC)/screenhackI.h
 circuit.o: $(srcdir)/texfont.h
 circuit.o: $(UTILS_SRC)/colors.h
@@ -1284,6 +1304,7 @@ circuit.o: $(HACK_SRC)/xlockmore.h
 cityflow.o: ../../config.h
 cityflow.o: $(HACK_SRC)/fps.h
 cityflow.o: $(srcdir)/gltrackball.h
+cityflow.o: $(HACK_SRC)/recanim.h
 cityflow.o: $(HACK_SRC)/screenhackI.h
 cityflow.o: $(UTILS_SRC)/colors.h
 cityflow.o: $(UTILS_SRC)/erase.h
@@ -1304,6 +1325,7 @@ companion.o: ../../config.h
 companion.o: $(HACK_SRC)/fps.h
 companion.o: $(srcdir)/gllist.h
 companion.o: $(srcdir)/gltrackball.h
+companion.o: $(HACK_SRC)/recanim.h
 companion.o: $(srcdir)/rotator.h
 companion.o: $(HACK_SRC)/screenhackI.h
 companion.o: $(UTILS_SRC)/colors.h
@@ -1334,6 +1356,7 @@ cow_udder.o: ../../config.h
 cow_udder.o: $(srcdir)/gllist.h
 crackberg.o: ../../config.h
 crackberg.o: $(HACK_SRC)/fps.h
+crackberg.o: $(HACK_SRC)/recanim.h
 crackberg.o: $(HACK_SRC)/screenhackI.h
 crackberg.o: $(UTILS_SRC)/colors.h
 crackberg.o: $(UTILS_SRC)/erase.h
@@ -1350,6 +1373,7 @@ crumbler.o: ../../config.h
 crumbler.o: $(HACK_SRC)/fps.h
 crumbler.o: $(srcdir)/gltrackball.h
 crumbler.o: $(srcdir)/quickhull.h
+crumbler.o: $(HACK_SRC)/recanim.h
 crumbler.o: $(srcdir)/rotator.h
 crumbler.o: $(HACK_SRC)/screenhackI.h
 crumbler.o: $(UTILS_SRC)/colors.h
@@ -1366,6 +1390,7 @@ crumbler.o: $(HACK_SRC)/xlockmore.h
 cube21.o: ../../config.h
 cube21.o: $(HACK_SRC)/fps.h
 cube21.o: $(srcdir)/gltrackball.h
+cube21.o: $(HACK_SRC)/recanim.h
 cube21.o: $(HACK_SRC)/screenhackI.h
 cube21.o: $(UTILS_SRC)/colors.h
 cube21.o: $(UTILS_SRC)/erase.h
@@ -1381,6 +1406,7 @@ cube21.o: $(HACK_SRC)/xlockmore.h
 cubenetic.o: ../../config.h
 cubenetic.o: $(HACK_SRC)/fps.h
 cubenetic.o: $(srcdir)/gltrackball.h
+cubenetic.o: $(HACK_SRC)/recanim.h
 cubenetic.o: $(srcdir)/rotator.h
 cubenetic.o: $(HACK_SRC)/screenhackI.h
 cubenetic.o: $(UTILS_SRC)/colors.h
@@ -1397,6 +1423,7 @@ cubenetic.o: $(HACK_SRC)/xlockmore.h
 cubestack.o: ../../config.h
 cubestack.o: $(HACK_SRC)/fps.h
 cubestack.o: $(srcdir)/gltrackball.h
+cubestack.o: $(HACK_SRC)/recanim.h
 cubestack.o: $(srcdir)/rotator.h
 cubestack.o: $(HACK_SRC)/screenhackI.h
 cubestack.o: $(UTILS_SRC)/colors.h
@@ -1413,6 +1440,7 @@ cubestack.o: $(HACK_SRC)/xlockmore.h
 cubestorm.o: ../../config.h
 cubestorm.o: $(HACK_SRC)/fps.h
 cubestorm.o: $(srcdir)/gltrackball.h
+cubestorm.o: $(HACK_SRC)/recanim.h
 cubestorm.o: $(srcdir)/rotator.h
 cubestorm.o: $(HACK_SRC)/screenhackI.h
 cubestorm.o: $(UTILS_SRC)/colors.h
@@ -1430,6 +1458,7 @@ cubetwist.o: ../../config.h
 cubetwist.o: $(HACK_SRC)/fps.h
 cubetwist.o: $(srcdir)/gltrackball.h
 cubetwist.o: $(srcdir)/normals.h
+cubetwist.o: $(HACK_SRC)/recanim.h
 cubetwist.o: $(srcdir)/rotator.h
 cubetwist.o: $(HACK_SRC)/screenhackI.h
 cubetwist.o: $(UTILS_SRC)/colors.h
@@ -1446,6 +1475,7 @@ cubetwist.o: $(HACK_SRC)/xlockmore.h
 cubicgrid.o: ../../config.h
 cubicgrid.o: $(HACK_SRC)/fps.h
 cubicgrid.o: $(srcdir)/gltrackball.h
+cubicgrid.o: $(HACK_SRC)/recanim.h
 cubicgrid.o: $(srcdir)/rotator.h
 cubicgrid.o: $(HACK_SRC)/screenhackI.h
 cubicgrid.o: $(UTILS_SRC)/colors.h
@@ -1462,6 +1492,7 @@ cubicgrid.o: $(HACK_SRC)/xlockmore.h
 dangerball.o: ../../config.h
 dangerball.o: $(HACK_SRC)/fps.h
 dangerball.o: $(srcdir)/gltrackball.h
+dangerball.o: $(HACK_SRC)/recanim.h
 dangerball.o: $(srcdir)/rotator.h
 dangerball.o: $(HACK_SRC)/screenhackI.h
 dangerball.o: $(srcdir)/sphere.h
@@ -1481,6 +1512,7 @@ discoball.o: ../../config.h
 discoball.o: $(HACK_SRC)/fps.h
 discoball.o: $(srcdir)/gltrackball.h
 discoball.o: $(srcdir)/normals.h
+discoball.o: $(HACK_SRC)/recanim.h
 discoball.o: $(srcdir)/rotator.h
 discoball.o: $(HACK_SRC)/screenhackI.h
 discoball.o: $(UTILS_SRC)/colors.h
@@ -1498,6 +1530,7 @@ dnalogo.o: ../../config.h
 dnalogo.o: $(HACK_SRC)/fps.h
 dnalogo.o: $(srcdir)/gltrackball.h
 dnalogo.o: $(srcdir)/normals.h
+dnalogo.o: $(HACK_SRC)/recanim.h
 dnalogo.o: $(srcdir)/rotator.h
 dnalogo.o: $(HACK_SRC)/screenhackI.h
 dnalogo.o: $(srcdir)/sphere.h
@@ -1518,6 +1551,7 @@ dnalogo.o: $(HACK_SRC)/xlockmore.h
 dolphin.o: $(srcdir)/atlantis.h
 dolphin.o: ../../config.h
 dolphin.o: $(HACK_SRC)/fps.h
+dolphin.o: $(HACK_SRC)/recanim.h
 dolphin.o: $(HACK_SRC)/screenhackI.h
 dolphin.o: $(UTILS_SRC)/colors.h
 dolphin.o: $(UTILS_SRC)/font-retry.h
@@ -1530,6 +1564,7 @@ dolphin.o: $(UTILS_SRC)/yarandom.h
 dropshadow.o: ../../config.h
 dropshadow.o: $(srcdir)/dropshadow.h
 dropshadow.o: $(HACK_SRC)/fps.h
+dropshadow.o: $(HACK_SRC)/recanim.h
 dropshadow.o: $(HACK_SRC)/screenhackI.h
 dropshadow.o: $(UTILS_SRC)/colors.h
 dropshadow.o: $(UTILS_SRC)/erase.h
@@ -1541,12 +1576,18 @@ dropshadow.o: $(UTILS_SRC)/usleep.h
 dropshadow.o: $(UTILS_SRC)/visual.h
 dropshadow.o: $(UTILS_SRC)/yarandom.h
 dropshadow.o: $(HACK_SRC)/xlockmoreI.h
+dymaxionmap-coords.o: ../../config.h
+dymaxionmap-coords.o: $(srcdir)/dymaxionmap-coords.h
 dymaxionmap.o: ../../config.h
+dymaxionmap.o: $(srcdir)/dymaxionmap-coords.h
 dymaxionmap.o: $(HACK_SRC)/fps.h
 dymaxionmap.o: $(srcdir)/gltrackball.h
-dymaxionmap.o: $(HACK_SRC)/images/gen/dymaxionmap_png.h
+dymaxionmap.o: $(HACK_SRC)/images/gen/earth_flat_png.h
+dymaxionmap.o: $(HACK_SRC)/images/gen/earth_night_png.h
+dymaxionmap.o: $(HACK_SRC)/images/gen/earth_png.h
 dymaxionmap.o: $(HACK_SRC)/images/gen/ground_png.h
 dymaxionmap.o: $(srcdir)/normals.h
+dymaxionmap.o: $(HACK_SRC)/recanim.h
 dymaxionmap.o: $(srcdir)/rotator.h
 dymaxionmap.o: $(HACK_SRC)/screenhackI.h
 dymaxionmap.o: $(srcdir)/sphere.h
@@ -1568,6 +1609,7 @@ endgame.o: $(srcdir)/chessmodels.h
 endgame.o: ../../config.h
 endgame.o: $(HACK_SRC)/fps.h
 endgame.o: $(srcdir)/gltrackball.h
+endgame.o: $(HACK_SRC)/recanim.h
 endgame.o: $(HACK_SRC)/screenhackI.h
 endgame.o: $(UTILS_SRC)/colors.h
 endgame.o: $(UTILS_SRC)/erase.h
@@ -1583,6 +1625,7 @@ endgame.o: $(HACK_SRC)/xlockmore.h
 energystream.o: ../../config.h
 energystream.o: $(HACK_SRC)/fps.h
 energystream.o: $(srcdir)/gltrackball.h
+energystream.o: $(HACK_SRC)/recanim.h
 energystream.o: $(srcdir)/rotator.h
 energystream.o: $(HACK_SRC)/screenhackI.h
 energystream.o: $(UTILS_SRC)/colors.h
@@ -1599,6 +1642,7 @@ energystream.o: $(HACK_SRC)/xlockmore.h
 engine.o: ../../config.h
 engine.o: $(HACK_SRC)/fps.h
 engine.o: $(srcdir)/gltrackball.h
+engine.o: $(HACK_SRC)/recanim.h
 engine.o: $(srcdir)/rotator.h
 engine.o: $(HACK_SRC)/screenhackI.h
 engine.o: $(srcdir)/texfont.h
@@ -1619,6 +1663,7 @@ erase-gl.o: $(UTILS_SRC)/utils.h
 esper.o: ../../config.h
 esper.o: $(HACK_SRC)/fps.h
 esper.o: $(srcdir)/grab-ximage.h
+esper.o: $(HACK_SRC)/recanim.h
 esper.o: $(HACK_SRC)/screenhackI.h
 esper.o: $(srcdir)/texfont.h
 esper.o: $(UTILS_SRC)/colors.h
@@ -1645,6 +1690,7 @@ extrusion.o: ../../config.h
 extrusion.o: $(srcdir)/extrusion.h
 extrusion.o: $(HACK_SRC)/fps.h
 extrusion.o: $(srcdir)/gltrackball.h
+extrusion.o: $(HACK_SRC)/recanim.h
 extrusion.o: $(srcdir)/rotator.h
 extrusion.o: $(HACK_SRC)/screenhackI.h
 extrusion.o: $(UTILS_SRC)/colors.h
@@ -1669,6 +1715,7 @@ flipflop.o: ../../config.h
 flipflop.o: $(HACK_SRC)/fps.h
 flipflop.o: $(srcdir)/gltrackball.h
 flipflop.o: $(srcdir)/grab-ximage.h
+flipflop.o: $(HACK_SRC)/recanim.h
 flipflop.o: $(HACK_SRC)/screenhackI.h
 flipflop.o: $(UTILS_SRC)/colors.h
 flipflop.o: $(UTILS_SRC)/erase.h
@@ -1685,6 +1732,7 @@ flipscreen3d.o: ../../config.h
 flipscreen3d.o: $(HACK_SRC)/fps.h
 flipscreen3d.o: $(srcdir)/gltrackball.h
 flipscreen3d.o: $(srcdir)/grab-ximage.h
+flipscreen3d.o: $(HACK_SRC)/recanim.h
 flipscreen3d.o: $(HACK_SRC)/screenhackI.h
 flipscreen3d.o: $(UTILS_SRC)/colors.h
 flipscreen3d.o: $(UTILS_SRC)/erase.h
@@ -1699,6 +1747,7 @@ flipscreen3d.o: $(HACK_SRC)/xlockmoreI.h
 flipscreen3d.o: $(HACK_SRC)/xlockmore.h
 fliptext.o: ../../config.h
 fliptext.o: $(HACK_SRC)/fps.h
+fliptext.o: $(HACK_SRC)/recanim.h
 fliptext.o: $(HACK_SRC)/screenhackI.h
 fliptext.o: $(srcdir)/texfont.h
 fliptext.o: $(UTILS_SRC)/colors.h
@@ -1717,6 +1766,7 @@ flurry.o: ../../config.h
 flurry.o: $(srcdir)/flurry.h
 flurry.o: $(HACK_SRC)/fps.h
 flurry.o: $(srcdir)/gltrackball.h
+flurry.o: $(HACK_SRC)/recanim.h
 flurry.o: $(srcdir)/rotator.h
 flurry.o: $(HACK_SRC)/screenhackI.h
 flurry.o: $(UTILS_SRC)/colors.h
@@ -1756,6 +1806,7 @@ flyingtoasters.o: $(srcdir)/gllist.h
 flyingtoasters.o: $(srcdir)/gltrackball.h
 flyingtoasters.o: $(HACK_SRC)/images/gen/chromesphere_png.h
 flyingtoasters.o: $(HACK_SRC)/images/gen/toast_png.h
+flyingtoasters.o: $(HACK_SRC)/recanim.h
 flyingtoasters.o: $(HACK_SRC)/screenhackI.h
 flyingtoasters.o: $(UTILS_SRC)/colors.h
 flyingtoasters.o: $(UTILS_SRC)/erase.h
@@ -1772,6 +1823,7 @@ flyingtoasters.o: $(HACK_SRC)/xlockmore.h
 fps-gl.o: ../../config.h
 fps-gl.o: $(HACK_SRC)/fpsI.h
 fps-gl.o: $(HACK_SRC)/fps.h
+fps-gl.o: $(HACK_SRC)/recanim.h
 fps-gl.o: $(HACK_SRC)/screenhackI.h
 fps-gl.o: $(srcdir)/texfont.h
 fps-gl.o: $(UTILS_SRC)/colors.h
@@ -1789,6 +1841,7 @@ gears.o: $(HACK_SRC)/fps.h
 gears.o: $(srcdir)/gltrackball.h
 gears.o: $(srcdir)/involute.h
 gears.o: $(srcdir)/normals.h
+gears.o: $(HACK_SRC)/recanim.h
 gears.o: $(srcdir)/rotator.h
 gears.o: $(HACK_SRC)/screenhackI.h
 gears.o: $(srcdir)/tube.h
@@ -1809,6 +1862,7 @@ geodesicgears.o: $(srcdir)/gllist.h
 geodesicgears.o: $(srcdir)/gltrackball.h
 geodesicgears.o: $(srcdir)/involute.h
 geodesicgears.o: $(srcdir)/normals.h
+geodesicgears.o: $(HACK_SRC)/recanim.h
 geodesicgears.o: $(srcdir)/rotator.h
 geodesicgears.o: $(HACK_SRC)/screenhackI.h
 geodesicgears.o: $(srcdir)/texfont.h
@@ -1828,6 +1882,7 @@ geodesic.o: $(HACK_SRC)/fps.h
 geodesic.o: $(srcdir)/gllist.h
 geodesic.o: $(srcdir)/gltrackball.h
 geodesic.o: $(srcdir)/normals.h
+geodesic.o: $(HACK_SRC)/recanim.h
 geodesic.o: $(srcdir)/rotator.h
 geodesic.o: $(HACK_SRC)/screenhackI.h
 geodesic.o: $(UTILS_SRC)/colors.h
@@ -1845,6 +1900,7 @@ gflux.o: ../../config.h
 gflux.o: $(HACK_SRC)/fps.h
 gflux.o: $(srcdir)/gltrackball.h
 gflux.o: $(srcdir)/grab-ximage.h
+gflux.o: $(HACK_SRC)/recanim.h
 gflux.o: $(HACK_SRC)/screenhackI.h
 gflux.o: $(UTILS_SRC)/colors.h
 gflux.o: $(UTILS_SRC)/erase.h
@@ -1860,6 +1916,7 @@ gflux.o: $(HACK_SRC)/xlockmore.h
 glblur.o: ../../config.h
 glblur.o: $(HACK_SRC)/fps.h
 glblur.o: $(srcdir)/gltrackball.h
+glblur.o: $(HACK_SRC)/recanim.h
 glblur.o: $(srcdir)/rotator.h
 glblur.o: $(HACK_SRC)/screenhackI.h
 glblur.o: $(UTILS_SRC)/colors.h
@@ -1875,6 +1932,7 @@ glblur.o: $(HACK_SRC)/xlockmoreI.h
 glblur.o: $(HACK_SRC)/xlockmore.h
 glcells.o: ../../config.h
 glcells.o: $(HACK_SRC)/fps.h
+glcells.o: $(HACK_SRC)/recanim.h
 glcells.o: $(HACK_SRC)/screenhackI.h
 glcells.o: $(UTILS_SRC)/colors.h
 glcells.o: $(UTILS_SRC)/erase.h
@@ -1890,6 +1948,7 @@ glcells.o: $(HACK_SRC)/xlockmore.h
 gleidescope.o: ../../config.h
 gleidescope.o: $(HACK_SRC)/fps.h
 gleidescope.o: $(srcdir)/grab-ximage.h
+gleidescope.o: $(HACK_SRC)/recanim.h
 gleidescope.o: $(HACK_SRC)/screenhackI.h
 gleidescope.o: $(UTILS_SRC)/colors.h
 gleidescope.o: $(UTILS_SRC)/erase.h
@@ -1908,6 +1967,7 @@ glforestfire.o: $(HACK_SRC)/fps.h
 glforestfire.o: $(srcdir)/gltrackball.h
 glforestfire.o: $(HACK_SRC)/images/gen/ground_png.h
 glforestfire.o: $(HACK_SRC)/images/gen/tree_png.h
+glforestfire.o: $(HACK_SRC)/recanim.h
 glforestfire.o: $(HACK_SRC)/screenhackI.h
 glforestfire.o: $(UTILS_SRC)/colors.h
 glforestfire.o: $(UTILS_SRC)/erase.h
@@ -1923,6 +1983,7 @@ glforestfire.o: $(HACK_SRC)/xlockmoreI.h
 glforestfire.o: $(HACK_SRC)/xlockmore.h
 glhanoi.o: ../../config.h
 glhanoi.o: $(HACK_SRC)/fps.h
+glhanoi.o: $(HACK_SRC)/recanim.h
 glhanoi.o: $(srcdir)/rotator.h
 glhanoi.o: $(HACK_SRC)/screenhackI.h
 glhanoi.o: $(UTILS_SRC)/colors.h
@@ -1939,6 +2000,7 @@ glhanoi.o: $(HACK_SRC)/xlockmore.h
 glknots.o: ../../config.h
 glknots.o: $(HACK_SRC)/fps.h
 glknots.o: $(srcdir)/gltrackball.h
+glknots.o: $(HACK_SRC)/recanim.h
 glknots.o: $(srcdir)/rotator.h
 glknots.o: $(HACK_SRC)/screenhackI.h
 glknots.o: $(srcdir)/tube.h
@@ -1958,6 +2020,7 @@ gllist.o: $(srcdir)/gllist.h
 glmatrix.o: ../../config.h
 glmatrix.o: $(HACK_SRC)/fps.h
 glmatrix.o: $(HACK_SRC)/images/gen/matrix3_png.h
+glmatrix.o: $(HACK_SRC)/recanim.h
 glmatrix.o: $(HACK_SRC)/screenhackI.h
 glmatrix.o: $(UTILS_SRC)/colors.h
 glmatrix.o: $(UTILS_SRC)/erase.h
@@ -1976,6 +2039,7 @@ glplanet.o: $(HACK_SRC)/fps.h
 glplanet.o: $(srcdir)/gltrackball.h
 glplanet.o: $(HACK_SRC)/images/gen/earth_night_png.h
 glplanet.o: $(HACK_SRC)/images/gen/earth_png.h
+glplanet.o: $(HACK_SRC)/recanim.h
 glplanet.o: $(srcdir)/rotator.h
 glplanet.o: $(HACK_SRC)/screenhackI.h
 glplanet.o: $(srcdir)/sphere.h
@@ -2004,6 +2068,7 @@ glschool.o: $(HACK_SRC)/fps.h
 glschool.o: $(srcdir)/glschool_alg.h
 glschool.o: $(srcdir)/glschool_gl.h
 glschool.o: $(srcdir)/glschool.h
+glschool.o: $(HACK_SRC)/recanim.h
 glschool.o: $(HACK_SRC)/screenhackI.h
 glschool.o: $(UTILS_SRC)/colors.h
 glschool.o: $(UTILS_SRC)/erase.h
@@ -2019,6 +2084,7 @@ glschool.o: $(HACK_SRC)/xlockmore.h
 glslideshow.o: ../../config.h
 glslideshow.o: $(HACK_SRC)/fps.h
 glslideshow.o: $(srcdir)/grab-ximage.h
+glslideshow.o: $(HACK_SRC)/recanim.h
 glslideshow.o: $(HACK_SRC)/screenhackI.h
 glslideshow.o: $(srcdir)/texfont.h
 glslideshow.o: $(UTILS_SRC)/colors.h
@@ -2034,6 +2100,7 @@ glslideshow.o: $(HACK_SRC)/xlockmoreI.h
 glslideshow.o: $(HACK_SRC)/xlockmore.h
 glsnake.o: ../../config.h
 glsnake.o: $(HACK_SRC)/fps.h
+glsnake.o: $(HACK_SRC)/recanim.h
 glsnake.o: $(HACK_SRC)/screenhackI.h
 glsnake.o: $(srcdir)/texfont.h
 glsnake.o: $(UTILS_SRC)/colors.h
@@ -2053,6 +2120,7 @@ gltext.o: $(srcdir)/gltrackball.h
 gltext.o: $(srcdir)/glut_mroman.h
 gltext.o: $(srcdir)/glut_roman.h
 gltext.o: $(srcdir)/glutstroke.h
+gltext.o: $(HACK_SRC)/recanim.h
 gltext.o: $(srcdir)/rotator.h
 gltext.o: $(HACK_SRC)/screenhackI.h
 gltext.o: $(srcdir)/sphere.h
@@ -2087,6 +2155,7 @@ hexstrut.o: ../../config.h
 hexstrut.o: $(HACK_SRC)/fps.h
 hexstrut.o: $(srcdir)/gltrackball.h
 hexstrut.o: $(srcdir)/normals.h
+hexstrut.o: $(HACK_SRC)/recanim.h
 hexstrut.o: $(srcdir)/rotator.h
 hexstrut.o: $(HACK_SRC)/screenhackI.h
 hexstrut.o: $(UTILS_SRC)/colors.h
@@ -2103,6 +2172,7 @@ hexstrut.o: $(HACK_SRC)/xlockmore.h
 hilbert.o: ../../config.h
 hilbert.o: $(HACK_SRC)/fps.h
 hilbert.o: $(srcdir)/gltrackball.h
+hilbert.o: $(HACK_SRC)/recanim.h
 hilbert.o: $(srcdir)/rotator.h
 hilbert.o: $(HACK_SRC)/screenhackI.h
 hilbert.o: $(srcdir)/sphere.h
@@ -2122,6 +2192,7 @@ hydrostat.o: ../../config.h
 hydrostat.o: $(HACK_SRC)/fps.h
 hydrostat.o: $(srcdir)/gltrackball.h
 hydrostat.o: $(srcdir)/normals.h
+hydrostat.o: $(HACK_SRC)/recanim.h
 hydrostat.o: $(HACK_SRC)/screenhackI.h
 hydrostat.o: $(srcdir)/sphere.h
 hydrostat.o: $(UTILS_SRC)/colors.h
@@ -2138,6 +2209,7 @@ hydrostat.o: $(HACK_SRC)/xlockmore.h
 hypertorus.o: ../../config.h
 hypertorus.o: $(HACK_SRC)/fps.h
 hypertorus.o: $(srcdir)/gltrackball.h
+hypertorus.o: $(HACK_SRC)/recanim.h
 hypertorus.o: $(HACK_SRC)/screenhackI.h
 hypertorus.o: $(UTILS_SRC)/colors.h
 hypertorus.o: $(UTILS_SRC)/erase.h
@@ -2152,6 +2224,7 @@ hypertorus.o: $(HACK_SRC)/xlockmoreI.h
 hypertorus.o: $(HACK_SRC)/xlockmore.h
 hypnowheel.o: ../../config.h
 hypnowheel.o: $(HACK_SRC)/fps.h
+hypnowheel.o: $(HACK_SRC)/recanim.h
 hypnowheel.o: $(srcdir)/rotator.h
 hypnowheel.o: $(HACK_SRC)/screenhackI.h
 hypnowheel.o: $(UTILS_SRC)/colors.h
@@ -2169,6 +2242,7 @@ involute.o: ../../config.h
 involute.o: $(HACK_SRC)/fps.h
 involute.o: $(srcdir)/involute.h
 involute.o: $(srcdir)/normals.h
+involute.o: $(HACK_SRC)/recanim.h
 involute.o: $(HACK_SRC)/screenhackI.h
 involute.o: $(UTILS_SRC)/colors.h
 involute.o: $(UTILS_SRC)/font-retry.h
@@ -2182,6 +2256,7 @@ jigglypuff.o: ../../config.h
 jigglypuff.o: $(HACK_SRC)/fps.h
 jigglypuff.o: $(srcdir)/gltrackball.h
 jigglypuff.o: $(HACK_SRC)/images/gen/jigglymap_png.h
+jigglypuff.o: $(HACK_SRC)/recanim.h
 jigglypuff.o: $(HACK_SRC)/screenhackI.h
 jigglypuff.o: $(UTILS_SRC)/colors.h
 jigglypuff.o: $(UTILS_SRC)/erase.h
@@ -2200,6 +2275,7 @@ jigsaw.o: $(HACK_SRC)/fps.h
 jigsaw.o: $(srcdir)/gltrackball.h
 jigsaw.o: $(srcdir)/grab-ximage.h
 jigsaw.o: $(srcdir)/normals.h
+jigsaw.o: $(HACK_SRC)/recanim.h
 jigsaw.o: $(srcdir)/rotator.h
 jigsaw.o: $(HACK_SRC)/screenhackI.h
 jigsaw.o: $(srcdir)/texfont.h
@@ -2218,6 +2294,7 @@ jigsaw.o: $(HACK_SRC)/xlockmore.h
 juggler3d.o: ../../config.h
 juggler3d.o: $(HACK_SRC)/fps.h
 juggler3d.o: $(srcdir)/gltrackball.h
+juggler3d.o: $(HACK_SRC)/recanim.h
 juggler3d.o: $(srcdir)/rotator.h
 juggler3d.o: $(HACK_SRC)/screenhackI.h
 juggler3d.o: $(srcdir)/sphere.h
@@ -2238,6 +2315,7 @@ kaleidocycle.o: ../../config.h
 kaleidocycle.o: $(HACK_SRC)/fps.h
 kaleidocycle.o: $(srcdir)/gltrackball.h
 kaleidocycle.o: $(srcdir)/normals.h
+kaleidocycle.o: $(HACK_SRC)/recanim.h
 kaleidocycle.o: $(srcdir)/rotator.h
 kaleidocycle.o: $(HACK_SRC)/screenhackI.h
 kaleidocycle.o: $(UTILS_SRC)/colors.h
@@ -2255,6 +2333,7 @@ klein.o: ../../config.h
 klein.o: $(srcdir)/curlicue.h
 klein.o: $(HACK_SRC)/fps.h
 klein.o: $(srcdir)/gltrackball.h
+klein.o: $(HACK_SRC)/recanim.h
 klein.o: $(HACK_SRC)/screenhackI.h
 klein.o: $(UTILS_SRC)/colors.h
 klein.o: $(UTILS_SRC)/erase.h
@@ -2275,6 +2354,7 @@ lament.o: $(srcdir)/gllist.h
 lament.o: $(srcdir)/gltrackball.h
 lament.o: $(HACK_SRC)/images/gen/lament512_png.h
 lament.o: $(srcdir)/normals.h
+lament.o: $(HACK_SRC)/recanim.h
 lament.o: $(srcdir)/rotator.h
 lament.o: $(HACK_SRC)/screenhackI.h
 lament.o: $(UTILS_SRC)/colors.h
@@ -2293,6 +2373,7 @@ lavalite.o: ../../config.h
 lavalite.o: $(HACK_SRC)/fps.h
 lavalite.o: $(srcdir)/gltrackball.h
 lavalite.o: $(srcdir)/marching.h
+lavalite.o: $(HACK_SRC)/recanim.h
 lavalite.o: $(srcdir)/rotator.h
 lavalite.o: $(HACK_SRC)/screenhackI.h
 lavalite.o: $(UTILS_SRC)/colors.h
@@ -2309,6 +2390,7 @@ lavalite.o: $(HACK_SRC)/xlockmoreI.h
 lavalite.o: $(HACK_SRC)/xlockmore.h
 lockward.o: ../../config.h
 lockward.o: $(HACK_SRC)/fps.h
+lockward.o: $(HACK_SRC)/recanim.h
 lockward.o: $(HACK_SRC)/screenhackI.h
 lockward.o: $(UTILS_SRC)/colors.h
 lockward.o: $(UTILS_SRC)/erase.h
@@ -2332,6 +2414,7 @@ maze3d.o: $(HACK_SRC)/images/gen/brick2_png.h
 maze3d.o: $(HACK_SRC)/images/gen/logo-32_png.h
 maze3d.o: $(HACK_SRC)/images/gen/start_png.h
 maze3d.o: $(HACK_SRC)/images/gen/wood2_png.h
+maze3d.o: $(HACK_SRC)/recanim.h
 maze3d.o: $(HACK_SRC)/screenhackI.h
 maze3d.o: $(UTILS_SRC)/colors.h
 maze3d.o: $(UTILS_SRC)/erase.h
@@ -2348,6 +2431,7 @@ maze3d.o: $(HACK_SRC)/xlockmore.h
 menger.o: ../../config.h
 menger.o: $(HACK_SRC)/fps.h
 menger.o: $(srcdir)/gltrackball.h
+menger.o: $(HACK_SRC)/recanim.h
 menger.o: $(srcdir)/rotator.h
 menger.o: $(HACK_SRC)/screenhackI.h
 menger.o: $(UTILS_SRC)/colors.h
@@ -2365,6 +2449,7 @@ mirrorblob.o: ../../config.h
 mirrorblob.o: $(HACK_SRC)/fps.h
 mirrorblob.o: $(srcdir)/gltrackball.h
 mirrorblob.o: $(srcdir)/grab-ximage.h
+mirrorblob.o: $(HACK_SRC)/recanim.h
 mirrorblob.o: $(HACK_SRC)/screenhackI.h
 mirrorblob.o: $(UTILS_SRC)/colors.h
 mirrorblob.o: $(UTILS_SRC)/erase.h
@@ -2382,6 +2467,7 @@ moebiusgears.o: $(HACK_SRC)/fps.h
 moebiusgears.o: $(srcdir)/gltrackball.h
 moebiusgears.o: $(srcdir)/involute.h
 moebiusgears.o: $(srcdir)/normals.h
+moebiusgears.o: $(HACK_SRC)/recanim.h
 moebiusgears.o: $(srcdir)/rotator.h
 moebiusgears.o: $(HACK_SRC)/screenhackI.h
 moebiusgears.o: $(UTILS_SRC)/colors.h
@@ -2398,6 +2484,7 @@ moebiusgears.o: $(HACK_SRC)/xlockmore.h
 moebius.o: ../../config.h
 moebius.o: $(HACK_SRC)/fps.h
 moebius.o: $(srcdir)/gltrackball.h
+moebius.o: $(HACK_SRC)/recanim.h
 moebius.o: $(srcdir)/rotator.h
 moebius.o: $(HACK_SRC)/screenhackI.h
 moebius.o: $(srcdir)/sphere.h
@@ -2417,6 +2504,7 @@ molecule.o: ../../config.h
 molecule.o: $(HACK_SRC)/fps.h
 molecule.o: $(srcdir)/gltrackball.h
 molecule.o: molecules.h
+molecule.o: $(HACK_SRC)/recanim.h
 molecule.o: $(srcdir)/rotator.h
 molecule.o: $(HACK_SRC)/screenhackI.h
 molecule.o: $(srcdir)/sphere.h
@@ -2435,6 +2523,7 @@ molecule.o: $(HACK_SRC)/xlockmoreI.h
 molecule.o: $(HACK_SRC)/xlockmore.h
 morph3d.o: ../../config.h
 morph3d.o: $(HACK_SRC)/fps.h
+morph3d.o: $(HACK_SRC)/recanim.h
 morph3d.o: $(HACK_SRC)/screenhackI.h
 morph3d.o: $(UTILS_SRC)/colors.h
 morph3d.o: $(UTILS_SRC)/erase.h
@@ -2449,12 +2538,14 @@ morph3d.o: $(HACK_SRC)/xlockmoreI.h
 morph3d.o: $(HACK_SRC)/xlockmore.h
 noof.o: ../../config.h
 noof.o: $(HACK_SRC)/fps.h
+noof.o: $(HACK_SRC)/recanim.h
 noof.o: $(HACK_SRC)/screenhackI.h
 noof.o: $(UTILS_SRC)/colors.h
 noof.o: $(UTILS_SRC)/erase.h
 noof.o: $(UTILS_SRC)/font-retry.h
 noof.o: $(UTILS_SRC)/grabscreen.h
 noof.o: $(UTILS_SRC)/hsv.h
+noof.o: $(UTILS_SRC)/pow2.h
 noof.o: $(UTILS_SRC)/resources.h
 noof.o: $(UTILS_SRC)/usleep.h
 noof.o: $(UTILS_SRC)/visual.h
@@ -2469,6 +2560,7 @@ peepers.o: $(srcdir)/gltrackball.h
 peepers.o: $(HACK_SRC)/images/gen/iris_png.h
 peepers.o: $(HACK_SRC)/images/gen/sclera_png.h
 peepers.o: $(srcdir)/normals.h
+peepers.o: $(HACK_SRC)/recanim.h
 peepers.o: $(srcdir)/rotator.h
 peepers.o: $(HACK_SRC)/screenhackI.h
 peepers.o: $(UTILS_SRC)/colors.h
@@ -2487,6 +2579,7 @@ photopile.o: ../../config.h
 photopile.o: $(srcdir)/dropshadow.h
 photopile.o: $(HACK_SRC)/fps.h
 photopile.o: $(srcdir)/grab-ximage.h
+photopile.o: $(HACK_SRC)/recanim.h
 photopile.o: $(HACK_SRC)/screenhackI.h
 photopile.o: $(srcdir)/texfont.h
 photopile.o: $(UTILS_SRC)/colors.h
@@ -2505,6 +2598,7 @@ pinion.o: $(HACK_SRC)/fps.h
 pinion.o: $(srcdir)/gltrackball.h
 pinion.o: $(srcdir)/involute.h
 pinion.o: $(srcdir)/normals.h
+pinion.o: $(HACK_SRC)/recanim.h
 pinion.o: $(HACK_SRC)/screenhackI.h
 pinion.o: $(srcdir)/texfont.h
 pinion.o: $(UTILS_SRC)/colors.h
@@ -2524,6 +2618,7 @@ pipes.o: $(srcdir)/buildlwo.h
 pipes.o: ../../config.h
 pipes.o: $(HACK_SRC)/fps.h
 pipes.o: $(srcdir)/gltrackball.h
+pipes.o: $(HACK_SRC)/recanim.h
 pipes.o: $(HACK_SRC)/screenhackI.h
 pipes.o: $(srcdir)/sphere.h
 pipes.o: $(srcdir)/teapot.h
@@ -2543,6 +2638,7 @@ polyhedra-gl.o: $(HACK_SRC)/fps.h
 polyhedra-gl.o: $(srcdir)/gltrackball.h
 polyhedra-gl.o: $(srcdir)/normals.h
 polyhedra-gl.o: $(srcdir)/polyhedra.h
+polyhedra-gl.o: $(HACK_SRC)/recanim.h
 polyhedra-gl.o: $(srcdir)/rotator.h
 polyhedra-gl.o: $(HACK_SRC)/screenhackI.h
 polyhedra-gl.o: $(srcdir)/teapot.h
@@ -2563,6 +2659,7 @@ polyhedra.o: $(srcdir)/polyhedra.h
 polytopes.o: ../../config.h
 polytopes.o: $(HACK_SRC)/fps.h
 polytopes.o: $(srcdir)/gltrackball.h
+polytopes.o: $(HACK_SRC)/recanim.h
 polytopes.o: $(HACK_SRC)/screenhackI.h
 polytopes.o: $(UTILS_SRC)/colors.h
 polytopes.o: $(UTILS_SRC)/erase.h
@@ -2579,6 +2676,7 @@ projectiveplane.o: ../../config.h
 projectiveplane.o: $(srcdir)/curlicue.h
 projectiveplane.o: $(HACK_SRC)/fps.h
 projectiveplane.o: $(srcdir)/gltrackball.h
+projectiveplane.o: $(HACK_SRC)/recanim.h
 projectiveplane.o: $(HACK_SRC)/screenhackI.h
 projectiveplane.o: $(UTILS_SRC)/colors.h
 projectiveplane.o: $(UTILS_SRC)/erase.h
@@ -2594,6 +2692,7 @@ projectiveplane.o: $(HACK_SRC)/xlockmore.h
 providence.o: ../../config.h
 providence.o: $(HACK_SRC)/fps.h
 providence.o: $(srcdir)/gltrackball.h
+providence.o: $(HACK_SRC)/recanim.h
 providence.o: $(HACK_SRC)/screenhackI.h
 providence.o: $(UTILS_SRC)/colors.h
 providence.o: $(UTILS_SRC)/erase.h
@@ -2608,6 +2707,7 @@ providence.o: $(HACK_SRC)/xlockmoreI.h
 providence.o: $(HACK_SRC)/xlockmore.h
 pulsar.o: ../../config.h
 pulsar.o: $(HACK_SRC)/fps.h
+pulsar.o: $(HACK_SRC)/recanim.h
 pulsar.o: $(HACK_SRC)/screenhackI.h
 pulsar.o: $(UTILS_SRC)/colors.h
 pulsar.o: $(UTILS_SRC)/erase.h
@@ -2623,6 +2723,7 @@ pulsar.o: $(HACK_SRC)/xlockmoreI.h
 pulsar.o: $(HACK_SRC)/xlockmore.h
 quasicrystal.o: ../../config.h
 quasicrystal.o: $(HACK_SRC)/fps.h
+quasicrystal.o: $(HACK_SRC)/recanim.h
 quasicrystal.o: $(srcdir)/rotator.h
 quasicrystal.o: $(HACK_SRC)/screenhackI.h
 quasicrystal.o: $(UTILS_SRC)/colors.h
@@ -2640,6 +2741,7 @@ queens.o: $(srcdir)/chessmodels.h
 queens.o: ../../config.h
 queens.o: $(HACK_SRC)/fps.h
 queens.o: $(srcdir)/gltrackball.h
+queens.o: $(HACK_SRC)/recanim.h
 queens.o: $(HACK_SRC)/screenhackI.h
 queens.o: $(UTILS_SRC)/colors.h
 queens.o: $(UTILS_SRC)/erase.h
@@ -2653,10 +2755,22 @@ queens.o: $(UTILS_SRC)/yarandom.h
 queens.o: $(HACK_SRC)/xlockmoreI.h
 queens.o: $(HACK_SRC)/xlockmore.h
 quickhull.o: ../../config.h
+quickhull.o: $(HACK_SRC)/fps.h
 quickhull.o: $(srcdir)/quickhull.h
+quickhull.o: $(HACK_SRC)/recanim.h
+quickhull.o: $(HACK_SRC)/screenhackI.h
+quickhull.o: $(UTILS_SRC)/colors.h
+quickhull.o: $(UTILS_SRC)/font-retry.h
+quickhull.o: $(UTILS_SRC)/grabscreen.h
+quickhull.o: $(UTILS_SRC)/hsv.h
+quickhull.o: $(UTILS_SRC)/resources.h
+quickhull.o: $(UTILS_SRC)/usleep.h
+quickhull.o: $(UTILS_SRC)/visual.h
+quickhull.o: $(UTILS_SRC)/yarandom.h
 raverhoop.o: ../../config.h
 raverhoop.o: $(HACK_SRC)/fps.h
 raverhoop.o: $(srcdir)/gltrackball.h
+raverhoop.o: $(HACK_SRC)/recanim.h
 raverhoop.o: $(srcdir)/rotator.h
 raverhoop.o: $(HACK_SRC)/screenhackI.h
 raverhoop.o: $(UTILS_SRC)/colors.h
@@ -2674,6 +2788,7 @@ razzledazzle.o: ../../config.h
 razzledazzle.o: $(HACK_SRC)/fps.h
 razzledazzle.o: $(srcdir)/gllist.h
 razzledazzle.o: $(srcdir)/normals.h
+razzledazzle.o: $(HACK_SRC)/recanim.h
 razzledazzle.o: $(HACK_SRC)/screenhackI.h
 razzledazzle.o: $(UTILS_SRC)/colors.h
 razzledazzle.o: $(UTILS_SRC)/erase.h
@@ -2694,6 +2809,7 @@ romanboy.o: ../../config.h
 romanboy.o: $(srcdir)/curlicue.h
 romanboy.o: $(HACK_SRC)/fps.h
 romanboy.o: $(srcdir)/gltrackball.h
+romanboy.o: $(HACK_SRC)/recanim.h
 romanboy.o: $(HACK_SRC)/screenhackI.h
 romanboy.o: $(UTILS_SRC)/colors.h
 romanboy.o: $(UTILS_SRC)/erase.h
@@ -2712,6 +2828,7 @@ rotator.o: $(UTILS_SRC)/yarandom.h
 rubikblocks.o: ../../config.h
 rubikblocks.o: $(HACK_SRC)/fps.h
 rubikblocks.o: $(srcdir)/gltrackball.h
+rubikblocks.o: $(HACK_SRC)/recanim.h
 rubikblocks.o: $(srcdir)/rotator.h
 rubikblocks.o: $(HACK_SRC)/screenhackI.h
 rubikblocks.o: $(UTILS_SRC)/colors.h
@@ -2728,6 +2845,7 @@ rubikblocks.o: $(HACK_SRC)/xlockmore.h
 rubik.o: ../../config.h
 rubik.o: $(HACK_SRC)/fps.h
 rubik.o: $(srcdir)/gltrackball.h
+rubik.o: $(HACK_SRC)/recanim.h
 rubik.o: $(HACK_SRC)/screenhackI.h
 rubik.o: $(UTILS_SRC)/colors.h
 rubik.o: $(UTILS_SRC)/erase.h
@@ -2759,6 +2877,7 @@ sballs.o: $(HACK_SRC)/fps.h
 sballs.o: $(srcdir)/gltrackball.h
 sballs.o: $(HACK_SRC)/images/gen/sball-bg_png.h
 sballs.o: $(HACK_SRC)/images/gen/sball_png.h
+sballs.o: $(HACK_SRC)/recanim.h
 sballs.o: $(HACK_SRC)/screenhackI.h
 sballs.o: $(UTILS_SRC)/colors.h
 sballs.o: $(UTILS_SRC)/erase.h
@@ -2777,6 +2896,7 @@ seccam.o: $(srcdir)/gllist.h
 shark.o: $(srcdir)/atlantis.h
 shark.o: ../../config.h
 shark.o: $(HACK_SRC)/fps.h
+shark.o: $(HACK_SRC)/recanim.h
 shark.o: $(HACK_SRC)/screenhackI.h
 shark.o: $(UTILS_SRC)/colors.h
 shark.o: $(UTILS_SRC)/font-retry.h
@@ -2791,6 +2911,7 @@ ships.o: $(srcdir)/gllist.h
 sierpinski3d.o: ../../config.h
 sierpinski3d.o: $(HACK_SRC)/fps.h
 sierpinski3d.o: $(srcdir)/gltrackball.h
+sierpinski3d.o: $(HACK_SRC)/recanim.h
 sierpinski3d.o: $(srcdir)/rotator.h
 sierpinski3d.o: $(HACK_SRC)/screenhackI.h
 sierpinski3d.o: $(UTILS_SRC)/colors.h
@@ -2809,6 +2930,7 @@ skytentacles.o: $(HACK_SRC)/fps.h
 skytentacles.o: $(srcdir)/gltrackball.h
 skytentacles.o: $(HACK_SRC)/images/gen/scales_png.h
 skytentacles.o: $(srcdir)/normals.h
+skytentacles.o: $(HACK_SRC)/recanim.h
 skytentacles.o: $(srcdir)/rotator.h
 skytentacles.o: $(HACK_SRC)/screenhackI.h
 skytentacles.o: $(UTILS_SRC)/colors.h
@@ -2825,6 +2947,7 @@ skytentacles.o: $(HACK_SRC)/xlockmoreI.h
 skytentacles.o: $(HACK_SRC)/xlockmore.h
 sonar-icmp.o: ../../config.h
 sonar-icmp.o: $(HACK_SRC)/fps.h
+sonar-icmp.o: $(HACK_SRC)/recanim.h
 sonar-icmp.o: $(HACK_SRC)/screenhackI.h
 sonar-icmp.o: $(srcdir)/sonar.h
 sonar-icmp.o: $(UTILS_SRC)/aligned_malloc.h
@@ -2842,6 +2965,7 @@ sonar-icmp.o: $(UTILS_SRC)/yarandom.h
 sonar.o: ../../config.h
 sonar.o: $(HACK_SRC)/fps.h
 sonar.o: $(srcdir)/gltrackball.h
+sonar.o: $(HACK_SRC)/recanim.h
 sonar.o: $(srcdir)/rotator.h
 sonar.o: $(HACK_SRC)/screenhackI.h
 sonar.o: $(srcdir)/sonar.h
@@ -2861,6 +2985,7 @@ sonar.o: $(HACK_SRC)/xlockmoreI.h
 sonar.o: $(HACK_SRC)/xlockmore.h
 sonar-sim.o: ../../config.h
 sonar-sim.o: $(HACK_SRC)/fps.h
+sonar-sim.o: $(HACK_SRC)/recanim.h
 sonar-sim.o: $(HACK_SRC)/screenhackI.h
 sonar-sim.o: $(srcdir)/sonar.h
 sonar-sim.o: $(UTILS_SRC)/colors.h
@@ -2875,6 +3000,7 @@ spheremonics.o: ../../config.h
 spheremonics.o: $(HACK_SRC)/fps.h
 spheremonics.o: $(srcdir)/gltrackball.h
 spheremonics.o: $(srcdir)/normals.h
+spheremonics.o: $(HACK_SRC)/recanim.h
 spheremonics.o: $(srcdir)/rotator.h
 spheremonics.o: $(HACK_SRC)/screenhackI.h
 spheremonics.o: $(srcdir)/texfont.h
@@ -2895,6 +3021,7 @@ splitflap.o: ../../config.h
 splitflap.o: $(HACK_SRC)/fps.h
 splitflap.o: $(srcdir)/gllist.h
 splitflap.o: $(srcdir)/gltrackball.h
+splitflap.o: $(HACK_SRC)/recanim.h
 splitflap.o: $(srcdir)/rotator.h
 splitflap.o: $(HACK_SRC)/screenhackI.h
 splitflap.o: $(srcdir)/texfont.h
@@ -2918,6 +3045,7 @@ splodesic.o: ../../config.h
 splodesic.o: $(HACK_SRC)/fps.h
 splodesic.o: $(srcdir)/gltrackball.h
 splodesic.o: $(srcdir)/normals.h
+splodesic.o: $(HACK_SRC)/recanim.h
 splodesic.o: $(srcdir)/rotator.h
 splodesic.o: $(HACK_SRC)/screenhackI.h
 splodesic.o: $(UTILS_SRC)/colors.h
@@ -2934,6 +3062,7 @@ splodesic.o: $(HACK_SRC)/xlockmore.h
 sproingies.o: ../../config.h
 sproingies.o: $(HACK_SRC)/fps.h
 sproingies.o: $(srcdir)/gllist.h
+sproingies.o: $(HACK_SRC)/recanim.h
 sproingies.o: $(HACK_SRC)/screenhackI.h
 sproingies.o: $(srcdir)/sproingies.h
 sproingies.o: $(UTILS_SRC)/colors.h
@@ -2948,6 +3077,7 @@ sproingies.o: $(UTILS_SRC)/yarandom.h
 sproingies.o: $(HACK_SRC)/xlockmoreI.h
 sproingiewrap.o: ../../config.h
 sproingiewrap.o: $(HACK_SRC)/fps.h
+sproingiewrap.o: $(HACK_SRC)/recanim.h
 sproingiewrap.o: $(HACK_SRC)/screenhackI.h
 sproingiewrap.o: $(srcdir)/sproingies.h
 sproingiewrap.o: $(UTILS_SRC)/colors.h
@@ -2965,6 +3095,7 @@ stairs.o: ../../config.h
 stairs.o: $(HACK_SRC)/fps.h
 stairs.o: $(srcdir)/gltrackball.h
 stairs.o: $(HACK_SRC)/images/gen/wood_png.h
+stairs.o: $(HACK_SRC)/recanim.h
 stairs.o: $(HACK_SRC)/screenhackI.h
 stairs.o: $(srcdir)/sphere.h
 stairs.o: $(UTILS_SRC)/colors.h
@@ -2983,6 +3114,7 @@ starwars.o: ../../config.h
 starwars.o: $(HACK_SRC)/fps.h
 starwars.o: $(srcdir)/glut_roman.h
 starwars.o: $(srcdir)/glutstroke.h
+starwars.o: $(HACK_SRC)/recanim.h
 starwars.o: $(HACK_SRC)/screenhackI.h
 starwars.o: $(srcdir)/starwars.h
 starwars.o: $(srcdir)/texfont.h
@@ -3007,6 +3139,7 @@ stonerview-move.o: $(UTILS_SRC)/yarandom.h
 stonerview.o: ../../config.h
 stonerview.o: $(HACK_SRC)/fps.h
 stonerview.o: $(srcdir)/gltrackball.h
+stonerview.o: $(HACK_SRC)/recanim.h
 stonerview.o: $(HACK_SRC)/screenhackI.h
 stonerview.o: $(srcdir)/stonerview.h
 stonerview.o: $(srcdir)/stonerview-move.h
@@ -3033,6 +3166,7 @@ stonerview-view.o: $(srcdir)/stonerview-move.h
 stonerview-view.o: $(srcdir)/stonerview-osc.h
 superquadrics.o: ../../config.h
 superquadrics.o: $(HACK_SRC)/fps.h
+superquadrics.o: $(HACK_SRC)/recanim.h
 superquadrics.o: $(HACK_SRC)/screenhackI.h
 superquadrics.o: $(UTILS_SRC)/colors.h
 superquadrics.o: $(UTILS_SRC)/erase.h
@@ -3048,6 +3182,7 @@ superquadrics.o: $(HACK_SRC)/xlockmore.h
 surfaces.o: ../../config.h
 surfaces.o: $(HACK_SRC)/fps.h
 surfaces.o: $(srcdir)/gltrackball.h
+surfaces.o: $(HACK_SRC)/recanim.h
 surfaces.o: $(srcdir)/rotator.h
 surfaces.o: $(HACK_SRC)/screenhackI.h
 surfaces.o: $(UTILS_SRC)/colors.h
@@ -3064,6 +3199,7 @@ surfaces.o: $(HACK_SRC)/xlockmore.h
 swim.o: $(srcdir)/atlantis.h
 swim.o: ../../config.h
 swim.o: $(HACK_SRC)/fps.h
+swim.o: $(HACK_SRC)/recanim.h
 swim.o: $(HACK_SRC)/screenhackI.h
 swim.o: $(UTILS_SRC)/colors.h
 swim.o: $(UTILS_SRC)/erase.h
@@ -3077,6 +3213,7 @@ swim.o: $(UTILS_SRC)/yarandom.h
 swim.o: $(HACK_SRC)/xlockmoreI.h
 tangram.o: ../../config.h
 tangram.o: $(HACK_SRC)/fps.h
+tangram.o: $(HACK_SRC)/recanim.h
 tangram.o: $(HACK_SRC)/screenhackI.h
 tangram.o: $(srcdir)/tangram_shapes.h
 tangram.o: $(srcdir)/texfont.h
@@ -3110,6 +3247,7 @@ timetunnel.o: $(HACK_SRC)/images/gen/timetunnel0_png.h
 timetunnel.o: $(HACK_SRC)/images/gen/timetunnel1_png.h
 timetunnel.o: $(HACK_SRC)/images/gen/timetunnel2_png.h
 timetunnel.o: $(HACK_SRC)/images/gen/tunnelstar_png.h
+timetunnel.o: $(HACK_SRC)/recanim.h
 timetunnel.o: $(srcdir)/rotator.h
 timetunnel.o: $(HACK_SRC)/screenhackI.h
 timetunnel.o: $(UTILS_SRC)/colors.h
@@ -3147,6 +3285,7 @@ toast.o: $(srcdir)/gllist.h
 topblock.o: ../../config.h
 topblock.o: $(HACK_SRC)/fps.h
 topblock.o: $(srcdir)/gltrackball.h
+topblock.o: $(HACK_SRC)/recanim.h
 topblock.o: $(HACK_SRC)/screenhackI.h
 topblock.o: $(srcdir)/sphere.h
 topblock.o: $(srcdir)/topblock.h
@@ -3174,6 +3313,7 @@ tronbit.o: ../../config.h
 tronbit.o: $(HACK_SRC)/fps.h
 tronbit.o: $(srcdir)/gllist.h
 tronbit.o: $(srcdir)/gltrackball.h
+tronbit.o: $(HACK_SRC)/recanim.h
 tronbit.o: $(srcdir)/rotator.h
 tronbit.o: $(HACK_SRC)/screenhackI.h
 tronbit.o: $(srcdir)/sphere.h
@@ -3194,6 +3334,7 @@ tube.o: ../../config.h
 tube.o: $(srcdir)/tube.h
 tunnel_draw.o: ../../config.h
 tunnel_draw.o: $(HACK_SRC)/fps.h
+tunnel_draw.o: $(HACK_SRC)/recanim.h
 tunnel_draw.o: $(HACK_SRC)/screenhackI.h
 tunnel_draw.o: $(srcdir)/tunnel_draw.h
 tunnel_draw.o: $(UTILS_SRC)/colors.h
@@ -3209,6 +3350,7 @@ tunnel_draw.o: $(HACK_SRC)/xlockmoreI.h
 unicrud.o: ../../config.h
 unicrud.o: $(HACK_SRC)/fps.h
 unicrud.o: $(srcdir)/gltrackball.h
+unicrud.o: $(HACK_SRC)/recanim.h
 unicrud.o: $(srcdir)/rotator.h
 unicrud.o: $(HACK_SRC)/screenhackI.h
 unicrud.o: $(srcdir)/texfont.h
@@ -3227,6 +3369,7 @@ unicrud.o: $(HACK_SRC)/xlockmore.h
 unknownpleasures.o: ../../config.h
 unknownpleasures.o: $(HACK_SRC)/fps.h
 unknownpleasures.o: $(srcdir)/gltrackball.h
+unknownpleasures.o: $(HACK_SRC)/recanim.h
 unknownpleasures.o: $(HACK_SRC)/screenhackI.h
 unknownpleasures.o: $(UTILS_SRC)/colors.h
 unknownpleasures.o: $(UTILS_SRC)/erase.h
@@ -3244,6 +3387,7 @@ vigilance.o: $(HACK_SRC)/fps.h
 vigilance.o: $(srcdir)/gllist.h
 vigilance.o: $(srcdir)/gltrackball.h
 vigilance.o: $(srcdir)/normals.h
+vigilance.o: $(HACK_SRC)/recanim.h
 vigilance.o: $(HACK_SRC)/screenhackI.h
 vigilance.o: $(UTILS_SRC)/colors.h
 vigilance.o: $(UTILS_SRC)/erase.h
@@ -3259,6 +3403,7 @@ vigilance.o: $(HACK_SRC)/xlockmoreI.h
 vigilance.o: $(HACK_SRC)/xlockmore.h
 voronoi.o: ../../config.h
 voronoi.o: $(HACK_SRC)/fps.h
+voronoi.o: $(HACK_SRC)/recanim.h
 voronoi.o: $(HACK_SRC)/screenhackI.h
 voronoi.o: $(UTILS_SRC)/colors.h
 voronoi.o: $(UTILS_SRC)/erase.h
@@ -3274,6 +3419,7 @@ voronoi.o: $(HACK_SRC)/xlockmore.h
 whale.o: $(srcdir)/atlantis.h
 whale.o: ../../config.h
 whale.o: $(HACK_SRC)/fps.h
+whale.o: $(HACK_SRC)/recanim.h
 whale.o: $(HACK_SRC)/screenhackI.h
 whale.o: $(UTILS_SRC)/colors.h
 whale.o: $(UTILS_SRC)/font-retry.h
@@ -3289,6 +3435,7 @@ winduprobot.o: $(srcdir)/gllist.h
 winduprobot.o: $(srcdir)/gltrackball.h
 winduprobot.o: $(HACK_SRC)/images/gen/chromesphere_png.h
 winduprobot.o: $(srcdir)/involute.h
+winduprobot.o: $(HACK_SRC)/recanim.h
 winduprobot.o: $(HACK_SRC)/screenhackI.h
 winduprobot.o: $(srcdir)/sphere.h
 winduprobot.o: $(srcdir)/texfont.h
@@ -3307,6 +3454,7 @@ winduprobot.o: $(HACK_SRC)/xlockmoreI.h
 winduprobot.o: $(HACK_SRC)/xlockmore.h
 xlock-gl-utils.o: ../../config.h
 xlock-gl-utils.o: $(HACK_SRC)/fps.h
+xlock-gl-utils.o: $(HACK_SRC)/recanim.h
 xlock-gl-utils.o: $(HACK_SRC)/screenhackI.h
 xlock-gl-utils.o: $(srcdir)/texfont.h
 xlock-gl-utils.o: $(UTILS_SRC)/colors.h
index cf21a94e1cd5d0716001e89ca0fe9aa2a088b138..8e783dbc0d7d242c7af652f1659c240afd3183be 100644 (file)
@@ -14,7 +14,6 @@
                        "*wireframe:    False       \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define free_crumbler 0
 # define release_crumbler 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -130,15 +129,16 @@ render_chunk (ModeInfo *mi, chunk *c)
   qh_mesh_t m;
   GLfloat d;
 
-  c->polygon_count = 0;
-  c->min.x = c->min.y = c->min.z =  999999;
-  c->max.x = c->max.y = c->max.z = -999999;
   if (c->nverts <= 3)
     {
       fprintf (stderr, "%s: nverts %d\n", progname, c->nverts);
       abort();
     }
 
+  c->polygon_count = 0;
+  c->min.x = c->min.y = c->min.z =  999999;
+  c->max.x = c->max.y = c->max.z = -999999;
+
   for (i = 0; i < c->nverts; i++)
     {
       if (c->verts[i].x < c->min.x) c->min.x = c->verts[i].x;
@@ -218,8 +218,9 @@ render_chunk (ModeInfo *mi, chunk *c)
 static void
 free_chunk (chunk *c)
 {
+  if (c->dlist)
+    glDeleteLists (c->dlist, 1);
   free (c->verts);
-  glDeleteLists (c->dlist, 1);
   free (c);
 }
 
@@ -334,15 +335,20 @@ split_chunk (ModeInfo *mi, chunk *c, int nchunks)
        render_chunk
    */
   crumbler_configuration *bp = &bps[MI_SCREEN(mi)];
-  chunk **chunks = (chunk **) calloc (nchunks, sizeof(*chunks));
-  int *keys = (int *) calloc (nchunks, sizeof(*keys));
+  chunk **chunks;
+  int *keys;
   int i, j;
-  chunk *c2;
+  int retries = 0;
+
+ RETRY:
+  chunks = (chunk **) calloc (nchunks, sizeof(*chunks));
+  keys = (int *) calloc (nchunks, sizeof(*keys));
 
   for (i = 0; i < nchunks; i++)
     {
       /* Fill keys with random numbers that are not duplicates. */
       Bool ok = True;
+      chunk *c2 = 0;
       if (nchunks >= c->nverts)
         {
           fprintf (stderr, "%s: nverts %d nchunks %d\n", progname,
@@ -351,21 +357,21 @@ split_chunk (ModeInfo *mi, chunk *c, int nchunks)
         }
       do {
         keys[i] = random() % c->nverts;
+        ok = True;
         for (j = 0; j < i; j++)
           if (keys[i] == keys[j])
             {
               ok = False;
               break;
             }
-        ok = True;
       } while (!ok);
 
       c2 = make_chunk();
       chunks[i] = c2;
       chunks[i]->nverts = 0;
       c2->verts = (qh_vertex_t *) calloc (c->nverts, sizeof(*c2->verts));
-      c2->color = (c->color + (random() % (1 + (bp->ncolors / 3)))
-                   % bp->ncolors);
+      c2->color = (c->color + (random() % (1 + (bp->ncolors / 3))))
+                   % bp->ncolors;
     }
 
   /* Add the verts to the approprate chunks
@@ -375,6 +381,8 @@ split_chunk (ModeInfo *mi, chunk *c, int nchunks)
       qh_vertex_t *v0 = &c->verts[i];
       int target_chunk = -1;
       double target_d2 = 9999999;
+      chunk *c2 = 0;
+
       for (j = 0; j < nchunks; j++)
         {
           qh_vertex_t *v1 = &c->verts[keys[j]];
@@ -392,17 +400,39 @@ split_chunk (ModeInfo *mi, chunk *c, int nchunks)
 
       c2 = chunks[target_chunk];
       c2->verts[c2->nverts++] = *v0;
+      if (c2->nverts > c->nverts) abort();
     }
 
+  free (keys);
+  keys = 0;
+
   for (i = 0; i < nchunks; i++)
     {
-      c2 = chunks[i];
+      chunk *c2 = chunks[i];
+
+      /* It is possible that the keys we have chosen have resulted in one or
+         more cells that have 3 or fewer points in them. If that's the case,
+         re-randomize.
+       */
+      if (c2->nverts <= 3)
+        {
+          for (j = 0; j < nchunks; j++)
+            free_chunk (chunks[j]);
+          free (chunks);
+          chunks = 0;
+          if (retries++ > 100)
+            {
+              fprintf(stderr, "%s: unsplittable\n", progname);
+              abort();
+            }
+          goto RETRY;
+        }
+
       if (i == 0)  /* The one we're gonna keep */
         pad_chunk (c2, c->nverts);
       render_chunk (mi, c2);
     }
 
-  free (keys);
   return chunks;
 }
 
@@ -646,6 +676,14 @@ init_crumbler (ModeInfo *mi)
 # undef R
     }
 
+# ifdef HAVE_MOBILE
+#  ifdef USE_IPHONE
+     density *= 0.5;  /* iPhone 6s runs out of memory at 4500 nverts. */
+#  else
+     density *= 0.3;  /* Android Nexus_5_8.1 emulator runs out earlier. */
+#  endif
+# endif
+
   {
     chunk *c;
     bp->nchunks = 1;
@@ -817,6 +855,21 @@ draw_crumbler (ModeInfo *mi)
   glXSwapBuffers(dpy, window);
 }
 
+
+ENTRYPOINT void
+free_crumbler (ModeInfo *mi)
+{
+  crumbler_configuration *bp = &bps[MI_SCREEN(mi)];
+  int i;
+  free (bp->trackball);
+  free (bp->rot);
+  free (bp->colors);
+  for (i = 0; i < bp->nchunks; i++)
+    free_chunk (bp->chunks[i]);
+  free (bp->chunks);
+}
+
+
 XSCREENSAVER_MODULE ("Crumbler", crumbler)
 
 #endif /* USE_GL */
index 4ef7fd1b4c5eb24671be4857ab044eb8377c049f..cf973c9ae6dd69e3b548351981bc81111a48c66f 100644 (file)
@@ -1,4 +1,4 @@
-/* cubestorm, Copyright (c) 2003-2014 Jamie Zawinski <jwz@jwz.org>
+/* cubestorm, Copyright (c) 2003-2018 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 #define DEF_SPEED       "1.0"
 #define DEF_THICKNESS   "0.06"
 #define DEF_COUNT       "4"
-#define DEF_DBUF        "False"
+#define DEF_LENGTH      "200"
+
+typedef struct {
+  GLfloat px, py, pz;
+  GLfloat rx, ry, rz;
+  int ccolor;
+} histcube;
 
 typedef struct {
   rotator *rot;
@@ -55,6 +61,9 @@ typedef struct {
 
   subcube *subcubes;
 
+  int hist_size, hist_count;
+  histcube *hist;
+
 } cube_configuration;
 
 static cube_configuration *bps = NULL;
@@ -63,7 +72,7 @@ static Bool do_spin;
 static Bool do_wander;
 static GLfloat speed;
 static GLfloat thickness;
-static Bool dbuf_p;
+static int max_length;
 
 static XrmOptionDescRec opts[] = {
   { "-spin",   ".spin",   XrmoptionNoArg, "True" },
@@ -74,14 +83,15 @@ static XrmOptionDescRec opts[] = {
   { "-db",     ".doubleBuffer", XrmoptionNoArg, "True"},
   { "+db",     ".doubleBuffer", XrmoptionNoArg, "False"},
   { "-thickness", ".thickness", XrmoptionSepArg, 0 },
+  { "-length", ".length", XrmoptionSepArg, 0 },
 };
 
 static argtype vars[] = {
   {&do_spin,   "spin",   "Spin",   DEF_SPIN,   t_Bool},
   {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool},
   {&speed,     "speed",  "Speed",  DEF_SPEED,  t_Float},
-  {&thickness, "thickness", "Thickness",  DEF_THICKNESS,  t_Float},
-  {&dbuf_p, "doubleBuffer", "DoubleBuffer", DEF_DBUF, t_Bool},
+  {&thickness,  "thickness", "Thickness", DEF_THICKNESS, t_Float},
+  {&max_length, "length",    "Length",    DEF_LENGTH,    t_Int},
 };
 
 ENTRYPOINT ModeSpecOpt cube_opts = {countof(opts), opts, countof(vars), vars, NULL};
@@ -235,10 +245,6 @@ init_cube (ModeInfo *mi)
 
   MI_INIT (mi, bps);
 
-# ifdef HAVE_JWZGLES
-  dbuf_p = True;
-# endif
-
   bp = &bps[MI_SCREEN(mi)];
 
   bp->glx_context = init_GL(mi);
@@ -247,6 +253,11 @@ init_cube (ModeInfo *mi)
 
   bp->trackball = gltrackball_init (True);
   bp->subcubes = (subcube *) calloc (MI_COUNT(mi), sizeof(subcube));
+
+  bp->hist_count = 0;
+  bp->hist_size = 100;
+  bp->hist = (histcube *) malloc (bp->hist_size * sizeof(*bp->hist));
+
   for (i = 0; i < MI_COUNT(mi); i++)
     {
       double wander_speed, spin_speed, spin_accel;
@@ -304,6 +315,70 @@ init_cube (ModeInfo *mi)
 }
 
 
+/* Originally, this program achieved the "accumulating cubes" effect by
+   simply not clearing the depth or color buffers between frames.  That
+   doesn't work on modern systems, particularly mobile: you can no longer
+   rely on your buffers being unmolested once you have yielded.  So now we
+   must save and re-render every polygon.  Noof has the same problem and
+   solves it by taking a screenshot of the frame buffer into a texture, but
+   cubestorm needs to restore the depth buffer as well as the color buffer.
+ */
+static void
+push_hist (ModeInfo *mi)
+{
+  cube_configuration *bp = &bps[MI_SCREEN(mi)];
+  double px, py, pz;
+  double rx = 0, ry = 0, rz = 0;
+  int i;
+
+  if (bp->hist_count > max_length &&
+      bp->hist_count > MI_COUNT(mi) &&
+      !bp->button_down_p)
+    {
+      /* Drop history off of the end. */
+      memmove (bp->hist,
+               bp->hist + MI_COUNT(mi), 
+               (bp->hist_count - MI_COUNT(mi)) * sizeof(*bp->hist));
+      bp->hist_count -= MI_COUNT(mi);
+    }
+
+  if (bp->hist_count + MI_COUNT(mi) >= bp->hist_size)
+    {
+      bp->hist_size = bp->hist_count + MI_COUNT(mi) + 100;
+      bp->hist = (histcube *)
+        realloc (bp->hist, bp->hist_size * sizeof(*bp->hist));
+    }
+  
+  get_position (bp->subcubes[0].rot, &px, &py, &pz, !bp->button_down_p);
+
+  for (i = 0; i < MI_COUNT(mi); i++)
+    {
+      subcube  *sc = &bp->subcubes[i];
+      histcube *hc = &bp->hist[bp->hist_count];
+      double rx2, ry2, rz2;
+
+      get_rotation (sc->rot, &rx2, &ry2, &rz2, !bp->button_down_p);
+
+      if (i == 0)  /* N+1 cubes rotate relative to cube 0 */
+        rx = rx2, ry = ry2, rz = rz2;
+      else
+        rx2 += rx, ry2 += ry, rz2 += rz;
+
+      hc->px = px;
+      hc->py = py;
+      hc->pz = pz;
+      hc->rx = rx2;
+      hc->ry = ry2;
+      hc->rz = rz2;
+      hc->ccolor = sc->ccolor;
+      sc->ccolor++;
+      if (sc->ccolor >= bp->ncolors)
+        sc->ccolor = 0;
+      bp->hist_count++;
+    }
+}
+
+
 ENTRYPOINT void
 draw_cube (ModeInfo *mi)
 {
@@ -312,14 +387,12 @@ draw_cube (ModeInfo *mi)
   Window window = MI_WINDOW(mi);
   int wire = MI_IS_WIREFRAME(mi);
   int i;
-  double x, y, z;
 
   if (!bp->glx_context)
     return;
 
-  glDrawBuffer(dbuf_p ? GL_BACK : GL_FRONT);
-
   glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   glShadeModel(GL_SMOOTH);
 
@@ -329,7 +402,7 @@ draw_cube (ModeInfo *mi)
 
   if (bp->clear_p)   /* we're in "no vapor trails" mode */
     {
-      glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
+      bp->hist_count = 0;
       if (! (random() % (int) (25 / speed)))
         bp->clear_p = False;
     }
@@ -342,47 +415,33 @@ draw_cube (ModeInfo *mi)
         }
     }
 
-  glPushMatrix ();
-
-  glScalef(1.1, 1.1, 1.1);
-
+  push_hist (mi);
   mi->polygon_count = 0;
-
-  get_position (bp->subcubes[0].rot, &x, &y, &z, !bp->button_down_p);
-  glTranslatef((x - 0.5) * 15,
-               (y - 0.5) * 15,
-               (z - 0.5) * 30);
-  gltrackball_rotate (bp->trackball);
-
-  glScalef (4.0, 4.0, 4.0);
-
-  for (i = 0; i < MI_COUNT(mi); i++)
+  for (i = 0; i < bp->hist_count; i++)
     {
       GLfloat bcolor[4] = {0.0, 0.0, 0.0, 1.0};
       GLfloat bspec[4]  = {1.0, 1.0, 1.0, 1.0};
       GLfloat bshiny    = 128.0;
 
+      histcube *hc = &bp->hist[i];
+
       glPushMatrix();
+      glScalef (1.1, 1.1, 1.1);
 
-      if (i != 0)  /* N+1 cubes rotate relative to cube 0 */
-        {
-          get_rotation (bp->subcubes[0].rot, &x, &y, &z, False);
-          glRotatef (x * 360, 1.0, 0.0, 0.0);
-          glRotatef (y * 360, 0.0, 1.0, 0.0);
-          glRotatef (z * 360, 0.0, 0.0, 1.0);
-        }
+      glTranslatef((hc->px - 0.5) * 15,
+                   (hc->py - 0.5) * 15,
+                   (hc->pz - 0.5) * 30);
+      gltrackball_rotate (bp->trackball);
 
-      get_rotation (bp->subcubes[i].rot, &x, &y, &z, !bp->button_down_p);
-      glRotatef (x * 360, 1.0, 0.0, 0.0);
-      glRotatef (y * 360, 0.0, 1.0, 0.0);
-      glRotatef (z * 360, 0.0, 0.0, 1.0);
+      glScalef (4.0, 4.0, 4.0);
 
-      bcolor[0] = bp->colors[bp->subcubes[i].ccolor].red   / 65536.0;
-      bcolor[1] = bp->colors[bp->subcubes[i].ccolor].green / 65536.0;
-      bcolor[2] = bp->colors[bp->subcubes[i].ccolor].blue  / 65536.0;
-      bp->subcubes[i].ccolor++;
-      if (bp->subcubes[i].ccolor >= bp->ncolors)
-        bp->subcubes[i].ccolor = 0;
+      glRotatef (hc->rx * 360, 1.0, 0.0, 0.0);
+      glRotatef (hc->ry * 360, 0.0, 1.0, 0.0);
+      glRotatef (hc->rz * 360, 0.0, 0.0, 1.0);
+
+      bcolor[0] = bp->colors[hc->ccolor].red   / 65536.0;
+      bcolor[1] = bp->colors[hc->ccolor].green / 65536.0;
+      bcolor[2] = bp->colors[hc->ccolor].blue  / 65536.0;
 
       if (wire)
         glColor3f (bcolor[0], bcolor[1], bcolor[2]);
@@ -399,13 +458,10 @@ draw_cube (ModeInfo *mi)
       glPopMatrix();
     }
 
-  glPopMatrix ();
-
   if (mi->fps_p) do_fps (mi);
   glFinish();
 
-  if (dbuf_p)
-    glXSwapBuffers(dpy, window);
+  glXSwapBuffers(dpy, window);
 }
 
 XSCREENSAVER_MODULE_2 ("CubeStorm", cubestorm, cube)
index 36246176aac7a25f695db27a18559487da933790..2b24f8311c74b8060377bdab84e6ac8b49f76998 100644 (file)
@@ -1,4 +1,4 @@
-/* DNA Logo, Copyright (c) 2001-2017 Jamie Zawinski <jwz@jwz.org>
+/* DNA Logo, Copyright (c) 2001-2018 Jamie Zawinski <jwz@jwz.org>
  *
  *      DNA Lounge
  *
                        "*wallFacets:       360     \n" \
                        "*barFacets:        90      \n" \
                        "*clockwise:        False   \n" \
-                       "*turns:            0.69    \n" \
-                       "*turnSpacing:      2.2     \n" \
-                       "*barSpacing:       0.2   \n" \
-                       "*wallHeight:       0.45    \n" \
+                       "*turns:            0.72    \n" \
+                       "*turnSpacing:      2.3     \n" \
+                       "*barSpacing:       0.268   \n" \
+                       "*wallHeight:       0.42    \n" \
                        "*wallThickness:    0.12    \n" \
                        "*barThickness:     0.058   \n" \
                        "*wallTaper:        0.95    \n" \
-                       "*gasketSize:       1.88    \n" \
+                       "*gasketSize:       2.0     \n" \
                        "*gasketDepth:      0.15    \n" \
                        "*gasketThickness:  0.4     \n" \
-                       "*frameSize:        1.20    \n" \
+                       "*frameSize:        1.28    \n" \
                        "*frameDepth:       0.01    \n" \
                        "*frameThickness:   0.03    \n" \
                        "*triangleSize:     0.045   \n" \
@@ -167,6 +167,11 @@ typedef struct {
   texture_font_data *font;
 # endif
 
+# ifdef DEBUG
+  GLfloat persp_off, pos_off;
+  texture_font_data *label_font;
+# endif
+
   GLfloat speed;
   glyph_mode mode;
   glyph_mode anim_state;
@@ -560,7 +565,7 @@ make_helix (logo_configuration *dc, int facetted, int wire)
   th  = 0;
   x1  = 1;
   y1  = 0;
-  x1b = 1 - dc->wall_thickness;
+  x1b = 1;
   y1b = 0;
 
   z1 = -(dc->turn_spacing * dc->turns / 2);
@@ -591,13 +596,13 @@ make_helix (logo_configuration *dc, int facetted, int wire)
 
   while (th + th_inc <= max_th)
     {
+      GLfloat thick = dc->wall_thickness;
+
       th += th_inc;
 
       x2 = cos (th);
       y2 = sin (th);
       z2 = z1 + z_inc;
-      x2b = x2 * (1 - dc->wall_thickness);
-      y2b = y2 * (1 - dc->wall_thickness);
 
       h2 = h1;
       h2off = h1off;
@@ -613,6 +618,11 @@ make_helix (logo_configuration *dc, int facetted, int wire)
                 h2off = h2 - dc->wall_height/2;
               else
                 h2off = dc->wall_height/2 - h2;
+
+              if (th + th_inc <= 0)
+                thick = 0;
+              else
+              thick *= cos (M_PI / 2 * (1 - (th / dc->wall_taper)));
             }
           else if (th >= max_th - dc->wall_taper)
             {
@@ -626,9 +636,17 @@ make_helix (logo_configuration *dc, int facetted, int wire)
                 h2off = dc->wall_height/2 - h2;
               else
                 h2off = h2 - dc->wall_height/2;
+
+              if (th + th_inc > max_th)
+                thick = 0;
+              else
+                thick *= cos(M_PI / 2 * (1 - ((max_th - th)/dc->wall_taper)));
             }
         }
 
+      x2b = x2 * (1 - thick);
+      y2b = y2 * (1 - thick);
+
       /* outer face
        */
       glFrontFace(GL_CW);
@@ -742,6 +760,11 @@ make_ladder (logo_configuration *dc, int facetted, int wire)
   th = (max_th * pad_ratio/2);
   z  = -(max_z / 2) + (max_z * pad_ratio/2);
 
+  /* ##### WHYYYYYY */
+  /* The image is not reflected across line y = -x and I don't know why. */
+  th += M_PI * -0.035;
+  z -= 0.08;
+
   if (!dc->clockwise)
     z = -z, z_inc = -z_inc;
 
@@ -2730,25 +2753,33 @@ draw_codeword_path (ModeInfo *mi)
 
 #endif /* CW */
 
-\f
-/* Window management, etc
- */
+
 ENTRYPOINT void
 reshape_logo (ModeInfo *mi, int width, int height)
 {
+# ifdef DEBUG
+  logo_configuration *dc = &dcs[MI_SCREEN(mi)];
+# endif
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  GLfloat persp = 64;  /* 30 */
+  GLfloat pos   = 13;  /* 30 */
+
+# ifdef DEBUG
+  persp += dc->persp_off;
+  pos += dc->pos_off;
+# endif
 
   glViewport (0, 0, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
-  gluPerspective (30.0, 1/h, 1.0, 100.0);
+  gluPerspective (persp, 1/h, 1, 100);
 
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
-  gluLookAt( 0.0, 0.0, 30.0,
-             0.0, 0.0, 0.0,
-             0.0, 1.0, 0.0);
+  gluLookAt( 0, 0, pos,
+             0, 0, 0,
+             0, 1, 0);
 
 # ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
   {
@@ -2886,6 +2917,10 @@ init_logo (ModeInfo *mi)
     dc->font = load_texture_font (MI_DISPLAY(mi), "cwFont");
 # endif
 
+# ifdef DEBUG
+    dc->label_font = load_texture_font (MI_DISPLAY(mi), "fpsFont");
+# endif
+
   {
     XColor xcolor;
 
@@ -3127,6 +3162,22 @@ logo_handle_event (ModeInfo *mi, XEvent *event)
       KeySym keysym;
       char c = 0;
       XLookupString (&event->xkey, &c, 1, &keysym, 0);
+
+# ifdef DEBUG
+      {
+        GLfloat step = 0.1;
+        if      (c == 'a') dc->persp_off += step;
+        else if (c == 'z') dc->persp_off -= step;
+        else if (c == 's') dc->pos_off   += step;
+        else if (c == 'x') dc->pos_off   -= step;
+        else return False;
+
+        /* dc->pos_off = -dc->persp_off; */
+        reshape_logo (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+        return True;
+      }
+# endif
+
       if (c == ' ' || c == '\t')
         {
           switch (dc->anim_state) {
@@ -3247,6 +3298,7 @@ draw_logo (ModeInfo *mi)
                         (random() % 200) +
                         (random() % 200));
       
+# ifndef DEBUG
   tick_spinner (mi, &dc->gasket_spinnerx);
   tick_spinner (mi, &dc->gasket_spinnery);
   tick_spinner (mi, &dc->gasket_spinnerz);
@@ -3257,6 +3309,7 @@ draw_logo (ModeInfo *mi)
   tick_spinner (mi, &dc->scene_spinnery);
   tick_spinner (mi, &dc->frame_spinner);
   link_spinners (mi, &dc->scene_spinnerx, &dc->scene_spinnery);
+# endif /* DEBUG */
 
   switch (dc->anim_state)
     {
@@ -3364,6 +3417,11 @@ draw_logo (ModeInfo *mi)
       break;
     }
 
+# ifdef DEBUG
+  dc->anim_state = HELIX;
+  dc->wire_overlay = 0;
+# endif
+
   pizza_p = (dc->anim_state == PIZZA ||
              dc->anim_state == PIZZA_IN ||
              dc->anim_state == PIZZA_OUT);
@@ -3559,6 +3617,17 @@ draw_logo (ModeInfo *mi)
   if (dc->wire_overlay > 0)
     dc->wire_overlay--;
 
+# ifdef DEBUG
+  {
+    char s[1024];
+    sprintf (s, "a/z, s/x; per = %0.2f pos = %0.2f",
+             dc->persp_off, dc->pos_off);
+    glColor3f (1,1,1);
+    print_texture_label (dpy, dc->label_font, MI_WIDTH(mi), MI_HEIGHT(mi),
+                         1, s);
+  }
+# endif
+
   if (mi->fps_p) do_fps (mi);
   glFinish();
 
diff --git a/hacks/glx/dymaxionmap-coords.c b/hacks/glx/dymaxionmap-coords.c
new file mode 100644 (file)
index 0000000..1eb064d
--- /dev/null
@@ -0,0 +1,685 @@
+/* http://www.rwgrayprojects.com/rbfnotes/maps/graymap6.html
+   Slightly modified by jwz for xscreensaver
+ */
+
+
+/**************************************************************/
+/*                                                            */
+/* This C program is copyrighted by  Robert W. Gray and may   */
+/* not be used in ANY for-profit project without written      */
+/* permission.                                                */
+/*                                                            */
+/**************************************************************/
+
+/* (Note: Robert Gray has kindly given me his permission to include
+   this code in xscreensaver. -- Jamie Zawinski, Apr 2018.)
+ */
+
+
+/**************************************************************/
+/*                                                            */
+/* This C program contains the Dymaxion map coordinate        */
+/* transformation routines for converting longitude/latitude  */
+/* points to (X, Y) points on the Dymaxion map.               */
+/*                                                            */
+/* This version uses the exact transformation equations.      */
+/**************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "dymaxionmap-coords.h"
+
+/************************************************************************/
+/* NOTE: in C, array indexing starts with element zero (0).  I choose   */
+/*       to start my array indexing with elemennt one (1) so all arrays */
+/*       are defined one element longer than they need to be.           */
+/************************************************************************/
+
+/************************************************************************/
+/* global variables accessable to all procedures                        */
+/************************************************************************/
+
+static double v_x[13], v_y[13], v_z[13];
+static double center_x[21], center_y[21], center_z[21];
+static double garc, gt, gdve, gel;
+
+/********************************************/
+/*      function pre-definitions            */
+/********************************************/
+
+static double radians(double degrees);
+static void rotate(double angle, double *x, double *y);
+static void r2(int axis, double alpha, double *x, double *y, double *z);
+static void init_stuff(void);
+/*static void convert_s_t_p(double lng, double lat, double *x, double *y);*/
+static void s_to_c(double theta, double phi, double *x, double *y, double *z);
+static void c_to_s(double *theta, double *phi, double x, double y, double z);
+static void s_tri_info(double x, double y, double z,
+                int *tri, int *lcd);
+static void dymax_point(int tri, int lcd,
+                double x, double y, double z,
+                double *dx, double *dy);
+static void conv_ll_t_sc(double lng, double lat, double *theta, double *phi);
+
+
+/****************************************/
+/*      function definitions            */
+/****************************************/
+
+
+void
+/* convert_s_t_p */
+dymaxion_convert
+(double lng, double lat, double *x, double *y)
+{
+  /***********************************************************/
+  /* This is the main control procedure.                     */
+  /***********************************************************/
+
+  double theta, phi;
+  double hx, hy, hz;
+  double px = 0, py = 0;
+  int tri, hlcd;
+
+  static int initted = 0;
+  if (! initted) {
+    init_stuff();
+    initted = 1;
+  }
+
+  /* Convert the given (long.,lat.) coordinate into spherical */
+  /* polar coordinates (r, theta, phi) with radius=1.         */
+  /* Angles are given in radians, NOT degrees.                */
+
+  conv_ll_t_sc(lng, lat, &theta, &phi);
+
+  /* convert the spherical polar coordinates into cartesian   */
+  /* (x, y, z) coordinates.                                   */
+
+  s_to_c(theta, phi, &hx, &hy, &hz);
+
+  /* determine which of the 20 spherical icosahedron triangles */
+  /* the given point is in and the LCD triangle.               */
+
+  s_tri_info(hx, hy, hz, &tri, &hlcd);
+
+  /* Determine the corresponding Fuller map plane (x, y) point */
+
+  dymax_point(tri, hlcd, hx, hy, hz, &px, &py);
+  *x = px;
+  *y = py;
+
+} /* end convert_s_t_p */
+
+
+static void conv_ll_t_sc(double lng, double lat, double *theta, double *phi)
+{
+  /* convert (long., lat.) point into spherical polar coordinates */
+  /* with r=radius=1.  Angles are given in radians.               */
+
+  double h_theta, h_phi;
+
+  h_theta = 90.0 - lat ;
+  h_phi = lng;
+  if (lng < 0.0) {h_phi = lng + 360.0;}
+  *theta = radians(h_theta);
+  *phi = radians(h_phi);
+
+} /* end conv_ll_t_sc */
+
+
+static double radians(double degrees)
+{
+    /* convert angles in degrees into angles in radians */
+
+    double pi2, c1;
+
+    pi2 = 2 * 3.14159265358979323846;
+    c1 = pi2 / 360;
+    return(c1 * degrees);
+
+} /* end of radians function */
+
+
+static void init_stuff()
+{
+   /* initializes the global variables which includes the */
+   /* vertix coordinates and mid-face coordinates.        */
+
+   double /* i, */ hold_x, hold_y, hold_z, magn;
+   /* double theta, phi; */
+
+   /* Cartesian coordinates for the 12 vertices of icosahedron */
+
+   v_x[1] =    0.420152426708710003;
+   v_y[1] =    0.078145249402782959;
+   v_z[1] =    0.904082550615019298;
+   v_x[2] =    0.995009439436241649 ;
+   v_y[2] =   -0.091347795276427931 ;
+   v_z[2] =    0.040147175877166645 ;
+   v_x[3] =    0.518836730327364437 ;
+   v_y[3] =    0.835420380378235850 ;
+   v_z[3] =    0.181331837557262454 ;
+   v_x[4] =   -0.414682225320335218 ;
+   v_y[4] =    0.655962405434800777 ;
+   v_z[4] =    0.630675807891475371 ;
+   v_x[5] =   -0.515455959944041808 ;
+   v_y[5] =   -0.381716898287133011 ;
+   v_z[5] =    0.767200992517747538 ;
+   v_x[6] =    0.355781402532944713 ;
+   v_y[6] =   -0.843580002466178147 ;
+   v_z[6] =    0.402234226602925571 ;
+   v_x[7] =    0.414682225320335218 ;
+   v_y[7] =   -0.655962405434800777 ;
+   v_z[7] =   -0.630675807891475371 ;
+   v_x[8] =    0.515455959944041808 ;
+   v_y[8] =    0.381716898287133011 ;
+   v_z[8] =   -0.767200992517747538 ;
+   v_x[9] =   -0.355781402532944713 ;
+   v_y[9] =    0.843580002466178147 ;
+   v_z[9] =   -0.402234226602925571 ;
+   v_x[10] =   -0.995009439436241649 ;
+   v_y[10] =    0.091347795276427931 ;
+   v_z[10] =   -0.040147175877166645 ;
+   v_x[11] =   -0.518836730327364437  ;
+   v_y[11] =   -0.835420380378235850  ;
+   v_z[11] =   -0.181331837557262454  ;
+   v_x[12] =   -0.420152426708710003 ;
+   v_y[12] =   -0.078145249402782959 ;
+   v_z[12] =   -0.904082550615019298 ;
+
+   /* now calculate mid face coordinates             */
+
+   hold_x = (v_x[1] + v_x[2] + v_x[3]) / 3.0 ;
+   hold_y = (v_y[1] + v_y[2] + v_y[3]) / 3.0 ;
+   hold_z = (v_z[1] + v_z[2] + v_z[3]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[1] = hold_x / magn;
+   center_y[1] = hold_y / magn;
+   center_z[1] = hold_z / magn;
+
+   hold_x = (v_x[1] + v_x[3] + v_x[4]) / 3.0 ;
+   hold_y = (v_y[1] + v_y[3] + v_y[4]) / 3.0 ;
+   hold_z = (v_z[1] + v_z[3] + v_z[4]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[2] = hold_x / magn;
+   center_y[2] = hold_y / magn;
+   center_z[2] = hold_z / magn;
+
+   hold_x = (v_x[1] + v_x[4] + v_x[5]) / 3.0 ;
+   hold_y = (v_y[1] + v_y[4] + v_y[5]) / 3.0 ;
+   hold_z = (v_z[1] + v_z[4] + v_z[5]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[3] = hold_x / magn;
+   center_y[3] = hold_y / magn;
+   center_z[3] = hold_z / magn;
+
+   hold_x = (v_x[1] + v_x[5] + v_x[6]) / 3.0 ;
+   hold_y = (v_y[1] + v_y[5] + v_y[6]) / 3.0 ;
+   hold_z = (v_z[1] + v_z[5] + v_z[6]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[4] = hold_x / magn;
+   center_y[4] = hold_y / magn;
+   center_z[4] = hold_z / magn;
+
+   hold_x = (v_x[1] + v_x[2] + v_x[6]) / 3.0 ;
+   hold_y = (v_y[1] + v_y[2] + v_y[6]) / 3.0 ;
+   hold_z = (v_z[1] + v_z[2] + v_z[6]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[5] = hold_x / magn;
+   center_y[5] = hold_y / magn;
+   center_z[5] = hold_z / magn;
+
+   hold_x = (v_x[2] + v_x[3] + v_x[8]) / 3.0 ;
+   hold_y = (v_y[2] + v_y[3] + v_y[8]) / 3.0 ;
+   hold_z = (v_z[2] + v_z[3] + v_z[8]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[6] = hold_x / magn;
+   center_y[6] = hold_y / magn;
+   center_z[6] = hold_z / magn;
+
+   hold_x = (v_x[8] + v_x[3] + v_x[9]) / 3.0 ;
+   hold_y = (v_y[8] + v_y[3] + v_y[9]) / 3.0 ;
+   hold_z = (v_z[8] + v_z[3] + v_z[9]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[7] = hold_x / magn;
+   center_y[7] = hold_y / magn;
+   center_z[7] = hold_z / magn;
+
+   hold_x = (v_x[9] + v_x[3] + v_x[4]) / 3.0 ;
+   hold_y = (v_y[9] + v_y[3] + v_y[4]) / 3.0 ;
+   hold_z = (v_z[9] + v_z[3] + v_z[4]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[8] = hold_x / magn;
+   center_y[8] = hold_y / magn;
+   center_z[8] = hold_z / magn;
+
+   hold_x = (v_x[10] + v_x[9] + v_x[4]) / 3.0 ;
+   hold_y = (v_y[10] + v_y[9] + v_y[4]) / 3.0 ;
+   hold_z = (v_z[10] + v_z[9] + v_z[4]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[9] = hold_x / magn;
+   center_y[9] = hold_y / magn;
+   center_z[9] = hold_z / magn;
+
+   hold_x = (v_x[5] + v_x[10] + v_x[4]) / 3.0 ;
+   hold_y = (v_y[5] + v_y[10] + v_y[4]) / 3.0 ;
+   hold_z = (v_z[5] + v_z[10] + v_z[4]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[10] = hold_x / magn;
+   center_y[10] = hold_y / magn;
+   center_z[10] = hold_z / magn;
+
+   hold_x = (v_x[5] + v_x[11] + v_x[10]) / 3.0 ;
+   hold_y = (v_y[5] + v_y[11] + v_y[10]) / 3.0 ;
+   hold_z = (v_z[5] + v_z[11] + v_z[10]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[11] = hold_x / magn;
+   center_y[11] = hold_y / magn;
+   center_z[11] = hold_z / magn;
+
+   hold_x = (v_x[5] + v_x[6] + v_x[11]) / 3.0 ;
+   hold_y = (v_y[5] + v_y[6] + v_y[11]) / 3.0 ;
+   hold_z = (v_z[5] + v_z[6] + v_z[11]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[12] = hold_x / magn;
+   center_y[12] = hold_y / magn;
+   center_z[12] = hold_z / magn;
+
+   hold_x = (v_x[11] + v_x[6] + v_x[7]) / 3.0 ;
+   hold_y = (v_y[11] + v_y[6] + v_y[7]) / 3.0 ;
+   hold_z = (v_z[11] + v_z[6] + v_z[7]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[13] = hold_x / magn;
+   center_y[13] = hold_y / magn;
+   center_z[13] = hold_z / magn;
+
+   hold_x = (v_x[7] + v_x[6] + v_x[2]) / 3.0 ;
+   hold_y = (v_y[7] + v_y[6] + v_y[2]) / 3.0 ;
+   hold_z = (v_z[7] + v_z[6] + v_z[2]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[14] = hold_x / magn;
+   center_y[14] = hold_y / magn;
+   center_z[14] = hold_z / magn;
+
+   hold_x = (v_x[8] + v_x[7] + v_x[2]) / 3.0 ;
+   hold_y = (v_y[8] + v_y[7] + v_y[2]) / 3.0 ;
+   hold_z = (v_z[8] + v_z[7] + v_z[2]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[15] = hold_x / magn;
+   center_y[15] = hold_y / magn;
+   center_z[15] = hold_z / magn;
+
+   hold_x = (v_x[12] + v_x[9] + v_x[8]) / 3.0 ;
+   hold_y = (v_y[12] + v_y[9] + v_y[8]) / 3.0 ;
+   hold_z = (v_z[12] + v_z[9] + v_z[8]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[16] = hold_x / magn;
+   center_y[16] = hold_y / magn;
+   center_z[16] = hold_z / magn;
+
+   hold_x = (v_x[12] + v_x[9] + v_x[10]) / 3.0 ;
+   hold_y = (v_y[12] + v_y[9] + v_y[10]) / 3.0 ;
+   hold_z = (v_z[12] + v_z[9] + v_z[10]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[17] = hold_x / magn;
+   center_y[17] = hold_y / magn;
+   center_z[17] = hold_z / magn;
+
+   hold_x = (v_x[12] + v_x[11] + v_x[10]) / 3.0 ;
+   hold_y = (v_y[12] + v_y[11] + v_y[10]) / 3.0 ;
+   hold_z = (v_z[12] + v_z[11] + v_z[10]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[18] = hold_x / magn;
+   center_y[18] = hold_y / magn;
+   center_z[18] = hold_z / magn;
+
+   hold_x = (v_x[12] + v_x[11] + v_x[7]) / 3.0 ;
+   hold_y = (v_y[12] + v_y[11] + v_y[7]) / 3.0 ;
+   hold_z = (v_z[12] + v_z[11] + v_z[7]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[19] = hold_x / magn;
+   center_y[19] = hold_y / magn;
+   center_z[19] = hold_z / magn;
+
+   hold_x = (v_x[12] + v_x[8] + v_x[7]) / 3.0 ;
+   hold_y = (v_y[12] + v_y[8] + v_y[7]) / 3.0 ;
+   hold_z = (v_z[12] + v_z[8] + v_z[7]) / 3.0 ;
+   magn = sqrt(hold_x * hold_x + hold_y * hold_y + hold_z * hold_z);
+   center_x[20] = hold_x / magn;
+   center_y[20] = hold_y / magn;
+   center_z[20] = hold_z / magn;
+
+   garc = 2.0 * asin( sqrt( 5 - sqrt(5)) / sqrt(10) );
+   gt = garc / 2.0;
+
+   gdve = sqrt( 3 + sqrt(5) ) / sqrt( 5 + sqrt(5) );
+   gel = sqrt(8) / sqrt(5 + sqrt(5));
+
+} /* end of int_stuff procedure */
+
+
+static void s_to_c(double theta, double phi, double *x, double *y, double *z)
+{
+    /* Covert spherical polar coordinates to cartesian coordinates. */
+    /* The angles are given in radians.                             */
+
+    *x = sin(theta) * cos(phi);
+    *y = sin(theta) * sin(phi);
+    *z = cos(theta);
+
+ } /* end s_to_c */
+
+
+static void c_to_s(double *lng, double *lat, double x, double y, double z)
+   {
+    /* convert cartesian coordinates into spherical polar coordinates. */
+    /* The angles are given in radians.                                */
+
+    double a;
+
+    if (x>0.0 && y>0.0){a = radians(0.0);}
+    if (x<0.0 && y>0.0){a = radians(180.0);}
+    if (x<0.0 && y<0.0){a = radians(180.0);}
+    if (x>0.0 && y<0.0){a = radians(360.0);}
+    *lat = acos(z);
+    if (x==0.0 && y>0.0){*lng = radians(90.0);}
+    if (x==0.0 && y<0.0){*lng = radians(270.0);}
+    if (x>0.0 && y==0.0){*lng = radians(0.0);}
+    if (x<0.0 && y==0.0){*lng = radians(180.0);}
+    if (x!=0.0 && y!=0.0){*lng = atan(y/x) + a;}
+
+} /* end c_to_s */
+
+
+void s_tri_info(double x, double y, double z,
+                int *tri, int *lcd)
+{
+  /* Determine which triangle and LCD triangle the point is in. */
+
+  double  h_dist1, h_dist2, h_dist3, h1, h2, h3;
+  int i, h_tri, h_lcd ;
+  int v1 = 0, v2 = 0, v3 = 0;
+
+  h_tri = 0;
+  h_dist1 = 9999.0;
+
+  /* Which triangle face center is the closest to the given point */
+  /* is the triangle in which the given point is in.              */
+
+  for (i = 1; i <=20; i = i + 1)
+   {
+     h1 = center_x[i] - x;
+     h2 = center_y[i] - y;
+     h3 = center_z[i] - z;
+     h_dist2 = sqrt(h1 * h1 + h2 * h2 + h3 * h3);
+     if (h_dist2 < h_dist1)
+      {
+        h_tri = i;
+        h_dist1 = h_dist2;
+      } /* end the if statement */
+   }  /* end the for statement */
+
+   *tri = h_tri;
+
+   /* Now the LCD triangle is determined. */
+
+   switch (h_tri)
+   {
+    case 1:  v1 =  1; v2 =  3; v3 =  2; break;
+    case 2:  v1 =  1; v2 =  4; v3 =  3; break;
+    case 3:  v1 =  1; v2 =  5; v3 =  4; break;
+    case 4:  v1 =  1; v2 =  6; v3 =  5; break;
+    case 5:  v1 =  1; v2 =  2; v3 =  6; break;
+    case 6:  v1 =  2; v2 =  3; v3 =  8; break;
+    case 7:  v1 =  3; v2 =  9; v3 =  8; break;
+    case 8:  v1 =  3; v2 =  4; v3 =  9; break;
+    case 9:  v1 =  4; v2 = 10; v3 =  9; break;
+    case 10: v1 =  4; v2 =  5; v3 = 10; break;
+    case 11: v1 =  5; v2 = 11; v3 = 10; break;
+    case 12: v1 =  5; v2 =  6; v3 = 11; break;
+    case 13: v1 =  6; v2 =  7; v3 = 11; break;
+    case 14: v1 =  2; v2 =  7; v3 =  6; break;
+    case 15: v1 =  2; v2 =  8; v3 =  7; break;
+    case 16: v1 =  8; v2 =  9; v3 = 12; break;
+    case 17: v1 =  9; v2 = 10; v3 = 12; break;
+    case 18: v1 = 10; v2 = 11; v3 = 12; break;
+    case 19: v1 = 11; v2 =  7; v3 = 12; break;
+    case 20: v1 =  8; v2 = 12; v3 =  7; break;
+   } /* end of switch statement */
+
+   h1 = x - v_x[v1];
+   h2 = y - v_y[v1];
+   h3 = z - v_z[v1];
+   h_dist1 = sqrt(h1 * h1 + h2 * h2 + h3 * h3);
+
+   h1 = x - v_x[v2];
+   h2 = y - v_y[v2];
+   h3 = z - v_z[v2];
+   h_dist2 = sqrt(h1 * h1 + h2 * h2 + h3 * h3);
+
+   h1 = x - v_x[v3];
+   h2 = y - v_y[v3];
+   h3 = z - v_z[v3];
+   h_dist3 = sqrt(h1 * h1 + h2 * h2 + h3 * h3);
+
+   if ( (h_dist1 <= h_dist2) && (h_dist2 <= h_dist3) ) {h_lcd = 1; }
+   if ( (h_dist1 <= h_dist3) && (h_dist3 <= h_dist2) ) {h_lcd = 6; }
+   if ( (h_dist2 <= h_dist1) && (h_dist1 <= h_dist3) ) {h_lcd = 2; }
+   if ( (h_dist2 <= h_dist3) && (h_dist3 <= h_dist1) ) {h_lcd = 3; }
+   if ( (h_dist3 <= h_dist1) && (h_dist1 <= h_dist2) ) {h_lcd = 5; }
+   if ( (h_dist3 <= h_dist2) && (h_dist2 <= h_dist1) ) {h_lcd = 4; }
+
+   *lcd = h_lcd;
+
+} /* end s_tri_info */
+
+
+static void dymax_point(int tri, int lcd,
+                double x, double y, double z,
+                 double *px, double *py)
+{
+  int axis, v1 = 0;
+  double hlng, hlat, h0x, h0y, h0z, h1x, h1y, h1z;
+
+  double gs;
+  double gx, gy, gz, ga1,ga2,ga3,ga1p,ga2p,ga3p,gxp,gyp/*,gzp*/;
+
+
+  /* In order to rotate the given point into the template spherical */
+  /* triangle, we need the spherical polar coordinates of the center */
+  /* of the face and one of the face vertices. So set up which vertex */
+  /* to use.                                                          */
+
+   switch (tri)
+   {
+    case 1:  v1 =  1;  break;
+    case 2:  v1 =  1;  break;
+    case 3:  v1 =  1;  break;
+    case 4:  v1 =  1;  break;
+    case 5:  v1 =  1;  break;
+    case 6:  v1 =  2;  break;
+    case 7:  v1 =  3;  break;
+    case 8:  v1 =  3;  break;
+    case 9:  v1 =  4;  break;
+    case 10: v1 =  4;  break;
+    case 11: v1 =  5;  break;
+    case 12: v1 =  5;  break;
+    case 13: v1 =  6;  break;
+    case 14: v1 =  2;  break;
+    case 15: v1 =  2;  break;
+    case 16: v1 =  8;  break;
+    case 17: v1 =  9;  break;
+    case 18: v1 = 10;  break;
+    case 19: v1 = 11;  break;
+    case 20: v1 =  8;  break;
+   } /* end of switch statement */
+
+   h0x = x;
+   h0y = y;
+   h0z = z;
+
+   h1x = v_x[v1];
+   h1y = v_y[v1];
+   h1z = v_z[v1];
+
+   c_to_s(&hlng, &hlat, center_x[tri], center_y[tri], center_z[tri]);
+
+   axis = 3;
+   r2(axis,hlng,&h0x,&h0y,&h0z);
+   r2(axis,hlng,&h1x,&h1y,&h1z);
+
+   axis = 2;
+   r2(axis,hlat,&h0x,&h0y,&h0z);
+   r2(axis,hlat,&h1x,&h1y,&h1z);
+
+   c_to_s(&hlng,&hlat,h1x,h1y,h1z);
+   hlng = hlng - radians(90.0);
+
+   axis = 3;
+   r2(axis,hlng,&h0x,&h0y,&h0z);
+
+   /* exact transformation equations */
+
+   gz = sqrt(1 - h0x * h0x - h0y * h0y);
+   gs = sqrt( 5 + 2 * sqrt(5) ) / ( gz * sqrt(15) );
+
+   gxp = h0x * gs ;
+   gyp = h0y * gs ;
+
+   ga1p = 2.0 * gyp / sqrt(3.0) + (gel / 3.0) ;
+   ga2p = gxp - (gyp / sqrt(3)) +  (gel / 3.0) ;
+   ga3p = (gel / 3.0) - gxp - (gyp / sqrt(3));
+
+   ga1 = gt + atan( (ga1p - 0.5 * gel) / gdve);
+   ga2 = gt + atan( (ga2p - 0.5 * gel) / gdve);
+   ga3 = gt + atan( (ga3p - 0.5 * gel) / gdve);
+
+   gx = 0.5 * (ga2 - ga3) ;
+
+   gy = (1.0 / (2.0 * sqrt(3)) ) * (2 * ga1 - ga2 - ga3);
+
+   /* Re-scale so plane triangle edge length is 1. */
+
+   x = gx / garc;
+   y = gy / garc;
+
+  /* rotate and translate to correct position          */
+
+  switch (tri)
+   {
+     case  1: rotate(240.0,&x, &y);
+             *px = x + 2.0; *py = y + 7.0 / (2.0 * sqrt(3.0)) ; break;
+     case  2: rotate(300.0, &x, &y); *px = x + 2.0;
+              *py = y + 5.0 / (2.0 * sqrt(3.0)) ; break;
+     case  3: rotate(0.0, &x, &y);
+             *px = x + 2.5; *py = y + 2.0 / sqrt(3.0); break;
+     case  4: rotate(60.0, &x, &y);
+              *px = x + 3.0; *py = y + 5.0 / (2.0 * sqrt(3.0)) ; break;
+     case  5: rotate(180.0, &x, &y);
+             *px = x + 2.5; *py = y + 4.0 * sqrt(3.0) / 3.0; break;
+     case  6: rotate(300.0, &x, &y);
+              *px = x + 1.5; *py = y + 4.0 * sqrt(3.0) / 3.0; break;
+     case  7: rotate(300.0, &x, &y);
+              *px = x + 1.0; *py = y + 5.0 / (2.0 * sqrt(3.0)) ; break;
+     case  8: rotate(0.0, &x, &y);
+              *px = x + 1.5; *py = y + 2.0 / sqrt(3.0); break;
+     case  9: if (lcd > 2)
+             {
+             rotate(300.0, &x, &y);
+             *px = x + 1.5; *py = y + 1.0 / sqrt(3.0);
+             }
+             else
+             {
+             rotate(0.0, &x, &y);
+             *px = x + 2.0; *py = y + 1.0 / (2.0 * sqrt(3.0));
+             }
+             break;
+
+     case 10: rotate(60.0, &x, &y);
+              *px = x + 2.5; *py = y + 1.0 / sqrt(3.0); break;
+     case 11: rotate(60.0, &x, &y);
+              *px = x + 3.5; *py = y + 1.0 / sqrt(3.0); break;
+     case 12: rotate(120.0, &x, &y);
+              *px = x + 3.5; *py = y + 2.0 / sqrt(3.0); break;
+     case 13: rotate(60.0, &x, &y);
+              *px = x + 4.0; *py = y + 5.0 / (2.0 * sqrt(3.0)); break;
+     case 14: rotate(0.0, &x, &y);
+             *px = x + 4.0; *py = y + 7.0 / (2.0 * sqrt(3.0)) ; break;
+     case 15: rotate(0.0, &x, &y);
+             *px = x + 5.0; *py = y + 7.0 / (2.0 * sqrt(3.0)) ; break;
+     case 16: if (lcd < 4)
+             {
+               rotate(60.0, &x, &y);
+               *px = x + 0.5; *py = y + 1.0 / sqrt(3.0);
+              }
+              else
+              {
+               rotate(0.0, &x, &y);
+               *px = x + 5.5; *py = y + 2.0 / sqrt(3.0);
+              }
+              break;
+     case 17: rotate(0.0, &x, &y);
+             *px = x + 1.0; *py = y + 1.0 / (2.0 * sqrt(3.0)); break;
+     case 18: rotate(120.0, &x, &y);
+              *px = x + 4.0; *py = y + 1.0 / (2.0 * sqrt(3.0)); break;
+     case 19: rotate(120.0, &x, &y);
+              *px = x + 4.5; *py = y + 2.0 / sqrt(3.0); break;
+     case 20: rotate(300.0, &x, &y);
+              *px = x + 5.0; *py = y + 5.0 / (2.0 * sqrt(3.0)); break;
+
+   } /* end switch statement */
+
+} /* end of dymax_point */
+
+
+static void rotate(double angle, double *x, double *y)
+{
+  /* Rotate the point to correct orientation in XY-plane. */
+
+  double ha, hx, hy ;
+
+  ha = radians(angle);
+  hx = *x;
+  hy = *y;
+  *x = hx * cos(ha) - hy * sin(ha);
+  *y = hx * sin(ha) + hy * cos(ha);
+
+} /* end rotate procedure */
+
+
+static void r2(int axis, double alpha, double *x, double *y, double *z)
+{
+  /* Rotate a 3-D point about the specified axis.         */
+
+  double a, b, c;
+
+  a = *x;
+  b = *y;
+  c = *z;
+  if (axis == 1)
+  {
+   *y = b * cos(alpha) + c * sin(alpha);
+   *z = c * cos(alpha) - b * sin(alpha);
+  }
+
+  if (axis == 2)
+  {
+   *x = a * cos(alpha) - c * sin(alpha);
+   *z = a * sin(alpha) + c * cos(alpha);
+  }
+
+  if (axis == 3)
+  {
+   *x = a * cos(alpha) + b * sin(alpha);
+   *y = b * cos(alpha) - a * sin(alpha);
+  }
+
+} /* end of r2 */
+
diff --git a/hacks/glx/dymaxionmap-coords.h b/hacks/glx/dymaxionmap-coords.h
new file mode 100644 (file)
index 0000000..fad4a04
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __DYMAXIONMAP_COORDS_H__
+#define __DYMAXIONMAP_COORDS_H__
+
+void dymaxion_convert (double lng, double lat, double *x, double *y);
+
+#endif /* __DYMAXIONMAP_COORDS_H__ */
index 425e4c2d299825990eb3202ad62d4f61598fedb2..711db2e0d20c631a02dbbb6bfab64511fd306b6f 100644 (file)
@@ -32,6 +32,7 @@
 #include "sphere.h"
 #include "normals.h"
 #include "texfont.h"
+#include "dymaxionmap-coords.h"
 
 #ifdef HAVE_XMU
 # ifndef VMS
 #define DEF_WANDER  "True"
 #define DEF_TEXTURE "True"
 #define DEF_STARS   "True"
+#define DEF_GRID    "True"
 #define DEF_SPEED   "1.0"
-#define DEF_IMAGE   "BUILTIN"
+#define DEF_IMAGE   "BUILTIN_FLAT"
+#define DEF_IMAGE2  "NONE"
+#define DEF_FRAMES  "720"
 
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
 #undef BELLRAND
 #define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
+#undef RANDSIGN
+#define RANDSIGN() ((random() & 1) ? 1 : -1)
 
 static int do_roll;
 static int do_wander;
 static int do_texture;
 static int do_stars;
+static int do_grid;
+static int frames;
 static GLfloat speed;
 static char *which_image;
+static char *which_image2;
 
 static XrmOptionDescRec opts[] = {
-  {"-speed",   ".dymaxionmap.speed",   XrmoptionSepArg, 0 },
-  {"-roll",    ".dymaxionmap.roll",    XrmoptionNoArg, "true" },
-  {"+roll",    ".dymaxionmap.roll",    XrmoptionNoArg, "false" },
-  {"-wander",  ".dymaxionmap.wander",  XrmoptionNoArg, "true" },
-  {"+wander",  ".dymaxionmap.wander",  XrmoptionNoArg, "false" },
-  {"-texture", ".dymaxionmap.texture", XrmoptionNoArg, "true" },
-  {"+texture", ".dymaxionmap.texture", XrmoptionNoArg, "false" },
-  {"-stars",   ".dymaxionmap.stars",   XrmoptionNoArg, "true" },
-  {"+stars",   ".dymaxionmap.stars",   XrmoptionNoArg, "false" },
-  {"-image",   ".dymaxionmap.image",  XrmoptionSepArg, 0 },
+  {"-speed",    ".speed",   XrmoptionSepArg, 0 },
+  {"-roll",     ".roll",    XrmoptionNoArg, "true" },
+  {"+roll",     ".roll",    XrmoptionNoArg, "false" },
+  {"-wander",   ".wander",  XrmoptionNoArg, "true" },
+  {"+wander",   ".wander",  XrmoptionNoArg, "false" },
+  {"-texture",  ".texture", XrmoptionNoArg, "true" },
+  {"+texture",  ".texture", XrmoptionNoArg, "false" },
+  {"-stars",    ".stars",   XrmoptionNoArg, "true" },
+  {"+stars",    ".stars",   XrmoptionNoArg, "false" },
+  {"-grid",     ".grid",    XrmoptionNoArg, "true" },
+  {"+grid",     ".grid",    XrmoptionNoArg, "false" },
+  {"-flat",     ".image",   XrmoptionNoArg, "BUILTIN_FLAT" },
+  {"-satellite",".image",   XrmoptionNoArg, "BUILTIN_SAT"  },
+  {"-image",    ".image",   XrmoptionSepArg, 0 },
+  {"-image2",   ".image2",  XrmoptionSepArg, 0 },
+  {"-frames",   ".frames",  XrmoptionSepArg, 0 },
 };
 
 static argtype vars[] = {
@@ -81,7 +96,10 @@ static argtype vars[] = {
   {&do_wander,  "wander",  "Wander",  DEF_WANDER,  t_Bool},
   {&do_texture,         "texture", "Texture", DEF_TEXTURE, t_Bool},
   {&do_stars,   "stars",   "Stars",   DEF_STARS,   t_Bool},
+  {&do_grid,    "grid",    "Grid",    DEF_GRID,    t_Bool},
   {&which_image, "image",   "Image",   DEF_IMAGE,   t_String},
+  {&which_image2,"image2",  "Image2",  DEF_IMAGE2,  t_String},
+  {&frames,      "frames",  "Frames",  DEF_FRAMES,  t_Int},
 };
 
 ENTRYPOINT ModeSpecOpt planet_opts = {countof(opts), opts, countof(vars), vars, NULL};
@@ -99,7 +117,10 @@ ModStruct   planet_description =
                    ISO C89 compilers are required to support" when including
                    the following XPM file... */
 # endif
-#include "images/gen/dymaxionmap_png.h"
+
+#include "images/gen/earth_flat_png.h"
+#include "images/gen/earth_png.h"
+#include "images/gen/earth_night_png.h"
 #include "images/gen/ground_png.h"
 
 #include "ximage-loader.h"
@@ -111,7 +132,7 @@ typedef struct {
   GLXContext *glx_context;
   GLuint starlist;
   int starcount;
-  rotator *rot;
+  rotator *rot, *rot2;
   trackball_state *trackball;
   Bool button_down_p;
   enum { STARTUP, FLAT, FOLD, 
@@ -120,60 +141,464 @@ typedef struct {
   GLfloat ratio;
   GLuint tex1, tex2;
   texture_font_data *font_data;
+  int loading_sw, loading_sh;
+
+  XImage *day, *night, *dusk, *cvt;
+  XImage **images;  /* One image for each frame of time-of-day. */
+  int nimages;
+
+  double current_frame;
+  Bool cache_p;
+  long delay;
+
 } planetstruct;
 
 
 static planetstruct *planets = NULL;
 
 
-/* Set up and enable texturing on our object */
+static double
+double_time (void)
+{
+  struct timeval now;
+# ifdef GETTIMEOFDAY_TWO_ARGS
+  struct timezone tzp;
+  gettimeofday(&now, &tzp);
+# else
+  gettimeofday(&now);
+# endif
+
+  return (now.tv_sec + ((double) now.tv_usec * 0.000001));
+}
+
+
+/* Draw faint latitude and longitude lines into the RGBA XImage.
+ */
 static void
-setup_png_texture (ModeInfo *mi, const unsigned char *png_data,
-                   unsigned long data_size)
+add_grid_lines (XImage *image)
 {
-  XImage *image = image_data_to_ximage (MI_DISPLAY (mi), MI_VISUAL (mi),
-                                        png_data, data_size);
-  char buf[1024];
-  clear_gl_error();
-  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-  /* iOS invalid enum:
-  glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
+  int i;
+  int off = 24;
+  for (i = 0; i < 24; i++)
+    {
+      int x = (i + 0.5) * image->width / (double) 24;
+      int y;
+      for (y = 0; y < image->height; y++)
+        {
+          unsigned long rgba = XGetPixel (image, x, y);
+          int r = (rgba >> 24) & 0xFF;
+          int g = (rgba >> 16) & 0xFF;
+          int b = (rgba >>  8) & 0xFF;
+          int a = (rgba >>  0) & 0xFF;
+          int off2 = (((r + g + b) / 3) < 0x7F ? off : -off);
+          r = MAX (0, MIN (0xFF, r + off2));
+          g = MAX (0, MIN (0xFF, g + off2));
+          b = MAX (0, MIN (0xFF, b + off2));
+          XPutPixel (image, x, y, (r << 24) | (g << 16) | (b << 8) | a);
+        }
+    }
+
+  for (i = 1; i < 11; i++)
+    {
+      int y = i * image->height / (double) 12;
+      int x;
+      for (x = 0; x < image->width; x++)
+        {
+          unsigned long rgba = XGetPixel (image, x, y);
+          int r = (rgba >> 24) & 0xFF;
+          int g = (rgba >> 16) & 0xFF;
+          int b = (rgba >>  8) & 0xFF;
+          int a = (rgba >>  0) & 0xFF;
+          int off2 = (((r + g + b) / 3) < 0x7F ? off : -off);
+          r = MAX (0, MIN (0xFF, r + off2));
+          g = MAX (0, MIN (0xFF, g + off2));
+          b = MAX (0, MIN (0xFF, b + off2));
+          XPutPixel (image, x, y, (r << 24) | (g << 16) | (b << 8) | a);
+        }
+    }
+}
+
+
+static void
+adjust_brightness (XImage *image, double amount)
+{
+  uint32_t *in = (uint32_t *) image->data;
+  int i;
+  int end = image->height * image->bytes_per_line / 4;
+  for (i = 0; i < end; i++)
+    {
+      uint32_t p = *in;
+      /* #### Why is this ABGR instead of RGBA? */
+      uint32_t a = (p >> 24) & 0xFF;
+      uint32_t g = (p >> 16) & 0xFF;
+      uint32_t b = (p >>  8) & 0xFF;
+      uint32_t r = (p >>  0) & 0xFF;
+      r = MAX(0, MIN(0xFF, (long) (r * amount)));
+      g = MAX(0, MIN(0xFF, (long) (g * amount)));
+      b = MAX(0, MIN(0xFF, (long) (b * amount)));
+      p = (a << 24) | (g << 16) | (b << 8) | r;
+      *in++ = p;
+    }
+}
+
+
+static GLfloat
+vector_angle (XYZ a, XYZ b)
+{
+  double La = sqrt (a.x*a.x + a.y*a.y + a.z*a.z);
+  double Lb = sqrt (b.x*b.x + b.y*b.y + b.z*b.z);
+  double cc, angle;
+
+  if (La == 0 || Lb == 0) return 0;
+  if (a.x == b.x && a.y == b.y && a.z == b.z) return 0;
+
+  /* dot product of two vectors is defined as:
+       La * Lb * cos(angle between vectors)
+     and is also defined as:
+       ax*bx + ay*by + az*bz
+     so:
+      La * Lb * cos(angle) = ax*bx + ay*by + az*bz
+      cos(angle)  = (ax*bx + ay*by + az*bz) / (La * Lb)
+      angle = acos ((ax*bx + ay*by + az*bz) / (La * Lb));
   */
-  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
-              image->width, image->height, 0,
-              GL_RGBA, GL_UNSIGNED_BYTE, image->data);
-  sprintf (buf, "builtin texture (%dx%d)", image->width, image->height);
-  check_gl_error(buf);
+  cc = (a.x*b.x + a.y*b.y + a.z*b.z) / (La * Lb);
+  if (cc > 1) cc = 1;  /* avoid fp rounding error (1.000001 => sqrt error) */
+  angle = acos (cc);
+
+  return (angle);
+}
+
+
+/* Creates a grayscale image encoding the day/night terminator for a random
+   axial tilt.
+ */
+static XImage *
+create_daylight_mask (Display *dpy, Visual *v, int w, int h)
+{
+  XImage *image = XCreateImage (dpy, v, 8, ZPixmap, 0, 0, w, h, 8, 0);
+  int x, y;
+  XYZ sun;
+  double axial_tilt = frand(23.4) / (180/M_PI) * RANDSIGN();
+  double dusk = M_PI * 0.035;
+  sun.x = 0;
+  sun.y = cos (axial_tilt);
+  sun.z = sin (axial_tilt);
+
+  image->data = (char *) malloc (image->height * image->bytes_per_line);
+
+  for (y = 0; y < image->height; y++)
+    {
+      double lat = -M_PI_2 + (M_PI * (y / (double) image->height));
+      double cosL = cos(lat);
+      double sinL = sin(lat);
+      for (x = 0; x < image->width; x++)
+        {
+          double lon = -M_PI_2 + (M_PI * 2 * (x / (double) image->width));
+          XYZ v;
+          double a;
+          unsigned long p;
+          v.x = cos(lon) * cosL;
+          v.y = sin(lon) * cosL;
+          v.z = sinL;
+          a = vector_angle (sun, v);
+          a -= M_PI_2;
+          a = (a < -dusk ? 1 : a >= dusk ? 0 : (dusk - a) / (dusk * 2));
+          p = 0xFF & (unsigned long) (a * 0xFF);
+          XPutPixel (image, x, y, p);
+        }
+    }
+  return image;
 }
 
 
-static Bool
-setup_file_texture (ModeInfo *mi, char *filename)
+static void
+load_images (ModeInfo *mi)
 {
-  Display *dpy = mi->dpy;
-  Visual *visual = mi->xgwa.visual;
-  char buf[1024];
+  planetstruct *gp = &planets[MI_SCREEN(mi)];
+  int i;
 
-  XImage *image = file_to_ximage (dpy, visual, filename);
-  if (!image) return False;
+  if (which_image && !strcmp (which_image, "BUILTIN_FLAT"))
+    {
+      which_image  = strdup("BUILTIN_FLAT");
+      which_image2 = strdup("BUILTIN_FLAT");
+    }
+  else if (which_image && !strcmp (which_image, "BUILTIN_SAT"))
+    {
+      which_image  = strdup("BUILTIN_DAY");
+      which_image2 = strdup("BUILTIN_NIGHT");
+    }
 
-  clear_gl_error();
-  glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-  glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
-  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
-              image->width, image->height, 0,
-              GL_RGBA, GL_UNSIGNED_BYTE, image->data);
-  sprintf (buf, "texture: %.100s (%dx%d)",
-          filename, image->width, image->height);
-  check_gl_error(buf);
-  return True;
+  if (!which_image)  which_image  = strdup("");
+  if (!which_image2) which_image2 = strdup("");
+
+  for (i = 0; i < 2; i++)
+    {
+      char *s = (i == 0 ? which_image : which_image2);
+      XImage *image;
+      if (!strcmp (s, "BUILTIN_DAY"))
+        image = image_data_to_ximage (MI_DISPLAY (mi), MI_VISUAL (mi),
+                                      earth_png, sizeof(earth_png));
+      else if (!strcmp (s, "BUILTIN_NIGHT"))
+        image = image_data_to_ximage (MI_DISPLAY (mi), MI_VISUAL (mi),
+                                      earth_night_png,sizeof(earth_night_png));
+      else if (!strcmp (s, "BUILTIN") ||
+               !strcmp (s, "BUILTIN_FLAT") ||
+               (i == 0 && !strcmp (s, "")))
+        image = image_data_to_ximage (MI_DISPLAY (mi), MI_VISUAL (mi),
+                                      earth_flat_png, sizeof(earth_flat_png));
+      else if (!strcmp (s, "NONE"))
+        image = 0;
+      else if (*s)
+        image = file_to_ximage (MI_DISPLAY (mi), MI_VISUAL (mi), s);
+      else
+        image = 0;
+
+      /* if (image) fprintf (stderr, "%s: %d: loaded %s\n", progname, i, s); */
+
+      if (i == 0)
+        gp->day = image;
+      else
+        gp->night = image;
+    }
+
+  if (gp->night && !gp->day) 
+    gp->day = gp->night, gp->night = 0;
+
+  gp->nimages = frames;
+  gp->current_frame = random() % gp->nimages;
+
+  if (gp->nimages < 1)
+    gp->nimages = 1;
+
+  if (gp->nimages < 2 && gp->night)
+    {
+      XDestroyImage (gp->night);
+      gp->night = 0;
+      gp->nimages = 1;
+    }
+
+  if (! gp->night)
+    gp->nimages = 1;
+
+  if (do_grid)
+    {
+      if (gp->day)   add_grid_lines (gp->day);
+      if (gp->night) add_grid_lines (gp->night);
+    }
+
+  if (gp->day && gp->night && !gp->dusk)
+    {
+      if (gp->day->width  != gp->night->width ||
+          gp->day->height != gp->night->height)
+        {
+          fprintf (stderr, "%s: day and night images must be the same size"
+                   " (%dx%d vs %dx%d)\n", progname,
+                   gp->day->width, gp->day->height,
+                   gp->night->width, gp->night->height);
+          exit (1);
+        }
+      gp->dusk = create_daylight_mask (MI_DISPLAY (mi), MI_VISUAL (mi),
+                                       gp->day->width, gp->day->height);
+    }
+
+  /* Make the day image brighter, because that's easier than doing it
+     with GL lights. */
+  adjust_brightness (gp->day, 1.4);
+
+  if (!strcmp (which_image, which_image2))
+    /* If day and night are the same image, make night way darker. */
+    adjust_brightness (gp->night, 0.2);
+  else if (gp->night)
+    /* Otherwise make it just a little darker. */
+    adjust_brightness (gp->night, 0.7);
+
+
+  gp->images = (XImage **) calloc (gp->nimages, sizeof(*gp->images));
+
+  /* Create 'cvt', a map that projects each pixel from Equirectangular to
+     Dymaxion.  It is 2x the width/height of the source images. We iterate
+     by half pixel to make sure we hit every pixel in 'out'. It would be
+     cleaner to iterate over 'out' instead of over 'in' but
+     dymaxionmap-coords.c only goes forward. This is... not super fast.
+   */
+  {
+    double W = 5.5;
+    double H = 3 * sqrt(3)/2;
+    int x2, y2;
+    int w = gp->day->width;
+    int h = gp->day->height;
+    uint32_t *out;
+
+    gp->cvt = XCreateImage (MI_DISPLAY(mi), MI_VISUAL(mi), 32, ZPixmap, 0, 0,
+                            gp->day->width*2, gp->day->height*2, 32, 0);
+    gp->cvt->data = (char *)
+      malloc (gp->cvt->height * gp->cvt->bytes_per_line);
+    out = (uint32_t *) gp->cvt->data;
+
+    for (y2 = 0; y2 < h*2; y2++)
+      {
+        double y = (double) y2/2;
+        double lat = -90 + (180 * (y / (double) h));
+        for (x2 = 0; x2 < w*2; x2++)
+          {
+            double x = (double) x2/2;
+            double lon = -180 + (360 * x / w);
+            double ox, oy;
+            dymaxion_convert (lon, lat, &ox, &oy);
+            ox = w - (w * ox / W);
+            oy =     (h * oy / H);
+
+            *out++ = (((((uint32_t) ox) & 0xFFFF) << 16) |
+                      ((((uint32_t) oy) & 0xFFFF)));
+          }
+      }
+  }
+
+  /* A 128 GB iPhone 6s dies at around 540 frames, ~1 GB of XImages.
+     A 16 GB iPad Air 2 dies at around 320 frames, ~640 MB.
+     Caching on mobile doesn't matter much: we can just run at 100% CPU.
+
+     On some systems it would be more efficient to cache the images inside
+     a texture on the GPU instead of moving it from RAM to GPU every few
+     frames; but on other systems, we'd just run out of GPU memory instead. */
+  {
+    unsigned long cache_size = (gp->day->width * gp->day->height * 4 *
+                                gp->nimages);
+# ifdef HAVE_MOBILE
+    unsigned long max = 320 * 1024 * 1024L;            /* 320 MB */
+# else
+    unsigned long max = 2 * 1024 * 1024 * 1024L;       /* 2 GB */
+# endif
+    gp->cache_p = (cache_size < max);
+  }
+}
+
+
+static void
+cache_current_frame (ModeInfo *mi)
+{
+  planetstruct *gp = &planets[MI_SCREEN(mi)];
+  XImage *blended, *dymaxion;
+  int i, x, y, w, h, end, xoff;
+  uint32_t *day, *night, *cvt, *out;
+  uint8_t *dusk;
+
+  if (gp->images[(int) gp->current_frame])
+    return;
+
+  xoff = (gp->dusk
+          ? gp->dusk->width * ((double) gp->current_frame / gp->nimages)
+          : 0);
+
+  w = gp->day->width;
+  h = gp->day->height;
+
+  if (!gp->night)
+    blended = gp->day;
+  else
+    {
+      /* Blend the foreground and background images through the dusk map.
+       */
+      blended = XCreateImage (MI_DISPLAY(mi), MI_VISUAL(mi), 
+                              gp->day->depth, ZPixmap, 0, 0, w, h, 32, 0);
+      if (!blended) abort();
+      blended->data = (char *) malloc (h * blended->bytes_per_line);
+      if (!blended->data) abort();
+
+      end = blended->height * blended->bytes_per_line / 4;
+      day   = (uint32_t *) gp->day->data;
+      night = (uint32_t *) gp->night->data;
+      dusk  = (uint8_t  *) gp->dusk->data;
+      out   = (uint32_t *) blended->data;
+
+      for (i = 0; i < end; i++)
+        {
+          uint32_t d = *day++;
+          uint32_t n = *night++;
+          uint32_t x = i % w;
+          uint32_t y = i / w;
+          double r = dusk[y * w + ((x + xoff) % w)] / 256.0;
+          double r2 = 1-r;
+# define ADD(M) (((unsigned long)             \
+                  ((((d >> M) & 0xFF) * r) +  \
+                   (((n >> M) & 0xFF) * r2))) \
+                 << M)
+          /* #### Why is this ABGR instead of RGBA? */
+          *out++ = (0xFF << 24) | ADD(16) | ADD(8) | ADD(0);
+# undef ADD
+        }
+    }
+
+  /* Convert blended Equirectangular to Dymaxion through the 'cvt' map.
+   */
+  dymaxion = XCreateImage (MI_DISPLAY(mi), MI_VISUAL(mi), 
+                          gp->day->depth, ZPixmap, 0, 0, w, h, 32, 0);
+  dymaxion->data = (char *) calloc (h, dymaxion->bytes_per_line);
+  
+  day = (uint32_t *) blended->data;
+  out = (uint32_t *) dymaxion->data;
+  cvt = (uint32_t *) gp->cvt->data;
+
+  for (y = 0; y < h*2; y++)
+    for (x = 0; x < w*2; x++)
+      {
+        unsigned long m  = *cvt++;
+        unsigned long dx = (m >> 16) & 0xFFFF;
+        unsigned long dy = m & 0xFFFF;
+        unsigned long p  = day[(y>>1) * w + (x>>1)];
+        unsigned long p2 = out[dy * w + dx];
+        if (p2 & 0xFF000000)
+          /* RGBA nonzero alpha: initialized. Average with existing,
+             otherwise the grid lines look terrible. */
+          p = (((((p>>24) & 0xFF) + ((p2>>24) & 0xFF)) >> 1) << 24 |
+               ((((p>>16) & 0xFF) + ((p2>>16) & 0xFF)) >> 1) << 16 |
+               ((((p>> 8) & 0xFF) + ((p2>> 8) & 0xFF)) >> 1) <<  8 |
+               ((((p>> 0) & 0xFF) + ((p2>> 0) & 0xFF)) >> 1) <<  0);
+        out[dy * w + dx] = p;
+      }
+
+  /* Fill in the triangles that are not a part of The World with the
+     color of the ocean to avoid texture-tearing on the folded edges.
+  */
+  out = (uint32_t *) dymaxion->data;
+  end = dymaxion->height * dymaxion->bytes_per_line / 4;
+  {
+    double lat = -48.44, lon = -123.39;   /* R'Lyeh */
+    int x = (lon + 180) * blended->width  / 360.0;
+    int y = (lat + 90)  * blended->height / 180.0;
+    unsigned long ocean = XGetPixel (gp->day, x, y);
+    for (i = 0; i < end; i++)
+      {
+        uint32_t p = *out;
+        if (! (p & 0xFF000000)) /* AGBR */
+          *out = ocean;
+        out++;
+      }
+  }
+
+  if (blended != gp->day)
+    XDestroyImage (blended);
+
+  gp->images[(int) gp->current_frame] = dymaxion;
+
+  if (!gp->cache_p)  /* Keep only one image around; recompute every time. */
+    {
+      i = ((int) gp->current_frame) - 1;
+      if (i < 0) i = gp->nimages - 1;
+      if (gp->images[i])
+        {
+          XDestroyImage (gp->images[i]);
+          gp->images[i] = 0;
+        }
+    }
 }
 
 
 static void
-setup_texture(ModeInfo * mi)
+setup_texture (ModeInfo * mi)
 {
   planetstruct *gp = &planets[MI_SCREEN(mi)];
+  XImage *ground;
 
   glGenTextures (1, &gp->tex1);
   glBindTexture (GL_TEXTURE_2D, gp->tex1);
@@ -185,18 +610,7 @@ setup_texture(ModeInfo * mi)
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
-  if (!which_image ||
-      !*which_image ||
-      !strcmp(which_image, "BUILTIN"))
-    {
-    BUILTIN:
-      setup_png_texture (mi, dymaxionmap_png, sizeof(dymaxionmap_png));
-    }
-  else
-    {
-      if (! setup_file_texture (mi, which_image))
-        goto BUILTIN;
-    }
+  load_images (mi);
 
   glGenTextures (1, &gp->tex2);
   glBindTexture (GL_TEXTURE_2D, gp->tex2);
@@ -208,14 +622,17 @@ setup_texture(ModeInfo * mi)
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
-  setup_png_texture (mi, ground_png, sizeof(ground_png));
-
-  check_gl_error("texture initialization");
-
-  /* Need to flip the texture top for bottom for some reason. */
-  glMatrixMode (GL_TEXTURE);
-  glScalef (1, -1, 1);
-  glMatrixMode (GL_MODELVIEW);
+  /* The underground image can go on flat, without the dymaxion transform. */
+  ground = image_data_to_ximage (MI_DISPLAY (mi), MI_VISUAL (mi),
+                                 ground_png, sizeof(ground_png));
+  clear_gl_error();
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+  /* glPixelStorei(GL_UNPACK_ROW_LENGTH, ground->width); */
+  glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
+                ground->width, ground->height, 0,
+                GL_RGBA, GL_UNSIGNED_BYTE, ground->data);
+  check_gl_error ("ground texture");
+  XDestroyImage (ground);
 }
 
 
@@ -298,23 +715,35 @@ reshape_planet (ModeInfo *mi, int width, int height)
 
 
 static void
-do_normal2 (Bool frontp, XYZ a, XYZ b, XYZ c)
+do_normal2 (ModeInfo *mi, Bool frontp, XYZ a, XYZ b, XYZ c)
 {
-  if (frontp)
-    do_normal (a.x, a.y, a.z,
-               b.x, b.y, b.z,
-               c.x, c.y, c.z);
-  else
-    do_normal (b.x, b.y, b.z,
-               a.x, a.y, a.z,
-               c.x, c.y, c.z);
+  XYZ n = (frontp
+           ? calc_normal (a, b, c)
+           : calc_normal (b, a, c));
+  glNormal3f (n.x, n.y, n.z);
+
+# if 0
+  if (frontp && MI_IS_WIREFRAME(mi))
+    {
+      glBegin (GL_LINES);
+      glVertex3f ((a.x + b.x + c.x) / 3,
+                  (a.y + b.y + c.y) / 3,
+                  (a.z + b.z + c.z) / 3);
+      glVertex3f ((a.x + b.x + c.x) / 3 + n.x,
+                  (a.y + b.y + c.y) / 3 + n.y,
+                  (a.z + b.z + c.z) / 3 + n.z);
+      glEnd();
+    }
+# endif
 }
 
 
 static void
-triangle0 (ModeInfo *mi, Bool frontp, GLfloat stel_ratio, int bitmask)
+triangle0 (ModeInfo *mi, Bool frontp, GLfloat stel_ratio, int facemask, 
+           XYZ *corners_ret)
 {
-  /* Render a triangle as six sub-triangles:
+  /* Render a triangle as six sub-triangles.
+     Facemask bits 0-5 indicate which sub-triangle to draw.
 
                 A
                / \
@@ -371,90 +800,101 @@ triangle0 (ModeInfo *mi, Bool frontp, GLfloat stel_ratio, int bitmask)
   }
 
 
-  if (bitmask & 1<<0)
+  if (facemask & 1<<0)
     {
-      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
       a  =  E;  b =  D;  c =  A;
       ta = tE; tb = tD; tc = tA;
-      do_normal2 (frontp, a, b, c);
+      do_normal2 (mi, frontp, a, b, c);
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
       glTexCoord2f (ta.x, ta.y); glVertex3f (a.x, a.y, a.z);
       glTexCoord2f (tb.x, tb.y); glVertex3f (b.x, b.y, b.z);
       glTexCoord2f (tc.x, tc.y); glVertex3f (c.x, c.y, c.z);
       glEnd();
       mi->polygon_count++;
     }
-  if (bitmask & 1<<1)
+  if (facemask & 1<<1)
     {
-      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
       a  =  D;  b =  F;  c =  A;
       ta = tD; tb = tF; tc = tA;
-      do_normal2 (frontp, a, b, c);
+      do_normal2 (mi, frontp, a, b, c);
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
       glTexCoord2f (ta.x, ta.y); glVertex3f (a.x, a.y, a.z);
       glTexCoord2f (tb.x, tb.y); glVertex3f (b.x, b.y, b.z);
       glTexCoord2f (tc.x, tc.y); glVertex3f (c.x, c.y, c.z);
       glEnd();
       mi->polygon_count++;
     }
-  if (bitmask & 1<<2)
+  if (facemask & 1<<2)
     {
-      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
       a  =  D;  b =  C;  c =  F;
       ta = tD; tb = tC; tc = tF;
-      do_normal2 (frontp, a, b, c);
+      do_normal2 (mi, frontp, a, b, c);
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
       glTexCoord2f (ta.x, ta.y); glVertex3f (a.x, a.y, a.z);
       glTexCoord2f (tb.x, tb.y); glVertex3f (b.x, b.y, b.z);
       glTexCoord2f (tc.x, tc.y); glVertex3f (c.x, c.y, c.z);
       glEnd();
       mi->polygon_count++;
     }
-  if (bitmask & 1<<3)
+  if (facemask & 1<<3)
     {
-      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
       a  =  G;  b =  C;  c =  D;
       ta = tG; tb = tC; tc = tD;
-      do_normal2 (frontp, a, b, c);
+      do_normal2 (mi, frontp, a, b, c);
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
       glTexCoord2f (ta.x, ta.y); glVertex3f (a.x, a.y, a.z);
       glTexCoord2f (tb.x, tb.y); glVertex3f (b.x, b.y, b.z);
       glTexCoord2f (tc.x, tc.y); glVertex3f (c.x, c.y, c.z);
       glEnd();
       mi->polygon_count++;
     }
-  if (bitmask & 1<<4)
+  if (facemask & 1<<4)
     {
-      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
       a  =  B;  b =  G;  c =  D;
       ta = tB; tb = tG; tc = tD;
-      do_normal2 (frontp, a, b, c);
+      do_normal2 (mi, frontp, a, b, c);
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
       glTexCoord2f (ta.x, ta.y); glVertex3f (a.x, a.y, a.z);
       glTexCoord2f (tb.x, tb.y); glVertex3f (b.x, b.y, b.z);
       glTexCoord2f (tc.x, tc.y); glVertex3f (c.x, c.y, c.z);
       glEnd();
       mi->polygon_count++;
     }
-  if (bitmask & 1<<5)
+  if (facemask & 1<<5)
     {
-      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
       a  =  B;  b =  D;  c =  E;
       ta = tB; tb = tD; tc = tE;
-      do_normal2 (frontp, a, b, c);
+      do_normal2 (mi, frontp, a, b, c);
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
       glTexCoord2f (ta.x, ta.y); glVertex3f (a.x, a.y, a.z);
       glTexCoord2f (tb.x, tb.y); glVertex3f (b.x, b.y, b.z);
       glTexCoord2f (tc.x, tc.y); glVertex3f (c.x, c.y, c.z);
       glEnd();
       mi->polygon_count++;
     }
-  if (bitmask & 1<<6)
+  if (facemask & 1<<6)
     {
-      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
       a  =  E;  b =  D;  c =  A;
       ta = tE; tb = tD; tc = tA;
-      do_normal2 (frontp, a, b, c);
+      do_normal2 (mi, frontp, a, b, c);
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
       glTexCoord2f (ta.x, ta.y); glVertex3f (a.x, a.y, a.z);
       glTexCoord2f (tb.x, tb.y); glVertex3f (b.x, b.y, b.z);
       glTexCoord2f (tc.x, tc.y); glVertex3f (c.x, c.y, c.z);
       glEnd();
       mi->polygon_count++;
     }
+
+  if (corners_ret)
+    {
+      corners_ret[0] = A;
+      corners_ret[1] = B;
+      corners_ret[2] = C;
+      corners_ret[3] = D;
+      corners_ret[4] = E;
+      corners_ret[5] = F;
+      corners_ret[6] = G;
+    }
 }
 
 
@@ -476,37 +916,41 @@ triangle0 (ModeInfo *mi, Bool frontp, GLfloat stel_ratio, int bitmask)
    Each triangle can be connected to at most two other triangles.
    We start from the middle, #12, and work our way to the edges.
    Its centroid is 0,0.
+
+   (Note that dymaxionmap-coords.c uses a different numbering system.)
  */
 static void
 triangle (ModeInfo *mi, int which, Bool frontp, 
           GLfloat fold_ratio, GLfloat stel_ratio)
 {
   planetstruct *gp = &planets[MI_SCREEN(mi)];
-  const GLfloat fg[3] = { 1, 1, 1 };
-  const GLfloat bg[3] = { 0.3, 0.3, 0.3 };
+  const GLfloat fg[] = { 1, 1, 1, 1 };
+  const GLfloat bg[] = { 0.3, 0.3, 0.3, 1 };
   int a = -1, b = -1;
   GLfloat max = acos (sqrt(5)/3);
   GLfloat rot = -max * fold_ratio / (M_PI/180);
   Bool wire = MI_IS_WIREFRAME(mi);
+  XYZ corners[7];
 
-  if (wire)
-    glColor3fv (fg);
+  glColor3fv (fg);
+  if (!wire)
+    glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, fg);
 
   switch (which) {
   case 3:                              /* One third of the face. */
-    triangle0 (mi, frontp, stel_ratio, 1<<3 | 1<<4);
+    triangle0 (mi, frontp, stel_ratio, 1<<3 | 1<<4, corners);
     break;
   case 4:                              /* Two thirds of the face: convex. */
-    triangle0 (mi, frontp, stel_ratio, 1<<1 | 1<<2 | 1<<3 | 1<<4);
+    triangle0 (mi, frontp, stel_ratio, 1<<1 | 1<<2 | 1<<3 | 1<<4, corners);
     break;
   case 6:                              /* One half of the face. */
-    triangle0 (mi, frontp, stel_ratio, 1<<1 | 1<<2 | 1<<3);
+    triangle0 (mi, frontp, stel_ratio, 1<<1 | 1<<2 | 1<<3, corners);
     break;
   case 7:                              /* One half of the face. */
-    triangle0 (mi, frontp, stel_ratio, 1<<2 | 1<<3 | 1<<4);
+    triangle0 (mi, frontp, stel_ratio, 1<<2 | 1<<3 | 1<<4, corners);
     break;
   default:                             /* Full face. */
-    triangle0 (mi, frontp, stel_ratio, 0x3F);
+    triangle0 (mi, frontp, stel_ratio, 0x3F, corners);
     break;
   }
 
@@ -611,6 +1055,95 @@ triangle (ModeInfo *mi, int which, Bool frontp,
       glMatrixMode(GL_MODELVIEW);
       glPopMatrix();
     }
+
+
+  /* Draw a border around the edge of the world.
+   */
+  if (!wire && frontp && stel_ratio == 0 && fold_ratio < 0.95)
+    {
+      int edges = 0;
+      GLfloat c[] = { 0, 0.2, 0.5, 1 };
+      c[3] = 1-fold_ratio;
+
+      switch (which)
+        {
+        case  0: edges = 1<<0 | 1<<2; break;
+        case  1: edges = 1<<2;        break;
+        case  2: edges = 1<<0;        break;
+        case  3: edges = 1<<3 | 1<<4; break;
+        case  4: edges = 1<<3 | 1<<5; break;
+        case  5: edges = 1<<0 | 1<<6; break;
+        case  6: edges = 1<<2 | 1<<7; break;
+        case 16: edges = 1<<0 | 1<<2; break;
+        case 21: edges = 1<<0 | 1<<2; break;
+        case 19: edges = 1<<0 | 1<<2; break;
+        case 12: edges = 1<<1;        break;
+        case 18: edges = 1<<0 | 1<<2; break;
+        case 17: edges = 1<<0 | 1<<2; break;
+        case  7: edges = 1<<8 | 1<<9; break;
+        case  9: edges = 1<<2;        break;
+        default: break;
+        }
+
+      glDisable (GL_TEXTURE_2D);
+      glDisable (GL_LIGHTING);
+      glLineWidth (2);
+      glColor4fv (c);
+      glBegin (GL_LINES);
+      if (edges & 1<<0)
+        {
+          glVertex3f (corners[0].x, corners[0].y, corners[0].z);
+          glVertex3f (corners[1].x, corners[1].y, corners[1].z);
+        }
+      if (edges & 1<<1)
+        {
+          glVertex3f (corners[1].x, corners[1].y, corners[1].z);
+          glVertex3f (corners[2].x, corners[2].y, corners[2].z);
+        }
+      if (edges & 1<<2)
+        {
+          glVertex3f (corners[2].x, corners[2].y, corners[2].z);
+          glVertex3f (corners[0].x, corners[0].y, corners[0].z);
+        }
+      if (edges & 1<<3)
+        {
+          glVertex3f (corners[1].x, corners[1].y, corners[1].z);
+          glVertex3f (corners[3].x, corners[3].y, corners[3].z);
+        }
+      if (edges & 1<<4)
+        {
+          glVertex3f (corners[3].x, corners[3].y, corners[3].z);
+          glVertex3f (corners[2].x, corners[2].y, corners[2].z);
+        }
+      if (edges & 1<<5)
+        {
+          glVertex3f (corners[3].x, corners[3].y, corners[3].z);
+          glVertex3f (corners[0].x, corners[0].y, corners[0].z);
+        }
+      if (edges & 1<<6)
+        {
+          glVertex3f (corners[0].x, corners[0].y, corners[0].z);
+          glVertex3f (corners[5].x, corners[5].y, corners[5].z);
+        }
+      if (edges & 1<<7)
+        {
+          glVertex3f (corners[0].x, corners[0].y, corners[0].z);
+          glVertex3f (corners[6].x, corners[6].y, corners[6].z);
+        }
+      if (edges & 1<<8)
+        {
+          glVertex3f (corners[1].x, corners[1].y, corners[1].z);
+          glVertex3f (corners[5].x, corners[5].y, corners[5].z);
+        }
+      if (edges & 1<<9)
+        {
+          glVertex3f (corners[5].x, corners[5].y, corners[5].z);
+          glVertex3f (corners[2].x, corners[2].y, corners[2].z);
+        }
+      glEnd();
+      glEnable (GL_TEXTURE_2D);
+      glEnable (GL_LIGHTING);
+    }
 }
 
 
@@ -721,6 +1254,7 @@ draw_axis (ModeInfo *mi)
   s = 0.96;
   glScalef (s, s, s);   /* tighten up the enclosing sphere */
 
+  glLineWidth (1);
   glColor3f (0.5, 0.5, 0);
 
   glRotatef (90,  1, 0, 0);    /* unit_sphere is off by 90 */
@@ -754,6 +1288,29 @@ planet_handle_event (ModeInfo *mi, XEvent *event)
       XLookupString (&event->xkey, &c, 1, &keysym, 0);
       if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
         {
+          int i;
+          double cf = gp->current_frame;
+
+          /* Switch between the satellite and flat map, preserving position. */
+          if (gp->day)   XDestroyImage (gp->day);
+          if (gp->night) XDestroyImage (gp->night);
+          if (gp->cvt)   XDestroyImage (gp->cvt);
+          gp->day    = 0;
+          gp->night  = 0;
+          gp->cvt    = 0;
+
+          for (i = 0; i < gp->nimages; i++)
+            if (gp->images[i]) XDestroyImage (gp->images[i]);
+          free (gp->images);
+          gp->images = 0;
+
+          which_image  = strdup (!strcmp (which_image, "BUILTIN_DAY")
+                                 ? "BUILTIN_FLAT" : "BUILTIN_DAY");
+          which_image2 = strdup (!strcmp (which_image2, "BUILTIN_NIGHT")
+                                 ? "BUILTIN_FLAT" : "BUILTIN_NIGHT");
+          load_images (mi);
+          gp->current_frame = cf;
+# if 0
           switch (gp->state) {
           case FLAT: case ICO: case STEL: case AXIS: case ICO2:
             gp->ratio = 1;
@@ -761,6 +1318,7 @@ planet_handle_event (ModeInfo *mi, XEvent *event)
           default:
             break;
           }
+# endif
           return True;
         }
     }
@@ -786,6 +1344,7 @@ init_planet (ModeInfo * mi)
   gp->state = STARTUP;
   gp->ratio = 0;
   gp->font_data = load_texture_font (mi->dpy, "labelFont");
+  gp->delay = MI_DELAY(mi);
 
   {
     double spin_speed  = 0.1;
@@ -795,6 +1354,7 @@ init_planet (ModeInfo * mi)
                            0, 1,
                            do_wander ? wander_speed : 0,
                            False);
+    gp->rot2 = make_rotator (0, 0, 0, 0, wander_speed, False);
     gp->trackball = gltrackball_init (True);
   }
 
@@ -813,11 +1373,10 @@ init_planet (ModeInfo * mi)
 
   if (!wire)
     {
-      GLfloat pos[4] = {0.4, 0.2, 0.4, 0.0};
-      GLfloat amb[4] = {0.4, 0.4, 0.4, 1.0};
-      GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0};
-      GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0};
-
+      GLfloat pos[4] = {1, 1, 1, 0};
+      GLfloat amb[4] = {0, 0, 0, 1};
+      GLfloat dif[4] = {1, 1, 1, 1};
+      GLfloat spc[4] = {0, 1, 1, 1};
       glEnable(GL_LIGHTING);
       glEnable(GL_LIGHT0);
       glLightfv(GL_LIGHT0, GL_POSITION, pos);
@@ -854,6 +1413,7 @@ draw_planet (ModeInfo * mi)
   int wire = MI_IS_WIREFRAME(mi);
   Display *dpy = MI_DISPLAY(mi);
   Window window = MI_WINDOW(mi);
+  long delay = gp->delay;
   double x, y, z;
 
   if (!gp->glx_context)
@@ -869,7 +1429,10 @@ draw_planet (ModeInfo * mi)
   if (! gp->button_down_p)
     switch (gp->state) {
     case STARTUP:  gp->ratio += speed * 0.01;  break;
-    case FLAT:     gp->ratio += speed * 0.005; break;
+    case FLAT:     gp->ratio += speed * 0.005 *
+        /* Stay flat longer if animating day and night. */
+        (gp->nimages <= 1 ? 1 : 0.3);
+      break;
     case FOLD:     gp->ratio += speed * 0.01;  break;
     case ICO:      gp->ratio += speed * 0.01;  break;
     case STEL_IN:  gp->ratio += speed * 0.05;  break;
@@ -918,6 +1481,18 @@ draw_planet (ModeInfo * mi)
   gltrackball_rotate (gp->trackball);
   glRotatef (current_device_rotation(), 0, 0, 1);
 
+# ifdef HAVE_MOBILE   /* Fill more of the screen. */
+    {
+      int size = MI_WIDTH(mi) < MI_HEIGHT(mi)
+        ? MI_WIDTH(mi) : MI_HEIGHT(mi);
+      GLfloat s = (size > 768 ? 1.4 :  /* iPad */
+                   2);                 /* iPhone */
+      glScalef (s, s, s);
+      if (MI_WIDTH(mi) < MI_HEIGHT(mi))
+        glRotatef (90, 0, 0, 1);
+    }
+# endif
+
   if (gp->state != STARTUP)
     {
       get_position (gp->rot, &x, &y, &z, !gp->button_down_p);
@@ -929,9 +1504,10 @@ draw_planet (ModeInfo * mi)
 
   if (do_roll && gp->state != STARTUP)
     {
-      get_rotation (gp->rot, &x, &y, 0, !gp->button_down_p);
-      glRotatef (x * 360, 1.0, 0.0, 0.0);
-      glRotatef (y * 360, 0.0, 1.0, 0.0);
+      double max = 65;
+      get_position (gp->rot2, &x, &y, 0, !gp->button_down_p);
+      glRotatef (max/2 - x*max, 1, 0, 0);
+      glRotatef (max/2 - y*max, 0, 1, 0);
     }
 
   if (do_stars)
@@ -949,11 +1525,57 @@ draw_planet (ModeInfo * mi)
     }
 
   if (! wire)
-    glEnable (GL_LIGHTING);
+    {
+      glEnable (GL_LIGHTING);
+      glEnable (GL_BLEND);
+      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    }
 
   if (do_texture)
     glEnable(GL_TEXTURE_2D);
 
+  if (do_texture /* && !gp->button_down_p */)
+    {
+      int i;
+      int prev = gp->current_frame;
+
+      /* By default, advance terminator by about an hour every 5 seconds. */
+      gp->current_frame += 0.1 * speed * (gp->nimages / 360.0);
+      while (gp->current_frame >= gp->nimages)
+        gp->current_frame -= gp->nimages;
+      i = gp->current_frame;
+
+      /* Load the current image into the texture.
+       */
+      if (i != prev || !gp->images[i])
+        {
+          double start = double_time();
+          cache_current_frame (mi);
+
+          glBindTexture (GL_TEXTURE_2D, gp->tex1);
+
+          /* Must be after glBindTexture */
+          glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+          glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+          glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+          glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+          glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+          glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
+                        gp->images[i]->width,
+                        gp->images[i]->height, 0,
+                        GL_RGBA, GL_UNSIGNED_BYTE,
+                        gp->images[i]->data);
+          check_gl_error ("texture");
+
+          /* If caching the image took a bunch of time, deduct that from
+             our per-frame delay to keep the timing a little smoother. */
+          delay -= 1000000 * (double_time() - start);
+          if (delay < 0) delay = 0;
+        }
+    }
+
+  glTranslatef (-0.5, -0.4, 0);
   glScalef (2.6, 2.6, 2.6);
 
   {
@@ -998,6 +1620,8 @@ draw_planet (ModeInfo * mi)
   if (mi->fps_p) do_fps (mi);
   glFinish();
   glXSwapBuffers(dpy, window);
+
+  MI_DELAY(mi) = delay;
 }
 
 
@@ -1005,6 +1629,16 @@ ENTRYPOINT void
 free_planet (ModeInfo * mi)
 {
   planetstruct *gp = &planets[MI_SCREEN(mi)];
+  int i;
+
+  if (gp->day)   XDestroyImage (gp->day);
+  if (gp->night) XDestroyImage (gp->night);
+  if (gp->dusk)  XDestroyImage (gp->dusk);
+  if (gp->cvt)   XDestroyImage (gp->cvt);
+
+  for (i = 0; i < gp->nimages; i++)
+    if (gp->images[i]) XDestroyImage (gp->images[i]);
+  free (gp->images);
 
   if (gp->glx_context) {
     glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(gp->glx_context));
index e08b23fd3c5d0e0859b1182643e553d65dbd4ce7..9f3e7941a512a7549a91acc58234dd552adfb23e 100644 (file)
@@ -8,15 +8,26 @@ dymaxionmap - An animation of Buckminster Fuller's unwrapped icosahedral globe.
 [\-window]
 [\-root]
 [\-delay \fInumber\fP]
+[\-speed \fIratio\fP]
 [\-no-wander]
 [\-no-roll]
 [\-no-stars]
+[\-no-grid]
+[\-flat]
+[\-satellite]
+[\-image \fIfile\fP]
+[\-image2 \fIfile\fP]
+[\-frames \fInumber\fP]
 [\-wireframe]
 [\-fps]
 .SH DESCRIPTION
 Buckminster Fuller's map of the Earth projected onto the surface of an
 unfolded icosahedron. It depicts the Earth's continents as one island, or
 nearly contiguous land masses.
+
+This screen saver animates the progression of the dusk terminator across
+the flattened globe. It includes both satellite and flat-colored map
+imagery, and can load and convert other Equirectangular-projected maps.
 .SH OPTIONS
 .TP 8
 .B \-visual \fIvisual\fP
@@ -32,14 +43,39 @@ Draw on the root window.
 .B \-delay \fInumber\fP
 Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
 .TP 8
+.B \-speed \fIratio\fP
+Speed of the animation. 0.5 means half as fast, 2 means twice as fast.
+.TP 8
 .B \-wander | \-no-wander
-Whether the object should wander around the screen.
+Whether the object should wander around the screen. Default yes.
 .TP 8
 .B \-roll | \-no-roll
-Whether the object should roll randomly.
+Whether the object should roll randomly. Default yes.
 .TP 8
 .B \-stars | \-no-stars
-Whether to display a star field.
+Whether to display a star field. Default yes.
+.TP 8
+.B \-grid | \-no-grid
+Whether to overlay a latitude/longitude grid over the map. Default yes.
+.TP 8
+.B \-flat
+Display a flat-colored map of the Earth. This is the default.
+.TP 8
+.B \-satellite
+Display a day-time satellite map of the Earth.
+.TP 8
+.B \-image \fIfile\fP
+An image to use for the day-time map.
+.TP 8
+.B \-image2 \fIfile\fP
+An image to use for the night-time map.
+The two images can be the same: the night-time one will be darkened.
+.TP 8
+.B \-frames \fInumber\fP
+The number of frames in the day/night animation. Default 720.
+Larger numbers are smoother, but use more memory.
+The day/night animation happens if \fIimage2\fP is set, or
+if \fIframes\fP is greater than 1.
 .TP 8
 .B \-wireframe | \-no-wireframe
 Render in wireframe instead of solid.
@@ -58,13 +94,24 @@ stored in the RESOURCE_MANAGER property.
 .SH SEE ALSO
 .BR X (1),
 .BR xscreensaver (1)
+.BR glplanet (1)
 .SH COPYRIGHT
-Copyright \(co 2016 by Jamie Zawinski.  Permission to use, copy, modify, 
+Copyright \(co 2016-2018 by Jamie Zawinski.  Permission to use, copy, modify, 
 distribute, and sell this software and its documentation for any purpose is 
 hereby granted without fee, provided that the above copyright notice appear 
 in all copies and that both that copyright notice and this permission notice
 appear in supporting documentation.  No representations are made about the 
 suitability of this software for any purpose.  It is provided "as is" without
 express or implied warranty.
+
+"Dymaxion Map" and "The Fuller Projection Map" are trademarks of
+The Buckminster Fuller Institute.
+
+The original Dymaxion Map image is copyright \(co 1982 by
+The Buckminster Fuller Institute. (This program does not use their
+imagery, only similar trigonometry.)
+
+The Dymaxion Map was covered by now-expired US Patent 2,393,676
+(Richard Buckminster Fuller, 1946).
 .SH AUTHOR
 Jamie Zawinski.
index c30b306ede1f0168f28b4cbb5a9c375e200934cb..f26a4ad2a5cddba9822c29dfe675f7b76d69051a 100644 (file)
 #define DEF_ROTATE  "True"
 #define DEF_ROLL    "True"
 #define DEF_WANDER  "True"
-#define DEF_SPIN    "0.03"
+#define DEF_SPIN    "1.0"
 #define DEF_TEXTURE "True"
 #define DEF_STARS   "True"
 #define DEF_RESOLUTION "128"
 #define DEF_IMAGE   "BUILTIN"
 #define DEF_IMAGE2  "BUILTIN"
 
+#define BLENDED_TERMINATOR
+
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
@@ -80,22 +82,23 @@ static int do_stars;
 static char *which_image;
 static char *which_image2;
 static int resolution;
+static GLfloat spin_arg;
 
 static XrmOptionDescRec opts[] = {
-  {"-rotate",  ".glplanet.rotate",  XrmoptionNoArg, "true" },
-  {"+rotate",  ".glplanet.rotate",  XrmoptionNoArg, "false" },
-  {"-roll",    ".glplanet.roll",    XrmoptionNoArg, "true" },
-  {"+roll",    ".glplanet.roll",    XrmoptionNoArg, "false" },
-  {"-wander",  ".glplanet.wander",  XrmoptionNoArg, "true" },
-  {"+wander",  ".glplanet.wander",  XrmoptionNoArg, "false" },
-  {"-texture", ".glplanet.texture", XrmoptionNoArg, "true" },
-  {"+texture", ".glplanet.texture", XrmoptionNoArg, "false" },
-  {"-stars",   ".glplanet.stars",   XrmoptionNoArg, "true" },
-  {"+stars",   ".glplanet.stars",   XrmoptionNoArg, "false" },
-  {"-spin",    ".glplanet.spin",    XrmoptionSepArg, 0 },
-  {"-image",   ".glplanet.image",   XrmoptionSepArg, 0 },
-  {"-image2",  ".glplanet.image2",  XrmoptionSepArg, 0 },
-  {"-resolution", ".glplanet.resolution", XrmoptionSepArg, 0 },
+  {"-rotate",  ".rotate",  XrmoptionNoArg, "true" },
+  {"+rotate",  ".rotate",  XrmoptionNoArg, "false" },
+  {"-roll",    ".roll",    XrmoptionNoArg, "true" },
+  {"+roll",    ".roll",    XrmoptionNoArg, "false" },
+  {"-wander",  ".wander",  XrmoptionNoArg, "true" },
+  {"+wander",  ".wander",  XrmoptionNoArg, "false" },
+  {"-texture", ".texture", XrmoptionNoArg, "true" },
+  {"+texture", ".texture", XrmoptionNoArg, "false" },
+  {"-stars",   ".stars",   XrmoptionNoArg, "true" },
+  {"+stars",   ".stars",   XrmoptionNoArg, "false" },
+  {"-spin",    ".spin",    XrmoptionSepArg, 0 },
+  {"-image",   ".image",   XrmoptionSepArg, 0 },
+  {"-image2",  ".image2",  XrmoptionSepArg, 0 },
+  {"-resolution", ".resolution", XrmoptionSepArg, 0 },
 };
 
 static argtype vars[] = {
@@ -104,6 +107,7 @@ static argtype vars[] = {
   {&do_wander,   "wander",  "Wander",  DEF_WANDER,  t_Bool},
   {&do_texture,  "texture", "Texture", DEF_TEXTURE, t_Bool},
   {&do_stars,    "stars",   "Stars",   DEF_STARS,   t_Bool},
+  {&spin_arg,    "spin",    "Spin",    DEF_SPIN,    t_Float},
   {&which_image, "image",   "Image",   DEF_IMAGE,   t_String},
   {&which_image2,"image2",  "Image",   DEF_IMAGE2,  t_String},
   {&resolution,  "resolution","Resolution", DEF_RESOLUTION, t_Int},
@@ -143,7 +147,6 @@ typedef struct {
   int screen_width, screen_height;
   GLXContext *glx_context;
   Window window;
-  XColor fg, bg;
   GLfloat z;
   GLfloat tilt;
   rotator *rot;
@@ -202,7 +205,7 @@ setup_file_texture (ModeInfo *mi, char *filename)
 
 
 static void
-setup_texture(ModeInfo * mi)
+setup_texture (ModeInfo * mi)
 {
   planetstruct *gp = &planets[MI_SCREEN(mi)];
 
@@ -316,6 +319,80 @@ init_stars (ModeInfo *mi)
 }
 
 
+#ifdef BLENDED_TERMINATOR
+static void
+terminator_tube (ModeInfo *mi, int resolution)
+{
+  Bool wire = MI_IS_WIREFRAME(mi);
+  GLfloat th;
+  GLfloat step = M_PI*2 / resolution;
+  GLfloat thickness = 0.1;  /* Dusk is about an hour wide. */
+  GLfloat c1[] = { 0, 0, 0, 1 };
+  GLfloat c2[] = { 0, 0, 0, 0 };
+
+  glPushMatrix();
+  if (wire)
+    {
+      c1[0] = c1[1] = 0.5;
+      c2[2] = 0.5;
+      glLineWidth (4);
+    }
+  glRotatef (90, 1, 0, 0);
+  glScalef (1.02, 1.02, 1.02);
+  glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
+  for (th = 0; th < M_PI*2 + step; th += step)
+    {
+      GLfloat x = cos(th);
+      GLfloat y = sin(th);
+      glColor4fv (c1);
+      if (!do_texture)
+        glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c1);
+      glNormal3f (x, y, 0);
+      glVertex3f (x, y,  thickness);
+      glColor4fv (c2);
+      if (!do_texture)
+        glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c2);
+      glVertex3f (x, y, -thickness);
+    }
+  glEnd();
+
+  /* There's a bit of a spike in the shading where the tube overlaps
+     the sphere, so extend the sphere a lot to try and avoid that. */
+# if 0 /* Nope, that doesn't help. */
+  glColor4fv (c1);
+  if (!do_texture)
+    glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c1);
+  glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
+  for (th = 0; th < M_PI*2 + step; th += step)
+    {
+      GLfloat x = cos(th);
+      GLfloat y = sin(th);
+      glNormal3f (x, y, 0);
+      glVertex3f (x, y, thickness);
+      glVertex3f (x, y, thickness + 10);
+    }
+  glEnd();
+
+  glColor4fv (c2);
+  if (!do_texture)
+    glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c2);
+  glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
+  for (th = 0; th < M_PI*2 + step; th += step)
+    {
+      GLfloat x = cos(th);
+      GLfloat y = sin(th);
+      glNormal3f (x, y, 0);
+      glVertex3f (x, y, -thickness);
+      glVertex3f (x, y, -thickness - 10);
+    }
+  glEnd();
+# endif /* 0 */
+
+  glPopMatrix();
+}
+#endif /* BLENDED_TERMINATOR */
+
+
 ENTRYPOINT void
 reshape_planet (ModeInfo *mi, int width, int height)
 {
@@ -388,17 +465,6 @@ init_planet (ModeInfo * mi)
          if (*s == ' ' || *s == '\t')
                *s = 0;
 
-    if (!XParseColor(mi->dpy, mi->xgwa.colormap, f, &gp->fg))
-      {
-               fprintf(stderr, "%s: unparsable color: \"%s\"\n", progname, f);
-               exit(1);
-      }
-    if (!XParseColor(mi->dpy, mi->xgwa.colormap, b, &gp->bg))
-      {
-               fprintf(stderr, "%s: unparsable color: \"%s\"\n", progname, f);
-               exit(1);
-      }
-
        free (f);
        free (b);
   }
@@ -416,6 +482,20 @@ init_planet (ModeInfo * mi)
     gp->trackball = gltrackball_init (True);
   }
 
+  if (!wire && !do_texture)
+    {
+      GLfloat pos[4] = {1, 1, 1, 0};
+      GLfloat amb[4] = {0, 0, 0, 1};
+      GLfloat dif[4] = {1, 1, 1, 1};
+      GLfloat spc[4] = {0, 1, 1, 1};
+      glEnable(GL_LIGHTING);
+      glEnable(GL_LIGHT0);
+      glLightfv(GL_LIGHT0, GL_POSITION, pos);
+      glLightfv(GL_LIGHT0, GL_AMBIENT,  amb);
+      glLightfv(GL_LIGHT0, GL_DIFFUSE,  dif);
+      glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
+    }
+
   if (wire)
     do_texture = False;
 
@@ -439,7 +519,39 @@ init_planet (ModeInfo * mi)
   gp->shadowlist = glGenLists(1);
   glNewList (gp->shadowlist, GL_COMPILE);
   glFrontFace(GL_CCW);
+
+  if (wire)
+    glColor4f (0.5, 0.5, 0, 1);
+# ifdef BLENDED_TERMINATOR
+  else
+    {
+      GLfloat c[] = { 0, 0, 0, 1 };
+      glColor4fv (c);
+      if (!do_texture)
+        glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c);
+    }
+# endif
+
+  glPushMatrix();
+  glScalef (1.01, 1.01, 1.01);
   unit_dome (resolution, resolution, wire);
+
+# ifdef BLENDED_TERMINATOR
+  terminator_tube (mi, resolution);
+  if (!wire)
+    {
+      /* We have to draw the transparent side of the mask too, 
+         though I'm not sure why. */
+      GLfloat c[] = { 0, 0, 0, 0 };
+      glColor4fv (c);
+      if (!do_texture)
+        glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c);
+      glRotatef (180, 1, 0, 0);
+      unit_dome (resolution, resolution, wire);
+    }
+# endif
+
+  glPopMatrix();
   glEndList();
 
   /* construct the polygons of the latitude/longitude/axis lines.
@@ -486,7 +598,7 @@ draw_planet (ModeInfo * mi)
 
   if (do_rotate && !gp->button_down_p)
     {
-      gp->z -= 0.001;     /* the sun sets in the west */
+      gp->z -= 0.001 * spin_arg;     /* the sun sets in the west */
       if (gp->z < 0) gp->z += 1;
     }
 
@@ -540,15 +652,19 @@ draw_planet (ModeInfo * mi)
 # endif
 
   if (wire)
-    glColor3f (0.5, 0.5, 1);
-  else
-    glColor3f (1, 1, 1);
-
-  if (do_texture)
+    glColor3f (0, 0, 0.5);
+  else if (do_texture)
     {
-      glEnable(GL_TEXTURE_2D);
+      glColor4f (1, 1, 1, 1);
+      glEnable (GL_TEXTURE_2D);
       glBindTexture (GL_TEXTURE_2D, gp->tex1);
     }
+  else
+    {
+      GLfloat c[] = { 0, 0.5, 0, 1 };
+      glColor4fv (c);
+      glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c);
+    }
 
   glPushMatrix();
   glRotatef (gp->z * 360, 0, 0, 1);
@@ -556,54 +672,134 @@ draw_planet (ModeInfo * mi)
   mi->polygon_count += resolution*resolution;
   glPopMatrix();
 
-  /* Originally we just used GL_LIGHT0 to produce the day/night sides of
-     the planet, but that always looked crappy, even with a vast number of
-     polygons, because the day/night terminator didn't exactly line up with
-     the polygon edges.
-
-     So instead, draw the full "day" sphere; clear the depth buffer; draw
-     a rotated/tilted half-sphere into the depth buffer only; then draw
-     the "night" sphere.  That lets us divide the sphere into the two maps,
-     and the dividing line can be at any angle, regardless of polygon layout.
-
-     The half-sphere is scaled slightly larger to avoid polygon fighting,
-     since those triangles won't exactly line up because of the rotation.
-
-     The downside of this is that the day/night terminator is 100% sharp.
-     It would be nice if it was a little blurry.
-   */
-
   if (wire)
     {
       glPushMatrix();
       glRotatef (gp->tilt, 1, 0, 0);
-      glColor3f(0, 0, 0);
+      glColor3f(1, 0, 0);
       glLineWidth(4);
       glCallList (gp->shadowlist);
       glLineWidth(1);
       mi->polygon_count += resolution*(resolution/2);
       glPopMatrix();
     }
-  else if (do_texture && gp->tex2)
+
+  else if (!do_texture || gp->tex2)
     {
-      glClear(GL_DEPTH_BUFFER_BIT);
-      glDisable(GL_TEXTURE_2D);
+      /* Originally we just used GL_LIGHT0 to produce the day/night sides of
+         the planet, but that always looked crappy, even with a vast number of
+         polygons, because the day/night terminator didn't exactly line up with
+         the polygon edges.
+       */
+
+#ifndef BLENDED_TERMINATOR
+
+      /* Method 1, use the depth buffer as a stencil.
+
+         - Draw the full "day" sphere;
+         - Clear the depth buffer;
+         - Draw a rotated/tilted half-sphere into the depth buffer only,
+           on the Eastern hemisphere, putting non-zero depth only on the
+           sunlit side;
+         - Draw the full "night" sphere, which will clip to dark parts only.
+
+         That lets us divide the sphere into the two maps, and the dividing
+         line can be at any angle, regardless of polygon layout.
+
+         The half-sphere is scaled slightly larger to avoid polygon fighting,
+         since those triangles won't exactly line up because of the rotation.
+
+         The downside of this is that the day/night terminator is 100% sharp.
+      */
+      glClear (GL_DEPTH_BUFFER_BIT);
       glColorMask (0, 0, 0, 0);
+      glDisable (GL_TEXTURE_2D);
       glPushMatrix();
       glRotatef (gp->tilt, 1, 0, 0);
       glScalef (1.01, 1.01, 1.01);
-      glCallList (gp->shadowlist);
+      glCallList (gp->shadowlist);             /* Fill in depth on sunlit side */
       mi->polygon_count += resolution*(resolution/2);
       glPopMatrix();
       glColorMask (1, 1, 1, 1);
-      glEnable(GL_TEXTURE_2D);
 
-      glBindTexture (GL_TEXTURE_2D, gp->tex2);
+      if (do_texture)
+        {
+          glEnable (GL_TEXTURE_2D);
+          glBindTexture (GL_TEXTURE_2D, gp->tex2);
+        }
+      else
+        {
+          GLfloat c[] = { 0, 0, 0.5, 1 };
+          glColor4fv (c);
+          if (! do_texture)
+            glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c);
+        }
+
       glPushMatrix();
       glRotatef (gp->z * 360, 0, 0, 1);
-      glCallList (gp->platelist);
+      glCallList (gp->platelist);              /* Fill in color on night side */
       mi->polygon_count += resolution*resolution;
       glPopMatrix();
+
+#else /* BLENDED_TERMINATOR */
+
+      /* Method 2, use the alpha buffer as a stencil.
+         - Draw the full "day" sphere;
+         - Clear the depth buffer; 
+         - Clear the alpha buffer;
+         - Draw a rotated/tilted half-sphere into the alpha buffer only,
+           on the Eastern hemisphere, putting non-zero alpha only on the
+           sunlit side;
+         - Also draw a fuzzy terminator ring into the alpha buffer;
+         - Clear the depth buffer again; 
+         - Draw the full "night" sphere, which will blend to dark parts only.
+       */
+      glColorMask (0, 0, 0, 1);
+      glClear (GL_COLOR_BUFFER_BIT);
+      glClear (GL_DEPTH_BUFFER_BIT);
+      glDisable (GL_TEXTURE_2D);
+
+      glPushMatrix();
+      glRotatef (gp->tilt, 1, 0, 0);
+      glScalef (1.01, 1.01, 1.01);
+      glCallList (gp->shadowlist);             /* Fill in alpha on sunlit side */
+      mi->polygon_count += resolution*(resolution/2);
+      glPopMatrix();
+
+      glClear (GL_DEPTH_BUFFER_BIT);
+
+      glColorMask (1, 1, 1, 1);
+      {
+        GLfloat c[] = { 1, 1, 1, 1 };
+        glColor4fv (c);
+        if (! do_texture)
+          glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c);
+      }
+      glEnable (GL_BLEND);
+      glBlendFunc (GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
+
+      if (do_texture)
+        {
+          glEnable (GL_TEXTURE_2D);
+          glBindTexture (GL_TEXTURE_2D, gp->tex2);
+        }
+      else
+        {
+          GLfloat c[] = { 0, 0, 0.5, 1 };
+          glColor4fv (c);
+          glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c);
+          glEnable (GL_LIGHTING);
+        }
+
+      glPushMatrix();
+      glRotatef (gp->z * 360, 0, 0, 1);
+      glCallList (gp->platelist);              /* Fill in color on night side */
+      mi->polygon_count += resolution*resolution;
+      glPopMatrix();
+      glDisable (GL_BLEND);
+      glBlendFunc (GL_ONE, GL_ZERO);
+
+#endif /* BLENDED_TERMINATOR */
     }
 
   if (gp->draw_axis)
@@ -618,6 +814,8 @@ draw_planet (ModeInfo * mi)
       glCallList (gp->latlonglist);
       mi->polygon_count += 24*24;
       glPopMatrix();
+      if (!wire && !do_texture)
+        glEnable (GL_LIGHTING);
       if (gp->draw_axis) gp->draw_axis--;
     }
   glPopMatrix();
index 44e48db12975ee97b2cf8b3bc19f20426c010e5a..6a62dc9a03225f8fd2348680b8c88d167b54701a 100644 (file)
@@ -9,13 +9,15 @@ glplanet - rotating 3d texture-mapped planet.
 [\-root]
 [\-delay \fInumber\fP]
 [\-image \fIfile\fP]
+[\-image2 \fIfile\fP]
 [\-resolution \fInumber\fP]
 [\-wireframe]
 [\-fps]
 .SH DESCRIPTION
-Draws a planet bouncing around in space.  The built-in image is a map
-of the earth, but you can wrap any texture around the sphere, e.g., the
-planetary textures that come with `ssystem'.
+Draws a planet bouncing around in space.  The built-in images are day and
+night maps of the Earth, but you can wrap any Equirectangular-projected
+map onto the sphere, e.g., the planetary textures included 
+with \fIssystem.\fP
 .SH OPTIONS
 .TP 8
 .B \-visual \fIvisual\fP
@@ -31,11 +33,15 @@ Draw on the root window.
 .B \-delay \fInumber\fP
 Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds.).
 .TP 8
-.B \-images \fIfile\fP
-The texture map to wrap around the planet's surface.
+.B \-image \fIfile\fP
+The day texture map to wrap around the planet's surface.
+.TP 8
+.B \-image2 \fIfile\fP
+The night texture map to wrap around the planet's surface.
+The two will be blended together at the dusk terminator.
 .TP 8
 .B \-resolution
-The resolution of the planet. Default: 128.
+The resolution of the planetary mesh. Default: 128.
 .TP 8
 .B \-wireframe
 Render in wireframe instead of solid.
@@ -54,13 +60,16 @@ stored in the RESOURCE_MANAGER property.
 .SH SEE ALSO
 .BR X (1),
 .BR xscreensaver (1)
+.BR dymaxionmap (1)
+.BR ssystem (1)
 .SH COPYRIGHT
-Copyright \(co 2002 by David Konerding.  Permission to use, copy, modify, 
-distribute, and sell this software and its documentation for any purpose is 
-hereby granted without fee, provided that the above copyright notice appear 
-in all copies and that both that copyright notice and this permission notice
-appear in supporting documentation.  No representations are made about the 
-suitability of this software for any purpose.  It is provided "as is" without
-express or implied warranty.
+Copyright \(co 2002-2018 by David Konerding and Jamie Zawinski.
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation.  No representations are made about the
+suitability of this software for any purpose.  It is provided "as is"
+without express or implied warranty.
 .SH AUTHOR
-David Konerding. 
+David Konerding and Jamie Zawinski
index 4b23035d050e908ade91a8c9b19a50b11b23ac6d..4e42840862fa65c408a9a9d6b977214025cb0027 100644 (file)
@@ -1,4 +1,4 @@
-/* noof, Copyright (c) 2004 Bill Torzewski <billt@worksitez.com>
+/* noof, Copyright (c) 2004-2018 Bill Torzewski <billt@worksitez.com>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 # define release_noof 0
 # define noof_handle_event 0
 #include "xlockmore.h"
+#include "pow2.h"
 
 #ifdef USE_GL /* whole file */
 
 #define N_SHAPES 7
 
-static int dbuf_p = 1;  /* always */
-
 ENTRYPOINT ModeSpecOpt noof_opts = {0, NULL, 0, NULL, NULL};
 
 typedef struct {
@@ -53,6 +52,8 @@ typedef struct {
 
   int tko;
 
+  GLuint screenshot_texture, tex_w, tex_h;
+
 } noof_configuration;
 
 static noof_configuration *bps = NULL;
@@ -379,6 +380,34 @@ draw_noof (ModeInfo *mi)
   if (!bp->glx_context)
     return;
   glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  /* In the olden days, one could just render directly into the front buffer,
+     or fail to clear the back buffer and assume that one's bits were still
+     there. Not so on modern devices, particularly mobile.  So to achieve
+     the effect of frame N+1 accumulating atop frame N, we must save and
+     restore a screenshot of frame N.
+   */
+  if (bp->screenshot_texture)
+    {
+      GLfloat tw = MI_WIDTH(mi)  / (GLfloat) bp->tex_w;
+      GLfloat th = MI_HEIGHT(mi) / (GLfloat) bp->tex_h;
+      glDisable (GL_BLEND);
+      glEnable (GL_TEXTURE_2D);
+      glBindTexture (GL_TEXTURE_2D, bp->screenshot_texture);
+      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+      glBegin (GL_QUADS);
+      glTexCoord2f (0,  0);  glVertex3f (0, 0, 0);
+      glTexCoord2f (tw, 0);  glVertex3f (bp->wd, 0, 0);
+      glTexCoord2f (tw, th); glVertex3f (bp->wd, bp->ht, 0);
+      glTexCoord2f (0,  th); glVertex3f (0, bp->ht, 0);
+      glEnd();
+      glDisable (GL_TEXTURE_2D);
+      glClear (GL_DEPTH_BUFFER_BIT);
+    }
+
   mi->polygon_count = 0;
 
   /**
@@ -404,11 +433,21 @@ draw_noof (ModeInfo *mi)
       mi->polygon_count += drawleaf(bp, i);
   }
 
+  if (bp->screenshot_texture)  /* Store a screenshot into the texture. */
+    {
+      glDisable (GL_BLEND);
+      glEnable (GL_TEXTURE_2D);
+      glBindTexture (GL_TEXTURE_2D, bp->screenshot_texture);
+      glCopyTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, 0, 0,
+                           MI_WIDTH(mi), MI_HEIGHT(mi));
+      check_gl_error("screenshot texture");
+      glDisable (GL_TEXTURE_2D);
+    }
+
   if (mi->fps_p) do_fps (mi);
   glFinish();
 
-  if (dbuf_p)
-    glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi));
+  glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi));
 }
 
 
@@ -416,6 +455,7 @@ ENTRYPOINT void
 reshape_noof(ModeInfo *mi, int w, int h)
 {
   noof_configuration *bp = &bps[MI_SCREEN(mi)];
+  char *s;
   glViewport(0, 0, w, h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -435,7 +475,21 @@ reshape_noof(ModeInfo *mi, int w, int h)
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
 
-  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  if (!bp->screenshot_texture)
+    glGenTextures (1, &bp->screenshot_texture);
+
+  glEnable (GL_TEXTURE_2D);
+  glBindTexture (GL_TEXTURE_2D, bp->screenshot_texture);
+
+  bp->tex_w = to_pow2 (MI_WIDTH(mi));
+  bp->tex_h = to_pow2 (MI_HEIGHT(mi));
+  s = calloc (4, bp->tex_w * bp->tex_h);  /* init with black */
+  glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, bp->tex_w, bp->tex_h, 0,
+                GL_RGBA, GL_UNSIGNED_BYTE, s);
+  check_gl_error ("texture generation");
+  free (s);
+  glDisable (GL_TEXTURE_2D);
+  glClear (GL_COLOR_BUFFER_BIT);
 }
 
 ENTRYPOINT void 
@@ -450,12 +504,12 @@ init_noof (ModeInfo *mi)
 
   bp->glx_context = init_GL(mi);
 
-  glDrawBuffer(dbuf_p ? GL_BACK : GL_FRONT);
   glEnable(GL_LINE_SMOOTH);
   glShadeModel(GL_FLAT);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   for (i = 0; i < N_SHAPES; i++)
     initshapes(bp, i);
+
   reshape_noof (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
 }
 
index 5278e6d36b62f61bf8fc2ee468ea2ae6ef0cdbb7..b82f470e847f51aa68a2de7c306ba9392dbc9967 100644 (file)
@@ -66,7 +66,9 @@ static XrmOptionDescRec opts[] = {
   { "-wander",       ".wander",    XrmoptionNoArg, "True"  },
   { "+wander",       ".wander",    XrmoptionNoArg, "False" },
   { "-symmetry",     ".symmetric", XrmoptionNoArg, "True"   },
+  { "-symmetric",    ".symmetric", XrmoptionNoArg, "True"   },
   { "-no-symmetry",  ".symmetric", XrmoptionNoArg, "False"  },
+  { "-nonsymmetric", ".symmetric", XrmoptionNoArg, "False"  },
   { "-speed",        ".speed",     XrmoptionSepArg, 0 },
   { "-contrast",     ".contrast",  XrmoptionSepArg, 0 },
 };
@@ -227,7 +229,7 @@ init_quasicrystal (ModeInfo *mi)
     }
 
   bp->symmetric_p =
-    get_boolean_resource (MI_DISPLAY (mi), "symmetry", "Symmetry");
+    get_boolean_resource (MI_DISPLAY (mi), "symmetric", "Symmetric");
 
   bp->contrast = get_float_resource (MI_DISPLAY (mi), "contrast", "Contrast");
   if (bp->contrast < 0 || bp->contrast > 100) 
index bf3036a1539bd61ded1953317c36c3227adafa0b..4c46ca0887f4c4fc3e73fb9482c16d9a2093e5e6 100644 (file)
 # include "config.h"
 #endif /* HAVE_CONFIG_H */
 
+extern const char *progname;
+
 #include "quickhull.h"
 
+#include "screenhackI.h" /* for jwxyz_abort */
+
 #include <math.h>   /* sqrt & fabs */
 #include <stdio.h>  /* FILE */
 #include <string.h> /* memcpy */
@@ -1189,6 +1193,22 @@ qh__init_context(qh_context_t* context, qh_vertex_t const* vertices,
   context->newhorizonedges.begin = QH_MALLOC(qh_index_t, nedges);
   context->valid = QH_MALLOC(char, nfaces);
 
+  if (!(context->edges &&
+        context->faces &&
+        context->facestack.begin &&
+        context->scratch.begin &&
+        context->horizonedges.begin &&
+        context->newhorizonedges.begin &&
+        context->valid)) {
+# ifdef HAVE_JWXYZ
+    jwxyz_abort ("%s: out of memory", progname);
+# else
+    fprintf (stderr, "%s: out of memory\n", progname);
+    exit (1);
+# endif
+  }
+
+
   context->vertices = QH_MALLOC(qh_vertex_t, nvertices);
   memcpy(context->vertices, vertices, sizeof(qh_vertex_t) * nvertices);
 
index e482ab6a580617061a58ca731922c86c4d5a60a6..3464c377fe481ede133a8fc7edeb3776c389e99c 100644 (file)
@@ -1,4 +1,4 @@
-/* sonar, Copyright (c) 1998-2017 Jamie Zawinski and Stephen Martin
+/* sonar, Copyright (c) 1998-2018 Jamie Zawinski and Stephen Martin
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -727,7 +727,9 @@ subnet_hosts (sonar_sensor_data *ssd, char **error_ret, char **desc_ret,
         {
           struct in_addr in2;
           unsigned long mask;
-          if (ifa->ifa_addr->sa_family != AF_INET)
+          if (! ifa->ifa_addr)
+            continue;
+          else if (ifa->ifa_addr->sa_family != AF_INET)
             {
               if (pd->debug_p)
                 fprintf (stderr, "%s:     if: %4s: %s\n", progname,
index 82838b40be2e40c83bf17f583ca32d1f5967f522..ac6780b2f6bc9a5d03a15864e8299686b8601e2a 100644 (file)
@@ -1,3 +1,13 @@
+
+
+Man 👨
+Blackula 🧛🏿
+Black male teacher 👨🏿‍🏫
+Female runner 🏃‍♀
+Woman astronaut 🏃‍🚀
+Multi-person group 👩🏿‍👨🏻‍👦🏽‍👧🏿
+
+
 ͠P
 ͠P͠P͠P͠
 P͠
index 942e7f9949aa9fbe18b7dd033f90f60e1d7ee06e..9f3d47c8b831031ee2e313f6c5dac6f3875da88d 100644 (file)
@@ -1,11 +1,17 @@
-# hacks/images/Makefile --- xscreensaver, Copyright (c) 2018 Jamie Zawinski.
+# hacks/images/Makefile.in --- xscreensaver, Copyright (c) 2018 Jamie Zawinski.
+# the `../configure' script generates `hacks/images/Makefile' from this file.
+
 
 srcdir         = .
-UTILS_SRC      = $(srcdir)/../../utils
+VPATH          = ${srcdir} ${srcdir}/bubbles ${srcdir}/m6502 \
+                 ${srcdir}/molecules ${srcdir}/noseguy
+top_srcdir     = ../..
+UTILS_SRC      = $(top_srcdir)/utils
 RM             = rm -f
 
 STAR           = *
 TARFILES       = Makefile \
+                 Makefile.in \
                  $(STAR).png \
                  $(STAR).gif \
                  $(STAR)/$(STAR).png \
@@ -14,21 +20,23 @@ TARFILES    = Makefile \
                  $(STAR)/$(STAR).pov \
                  $(STAR)/$(STAR).txt \
 
-default:: all
-
-all::
-       @if [ ! -d gen ]; then mkdir gen ; fi
-       @for f in *.png */*.png ; do                                    \
-         f2=`echo "$$f" |                                              \
-             sed -e 's@^.*/@@'                                         \
-                 -e 's@^\(.*\)\.\([^./]*\)$$@gen/\1_\2.h@'` ;          \
-         if [ ! -f "$$f2" -o "$$f" -nt "$$f2" ]; then                  \
-           echo $(UTILS_SRC)/bin2c "$$f" "$$f2" ;                      \
-                $(UTILS_SRC)/bin2c "$$f" "$$f2" ;                      \
-         fi ;                                                          \
-       done
-
-clean::
+PNG_HDRS       = $(shell find $(srcdir) -name \*.png | \
+                   sed 's@^.*/\(.*\)\.\(png\)$$@gen/\1_\2.h@')
+
+default: all
+
+all: gen $(PNG_HDRS)
+
+gen:
+       mkdir gen
+
+# %.png dependency below works because VPATH contains subdirs
+# of 'images' dir not only 'images' itself
+gen/%_png.h: %.png
+       echo $(UTILS_SRC)/bin2c "$<" "$@"
+       $(UTILS_SRC)/bin2c "$<" "$@"
+
+clean:
        $(RM) -r gen
 
 echo_tarfiles:
diff --git a/hacks/images/Makefile.in b/hacks/images/Makefile.in
new file mode 100644 (file)
index 0000000..497ebfc
--- /dev/null
@@ -0,0 +1,54 @@
+# hacks/images/Makefile.in --- xscreensaver, Copyright (c) 2018 Jamie Zawinski.
+# the `../configure' script generates `hacks/images/Makefile' from this file.
+
+@SET_MAKE@
+srcdir         = @srcdir@
+VPATH          = ${srcdir} ${srcdir}/bubbles ${srcdir}/m6502 \
+                 ${srcdir}/molecules ${srcdir}/noseguy
+top_srcdir     = @top_srcdir@
+UTILS_SRC      = $(top_srcdir)/utils
+RM             = rm -f
+
+STAR           = *
+TARFILES       = Makefile \
+                 Makefile.in \
+                 $(STAR).png \
+                 $(STAR).gif \
+                 $(STAR)/$(STAR).png \
+                 $(STAR)/$(STAR).asm \
+                 $(STAR)/$(STAR).pdb \
+                 $(STAR)/$(STAR).pov \
+                 $(STAR)/$(STAR).txt \
+
+PNG_HDRS       = $(shell find $(srcdir) -name \*.png | \
+                   sed 's@^.*/\(.*\)\.\(png\)$$@gen/\1_\2.h@')
+
+default: all
+
+all: gen $(PNG_HDRS)
+
+gen:
+       mkdir gen
+
+# %.png dependency below works because VPATH contains subdirs
+# of 'images' dir not only 'images' itself
+gen/%_png.h: %.png
+       echo $(UTILS_SRC)/bin2c "$<" "$@"
+       $(UTILS_SRC)/bin2c "$<" "$@"
+
+clean:
+       $(RM) -r gen
+
+echo_tarfiles:
+       @echo $(TARFILES)
+
+install:
+install-program:
+install-man:
+install-strip:
+uninstall:
+uninstall-program:
+uninstall-man:
+depend:
+distdepend:
+tags:
diff --git a/hacks/images/dymaxionmap.png b/hacks/images/dymaxionmap.png
deleted file mode 100644 (file)
index 2718c3a..0000000
Binary files a/hacks/images/dymaxionmap.png and /dev/null differ
diff --git a/hacks/images/earth_flat.png b/hacks/images/earth_flat.png
new file mode 100644 (file)
index 0000000..e3e1b60
Binary files /dev/null and b/hacks/images/earth_flat.png differ
diff --git a/hacks/images/testcard_bbcf.png b/hacks/images/testcard_bbcf.png
new file mode 100644 (file)
index 0000000..2a71585
Binary files /dev/null and b/hacks/images/testcard_bbcf.png differ
diff --git a/hacks/images/testcard_pm5544.png b/hacks/images/testcard_pm5544.png
new file mode 100644 (file)
index 0000000..37a292a
Binary files /dev/null and b/hacks/images/testcard_pm5544.png differ
diff --git a/hacks/images/testcard_rca.png b/hacks/images/testcard_rca.png
new file mode 100644 (file)
index 0000000..220f616
Binary files /dev/null and b/hacks/images/testcard_rca.png differ
index cbb6fae9f09fec5388927d8b6f62563c63f43178..78601439d9743fa1271803e2be963c8dba81bf6f 100644 (file)
@@ -696,6 +696,7 @@ static void inter_init(Display* dpy, Window win, struct inter_context* c)
   int mono;
   int gray;
   int radius;
+  double scale = 1;
   XGCValues val;
   Bool dbuf = get_boolean_resource (dpy, "doubleBuffer", "Boolean");
 
@@ -749,6 +750,9 @@ static void inter_init(Display* dpy, Window win, struct inter_context* c)
   if(radius < 1)
     radius = 1;
 
+  if (xgwa.width > 2560) scale = 3.5;  /* Retina displays */
+  radius *= scale;
+
   create_image(dpy, c, &xgwa);
 
   if(!mono) {
@@ -843,7 +847,7 @@ static void inter_init(Display* dpy, Window win, struct inter_context* c)
       ((float)radius);
     c->wave_height[i] = 
       (unsigned)
-      ((max + max*cos(fi/50.0)) / 2.0);
+      ((max + max*cos(fi/(50.0 * scale))) / 2.0);
   }
 
   c->source = calloc(c->count, sizeof(struct inter_source));
index d18fa3da3e834179d46985e32c8b248e445d39ce..9ef0e7a1e26f0ea1b0690d417aef8db1e83a2502 100644 (file)
@@ -40,6 +40,9 @@
 #include "screenhackI.h"
 #include "recanim.h"
 
+#undef gettimeofday  /* wrapped by recanim.h */
+#undef time
+
 struct record_anim_state {
   Screen *screen;
   Window window;
@@ -58,6 +61,62 @@ struct record_anim_state {
 # endif /* !USE_GL */
 };
 
+
+static double
+double_time (void)
+{
+  struct timeval now;
+# ifdef GETTIMEOFDAY_TWO_ARGS
+  struct timezone tzp;
+  gettimeofday(&now, &tzp);
+# else
+  gettimeofday(&now);
+# endif
+
+  return (now.tv_sec + ((double) now.tv_usec * 0.000001));
+}
+
+
+/* Some of the hacks set their timing based on the real-world wall clock,
+   so to make the animations record at a sensible speed, we need to slow
+   down that clock by discounting the time taken up by snapshotting and
+   saving the frame.
+ */
+static double recanim_time_warp = 0;
+
+void
+screenhack_record_anim_gettimeofday (struct timeval *tv
+# ifdef GETTIMEOFDAY_TWO_ARGS
+                                     , struct timezone *tz
+# endif
+                                     )
+{
+  gettimeofday (tv
+# ifdef GETTIMEOFDAY_TWO_ARGS
+                , tz
+# endif
+                );
+  tv->tv_sec  -= (time_t) recanim_time_warp;
+  tv->tv_usec -= 1000000 * (recanim_time_warp - (time_t) recanim_time_warp);
+}
+
+time_t
+screenhack_record_anim_time (time_t *o)
+{
+  struct timeval tv;
+# ifdef GETTIMEOFDAY_TWO_ARGS
+  struct timezone tz;
+# endif
+  screenhack_record_anim_gettimeofday (&tv
+# ifdef GETTIMEOFDAY_TWO_ARGS
+                                       , &tz
+# endif
+                                       );
+  if (o) *o = tv.tv_sec;
+  return tv.tv_sec;
+}
+
+
 record_anim_state *
 screenhack_record_anim_init (Screen *screen, Window window, int target_frames)
 {
@@ -147,6 +206,7 @@ void
 screenhack_record_anim (record_anim_state *st)
 {
   int bytes_per_line = st->xgwa.width * 3;
+  double start_time = double_time();
 
 # ifndef USE_GL
 
@@ -264,6 +324,8 @@ screenhack_record_anim (record_anim_state *st)
 
   if (++st->frame_count >= st->target_frames)
     screenhack_record_anim_free (st);
+
+  recanim_time_warp += double_time() - start_time;
 }
 
 
index acb1b929cf8d4380a58f9fb9379a192e6483d1e3..a7e8cf32134c7d97b5c9cc5b21d31217079bd15c 100644 (file)
@@ -1,4 +1,4 @@
-/* recanim, Copyright (c) 2014 Jamie Zawinski <jwz@jwz.org>
+/* recanim, Copyright (c) 2014-2018 Jamie Zawinski <jwz@jwz.org>
  * Record animation frames of the running screenhack.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -24,4 +24,13 @@ extern record_anim_state *screenhack_record_anim_init (Screen *, Window,
 extern void screenhack_record_anim (record_anim_state *);
 extern void screenhack_record_anim_free (record_anim_state *);
 
+extern time_t screenhack_record_anim_time (time_t *);
+extern void screenhack_record_anim_gettimeofday (struct timeval *
+# ifdef GETTIMEOFDAY_TWO_ARGS
+                                                 , struct timezone *
+# endif
+                                                 );
+#define time screenhack_record_anim_time
+#define gettimeofday screenhack_record_anim_gettimeofday
+
 #endif /* __XSCREENSAVER_RECORD_ANIM_H__ */
index 0a7b0d59fd4ccbabed687cd94891f4f028558685..b53ef746df6f63d4ef9fe35f8be08882396154e6 100644 (file)
 #include "fps.h"
 #include "font-retry.h"
 
+#ifdef HAVE_RECORD_ANIM
+# include "recanim.h"
+#endif
+
 /* Be Posixly correct */
 #undef  bzero
 #define bzero  __ERROR_use_memset_not_bzero_in_xscreensaver__
index 4fcf7b176c77a39e50c0d49333b336cbb87f6aba..b9a8bd93ee6f05d1307d7272948e2767e5615b22 100644 (file)
@@ -12,9 +12,6 @@
 #include "screenhack.h"
 #include "delaunay.h"
 
-#undef DO_VORONOI
-
-
 #ifndef HAVE_JWXYZ
 # define XK_MISCELLANY
 # include <X11/keysymdef.h>
@@ -43,8 +40,20 @@ struct state {
   async_load_state *img_loader;
   XRectangle geom;
   Bool button_down_p;
+  enum { DELAUNAY, VORONOI } mode;
 };
 
+typedef struct {
+  int npoints;
+  XPoint ctr;
+  XPoint *p;
+} voronoi_polygon;
+
+typedef struct {
+  XPoint p;
+  double slope;
+} voronoi_pa;
+
 
 /* Returns the current time in seconds as a double.
  */
@@ -276,6 +285,23 @@ analyze (struct state *st)
   unsigned int w, h, bw, d;
   unsigned long histo[256];
 
+  {
+    char *s = get_string_resource (st->dpy, "mode", "Mode");
+    if (!s || !*s || !strcasecmp(s, "random"))
+      st->mode = (random() & 1) ? DELAUNAY : VORONOI;
+    else if (!strcasecmp(s, "delaunay"))
+      st->mode = DELAUNAY;
+    else if (!strcasecmp(s, "voronoi"))
+      st->mode = VORONOI;
+    else
+      {
+        fprintf (stderr, 
+                 "%s: mode must be delaunay, voronoi or random, not \"%s\"\n",
+                 progname, s);
+        exit (1);
+      }
+  }
+
   flush_cache (st);
 
   /* Convert the loaded pixmap to an XImage.
@@ -406,7 +432,6 @@ analyze (struct state *st)
 }
 
 
-#ifndef DO_VORONOI
 /* True if the distance between any two corners is too small for it to
    make sense to draw an outline around this triangle.
  */
@@ -422,17 +447,47 @@ small_triangle_p (const XPoint *p)
   if (abs (p[2].y - p[0].y) < min) return True;
   return False;
 }
-#endif /* DO_VORONOI */
 
-#ifdef DO_VORONOI
+static Bool
+small_cell_p (const voronoi_polygon *p)
+{
+  int min = 4;
+  if (abs (p->p[0].x - p->ctr.x) < min) return True;
+  if (abs (p->p[0].y - p->ctr.y) < min) return True;
+  return False;
+}
+
+
+static int
+cmp_ccw (const void *v1, const void *v2)
+{
+  const voronoi_pa *p1,*p2;
+  p1 = v1;
+  p2 = v2;
+  if      (p1->slope < p2->slope) return -1;
+  else if (p1->slope > p2->slope) return  1;
+  return 0;
+}
+
+static void
+sort_ccw (XPoint *ctr, XPoint *p, int npoints)
+{
+  voronoi_pa *pa = (void *) malloc (npoints * sizeof(*pa));
+  int i;
+  for (i = 0; i < npoints; i++)
+    {
+      pa[i].p = p[i];
+      pa[i].slope = atan2 (p[i].x - ctr->x, p[i].y - ctr->y);
+    }
+  qsort (pa, npoints, sizeof(*pa), cmp_ccw);
+  for (i = 0; i < npoints; i++)
+    p[i] = pa[i].p;
+  free (pa);
+}
 
-typedef struct {
-  int npoints;
-  XPoint *p;
-} voronoi_polygon;
 
 static voronoi_polygon *
-delaunay_to_voronoi (int np, XYZ *p, int nv, ITRIANGLE *v)
+delaunay_to_voronoi (int np, XYZ *p, int nv, ITRIANGLE *v, double scale)
 {
   struct tri_list {
     int count, size;
@@ -444,15 +499,6 @@ delaunay_to_voronoi (int np, XYZ *p, int nv, ITRIANGLE *v)
     calloc (np + 1, sizeof(*vert_to_tri));
   voronoi_polygon *out = (voronoi_polygon *) calloc (np + 1, sizeof(*out));
 
-/*
-  for (i = 0; i < np; i++)
-    printf("# p %d = %d %d\n", i, (int)p[i].x, (int)p[i].y);
-  printf("\n");
-  for (i = 0; i < nv; i++)
-    printf("@ t %d = %d %d %d\n", i, (int)v[i].p1, (int)v[i].p2, (int)v[i].p3);
-  printf("\n");
-*/
-
   /* Iterate the triangles to construct a map of vertices to the
      triangles that contain them.
    */
@@ -474,59 +520,47 @@ delaunay_to_voronoi (int np, XYZ *p, int nv, ITRIANGLE *v)
         }
     }
 
-/*
-  for (i = 0; i < nv; i++)
-    {
-      struct tri_list *t = &vert_to_tri[i];
-      printf("p %d [%d %d]:", i, (int)p[i].x, (int)p[i].y);
-      for (j = 0; j < t->count; j++) {
-        int tt = t->tri[j];
-        printf(" t %d [%d(%d %d) %d(%d %d) %d(%d %d)]",
-               tt,
-               (int)v[tt].p1,
-               (int)p[v[tt].p1].x, (int)p[v[tt].p1].y,
-               (int)v[tt].p2,
-               (int)p[v[tt].p2].x, (int)p[v[tt].p2].y,
-               (int)v[tt].p3,
-               (int)p[v[tt].p3].x, (int)p[v[tt].p3].y
-               );
-        if (tt < 0 || tt >= nv) abort();
-      }
-      printf("\n");
-    }
-*/
-
   /* For every vertex, compose a polygon whose corners are the centers
      of each triangle using that vertex.  Skip any with less than 3 points.
+
+     This is currently omitting the voronoi cells that should touch the edges
+     of the outer rectangle. Not sure exactly how to include those.
    */
   for (i = 0; i < np; i++)
     {
+      long ctr_x = 0, ctr_y = 0;
       struct tri_list *t = &vert_to_tri[i];
       int n = t->count;
       if (n < 3) n = 0;
       out[i].npoints = n;
+      if (n == 0) continue;
+      out[i].ctr.x = out[i].ctr.y = 0;
       out[i].p = (n > 0
                   ? (XPoint *) calloc (out[i].npoints + 1, sizeof (*out[i].p))
                   : 0);
-//printf("%d: ", i);
       for (j = 0; j < out[i].npoints; j++)
         {
           ITRIANGLE *tt = &v[t->tri[j]];
-          out[i].p[j].x = (p[tt->p1].x + p[tt->p2].x + p[tt->p3].x) / 3;
-          out[i].p[j].y = (p[tt->p1].y + p[tt->p2].y + p[tt->p3].y) / 3;
-//printf(" [%d: %d %d]", j, out[i].p[j].x, out[i].p[j].y);
+          out[i].p[j].x = scale * (p[tt->p1].x + p[tt->p2].x + p[tt->p3].x) / 3;
+          out[i].p[j].y = scale * (p[tt->p1].y + p[tt->p2].y + p[tt->p3].y) / 3;
+          ctr_x += out[i].p[j].x;
+          ctr_y += out[i].p[j].y;
         }
-//printf("\n");
+      out[i].ctr.x = ctr_x / out[i].npoints;  /* long -> short */
+      out[i].ctr.y = ctr_y / out[i].npoints;
+      if (out[i].ctr.x < 0) abort();
+      if (out[i].ctr.y < 0) abort();
+      sort_ccw (&out[i].ctr, out[i].p, out[i].npoints);
     }
 
+  for (i = 0; i < np+1; i++)
+    if (vert_to_tri[i].tri)
+      free (vert_to_tri[i].tri);
   free (vert_to_tri);
+
   return out;
 }
 
-#endif /* DO_VORONOI */
-
-
-
 
 static void
 tessellate (struct state *st)
@@ -667,83 +701,92 @@ tessellate (struct state *st)
       XFillRectangle (st->dpy, st->output, st->pgc, 
                       0, 0, st->xgwa.width, st->xgwa.height);
 
-#ifdef DO_VORONOI
-
-      voronoi_polygon *polys = delaunay_to_voronoi (nv, p, ntri, v);
-      for (i = 0; i < nv; i++)
+      switch (st->mode) {
+      case VORONOI:
         {
-          if (polys[i].npoints >= 3)
+          voronoi_polygon *polys =
+            delaunay_to_voronoi (nv, p, ntri, v, wscale);
+          for (i = 0; i < nv; i++)
             {
-              unsigned long color = XGetPixel (st->img, p[i].x, p[i].y);
-              XSetForeground (st->dpy, st->pgc, color);
-              XFillPolygon (st->dpy, st->output, st->pgc,
-                            polys[i].p, polys[i].npoints,
-                            Convex, CoordModeOrigin);
-
-              if (st->outline_p)
+              if (polys[i].npoints >= 3)
                 {
-                  XColor bd;
-                  double scale = 0.8;
-                  bd.pixel = color;
-                  XQueryColor (st->dpy, st->xgwa.colormap, &bd);
-                  bd.red   *= scale;
-                  bd.green *= scale;
-                  bd.blue  *= scale;
-
-                  /* bd.red = 0xFFFF; bd.green = 0; bd.blue = 0; */
-
-                  XAllocColor (st->dpy, st->xgwa.colormap, &bd);
-                  XSetForeground (st->dpy, st->pgc, bd.pixel);
-                  XDrawLines (st->dpy, st->output, st->pgc,
-                              polys[i].p, polys[i].npoints,
-                              CoordModeOrigin);
-                  XFreeColors (st->dpy, st->xgwa.colormap, &bd.pixel, 1, 0);
+                  unsigned long color = XGetPixel (st->img,
+                                                   polys[i].ctr.x / wscale,
+                                                   polys[i].ctr.y / wscale);
+                  XSetForeground (st->dpy, st->pgc, color);
+                  XFillPolygon (st->dpy, st->output, st->pgc,
+                                polys[i].p, polys[i].npoints,
+                                Convex, CoordModeOrigin);
+
+                  if (st->outline_p && !small_cell_p(&polys[i]))
+                    {
+                      XColor bd;
+                      double scale = 0.8;
+                      bd.pixel = color;
+                      XQueryColor (st->dpy, st->xgwa.colormap, &bd);
+                      bd.red   *= scale;
+                      bd.green *= scale;
+                      bd.blue  *= scale;
+
+                      /* bd.red = 0xFFFF; bd.green = 0; bd.blue = 0; */
+
+                      XAllocColor (st->dpy, st->xgwa.colormap, &bd);
+                      XSetForeground (st->dpy, st->pgc, bd.pixel);
+                      XDrawLines (st->dpy, st->output, st->pgc,
+                                  polys[i].p, polys[i].npoints,
+                                  CoordModeOrigin);
+                      XFreeColors (st->dpy, st->xgwa.colormap, &bd.pixel,
+                                   1, 0);
+                    }
                 }
+              if (polys[i].p) free (polys[i].p);
+              polys[i].p = 0;
             }
-          if (polys[i].p) free (polys[i].p);
-          polys[i].p = 0;
+          free (polys);
         }
-      free (polys);
-
-#else /* !DO_VORONOI */
+        break;
 
-      for (i = 0; i < ntri; i++)
-        {
-          XPoint xp[3];
-          unsigned long color;
-          xp[0].x = p[v[i].p1].x * wscale; xp[0].y = p[v[i].p1].y * wscale;
-          xp[1].x = p[v[i].p2].x * wscale; xp[1].y = p[v[i].p2].y * wscale;
-          xp[2].x = p[v[i].p3].x * wscale; xp[2].y = p[v[i].p3].y * wscale;
-
-          /* Set the color of this triangle to the pixel at its midpoint. */
-          color = XGetPixel (st->img,
-                             (xp[0].x + xp[1].x + xp[2].x) / (3 * wscale),
-                             (xp[0].y + xp[1].y + xp[2].y) / (3 * wscale));
-
-          XSetForeground (st->dpy, st->pgc, color);
-          XFillPolygon (st->dpy, st->output, st->pgc, xp, countof(xp),
-                        Convex, CoordModeOrigin);
-
-          if (st->outline_p && !small_triangle_p(xp))
-            {  /* Border the triangle with a color that is darker */
-              XColor bd;
-              double scale = 0.8;
-              bd.pixel = color;
-              XQueryColor (st->dpy, st->xgwa.colormap, &bd);
-              bd.red   *= scale;
-              bd.green *= scale;
-              bd.blue  *= scale;
-
-              /* bd.red = 0xFFFF; bd.green = 0; bd.blue = 0; */
-
-              XAllocColor (st->dpy, st->xgwa.colormap, &bd);
-              XSetForeground (st->dpy, st->pgc, bd.pixel);
-              XDrawLines (st->dpy, st->output, st->pgc,
-                          xp, countof(xp), CoordModeOrigin);
-              XFreeColors (st->dpy, st->xgwa.colormap, &bd.pixel, 1, 0);
-            }
-        }
-#endif /* !DO_VORONOI */
+      case DELAUNAY:
+        for (i = 0; i < ntri; i++)
+          {
+            XPoint xp[3];
+            unsigned long color;
+            xp[0].x = p[v[i].p1].x * wscale; xp[0].y = p[v[i].p1].y * wscale;
+            xp[1].x = p[v[i].p2].x * wscale; xp[1].y = p[v[i].p2].y * wscale;
+            xp[2].x = p[v[i].p3].x * wscale; xp[2].y = p[v[i].p3].y * wscale;
+
+            /* Set the color of this triangle to the pixel at its midpoint. */
+            color = XGetPixel (st->img,
+                               (xp[0].x + xp[1].x + xp[2].x) / (3 * wscale),
+                               (xp[0].y + xp[1].y + xp[2].y) / (3 * wscale));
+
+            XSetForeground (st->dpy, st->pgc, color);
+            XFillPolygon (st->dpy, st->output, st->pgc, xp, countof(xp),
+                          Convex, CoordModeOrigin);
+
+            if (st->outline_p && !small_triangle_p(xp))
+              {        /* Border the triangle with a color that is darker */
+                XColor bd;
+                double scale = 0.8;
+                bd.pixel = color;
+                XQueryColor (st->dpy, st->xgwa.colormap, &bd);
+                bd.red   *= scale;
+                bd.green *= scale;
+                bd.blue  *= scale;
+
+                /* bd.red = 0xFFFF; bd.green = 0; bd.blue = 0; */
+
+                XAllocColor (st->dpy, st->xgwa.colormap, &bd);
+                XSetForeground (st->dpy, st->pgc, bd.pixel);
+                XDrawLines (st->dpy, st->output, st->pgc,
+                            xp, countof(xp), CoordModeOrigin);
+                XFreeColors (st->dpy, st->xgwa.colormap, &bd.pixel, 1, 0);
+              }
+          }
+        break;
+      default:
+        abort();
+      }
 
       free (p);
       free (v);
@@ -935,6 +978,7 @@ static const char *tessellimage_defaults [] = {
   ".lowrez:                     True",
   "*dontClearRoot:             True",
   "*fpsSolid:                  true",
+  "*mode:                      random",
   "*delay:                     30000",
   "*duration:                  120",
   "*duration2:                 0.4",
@@ -956,6 +1000,7 @@ static XrmOptionDescRec tessellimage_options [] = {
   { "-duration2",      ".duration2",           XrmoptionSepArg, 0 },
   { "-max-depth",      ".maxDepth",            XrmoptionSepArg, 0 },
   { "-max-resolution", ".maxResolution",       XrmoptionSepArg, 0 },
+  { "-mode",           ".mode",                XrmoptionSepArg, 0 },
   { "-outline",                ".outline",             XrmoptionNoArg, "True"  },
   { "-no-outline",     ".outline",             XrmoptionNoArg, "False" },
   { "-fill-screen",    ".fillScreen",          XrmoptionNoArg, "True"  },
index 17732d7b6fe9552a3378f44f2382125be135098f..cc2162111171ff5bdef371fb0248fc62c15d1bb8 100644 (file)
@@ -370,7 +370,8 @@ backdrop (struct testx11 *st, Drawable t)
     const float s0 = 2 * M_PI / tile_count;
     float y_fac = sin ((y + st->frame / 16.0) * s0);
     for (x = 0; x != tile_count; ++x) {
-      unsigned c = ((sin ((x + st->frame / 8.0) * s0) * y_fac) - 1) / 2 * st->backdrop_ncolors / 2;
+      int c = ((sin ((x + st->frame / 8.0) * s0) * y_fac) - 1) / 2 *
+              st->backdrop_ncolors / 2;
       c = (c + st->frame) % st->backdrop_ncolors;
       XSetBackground (st->dpy, st->backdrop_black_gc,
                       st->backdrop_colors[c].pixel);
diff --git a/hacks/vfeedback.c b/hacks/vfeedback.c
new file mode 100644 (file)
index 0000000..5b482a7
--- /dev/null
@@ -0,0 +1,628 @@
+/* vfeedback, Copyright (c) 2018 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ *
+ * Simulates video feedback: pointing a video camera at an NTSC television.
+ *
+ * Created: 4-Aug-2018.
+ *
+ * TODO:
+ *
+ * - Figure out better UI gestures on mobile to pan, zoom and rotate.
+ *
+ * - When zoomed in really far, grab_rectangle should decompose pixels
+ *   into RGB phosphor dots.
+ *
+ * - Maybe load an image and chroma-key it, letting transparency bleed,
+ *   for that Amiga Genlock, Cabaret Voltaire look.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include "screenhack.h"
+#include "analogtv.h"
+
+#include <time.h>
+
+#undef DEBUG
+#undef DARKEN
+
+#ifdef DEBUG
+# include "ximage-loader.h"
+# include "images/gen/testcard_bbcf_png.h"
+#endif
+
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#define RANDSIGN() ((random() & 1) ? 1 : -1)
+
+struct state {
+  Display *dpy;
+  Window window;
+  XWindowAttributes xgwa;
+  int w, h;
+  Pixmap pix;
+  GC gc;
+  double start, last_time;
+  double noise;
+  double zoom, rot;
+  double value, svalue, speed, dx, dy, ds, dth;
+
+  struct { double x, y, w, h, th; } rect, orect;
+  struct { int x, y, s; } specular;
+
+  enum { POWERUP, IDLE, MOVE } state;
+  analogtv *tv;
+  analogtv_reception rec;
+  Bool button_down_p;
+  int mouse_x, mouse_y;
+  double mouse_th;
+  Bool dragmode;
+
+# ifdef DEBUG
+  XImage *tcimg;
+# endif
+
+};
+
+
+static void
+twiddle_knobs (struct state *st)
+{
+  st->rec.ofs = random() % ANALOGTV_SIGNAL_LEN;                /* roll picture once */
+  st->rec.level = 0.8 + frand(1.0);  /* signal strength (low = dark, static) */
+  st->tv->color_control    = frand(1.0) * RANDSIGN();
+  st->tv->contrast_control = 0.4 + frand(1.0);
+  st->tv->tint_control     = frand(360);
+}
+
+
+static void
+twiddle_camera (struct state *st)
+{
+# if 0
+  st->rect.x  = 0;
+  st->rect.y  = 0;
+  st->rect.w  = 1;
+  st->rect.h  = 1;
+  st->rect.th = 0;
+# else
+  st->rect.x = frand(0.1) * RANDSIGN();
+  st->rect.y = frand(0.1) * RANDSIGN();
+  st->rect.w = st->rect.h = 1 + frand(0.4) * RANDSIGN();
+  st->rect.th = 0.2 + frand(1.0) * RANDSIGN();
+# endif
+}
+
+
+static void *
+vfeedback_init (Display *dpy, Window window)
+{
+  struct state *st = (struct state *) calloc (1, sizeof(*st));
+  XGCValues gcv;
+
+  st->dpy = dpy;
+  st->window = window;
+  st->tv = analogtv_allocate (st->dpy, st->window);
+  analogtv_set_defaults (st->tv, "");
+  st->tv->need_clear = 1;
+  st->rec.input = analogtv_input_allocate();
+  analogtv_setup_sync (st->rec.input, 1, 0);
+  st->tv->use_color = 1;
+  st->tv->powerup = 0;
+  st->rec.multipath = 0;
+  twiddle_camera (st);
+  twiddle_knobs (st);
+  st->noise = get_float_resource (st->dpy, "noise", "Float");
+  st->speed = get_float_resource (st->dpy, "speed", "Float");
+
+  XGetWindowAttributes (dpy, window, &st->xgwa);
+
+  st->state = POWERUP;
+  st->value = 0;
+
+  st->w = 640;
+  st->h = 480;
+  gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap,
+                                       "foreground", "Foreground");
+  st->gc = XCreateGC (dpy, st->window, GCForeground, &gcv);
+
+  st->orect = st->rect;
+
+# ifdef DEBUG
+  {
+    int w, h;
+    Pixmap p;
+    p = image_data_to_pixmap (dpy, window,
+                              testcard_bbcf_png, sizeof(testcard_bbcf_png),
+                              &w, &h, 0);
+    st->tcimg = XGetImage (dpy, p, 0, 0, w, h, ~0L, ZPixmap);
+    XFreePixmap (dpy, p);
+  }
+# endif
+
+# ifndef HAVE_JWXYZ
+  XSelectInput (dpy, window,
+                PointerMotionMask | st->xgwa.your_event_mask);
+# endif
+
+  return st;
+}
+
+
+static double
+ease_fn (double r)
+{
+  return cos ((r/2 + 1) * M_PI) + 1; /* Smooth curve up, end at slope 1. */
+}
+
+
+static double
+ease_ratio (double r)
+{
+  double ease = 0.5;
+  if      (r <= 0)     return 0;
+  else if (r >= 1)     return 1;
+  else if (r <= ease)  return     ease * ease_fn (r / ease);
+  else if (r > 1-ease) return 1 - ease * ease_fn ((1 - r) / ease);
+  else                 return r;
+}
+
+
+static XImage *
+grab_rectangle (struct state *st)
+{
+  XImage *in, *out;
+
+  /* Under XQuartz we can't just do XGetImage on the Window, we have to
+     go through an intermediate Pixmap first.  I don't understand why.
+   */
+  if (! st->pix)
+    st->pix = XCreatePixmap (st->dpy, st->window, 
+                             st->xgwa.width, st->xgwa.height, st->xgwa.depth);
+
+  XCopyArea (st->dpy, st->window, st->pix, st->gc, 0, 0,
+             st->xgwa.width, st->xgwa.height, 0, 0);
+
+  if (st->specular.s)
+    {
+      double p = 0.2;
+      double r = (st->svalue <    p ? st->svalue/p :
+                  st->svalue >= 1-p ? (1-st->svalue)/p :
+                  1);
+      double s = st->specular.s * ease_ratio (r * 2);
+      XFillArc (st->dpy, st->pix, st->gc,
+                st->specular.x - s/2,
+                st->specular.y - s/2,
+                s, s, 0, 360*64);
+    }
+
+# ifdef DEBUG
+  in = st->tcimg;
+# else
+  in = XGetImage (st->dpy, st->pix,
+                  0, 0, st->xgwa.width, st->xgwa.height,
+                  ~0L, ZPixmap);
+  /* Could actually use st->tv->image here, except we don't have the
+     subrectangle being used (overall_top, usewidth, etc.) */
+# endif
+
+  out = XCreateImage (st->dpy, st->xgwa.visual, st->xgwa.depth,
+                      ZPixmap, 0, NULL,
+                      st->w, st->h, 8, 0);
+
+  if (! in) abort();
+  if (! out) abort();
+  out->data = (char *) calloc (out->height, out->bytes_per_line);
+  if (! out->data) abort();
+
+  {
+    double C = cos (st->rect.th);
+    double S = sin (st->rect.th);
+    unsigned long black = BlackPixelOfScreen (st->xgwa.screen);
+    int ox, oy;
+    for (oy = 0; oy < out->height; oy++)
+      {
+        double doy = (double) oy / out->height;
+        double diy = st->rect.h * doy + st->rect.y - 0.5;
+
+        float dix_mul = (float) st->rect.w / out->width;
+        float dix_add = (-0.5 + st->rect.x) * st->rect.w;
+        float ix_add = (-diy * S + 0.5) * in->width;
+        float iy_add = ( diy * C + 0.5) * in->height;
+        float ix_mul = C * in->width;
+        float iy_mul = S * in->height;
+
+        ix_add += dix_add * ix_mul;
+        iy_add += dix_add * iy_mul;
+        ix_mul *= dix_mul;
+        iy_mul *= dix_mul;
+
+        if (in->bits_per_pixel == 32 &&
+            out->bits_per_pixel == 32)
+          {
+            /* Unwrapping XGetPixel and XPutPixel gains us several FPS here */
+            uint32_t *out_line =
+              (uint32_t *) (out->data + out->bytes_per_line * oy);
+            for (ox = 0; ox < out->width; ox++)
+              {
+                float dix = ox;
+                int ix = dix * ix_mul + ix_add;
+                int iy = dix * iy_mul + iy_add;
+                unsigned long p = (ix >= 0 && ix < in->width &&
+                                   iy >= 0 && iy < in->height
+                                   ? ((uint32_t *)
+                                      (in->data + in->bytes_per_line * iy))[ix]
+                                   : black);
+# ifdef HAVE_JWXYZ
+                p |= black;   /* We get 0 instead of BlackPixel... */
+# endif
+                out_line[ox] = p;
+              }
+          }
+        else
+          for (ox = 0; ox < out->width; ox++)
+            {
+              float dix = ox;
+              int ix = dix * ix_mul + ix_add;
+              int iy = dix * iy_mul + iy_add;
+              unsigned long p = (ix >= 0 && ix < in->width &&
+                                 iy >= 0 && iy < in->height
+                                 ? XGetPixel (in, ix, iy)
+                                 : black);
+# ifdef HAVE_JWXYZ
+              p |= black;   /* We get 0 instead of BlackPixel... */
+# endif
+              XPutPixel (out, ox, oy, p);
+            }
+      }
+  }
+
+# ifndef DEBUG
+  XDestroyImage (in);
+# endif
+
+  return out;
+}
+
+
+static double
+double_time (void)
+{
+  struct timeval now;
+# ifdef GETTIMEOFDAY_TWO_ARGS
+  struct timezone tzp;
+  gettimeofday(&now, &tzp);
+# else
+  gettimeofday(&now);
+# endif
+
+  return (now.tv_sec + ((double) now.tv_usec * 0.000001));
+}
+
+
+static unsigned long
+vfeedback_draw (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
+  const analogtv_reception *rec = &st->rec;
+  double then = double_time(), now, timedelta;
+  XImage *img = 0;
+
+  switch (st->state) {
+  case POWERUP: case IDLE: break;
+  case MOVE:
+    st->rect.x  = st->orect.x  + st->dx  * ease_ratio (st->value);
+    st->rect.y  = st->orect.y  + st->dy  * ease_ratio (st->value);
+    st->rect.th = st->orect.th + st->dth * ease_ratio (st->value);
+    st->rect.w  = st->orect.w * (1 + (st->ds * ease_ratio (st->value)));
+    st->rect.h  = st->orect.h * (1 + (st->ds * ease_ratio (st->value)));
+    break;
+  default:
+    abort();
+    break;
+  }
+
+  if (! st->button_down_p)
+    {
+      st->value  += 0.03 * st->speed;
+      if (st->value > 1 || st->state == POWERUP)
+        {
+          st->orect = st->rect;
+          st->value = 0;
+          st->dx = st->dy = st->ds = st->dth = 0;
+
+          switch (st->state) {
+          case POWERUP:
+            /* Wait until the monitor has warmed up before turning on
+               the camcorder? */
+            /* if (st->tv->powerup > 4.0) */
+              st->state = IDLE;
+            break;
+          case IDLE:
+            st->state = MOVE;
+            if (! (random() % 5))
+              st->ds = frand(0.2) * RANDSIGN();                /* zoom */
+            if (! (random() % 3))
+              st->dth = frand(0.2) * RANDSIGN();       /* rotate */
+            if (! (random() % 8))
+              st->dx = frand(0.05) * RANDSIGN(),       /* pan */
+              st->dy = frand(0.05) * RANDSIGN();
+            if (! (random() % 2000))
+              {
+                twiddle_knobs (st);
+                if (! (random() % 10))
+                  twiddle_camera (st);
+              }
+            break;
+          case MOVE:
+            st->state = IDLE;
+            st->value = 0.3;
+            break;
+          default:
+            abort();
+            break;
+          }
+        }
+
+      /* Draw a specular reflection somewhere on the screen, to mix it up
+         with a little noise from environmental light.
+       */
+      if (st->specular.s)
+        {
+          st->svalue += 0.01 * st->speed;
+          if (st->svalue > 1)
+            {
+              st->svalue = 0;
+              st->specular.s = 0;
+            }
+        }
+      else if (! (random() % 300))
+        {
+# if 1
+          /* Center on the monitor's screen, depth 1 */
+          int cx = st->xgwa.width / 2;
+          int cy = st->xgwa.height / 2;
+# else
+          /* Center on the monitor's screen, depth 0 -- but this clips. */
+          int cx = (st->rect.x + st->rect.w / 2) * st->xgwa.width;
+          int cy = (st->rect.y + st->rect.h / 2) * st->xgwa.height;
+# endif
+          int ww = 4 + (st->rect.h * st->xgwa.height) / 12;
+          st->specular.x = cx + (random() % ww) * RANDSIGN();
+          st->specular.y = cy + (random() % ww) * RANDSIGN();
+          st->specular.s = ww * (0.8 + frand(0.4));
+          st->svalue = 0;
+        }
+    }
+
+  if (st->last_time == 0)
+    st->start = then;
+
+  if (st->state != POWERUP)
+    {
+      img = grab_rectangle (st);
+      analogtv_load_ximage (st->tv, st->rec.input, img, 0, 0, 0, 0, 0);
+    }
+
+  analogtv_reception_update (&st->rec);
+  analogtv_draw (st->tv, st->noise, &rec, 1);
+  if (img)
+    XDestroyImage (img);
+
+  now = double_time();
+  timedelta = (1 / 29.97) - (now - then);
+
+  st->tv->powerup = then - st->start;
+  st->last_time = then;
+
+  return timedelta > 0 ? timedelta * 1000000 : 0;
+}
+
+
+static void
+vfeedback_reshape (Display *dpy, Window window, void *closure, 
+                    unsigned int w, unsigned int h)
+{
+  struct state *st = (struct state *) closure;
+  analogtv_reconfigure (st->tv);
+  XGetWindowAttributes (dpy, window, &st->xgwa);
+
+  if (st->pix)
+    {
+      XFreePixmap (dpy, st->pix);
+      st->pix = 0;
+    }
+}
+
+
+static Bool
+vfeedback_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+  struct state *st = (struct state *) closure;
+  double i = 0.02;
+
+  /* Pan with left button and no modifier keys.
+     Rotate with other buttons, or left-with-modifiers.
+   */
+  if (event->xany.type == ButtonPress &&
+      (event->xbutton.button == Button1 ||
+       event->xbutton.button == Button2 ||
+       event->xbutton.button == Button3))
+    {
+      st->button_down_p = True;
+      st->mouse_x = event->xbutton.x;
+      st->mouse_y = event->xbutton.y;
+      st->mouse_th = st->rect.th;
+      st->dragmode = (event->xbutton.button == Button1 && 
+                      !event->xbutton.state);
+      return True;
+    }
+  else if (event->xany.type == ButtonRelease &&
+           (event->xbutton.button == Button1 ||
+            event->xbutton.button == Button2 ||
+            event->xbutton.button == Button3))
+    {
+      st->button_down_p = False;
+      return True;
+    }
+  else if (event->xany.type == MotionNotify && st->button_down_p)
+    {
+      if (st->dragmode)
+        {
+          double dx = st->mouse_x - event->xmotion.x;
+          double dy = st->mouse_y - event->xmotion.y;
+          st->rect.x += dx / st->xgwa.width  * st->rect.w;
+          st->rect.y += dy / st->xgwa.height * st->rect.h;
+          st->mouse_x = event->xmotion.x;
+          st->mouse_y = event->xmotion.y;
+        }
+      else
+        {
+          /* Angle between center and initial click */
+          double a1 = -atan2 (st->mouse_y - st->xgwa.height / 2,
+                              st->mouse_x - st->xgwa.width  / 2);
+          /* Angle between center and drag position */
+          double a2 = -atan2 (event->xmotion.y - st->xgwa.height / 2,
+                              event->xmotion.x - st->xgwa.width  / 2);
+          /* Cumulatively rotate by difference between them */
+          st->rect.th = a2 - a1 + st->mouse_th;
+        }
+      goto OK;
+    }
+
+  /* Zoom with mouse wheel */
+
+  else if (event->xany.type == ButtonPress &&
+           (event->xbutton.button == Button4 ||
+            event->xbutton.button == Button6))
+    {
+      i = 1-i;
+      goto ZZ;
+    }
+  else if (event->xany.type == ButtonPress &&
+           (event->xbutton.button == Button5 ||
+            event->xbutton.button == Button7))
+    {
+      i = 1+i;
+      goto ZZ;
+    }
+  else if (event->type == KeyPress)
+    {
+      KeySym keysym;
+      char c = 0;
+      XLookupString (&event->xkey, &c, 1, &keysym, 0);
+      switch (keysym) {
+        /* pan with arrow keys */
+      case XK_Up:    st->rect.y += i; goto OK; break;
+      case XK_Down:  st->rect.y -= i; goto OK; break;
+      case XK_Left:  st->rect.x += i; goto OK; break;
+      case XK_Right: st->rect.x -= i; goto OK; break;
+      default: break;
+      }
+      switch (c) {
+
+        /* rotate with <> */
+      case '<': case ',': st->rect.th += i; goto OK; break;
+      case '>': case '.': st->rect.th -= i; goto OK; break;
+
+        /* zoom with += */
+      case '-': case '_':
+        i = 1+i;
+        goto ZZ;
+      case '=': case '+':
+        i = 1-i;
+      ZZ:
+        st->orect = st->rect;
+        st->rect.w *= i;
+        st->rect.h *= i;
+        st->rect.x += (st->orect.w - st->rect.w) / 2;
+        st->rect.y += (st->orect.h - st->rect.h) / 2;
+        goto OK;
+        break;
+
+        /* tv controls with T, C, B, O */
+      case 't': st->tv->tint_control       += 5;    goto OK; break;
+      case 'T': st->tv->tint_control       -= 5;    goto OK; break;
+      case 'c': st->tv->color_control      += 0.1;  goto OK; break;
+      case 'C': st->tv->color_control      -= 0.1;  goto OK; break;
+      case 'b': st->tv->brightness_control += 0.01; goto OK; break;
+      case 'B': st->tv->brightness_control -= 0.01; goto OK; break;
+      case 'o': st->tv->contrast_control   += 0.1;  goto OK; break;
+      case 'O': st->tv->contrast_control   -= 0.1;  goto OK; break;
+      case 'r': st->rec.level              += 0.01; goto OK; break;
+      case 'R': st->rec.level              -= 0.01; goto OK; break;
+      default: break;
+      }
+      goto NOPE;
+    OK:
+# if 0
+      fprintf (stderr, " %.6f x %.6f @ %.6f, %.6f %.6f\t",
+               st->rect.w, st->rect.h,
+               st->rect.x, st->rect.y, st->rect.th);
+      fprintf (stderr," T=%.2f C=%.2f B=%.2f O=%.2f R=%.3f\n",
+               st->tv->tint_control,
+               st->tv->color_control/* * 100*/,
+               st->tv->brightness_control/* * 100*/,
+               st->tv->contrast_control/* * 100*/,
+               st->rec.level);
+# endif
+      st->value = 0;
+      st->state = IDLE;
+      st->orect = st->rect;
+      return True;
+    }
+
+ NOPE:
+  if (screenhack_event_helper (dpy, window, event))
+    {
+      /* SPC or RET re-randomize the TV controls. */
+      twiddle_knobs (st);
+      goto OK;
+    }
+
+  return False;
+}
+
+
+static void
+vfeedback_free (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
+  analogtv_release (st->tv);
+  if (st->pix)
+    XFreePixmap (dpy, st->pix);
+  XFreeGC (dpy, st->gc);
+  free (st);
+}
+
+
+static const char *vfeedback_defaults [] = {
+
+  ".foreground:  #CCCC44",
+  ".background:  #000000",
+  "*noise:       0.02",
+  "*speed:       1.0",
+  ANALOGTV_DEFAULTS
+  "*TVBrightness: 1.5",
+  "*TVContrast:   150",
+  0
+};
+
+static XrmOptionDescRec vfeedback_options [] = {
+  { "-noise",           ".noise",     XrmoptionSepArg, 0 },
+  { "-speed",           ".speed",     XrmoptionSepArg, 0 },
+  ANALOGTV_OPTIONS
+  { 0, 0, 0, 0 }
+};
+
+XSCREENSAVER_MODULE ("VFeedback", vfeedback)
diff --git a/hacks/vfeedback.man b/hacks/vfeedback.man
new file mode 100644 (file)
index 0000000..d58fe06
--- /dev/null
@@ -0,0 +1,71 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+vfeedback - Simulates video feedback.
+.SH SYNOPSIS
+.B vfeedback
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-tv-color \fInumber\fP]
+[\-tv-tint \fInumber\fP]
+[\-noise \fInumber\fP]
+[\-tv-brightness \fInumber\fP]
+[\-tv-contrast \fInumber\fP]
+[\-fps]
+.SH DESCRIPTION
+Simulates video feedback: pointing a video camera at an NTSC television.
+.SH OPTIONS
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-tv-color \fInumber\fP
+Color Knob.  0 - 1000. Default: 70.
+.TP 8
+.B \-tv-tint \fInumber\fP
+Tint Knob.  0 - 100.  Default: 5.
+.TP 8
+.B \-noise \fInumber\fP
+Analog noise.  0.0 - 0.2.  Default: 0.02.
+.TP 8
+.B \-darken \fInumber\fP
+Darken the looped image.       0.0 - 1.0.  Default: 0.7.
+.TP 8
+.B \-tv-brightness \fInumber\fP
+Brightness Knob.  0.0 - 100.0. Default: 3.0.
+.TP 8
+.B \-tv-contrast \fInumber\fP
+Contrast Knob. 0 - 1500.  Default: 1000.
+.TP 8
+.B \-fps | \-no-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2018 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski.
index dfaf05de8b66ff730aa6641eec931633ce60553a..80cc7d91734d8ad29eb6b350e69b3ed3fea0eebd 100644 (file)
  * pictures from your images directory, some show color bars, and some
  * just have static. Some channels receive two stations simultaneously
  * so you see a ghostly, misaligned image.
- *
- * It's easy to add some test patterns by compiling in an XPM, but I
- * can't find any that are clearly freely redistributable.
- *
  */
 
 #ifdef HAVE_CONFIG_H
 #include "ximage-loader.h"
 #include "analogtv.h"
 
-#include "images/logo-50.xpm"
+#define USE_TEST_PATTERNS
+
+#include "images/gen/logo-180_png.h"
+
+#ifdef USE_TEST_PATTERNS
+# include "images/gen/testcard_rca_png.h"
+# include "images/gen/testcard_pm5544_png.h"
+# include "images/gen/testcard_bbcf_png.h"
+#endif
 
-/* #define DEBUG 1 */
-/* #define USE_TEST_PATTERNS */
 
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
@@ -75,6 +77,10 @@ struct state {
   int n_stations;
   analogtv_input *stations[MAX_STATIONS];
   Bool image_loading_p;
+  XImage *logo, *logo_mask;
+# ifdef USE_TEST_PATTERNS
+  XImage *test_patterns[MAX_STATIONS];
+# endif
 
   int curinputi;
   int change_ticks;
@@ -155,13 +161,18 @@ update_smpte_colorbars(analogtv_input *input)
   ypos=ANALOGTV_V/5;
   xpos=ANALOGTV_VIS_START + ANALOGTV_VIS_LEN/2;
 
-  if (! st->colorbars_only_p)
+  /* if (! st->colorbars_only_p) */
   {
     char localname[256];
     if (gethostname (localname, sizeof (localname))==0) {
+      int L;
       localname[sizeof(localname)-1]=0; /* "The returned name is null-
                                            terminated unless insufficient 
                                            space is provided" */
+      L = strlen(localname);
+      if (L > 6 && !strcmp(".local", localname+L-6))
+        localname[L-6] = 0;
+
       localname[24]=0; /* limit length */
 
       analogtv_draw_string_centered(input, &st->ugly_font, localname,
@@ -170,9 +181,15 @@ update_smpte_colorbars(analogtv_input *input)
   }
   ypos += st->ugly_font.char_h*5/2;
 
-  if (! st->colorbars_only_p)
-    analogtv_draw_xpm(st->tv, input,
-                      logo_50_xpm, xpos - 100, ypos);
+  if (st->logo)
+    {
+      int w2 = st->tv->xgwa.width  * 0.2;
+      int h2 = st->tv->xgwa.height * 0.2;
+      analogtv_load_ximage (st->tv, input, st->logo, st->logo_mask,
+                            (st->tv->xgwa.width - w2) / 2,
+                            st->tv->xgwa.height * 0.28,
+                            w2, h2);
+    }
 
   ypos += 58;
 
@@ -182,7 +199,7 @@ update_smpte_colorbars(analogtv_input *input)
   ypos += st->ugly_font.char_h*4;
 #endif
 
-  if (! st->colorbars_only_p)
+  /* if (! st->colorbars_only_p) */
   {
     char timestamp[256];
     time_t t = time ((time_t *) 0);
@@ -199,73 +216,6 @@ update_smpte_colorbars(analogtv_input *input)
   input->next_update_time += 1.0;
 }
 
-#if 0
-static void
-draw_color_square(analogtv_input *input)
-{
-  double xs,ys;
-
-  analogtv_draw_solid_rel_lcp(input, 0.0, 1.0, 0.0, 1.0,
-                              30.0, 0.0, 0.0);
-  
-  for (xs=0.0; xs<0.9999; xs+=1.0/15.0) {
-    analogtv_draw_solid_rel_lcp(input, xs, xs, 0.0, 1.0,
-                                100.0, 0.0, 0.0);
-  }
-
-  for (ys=0.0; ys<0.9999; ys+=1.0/11.0) {
-    analogtv_draw_solid_rel_lcp(input, 0.0, 1.0, ys, ys,
-                                100.0, 0.0, 0.0);
-  }
-
-  for (ys=0.0; ys<0.9999; ys+=0.01) {
-    
-    analogtv_draw_solid_rel_lcp(input, 0.0/15, 1.0/15, ys, ys+0.01,
-                                40.0, 45.0, 103.5*(1.0-ys) + 347.0*ys);
-
-    analogtv_draw_solid_rel_lcp(input, 14.0/15, 15.0/15, ys, ys+0.01,
-                                40.0, 45.0, 103.5*(ys) + 347.0*(1.0-ys));
-  }
-
-  for (ys=0.0; ys<0.9999; ys+=0.02) {
-    analogtv_draw_solid_rel_lcp(input, 1.0/15, 2.0/15, ys*2.0/11.0+1.0/11.0, 
-                                (ys+0.01)*2.0/11.0+1.0/11.0,
-                                100.0*(1.0-ys), 0.0, 0.0);
-  }
-
-
-}
-#endif
-
-static const char *xanalogtv_defaults [] = {
-  ".background:                black",
-  ".foreground:                white",
-  "*delay:             5",
-  "*grabDesktopImages:  False",   /* HAVE_JWXYZ */
-  "*chooseRandomImages: True",    /* HAVE_JWXYZ */
-  ANALOGTV_DEFAULTS
-  0,
-};
-
-static XrmOptionDescRec xanalogtv_options [] = {
-  { "-delay",          ".delay",               XrmoptionSepArg, 0 },
-  { "-colorbars-only", ".colorbarsOnly",       XrmoptionNoArg, "True" },
-  ANALOGTV_OPTIONS
-  { 0, 0, 0, 0 }
-};
-
-
-#ifdef USE_TEST_PATTERNS
-
-#include "images/earth.xpm"
-
-char **test_patterns[] = {
-  earth_xpm,
-};
-
-#endif
-
-
 static int
 getticks(struct state *st)
 {
@@ -346,7 +296,7 @@ static void image_loaded_cb (Screen *screen, Window window, Drawable pixmap,
     XFreePixmap(st->dpy, pixmap);
 
     analogtv_setup_sync(input, 1, (random()%20)==0);
-    analogtv_load_ximage(st->tv, input, image);
+    analogtv_load_ximage(st->tv, input, image, 0, 0, 0, 0, 0);
     if (image) XDestroyImage(image);
     st->chansettings[this].image_loaded_p = True;
 #if 0
@@ -412,9 +362,13 @@ static void load_station_images(struct state *st)
     }
 #ifdef USE_TEST_PATTERNS
     else if (random()%5==0) {
-      j=random()%countof(test_patterns);
-      analogtv_setup_sync(input);
-      analogtv_load_xpm(tv, input, test_patterns[j]);
+      int count = 0, j;
+      for (count = 0; st->test_patterns[count]; count++)
+        ;
+      j=random()%count;
+      analogtv_setup_sync(input, 1, 0);
+      analogtv_load_ximage(st->tv, input, st->test_patterns[j],
+                           0, 0, 0, 0, 0);
       analogtv_setup_teletext(input);
     }
 #endif
@@ -434,6 +388,7 @@ xanalogtv_init (Display *dpy, Window window)
   int i;
   int last_station=42;
   int delay = get_integer_resource(dpy, "delay", "Integer");
+
   if (delay < 1) delay = 1;
 
   analogtv_make_font(dpy, window, &st->ugly_font, 7, 10, "6x10");
@@ -445,6 +400,48 @@ xanalogtv_init (Display *dpy, Window window)
   st->colorbars_only_p =
     get_boolean_resource(dpy, "colorbarsOnly", "ColorbarsOnly");
 
+  /* if (!st->colorbars_only_p) */
+    {
+      int w, h;
+      Pixmap mask = 0;
+      Pixmap p = image_data_to_pixmap (dpy, window,
+                                       logo_180_png, sizeof(logo_180_png),
+                                       &w, &h, &mask);
+      st->logo = XGetImage (dpy, p, 0, 0, w, h, ~0L, ZPixmap);
+      XFreePixmap (dpy, p);
+      if (mask)
+        {
+          st->logo_mask = XGetImage (dpy, mask, 0, 0, w, h, ~0L, ZPixmap);
+          XFreePixmap (dpy, mask);
+        }
+    }
+
+# ifdef USE_TEST_PATTERNS
+  {
+    int i = 0;
+    int w, h;
+    Pixmap p;
+    p = image_data_to_pixmap (dpy, window,
+                              testcard_rca_png, sizeof(testcard_rca_png),
+                              &w, &h, 0);
+    st->test_patterns[i++] = XGetImage (dpy, p, 0, 0, w, h, ~0L, ZPixmap);
+    XFreePixmap (dpy, p);
+
+    p = image_data_to_pixmap (dpy, window,
+                              testcard_pm5544_png, sizeof(testcard_pm5544_png),
+                              &w, &h, 0);
+    st->test_patterns[i++] = XGetImage (dpy, p, 0, 0, w, h, ~0L, ZPixmap);
+    XFreePixmap (dpy, p);
+
+    p = image_data_to_pixmap (dpy, window,
+                              testcard_bbcf_png, sizeof(testcard_bbcf_png),
+                              &w, &h, 0);
+    st->test_patterns[i++] = XGetImage (dpy, p, 0, 0, w, h, ~0L, ZPixmap);
+    XFreePixmap (dpy, p);
+  }
+# endif /* USE_TEST_PATTERNS */
+
+
   add_stations(st);
 
   analogtv_set_defaults(st->tv, "");
@@ -622,8 +619,36 @@ xanalogtv_free (Display *dpy, Window window, void *closure)
 {
   struct state *st = (struct state *) closure;
   analogtv_release(st->tv);
+  if (st->logo) XDestroyImage (st->logo);
+  if (st->logo_mask) XDestroyImage (st->logo_mask);
+# ifdef USE_TEST_PATTERNS
+  {
+    int i;
+    for (i = 0; i < countof(st->test_patterns); i++)
+      if (st->test_patterns[i]) XDestroyImage (st->test_patterns[i]);
+  }
+# endif
   free (st);
 }
 
 
+static const char *xanalogtv_defaults [] = {
+  ".background:                black",
+  ".foreground:                white",
+  "*delay:             5",
+  "*grabDesktopImages:  False",   /* HAVE_JWXYZ */
+  "*chooseRandomImages: True",    /* HAVE_JWXYZ */
+  "*colorbarsOnly:      False",
+  ANALOGTV_DEFAULTS
+  0,
+};
+
+static XrmOptionDescRec xanalogtv_options [] = {
+  { "-delay",          ".delay",               XrmoptionSepArg, 0 },
+  { "-colorbars-only", ".colorbarsOnly",       XrmoptionNoArg, "True" },
+  ANALOGTV_OPTIONS
+  { 0, 0, 0, 0 }
+};
+
+
 XSCREENSAVER_MODULE ("XAnalogTV", xanalogtv)
index 25283401fea17b10e5a89b5301f6bcf5b2841dba..1037460afb35d00433b6ea19fff3ce3f713597d8 100644 (file)
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
+# undef MAX
+# undef MIN
+# define MAX(A,B) ((A)>(B)?(A):(B))
+# define MIN(A,B) ((A)<(B)?(A):(B))
+
 #include "xshm.h"
 
 #include "images/gen/bob_png.h"
@@ -226,7 +231,15 @@ InitFlame(struct state *st)
   THROTTLE (st->vartrend, "vartrend");
 # undef THROTTLE
 
-
+#if 0
+  if (st->width > 2560)  /* Retina displays */
+    {
+      /* #### One of these knobs must mean "make the fire be twice as tall"
+         but I can't figure out how. Changing any of the default values
+         of any of these seems to just make it all go crappy. */
+      st->ivspread = MAX (0, MIN (255, st->ivspread + 1));
+    }
+#endif
 
   st->hspread = st->ihspread;
   st->vspread = st->ivspread;
@@ -584,143 +597,117 @@ FlamePasteData(struct state *st,
 }
 
 
-static Pixmap
-double_pixmap (Display *dpy, Visual *visual, int depth, Pixmap pixmap,
-               int pix_w, int pix_h)
+static XImage *
+double_ximage (Display *dpy, Visual *visual, XImage *image)
 {
   int x, y;
-  Pixmap p2 = XCreatePixmap(dpy, pixmap, pix_w*2, pix_h*2, depth);
-  XImage *i1 = XGetImage (dpy, pixmap, 0, 0, pix_w, pix_h, ~0L, 
-                          (depth == 1 ? XYPixmap : ZPixmap));
-  XImage *i2 = XCreateImage (dpy, visual, depth, 
-                             (depth == 1 ? XYPixmap : ZPixmap), 0, 0,
-                             pix_w*2, pix_h*2, 8, 0);
-  XGCValues gcv;
-  GC gc = XCreateGC (dpy, p2, 0, &gcv);
-  i2->data = (char *) calloc(i2->height, i2->bytes_per_line);
-  for (y = 0; y < pix_h; y++)
-    for (x = 0; x < pix_w; x++)
+  XImage *out = XCreateImage (dpy, visual, image->depth, ZPixmap, 0, 0,
+                              image->width * 2, image->height * 2, 8, 0);
+  out->data = (char *) malloc (out->height * out->bytes_per_line);
+  for (y = 0; y < image->width; y++)
+    for (x = 0; x < image->height; x++)
       {
-       unsigned long p = XGetPixel(i1, x, y);
-       XPutPixel(i2, x*2,   y*2,   p);
-       XPutPixel(i2, x*2+1, y*2,   p);
-       XPutPixel(i2, x*2,   y*2+1, p);
-       XPutPixel(i2, x*2+1, y*2+1, p);
+       unsigned long p = XGetPixel (image, x, y);
+       XPutPixel (out, x*2,   y*2,   p);
+       XPutPixel (out, x*2+1, y*2,   p);
+       XPutPixel (out, x*2,   y*2+1, p);
+       XPutPixel (out, x*2+1, y*2+1, p);
       }
-  free(i1->data); i1->data = 0;
-  XDestroyImage(i1);
-  XPutImage(dpy, p2, gc, i2, 0, 0, 0, 0, i2->width, i2->height);
-  XFreeGC (dpy, gc);
-  free(i2->data); i2->data = 0;
-  XDestroyImage(i2);
-  XFreePixmap(dpy, pixmap);
-  return p2;
+  XDestroyImage (image);
+  return out;
 }
 
 
 static unsigned char *
-reformat_pixmap (struct state *st, Pixmap pixmap, Pixmap mask, int *w, int *h)
+gaussian_blur (unsigned char *in, int w, int h, double r)
 {
-  XImage *image = 0, *mimage = 0;
-  int x, y;
-  unsigned char *result, *o;
-  XColor colors[256];
-  Bool cmap_p = has_writable_cells (st->screen, st->visual);
-
-  while (*w < st->width  / 10 &&
-         *h < st->height / 10)
-    {
-      pixmap = double_pixmap (st->dpy, st->visual, st->depth, pixmap, *w, *h);
-      if (mask)
-        mask = double_pixmap (st->dpy, st->visual, st->depth, mask, *w, *h);
-      *w *= 2;
-      *h *= 2;
-    }
-
-  if (cmap_p)
-    {
-      int i;
-      for (i = 0; i < countof (colors); i++)
-        colors[i].pixel = i;
-      XQueryColors (st->dpy, st->colormap, colors, countof (colors));
-    }
-
-  image  = XGetImage (st->dpy, pixmap, 0, 0, *w, *h, ~0L, ZPixmap);
-  XFreePixmap(st->dpy, pixmap);
+  unsigned char *out = malloc(w * h);
+  int rs = (int) ((r * 2.57) + 0.5);
+  int i, j;
 
-  if (mask)
-    {
-      mimage = XGetImage (st->dpy, mask,   0, 0, *w, *h, ~0L, ZPixmap);
-      XFreePixmap(st->dpy, mask);
-    }
-
-  result = (unsigned char *) malloc (image->width * image->height);
-  o = result;
-  for (y = 0; y < image->height; y++)
-    for (x = 0; x < image->width; x++)
+  for (i = 0; i < h; i ++)
+    for (j = 0; j < w; j++) 
       {
-        unsigned long rgb = XGetPixel (image, x, y);
-        unsigned long a   = mimage ? XGetPixel (mimage, x, y) : 1;
-        unsigned long gray;
-        if (!a)
-          rgb = 0xFFFFFFFFL;
-        if (cmap_p)
-          gray = ((200 - ((((colors[rgb].red   >> 8) & 0xFF) +
-                           ((colors[rgb].green >> 8) & 0xFF) +
-                           ((colors[rgb].blue  >> 8) & 0xFF))
-                          >> 1))
-                  & 0xFF);
-        else
-          /* This is *so* not handling all the cases... */
-          gray = (image->depth > 16
-                  ? ((((rgb >> 24) & 0xFF) +
-                      ((rgb >> 16) & 0xFF) +
-                      ((rgb >>  8) & 0xFF) +
-                      ((rgb      ) & 0xFF)) >> 2)
-                  : ((((rgb >> 12) & 0x0F) +
-                      ((rgb >>  8) & 0x0F) +
-                      ((rgb >>  4) & 0x0F) +
-                      ((rgb      ) & 0x0F)) >> 1));
-
-        *o++ = 255 - gray;
+        double val = 0, wsum = 0;
+        int ix, iy;
+        for (iy = i-rs; iy<i+rs+1; iy++)
+          for (ix = j-rs; ix<j+rs+1; ix++)
+            {
+              int x = MIN(w-1, MAX(0, ix));
+              int y = MIN(h-1, MAX(0, iy));
+              int dsq = (ix-j)*(ix-j)+(iy-i)*(iy-i);
+              double wght = exp (-dsq / (2*r*r)) / (M_PI*2*r*r);
+              val += in[y*w+x] * wght;
+              wsum += wght;
+            }
+        out[i*w+j] = val/wsum;            
       }
 
-  *w = image->width;
-  *h = image->height;
-  XDestroyImage (image);
-  if (mimage)
-    XDestroyImage (mimage);
-
-  return result;
-
+  free (in);
+  return out;
 }
 
 
 static unsigned char *
-loadBitmap(struct state *st, int *w, int *h)
+loadBitmap (struct state *st)
 {
+  int x, y;
+  unsigned char *result, *o;
+  int blur = 0;
+
 # ifdef HAVE_JWXYZ
   const char *bitmap_name = "(default)"; /* #### always use builtin */
 # else
   char *bitmap_name = get_string_resource (st->dpy, "bitmap", "Bitmap");
 # endif
-  Pixmap p = 0, mask = 0;
+  XImage *image = 0;
   if (!bitmap_name ||
       !*bitmap_name ||
       !strcmp(bitmap_name, "none"))
     ;
   else if (!strcmp(bitmap_name, "(default)"))   /* use the builtin */
-    p = image_data_to_pixmap (st->dpy, st->window,
-                              bob_png, sizeof(bob_png),
-                              w, h, &mask);
-  else  /* load a bitmap file */
-    p = file_to_pixmap (st->dpy, st->window, bitmap_name,
-                        &st->width, &st->height, 0);
-
-  if (!p) return 0;
-  return reformat_pixmap (st, p, mask, w, h);
+    image = image_data_to_ximage (st->dpy, st->visual,
+                                  bob_png, sizeof(bob_png));
+  else
+    image = file_to_ximage (st->dpy, st->visual, bitmap_name);
+
+  if (! image) return 0;
+
+  while (image->width  < st->width  / 10 &&
+         image->height < st->height / 10)
+    {
+      image = double_ximage (st->dpy, st->visual, image);
+      blur++;
+    }
+
+  result = (unsigned char *) malloc (image->width * image->height);
+  o = result;
+  for (y = 0; y < image->height; y++)
+    for (x = 0; x < image->width; x++)
+      {
+        unsigned long agbr = XGetPixel (image, x, image->height - y - 1);
+        unsigned long a    = (agbr >> 24) & 0xFF;
+        unsigned long gray = (a == 0
+                              ? 0xFF
+                              : ((((agbr >> 16) & 0xFF) +
+                                  ((agbr >>  8) & 0xFF) +
+                                  ((agbr >>  0) & 0xFF))
+                                 / 3));
+        if (gray < 96) gray /= 2;  /* a little more contrast */
+        *o++ = 255 - gray;
+      }
+
+  /* If we enlarged the image, file off the sharp edges. */
+  if (blur > 0)
+    result = gaussian_blur (result, image->width, image->height, blur * 1.7);
+
+  st->theimx = image->width;
+  st->theimy = image->height;
+  XDestroyImage (image);
+  return result;
 }
 
+
 static void *
 xflame_init (Display *dpy, Window win)
 {
@@ -735,7 +722,7 @@ xflame_init (Display *dpy, Window win)
 
   GetXInfo(st);
   InitColors(st);
-  st->theim = loadBitmap(st, &st->theimx, &st->theimy);
+  st->theim = loadBitmap(st);
 
   MakeImage(st);
   InitFlame(st);
index f122e3790773768c4cc16959cedd41b9c8ad44f2..382699bb53b84eafef8d4c2e1acee10002138ee4 100644 (file)
@@ -105,7 +105,8 @@ make_ximage (Display *dpy, Visual *visual, const char *filename,
       pb = gdk_pixbuf_new_from_file (filename);
       if (!pb)
         {
-          fprintf (stderr, "%s: GDK unable to load %s\n", progname, filename);
+          fprintf (stderr, "%s: GDK unable to load %s: %s\n",
+                   progname, filename, (gerr ? gerr->message : "?"));
           return 0;
         }
 # endif /* HAVE_GTK2 */
@@ -116,11 +117,14 @@ make_ximage (Display *dpy, Visual *visual, const char *filename,
       GInputStream *s =
         g_memory_input_stream_new_from_data (image_data, data_size, 0);
       pb = gdk_pixbuf_new_from_stream (s, 0, &gerr);
-      /* #### free s? */
+
+      g_input_stream_close (s, NULL, NULL);
+      g_object_unref (s);
+
       if (! pb)
         {
-          fprintf (stderr, "%s: GDK unable to parse built-in image data\n",
-                   progname);
+          /* fprintf (stderr, "%s: GDK unable to parse image data: %s\n",
+                   progname, (gerr ? gerr->message : "?")); */
           return 0;
         }
 # else /* !HAVE_GTK2 */
@@ -622,6 +626,7 @@ flip_ximage (XImage *ximage)
   char *data2, *in, *out;
   int y;
 
+  if (!ximage) return;
   data2 = malloc (ximage->bytes_per_line * ximage->height);
   if (!data2) abort();
   in = ximage->data;
@@ -657,6 +662,11 @@ file_to_pixmap (Display *dpy, Window window, const char *filename,
 }
 
 
+/* This XImage has RGBA data, which is what OpenGL code typically expects.
+   Also it is upside down: the origin is at the bottom left of the image.
+   X11 typically expects 0RGB as it has no notion of alpha, only 1-bit masks.
+   With X11 code, you should probably use the _pixmap routines instead.
+ */
 XImage *
 image_data_to_ximage (Display *dpy, Visual *visual,
                       const unsigned char *image_data,
@@ -667,10 +677,6 @@ image_data_to_ximage (Display *dpy, Visual *visual,
   return ximage;
 }
 
-/* This XImage has RGBA data, which is what OpenGL code typically expects.
-   X11 typically expects 0RGB as it has no notion of alpha, only 1-bit masks.
-   With X11 code, you should probably use the _pixmap routines instead.
- */
 XImage *
 file_to_ximage (Display *dpy, Visual *visual, const char *filename)
 {
index f5b714ae7451887ce1b3ebfa8f17b6cfd916ee29..bed163f3ccb556c69260d14b3b153956df8ba9d2 100644 (file)
@@ -23,14 +23,15 @@ extern Pixmap image_data_to_pixmap (Display *, Window,
                                     int *width_ret, int *height_ret,
                                     Pixmap *mask_ret);
 
-extern XImage *image_data_to_ximage (Display *, Visual *,
-                                     const unsigned char *image_data,
-                                     unsigned long data_size);
-
 /* This XImage has RGBA data, which is what OpenGL code typically expects.
+   Also it is upside down: the origin is at the bottom left of the image.
    X11 typically expects 0RGB as it has no notion of alpha, only 1-bit masks.
    With X11 code, you should probably use the _pixmap routines instead.
  */
+extern XImage *image_data_to_ximage (Display *, Visual *,
+                                     const unsigned char *image_data,
+                                     unsigned long data_size);
+
 extern XImage *file_to_ximage (Display *, Visual *, const char *filename);
 
 #endif /* _XIMAGE_LOADER_H_ */
index 73d1c147c64727ba3c52c0ab3f6f85d2c24181c0..2b74b799160aa10f178660915cecd803151838f0 100644 (file)
@@ -1112,10 +1112,11 @@ jwxyz_gl_copy_area (Display *dpy, Drawable src, Drawable dst, GC gc,
 
     glBindTexture (GL_TEXTURE_2D, src->texture);
 
-    jwxyz_gl_draw_image (GL_TEXTURE_2D, to_pow2(src->frame.width),
+    jwxyz_gl_draw_image (dpy, gc, GL_TEXTURE_2D, to_pow2(src->frame.width),
                          to_pow2(src->frame.height),
                          src_x, src->frame.height - src_y - height,
-                         width, height, dst_x, dst_y);
+                         jwxyz_drawable_depth (src), width, height,
+                         dst_x, dst_y, False);
     return;
   }
 
@@ -1615,7 +1616,7 @@ jwxyz_draw_random_image (Display *dpy, Drawable drawable, GC gc)
   jmethodID   m = (*env)->GetMethodID (env, c, 
                                        (grab_p
                                         ? "getScreenshot"
-                                        : "loadRandomImage"),
+                                        : "checkThenLoadRandomImage"),
                                        "(IIZ)[Ljava/lang/Object;");
   if ((*env)->ExceptionOccurred(env)) abort();
   jobjectArray img_name = (
index 9476d2a0dcefe1c9e16bef123766e176cb17c8a2..96d54b88ef4ffc3c2f8afebb6579a406db5b8cb3 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-2017 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1991-2018 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -459,6 +459,8 @@ jwxyz_load_native_font (Window main_window, int traits_jwxyz, int mask_jwxyz,
     }
   }
 
+  [font_name release];
+
   if (nsfont)
   {
     if (family_name_ret)
index 81ffe373e5049a133352344388f085d3863b8fd2..1a31ae37a1dce4356b1df08d9cf29d3243decb65 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-2016 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1991-2018 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -103,21 +103,21 @@ XDisplayHeightMM (Display *dpy, int screen)
 unsigned long
 XBlackPixelOfScreen(Screen *screen)
 {
-  return DefaultVisualOfScreen (screen)->rgba_masks[3];
+  return DefaultVisualOfScreen (screen)->alpha_mask;
 }
 
 unsigned long
 XWhitePixelOfScreen(Screen *screen)
 {
-  const unsigned long *masks = DefaultVisualOfScreen (screen)->rgba_masks;
-  return masks[0] | masks[1] | masks[2] | masks[3];
+  Visual *v = DefaultVisualOfScreen (screen);
+  return (v->red_mask | v->green_mask |v->blue_mask | v->alpha_mask);
 }
 
 unsigned long
 XCellsOfScreen(Screen *screen)
 {
-  const unsigned long *masks = DefaultVisualOfScreen (screen)->rgba_masks;
-  return masks[0] | masks[1] | masks[2];
+  Visual *v = DefaultVisualOfScreen (screen);
+  return (v->red_mask | v->green_mask |v->blue_mask);
 }
 
 void
@@ -579,13 +579,12 @@ XGetGeometry (Display *dpy, Drawable d, Window *root_ret,
 Status
 XAllocColor (Display *dpy, Colormap cmap, XColor *color)
 {
-  const unsigned long *masks =
-    DefaultVisualOfScreen(DefaultScreenOfDisplay(dpy))->rgba_masks;
+  Visual *v = DefaultVisualOfScreen (DefaultScreenOfDisplay (dpy));
   color->pixel =
-    (((color->red   << 16) >> (31 - i_log2(masks[0]))) & masks[0]) |
-    (((color->green << 16) >> (31 - i_log2(masks[1]))) & masks[1]) |
-    (((color->blue  << 16) >> (31 - i_log2(masks[2]))) & masks[2]) |
-    masks[3];
+    (((color->red   << 16) >> (31 - i_log2(v->red_mask)))   & v->red_mask)   |
+    (((color->green << 16) >> (31 - i_log2(v->green_mask))) & v->green_mask) |
+    (((color->blue  << 16) >> (31 - i_log2(v->blue_mask)))  & v->blue_mask)  |
+    v->alpha_mask;
   return 1;
 }
 
@@ -713,6 +712,25 @@ ximage_putpixel_1 (XImage *ximage, int x, int y, unsigned long pixel)
   return 0;
 }
 
+static unsigned long
+ximage_getpixel_8 (XImage *ximage, int x, int y)
+{
+  return ((unsigned long)
+          *((uint8_t *) ximage->data +
+            (y * ximage->bytes_per_line) +
+            x));
+}
+
+static int
+ximage_putpixel_8 (XImage *ximage, int x, int y, unsigned long pixel)
+{
+  *((uint8_t *) ximage->data +
+    (y * ximage->bytes_per_line) +
+    x) = (uint8_t) pixel;
+  return 0;
+}
+
+
 static unsigned long
 ximage_getpixel_32 (XImage *ximage, int x, int y)
 {
@@ -736,9 +754,9 @@ Status
 XInitImage (XImage *ximage)
 {
   if (!ximage->bytes_per_line)
-    ximage->bytes_per_line = (ximage->depth == 1
-                              ? (ximage->width + 7) / 8
-                              ximage->width * 4);
+    ximage->bytes_per_line = (ximage->depth == 1 ? (ximage->width + 7) / 8 :
+                              ximage->depth == 8 ? ximage->width :
+                              ximage->width * 4);
 
   if (ximage->depth == 1) {
     ximage->f.put_pixel = ximage_putpixel_1;
@@ -746,6 +764,9 @@ XInitImage (XImage *ximage)
   } else if (ximage->depth == 32 || ximage->depth == 24) {
     ximage->f.put_pixel = ximage_putpixel_32;
     ximage->f.get_pixel = ximage_getpixel_32;
+  } else if (ximage->depth == 8) {
+    ximage->f.put_pixel = ximage_putpixel_8;
+    ximage->f.get_pixel = ximage_getpixel_8;
   } else {
     Assert (0, "unknown depth");
   }
@@ -770,9 +791,9 @@ XCreateImage (Display *dpy, Visual *visual, unsigned int depth,
   ximage->bitmap_pad = bitmap_pad;
   ximage->depth = depth;
   Visual *v = DefaultVisualOfScreen (DefaultScreenOfDisplay (dpy));
-  ximage->red_mask   = (depth == 1 ? 0 : v->rgba_masks[0]);
-  ximage->green_mask = (depth == 1 ? 0 : v->rgba_masks[1]);
-  ximage->blue_mask  = (depth == 1 ? 0 : v->rgba_masks[2]);
+  ximage->red_mask   = (depth == 1 ? 0 : v->red_mask);
+  ximage->green_mask = (depth == 1 ? 0 : v->green_mask);
+  ximage->blue_mask  = (depth == 1 ? 0 : v->blue_mask);
   ximage->bits_per_pixel = (depth == 1 ? 1 : visual_depth (NULL, NULL));
   ximage->bytes_per_line = bytes_per_line;
 
@@ -1497,11 +1518,10 @@ jwxyz_draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
   {
 # define ROTL(x, rot) (((x) << ((rot) & 31)) | ((x) >> (32 - ((rot) & 31))))
 
-    const unsigned long *masks =
-      DefaultVisualOfScreen (DefaultScreenOfDisplay(dpy))->rgba_masks;
-    unsigned shift = (i_log2 (masks[3]) - i_log2 (masks[1])) & 31;
-    uint32_t mask = ROTL(masks[1], shift) & masks[3],
-             color = gcv->foreground & ~masks[3];
+    Visual *v = DefaultVisualOfScreen (DefaultScreenOfDisplay(dpy));
+    unsigned shift = (i_log2 (v->alpha_mask) - i_log2 (v->green_mask)) & 31;
+    uint32_t mask = ROTL(v->green_mask, shift) & v->alpha_mask,
+             color = gcv->foreground & ~v->alpha_mask;
     uint32_t *s = (uint32_t *)data;
     uint32_t *end = s + (w * h);
     while (s < end) {
@@ -1768,7 +1788,7 @@ visual_depth (Screen *s, Visual *v)
 int
 visual_cells (Screen *s, Visual *v)
 {
-  return (int)(v->rgba_masks[0] | v->rgba_masks[1] | v->rgba_masks[2]);
+  return (int)(v->red_mask | v->green_mask | v->blue_mask);
 }
 
 int
@@ -1781,9 +1801,9 @@ void
 visual_rgb_masks (Screen *s, Visual *v, unsigned long *red_mask,
                   unsigned long *green_mask, unsigned long *blue_mask)
 {
-  *red_mask = v->rgba_masks[0];
-  *green_mask = v->rgba_masks[1];
-  *blue_mask = v->rgba_masks[2];
+  *red_mask = v->red_mask;
+  *green_mask = v->green_mask;
+  *blue_mask = v->blue_mask;
 }
 
 int
index 9bf2661e6982592ea1748c3373f2012da5e5271e..369d16fbbc1ff73763668a10cc41f6245d3fcfbd 100644 (file)
    Xlib and that do OpenGL-ish things that bear some resemblance to the
    things that Xlib might have done.
 
-   This is the version of jwxyz for Android.  The version used by MacOS
+   This is the version of jwxyz for Android.  The version used by macOS
    and iOS is in jwxyz.m.
  */
 
 /* Be advised, this is all very much a work in progress. */
 
-/* FWIW, at one point macOS 10.x could actually run with 256 colors. It might
-   not be able to do this anymore, though.
+/* There is probably no reason to ever implement indexed-color rendering here,
+   even if many screenhacks still work with PseudoColor.
+   - OpenGL ES 1.1 (Android, iOS) doesn't support indexed color.
+   - macOS only provides indexed color via AGL (now deprecated), not
+     NSOpenGLPixelFormat.
  */
 
 /* TODO:
@@ -134,6 +137,8 @@ struct jwxyz_Display {
 
   int gc_function;
   Bool gc_alpha_allowed_p;
+  int gc_clip_x_origin, gc_clip_y_origin;
+  GLuint gc_clip_mask;
 
   // Alternately, there could be one queue per pixmap.
   size_t queue_size, queue_capacity;
@@ -147,6 +152,8 @@ struct jwxyz_Display {
 struct jwxyz_GC {
   XGCValues gcv;
   unsigned int depth;
+  GLuint clip_mask;
+  unsigned clip_mask_width, clip_mask_height;
 };
 
 struct jwxyz_linked_point {
@@ -220,6 +227,62 @@ gl_check_ver (const struct gl_version *caps,
 #endif
 
 
+static void
+tex_parameters (Display *d, GLuint texture)
+{
+  // TODO: Check for (ARB|EXT|NV)_texture_rectangle. (All three are alike.)
+  // Rectangle textures should be present on OS X with the following exceptions:
+  // - Generic renderer on PowerPC OS X 10.4 and earlier
+  // - ATI Rage 128
+  glBindTexture (d->gl_texture_target, texture);
+  // TODO: This is all somewhere else. Refactor.
+  glTexParameteri (d->gl_texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+  glTexParameteri (d->gl_texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+  // This might be redundant for rectangular textures.
+# ifndef HAVE_JWZGLES
+  const GLint wrap = GL_CLAMP;
+# else  // HAVE_JWZGLES
+  const GLint wrap = GL_CLAMP_TO_EDGE;
+# endif // HAVE_JWZGLES
+
+  // In OpenGL, CLAMP_TO_EDGE is OpenGL 1.2 or GL_SGIS_texture_edge_clamp.
+  // This is always present with OpenGL ES.
+  glTexParameteri (d->gl_texture_target, GL_TEXTURE_WRAP_S, wrap);
+  glTexParameteri (d->gl_texture_target, GL_TEXTURE_WRAP_T, wrap);
+}
+
+static void
+tex_size (Display *dpy, unsigned *tex_w, unsigned *tex_h)
+{
+  if (!dpy->gl_texture_npot_p) {
+    *tex_w = to_pow2(*tex_w);
+    *tex_h = to_pow2(*tex_h);
+  }
+}
+
+static void
+tex_image (Display *dpy, GLenum internalformat,
+           unsigned *tex_w, unsigned *tex_h, GLenum format, GLenum type,
+           const void *data)
+{
+  unsigned w = *tex_w, h = *tex_h;
+  tex_size (dpy, tex_w, tex_h);
+
+  // TODO: Would using glTexSubImage2D exclusively be faster?
+  if (*tex_w == w && *tex_h == h) {
+    glTexImage2D (dpy->gl_texture_target, 0, internalformat, *tex_w, *tex_h,
+                  0, format, type, data);
+  } else {
+    // TODO: Sampling the last row might be a problem if src_x != 0.
+    glTexImage2D (dpy->gl_texture_target, 0, internalformat, *tex_w, *tex_h,
+                  0, format, type, NULL);
+    glTexSubImage2D (dpy->gl_texture_target, 0, 0, 0, w, h,
+                     format, type, data);
+  }
+}
+
+
 extern const struct jwxyz_vtbl gl_vtbl;
 
 Display *
@@ -301,19 +364,24 @@ jwxyz_gl_make_display (Window w)
   Visual *v = &d->visual;
   v->class      = TrueColor;
   if (d->pixel_format == GL_BGRA_EXT) {
-    v->rgba_masks[0] = 0x00ff0000;
-    v->rgba_masks[1] = 0x0000ff00;
-    v->rgba_masks[2] = 0x000000ff;
-    v->rgba_masks[3] = 0xff000000;
+    v->red_mask   = 0x00ff0000;
+    v->green_mask = 0x0000ff00;
+    v->blue_mask  = 0x000000ff;
+    v->alpha_mask = 0xff000000;
   } else {
     Assert(d->pixel_format == GL_RGBA,
            "jwxyz_gl_make_display: Unknown pixel_format");
+    unsigned long masks[4];
     for (unsigned i = 0; i != 4; ++i) {
       union color_bytes color;
       color.pixel = 0;
       color.bytes[i] = 0xff;
-      v->rgba_masks[i] = color.pixel;
+      masks[i] = color.pixel;
     }
+    v->red_mask   = masks[0];
+    v->green_mask = masks[1];
+    v->blue_mask  = masks[2];
+    v->alpha_mask = masks[3];
   }
 
   d->timers_data = jwxyz_sources_init (XtDisplayToApplicationContext (d));
@@ -321,39 +389,36 @@ jwxyz_gl_make_display (Window w)
   d->window_background = BlackPixel(d,0);
 
   d->main_window = w;
+
   {
-    GLint max_texture_size;
+    GLint max_texture_size, max_texture_units;
     glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_texture_size);
-    Log ("GL_MAX_TEXTURE_SIZE: %d\n", max_texture_size);
+    glGetIntegerv (GL_MAX_TEXTURE_UNITS, &max_texture_units);
+    Log ("GL_MAX_TEXTURE_SIZE: %d, GL_MAX_TEXTURE_UNITS: %d\n",
+         max_texture_size, max_texture_units);
+
+    // OpenGL ES 1.1 and OpenGL 1.3 both promise at least 2 texture units:
+    // OpenGL (R) ES Common/Common-Lite Profile Specification, Version 1.1.12 (Full Specification)
+    // https://www.khronos.org/registry/OpenGL/specs/es/1.1/es_full_spec_1.1.pdf
+    // * Table 6.22. Implementation Dependent Values
+    // * D.2 Enhanced Texture Processing
+    // (OpenGL 1.2 provides multitexturing as an ARB extension, and requires 1
+    // texture unit only.)
+
+    // ...but the glGet reference page contradicts this, and says there can be
+    // just one.
+    // https://www.khronos.org/registry/OpenGL-Refpages/es1.1/xhtml/glGet.xml
   }
+
   glGenTextures (countof (d->textures), d->textures);
 
   for (unsigned i = 0; i != countof (d->textures); i++) {
-    // TODO: Check for (ARB|EXT|NV)_texture_rectangle. (All three are alike.)
-    // Rectangle textures should be present on OS X with the following exceptions:
-    // - Generic renderer on PowerPC OS X 10.4 and earlier
-    // - ATI Rage 128
-    glBindTexture (d->gl_texture_target, d->textures[i]);
-    // TODO: This is all somewhere else. Refactor.
-    glTexParameteri (d->gl_texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri (d->gl_texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
-    // This might be redundant for rectangular textures.
-# ifndef HAVE_JWZGLES
-    const GLint wrap = GL_CLAMP;
-# else  // HAVE_JWZGLES
-    const GLint wrap = GL_CLAMP_TO_EDGE;
-# endif // HAVE_JWZGLES
-
-    // In OpenGL, CLAMP_TO_EDGE is OpenGL 1.2 or GL_SGIS_texture_edge_clamp.
-    // This is always present with OpenGL ES.
-    glTexParameteri (d->gl_texture_target, GL_TEXTURE_WRAP_S, wrap);
-    glTexParameteri (d->gl_texture_target, GL_TEXTURE_WRAP_T, wrap);
+    tex_parameters (d, d->textures[i]);
   }
 
   d->gc_function = GXcopy;
   d->gc_alpha_allowed_p = False;
+  d->gc_clip_mask = 0;
 
   jwxyz_assert_display(d);
   return d;
@@ -446,7 +511,7 @@ visual (Display *dpy)
 
    All drawing functions:
    function                                | glLogicOp w/ GL_COLOR_LOGIC_OP
-   clip_x_origin, clip_y_origin, clip_mask | Stencil mask
+   clip_x_origin, clip_y_origin, clip_mask | Multitexturing w/ GL_TEXTURE1
 
    Shape drawing functions:
    foreground, background                  | glColor*
@@ -483,8 +548,12 @@ enqueue (Display *dpy, Drawable d, GC gc, int mode, size_t count,
          unsigned long pixel)
 {
   if (dpy->queue_size &&
-      (dpy->gc_function != gc->gcv.function ||
+      (!gc || /* Could allow NULL GCs here... */
+       dpy->gc_function != gc->gcv.function ||
        dpy->gc_alpha_allowed_p != gc->gcv.alpha_allowed_p ||
+       dpy->gc_clip_mask != gc->clip_mask ||
+       dpy->gc_clip_x_origin != gc->gcv.clip_x_origin ||
+       dpy->gc_clip_y_origin != gc->gcv.clip_y_origin ||
        dpy->queue_mode != mode ||
        dpy->queue_drawable != d)) {
     jwxyz_gl_flush (dpy);
@@ -528,8 +597,21 @@ enqueue (Display *dpy, Drawable d, GC gc, int mode, size_t count,
   dpy->queue_drawable = d;
 
   union color_bytes color;
-  // TODO: validate color
-  JWXYZ_QUERY_COLOR (dpy, pixel, 0xffull, color.bytes);
+
+  // Like query_color, but for bytes.
+  jwxyz_validate_pixel (dpy, pixel, jwxyz_drawable_depth (d),
+                        gc ? gc->gcv.alpha_allowed_p : False);
+
+  if (jwxyz_drawable_depth (d) == 1) {
+    uint8_t b = pixel ? 0xff : 0;
+    color.bytes[0] = b;
+    color.bytes[1] = b;
+    color.bytes[2] = b;
+    color.bytes[3] = 0xff;
+  } else {
+    JWXYZ_QUERY_COLOR (dpy, pixel, 0xffull, color.bytes);
+  }
+
   for (size_t i = 0; i != count; ++i) // TODO: wmemset when applicable.
     dpy->queue_color[i + old_size] = color.pixel;
 
@@ -556,44 +638,49 @@ finish_triangle_strip (Display *dpy, GLfloat *enqueue_result)
 
 
 static void
-set_clip_mask (GC gc)
-{
-  Assert (!gc->gcv.clip_mask, "set_clip_mask: TODO");
-}
-
-
-static void
-set_color (Display *dpy, unsigned long pixel, unsigned int depth,
-           Bool alpha_allowed_p)
+query_color (Display *dpy, unsigned long pixel, unsigned int depth,
+             Bool alpha_allowed_p, GLfloat *rgba)
 {
   jwxyz_validate_pixel (dpy, pixel, depth, alpha_allowed_p);
 
   if (depth == 1) {
     GLfloat f = pixel;
-    glColor4f (f, f, f, 1);
+    rgba[0] = f;
+    rgba[1] = f;
+    rgba[2] = f;
+    rgba[3] = 1;
   } else {
-    GLfloat rgba[4];
     JWXYZ_QUERY_COLOR (dpy, pixel, 1.0f, rgba);
-    glColor4f (rgba[0], rgba[1], rgba[2], rgba[3]);
   }
 }
 
+
+static void
+set_color (Display *dpy, unsigned long pixel, unsigned int depth,
+           Bool alpha_allowed_p)
+{
+  GLfloat rgba[4];
+  query_color (dpy, pixel, depth, alpha_allowed_p, rgba);
+  glColor4f (rgba[0], rgba[1], rgba[2], rgba[3]);
+}
+
 /* Pushes a GC context; sets Function and ClipMask. */
 void
 jwxyz_gl_set_gc (Display *dpy, GC gc)
 {
   int function;
   Bool alpha_allowed_p;
+  GLuint clip_mask;
 
   // GC is NULL for XClearArea and XClearWindow.
   if (gc) {
     function = gc->gcv.function;
-    alpha_allowed_p = gc->gcv.alpha_allowed_p;
-    set_clip_mask (gc);
+    alpha_allowed_p = gc->gcv.alpha_allowed_p || gc->clip_mask;
+    clip_mask = gc->clip_mask;
   } else {
     function = GXcopy;
     alpha_allowed_p = False;
-    // TODO: Set null clip mask for NULL GC here.
+    clip_mask = 0;
   }
 
   /* GL_COLOR_LOGIC_OP: OpenGL 1.1. */
@@ -616,16 +703,54 @@ jwxyz_gl_set_gc (Display *dpy, GC gc)
      widespread.
    */
 
-  if (alpha_allowed_p != dpy->gc_alpha_allowed_p) {
-    dpy->gc_alpha_allowed_p = alpha_allowed_p;
-    if (gc && gc->gcv.alpha_allowed_p) {
-      // TODO: Maybe move glBlendFunc to XCreatePixmap?
-      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-      glEnable (GL_BLEND);
-    } else {
-      glDisable (GL_BLEND);
+  dpy->gc_alpha_allowed_p = alpha_allowed_p;
+  if (alpha_allowed_p || clip_mask) {
+    // TODO: Maybe move glBlendFunc to XCreatePixmap?
+    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    glEnable (GL_BLEND);
+  } else {
+    glDisable (GL_BLEND);
+  }
+
+  /* Texture units:
+     GL_TEXTURE0: Texture for XPutImage/XCopyArea (if applicable)
+     GL_TEXTURE1: Texture for clip masks (if applicable)
+   */
+  dpy->gc_clip_mask = clip_mask;
+
+  glActiveTexture (GL_TEXTURE1);
+  if (clip_mask) {
+    glEnable (dpy->gl_texture_target);
+    glBindTexture (dpy->gl_texture_target, gc->clip_mask);
+
+    glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
+               alpha_allowed_p ? GL_MODULATE : GL_REPLACE);
+
+    glMatrixMode (GL_TEXTURE);
+    glLoadIdentity ();
+
+    unsigned
+      tex_w = gc->clip_mask_width + 2, tex_h = gc->clip_mask_height + 2;
+    tex_size (dpy, &tex_w, &tex_h);
+
+# ifndef HAVE_JWZGLES
+    if (dpy->gl_texture_target == GL_TEXTURE_RECTANGLE_EXT)
+    {
+      glScalef (1, -1, 1);
     }
+    else
+# endif
+    {
+      glScalef (1.0f / tex_w, -1.0f / tex_h, 1);
+    }
+
+    glTranslatef (1 - gc->gcv.clip_x_origin,
+                  1 - gc->gcv.clip_y_origin - (int)gc->clip_mask_height - 2,
+                  0);
+  } else {
+    glDisable (dpy->gl_texture_target);
   }
+  glActiveTexture (GL_TEXTURE0);
 }
 
 
@@ -720,14 +845,18 @@ clear_texture (Display *dpy)
                 0, dpy->pixel_format, gl_pixel_type (dpy), NULL);
 }
 
+
 static void
-set_white (void)
+vertex_pointer (Display *dpy, GLenum type, GLsizei stride,
+                const void *pointer)
 {
-#ifdef HAVE_JWZGLES
-  glColor4f (1, 1, 1, 1);
-#else
-  glColor3ub (0xff, 0xff, 0xff);
-#endif
+  glVertexPointer(2, type, stride, pointer);
+  if (dpy->gc_clip_mask) {
+    glClientActiveTexture (GL_TEXTURE1);
+    glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+    glTexCoordPointer (2, type, stride, pointer);
+    glClientActiveTexture (GL_TEXTURE0);
+  }
 }
 
 
@@ -747,7 +876,8 @@ jwxyz_gl_flush (Display *dpy)
 
   // TODO: Use glColor instead of glColorPointer if there's just one color.
   // TODO: Does OpenGL use both GL_COLOR_ARRAY and glColor at the same time?
-  set_white();
+  //       (Probably not.)
+  glColor4f (1, 1, 1, 1);
 
   Bool shifted = dpy->queue_mode == GL_POINTS || dpy->queue_mode == GL_LINES;
   if (shifted) {
@@ -756,9 +886,9 @@ jwxyz_gl_flush (Display *dpy)
   }
 
   glColorPointer (4, GL_UNSIGNED_BYTE, 0, dpy->queue_color);
-  glVertexPointer (2,
-                   dpy->queue_mode == GL_TRIANGLE_STRIP ? GL_FLOAT : GL_SHORT,
-                   0, dpy->queue_vertex);
+  vertex_pointer (dpy,
+                  dpy->queue_mode == GL_TRIANGLE_STRIP ? GL_FLOAT : GL_SHORT,
+                  0, dpy->queue_vertex);
   glDrawArrays (dpy->queue_mode, 0, dpy->queue_size);
 
   // TODO: This is right, right?
@@ -766,8 +896,8 @@ jwxyz_gl_flush (Display *dpy)
     Assert (!(dpy->queue_size % 2), "bad count for GL_LINES");
     glColorPointer (4, GL_UNSIGNED_BYTE, sizeof(GLubyte) * 8,
                     dpy->queue_color);
-    glVertexPointer (2, GL_SHORT, sizeof(GLshort) * 4,
-                     (GLshort *)dpy->queue_vertex + 2);
+    vertex_pointer (dpy, GL_SHORT, sizeof(GLshort) * 4,
+                    (GLshort *)dpy->queue_vertex + 2);
     glDrawArrays (GL_POINTS, 0, dpy->queue_size / 2);
   }
 
@@ -833,30 +963,44 @@ jwxyz_gl_copy_area_write_tex_image (Display *dpy, GC gc, int src_x, int src_y,
   /* Must match what's in jwxyz_gl_copy_area_read_tex_image. */
   glBindTexture (dpy->gl_texture_target, dpy->textures[texture_rgba]);
 
-  jwxyz_gl_draw_image (dpy->gl_texture_target, tex_w, tex_h, 0, 0,
-                       width, height, dst_x, dst_y);
+  jwxyz_gl_draw_image (dpy, gc, dpy->gl_texture_target, tex_w, tex_h,
+                       0, 0, gc->depth, width, height, dst_x, dst_y, False);
 
   clear_texture (dpy);
 }
 
 
 void
-jwxyz_gl_draw_image (GLenum gl_texture_target,
+jwxyz_gl_draw_image (Display *dpy, GC gc, GLenum gl_texture_target,
                      unsigned int tex_w, unsigned int tex_h,
-                     int src_x, int src_y,
+                     int src_x, int src_y, int src_depth,
                      unsigned int width, unsigned int height,
-                     int dst_x, int dst_y)
+                     int dst_x, int dst_y, Bool flip_y)
 {
-  set_white ();
-  glEnable (gl_texture_target);
+  if (!gc || src_depth == gc->depth) {
+    glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+  } else {
+    Assert (src_depth == 1 && gc->depth == 32,
+            "jwxyz_gl_draw_image: bad depths");
+
+    set_color (dpy, gc->gcv.background, gc->depth, gc->gcv.alpha_allowed_p);
+
+    GLfloat rgba[4];
+    query_color (dpy, gc->gcv.foreground, gc->depth, gc->gcv.alpha_allowed_p,
+                 rgba);
+    glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
+    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, rgba);
+  }
 
+  glEnable (gl_texture_target);
   glEnableClientState (GL_TEXTURE_COORD_ARRAY);
   glEnableClientState (GL_VERTEX_ARRAY);
-    
-  /* TODO: Copied from XPutImage. Refactor. */
+
+  Assert (!glIsEnabled (GL_COLOR_ARRAY), "glIsEnabled (GL_COLOR_ARRAY)");
+  Assert (!glIsEnabled (GL_NORMAL_ARRAY), "glIsEnabled (GL_NORMAL_ARRAY)");
+
   /* TODO: EXT_draw_texture or whatever it's called. */
-  GLfloat vertices[4][2] =
-  {
+  GLfloat vertices[4][2] = {
     {dst_x, dst_y},
     {dst_x, dst_y + height},
     {dst_x + width, dst_y + height},
@@ -864,9 +1008,14 @@ jwxyz_gl_draw_image (GLenum gl_texture_target,
   };
 
   GLfloat
-    tex_x0 = src_x, tex_y0 = src_y + height,
+    tex_x0 = src_x, tex_y0 = src_y,
     tex_x1 = src_x + width, tex_y1 = src_y;
 
+  if (flip_y)
+    tex_y1 += height;
+  else
+    tex_y0 += height;
+
 # ifndef HAVE_JWZGLES
   if (gl_texture_target != GL_TEXTURE_RECTANGLE_EXT)
 # endif
@@ -878,21 +1027,22 @@ jwxyz_gl_draw_image (GLenum gl_texture_target,
     tex_y1 *= my;
   }
 
-  GLfloat tex_coords[4][2] =
-  {
+  GLfloat tex_coords[4][2] = {
     {tex_x0, tex_y0},
     {tex_x0, tex_y1},
     {tex_x1, tex_y1},
     {tex_x1, tex_y0}
   };
 
-  glVertexPointer (2, GL_FLOAT, 0, vertices);
+  vertex_pointer (dpy, GL_FLOAT, 0, vertices);
   glTexCoordPointer (2, GL_FLOAT, 0, tex_coords);
   glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
 
+//clear_texture();
   glDisable (gl_texture_target);
 }
 
+#if 0
 void
 jwxyz_gl_copy_area_read_pixels (Display *dpy, Drawable src, Drawable dst,
                                 GC gc, int src_x, int src_y,
@@ -903,6 +1053,7 @@ jwxyz_gl_copy_area_read_pixels (Display *dpy, Drawable src, Drawable dst,
   XPutImage (dpy, dst, gc, img, 0, 0, dst_x, dst_y, width, height);
   XDestroyImage (img);
 }
+#endif
 
 
 static int
@@ -934,7 +1085,7 @@ DrawLines (Display *dpy, Drawable d, GC gc, XPoint *points, int count,
   
   glEnableClientState (GL_VERTEX_ARRAY);
   glDisableClientState (GL_TEXTURE_COORD_ARRAY);
-  glVertexPointer (2, GL_SHORT, 0, vertices);
+  vertex_pointer (dpy, GL_SHORT, 0, vertices);
   glDrawArrays (GL_LINE_STRIP, 0, count);
   
   free (vertices);
@@ -942,7 +1093,7 @@ DrawLines (Display *dpy, Drawable d, GC gc, XPoint *points, int count,
   if (gc->gcv.cap_style != CapNotLast) {
     // TODO: How does this look with multisampling?
     // TODO: Disable me for closed loops.
-    glVertexPointer (2, GL_SHORT, 0, p);
+    vertex_pointer (dpy, GL_SHORT, 0, p);
     glDrawArrays (GL_POINTS, 0, 1);
   }
 
@@ -1114,7 +1265,7 @@ FillPolygon (Display *dpy, Drawable d, GC gc,
     glEnableClientState (GL_VERTEX_ARRAY);
     glDisableClientState (GL_TEXTURE_COORD_ARRAY);
 
-    glVertexPointer (2, GL_SHORT, 0, vertices);
+    vertex_pointer (dpy, GL_SHORT, 0, vertices);
     glDrawArrays (GL_TRIANGLE_FAN, 0, npoints);
 
     free(vertices);
@@ -1126,7 +1277,7 @@ FillPolygon (Display *dpy, Drawable d, GC gc,
     linked_point *root;
     root = (linked_point *) malloc( sizeof(linked_point) );
     set_points_list(points,npoints,root);
-    traverse_points_list(root);
+    traverse_points_list(dpy, root);
 
   } else {
     Assert((shape == Convex || shape == Nonconvex),
@@ -1279,7 +1430,7 @@ draw_arc_gl (Display *dpy, Drawable d, GC gc, int x, int y,
   glDisableClientState (GL_TEXTURE_COORD_ARRAY);
   glEnableClientState (GL_VERTEX_ARRAY);
   
-  glVertexPointer (2, GL_FLOAT, 0, data);
+  vertex_pointer (dpy, GL_FLOAT, 0, data);
   glDrawArrays (fill_p ? GL_TRIANGLE_FAN : GL_LINE_STRIP,
                 0,
                 (GLsizei)((data_ptr - data) / 2));
@@ -1340,21 +1491,26 @@ CreateGC (Display *dpy, Drawable d, unsigned long mask, XGCValues *xgcv)
 }
 
 
+static void
+free_clip_mask (Display *dpy, GC gc)
+{
+  if (gc->gcv.clip_mask) {
+    if (dpy->gc_clip_mask == gc->clip_mask) {
+      jwxyz_gl_flush (dpy);
+      dpy->gc_clip_mask = 0;
+    }
+    glDeleteTextures (1, &gc->clip_mask);
+  }
+}
+
+
 static int
 FreeGC (Display *dpy, GC gc)
 {
   if (gc->gcv.font)
     XUnloadFont (dpy, gc->gcv.font);
 
-  // TODO
-/*
-  Assert (!!gc->gcv.clip_mask == !!gc->clip_mask, "GC clip mask mixup");
-
-  if (gc->gcv.clip_mask) {
-    XFreePixmap (dpy, gc->gcv.clip_mask);
-    CGImageRelease (gc->clip_mask);
-  }
-*/
+  free_clip_mask (dpy, gc);
   free (gc);
   return 0;
 }
@@ -1447,8 +1603,6 @@ PutImage (Display *dpy, Drawable d, GC gc, XImage *ximage,
 # endif
 
     // glPixelStorei (GL_UNPACK_ALIGNMENT, 4); // Probably unnecessary.
-
-    set_white ();
   } else {
     Assert (bpp == 1, "expected 1 or 32 bpp");
     Assert ((src_x % 8) == 0,
@@ -1526,9 +1680,6 @@ PutImage (Display *dpy, Drawable d, GC gc, XImage *ximage,
     tex_index = texture_mono;
 
     // glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
-
-    set_color (dpy, gc->gcv.foreground, gc->depth, gc->gcv.alpha_allowed_p);
-    // TODO: Deal with the background color.
   }
 
 # if 1 // defined HAVE_JWZGLES
@@ -1536,80 +1687,19 @@ PutImage (Display *dpy, Drawable d, GC gc, XImage *ximage,
   // TODO: Make use of OES_draw_texture.
 
   unsigned tex_w = src_w, tex_h = h;
-  if (!dpy->gl_texture_npot_p) {
-    tex_w = to_pow2(tex_w);
-    tex_h = to_pow2(tex_h);
-  }
-
   glBindTexture (dpy->gl_texture_target, dpy->textures[tex_index]);
 
   // A fun project: reimplement xshm.c by means of a PBO using
   // GL_MAP_UNSYNCHRONIZED_BIT.
 
-  // TODO: Would using glTexSubImage2D exclusively be faster?
-  if (tex_w == src_w && tex_h == h) {
-    glTexImage2D (dpy->gl_texture_target, 0, tex_internalformat, tex_w, tex_h,
-                  0, tex_format, tex_type, tex_data);
-  } else {
-    // TODO: Sampling the last row might be a problem if src_x != 0.
-    glTexImage2D (dpy->gl_texture_target, 0, tex_internalformat, tex_w, tex_h,
-                  0, tex_format, tex_type, NULL);
-    glTexSubImage2D (dpy->gl_texture_target, 0, 0, 0, src_w, h,
-                     tex_format, tex_type, tex_data);
-  }
+  tex_image (dpy, tex_internalformat, &tex_w, &tex_h, tex_format, tex_type,
+             tex_data);
 
   if (bpp == 1)
     free(tex_data);
 
-  // TODO: This looks a lot like jwxyz_gl_draw_image. Refactor.
-
-  // glEnable (dpy->gl_texture_target);
-  // glColor4f (0.5, 0, 1, 1);
-  glEnable (dpy->gl_texture_target);
-  glEnableClientState (GL_VERTEX_ARRAY);
-  glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-
-  // TODO: Why are these ever turned on in the first place?
-  glDisableClientState (GL_COLOR_ARRAY);
-  glDisableClientState (GL_NORMAL_ARRAY);
-  // glDisableClientState (GL_TEXTURE_COORD_ARRAY);
-
-  GLfloat vertices[4][2] =
-  {
-    {dest_x, dest_y},
-    {dest_x, dest_y + h},
-    {dest_x + w, dest_y + h},
-    {dest_x + w, dest_y}
-  };
-
-  GLfloat texcoord_w, texcoord_h;
-#  ifndef HAVE_JWZGLES
-  if (dpy->gl_texture_target == GL_TEXTURE_RECTANGLE_EXT) {
-    texcoord_w = w;
-    texcoord_h = h;
-  } else
-#  endif /* HAVE_JWZGLES */
-  {
-    texcoord_w = (double)w / tex_w;
-    texcoord_h = (double)h / tex_h;
-  }
-
-  GLfloat tex_coords[4][2];
-  tex_coords[0][0] = 0;
-  tex_coords[0][1] = 0;
-  tex_coords[1][0] = 0;
-  tex_coords[1][1] = texcoord_h;
-  tex_coords[2][0] = texcoord_w;
-  tex_coords[2][1] = texcoord_h;
-  tex_coords[3][0] = texcoord_w;
-  tex_coords[3][1] = 0;
-
-  glVertexPointer (2, GL_FLOAT, 0, vertices);
-  glTexCoordPointer (2, GL_FLOAT, 0, tex_coords);
-  glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
-
-//clear_texture();
-  glDisable (dpy->gl_texture_target);
+  jwxyz_gl_draw_image (dpy, gc, dpy->gl_texture_target, tex_w, tex_h,
+                       0, 0, bpp, w, h, dest_x, dest_y, True);
 # else
   glRasterPos2i (dest_x, dest_y);
   glPixelZoom (1, -1);
@@ -1738,47 +1828,101 @@ GetSubImage (Display *dpy, Drawable d, int x, int y,
 }
 
 
-#if 0
-static Pixmap
-copy_pixmap (Display *dpy, Pixmap p)
+static int
+SetClipMask (Display *dpy, GC gc, Pixmap m)
 {
-  if (!p) return 0;
-  Assert (p->type == PIXMAP, "not a pixmap");
-
-  Pixmap p2 = 0;
-
-  Window root;
-  int x, y;
-  unsigned int width, height, border_width, depth;
-  if (XGetGeometry (dpy, p, &root,
-                    &x, &y, &width, &height, &border_width, &depth)) {
-    XGCValues gcv;
-    gcv.function = GXcopy;
-    GC gc = XCreateGC (dpy, p, GCFunction, &gcv);
-    if (gc) {
-      p2 = XCreatePixmap (dpy, p, width, height, depth);
-      if (p2)
-        XCopyArea (dpy, p, p2, gc, 0, 0, width, height, 0, 0);
-      XFreeGC (dpy, gc);
-    }
+  Assert (m != dpy->main_window, "not a pixmap");
+
+  free_clip_mask (dpy, gc);
+
+  if (!m) {
+    gc->clip_mask = 0;
+    return 0;
   }
 
-  Assert (p2, "could not copy pixmap");
+  Assert (jwxyz_drawable_depth (m) == 1, "wrong depth for clip mask");
 
-  return p2;
-}
-#endif
+  const XRectangle *frame = jwxyz_frame (m);
+  gc->clip_mask_width = frame->width;
+  gc->clip_mask_height = frame->height;
 
+  /* Apparently GL_ALPHA isn't a valid format for a texture used in an FBO:
 
-static int
-SetClipMask (Display *dpy, GC gc, Pixmap m)
-{
-  Log ("TODO: No clip masks yet");
-  /* Protip: Do glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-     clearing just the stencil buffer in a packed depth/stencil arrangement is
-     slower than the above. Adreno recommends this, but other GPUs probably
-     benefit as well.
+    (86) Are any one- or two- component formats color-renderable?
+
+            Presently none of the one- or two- component texture formats
+            defined in unextended OpenGL is color-renderable.  The R
+            and RG float formats defined by the NV_float_buffer
+            extension are color-renderable.
+
+            Although an early draft of the FBO specification permitted
+            rendering into alpha, luminance, and intensity formats, this
+            this capability was pulled when it was realized that it was
+            under-specified exactly how rendering into these formats
+            would work.  (specifically, how R/G/B/A map to I/L/A)
+
+     <https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_framebuffer_object.txt>
+
+     ...Therefore, 1-bit drawables get to have wasted color channels.
+     Currently, R=G=B=grey, and the alpha channel is unused.
    */
+
+  /* There doesn't seem to be any way to move what's on one of the color
+     channels to the alpha channel in GLES 1.1 without leaving the GPU.
+   */
+
+  /* GLES 1.1 only supports GL_CLAMP_TO_EDGE or GL_REPEAT for
+     GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T, so to prevent drawing outside
+     the clip mask pixmap, there's two options:
+     1. Use glScissor.
+     2. Add a black border.
+
+     Option #2 is in use here.
+
+     The following converts in-place an RGBA image to alpha-only image with a
+     1px black border.
+   */
+
+  // Prefix/suffix: 1 row+1 pixel, rounded to nearest int32.
+  size_t pad0 = frame->width + 3, pad = (pad0 + 3) & ~3;
+  uint8_t *data = malloc(2 * pad + frame->width * frame->height * 4);
+
+  uint8_t *rgba = data + pad;
+  uint8_t *alpha = rgba;
+  uint8_t *alpha0 = alpha - pad0;
+  memset (alpha0, 0, pad0); // Top row.
+
+  jwxyz_gl_flush (dpy);
+  jwxyz_bind_drawable (dpy, dpy->main_window, m);
+  glReadPixels (0, 0, frame->width, frame->height, GL_RGBA, GL_UNSIGNED_BYTE,
+                rgba);
+
+  for (unsigned y = 0; y != frame->height; ++y) {
+    for (unsigned x = 0; x != frame->width; ++x)
+      alpha[x] = rgba[x * 4];
+
+    rgba += frame->width * 4;
+
+    alpha += frame->width;
+    alpha[0] = 0;
+    alpha[1] = 0;
+    alpha += 2;
+  }
+
+  alpha -= 2;
+  memset (alpha, 0, pad0); // Bottom row.
+
+  glGenTextures (1, &gc->clip_mask);
+  tex_parameters (dpy, gc->clip_mask);
+
+  glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+
+  unsigned tex_w = frame->width + 2, tex_h = frame->height + 2;
+  tex_image (dpy, GL_ALPHA, &tex_w, &tex_h, GL_ALPHA, GL_UNSIGNED_BYTE,
+             alpha0);
+
+  free(data);
+
   return 0;
 }
 
@@ -1859,7 +2003,7 @@ Bool is_same_slope(linked_point * a)
     return aa == bb;
 }
 
-void draw_three_vertices(linked_point * a, Bool triangle)
+void draw_three_vertices(Display *dpy, linked_point * a, Bool triangle)
 {
 
     linked_point *b;
@@ -1882,7 +2026,7 @@ void draw_three_vertices(linked_point * a, Bool triangle)
     }
 
     glEnableClientState(GL_VERTEX_ARRAY);
-    glVertexPointer(2, GL_FLOAT, 0, vertices);
+    vertex_pointer(dpy, GL_FLOAT, 0, vertices);
     glDrawArrays(drawType, 0, 3);
 
     free(b);  // cut midpoint off from remaining polygon vertex list
@@ -1919,16 +2063,16 @@ Bool is_three_point_loop(linked_point * head)
 }
 
 
-void traverse_points_list(linked_point * root)
+void traverse_points_list(Display *dpy, linked_point * root)
 {
     linked_point *head;
     head = root;
 
     while (!is_three_point_loop(head)) {
         if (is_an_ear(head)) {
-            draw_three_vertices(head, True);
+            draw_three_vertices(dpy, head, True);
         } else if (is_same_slope(head)) {
-            draw_three_vertices(head, False);
+            draw_three_vertices(dpy, head, False);
         } else {
             head = head->next;
         }
@@ -1936,9 +2080,9 @@ void traverse_points_list(linked_point * root)
 
     // handle final three vertices in polygon
     if (is_an_ear(head)) {
-        draw_three_vertices(head, True);
+        draw_three_vertices(dpy, head, True);
     } else if (is_same_slope(head)) {
-        draw_three_vertices(head, False);
+        draw_three_vertices(dpy, head, False);
     } else {
         free(head->next->next);
         free(head->next);
index a419965be594b9b9388602a65c0f9cdc3603d700..b1b333275f6a961d5a69718cee8273644caa9c79 100644 (file)
@@ -64,12 +64,17 @@ jwxyz_image_make_display (Window w, const unsigned char *rgba_bytes)
   Visual *v = &d->visual;
   v->class      = TrueColor;
   Assert (rgba_bytes[3] == 3, "alpha not last");
+  unsigned long masks[4];
   for (unsigned i = 0; i != 4; ++i) {
     union color_bytes color;
     color.pixel = 0;
     color.bytes[rgba_bytes[i]] = 0xff;
-    v->rgba_masks[i] = color.pixel;
+    masks[i] = color.pixel;
   }
+  v->red_mask   = masks[0];
+  v->green_mask = masks[1];
+  v->blue_mask  = masks[2];
+  v->alpha_mask = masks[3];
 
   d->timers_data = jwxyz_sources_init (XtDisplayToApplicationContext (d));
   d->window_background = BlackPixel(d,0);
index 0e289c784651a209ba0df134f440aad33cd13fab..c70bdbe862ef0da3c5702d3109d19df686a31f81 100644 (file)
@@ -473,8 +473,9 @@ extern int XFreePixmap (Display *, Pixmap);
 extern char *XGetAtomName (Display *, Atom);
 
 extern void set_points_list(XPoint *points, int npoints, linked_point *root);
-extern void traverse_points_list(linked_point * root);
-extern void draw_three_vertices(linked_point * a, Bool triangle);
+extern void traverse_points_list(Display *dpy, linked_point * root);
+extern void draw_three_vertices(Display *dpy, linked_point * a,
+                                Bool triangle);
 extern double compute_edge_length(linked_point * a, linked_point * b);
 extern double get_angle(double a, double b, double c);
 extern Bool is_same_slope(linked_point * a);
@@ -537,7 +538,8 @@ extern void check_gl_error (const char *type);
 // Only utils/xft.c uses this, out of necessity.
 struct jwxyz_Visual {
   int class;           /* class of screen (monochrome, etc.) */
-  unsigned long rgba_masks[4]; /* mask values */
+  unsigned long red_mask, green_mask, blue_mask;       /* same as Xlib.h */
+  unsigned long alpha_mask;                            /* new */
 };
 
 struct jwxyz_XGCValues {
index 9e7b57b330a5bdd34793ab1c2f9cd4af9093f702..4256f6df438edba34bd15847870a9b096c14b313 100644 (file)
@@ -342,11 +342,16 @@ jwxyz_quartz_make_display (Window w)
   union color_bytes color;
   convert_mode_t mode =
     convert_mode_invert (convert_mode_to_rgba (d->bitmap_info));
+  unsigned long masks[4];
   for (unsigned i = 0; i != 4; ++i) {
     color.pixel = 0;
     color.bytes[i] = 0xff;
-    v->rgba_masks[i] = convert_px (color.pixel, mode);
+    masks[i] = convert_px (color.pixel, mode);
   }
+  v->red_mask   = masks[0];
+  v->green_mask = masks[1];
+  v->blue_mask  = masks[2];
+  v->alpha_mask = masks[3];
 
   CGBitmapInfo byte_order = d->bitmap_info & kCGBitmapByteOrderMask;
   Assert ( ! (d->bitmap_info & kCGBitmapFloatComponents) &&
@@ -1501,12 +1506,17 @@ jwxyz_png_to_ximage (Display *dpy, Visual *visual,
   NSImage *img = [[NSImage alloc] initWithData:
                                     [NSData dataWithBytes:png_data
                                             length:data_size]];
+  if (! img) return 0;
 #ifndef USE_IPHONE
   NSBitmapImageRep *bm = [NSBitmapImageRep
                            imageRepWithData:
                              [NSBitmapImageRep
                                TIFFRepresentationOfImageRepsInArray:
                                  [img representations]]];
+  if (!bm) {
+    [img release];
+    return 0;
+  }
   int width   = [img size].width;
   int height  = [img size].height;
   size_t ibpp = [bm bitsPerPixel];
@@ -1517,6 +1527,10 @@ jwxyz_png_to_ximage (Display *dpy, Visual *visual,
                          : 0);
 #else  // USE_IPHONE
   CGImageRef cgi = [img CGImage];
+  if (!cgi) {
+    [img release];
+    return 0;
+  }
   int width = CGImageGetWidth (cgi);
   int height = CGImageGetHeight (cgi);
   size_t ibpp = 32;
index 5d0181eed51bb34a763a9480e23905d8b8ad6932..6a38d2effdf9b70b0514d6edbd4a7877f1db36d2 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-2016 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1991-2018 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 
 #define JWXYZ_QUERY_COLOR(dpy, pixel, mult, rgba) \
   { \
-    const unsigned long *_MASKS = \
-       DefaultVisualOfScreen (DefaultScreenOfDisplay (dpy))->rgba_masks; \
-    for (unsigned i = 0; i != 4; ++i) \
-      (rgba)[i] = ((pixel) & _MASKS[i]) * (mult) / _MASKS[i]; \
+    Visual *_V = DefaultVisualOfScreen (DefaultScreenOfDisplay (dpy)); \
+    (rgba)[0] = ((pixel) & _V->red_mask)   * (mult) / _V->red_mask;    \
+    (rgba)[1] = ((pixel) & _V->green_mask) * (mult) / _V->green_mask;  \
+    (rgba)[2] = ((pixel) & _V->blue_mask)  * (mult) / _V->blue_mask;   \
+    (rgba)[3] = ((pixel) & _V->alpha_mask) * (mult) / _V->alpha_mask;  \
   }
 
 /* jwxyz.m, jwxyz-gl.c, jwxyz-image.c */
@@ -167,11 +168,13 @@ extern void jwxyz_gl_copy_area_write_tex_image (Display *dpy, GC gc,
                                                 unsigned int width,
                                                 unsigned int height,
                                                 int dst_x, int dst_y);
-extern void jwxyz_gl_draw_image (GLenum target,
+
+extern void jwxyz_gl_draw_image (Display *dpy, GC gc,
+                                 GLenum gl_texture_target,
                                  unsigned int tex_w, unsigned int tex_h,
-                                 int src_x, int src_y,
+                                 int src_x, int src_y, int src_depth,
                                  unsigned int width, unsigned int height,
-                                 int dst_x, int dst_y);
+                                 int dst_x, int dst_y, Bool flip_y);
 
 /* glReadPixels followed by glTexImage2D. This is terrible, so only use this
    if nothing else works.
index 3df134ab003e41d56fb39a0be514c7ef9f444e44..e0437e06eb530a323adf0e9157fbb5b55c31e32c 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2012-2016 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2012-2018 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -3084,6 +3084,25 @@ jwzgles_glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat,
 }
 
 
+void
+jwzgles_glCopyTexSubImage2D (GLenum target, GLint level, 
+                             GLint xoff, GLint yoff, 
+                             GLint x, GLint y, 
+                             GLsizei width, GLsizei height)
+{
+  Assert (!state->compiling_verts, 
+          "glCopyTexSubImage2D not allowed inside glBegin");
+  Assert (!state->compiling_list,    /* technically legal, but stupid! */
+          "glCopyTexSubImage2D not allowed inside glNewList");
+  if (! state->replaying_list)
+    LOG9 ("direct %-12s %s %d %d %d %d %d %d %d", "glCopyTexSubImage2D", 
+          mode_desc(target), level, xoff, yoff, x, y, width, height);
+  glCopyTexSubImage2D (target, level,   /* the real one */
+                       xoff, yoff, x, y, width, height);
+  CHECK("glCopyTexSubImage2D");
+}
+
+
 /* OpenGLES doesn't have auto texture-generation at all!
    "Oh, just rewrite that code to use GPU shaders", they say.
    How fucking convenient.
index dc71b075db33c4c60281b413395ea41df57a220a..8f0920887bc08108fa781b3e378472679712c820 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2012-2015 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2012-2018 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -204,6 +204,7 @@ extern void jwzgles_glViewport (GLuint, GLuint, GLuint, GLuint);
 extern void jwzgles_glTranslatef (GLfloat, GLfloat, GLfloat);
 extern void jwzgles_glRotatef (GLfloat, GLfloat, GLfloat, GLfloat);
 extern void jwzgles_glRotated (GLdouble, GLdouble x, GLdouble y, GLdouble z);
+extern void jwzgles_glReadBuffer (GLuint);
 extern void jwzgles_glScalef (GLfloat, GLfloat, GLfloat);
 extern void jwzgles_glColor3f (GLfloat, GLfloat, GLfloat);
 extern void jwzgles_glColor4f (GLfloat, GLfloat, GLfloat, GLfloat);
@@ -289,6 +290,10 @@ extern void jwzgles_glCopyTexImage2D (GLenum target, GLint level,
                                       GLint x, GLint y, 
                                       GLsizei width, GLsizei height, 
                                       GLint border);
+extern void jwzgles_glCopyTexSubImage2D (GLenum target, GLint level, 
+                                         GLint xoff, GLint yoff, 
+                                         GLint x, GLint y, 
+                                         GLsizei width, GLsizei height);
 extern void jwzgles_glInterleavedArrays (GLenum, GLsizei, const GLvoid *);
 extern void jwzgles_glTexEnvf (GLuint, GLuint, GLfloat);
 extern void jwzgles_glTexEnvi (GLuint, GLuint, GLuint);
index 89066f9ec9078ca9ebd91639c9c9932a9a887737..9b84188df397b1ad3a320b8a53235816c1e85ca0 100644 (file)
@@ -1,4 +1,4 @@
-# Auto-generated: Thu Apr 12 13:00:50 PDT 2018
+# Auto-generated: Sun Aug 12 16:36:38 PDT 2018
 driver/demo-Gtk-conf.c
 driver/demo-Gtk.c
 driver/screensaver-properties.desktop.in
@@ -74,6 +74,7 @@ hacks/config/euler2d.xml
 hacks/config/extrusion.xml
 hacks/config/fadeplot.xml
 hacks/config/fiberlamp.xml
+hacks/config/filmleader.xml
 hacks/config/fireworkx.xml
 hacks/config/flag.xml
 hacks/config/flame.xml
@@ -97,6 +98,7 @@ hacks/config/glcells.xml
 hacks/config/gleidescope.xml
 hacks/config/glforestfire.xml
 hacks/config/glhanoi.xml
+hacks/config/glitchpeg.xml
 hacks/config/glknots.xml
 hacks/config/glmatrix.xml
 hacks/config/glplanet.xml
@@ -237,6 +239,7 @@ hacks/config/twang.xml
 hacks/config/unicrud.xml
 hacks/config/unknownpleasures.xml
 hacks/config/vermiculate.xml
+hacks/config/vfeedback.xml
 hacks/config/vidwhacker.xml
 hacks/config/vigilance.xml
 hacks/config/vines.xml
index 9817517d133fc7ddba2e6a82a98d71ba85461ec4..aee19eef993a96f46150276d6fbdc11dd346346f 100644 (file)
--- a/setup.com
+++ b/setup.com
@@ -38,6 +38,7 @@ $ eruption    :== $'mydir'eruption
 $ euler2d      :== $'mydir'euler2d
 $ fadeplot     :== $'mydir'fadeplot
 $ fiberlamp    :== $'mydir'fiberlamp
+$ filmleader   :== $'mydir'filmleader
 $ fireworkx    :== $'mydir'fireworkx
 $ flame                :== $'mydir'flame
 $ flow         :== $'mydir'flow
@@ -45,6 +46,7 @@ $ fluidballs  :== $'mydir'fluidballs
 $ fontglide    :== $'mydir'fontglide
 $ fuzzyflakes  :== $'mydir'fuzzyflakes
 $ galaxy       :== $'mydir'galaxy
+$ glitchpeg    :== $'mydir'glitchpeg
 $ goop         :== $'mydir'goop
 $ grav         :== $'mydir'grav
 $ greynetic    :== $'mydir'greynetic
@@ -107,6 +109,7 @@ $ triangle  :== $'mydir'triangle
 $ truchet      :== $'mydir'truchet
 $ twang                :== $'mydir'twang
 $ vermiculate  :== $'mydir'vermiculate
+$ vfeedback    :== $'mydir'vfeedback
 $ wander       :== $'mydir'wander
 $ webcollage-helper    :== $'mydir'webcollage-helper
 $ whirlwindwarp        :== $'mydir'whirlwindwarp
index ef22918d386b665456f53e7759958c193a681fde..56fc602f06155eb64ac66d874a18b83bf899989b 100644 (file)
@@ -113,7 +113,8 @@ OBJS                = alpha.o colors.o fade.o grabscreen.o grabclient.o hsv.o \
                  visual-gl.o xmu.o logo.o yarandom.o erase.o \
                  xshm.o xdbe.o colorbars.o minixpm.o textclient.o \
                  textclient-mobile.o aligned_malloc.o thread_util.o \
-                 async_netdb.o xft.o utf8wc.o pow2.o font-retry.o
+                 async_netdb.o xft.o utf8wc.o pow2.o \
+                 font-retry.o font-retry-xft.o
 HDRS           = alpha.h colors.h fade.h grabscreen.h hsv.h resources.h \
                  spline.h usleep.h utils.h version.h visual.h vroot.h xmu.h \
                  yarandom.h erase.h xshm.h xdbe.h colorbars.h minixpm.h \
@@ -189,8 +190,14 @@ echo_tarfiles:
 
 
 # How we build object files in this directory.
+CCUTILS = $(INCLUDES) $(DEFS) $(CPPFLAGS) $(CFLAGS) $(X_CFLAGS)
 .c.o:
-       $(CC) -c $(INCLUDES) $(DEFS) $(CPPFLAGS) $(CFLAGS) $(X_CFLAGS) $<
+       $(CC) -c $(CCUTILS) $<
+
+# Two versions of this: driver/ does not link with Xft, but hacks/ does.
+font-retry-xft.o: font-retry.c
+       $(CC) -c $(CCUTILS) -DUSE_XFT $< -o $@
+
 
 # Rules for generating the VMS makefiles on Unix, so that it doesn't have to
 # be done by hand...
@@ -257,6 +264,8 @@ fade.o: $(srcdir)/visual.h
 font-retry.o: ../config.h
 font-retry.o: $(srcdir)/font-retry.h
 font-retry.o: $(srcdir)/utils.h
+font-retry.o: $(srcdir)/visual.h
+font-retry.o: $(srcdir)/xft.h
 grabclient.o: ../config.h
 grabclient.o: $(srcdir)/grabscreen.h
 grabclient.o: $(srcdir)/resources.h
index b5e87abe3a88b91b041ae0c7b9d3f41facfdeef8..3e2bc871a9984e7c249f64ae73d732799de58039 100644 (file)
@@ -60,7 +60,6 @@ draw_colorbars (Screen *screen, Visual *visual,
                 Pixmap logo, Pixmap logo_mask)
 {
   Display *dpy = DisplayOfScreen (screen);
-  int oy = y;
   int ypct = 0;
   int j;
   XGCValues gcv;
@@ -106,8 +105,6 @@ draw_colorbars (Screen *screen, Visual *visual,
       y = y2;
     }
 
-  y = oy;
-
   /* Add in the xscreensaver logo */
   if (logo)
     {
index 395ffbe58f66dd31090aaacacf2b16dc29876e20..c3e91a08e8b6e1d24c80659698a7130d8fc852ff 100644 (file)
@@ -16,6 +16,8 @@
 #define _GNU_SOURCE
 
 #include "utils.h"
+#include "visual.h"
+#include "xft.h"
 #include "font-retry.h"
 
 extern const char *progname;
@@ -23,13 +25,27 @@ extern const char *progname;
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
-XFontStruct *
-load_font_retry (Display *dpy, const char *xlfd)
+static void *
+load_font_retry_1 (Display *dpy, int screen, const char *xlfd, Bool xft_p)
 {
-  XFontStruct *f = XLoadQueryFont (dpy, xlfd);
+
+# ifdef USE_XFT
+#  define LOADFONT() (xft_p \
+                      ? (void *) XftFontOpenXlfd (dpy, screen, xlfd) \
+                      : (void *) XLoadQueryFont (dpy, xlfd))
+# else
+#  define LOADFONT() ((void *) XLoadQueryFont (dpy, xlfd))
+# endif
+
+  void *f = LOADFONT();
+
+# ifndef USE_XFT
+  if (xft_p) abort();
+# endif
+
 # ifdef HAVE_JWXYZ
   return f;
-# else
+# else /* !HAVE_JWXYZ */
   if (f)
     return f;
   else
@@ -73,7 +89,8 @@ load_font_retry (Display *dpy, const char *xlfd)
         {
           fprintf (stderr, "%s: unloadable, unparsable font: \"%s\"\n",
                    progname, xlfd);
-          return XLoadQueryFont (dpy, "fixed");
+          xlfd = "fixed";
+          return LOADFONT();
         }
       else
         {
@@ -129,7 +146,7 @@ load_font_retry (Display *dpy, const char *xlfd)
                                  "*",                  /* average width */
                                  charsets[a]);
                         /* fprintf(stderr, "%s: trying %s\n", progname, buf);*/
-                        f = XLoadQueryFont (dpy, buf);
+                        f = LOADFONT();
                         if (f)
                           {
                             /* fprintf (stderr,
@@ -141,8 +158,32 @@ load_font_retry (Display *dpy, const char *xlfd)
 
           fprintf (stderr, "%s: unable to find any alternatives to \"%s\"\n",
                    progname, xlfd);
-          return XLoadQueryFont (dpy, "fixed");
+          xlfd = "fixed";
+          return LOADFONT();
         }
     }
-# endif
+# endif /* !HAVE_JWXYZ */
+}
+
+XFontStruct *
+load_font_retry (Display *dpy, const char *xlfd)
+{
+  return (XFontStruct *) load_font_retry_1 (dpy, 0, xlfd, 0);
+}
+
+#ifdef USE_XFT
+XftFont *
+load_xft_font_retry (Display *dpy, int screen, const char *xlfd)
+{
+  return (XftFont *) load_font_retry_1 (dpy, screen, xlfd, 1);
+}
+
+#elif defined(HAVE_JWXYZ)
+
+XftFont *
+load_xft_font_retry (Display *dpy, int screen, const char *xlfd)
+{
+  return XftFontOpenXlfd (dpy, screen, xlfd);
 }
+
+#endif /* !HAVE_JWXYZ */
index 94b4442b6ffc8b06ee59eb73f00764caee2b2068..83ba0e0e576270e58006952e3b18b1c5504d9e0e 100644 (file)
@@ -17,4 +17,8 @@
  */
 extern XFontStruct *load_font_retry (Display *, const char *xlfd);
 
+# ifdef __XSCREENSAVER_XFT_H__  /* if xft.h has been included */
+extern XftFont *load_xft_font_retry (Display *, int screen, const char *xlfd);
+# endif
+
 #endif /* __FONT_RETRY_H__ */
index 1f8fcc1393f0ce0b3a79b343f08c9f8f5d0f6ab7..c948f220a30ed4c9d21f317c4cfa61cc2cac406b 100644 (file)
@@ -258,6 +258,7 @@ utf8_split (const char *string, int *length_ret)
   const unsigned char *end = in + len;
   char **ret = (char **) malloc ((len+1) * sizeof(*ret));
   int i = 0;
+  int zwjp = 0;
   if (!ret) return 0;
 
   while (in < end)
@@ -272,13 +273,28 @@ utf8_split (const char *string, int *length_ret)
 
       /* If this is a Combining Diacritical, append it to the previous
          character. E.g., "y\314\206\314\206" is one string, not three.
+
+         If this is ZWJ, Zero Width Joiner, then we append both this character
+         and the following character, e.g. "X ZWJ Y" is one string not three.
+
+         #### Hmmm, should this also include every character in the
+         "Symbol, Modifier" category, or does ZWJ get used for those?
+         https://www.fileformat.info/info/unicode/category/Sk/list.htm
+
+         Is it intended that "Latin small letter C, 0063" + "Cedilla, 00B8"
+         should be a single glyph? Or is that what "Combining Cedilla, 0327"
+         is for?  I'm confused by the fact that the skin tones (1F3FB-1F3FF)
+         do not seem to be in a readily-identifiable block the way the various
+         combining diacriticals are.
        */
       if (i > 1 && 
-          ((uc >=  0x300 && uc <=  0x36F) || /* Combining Diacritical */
-           (uc >= 0x1AB0 && uc <= 0x1AFF) || /* Combining Diacritical Ext. */
-           (uc >= 0x1DC0 && uc <= 0x1DFF) || /* Combining Diacritical Supp. */
-           (uc >= 0x20D0 && uc <= 0x20FF) || /* Combining Diacritical Sym. */
-           (uc >= 0xFE20 && uc <= 0xFE2F)))  /* Combining Half Marks */
+          ((uc >=   0x300 && uc <=   0x36F) || /* Combining Diacritical */
+           (uc >=  0x1AB0 && uc <=  0x1AFF) || /* Combining Diacritical Ext. */
+           (uc >=  0x1DC0 && uc <=  0x1DFF) || /* Combining Diacritical Supp. */
+           (uc >=  0x20D0 && uc <=  0x20FF) || /* Combining Diacritical Sym. */
+           (uc >=  0xFE20 && uc <=  0xFE2F) || /* Combining Half Marks */
+           (uc >= 0x1F3FB && uc <= 0x1F3FF) || /* Emoji skin tone modifiers */
+           zwjp || uc == 0x200D))              /* Zero Width Joiner */
         {
           long L1 = strlen(ret[i-2]);
           long L2 = strlen(ret[i-1]);
@@ -289,6 +305,7 @@ utf8_split (const char *string, int *length_ret)
           free (ret[i-2]);
           ret[i-2] = s2;
           i--;
+          zwjp = (uc == 0x200D);  /* Swallow the next character as well */
         }
     }
   ret[i] = 0;
@@ -818,6 +835,7 @@ main (int argc, char **argv)
       free (out16);
     }
 
+  /* Check conversion from UTF8 to Latin1 and ASCII. */
   {
     const char *utf8 = ("son \303\256le int\303\251rieure, \303\240 "
                         "c\303\264t\303\251 de l'alc\303\264ve "
@@ -850,6 +868,58 @@ main (int argc, char **argv)
     free (ascii2);
   }
 
+  /* Check de-composition of emoji that should all be treated as a unit
+     for measurement and display purposes. */
+  {
+    static const char * const tests[] = { 
+
+      /* 0: "Man" */
+      " \360\237\221\250 ",
+
+      /* 1: "Blackula" = "Vampire, dark skin tone" = 1F9DB 1F3FF */
+      " \360\237\247\233\360\237\217\277 ",
+
+      /* 2: "Black male teacher" = "Man, dark skin tone, ZWJ, school" =
+            1F468 1F3FF 200D 1F3EB
+       */
+      " \360\237\221\250\360\237\217\277\342\200\215\360\237\217\253 ",
+
+      /* 3: "Female runner" = "Runner, ZWJ, female sign" = 1F3C3 200D 2640 */
+      " \360\237\217\203\342\200\215\342\231\200 ",
+
+      /* 4: "Woman astronaut" = "Woman, ZWJ, rocket ship" = 1F3C3 200D 1F680 */
+      " \360\237\217\203\342\200\215\360\237\232\200 ",
+
+      /* 5:
+         Group of people displayed as a single glyph:
+           Woman, dark skin tone, ZWJ,   1F469 1F3FF 200D
+           Man, light skin tone, ZWJ,    1F468 1F3FB 200D
+           Boy, medium skin tone, ZWJ,   1F466 1F3FD 200D
+           Girl, dark skin tone.         1F467 1F3FF
+       */
+      " \360\237\221\251\360\237\217\277\342\200\215"
+       "\360\237\221\250\360\237\217\273\342\200\215"
+       "\360\237\221\246\360\237\217\275\342\200\215"
+       "\360\237\221\247\360\237\217\277 ",
+    };
+    int i;
+    for (i = 0; i < sizeof(tests)/sizeof(*tests); i++)
+      {
+        int L = 0;
+        char **out = utf8_split (tests[i], &L);
+        char name[100];
+        int j;
+        sprintf (name, "SPLIT %d: %d glyphs", i, L-2);
+        if (L != 3)
+          {
+            LOG (stderr, name, tests[i]);
+            ok = 0;
+          }
+        for (j = 0; j < L; j++)
+          free (out[j]);
+        free (out);
+      }
+  }
 
   if (ok) fprintf (stderr, "OK\n");
   return (ok == 0);
index 61d904b43f58178df65490cf97d4b63edf7df0c6..5ad7580a6593db592278d141cffb5bb308596cd6 100644 (file)
@@ -1,2 +1,2 @@
 static const char screensaver_id[] =
-       "@(#)xscreensaver 5.39 (12-Apr-2018), by Jamie Zawinski (jwz@jwz.org)";
+       "@(#)xscreensaver 5.40 (12-Aug-2018), by Jamie Zawinski (jwz@jwz.org)";
index c6bb288253ae734d5900f5e32f1b7ab89c50e3f7..c4b940b4bee0a5135ebaeff4fd5e2526aa7184d6 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1999-2011 by Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1999-2018 by Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -47,10 +47,7 @@ get_gl_visual (Screen *screen)
 # define DB GLX_DOUBLEBUFFER
 # define ST GLX_STENCIL_SIZE
 
-# if defined(GL_SAMPLE_BUFFERS)
-#  define SB GL_SAMPLE_BUFFERS
-#  define SM GL_SAMPLES
-# elif defined(GLX_SAMPLE_BUFFERS)
+# if defined(GLX_SAMPLE_BUFFERS) /* Needs to come before GL_SAMPLE_BUFFERS */
 #  define SB GLX_SAMPLE_BUFFERS
 #  define SM GLX_SAMPLES
 # elif defined(GLX_SAMPLE_BUFFERS_ARB)
@@ -59,8 +56,12 @@ get_gl_visual (Screen *screen)
 # elif defined(GLX_SAMPLE_BUFFERS_SGIS)
 #  define SB GLX_SAMPLE_BUFFERS_SGIS
 #  define SM GLX_SAMPLES_SGIS
+# elif defined(GL_SAMPLE_BUFFERS)
+#  define SB GL_SAMPLE_BUFFERS
+#  define SM GL_SAMPLES
 # endif
 
+
   int attrs[][40] = {
 # ifdef SB                               /* rgba double stencil multisample */
    { GLX_RGBA, R,8, G,8, B,8, A,8, D,8, DB, ST,1, SB,1, SM,8, 0 },
index bdfbdb43e750d0850e41f8a80b26f72190151939..92457527ee29e8e26198558e8d53b70af77afae6 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2014-2016 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2014-2018 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -194,16 +194,12 @@ XftColorAllocValue (Display *dpy,
   if (!dpy || !visual || !color || !result) abort();
   if (visual->class == TrueColor)
     {
-      int red_shift, red_len;
-      int green_shift, green_len;
-      int blue_shift, blue_len;
-
-      red_shift   = maskbase (visual->rgba_masks[0]);
-      red_len     = masklen  (visual->rgba_masks[0]);
-      green_shift = maskbase (visual->rgba_masks[1]);
-      green_len   = masklen (visual->rgba_masks[1]);
-      blue_shift  = maskbase (visual->rgba_masks[2]);
-      blue_len    = masklen (visual->rgba_masks[2]);
+      int red_shift   = maskbase (visual->red_mask);
+      int red_len     = masklen  (visual->red_mask);
+      int green_shift = maskbase (visual->green_mask);
+      int green_len   = masklen (visual->green_mask);
+      int blue_shift  = maskbase (visual->blue_mask);
+      int blue_len    = masklen (visual->blue_mask);
       result->pixel = (((color->red   >> (16 - red_len))   << red_shift)   |
                        ((color->green >> (16 - green_len)) << green_shift) |
                        ((color->blue  >> (16 - blue_len))  << blue_shift));
index fdc85df8110bd24725d82eae6b75e7de7e5afeb9..1e14f513f9f4d93a8605e27393a8a921908aee82 100644 (file)
@@ -1,5 +1,5 @@
 %define        name xscreensaver
-%define        version 5.39
+%define        version 5.40
 
 Summary:       X screen saver and locker
 Name:          %{name}